@@ -68,13 +68,33 @@ export class Firehose {
6868 private sub : Subscription < RepoEvent >
6969 private abortController : AbortController
7070 private destoryDefer : Deferrable
71+ private matchCollection : ( ( col : string ) => boolean ) | null = null
7172
7273 constructor ( public opts : FirehoseOptions ) {
7374 this . destoryDefer = createDeferrable ( )
7475 this . abortController = new AbortController ( )
7576 if ( this . opts . getCursor && this . opts . runner ) {
7677 throw new Error ( 'Must set only `getCursor` or `runner`' )
7778 }
79+ if ( opts . filterCollections ) {
80+ const exact = new Set < string > ( )
81+ const prefixes : string [ ] = [ ]
82+
83+ for ( const pattern of opts . filterCollections ) {
84+ if ( pattern . endsWith ( '.*' ) ) {
85+ prefixes . push ( pattern . slice ( 0 , - 2 ) )
86+ } else {
87+ exact . add ( pattern )
88+ }
89+ }
90+ this . matchCollection = ( col : string ) : boolean => {
91+ if ( exact . has ( col ) ) return true
92+ for ( const prefix of prefixes ) {
93+ if ( col . startsWith ( prefix ) ) return true
94+ }
95+ return false
96+ }
97+ }
7898 this . sub = new Subscription ( {
7999 ...opts ,
80100 service : opts . service ?? 'wss://bsky.network' ,
@@ -136,11 +156,11 @@ export class Firehose {
136156 try {
137157 if ( isCommit ( evt ) && ! this . opts . excludeCommit ) {
138158 return this . opts . unauthenticatedCommits
139- ? await parseCommitUnauthenticated ( evt , this . opts . filterCollections )
159+ ? await parseCommitUnauthenticated ( evt , this . matchCollection )
140160 : await parseCommitAuthenticated (
141161 this . opts . idResolver ,
142162 evt ,
143- this . opts . filterCollections ,
163+ this . matchCollection ,
144164 )
145165 } else if ( isAccount ( evt ) && ! this . opts . excludeAccount ) {
146166 const parsed = parseAccount ( evt )
@@ -184,11 +204,11 @@ export class Firehose {
184204export const parseCommitAuthenticated = async (
185205 idResolver : IdResolver ,
186206 evt : Commit ,
187- filterCollections ?: string [ ] ,
207+ matchCollection ?: ( ( col : string ) => boolean ) | null ,
188208 forceKeyRefresh = false ,
189209) : Promise < CommitEvt [ ] > => {
190210 const did = evt . repo
191- const ops = maybeFilterOps ( evt . ops , filterCollections )
211+ const ops = maybeFilterOps ( evt . ops , matchCollection )
192212 if ( ops . length === 0 ) {
193213 return [ ]
194214 }
@@ -210,7 +230,7 @@ export const parseCommitAuthenticated = async (
210230 } )
211231 } catch ( err ) {
212232 if ( err instanceof RepoVerificationError && ! forceKeyRefresh ) {
213- return parseCommitAuthenticated ( idResolver , evt , filterCollections , true )
233+ return parseCommitAuthenticated ( idResolver , evt , matchCollection , true )
214234 }
215235 throw err
216236 }
@@ -228,20 +248,20 @@ export const parseCommitAuthenticated = async (
228248
229249export const parseCommitUnauthenticated = async (
230250 evt : Commit ,
231- filterCollections ?: string [ ] ,
251+ matchCollection ?: ( ( col : string ) => boolean ) | null ,
232252) : Promise < CommitEvt [ ] > => {
233- const ops = maybeFilterOps ( evt . ops , filterCollections )
253+ const ops = maybeFilterOps ( evt . ops , matchCollection )
234254 return formatCommitOps ( evt , ops )
235255}
236256
237257const maybeFilterOps = (
238258 ops : RepoOp [ ] ,
239- filterCollections ?: string [ ] ,
259+ matchCollection ?: ( ( col : string ) => boolean ) | null ,
240260) : RepoOp [ ] => {
241- if ( ! filterCollections ) return ops
261+ if ( ! matchCollection ) return ops
242262 return ops . filter ( ( op ) => {
243263 const { collection } = parseDataKey ( op . path )
244- return filterCollections . includes ( collection )
264+ return matchCollection ( collection )
245265 } )
246266}
247267
0 commit comments