UNPKG

@orbit/records

Version:

A flexible data access and synchronization layer.

196 lines (166 loc) 5.48 kB
import { Orbit } from '@orbit/core'; import { RequestOptions, Source, SourceClass, SourceSettings } from '@orbit/data'; import { Dict } from '@orbit/utils'; import { StandardValidator, ValidatorForFn } from '@orbit/validators'; import { RecordKeyMap } from './record-key-map'; import { RecordNormalizer } from './record-normalizer'; import { RecordQueryBuilder } from './record-query-builder'; import { RecordSchema } from './record-schema'; import { RecordTransformBuilder } from './record-transform-builder'; import { buildRecordValidatorFor } from './record-validators/record-validator-builder'; import { StandardRecordValidator } from './record-validators/standard-record-validators'; import { StandardRecordNormalizer } from './standard-record-normalizer'; const { assert } = Orbit; export interface RecordSourceQueryOptions extends RequestOptions { raiseNotFoundExceptions?: boolean; } export interface RecordSourceSettings< QO extends RequestOptions = RecordSourceQueryOptions, TO extends RequestOptions = RequestOptions, QB = RecordQueryBuilder, TB = RecordTransformBuilder > extends SourceSettings<QO, TO, QB, TB> { schema: RecordSchema; keyMap?: RecordKeyMap; normalizer?: RecordNormalizer; /** * A completely custom set of validators. */ validatorFor?: ValidatorForFn<StandardValidator | StandardRecordValidator>; /** * Custom validators to override, and be merged with, the standard ones which * will be built as long as `autoValidate !== false`. */ validators?: Dict<StandardValidator | StandardRecordValidator>; /** * Automatically validate the contents of all requests. * * If true, builds a `validatorFor` function if one has not been provided. * This will include standard validators as well as any custom `validators` * that may be provided. * * @default true */ autoValidate?: boolean; /** * Automatically upgrade this source whenever its schema is upgraded. * * Override the `upgrade` method to provide an upgrade implementation. * * @default true */ autoUpgrade?: boolean; } export type RecordSourceClass< QO extends RequestOptions = RecordSourceQueryOptions, TO extends RequestOptions = RequestOptions, QB = RecordQueryBuilder, TB = RecordTransformBuilder > = SourceClass<QO, TO, QB, TB>; /** * Abstract base class for record-based sources. */ export abstract class RecordSource< QO extends RequestOptions = RecordSourceQueryOptions, TO extends RequestOptions = RequestOptions, QB = RecordQueryBuilder, TB = RecordTransformBuilder > extends Source<QO, TO, QB, TB> { protected _keyMap?: RecordKeyMap; protected _schema: RecordSchema; protected _validatorFor?: ValidatorForFn< StandardValidator | StandardRecordValidator >; // Unlike in `Source`, builders will always be set protected _queryBuilder!: QB; protected _transformBuilder!: TB; constructor(settings: RecordSourceSettings<QO, TO, QB, TB>) { const autoActivate = settings.autoActivate === undefined || settings.autoActivate; const { schema } = settings; let { validatorFor, validators } = settings; const autoValidate = settings.autoValidate !== false; if (!autoValidate) { assert( 'RecordSource should not be constructed with a `validatorFor` or `validators` if `autoValidate === false`', validators === undefined && validatorFor === undefined ); } else if (validatorFor !== undefined) { assert( 'RecordSource can be constructed with either a `validatorFor` or `validators`, but not both', validators === undefined ); } else { validatorFor = buildRecordValidatorFor({ validators }); } assert( "RecordSource's `schema` must be specified in `settings.schema` constructor argument", !!schema ); if ( settings.queryBuilder === undefined || settings.transformBuilder === undefined ) { let { normalizer } = settings; if (normalizer === undefined) { normalizer = new StandardRecordNormalizer({ schema, keyMap: settings.keyMap, validateInputs: autoValidate }); } if (settings.queryBuilder === undefined) { (settings as any).queryBuilder = new RecordQueryBuilder({ schema, normalizer, validatorFor }); } if (settings.transformBuilder === undefined) { (settings as any).transformBuilder = new RecordTransformBuilder({ schema, normalizer, validatorFor }); } } super({ ...settings, autoActivate: false }); this._schema = schema; this._keyMap = settings.keyMap; this._validatorFor = validatorFor; if (settings.autoUpgrade === undefined || settings.autoUpgrade) { this._schema.on('upgrade', () => this.upgrade()); } if (autoActivate) { this.activate(); } } get schema(): RecordSchema { return this._schema; } get keyMap(): RecordKeyMap | undefined { return this._keyMap; } get validatorFor(): | ValidatorForFn<StandardValidator | StandardRecordValidator> | undefined { return this._validatorFor; } get queryBuilder(): QB { return this._queryBuilder; } get transformBuilder(): TB { return this._transformBuilder; } /** * Upgrade source as part of a schema upgrade. */ async upgrade(): Promise<void> { return; } }