mvom
Version:
Multivalue Object Mapper
134 lines (133 loc) • 9.41 kB
TypeScript
import type { RequiredModelMeta } from './compileModel';
import type { BaseSchemaType, SchemaTypeDefinitionBoolean, SchemaTypeDefinitionISOCalendarDate, SchemaTypeDefinitionISOCalendarDateTime, SchemaTypeDefinitionISOTime, SchemaTypeDefinitionNumber, SchemaTypeDefinitionScalar, SchemaTypeDefinitionString, SchemaTypePath } from './schemaType';
import type { DataTransformer, DecryptFn, EncryptFn, FlattenObject, ISOCalendarDate, ISOCalendarDateTime, ISOTime, MarkRequired, MvRecord, Remap } from './types';
export type SchemaTypeDefinition = Schema | SchemaTypeDefinitionScalar | SchemaDefinition | SchemaTypeDefinitionArray;
type SchemaTypeDefinitionArray = readonly [Schema] | readonly [SchemaTypeDefinitionScalar] | readonly [[SchemaTypeDefinitionScalar]] | readonly [SchemaDefinition];
export interface SchemaDefinition {
[x: string]: SchemaTypeDefinition;
}
export interface SchemaForeignKeyDefinition {
file: string | string[];
keysToIgnore?: string[];
entityName: string;
}
export interface SchemaCompoundForeignKeyDefinition {
[key: number]: SchemaForeignKeyDefinition;
splitCharacter: string;
}
type PickAndMark<T extends SchemaTypeDefinitionScalar, K extends keyof T = never> = MarkRequired<Pick<T, 'dictionary' | 'type' | K>, 'dictionary'>;
export type DictionaryTypeDefinitionString = Remap<PickAndMark<SchemaTypeDefinitionString>>;
export type DictionaryTypeDefinitionNumber = Remap<PickAndMark<SchemaTypeDefinitionNumber>>;
export type DictionaryTypeDefinitionBoolean = Remap<PickAndMark<SchemaTypeDefinitionBoolean>>;
export type DictionaryTypeDefinitionISOCalendarDate = Remap<PickAndMark<SchemaTypeDefinitionISOCalendarDate>>;
export type DictionaryTypeDefinitionISOCalendarDateTime = Remap<PickAndMark<SchemaTypeDefinitionISOCalendarDateTime, 'dbFormat'>>;
export type DictionaryTypeDefinitionISOTime = Remap<PickAndMark<SchemaTypeDefinitionISOTime, 'dbFormat'>>;
export type DictionaryTypeDefinition = DictionaryTypeDefinitionString | DictionaryTypeDefinitionNumber | DictionaryTypeDefinitionBoolean | DictionaryTypeDefinitionISOCalendarDate | DictionaryTypeDefinitionISOCalendarDateTime | DictionaryTypeDefinitionISOTime;
export type DictionaryDefinition = string | DictionaryTypeDefinition;
export type DictionariesOption = Record<string, DictionaryDefinition>;
export interface SchemaConstructorOptions<TDictionaries extends DictionariesOption> {
dictionaries?: TDictionaries;
idMatch?: RegExp;
idForeignKey?: SchemaForeignKeyDefinition | SchemaCompoundForeignKeyDefinition;
encrypt?: EncryptFn;
decrypt?: DecryptFn;
}
interface DictionaryTypeDetail {
dictionary: string;
dataTransformer: DataTransformer;
}
/** Infer whether a schema type definition is required and union the result with null if it is not */
type InferRequiredType<TScalar, TType> = TScalar extends {
required: true;
} ? TType : TType | null;
/**
* Infer the output of a string type definition with specific handling for enumerations
* If an enumeration is a readonly array, the return type of the definition will be a union
* of the array elements. Otherwise, the return type will be a string.
*/
type InferStringType<TString extends SchemaTypeDefinitionString> = TString['enum'] extends readonly (infer E)[] ? E : string;
/**
* Infer the output type of an array schema definition
*
* Allows a constraint to be specified to filter the output to only include scalar arrays of a specific type
*/
type InferArraySchemaType<TSchemaTypeDefinition extends SchemaTypeDefinitionArray, TConstraint> = TSchemaTypeDefinition extends [infer TArrayDefinition] ? TArrayDefinition extends SchemaTypeDefinitionScalar ? TArrayDefinition extends TConstraint ? InferSchemaType<TArrayDefinition, TConstraint>[] : never : InferSchemaType<TArrayDefinition, TConstraint>[] : never;
/** Infer the output type of a schema type definition */
type InferSchemaType<TSchemaTypeDefinition, TConstraint> = TSchemaTypeDefinition extends SchemaTypeDefinitionBoolean ? InferRequiredType<TSchemaTypeDefinition, boolean> : TSchemaTypeDefinition extends SchemaTypeDefinitionString ? InferRequiredType<TSchemaTypeDefinition, InferStringType<TSchemaTypeDefinition>> : TSchemaTypeDefinition extends SchemaTypeDefinitionNumber ? InferRequiredType<TSchemaTypeDefinition, number> : TSchemaTypeDefinition extends SchemaTypeDefinitionISOCalendarDate ? InferRequiredType<TSchemaTypeDefinition, ISOCalendarDate> : TSchemaTypeDefinition extends SchemaTypeDefinitionISOCalendarDateTime ? InferRequiredType<TSchemaTypeDefinition, ISOCalendarDateTime> : TSchemaTypeDefinition extends SchemaTypeDefinitionISOTime ? InferRequiredType<TSchemaTypeDefinition, ISOTime> : TSchemaTypeDefinition extends Schema<infer TSubSchemaDefinition> ? InferDocumentObject<Schema<TSubSchemaDefinition>, TConstraint> : TSchemaTypeDefinition extends SchemaTypeDefinitionArray ? InferArraySchemaType<TSchemaTypeDefinition, TConstraint> : TSchemaTypeDefinition extends SchemaDefinition ? InferDocumentObject<Schema<TSchemaTypeDefinition>, TConstraint> : never;
/**
* Infer the shape of a `Document` instance based upon the Schema it was instantiated with
*
* Allows a constraint to be specified to filter the output to only include properties of a specific type
*/
export type InferDocumentObject<TSchema extends Schema | null, TConstraint = SchemaTypeDefinition> = TSchema extends Schema<infer TSchemaDefinition> ? {
[K in keyof TSchemaDefinition as TSchemaDefinition[K] extends TConstraint ? K : never]: InferSchemaType<TSchemaDefinition[K], TConstraint>;
} : {
_raw: MvRecord;
};
/** Infer the shape of a `Model` instance based upon the Schema it was instantiated with */
export type InferModelObject<TSchema extends Schema | null> = Remap<InferDocumentObject<TSchema> & RequiredModelMeta>;
/**
* Flatten a document to string keyPath (i.e. { "foo.bar.baz": number })
*
* Allows a constraint to be specified to filter the output to only include properties of a specific type
*/
export type FlattenDocument<TSchema extends Schema, TConstraint = SchemaTypeDefinition> = InferDocumentObject<TSchema, TConstraint> extends infer O extends Record<string, unknown> ? FlattenObject<O> : never;
/** Infer the string keyPaths of a schema */
export type InferSchemaPaths<TSchema extends Schema> = Extract<keyof FlattenDocument<TSchema>, string>;
/** Schema constructor */
declare class Schema<TSchemaDefinition extends SchemaDefinition = SchemaDefinition, TDictionaries extends DictionariesOption = Record<never, never>> {
/** Key/value pairs of schema object path structure and associated multivalue dictionary ids */
dictPaths: Map<string, DictionaryTypeDetail>;
/** The compiled schema object path structure */
readonly paths: Map<string, BaseSchemaType>;
/** Foreign key definition for the record id */
readonly idForeignKey?: SchemaForeignKeyDefinition | SchemaCompoundForeignKeyDefinition;
/** Regular expression to validate the record id against */
readonly idMatch?: RegExp;
/** The schema definition passed to the constructor */
private readonly definition;
/** Map of the compiled schema object position paths */
private readonly positionPaths;
/** Map of all subdocument schemas represented in this Schema with parentPath as key */
private readonly subdocumentSchemas;
/** Optional function to use for encryption of sensitive data */
private readonly encrypt?;
/** Optional function to use for decryption of sensitive data */
private readonly decrypt?;
constructor(definition: TSchemaDefinition, { dictionaries, idForeignKey, idMatch, encrypt, decrypt, }?: SchemaConstructorOptions<TDictionaries>);
/** Get all multivalue data paths in this schema and its subdocument schemas */
getMvPaths(): SchemaTypePath[];
/** Transform the paths to positions */
transformPathsToDbPositions(paths: readonly string[]): number[];
/**
* Transform the path to its ordinal position. Returning a '.' delimited string. Ex. "1.2.3"
* @throws {Error} Invalid path provided
*/
transformPathToOrdinalPosition(path: InferSchemaPaths<Schema<TSchemaDefinition, TDictionaries>>): `${number}.${number}.${number}`;
/** Build the dictionary path map for additional dictionaries provided as schema options */
private buildDictionaryPaths;
/**
* Get all positionPaths with path as key and position array as value including children schemas
* e.g. parent field 'foo' has a child schema which has ["bar",[2]], the returned positionPath will be ["foo.bar",[2]].
*/
private getPositionPaths;
/** Construct instance member paths */
private buildPaths;
/**
* Cast an array to a schemaType
* @throws {@link InvalidParameterError} An invalid parameter was passed to the function
*/
private castArray;
/**
* Cast a scalar definition to a scalar schemaType
* @throws {@link InvalidParameterError} An invalid parameter was passed to the function
*/
private castScalar;
/** Perform ancillary updates needed when a subdocument is in the Schema definition */
private handleSubDocumentSchemas;
/** Determine if an object matches the structure of a scalar definition */
private isScalarDefinition;
/** Merge subdocument schema dictionaries with the parent schema's dictionaries */
private mergeSchemaDictionaries;
}
export default Schema;