@cranq/document-utils
Utilities for manipulating documents in a document store.
Terms
Document
A document is any record (JS object) that has a __collectionId
property.
Documents may contain other documents, or references to documents.
Documents extend the Document
type.
Example:
type Dog = {
__collectionId: "dogs",
name: string;
owner: Person;
};
type Person = {
__collectionId: "people",
name: string;
}
const buddy: Dog = {
__collectionId: "dogs",
name: "Buddy",
owner: {
__collectionId: "people",
name: "Jane Doe"
}
}
Reference
A reference to a document identifies a document in a document store, and is
a record (JS object) with exactly two properties:
References are of the Reference
type.
__collectionId
- same as the collection ID of the referenced document__documentId
- identifies the referenced document in its collection
Example:
const buddyRef: Reference<Dog> = {
__collectionId: "dogs",
__documentId: "buddy"
}
Truncated document
A truncated document is a document with all its sub-documents replaced with
references.
Truncated documents satisfy the TruncatedDocument<D>
type,
where D extends Document
.
Example:
const buddyTruncated: TruncateDocument<Dog> = {
__collectionId: "dogs",
name: "Buddy",
owner: {
__collectionId: "people",
__documentId: "jane-doe"
}
}
Restored document
A restored document is a document restored from a truncated document.
Restored documents are ordinary documents, but their restored types can be
calculated using the RestoreDocument
generic. RestoreDocument<TR>
will be the same as D
, given that TR = TruncateDocument<D>
.
Document collection
A document collection is a dictionary (JS object) of truncated documents of
the same collection ID, indexed by their document IDs.
The type of a document collection is based on type of the documents it contains.
Eg: DocumentCollection<D>
.
Example:
const dogs: DocumentCollection<Dog> = {
"buddy": {
__collectionId: "dogs",
name: "Buddy",
owner: {
__collectionId: "people",
__documentId: "jane-doe"
}
}
}
Document store
A document store is a dictionary (JS object) of document collections, indexed
by collection IDs.
The type of a document store is based on the types of all the documents it can
store. Eg: DocumentStore<Dog | Person>
Example:
const documentStore: DocumentStore<Dog | Person> = {
"dogs": {
"buddy": {
__collectionId: "dogs",
name: "Buddy",
owner: {
__collectionId: "people",
__documentId: "jane-doe"
}
}
},
"people": {
"jane-doe": {
__collectionId: "people",
name: "Jane Doe"
}
}
}
Common usage
Retrieving (truncated) document from the store
Example:
const buddyTruncated = getDocument(documentStore, "dogs", "buddy");
Retrieving (deep) document from the store
Retrieving a deep document out of the store, when compared to getDocument()
,
incurs some performance penalty proportional to the complexity of the document
being retrieved, as it needs to be assembled on the fly.
Example:
const buddy = getDeepDocument(documentStore, "dogs", "buddy");
Retrieving field from the store
Example:
const buddyName = getField(documentStore, "dogs", "buddy", "name");
Writing (truncated) document to the store
Example:
documentStore = setDocument(documentStore, "dogs", "buddy", {
__collectionId: "dogs",
name: "Buddy",
owner: {
__collectionId: "people",
__documentId: "jane-doe"
}
})
A mutable version exists for setDocument()
, with identical arguments,
and void
return type: setDocumentMutable()
.
Appending (truncated) document in the store
Appending a document changes the value of specified field, leaving other fields
unaffected. Fields values may be specified either as a value, or as a function -
receiving current value and returning new value.
Example:
documentStore = appendDocument(documentStore, "dogs", "buddy", {
name: "Fido"
})
documentStore = appendDocument(documentStore, "people", "jane.doe", {
name: (name) => `${name} Jr.`
})
A mutable version exists for appendDocument()
, with identical arguments,
and void
return type: appendDocumentMutable()
.
Writing (deep) document to the store
Writing a deep document into the store, when compared to setDocument()
, incurs
some performance penalty proportional to the complexity of the document being
written, as it needs to be broken down on the fly.
Example:
documentStore = setDeepDocument(documentStore, "dogs", "buddy", {
__collectionId: "dogs",
name: "Buddy",
owner: {
__collectionId: "people",
name: "Jane Doe"
}
})
A mutable version exists for setDeepDocument()
, with identical arguments,
and void
return type: setDeepDocumentMutable()
.