Exported Types
Types re-exported from the package entry point (flintfire). For the classes
these types describe, see FirestoreRepository and
FirestoreQueryBuilder (which also documents
FirestoreCollectionGroup and FirestoreCollectionGroupQueryBuilder); for the runtime helpers, see
Helpers & Utilities.
ID—stringdocument-identifier alias.RepositoryConstructorArgs<T, W, WO, S = any>— the positional constructor tuple forFirestoreRepository:(db, collectionPath, validator?, parentPath?, readConverter?, schemas?, allowLegacyDatastoreIds?). The validator is required whenWOdiverges fromWand optional when they match.Sis the stored (at-rest) type, carried in theschemasslot so a subclass’s declaredSis checked against thestoredSchemait passes. Returned byFirestoreRepository.withSchemaArgsso subclasses can spread it intosuper(...)(ADR-0042).RepositorySchemaSetFor<S = any>— the repository schema bundle (read/create/update/stored?), parameterized by the stored type.storedisZodObject<any> & ZodType<S>, which is what makes theScheck above possible.RepositorySchemaSetis the erased alias (RepositorySchemaSetFor<any>) and is what therepo.schemasgetter returns — the stored type is checked on construction, not imposed on reads.FirestoreDocument<T>— the flat read-result shape. For a concreteT, equivalent toOmit<T, 'id'> & { readonly id: ID }; for unresolved generics it is a distributive conditional so union read models narrow correctly (ADR-0028). Returned by every read (getById,getAll, query terminals, hook payloads, …).DataOf<R>— extracts a repository’s read-data type (OmitId<T>) without spelling the generics.StoredDataOf<R>— extracts a repository’s stored-data type (OmitId<S>).DocumentOf<R>— extracts a repository’s document result type (FirestoreDocument<DataOf<R>>); name a returned document type without spelling the generics.CollectionGroupDocument<T>— the read-result shape of a collection-group query:Omit<T, 'id' | 'path' | 'parentPath'>plus a readonlyid, the full documentpath('users/u1/posts/p1'), and the containing collection’sparentPath('users/u1/posts'). All plain strings, so a result stays JSON-serializable — rebuild a reference withdb.doc(row.path). Ids are not unique across a group, sopathis the identity that distinguishes two rows. Compose it with the extractors to name a row:CollectionGroupDocument<DataOf<typeof postRepo>>. BothFirestoreDocumentandCollectionGroupDocumentdistributeOmitover union read models (ADR-0028).DocumentMetadata— snapshot provenance paired with reads and detailed listeners:ref(liveDocumentReference— not JSON-serializable),path,parentPath,createTime,updateTime,readTime. Delivered as a sibling of the document, never overlaid onto it.WithMetadata<D>—{ doc: D; metadata: DocumentMetadata }, returned by any read called with{ withMetadata: true }.docstays JSON-serializable;metadata.refdoes not.WriteMetadata— commit receipt{ writeTime: Timestamp }returned by a non-transactional write called with{ withMetadata: true }. This is the Admin SDK write-result timestamp, notDocumentMetadata.updateTimeand not a JSON field on the document body. Absent from every*InTransactionhelper.WriteResultWithMetadata<R>—R & WriteMetadata(for example{ id, writeTime }). Prefer this enrichment over a universal{ result, metadata }wrapper so default callers keep reading.id.DetailedDocumentChange<R>— one mappeddocChanges()entry:type,doc,metadata,oldIndex,newIndex. Fortype: 'removed',docandmetadatadescribe the document as it last was — branch ontype, not onexists.DetailedQuerySnapshot<R>— detailed listener payload:docs,changes,size,empty,readTime.InvalidDocumentIdReason— machine-readable cause carried byInvalidDocumentIdError:'not_string' | 'empty' | 'contains_slash' | 'reserved_dot_segment' | 'reserved_namespace' | 'too_long' | 'invalid_utf8'(the error class is documented in Error Handling).InvalidPaginationCursorReason— machine-readable cause carried byInvalidPaginationCursorError:'malformed' | 'source_mismatch' | 'stale'(see Error Handling).HookEvent— union of supported lifecycle hook names.HookContext<E>— second argument to every lifecycle hook:event,execution('direct'|'transaction'),retryable, and (on the transaction branch only) diagnosticattempt: number | null. See Lifecycle Hooks.WriteOutcome— discriminated persistence outcome carried byWriteOutcomeError(see Error Handling).UpdateOptions—{ merge?: boolean; returnDoc?: boolean; withMetadata?: boolean; lastUpdateTime?: Timestamp }.returnDocandwithMetadataare mutually exclusive.ReadConverter<T>— read-only converter: thefromFirestore(snapshot) => Tmapper passed asreadConverter(the repository builds the fullFirestoreDataConverterinternally). See Read Converters.SafeResult<T>—{ success: true; data } | { success: false; error: ValidationError }returned bysafeValidate.PaginatedResult<T>—{ items; nextCursor; hasMore }from cursor pagination.DeepPartial<T>— recursively-optionalT(nested map properties optional too); the terminal result shape afterselect(...). It recurses into every object not assignable to the leaf set (there is no plain-map predicate); leaf values are preserved whole — scalars,Date, Firestore value classes (Timestamp,GeoPoint,DocumentReference,FieldValue, vector values), byte values (Uint8Array/Buffer), functions, and arrays. The leaf test is distributive over unions. A custom class instance produced by areadConverteras a field value is not a known leaf, so it recurses and its methods type as optional after a projection. Guarding only the field does not make such a method callable (row.value?.method()still errors —methodis now optional too); guard the method as well (row.value?.method?.()) or assert the field back to its class type after a null check ((row.value as ClassType).method()).FieldPaths<T>/PathValue<T, P>— typed field-path union and the value type at a path. Query/builder surfaces compose these over the stored shape after synthetic-idremoval (FieldPaths<OmitId<S>>). Declared literal keys beside a string index signature (for example{ name: string } & Record<string, unknown>, or the same shape with an explicit syntheticid) are preserved as typed paths; arbitrary dynamic map keys are not — use an SDKFieldPathfor those. Nested intersections recover their declared children recursively. When the stored model also declaresid, that key is excluded from typed paths (FieldPaths<OmitId<S>>) even though a string index still makes value-position access atidlegal at the index value type onStoredDataOf/OmitId<S>itself.OmitId<S>— distributive synthetic-idremoval for stored/read models. When a member explicitly declares a literalid, the helper omits it from the declared-key portion and reattaches any original string/number index signatures so declared siblings keep precise types while value-position dynamic indexing survives; otherwise it returns that member unchanged (so an intersection withRecord<string, unknown>keeps both its declared keys and its value-position index signature). Use when annotating a reusableQueryFilterFactorypredicate over a union model:(f: QueryFilterFactory<OmitId<UnionStored>>) => …. PreferStoredDataOf<typeof repo>for repository-bound predicates. See ADR-0028.QueryFilterFactory<S>— the callback argument ofwhereFilter(...): schema-awarewhere/whereId/and/orbuilders that return an SDKFilter.and()andor()throw when called with no filters.Filteritself is not re-exported — import it fromfirebase-admin/firestore, as withFieldPathandWhereFilterOp. Useful for extracting a reusable typed predicate — annotate the shape withStoredDataOf<typeof repo>, which already excludes the syntheticidfrom typed query paths (FieldPaths<OmitId<S>>) while retaining value-position index access when the stored model has a string index:const mine = (f: QueryFilterFactory<StoredDataOf<typeof postRepo>>) => f.or(…).Sis invariant: a predicate annotated with a different repository’s shape (or one that still includesidas a declared typed path) is a compile error rather than silently accepted.CollectionGroupFilterFactory<S>— the collection-group counterpart, handed tocollectionGroup().query().whereFilter(...). Identical toQueryFilterFactory<S>except that the document-name helper iswherePath(op, fullPathOrRef)rather thanwhereId(op, id), because a collection-group query matchesdocumentId()against the full document path. Same invariance rules.ReadOnlyTransactionalRepository<T, S = T>— type-level surface for{ readOnly: true }/runReadOnlyAttransaction callbacks. Membership is pure or transaction-scoped only:getInTransaction,getManyInTransaction,fromSnapshot,validate,id/newId,getCollectionPath, and thereadSchema/schemasaccessors. Write helpers and non-transactional reads (getById,getMany,getAll,query) are absent from the type so they cannot bypass the transaction orreadTime. The optional second type parameterSis the stored model used to typefieldMaskpaths ongetManyInTransaction(mirroringselect()/where()); it defaults toTso existing one-argument uses keep compiling. See Transactions.UpdateInput<T>— update payload type; for a concreteT,UpdateData<Omit<T, 'id'>>(typed dot-notation paths). Distributes over union write models (ADR-0028).CreateInput<T>— create payload type; for a concreteT,WithFieldValue<Omit<T, 'id'>>;idis not a member. Distributes over union write models, so each branch is writable and cross-branch payloads stay rejected (ADR-0028).CreateOutput<T>— parsed create output (Omit<T, 'id'>for a concreteT) that after-create hooks observe. Distributes over unions (ADR-0028).Validator<Input, Output = Input>— validation contract produced bymakeValidator(...).RepositorySchemaSet— bundle of schemas attached to a repository:read/create/update, plus an optionalstoredcarrying the effective at-rest shape (the suppliedstoredSchema, or the read schema when none was given).storedis whatcollectionGroup()inspects to reject a stored shape colliding with group identity; for the stored shape as a type, useStoredDataOf<typeof repo>.SentinelPolicy—'permissive' | 'strict'(the v3 default is'strict').FieldValueKind— union of recognized Firestore sentinel kinds.BulkWriteOperationKind—'create' | 'set' | 'update' | 'patch' | 'delete', the verb setbulkWriteaccepts.BulkWriteOperation<W>— one entry in abulkWritelist, discriminated onop. Onlycreatemay omitid; onlyupdate/patch/deleteacceptlastUpdateTime?.BulkWriteResult— positional per-operation outcome, discriminated onok. Successes carry{ index, id, op, ok: true, writeTime }; failures carry{ index, id, op, ok: false, error }plus an optionalfailedAttempts(present only when the backend rejected the write, absent for a validation or malformed-id rejection where nothing was attempted).BulkWriteOptions—{ skipHooks?: boolean; throttling? }.skipHooksis required when the repository has any bulk hook registered;throttlingis forwarded verbatim todb.bulkWriter.CountAggregation—{ kind: 'count' }.SumAggregation<S>/AverageAggregation<S>—{ kind: 'sum' | 'average', field }, wherefieldis a numeric stored path (NumericFieldPaths<S> | FieldPath).AggregationSpecEntry<S>— the union of the three above;AggregationSpec<S>isRecord<string, AggregationSpecEntry<S>>, the alias → aggregation mapaggregate(spec)takes.AggregationResult<Spec>— the resolved result for a spec: each alias maps tonumberforcount/sumandnumber | nullforaverage.QueryExplainResult<R>—{ metrics, documents }fromexplain().documentsisnullfor a plan-only request andR[](possibly[]) whenanalyze: true.QueryExplainStreamResult<R>— one chunk fromexplainStream();documentandmetricsare both optional, because metrics arrive as a separate chunk from the documents.ReadOnlyQuery<T, W = T, S = T, R = FirestoreDocument<T>>— a read-only view ofFirestoreQueryBuilder: the entire read surface (filtering, composite filters, document-name queries, ordering, projection, bounds, aggregation, pagination, streaming, listeners, explain) withupdate()/delete()absent at every chain depth. Every clause member returnsReadOnlyQuery(notthis), so the narrowing survives a fluent chain;repo.query()is assignable with no cast. Type-level only — a deliberate cast back to the concrete builder still reaches the write terminals. See Read-only view.
Write interceptors
Section titled “Write interceptors”The seven types describing
registerWriteInterceptor (ADR-0040). The two
internal staging types (StagingTarget, WriteGroup) are deliberately not exported — an
interceptor never touches the batch or transaction directly.
WriteInterceptor<T, W, WO>— either flavour below; what a repository stores.WriteOnlyInterceptor<T, W, WO>—{ name, write }, withread?: undefined. Its writes are staged into aWriteBatch, so the fixed-batch helpers and query write terminals keep working. Theread?: undefined(rather than an absent key) is what makes the registration overloads discriminate.ReadCapableInterceptor<T, W, WO, R>—{ name, read, write }.Ris inferred fromread’s return type and handed towriteasreads. Registering one promotes every single-document write on that repository to a transaction, and makes the bulk paths and{ withMetadata: true }refuse.InterceptedWriteKind—'create' | 'update' | 'delete'.patchreports as'update';upsertreports whichever write it performed.InterceptedWrite<T, W, WO>— the domain write, discriminated onkind.'create'carriesdata: CreateOutput<WO>,'update'carriesdata: UpdateInput<W>, and'delete'carriesdocument: FirestoreDocument<T>— the whole stored document, because every delete path pre-reads it. All three carryid: ID. Each is what is actually being written, after schema parsing and transforms — not the caller’s raw argument. On'update', a merge write arrives dot-path normalized.patch(),update(…, { merge: true })andbulkPatch()normalize nested objects into field paths before validating, sopatch(id, { address: { city: 'c' } })reaches the interceptor as{ 'address.city': 'c' }, while a plainupdate()keeps{ address: { city: 'c' } }. Both reportkind: 'update', andUpdateInput<W>admits dotted keys, so TypeScript does not flag the difference — read a nested field aswrite.data['address.city'], notwrite.data.address?.city. Flat payloads are unaffected.InterceptorWriter— the staging surface:createWithId/set/update/patch/delete, each taking the target repository positionally and generic over that repository’s parameters, so a sibling payload is checked against the target’s write model. Every member butsetis named after — and behaves as — the repository method of the same name;sethas no repository counterpart and keeps the Firestore verb. Stages only; it cannot commit.InterceptorReader—get(repo, id), joining the transaction the write will be staged into.
The package also exports runtime helpers — validation combinators, timestamp utilities, and
dot-notation utilities — documented on the Helpers & Utilities
page. The vector-search extension (flintfire/vector) exports
withVectorSearch, vectorEmbeddingSchema, VectorDistanceMeasure, isVectorFieldValue, and
related constants — see Vector Search.