Helpers & Utilities
The package root exports the runtime helpers the ORM uses internally so you can reuse them in your own code. They fall into three families. For the narrative guides that use them, see Per-Field Sentinel Approval, Timestamps ↔ Millis, and Dot Notation.
Validation combinators
Section titled “Validation combinators”Per-field write combinators let each field accept only its declared type or an explicitly
approved FieldValue sentinel. Build a writeSchema overlay from them — see
Per-Field Sentinel Approval.
| Combinator | Field accepts |
|---|---|
zNumberWrite() |
number or FieldValue.increment() |
zArrayWrite(elem) |
elem[] or FieldValue.arrayUnion() / arrayRemove() |
zDateWrite() |
Date or FieldValue.serverTimestamp() |
withDelete(schema) |
the wrapped type or FieldValue.delete() |
zSentinel(...kinds) |
a sentinel of one of the named kinds (compose with z.union) |
zNumberWrite() / zArrayWrite() / zDateWrite() also accept { allowDelete: true } to
additionally permit FieldValue.delete(). A delete() sentinel is still rejected on create /
bulkCreate / upsert regardless — clear a field with update() / patch().
The lower-level primitives the repository is built from are also exported:
makeValidator<T extends ZodObject, U extends ZodObject = T>(readSchema: T, updateSchema?: U, opts?: { sentinelPolicy?: SentinelPolicy }): Validator<z.input<T>, z.output<T>>
Build the Validator a repository uses. Derives the create schema (top-level id stripped) and,
unless an explicit updateSchema is given, a .partial() update schema; sentinelPolicy defaults
to 'strict'. withSchema(...) calls this for you.
isFieldValueSentinel(value: unknown): boolean
true when value is a Firestore FieldValue sentinel instance (admin FieldValue identity, plus
a structural check for VectorValue).
whichFieldValue(value: unknown): FieldValueKind
Classify a write sentinel into its FieldValueKind — 'serverTimestamp', 'arrayUnion',
'arrayRemove', 'increment', 'delete', 'vector', or 'unknown'.
collectSentinelPaths(input: unknown, basePath?): Path[]
Recursively collect every object path at which a FieldValue sentinel appears in input.
Timestamp utilities
Section titled “Timestamp utilities”Store Firestore Timestamps on write and read them as milliseconds-since-epoch numbers. See
Timestamps ↔ Millis.
| Export | Purpose |
|---|---|
createMillisTimestampConverter<T>(fields?) |
Build a readConverter mapper (recursive Timestamp -> number read conversion) |
convertTimestampsToMillis<T>(data) |
Recursively convert every Timestamp in a value to an ms number (returns a copy) |
convertTimestampToMillis(ts) |
Convert a single Timestamp to an ms number (throws if not a Timestamp) |
convertMillisToTimestamp(ms) |
Convert an ms number to a Timestamp (throws TypeError if not a finite number) |
convertTimestampsToMillis uses a structural toMillis duck-check and never references
firebase-admin, so it is safe to reuse in shared/browser code; non-Timestamp value types (a
VectorValue, GeoPoint, or DocumentReference) are left untouched.
Dot-notation utilities
Section titled “Dot-notation utilities”Build and inspect dot-notation payloads. See Dot Notation.
import { isDotNotation, hasDotNotationKeys, expandDotNotation, flattenToDotNotation, mergeDotNotationUpdate, validateDotNotationPath, getRootFields, getDotNotationDepth,} from 'flintfire';| Utility | Signature | Behavior |
|---|---|---|
isDotNotation(key) |
(key: string) => boolean |
true when the key contains a .. |
hasDotNotationKeys(obj) |
(obj: Record<string, any>) => boolean |
true when any key in the object uses dot notation. |
expandDotNotation(flatObj) |
<T = any>(flatObj: Record<string, any>) => T |
Expands flat dot-notation keys into a nested object. Throws if any segment is __proto__, prototype, or constructor. |
flattenToDotNotation(obj, prefix?) |
(obj: Record<string, any>, prefix?: string) => Record<string, any> |
Flattens a nested object into dot-notation keys. Only plain objects are flattened — arrays, Date instances, and class instances are left as-is. |
mergeDotNotationUpdate(existing, updates) |
(existing: Record<string, any>, updates: Record<string, any>) => Record<string, any> |
Merges a mixed regular/dot-notation update into existing data, skipping undefined values. Throws on a __proto__ / prototype / constructor segment. |
validateDotNotationPath(key) |
(key: string) => void |
Throws if the path is empty, starts or ends with a ., contains an empty segment, or uses a __proto__ / prototype / constructor segment (prototype-pollution guard). |
getRootFields(keys) |
(keys: string[]) => string[] |
Returns the unique top-level roots, e.g. ['address.city', 'address.zip', 'name'] → ['address', 'name']. |
getDotNotationDepth(key) |
(key: string) => number |
Number of path segments, e.g. 'address.city' → 2, 'name' → 1. |