typesaurus
Version:
Type-safe ODM for Firestore
160 lines (159 loc) • 9.18 kB
TypeScript
import type { TypesaurusUtils as Utils } from "./utils.js";
import type { TypesaurusCore as Core } from "./core.js";
import type { TypesaurusUpdate as Update } from "./update.js";
export declare const transaction: TypesaurusTransaction.Function;
export declare namespace TypesaurusTransaction {
interface Function {
<Schema extends Core.PlainSchema, Environment extends Core.RuntimeEnvironment, Props extends Core.DocProps & {
environment: Environment;
}>(db: Core.DB<Schema>, options?: Core.OperationOptions<Environment>): ReadChain<Schema, Props>;
}
/**
* The document reference type.
*/
interface ReadRef<Def extends Core.DocDef, Props extends Core.DocProps> {
type: "ref";
collection: ReadCollection<Def, Props>;
id: Def["Id"];
}
/**
* The document reference type.
*/
interface WriteRef<Def extends Core.DocDef, Props extends Core.DocProps> extends DocAPI<Def, Props> {
type: "ref";
collection: WriteCollection<Def, Props>;
id: Def["Id"];
}
interface DocAPI<Def extends Core.DocDef, Props extends Core.DocProps> {
set(data: Core.AssignArg<Core.IntersectVariableModelType<Def["Model"]>, Props>): void;
update(data: Update.Arg<Def, Props>): void;
upset(data: Core.AssignArg<Core.IntersectVariableModelType<Def["Model"]>, Props>): void;
remove(): void;
}
/**
* The document type. It contains the reference in the DB and the model data.
*/
interface ReadDoc<Def extends Core.DocDef, Props extends Core.DocProps> {
type: "doc";
ref: ReadRef<Def, Props>;
data: Props["environment"] extends "server" ? Core.ServerData<Core.IntersectVariableModelType<Def["Model"]>> : Core.Data<Core.IntersectVariableModelType<Def["Model"]>, "present">;
props: Props;
}
/**
* The document type. It contains the reference in the DB and the model data.
*/
interface WriteDoc<Def extends Core.DocDef, Props extends Core.DocProps> extends DocAPI<Def, Props> {
type: "doc";
ref: WriteRef<Def, Props>;
data: Props["environment"] extends "server" ? Core.ServerData<Core.IntersectVariableModelType<Def["Model"]>> : Core.Data<Core.IntersectVariableModelType<Def["Model"]>, "present">;
props: Props;
narrow<NarrowToModel extends Core.ModelType>(fn: Core.DocNarrowFunction<Core.IntersectVariableModelType<Def["WideModel"]>, NarrowToModel>): WriteDoc<{
Model: NarrowToModel;
Name: Def["Name"];
Id: Def["Id"];
WideModel: Def["WideModel"];
Flags: Def["Flags"] & {
Reduced: true;
};
}, Props> | undefined;
}
type AnyWriteCollection<Def extends Core.DocDef, Props extends Core.DocProps> = WriteCollection<Def, Props> | NestedWriteCollection<Def, Props, WriteSchema<Props>>;
interface WriteSchema<Props extends Core.DocProps> {
[CollectionPath: string]: AnyWriteCollection<Core.DocDef, Props>;
}
interface NestedWriteCollection<Def extends Core.DocDef, Props extends Core.DocProps, NestedSchema extends WriteSchema<Props>> extends WriteCollection<Def, Props> {
(id: Def["Id"]): NestedSchema;
}
/**
*
*/
interface WriteCollection<Def extends Core.DocDef, Props extends Core.DocProps> {
/** The Firestore path */
path: string;
set(id: Def["Id"], data: Core.AssignArg<Core.IntersectVariableModelType<Def["Model"]>, Props>): void;
upset(id: Def["Id"], data: Core.AssignArg<Core.IntersectVariableModelType<Def["Model"]>, Props>): void;
update(id: Def["Id"], data: Update.Arg<Def, Props>): void;
remove(id: Def["Id"]): void;
}
type AnyReadCollection<Def extends Core.DocDef, Props extends Core.DocProps> = ReadCollection<Def, Props> | NestedReadCollection<Def, Props, ReadSchema<Props>>;
interface ReadSchema<Props extends Core.DocProps> {
[CollectionPath: string]: AnyReadCollection<Core.DocDef, Props>;
}
interface NestedReadCollection<Def extends Core.DocDef, Props extends Core.DocProps, NestedSchema extends ReadSchema<Props>> extends ReadCollection<Def, Props> {
(id: Def["Id"]): NestedSchema;
}
interface ReadCollection<Def extends Core.DocDef, Props extends Core.DocProps> extends Core.PlainCollection<Def> {
/** The Firestore path */
path: string;
get(id: Def["Id"]): Promise<ReadDoc<Def, Props> | null>;
}
/**
* The transaction read API object. It contains {@link ReadHelpers.get|get}
* the function that allows reading documents from the database.
*/
interface ReadHelpers<Schema extends Core.PlainSchema, Props extends Core.DocProps> {
db: ReadDB<Schema, Props>;
}
/**
* The transaction write API object. It unions a set of functions ({@link WriteHelpers.set|set},
* {@link WriteHelpers.update|update} and {@link WriteHelpers.remove|remove})
* that are similar to regular set, update and remove with the only
* difference that the transaction counterparts will retry writes if
* the state of data received with {@link ReadHelpers.get|get} would change.
*/
interface WriteHelpers<Schema extends Core.PlainSchema, ReadResult, Props extends Core.DocProps> {
/** The result of the read function. */
result: ReadDocsToWriteDocs<ReadResult, Props>;
db: WriteDB<Schema, Props>;
}
type ReadDocsToWriteDocs<Result, Props extends Core.DocProps> = Result extends ReadDoc<infer Def, Props> ? WriteDoc<Def, Props> : Result extends ReadRef<infer Def, Props> ? WriteRef<Def, Props> : Result extends object ? {
[Key in keyof Result]: ReadDocsToWriteDocs<Result[Key], Props>;
} : Result;
interface ReadChain<Schema extends Core.PlainSchema, Props extends Core.DocProps> {
read: <ReadResult>(callback: ReadFunction<Schema, ReadResult, Props>) => WriteChain<Schema, ReadResult, Props>;
}
/**
* The transaction body function type.
*/
type ReadFunction<Schema extends Core.PlainSchema, ReadResult, Props extends Core.DocProps> = ($: ReadHelpers<Schema, Props>) => Promise<ReadResult>;
interface WriteChain<Schema extends Core.PlainSchema, ReadResult, Props extends Core.DocProps> {
write: <WriteResult>(callback: WriteFunction<Schema, ReadResult, WriteResult, Props>) => WriteDocsToDocs<WriteResult, Props>;
}
/**
* The transaction body function type.
*/
type WriteFunction<Schema extends Core.PlainSchema, ReadResult, WriteResult, Props extends Core.DocProps> = ($: WriteHelpers<Schema, ReadResult, Props>) => WriteResult;
type ReadDB<Schema extends Core.PlainSchema, Props extends Core.DocProps, BasePath extends string | false = false> = {
[Name in keyof Schema]: Name extends string ? Schema[Name] extends Core.NestedPlainCollection<infer Model, infer Schema, infer CustomId, infer CustomName> ? NestedReadCollection<{
Model: Model;
Name: CustomName extends string ? CustomName : Name;
Id: CustomId extends Core.Id<any> | string ? CustomId : Core.Id<Utils.ComposePath<BasePath, Name>>;
WideModel: Model;
Flags: Core.DocDefFlags;
}, Props, ReadDB<Schema, Props, Utils.ComposePath<BasePath, Name>>> : Schema[Name] extends Core.PlainCollection<infer Model, infer CustomId, infer CustomName> ? ReadCollection<{
Model: Model;
Name: CustomName extends string ? CustomName : Name;
Id: CustomId extends Core.Id<any> | string ? CustomId : Core.Id<Utils.ComposePath<BasePath, Name>>;
WideModel: Model;
Flags: Core.DocDefFlags;
}, Props> : never : never;
};
type WriteDocsToDocs<Result, Props extends Core.DocProps> = Result extends WriteDoc<infer Def, Props> ? Core.Doc<Def, Props> : Result extends WriteRef<infer Def, Props> ? Core.Ref<Def> : Result extends object ? {
[Key in keyof Result]: WriteDocsToDocs<Result[Key], Props>;
} : Result;
type WriteDB<Schema extends Core.PlainSchema, Props extends Core.DocProps, BasePath extends string | false = false> = {
[Name in keyof Schema]: Name extends string ? Schema[Name] extends Core.NestedPlainCollection<infer Model, infer Schema, infer CustomId, infer CustomName> ? NestedWriteCollection<{
Model: Model;
Name: CustomName extends string ? CustomName : Name;
Id: CustomId extends Core.Id<any> | string ? CustomId : Core.Id<Utils.ComposePath<BasePath, Name>>;
WideModel: Model;
Flags: Core.DocDefFlags;
}, Props, WriteDB<Schema, Props, Utils.ComposePath<BasePath, Name>>> : Schema[Name] extends Core.PlainCollection<infer Model, infer CustomId, infer CustomName> ? WriteCollection<{
Model: Model;
Name: CustomName extends string ? CustomName : Name;
Id: CustomId extends Core.Id<any> | string ? CustomId : Core.Id<Utils.ComposePath<BasePath, Name>>;
WideModel: Model;
Flags: Core.DocDefFlags;
}, Props> : never : never;
};
}