diff --git a/.babelrc b/.babelrc index 22688b58..79c8cf16 100644 --- a/.babelrc +++ b/.babelrc @@ -1,12 +1,7 @@ { - "presets": [ - [ - "@babel/preset-env", - { - "targets": { - "browsers": ["last 2 versions", "safari >= 7", "> 1%", "IE 11"] - } - } - ] + "presets": ["@babel/env"], + "plugins": [ + "@babel/proposal-class-properties", + "@babel/proposal-object-rest-spread" ] } diff --git a/.circleci/config.yml b/.circleci/config.yml index 49973eec..91f54a67 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -2,7 +2,7 @@ version: 2 jobs: test: docker: - - image: circleci/node:10-browsers + - image: circleci/node:10 steps: - checkout - run: npm install diff --git a/.eslintrc.json b/.eslintrc.json index e3578aad..d37cbec2 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,3 +1,33 @@ { - "extends": "standard" + "extends": [ + "plugin:@typescript-eslint/recommended", + "standard-with-typescript" + ], + "parser": "@typescript-eslint/parser", + "parserOptions": { + "project": "./tsconfig.json" + }, + "plugins": [ + "@typescript-eslint" + ], + "rules": { + "@typescript-eslint/explicit-function-return-type": "off", + "@typescript-eslint/strict-boolean-expressions": "off", + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/restrict-plus-operands": "off", + "@typescript-eslint/restrict-template-expressions": "off", + "@typescript-eslint/promise-function-async": "off", + "@typescript-eslint/no-dynamic-delete": "off", + "@typescript-eslint/consistent-type-assertions": "off", + "@typescript-eslint/no-this-alias": "off", + "@typescript-eslint/no-empty-function": "off", + "@typescript-eslint/no-unused-vars": "off", + "@typescript-eslint/no-extraneous-class": "off", + "@typescript-eslint/no-floating-promises": "off", + "new-cap": "off", + "no-dupe-class-members": "off", + "no-unused-vars": "off", + "no-void": "off", + "no-prototype-builtins": "off" + } } diff --git a/.gitignore b/.gitignore index b734a2f0..86faa057 100644 --- a/.gitignore +++ b/.gitignore @@ -25,8 +25,10 @@ junit/ jsconfig.json .nyc_output -coverage/ -doc/ node_modules/ typings yarn.lock +package-lock.json +build +dist/**/*.d.ts +*.tgz diff --git a/AUTHORS b/AUTHORS index 90cb6408..c7cc579e 100644 --- a/AUTHORS +++ b/AUTHORS @@ -38,5 +38,6 @@ Tomás Fox Trey Nelson Viktor Zozulyak Warren Taylor +Wick wilgert Yunchi Luo diff --git a/CHANGELOG.md b/CHANGELOG.md index e2bb8883..e36c995a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +##### 4.0.0-beta.4 - 9 February 2020 + +- Use babel in roll-up + +##### 4.0.0-beta.1 - 31 January 2020 + +- [#560] - Typescript migration + ##### 3.0.5 - 2 December 2018 ###### Bug fixes diff --git a/bower.json b/bower.json deleted file mode 100644 index 9d10f272..00000000 --- a/bower.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "name": "js-data", - "description": "Robust, framework-agnostic in-memory data store.", - "homepage": "http://www.js-data.io", - "repository": { - "type": "git", - "url": "https://github.com/js-data/js-data.git" - }, - "authors": [ - "Jason Dobry " - ], - "main": "./dist/js-data.js", - "ignore": [ - ".idea/", - ".*", - "*.iml", - "src/", - "dist/js-data-tests.js", - "dist/js-data-tests.js.map", - "lib/", - "doc/", - "guide/", - "coverage/", - "Gruntfile.js", - "scripts/", - "node_modules/", - "test/", - "package.json", - "karma.conf.js", - "karma.start.js", - "rollup.config.js", - "rollup-tests.config.js" - ] -} diff --git a/conf.json b/conf.json deleted file mode 100644 index 677911d6..00000000 --- a/conf.json +++ /dev/null @@ -1,27 +0,0 @@ - { - "source": { - "includePattern": ".*js$" - }, - "plugins": ["plugins/markdown"], - "opts": { - "template": "./node_modules/ink-docstrap/template", - "destination": "./doc/", - "recurse": true, - "verbose": true, - "readme": "./README.md", - "package": "./package.json" - }, - "templates": { - "theme": "jsdata", - "systemName": "js-data", - "copyright": "js-data Copyright © 2014-2020 js-data project authors", - "outputSourceFiles": true, - "linenums": true, - "logoFile": "https://raw.githubusercontent.com/js-data/js-data/master/js-data-64.png", - "footer": "", - "analytics": { - "ua": "UA-55528236-2", - "domain": "api.js-data.io" - } - } -} diff --git a/dist/js-data.d.ts b/dist/js-data.d.ts deleted file mode 100644 index 38b8f184..00000000 --- a/dist/js-data.d.ts +++ /dev/null @@ -1,391 +0,0 @@ -export const version: { - alpha: string|boolean - beta: string|boolean - full: string - major: number - minor: number - patch: number -} -export interface Diff { - added: any - changed: any - removed: any -} -export const utils: { - Promise: PromiseConstructor - _(dest: any, src: any): void - _forRelation(opts: any, def: any, fn: Function, ctx: Object): void - _getIndex(list: any[], relation: any): number - addHiddenPropsToTarget(target: Object, props: Object): void - areDifferent(a: Object, b: Object, opts: any): boolean - classCallCheck(instance: Object, ctor: Function): void - copy(from: any, to?: any, stackFrom?: any, stackTo?: any, blacklist?: any[], plain?: boolean): any - deepFillIn(dest: Object, source: Object): Object - deepMixIn(dest: Object, source: Object): Object - diffObjects(a: any, b: any, opts: any): Diff - equal(a: any, b: any): boolean - eventify(target: any, getter: Function, setter: Function, enumerable?: boolean): void - extend(props?: any, classProps?: any): Function - fillIn(dest: Object, src: Object): void - findIndex(array: any[], fn: Function): void - forEachRelation(mapper: any, opts: any, fn: Function, ctx?: any): void - forOwn(obj: any, fn: Function, thisArg?: Object): void - fromJson(json: any): any - 'get'(object: Object, prop: string): any - getSuper(instance: any, isCtor?: boolean): Function - intersection(array1: any[], array2: any[]): any[] - isArray(arg: any): boolean - isBlacklisted(prop: string, bl: any[]): boolean - isBoolean(value: any): boolean - isBrowser: boolean - isDate(value: any): boolean - isFunction(value: any): boolean - isInteger(value: any): boolean - isNull(value: any): boolean - isNumber(value: any): boolean - isObject(value: any): boolean - isRegExp(value: any): boolean - isSorN(value: any): boolean - isString(value: any): boolean - isUndefined(value: any): boolean - logify(target: any, defaultNamespace: any): void - noDupeAdd(array: any[], record: any, fn: Function): void - omit(props: Object, keys: string[]): Object - plainCopy(from: any): any - possibleConstructorReturn(self: Object, call: Object|Function): Object - reject(value: any): Promise - remove(array: any[], fn: Function): void - resolve(value: any): Promise - set(object: Object, path: string, value?: any): void - deepEqual(a: any, b: any): boolean - toJson(value: any, replacer?: Function, space?: number): string - unset(object: Object, path: string): void -} -export class Settable { - static extend(instanceProps?: any, classProps?: any): any -} -export class Component { - static extend(instanceProps?: any, classProps?: any): any - constructor(opts?: any) - _listeners: Object - dbg(...args: any[]): void - emit(key: string, ...args: any[]): void - log(level: string, ...args: any[]): void - off(key?: string, handler?: Function): void - on(key: string, handler: Function, ctx?: any): void -} -export class Record extends Component { - static mapper: Mapper - constructor(props?: any, opts?: any) - _set(prop: any, value?: any): void - _get(prop: string): any - _unset(prop: any): void - _mapper(): Mapper - afterLoadRelations(): void - afterSave(): void - beforeSave(): void - beforeLoadRelations(): void - changeHistory(): any[] - changes(opts?: any): Diff - commit(): this - create(opts?: any): Promise - destroy(opts?: any): Promise - isNew(): boolean - loadRelations(relations: any, opts?: any): Promise - 'get'(key: string): any - hasChanges(opts?: any): boolean - previous(key: any): any - revert(opts?: any): this - save(opts?: any): Promise - 'set'(key: string, value?: any, opts?: any): void - toJSON(opts?: any): any - unset(key: string, opts?: any): void - validate(opts?: any): any -} -export class Mapper extends Component { - _adapters: Object - applySchema: boolean - name: string - defaultAdapter: string - debug: boolean - idAttribute: string - lifecycleMethods: any - notify: boolean - raw: boolean - recordClass: typeof Record - relationList: any[] - relationFields: string[] - schema: Schema - constructor(opts?: any) - afterCount(query: any, opts: any, result: any): any - afterCreate(props: any, opts: any, result: any): any - afterCreateMany(records: any[], opts: any, result: any): any - afterDestroy(id: string|number, opts: any, result: any): any - afterDestroyAll(query: any, opts: any, result: any): any - afterFind(id: string|number, opts: any, result: any): any - afterFindAll(query: any, opts: any, result: any): any - afterSum(field: string, query: any, opts: any, result: any): any - afterUpdate(id: string|number, props: any, opts: any, result: any): any - afterUpdateAll(props: any, query: any, opts: any, result: any): any - afterUpdateMany(records: any[], opts: any, result: any): any - beforeCreate(props: any, opts: any): any - beforeCreateMany(records: any[], opts: any): any - beforeCount(query: any, opts: any): any - beforeDestroy(id: string|number, opts: any): any - beforeDestroyAll(query: any, opts: any): any - beforeFind(id: string|number, opts: any): any - beforeFindAll(query: any, opts: any): any - beforeSum(field: string, query: any, opts: any): any - beforeUpdate(id: string|number, opts: any): any - beforeUpdateAll(query: any, opts: any): any - beforeUpdateMany(records: any[], opts: any): any - _end(result: any, opts: any, skip?: boolean): any - belongsTo(relatedMapper: any, opts: any): void - count(query: any, opts?: any): Promise - create(props: any, opts?: any): Promise - createInstance(props: any, opts?: any): any - createMany(records: any[], opts?: any): Promise - createRecord(props?: any, opts?: any): Record - crud(method: any, ...args: any[]): Promise - destroy(id: string|number, opts?: any): Promise - destroyAll(query: any, opts?: any): Promise - find(id: string|number, opts?: any): Promise - findAll(query: any, opts?: any): Promise - getAdapter(name: any): any - getAdapterName(opts?: any): any - getAdapters(): any - getSchema(): Schema - hasMany(relatedMapper: any, opts: any): void - hasOne(relatedMapper: any, opts: any): void - is(record: any): boolean - registerAdapter(name: string, adapter: any, opts?: any): void - sum(field: string, query: any, opts?: any): Promise - toJSON(record: any, opts?: any): {} - update(id: string|number, props: any, opts?: any): Promise - updateAll(props: any, query: any, opts?: any): Promise - updateMany(records: any[], opts?: any): Promise - validate(records: any|any[], opts?: any): any -} -export class Collection extends Component { - idAttribute: string - onConflict: string - recordOpts: any - index: Index - indexes: any - mapper: Mapper - constructor(records?: any[], opts?: any) - _onRecordEvent(...args: any[]): void - add(records: any, opts?: any): any - afterAdd(...args: any[]): void - afterRemove(...args: any[]): void - afterRemoveAll(...args: any[]): void - beforeAdd(...args: any[]): void - beforeRemove(...args: any[]): void - beforeRemoveAll(...args: any[]): void - between(leftKeys: any, rightKeys: any, opts?: any): any[] - createIndex(name: any, fieldList: any, opts?: any): this - filter(query: any, thisArg?: any): any[] - forEach(cb: Function, thisArg?: any): void - get(id: string|number): any - getAll(...args: any[]): any[] - getIndex(name: string): any - limit(num: number): any[] - map(cb: any, thisArg: any): any[] - mapCall(funcName: string, ...args: any[]): any[] - prune(): any[] - query(): Query - recordId(record?: any): any - reduce(cb: Function, initialValue: any): any - remove(id: string|number, opts?: any): any - removeAll(query: any, opts?: any): any[] - skip(num: number): any[] - toJSON(opts?: any): any[] - unsaved(): any[] - updateIndex(record: any, opts?: any): void - updateIndexes(record: any): void -} -export class LinkedCollection extends Collection { - _added: Object - datastore: DataStore -} -export class Container extends Component { - mapperDefaults: any - mapperClass: typeof Mapper - _adapters: Object - _mappers: Object - as(name: string): any - constructor(opts?: any) - createRecord(name: string, props?: any, opts?: any): Record - defineMapper(name: string, opts?: any): Mapper - defineResource(name: string, opts?: any): Mapper - getAdapter(name: any): any - getAdapterName(opts?: any): string - getAdapters(): any - getMapper(name: string): Mapper - getMapperByName(name:string): Mapper - registerAdapter(name: string, adapter: any, opts?: any): void -} -export class SimpleStore extends Container { - collectionClass: typeof Collection - _collections: Object - _pendingQueries: Object - _completedQueries: Object - usePendingFind: boolean - usePendingFindAll: boolean - as(name: string): Mapper|Collection - constructor(opts?: any) - add(mapperName: string, records: any[]|any, opts?: any): any[]|any - addToCache(mapperName: string, data: any, opts: any): any - between(mapperName: string, leftKeys: any, rightKeys: any, opts?: any): any[] - cachedFind(mapperName: string, id: string|number, opts: any): any - cachedFindAll(mapperName: string, hash: string, opts: any): any - cacheFind(mapperName: string, data: any, id: string|number, opts: any): void - cacheFindAll(mapperName: string, data: any, hash: string, opts: any): void - clear(): any - createIndex(mapperName: string, name: any, fieldList: any, opts?: any): Collection - filter(mapperName: string, query: any, thisArg?: any): any[] - get(mapperName: string, id: string|number): any - getAll(mapperName: string, ...args: any[]): any[] - query(mapperName: string): Query - remove(mapperName: string, id: string|number, opts?: any): any - removeAll(mapperName: string, query?: any, opts?: any): void|any[] - toJson(mapperName: string, opts?: any): any[] - _callSuper(method: string, ...args: any[]): any - _end(mapperName: string, data: any, opts?: any): any - create(mapperName: string, record: any, opts?: any): Promise - createMany(mapperName: string, records: any, opts?: any): Promise - defineMapper(mapperName: string, opts?: any): Mapper - destroy(mapperName: string, id: any, opts?: any): Promise - destroyAll(mapperName: string, query?: any, opts?: any): Promise - find(mapperName: string, id: any, opts?: any): Promise - findAll(mapperName: string, query?: any, opts?: any): Promise - cachedFind(mapperName: string, id: any, opts?: any): any - cachedFindAll(mapperName: string, query: any, opts?: any): any - hashQuery(mapperName: string, query: any, opts?: any): string - getCollection(mapperName: string): Collection - update(mapperName: string, id: any, record: any, opts?: any): Promise - updateAll(mapperName: string, props: any, query?: any, opts?: any): Promise - updateMany(mapperName: string, records: any, opts?: any): Promise -} -export class DataStore extends SimpleStore { - collectionClass: typeof LinkedCollection - as(name: string): Mapper|LinkedCollection - createIndex(mapperName: string, name: any, fieldList: any, opts?: any): LinkedCollection - getCollection(mapperName: string): LinkedCollection -} -export class Query extends Component { - static ops: { - '=='(value: any, predicate: any): boolean - '==='(value: any, predicate: any): boolean - '!='(value: any, predicate: any): boolean - '!=='(value: any, predicate: any): boolean - '>'(value: any, predicate: any): boolean - '>='(value: any, predicate: any): boolean - '<'(value: any, predicate: any): boolean - '<='(value: any, predicate: any): boolean - 'isectEmpty'(value: any, predicate: any): boolean - 'isectNotEmpty'(value: any, predicate: any): number - 'in'(value: any, predicate: any): boolean - 'notIn'(value: any, predicate: any): boolean - 'contains'(value: any, predicate: any): boolean - 'notContains'(value: any, predicate: any): boolean - } - collection: Collection|LinkedCollection - data: any[] - constructor(collection?: Collection) - compare(orderBy: any, index: any, a: any, b: any): any - evaluate(value: any, op: string, predicate: any): boolean - like(pattern: any, flags: any): RegExp - getData(): any[] - between(leftKeys: any, rightKeys: any, opts?: any): this - get(keyList?: any[], opts?: any): this - getAll(...args: any[]): this - filter(query: any, thisArg?: any): this - skip(num: number): this - limit(num: number): this - forEach(forEachFn: Function, thisArg?: any): this - map(mapFn: Function, thisArg?: any): this - mapCall(funcName: string, ...args: any[]): this - run(): any[] -} -export interface SchemaValidationError { - expected: any - actual: string - path: string -} -export class Schema extends Component { - static types: { - array(value: any): boolean - boolean(value: any): boolean - integer(value: any): boolean - 'null'(value: any): boolean - number(value: any): boolean - object(value: any): boolean - string(value: any): boolean - } - static typeGroupValidators: { - array(value: any, schema: any, opts: any): SchemaValidationError[] - integer(value: any, schema: any, opts: any): SchemaValidationError[] - number(value: any, schema: any, opts: any): SchemaValidationError[] - numeric(value: any, schema: any, opts: any): SchemaValidationError[] - object(value: any, schema: any, opts: any): SchemaValidationError[] - string(value: any, schema: any, opts: any): SchemaValidationError[] - } - static validationKeywords: { - allOf(value: any, schema: any, opts: any): SchemaValidationError[] - anyOf(value: any, schema: any, opts: any): SchemaValidationError[] - dependencies(value: any, schema: any, opts: any): void - enum(value: any, schema: any, opts: any): SchemaValidationError - items(value: any, schema: any, opts: any): SchemaValidationError[] - maximum(value: any, schema: any, opts: any): SchemaValidationError - maxItems(value: any, schema: any, opts: any): SchemaValidationError - maxLength(value: any, schema: any, opts: any): SchemaValidationError - maxProperties(value: any, schema: any, opts: any): SchemaValidationError - minimum(value: any, schema: any, opts: any): SchemaValidationError - minItems(value: any, schema: any, opts: any): SchemaValidationError - minLength(value: any, schema: any, opts: any): SchemaValidationError - minProperties(value: any, schema: any, opts: any): SchemaValidationError - multipleOf(value: any, schema: any, opts: any): SchemaValidationError - not(value: any, schema: any, opts: any): SchemaValidationError - oneOf(value: any, schema: any, opts: any): SchemaValidationError[] - pattern(value: any, schema: any, opts: any): SchemaValidationError - properties(value: any, schema: any, opts: any): SchemaValidationError[] - required(value: any, schema: any, opts: any): SchemaValidationError[] - type(value: any, schema: any, opts: any): SchemaValidationError - uniqueItems(value: any, schema: any, opts: any): SchemaValidationError - } - static validate(value: any, schema: any, opts: any): SchemaValidationError[] - properties: any - constructor(definition: any) - apply(target: any, opts?: any): void - applyDefaults(target: any): void - makeDescriptor(prop: string, schema: Schema, opts?: any): any - pick(value: any): any - validate(value: any, opts?: any): SchemaValidationError[] -} -export class Index { - fieldList: string[] - fieldGetter: Function - hashCode: Function - isIndex: boolean - keys: any[] - values: any[] - constructor(fieldList: string[], opts?: any) - 'set'(keyList: any[], value: any): void - 'get'(keyList: any[]): any - getAll(): any[] - visitAll(cb: Function, thisArg?: any): void - between(leftKeys: any, rightKeys: any, opts?: any): any[] - _between(leftKeys: any, rightKeys: any, opts: any): any[] - peek(): any - clear(): void - insertRecord(data: any): void - removeRecord(data: any): any - updateRecord(data: any): void -} -export const belongsToType: string -export const hasManyType: string -export const hasOneType: string -export const belongsTo: (related: any, opts: any) => (target: any) => void -export const hasMany: (related: any, opts: any) => (target: any) => void -export const hasOne: (related: any, opts: any) => (target: any) => void diff --git a/dist/js-data.es2015.flow.js b/dist/js-data.es2015.flow.js deleted file mode 100644 index d33b4fe0..00000000 --- a/dist/js-data.es2015.flow.js +++ /dev/null @@ -1,411 +0,0 @@ -/** - * Flowtype definitions for js-data - * Generated by Flowgen from a Typescript Definition - * Flowgen v1.2.0 - * - */ - -declare export var version: { - alpha: string | boolean, - beta: string | boolean, - full: string, - major: number, - minor: number, - patch: number -}; -declare export interface Diff { - added: any, - changed: any, - removed: any -} -declare export var utils: { - Promise: PromiseConstructor, - _(dest: any, src: any): void, - _forRelation(opts: any, def: any, fn: Function, ctx: Object): void, - _getIndex(list: any[], relation: any): number, - addHiddenPropsToTarget(target: Object, props: Object): void, - areDifferent(a: Object, b: Object, opts: any): boolean, - classCallCheck(instance: Object, ctor: Function): void, - copy( - from: any, - to?: any, - stackFrom?: any, - stackTo?: any, - blacklist?: any[], - plain?: boolean): any, - deepFillIn(dest: Object, source: Object): Object, - deepMixIn(dest: Object, source: Object): Object, - diffObjects(a: any, b: any, opts: any): Diff, - equal(a: any, b: any): boolean, - eventify(target: any, getter: Function, setter: Function, enumerable?: boolean): void, - extend(props?: any, classProps?: any): Function, - fillIn(dest: Object, src: Object): void, - findIndex(array: any[], fn: Function): void, - forEachRelation(mapper: any, opts: any, fn: Function, ctx?: any): void, - forOwn(obj: any, fn: Function, thisArg?: Object): void, - fromJson(json: any): any, - get(object: Object, prop: string): any, - getSuper(instance: any, isCtor?: boolean): Function, - intersection(array1: any[], array2: any[]): any[], - isArray(arg: any): boolean, - isBlacklisted(prop: string, bl: any[]): boolean, - isBoolean(value: any): boolean, - isBrowser: boolean, - isDate(value: any): boolean, - isFunction(value: any): boolean, - isInteger(value: any): boolean, - isNull(value: any): boolean, - isNumber(value: any): boolean, - isObject(value: any): boolean, - isRegExp(value: any): boolean, - isSorN(value: any): boolean, - isString(value: any): boolean, - isUndefined(value: any): boolean, - logify(target: any, defaultNamespace: any): void, - noDupeAdd(array: any[], record: any, fn: Function): void, - omit(props: Object, keys: string[]): Object, - plainCopy(from: any): any, - possibleConstructorReturn(self: Object, call: Object | Function): Object, - reject(value: any): Promise, - remove(array: any[], fn: Function): void, - resolve(value: any): Promise, - set(object: Object, path: string, value?: any): void, - deepEqual(a: any, b: any): boolean, - toJson(value: any, replacer?: Function, space?: number): string, - unset(object: Object, path: string): void -}; -declare export class Settable { - extend(instanceProps?: any, classProps?: any): any -} -declare export class Component { - extend(instanceProps?: any, classProps?: any): any; - constructor(opts?: any): this; - _listeners: Object; - dbg(...args: any[]): void; - emit(key: string, ...args: any[]): void; - log(level: string, ...args: any[]): void; - off(key?: string, handler?: Function): void; - on(key: string, handler: Function, ctx?: any): void -} -declare export class Record mixins Component { - mapper: Mapper; - constructor(props?: any, opts?: any): this; - _set(prop: any, value?: any): void; - _get(prop: string): any; - _unset(prop: any): void; - _mapper(): Mapper; - afterLoadRelations(): void; - afterSave(): void; - beforeSave(): void; - beforeLoadRelations(): void; - changeHistory(): any[]; - changes(opts?: any): Diff; - commit(): this; - create(opts?: any): Promise; - destroy(opts?: any): Promise; - isNew(): boolean; - loadRelations(relations: any, opts?: any): Promise; - get(key: string): any; - hasChanges(opts?: any): boolean; - previous(key: any): any; - revert(opts?: any): this; - save(opts?: any): Promise; - set(key: string, value?: any, opts?: any): void; - toJSON(opts?: any): any; - unset(key: string, opts?: any): void; - validate(opts?: any): any -} -declare export class Mapper mixins Component { - _adapters: Object; - applySchema: boolean; - name: string; - defaultAdapter: string; - debug: boolean; - idAttribute: string; - lifecycleMethods: any; - notify: boolean; - raw: boolean; - recordClass: typeof Record; - relationList: any[]; - relationFields: string[]; - schema: Schema; - constructor(opts?: any): this; - afterCount(query: any, opts: any, result: any): any; - afterCreate(props: any, opts: any, result: any): any; - afterCreateMany(records: any[], opts: any, result: any): any; - afterDestroy(id: string | number, opts: any, result: any): any; - afterDestroyAll(query: any, opts: any, result: any): any; - afterFind(id: string | number, opts: any, result: any): any; - afterFindAll(query: any, opts: any, result: any): any; - afterSum(field: string, query: any, opts: any, result: any): any; - afterUpdate(id: string | number, props: any, opts: any, result: any): any; - afterUpdateAll(props: any, query: any, opts: any, result: any): any; - afterUpdateMany(records: any[], opts: any, result: any): any; - beforeCreate(props: any, opts: any): any; - beforeCreateMany(records: any[], opts: any): any; - beforeCount(query: any, opts: any): any; - beforeDestroy(id: string | number, opts: any): any; - beforeDestroyAll(query: any, opts: any): any; - beforeFind(id: string | number, opts: any): any; - beforeFindAll(query: any, opts: any): any; - beforeSum(field: string, query: any, opts: any): any; - beforeUpdate(id: string | number, opts: any): any; - beforeUpdateAll(query: any, opts: any): any; - beforeUpdateMany(records: any[], opts: any): any; - _end(result: any, opts: any, skip?: boolean): any; - belongsTo(relatedMapper: any, opts: any): void; - count(query: any, opts?: any): Promise; - create(props: any, opts?: any): Promise; - createInstance(props: any, opts?: any): any; - createMany(records: any[], opts?: any): Promise; - createRecord(props?: any, opts?: any): Record; - crud(method: any, ...args: any[]): Promise; - destroy(id: string | number, opts?: any): Promise; - destroyAll(query: any, opts?: any): Promise; - find(id: string | number, opts?: any): Promise; - findAll(query: any, opts?: any): Promise; - getAdapter(name: any): any; - getAdapterName(opts?: any): any; - getAdapters(): any; - getSchema(): Schema; - hasMany(relatedMapper: any, opts: any): void; - hasOne(relatedMapper: any, opts: any): void; - is(record: any): boolean; - registerAdapter(name: string, adapter: any, opts?: any): void; - sum(field: string, query: any, opts?: any): Promise; - toJSON(record: any, opts?: any): {}; - update(id: string | number, props: any, opts?: any): Promise; - updateAll(props: any, query: any, opts?: any): Promise; - updateMany(records: any[], opts?: any): Promise; - validate(records: any | any[], opts?: any): any -} -declare export class Collection mixins Component { - idAttribute: string; - onConflict: string; - recordOpts: any; - index: Index; - indexes: any; - mapper: Mapper; - constructor(records?: any[], opts?: any): this; - _onRecordEvent(...args: any[]): void; - add(records: any, opts?: any): any; - afterAdd(...args: any[]): void; - afterRemove(...args: any[]): void; - afterRemoveAll(...args: any[]): void; - beforeAdd(...args: any[]): void; - beforeRemove(...args: any[]): void; - beforeRemoveAll(...args: any[]): void; - between(leftKeys: any, rightKeys: any, opts?: any): any[]; - createIndex(name: any, fieldList: any, opts?: any): this; - filter(query: any, thisArg?: any): any[]; - forEach(cb: Function, thisArg?: any): void; - get(id: string | number): any; - getAll(...args: any[]): any[]; - getIndex(name: string): any; - limit(num: number): any[]; - map(cb: any, thisArg: any): any[]; - mapCall(funcName: string, ...args: any[]): any[]; - prune(): any[]; - query(): Query; - recordId(record?: any): any; - reduce(cb: Function, initialValue: any): any; - remove(id: string | number, opts?: any): any; - removeAll(query: any, opts?: any): any[]; - skip(num: number): any[]; - toJSON(opts?: any): any[]; - unsaved(): any[]; - updateIndex(record: any, opts?: any): void; - updateIndexes(record: any): void -} -declare export class LinkedCollection mixins Collection { - _added: Object; - datastore: DataStore -} -declare export class Container mixins Component { - mapperDefaults: any; - mapperClass: typeof Mapper; - _adapters: Object; - _mappers: Object; - as(name: string): any; - constructor(opts?: any): this; - createRecord(name: string, props?: any, opts?: any): Record; - defineMapper(name: string, opts?: any): Mapper; - defineResource(name: string, opts?: any): Mapper; - getAdapter(name: any): any; - getAdapterName(opts?: any): string; - getAdapters(): any; - getMapper(name: string): Mapper; - getMapperByName(name: string): Mapper; - registerAdapter(name: string, adapter: any, opts?: any): void -} -declare export class SimpleStore mixins Container { - collectionClass: typeof Collection; - _collections: Object; - _pendingQueries: Object; - _completedQueries: Object; - usePendingFind: boolean; - usePendingFindAll: boolean; - as(name: string): Mapper | Collection; - constructor(opts?: any): this; - add(mapperName: string, records: any[] | any, opts?: any): any[] | any; - addToCache(mapperName: string, data: any, opts: any): any; - between(mapperName: string, leftKeys: any, rightKeys: any, opts?: any): any[]; - cachedFind(mapperName: string, id: string | number, opts: any): any; - cachedFindAll(mapperName: string, hash: string, opts: any): any; - cacheFind(mapperName: string, data: any, id: string | number, opts: any): void; - cacheFindAll(mapperName: string, data: any, hash: string, opts: any): void; - clear(): any; - createIndex(mapperName: string, name: any, fieldList: any, opts?: any): Collection; - filter(mapperName: string, query: any, thisArg?: any): any[]; - get(mapperName: string, id: string | number): any; - getAll(mapperName: string, ...args: any[]): any[]; - query(mapperName: string): Query; - remove(mapperName: string, id: string | number, opts?: any): any; - removeAll(mapperName: string, query?: any, opts?: any): void | any[]; - toJson(mapperName: string, opts?: any): any[]; - _callSuper(method: string, ...args: any[]): any; - _end(mapperName: string, data: any, opts?: any): any; - create(mapperName: string, record: any, opts?: any): Promise; - createMany(mapperName: string, records: any, opts?: any): Promise; - defineMapper(mapperName: string, opts?: any): Mapper; - destroy(mapperName: string, id: any, opts?: any): Promise; - destroyAll(mapperName: string, query?: any, opts?: any): Promise; - find(mapperName: string, id: any, opts?: any): Promise; - findAll(mapperName: string, query?: any, opts?: any): Promise; - cachedFind(mapperName: string, id: any, opts?: any): any; - cachedFindAll(mapperName: string, query: any, opts?: any): any; - hashQuery(mapperName: string, query: any, opts?: any): string; - getCollection(mapperName: string): Collection; - update(mapperName: string, id: any, record: any, opts?: any): Promise; - updateAll(mapperName: string, props: any, query?: any, opts?: any): Promise; - updateMany(mapperName: string, records: any, opts?: any): Promise -} -declare export class DataStore mixins SimpleStore { - collectionClass: typeof LinkedCollection; - as(name: string): Mapper | LinkedCollection; - createIndex(mapperName: string, name: any, fieldList: any, opts?: any): LinkedCollection; - getCollection(mapperName: string): LinkedCollection -} -declare export class Query mixins Component { - ops: { == - (value: any, predicate: any): boolean, - === - (value: any, predicate: any): boolean, - != - (value: any, predicate: any): boolean, - !== - (value: any, predicate: any): boolean, - > - (value: any, predicate: any): boolean, - >= - (value: any, predicate: any): boolean, - < - (value: any, predicate: any): boolean, - <= - (value: any, predicate: any): boolean, - isectEmpty(value: any, predicate: any): boolean, - isectNotEmpty(value: any, predicate: any): number, - in (value: any, predicate: any): boolean, - notIn(value: any, predicate: any): boolean, - contains(value: any, predicate: any): boolean, - notContains(value: any, predicate: any): boolean - }; - collection: Collection | LinkedCollection; - data: any[]; - constructor(collection?: Collection): this; - compare(orderBy: any, index: any, a: any, b: any): any; - evaluate(value: any, op: string, predicate: any): boolean; - like(pattern: any, flags: any): RegExp; - getData(): any[]; - between(leftKeys: any, rightKeys: any, opts?: any): this; - get(keyList?: any[], opts?: any): this; - getAll(...args: any[]): this; - filter(query: any, thisArg?: any): this; - skip(num: number): this; - limit(num: number): this; - forEach(forEachFn: Function, thisArg?: any): this; - map(mapFn: Function, thisArg?: any): this; - mapCall(funcName: string, ...args: any[]): this; - run(): any[] -} -declare export interface SchemaValidationError { - expected: any, - actual: string, - path: string -} -declare export class Schema mixins Component { - types: { - array(value: any): boolean, - boolean(value: any): boolean, - integer(value: any): boolean, - null(value: any): boolean, - number(value: any): boolean, - object(value: any): boolean, - string(value: any): boolean - }; - typeGroupValidators: { - array(value: any, schema: any, opts: any): SchemaValidationError[], - integer(value: any, schema: any, opts: any): SchemaValidationError[], - number(value: any, schema: any, opts: any): SchemaValidationError[], - numeric(value: any, schema: any, opts: any): SchemaValidationError[], - object(value: any, schema: any, opts: any): SchemaValidationError[], - string(value: any, schema: any, opts: any): SchemaValidationError[] - }; - validationKeywords: { - allOf(value: any, schema: any, opts: any): SchemaValidationError[], - anyOf(value: any, schema: any, opts: any): SchemaValidationError[], - dependencies(value: any, schema: any, opts: any): void, - enum(value: any, schema: any, opts: any): SchemaValidationError, - items(value: any, schema: any, opts: any): SchemaValidationError[], - maximum(value: any, schema: any, opts: any): SchemaValidationError, - maxItems(value: any, schema: any, opts: any): SchemaValidationError, - maxLength(value: any, schema: any, opts: any): SchemaValidationError, - maxProperties(value: any, schema: any, opts: any): SchemaValidationError, - minimum(value: any, schema: any, opts: any): SchemaValidationError, - minItems(value: any, schema: any, opts: any): SchemaValidationError, - minLength(value: any, schema: any, opts: any): SchemaValidationError, - minProperties(value: any, schema: any, opts: any): SchemaValidationError, - multipleOf(value: any, schema: any, opts: any): SchemaValidationError, - not(value: any, schema: any, opts: any): SchemaValidationError, - oneOf(value: any, schema: any, opts: any): SchemaValidationError[], - pattern(value: any, schema: any, opts: any): SchemaValidationError, - properties(value: any, schema: any, opts: any): SchemaValidationError[], - required(value: any, schema: any, opts: any): SchemaValidationError[], - type(value: any, schema: any, opts: any): SchemaValidationError, - uniqueItems(value: any, schema: any, opts: any): SchemaValidationError - }; - validate(value: any, schema: any, opts: any): SchemaValidationError[]; - properties: any; - constructor(definition: any): this; - apply(target: any, opts?: any): void; - applyDefaults(target: any): void; - makeDescriptor(prop: string, schema: Schema, opts?: any): any; - pick(value: any): any; - validate(value: any, opts?: any): SchemaValidationError[] -} -declare export class Index { - fieldList: string[]; - fieldGetter: Function; - hashCode: Function; - isIndex: boolean; - keys: any[]; - values: any[]; - constructor(fieldList: string[], opts?: any): this; - set(keyList: any[], value: any): void; - get(keyList: any[]): any; - getAll(): any[]; - visitAll(cb: Function, thisArg?: any): void; - between(leftKeys: any, rightKeys: any, opts?: any): any[]; - _between(leftKeys: any, rightKeys: any, opts: any): any[]; - peek(): any; - clear(): void; - insertRecord(data: any): void; - removeRecord(data: any): any; - updateRecord(data: any): void -} -declare export var belongsToType: string; -declare export var hasManyType: string; -declare export var hasOneType: string; -declare export var belongsTo: (related: any, opts: any) => (target: any) => void; -declare export var hasMany: (related: any, opts: any) => (target: any) => void; -declare export var hasOne: (related: any, opts: any) => (target: any) => void; diff --git a/dist/js-data.es2015.js b/dist/js-data.es2015.js index 886f6f8d..d038f451 100644 --- a/dist/js-data.es2015.js +++ b/dist/js-data.es2015.js @@ -1,14524 +1,12399 @@ /*! * js-data -* @version 3.0.6 - Homepage +* @version 4.0.0-beta.4 - Homepage * @author js-data project authors * @copyright (c) 2014-2016 js-data project authors * @license MIT * * @overview js-data is a framework-agnostic, datastore-agnostic ORM/ODM for Node.js and the Browser. */ -function _typeof(obj) { - if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { - _typeof = function (obj) { - return typeof obj; - }; - } else { - _typeof = function (obj) { - return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; - }; - } - - return _typeof(obj); -} - -function _defineProperty(obj, key, value) { - if (key in obj) { - Object.defineProperty(obj, key, { - value: value, - enumerable: true, - configurable: true, - writable: true - }); - } else { - obj[key] = value; - } - - return obj; -} - -function _toConsumableArray(arr) { - return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); -} - -function _arrayWithoutHoles(arr) { - if (Array.isArray(arr)) { - for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; - - return arr2; - } -} - -function _iterableToArray(iter) { - if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); -} - -function _nonIterableSpread() { - throw new TypeError("Invalid attempt to spread non-iterable instance"); -} - -/** - * Utility methods used by JSData. - * - * @example - * import { utils } from 'js-data'; - * console.log(utils.isString('foo')); // true - * - * @namespace utils - * @type {Object} - */ -var DOMAIN = 'utils'; -var INFINITY = 1 / 0; -var MAX_INTEGER = 1.7976931348623157e308; -var BOOL_TAG = '[object Boolean]'; -var DATE_TAG = '[object Date]'; -var FUNC_TAG = '[object Function]'; -var NUMBER_TAG = '[object Number]'; -var OBJECT_TAG = '[object Object]'; -var REGEXP_TAG = '[object RegExp]'; -var STRING_TAG = '[object String]'; -var objToString = Object.prototype.toString; -var PATH = /^(.+)\.(.+)$/; -var ERRORS = { - '400': function _() { - return "expected: ".concat(arguments[0], ", found: ").concat(arguments[2] ? arguments[1] : _typeof(arguments[1])); - }, - '404': function _() { - return "".concat(arguments[0], " not found"); - } +/** + * Utility methods used by JSData. + * + * @example + * import { utils } from 'js-data'; + * console.log(utils.isString('foo')); // true + * + * @namespace utils + * @type {Object} + */ +const DOMAIN = 'utils'; +const INFINITY = 1 / 0; +const MAX_INTEGER = 1.7976931348623157e308; +const BOOL_TAG = '[object Boolean]'; +const DATE_TAG = '[object Date]'; +const FUNC_TAG = '[object Function]'; +const NUMBER_TAG = '[object Number]'; +const OBJECT_TAG = '[object Object]'; +const REGEXP_TAG = '[object RegExp]'; +const STRING_TAG = '[object String]'; +const objToString = Object.prototype.toString; +const PATH = /^(.+)\.(.+)$/; +const ERRORS = { + '400'(...args) { + return `expected: ${args[0]}, found: ${args[2] ? args[1] : typeof args[1]}`; + }, + '404'(...args) { + return `${args[0]} not found`; + } +}; +const toInteger = value => { + if (!value) { + return 0; + } + // Coerce to number + value = +value; + if (value === INFINITY || value === -INFINITY) { + const sign = value < 0 ? -1 : 1; + return sign * MAX_INTEGER; + } + const remainder = value % 1; + return value === value ? (remainder ? value - remainder : value) : 0; // eslint-disable-line +}; +const toStr = value => objToString.call(value); +const isPlainObject = value => !!value && typeof value === 'object' && value.constructor === Object; +const mkdirP = (object, path) => { + if (!path) { + return object; + } + const parts = path.split('.'); + parts.forEach(key => { + if (!object[key]) { + object[key] = {}; + } + object = object[key]; + }); + return object; +}; +const utils = { + /** + * Shallow copy properties that meet the following criteria from `src` to + * `dest`: + * + * - own enumerable + * - not a function + * - does not start with "_" + * + * @method utils._ + * @param {object} dest Destination object. + * @param {object} src Source object. + * @private + * @since 3.0.0 + */ + _(dest, src) { + utils.forOwn(src, (value, key) => { + if (key && dest[key] === undefined && !utils.isFunction(value) && key.indexOf('_') !== 0) { + dest[key] = value; + } + }); + }, + /** + * Recursively iterates over relations found in `opts.with`. + * + * @method utils._forRelation + * @param {object} opts Configuration options. + * @param {Relation} def Relation definition. + * @param {Function} fn Callback function. + * @param {*} [thisArg] Execution context for the callback function. + * @private + * @since 3.0.0 + */ + _forRelation(opts = {}, def, fn, thisArg) { + const relationName = def.relation; + let containedName = null; + let index; + opts.with = opts.with || []; + if ((index = utils._getIndex(opts.with, relationName)) >= 0) { + containedName = relationName; + } + else if ((index = utils._getIndex(opts.with, def.localField)) >= 0) { + containedName = def.localField; + } + if (opts.withAll) { + fn.call(thisArg, def, {}); + return; + } + else if (!containedName) { + return; + } + const optsCopy = {}; + utils.fillIn(optsCopy, def.getRelation()); + utils.fillIn(optsCopy, opts); + optsCopy.with = opts.with.slice(); + optsCopy._activeWith = optsCopy.with.splice(index, 1)[0]; + optsCopy.with.forEach((relation, i) => { + if (relation && + relation.indexOf(containedName) === 0 && + relation.length >= containedName.length && + relation[containedName.length] === '.') { + optsCopy.with[i] = relation.substr(containedName.length + 1); + } + else { + optsCopy.with[i] = ''; + } + }); + fn.call(thisArg, def, optsCopy); + }, + /** + * Find the index of a relation in the given list + * + * @method utils._getIndex + * @param {string[]} list List to search. + * @param {string} relation Relation to find. + * @private + * @returns {number} + */ + _getIndex(list, relation) { + let index = -1; + list.forEach((_relation, i) => { + if (_relation === relation) { + index = i; + return false; + } + else if (utils.isObject(_relation)) { + if (_relation.relation === relation) { + index = i; + return false; + } + } + }); + return index; + }, + /** + * Define hidden (non-enumerable), writable properties on `target` from the + * provided `props`. + * + * @example + * import { utils } from 'js-data'; + * function Cat () {} + * utils.addHiddenPropsToTarget(Cat.prototype, { + * say () { + * console.log('meow'); + * } + * }); + * const cat = new Cat(); + * cat.say(); // "meow" + * + * @method utils.addHiddenPropsToTarget + * @param {object} target That to which `props` should be added. + * @param {object} props Properties to be added to `target`. + * @since 3.0.0 + */ + addHiddenPropsToTarget(target, props) { + const map = {}; + Object.keys(props).forEach(propName => { + const descriptor = Object.getOwnPropertyDescriptor(props, propName); + descriptor.enumerable = false; + map[propName] = descriptor; + }); + Object.defineProperties(target, map); + }, + /** + * Return whether the two objects are deeply different. + * + * @example + * import { utils } from 'js-data'; + * utils.areDifferent({}, {}); // false + * utils.areDifferent({ a: 1 }, { a: 1 }); // false + * utils.areDifferent({ foo: 'bar' }, {}); // true + * + * @method utils.areDifferent + * @param newObject + * @param oldObject + * @param {object} [opts] Configuration options. + * @param {Function} [opts.equalsFn={@link utils.deepEqual}] Equality function. + * @param {array} [opts.ignore=[]] Array of strings or RegExp of fields to ignore. + * @returns {boolean} Whether the two objects are deeply different. + * @see utils.diffObjects + * @since 3.0.0 + */ + areDifferent(newObject, oldObject, opts = {}) { + const diff = utils.diffObjects(newObject, oldObject, opts); + const diffCount = Object.keys(diff.added).length + Object.keys(diff.removed).length + Object.keys(diff.changed).length; + return diffCount > 0; + }, + /** + * Deep copy a value. + * + * @example + * import { utils } from 'js-data'; + * const a = { foo: { bar: 'baz' } }; + * const b = utils.copy(a); + * a === b; // false + * utils.areDifferent(a, b); // false + * + * @param {*} from Value to deep copy. + * @param {*} [to] Destination object for the copy operation. + * @param {*} [stackFrom] For internal use. + * @param {*} [stackTo] For internal use. + * @param {string[]|RegExp[]} [blacklist] List of strings or RegExp of + * properties to skip. + * @param {boolean} [plain] Whether to make a plain copy (don't try to use + * original prototype). + * @returns {*} Deep copy of `from`. + * @since 3.0.0 + */ + copy(from, to, stackFrom, stackTo, blacklist, plain) { + if (!to) { + to = from; + if (from) { + if (utils.isArray(from)) { + to = utils.copy(from, [], stackFrom, stackTo, blacklist, plain); + } + else if (utils.isDate(from)) { + to = new Date(from.getTime()); + } + else if (utils.isRegExp(from)) { + to = new RegExp(from.source, from.toString().match(/[^/]*$/)[0]); + to.lastIndex = from.lastIndex; + } + else if (utils.isObject(from)) { + if (plain) { + to = utils.copy(from, {}, stackFrom, stackTo, blacklist, plain); + } + else { + to = utils.copy(from, Object.create(Object.getPrototypeOf(from)), stackFrom, stackTo, blacklist, plain); + } + } + } + } + else { + if (from === to) { + throw utils.err(`${DOMAIN}.copy`)(500, 'Cannot copy! Source and destination are identical.'); + } + stackFrom = stackFrom || []; + stackTo = stackTo || []; + if (utils.isObject(from)) { + const index = stackFrom.indexOf(from); + if (index !== -1) { + return stackTo[index]; + } + stackFrom.push(from); + stackTo.push(to); + } + let result; + if (utils.isArray(from)) { + let i; + to.length = 0; + for (i = 0; i < from.length; i++) { + result = utils.copy(from[i], null, stackFrom, stackTo, blacklist, plain); + if (utils.isObject(from[i])) { + stackFrom.push(from[i]); + stackTo.push(result); + } + to.push(result); + } + } + else { + if (utils.isArray(to)) { + to.length = 0; + } + else { + utils.forOwn(to, (value, key) => { + delete to[key]; + }); + } + for (const key in from) { + if (from.hasOwnProperty(key)) { + if (utils.isBlacklisted(key, blacklist)) { + continue; + } + result = utils.copy(from[key], null, stackFrom, stackTo, blacklist, plain); + if (utils.isObject(from[key])) { + stackFrom.push(from[key]); + stackTo.push(result); + } + to[key] = result; + } + } + } + } + return to; + }, + /** + * Recursively shallow fill in own enumerable properties from `source` to + * `dest`. + * + * @example + * import { utils } from 'js-data'; + * const a = { foo: { bar: 'baz' }, beep: 'boop' }; + * const b = { beep: 'bip' }; + * utils.deepFillIn(b, a); + * console.log(b); // {"foo":{"bar":"baz"},"beep":"bip"} + * + * @method utils.deepFillIn + * @param {object} dest The destination object. + * @param {object} source The source object. + * @see utils.fillIn + * @see utils.deepMixIn + * @since 3.0.0 + */ + deepFillIn(dest, source) { + if (source) { + utils.forOwn(source, (value, key) => { + const existing = dest[key]; + if (isPlainObject(value) && isPlainObject(existing)) { + utils.deepFillIn(existing, value); + } + else if (!dest.hasOwnProperty(key) || dest[key] === undefined) { + dest[key] = value; + } + }); + } + return dest; + }, + /** + * Recursively shallow copy enumerable properties from `source` to `dest`. + * + * @example + * import { utils } from 'js-data'; + * const a = { foo: { bar: 'baz' }, beep: 'boop' }; + * const b = { beep: 'bip' }; + * utils.deepFillIn(b, a); + * console.log(b); // {"foo":{"bar":"baz"},"beep":"boop"} + * + * @method utils.deepMixIn + * @param {object} dest The destination object. + * @param {object} source The source object. + * @see utils.fillIn + * @see utils.deepFillIn + * @since 3.0.0 + */ + deepMixIn(dest, source) { + if (source) { + // tslint:disable-next-line:forin + for (const key in source) { + const value = source[key]; + const existing = dest[key]; + if (isPlainObject(value) && isPlainObject(existing)) { + utils.deepMixIn(existing, value); + } + else { + dest[key] = value; + } + } + } + return dest; + }, + /** + * Return a diff of the base object to the comparison object. + * + * @example + * import { utils } from 'js-data'; + * const oldObject = { foo: 'bar', a: 1234 }; + * const newObject = { beep: 'boop', a: 5678 }; + * const diff = utils.diffObjects(oldObject, newObject); + * console.log(diff.added); // {"beep":"boop"} + * console.log(diff.changed); // {"a":5678} + * console.log(diff.removed); // {"foo":undefined} + * + * @method utils.diffObjects + * @param {object} newObject Comparison object. + * @param {object} oldObject Base object. + * @param {object} [opts] Configuration options. + * @param {Function} [opts.equalsFn={@link utils.deepEqual}] Equality function. + * @param {array} [opts.ignore=[]] Array of strings or RegExp of fields to ignore. + * @returns {Object} The diff from the base object to the comparison object. + * @see utils.areDifferent + * @since 3.0.0 + */ + diffObjects(newObject, oldObject, opts = {}) { + let equalsFn = opts.equalsFn; + const blacklist = opts.ignore; + const diff = { + added: {}, + changed: {}, + removed: {} + }; + if (!utils.isFunction(equalsFn)) { + equalsFn = utils.deepEqual; + } + const newKeys = Object.keys(newObject).filter(key => !utils.isBlacklisted(key, blacklist)); + const oldKeys = Object.keys(oldObject).filter(key => !utils.isBlacklisted(key, blacklist)); + // Check for properties that were added or changed + newKeys.forEach(key => { + const oldValue = oldObject[key]; + const newValue = newObject[key]; + if (equalsFn(oldValue, newValue)) { + return; + } + if (oldValue === undefined) { + diff.added[key] = newValue; + } + else { + diff.changed[key] = newValue; + } + }); + // Check for properties that were removed + oldKeys.forEach(key => { + const oldValue = oldObject[key]; + const newValue = newObject[key]; + if (newValue === undefined && oldValue !== undefined) { + diff.removed[key] = undefined; + } + }); + return diff; + }, + /** + * Return whether the two values are equal according to the `==` operator. + * + * @example + * import { utils } from 'js-data'; + * console.log(utils.equal(1,1)); // true + * console.log(utils.equal(1,'1')); // true + * console.log(utils.equal(93, 66)); // false + * + * @method utils.equal + * @param {*} a First value in the comparison. + * @param {*} b Second value in the comparison. + * @returns {boolean} Whether the two values are equal according to `==`. + * @since 3.0.0 + */ + equal(a, b) { + // tslint:disable-next-line:triple-equals + return a == b; // eslint-disable-line + }, + /** + * Produce a factory function for making Error objects with the provided + * metadata. Used throughout the various js-data components. + * + * @example + * import { utils } from 'js-data'; + * const errorFactory = utils.err('domain', 'target'); + * const error400 = errorFactory(400, 'expected type', 'actual type'); + * console.log(error400); // [Error: [domain:target] expected: expected type, found: string + * http://www.js-data.io/v3.0/docs/errors#400] + * @method utils.err + * @param {string} domain Namespace. + * @param {string} target Target. + * @returns {Function} Factory function. + * @since 3.0.0 + */ + err(domain, target) { + return (code, ...args) => { + const prefix = `[${domain}:${target}] `; + let message = ERRORS[code].apply(null, args); + message = `${prefix}${message} +http://www.js-data.io/v3.0/docs/errors#${code}`; + return new Error(message); + }; + }, + /** + * Add eventing capabilities into the target object. + * + * @example + * import { utils } from 'js-data'; + * const user = { name: 'John' }; + * utils.eventify(user); + * user.on('foo', () => console.log(arguments)); + * user.emit('foo', 1, 'bar'); // should log to console values (1, "bar") + * + * @method utils.eventify + * @param {object} target Target object. + * @param {Function} [getter] Custom getter for retrieving the object's event + * listeners. + * @param {Function} [setter] Custom setter for setting the object's event + * listeners. + * @since 3.0.0 + */ + eventify(target, getter, setter) { + target = target || this; + let _events = {}; + if (!getter && !setter) { + getter = () => _events; + setter = value => (_events = value); + } + Object.defineProperties(target, { + emit: { + value(...args) { + const events = getter.call(this) || {}; + const type = args.shift(); + let listeners = events[type] || []; + let i; + for (i = 0; i < listeners.length; i++) { + listeners[i].f.apply(listeners[i].c, args); + } + listeners = events.all || []; + args.unshift(type); + for (i = 0; i < listeners.length; i++) { + listeners[i].f.apply(listeners[i].c, args); + } + } + }, + off: { + value(type, func) { + const events = getter.call(this); + const listeners = events[type]; + if (!listeners) { + setter.call(this, {}); + } + else if (func) { + for (let i = 0; i < listeners.length; i++) { + if (listeners[i].f === func) { + listeners.splice(i, 1); + break; + } + } + } + else { + listeners.splice(0, listeners.length); + } + } + }, + on: { + value(type, func, thisArg) { + if (!getter.call(this)) { + setter.call(this, {}); + } + const events = getter.call(this); + events[type] = events[type] || []; + events[type].push({ + c: thisArg, + f: func + }); + } + } + }); + }, + /** + * Shallow copy own enumerable properties from `src` to `dest` that are on + * `src` but are missing from `dest. + * + * @example + * import { utils } from 'js-data'; + * const a = { foo: 'bar', beep: 'boop' }; + * const b = { beep: 'bip' }; + * utils.fillIn(b, a); + * console.log(b); // {"foo":"bar","beep":"bip"} + * + * @method utils.fillIn + * @param {object} dest The destination object. + * @param src + * @see utils.deepFillIn + * @see utils.deepMixIn + * @since 3.0.0 + */ + fillIn(dest, src) { + utils.forOwn(src, (value, key) => { + if (!dest.hasOwnProperty(key) || dest[key] === undefined) { + dest[key] = value; + } + }); + }, + /** + * Find the last index of an item in an array according to the given checker function. + * + * @example + * import { utils } from 'js-data'; + * + * const john = { name: 'John', age: 20 }; + * const sara = { name: 'Sara', age: 25 }; + * const dan = { name: 'Dan', age: 20 }; + * const users = [john, sara, dan]; + * + * console.log(utils.findIndex(users, (user) => user.age === 25)); // 1 + * console.log(utils.findIndex(users, (user) => user.age > 19)); // 2 + * console.log(utils.findIndex(users, (user) => user.name === 'John')); // 0 + * console.log(utils.findIndex(users, (user) => user.name === 'Jimmy')); // -1 + * + * @method utils.findIndex + * @param {array} array The array to search. + * @param {Function} fn Checker function. + * @returns {number} Index if found or -1 if not found. + * @since 3.0.0 + */ + findIndex(array, fn) { + let index = -1; + if (!array) { + return index; + } + array.forEach((record, i) => { + if (fn(record)) { + index = i; + return false; + } + }); + return index; + }, + /** + * Recursively iterate over a {@link Mapper}'s relations according to + * `opts.with`. + * + * @method utils.forEachRelation + * @param {Mapper} mapper Mapper. + * @param {object} opts Configuration options. + * @param {Function} fn Callback function. + * @param {*} thisArg Execution context for the callback function. + * @since 3.0.0 + */ + forEachRelation(mapper, opts, fn, thisArg) { + const relationList = mapper.relationList || []; + if (!relationList.length) { + return; + } + relationList.forEach(def => { + utils._forRelation(opts, def, fn, thisArg); + }); + }, + /** + * Iterate over an object's own enumerable properties. + * + * @example + * import { utils } from 'js-data'; + * const a = { b: 1, c: 4 }; + * let sum = 0; + * utils.forOwn(a, function (value, key) { + * sum += value; + * }); + * console.log(sum); // 5 + * + * @method utils.forOwn + * @param obj + * @param {Function} fn Iteration function. + * @param {object} [thisArg] Content to which to bind `fn`. + * @since 3.0.0 + */ + forOwn(obj, fn, thisArg) { + const keys = Object.keys(obj); + const len = keys.length; + let i; + for (i = 0; i < len; i++) { + if (fn.call(thisArg, obj[keys[i]], keys[i], obj) === false) { + break; + } + } + }, + /** + * Proxy for `JSON.parse`. + * + * @example + * import { utils } from 'js-data'; + * + * const a = utils.fromJson('{"name" : "John"}'); + * console.log(a); // { name: 'John' } + * + * @method utils.fromJson + * @param {string} json JSON to parse. + * @returns {Object} Parsed object. + * @see utils.toJson + * @since 3.0.0 + */ + fromJson(json) { + return utils.isString(json) ? JSON.parse(json) : json; + }, + /** + * Retrieve the specified property from the given object. Supports retrieving + * nested properties. + * + * @example + * import { utils } from 'js-data'; + * const a = { foo: { bar: 'baz' }, beep: 'boop' }; + * console.log(utils.get(a, 'beep')); // "boop" + * console.log(utils.get(a, 'foo.bar')); // "baz" + * + * @method utils.get + * @param {object} object Object from which to retrieve a property's value. + * @param {string} prop Property to retrieve. + * @returns {*} Value of the specified property. + * @see utils.set + * @since 3.0.0 + */ + get(object, prop) { + if (!prop) { + return; + } + /* if prop is function, get the property by calling a function, passing an object as a parameter */ + if (utils.isFunction(prop)) { + return prop(object); + } + const parts = prop.split('.'); + const last = parts.pop(); + while ((prop = parts.shift())) { + // eslint-disable-line + object = object[prop]; + if (object == null) { + // eslint-disable-line + return; + } + } + return object[last]; + }, + /** + * Return the superclass for the given instance or subclass. If an instance is + * provided, then finds the parent class of the instance's constructor. + * + * @example + * import { utils } from 'js-data'; + * // using ES2015 classes + * class Foo {} + * class Bar extends Foo {} + * const barInstance = new Bar(); + * let baseType = utils.getSuper(barInstance); + * console.log(Foo === baseType); // true + * + * // using Function constructor with utils.extend + * function Foo () {} + * Foo.extend = utils.extend; + * const Bar = Foo.extend(); + * const barInstance = new Bar(); + * let baseType = utils.getSuper(barInstance); + * console.log(Foo === baseType); // true + * + * @method utils.getSuper + * @param {Object|Function} instance Instance or constructor. + * @param {boolean} [isCtor=false] Whether `instance` is a constructor. + * @returns {Constructor} The superclass (grandparent constructor). + * @since 3.0.0 + */ + getSuper(instance, isCtor) { + const ctor = isCtor ? instance : instance.constructor; + if (ctor.hasOwnProperty('__super__')) { + return ctor.__super__; + } + return Object.getPrototypeOf(ctor) || ctor.__proto__; // eslint-disable-line + }, + /** + * Return the intersection of two arrays. + * + * @example + * import { utils } from 'js-data'; + * const arrA = ['green', 'red', 'blue', 'red']; + * const arrB = ['green', 'yellow', 'red']; + * const intersected = utils.intersection(arrA, arrB); + * + * console.log(intersected); // ['green', 'red']) + * + * @method utils.intersection + * @param {array} array1 First array. + * @param {array} array2 Second array. + * @returns {Array} Array of elements common to both arrays. + * @since 3.0.0 + */ + intersection(array1, array2) { + if (!array1 || !array2) { + return []; + } + array1 = Array.isArray(array1) ? array1 : [array1]; + array2 = Array.isArray(array2) ? array2 : [array2]; + const result = []; + let item; + let i; + const len = array1.length; + for (i = 0; i < len; i++) { + item = array1[i]; + if (result.indexOf(item) !== -1) { + continue; + } + if (array2.indexOf(item) !== -1) { + result.push(item); + } + } + return result; + }, + /** + * Proxy for `Array.isArray`. + * + * @example + * import { utils } from 'js-data'; + * const a = [1,2,3,4,5]; + * const b = { foo: "bar" }; + * console.log(utils.isArray(a)); // true + * console.log(utils.isArray(b)); // false + * + * @method utils.isArray + * @param {*} value The value to test. + * @returns {boolean} Whether the provided value is an array. + * @since 3.0.0 + */ + isArray: Array.isArray, + /** + * Return whether `prop` is matched by any string or regular expression in + * `blacklist`. + * + * @example + * import { utils } from 'js-data'; + * const blacklist = [/^\$hashKey/g, /^_/g, 'id']; + * console.log(utils.isBlacklisted("$hashKey", blacklist)); // true + * console.log(utils.isBlacklisted("id", blacklist)); // true + * console.log(utils.isBlacklisted("_myProp", blacklist)); // true + * console.log(utils.isBlacklisted("my_id", blacklist)); // false + * + * @method utils.isBlacklisted + * @param {string} prop The name of a property to check. + * @param {array} blacklist Array of strings and regular expressions. + * @returns {boolean} Whether `prop` was matched. + * @since 3.0.0 + */ + isBlacklisted(prop, blacklist) { + if (!blacklist || !blacklist.length) { + return false; + } + let matches; + for (const item of blacklist) { + if ((toStr(item) === REGEXP_TAG && item.test(prop)) || item === prop) { + matches = prop; + return !!matches; + } + } + return !!matches; + }, + /** + * Return whether the provided value is a boolean. + * + * @example + * import { utils } from 'js-data'; + * const a = true; + * const b = { foo: "bar" }; + * console.log(utils.isBoolean(a)); // true + * console.log(utils.isBoolean(b)); // false + * + * @method utils.isBoolean + * @param {*} value The value to test. + * @returns {boolean} Whether the provided value is a boolean. + * @since 3.0.0 + */ + isBoolean(value) { + return toStr(value) === BOOL_TAG; + }, + /** + * Return whether the provided value is a date. + * + * @example + * import { utils } from 'js-data'; + * const a = new Date(); + * const b = { foo: "bar" }; + * console.log(utils.isDate(a)); // true + * console.log(utils.isDate(b)); // false + * + * @method utils.isDate + * @param {*} value The value to test. + * @returns {Date} Whether the provided value is a date. + * @since 3.0.0 + */ + isDate(value) { + return value && typeof value === 'object' && toStr(value) === DATE_TAG; + }, + /** + * Return whether the provided value is a function. + * + * @example + * import { utils } from 'js-data'; + * const a = function () { console.log('foo bar'); }; + * const b = { foo: "bar" }; + * console.log(utils.isFunction(a)); // true + * console.log(utils.isFunction(b)); // false + * + * @method utils.isFunction + * @param {*} value The value to test. + * @returns {boolean} Whether the provided value is a function. + * @since 3.0.0 + */ + isFunction(value) { + return typeof value === 'function' || (value && toStr(value) === FUNC_TAG); + }, + /** + * Return whether the provided value is an integer. + * + * @example + * import { utils } from 'js-data'; + * const a = 1; + * const b = 1.25; + * const c = '1'; + * console.log(utils.isInteger(a)); // true + * console.log(utils.isInteger(b)); // false + * console.log(utils.isInteger(c)); // false + * + * @method utils.isInteger + * @param {*} value The value to test. + * @returns {boolean} Whether the provided value is an integer. + * @since 3.0.0 + */ + isInteger(value) { + // tslint:disable-next-line:triple-equals + return toStr(value) === NUMBER_TAG && value == toInteger(value); // eslint-disable-line + }, + /** + * Return whether the provided value is `null`. + * + * @example + * import { utils } from 'js-data'; + * const a = null; + * const b = { foo: "bar" }; + * console.log(utils.isNull(a)); // true + * console.log(utils.isNull(b)); // false + * + * @method utils.isNull + * @param {*} value The value to test. + * @returns {boolean} Whether the provided value is `null`. + * @since 3.0.0 + */ + isNull(value) { + return value === null; + }, + /** + * Return whether the provided value is a number. + * + * @example + * import { utils } from 'js-data'; + * const a = 1; + * const b = -1.25; + * const c = '1'; + * console.log(utils.isNumber(a)); // true + * console.log(utils.isNumber(b)); // true + * console.log(utils.isNumber(c)); // false + * + * @method utils.isNumber + * @param {*} value The value to test. + * @returns {boolean} Whether the provided value is a number. + * @since 3.0.0 + */ + isNumber(value) { + const type = typeof value; + return type === 'number' || (value && type === 'object' && toStr(value) === NUMBER_TAG); + }, + /** + * Return whether the provided value is an object. + * + * @example + * import { utils } from 'js-data'; + * const a = { foo: "bar" }; + * const b = 'foo bar'; + * console.log(utils.isObject(a)); // true + * console.log(utils.isObject(b)); // false + * + * @method utils.isObject + * @param {*} value The value to test. + * @returns {boolean} Whether the provided value is an object. + * @since 3.0.0 + */ + isObject(value) { + return toStr(value) === OBJECT_TAG; + }, + /** + * Return whether the provided value is a regular expression. + * + * @example + * import { utils } from 'js-data'; + * const a = /^\$.+$/ig; + * const b = new RegExp('^\$.+$', 'ig'); + * const c = { foo: "bar" }; + * console.log(utils.isRegExp(a)); // true + * console.log(utils.isRegExp(b)); // true + * console.log(utils.isRegExp(c)); // false + * + * @method utils.isRegExp + * @param {*} value The value to test. + * @returns {boolean} Whether the provided value is a regular expression. + * @since 3.0.0 + */ + isRegExp(value) { + return toStr(value) === REGEXP_TAG; + }, + /** + * Return whether the provided value is a string or a number. + * + * @example + * import { utils } from 'js-data'; + * console.log(utils.isSorN('')); // true + * console.log(utils.isSorN(-1.65)); // true + * console.log(utils.isSorN('my string')); // true + * console.log(utils.isSorN({})); // false + * console.log(utils.isSorN([1,2,4])); // false + * + * @method utils.isSorN + * @param {*} value The value to test. + * @returns {boolean} Whether the provided value is a string or a number. + * @since 3.0.0 + */ + isSorN(value) { + return utils.isString(value) || utils.isNumber(value); + }, + /** + * Return whether the provided value is a string. + * + * @example + * import { utils } from 'js-data'; + * console.log(utils.isString('')); // true + * console.log(utils.isString('my string')); // true + * console.log(utils.isString(100)); // false + * console.log(utils.isString([1,2,4])); // false + * + * @method utils.isString + * @param {*} value The value to test. + * @returns {boolean} Whether the provided value is a string. + * @since 3.0.0 + */ + isString(value) { + return typeof value === 'string' || (value && typeof value === 'object' && toStr(value) === STRING_TAG); + }, + /** + * Return whether the provided value is a `undefined`. + * + * @example + * import { utils } from 'js-data'; + * const a = undefined; + * const b = { foo: "bar"}; + * console.log(utils.isUndefined(a)); // true + * console.log(utils.isUndefined(b.baz)); // true + * console.log(utils.isUndefined(b)); // false + * console.log(utils.isUndefined(b.foo)); // false + * + * @method utils.isUndefined + * @param {*} value The value to test. + * @returns {boolean} Whether the provided value is a `undefined`. + * @since 3.0.0 + */ + isUndefined(value) { + return value === undefined; + }, + /** + * Mix in logging capabilities to the target. + * + * @example + * import { utils } from 'js-data'; + * const a = { foo: "bar"}; + * + * // Add standard logging to an object + * utils.logify(a); + * a.log('info', 'test log info'); // output 'test log info' to console. + * + * // Toggle debug output of an object + * a.dbg('test debug output'); // does not output because debug is off. + * a.debug = true; + * a.dbg('test debug output'); // output 'test debug output' to console. + * + * @method utils.logify + * @param {*} target The target. + * @since 3.0.0 + */ + logify(target) { + utils.addHiddenPropsToTarget(target, { + dbg(...args) { + if (utils.isFunction(this.log)) { + this.log('debug', ...args); + } + }, + log(level, ...args) { + if (level && !args.length) { + args.push(level); + level = 'debug'; + } + if (level === 'debug' && !this.debug) { + return; + } + const prefix = `${level.toUpperCase()}: (${this.name || this.constructor.name})`; + if (utils.isFunction(console[level])) { + console[level](prefix, ...args); + } + else { + console.log(prefix, ...args); + } + } + }); + }, + /** + * Adds the given record to the provided array only if it's not already in the + * array. + * + * @example + * import { utils } from 'js-data'; + * const colors = ['red', 'green', 'yellow']; + * + * console.log(colors.length); // 3 + * utils.noDupeAdd(colors, 'red'); + * console.log(colors.length); // 3, red already exists + * + * utils.noDupeAdd(colors, 'blue'); + * console.log(colors.length); // 4, blue was added + * + * @method utils.noDupeAdd + * @param {array} array The array. + * @param {*} record The value to add. + * @param {Function} fn Callback function passed to {@link utils.findIndex}. + * @since 3.0.0 + */ + noDupeAdd(array, record, fn) { + if (!array) { + return; + } + const index = this.findIndex(array, fn); + if (index < 0) { + array.push(record); + } + }, + /** + * Return a shallow copy of the provided object, minus the properties + * specified in `keys`. + * + * @example + * import { utils } from 'js-data'; + * const a = { name: 'John', $hashKey: 1214910 }; + * + * let b = utils.omit(a, ['$hashKey']); + * console.log(b); // { name: 'John' } + * + * @method utils.omit + * @param {object} props The object to copy. + * @param {string[]} keys Array of strings, representing properties to skip. + * @returns {Object} Shallow copy of `props`, minus `keys`. + * @since 3.0.0 + */ + omit(props, keys) { + const _props = {}; + utils.forOwn(props, (value, key) => { + if (keys.indexOf(key) === -1) { + _props[key] = value; + } + }); + return _props; + }, + /** + * Return a shallow copy of the provided object, but only include the + * properties specified in `keys`. + * + * @example + * import { utils } from 'js-data'; + * const a = { name: 'John', $hashKey: 1214910 }; + * + * let b = utils.pick(a, ['$hashKey']); + * console.log(b); // { $hashKey: 1214910 } + * + * @method utils.pick + * @param {object} props The object to copy. + * @param {string[]} keys Array of strings, representing properties to keep. + * @returns {Object} Shallow copy of `props`, but only including `keys`. + * @since 3.0.0 + */ + pick(props, keys) { + return keys.reduce((map, key) => { + map[key] = props[key]; + return map; + }, {}); + }, + /** + * Return a plain copy of the given value. + * + * @example + * import { utils } from 'js-data'; + * const a = { name: 'John' }; + * let b = utils.plainCopy(a); + * console.log(a === b); // false + * + * @method utils.plainCopy + * @param {*} value The value to copy. + * @returns {*} Plain copy of `value`. + * @see utils.copy + * @since 3.0.0 + */ + plainCopy(value) { + return utils.copy(value, undefined, undefined, undefined, undefined, true); + }, + /** + * Shortcut for `utils.Promise.reject(value)`. + * + * @example + * import { utils } from 'js-data'; + * + * utils.reject("Testing static reject").then(function (data) { + * // not called + * }).catch(function (reason) { + * console.log(reason); // "Testing static reject" + * }); + * + * @method utils.reject + * @param {*} [value] Value with which to reject the Promise. + * @returns {Promise} Promise reject with `value`. + */ + reject(value) { + return Promise.reject(value); + }, + /** + * Remove the last item found in array according to the given checker function. + * + * @example + * import { utils } from 'js-data'; + * + * const colors = ['red', 'green', 'yellow', 'red']; + * utils.remove(colors, (color) => color === 'red'); + * console.log(colors); // ['red', 'green', 'yellow'] + * + * @method utils.remove + * @param {array} array The array to search. + * @param {Function} fn Checker function. + */ + remove(array, fn) { + if (!array || !array.length) { + return; + } + const index = this.findIndex(array, fn); + if (index >= 0) { + array.splice(index, 1); // todo should this be recursive? + } + }, + /** + * Shortcut for `utils.Promise.resolve(value)`. + * + * @example + * import { utils } from 'js-data'; + * + * utils.resolve("Testing static resolve").then(function (data) { + * console.log(data); // "Testing static resolve" + * }).catch(function (reason) { + * // not called + * }); + * + * @param {*} [value] Value with which to resolve the Promise. + * @returns {Promise} Promise resolved with `value`. + */ + resolve(value) { + return Promise.resolve(value); + }, + /** + * Set the value at the provided key or path. + * + * @example + * import { utils } from 'js-data'; + * + * const john = { + * name: 'John', + * age: 25, + * parent: { + * name: 'John's Mom', + * age: 50 + * } + * }; + * // set value by key + * utils.set(john, 'id', 98); + * console.log(john.id); // 98 + * + * // set value by path + * utils.set(john, 'parent.id', 20); + * console.log(john.parent.id); // 20 + * + * // set value by path/value map + * utils.set(john, { + * 'id': 1098, + * 'parent': { id: 1020 }, + * 'parent.age': '55' + * }); + * console.log(john.id); // 1098 + * console.log(john.parent.id); // 1020 + * console.log(john.parent.age); // 55 + * + * @method utils.set + * @param {object} object The object on which to set a property. + * @param {(string|Object)} path The key or path to the property. Can also + * pass in an object of path/value pairs, which will all be set on the target + * object. + * @param {*} [value] The value to set. + */ + set(object, path, value, opts) { + if (utils.isObject(path)) { + utils.forOwn(path, (value, _path) => { + utils.set(object, _path, value); + }); + } + else { + const parts = PATH.exec(path); + if (parts) { + mkdirP(object, parts[1])[parts[2]] = value; + } + else { + object[path] = value; + } + } + }, + /** + * Check whether the two provided objects are deeply equal. + * + * @example + * import { utils } from 'js-data'; + * + * const objA = { + * name: 'John', + * id: 27, + * nested: { + * item: 'item 1', + * colors: ['red', 'green', 'blue'] + * } + * }; + * + * const objB = { + * name: 'John', + * id: 27, + * nested: { + * item: 'item 1', + * colors: ['red', 'green', 'blue'] + * } + * }; + * + * console.log(utils.deepEqual(a,b)); // true + * objB.nested.colors.add('yellow'); // make a change to a nested object's array + * console.log(utils.deepEqual(a,b)); // false + * + * @method utils.deepEqual + * @param {object} a First object in the comparison. + * @param {object} b Second object in the comparison. + * @returns {boolean} Whether the two provided objects are deeply equal. + * @see utils.equal + * @since 3.0.0 + */ + deepEqual(a, b) { + if (a === b) { + return true; + } + let _equal = true; + if (utils.isArray(a) && utils.isArray(b)) { + if (a.length !== b.length) { + return false; + } + for (let i = a.length; i--;) { + if (!utils.deepEqual(a[i], b[i])) { + // Exit loop early + return false; + } + } + } + else if (utils.isObject(a) && utils.isObject(b)) { + utils.forOwn(a, (value, key) => { + if (!(_equal = utils.deepEqual(value, b[key]))) { + // Exit loop early + return false; + } + }); + if (_equal) { + utils.forOwn(b, (value, key) => { + if (!(_equal = utils.deepEqual(value, a[key]))) { + // Exit loop early + return false; + } + }); + } + } + else { + return false; + } + return _equal; + }, + /** + * Proxy for `JSON.stringify`. + * + * @example + * import { utils } from 'js-data'; + * + * const a = { name: 'John' }; + * let jsonVal = utils.toJson(a); + * console.log(jsonVal); // '{"name" : "John"}' + * + * @method utils.toJson + * @param {*} value Value to serialize to JSON. + * @returns {string} JSON string. + * @see utils.fromJson + * @since 3.0.0 + */ + toJson: JSON.stringify, + /** + * Unset the value at the provided key or path. + * + * @example + * import { utils } from 'js-data'; + * + * const john = { + * name: 'John', + * age: 25, + * parent: { + * name: 'John's Mom', + * age: 50 + * } + * }; + * + * utils.unset(john, age); + * utils.unset(john, parent.age); + * + * console.log(john.age); // null + * console.log(john.parent.age); // null + * + * @method utils.unset + * @param {object} object The object from which to delete the property. + * @param {string} path The key or path to the property. + * @see utils.set + * @since 3.0.0 + */ + unset(object, path) { + const parts = path.split('.'); + const last = parts.pop(); + while ((path = parts.shift())) { + // eslint-disable-line + object = object[path]; + if (object == null) { + // eslint-disable-line + return; + } + } + object[last] = undefined; + }, + /** + * Gets default locale for the js-data context. + * + * @example + * import { utils } from 'js-data'; + * + * + * utils.getDefaultLocale(); + * + * @method utils.getDefaultLocale + * @since 4.0.0 + */ + getDefaultLocale() { + return 'en'; + } +}; +const safeSetProp = (record, field, value) => { + var _a; + if ((_a = record) === null || _a === void 0 ? void 0 : _a._set) { + record._set(`props.${field}`, value); + } + else { + utils.set(record, field, value); + } +}; +const safeSetLink = (record, field, value) => { + var _a; + if ((_a = record) === null || _a === void 0 ? void 0 : _a._set) { + record._set(`links.${field}`, value); + } + else { + utils.set(record, field, value); + } }; -var toInteger = function toInteger(value) { - if (!value) { - return 0; - } // Coerce to number - - - value = +value; - - if (value === INFINITY || value === -INFINITY) { - var sign = value < 0 ? -1 : 1; - return sign * MAX_INTEGER; - } - - var remainder = value % 1; - return value === value ? remainder ? value - remainder : value : 0; // eslint-disable-line -}; - -var toStr = function toStr(value) { - return objToString.call(value); -}; - -var isPlainObject = function isPlainObject(value) { - return !!value && _typeof(value) === 'object' && value.constructor === Object; -}; - -var mkdirP = function mkdirP(object, path) { - if (!path) { - return object; - } +/** + * A base class which gives instances private properties. + * + * Typically you won't instantiate this class directly, but you may find it + * useful as an abstract class for your own components. + * + * @example + * import {Settable} from 'js-data'; + * + * class CustomSettableClass extends Settable { + * foo () { return 'bar'; } + * static beep () { return 'boop'; } + * } + * + * const customSettable = new CustomSettableClass(); + * console.log(customSettable.foo()); + * console.log(CustomSettableClass.beep()); + * + * @since 3.0.0 + */ +class Settable { + constructor() { + const _props = {}; + Object.defineProperties(this, { + _get: { + value(key) { + return utils.get(_props, key); + } + }, + _set: { + value(key, value) { + return utils.set(_props, key, value); + } + }, + _unset: { + value(key) { + return utils.unset(_props, key); + } + } + }); + } +} - var parts = path.split('.'); - parts.forEach(function (key) { - if (!object[key]) { - object[key] = {}; - } +/** + * The base class from which all JSData components inherit some basic + * functionality. + * + * Typically you won't instantiate this class directly, but you may find it + * useful as an abstract class for your own components. + * + * @example + * import {Component} from 'js-data' + * + * class CustomComponentClass extends Component { + * foo () { return 'bar'; } + * static beep () { return 'boop'; } + * } + * const customComponent = new CustomComponentClass(); + * console.log(customComponent.foo()); + * console.log(CustomComponentClass.beep()); + * ``` + * + * @param {object} [opts] Configuration options. + * @param {boolean} [opts.debug=false] See {@link Component#debug}. + * @returns {Component} A new {@link Component} instance. + * @since 3.0.0 + */ +class Component extends Settable { + constructor(opts = {}) { + var _a; + super(); + /** + * Event listeners attached to this Component. __Do not modify.__ Use + * {@link Component#on} and {@link Component#off} instead. + * + * @name Component#_listeners + * @private + * @instance + * @since 3.0.0 + * @type {Object} + */ + this._listeners = {}; + this.debug = (_a = opts.debug, (_a !== null && _a !== void 0 ? _a : false)); + } +} +utils.logify(Component.prototype); +utils.eventify(Component.prototype, function () { + return this._listeners; +}, function (value) { + this._listeners = value; +}); - object = object[key]; - }); - return object; +const DOMAIN$1 = 'Query'; +const INDEX_ERR = 'Index inaccessible after first operation'; +// Reserved words used by JSData's Query Syntax +const reserved = { + limit: '', + offset: '', + orderBy: '', + skip: '', + sort: '', + where: '', + locale: '' +}; +// Used by our JavaScript implementation of the LIKE operator +const escapeRegExp = /([.*+?^=!:${}()|[\]/\\])/g; +const percentRegExp = /%/g; +const underscoreRegExp = /_/g; +function escape(pattern) { + return pattern.replace(escapeRegExp, '\\$1'); +} +/** + * A class used by the {@link Collection} class to build queries to be executed + * against the collection's data. An instance of `Query` is returned by + * {@link Collection#query}. Query instances are typically short-lived, and you + * shouldn't have to create them yourself. Just use {@link Collection#query}. + * + * ```javascript + * import { Query } from 'js-data'; + * ``` + * + * @example Query intro + * const JSData = require('js-data'); + * const { DataStore } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new DataStore(); + * store.defineMapper('post'); + * const posts = [ + * { author: 'John', age: 30, status: 'published', id: 1 }, + * { author: 'Sally', age: 31, status: 'draft', id: 2 }, + * { author: 'Mike', age: 32, status: 'draft', id: 3 }, + * { author: 'Adam', age: 33, status: 'deleted', id: 4 }, + * { author: 'Adam', age: 33, status: 'draft', id: 5 } + * ] + * store.add('post', posts); + * const drafts = store.query('post').filter({ status: 'draft' }).limit(2).run(); + * console.log(drafts); + * + * @class Query + * @extends Component + * @param {Collection} collection The collection on which this query operates. + * @since 3.0.0 + */ +class Query extends Component { + constructor(collection) { + super(); + this.collection = collection; + /** + * The current data result of this query. + * + * @name Query#data + * @since 3.0.0 + * @type {Array} + */ + this.data = null; + } + _applyWhereFromObject(where) { + const fields = []; + const ops = []; + const predicates = []; + utils.forOwn(where, (clause, field) => { + if (!utils.isObject(clause)) { + clause = { + '==': clause + }; + } + utils.forOwn(clause, (expr, op) => { + fields.push(field); + ops.push(op); + predicates.push(expr); + }); + }); + return { + fields, + ops, + predicates + }; + } + _applyWhereFromArray(where) { + const groups = []; + where.forEach((_where, i) => { + if (utils.isString(_where)) { + return; + } + const prev = where[i - 1]; + const parser = utils.isArray(_where) ? this._applyWhereFromArray : this._applyWhereFromObject; + const group = parser.call(this, _where); + if (prev === 'or') { + group.isOr = true; + } + groups.push(group); + }); + groups.isArray = true; + return groups; + } + _testObjectGroup(keep, first, group, item) { + let i; + const fields = group.fields; + const ops = group.ops; + const predicates = group.predicates; + const len = ops.length; + for (i = 0; i < len; i++) { + let op = ops[i]; + const isOr = op.charAt(0) === '|'; + op = isOr ? op.substr(1) : op; + const expr = this.evaluate(utils.get(item, fields[i]), op, predicates[i]); + if (expr !== undefined) { + keep = first ? expr : isOr ? keep || expr : keep && expr; + } + first = false; + } + return { keep, first }; + } + _testArrayGroup(keep, first, groups, item) { + let i; + const len = groups.length; + for (i = 0; i < len; i++) { + const group = groups[i]; + const parser = group.isArray ? this._testArrayGroup : this._testObjectGroup; + const result = parser.call(this, true, true, group, item); + if (groups[i - 1]) { + if (group.isOr) { + keep = keep || result.keep; + } + else { + keep = keep && result.keep; + } + } + else { + keep = result.keep; + } + first = result.first; + } + return { keep, first }; + } + /** + * Find all entities between two boundaries. + * + * @example Get the users ages 18 to 30. + * const JSData = require('js-data'); + * const { DataStore } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new DataStore(); + * store.defineMapper('user'); + * const users = [ + * { name: 'Peter', age: 25, id: 1 }, + * { name: 'Jim', age: 19, id: 2 }, + * { name: 'Mike', age: 17, id: 3 }, + * { name: 'Alan', age: 29, id: 4 }, + * { name: 'Katie', age: 33, id: 5 } + * ]; + * store.add('user', users) + * const filteredUsers = store + * .query('user') + * .between(18, 30, { index: 'age' }) + * .run(); + * console.log(filteredUsers); + * + * @example Same as above. + * const JSData = require('js-data'); + * const { DataStore } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new DataStore(); + * store.defineMapper('user'); + * const users = [ + * { name: 'Peter', age: 25, id: 1 }, + * { name: 'Jim', age: 19, id: 2 }, + * { name: 'Mike', age: 17, id: 3 }, + * { name: 'Alan', age: 29, id: 4 }, + * { name: 'Katie', age: 33, id: 5 } + * ]; + * store.add('user', users) + * const filteredUsers = store + * .query('user') + * .between([18], [30], { index: 'age' }) + * .run(); + * console.log(filteredUsers); + * + * @method Query#between + * @param {array} leftKeys Keys defining the left boundary. + * @param {array} rightKeys Keys defining the right boundary. + * @param {object} [opts] Configuration options. + * @param {string} [opts.index] Name of the secondary index to use in the + * query. If no index is specified, the main index is used. + * @param {boolean} [opts.leftInclusive=true] Whether to include entities + * on the left boundary. + * @param {boolean} [opts.rightInclusive=false] Whether to include entities + * on the left boundary. + * @param {boolean} [opts.limit] Limit the result to a certain number. + * @param {boolean} [opts.offset] The number of resulting entities to skip. + * @returns {Query} A reference to itself for chaining. + * @since 3.0.0 + */ + between(leftKeys, rightKeys, opts = {}) { + if (this.data) { + throw utils.err(`${DOMAIN$1}#between`)(500, 'Cannot access index'); + } + this.data = this.collection.getIndex(opts.index).between(leftKeys, rightKeys, opts); + return this; + } + /** + * The comparison function used by the {@link Query} class. + * + * @method Query#compare + * @param {array} orderBy An orderBy clause used for sorting and sub-sorting. + * @param {number} index The index of the current orderBy clause being used. + * @param {*} a The first item in the comparison. + * @param {*} b The second item in the comparison. + * @returns {number} -1 if `b` should preceed `a`. 0 if `a` and `b` are equal. + * 1 if `a` should preceed `b`. + * @since 3.0.0 + */ + compare(orderBy, index, a, b, compare) { + const def = orderBy[index]; + let cA = utils.get(a, def[0]); + let cB = utils.get(b, def[0]); + if (cA && utils.isString(cA)) { + cA = cA.toUpperCase(); + } + if (cB && utils.isString(cB)) { + cB = cB.toUpperCase(); + } + if (a === undefined) { + a = null; + } + if (b === undefined) { + b = null; + } + if (def[1].toUpperCase() === 'DESC') { + const temp = cB; + cB = cA; + cA = temp; + } + /* Fix: compare by using collator */ + // let isNumeric = false + // if (utils.isNumber(cA) || utils.isNumber(cB)) { + // isNumeric = true + // } + const n = compare(cA, cB); + if (n === -1 || n === 1) { + return n; + } + else { + if (index < orderBy.length - 1) { + return this.compare(orderBy, index + 1, a, b, compare); + } + else { + return 0; + } + } + } + /** + * Predicate evaluation function used by the {@link Query} class. + * + * @method Query#evaluate + * @param {*} value The value to evaluate. + * @param {string} op The operator to use in this evaluation. + * @param {*} predicate The predicate to use in this evaluation. + * @returns {boolean} Whether the value passed the evaluation or not. + * @since 3.0.0 + */ + evaluate(value, op, predicate) { + const ops = Query.ops; + if (ops[op]) { + return ops[op](value, predicate); + } + if (op.indexOf('like') === 0) { + return this.like(predicate, op.substr(4)).exec(value) !== null; + } + else if (op.indexOf('notLike') === 0) { + return this.like(predicate, op.substr(7)).exec(value) === null; + } + } + /** + * Find the record or records that match the provided query or are accepted by + * the provided filter function. + * + * @example Get the draft posts by authors younger than 30 + * const JSData = require('js-data'); + * const { DataStore } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new DataStore(); + * store.defineMapper('post') + * const posts = [ + * { author: 'John', age: 30, status: 'published', id: 1 }, + * { author: 'Sally', age: 31, status: 'published', id: 2 }, + * { author: 'Mike', age: 32, status: 'draft', id: 3 }, + * { author: 'Adam', age: 33, status: 'deleted', id: 4 }, + * { author: 'Adam', age: 33, status: 'published', id: 5 } + * { author: 'Peter', age: 25, status: 'deleted', id: 6 }, + * { author: 'Sally', age: 21, status: 'draft', id: 7 }, + * { author: 'Jim', age: 27, status: 'draft', id: 8 }, + * { author: 'Jim', age: 27, status: 'published', id: 9 }, + * { author: 'Jason', age: 55, status: 'published', id: 10 } + * ]; + * store.add('post', posts); + * const results = store + * .query('post') + * .filter({ + * where: { + * status: { + * '==': 'draft' + * }, + * age: { + * '<': 30 + * } + * } + * }) + * .run(); + * console.log(results); + * + * @example Use a custom filter function + * const posts = query + * .filter(function (post) { + * return post.isReady(); + * }) + * .run(); + * + * @method Query#filter + * @param {(Object|Function)} [query={}] Selection query or filter + * function. + * @param {Function} [thisArg] Context to which to bind `queryOrFn` if + * `queryOrFn` is a function. + * @returns {Query} A reference to itself for chaining. + * @since 3.0.0 + */ + filter(query = {}, thisArg) { + /** + * Selection query as defined by JSData's [Query Syntax][querysyntax]. + * + * [querysyntax]: http://www.js-data.io/v3.0/docs/query-syntax + * + * @example Empty "findAll" query + * const JSData = require('js-data'); + * const { DataStore } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new DataStore(); + * store.defineMapper('post') + * store.findAll('post').then((posts) => { + * console.log(posts); // [...] + * }); + * + * @example Empty "filter" query + * const JSData = require('js-data'); + * const { DataStore } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new DataStore(); + * store.defineMapper('post'); + * const posts = store.filter('post'); + * console.log(posts); // [...] + * + * @example Complex "filter" query + * const JSData = require('js-data'); + * const { DataStore } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new DataStore(); + * const PAGE_SIZE = 2; + * let currentPage = 3; + * + * store.defineMapper('post'); + * const posts = [ + * { author: 'John', age: 30, status: 'published', id: 1 }, + * { author: 'Sally', age: 31, status: 'published', id: 2 }, + * { author: 'Mike', age: 32, status: 'draft', id: 3 }, + * { author: 'Adam', age: 33, status: 'deleted', id: 4 }, + * { author: 'Adam', age: 33, status: 'published', id: 5 } + * { author: 'Peter', age: 25, status: 'deleted', id: 6 }, + * { author: 'Sally', age: 21, status: 'draft', id: 7 }, + * { author: 'Jim', age: 27, status: 'draft', id: 8 }, + * { author: 'Jim', age: 27, status: 'published', id: 9 }, + * { author: 'Jason', age: 55, status: 'published', id: 10 } + * ]; + * store.add('post', posts); + * // Retrieve a filtered page of blog posts + * // Would typically replace filter with findAll + * const results = store.filter('post', { + * where: { + * status: { + * // WHERE status = 'published' + * '==': 'published' + * }, + * author: { + * // AND author IN ('bob', 'alice') + * 'in': ['bob', 'alice'], + * // OR author IN ('karen') + * '|in': ['karen'] + * } + * }, + * orderBy: [ + * // ORDER BY date_published DESC, + * ['date_published', 'DESC'], + * // ORDER BY title ASC + * ['title', 'ASC'] + * ], + * // LIMIT 2 + * limit: PAGE_SIZE, + * // SKIP 4 + * offset: PAGE_SIZE * (currentPage - 1) + * }); + * console.log(results); + * + * @namespace query + * @property {number} [limit] See {@link query.limit}. + * @property {number} [offset] See {@link query.offset}. + * @property {string|Array[]} [orderBy] See {@link query.orderBy}. + * @property {number} [skip] Alias for {@link query.offset}. + * @property {string|Array[]} [sort] Alias for {@link query.orderBy}. + * @property {Object} [where] See {@link query.where}. + * @property {String} [locale] See {@link query.locale}. + * @since 3.0.0 + * @tutorial ["http://www.js-data.io/v3.0/docs/query-syntax","JSData's Query Syntax"] + */ + this.getData(); + if (utils.isObject(query)) { + let where = {}; + /** + * Filtering criteria. Records that do not meet this criteria will be exluded + * from the result. + * + * @example Return posts where author is at least 32 years old + * const JSData = require('js-data'); + * const { DataStore } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new DataStore(); + * store.defineMapper('post') + * const posts = [ + * { author: 'John', age: 30, id: 5 }, + * { author: 'Sally', age: 31, id: 6 }, + * { author: 'Mike', age: 32, id: 7 }, + * { author: 'Adam', age: 33, id: 8 }, + * { author: 'Adam', age: 33, id: 9 } + * ]; + * store.add('post', posts); + * const results = store.filter('post', { + * where: { + * age: { + * '>=': 30 + * } + * } + * }); + * console.log(results); + * + * @name query.where + * @type {Object} + * @see http://www.js-data.io/v3.0/docs/query-syntax + * @since 3.0.0 + */ + if (utils.isObject(query.where) || utils.isArray(query.where)) { + where = query.where; + } + utils.forOwn(query, (value, key) => { + if (!(key in reserved) && !(key in where)) { + where[key] = { + '==': value + }; + } + }); + let groups; + // Apply filter for each field + if (utils.isObject(where) && Object.keys(where).length !== 0) { + groups = this._applyWhereFromArray([where]); + } + else if (utils.isArray(where)) { + groups = this._applyWhereFromArray(where); + } + if (groups) { + this.data = this.data.filter(item => this._testArrayGroup(true, true, groups, item).keep); + } + // Sort + let orderBy = query.orderBy || query.sort; + if (utils.isString(orderBy)) { + orderBy = [[orderBy, 'ASC']]; + } + if (!utils.isArray(orderBy)) { + orderBy = null; + } + /** + * Determines how records should be ordered in the result. + * + * @example Order posts by `author` then by `id` descending + * const JSData = require('js-data'); + * const { DataStore } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new DataStore(); + * store.defineMapper('post') + * const posts = [ + * { author: 'John', age: 30, id: 5 }, + * { author: 'Sally', age: 31, id: 6 }, + * { author: 'Mike', age: 32, id: 7 }, + * { author: 'Adam', age: 33, id: 8 }, + * { author: 'Adam', age: 33, id: 9 } + * ]; + * store.add('post', posts); + * const results = store.filter('post', { + * orderBy:[['author','ASC'],['id','DESC']] + * }); + * console.log(results); + * + * @name query.orderBy + * @type {string|Array[]} + * @see http://www.js-data.io/v3.0/docs/query-syntax + * @since 3.0.0 + */ + if (orderBy) { + const index = 0; + orderBy.forEach((def, i) => { + if (utils.isString(def)) { + orderBy[i] = [def, 'ASC']; + } + }); + let locale = utils.getDefaultLocale(); + if (utils.isString(query.locale)) { + locale = query.locale; + } + /** The locale params has to be explicitly set for the collator.compare to work. + * + * @example Order posts with specific locale, defaults to 'en' + * const JSData = require('js-data'); + * const { DataStore } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new DataStore(); + * store.defineMapper('post') + * const posts = [ + * { author: 'คลอน', age: 30, id: 5 }, + * { author: 'กลอน', age: 31, id: 6 }, + * { author: 'สาระ', age: 32, id: 7 }, + * { author: 'ศาลา', age: 33, id: 8 }, + * { author: 'จักรพรรณ', age: 33, id: 9 } + * ]; + * store.add('post', posts); + * const results = store.filter('post', { + * orderBy:[['author','ASC'],['id','DESC']], + * locale: 'th' + * }); + * console.log(results); + * + * @name query.locale + * @type {string} + * @see http://www.js-data.io/v4.0/docs/query-syntax + * @since 4.0.0 + */ + const collator = new Intl.Collator(locale, { + numeric: true + }); + this.data.sort((a, b) => this.compare(orderBy, index, a, b, collator.compare)); + } + /** + * Number of records to skip. + * + * @example Retrieve the first "page" of blog posts using findAll + * const JSData = require('js-data'); + * const { DataStore } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new DataStore(); + * store.defineMapper('post'); + * const PAGE_SIZE = 10; + * let currentPage = 1; + * store.findAll('post', { + * offset: PAGE_SIZE * (currentPage 1) + * limit: PAGE_SIZE + * }); + * + * @example Retrieve the last "page" of blog posts using filter + * const JSData = require('js-data'); + * const { DataStore } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new DataStore(); + * + * const PAGE_SIZE = 5; + * let currentPage = 2; + * store.defineMapper('post'); + * const posts = [ + * { author: 'John', age: 30, id: 1 }, + * { author: 'Sally', age: 31, id: 2 }, + * { author: 'Mike', age: 32, id: 3 }, + * { author: 'Adam', age: 33, id: 4 }, + * { author: 'Adam', age: 33, id: 5 }, + * { author: 'Peter', age: 25, id: 6 }, + * { author: 'Sally', age: 21, id: 7 }, + * { author: 'Jim', age: 27, id: 8 }, + * { author: 'Jim', age: 27, id: 9 }, + * { author: 'Jason', age: 55, id: 10 } + * ]; + * store.add('post', posts); + * const results = store.filter('post', { + * offset: PAGE_SIZE * (currentPage 1) + * limit: PAGE_SIZE + * }); + * console.log(results) + * + * @name query.offset + * @type {number} + * @see http://www.js-data.io/v3.0/docs/query-syntax + * @since 3.0.0 + */ + if (utils.isNumber(query.skip)) { + this.skip(query.skip); + } + else if (utils.isNumber(query.offset)) { + this.skip(query.offset); + } + /** + * Maximum number of records to retrieve. + * + * @example Retrieve the first "page" of blog posts using findAll + * const JSData = require('js-data'); + * const { DataStore } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new DataStore(); + * store.defineMapper('post'); + * + * const PAGE_SIZE = 10 + * let currentPage = 1 + * store.findAll('post', { + * offset: PAGE_SIZE * (currentPage 1) + * limit: PAGE_SIZE + * }); + * + * @example Retrieve the last "page" of blog posts using filter + * const JSData = require('js-data'); + * const { DataStore } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new DataStore(); + * + * const PAGE_SIZE = 5 + * let currentPage = 2 + * store.defineMapper('post') + * const posts = [ + * { author: 'John', age: 30, id: 1 }, + * { author: 'Sally', age: 31, id: 2 }, + * { author: 'Mike', age: 32, id: 3 }, + * { author: 'Adam', age: 33, id: 4 }, + * { author: 'Adam', age: 33, id: 5 }, + * { author: 'Peter', age: 25, id: 6 }, + * { author: 'Sally', age: 21, id: 7 }, + * { author: 'Jim', age: 27, id: 8 }, + * { author: 'Jim', age: 27, id: 9 }, + * { author: 'Jason', age: 55, id: 10 } + * ]; + * store.add('post', posts); + * const results = store.filter('post', { + * offset: PAGE_SIZE * (currentPage 1) + * limit: PAGE_SIZE + * }); + * console.log(results) + * + * @name query.limit + * @type {number} + * @see http://www.js-data.io/v3.0/docs/query-syntax + * @since 3.0.0 + */ + if (utils.isNumber(query.limit)) { + this.limit(query.limit); + } + } + else if (utils.isFunction(query)) { + this.data = this.data.filter(query, thisArg); + } + return this; + } + /** + * Iterate over all entities. + * + * @method Query#forEach + * @param {Function} forEachFn Iteration function. + * @param {*} [thisArg] Context to which to bind `forEachFn`. + * @returns {Query} A reference to itself for chaining. + * @since 3.0.0 + */ + forEach(forEachFn, thisArg) { + this.getData().forEach(forEachFn, thisArg); + return this; + } + /** + * Find the entity or entities that match the provided key. + * + * @example Get the entity whose primary key is 25. + * const entities = query.get(25).run(); + * + * @example Same as above. + * const entities = query.get([25]).run(); + * + * @example Get all users who are active and have the "admin" role. + * const activeAdmins = query.get(['active', 'admin'], { + * index: 'activityAndRoles' + * }).run(); + * + * @example Get all entities that match a certain weather condition. + * const niceDays = query.get(['sunny', 'humid', 'calm'], { + * index: 'weatherConditions' + * }).run(); + * + * @method Query#get + * @param {array} keyList Key(s) defining the entity to retrieve. If + * `keyList` is not an array (i.e. for a single-value key), it will be + * wrapped in an array. + * @param {object} [opts] Configuration options. + * @param {string} [opts.string] Name of the secondary index to use in the + * query. If no index is specified, the main index is used. + * @returns {Query} A reference to itself for chaining. + * @since 3.0.0 + */ + get(keyList = [], opts = {}) { + if (this.data) { + throw utils.err(`${DOMAIN$1}#get`)(500, INDEX_ERR); + } + if (keyList && !utils.isArray(keyList)) { + keyList = [keyList]; + } + if (!keyList.length) { + this.getData(); + return this; + } + this.data = this.collection.getIndex(opts.index).get(keyList); + return this; + } + getAll(...args) { + let opts = {}; + if (this.data) { + throw utils.err(`${DOMAIN$1}#getAll`)(500, INDEX_ERR); + } + if (!args.length || (args.length === 1 && utils.isObject(args[0]))) { + this.getData(); + return this; + } + else if (args.length && utils.isObject(args[args.length - 1])) { + opts = args[args.length - 1]; + args.pop(); + } + const index = this.collection.getIndex(opts.index); + this.data = []; + args.forEach(keyList => { + this.data = this.data.concat(index.get(keyList)); + }); + return this; + } + /** + * Return the current data result of this query. + * + * @method Query#getData + * @returns {Array} The data in this query. + * @since 3.0.0 + */ + getData() { + if (!this.data) { + this.data = this.collection.index.getAll(); + } + return this.data; + } + /** + * Implementation used by the `like` operator. Takes a pattern and flags and + * returns a `RegExp` instance that can test strings. + * + * @method Query#like + * @param {string} pattern Testing pattern. + * @param {string} flags Flags for the regular expression. + * @returns {RegExp} Regular expression for testing strings. + * @since 3.0.0 + */ + like(pattern, flags) { + return new RegExp(`^${escape(pattern) + .replace(percentRegExp, '.*') + .replace(underscoreRegExp, '.')}$`, flags); + } + /** + * Limit the result. + * + * @example Get only the first 2 posts. + * const store = new JSData.DataStore(); + * store.defineMapper('post'); + * const posts = [ + * { author: 'John', age: 30, status: 'published', id: 1 }, + * { author: 'Sally', age: 31, status: 'draft', id: 2 }, + * { author: 'Mike', age: 32, status: 'draft', id: 3 }, + * { author: 'Adam', age: 33, status: 'deleted', id: 4 }, + * { author: 'Adam', age: 33, status: 'draft', id: 5 } + * ]; + * store.add('post', posts); + * const results = store.query('post').limit(2).run(); + * console.log(results); + * + * @method Query#limit + * @param {number} num The maximum number of entities to keep in the result. + * @returns {Query} A reference to itself for chaining. + * @since 3.0.0 + */ + limit(num) { + if (!utils.isNumber(num)) { + throw utils.err(`${DOMAIN$1}#limit`, 'num')(400, 'number', num); + } + const data = this.getData(); + this.data = data.slice(0, Math.min(data.length, num)); + return this; + } + /** + * Apply a mapping function to the result data. + * + * @example + * const JSData = require('js-data'); + * const { DataStore } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new DataStore(); + * store.defineMapper('user'); + * const users = [ + * { name: 'Peter', age: 25, id: 1 }, + * { name: 'Jim', age: 19, id: 2 }, + * { name: 'Mike', age: 17, id: 3 }, + * { name: 'Alan', age: 29, id: 4 }, + * { name: 'Katie', age: 33, id: 5 } + * ]; + * store.add('user', users); + * const ages = store + * .query('user') + * .map(function (user) { + * return user.age; + * }) + * .run(); + * console.log(ages); + * + * @method Query#map + * @param {Function} mapFn Mapping function. + * @param {*} [thisArg] Context to which to bind `mapFn`. + * @returns {Query} A reference to itself for chaining. + * @since 3.0.0 + */ + map(mapFn, thisArg) { + this.data = this.getData().map(mapFn, thisArg); + return this; + } + /** + * Return the result of calling the specified function on each item in this + * collection's main index. + * + * @example + * const stringAges = UserCollection.query().mapCall('toString').run(); + * + * @method Query#mapCall + * @param {string} funcName Name of function to call + * @param args Remaining arguments to be passed to the function. + * @returns {Query} A reference to itself for chaining. + * @since 3.0.0 + */ + mapCall(funcName, ...args) { + this.data = this.getData().map(item => item[funcName](...args)); + return this; + } + /** + * Complete the execution of the query and return the resulting data. + * + * @method Query#run + * @returns {Array} The result of executing this query. + * @since 3.0.0 + */ + run() { + const data = this.data; + this.data = null; + return data; + } + /** + * Skip a number of results. + * + * @example Get all but the first 2 posts. + * const JSData = require('js-data'); + * const { DataStore } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new DataStore(); + * store.defineMapper('post'); + * const posts = [ + * { author: 'John', age: 30, status: 'published', id: 1 }, + * { author: 'Sally', age: 31, status: 'draft', id: 2 }, + * { author: 'Mike', age: 32, status: 'draft', id: 3 }, + * { author: 'Adam', age: 33, status: 'deleted', id: 4 }, + * { author: 'Adam', age: 33, status: 'draft', id: 5 } + * ]; + * store.add('post', posts); + * const results = store.query('post').skip(2).run(); + * console.log(results); + * + * @method Query#skip + * @param {number} num The number of entities to skip. + * @returns {Query} A reference to itself for chaining. + * @since 3.0.0 + */ + skip(num) { + if (!utils.isNumber(num)) { + throw utils.err(`${DOMAIN$1}#skip`, 'num')(400, 'number', num); + } + const data = this.getData(); + if (num < data.length) { + this.data = data.slice(num); + } + else { + this.data = []; + } + return this; + } +} +/** + * The filtering operators supported by {@link Query#filter}, and which are + * implemented by adapters (for the most part). + * + * @example Variant 1 + * const JSData = require('js-data'); + * const { DataStore } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new DataStore(); + * store.defineMapper('post'); + * const posts = [ + * { author: 'John', age: 30, status: 'published', id: 1 }, + * { author: 'Sally', age: 31, status: 'published', id: 2 }, + * { author: 'Mike', age: 32, status: 'published', id: 3 }, + * { author: 'Adam', age: 33, status: 'deleted', id: 4 }, + * { author: 'Adam', age: 33, status: 'published', id: 5 } + * ]; + * store.add('post', posts); + * const publishedPosts = store.filter('post', { + * status: 'published', + * limit: 2 + * }); + * console.log(publishedPosts); + * + * + * @example Variant 2 + * const JSData = require('js-data'); + * const { DataStore } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new DataStore(); + * store.defineMapper('post') + * const posts = [ + * { author: 'John', age: 30, status: 'published', id: 1 }, + * { author: 'Sally', age: 31, status: 'published', id: 2 }, + * { author: 'Mike', age: 32, status: 'published', id: 3 }, + * { author: 'Adam', age: 33, status: 'deleted', id: 4 }, + * { author: 'Adam', age: 33, status: 'published', id: 5 } + * ]; + * store.add('post', posts); + * const publishedPosts = store.filter('post', { + * where: { + * status: { + * '==': 'published' + * } + * }, + * limit: 2 + * }); + * console.log(publishedPosts); + * + * @example Variant 3 + * const JSData = require('js-data'); + * const { DataStore } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new DataStore(); + * store.defineMapper('post'); + * const posts = [ + * { author: 'John', age: 30, status: 'published', id: 1 }, + * { author: 'Sally', age: 31, status: 'published', id: 2 }, + * { author: 'Mike', age: 32, status: 'published', id: 3 }, + * { author: 'Adam', age: 33, status: 'deleted', id: 4 }, + * { author: 'Adam', age: 33, status: 'published', id: 5 } + * ]; + * store.add('post', posts); + * const publishedPosts = store + * .query('post') + * .filter({ status: 'published' }) + * .limit(2) + * .run(); + * console.log(publishedPosts); + * + * @example Variant 4 + * const JSData = require('js-data'); + * const { DataStore } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new DataStore(); + * store.defineMapper('post'); + * const posts = [ + * { author: 'John', age: 30, status: 'published', id: 1 }, + * { author: 'Sally', age: 31, status: 'published', id: 2 }, + * { author: 'Mike', age: 32, status: 'published', id: 3 }, + * { author: 'Adam', age: 33, status: 'deleted', id: 4 }, + * { author: 'Adam', age: 33, status: 'published', id: 5 } + * ]; + * store.add('post', posts); + * const publishedPosts = store + * .query('post') + * .filter({ + * where: { + * status: { + * '==': 'published' + * } + * } + * }) + * .limit(2) + * .run(); + * console.log(publishedPosts); + * + * @example Multiple operators + * const JSData = require('js-data'); + * const { DataStore } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new DataStore(); + * store.defineMapper('post'); + * const posts = [ + * { author: 'John', age: 30, status: 'published', id: 1 }, + * { author: 'Sally', age: 31, status: 'published', id: 2 }, + * { author: 'Mike', age: 32, status: 'published', id: 3 }, + * { author: 'Adam', age: 33, status: 'deleted', id: 4 }, + * { author: 'Adam', age: 33, status: 'published', id: 5 } + * ]; + * store.add('post', posts); + * + * const myPublishedPosts = store.filter('post', { + * where: { + * status: { + * '==': 'published' + * }, + * user_id: { + * '==': currentUser.id + * } + * } + * }); + * + * console.log(myPublishedPosts); + * + * @name Query.ops + * @property {Function} == Equality operator. + * @property {Function} != Inequality operator. + * @property {Function} > Greater than operator. + * @property {Function} >= Greater than (inclusive) operator. + * @property {Function} < Less than operator. + * @property {Function} <= Less than (inclusive) operator. + * @property {Function} isectEmpty Operator that asserts that the intersection + * between two arrays is empty. + * @property {Function} isectNotEmpty Operator that asserts that the + * intersection between two arrays is __not__ empty. + * @property {Function} in Operator that asserts whether a value is in an + * array. + * @property {Function} notIn Operator that asserts whether a value is __not__ + * in an array. + * @property {Function} contains Operator that asserts whether an array + * contains a value. + * @property {Function} notContains Operator that asserts whether an array + * does __not__ contain a value. + * @since 3.0.0 + * @type {Object} + */ +Query.ops = { + '='(value, predicate) { + // tslint:disable-next-line:triple-equals + return value == predicate; // eslint-disable-line + }, + '=='(value, predicate) { + // tslint:disable-next-line:triple-equals + return value == predicate; // eslint-disable-line + }, + '==='(value, predicate) { + return value === predicate; + }, + '!='(value, predicate) { + // tslint:disable-next-line:triple-equals + return value != predicate; // eslint-disable-line + }, + '!=='(value, predicate) { + return value !== predicate; + }, + '>'(value, predicate) { + return value > predicate; + }, + '>='(value, predicate) { + return value >= predicate; + }, + '<'(value, predicate) { + return value < predicate; + }, + '<='(value, predicate) { + return value <= predicate; + }, + isectEmpty(value, predicate) { + return !utils.intersection(value || [], predicate || []).length; + }, + isectNotEmpty(value, predicate) { + return utils.intersection(value || [], predicate || []).length; + }, + in(value, predicate) { + return predicate.indexOf(value) !== -1; + }, + notIn(value, predicate) { + return predicate.indexOf(value) === -1; + }, + contains(value, predicate) { + return (value || []).indexOf(predicate) !== -1; + }, + notContains(value, predicate) { + return (value || []).indexOf(predicate) === -1; + } }; -var utils = { - /** - * Reference to the Promise constructor used by JSData. Defaults to - * `window.Promise` or `global.Promise`. - * - * @example Make JSData use a different `Promise` constructor - * import Promise from 'bluebird'; - * import { utils } from 'js-data'; - * utils.Promise = Promise; - * - * @name utils.Promise - * @since 3.0.0 - * @type {Function} - */ - Promise: Promise, - - /** - * Shallow copy properties that meet the following criteria from `src` to - * `dest`: - * - * - own enumerable - * - not a function - * - does not start with "_" - * - * @method utils._ - * @param {object} dest Destination object. - * @param {object} src Source object. - * @private - * @since 3.0.0 - */ - _: function _(dest, src) { - utils.forOwn(src, function (value, key) { - if (key && dest[key] === undefined && !utils.isFunction(value) && key.indexOf('_') !== 0) { - dest[key] = value; - } - }); - }, - - /** - * Recursively iterates over relations found in `opts.with`. - * - * @method utils._forRelation - * @param {object} opts Configuration options. - * @param {Relation} def Relation definition. - * @param {Function} fn Callback function. - * @param {*} [thisArg] Execution context for the callback function. - * @private - * @since 3.0.0 - */ - _forRelation: function _forRelation(opts, def, fn, thisArg) { - var relationName = def.relation; - var containedName = null; - var index; - opts || (opts = {}); - opts.with || (opts.with = []); - - if ((index = utils._getIndex(opts.with, relationName)) >= 0) { - containedName = relationName; - } else if ((index = utils._getIndex(opts.with, def.localField)) >= 0) { - containedName = def.localField; - } - - if (opts.withAll) { - fn.call(thisArg, def, {}); - return; - } else if (!containedName) { - return; - } - - var optsCopy = {}; - utils.fillIn(optsCopy, def.getRelation()); - utils.fillIn(optsCopy, opts); - optsCopy.with = opts.with.slice(); - optsCopy._activeWith = optsCopy.with.splice(index, 1)[0]; - optsCopy.with.forEach(function (relation, i) { - if (relation && relation.indexOf(containedName) === 0 && relation.length >= containedName.length && relation[containedName.length] === '.') { - optsCopy.with[i] = relation.substr(containedName.length + 1); - } else { - optsCopy.with[i] = ''; - } - }); - fn.call(thisArg, def, optsCopy); - }, - - /** - * Find the index of a relation in the given list - * - * @method utils._getIndex - * @param {string[]} list List to search. - * @param {string} relation Relation to find. - * @private - * @returns {number} - */ - _getIndex: function _getIndex(list, relation) { - var index = -1; - list.forEach(function (_relation, i) { - if (_relation === relation) { - index = i; - return false; - } else if (utils.isObject(_relation)) { - if (_relation.relation === relation) { - index = i; - return false; - } - } - }); - return index; - }, - - /** - * Define hidden (non-enumerable), writable properties on `target` from the - * provided `props`. - * - * @example - * import { utils } from 'js-data'; - * function Cat () {} - * utils.addHiddenPropsToTarget(Cat.prototype, { - * say () { - * console.log('meow'); - * } - * }); - * const cat = new Cat(); - * cat.say(); // "meow" - * - * @method utils.addHiddenPropsToTarget - * @param {object} target That to which `props` should be added. - * @param {object} props Properties to be added to `target`. - * @since 3.0.0 - */ - addHiddenPropsToTarget: function addHiddenPropsToTarget(target, props) { - var map = {}; - Object.keys(props).forEach(function (propName) { - var descriptor = Object.getOwnPropertyDescriptor(props, propName); - descriptor.enumerable = false; - map[propName] = descriptor; - }); - Object.defineProperties(target, map); - }, - - /** - * Return whether the two objects are deeply different. - * - * @example - * import { utils } from 'js-data'; - * utils.areDifferent({}, {}); // false - * utils.areDifferent({ a: 1 }, { a: 1 }); // false - * utils.areDifferent({ foo: 'bar' }, {}); // true - * - * @method utils.areDifferent - * @param {object} a Base object. - * @param {object} b Comparison object. - * @param {object} [opts] Configuration options. - * @param {Function} [opts.equalsFn={@link utils.deepEqual}] Equality function. - * @param {array} [opts.ignore=[]] Array of strings or RegExp of fields to ignore. - * @returns {boolean} Whether the two objects are deeply different. - * @see utils.diffObjects - * @since 3.0.0 - */ - areDifferent: function areDifferent(newObject, oldObject, opts) { - opts || (opts = {}); - var diff = utils.diffObjects(newObject, oldObject, opts); - var diffCount = Object.keys(diff.added).length + Object.keys(diff.removed).length + Object.keys(diff.changed).length; - return diffCount > 0; - }, - - /** - * Verified that the given constructor is being invoked via `new`, as opposed - * to just being called like a normal function. - * - * @example - * import { utils } from 'js-data'; - * function Cat () { - * utils.classCallCheck(this, Cat); - * } - * const cat = new Cat(); // this is ok - * Cat(); // this throws an error - * - * @method utils.classCallCheck - * @param {*} instance Instance that is being constructed. - * @param {Constructor} ctor Constructor function used to construct the - * instance. - * @since 3.0.0 - * @throws {Error} Throws an error if the constructor is being improperly - * invoked. - */ - classCallCheck: function classCallCheck(instance, ctor) { - if (!(instance instanceof ctor)) { - throw utils.err("".concat(ctor.name))(500, 'Cannot call a class as a function'); - } - }, - - /** - * Deep copy a value. - * - * @example - * import { utils } from 'js-data'; - * const a = { foo: { bar: 'baz' } }; - * const b = utils.copy(a); - * a === b; // false - * utils.areDifferent(a, b); // false - * - * @param {*} from Value to deep copy. - * @param {*} [to] Destination object for the copy operation. - * @param {*} [stackFrom] For internal use. - * @param {*} [stackTo] For internal use. - * @param {string[]|RegExp[]} [blacklist] List of strings or RegExp of - * properties to skip. - * @param {boolean} [plain] Whether to make a plain copy (don't try to use - * original prototype). - * @returns {*} Deep copy of `from`. - * @since 3.0.0 - */ - copy: function copy(from, to, stackFrom, stackTo, blacklist, plain) { - if (!to) { - to = from; - - if (from) { - if (utils.isArray(from)) { - to = utils.copy(from, [], stackFrom, stackTo, blacklist, plain); - } else if (utils.isDate(from)) { - to = new Date(from.getTime()); - } else if (utils.isRegExp(from)) { - to = new RegExp(from.source, from.toString().match(/[^/]*$/)[0]); - to.lastIndex = from.lastIndex; - } else if (utils.isObject(from)) { - if (plain) { - to = utils.copy(from, {}, stackFrom, stackTo, blacklist, plain); - } else { - to = utils.copy(from, Object.create(Object.getPrototypeOf(from)), stackFrom, stackTo, blacklist, plain); - } - } - } - } else { - if (from === to) { - throw utils.err("".concat(DOMAIN, ".copy"))(500, 'Cannot copy! Source and destination are identical.'); - } - - stackFrom = stackFrom || []; - stackTo = stackTo || []; - - if (utils.isObject(from)) { - var index = stackFrom.indexOf(from); - - if (index !== -1) { - return stackTo[index]; - } - - stackFrom.push(from); - stackTo.push(to); - } - - var result; - - if (utils.isArray(from)) { - var i; - to.length = 0; - - for (i = 0; i < from.length; i++) { - result = utils.copy(from[i], null, stackFrom, stackTo, blacklist, plain); - - if (utils.isObject(from[i])) { - stackFrom.push(from[i]); - stackTo.push(result); - } - - to.push(result); - } - } else { - if (utils.isArray(to)) { - to.length = 0; - } else { - utils.forOwn(to, function (value, key) { - delete to[key]; - }); - } - - for (var key in from) { - if (Object.hasOwnProperty.call(from, key)) { - if (utils.isBlacklisted(key, blacklist)) { - continue; - } - - result = utils.copy(from[key], null, stackFrom, stackTo, blacklist, plain); - - if (utils.isObject(from[key])) { - stackFrom.push(from[key]); - stackTo.push(result); - } - - to[key] = result; - } - } - } - } - - return to; - }, - - /** - * Recursively shallow fill in own enumerable properties from `source` to - * `dest`. - * - * @example - * import { utils } from 'js-data'; - * const a = { foo: { bar: 'baz' }, beep: 'boop' }; - * const b = { beep: 'bip' }; - * utils.deepFillIn(b, a); - * console.log(b); // {"foo":{"bar":"baz"},"beep":"bip"} - * - * @method utils.deepFillIn - * @param {object} dest The destination object. - * @param {object} source The source object. - * @see utils.fillIn - * @see utils.deepMixIn - * @since 3.0.0 - */ - deepFillIn: function deepFillIn(dest, source) { - if (source) { - utils.forOwn(source, function (value, key) { - var existing = dest[key]; - - if (isPlainObject(value) && isPlainObject(existing)) { - utils.deepFillIn(existing, value); - } else if (!Object.hasOwnProperty.call(dest, key) || dest[key] === undefined) { - dest[key] = value; - } - }); - } - - return dest; - }, - - /** - * Recursively shallow copy enumerable properties from `source` to `dest`. - * - * @example - * import { utils } from 'js-data'; - * const a = { foo: { bar: 'baz' }, beep: 'boop' }; - * const b = { beep: 'bip' }; - * utils.deepFillIn(b, a); - * console.log(b); // {"foo":{"bar":"baz"},"beep":"boop"} - * - * @method utils.deepMixIn - * @param {object} dest The destination object. - * @param {object} source The source object. - * @see utils.fillIn - * @see utils.deepFillIn - * @since 3.0.0 - */ - deepMixIn: function deepMixIn(dest, source) { - if (source) { - for (var key in source) { - var value = source[key]; - var existing = dest[key]; - - if (isPlainObject(value) && isPlainObject(existing)) { - utils.deepMixIn(existing, value); - } else { - dest[key] = value; - } - } - } - - return dest; - }, - - /** - * Return a diff of the base object to the comparison object. - * - * @example - * import { utils } from 'js-data'; - * const oldObject = { foo: 'bar', a: 1234 }; - * const newObject = { beep: 'boop', a: 5678 }; - * const diff = utils.diffObjects(oldObject, newObject); - * console.log(diff.added); // {"beep":"boop"} - * console.log(diff.changed); // {"a":5678} - * console.log(diff.removed); // {"foo":undefined} - * - * @method utils.diffObjects - * @param {object} newObject Comparison object. - * @param {object} oldObject Base object. - * @param {object} [opts] Configuration options. - * @param {Function} [opts.equalsFn={@link utils.deepEqual}] Equality function. - * @param {array} [opts.ignore=[]] Array of strings or RegExp of fields to ignore. - * @returns {Object} The diff from the base object to the comparison object. - * @see utils.areDifferent - * @since 3.0.0 - */ - diffObjects: function diffObjects(newObject, oldObject, opts) { - opts || (opts = {}); - var equalsFn = opts.equalsFn; - var blacklist = opts.ignore; - var diff = { - added: {}, - changed: {}, - removed: {} - }; - - if (!utils.isFunction(equalsFn)) { - equalsFn = utils.deepEqual; - } - - var newKeys = Object.keys(newObject).filter(function (key) { - return !utils.isBlacklisted(key, blacklist); - }); - var oldKeys = Object.keys(oldObject).filter(function (key) { - return !utils.isBlacklisted(key, blacklist); - }); // Check for properties that were added or changed - - newKeys.forEach(function (key) { - var oldValue = oldObject[key]; - var newValue = newObject[key]; - - if (equalsFn(oldValue, newValue)) { - return; - } - - if (oldValue === undefined) { - diff.added[key] = newValue; - } else { - diff.changed[key] = newValue; - } - }); // Check for properties that were removed - - oldKeys.forEach(function (key) { - var oldValue = oldObject[key]; - var newValue = newObject[key]; - - if (newValue === undefined && oldValue !== undefined) { - diff.removed[key] = undefined; - } - }); - return diff; - }, - - /** - * Return whether the two values are equal according to the `==` operator. - * - * @example - * import { utils } from 'js-data'; - * console.log(utils.equal(1,1)); // true - * console.log(utils.equal(1,'1')); // true - * console.log(utils.equal(93, 66)); // false - * - * @method utils.equal - * @param {*} a First value in the comparison. - * @param {*} b Second value in the comparison. - * @returns {boolean} Whether the two values are equal according to `==`. - * @since 3.0.0 - */ - equal: function equal(a, b) { - return a == b; // eslint-disable-line - }, - - /** - * Produce a factory function for making Error objects with the provided - * metadata. Used throughout the various js-data components. - * - * @example - * import { utils } from 'js-data'; - * const errorFactory = utils.err('domain', 'target'); - * const error400 = errorFactory(400, 'expected type', 'actual type'); - * console.log(error400); // [Error: [domain:target] expected: expected type, found: string - http://www.js-data.io/v3.0/docs/errors#400] - * @method utils.err - * @param {string} domain Namespace. - * @param {string} target Target. - * @returns {Function} Factory function. - * @since 3.0.0 - */ - err: function err(domain, target) { - return function (code) { - var prefix = "[".concat(domain, ":").concat(target, "] "); - var message = ERRORS[code].apply(null, Array.prototype.slice.call(arguments, 1)); - message = "".concat(prefix).concat(message, "\nhttp://www.js-data.io/v3.0/docs/errors#").concat(code); - return new Error(message); - }; - }, - - /** - * Add eventing capabilities into the target object. - * - * @example - * import { utils } from 'js-data'; - * const user = { name: 'John' }; - * utils.eventify(user); - * user.on('foo', () => console.log(arguments)); - * user.emit('foo', 1, 'bar'); // should log to console values (1, "bar") - * - * @method utils.eventify - * @param {object} target Target object. - * @param {Function} [getter] Custom getter for retrieving the object's event - * listeners. - * @param {Function} [setter] Custom setter for setting the object's event - * listeners. - * @since 3.0.0 - */ - eventify: function eventify(target, getter, setter) { - target = target || this; - var _events = {}; - - if (!getter && !setter) { - getter = function getter() { - return _events; - }; - - setter = function setter(value) { - _events = value; - }; - } - - Object.defineProperties(target, { - emit: { - value: function value() { - var events = getter.call(this) || {}; - - for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { - args[_key] = arguments[_key]; - } - - var type = args.shift(); - var listeners = events[type] || []; - var i; - - for (i = 0; i < listeners.length; i++) { - listeners[i].f.apply(listeners[i].c, args); - } - - listeners = events.all || []; - args.unshift(type); - - for (i = 0; i < listeners.length; i++) { - listeners[i].f.apply(listeners[i].c, args); - } - } - }, - off: { - value: function value(type, func) { - var events = getter.call(this); - var listeners = events[type]; - - if (!listeners) { - setter.call(this, {}); - } else if (func) { - for (var i = 0; i < listeners.length; i++) { - if (listeners[i].f === func) { - listeners.splice(i, 1); - break; - } - } - } else { - listeners.splice(0, listeners.length); - } - } - }, - on: { - value: function value(type, func, thisArg) { - if (!getter.call(this)) { - setter.call(this, {}); - } - - var events = getter.call(this); - events[type] = events[type] || []; - events[type].push({ - c: thisArg, - f: func - }); - } - } - }); - }, - - /** - * Used for sublcassing. Invoke this method in the context of a superclass to - * to produce a subclass based on `props` and `classProps`. - * - * @example - * import { utils } from 'js-data'; - * function Animal () {} - * Animal.extend = utils.extend; - * const Cat = Animal.extend({ - * say () { - * console.log('meow'); - * } - * }); - * const cat = new Cat(); - * cat instanceof Animal; // true - * cat instanceof Cat; // true - * cat.say(); // "meow" - * - * @method utils.extend - * @param {object} props Instance properties for the subclass. - * @param {object} [props.constructor] Provide a custom constructor function - * to use as the subclass. - * @param {object} props Static properties for the subclass. - * @returns {Constructor} A new subclass. - * @since 3.0.0 - */ - extend: function extend(props, classProps) { - var superClass = this; - - var _subClass; - - props || (props = {}); - classProps || (classProps = {}); - - if (Object.hasOwnProperty.call(props, 'constructor')) { - _subClass = props.constructor; - delete props.constructor; - } else { - _subClass = function subClass() { - utils.classCallCheck(this, _subClass); - - for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { - args[_key2] = arguments[_key2]; - } - - superClass.apply(this, args); - }; - } // Setup inheritance of instance members - - - _subClass.prototype = Object.create(superClass && superClass.prototype, { - constructor: { - configurable: true, - enumerable: false, - value: _subClass, - writable: true - } - }); - var obj = Object; // Setup inheritance of static members - - if (obj.setPrototypeOf) { - obj.setPrototypeOf(_subClass, superClass); - } else if (classProps.strictEs6Class) { - _subClass.__proto__ = superClass; // eslint-disable-line - } else { - utils.forOwn(superClass, function (value, key) { - _subClass[key] = value; - }); - } - - if (!Object.hasOwnProperty.call(_subClass, '__super__')) { - Object.defineProperty(_subClass, '__super__', { - configurable: true, - value: superClass - }); - } - - utils.addHiddenPropsToTarget(_subClass.prototype, props); - utils.fillIn(_subClass, classProps); - return _subClass; - }, - - /** - * Shallow copy own enumerable properties from `src` to `dest` that are on - * `src` but are missing from `dest. - * - * @example - * import { utils } from 'js-data'; - * const a = { foo: 'bar', beep: 'boop' }; - * const b = { beep: 'bip' }; - * utils.fillIn(b, a); - * console.log(b); // {"foo":"bar","beep":"bip"} - * - * @method utils.fillIn - * @param {object} dest The destination object. - * @param {object} source The source object. - * @see utils.deepFillIn - * @see utils.deepMixIn - * @since 3.0.0 - */ - fillIn: function fillIn(dest, src) { - utils.forOwn(src, function (value, key) { - if (!Object.hasOwnProperty.call(dest, key) || dest[key] === undefined) { - dest[key] = value; - } - }); - }, - - /** - * Find the last index of an item in an array according to the given checker function. - * - * @example - * import { utils } from 'js-data'; - * - * const john = { name: 'John', age: 20 }; - * const sara = { name: 'Sara', age: 25 }; - * const dan = { name: 'Dan', age: 20 }; - * const users = [john, sara, dan]; - * - * console.log(utils.findIndex(users, (user) => user.age === 25)); // 1 - * console.log(utils.findIndex(users, (user) => user.age > 19)); // 2 - * console.log(utils.findIndex(users, (user) => user.name === 'John')); // 0 - * console.log(utils.findIndex(users, (user) => user.name === 'Jimmy')); // -1 - * - * @method utils.findIndex - * @param {array} array The array to search. - * @param {Function} fn Checker function. - * @returns {number} Index if found or -1 if not found. - * @since 3.0.0 - */ - findIndex: function findIndex(array, fn) { - var index = -1; - - if (!array) { - return index; - } - - array.forEach(function (record, i) { - if (fn(record)) { - index = i; - return false; - } - }); - return index; - }, - - /** - * Recursively iterate over a {@link Mapper}'s relations according to - * `opts.with`. - * - * @method utils.forEachRelation - * @param {Mapper} mapper Mapper. - * @param {object} opts Configuration options. - * @param {Function} fn Callback function. - * @param {*} thisArg Execution context for the callback function. - * @since 3.0.0 - */ - forEachRelation: function forEachRelation(mapper, opts, fn, thisArg) { - var relationList = mapper.relationList || []; - - if (!relationList.length) { - return; - } - - relationList.forEach(function (def) { - utils._forRelation(opts, def, fn, thisArg); - }); - }, - - /** - * Iterate over an object's own enumerable properties. - * - * @example - * import { utils } from 'js-data'; - * const a = { b: 1, c: 4 }; - * let sum = 0; - * utils.forOwn(a, function (value, key) { - * sum += value; - * }); - * console.log(sum); // 5 - * - * @method utils.forOwn - * @param {object} object The object whose properties are to be enumerated. - * @param {Function} fn Iteration function. - * @param {object} [thisArg] Content to which to bind `fn`. - * @since 3.0.0 - */ - forOwn: function forOwn(obj, fn, thisArg) { - var keys = Object.keys(obj); - var len = keys.length; - var i; - - for (i = 0; i < len; i++) { - if (fn.call(thisArg, obj[keys[i]], keys[i], obj) === false) { - break; - } - } - }, - - /** - * Proxy for `JSON.parse`. - * - * @example - * import { utils } from 'js-data'; - * - * const a = utils.fromJson('{"name" : "John"}'); - * console.log(a); // { name: 'John' } - * - * @method utils.fromJson - * @param {string} json JSON to parse. - * @returns {Object} Parsed object. - * @see utils.toJson - * @since 3.0.0 - */ - fromJson: function fromJson(json) { - return utils.isString(json) ? JSON.parse(json) : json; - }, - - /** - * Retrieve the specified property from the given object. Supports retrieving - * nested properties. - * - * @example - * import { utils } from 'js-data'; - * const a = { foo: { bar: 'baz' }, beep: 'boop' }; - * console.log(utils.get(a, 'beep')); // "boop" - * console.log(utils.get(a, 'foo.bar')); // "baz" - * - * @method utils.get - * @param {object} object Object from which to retrieve a property's value. - * @param {string} prop Property to retrieve. - * @returns {*} Value of the specified property. - * @see utils.set - * @since 3.0.0 - */ - get: function get(object, prop) { - if (!prop) { - return; - } - - var parts = prop.split('.'); - var last = parts.pop(); - - while (prop = parts.shift()) { - // eslint-disable-line - object = object[prop]; - - if (object == null) { - // eslint-disable-line - return; - } - } - - return object[last]; - }, - - /** - * Return the superclass for the given instance or subclass. If an instance is - * provided, then finds the parent class of the instance's constructor. - * - * @example - * import { utils } from 'js-data'; - * // using ES2015 classes - * class Foo {} - * class Bar extends Foo {} - * const barInstance = new Bar(); - * let baseType = utils.getSuper(barInstance); - * console.log(Foo === baseType); // true - * - * // using Function constructor with utils.extend - * function Foo () {} - * Foo.extend = utils.extend; - * const Bar = Foo.extend(); - * const barInstance = new Bar(); - * let baseType = utils.getSuper(barInstance); - * console.log(Foo === baseType); // true - * - * @method utils.getSuper - * @param {Object|Function} instance Instance or constructor. - * @param {boolean} [isCtor=false] Whether `instance` is a constructor. - * @returns {Constructor} The superclass (grandparent constructor). - * @since 3.0.0 - */ - getSuper: function getSuper(instance, isCtor) { - var ctor = isCtor ? instance : instance.constructor; - - if (Object.hasOwnProperty.call(ctor, '__super__')) { - return ctor.__super__; - } - - return Object.getPrototypeOf(ctor) || ctor.__proto__; // eslint-disable-line - }, - - /** - * Return the intersection of two arrays. - * - * @example - * import { utils } from 'js-data'; - * const arrA = ['green', 'red', 'blue', 'red']; - * const arrB = ['green', 'yellow', 'red']; - * const intersected = utils.intersection(arrA, arrB); - * - * console.log(intersected); // ['green', 'red']) - * - * @method utils.intersection - * @param {array} array1 First array. - * @param {array} array2 Second array. - * @returns {Array} Array of elements common to both arrays. - * @since 3.0.0 - */ - intersection: function intersection(array1, array2) { - if (!array1 || !array2) { - return []; - } - - array1 = Array.isArray(array1) ? array1 : [array1]; - array2 = Array.isArray(array2) ? array2 : [array2]; - var result = []; - var item; - var i; - var len = array1.length; - - for (i = 0; i < len; i++) { - item = array1[i]; - - if (result.indexOf(item) !== -1) { - continue; - } - - if (array2.indexOf(item) !== -1) { - result.push(item); - } - } - - return result; - }, - - /** - * Proxy for `Array.isArray`. - * - * @example - * import { utils } from 'js-data'; - * const a = [1,2,3,4,5]; - * const b = { foo: "bar" }; - * console.log(utils.isArray(a)); // true - * console.log(utils.isArray(b)); // false - * - * @method utils.isArray - * @param {*} value The value to test. - * @returns {boolean} Whether the provided value is an array. - * @since 3.0.0 - */ - isArray: Array.isArray, - - /** - * Return whether `prop` is matched by any string or regular expression in - * `blacklist`. - * - * @example - * import { utils } from 'js-data'; - * const blacklist = [/^\$hashKey/g, /^_/g, 'id']; - * console.log(utils.isBlacklisted("$hashKey", blacklist)); // true - * console.log(utils.isBlacklisted("id", blacklist)); // true - * console.log(utils.isBlacklisted("_myProp", blacklist)); // true - * console.log(utils.isBlacklisted("my_id", blacklist)); // false - * - * @method utils.isBlacklisted - * @param {string} prop The name of a property to check. - * @param {array} blacklist Array of strings and regular expressions. - * @returns {boolean} Whether `prop` was matched. - * @since 3.0.0 - */ - isBlacklisted: function isBlacklisted(prop, blacklist) { - if (!blacklist || !blacklist.length) { - return false; - } - - var matches; - - for (var i = 0; i < blacklist.length; i++) { - if (toStr(blacklist[i]) === REGEXP_TAG && blacklist[i].test(prop) || blacklist[i] === prop) { - matches = prop; - return !!matches; - } - } - - return !!matches; - }, - - /** - * Return whether the provided value is a boolean. - * - * @example - * import { utils } from 'js-data'; - * const a = true; - * const b = { foo: "bar" }; - * console.log(utils.isBoolean(a)); // true - * console.log(utils.isBoolean(b)); // false - * - * @method utils.isBoolean - * @param {*} value The value to test. - * @returns {boolean} Whether the provided value is a boolean. - * @since 3.0.0 - */ - isBoolean: function isBoolean(value) { - return toStr(value) === BOOL_TAG; - }, - - /** - * Return whether the provided value is a date. - * - * @example - * import { utils } from 'js-data'; - * const a = new Date(); - * const b = { foo: "bar" }; - * console.log(utils.isDate(a)); // true - * console.log(utils.isDate(b)); // false - * - * @method utils.isDate - * @param {*} value The value to test. - * @returns {Date} Whether the provided value is a date. - * @since 3.0.0 - */ - isDate: function isDate(value) { - return value && _typeof(value) === 'object' && toStr(value) === DATE_TAG; - }, - - /** - * Return whether the provided value is a function. - * - * @example - * import { utils } from 'js-data'; - * const a = function () { console.log('foo bar'); }; - * const b = { foo: "bar" }; - * console.log(utils.isFunction(a)); // true - * console.log(utils.isFunction(b)); // false - * - * @method utils.isFunction - * @param {*} value The value to test. - * @returns {boolean} Whether the provided value is a function. - * @since 3.0.0 - */ - isFunction: function isFunction(value) { - return typeof value === 'function' || value && toStr(value) === FUNC_TAG; - }, - - /** - * Return whether the provided value is an integer. - * - * @example - * import { utils } from 'js-data'; - * const a = 1; - * const b = 1.25; - * const c = '1'; - * console.log(utils.isInteger(a)); // true - * console.log(utils.isInteger(b)); // false - * console.log(utils.isInteger(c)); // false - * - * @method utils.isInteger - * @param {*} value The value to test. - * @returns {boolean} Whether the provided value is an integer. - * @since 3.0.0 - */ - isInteger: function isInteger(value) { - return toStr(value) === NUMBER_TAG && value == toInteger(value); // eslint-disable-line - }, - - /** - * Return whether the provided value is `null`. - * - * @example - * import { utils } from 'js-data'; - * const a = null; - * const b = { foo: "bar" }; - * console.log(utils.isNull(a)); // true - * console.log(utils.isNull(b)); // false - * - * @method utils.isNull - * @param {*} value The value to test. - * @returns {boolean} Whether the provided value is `null`. - * @since 3.0.0 - */ - isNull: function isNull(value) { - return value === null; - }, - - /** - * Return whether the provided value is a number. - * - * @example - * import { utils } from 'js-data'; - * const a = 1; - * const b = -1.25; - * const c = '1'; - * console.log(utils.isNumber(a)); // true - * console.log(utils.isNumber(b)); // true - * console.log(utils.isNumber(c)); // false - * - * @method utils.isNumber - * @param {*} value The value to test. - * @returns {boolean} Whether the provided value is a number. - * @since 3.0.0 - */ - isNumber: function isNumber(value) { - var type = _typeof(value); - - return type === 'number' || value && type === 'object' && toStr(value) === NUMBER_TAG; - }, - - /** - * Return whether the provided value is an object. - * - * @example - * import { utils } from 'js-data'; - * const a = { foo: "bar" }; - * const b = 'foo bar'; - * console.log(utils.isObject(a)); // true - * console.log(utils.isObject(b)); // false - * - * @method utils.isObject - * @param {*} value The value to test. - * @returns {boolean} Whether the provided value is an object. - * @since 3.0.0 - */ - isObject: function isObject(value) { - return toStr(value) === OBJECT_TAG; - }, - - /** - * Return whether the provided value is a regular expression. - * - * @example - * import { utils } from 'js-data'; - * const a = /^\$.+$/ig; - * const b = new RegExp('^\$.+$', 'ig'); - * const c = { foo: "bar" }; - * console.log(utils.isRegExp(a)); // true - * console.log(utils.isRegExp(b)); // true - * console.log(utils.isRegExp(c)); // false - * - * @method utils.isRegExp - * @param {*} value The value to test. - * @returns {boolean} Whether the provided value is a regular expression. - * @since 3.0.0 - */ - isRegExp: function isRegExp(value) { - return toStr(value) === REGEXP_TAG; - }, - - /** - * Return whether the provided value is a string or a number. - * - * @example - * import { utils } from 'js-data'; - * console.log(utils.isSorN('')); // true - * console.log(utils.isSorN(-1.65)); // true - * console.log(utils.isSorN('my string')); // true - * console.log(utils.isSorN({})); // false - * console.log(utils.isSorN([1,2,4])); // false - * - * @method utils.isSorN - * @param {*} value The value to test. - * @returns {boolean} Whether the provided value is a string or a number. - * @since 3.0.0 - */ - isSorN: function isSorN(value) { - return utils.isString(value) || utils.isNumber(value); - }, - - /** - * Return whether the provided value is a string. - * - * @example - * import { utils } from 'js-data'; - * console.log(utils.isString('')); // true - * console.log(utils.isString('my string')); // true - * console.log(utils.isString(100)); // false - * console.log(utils.isString([1,2,4])); // false - * - * @method utils.isString - * @param {*} value The value to test. - * @returns {boolean} Whether the provided value is a string. - * @since 3.0.0 - */ - isString: function isString(value) { - return typeof value === 'string' || value && _typeof(value) === 'object' && toStr(value) === STRING_TAG; - }, - - /** - * Return whether the provided value is a `undefined`. - * - * @example - * import { utils } from 'js-data'; - * const a = undefined; - * const b = { foo: "bar"}; - * console.log(utils.isUndefined(a)); // true - * console.log(utils.isUndefined(b.baz)); // true - * console.log(utils.isUndefined(b)); // false - * console.log(utils.isUndefined(b.foo)); // false - * - * @method utils.isUndefined - * @param {*} value The value to test. - * @returns {boolean} Whether the provided value is a `undefined`. - * @since 3.0.0 - */ - isUndefined: function isUndefined(value) { - return value === undefined; - }, - - /** - * Mix in logging capabilities to the target. - * - * @example - * import { utils } from 'js-data'; - * const a = { foo: "bar"}; - * - * // Add standard logging to an object - * utils.logify(a); - * a.log('info', 'test log info'); // output 'test log info' to console. - * - * // Toggle debug output of an object - * a.dbg('test debug output'); // does not output because debug is off. - * a.debug = true; - * a.dbg('test debug output'); // output 'test debug output' to console. - * - * @method utils.logify - * @param {*} target The target. - * @since 3.0.0 - */ - logify: function logify(target) { - utils.addHiddenPropsToTarget(target, { - dbg: function dbg() { - if (utils.isFunction(this.log)) { - for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { - args[_key3] = arguments[_key3]; - } - - this.log.apply(this, ['debug'].concat(args)); - } - }, - log: function log(level) { - for (var _len4 = arguments.length, args = new Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) { - args[_key4 - 1] = arguments[_key4]; - } - - if (level && !args.length) { - args.push(level); - level = 'debug'; - } - - if (level === 'debug' && !this.debug) { - return; - } - - var prefix = "".concat(level.toUpperCase(), ": (").concat(this.name || this.constructor.name, ")"); - - if (utils.isFunction(console[level])) { - var _console; - - (_console = console)[level].apply(_console, [prefix].concat(args)); - } else { - var _console2; - - (_console2 = console).log.apply(_console2, [prefix].concat(args)); - } - } - }); - }, - - /** - * Adds the given record to the provided array only if it's not already in the - * array. - * - * @example - * import { utils } from 'js-data'; - * const colors = ['red', 'green', 'yellow']; - * - * console.log(colors.length); // 3 - * utils.noDupeAdd(colors, 'red'); - * console.log(colors.length); // 3, red already exists - * - * utils.noDupeAdd(colors, 'blue'); - * console.log(colors.length); // 4, blue was added - * - * @method utils.noDupeAdd - * @param {array} array The array. - * @param {*} record The value to add. - * @param {Function} fn Callback function passed to {@link utils.findIndex}. - * @since 3.0.0 - */ - noDupeAdd: function noDupeAdd(array, record, fn) { - if (!array) { - return; - } - - var index = this.findIndex(array, fn); - - if (index < 0) { - array.push(record); - } - }, - - /** - * Return a shallow copy of the provided object, minus the properties - * specified in `keys`. - * - * @example - * import { utils } from 'js-data'; - * const a = { name: 'John', $hashKey: 1214910 }; - * - * let b = utils.omit(a, ['$hashKey']); - * console.log(b); // { name: 'John' } - * - * @method utils.omit - * @param {object} props The object to copy. - * @param {string[]} keys Array of strings, representing properties to skip. - * @returns {Object} Shallow copy of `props`, minus `keys`. - * @since 3.0.0 - */ - omit: function omit(props, keys) { - var _props = {}; - utils.forOwn(props, function (value, key) { - if (keys.indexOf(key) === -1) { - _props[key] = value; - } - }); - return _props; - }, - - /** - * Return a shallow copy of the provided object, but only include the - * properties specified in `keys`. - * - * @example - * import { utils } from 'js-data'; - * const a = { name: 'John', $hashKey: 1214910 }; - * - * let b = utils.pick(a, ['$hashKey']); - * console.log(b); // { $hashKey: 1214910 } - * - * @method utils.pick - * @param {object} props The object to copy. - * @param {string[]} keys Array of strings, representing properties to keep. - * @returns {Object} Shallow copy of `props`, but only including `keys`. - * @since 3.0.0 - */ - pick: function pick(props, keys) { - return keys.reduce(function (map, key) { - map[key] = props[key]; - return map; - }, {}); - }, - - /** - * Return a plain copy of the given value. - * - * @example - * import { utils } from 'js-data'; - * const a = { name: 'John' }; - * let b = utils.plainCopy(a); - * console.log(a === b); // false - * - * @method utils.plainCopy - * @param {*} value The value to copy. - * @returns {*} Plain copy of `value`. - * @see utils.copy - * @since 3.0.0 - */ - plainCopy: function plainCopy(value) { - return utils.copy(value, undefined, undefined, undefined, undefined, true); - }, - - /** - * Shortcut for `utils.Promise.reject(value)`. - * - * @example - * import { utils } from 'js-data'; - * - * utils.reject("Testing static reject").then(function (data) { - * // not called - * }).catch(function (reason) { - * console.log(reason); // "Testing static reject" - * }); - * - * @method utils.reject - * @param {*} [value] Value with which to reject the Promise. - * @returns {Promise} Promise reject with `value`. - * @see utils.Promise - * @since 3.0.0 - */ - reject: function reject(value) { - return utils.Promise.reject(value); - }, - - /** - * Remove the last item found in array according to the given checker function. - * - * @example - * import { utils } from 'js-data'; - * - * const colors = ['red', 'green', 'yellow', 'red']; - * utils.remove(colors, (color) => color === 'red'); - * console.log(colors); // ['red', 'green', 'yellow'] - * - * @method utils.remove - * @param {array} array The array to search. - * @param {Function} fn Checker function. - */ - remove: function remove(array, fn) { - if (!array || !array.length) { - return; - } - - var index = this.findIndex(array, fn); - - if (index >= 0) { - array.splice(index, 1); // todo should this be recursive? - } - }, - - /** - * Shortcut for `utils.Promise.resolve(value)`. - * - * @example - * import { utils } from 'js-data'; - * - * utils.resolve("Testing static resolve").then(function (data) { - * console.log(data); // "Testing static resolve" - * }).catch(function (reason) { - * // not called - * }); - * - * @param {*} [value] Value with which to resolve the Promise. - * @returns {Promise} Promise resolved with `value`. - * @see utils.Promise - * @since 3.0.0 - */ - resolve: function resolve(value) { - return utils.Promise.resolve(value); - }, - - /** - * Set the value at the provided key or path. - * - * @example - * import { utils } from 'js-data'; - * - * const john = { - * name: 'John', - * age: 25, - * parent: { - * name: 'John's Mom', - * age: 50 - * } - * }; - * // set value by key - * utils.set(john, 'id', 98); - * console.log(john.id); // 98 - * - * // set value by path - * utils.set(john, 'parent.id', 20); - * console.log(john.parent.id); // 20 - * - * // set value by path/value map - * utils.set(john, { - * 'id': 1098, - * 'parent': { id: 1020 }, - * 'parent.age': '55' - * }); - * console.log(john.id); // 1098 - * console.log(john.parent.id); // 1020 - * console.log(john.parent.age); // 55 - * - * @method utils.set - * @param {object} object The object on which to set a property. - * @param {(string|Object)} path The key or path to the property. Can also - * pass in an object of path/value pairs, which will all be set on the target - * object. - * @param {*} [value] The value to set. - */ - set: function set(object, path, value) { - if (utils.isObject(path)) { - utils.forOwn(path, function (value, _path) { - utils.set(object, _path, value); - }); - } else { - var parts = PATH.exec(path); - - if (parts) { - mkdirP(object, parts[1])[parts[2]] = value; - } else { - object[path] = value; - } - } - }, - - /** - * Check whether the two provided objects are deeply equal. - * - * @example - * import { utils } from 'js-data'; - * - * const objA = { - * name: 'John', - * id: 27, - * nested: { - * item: 'item 1', - * colors: ['red', 'green', 'blue'] - * } - * }; - * - * const objB = { - * name: 'John', - * id: 27, - * nested: { - * item: 'item 1', - * colors: ['red', 'green', 'blue'] - * } - * }; - * - * console.log(utils.deepEqual(a,b)); // true - * objB.nested.colors.add('yellow'); // make a change to a nested object's array - * console.log(utils.deepEqual(a,b)); // false - * - * @method utils.deepEqual - * @param {object} a First object in the comparison. - * @param {object} b Second object in the comparison. - * @returns {boolean} Whether the two provided objects are deeply equal. - * @see utils.equal - * @since 3.0.0 - */ - deepEqual: function deepEqual(a, b) { - if (a === b) { - return true; - } - - var _equal = true; - - if (utils.isArray(a) && utils.isArray(b)) { - if (a.length !== b.length) { - return false; - } - - for (var i = a.length; i--;) { - if (!utils.deepEqual(a[i], b[i])) { - // Exit loop early - return false; - } - } - } else if (utils.isObject(a) && utils.isObject(b)) { - utils.forOwn(a, function (value, key) { - if (!(_equal = utils.deepEqual(value, b[key]))) { - // Exit loop early - return false; - } - }); - - if (_equal) { - utils.forOwn(b, function (value, key) { - if (!(_equal = utils.deepEqual(value, a[key]))) { - // Exit loop early - return false; - } - }); - } - } else { - return false; - } - - return _equal; - }, - - /** - * Proxy for `JSON.stringify`. - * - * @example - * import { utils } from 'js-data'; - * - * const a = { name: 'John' }; - * let jsonVal = utils.toJson(a); - * console.log(jsonVal); // '{"name" : "John"}' - * - * @method utils.toJson - * @param {*} value Value to serialize to JSON. - * @returns {string} JSON string. - * @see utils.fromJson - * @since 3.0.0 - */ - toJson: JSON.stringify, - - /** - * Unset the value at the provided key or path. - * - * @example - * import { utils } from 'js-data'; - * - * const john = { - * name: 'John', - * age: 25, - * parent: { - * name: 'John's Mom', - * age: 50 - * } - * }; - * - * utils.unset(john, age); - * utils.unset(john, parent.age); - * - * console.log(john.age); // null - * console.log(john.parent.age); // null - * - * @method utils.unset - * @param {object} object The object from which to delete the property. - * @param {string} path The key or path to the property. - * @see utils.set - * @since 3.0.0 - */ - unset: function unset(object, path) { - var parts = path.split('.'); - var last = parts.pop(); - - while (path = parts.shift()) { - // eslint-disable-line - object = object[path]; - - if (object == null) { - // eslint-disable-line - return; - } - } - - object[last] = undefined; - } -}; -var safeSetProp = function safeSetProp(record, field, value) { - if (record && record._set) { - record._set("props.".concat(field), value); - } else { - utils.set(record, field, value); - } -}; -var safeSetLink = function safeSetLink(record, field, value) { - if (record && record._set) { - record._set("links.".concat(field), value); - } else { - utils.set(record, field, value); - } -}; +// TODO: remove this when the rest of the project is cleaned +const belongsToType = 'belongsTo'; +const hasManyType = 'hasMany'; +const hasOneType = 'hasOne'; +const DOMAIN$2 = 'Relation'; +class Relation { + constructor(relatedMapper, options = {}) { + this.TYPE_NAME = DOMAIN$2; + options.type = this.constructor.TYPE_NAME; + this.validateOptions(relatedMapper, options); + if (typeof relatedMapper === 'object') { + this.relatedMapper = relatedMapper; + } + utils.fillIn(this, options); + } + get canAutoAddLinks() { + return this.add === undefined || !!this.add; + } + get relatedCollection() { + return this.mapper.datastore.getCollection(this.relation); + } + validateOptions(related, opts) { + const DOMAIN_ERR = `new ${DOMAIN$2}`; + const localField = opts.localField; + if (!localField) { + throw utils.err(DOMAIN_ERR, 'opts.localField')(400, 'string', localField); + } + const foreignKey = (opts.foreignKey = opts.foreignKey || opts.localKey); + if (!foreignKey && (opts.type === belongsToType || opts.type === hasOneType)) { + throw utils.err(DOMAIN_ERR, 'opts.foreignKey')(400, 'string', foreignKey); + } + if (utils.isString(related)) { + opts.relation = related; + if (!utils.isFunction(opts.getRelation)) { + throw utils.err(DOMAIN_ERR, 'opts.getRelation')(400, 'function', opts.getRelation); + } + } + else if (related) { + opts.relation = related.name; + } + else { + throw utils.err(DOMAIN_ERR, 'related')(400, 'Mapper or string', related); + } + } + assignTo(mapper) { + this.name = mapper.name; + Object.defineProperty(this, 'mapper', { value: mapper }); + if (!mapper.relationList) + Object.defineProperty(mapper, 'relationList', { value: [] }); + if (!mapper.relationFields) + Object.defineProperty(mapper, 'relationFields', { value: [] }); + mapper.relationList.push(this); + mapper.relationFields.push(this.localField); + } + canFindLinkFor(record) { + return !!(this.foreignKey || this.localKey); + } + getRelation() { + return this.relatedMapper; + } + getForeignKey(record) { + return utils.get(record, this.mapper.idAttribute); + } + setForeignKey(record, relatedRecord) { + if (!record || !relatedRecord) { + return; + } + this._setForeignKey(record, relatedRecord); + } + _setForeignKey(record, relatedRecords) { + const idAttribute = this.mapper.idAttribute; + if (!utils.isArray(relatedRecords)) { + relatedRecords = [relatedRecords]; + } + relatedRecords.forEach(relatedRecord => { + utils.set(relatedRecord, this.foreignKey, utils.get(record, idAttribute)); + }); + } + getLocalField(record) { + return utils.get(record, this.localField); + } + setLocalField(record, relatedData) { + return utils.set(record, this.localField, relatedData); + } + getInverse(mapper) { + if (!this.inverse) { + this.findInverseRelation(mapper); + } + return this.inverse; + } + findInverseRelation(mapper) { + this.getRelation().relationList.forEach(def => { + if (def.getRelation() === mapper && this.isInversedTo(def) && this !== def) { + this.inverse = def; + return true; + } + }); + } + isInversedTo(def) { + return !def.foreignKey || def.foreignKey === this.foreignKey; + } + addLinkedRecords(records) { + const datastore = this.mapper.datastore; + records.forEach(record => { + let relatedData = this.getLocalField(record); + if (utils.isFunction(this.add)) { + relatedData = this.add(datastore, this, record); + } + else if (relatedData) { + relatedData = this.linkRecord(record, relatedData); + } + const isEmptyLinks = !relatedData || (utils.isArray(relatedData) && !relatedData.length); + if (isEmptyLinks && this.canFindLinkFor(record)) { + relatedData = this.findExistingLinksFor(record); + } + if (relatedData) { + this.setLocalField(record, relatedData); + } + }); + } + removeLinkedRecords(relatedMapper, records) { + const localField = this.localField; + records.forEach(record => { + utils.set(record, localField, undefined); + }); + } + linkRecord(record, relatedRecord) { + const relatedId = utils.get(relatedRecord, this.mapper.idAttribute); + if (relatedId === undefined) { + const unsaved = this.relatedCollection.unsaved(); + if (unsaved.indexOf(relatedRecord) === -1) { + if (this.canAutoAddLinks) { + relatedRecord = this.relatedCollection.add(relatedRecord); + } + } + } + else { + if (relatedRecord !== this.relatedCollection.get(relatedId)) { + this.setForeignKey(record, relatedRecord); + if (this.canAutoAddLinks) { + relatedRecord = this.relatedCollection.add(relatedRecord); + } + } + } + return relatedRecord; + } + // e.g. user hasMany post via "foreignKey", so find all posts of user + findExistingLinksByForeignKey(id) { + if (id === undefined || id === null) { + return; + } + return this.relatedCollection.filter({ + [this.foreignKey]: id + }); + } + ensureLinkedDataHasProperType(props, opts) { + const relatedMapper = this.getRelation(); + const relationData = this.getLocalField(props); + if (utils.isArray(relationData) && (!relationData.length || relatedMapper.is(relationData[0]))) { + return; + } + if (relationData && !relatedMapper.is(relationData)) { + utils.set(props, this.localField, relatedMapper.createRecord(relationData, opts)); + } + } + isRequiresParentId() { + return false; + } + isRequiresChildId() { + return false; + } + createChildRecord(props, relationData, opts) { + this.setForeignKey(props, relationData); + return this.createLinked(relationData, opts).then(result => { + this.setLocalField(props, result); + }); + } + createLinked(props, opts) { + const create = utils.isArray(props) ? 'createMany' : 'create'; + return this.getRelation()[create](props, opts); + } +} -/** - * A base class which gives instances private properties. - * - * Typically you won't instantiate this class directly, but you may find it - * useful as an abstract class for your own components. - * - * See {@link Settable.extend} for an example of using {@link Settable} as a - * base class. - * - *```javascript - * import {Settable} from 'js-data' - * ``` - * - * @class Settable - * @returns {Settable} A new {@link Settable} instance. - * @since 3.0.0 +const DOMAIN$3 = 'Record'; +function superMethod(mapper, name) { + var _a; + const store = mapper.datastore; + if ((_a = store) === null || _a === void 0 ? void 0 : _a[name]) { + return (...args) => store[name](mapper.name, ...args); + } + return mapper[name].bind(mapper); +} +// Cache these strings +const creatingPath = 'creating'; +const noValidatePath = 'noValidate'; +const keepChangeHistoryPath = 'keepChangeHistory'; +const previousPath = 'previous'; +/** + * js-data's Record class. An instance of `Record` corresponds to an in-memory + * representation of a single row or document in a database, Firebase, + * localstorage, etc. Basically, a `Record` instance represents whatever kind of + * entity in your persistence layer that has a primary key. + * + * ```javascript + * import {Record} from 'js-data' + * ``` + * + * @example Record#constructor + * const JSData = require('js-data'); + * const { Record } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * // Instantiate a plain record + * let record = new Record(); + * console.log('record: ' + JSON.stringify(record)); + * + * // You can supply properties on instantiation + * record = new Record({ name: 'John' }); + * console.log('record: ' + JSON.stringify(record)); + * + * @example Record#constructor2 + * const JSData = require('js-data'); + * const { Mapper } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * // Instantiate a record that's associated with a Mapper: + * const UserMapper = new Mapper({ name: 'user' }); + * const User = UserMapper.recordClass; + * const user = UserMapper.createRecord({ name: 'John' }); + * const user2 = new User({ name: 'Sally' }); + * console.log('user: ' + JSON.stringify(user)); + * console.log('user2: ' + JSON.stringify(user2)); + * + * @example Record#constructor3 + * const JSData = require('js-data'); + * const { Container } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new Container(); + * store.defineMapper('user'); + * + * // Instantiate a record that's associated with a store's Mapper + * const user = store.createRecord('user', { name: 'John' }); + * console.log('user: ' + JSON.stringify(user)); + * + * @example Record#constructor4 + * const JSData = require('js-data'); + * const { Container } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new Container(); + * store.defineMapper('user', { + * schema: { + * properties: { + * name: { type: 'string' } + * } + * } + * }); + * + * // Validate on instantiation + * const user = store.createRecord('user', { name: 1234 }); + * console.log('user: ' + JSON.stringify(user)); + * + * @example Record#constructor5 + * const JSData = require('js-data'); + * const { Container } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new Container(); + * store.defineMapper('user', { + * schema: { + * properties: { + * name: { type: 'string' } + * } + * } + * }); + * + * // Skip validation on instantiation + * const user = store.createRecord('user', { name: 1234 }, { noValidate: true }); + * console.log('user: ' + JSON.stringify(user)); + * console.log('user.isValid(): ' + user.isValid()); + * + * @class Record + * @extends Settable + * @param {object} [props] The initial properties of the new Record instance. + * @param {object} [opts] Configuration options. + * @param {boolean} [opts.noValidate=false] Whether to skip validation on the + * initial properties. + * @param {boolean} [opts.validateOnSet=true] Whether to enable setter + * validation on properties after the Record has been initialized. + * @since 3.0.0 + */ +class Record extends Settable { + constructor(props = {}, opts = {}) { + var _a; + super(); + const _set = this._set; + const mapper = this.constructor.mapper; + _set(creatingPath, true); + _set(noValidatePath, !!opts.noValidate); + _set(keepChangeHistoryPath, opts.keepChangeHistory === undefined ? (mapper ? mapper.keepChangeHistory : true) : opts.keepChangeHistory); + // Set the idAttribute value first, if it exists. + const id = mapper ? utils.get(props, mapper.idAttribute) : undefined; + if (id !== undefined) { + utils.set(this, mapper.idAttribute, id); + } + utils.fillIn(this, props); + _set(creatingPath, false); + if (opts.validateOnSet !== undefined) { + _set(noValidatePath, !opts.validateOnSet); + } + else if (((_a = mapper) === null || _a === void 0 ? void 0 : _a.validateOnSet) !== undefined) { + _set(noValidatePath, !mapper.validateOnSet); + } + else { + _set(noValidatePath, false); + } + _set(previousPath, mapper ? mapper.toJSON(props) : utils.plainCopy(props)); + } + /** + * Returns the {@link Mapper} paired with this record's class, if any. + * + * @method Record#_mapper + * @returns {Mapper} The {@link Mapper} paired with this record's class, if any. + * @since 3.0.0 + */ + _mapper() { + const mapper = this.constructor.mapper; + if (!mapper) { + throw utils.err(`${DOMAIN$3}#_mapper`, '')(404, 'mapper'); + } + return mapper; + } + /** + * Lifecycle hook. + * + * @method Record#afterLoadRelations + * @param {string[]} relations The `relations` argument passed to {@link Record#loadRelations}. + * @param {object} opts The `opts` argument passed to {@link Record#loadRelations}. + * @since 3.0.0 + */ + afterLoadRelations(relations, opts) { } + /** + * Lifecycle hook. + * + * @method Record#beforeLoadRelations + * @param {string[]} relations The `relations` argument passed to {@link Record#loadRelations}. + * @param {object} opts The `opts` argument passed to {@link Record#loadRelations}. + * @since 3.0.0 + */ + beforeLoadRelations(relations, opts) { } + /** + * Return the change history of this record since it was instantiated or + * {@link Record#commit} was called. + * + * @method Record#changeHistory + * @since 3.0.0 + */ + changeHistory() { + return (this._get('history') || []).slice(); + } + /** + * Return changes to this record since it was instantiated or + * {@link Record#commit} was called. + * + * @example Record#changes + * const JSData = require('js-data'); + * const { Container } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new Container(); + * store.defineMapper('user'); + * const user = store.createRecord('user'); + * console.log('user changes: ' + JSON.stringify(user.changes())); + * user.name = 'John'; + * console.log('user changes: ' + JSON.stringify(user.changes())); + * + * @method Record#changes + * @param [opts] Configuration options. + * @param {Function} [opts.equalsFn={@link utils.deepEqual}] Equality function. + * @param {array} [opts.ignore=[]] Array of strings or RegExp of fields to ignore. + * @returns {Object} Object describing the changes to this record since it was + * instantiated or its {@link Record#commit} method was last called. + * @since 3.0.0 + */ + changes(opts = {}) { + return utils.diffObjects(typeof this.toJSON === 'function' ? this.toJSON(opts) : this, this._get('previous'), opts); + } + /** + * Make the record's current in-memory state it's only state, with any + * previous property values being set to current values. + * + * @example Record#commit + * const JSData = require('js-data'); + * const { Container } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new Container(); + * store.defineMapper('user'); + * const user = store.createRecord('user'); + * console.log('user hasChanges: ' + user.hasChanges()); + * user.name = 'John'; + * console.log('user hasChanges: ' + user.hasChanges()); + * user.commit(); + * console.log('user hasChanges: ' + user.hasChanges()); + * + * @method Record#commit + * @param {object} [opts] Configuration options. Passed to {@link Record#toJSON}. + * @since 3.0.0 + */ + commit(opts) { + this._set('changed'); // unset + this._set('changing', false); + this._set('history', []); // clear history + this._set('previous', this.toJSON(opts)); + } + /** + * Call {@link Mapper#destroy} using this record's primary key. + * + * @example + * import { Container } from 'js-data'; + * import { RethinkDBAdapter } from 'js-data-rethinkdb'; + * + * const store = new Container(); + * store.registerAdapter('rethink', new RethinkDBAdapter(), { default: true }); + * store.defineMapper('user'); + * store.find('user', 1234).then((user) => { + * console.log(user.id); // 1234 + * + * // Destroy this user from the database + * return user.destroy(); + * }); + * + * @method Record#destroy + * @param {object} [opts] Configuration options passed to {@link Mapper#destroy}. + * @returns {Promise} The result of calling {@link Mapper#destroy} with the + * primary key of this record. + * @since 3.0.0 + */ + destroy(opts = {}) { + const mapper = this._mapper(); + return superMethod(mapper, 'destroy')(utils.get(this, mapper.idAttribute), opts); + } + /** + * Return the value at the given path for this instance. + * + * @example Record#get + * const JSData = require('js-data'); + * const { Container } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * const store = new Container(); + * store.defineMapper('user'); + * + * const user = store.createRecord('user', { name: 'Bob' }); + * console.log('user.get("name"): ' + user.get('name')); + * + * @method Record#get + * @param {string} key Path of value to retrieve. + * @returns {*} Value at path. + * @since 3.0.0 + */ + get(key) { + return utils.get(this, key); + } + /** + * Return whether this record has changed since it was instantiated or + * {@link Record#commit} was called. + * + * @example Record#hasChanges + * const JSData = require('js-data'); + * const { Container } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * const store = new Container(); + * store.defineMapper('user'); + * const user = store.createRecord('user'); + * console.log('user hasChanges: ' + user.hasChanges()); + * user.name = 'John'; + * console.log('user hasChanges: ' + user.hasChanges()); + * user.commit(); + * console.log('user hasChanges: ' + user.hasChanges()); + * + * @method Record#hasChanges + * @param [opts] Configuration options. + * @param {Function} [opts.equalsFn={@link utils.deepEqual}] Equality function. + * @param {array} [opts.ignore=[]] Array of strings or RegExp of fields to ignore. + * @returns {boolean} Return whether the record has changed since it was + * instantiated or since its {@link Record#commit} method was called. + * @since 3.0.0 + */ + hasChanges(opts) { + const quickHasChanges = !!(this._get('changed') || []).length; + return (quickHasChanges || + utils.areDifferent(typeof this.toJSON === 'function' ? this.toJSON(opts) : this, this._get('previous'), opts)); + } + /** + * Return whether the record is unsaved. Records that have primary keys are + * considered "saved". Records without primary keys are considered "unsaved". + * + * @example Record#isNew + * const JSData = require('js-data'); + * const { Container } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * const store = new Container(); + * store.defineMapper('user'); + * const user = store.createRecord('user', { + * id: 1234 + * }); + * const user2 = store.createRecord('user'); + * console.log('user isNew: ' + user.isNew()); // false + * console.log('user2 isNew: ' + user2.isNew()); // true + * + * @method Record#isNew + * @returns {boolean} Whether the record is unsaved. + * @since 3.0.0 + */ + isNew(opts) { + return utils.get(this, this._mapper().idAttribute) === undefined; + } + /** + * Return whether the record in its current state passes validation. + * + * @example Record#isValid + * const JSData = require('js-data'); + * const { Container } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * const store = new Container(); + * store.defineMapper('user', { + * schema: { + * properties: { + * name: { type: 'string' } + * } + * } + * }); + * const user = store.createRecord('user', { + * name: 1234 + * }, { + * noValidate: true // this allows us to put the record into an invalid state + * }); + * console.log('user isValid: ' + user.isValid()); + * user.name = 'John'; + * console.log('user isValid: ' + user.isValid()); + * + * @method Record#isValid + * @param {object} [opts] Configuration options. Passed to {@link Mapper#validate}. + * @returns {boolean} Whether the record in its current state passes + * validation. + * @since 3.0.0 + */ + isValid(opts) { + return !this._mapper().validate(this, opts); + } + removeInverseRelation(currentParent, id, inverseDef, idAttribute) { + if (inverseDef.type === hasOneType) { + safeSetLink(currentParent, inverseDef.localField, undefined); + } + else if (inverseDef.type === hasManyType) { + // e.g. remove comment from otherPost.comments + const children = utils.get(currentParent, inverseDef.localField); + if (id === undefined) { + utils.remove(children, child => child === this); + } + else { + utils.remove(children, child => child === this || id === utils.get(child, idAttribute)); + } + } + } + setupInverseRelation(record, id, inverseDef, idAttribute) { + // Update (set) inverse relation + if (inverseDef.type === hasOneType) { + // e.g. someUser.profile = profile + safeSetLink(record, inverseDef.localField, this); + } + else if (inverseDef.type === hasManyType) { + // e.g. add comment to somePost.comments + const children = utils.get(record, inverseDef.localField); + if (id === undefined) { + utils.noDupeAdd(children, this, child => child === this); + } + else { + utils.noDupeAdd(children, this, child => child === this || id === utils.get(child, idAttribute)); + } + } + } + /** + * Lazy load relations of this record, to be attached to the record once their + * loaded. + * + * @example + * import { Container } from 'js-data'; + * import { RethinkDBAdapter } from 'js-data-rethinkdb'; + * + * const store = new Container(); + * store.registerAdapter('rethink', new RethinkDBAdapter(), { default: true }); + * store.defineMapper('user', { + * relations: { + * hasMany: { + * post: { + * localField: 'posts', + * foreignKey: 'user_id' + * } + * } + * } + * }); + * store.defineMapper('post', { + * relations: { + * belongsTo: { + * user: { + * localField: 'user', + * foreignKey: 'user_id' + * } + * } + * } + * }); + * store.find('user', 1234).then((user) => { + * console.log(user.id); // 1234 + * + * // Load the user's post relations + * return user.loadRelations(['post']); + * }).then((user) => { + * console.log(user.posts); // [{...}, {...}, ...] + * }); + * + * @method Record#loadRelations + * @param {string[]} [relations] List of relations to load. Can use localField + * names or Mapper names to pick relations. + * @param {object} [opts] Configuration options. + * @returns {Promise} Resolves with the record, with the loaded relations now + * attached. + * @since 3.0.0 + */ + loadRelations(relations = [], opts = {}) { + let op; + const mapper = this._mapper(); + if (utils.isString(relations)) { + relations = [relations]; + } + opts.with = relations; + // Fill in "opts" with the Model's configuration + utils._(opts, mapper); + opts.adapter = mapper.getAdapterName(opts); + // beforeLoadRelations lifecycle hook + op = opts.op = 'beforeLoadRelations'; + return utils + .resolve(this[op](relations, opts)) + .then(() => { + // Now delegate to the adapter + op = opts.op = 'loadRelations'; + mapper.dbg(op, this, relations, opts); + const tasks = []; + let task; + utils.forEachRelation(mapper, opts, (def, optsCopy) => { + const relatedMapper = def.getRelation(); + optsCopy.raw = false; + if (utils.isFunction(def.load)) { + task = def.load(mapper, def, this, opts); + } + else if (def.type === 'hasMany' || def.type === 'hasOne') { + if (def.foreignKey) { + task = superMethod(relatedMapper, 'findAll')({ + [def.foreignKey]: utils.get(this, mapper.idAttribute) + }, optsCopy).then(relatedData => def.type === 'hasOne' ? (relatedData.length ? relatedData[0] : undefined) : relatedData); + } + else if (def.localKeys) { + task = superMethod(relatedMapper, 'findAll')({ + where: { + [relatedMapper.idAttribute]: { + in: utils.get(this, def.localKeys) + } + } + }); + } + else if (def.foreignKeys) { + task = superMethod(relatedMapper, 'findAll')({ + where: { + [def.foreignKeys]: { + contains: utils.get(this, mapper.idAttribute) + } + } + }, opts); + } + } + else if (def.type === 'belongsTo') { + const key = utils.get(this, def.foreignKey); + if (utils.isSorN(key)) { + task = superMethod(relatedMapper, 'find')(key, optsCopy); + } + } + if (task) { + task = task.then(relatedData => { + def.setLocalField(this, relatedData); + }); + tasks.push(task); + } + }); + return Promise.all(tasks); + }) + .then(() => { + // afterLoadRelations lifecycle hook + op = opts.op = 'afterLoadRelations'; + return utils.resolve(this[op](relations, opts)).then(() => this); + }); + } + /** + * Return the properties with which this record was instantiated. + * + * @example Record#previous + * const JSData = require('js-data'); + * const { Container } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * const store = new Container(); + * store.defineMapper('user'); + * const user = store.createRecord('user', { + * name: 'William' + * }); + * console.log('user previous: ' + JSON.stringify(user.previous())); + * user.name = 'Bob'; + * console.log('user previous: ' + JSON.stringify(user.previous())); + * user.commit(); + * console.log('user previous: ' + JSON.stringify(user.previous())); + * + * @method Record#previous + * @param {string} [key] If specified, return just the initial value of the + * given key. + * @returns {Object} The initial properties of this record. + * @since 3.0.0 + */ + previous(key) { + if (key) { + return this._get(`previous.${key}`); + } + return this._get('previous'); + } + /** + * Revert changes to this record back to the properties it had when it was + * instantiated. + * + * @example Record#revert + * const JSData = require('js-data'); + * const { Container } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * const store = new Container(); + * store.defineMapper('user'); + * const user = store.createRecord('user', { + * name: 'William' + * }); + * console.log('user: ' + JSON.stringify(user)); + * user.name = 'Bob'; + * console.log('user: ' + JSON.stringify(user)); + * user.revert(); + * console.log('user: ' + JSON.stringify(user)); + * + * @method Record#revert + * @param {object} [opts] Configuration options. + * @param {string[]} [opts.preserve] Array of strings or Regular Expressions + * denoting properties that should not be reverted. + * @since 3.0.0 + */ + revert(opts = {}) { + const previous = this._get('previous'); + opts.preserve = opts.preserve || []; + utils.forOwn(this, (value, key) => { + if (key !== this._mapper().idAttribute && + !previous.hasOwnProperty(key) && + this.hasOwnProperty(key) && + opts.preserve.indexOf(key) === -1) { + delete this[key]; + } + }); + utils.forOwn(previous, (value, key) => { + if (opts.preserve.indexOf(key) === -1) { + this[key] = value; + } + }); + this.commit(); + } + /** + * Delegates to {@link Mapper#create} or {@link Mapper#update}. + * + * @example + * import { Container } from 'js-data'; + * import { RethinkDBAdapter } from 'js-data-rethinkdb'; + * + * const store = new Container(); + * store.registerAdapter('rethink', new RethinkDBAdapter(), { default: true }); + * store.defineMapper('session'); + * const session = store.createRecord('session', { topic: 'Node.js' }); + * + * // Create a new record in the database + * session.save().then(() => { + * console.log(session.id); // 1234 + * + * session.skill_level = 'beginner'; + * + * // Update the record in the database + * return session.save(); + * }); + * + * @method Record#save + * @param {object} [opts] Configuration options. See {@link Mapper#create} and + * {@link Mapper#update}. + * @param {boolean} [opts.changesOnly] Equality function. Default uses `===`. + * @param {Function} [opts.equalsFn] Passed to {@link Record#changes} when + * `opts.changesOnly` is `true`. + * @param {array} [opts.ignore] Passed to {@link Record#changes} when + * `opts.changesOnly` is `true`. + * @returns {Promise} The result of calling {@link Mapper#create} or + * {@link Mapper#update}. + * @since 3.0.0 + */ + save(opts = {}) { + const mapper = this._mapper(); + const id = utils.get(this, mapper.idAttribute); + let props = this; + const postProcess = result => { + const record = opts.raw ? result.data : result; + if (record) { + utils.deepMixIn(this, record); + this.commit(); + } + return result; + }; + if (id === undefined) { + return superMethod(mapper, 'create')(props, opts).then(postProcess); + } + if (opts.changesOnly) { + const changes = this.changes(opts); + props = {}; + utils.fillIn(props, changes.added); + utils.fillIn(props, changes.changed); + } + return superMethod(mapper, 'update')(id, props, opts).then(postProcess); + } + /** + * Set the value for a given key, or the values for the given keys if "key" is + * an object. Triggers change events on those properties that have `track: true` + * in {@link Mapper#schema}. + * + * @example Record#set + * const JSData = require('js-data'); + * const { Container } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * const store = new Container(); + * store.defineMapper('user'); + * + * const user = store.createRecord('user'); + * console.log('user: ' + JSON.stringify(user)); + * + * user.set('name', 'Bob'); + * console.log('user: ' + JSON.stringify(user)); + * + * user.set({ age: 30, role: 'admin' }); + * console.log('user: ' + JSON.stringify(user)); + * + * @fires Record#change + * @method Record#set + * @param {(string|Object)} key Key to set or hash of key-value pairs to set. + * @param {*} [value] Value to set for the given key. + * @param {object} [opts] Configuration options. + * @param {boolean} [opts.silent=false] Whether to trigger change events. + * @since 3.0.0 + */ + set(key, value, opts) { + if (utils.isObject(key)) { + opts = value; + } + opts = opts || {}; + if (opts.silent) { + this._set('silent', true); + } + utils.set(this, key, value); + if (!this._get('eventId')) { + this._set('silent'); // unset + } + } + /** + * Return a plain object representation of this record. If the class from + * which this record was created has a Mapper, then {@link Mapper#toJSON} will + * be called with this record instead. + * + * @example Record#toJSON + * const JSData = require('js-data'); + * const { Container } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * const store = new Container(); + * store.defineMapper('user', { + * schema: { + * properties: { + * name: { type: 'string' } + * } + * } + * }); + * + * const user = store.createRecord('user', { + * name: 'John', + * $$hashKey: '1234' + * }); + * console.log('user: ' + JSON.stringify(user.toJSON())); + * + * @method Record#toJSON + * @param {object} [opts] Configuration options. + * @param {string[]} [opts.with] Array of relation names or relation fields + * to include in the representation. Only available as an option if the class + * from which this record was created has a Mapper and this record resides in + * an instance of {@link DataStore}. + * @returns {Object} Plain object representation of this record. + * @since 3.0.0 + */ + toJSON(opts) { + const mapper = this.constructor.mapper; + if (mapper) { + return mapper.toJSON(this, opts); + } + else { + const json = {}; + utils.forOwn(this, (prop, key) => { + json[key] = utils.plainCopy(prop); + }); + return json; + } + } + /** + * Unset the value for a given key. Triggers change events on those properties + * that have `track: true` in {@link Mapper#schema}. + * + * @example Record#unset + * const JSData = require('js-data'); + * const { Container } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * const store = new Container(); + * store.defineMapper('user'); + * + * const user = store.createRecord('user', { + * name: 'John' + * }); + * console.log('user: ' + JSON.stringify(user)); + * + * user.unset('name'); + * console.log('user: ' + JSON.stringify(user)); + * + * @method Record#unset + * @param {string} key Key to unset. + * @param {object} [opts] Configuration options. + * @param {boolean} [opts.silent=false] Whether to trigger change events. + * @since 3.0.0 + */ + unset(key, opts) { + this.set(key, undefined, opts); + } + /** + * Validate this record based on its current properties. + * + * @example Record#validate + * const JSData = require('js-data'); + * const { Container } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * const store = new Container(); + * store.defineMapper('user', { + * schema: { + * properties: { + * name: { type: 'string' } + * } + * } + * }); + * const user = store.createRecord('user', { + * name: 1234 + * }, { + * noValidate: true // this allows us to put the record into an invalid state + * }); + * console.log('user validation: ' + JSON.stringify(user.validate())); + * user.name = 'John'; + * console.log('user validation: ' + user.validate()); + * + * @method Record#validate + * @param {object} [opts] Configuration options. Passed to {@link Mapper#validate}. + * @returns {*} Array of errors or `undefined` if no errors. + * @since 3.0.0 + */ + validate(opts) { + return this._mapper().validate(this, opts); + } +} +Record.creatingPath = creatingPath; +Record.noValidatePath = noValidatePath; +Record.keepChangeHistoryPath = keepChangeHistoryPath; +Record.previousPath = previousPath; +/** + * Allow records to emit events. + * + * An record's registered listeners are stored in the record's private data. + */ +utils.eventify(Record.prototype, function () { + return this._get('events'); +}, function (value) { + this._set('events', value); +}); +/** + * Fired when a record changes. Only works for records that have tracked fields. + * See {@link Record~changeListener} on how to listen for this event. + * + * @event Record#change + * @see Record~changeListener + */ +/** + * Callback signature for the {@link Record#event:change} event. + * + * @example + * function onChange (record, changes) { + * // do something + * } + * record.on('change', onChange); + * + * @callback Record~changeListener + * @param {Record} The Record that changed. + * @param {object} The changes. + * @see Record#event:change + * @since 3.0.0 + */ +/** + * Create a subclass of this Record: + * @example Record.extend + * const JSData = require('js-data'); + * const { Record } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * // Extend the class using ES2015 class syntax. + * class CustomRecordClass extends Record { + * foo () { return 'bar'; } + * static beep () { return 'boop'; } + * } + * const customRecord = new CustomRecordClass(); + * console.log(customRecord.foo()); + * console.log(CustomRecordClass.beep()); + * + * // Extend the class using alternate method. + * const OtherRecordClass = Record.extend({ + * foo () { return 'bar'; } + * }, { + * beep () { return 'boop'; } + * }); + * const otherRecord = new OtherRecordClass(); + * console.log(otherRecord.foo()); + * console.log(OtherRecordClass.beep()); + * + * // Extend the class, providing a custom constructor. + * function AnotherRecordClass () { + * Record.call(this); + * this.created_at = new Date().getTime(); + * } + * Record.extend({ + * constructor: AnotherRecordClass, + * foo () { return 'bar'; } + * }, { + * beep () { return 'boop'; } + * }); + * const anotherRecord = new AnotherRecordClass(); + * console.log(anotherRecord.created_at); + * console.log(anotherRecord.foo()); + * console.log(AnotherRecordClass.beep()); + * + * @method Record.extend + * @param {object} [props={}] Properties to add to the prototype of the + * subclass. + * @param {object} [props.constructor] Provide a custom constructor function + * to be used as the subclass itself. + * @param {object} [classProps={}] Static properties to add to the subclass. + * @returns {Constructor} Subclass of this Record class. + * @since 3.0.0 */ -function Settable() { - var _props = {}; - Object.defineProperties(this, { - /** - * Get a private property of this instance. - * - * __Don't use the method unless you know what you're doing.__ - * - * @method Settable#_get - * @param {string} key The property to retrieve. - * @returns {*} The value of the property. - * @since 3.0.0 - */ - _get: { - value: function value(key) { - return utils.get(_props, key); - } - }, - - /** - * Set a private property of this instance. - * - * __Don't use the method unless you know what you're doing.__ - * - * @method __Don't use the method unless you know what you're doing.__#_set - * @param {(string|Object)} key The key or path to the property. Can also - * pass in an object of key/value pairs, which will all be set on the instance. - * @param {*} [value] The value to set. - * @since 3.0.0 - */ - _set: { - value: function value(key, _value) { - return utils.set(_props, key, _value); - } - }, - - /** - * Unset a private property of this instance. - * - * __Don't use the method unless you know what you're doing.__ - * - * @method __Don't use the method unless you know what you're doing.__#_unset - * @param {string} key The property to unset. - * @since 3.0.0 - */ - _unset: { - value: function value(key) { - return utils.unset(_props, key); - } - } - }); +function sort(a, b, hashCode) { + // Short-circuit comparison if a and b are strictly equal + // This is absolutely necessary for indexed objects that + // don't have the idAttribute field + if (a === b) { + return 0; + } + else if (hashCode) { + a = hashCode(a); + b = hashCode(b); + } + return (a === null && b === null) || (a === undefined && b === undefined) + ? -1 + : a === null || a === undefined + ? -1 + : b === null || b === undefined + ? 1 + : a < b + ? -1 + : a > b + ? 1 + : 0; +} +function insertAt(array, index, value) { + array.splice(index, 0, value); + return array; +} +function removeAt(array, index) { + array.splice(index, 1); + return array; +} +function binarySearch(array, value, field) { + let lo = 0; + let hi = array.length; + let compared; + let mid; + while (lo < hi) { + // tslint:disable-next-line:no-bitwise + mid = ((lo + hi) / 2) | 0; + compared = sort(value, array[mid], field); + if (compared === 0) { + return { + found: true, + index: mid + }; + } + else if (compared < 0) { + hi = mid; + } + else { + lo = mid + 1; + } + } + return { + found: false, + index: hi + }; } -/** - * Create a subclass of this Settable: - * - * @example Settable.extend - * const JSData = require('js-data'); - * const { Settable } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * // Extend the class using ES2015 class syntax. - * class CustomSettableClass extends Settable { - * foo () { return 'bar'; } - * static beep () { return 'boop'; } - * } - * const customSettable = new CustomSettableClass(); - * console.log(customSettable.foo()); - * console.log(CustomSettableClass.beep()); - * - * // Extend the class using alternate method. - * const OtherSettableClass = Settable.extend({ - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }); - * const otherSettable = new OtherSettableClass(); - * console.log(otherSettable.foo()); - * console.log(OtherSettableClass.beep()); - * - * // Extend the class, providing a custom constructor. - * function AnotherSettableClass () { - * Settable.call(this); - * this.created_at = new Date().getTime(); - * } - * Settable.extend({ - * constructor: AnotherSettableClass, - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }) - * const anotherSettable = new AnotherSettableClass(); - * console.log(anotherSettable.created_at); - * console.log(anotherSettable.foo()); - * console.log(AnotherSettableClass.beep()); - * - * @method Settable.extend - * @param {object} [props={}] Properties to add to the prototype of the - * subclass. - * @param {object} [props.constructor] Provide a custom constructor function - * to be used as the subclass itself. - * @param {object} [classProps={}] Static properties to add to the subclass. - * @returns {Constructor} Subclass of this Settable class. - * @since 3.0.0 - */ -Settable.extend = utils.extend; +// Copyright (c) 2015, InternalFX. +class Index { + constructor(fieldList = [], opts = {}) { + if (!utils.isArray(fieldList)) { + throw new Error('fieldList must be an array.'); + } + this.fieldList = fieldList; + this.fieldGetter = opts.fieldGetter; + this.hashCode = opts.hashCode; + this.isIndex = true; + this.keys = []; + this.values = []; + } + set(keyList, value) { + if (!utils.isArray(keyList)) { + keyList = [keyList]; + } + const key = keyList.shift() || undefined; + const pos = binarySearch(this.keys, key); + if (keyList.length === 0) { + if (pos.found) { + const dataLocation = binarySearch(this.values[pos.index], value, this.hashCode); + if (!dataLocation.found) { + insertAt(this.values[pos.index], dataLocation.index, value); + } + } + else { + insertAt(this.keys, pos.index, key); + insertAt(this.values, pos.index, [value]); + } + } + else { + if (pos.found) { + this.values[pos.index].set(keyList, value); + } + else { + insertAt(this.keys, pos.index, key); + const newIndex = new Index([], { hashCode: this.hashCode }); + newIndex.set(keyList, value); + insertAt(this.values, pos.index, newIndex); + } + } + } + get(keyList) { + if (!utils.isArray(keyList)) { + keyList = [keyList]; + } + const key = keyList.shift() || undefined; + const pos = binarySearch(this.keys, key); + if (keyList.length === 0) { + if (pos.found) { + if (this.values[pos.index].isIndex) { + return this.values[pos.index].getAll(); + } + else { + return this.values[pos.index].slice(); + } + } + else { + return []; + } + } + else { + if (pos.found) { + return this.values[pos.index].get(keyList); + } + else { + return []; + } + } + } + getAll(opts = {}) { + let results = []; + const values = this.values; + if (opts.order === 'desc') { + for (let i = values.length - 1; i >= 0; i--) { + const value = values[i]; + if (value.isIndex) { + results = results.concat(value.getAll(opts)); + } + else { + results = results.concat(value); + } + } + } + else { + for (const value of values) { + if (value.isIndex) { + results = results.concat(value.getAll(opts)); + } + else { + results = results.concat(value); + } + } + } + return results; + } + visitAll(cb, thisArg) { + this.values.forEach(value => { + if (value.isIndex) { + value.visitAll(cb, thisArg); + } + else { + value.forEach(cb, thisArg); + } + }); + } + between(leftKeys, rightKeys, opts = {}) { + if (!utils.isArray(leftKeys)) { + leftKeys = [leftKeys]; + } + if (!utils.isArray(rightKeys)) { + rightKeys = [rightKeys]; + } + utils.fillIn(opts, { + leftInclusive: true, + rightInclusive: false, + limit: undefined, + offset: 0 + }); + const results = this._between(leftKeys, rightKeys, opts); + if (opts.limit) { + return results.slice(opts.offset, opts.limit + opts.offset); + } + else { + return results.slice(opts.offset); + } + } + _between(leftKeys, rightKeys, opts) { + let results = []; + const leftKey = leftKeys.shift(); + const rightKey = rightKeys.shift(); + let pos; + if (leftKey !== undefined) { + pos = binarySearch(this.keys, leftKey); + } + else { + pos = { + found: false, + index: 0 + }; + } + if (leftKeys.length === 0) { + if (pos.found && opts.leftInclusive === false) { + pos.index += 1; + } + for (let i = pos.index; i < this.keys.length; i += 1) { + if (rightKey !== undefined) { + if (opts.rightInclusive) { + if (this.keys[i] > rightKey) { + break; + } + } + else { + if (this.keys[i] >= rightKey) { + break; + } + } + } + if (this.values[i].isIndex) { + results = results.concat(this.values[i].getAll()); + } + else { + results = results.concat(this.values[i]); + } + if (opts.limit) { + if (results.length >= opts.limit + opts.offset) { + break; + } + } + } + } + else { + for (let i = pos.index; i < this.keys.length; i += 1) { + const currKey = this.keys[i]; + if (currKey > rightKey) { + break; + } + if (this.values[i].isIndex) { + if (currKey === leftKey) { + results = results.concat(this.values[i]._between(utils.copy(leftKeys), rightKeys.map(() => undefined), opts)); + } + else if (currKey === rightKey) { + results = results.concat(this.values[i]._between(leftKeys.map(() => undefined), utils.copy(rightKeys), opts)); + } + else { + results = results.concat(this.values[i].getAll()); + } + } + else { + results = results.concat(this.values[i]); + } + if (opts.limit) { + if (results.length >= opts.limit + opts.offset) { + break; + } + } + } + } + if (opts.limit) { + return results.slice(0, opts.limit + opts.offset); + } + else { + return results; + } + } + peek() { + return this.values.length ? (this.values[0].isIndex ? this.values[0].peek() : this.values[0]) : []; + } + clear() { + this.keys = []; + this.values = []; + } + insertRecord(data) { + const keyList = this.fieldList.map(field => utils.isFunction(field) ? field(data) || undefined : data[field] || undefined); + this.set(keyList, data); + } + removeRecord(data) { + let removed; + const isUnique = this.hashCode(data) !== undefined; + this.values.forEach((value, i) => { + if (value.isIndex) { + if (value.removeRecord(data)) { + if (value.keys.length === 0) { + removeAt(this.keys, i); + removeAt(this.values, i); + } + removed = true; + return false; + } + } + else { + let dataLocation = {}; + if (this.keys[i] === undefined || !isUnique) { + for (let j = value.length - 1; j >= 0; j--) { + if (value[j] === data) { + dataLocation = { + found: true, + index: j + }; + break; + } + } + } + else if (isUnique) { + dataLocation = binarySearch(value, data, this.hashCode); + } + if (dataLocation.found) { + removeAt(value, dataLocation.index); + if (value.length === 0) { + removeAt(this.keys, i); + removeAt(this.values, i); + } + removed = true; + return false; + } + } + }); + return removed ? data : undefined; + } + updateRecord(data) { + const removed = this.removeRecord(data); + if (removed !== undefined) { + this.insertRecord(data); + } + } +} -/** - * The base class from which all JSData components inherit some basic - * functionality. - * - * Typically you won't instantiate this class directly, but you may find it - * useful as an abstract class for your own components. - * - * See {@link Component.extend} for an example of using {@link Component} as a - * base class. - * - *```javascript - * import {Component} from 'js-data' - * ``` - * - * @class Component - * @param {object} [opts] Configuration options. - * @param {boolean} [opts.debug=false] See {@link Component#debug}. - * @returns {Component} A new {@link Component} instance. - * @since 3.0.0 +const { noValidatePath: noValidatePath$1 } = Record; +const DOMAIN$4 = 'Collection'; +const COLLECTION_DEFAULTS = { + commitOnMerge: true, + emitRecordEvents: true, + idAttribute: 'id', + onConflict: 'merge' +}; +/** + * An ordered set of {@link Record} instances. + * + * @example Collection#constructor + * // import { Collection, Record } from 'js-data'; + * const JSData = require('js-data'); + * const {Collection, Record} = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const user1 = new Record({ id: 1 }); + * const user2 = new Record({ id: 2 }); + * const UserCollection = new Collection([user1, user2]); + * console.log(UserCollection.get(1) === user1); + * + * @class Collection + * @extends Component + * @param {array} [records] Initial set of records to insert into the + * collection. + * @param {object} [opts] Configuration options. + * @param {string} [opts.commitOnMerge] See {@link Collection#commitOnMerge}. + * @param {string} [opts.idAttribute] See {@link Collection#idAttribute}. + * @param {string} [opts.onConflict="merge"] See {@link Collection#onConflict}. + * @param {string} [opts.mapper] See {@link Collection#mapper}. + * @since 3.0.0 + */ +class Collection extends Component { + constructor(records = {}, opts = {}) { + super(opts); + /** + * Object that holds the secondary indexes of this collection. + * + * @name Collection#indexes + * @type {Object.} + */ + this.indexes = {}; + this._added = {}; + if (records && !utils.isArray(records)) { + opts = records; + records = []; + } + if (utils.isString(opts)) { + opts = { idAttribute: opts }; + } + // Apply user-provided configuration + utils.fillIn(this, opts); + // Fill in any missing options with the defaults + utils.fillIn(this, utils.copy(COLLECTION_DEFAULTS)); + if (!this.queryClass) { + this.queryClass = Query; + } + const idAttribute = this.recordId(); + this.index = new Index([idAttribute], { + hashCode(obj) { + return utils.get(obj, idAttribute); + } + }); + // Insert initial data into the collection + if (utils.isObject(records) || (utils.isArray(records) && records.length)) { + this.add(records); + } + } + /** + * Used to bind to events emitted by records in this Collection. + * + * @method Collection#_onRecordEvent + * @since 3.0.0 + * @private + * @param {...*} [args] Args passed to {@link Collection#emit}. + */ + _onRecordEvent(...args) { + if (this.emitRecordEvents) { + this.emit(...args); + } + } + /** + * Insert the provided record or records. + * + * If a record is already in the collection then the provided record will + * either merge with or replace the existing record based on the value of the + * `onConflict` option. + * + * The collection's secondary indexes will be updated as each record is + * visited. + * + * @method Collection#add + * @since 3.0.0 + * @param {(Object|Object[]|Record|Record[])} records The record or records to insert. + * @param {object} [opts] Configuration options. + * @param {boolean} [opts.commitOnMerge=true] See {@link Collection#commitOnMerge}. + * @param {boolean} [opts.noValidate] See {@link Record#noValidate}. + * @param {string} [opts.onConflict] See {@link Collection#onConflict}. + * @returns {(Object|Object[]|Record|Record[])} The added record or records. + */ + add(records, opts = {}) { + // Fill in "opts" with the Collection's configuration + utils._(opts, this); + records = this.beforeAdd(records, opts) || records; + // Track whether just one record or an array of records is being inserted + let singular = false; + const idAttribute = this.recordId(); + if (!utils.isArray(records)) { + if (utils.isObject(records)) { + records = [records]; + singular = true; + } + else { + throw utils.err(`${DOMAIN$4}#add`, 'records')(400, 'object or array', records); + } + } + // Map the provided records to existing records. + // New records will be inserted. If any records map to existing records, + // they will be merged into the existing records according to the onConflict + // option. + records = records.map(record => { + const id = this.recordId(record); + // Grab existing record if there is one + const existing = id === undefined ? id : this.get(id); + // If the currently visited record is just a reference to an existing + // record, then there is nothing to be done. Exit early. + if (record === existing) { + return existing; + } + if (existing) { + // Here, the currently visited record corresponds to a record already + // in the collection, so we need to merge them + const onConflict = opts.onConflict || this.onConflict; + if (onConflict !== 'merge' && + onConflict !== 'replace' && + onConflict !== 'skip') { + throw utils.err(`${DOMAIN$4}#add`, 'opts.onConflict')(400, 'one of (merge, replace, skip)', onConflict, true); + } + const existingNoValidate = existing._get(noValidatePath$1); + if (opts.noValidate) { + // Disable validation + existing._set(noValidatePath$1, true); + } + if (onConflict === 'merge') { + utils.deepMixIn(existing, record); + } + else if (onConflict === 'replace') { + utils.forOwn(existing, (value, key) => { + if (key !== idAttribute && record[key] === undefined) { + existing[key] = undefined; + } + }); + existing.set(record); + } // else if(onConflict === 'skip'){ do nothing } + if (opts.noValidate) { + // Restore previous `noValidate` value + existing._set(noValidatePath$1, existingNoValidate); + } + record = existing; + if (opts.commitOnMerge && utils.isFunction(record.commit)) { + record.commit(); + } + // Update all indexes in the collection + this.updateIndexes(record); + } + else { + // Here, the currently visited record does not correspond to any record + // in the collection, so (optionally) instantiate this record and insert + // it into the collection + record = this.mapper ? this.mapper.createRecord(record, opts) : record; + this.index.insertRecord(record); + utils.forOwn(this.indexes, (index, name) => { + index.insertRecord(record); + }); + if (record && utils.isFunction(record.on)) { + record.on('all', this._onRecordEvent, this); + } + } + return record; + }); + // Finally, return the inserted data + const result = singular ? records[0] : records; + if (!opts.silent) { + this.emit('add', result); + } + return this.afterAdd(records, opts, result) || result; + } + /** + * Lifecycle hook called by {@link Collection#add}. If this method returns a + * value then {@link Collection#add} will return that same value. + * + * @method Collection#method + * @since 3.0.0 + * @param {(Object|Object[]|Record|Record[])} record The record or records + * that were added to this Collection by {@link Collection#add}. + * @param {object} opts The `opts` argument passed to {@link Collection#add}. + * @param result + */ + afterAdd(record, opts, result) { + return null; + } + /** + * Lifecycle hook called by {@link Collection#remove}. If this method returns + * a value then {@link Collection#remove} will return that same value. + * + * @method Collection#afterRemove + * @since 3.0.0 + * @param {(string|number)} id The `id` argument passed to {@link Collection#remove}. + * @param {object} opts The `opts` argument passed to {@link Collection#remove}. + * @param {object} record The result that will be returned by {@link Collection#remove}. + */ + afterRemove(id, opts, record) { + return null; + } + /** + * Lifecycle hook called by {@link Collection#removeAll}. If this method + * returns a value then {@link Collection#removeAll} will return that same + * value. + * + * @method Collection#afterRemoveAll + * @since 3.0.0 + * @param {object} query The `query` argument passed to {@link Collection#removeAll}. + * @param {object} opts The `opts` argument passed to {@link Collection#removeAll}. + * @param {object} records The result that will be returned by {@link Collection#removeAll}. + */ + afterRemoveAll(query, opts, records) { + return null; + } + /** + * Lifecycle hook called by {@link Collection#add}. If this method returns a + * value then the `records` argument in {@link Collection#add} will be + * re-assigned to the returned value. + * + * @method Collection#beforeAdd + * @since 3.0.0 + * @param {(Object|Object[]|Record|Record[])} records The `records` argument passed to {@link Collection#add}. + * @param {object} opts The `opts` argument passed to {@link Collection#add}. + */ + beforeAdd(records, opts) { + return null; + } + /** + * Lifecycle hook called by {@link Collection#remove}. + * + * @method Collection#beforeRemove + * @since 3.0.0 + * @param {(string|number)} id The `id` argument passed to {@link Collection#remove}. + * @param {object} opts The `opts` argument passed to {@link Collection#remove}. + */ + beforeRemove(id, opts) { + return null; + } + /** + * Lifecycle hook called by {@link Collection#removeAll}. + * + * @method Collection#beforeRemoveAll + * @since 3.0.0 + * @param {object} query The `query` argument passed to {@link Collection#removeAll}. + * @param {object} opts The `opts` argument passed to {@link Collection#removeAll}. + */ + beforeRemoveAll(query, opts) { + return null; + } + /** + * Find all records between two boundaries. + * + * Shortcut for `collection.query().between(18, 30, { index: 'age' }).run()` + * + * @example + * // Get all users ages 18 to 30 + * const users = collection.between(18, 30, { index: 'age' }); + * + * @example + * // Same as above + * const users = collection.between([18], [30], { index: 'age' }); + * + * @method Collection#between + * @since 3.0.0 + * @param {array} leftKeys Keys defining the left boundary. + * @param {array} rightKeys Keys defining the right boundary. + * @param {object} [opts] Configuration options. + * @param {string} [opts.index] Name of the secondary index to use in the + * query. If no index is specified, the main index is used. + * @param {boolean} [opts.leftInclusive=true] Whether to include records + * on the left boundary. + * @param {boolean} [opts.rightInclusive=false] Whether to include records + * on the left boundary. + * @param {boolean} [opts.limit] Limit the result to a certain number. + * @param {boolean} [opts.offset] The number of resulting records to skip. + * @returns {Object[]|Record[]} The result. + */ + between(leftKeys, rightKeys, opts) { + return this.query() + .between(leftKeys, rightKeys, opts) + .run(); + } + /** + * Create a new secondary index on the contents of the collection. + * + * @example + * // Index users by age + * collection.createIndex('age'); + * + * @example + * // Index users by status and role + * collection.createIndex('statusAndRole', ['status', 'role']); + * + * @method Collection#createIndex + * @since 3.0.0 + * @param {string} name The name of the new secondary index. + * @param {string[]} [fieldList] Array of field names to use as the key or + * compound key of the new secondary index. If no fieldList is provided, then + * the name will also be the field that is used to index the collection. + * @param opts + */ + createIndex(name, fieldList, opts = {}) { + if (utils.isString(name) && fieldList === undefined) { + fieldList = [name]; + } + opts.hashCode = opts.hashCode || (obj => this.recordId(obj)); + const index = (this.indexes[name] = new Index(fieldList, opts)); + this.index.visitAll(index.insertRecord, index); + } + /** + * Find the record or records that match the provided query or pass the + * provided filter function. + * + * Shortcut for `collection.query().filter(queryOrFn[, thisArg]).run()` + * + * @example Collection#filter + * const JSData = require('js-data'); + * const { Collection } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const collection = new Collection([ + * { id: 1, status: 'draft', created_at_timestamp: new Date().getTime() } + * ]); + * + * // Get the draft posts created less than three months ago + * let posts = collection.filter({ + * where: { + * status: { + * '==': 'draft' + * }, + * created_at_timestamp: { + * '>=': (new Date().getTime() - (1000 \* 60 \* 60 \* 24 \* 30 \* 3)) // 3 months ago + * } + * } + * }); + * console.log(posts); + * + * // Use a custom filter function + * posts = collection.filter((post) => post.id % 2 === 0); + * + * @method Collection#filter + * @param {(Object|Function)} [queryOrFn={}] Selection query or filter + * function. + * @param {object} [thisArg] Context to which to bind `queryOrFn` if + * `queryOrFn` is a function. + * @returns {Array} The result. + * @see query + * @since 3.0.0 + */ + filter(queryOrFn, thisArg) { + return this.query() + .filter(queryOrFn, thisArg) + .run(); + } + /** + * Iterate over all records. + * + * @example + * collection.forEach(function (record) { + * // do something + * }); + * + * @method Collection#forEach + * @since 3.0.0 + * @param {Function} forEachFn Iteration function. + * @param {*} [thisArg] Context to which to bind `forEachFn`. + * @returns {Array} The result. + */ + forEach(forEachFn, thisArg) { + this.index.visitAll(forEachFn, thisArg); + } + /** + * Get the record with the given id. + * + * @method Collection#get + * @since 3.0.0 + * @param {(string|number)} id The primary key of the record to get. + * @returns {(Object|Record)} The record with the given id. + */ + get(id) { + const instances = id === undefined + ? [] + : this.query() + .get(id) + .run(); + return instances.length ? instances[0] : undefined; + } + getAll(...args) { + return this.query() + .getAll(...args) + .run(); + } + /** + * Return the index with the given name. If no name is provided, return the + * main index. Throws an error if the specified index does not exist. + * + * @method Collection#getIndex + * @since 3.0.0 + * @param {string} [name] The name of the index to retrieve. + */ + getIndex(name) { + const index = name ? this.indexes[name] : this.index; + if (!index) { + throw utils.err(`${DOMAIN$4}#getIndex`, name)(404, 'index'); + } + return index; + } + /** + * Limit the result. + * + * Shortcut for `collection.query().limit(maximumNumber).run()` + * + * @example + * const posts = collection.limit(10); + * + * @method Collection#limit + * @since 3.0.0 + * @param {number} num The maximum number of records to keep in the result. + * @returns {Array} The result. + */ + limit(num) { + return this.query() + .limit(num) + .run(); + } + /** + * Apply a mapping function to all records. + * + * @example + * const names = collection.map((user) => user.name); + * + * @method Collection#map + * @since 3.0.0 + * @param {Function} mapFn Mapping function. + * @param {*} [thisArg] Context to which to bind `mapFn`. + * @returns {Array} The result of the mapping. + */ + map(cb, thisArg) { + const data = []; + this.index.visitAll(value => { + data.push(cb.call(thisArg, value)); + }); + return data; + } + /** + * Return the result of calling the specified function on each record in this + * collection's main index. + * + * @method Collection#mapCall + * @since 3.0.0 + * @param {string} funcName Name of function to call + * @param {...*} [args] Remaining arguments to be passed to the function. + * @returns {Array} The result. + */ + mapCall(funcName, ...args) { + const data = []; + this.index.visitAll(record => { + data.push(record[funcName](...args)); + }); + return data; + } + /** + * Return all "unsaved" (not uniquely identifiable) records in this colleciton. + * + * @method Collection#prune + * @param {object} [opts] Configuration options, passed to {@link Collection#removeAll}. + * @since 3.0.0 + * @returns {Array} The removed records, if any. + */ + prune(opts) { + return this.removeAll(this.unsaved(), opts); + } + /** + * Create a new query to be executed against the contents of the collection. + * The result will be all or a subset of the contents of the collection. + * + * @example + * // Grab page 2 of users between ages 18 and 30 + * collection.query() + * .between(18, 30, { index: 'age' }) // between ages 18 and 30 + * .skip(10) // second page + * .limit(10) // page size + * .run(); + * + * @method Collection#query + * @since 3.0.0 + * @returns {Query} New query object. + */ + query() { + const Ctor = this.queryClass; + return new Ctor(this); + } + /** + * Return the primary key of the given, or if no record is provided, return the + * name of the field that holds the primary key of records in this Collection. + * + * @method Collection#recordId + * @since 3.0.0 + * @param {(Object|Record)} [record] The record whose primary key is to be + * returned. + * @returns {(string|number)} Primary key or name of field that holds primary + * key. + */ + recordId(record) { + if (record) { + return utils.get(record, this.recordId()); + } + return this.mapper ? this.mapper.idAttribute : this.idAttribute; + } + /** + * Reduce the data in the collection to a single value and return the result. + * + * @example + * const totalVotes = collection.reduce((prev, record) => { + * return prev + record.upVotes + record.downVotes; + * }, 0); + * + * @method Collection#reduce + * @since 3.0.0 + * @param {Function} cb Reduction callback. + * @param {*} initialValue Initial value of the reduction. + * @returns {*} The result. + */ + reduce(cb, initialValue) { + const data = this.getAll(); + return data.reduce(cb, initialValue); + } + /** + * Remove the record with the given id from this Collection. + * + * @method Collection#remove + * @since 3.0.0 + * @param {(string|number|object|Record)} idOrRecord The primary key of the + * record to be removed, or a reference to the record that is to be removed. + * @param {object} [opts] Configuration options. + * @returns {Object|Record} The removed record, if any. + */ + remove(idOrRecord, opts = {}) { + this.beforeRemove(idOrRecord, opts); + let record = utils.isSorN(idOrRecord) ? this.get(idOrRecord) : idOrRecord; + // The record is in the collection, remove it + if (utils.isObject(record)) { + record = this.index.removeRecord(record); + if (record) { + utils.forOwn(this.indexes, (index, name) => { + index.removeRecord(record); + }); + if (utils.isFunction(record.off)) { + record.off('all', this._onRecordEvent, this); + } + if (!opts.silent) { + this.emit('remove', record); + } + } + } + return this.afterRemove(idOrRecord, opts, record) || record; + } + /** + * Remove from this collection the given records or the records selected by + * the given "query". + * + * @method Collection#removeAll + * @since 3.0.0 + * @param {Object|Object[]|Record[]} [queryOrRecords={}] Records to be removed or selection query. See {@link query}. + * @param {object} [queryOrRecords.where] See {@link query.where}. + * @param {number} [queryOrRecords.offset] See {@link query.offset}. + * @param {number} [queryOrRecords.limit] See {@link query.limit}. + * @param {string|Array[]} [queryOrRecords.orderBy] See {@link query.orderBy}. + * @param {object} [opts] Configuration options. + * @returns {(Object[]|Record[])} The removed records, if any. + */ + removeAll(queryOrRecords, opts = {}) { + this.beforeRemoveAll(queryOrRecords, opts); + let records = utils.isArray(queryOrRecords) + ? queryOrRecords.slice() + : this.filter(queryOrRecords); + // Remove each selected record from the collection + const optsCopy = utils.plainCopy(opts); + optsCopy.silent = true; + records = records + .map(record => this.remove(record, optsCopy)) + .filter(record => record); + if (!opts.silent) { + this.emit('remove', records); + } + return this.afterRemoveAll(queryOrRecords, opts, records) || records; + } + /** + * Skip a number of results. + * + * Shortcut for `collection.query().skip(numberToSkip).run()` + * + * @example + * const posts = collection.skip(10); + * + * @method Collection#skip + * @since 3.0.0 + * @param {number} num The number of records to skip. + * @returns {Array} The result. + */ + skip(num) { + return this.query() + .skip(num) + .run(); + } + /** + * Return the plain JSON representation of all items in this collection. + * Assumes records in this collection have a toJSON method. + * + * @method Collection#toJSON + * @since 3.0.0 + * @param {object} [opts] Configuration options. + * @param {string[]} [opts.with] Array of relation names or relation fields + * to include in the representation. + * @returns {Array} The records. + */ + toJSON(opts) { + return this.mapCall('toJSON', opts); + } + /** + * Return all "unsaved" (not uniquely identifiable) records in this colleciton. + * + * @method Collection#unsaved + * @since 3.0.0 + * @returns {Array} The unsaved records, if any. + */ + unsaved(opts) { + return this.index.get(); + } + /** + * Update a record's position in a single index of this collection. See + * {@link Collection#updateIndexes} to update a record's position in all + * indexes at once. + * + * @method Collection#updateIndex + * @since 3.0.0 + * @param {object} record The record to update. + * @param {object} [opts] Configuration options. + * @param {string} [opts.index] The index in which to update the record's + * position. If you don't specify an index then the record will be updated + * in the main index. + */ + updateIndex(record, opts = {}) { + this.getIndex(opts.index).updateRecord(record); + } + /** + * Updates all indexes in this collection for the provided record. Has no + * effect if the record is not in the collection. + * + * @method Collection#updateIndexes + * @since 3.0.0 + * @param {object} record TODO + */ + updateIndexes(record) { + this.index.updateRecord(record); + utils.forOwn(this.indexes, index => index.updateRecord(record)); + } +} +/** + * Fired when a record changes. Only works for records that have tracked changes. + * See {@link Collection~changeListener} on how to listen for this event. + * + * @event Collection#change + * @see Collection~changeListener + */ +/** + * Callback signature for the {@link Collection#event:change} event. + * + * @example + * function onChange (record, changes) { + * // do something + * } + * collection.on('change', onChange); + * + * @callback Collection~changeListener + * @param {Record} The Record that changed. + * @param {object} The changes. + * @see Collection#event:change + * @since 3.0.0 + */ +/** + * Fired when one or more records are added to the Collection. See + * {@link Collection~addListener} on how to listen for this event. + * + * @event Collection#add + * @see Collection~addListener + * @see Collection#event:add + * @see Collection#add + */ +/** + * Callback signature for the {@link Collection#event:add} event. + * + * @example + * function onAdd (recordOrRecords) { + * // do something + * } + * collection.on('add', onAdd); + * + * @callback Collection~addListener + * @param {Record|Record[]} The Record or Records that were added. + * @see Collection#event:add + * @see Collection#add + * @since 3.0.0 + */ +/** + * Fired when one or more records are removed from the Collection. See + * {@link Collection~removeListener} for how to listen for this event. + * + * @event Collection#remove + * @see Collection~removeListener + * @see Collection#event:remove + * @see Collection#remove + * @see Collection#removeAll + */ +/** + * Callback signature for the {@link Collection#event:remove} event. + * + * @example + * function onRemove (recordsOrRecords) { + * // do something + * } + * collection.on('remove', onRemove); + * + * @callback Collection~removeListener + * @param {Record|Record[]} Record or Records that were removed. + * @see Collection#event:remove + * @see Collection#remove + * @see Collection#removeAll + * @since 3.0.0 + */ +/** + * Create a subclass of this Collection: + * @example Collection.extend + * const JSData = require('js-data'); + * const { Collection } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * // Extend the class using ES2015 class syntax. + * class CustomCollectionClass extends Collection { + * foo () { return 'bar'; } + * static beep () { return 'boop'; } + * } + * const customCollection = new CustomCollectionClass(); + * console.log(customCollection.foo()); + * console.log(CustomCollectionClass.beep()); + * + * // Extend the class using alternate method. + * const OtherCollectionClass = Collection.extend({ + * foo () { return 'bar'; } + * }, { + * beep () { return 'boop'; } + * }); + * const otherCollection = new OtherCollectionClass(); + * console.log(otherCollection.foo()); + * console.log(OtherCollectionClass.beep()); + * + * // Extend the class, providing a custom constructor. + * function AnotherCollectionClass () { + * Collection.call(this); + * this.created_at = new Date().getTime(); + * } + * Collection.extend({ + * constructor: AnotherCollectionClass, + * foo () { return 'bar'; } + * }, { + * beep () { return 'boop'; } + * }); + * const anotherCollection = new AnotherCollectionClass(); + * console.log(anotherCollection.created_at); + * console.log(anotherCollection.foo()); + * console.log(AnotherCollectionClass.beep()); + * + * @method Collection.extend + * @param {object} [props={}] Properties to add to the prototype of the + * subclass. + * @param {object} [props.constructor] Provide a custom constructor function + * to be used as the subclass itself. + * @param {object} [classProps={}] Static properties to add to the subclass. + * @returns {Constructor} Subclass of this Collection class. + * @since 3.0.0 */ -function Component(opts) { - Settable.call(this); - opts || (opts = {}); - /** - * Whether to enable debug-level logs for this component. Anything that - * extends `Component` inherits this option and the corresponding logging - * functionality. - * - * @example Component#debug - * const JSData = require('js-data'); - * const { Component } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const component = new Component(); - * component.log('debug', 'some message'); // nothing gets logged - * // Display debug logs: - * component.debug = true; - * component.log('debug', 'other message'); // this DOES get logged - * - * @default false - * @name Component#debug - * @since 3.0.0 - * @type {boolean} - */ - - this.debug = Object.hasOwnProperty.call(opts, 'debug') ? !!opts.debug : false; - /** - * Event listeners attached to this Component. __Do not modify.__ Use - * {@link Component#on} and {@link Component#off} instead. - * - * @name Component#_listeners - * @private - * @instance - * @since 3.0.0 - * @type {Object} - */ - - Object.defineProperty(this, '_listeners', { - value: {}, - writable: true - }); +class TsDataError extends Error { } -var Component$1 = Settable.extend({ - constructor: Component +const DOMAIN$5 = 'Schema'; +/** + * A function map for each of the seven primitive JSON types defined by the core specification. + * Each function will check a given value and return true or false if the value is an instance of that type. + * ``` + * types.integer(1) // returns true + * types.string({}) // returns false + * ``` + * http://json-schema.org/latest/json-schema-core.html#anchor8 + * @name Schema.types + * @type {object} + */ +const types = { + array: utils.isArray, + boolean: utils.isBoolean, + integer: utils.isInteger, + null: utils.isNull, + number: utils.isNumber, + object: utils.isObject, + string: utils.isString +}; +/** + * @ignore + */ +function segmentToString(segment, prev) { + let str = ''; + if (segment) { + if (utils.isNumber(segment)) { + str += `[${segment}]`; + } + else if (prev) { + str += `.${segment}`; + } + else { + str += `${segment}`; + } + } + return str; +} +/** + * @ignore + */ +function makePath(opts = {}) { + let path = ''; + const segments = opts.path || []; + segments.forEach(segment => { + path += segmentToString(segment, path); + }); + path += segmentToString(opts.prop, path); + return path; +} +/** + * @ignore + */ +function makeError(actual, expected, opts) { + return { + expected, + actual: '' + actual, + path: makePath(opts) + }; +} +/** + * @ignore + */ +function addError(actual, expected, opts, errors) { + errors.push(makeError(actual, expected, opts)); +} +/** + * @ignore + */ +function maxLengthCommon(keyword, value, schema, opts) { + const max = schema[keyword]; + if (value.length > max) { + return makeError(value.length, `length no more than ${max}`, opts); + } +} +/** + * @ignore + */ +function minLengthCommon(keyword, value, schema, opts) { + const min = schema[keyword]; + if (value.length < min) { + return makeError(value.length, `length no less than ${min}`, opts); + } +} +/** + * A map of all object member validation functions for each keyword defined in the JSON Schema. + * @name Schema.validationKeywords + * @type {object} + */ +const validationKeywords = { + /** + * Validates the provided value against all schemas defined in the Schemas `allOf` keyword. + * The instance is valid against if and only if it is valid against all the schemas declared in the Schema's value. + * + * The value of this keyword MUST be an array. This array MUST have at least one element. + * Each element of this array MUST be a valid JSON Schema. + * + * see http://json-schema.org/latest/json-schema-validation.html#anchor82 + * + * @name Schema.validationKeywords.allOf + * @method + * @param {*} value Value to be validated. + * @param {object} schema Schema containing the `allOf` keyword. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. + */ + allOf(value, schema, opts) { + let allErrors = []; + schema.allOf.forEach(_schema => { + allErrors = allErrors.concat(validate(value, _schema, opts) || []); + }); + return allErrors.length ? allErrors : undefined; + }, + /** + * Validates the provided value against all schemas defined in the Schemas `anyOf` keyword. + * The instance is valid against this keyword if and only if it is valid against + * at least one of the schemas in this keyword's value. + * + * The value of this keyword MUST be an array. This array MUST have at least one element. + * Each element of this array MUST be an object, and each object MUST be a valid JSON Schema. + * see http://json-schema.org/latest/json-schema-validation.html#anchor85 + * + * @name Schema.validationKeywords.anyOf + * @method + * @param {*} value Value to be validated. + * @param {object} schema Schema containing the `anyOf` keyword. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. + */ + anyOf(value, schema, opts) { + let validated = false; + let allErrors = []; + schema.anyOf.forEach(_schema => { + const errors = validate(value, _schema, opts); + if (errors) { + allErrors = allErrors.concat(errors); + } + else { + validated = true; + } + }); + return validated ? undefined : allErrors; + }, + /** + * http://json-schema.org/latest/json-schema-validation.html#anchor70 + * + * @name Schema.validationKeywords.dependencies + * @method + * @param {*} value TODO + * @param {object} schema TODO + * @param {object} opts TODO + */ + dependencies(value, schema, opts) { + // TODO + }, + /** + * Validates the provided value against an array of possible values defined by the Schema's `enum` keyword + * Validation succeeds if the value is deeply equal to one of the values in the array. + * see http://json-schema.org/latest/json-schema-validation.html#anchor76 + * + * @name Schema.validationKeywords.enum + * @method + * @param {*} value Value to validate + * @param {object} schema Schema containing the `enum` keyword. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. + */ + enum(value, schema, opts) { + const possibleValues = schema.enum; + if (utils.findIndex(possibleValues, item => utils.deepEqual(item, value)) === -1) { + return makeError(value, `one of (${possibleValues.join(', ')})`, opts); + } + }, + /** + * Validates each of the provided array values against a schema or an array of schemas defined by the Schema's + * `items` keyword + * see http://json-schema.org/latest/json-schema-validation.html#anchor37 for validation rules. + * + * @name Schema.validationKeywords.items + * @method + * @param {*} value Array to be validated. + * @param {object} schema Schema containing the items keyword. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. + */ + items(value, schema, opts = {}) { + // TODO: additionalItems + let items = schema.items; + let errors = []; + const checkingTuple = utils.isArray(items); + const length = value.length; + for (let prop = 0; prop < length; prop++) { + if (checkingTuple) { + // Validating a tuple, instead of just checking each item against the + // same schema + items = schema.items[prop]; + } + opts.prop = prop; + errors = errors.concat(validate(value[prop], items, opts) || []); + } + return errors.length ? errors : undefined; + }, + /** + * Validates the provided number against a maximum value defined by the Schema's `maximum` keyword + * Validation succeeds if the value is a number, and is less than, or equal to, the value of this keyword. + * http://json-schema.org/latest/json-schema-validation.html#anchor17 + * + * @name Schema.validationKeywords.maximum + * @method + * @param {*} value Number to validate against the keyword. + * @param {object} schema Schema containing the `maximum` keyword. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. + */ + maximum(value, schema, opts) { + // Must be a number + const maximum = schema.maximum; + // Must be a boolean + // Depends on maximum + // default: false + const exclusiveMaximum = schema.exclusiveMaximum; + if (typeof value === typeof maximum && !(exclusiveMaximum ? maximum > value : maximum >= value)) { + return exclusiveMaximum + ? makeError(value, `no more than nor equal to ${maximum}`, opts) + : makeError(value, `no more than ${maximum}`, opts); + } + }, + /** + * Validates the length of the provided array against a maximum value defined by the Schema's `maxItems` keyword. + * Validation succeeds if the length of the array is less than, or equal to the value of this keyword. + * see http://json-schema.org/latest/json-schema-validation.html#anchor42 + * + * @name Schema.validationKeywords.maxItems + * @method + * @param {*} value Array to be validated. + * @param {object} schema Schema containing the `maxItems` keyword. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. + */ + maxItems(value, schema, opts) { + if (utils.isArray(value)) { + return maxLengthCommon('maxItems', value, schema, opts); + } + }, + /** + * Validates the length of the provided string against a maximum value defined in the Schema's `maxLength` keyword. + * Validation succeeds if the length of the string is less than, or equal to the value of this keyword. + * see http://json-schema.org/latest/json-schema-validation.html#anchor26 + * + * @name Schema.validationKeywords.maxLength + * @method + * @param {*} value String to be validated. + * @param {object} schema Schema containing the `maxLength` keyword. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. + */ + maxLength(value, schema, opts) { + return maxLengthCommon('maxLength', value, schema, opts); + }, + /** + * Validates the count of the provided object's properties against a maximum value defined in the Schema's + * `maxProperties` keyword. + * Validation succeeds if the object's property count is less than, or equal to the value of this keyword. + * see http://json-schema.org/latest/json-schema-validation.html#anchor54 + * + * @name Schema.validationKeywords.maxProperties + * @method + * @param {*} value Object to be validated. + * @param {object} schema Schema containing the `maxProperties` keyword. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. + */ + maxProperties(value, schema, opts) { + // validate only objects + if (!utils.isObject(value)) + return; + const maxProperties = schema.maxProperties; + const length = Object.keys(value).length; + if (length > maxProperties) { + return makeError(length, `no more than ${maxProperties} properties`, opts); + } + }, + /** + * Validates the provided value against a minimum value defined by the Schema's `minimum` keyword + * Validation succeeds if the value is a number and is greater than, or equal to, the value of this keyword. + * http://json-schema.org/latest/json-schema-validation.html#anchor21 + * + * @name Schema.validationKeywords.minimum + * @method + * @param {*} value Number to validate against the keyword. + * @param {object} schema Schema containing the `minimum` keyword. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. + */ + minimum(value, schema, opts) { + // Must be a number + const minimum = schema.minimum; + // Must be a boolean + // Depends on minimum + // default: false + const exclusiveMinimum = schema.exclusiveMinimum; + if (typeof value === typeof minimum && !(exclusiveMinimum ? value > minimum : value >= minimum)) { + return exclusiveMinimum + ? makeError(value, `no less than nor equal to ${minimum}`, opts) + : makeError(value, `no less than ${minimum}`, opts); + } + }, + /** + * Validates the length of the provided array against a minimum value defined by the Schema's `minItems` keyword. + * Validation succeeds if the length of the array is greater than, or equal to the value of this keyword. + * see http://json-schema.org/latest/json-schema-validation.html#anchor45 + * + * @name Schema.validationKeywords.minItems + * @method + * @param {*} value Array to be validated. + * @param {object} schema Schema containing the `minItems` keyword. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. + */ + minItems(value, schema, opts) { + if (utils.isArray(value)) { + return minLengthCommon('minItems', value, schema, opts); + } + }, + /** + * Validates the length of the provided string against a minimum value defined in the Schema's `minLength` keyword. + * Validation succeeds if the length of the string is greater than, or equal to the value of this keyword. + * see http://json-schema.org/latest/json-schema-validation.html#anchor29 + * + * @name Schema.validationKeywords.minLength + * @method + * @param {*} value String to be validated. + * @param {object} schema Schema containing the `minLength` keyword. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. + */ + minLength(value, schema, opts) { + return minLengthCommon('minLength', value, schema, opts); + }, + /** + * Validates the count of the provided object's properties against a minimum value defined in the Schema's + * `minProperties` keyword. + * Validation succeeds if the object's property count is greater than, or equal to the value of this keyword. + * see http://json-schema.org/latest/json-schema-validation.html#anchor57 + * + * @name Schema.validationKeywords.minProperties + * @method + * @param {*} value Object to be validated. + * @param {object} schema Schema containing the `minProperties` keyword. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. + */ + minProperties(value, schema, opts) { + // validate only objects + if (!utils.isObject(value)) + return; + const minProperties = schema.minProperties; + const length = Object.keys(value).length; + if (length < minProperties) { + return makeError(length, `no more than ${minProperties} properties`, opts); + } + }, + /** + * Validates the provided number is a multiple of the number defined in the Schema's `multipleOf` keyword. + * Validation succeeds if the number can be divided equally into the value of this keyword. + * see http://json-schema.org/latest/json-schema-validation.html#anchor14 + * + * @name Schema.validationKeywords.multipleOf + * @method + * @param {*} value Number to be validated. + * @param {object} schema Schema containing the `multipleOf` keyword. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. + */ + multipleOf(value, schema, opts) { + const multipleOf = schema.multipleOf; + if (utils.isNumber(value)) { + if ((value / multipleOf) % 1 !== 0) { + return makeError(value, `multipleOf ${multipleOf}`, opts); + } + } + }, + /** + * Validates the provided value is not valid with any of the schemas defined in the Schema's `not` keyword. + * An instance is valid against this keyword if and only if it is NOT valid against the schemas in this keyword's + * value. + * + * see http://json-schema.org/latest/json-schema-validation.html#anchor91 + * @name Schema.validationKeywords.not + * @method + * @param {*} value to be checked. + * @param {object} schema Schema containing the not keyword. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. + */ + not(value, schema, opts) { + if (!validate(value, schema.not, opts)) { + // TODO: better messaging + return makeError('succeeded', 'should have failed', opts); + } + }, + /** + * Validates the provided value is valid with one and only one of the schemas defined in the Schema's `oneOf` keyword. + * An instance is valid against this keyword if and only if it is valid against a single schemas in this keyword's + * value. + * + * see http://json-schema.org/latest/json-schema-validation.html#anchor88 + * @name Schema.validationKeywords.oneOf + * @method + * @param {*} value to be checked. + * @param {object} schema Schema containing the `oneOf` keyword. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. + */ + oneOf(value, schema, opts) { + let validated = false; + let allErrors = []; + schema.oneOf.forEach(_schema => { + const errors = validate(value, _schema, opts); + if (errors) { + allErrors = allErrors.concat(errors); + } + else if (validated) { + allErrors = [makeError('valid against more than one', 'valid against only one', opts)]; + validated = false; + return false; + } + else { + validated = true; + } + }); + return validated ? undefined : allErrors; + }, + /** + * Validates the provided string matches a pattern defined in the Schema's `pattern` keyword. + * Validation succeeds if the string is a match of the regex value of this keyword. + * + * see http://json-schema.org/latest/json-schema-validation.html#anchor33 + * @name Schema.validationKeywords.pattern + * @method + * @param {*} value String to be validated. + * @param {object} schema Schema containing the `pattern` keyword. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. + */ + pattern(value, schema, opts) { + const pattern = schema.pattern; + if (utils.isString(value) && !value.match(pattern)) { + return makeError(value, pattern, opts); + } + }, + /** + * Validates the provided object's properties against a map of values defined in the Schema's `properties` keyword. + * Validation succeeds if the object's property are valid with each of the schema's in the provided map. + * Validation also depends on the additionalProperties and or patternProperties. + * + * see http://json-schema.org/latest/json-schema-validation.html#anchor64 for more info. + * + * @name Schema.validationKeywords.properties + * @method + * @param {*} value Object to be validated. + * @param {object} schema Schema containing the `properties` keyword. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. + */ + properties(value, schema, opts = {}) { + if (utils.isArray(value)) { + return; + } + // Can be a boolean or an object + // Technically the default is an "empty schema", but here "true" is + // functionally the same + const additionalProperties = schema.additionalProperties === undefined ? true : schema.additionalProperties; + const validated = []; + // "p": The property set from "properties". + // Default is an object + const properties = schema.properties || {}; + // "pp": The property set from "patternProperties". + // Default is an object + const patternProperties = schema.patternProperties || {}; + let errors = []; + utils.forOwn(properties, (_schema, prop) => { + opts.prop = prop; + errors = errors.concat(validate(value[prop], _schema, opts) || []); + validated.push(prop); + }); + const toValidate = utils.omit(value, validated); + utils.forOwn(patternProperties, (_schema, pattern) => { + utils.forOwn(toValidate, (undef, prop) => { + if (prop.match(pattern)) { + opts.prop = prop; + errors = errors.concat(validate(value[prop], _schema, opts) || []); + validated.push(prop); + } + }); + }); + const keys = Object.keys(utils.omit(value, validated)); + // If "s" is not empty, validation fails + if (additionalProperties === false) { + if (keys.length) { + const origProp = opts.prop; + opts.prop = ''; + addError(`extra fields: ${keys.join(', ')}`, 'no extra fields', opts, errors); + opts.prop = origProp; + } + } + else if (utils.isObject(additionalProperties)) { + // Otherwise, validate according to provided schema + keys.forEach(prop => { + opts.prop = prop; + errors = errors.concat(validate(value[prop], additionalProperties, opts) || []); + }); + } + return errors.length ? errors : undefined; + }, + /** + * Validates the provided object's has all properties listed in the Schema's `properties` keyword array. + * Validation succeeds if the object contains all properties provided in the array value of this keyword. + * see http://json-schema.org/latest/json-schema-validation.html#anchor61 + * + * @name Schema.validationKeywords.required + * @method + * @param {*} value Object to be validated. + * @param {object} schema Schema containing the `required` keyword. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. + */ + required(value, schema, opts = {}) { + const required = schema.required; + const errors = []; + if (!opts.existingOnly) { + required.forEach(prop => { + if (utils.get(value, prop) === undefined) { + const prevProp = opts.prop; + opts.prop = prop; + addError(undefined, 'a value', opts, errors); + opts.prop = prevProp; + } + }); + } + return errors.length ? errors : undefined; + }, + /** + * Validates the provided value's type is equal to the type, or array of types, defined in the Schema's `type` + * keyword. + * see http://json-schema.org/latest/json-schema-validation.html#anchor79 + * + * @name Schema.validationKeywords.type + * @method + * @param {*} value Value to be validated. + * @param {object} schema Schema containing the `type` keyword. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. + */ + type(value, schema, opts) { + let type = schema.type; + let validType; + // Can be one of several types + if (utils.isString(type)) { + type = [type]; + } + // Try to match the value against an expected type + type.forEach(_type => { + // TODO: throw an error if type is not defined + if (types[_type](value, schema, opts)) { + // Matched a type + validType = _type; + return false; + } + }); + // Value did not match any expected type + if (!validType) { + return makeError(value !== undefined && value !== null ? typeof value : '' + value, `one of (${type.join(', ')})`, opts); + } + // Run keyword validators for matched type + // http://json-schema.org/latest/json-schema-validation.html#anchor12 + const validator = typeGroupValidators[validType]; + if (validator) { + return validator(value, schema, opts); + } + }, + /** + * Validates the provided array values are unique. + * Validation succeeds if the items in the array are unique, but only if the value of this keyword is true + * see http://json-schema.org/latest/json-schema-validation.html#anchor49 + * + * @name Schema.validationKeywords.uniqueItems + * @method + * @param {*} value Array to be validated. + * @param {object} schema Schema containing the `uniqueItems` keyword. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. + */ + uniqueItems(value, schema, opts) { + var _a; + if (((_a = value) === null || _a === void 0 ? void 0 : _a.length) && schema.uniqueItems) { + const length = value.length; + let item, i, j; + // Check n - 1 items + for (i = length - 1; i > 0; i--) { + item = value[i]; + // Only compare against unchecked items + for (j = i - 1; j >= 0; j--) { + // Found a duplicate + if (utils.deepEqual(item, value[j])) { + return makeError(item, 'no duplicates', opts); + } + } + } + } + } +}; +/** + * @ignore + */ +function runOps(ops, value, schema, opts) { + let errors = []; + ops.forEach(op => { + if (schema[op] !== undefined) { + errors = errors.concat(validationKeywords[op](value, schema, opts) || []); + } + }); + return errors.length ? errors : undefined; +} +/** + * Validation keywords validated for any type: + * + * - `enum` + * - `type` + * - `allOf` + * - `anyOf` + * - `oneOf` + * - `not` + * + * @name Schema.ANY_OPS + * @type {string[]} + */ +const ANY_OPS = ['enum', 'type', 'allOf', 'anyOf', 'oneOf', 'not']; +/** + * Validation keywords validated for array types: + * + * - `items` + * - `maxItems` + * - `minItems` + * - `uniqueItems` + * + * @name Schema.ARRAY_OPS + * @type {string[]} + */ +const ARRAY_OPS = ['items', 'maxItems', 'minItems', 'uniqueItems']; +/** + * Validation keywords validated for numeric (number and integer) types: + * + * - `multipleOf` + * - `maximum` + * - `minimum` + * + * @name Schema.NUMERIC_OPS + * @type {string[]} + */ +const NUMERIC_OPS = ['multipleOf', 'maximum', 'minimum']; +/** + * Validation keywords validated for object types: + * + * - `maxProperties` + * - `minProperties` + * - `required` + * - `properties` + * - `dependencies` + * + * @name Schema.OBJECT_OPS + * @type {string[]} + */ +const OBJECT_OPS = ['maxProperties', 'minProperties', 'required', 'properties', 'dependencies']; +/** + * Validation keywords validated for string types: + * + * - `maxLength` + * - `minLength` + * - `pattern` + * + * @name Schema.STRING_OPS + * @type {string[]} + */ +const STRING_OPS = ['maxLength', 'minLength', 'pattern']; +/** + * http://json-schema.org/latest/json-schema-validation.html#anchor75 + * @ignore + */ +const validateAny = (value, schema, opts) => runOps(ANY_OPS, value, schema, opts); +/** + * Validates the provided value against a given Schema according to the http://json-schema.org/ v4 specification. + * + * @name Schema.validate + * @method + * @param {*} value Value to be validated. + * @param {object} schema Valid Schema according to the http://json-schema.org/ v4 specification. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. + */ +const validate = (value, schema, opts = {}) => { + let errors = []; + opts.ctx = opts.ctx || { value, schema }; + let shouldPop; + const prevProp = opts.prop; + if (schema === undefined) { + return; + } + if (!utils.isObject(schema)) { + throw utils.err(`${DOMAIN$5}#validate`)(500, `Invalid schema at path: "${opts.path}"`); + } + if (opts.path === undefined) { + opts.path = []; + } + // Track our location as we recurse + if (opts.prop !== undefined) { + shouldPop = true; + opts.path.push(opts.prop); + opts.prop = undefined; + } + // Validate against parent schema + if (schema.extends) { + // opts.path = path + // opts.prop = prop + if (utils.isFunction(schema.extends.validate)) { + errors = errors.concat(schema.extends.validate(value, opts) || []); + } + else { + errors = errors.concat(validate(value, schema.extends, opts) || []); + } + } + if (value === undefined) { + // Check if property is required + if (schema.required === true && !opts.existingOnly) { + addError(value, 'a value', opts, errors); + } + if (shouldPop) { + opts.path.pop(); + opts.prop = prevProp; + } + return errors.length ? errors : undefined; + } + errors = errors.concat(validateAny(value, schema, opts) || []); + if (shouldPop) { + opts.path.pop(); + opts.prop = prevProp; + } + return errors.length ? errors : undefined; +}; +// These strings are cached for optimal performance of the change detection +// boolean - Whether a Record is changing in the current execution frame +const changingPath = 'changing'; +// string[] - Properties that have changed in the current execution frame +const changedPath = 'changed'; +// Object[] - History of change records +const changeHistoryPath = 'history'; +// boolean - Whether a Record is currently being instantiated +const creatingPath$1 = 'creating'; +// number - The setTimeout change event id of a Record, if any +const eventIdPath = 'eventId'; +// boolean - Whether to skip validation for a Record's currently changing property +const noValidatePath$2 = 'noValidate'; +// boolean - Whether to preserve Change History for a Record +const keepChangeHistoryPath$1 = 'keepChangeHistory'; +// boolean - Whether to skip change notification for a Record's currently +// changing property +const silentPath = 'silent'; +const validationFailureMsg = 'validation failed'; +/** + * A map of validation functions grouped by type. + * + * @name Schema.typeGroupValidators + * @type {object} + */ +const typeGroupValidators = { + /** + * Validates the provided value against the schema using all of the validation keywords specific to instances of an + * array. + * The validation keywords for the type `array` are: + * ``` + * ['items', 'maxItems', 'minItems', 'uniqueItems'] + * ``` + * see http://json-schema.org/latest/json-schema-validation.html#anchor25 + * + * @name Schema.typeGroupValidators.array + * @method + * @param {*} value Array to be validated. + * @param {object} schema Schema containing at least one array keyword. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. + */ + array: (value, schema, opts) => runOps(ARRAY_OPS, value, schema, opts), + /** + * Validates the provided value against the schema using all of the validation keywords specific to instances of an + * integer. + * The validation keywords for the type `integer` are: + * ``` + * ['multipleOf', 'maximum', 'minimum'] + * ``` + * @name Schema.typeGroupValidators.integer + * @method + * @param {*} value Number to be validated. + * @param {object} schema Schema containing at least one `integer` keyword. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. + */ + integer: (value, schema, opts) => + // Additional validations for numerics are the same + typeGroupValidators.numeric(value, schema, opts), + /** + * Validates the provided value against the schema using all of the validation keywords specific to instances of an + * number. + * The validation keywords for the type `number` are: + * ``` + * ['multipleOf', 'maximum', 'minimum'] + * ``` + * @name Schema.typeGroupValidators.number + * @method + * @param {*} value Number to be validated. + * @param {object} schema Schema containing at least one `number` keyword. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. + */ + number: (value, schema, opts) => + // Additional validations for numerics are the same + typeGroupValidators.numeric(value, schema, opts), + /** + * Validates the provided value against the schema using all of the validation keywords specific to instances of a + * number or integer. + * The validation keywords for the type `numeric` are: + * ``` + * ['multipleOf', 'maximum', 'minimum'] + * ``` + * See http://json-schema.org/latest/json-schema-validation.html#anchor13. + * + * @name Schema.typeGroupValidators.numeric + * @method + * @param {*} value Number to be validated. + * @param {object} schema Schema containing at least one `numeric` keyword. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. + */ + numeric: (value, schema, opts) => runOps(NUMERIC_OPS, value, schema, opts), + /** + * Validates the provided value against the schema using all of the validation keywords specific to instances of an + * object. + * The validation keywords for the type `object` are: + * ``` + * ['maxProperties', 'minProperties', 'required', 'properties', 'dependencies'] + * ``` + * See http://json-schema.org/latest/json-schema-validation.html#anchor53. + * + * @name Schema.typeGroupValidators.object + * @method + * @param {*} value Object to be validated. + * @param {object} schema Schema containing at least one `object` keyword. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. + */ + object: (value, schema, opts) => runOps(OBJECT_OPS, value, schema, opts), + /** + * Validates the provided value against the schema using all of the validation keywords specific to instances of an + * string. + * The validation keywords for the type `string` are: + * ``` + * ['maxLength', 'minLength', 'pattern'] + * ``` + * See http://json-schema.org/latest/json-schema-validation.html#anchor25. + * + * @name Schema.typeGroupValidators.string + * @method + * @param {*} value String to be validated. + * @param {object} schema Schema containing at least one `string` keyword. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. + */ + string: (value, schema, opts) => runOps(STRING_OPS, value, schema, opts) +}; +/** + * js-data's Schema class. + * + * @example Schema#constructor + * const JSData = require('js-data'); + * const { Schema } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const PostSchema = new Schema({ + * type: 'object', + * properties: { + * title: { type: 'string' } + * } + * }); + * PostSchema.validate({ title: 1234 }); + * + * @example + * const JSData = require('js-data'); + * const { Schema } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * class CustomSchemaClass extends Schema { + * foo () { return 'bar'; } + * static beep () { return 'boop'; } + * } + * const customSchema = new CustomSchemaClass(); + * console.log(customSchema.foo()); + * console.log(CustomSchemaClass.beep()); + * + * @class Schema + * @extends Component + * @param {object} definition Schema definition according to json-schema.org + */ +class Schema extends Component { + constructor(definition = {}) { + super(); + // TODO: schema validation + utils.fillIn(this, definition); + if (this.type === 'object') { + this.properties = this.properties || {}; + utils.forOwn(this.properties, (_definition, prop) => { + if (!(_definition instanceof Schema)) { + this.properties[prop] = new Schema(_definition); + } + }); + } + else if (this.type === 'array' && this.items && !(this.items instanceof Schema)) { + this.items = new Schema(this.items); + } + if (this.extends && !(this.extends instanceof Schema)) { + this.extends = new Schema(this.extends); + } + ['allOf', 'anyOf', 'oneOf'].forEach(validationKeyword => { + if (this[validationKeyword]) { + this[validationKeyword].forEach((_definition, i) => { + if (!(_definition instanceof Schema)) { + this[validationKeyword][i] = new Schema(_definition); + } + }); + } + }); + } + /** + * This adds ES5 getters/setters to the target based on the "properties" in + * this Schema, which makes possible change tracking and validation on + * property assignment. + * + * @name Schema#apply + * @method + * @param {object} target The prototype to which to apply this schema. + * @param opts + */ + apply(target, opts = {}) { + opts.getter = opts.getter || '_get'; + opts.setter = opts.setter || '_set'; + opts.unsetter = opts.unsetter || '_unset'; + opts.track = opts.track || this.track; + const properties = this.properties || {}; + utils.forOwn(properties, (schema, prop) => { + Object.defineProperty(target, prop, this.makeDescriptor(prop, schema, opts)); + }); + } + /** + * Apply default values to the target object for missing values. + * + * @name Schema#applyDefaults + * @method + * @param {object} target The target to which to apply values for missing values. + */ + applyDefaults(target) { + if (!target) { + return; + } + const properties = this.properties || {}; + const hasSet = utils.isFunction(target.set) || utils.isFunction(target._set); + utils.forOwn(properties, (schema, prop) => { + if (schema.hasOwnProperty('default') && utils.get(target, prop) === undefined) { + if (hasSet) { + target.set(prop, utils.plainCopy(schema.default), { silent: true }); + } + else { + utils.set(target, prop, utils.plainCopy(schema.default)); + } + } + if (schema.type === 'object' && schema.properties) { + if (hasSet) { + const orig = target._get('noValidate'); + target._set('noValidate', true); + utils.set(target, prop, utils.get(target, prop) || {}, { silent: true }); + target._set('noValidate', orig); + } + else { + utils.set(target, prop, utils.get(target, prop) || {}); + } + schema.applyDefaults(utils.get(target, prop)); + } + }); + } + /** + * Assemble a property descriptor for tracking and validating changes to + * a property according to the given schema. This method is called when + * {@link Mapper#applySchema} is set to `true`. + * + * @name Schema#makeDescriptor + * @method + * @param {string} prop The property name. + * @param {(Schema|object)} schema The schema for the property. + * @param {object} [opts] Optional configuration. + * @param {function} [opts.getter] Custom getter function. + * @param {function} [opts.setter] Custom setter function. + * @param {function} [opts.track] Whether to track changes. + * @returns {object} A property descriptor for the given schema. + */ + makeDescriptor(prop, schema, opts) { + const descriptor = { + // Better to allow configurability, but at the user's own risk + configurable: true, + // These properties are enumerable by default, but regardless of their + // enumerability, they won't be "own" properties of individual records + enumerable: schema.enumerable === undefined ? true : !!schema.enumerable, + get() { + return this._get(keyPath); + }, + set(value) { + // These are accessed a lot + const _get = this[getter]; + const _set = this[setter]; + const _unset = this[unsetter]; + // Optionally check that the new value passes validation + if (!_get(noValidatePath$2)) { + const errors = schema.validate(value, { path: [prop] }); + if (errors) { + // Immediately throw an error, preventing the record from getting into + // an invalid state + const error = new TsDataError(validationFailureMsg); + error.errors = errors; + throw error; + } + } + // TODO: Make it so tracking can be turned on for all properties instead of + // only per-property + if (track && !_get(creatingPath$1)) { + // previous is versioned on database commit + // props are versioned on set() + const previous = _get(previousPath); + const current = _get(keyPath); + let changing = _get(changingPath); + let changed = _get(changedPath); + if (!changing) { + // Track properties that are changing in the current event loop + changed = []; + } + // Add changing properties to this array once at most + const index = changed.indexOf(prop); + if (current !== value && index === -1) { + changed.push(prop); + } + if (previous === value) { + if (index >= 0) { + changed.splice(index, 1); + } + } + // No changes in current event loop + if (!changed.length) { + changing = false; + _unset(changingPath); + _unset(changedPath); + // Cancel pending change event + if (_get(eventIdPath)) { + clearTimeout(_get(eventIdPath)); + _unset(eventIdPath); + } + } + // Changes detected in current event loop + if (!changing && changed.length) { + _set(changedPath, changed); + _set(changingPath, true); + // Saving the timeout id allows us to batch all changes in the same + // event loop into a single "change" + // TODO: Optimize + _set(eventIdPath, setTimeout(() => { + // Previous event loop where changes were gathered has ended, so + // notify any listeners of those changes and prepare for any new + // changes + _unset(changedPath); + _unset(eventIdPath); + _unset(changingPath); + // TODO: Optimize + if (!_get(silentPath)) { + let i; + for (i = 0; i < changed.length; i++) { + this.emit('change:' + changed[i], this, utils.get(this, changed[i])); + } + const changes = utils.diffObjects({ [prop]: value }, { [prop]: current }); + if (_get(keepChangeHistoryPath$1)) { + const changeRecord = utils.plainCopy(changes); + changeRecord.timestamp = new Date().getTime(); + let changeHistory = _get(changeHistoryPath); + if (!changeHistory) + _set(changeHistoryPath, (changeHistory = [])); + changeHistory.push(changeRecord); + } + this.emit('change', this, changes); + } + _unset(silentPath); + }, 0)); + } + } + _set(keyPath, value); + return value; + } + }; + // Cache a few strings for optimal performance + const keyPath = `props.${prop}`; + const previousPath = `previous.${prop}`; + const getter = opts.getter; + const setter = opts.setter; + const unsetter = opts.unsetter; + const track = utils.isBoolean(opts.track) ? opts.track : schema.track; + if (utils.isFunction(schema.get)) { + const originalGet = descriptor.get; + descriptor.get = function () { + return schema.get.call(this, originalGet); + }; + } + if (utils.isFunction(schema.set)) { + const originalSet = descriptor.set; + descriptor.set = function (value) { + return schema.set.call(this, value, originalSet); + }; + } + return descriptor; + } + /** + * Create a copy of the given value that contains only the properties defined + * in this schema. + * + * @name Schema#pick + * @method + * @param {*} value The value to copy. + * @returns {*} The copy. + */ + pick(value, opts) { + if (value === undefined) { + return; + } + if (this.type === 'object') { + const copy = {}; + const properties = this.properties; + if (properties) { + utils.forOwn(properties, (_definition, prop) => { + copy[prop] = _definition.pick(value[prop]); + }); + } + if (this.extends) { + utils.fillIn(copy, this.extends.pick(value)); + } + // Conditionally copy properties not defined in "properties" + if (this.additionalProperties) { + for (const key in value) { + if (!properties[key]) { + copy[key] = utils.plainCopy(value[key]); + } + } + } + return copy; + } + else if (this.type === 'array') { + return value.map(item => { + const _copy = this.items ? this.items.pick(item) : {}; + if (this.extends) { + utils.fillIn(_copy, this.extends.pick(item)); + } + return _copy; + }); + } + return utils.plainCopy(value); + } + /** + * Validate the provided value against this schema. + * + * @name Schema#validate + * @method + * @param {*} value Value to validate. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. + */ + validate(value, opts) { + return validate(value, this, opts); + } +} +Schema.ANY_OPS = ANY_OPS; +Schema.ARRAY_OPS = ARRAY_OPS; +Schema.NUMERIC_OPS = NUMERIC_OPS; +Schema.OBJECT_OPS = OBJECT_OPS; +Schema.STRING_OPS = STRING_OPS; +Schema.typeGroupValidators = typeGroupValidators; +Schema.types = types; +Schema.validate = validate; +Schema.validationKeywords = validationKeywords; + +class BelongsToRelation extends Relation { + getForeignKey(record) { + return utils.get(record, this.foreignKey); + } + _setForeignKey(record, relatedRecord) { + utils.set(record, this.foreignKey, utils.get(relatedRecord, this.getRelation().idAttribute)); + } + findExistingLinksFor(record) { + // console.log('\tBelongsTo#findExistingLinksFor', record) + if (!record) { + return; + } + const relatedId = utils.get(record, this.foreignKey); + if (relatedId !== undefined && relatedId !== null) { + return this.relatedCollection.get(relatedId); + } + } + isRequiresParentId() { + return true; + } + createParentRecord(props, opts) { + const relationData = this.getLocalField(props); + return this.createLinked(relationData, opts).then(record => { + this.setForeignKey(props, record); + }); + } + createChildRecord() { + throw new Error('"BelongsTo" relation does not support child creation as it cannot have children.'); + } +} +BelongsToRelation.TYPE_NAME = 'belongsTo'; + +class HasManyRelation extends Relation { + validateOptions(related, opts) { + super.validateOptions(related, opts); + const { localKeys, foreignKeys, foreignKey } = opts; + if (!foreignKey && !localKeys && !foreignKeys) { + throw utils.err('new Relation', 'opts.')(400, 'string', foreignKey); + } + } + canFindLinkFor(record) { + const hasForeignKeys = this.foreignKey || this.foreignKeys; + return !!(hasForeignKeys || (this.localKeys && utils.get(record, this.localKeys))); + } + linkRecord(record, relatedRecords) { + const relatedCollection = this.relatedCollection; + const canAutoAddLinks = this.canAutoAddLinks; + const foreignKey = this.foreignKey; + const unsaved = this.relatedCollection.unsaved(); + return relatedRecords.map(relatedRecord => { + const relatedId = relatedCollection.recordId(relatedRecord); + if ((relatedId === undefined && unsaved.indexOf(relatedRecord) === -1) || + relatedRecord !== relatedCollection.get(relatedId)) { + if (foreignKey) { + // TODO: slow, could be optimized? But user loses hook + this.setForeignKey(record, relatedRecord); + } + if (canAutoAddLinks) { + relatedRecord = relatedCollection.add(relatedRecord); + } + } + return relatedRecord; + }); + } + findExistingLinksFor(record) { + var _a; + const id = utils.get(record, this.mapper.idAttribute); + const ids = this.localKeys ? utils.get(record, this.localKeys) : null; + let records; + if (id !== undefined && this.foreignKey) { + records = this.findExistingLinksByForeignKey(id); + } + else if (this.localKeys && ids) { + records = this.findExistingLinksByLocalKeys(ids); + } + else if (id !== undefined && this.foreignKeys) { + records = this.findExistingLinksByForeignKeys(id); + } + if ((_a = records) === null || _a === void 0 ? void 0 : _a.length) { + return records; + } + } + // e.g. user hasMany group via "foreignKeys", so find all users of a group + findExistingLinksByLocalKeys(ids) { + return this.relatedCollection.filter({ + where: { + [this.relatedCollection.mapper.idAttribute]: { + in: ids + } + } + }); + } + // e.g. group hasMany user via "localKeys", so find all groups that own a user + findExistingLinksByForeignKeys(id) { + return this.relatedCollection.filter({ + where: { + [this.foreignKeys]: { + contains: id + } + } + }); + } + isRequiresParentId() { + return !!this.localKeys && this.localKeys.length > 0; + } + isRequiresChildId() { + return !!this.foreignKey; + } + createParentRecord(props, opts) { + const relationData = this.getLocalField(props); + const foreignIdField = this.getRelation().idAttribute; + return this.createLinked(relationData, opts).then(records => { + utils.set(props, this.localKeys, records.map(record => utils.get(record, foreignIdField))); + }); + } + createLinked(props, opts) { + return this.getRelation().createMany(props, opts); + } +} +HasManyRelation.TYPE_NAME = 'hasMany'; + +class HasOneRelation extends Relation { + findExistingLinksFor(relatedMapper, record) { + var _a; + const recordId = utils.get(record, relatedMapper.idAttribute); + const records = this.findExistingLinksByForeignKey(recordId); + if ((_a = records) === null || _a === void 0 ? void 0 : _a.length) { + return records[0]; + } + } + isRequiresChildId() { + return true; + } +} +HasOneRelation.TYPE_NAME = 'hasOne'; + +[BelongsToRelation, HasManyRelation, HasOneRelation].forEach(RelationType => { + Relation[RelationType.TYPE_NAME] = (related, options) => new RelationType(related, options); }); -/** - * Create a subclass of this Component: - * - * @example Component.extend - * const JSData = require('js-data'); - * const { Component } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * // Extend the class using ES2015 class syntax. - * class CustomComponentClass extends Component { - * foo () { return 'bar'; } - * static beep () { return 'boop'; } - * } - * const customComponent = new CustomComponentClass(); - * console.log(customComponent.foo()); - * console.log(CustomComponentClass.beep()); - * - * // Extend the class using alternate method. - * const OtherComponentClass = Component.extend({ - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }); - * const otherComponent = new OtherComponentClass(); - * console.log(otherComponent.foo()); - * console.log(OtherComponentClass.beep()); - * - * // Extend the class, providing a custom constructor. - * function AnotherComponentClass () { - * Component.call(this); - * this.created_at = new Date().getTime(); - * } - * Component.extend({ - * constructor: AnotherComponentClass, - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }) - * const anotherComponent = new AnotherComponentClass(); - * console.log(anotherComponent.created_at); - * console.log(anotherComponent.foo()); - * console.log(AnotherComponentClass.beep()); - * - * @method Component.extend - * @param {object} [props={}] Properties to add to the prototype of the - * subclass. - * @param {object} [props.constructor] Provide a custom constructor function - * to be used as the subclass itself. - * @param {object} [classProps={}] Static properties to add to the subclass. - * @returns {Constructor} Subclass of this Component class. - * @since 3.0.0 - */ - -Component.extend = utils.extend; -/** - * Log the provided values at the "debug" level. Debug-level logs are only - * logged if {@link Component#debug} is `true`. - * - * `.dbg(...)` is shorthand for `.log('debug', ...)`. - * - * @method Component#dbg - * @param {...*} [args] Values to log. - * @since 3.0.0 - */ -/** - * Log the provided values. By default sends values to `console[level]`. - * Debug-level logs are only logged if {@link Component#debug} is `true`. - * - * Will attempt to use appropriate `console` methods if they are available. - * - * @method Component#log - * @param {string} level Log level. - * @param {...*} [args] Values to log. - * @since 3.0.0 - */ +/** + * BelongsTo relation decorator. You probably won't use this directly. + * + * @method + * @param {Mapper} related The relation the target belongs to. + * @param {object} opts Configuration options. + * @param {string} opts.foreignKey The field that holds the primary key of the + * related record. + * @param {string} opts.localField The field that holds a reference to the + * related record object. + * @returns {Function} Invocation function, which accepts the target as the only + * parameter. + */ +function belongsTo(related, opts) { + return mapper => { + Relation.belongsTo(related, opts).assignTo(mapper); + }; +} +/** + * HasMany relation decorator. You probably won't use this directly. + * + * @method + * @param {Mapper} related The relation of which the target has many. + * @param {object} opts Configuration options. + * @param {string} [opts.foreignKey] The field that holds the primary key of the + * related record. + * @param {string} opts.localField The field that holds a reference to the + * related record object. + * @returns {Function} Invocation function, which accepts the target as the only + * parameter. + */ +function hasMany(related, opts) { + return mapper => { + Relation.hasMany(related, opts).assignTo(mapper); + }; +} +/** + * HasOne relation decorator. You probably won't use this directly. + * + * @method + * @param {Mapper} related The relation of which the target has one. + * @param {object} opts Configuration options. + * @param {string} [opts.foreignKey] The field that holds the primary key of the + * related record. + * @param {string} opts.localField The field that holds a reference to the + * related record object. + * @returns {Function} Invocation function, which accepts the target as the only + * parameter. + */ +function hasOne(related, opts) { + return mapper => { + Relation.hasOne(related, opts).assignTo(mapper); + }; +} -utils.logify(Component.prototype); -/** - * Register a new event listener on this Component. - * - * @example - * // Listen for all "afterCreate" events in a DataStore - * store.on('afterCreate', (mapperName, props, opts, result) => { - * console.log(mapperName); // "post" - * console.log(props.id); // undefined - * console.log(result.id); // 1234 - * }); - * store.create('post', { title: 'Modeling your data' }).then((post) => { - * console.log(post.id); // 1234 - * }); - * - * @example - * // Listen for the "add" event on a collection - * collection.on('add', (records) => { - * console.log(records); // [...] - * }); - * - * @example - * // Listen for "change" events on a record - * post.on('change', (record, changes) => { - * console.log(changes); // { changed: { title: 'Modeling your data' } } - * }); - * post.title = 'Modeling your data'; - * - * @method Component#on - * @param {string} event Name of event to subsribe to. - * @param {Function} listener Listener function to handle the event. - * @param {*} [ctx] Optional content in which to invoke the listener. - * @since 3.0.0 +const DOMAIN$6 = 'Mapper'; +const applyDefaultsHooks = ['beforeCreate', 'beforeCreateMany']; +const validatingHooks = ['beforeCreate', 'beforeCreateMany', 'beforeUpdate', 'beforeUpdateAll', 'beforeUpdateMany']; +function makeNotify(num) { + return function (...args) { + var _a; + const opts = args[args.length - num]; + const op = opts.op; + this.dbg(op, ...args); + if (applyDefaultsHooks.indexOf(op) !== -1 && opts.applyDefaults !== false) { + const schema = this.getSchema(); + if ((_a = schema) === null || _a === void 0 ? void 0 : _a.applyDefaults) { + let toProcess = args[0]; + if (!utils.isArray(toProcess)) { + toProcess = [toProcess]; + } + toProcess.forEach(record => { + schema.applyDefaults(record); + }); + } + } + // Automatic validation + if (validatingHooks.indexOf(op) !== -1 && !opts.noValidate) { + // Save current value of option + const originalExistingOnly = opts.existingOnly; + // For updates, ignore required fields if they aren't present + if (op.indexOf('beforeUpdate') === 0 && opts.existingOnly === undefined) { + opts.existingOnly = true; + } + const errors = this.validate(args[op === 'beforeUpdate' ? 1 : 0], utils.pick(opts, ['existingOnly'])); + // Restore option + opts.existingOnly = originalExistingOnly; + // Abort lifecycle due to validation errors + if (errors) { + const err = new TsDataError('validation failed'); + err.errors = errors; + return utils.reject(err); + } + } + // Emit lifecycle event + if (opts.notify || (opts.notify === undefined && this.notify)) { + setTimeout(() => { + this.emit(op, ...args); + }); + } + }; +} +// These are the default implementations of all of the lifecycle hooks +const notify = makeNotify(1); +const notify2 = makeNotify(2); +// This object provides meta information used by Mapper#crud to actually +// execute each lifecycle method +const LIFECYCLE_METHODS = { + count: { + defaults: [{}, {}], + skip: true, + types: [] + }, + destroy: { + defaults: [{}, {}], + skip: true, + types: [] + }, + destroyAll: { + defaults: [{}, {}], + skip: true, + types: [] + }, + find: { + defaults: [undefined, {}], + types: [] + }, + findAll: { + defaults: [{}, {}], + types: [] + }, + sum: { + defaults: [undefined, {}, {}], + skip: true, + types: [] + }, + update: { + adapterArgs(mapper, id, props, opts) { + return [id, mapper.toJSON(props, opts), opts]; + }, + beforeAssign: 1, + defaults: [undefined, {}, {}], + types: [] + }, + updateAll: { + adapterArgs(mapper, props, query, opts) { + return [mapper.toJSON(props, opts), query, opts]; + }, + beforeAssign: 0, + defaults: [{}, {}, {}], + types: [] + }, + updateMany: { + adapterArgs(mapper, records, opts) { + return [records.map(record => mapper.toJSON(record, opts)), opts]; + }, + beforeAssign: 0, + defaults: [[], {}], + types: [] + } +}; +const MAPPER_DEFAULTS = { + _adapters: {}, + applyDefaults: true, + applySchema: true, + defaultAdapter: 'http', + idAttribute: 'id', + keepChangeHistory: true, + notify: true, + noValidate: false, + raw: false, + validateOnSet: true +}; +/** + * The core of JSData's [ORM/ODM][orm] implementation. Given a minimum amount of + * meta information about a resource, a Mapper can perform generic CRUD + * operations against that resource. Apart from its configuration, a Mapper is + * stateless. The particulars of various persistence layers have been abstracted + * into adapters, which a Mapper uses to perform its operations. + * + * The term "Mapper" comes from the [Data Mapper Pattern][pattern] described in + * Martin Fowler's [Patterns of Enterprise Application Architecture][book]. A + * Data Mapper moves data between [in-memory object instances][record] and a + * relational or document-based database. JSData's Mapper can work with any + * persistence layer you can write an adapter for. + * + * _("Model" is a heavily overloaded term and is avoided in this documentation + * to prevent confusion.)_ + * + * [orm]: https://en.wikipedia.org/wiki/Object-relational_mapping + * + * @example + * [pattern]: https://en.wikipedia.org/wiki/Data_mapper_pattern + * [book]: http://martinfowler.com/books/eaa.html + * [record]: Record.html + * // Import and instantiate + * import { Mapper } from 'js-data'; + * const UserMapper = new Mapper({ name: 'user' }); + * + * @example + * // Define a Mapper using the Container component + * import { Container } from 'js-data'; + * const store = new Container(); + * store.defineMapper('user'); + * + * @class Mapper + * @extends Component + * @param {object} opts Configuration options. + * @param {boolean} [opts.applySchema=true] See {@link Mapper#applySchema}. + * @param {boolean} [opts.debug=false] See {@link Component#debug}. + * @param {string} [opts.defaultAdapter=http] See {@link Mapper#defaultAdapter}. + * @param {string} [opts.idAttribute=id] See {@link Mapper#idAttribute}. + * @param {object} [opts.methods] See {@link Mapper#methods}. + * @param {string} opts.name See {@link Mapper#name}. + * @param {boolean} [opts.notify] See {@link Mapper#notify}. + * @param {boolean} [opts.raw=false] See {@link Mapper#raw}. + * @param {Function|boolean} [opts.recordClass] See {@link Mapper#recordClass}. + * @param {Object|Schema} [opts.schema] See {@link Mapper#schema}. + * @returns {Mapper} A new {@link Mapper} instance. + * @see http://www.js-data.io/v3.0/docs/components-of-jsdata#mapper + * @since 3.0.0 + * @tutorial ["http://www.js-data.io/v3.0/docs/components-of-jsdata#mapper","Components of JSData: Mapper"] + * @tutorial ["http://www.js-data.io/v3.0/docs/modeling-your-data","Modeling your data"] + */ +class Mapper extends Component { + constructor(opts = {}) { + super(); + /** + * The meta information describing this Mapper's available lifecycle + * methods. __Do not modify.__ + * + * @name Mapper#lifecycleMethods + * @since 3.0.0 + * @type {Object} + */ + this.lifecycleMethods = LIFECYCLE_METHODS; + /** + * Mapper lifecycle hook called by {@link Mapper#count}. If this method + * returns a promise then {@link Mapper#count} will wait for the promise + * to resolve before continuing. + * + * @method Mapper#afterCount + * @param {object} query The `query` argument passed to {@link Mapper#count}. + * @param {object} opts The `opts` argument passed to {@link Mapper#count}. + * @param {*} result The result, if any. + * @since 3.0.0 + */ + this.afterCount = notify2; + /** + * Mapper lifecycle hook called by {@link Mapper#create}. If this method + * returns a promise then {@link Mapper#create} will wait for the promise + * to resolve before continuing. + * + * @method Mapper#afterCreate + * @param {object} props The `props` argument passed to {@link Mapper#create}. + * @param {object} opts The `opts` argument passed to {@link Mapper#create}. + * @param {*} result The result, if any. + * @since 3.0.0 + */ + this.afterCreate = notify2; + /** + * Mapper lifecycle hook called by {@link Mapper#createMany}. If this method + * returns a promise then {@link Mapper#createMany} will wait for the promise + * to resolve before continuing. + * + * @method Mapper#afterCreateMany + * @param {array} records The `records` argument passed to {@link Mapper#createMany}. + * @param {object} opts The `opts` argument passed to {@link Mapper#createMany}. + * @param {*} result The result, if any. + * @since 3.0.0 + */ + this.afterCreateMany = notify2; + /** + * Mapper lifecycle hook called by {@link Mapper#destroy}. If this method + * returns a promise then {@link Mapper#destroy} will wait for the promise + * to resolve before continuing. + * + * @method Mapper#afterDestroy + * @param {(string|number)} id The `id` argument passed to {@link Mapper#destroy}. + * @param {object} opts The `opts` argument passed to {@link Mapper#destroy}. + * @param {*} result The result, if any. + * @since 3.0.0 + */ + this.afterDestroy = notify2; + /** + * Mapper lifecycle hook called by {@link Mapper#destroyAll}. If this method + * returns a promise then {@link Mapper#destroyAll} will wait for the promise + * to resolve before continuing. + * + * @method Mapper#afterDestroyAll + * @param {*} data The `data` returned by the adapter. + * @param {query} query The `query` argument passed to {@link Mapper#destroyAll}. + * @param {object} opts The `opts` argument passed to {@link Mapper#destroyAll}. + * @param {*} result The result, if any. + * @since 3.0.0 + */ + this.afterDestroyAll = notify2; + /** + * Mapper lifecycle hook called by {@link Mapper#find}. If this method + * returns a promise then {@link Mapper#find} will wait for the promise + * to resolve before continuing. + * + * @method Mapper#afterFind + * @param {(string|number)} id The `id` argument passed to {@link Mapper#find}. + * @param {object} opts The `opts` argument passed to {@link Mapper#find}. + * @param {*} result The result, if any. + * @since 3.0.0 + */ + this.afterFind = notify2; + /** + * Mapper lifecycle hook called by {@link Mapper#findAll}. If this method + * returns a promise then {@link Mapper#findAll} will wait for the promise + * to resolve before continuing. + * + * @method Mapper#afterFindAll + * @param {object} query The `query` argument passed to {@link Mapper#findAll}. + * @param {object} opts The `opts` argument passed to {@link Mapper#findAll}. + * @param {*} result The result, if any. + * @since 3.0.0 + */ + this.afterFindAll = notify2; + /** + * Mapper lifecycle hook called by {@link Mapper#sum}. If this method + * returns a promise then {@link Mapper#sum} will wait for the promise + * to resolve before continuing. + * + * @method Mapper#afterSum + * @param {object} query The `query` argument passed to {@link Mapper#sum}. + * @param {object} opts The `opts` argument passed to {@link Mapper#sum}. + * @param {*} result The result, if any. + * @since 3.0.0 + */ + this.afterSum = notify2; + /** + * Mapper lifecycle hook called by {@link Mapper#update}. If this method + * returns a promise then {@link Mapper#update} will wait for the promise + * to resolve before continuing. + * + * @method Mapper#afterUpdate + * @param {(string|number)} id The `id` argument passed to {@link Mapper#update}. + * @param {props} props The `props` argument passed to {@link Mapper#update}. + * @param {object} opts The `opts` argument passed to {@link Mapper#update}. + * @param {*} result The result, if any. + * @since 3.0.0 + */ + this.afterUpdate = notify2; + /** + * Mapper lifecycle hook called by {@link Mapper#updateAll}. If this method + * returns a promise then {@link Mapper#updateAll} will wait for the promise + * to resolve before continuing. + * + * @method Mapper#afterUpdateAll + * @param {object} props The `props` argument passed to {@link Mapper#updateAll}. + * @param {object} query The `query` argument passed to {@link Mapper#updateAll}. + * @param {object} opts The `opts` argument passed to {@link Mapper#updateAll}. + * @param {*} result The result, if any. + * @since 3.0.0 + */ + this.afterUpdateAll = notify2; + /** + * Mapper lifecycle hook called by {@link Mapper#updateMany}. If this method + * returns a promise then {@link Mapper#updateMany} will wait for the promise + * to resolve before continuing. + * + * @method Mapper#afterUpdateMany + * @param {array} records The `records` argument passed to {@link Mapper#updateMany}. + * @param {object} opts The `opts` argument passed to {@link Mapper#updateMany}. + * @param {*} result The result, if any. + * @since 3.0.0 + */ + this.afterUpdateMany = notify2; + /** + * Mapper lifecycle hook called by {@link Mapper#create}. If this method + * returns a promise then {@link Mapper#create} will wait for the promise + * to resolve before continuing. + * + * @method Mapper#beforeCreate + * @param {object} props The `props` argument passed to {@link Mapper#create}. + * @param {object} opts The `opts` argument passed to {@link Mapper#create}. + * @since 3.0.0 + */ + this.beforeCreate = notify; + /** + * Mapper lifecycle hook called by {@link Mapper#createMany}. If this method + * returns a promise then {@link Mapper#createMany} will wait for the promise + * to resolve before continuing. + * + * @method Mapper#beforeCreateMany + * @param {array} records The `records` argument passed to {@link Mapper#createMany}. + * @param {object} opts The `opts` argument passed to {@link Mapper#createMany}. + * @since 3.0.0 + */ + this.beforeCreateMany = notify; + /** + * Mapper lifecycle hook called by {@link Mapper#count}. If this method + * returns a promise then {@link Mapper#count} will wait for the promise + * to resolve before continuing. + * + * @method Mapper#beforeCount + * @param {object} query The `query` argument passed to {@link Mapper#count}. + * @param {object} opts The `opts` argument passed to {@link Mapper#count}. + * @since 3.0.0 + */ + this.beforeCount = notify; + /** + * Mapper lifecycle hook called by {@link Mapper#destroy}. If this method + * returns a promise then {@link Mapper#destroy} will wait for the promise + * to resolve before continuing. + * + * @method Mapper#beforeDestroy + * @param {(string|number)} id The `id` argument passed to {@link Mapper#destroy}. + * @param {object} opts The `opts` argument passed to {@link Mapper#destroy}. + * @since 3.0.0 + */ + this.beforeDestroy = notify; + /** + * Mapper lifecycle hook called by {@link Mapper#destroyAll}. If this method + * returns a promise then {@link Mapper#destroyAll} will wait for the promise + * to resolve before continuing. + * + * @method Mapper#beforeDestroyAll + * @param {query} query The `query` argument passed to {@link Mapper#destroyAll}. + * @param {object} opts The `opts` argument passed to {@link Mapper#destroyAll}. + * @since 3.0.0 + */ + this.beforeDestroyAll = notify; + /** + * Mappers lifecycle hook called by {@link Mapper#find}. If this method + * returns a promise then {@link Mapper#find} will wait for the promise + * to resolve before continuing. + * + * @method Mapper#beforeFind + * @param {(string|number)} id The `id` argument passed to {@link Mapper#find}. + * @param {object} opts The `opts` argument passed to {@link Mapper#find}. + * @since 3.0.0 + */ + this.beforeFind = notify; + /** + * Mapper lifecycle hook called by {@link Mapper#findAll}. If this method + * returns a promise then {@link Mapper#findAll} will wait for the promise + * to resolve before continuing. + * + * @method Mapper#beforeFindAll + * @param {object} query The `query` argument passed to {@link Mapper#findAll}. + * @param {object} opts The `opts` argument passed to {@link Mapper#findAll}. + * @since 3.0.0 + */ + this.beforeFindAll = notify; + /** + * Mapper lifecycle hook called by {@link Mapper#sum}. If this method + * returns a promise then {@link Mapper#sum} will wait for the promise + * to resolve before continuing. + * + * @method Mapper#beforeSum + * @param {string} field The `field` argument passed to {@link Mapper#sum}. + * @param {object} query The `query` argument passed to {@link Mapper#sum}. + * @param {object} opts The `opts` argument passed to {@link Mapper#sum}. + * @since 3.0.0 + */ + this.beforeSum = notify; + /** + * Mapper lifecycle hook called by {@link Mapper#update}. If this method + * returns a promise then {@link Mapper#update} will wait for the promise + * to resolve before continuing. + * + * @method Mapper#beforeUpdate + * @param {(string|number)} id The `id` argument passed to {@link Mapper#update}. + * @param {props} props The `props` argument passed to {@link Mapper#update}. + * @param {object} opts The `opts` argument passed to {@link Mapper#update}. + * @since 3.0.0 + */ + this.beforeUpdate = notify; + /** + * Mapper lifecycle hook called by {@link Mapper#updateAll}. If this method + * returns a promise then {@link Mapper#updateAll} will wait for the promise + * to resolve before continuing. + * + * @method Mapper#beforeUpdateAll + * @param {object} props The `props` argument passed to {@link Mapper#updateAll}. + * @param {object} query The `query` argument passed to {@link Mapper#updateAll}. + * @param {object} opts The `opts` argument passed to {@link Mapper#updateAll}. + * @since 3.0.0 + */ + this.beforeUpdateAll = notify; + /** + * Mapper lifecycle hook called by {@link Mapper#updateMany}. If this method + * returns a promise then {@link Mapper#updateMany} will wait for the promise + * to resolve before continuing. + * + * @method Mapper#beforeUpdateMany + * @param {array} records The `records` argument passed to {@link Mapper#updateMany}. + * @param {object} opts The `opts` argument passed to {@link Mapper#updateMany}. + * @since 3.0.0 + */ + this.beforeUpdateMany = notify; + // Apply user-provided configuration + utils.fillIn(this, opts); + // Fill in any missing options with the defaults + utils.fillIn(this, utils.copy(MAPPER_DEFAULTS)); + /** + * The name for this Mapper. This is the minimum amount of meta information + * required for a Mapper to be able to execute CRUD operations for a + * Resource. + * + * @name Mapper#name + * @since 3.0.0 + * @type {string} + */ + if (!this.name) { + throw utils.err(`new ${DOMAIN$6}`, 'opts.name')(400, 'string', this.name); + } + // Setup schema, with an empty default schema if necessary + if (this.schema) { + this.schema.type = this.schema.type || 'object'; + if (!(this.schema instanceof Schema)) { + this.schema = new Schema(this.schema || { type: 'object' }); + } + } + // Create a subclass of Record that's tied to this Mapper + if (this.recordClass === undefined) { + // tslint:disable-next-line:max-classes-per-file + this.recordClass = class TiedRecord extends Record { + }; + } + if (this.recordClass) { + this.recordClass.mapper = this; + /** + * Functions that should be added to the prototype of {@link Mapper#recordClass}. + * + * @name Mapper#methods + * @since 3.0.0 + * @type {Object} + */ + if (utils.isObject(this.methods)) { + utils.addHiddenPropsToTarget(this.recordClass.prototype, this.methods); + } + // We can only apply the schema to the prototype of this.recordClass if the + // class extends Record + if (Record.prototype.isPrototypeOf(Object.create(this.recordClass.prototype)) && + this.schema && + this.schema.apply && + this.applySchema) { + this.schema.apply(this.recordClass.prototype); + } + } + } + /** + * This method is called at the end of most lifecycle methods. It does the + * following: + * + * 1. If `opts.raw` is `true`, add this Mapper's configuration to the `opts` + * argument as metadata for the operation. + * 2. Wrap the result data appropriately using {@link Mapper#wrap}, which + * calls {@link Mapper#createRecord}. + * + * @method Mapper#_end + * @private + * @since 3.0.0 + */ + _end(result, opts, skip = false) { + if (opts.raw) { + utils._(result, opts); + } + if (skip) { + return result; + } + let _data = opts.raw ? result.data : result; + if (_data && utils.isFunction(this.wrap)) { + _data = this.wrap(_data, opts); + if (opts.raw) { + result.data = _data; + } + else { + result = _data; + } + } + return result; + } + /** + * Define a belongsTo relationship. Only useful if you're managing your + * Mappers manually and not using a Container or DataStore component. + * + * @example + * PostMapper.belongsTo(UserMapper, { + * // post.user_id points to user.id + * foreignKey: 'user_id' + * // user records will be attached to post records at "post.user" + * localField: 'user' + * }); + * + * CommentMapper.belongsTo(UserMapper, { + * // comment.user_id points to user.id + * foreignKey: 'user_id' + * // user records will be attached to comment records at "comment.user" + * localField: 'user' + * }); + * CommentMapper.belongsTo(PostMapper, { + * // comment.post_id points to post.id + * foreignKey: 'post_id' + * // post records will be attached to comment records at "comment.post" + * localField: 'post' + * }); + * + * @method Mapper#belongsTo + * @see http://www.js-data.io/v3.0/docs/relations + * @since 3.0.0 + */ + belongsTo(relatedMapper, opts) { + return belongsTo(relatedMapper, opts)(this); + } + /** + * Select records according to the `query` argument and return the count. + * + * {@link Mapper#beforeCount} will be called before calling the adapter. + * {@link Mapper#afterCount} will be called after calling the adapter. + * + * @example + * // Get the number of published blog posts + * PostMapper.count({ status: 'published' }).then((numPublished) => { + * console.log(numPublished); // e.g. 45 + * }); + * + * @method Mapper#count + * @param {object} [query={}] Selection query. See {@link query}. + * @param {object} [query.where] See {@link query.where}. + * @param {number} [query.offset] See {@link query.offset}. + * @param {number} [query.limit] See {@link query.limit}. + * @param {string|Array[]} [query.orderBy] See {@link query.orderBy}. + * @param {object} [opts] Configuration options. Refer to the `count` method + * of whatever adapter you're using for more configuration options. + * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the + * adapter to use. + * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}. + * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}. + * @returns {Promise} Resolves with the count of the selected records. + * @since 3.0.0 + */ + count(query, opts) { + return this.crud('count', query, opts); + } + /** + * Fired during {@link Mapper#create}. See + * {@link Mapper~beforeCreateListener} for how to listen for this event. + * + * @event Mapper#beforeCreate + * @see Mapper~beforeCreateListener + * @see Mapper#create + */ + /** + * Callback signature for the {@link Mapper#event:beforeCreate} event. + * + * @example + * function onBeforeCreate (props, opts) { + * // do something + * } + * store.on('beforeCreate', onBeforeCreate); + * + * @callback Mapper~beforeCreateListener + * @param {object} props The `props` argument passed to {@link Mapper#beforeCreate}. + * @param {object} opts The `opts` argument passed to {@link Mapper#beforeCreate}. + * @see Mapper#event:beforeCreate + * @see Mapper#create + * @since 3.0.0 + */ + /** + * Fired during {@link Mapper#create}. See + * {@link Mapper~afterCreateListener} for how to listen for this event. + * + * @event Mapper#afterCreate + * @see Mapper~afterCreateListener + * @see Mapper#create + */ + /** + * Callback signature for the {@link Mapper#event:afterCreate} event. + * + * @example + * function onAfterCreate (props, opts, result) { + * // do something + * } + * store.on('afterCreate', onAfterCreate); + * + * @callback Mapper~afterCreateListener + * @param {object} props The `props` argument passed to {@link Mapper#afterCreate}. + * @param {object} opts The `opts` argument passed to {@link Mapper#afterCreate}. + * @param {object} result The `result` argument passed to {@link Mapper#afterCreate}. + * @see Mapper#event:afterCreate + * @see Mapper#create + * @since 3.0.0 + */ + /** + * Create and save a new the record using the provided `props`. + * + * {@link Mapper#beforeCreate} will be called before calling the adapter. + * {@link Mapper#afterCreate} will be called after calling the adapter. + * + * @example + * // Create and save a new blog post + * PostMapper.create({ + * title: 'Modeling your data', + * status: 'draft' + * }).then((post) => { + * console.log(post); // { id: 1234, status: 'draft', ... } + * }); + * + * @fires Mapper#beforeCreate + * @fires Mapper#afterCreate + * @method Mapper#create + * @param {object} props The properties for the new record. + * @param {object} [opts] Configuration options. Refer to the `create` method + * of whatever adapter you're using for more configuration options. + * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the + * adapter to use. + * @param {boolean} [opts.noValidate={@link Mapper#noValidate}] See {@link Mapper#noValidate}. + * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}. + * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}. + * @param {string[]} [opts.with=[]] Relations to create in a cascading + * create if `props` contains nested relations. NOT performed in a + * transaction. Each nested create will result in another {@link Mapper#create} + * or {@link Mapper#createMany} call. + * @param {string[]} [opts.pass=[]] Relations to send to the adapter as part + * of the payload. Normally relations are not sent. + * @returns {Promise} Resolves with the created record. + * @since 3.0.0 + */ + create(props = {}, opts = {}) { + const originalRecord = props; + let parentRelationMap = {}; + let adapterResponse = {}; + // Fill in "opts" with the Mapper's configuration + utils._(opts, this); + opts.adapter = this.getAdapterName(opts); + opts.op = 'beforeCreate'; + return this._runHook(opts.op, props, opts) + .then(props => { + opts.with = opts.with || []; + return this._createParentRecordIfRequired(props, opts); + }) + .then(relationMap => { + parentRelationMap = relationMap; + }) + .then(() => { + opts.op = 'create'; + return this._invokeAdapterMethod(opts.op, props, opts); + }) + .then(result => { + adapterResponse = result; + }) + .then(() => { + const createdProps = opts.raw ? adapterResponse.data : adapterResponse; + return this._createOrAssignChildRecordIfRequired(createdProps, { + opts, + parentRelationMap, + originalProps: props + }); + }) + .then(createdProps => { + return this._commitChanges(originalRecord, createdProps); + }) + .then(record => { + if (opts.raw) { + adapterResponse.data = record; + } + else { + adapterResponse = record; + } + const result = this._end(adapterResponse, opts); + opts.op = 'afterCreate'; + return this._runHook(opts.op, props, opts, result); + }); + } + _commitChanges(recordOrRecords, newValues) { + if (utils.isArray(recordOrRecords)) { + return recordOrRecords.map((record, i) => this._commitChanges(record, newValues[i])); + } + utils.set(recordOrRecords, newValues, { silent: true }); + if (utils.isFunction(recordOrRecords.commit)) { + recordOrRecords.commit(); + } + return recordOrRecords; + } + /** + * Use {@link Mapper#createRecord} instead. + * @deprecated + * @method Mapper#createInstance + * @param {Object|Array} props See {@link Mapper#createRecord}. + * @param {object} [opts] See {@link Mapper#createRecord}. + * @returns {Object|Array} See {@link Mapper#createRecord}. + * @see Mapper#createRecord + * @since 3.0.0 + */ + createInstance(props, opts) { + return this.createRecord(props, opts); + } + /** + * Creates parent record for relation types like BelongsTo or HasMany with localKeys + * in order to satisfy foreignKey dependency (so called child records). + * @param {object} props See {@link Mapper#create}. + * @param {object} opts See {@link Mapper#create}. + * @returns {Object} cached parent records map + * @see Mapper#create + * @since 3.0.0 + */ + _createParentRecordIfRequired(props, opts) { + const tasks = []; + const relations = []; + utils.forEachRelation(this, opts, (def, optsCopy) => { + if (!def.isRequiresParentId() || !def.getLocalField(props)) { + return; + } + optsCopy.raw = false; + relations.push(def); + tasks.push(def.createParentRecord(props, optsCopy)); + }); + return Promise.all(tasks).then(records => { + return relations.reduce((map, relation, index) => { + relation.setLocalField(map, records[index]); + return map; + }, {}); + }); + } + /** + * Creates child record for relation types like HasOne or HasMany with foreignKey + * in order to satisfy foreignKey dependency (so called parent records). + * @param {object} props See {@link Mapper#create}. + * @param {object} context contains collected information. + * @param {object} context.opts See {@link Mapper#create}. + * @param {object} context.parentRelationMap contains parent records map + * @param {object} context.originalProps contains data passed into {@link Mapper#create} method + * @return {Promise} updated props + * @see Mapper#create + * @since 3.0.0 + */ + _createOrAssignChildRecordIfRequired(props, context) { + const tasks = []; + utils.forEachRelation(this, context.opts, (def, optsCopy) => { + const relationData = def.getLocalField(context.originalProps); + if (!relationData) { + return; + } + optsCopy.raw = false; + // Create hasMany and hasOne after the main create because we needed + // a generated id to attach to these items + if (def.isRequiresChildId()) { + tasks.push(def.createChildRecord(props, relationData, optsCopy)); + } + else if (def.isRequiresParentId()) { + const parent = def.getLocalField(context.parentRelationMap); + if (parent) { + def.setLocalField(props, parent); + } + } + }); + return Promise.all(tasks).then(() => props); + } + /** + * Fired during {@link Mapper#createMany}. See + * {@link Mapper~beforeCreateManyListener} for how to listen for this event. + * + * @event Mapper#beforeCreateMany + * @see Mapper~beforeCreateManyListener + * @see Mapper#createMany + */ + /** + * Callback signature for the {@link Mapper#event:beforeCreateMany} event. + * + * @example + * function onBeforeCreateMany (records, opts) { + * // do something + * } + * store.on('beforeCreateMany', onBeforeCreateMany); + * + * @callback Mapper~beforeCreateManyListener + * @param {object} records The `records` argument received by {@link Mapper#beforeCreateMany}. + * @param {object} opts The `opts` argument received by {@link Mapper#beforeCreateMany}. + * @see Mapper#event:beforeCreateMany + * @see Mapper#createMany + * @since 3.0.0 + */ + /** + * Fired during {@link Mapper#createMany}. See + * {@link Mapper~afterCreateManyListener} for how to listen for this event. + * + * @event Mapper#afterCreateMany + * @see Mapper~afterCreateManyListener + * @see Mapper#createMany + */ + /** + * Callback signature for the {@link Mapper#event:afterCreateMany} event. + * + * @example + * function onAfterCreateMany (records, opts, result) { + * // do something + * } + * store.on('afterCreateMany', onAfterCreateMany); + * + * @callback Mapper~afterCreateManyListener + * @param {object} records The `records` argument received by {@link Mapper#afterCreateMany}. + * @param {object} opts The `opts` argument received by {@link Mapper#afterCreateMany}. + * @param {object} result The `result` argument received by {@link Mapper#afterCreateMany}. + * @see Mapper#event:afterCreateMany + * @see Mapper#createMany + * @since 3.0.0 + */ + /** + * Given an array of records, batch create them via an adapter. + * + * {@link Mapper#beforeCreateMany} will be called before calling the adapter. + * {@link Mapper#afterCreateMany} will be called after calling the adapter. + * + * @example + * // Create and save several new blog posts + * PostMapper.createMany([{ + * title: 'Modeling your data', + * status: 'draft' + * }, { + * title: 'Reading data', + * status: 'draft' + * }]).then((posts) => { + * console.log(posts[0]); // { id: 1234, status: 'draft', ... } + * console.log(posts[1]); // { id: 1235, status: 'draft', ... } + * }); + * + * @fires Mapper#beforeCreate + * @fires Mapper#afterCreate + * @method Mapper#createMany + * @param {Record[]} records Array of records to be created in one batch. + * @param {object} [opts] Configuration options. Refer to the `createMany` + * method of whatever adapter you're using for more configuration options. + * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the + * adapter to use. + * @param {boolean} [opts.noValidate={@link Mapper#noValidate}] See {@link Mapper#noValidate}. + * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}. + * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}. + * @param {string[]} [opts.with=[]] Relations to create in a cascading + * create if `records` contains nested relations. NOT performed in a + * transaction. Each nested create will result in another {@link Mapper#createMany} + * call. + * @param {string[]} [opts.pass=[]] Relations to send to the adapter as part + * of the payload. Normally relations are not sent. + * @returns {Promise} Resolves with the created records. + * @since 3.0.0 + * @tutorial ["http://www.js-data.io/v3.0/docs/saving-data","Saving data"] + */ + createMany(records = [], opts = {}) { + // Default values for arguments + const originalRecords = records; + let adapterResponse; + // Fill in "opts" with the Mapper's configuration + utils._(opts, this); + opts.adapter = this.getAdapterName(opts); + // beforeCreateMany lifecycle hook + opts.op = 'beforeCreateMany'; + return this._runHook(opts.op, records, opts) + .then(records => { + // Deep pre-create belongsTo relations + const belongsToRelationData = {}; + opts.with = opts.with || []; + let tasks = []; + utils.forEachRelation(this, opts, (def, optsCopy) => { + const relationData = records.map(record => def.getLocalField(record)).filter(Boolean); + if (def.type === belongsToType && relationData.length === records.length) { + // Create belongsTo relation first because we need a generated id to + // attach to the child + optsCopy.raw = false; + tasks.push(def + .createLinked(relationData, optsCopy) + .then(relatedRecords => { + records.forEach((record, i) => def.setForeignKey(record, relatedRecords[i])); + }) + .then(relatedRecords => { + def.setLocalField(belongsToRelationData, relatedRecords); + })); + } + }); + return Promise.all(tasks) + .then(() => { + opts.op = 'createMany'; + return this._invokeAdapterMethod(opts.op, records, opts); + }) + .then(result => { + adapterResponse = result; + }) + .then(() => { + const createdRecordsData = opts.raw ? adapterResponse.data : adapterResponse; + // Deep post-create hasOne relations + tasks = []; + utils.forEachRelation(this, opts, (def, optsCopy) => { + const relationData = records.map(record => def.getLocalField(record)).filter(Boolean); + if (relationData.length !== records.length) { + return; + } + optsCopy.raw = false; + const belongsToData = def.getLocalField(belongsToRelationData); + let task; + // Create hasMany and hasOne after the main create because we needed + // a generated id to attach to these items + if (def.type === hasManyType) { + // Not supported + this.log('warn', 'deep createMany of hasMany type not supported!'); + } + else if (def.type === hasOneType) { + createdRecordsData.forEach((createdRecordData, i) => { + def.setForeignKey(createdRecordData, relationData[i]); + }); + task = def + .getRelation() + .createMany(relationData, optsCopy) + .then(relatedData => { + createdRecordsData.forEach((createdRecordData, i) => { + def.setLocalField(createdRecordData, relatedData[i]); + }); + }); + } + else if (def.type === belongsToType && + belongsToData && + belongsToData.length === createdRecordsData.length) { + createdRecordsData.forEach((createdRecordData, i) => { + def.setLocalField(createdRecordData, belongsToData[i]); + }); + } + if (task) { + tasks.push(task); + } + }); + return Promise.all(tasks).then(() => { + return this._commitChanges(originalRecords, createdRecordsData); + }); + }); + }) + .then(records => { + if (opts.raw) { + adapterResponse.data = records; + } + else { + adapterResponse = records; + } + const result = this._end(adapterResponse, opts); + opts.op = 'afterCreateMany'; + return this._runHook(opts.op, records, opts, result); + }); + } + /** + * Create an unsaved, uncached instance of this Mapper's + * {@link Mapper#recordClass}. + * + * Returns `props` if `props` is already an instance of + * {@link Mapper#recordClass}. + * + * __Note:__ This method does __not__ interact with any adapter, and does + * __not__ save any data. It only creates new objects in memory. + * + * @example + * // Create empty unsaved record instance + * const post = PostMapper.createRecord(); + * + * @example + * // Create an unsaved record instance with inital properties + * const post = PostMapper.createRecord({ + * title: 'Modeling your data', + * status: 'draft' + * }); + * + * @example + * // Create a record instance that corresponds to a saved record + * const post = PostMapper.createRecord({ + * // JSData thinks this record has been saved if it has a primary key + * id: 1234, + * title: 'Modeling your data', + * status: 'draft' + * }); + * + * @example + * // Create record instances from an array + * const posts = PostMapper.createRecord([{ + * title: 'Modeling your data', + * status: 'draft' + * }, { + * title: 'Reading data', + * status: 'draft' + * }]); + * + * @example + * // Records are validated by default + * import { Mapper } from 'js-data'; + * const PostMapper = new Mapper({ + * name: 'post', + * schema: { properties: { title: { type: 'string' } } } + * }); + * try { + * const post = PostMapper.createRecord({ + * title: 1234, + * }); + * } catch (err) { + * console.log(err.errors); // [{ expected: 'one of (string)', actual: 'number', path: 'title' }] + * } + * + * @example + * // Skip validation + * import { Mapper } from 'js-data'; + * const PostMapper = new Mapper({ + * name: 'post', + * schema: { properties: { title: { type: 'string' } } } + * }); + * const post = PostMapper.createRecord({ + * title: 1234, + * }, { noValidate: true }); + * console.log(post.isValid()); // false + * + * @method Mapper#createRecord + * @param {Object|Object[]} props The properties for the Record instance or an + * array of property objects for the Record instances. + * @param {object} [opts] Configuration options. + * @param {boolean} [opts.noValidate={@link Mapper#noValidate}] See {@link Mapper#noValidate}. + * @returns {Record|Record[]} The Record instance or Record instances. + * @since 3.0.0 + */ + createRecord(props = {}, opts) { + if (utils.isArray(props)) { + return props.map(_props => this.createRecord(_props, opts)); + } + if (!utils.isObject(props)) { + throw utils.err(`${DOMAIN$6}#createRecord`, 'props')(400, 'array or object', props); + } + if (this.relationList) { + this.relationList.forEach(def => { + def.ensureLinkedDataHasProperType(props, opts); + }); + } + const RecordCtor = this.recordClass; + const result = !RecordCtor || props instanceof RecordCtor ? props : new RecordCtor(props, opts); + return result; + // Record.mapper = this; + // return new Record(props); + } + /** + * Lifecycle invocation method. You probably won't call this method directly. + * + * @method Mapper#crud + * @param {string} method Name of the lifecycle method to invoke. + * @param {...*} args Arguments to pass to the lifecycle method. + * @returns {Promise} + * @since 3.0.0 + */ + crud(method, ...args) { + const config = this.lifecycleMethods[method]; + if (!config) { + throw utils.err(`${DOMAIN$6}#crud`, method)(404, 'method'); + } + const upper = `${method.charAt(0).toUpperCase()}${method.substr(1)}`; + const before = `before${upper}`; + const after = `after${upper}`; + let op; + // Default values for arguments + config.defaults.forEach((value, i) => { + if (args[i] === undefined) { + args[i] = utils.copy(value); + } + }); + const opts = args[args.length - 1]; + // Fill in "opts" with the Mapper's configuration + utils._(opts, this); + const adapter = opts.adapter = this.getAdapterName(opts); + // before lifecycle hook + op = opts.op = before; + return utils + .resolve(this[op](...args)) + .then(_value => { + if (args[config.beforeAssign] !== undefined) { + // Allow for re-assignment from lifecycle hook + args[config.beforeAssign] = _value === undefined ? args[config.beforeAssign] : _value; + } + // Now delegate to the adapter + op = opts.op = method; + args = config.adapterArgs ? config.adapterArgs(this, ...args) : args; + this.dbg(op, ...args); + return utils.resolve(this.getAdapter(adapter)[op](this, ...args)); + }) + .then(result => { + // force noValidate on find/findAll + const noValidate = /find/.test(op) || opts.noValidate; + const _opts = Object.assign({}, opts, { noValidate }); + result = this._end(result, _opts, !!config.skip); + args.push(result); + // after lifecycle hook + op = opts.op = after; + return utils.resolve(this[op](...args)).then(_result => { + // Allow for re-assignment from lifecycle hook + return _result === undefined ? result : _result; + }); + }); + } + /** + * Fired during {@link Mapper#destroy}. See + * {@link Mapper~beforeDestroyListener} for how to listen for this event. + * + * @event Mapper#beforeDestroy + * @see Mapper~beforeDestroyListener + * @see Mapper#destroy + */ + /** + * Callback signature for the {@link Mapper#event:beforeDestroy} event. + * + * @example + * function onBeforeDestroy (id, opts) { + * // do something + * } + * store.on('beforeDestroy', onBeforeDestroy); + * + * @callback Mapper~beforeDestroyListener + * @param {string|number} id The `id` argument passed to {@link Mapper#beforeDestroy}. + * @param {object} opts The `opts` argument passed to {@link Mapper#beforeDestroy}. + * @see Mapper#event:beforeDestroy + * @see Mapper#destroy + * @since 3.0.0 + */ + /** + * Fired during {@link Mapper#destroy}. See + * {@link Mapper~afterDestroyListener} for how to listen for this event. + * + * @event Mapper#afterDestroy + * @see Mapper~afterDestroyListener + * @see Mapper#destroy + */ + /** + * Callback signature for the {@link Mapper#event:afterDestroy} event. + * + * @example + * function onAfterDestroy (id, opts, result) { + * // do something + * } + * store.on('afterDestroy', onAfterDestroy); + * + * @callback Mapper~afterDestroyListener + * @param {string|number} id The `id` argument passed to {@link Mapper#afterDestroy}. + * @param {object} opts The `opts` argument passed to {@link Mapper#afterDestroy}. + * @param {object} result The `result` argument passed to {@link Mapper#afterDestroy}. + * @see Mapper#event:afterDestroy + * @see Mapper#destroy + * @since 3.0.0 + */ + /** + * Using an adapter, destroy the record with the given primary key. + * + * {@link Mapper#beforeDestroy} will be called before destroying the record. + * {@link Mapper#afterDestroy} will be called after destroying the record. + * + * @example + * // Destroy a specific blog post + * PostMapper.destroy(1234).then(() => { + * // Blog post #1234 has been destroyed + * }); + * + * @example + * // Get full response + * PostMapper.destroy(1234, { raw: true }).then((result) => { + * console.log(result.deleted); e.g. 1 + * console.log(...); // etc., more metadata can be found on the result + * }); + * + * @fires Mapper#beforeDestroy + * @fires Mapper#afterDestroy + * @method Mapper#destroy + * @param {(string|number)} id The primary key of the record to destroy. + * @param {object} [opts] Configuration options. Refer to the `destroy` method + * of whatever adapter you're using for more configuration options. + * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the + * adapter to use. + * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}. + * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}. + * @returns {Promise} Resolves when the record has been destroyed. Resolves + * even if no record was found to be destroyed. + * @since 3.0.0 + * @tutorial ["http://www.js-data.io/v3.0/docs/saving-data","Saving data"] + */ + destroy(id, opts) { + return this.crud('destroy', id, opts); + } + /** + * Fired during {@link Mapper#destroyAll}. See + * {@link Mapper~beforeDestroyAllListener} for how to listen for this event. + * + * @event Mapper#beforeDestroyAll + * @see Mapper~beforeDestroyAllListener + * @see Mapper#destroyAll + */ + /** + * Callback signature for the {@link Mapper#event:beforeDestroyAll} event. + * + * @example + * function onBeforeDestroyAll (query, opts) { + * // do something + * } + * store.on('beforeDestroyAll', onBeforeDestroyAll); + * + * @callback Mapper~beforeDestroyAllListener + * @param {object} query The `query` argument passed to {@link Mapper#beforeDestroyAll}. + * @param {object} opts The `opts` argument passed to {@link Mapper#beforeDestroyAll}. + * @see Mapper#event:beforeDestroyAll + * @see Mapper#destroyAll + * @since 3.0.0 + */ + /** + * Fired during {@link Mapper#destroyAll}. See + * {@link Mapper~afterDestroyAllListener} for how to listen for this event. + * + * @event Mapper#afterDestroyAll + * @see Mapper~afterDestroyAllListener + * @see Mapper#destroyAll + */ + /** + * Callback signature for the {@link Mapper#event:afterDestroyAll} event. + * + * @example + * function onAfterDestroyAll (query, opts, result) { + * // do something + * } + * store.on('afterDestroyAll', onAfterDestroyAll); + * + * @callback Mapper~afterDestroyAllListener + * @param {object} query The `query` argument passed to {@link Mapper#afterDestroyAll}. + * @param {object} opts The `opts` argument passed to {@link Mapper#afterDestroyAll}. + * @param {object} result The `result` argument passed to {@link Mapper#afterDestroyAll}. + * @see Mapper#event:afterDestroyAll + * @see Mapper#destroyAll + * @since 3.0.0 + */ + /** + * Destroy the records selected by `query` via an adapter. If no `query` is + * provided then all records will be destroyed. + * + * {@link Mapper#beforeDestroyAll} will be called before destroying the records. + * {@link Mapper#afterDestroyAll} will be called after destroying the records. + * + * @example + * // Destroy all blog posts + * PostMapper.destroyAll().then(() => { + * // All blog posts have been destroyed + * }); + * + * @example + * // Destroy all "draft" blog posts + * PostMapper.destroyAll({ status: 'draft' }).then(() => { + * // All "draft" blog posts have been destroyed + * }); + * + * @example + * // Get full response + * const query = null; + * const options = { raw: true }; + * PostMapper.destroyAll(query, options).then((result) => { + * console.log(result.deleted); e.g. 14 + * console.log(...); // etc., more metadata can be found on the result + * }); + * + * @fires Mapper#beforeDestroyAll + * @fires Mapper#afterDestroyAll + * @method Mapper#destroyAll + * @param {object} [query={}] Selection query. See {@link query}. + * @param {object} [query.where] See {@link query.where}. + * @param {number} [query.offset] See {@link query.offset}. + * @param {number} [query.limit] See {@link query.limit}. + * @param {string|Array[]} [query.orderBy] See {@link query.orderBy}. + * @param {object} [opts] Configuration options. Refer to the `destroyAll` + * method of whatever adapter you're using for more configuration options. + * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the + * adapter to use. + * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}. + * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}. + * @returns {Promise} Resolves when the records have been destroyed. Resolves + * even if no records were found to be destroyed. + * @see query + * @since 3.0.0 + * @tutorial ["http://www.js-data.io/v3.0/docs/saving-data","Saving data"] + */ + destroyAll(query, opts) { + return this.crud('destroyAll', query, opts); + } + /** + * Fired during {@link Mapper#find}. See + * {@link Mapper~beforeFindListener} for how to listen for this event. + * + * @event Mapper#beforeFind + * @see Mapper~beforeFindListener + * @see Mapper#find + */ + /** + * Callback signature for the {@link Mapper#event:beforeFind} event. + * + * @example + * function onBeforeFind (id, opts) { + * // do something + * } + * store.on('beforeFind', onBeforeFind); + * + * @callback Mapper~beforeFindListener + * @param {string|number} id The `id` argument passed to {@link Mapper#beforeFind}. + * @param {object} opts The `opts` argument passed to {@link Mapper#beforeFind}. + * @see Mapper#event:beforeFind + * @see Mapper#find + * @since 3.0.0 + */ + /** + * Fired during {@link Mapper#find}. See + * {@link Mapper~afterFindListener} for how to listen for this event. + * + * @event Mapper#afterFind + * @see Mapper~afterFindListener + * @see Mapper#find + */ + /** + * Callback signature for the {@link Mapper#event:afterFind} event. + * + * @example + * function onAfterFind (id, opts, result) { + * // do something + * } + * store.on('afterFind', onAfterFind); + * + * @callback Mapper~afterFindListener + * @param {string|number} id The `id` argument passed to {@link Mapper#afterFind}. + * @param {object} opts The `opts` argument passed to {@link Mapper#afterFind}. + * @param {object} result The `result` argument passed to {@link Mapper#afterFind}. + * @see Mapper#event:afterFind + * @see Mapper#find + * @since 3.0.0 + */ + /** + * Retrieve via an adapter the record with the given primary key. + * + * {@link Mapper#beforeFind} will be called before calling the adapter. + * {@link Mapper#afterFind} will be called after calling the adapter. + * + * @example + * PostMapper.find(1).then((post) => { + * console.log(post); // { id: 1, ...} + * }); + * + * @example + * // Get full response + * PostMapper.find(1, { raw: true }).then((result) => { + * console.log(result.data); // { id: 1, ...} + * console.log(result.found); // 1 + * console.log(...); // etc., more metadata can be found on the result + * }); + * + * @fires Mapper#beforeFind + * @fires Mapper#afterFind + * @method Mapper#find + * @param {(string|number)} id The primary key of the record to retrieve. + * @param {object} [opts] Configuration options. Refer to the `find` method + * of whatever adapter you're using for more configuration options. + * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the + * adapter to use. + * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}. + * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}. + * @param {string[]} [opts.with=[]] Relations to eager load in the request. + * @returns {Promise} Resolves with the found record. Resolves with + * `undefined` if no record was found. + * @see http://www.js-data.io/v3.0/docs/reading-data + * @since 3.0.0 + * @tutorial ["http://www.js-data.io/v3.0/docs/reading-data","Reading data"] + */ + find(id, opts) { + return this.crud('find', id, opts); + } + /** + * Fired during {@link Mapper#findAll}. See + * {@link Mapper~beforeFindAllListener} for how to listen for this event. + * + * @event Mapper#beforeFindAll + * @see Mapper~beforeFindAllListener + * @see Mapper#findAll + */ + /** + * Callback signature for the {@link Mapper#event:beforeFindAll} event. + * + * @example + * function onBeforeFindAll (query, opts) { + * // do something + * } + * store.on('beforeFindAll', onBeforeFindAll); + * + * @callback Mapper~beforeFindAllListener + * @param {object} query The `query` argument passed to {@link Mapper#beforeFindAll}. + * @param {object} opts The `opts` argument passed to {@link Mapper#beforeFindAll}. + * @see Mapper#event:beforeFindAll + * @see Mapper#findAll + * @since 3.0.0 + */ + /** + * Fired during {@link Mapper#findAll}. See + * {@link Mapper~afterFindAllListener} for how to listen for this event. + * + * @event Mapper#afterFindAll + * @see Mapper~afterFindAllListener + * @see Mapper#findAll + */ + /** + * Callback signature for the {@link Mapper#event:afterFindAll} event. + * + * @example + * function onAfterFindAll (query, opts, result) { + * // do something + * } + * store.on('afterFindAll', onAfterFindAll); + * + * @callback Mapper~afterFindAllListener + * @param {object} query The `query` argument passed to {@link Mapper#afterFindAll}. + * @param {object} opts The `opts` argument passed to {@link Mapper#afterFindAll}. + * @param {object} result The `result` argument passed to {@link Mapper#afterFindAll}. + * @see Mapper#event:afterFindAll + * @see Mapper#findAll + * @since 3.0.0 + */ + /** + * Using the `query` argument, select records to retrieve via an adapter. + * + * {@link Mapper#beforeFindAll} will be called before calling the adapter. + * {@link Mapper#afterFindAll} will be called after calling the adapter. + * + * @example + * // Find all "published" blog posts + * PostMapper.findAll({ status: 'published' }).then((posts) => { + * console.log(posts); // [{ id: 1, status: 'published', ...}, ...] + * }); + * + * @example + * // Get full response + * PostMapper.findAll({ status: 'published' }, { raw: true }).then((result) => { + * console.log(result.data); // [{ id: 1, status: 'published', ...}, ...] + * console.log(result.found); // e.g. 13 + * console.log(...); // etc., more metadata can be found on the result + * }); + * + * @fires Mapper#beforeFindAll + * @fires Mapper#afterFindAll + * @method Mapper#findAll + * @param {object} [query={}] Selection query. See {@link query}. + * @param {object} [query.where] See {@link query.where}. + * @param {number} [query.offset] See {@link query.offset}. + * @param {number} [query.limit] See {@link query.limit}. + * @param {string|Array[]} [query.orderBy] See {@link query.orderBy}. + * @param {object} [opts] Configuration options. Refer to the `findAll` method + * of whatever adapter you're using for more configuration options. + * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the + * adapter to use. + * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}. + * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}. + * @param {string[]} [opts.with=[]] Relations to eager load in the request. + * @returns {Promise} Resolves with the found records, if any. + * @see query + * @since 3.0.0 + * @tutorial ["http://www.js-data.io/v3.0/docs/reading-data","Reading data"] + */ + findAll(query, opts) { + return this.crud('findAll', query, opts); + } + /** + * Return the registered adapter with the given name or the default adapter if + * no name is provided. + * + * @method Mapper#getAdapter + * @param {string} [name] The name of the adapter to retrieve. + * @returns {Adapter} The adapter. + * @since 3.0.0 + * @tutorial ["http://www.js-data.io/v3.0/docs/connecting-to-a-data-source","Connecting to a data source"] + */ + getAdapter(name) { + this.dbg('getAdapter', 'name:', name); + const adapter = this.getAdapterName(name); + if (!adapter) { + throw utils.err(`${DOMAIN$6}#getAdapter`, 'name')(400, 'string', name); + } + return this.getAdapters()[adapter]; + } + /** + * Return the name of a registered adapter based on the given name or options, + * or the name of the default adapter if no name provided. + * + * @method Mapper#getAdapterName + * @param {(Object|string)} [opts] The name of an adapter or options, if any. + * @returns {string} The name of the adapter. + * @since 3.0.0 + * @tutorial ["http://www.js-data.io/v3.0/docs/connecting-to-a-data-source","Connecting to a data source"] + */ + getAdapterName(opts = {}) { + if (utils.isString(opts)) { + opts = { adapter: opts }; + } + return opts.adapter || opts.defaultAdapter; + } + /** + * Get the object of registered adapters for this Mapper. + * + * @method Mapper#getAdapters + * @returns {Object} {@link Mapper#_adapters} + * @since 3.0.0 + * @tutorial ["http://www.js-data.io/v3.0/docs/connecting-to-a-data-source","Connecting to a data source"] + */ + getAdapters() { + return this._adapters; + } + /** + * Returns this Mapper's {@link Schema}. + * + * @method Mapper#getSchema + * @returns {Schema} This Mapper's {@link Schema}. + * @see Mapper#schema + * @since 3.0.0 + */ + getSchema() { + return this.schema; + } + /** + * Defines a hasMany relationship. Only useful if you're managing your + * Mappers manually and not using a Container or DataStore component. + * + * @example + * UserMapper.hasMany(PostMapper, { + * // post.user_id points to user.id + * foreignKey: 'user_id' + * // post records will be attached to user records at "user.posts" + * localField: 'posts' + * }); + * + * @method Mapper#hasMany + * @see http://www.js-data.io/v3.0/docs/relations + * @since 3.0.0 + */ + hasMany(relatedMapper, opts) { + return hasMany(relatedMapper, opts)(this); + } + /** + * Defines a hasOne relationship. Only useful if you're managing your Mappers + * manually and not using a {@link Container} or {@link DataStore} component. + * + * @example + * UserMapper.hasOne(ProfileMapper, { + * // profile.user_id points to user.id + * foreignKey: 'user_id' + * // profile records will be attached to user records at "user.profile" + * localField: 'profile' + * }); + * + * @method Mapper#hasOne + * @see http://www.js-data.io/v3.0/docs/relations + * @since 3.0.0 + */ + hasOne(relatedMapper, opts) { + return hasOne(relatedMapper, opts)(this); + } + /** + * Return whether `record` is an instance of this Mapper's recordClass. + * + * @example + * const post = PostMapper.createRecord(); + * + * console.log(PostMapper.is(post)); // true + * // Equivalent to what's above + * console.log(post instanceof PostMapper.recordClass); // true + * + * @method Mapper#is + * @param {Object|Record} record The record to check. + * @returns {boolean} Whether `record` is an instance of this Mapper's + * {@link Mapper#recordClass}. + * @since 3.0.0 + */ + is(record) { + const recordClass = this.recordClass; + return recordClass ? record instanceof recordClass : false; + } + /** + * Register an adapter on this Mapper under the given name. + * + * @method Mapper#registerAdapter + * @param {string} name The name of the adapter to register. + * @param {Adapter} adapter The adapter to register. + * @param {object} [opts] Configuration options. + * @param {boolean} [opts.default=false] Whether to make the adapter the + * default adapter for this Mapper. + * @since 3.0.0 + * @tutorial ["http://www.js-data.io/v3.0/docs/connecting-to-a-data-source","Connecting to a data source"] + */ + registerAdapter(name, adapter, opts = {}) { + this.getAdapters()[name] = adapter; + // Optionally make it the default adapter for the target. + if (opts === true || opts.default) { + this.defaultAdapter = name; + } + } + _runHook(hookName, ...hookArgs) { + const defaultValueIndex = hookName.indexOf('after') === 0 ? hookArgs.length - 1 : 0; + return utils + .resolve(this[hookName](...hookArgs)) + .then(overridenResult => (overridenResult === undefined ? hookArgs[defaultValueIndex] : overridenResult)); + } + _invokeAdapterMethod(method, propsOrRecords, opts) { + const conversionOptions = { with: opts.pass || [] }; + let object; + this.dbg(opts.op, propsOrRecords, opts); + if (utils.isArray(propsOrRecords)) { + object = propsOrRecords.map(record => this.toJSON(record, conversionOptions)); + } + else { + object = this.toJSON(propsOrRecords, conversionOptions); + } + return this.getAdapter(opts.adapter)[method](this, object, opts); + } + /** + * Select records according to the `query` argument, and aggregate the sum + * value of the property specified by `field`. + * + * {@link Mapper#beforeSum} will be called before calling the adapter. + * {@link Mapper#afterSum} will be called after calling the adapter. + * + * @example + * PurchaseOrderMapper.sum('amount', { status: 'paid' }).then((amountPaid) => { + * console.log(amountPaid); // e.g. 451125.34 + * }); + * + * @method Mapper#sum + * @param {string} field The field to sum. + * @param {object} [query={}] Selection query. See {@link query}. + * @param {object} [query.where] See {@link query.where}. + * @param {number} [query.offset] See {@link query.offset}. + * @param {number} [query.limit] See {@link query.limit}. + * @param {string|Array[]} [query.orderBy] See {@link query.orderBy}. + * @param {object} [opts] Configuration options. Refer to the `sum` method + * of whatever adapter you're using for more configuration options. + * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the + * adapter to use. + * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}. + * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}. + * @returns {Promise} Resolves with the aggregated sum. + * @since 3.0.0 + */ + sum(field, query, opts) { + return this.crud('sum', field, query, opts); + } + /** + * Return a plain object representation of the given record. Relations can + * be optionally be included. Non-schema properties can be excluded. + * + * @example + * import { Mapper, Schema } from 'js-data'; + * const PersonMapper = new Mapper({ + * name: 'person', + * schema: { + * properties: { + * name: { type: 'string' }, + * id: { type: 'string' } + * } + * } + * }); + * const person = PersonMapper.createRecord({ id: 1, name: 'John', foo: 'bar' }); + * // "foo" is stripped by toJSON() + * console.log(PersonMapper.toJSON(person)); // {"id":1,"name":"John"} + * + * const PersonRelaxedMapper = new Mapper({ + * name: 'personRelaxed', + * schema: { + * properties: { + * name: { type: 'string' }, + * id: { type: 'string' } + * }, + * additionalProperties: true + * } + * }); + * const person2 = PersonRelaxedMapper.createRecord({ id: 1, name: 'John', foo: 'bar' }); + * // "foo" is not stripped by toJSON + * console.log(PersonRelaxedMapper.toJSON(person2)); // {"id":1,"name":"John","foo":"bar"} + * + * @method Mapper#toJSON + * @param {Record|Record[]} records Record or records from which to create a + * POJO representation. + * @param {object} [opts] Configuration options. + * @param {string[]} [opts.with] Array of relation names or relation fields + * to include in the POJO representation. + * @param {boolean} [opts.withAll] Whether to simply include all relations in + * the representation. Overrides `opts.with`. + * @returns {Object|Object[]} POJO representation of the record or records. + * @since 3.0.0 + */ + toJSON(records, opts = {}) { + let record; + if (utils.isArray(records)) { + return records.map(record => this.toJSON(record, opts)); + } + else { + record = records; + } + const relationFields = (this ? this.relationFields : []) || []; + let json = {}; + // Copy properties defined in the schema + if (this && this.schema) { + json = this.schema.pick(record); + } + else { + for (const key in record) { + if (relationFields.indexOf(key) === -1) { + json[key] = utils.plainCopy(record[key]); + } + } + } + // The user wants to include relations in the resulting plain object representation + if (this && opts.withAll) { + opts.with = relationFields.slice(); + } + if (this && opts.with) { + if (utils.isString(opts.with)) { + opts.with = [opts.with]; + } + utils.forEachRelation(this, opts, (def, optsCopy) => { + const relationData = def.getLocalField(record); + if (relationData) { + // The actual recursion + if (utils.isArray(relationData)) { + def.setLocalField(json, relationData.map(item => { + return def.getRelation().toJSON(item, optsCopy); + })); + } + else { + def.setLocalField(json, def.getRelation().toJSON(relationData, optsCopy)); + } + } + }); + } + return json; + } + /** + * Fired during {@link Mapper#update}. See + * {@link Mapper~beforeUpdateListener} for how to listen for this event. + * + * @event Mapper#beforeUpdate + * @see Mapper~beforeUpdateListener + * @see Mapper#update + */ + /** + * Callback signature for the {@link Mapper#event:beforeUpdate} event. + * + * @example + * function onBeforeUpdate (id, props, opts) { + * // do something + * } + * store.on('beforeUpdate', onBeforeUpdate); + * + * @callback Mapper~beforeUpdateListener + * @param {string|number} id The `id` argument passed to {@link Mapper#beforeUpdate}. + * @param {object} props The `props` argument passed to {@link Mapper#beforeUpdate}. + * @param {object} opts The `opts` argument passed to {@link Mapper#beforeUpdate}. + * @see Mapper#event:beforeUpdate + * @see Mapper#update + * @since 3.0.0 + */ + /** + * Fired during {@link Mapper#update}. See + * {@link Mapper~afterUpdateListener} for how to listen for this event. + * + * @event Mapper#afterUpdate + * @see Mapper~afterUpdateListener + * @see Mapper#update + */ + /** + * Callback signature for the {@link Mapper#event:afterUpdate} event. + * + * @example + * function onAfterUpdate (id, props, opts, result) { + * // do something + * } + * store.on('afterUpdate', onAfterUpdate); + * + * @callback Mapper~afterUpdateListener + * @param {string|number} id The `id` argument passed to {@link Mapper#afterUpdate}. + * @param {object} props The `props` argument passed to {@link Mapper#afterUpdate}. + * @param {object} opts The `opts` argument passed to {@link Mapper#afterUpdate}. + * @param {object} result The `result` argument passed to {@link Mapper#afterUpdate}. + * @see Mapper#event:afterUpdate + * @see Mapper#update + * @since 3.0.0 + */ + /** + * Using an adapter, update the record with the primary key specified by the + * `id` argument. + * + * {@link Mapper#beforeUpdate} will be called before updating the record. + * {@link Mapper#afterUpdate} will be called after updating the record. + * + * @example + * // Update a specific post + * PostMapper.update(1234, { + * status: 'published', + * published_at: new Date() + * }).then((post) => { + * console.log(post); // { id: 1234, status: 'published', ... } + * }); + * + * @fires Mapper#beforeUpdate + * @fires Mapper#afterUpdate + * @method Mapper#update + * @param {(string|number)} id The primary key of the record to update. + * @param {object} props The update to apply to the record. + * @param {object} [opts] Configuration options. Refer to the `update` method + * of whatever adapter you're using for more configuration options. + * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the + * adapter to use. + * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}. + * @param {boolean} [opts.noValidate={@link Mapper#noValidate}] See {@link Mapper#noValidate}. + * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}. + * transaction. + * @returns {Promise} Resolves with the updated record. Rejects if the record + * could not be found. + * @since 3.0.0 + * @tutorial ["http://www.js-data.io/v3.0/docs/saving-data","Saving data"] + */ + update(id, props, opts) { + return this.crud('update', id, props, opts); + } + /** + * Fired during {@link Mapper#updateAll}. See + * {@link Mapper~beforeUpdateAllListener} for how to listen for this event. + * + * @event Mapper#beforeUpdateAll + * @see Mapper~beforeUpdateAllListener + * @see Mapper#updateAll + */ + /** + * Callback signature for the {@link Mapper#event:beforeUpdateAll} event. + * + * @example + * function onBeforeUpdateAll (props, query, opts) { + * // do something + * } + * store.on('beforeUpdateAll', onBeforeUpdateAll); + * + * @callback Mapper~beforeUpdateAllListener + * @param {object} props The `props` argument received by {@link Mapper#beforeUpdateAll}. + * @param {object} query The `query` argument received by {@link Mapper#beforeUpdateAll}. + * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdateAll}. + * @see Mapper#event:beforeUpdateAll + * @see Mapper#updateAll + * @since 3.0.0 + */ + /** + * Fired during {@link Mapper#updateAll}. See + * {@link Mapper~afterUpdateAllListener} for how to listen for this event. + * + * @event Mapper#afterUpdateAll + * @see Mapper~afterUpdateAllListener + * @see Mapper#updateAll + */ + /** + * Callback signature for the {@link Mapper#event:afterUpdateAll} event. + * + * @example + * function onAfterUpdateAll (props, query, opts, result) { + * // do something + * } + * store.on('afterUpdateAll', onAfterUpdateAll); + * + * @callback Mapper~afterUpdateAllListener + * @param {object} props The `props` argument received by {@link Mapper#afterUpdateAll}. + * @param {object} query The `query` argument received by {@link Mapper#afterUpdateAll}. + * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdateAll}. + * @param {object} result The `result` argument received by {@link Mapper#afterUpdateAll}. + * @see Mapper#event:afterUpdateAll + * @see Mapper#updateAll + * @since 3.0.0 + */ + /** + * Using the `query` argument, perform the a single updated to the selected + * records. + * + * {@link Mapper#beforeUpdateAll} will be called before making the update. + * {@link Mapper#afterUpdateAll} will be called after making the update. + * + * @example + * // Turn all of John's blog posts into drafts. + * const update = { status: draft: published_at: null }; + * const query = { userId: 1234 }; + * PostMapper.updateAll(update, query).then((posts) => { + * console.log(posts); // [...] + * }); + * + * @fires Mapper#beforeUpdateAll + * @fires Mapper#afterUpdateAll + * @method Mapper#updateAll + * @param {object} props Update to apply to selected records. + * @param {object} [query={}] Selection query. See {@link query}. + * @param {object} [query.where] See {@link query.where}. + * @param {number} [query.offset] See {@link query.offset}. + * @param {number} [query.limit] See {@link query.limit}. + * @param {string|Array[]} [query.orderBy] See {@link query.orderBy}. + * @param {object} [opts] Configuration options. Refer to the `updateAll` + * method of whatever adapter you're using for more configuration options. + * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the + * adapter to use. + * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}. + * @param {boolean} [opts.noValidate={@link Mapper#noValidate}] See {@link Mapper#noValidate}. + * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}. + * @returns {Promise} Resolves with the update records, if any. + * @see query + * @since 3.0.0 + * @tutorial ["http://www.js-data.io/v3.0/docs/saving-data","Saving data"] + */ + updateAll(props, query, opts) { + return this.crud('updateAll', props, query, opts); + } + /** + * Fired during {@link Mapper#updateMany}. See + * {@link Mapper~beforeUpdateManyListener} for how to listen for this event. + * + * @event Mapper#beforeUpdateMany + * @see Mapper~beforeUpdateManyListener + * @see Mapper#updateMany + */ + /** + * Callback signature for the {@link Mapper#event:beforeUpdateMany} event. + * + * @example + * function onBeforeUpdateMany (records, opts) { + * // do something + * } + * store.on('beforeUpdateMany', onBeforeUpdateMany); + * + * @callback Mapper~beforeUpdateManyListener + * @param {object} records The `records` argument received by {@link Mapper#beforeUpdateMany}. + * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdateMany}. + * @see Mapper#event:beforeUpdateMany + * @see Mapper#updateMany + * @since 3.0.0 + */ + /** + * Fired during {@link Mapper#updateMany}. See + * {@link Mapper~afterUpdateManyListener} for how to listen for this event. + * + * @event Mapper#afterUpdateMany + * @see Mapper~afterUpdateManyListener + * @see Mapper#updateMany + */ + /** + * Callback signature for the {@link Mapper#event:afterUpdateMany} event. + * + * @example + * function onAfterUpdateMany (records, opts, result) { + * // do something + * } + * store.on('afterUpdateMany', onAfterUpdateMany); + * + * @callback Mapper~afterUpdateManyListener + * @param {object} records The `records` argument received by {@link Mapper#afterUpdateMany}. + * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdateMany}. + * @param {object} result The `result` argument received by {@link Mapper#afterUpdateMany}. + * @see Mapper#event:afterUpdateMany + * @see Mapper#updateMany + * @since 3.0.0 + */ + /** + * Given an array of updates, perform each of the updates via an adapter. Each + * "update" is a hash of properties with which to update an record. Each + * update must contain the primary key of the record to be updated. + * + * {@link Mapper#beforeUpdateMany} will be called before making the update. + * {@link Mapper#afterUpdateMany} will be called after making the update. + * + * @example + * PostMapper.updateMany([ + * { id: 1234, status: 'draft' }, + * { id: 2468, status: 'published', published_at: new Date() } + * ]).then((posts) => { + * console.log(posts); // [...] + * }); + * + * @fires Mapper#beforeUpdateMany + * @fires Mapper#afterUpdateMany + * @method Mapper#updateMany + * @param {Record[]} records Array up record updates. + * @param {object} [opts] Configuration options. Refer to the `updateMany` + * method of whatever adapter you're using for more configuration options. + * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the + * adapter to use. + * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}. + * @param {boolean} [opts.noValidate={@link Mapper#noValidate}] See {@link Mapper#noValidate}. + * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}. + * @returns {Promise} Resolves with the updated records. Rejects if any of the + * records could be found. + * @since 3.0.0 + * @tutorial ["http://www.js-data.io/v3.0/docs/saving-data","Saving data"] + */ + updateMany(records, opts) { + return this.crud('updateMany', records, opts); + } + /** + * Validate the given record or records according to this Mapper's + * {@link Schema}. If there are no validation errors then the return value + * will be `undefined`. + * + * @example + * import {Mapper, Schema} from 'js-data' + * const PersonSchema = new Schema({ + * properties: { + * name: { type: 'string' }, + * id: { type: 'string' } + * } + * }); + * const PersonMapper = new Mapper({ + * name: 'person', + * schema: PersonSchema + * }); + * let errors = PersonMapper.validate({ name: 'John' }); + * console.log(errors); // undefined + * errors = PersonMapper.validate({ name: 123 }); + * console.log(errors); // [{ expected: 'one of (string)', actual: 'number', path: 'name' }] + * + * @method Mapper#validate + * @param {Object|Object[]} record The record or records to validate. + * @param {object} [opts] Configuration options. Passed to + * {@link Schema#validate}. + * @returns {Object[]} Array of errors or `undefined` if no errors. + * @since 3.0.0 + */ + validate(record, opts = {}) { + const schema = this.getSchema(); + if (!schema) { + return; + } + const _opts = utils.pick(opts, ['existingOnly']); + if (utils.isArray(record)) { + const errors = record.map(_record => schema.validate(_record, utils.pick(_opts, ['existingOnly']))); + return errors.some(Boolean) ? errors : undefined; + } + return schema.validate(record, _opts); + } + /** + * Method used to wrap data returned by an adapter with this Mapper's + * {@link Mapper#recordClass}. This method is used by all of a Mapper's CRUD + * methods. The provided implementation of this method assumes that the `data` + * passed to it is a record or records that need to be wrapped with + * {@link Mapper#createRecord}. Override with care. + * + * Provided implementation of {@link Mapper#wrap}: + * + * ``` + * function (data, opts) { + * return this.createRecord(data, opts); + * } + * ``` + * + * @example + * const PostMapper = new Mapper({ + * name: 'post', + * // Override to customize behavior + * wrap (data, opts) { + * const originalWrap = this.constructor.prototype.wrap; + * // Let's say "GET /post" doesn't return JSON quite like JSData expects, + * // but the actual post records are nested under a "posts" field. So, + * // we override Mapper#wrap to handle this special case. + * if (opts.op === 'findAll') { + * return originalWrap.call(this, data.posts, opts); + * } + * // Otherwise perform original behavior + * return originalWrap.call(this, data, opts); + * } + * }); + * + * @method Mapper#wrap + * @param {Object|Object[]} data The record or records to be wrapped. + * @param {object} [opts] Configuration options. Passed to {@link Mapper#createRecord}. + * @returns {Record|Record[]} The wrapped record or records. + * @since 3.0.0 + */ + wrap(data, opts) { + return this.createRecord(data, opts); + } + /** + * @ignore + */ + defineRelations() { + // Setup the mapper's relations, including generating Mapper#relationList + // and Mapper#relationFields + utils.forOwn(this.relations, (group, type) => { + utils.forOwn(group, (relations, _name) => { + if (utils.isObject(relations)) { + relations = [relations]; + } + relations.forEach(def => { + const relatedMapper = this.datastore.getMapperByName(_name) || _name; + def.getRelation = () => this.datastore.getMapper(_name); + if (typeof Relation[type] !== 'function') { + throw utils.err(DOMAIN$6, 'defineRelations')(400, 'relation type (hasOne, hasMany, etc)', type, true); + } + this[type](relatedMapper, def); + }); + }); + }); + } +} +/** + * Create a subclass of this Mapper: + * + * @example Mapper.extend + * const JSData = require('js-data'); + * const { Mapper } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * // Extend the class using ES2015 class syntax. + * class CustomMapperClass extends Mapper { + * foo () { return 'bar'; } + * static beep () { return 'boop'; } + * }; + * const customMapper = new CustomMapperClass(); + * console.log(customMapper.foo()); + * console.log(CustomMapperClass.beep()); + * + * // Extend the class using alternate method. + * const OtherMapperClass = Mapper.extend({ + * foo () { return 'bar'; } + * }, { + * beep () { return 'boop'; } + * }); + * const otherMapper = new OtherMapperClass(); + * console.log(otherMapper.foo()); + * console.log(OtherMapperClass.beep()); + * + * // Extend the class, providing a custom constructor. + * function AnotherMapperClass () { + * Mapper.call(this); + * this.created_at = new Date().getTime(); + * } + * Mapper.extend({ + * constructor: AnotherMapperClass, + * foo () { return 'bar'; } + * }, { + * beep () { return 'boop'; } + * }) + * const anotherMapper = new AnotherMapperClass(); + * console.log(anotherMapper.created_at); + * console.log(anotherMapper.foo()); + * console.log(AnotherMapperClass.beep()); + * + * @method Mapper.extend + * @param {object} [props={}] Properties to add to the prototype of the + * subclass. + * @param {object} [props.constructor] Provide a custom constructor function + * to be used as the subclass itself. + * @param {object} [classProps={}] Static properties to add to the subclass. + * @returns {Constructor} Subclass of this Mapper class. + * @since 3.0.0 */ -/** - * Remove an event listener from this Component. If no listener is provided, - * then all listeners for the specified event will be removed. If no event is - * specified then all listeners for all events will be removed. - * - * @example - * // Remove a particular listener for a particular event - * collection.off('add', handler); - * - * @example - * // Remove all listeners for a particular event - * record.off('change'); - * - * @example - * // Remove all listeners to all events - * store.off(); - * - * @method Component#off - * @param {string} [event] Name of event to unsubsribe to. - * @param {Function} [listener] Listener to remove. - * @since 3.0.0 - */ +const DOMAIN$7 = 'Container'; +const proxiedMapperMethods = [ + 'count', + 'create', + 'createMany', + 'createRecord', + 'destroy', + 'destroyAll', + 'find', + 'findAll', + 'getSchema', + 'is', + 'sum', + 'toJSON', + 'update', + 'updateAll', + 'updateMany', + 'validate' +]; +/** + * The `Container` class is a place to define and store {@link Mapper} instances. + * + * `Container` makes it easy to manage your Mappers. Without a container, you + * need to manage Mappers yourself, including resolving circular dependencies + * among relations. All Mappers in a container share the same adapters, so you + * don't have to register adapters for every single Mapper. + * + * @example Container#constructor + * // import { Container } from 'js-data'; + * const JSData = require('js-data'); + * const {Container} = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new Container(); + * + * @class Container + * @extends Component + * @param {object} [opts] Configuration options. + * @param {boolean} [opts.debug=false] See {@link Component#debug}. + * @param {Constructor} [opts.mapperClass] See {@link Container#mapperClass}. + * @param {object} [opts.mapperDefaults] See {@link Container#mapperDefaults}. + * @since 3.0.0 + */ +class Container extends Component { + constructor(opts = {}) { + super(); + Object.defineProperties(this, { + /** + * The adapters registered with this Container, which are also shared by all + * Mappers in this Container. + * + * @name Container#_adapters + * @see Container#registerAdapter + * @since 3.0.0 + * @type {Object} + */ + _adapters: { + value: {} + }, + /** + * The the mappers in this container + * + * @name Container#_mappers + * @see Mapper + * @since 3.0.0 + * @type {Object} + */ + _mappers: { + value: {} + }, + /** + * Constructor function to use in {@link Container#defineMapper} to create new + * {@link Mapper} instances. {@link Container#mapperClass} should extend + * {@link Mapper}. By default {@link Mapper} is used to instantiate Mappers. + * + * @example Container#mapperClass + * // import { Container, Mapper } from 'js-data'; + * const JSData = require('js-data'); + * const { Container, Mapper } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * class MyMapperClass extends Mapper { + * foo () { return 'bar' } + * } + * const store = new Container({ + * mapperClass: MyMapperClass + * }); + * store.defineMapper('user'); + * console.log(store.getMapper('user').foo()); + * + * @name Container#mapperClass + * @see Mapper + * @since 3.0.0 + * @type {Constructor} + */ + mapperClass: { + value: undefined, + writable: true + } + }); + // Apply options provided by the user + utils.fillIn(this, opts); + /** + * Defaults options to pass to {@link Container#mapperClass} when creating a + * new {@link Mapper}. + * + * @example Container#mapperDefaults + * // import { Container } from 'js-data'; + * const JSData = require('js-data'); + * const { Container } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new Container({ + * mapperDefaults: { + * idAttribute: '_id' + * } + * }); + * store.defineMapper('user'); + * console.log(store.getMapper('user').idAttribute); + * + * @default {} + * @name Container#mapperDefaults + * @since 3.0.0 + * @type {Object} + */ + this.mapperDefaults = this.mapperDefaults || {}; + // Use the Mapper class if the user didn't provide a mapperClass + this.mapperClass = this.mapperClass || Mapper; + } + /** + * Register a new event listener on this Container. + * + * Proxy for {@link Component#on}. If an event was emitted by a {@link Mapper} + * in the Container, then the name of the {@link Mapper} will be prepended to + * the arugments passed to the listener. + * + * @example Container#on + * // import { Container } from 'js-data'; + * const JSData = require('js-data'); + * const { Container } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new Container(); + * store.on('foo', function (...args) { console.log(args.join(':')) }); + * store.defineMapper('user'); + * store.emit('foo', 'arg1', 'arg2'); + * store.getMapper('user').emit('foo', 'arg1', 'arg2'); + * + * @method Container#on + * @param {string} event Name of event to subsribe to. + * @param {Function} listener Listener function to handle the event. + * @param {*} [ctx] Optional content in which to invoke the listener. + * @since 3.0.0 + */ + /** + * Used to bind to events emitted by mappers in this container. + * + * @method Container#_onMapperEvent + * @param {string} name Name of the mapper that emitted the event. + * @param {...*} [args] Args See {@link Mapper#emit}. + * @private + * @since 3.0.0 + */ + _onMapperEvent(name, ...args) { + const type = args.shift(); + this.emit(type, name, ...args); + } + /** + * Return a container scoped to a particular mapper. + * + * @example Container#as + * // import { Container } from 'js-data'; + * const JSData = require('js-data'); + * const { Container } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new Container(); + * const UserMapper = store.defineMapper('user'); + * const UserStore = store.as('user'); + * + * const user1 = store.createRecord('user', { name: 'John' }); + * const user2 = UserStore.createRecord({ name: 'John' }); + * const user3 = UserMapper.createRecord({ name: 'John' }); + * console.log(user1 === user2); + * console.log(user2 === user3); + * console.log(user1 === user3); + * + * @method Container#as + * @param {string} name Name of the {@link Mapper}. + * @returns {Object} A container scoped to a particular mapper. + * @since 3.0.0 + */ + as(name) { + const props = {}; + const original = this; + proxiedMapperMethods.forEach(method => { + props[method] = { + writable: true, + value(...args) { + return original[method](name, ...args); + } + }; + }); + props.getMapper = { + writable: true, + value() { + return original.getMapper(name); + } + }; + return Object.create(this, props); + } + /** + * Create a new mapper and register it in this container. + * + * @example Container#defineMapper + * // import { Container } from 'js-data'; + * const JSData = require('js-data'); + * const { Container } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new Container({ + * mapperDefaults: { foo: 'bar' } + * }); + * // Container#defineMapper returns a direct reference to the newly created + * // Mapper. + * const UserMapper = store.defineMapper('user'); + * console.log(UserMapper === store.getMapper('user')); + * console.log(UserMapper === store.as('user').getMapper()); + * console.log(UserMapper.foo); + * + * @method Container#defineMapper + * @param {string} name Name under which to register the new {@link Mapper}. + * {@link Mapper#name} will be set to this value. + * @param {object} [opts] Configuration options. Passed to + * {@link Container#mapperClass} when creating the new {@link Mapper}. + * @returns {Mapper} The newly created instance of {@link Mapper}. + * @see Container#as + * @since 3.0.0 + */ + defineMapper(name, opts) { + // For backwards compatibility with defineResource + if (utils.isObject(name)) { + opts = name; + name = opts.name; + } + if (!utils.isString(name)) { + throw utils.err(`${DOMAIN$7}#defineMapper`, 'name')(400, 'string', name); + } + // Default values for arguments + opts = opts || {}; + // Set Mapper#name + opts.name = name; + opts.relations = opts.relations || {}; + // Check if the user is overriding the datastore's default mapperClass + const mapperClass = opts.mapperClass || this.mapperClass; + delete opts.mapperClass; + // Apply the datastore's defaults to the options going into the mapper + utils.fillIn(opts, this.mapperDefaults); + // Instantiate a mapper + const mapper = (this._mappers[name] = new mapperClass(opts)); // eslint-disable-line + mapper.relations = mapper.relations || {}; + // Make sure the mapper's name is set + mapper.name = name; + // All mappers in this datastore will share adapters + mapper._adapters = this.getAdapters(); + mapper.datastore = this; + mapper.on('all', (...args) => this._onMapperEvent(name, ...args)); + mapper.defineRelations(); + return mapper; + } + defineResource(name, opts) { + console.warn('DEPRECATED: defineResource is deprecated, use defineMapper instead'); + return this.defineMapper(name, opts); + } + /** + * Return the registered adapter with the given name or the default adapter if + * no name is provided. + * + * @method Container#getAdapter + * @param {string} [name] The name of the adapter to retrieve. + * @returns {Adapter} The adapter. + * @since 3.0.0 + */ + getAdapter(name) { + const adapter = this.getAdapterName(name); + if (!adapter) { + throw utils.err(`${DOMAIN$7}#getAdapter`, 'name')(400, 'string', name); + } + return this.getAdapters()[adapter]; + } + /** + * Return the name of a registered adapter based on the given name or options, + * or the name of the default adapter if no name provided. + * + * @method Container#getAdapterName + * @param {(Object|string)} [opts] The name of an adapter or options, if any. + * @returns {string} The name of the adapter. + * @since 3.0.0 + */ + getAdapterName(opts = {}) { + if (utils.isString(opts)) { + opts = { adapter: opts }; + } + return opts.adapter || this.mapperDefaults.defaultAdapter; + } + /** + * Return the registered adapters of this container. + * + * @method Container#getAdapters + * @returns {Adapter} + * @since 3.0.0 + */ + getAdapters() { + return this._adapters; + } + /** + * Return the mapper registered under the specified name. + * + * @example Container#getMapper + * // import { Container } from 'js-data'; + * const JSData = require('js-data'); + * const { Container } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new Container(); + * // Container#defineMapper returns a direct reference to the newly created + * // Mapper. + * const UserMapper = store.defineMapper('user'); + * console.log(UserMapper === store.getMapper('user')); + * console.log(UserMapper === store.as('user').getMapper()); + * store.getMapper('profile'); // throws Error, there is no mapper with name "profile" + * + * @method Container#getMapper + * @param {string} name {@link Mapper#name}. + * @returns {Mapper} + * @since 3.0.0 + */ + getMapper(name) { + const mapper = this.getMapperByName(name); + if (!mapper) { + throw utils.err(`${DOMAIN$7}#getMapper`, name)(404, 'mapper'); + } + return mapper; + } + /** + * Return the mapper registered under the specified name. + * Doesn't throw error if mapper doesn't exist. + * + * @example Container#getMapperByName + * // import { Container } from 'js-data'; + * const JSData = require('js-data'); + * const { Container } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new Container(); + * // Container#defineMapper returns a direct reference to the newly created + * // Mapper. + * const UserMapper = store.defineMapper('user'); + * console.log(UserMapper === store.getMapper('user')); + * console.log(UserMapper === store.as('user').getMapper()); + * console.log(store.getMapper('profile')); // Does NOT throw an error + * + * @method Container#getMapperByName + * @param {string} name {@link Mapper#name}. + * @returns {Mapper} + * @since 3.0.0 + */ + getMapperByName(name) { + return this._mappers[name]; + } + /** + * Register an adapter on this container under the given name. Adapters + * registered on a container are shared by all mappers in the container. + * + * @example + * import { Container } from 'js-data'; + * import { RethinkDBAdapter } from 'js-data-rethinkdb'; + * const store = new Container(); + * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); + * + * @method Container#registerAdapter + * @param {string} name The name of the adapter to register. + * @param {Adapter} adapter The adapter to register. + * @param {object} [opts] Configuration options. + * @param {boolean} [opts.default=false] Whether to make the adapter the + * default adapter for all Mappers in this container. + * @since 3.0.0 + * @tutorial ["http://www.js-data.io/v3.0/docs/connecting-to-a-data-source","Connecting to a data source"] + */ + registerAdapter(name, adapter, opts = {}) { + this.getAdapters()[name] = adapter; + // Optionally make it the default adapter for the target. + if (opts === true || opts.default) { + this.mapperDefaults.defaultAdapter = name; + utils.forOwn(this._mappers, mapper => { + mapper.defaultAdapter = name; + }); + } + } + /** + * Wrapper for {@link Mapper#count}. + * + * @example + * // Get the number of published blog posts + * import { Container } from 'js-data'; + * import RethinkDBAdapter from 'js-data-rethinkdb'; + * const store = new Container(); + * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); + * store.defineMapper('post'); + * + * store.count('post', { status: 'published' }).then((numPublished) => { + * console.log(numPublished); // e.g. 45 + * }); + * + * @method Container#count + * @param {string} name Name of the {@link Mapper} to target. + * @param {object} [query] See {@link Mapper#count}. + * @param {object} [opts] See {@link Mapper#count}. + * @returns {Promise} See {@link Mapper#count}. + * @see Mapper#count + * @since 3.0.0 + */ + count(name, query, opts) { + return this.getMapper(name).count(query, opts); + } + /** + * Fired during {@link Container#create}. See + * {@link Container~beforeCreateListener} for how to listen for this event. + * + * @event Container#beforeCreate + * @see Container~beforeCreateListener + * @see Container#create + */ + /** + * Callback signature for the {@link Container#event:beforeCreate} event. + * + * @example + * function onBeforeCreate (mapperName, props, opts) { + * // do something + * } + * store.on('beforeCreate', onBeforeCreate); + * + * @callback Container~beforeCreateListener + * @param {string} name The `name` argument received by {@link Mapper#beforeCreate}. + * @param {object} props The `props` argument received by {@link Mapper#beforeCreate}. + * @param {object} opts The `opts` argument received by {@link Mapper#beforeCreate}. + * @see Container#event:beforeCreate + * @see Container#create + * @since 3.0.0 + */ + /** + * Fired during {@link Container#create}. See + * {@link Container~afterCreateListener} for how to listen for this event. + * + * @event Container#afterCreate + * @see Container~afterCreateListener + * @see Container#create + */ + /** + * Callback signature for the {@link Container#event:afterCreate} event. + * + * @example + * function onAfterCreate (mapperName, props, opts, result) { + * // do something + * } + * store.on('afterCreate', onAfterCreate); + * + * @callback Container~afterCreateListener + * @param {string} name The `name` argument received by {@link Mapper#afterCreate}. + * @param {object} props The `props` argument received by {@link Mapper#afterCreate}. + * @param {object} opts The `opts` argument received by {@link Mapper#afterCreate}. + * @param {object} result The `result` argument received by {@link Mapper#afterCreate}. + * @see Container#event:afterCreate + * @see Container#create + * @since 3.0.0 + */ + /** + * Wrapper for {@link Mapper#create}. + * + * @example + * // Create and save a new blog post + * import { Container } from 'js-data'; + * import RethinkDBAdapter from 'js-data-rethinkdb'; + * const store = new Container(); + * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); + * store.defineMapper('post'); + * + * store.create('post', { + * title: 'Modeling your data', + * status: 'draft' + * }).then((post) => { + * console.log(post); // { id: 1234, status: 'draft', ... } + * }); + * + * @fires Container#beforeCreate + * @fires Container#afterCreate + * @method Container#create + * @param {string} name Name of the {@link Mapper} to target. + * @param {object} props See {@link Mapper#create}. + * @param {object} [opts] See {@link Mapper#create}. + * @returns {Promise} See {@link Mapper#create}. + * @see Mapper#create + * @since 3.0.0 + */ + create(name, props, opts) { + return this.getMapper(name).create(props, opts); + } + /** + * Fired during {@link Container#createMany}. See + * {@link Container~beforeCreateManyListener} for how to listen for this event. + * + * @event Container#beforeCreateMany + * @see Container~beforeCreateManyListener + * @see Container#createMany + */ + /** + * Callback signature for the {@link Container#event:beforeCreateMany} event. + * + * @example + * function onBeforeCreateMany (mapperName, records, opts) { + * // do something + * } + * store.on('beforeCreateMany', onBeforeCreateMany); + * + * @callback Container~beforeCreateManyListener + * @param {string} name The `name` argument received by {@link Mapper#beforeCreateMany}. + * @param {object} records The `records` argument received by {@link Mapper#beforeCreateMany}. + * @param {object} opts The `opts` argument received by {@link Mapper#beforeCreateMany}. + * @see Container#event:beforeCreateMany + * @see Container#createMany + * @since 3.0.0 + */ + /** + * Fired during {@link Container#createMany}. See + * {@link Container~afterCreateManyListener} for how to listen for this event. + * + * @event Container#afterCreateMany + * @see Container~afterCreateManyListener + * @see Container#createMany + */ + /** + * Callback signature for the {@link Container#event:afterCreateMany} event. + * + * @example + * function onAfterCreateMany (mapperName, records, opts, result) { + * // do something + * } + * store.on('afterCreateMany', onAfterCreateMany); + * + * @callback Container~afterCreateManyListener + * @param {string} name The `name` argument received by {@link Mapper#afterCreateMany}. + * @param {object} records The `records` argument received by {@link Mapper#afterCreateMany}. + * @param {object} opts The `opts` argument received by {@link Mapper#afterCreateMany}. + * @param {object} result The `result` argument received by {@link Mapper#afterCreateMany}. + * @see Container#event:afterCreateMany + * @see Container#createMany + * @since 3.0.0 + */ + /** + * Wrapper for {@link Mapper#createMany}. + * + * @example + * // Create and save several new blog posts + * import { Container } from 'js-data'; + * import RethinkDBAdapter from 'js-data-rethinkdb'; + * const store = new Container(); + * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); + * store.defineMapper('post'); + * + * store.createMany('post', [{ + * title: 'Modeling your data', + * status: 'draft' + * }, { + * title: 'Reading data', + * status: 'draft' + * }]).then((posts) => { + * console.log(posts[0]); // { id: 1234, status: 'draft', ... } + * console.log(posts[1]); // { id: 1235, status: 'draft', ... } + * }); + * + * @fires Container#beforeCreateMany + * @fires Container#afterCreateMany + * @method Container#createMany + * @param {string} name Name of the {@link Mapper} to target. + * @param {Record[]} records See {@link Mapper#createMany}. + * @param {object} [opts] See {@link Mapper#createMany}. + * @returns {Promise} See {@link Mapper#createMany}. + * @see Mapper#createMany + * @since 3.0.0 + */ + createMany(name, records, opts) { + return this.getMapper(name).createMany(records, opts); + } + /** + * Wrapper for {@link Mapper#createRecord}. + * + * __Note:__ This method does __not__ interact with any adapter, and does + * __not__ save any data. It only creates new objects in memory. + * + * @example + * // Create empty unsaved record instance + * import { Container } from 'js-data'; + * const store = new Container(); + * store.defineMapper('post'); + * const post = PostMapper.createRecord(); + * + * @method Container#createRecord + * @param {string} name Name of the {@link Mapper} to target. + * @param {Object|Object[]} props See {@link Mapper#createRecord}. + * @param {object} [opts] See {@link Mapper#createRecord}. + * @returns {Promise} See {@link Mapper#createRecord}. + * @see Mapper#createRecord + * @since 3.0.0 + */ + createRecord(name, props, opts) { + return this.getMapper(name).createRecord(props, opts); + } + /** + * Fired during {@link Container#destroy}. See + * {@link Container~beforeDestroyListener} for how to listen for this event. + * + * @event Container#beforeDestroy + * @see Container~beforeDestroyListener + * @see Container#destroy + */ + /** + * Callback signature for the {@link Container#event:beforeDestroy} event. + * + * @example + * function onBeforeDestroy (mapperName, id, opts) { + * // do something + * } + * store.on('beforeDestroy', onBeforeDestroy); + * + * @callback Container~beforeDestroyListener + * @param {string} name The `name` argument received by {@link Mapper#beforeDestroy}. + * @param {string|number} id The `id` argument received by {@link Mapper#beforeDestroy}. + * @param {object} opts The `opts` argument received by {@link Mapper#beforeDestroy}. + * @see Container#event:beforeDestroy + * @see Container#destroy + * @since 3.0.0 + */ + /** + * Fired during {@link Container#destroy}. See + * {@link Container~afterDestroyListener} for how to listen for this event. + * + * @event Container#afterDestroy + * @see Container~afterDestroyListener + * @see Container#destroy + */ + /** + * Callback signature for the {@link Container#event:afterDestroy} event. + * + * @example + * function onAfterDestroy (mapperName, id, opts, result) { + * // do something + * } + * store.on('afterDestroy', onAfterDestroy); + * + * @callback Container~afterDestroyListener + * @param {string} name The `name` argument received by {@link Mapper#afterDestroy}. + * @param {string|number} id The `id` argument received by {@link Mapper#afterDestroy}. + * @param {object} opts The `opts` argument received by {@link Mapper#afterDestroy}. + * @param {object} result The `result` argument received by {@link Mapper#afterDestroy}. + * @see Container#event:afterDestroy + * @see Container#destroy + * @since 3.0.0 + */ + /** + * Wrapper for {@link Mapper#destroy}. + * + * @example + * // Destroy a specific blog post + * import { Container } from 'js-data'; + * import RethinkDBAdapter from 'js-data-rethinkdb'; + * const store = new Container(); + * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); + * store.defineMapper('post'); + * + * store.destroy('post', 1234).then(() => { + * // Blog post #1234 has been destroyed + * }); + * + * @fires Container#beforeDestroy + * @fires Container#afterDestroy + * @method Container#destroy + * @param {string} name Name of the {@link Mapper} to target. + * @param {(string|number)} id See {@link Mapper#destroy}. + * @param {object} [opts] See {@link Mapper#destroy}. + * @returns {Promise} See {@link Mapper#destroy}. + * @see Mapper#destroy + * @since 3.0.0 + */ + destroy(name, id, opts) { + return this.getMapper(name).destroy(id, opts); + } + /** + * Fired during {@link Container#destroyAll}. See + * {@link Container~beforeDestroyAllListener} for how to listen for this event. + * + * @event Container#beforeDestroyAll + * @see Container~beforeDestroyAllListener + * @see Container#destroyAll + */ + /** + * Callback signature for the {@link Container#event:beforeDestroyAll} event. + * + * @example + * function onBeforeDestroyAll (mapperName, query, opts) { + * // do something + * } + * store.on('beforeDestroyAll', onBeforeDestroyAll); + * + * @callback Container~beforeDestroyAllListener + * @param {string} name The `name` argument received by {@link Mapper#beforeDestroyAll}. + * @param {object} query The `query` argument received by {@link Mapper#beforeDestroyAll}. + * @param {object} opts The `opts` argument received by {@link Mapper#beforeDestroyAll}. + * @see Container#event:beforeDestroyAll + * @see Container#destroyAll + * @since 3.0.0 + */ + /** + * Fired during {@link Container#destroyAll}. See + * {@link Container~afterDestroyAllListener} for how to listen for this event. + * + * @event Container#afterDestroyAll + * @see Container~afterDestroyAllListener + * @see Container#destroyAll + */ + /** + * Callback signature for the {@link Container#event:afterDestroyAll} event. + * + * @example + * function onAfterDestroyAll (mapperName, query, opts, result) { + * // do something + * } + * store.on('afterDestroyAll', onAfterDestroyAll); + * + * @callback Container~afterDestroyAllListener + * @param {string} name The `name` argument received by {@link Mapper#afterDestroyAll}. + * @param {object} query The `query` argument received by {@link Mapper#afterDestroyAll}. + * @param {object} opts The `opts` argument received by {@link Mapper#afterDestroyAll}. + * @param {object} result The `result` argument received by {@link Mapper#afterDestroyAll}. + * @see Container#event:afterDestroyAll + * @see Container#destroyAll + * @since 3.0.0 + */ + /** + * Wrapper for {@link Mapper#destroyAll}. + * + * @example + * // Destroy all "draft" blog posts + * import { Container } from 'js-data'; + * import RethinkDBAdapter from 'js-data-rethinkdb'; + * const store = new Container(); + * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); + * store.defineMapper('post'); + * + * store.destroyAll('post', { status: 'draft' }).then(() => { + * // All "draft" blog posts have been destroyed + * }); + * + * @fires Container#beforeDestroyAll + * @fires Container#afterDestroyAll + * @method Container#destroyAll + * @param {string} name Name of the {@link Mapper} to target. + * @param {object} [query] See {@link Mapper#destroyAll}. + * @param {object} [opts] See {@link Mapper#destroyAll}. + * @returns {Promise} See {@link Mapper#destroyAll}. + * @see Mapper#destroyAll + * @since 3.0.0 + */ + destroyAll(name, query, opts) { + return this.getMapper(name).destroyAll(query, opts); + } + /** + * Fired during {@link Container#find}. See + * {@link Container~beforeFindListener} for how to listen for this event. + * + * @event Container#beforeFind + * @see Container~beforeFindListener + * @see Container#find + */ + /** + * Callback signature for the {@link Container#event:beforeFind} event. + * + * @example + * function onBeforeFind (mapperName, id, opts) { + * // do something + * } + * store.on('beforeFind', onBeforeFind); + * + * @callback Container~beforeFindListener + * @param {string} name The `name` argument received by {@link Mapper#beforeFind}. + * @param {string|number} id The `id` argument received by {@link Mapper#beforeFind}. + * @param {object} opts The `opts` argument received by {@link Mapper#beforeFind}. + * @see Container#event:beforeFind + * @see Container#find + * @since 3.0.0 + */ + /** + * Fired during {@link Container#find}. See + * {@link Container~afterFindListener} for how to listen for this event. + * + * @event Container#afterFind + * @see Container~afterFindListener + * @see Container#find + */ + /** + * Callback signature for the {@link Container#event:afterFind} event. + * + * @example + * function onAfterFind (mapperName, id, opts, result) { + * // do something + * } + * store.on('afterFind', onAfterFind); + * + * @callback Container~afterFindListener + * @param {string} name The `name` argument received by {@link Mapper#afterFind}. + * @param {string|number} id The `id` argument received by {@link Mapper#afterFind}. + * @param {object} opts The `opts` argument received by {@link Mapper#afterFind}. + * @param {object} result The `result` argument received by {@link Mapper#afterFind}. + * @see Container#event:afterFind + * @see Container#find + * @since 3.0.0 + */ + /** + * Wrapper for {@link Mapper#find}. + * + * @example + * import { Container } from 'js-data'; + * import RethinkDBAdapter from 'js-data-rethinkdb'; + * const store = new Container(); + * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); + * store.defineMapper('post'); + * + * store.find('post', 1).then((post) => { + * console.log(post) // { id: 1, ...} + * }); + * + * @fires Container#beforeFind + * @fires Container#afterFind + * @method Container#find + * @param {string} name Name of the {@link Mapper} to target. + * @param {(string|number)} id See {@link Mapper#find}. + * @param {object} [opts] See {@link Mapper#find}. + * @returns {Promise} See {@link Mapper#find}. + * @see Mapper#find + * @since 3.0.0 + */ + find(name, id, opts) { + return this.getMapper(name).find(id, opts); + } + /** + * Fired during {@link Container#findAll}. See + * {@link Container~beforeFindAllListener} for how to listen for this event. + * + * @event Container#beforeFindAll + * @see Container~beforeFindAllListener + * @see Container#findAll + */ + /** + * Callback signature for the {@link Container#event:beforeFindAll} event. + * + * @example + * function onBeforeFindAll (mapperName, query, opts) { + * // do something + * } + * store.on('beforeFindAll', onBeforeFindAll); + * + * @callback Container~beforeFindAllListener + * @param {string} name The `name` argument received by {@link Mapper#beforeFindAll}. + * @param {object} query The `query` argument received by {@link Mapper#beforeFindAll}. + * @param {object} opts The `opts` argument received by {@link Mapper#beforeFindAll}. + * @see Container#event:beforeFindAll + * @see Container#findAll + * @since 3.0.0 + */ + /** + * Fired during {@link Container#findAll}. See + * {@link Container~afterFindAllListener} for how to listen for this event. + * + * @event Container#afterFindAll + * @see Container~afterFindAllListener + * @see Container#findAll + */ + /** + * Callback signature for the {@link Container#event:afterFindAll} event. + * + * @example + * function onAfterFindAll (mapperName, query, opts, result) { + * // do something + * } + * store.on('afterFindAll', onAfterFindAll); + * + * @callback Container~afterFindAllListener + * @param {string} name The `name` argument received by {@link Mapper#afterFindAll}. + * @param {object} query The `query` argument received by {@link Mapper#afterFindAll}. + * @param {object} opts The `opts` argument received by {@link Mapper#afterFindAll}. + * @param {object} result The `result` argument received by {@link Mapper#afterFindAll}. + * @see Container#event:afterFindAll + * @see Container#findAll + * @since 3.0.0 + */ + /** + * Wrapper for {@link Mapper#createRecord}. + * + * @example + * // Find all "published" blog posts + * import { Container } from 'js-data'; + * import RethinkDBAdapter from 'js-data-rethinkdb'; + * const store = new Container(); + * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); + * store.defineMapper('post'); + * + * store.findAll('post', { status: 'published' }).then((posts) => { + * console.log(posts); // [{ id: 1, ...}, ...] + * }); + * + * @fires Container#beforeFindAll + * @fires Container#afterFindAll + * @method Container#findAll + * @param {string} name Name of the {@link Mapper} to target. + * @param {object} [query] See {@link Mapper#findAll}. + * @param {object} [opts] See {@link Mapper#findAll}. + * @returns {Promise} See {@link Mapper#findAll}. + * @see Mapper#findAll + * @since 3.0.0 + */ + findAll(name, query, opts) { + return this.getMapper(name).findAll(query, opts); + } + /** + * Wrapper for {@link Mapper#getSchema}. + * + * @method Container#getSchema + * @param {string} name Name of the {@link Mapper} to target. + * @returns {Schema} See {@link Mapper#getSchema}. + * @see Mapper#getSchema + * @since 3.0.0 + */ + getSchema(name) { + return this.getMapper(name).getSchema(); + } + /** + * Wrapper for {@link Mapper#is}. + * + * @example + * import { Container } from 'js-data'; + * const store = new Container(); + * store.defineMapper('post'); + * const post = store.createRecord(); + * + * console.log(store.is('post', post)); // true + * // Equivalent to what's above + * console.log(post instanceof store.getMapper('post').recordClass); // true + * + * @method Container#is + * @param {string} name Name of the {@link Mapper} to target. + * @param {Object|Record} record See {@link Mapper#is}. + * @returns {boolean} See {@link Mapper#is}. + * @see Mapper#is + * @since 3.0.0 + */ + is(name, record) { + return this.getMapper(name).is(record); + } + /** + * Wrapper for {@link Mapper#sum}. + * + * @example + * import { Container } from 'js-data'; + * import RethinkDBAdapter from 'js-data-rethinkdb'; + * const store = new Container(); + * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); + * store.defineMapper('purchase_order'); + * + * store.sum('purchase_order', 'amount', { status: 'paid' }).then((amountPaid) => { + * console.log(amountPaid); // e.g. 451125.34 + * }); + * + * @method Container#sum + * @param {string} name Name of the {@link Mapper} to target. + * @param {string} field See {@link Mapper#sum}. + * @param {object} [query] See {@link Mapper#sum}. + * @param {object} [opts] See {@link Mapper#sum}. + * @returns {Promise} See {@link Mapper#sum}. + * @see Mapper#sum + * @since 3.0.0 + */ + sum(name, field, query, opts) { + return this.getMapper(name).sum(field, query, opts); + } + /** + * Wrapper for {@link Mapper#toJSON}. + * + * @example + * import { Container } from 'js-data'; + * import RethinkDBAdapter from 'js-data-rethinkdb'; + * const store = new Container(); + * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); + * store.defineMapper('person', { + * schema: { + * properties: { + * name: { type: 'string' }, + * id: { type: 'string' } + * } + * } + * }); + * const person = store.createRecord('person', { id: 1, name: 'John', foo: 'bar' }); + * // "foo" is stripped by toJSON() + * console.log(store.toJSON('person', person)); // {"id":1,"name":"John"} + * + * store.defineMapper('personRelaxed', { + * schema: { + * properties: { + * name: { type: 'string' }, + * id: { type: 'string' } + * }, + * additionalProperties: true + * } + * }); + * const person2 = store.createRecord('personRelaxed', { id: 1, name: 'John', foo: 'bar' }); + * // "foo" is not stripped by toJSON + * console.log(store.toJSON('personRelaxed', person2)); // {"id":1,"name":"John","foo":"bar"} + * + * @method Container#toJSON + * @param {string} name Name of the {@link Mapper} to target. + * @param {Record|Record[]} records See {@link Mapper#toJSON}. + * @param {object} [opts] See {@link Mapper#toJSON}. + * @returns {Object|Object[]} See {@link Mapper#toJSON}. + * @see Mapper#toJSON + * @since 3.0.0 + */ + toJSON(name, records, opts) { + return this.getMapper(name).toJSON(records, opts); + } + /** + * Fired during {@link Container#update}. See + * {@link Container~beforeUpdateListener} for how to listen for this event. + * + * @event Container#beforeUpdate + * @see Container~beforeUpdateListener + * @see Container#update + */ + /** + * Callback signature for the {@link Container#event:beforeUpdate} event. + * + * @example + * function onBeforeUpdate (mapperName, id, props, opts) { + * // do something + * } + * store.on('beforeUpdate', onBeforeUpdate); + * + * @callback Container~beforeUpdateListener + * @param {string} name The `name` argument received by {@link Mapper#beforeUpdate}. + * @param {string|number} id The `id` argument received by {@link Mapper#beforeUpdate}. + * @param {object} props The `props` argument received by {@link Mapper#beforeUpdate}. + * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdate}. + * @see Container#event:beforeUpdate + * @see Container#update + * @since 3.0.0 + */ + /** + * Fired during {@link Container#update}. See + * {@link Container~afterUpdateListener} for how to listen for this event. + * + * @event Container#afterUpdate + * @see Container~afterUpdateListener + * @see Container#update + */ + /** + * Callback signature for the {@link Container#event:afterUpdate} event. + * + * @example + * function onAfterUpdate (mapperName, id, props, opts, result) { + * // do something + * } + * store.on('afterUpdate', onAfterUpdate); + * + * @callback Container~afterUpdateListener + * @param {string} name The `name` argument received by {@link Mapper#afterUpdate}. + * @param {string|number} id The `id` argument received by {@link Mapper#afterUpdate}. + * @param {object} props The `props` argument received by {@link Mapper#afterUpdate}. + * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdate}. + * @param {object} result The `result` argument received by {@link Mapper#afterUpdate}. + * @see Container#event:afterUpdate + * @see Container#update + * @since 3.0.0 + */ + /** + * Wrapper for {@link Mapper#update}. + * + * @example + * import { Container } from 'js-data'; + * import RethinkDBAdapter from 'js-data-rethinkdb'; + * const store = new Container(); + * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); + * store.defineMapper('post'); + * + * store.update('post', 1234, { + * status: 'published', + * published_at: new Date() + * }).then((post) => { + * console.log(post); // { id: 1234, status: 'published', ... } + * }); + * + * @fires Container#beforeUpdate + * @fires Container#afterUpdate + * @method Container#update + * @param {string} name Name of the {@link Mapper} to target. + * @param {(string|number)} id See {@link Mapper#update}. + * @param {object} props See {@link Mapper#update}. + * @param {object} [opts] See {@link Mapper#update}. + * @returns {Promise} See {@link Mapper#update}. + * @see Mapper#update + * @since 3.0.0 + * @tutorial ["http://www.js-data.io/v3.0/docs/saving-data","Saving data"] + */ + update(name, id, props, opts) { + return this.getMapper(name).update(id, props, opts); + } + /** + * Fired during {@link Container#updateAll}. See + * {@link Container~beforeUpdateAllListener} for how to listen for this event. + * + * @event Container#beforeUpdateAll + * @see Container~beforeUpdateAllListener + * @see Container#updateAll + */ + /** + * Callback signature for the {@link Container#event:beforeUpdateAll} event. + * + * @example + * function onBeforeUpdateAll (mapperName, props, query, opts) { + * // do something + * } + * store.on('beforeUpdateAll', onBeforeUpdateAll); + * + * @callback Container~beforeUpdateAllListener + * @param {string} name The `name` argument received by {@link Mapper#beforeUpdateAll}. + * @param {object} props The `props` argument received by {@link Mapper#beforeUpdateAll}. + * @param {object} query The `query` argument received by {@link Mapper#beforeUpdateAll}. + * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdateAll}. + * @see Container#event:beforeUpdateAll + * @see Container#updateAll + * @since 3.0.0 + */ + /** + * Fired during {@link Container#updateAll}. See + * {@link Container~afterUpdateAllListener} for how to listen for this event. + * + * @event Container#afterUpdateAll + * @see Container~afterUpdateAllListener + * @see Container#updateAll + */ + /** + * Callback signature for the {@link Container#event:afterUpdateAll} event. + * + * @example + * function onAfterUpdateAll (mapperName, props, query, opts, result) { + * // do something + * } + * store.on('afterUpdateAll', onAfterUpdateAll); + * + * @callback Container~afterUpdateAllListener + * @param {string} name The `name` argument received by {@link Mapper#afterUpdateAll}. + * @param {object} props The `props` argument received by {@link Mapper#afterUpdateAll}. + * @param {object} query The `query` argument received by {@link Mapper#afterUpdateAll}. + * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdateAll}. + * @param {object} result The `result` argument received by {@link Mapper#afterUpdateAll}. + * @see Container#event:afterUpdateAll + * @see Container#updateAll + * @since 3.0.0 + */ + /** + * Wrapper for {@link Mapper#updateAll}. + * + * @example + * // Turn all of John's blog posts into drafts. + * import { Container } from 'js-data'; + * import RethinkDBAdapter from 'js-data-rethinkdb'; + * const store = new Container(); + * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); + * store.defineMapper('post'); + * + * const update = { status: draft: published_at: null }; + * const query = { userId: 1234 }; + * store.updateAll('post', update, query).then((posts) => { + * console.log(posts); // [...] + * }); + * + * @fires Container#beforeUpdateAll + * @fires Container#afterUpdateAll + * @method Container#updateAll + * @param {string} name Name of the {@link Mapper} to target. + * @param {object} props See {@link Mapper#updateAll}. + * @param {object} [query] See {@link Mapper#updateAll}. + * @param {object} [opts] See {@link Mapper#updateAll}. + * @returns {Promise} See {@link Mapper#updateAll}. + * @see Mapper#updateAll + * @since 3.0.0 + */ + updateAll(name, props, query, opts) { + return this.getMapper(name).updateAll(props, query, opts); + } + /** + * Fired during {@link Container#updateMany}. See + * {@link Container~beforeUpdateManyListener} for how to listen for this event. + * + * @event Container#beforeUpdateMany + * @see Container~beforeUpdateManyListener + * @see Container#updateMany + */ + /** + * Callback signature for the {@link Container#event:beforeUpdateMany} event. + * + * @example + * function onBeforeUpdateMany (mapperName, records, opts) { + * // do something + * } + * store.on('beforeUpdateMany', onBeforeUpdateMany); + * + * @callback Container~beforeUpdateManyListener + * @param {string} name The `name` argument received by {@link Mapper#beforeUpdateMany}. + * @param {object} records The `records` argument received by {@link Mapper#beforeUpdateMany}. + * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdateMany}. + * @see Container#event:beforeUpdateMany + * @see Container#updateMany + * @since 3.0.0 + */ + /** + * Fired during {@link Container#updateMany}. See + * {@link Container~afterUpdateManyListener} for how to listen for this event. + * + * @event Container#afterUpdateMany + * @see Container~afterUpdateManyListener + * @see Container#updateMany + */ + /** + * Callback signature for the {@link Container#event:afterUpdateMany} event. + * + * @example + * function onAfterUpdateMany (mapperName, records, opts, result) { + * // do something + * } + * store.on('afterUpdateMany', onAfterUpdateMany); + * + * @callback Container~afterUpdateManyListener + * @param {string} name The `name` argument received by {@link Mapper#afterUpdateMany}. + * @param {object} records The `records` argument received by {@link Mapper#afterUpdateMany}. + * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdateMany}. + * @param {object} result The `result` argument received by {@link Mapper#afterUpdateMany}. + * @see Container#event:afterUpdateMany + * @see Container#updateMany + * @since 3.0.0 + */ + /** + * Wrapper for {@link Mapper#updateMany}. + * + * @example + * import { Container } from 'js-data'; + * import RethinkDBAdapter from 'js-data-rethinkdb'; + * const store = new Container(); + * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); + * store.defineMapper('post'); + * + * store.updateMany('post', [ + * { id: 1234, status: 'draft' }, + * { id: 2468, status: 'published', published_at: new Date() } + * ]).then((posts) => { + * console.log(posts); // [...] + * }); + * + * @fires Container#beforeUpdateMany + * @fires Container#afterUpdateMany + * @method Container#updateMany + * @param {string} name Name of the {@link Mapper} to target. + * @param {(Object[]|Record[])} records See {@link Mapper#updateMany}. + * @param {object} [opts] See {@link Mapper#updateMany}. + * @returns {Promise} See {@link Mapper#updateMany}. + * @see Mapper#updateMany + * @since 3.0.0 + */ + updateMany(name, record, opts) { + return this.getMapper(name).updateMany(record, opts); + } + /** + * Wrapper for {@link Mapper#validate}. + * + * @example + * import { Container } from 'js-data'; + * const store = new Container(); + * store.defineMapper('post', { + * schema: { + * properties: { + * name: { type: 'string' }, + * id: { type: 'string' } + * } + * } + * }); + * let errors = store.validate('post', { name: 'John' }); + * console.log(errors); // undefined + * errors = store.validate('post', { name: 123 }); + * console.log(errors); // [{ expected: 'one of (string)', actual: 'number', path: 'name' }] + * + * @method Container#validate + * @param {string} name Name of the {@link Mapper} to target. + * @param {(Object[]|Record[])} records See {@link Mapper#validate}. + * @param {object} [opts] See {@link Mapper#validate}. + * @returns {Promise} See {@link Mapper#validate}. + * @see Mapper#validate + * @since 3.0.0 + */ + validate(name, record, opts) { + return this.getMapper(name).validate(record, opts); + } +} -/** - * Trigger an event on this Component. - * - * @example Component#emit - * // import { Collection, DataStore } from 'js-data'; - * const JSData = require('js-data'); - * const { Collection, DataStore } = JSData; - * - * const collection = new Collection(); - * collection.on('foo', function (msg) { - * console.log(msg); - * }); - * collection.emit('foo', 'bar'); - * - * const store = new DataStore(); - * store.on('beep', function (msg) { - * console.log(msg); - * }); - * store.emit('beep', 'boop'); - * - * @method Component#emit - * @param {string} event Name of event to emit. - * @param {...*} [args] Arguments to pass to any listeners. - * @since 3.0.0 +const DOMAIN$8 = 'SimpleStore'; +const proxiedCollectionMethods = [ + 'add', + 'between', + 'createIndex', + 'filter', + 'get', + 'getAll', + 'prune', + 'query', + 'toJSON', + 'unsaved' +]; +const ownMethodsForScoping = ['addToCache', 'cachedFind', 'cachedFindAll', 'cacheFind', 'cacheFindAll', 'hashQuery']; +const cachedFn = function (name, hashOrId, opts) { + const cached = this._completedQueries[name][hashOrId]; + if (utils.isFunction(cached)) { + return cached(name, hashOrId, opts); + } + return cached; +}; +const SIMPLESTORE_DEFAULTS = { + /** + * Whether to use the pending query if a `find` request for the specified + * record is currently underway. Can be set to `true`, `false`, or to a + * function that returns `true` or `false`. + * + * @default true + * @name SimpleStore#usePendingFind + * @since 3.0.0 + * @type {boolean|Function} + */ + usePendingFind: true, + /** + * Whether to use the pending query if a `findAll` request for the given query + * is currently underway. Can be set to `true`, `false`, or to a function that + * returns `true` or `false`. + * + * @default true + * @name SimpleStore#usePendingFindAll + * @since 3.0.0 + * @type {boolean|Function} + */ + usePendingFindAll: true +}; +/** + * The `SimpleStore` class is an extension of {@link Container}. Not only does + * `SimpleStore` manage mappers, but also collections. `SimpleStore` implements the + * asynchronous {@link Mapper} methods, such as {@link Mapper#find} and + * {@link Mapper#create}. If you use the asynchronous `SimpleStore` methods + * instead of calling them directly on the mappers, then the results of the + * method calls will be inserted into the store's collections. You can think of + * a `SimpleStore` as an [Identity Map](https://en.wikipedia.org/wiki/Identity_map_pattern) + * for the [ORM](https://en.wikipedia.org/wiki/Object-relational_mapping) + * (the Mappers). + * + * ```javascript + * import { SimpleStore } from 'js-data'; + * ``` + * + * @example + * import { SimpleStore } from 'js-data'; + * import { HttpAdapter } from 'js-data-http'; + * const store = new SimpleStore(); + * + * // SimpleStore#defineMapper returns a direct reference to the newly created + * // Mapper. + * const UserMapper = store.defineMapper('user'); + * + * // SimpleStore#as returns the store scoped to a particular Mapper. + * const UserStore = store.as('user'); + * + * // Call "find" on "UserMapper" (Stateless ORM) + * UserMapper.find(1).then((user) => { + * // retrieved a "user" record via the http adapter, but that's it + * + * // Call "find" on "store" targeting "user" (Stateful SimpleStore) + * return store.find('user', 1); // same as "UserStore.find(1)" + * }).then((user) => { + * // not only was a "user" record retrieved, but it was added to the + * // store's "user" collection + * const cachedUser = store.getCollection('user').get(1); + * console.log(user === cachedUser); // true + * }); + * + * @class SimpleStore + * @extends Container + * @param {object} [opts] Configuration options. See {@link Container}. + * @param {boolean} [opts.collectionClass={@link Collection}] See {@link SimpleStore#collectionClass}. + * @param {boolean} [opts.debug=false] See {@link Component#debug}. + * @param {boolean|Function} [opts.usePendingFind=true] See {@link SimpleStore#usePendingFind}. + * @param {boolean|Function} [opts.usePendingFindAll=true] See {@link SimpleStore#usePendingFindAll}. + * @returns {SimpleStore} + * @see Container + * @since 3.0.0 + * @tutorial ["http://www.js-data.io/v3.0/docs/components-of-jsdata#SimpleStore","Components of JSData: SimpleStore"] + * @tutorial ["http://www.js-data.io/v3.0/docs/working-with-the-SimpleStore","Working with the SimpleStore"] + * @tutorial ["http://www.js-data.io/v3.0/docs/jsdata-and-the-browser","Notes on using JSData in the Browser"] + */ +class SimpleStore extends Container { + constructor(opts = {}) { + super(Object.assign(Object.assign({}, SIMPLESTORE_DEFAULTS), opts)); + this._collections = {}; + this._completedQueries = {}; + this._pendingQueries = {}; + /** + * Retrieve a cached `find` result, if any. This method is called during + * {@link SimpleStore#find} to determine if {@link Mapper#find} needs to be + * called. If this method returns `undefined` then {@link Mapper#find} will + * be called. Otherwise {@link SimpleStore#find} will immediately resolve with + * the return value of this method. + * + * When using {@link SimpleStore} in the browser, you can override this method + * to implement your own cache-busting strategy. + * + * @example + * const store = new SimpleStore({ + * cachedFind (mapperName, id, opts) { + * // Let's say for a particular Resource, we always want to pull fresh from the server + * if (mapperName === 'schedule') { + * // Return undefined to trigger a Mapper#find call + * return; + * } + * // Otherwise perform default behavior + * return SimpleStore.prototype.cachedFind.call(this, mapperName, id, opts); + * } + * }); + * + * @example + * // Extend using ES2015 class syntax. + * class MyStore extends SimpleStore { + * cachedFind (mapperName, id, opts) { + * // Let's say for a particular Resource, we always want to pull fresh from the server + * if (mapperName === 'schedule') { + * // Return undefined to trigger a Mapper#find call + * return; + * } + * // Otherwise perform default behavior + * return super.cachedFind(mapperName, id, opts); + * } + * } + * const store = new MyStore(); + * + * @method SimpleStore#cachedFind + * @param {string} name The `name` argument passed to {@link SimpleStore#find}. + * @param {(string|number)} id The `id` argument passed to {@link SimpleStore#find}. + * @param {object} opts The `opts` argument passed to {@link SimpleStore#find}. + * @since 3.0.0 + */ + this.cachedFind = cachedFn; + /** + * Retrieve a cached `findAll` result, if any. This method is called during + * {@link SimpleStore#findAll} to determine if {@link Mapper#findAll} needs to be + * called. If this method returns `undefined` then {@link Mapper#findAll} will + * be called. Otherwise {@link SimpleStore#findAll} will immediately resolve with + * the return value of this method. + * + * When using {@link SimpleStore} in the browser, you can override this method + * to implement your own cache-busting strategy. + * + * @example + * const store = new SimpleStore({ + * cachedFindAll (mapperName, hash, opts) { + * // Let's say for a particular Resource, we always want to pull fresh from the server + * if (mapperName === 'schedule') { + * // Return undefined to trigger a Mapper#findAll call + * return undefined; + * } + * // Otherwise perform default behavior + * return SimpleStore.prototype.cachedFindAll.call(this, mapperName, hash, opts); + * } + * }); + * + * @example + * // Extend using ES2015 class syntax. + * class MyStore extends SimpleStore { + * cachedFindAll (mapperName, hash, opts) { + * // Let's say for a particular Resource, we always want to pull fresh from the server + * if (mapperName === 'schedule') { + * // Return undefined to trigger a Mapper#findAll call + * return undefined; + * } + * // Otherwise perform default behavior + * return super.cachedFindAll(mapperName, hash, opts); + * } + * } + * const store = new MyStore(); + * + * @method SimpleStore#cachedFindAll + * @param {string} name The `name` argument passed to {@link SimpleStore#findAll}. + * @param {string} hash The result of calling {@link SimpleStore#hashQuery} on + * the `query` argument passed to {@link SimpleStore#findAll}. + * @param {object} opts The `opts` argument passed to {@link SimpleStore#findAll}. + * @since 3.0.0 + */ + this.cachedFindAll = cachedFn; + this.collectionClass = this.collectionClass || Collection; + } + /** + * Internal method used to handle Mapper responses. + * + * @method SimpleStore#_end + * @private + * @param {string} name Name of the {@link Collection} to which to + * add the data. + * @param {object} result The result from a Mapper. + * @param {object} [opts] Configuration options. + * @returns {(Object|Array)} Result. + */ + _end(name, result, opts) { + let data = opts.raw ? result.data : result; + if (data && utils.isFunction(this.addToCache)) { + data = this.addToCache(name, data, opts); + if (opts.raw) { + result.data = data; + } + else { + result = data; + } + } + return result; + } + /** + * Register a new event listener on this SimpleStore. + * + * Proxy for {@link Container#on}. If an event was emitted by a Mapper or + * Collection in the SimpleStore, then the name of the Mapper or Collection will + * be prepended to the arugments passed to the provided event handler. + * + * @example + * // Listen for all "afterCreate" events in a SimpleStore + * store.on('afterCreate', (mapperName, props, opts, result) => { + * console.log(mapperName); // "post" + * console.log(props.id); // undefined + * console.log(result.id); // 1234 + * }); + * store.create('post', { title: 'Modeling your data' }).then((post) => { + * console.log(post.id); // 1234 + * }); + * + * @example + * // Listen for the "add" event on a collection + * store.on('add', (mapperName, records) => { + * console.log(records); // [...] + * }); + * + * @example + * // Listen for "change" events on a record + * store.on('change', (mapperName, record, changes) => { + * console.log(changes); // { changed: { title: 'Modeling your data' } } + * }); + * post.title = 'Modeling your data'; + * + * @method SimpleStore#on + * @param {string} event Name of event to subsribe to. + * @param {Function} listener Listener function to handle the event. + * @param {*} [ctx] Optional content in which to invoke the listener. + */ + /** + * Used to bind to events emitted by collections in this store. + * + * @method SimpleStore#_onCollectionEvent + * @private + * @param {string} name Name of the collection that emitted the event. + * @param {...*} [args] Args passed to {@link Collection#emit}. + */ + _onCollectionEvent(name, ...args) { + const type = args.shift(); + this.emit(type, name, ...args); + } + /** + * This method takes the data received from {@link SimpleStore#find}, + * {@link SimpleStore#findAll}, {@link SimpleStore#update}, etc., and adds the + * data to the store. _You don't need to call this method directly._ + * + * If you're using the http adapter and your response data is in an unexpected + * format, you may need to override this method so the right data gets added + * to the store. + * + * @example + * const store = new SimpleStore({ + * addToCache (mapperName, data, opts) { + * // Let's say for a particular Resource, response data is in a weird format + * if (name === 'comment') { + * // Re-assign the variable to add the correct records into the stores + * data = data.items; + * } + * // Now perform default behavior + * return SimpleStore.prototype.addToCache.call(this, mapperName, data, opts); + * } + * }); + * + * @example + * // Extend using ES2015 class syntax. + * class MyStore extends SimpleStore { + * addToCache (mapperName, data, opts) { + * // Let's say for a particular Resource, response data is in a weird format + * if (name === 'comment') { + * // Re-assign the variable to add the correct records into the stores + * data = data.items; + * } + * // Now perform default behavior + * return super.addToCache(mapperName, data, opts); + * } + * } + * const store = new MyStore(); + * + * @method SimpleStore#addToCache + * @param {string} name Name of the {@link Mapper} to target. + * @param {*} data Data from which data should be selected for add. + * @param {object} [opts] Configuration options. + */ + addToCache(name, data, opts) { + return this.getCollection(name).add(data, opts); + } + /** + * Return the store scoped to a particular mapper/collection pair. + * + * @example SimpleStore.as + * const JSData = require('js-data'); + * const { SimpleStore } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new SimpleStore(); + * const UserMapper = store.defineMapper('user'); + * const UserStore = store.as('user'); + * + * const user1 = store.createRecord('user', { name: 'John' }); + * const user2 = UserStore.createRecord({ name: 'John' }); + * const user3 = UserMapper.createRecord({ name: 'John' }); + * console.log(user1 === user2); + * console.log(user2 === user3); + * console.log(user1 === user3); + * + * @method SimpleStore#as + * @param {string} name Name of the {@link Mapper}. + * @returns {Object} The store, scoped to a particular Mapper/Collection pair. + * @since 3.0.0 + */ + as(name) { + const props = {}; + const original = this; + const methods = ownMethodsForScoping.concat(proxiedMapperMethods).concat(proxiedCollectionMethods); + methods.forEach(method => { + props[method] = { + writable: true, + value(...args) { + return original[method](name, ...args); + } + }; + }); + props.getMapper = { + writable: true, + value() { + return original.getMapper(name); + } + }; + props.getCollection = { + writable: true, + value() { + return original.getCollection(name); + } + }; + return Object.create(this, props); + } + /** + * Mark a {@link Mapper#find} result as cached by adding an entry to + * {@link SimpleStore#_completedQueries}. By default, once a `find` entry is + * added it means subsequent calls to the same Resource with the same `id` + * argument will immediately resolve with the result of calling + * {@link SimpleStore#get} instead of delegating to {@link Mapper#find}. + * + * As part of implementing your own caching strategy, you may choose to + * override this method. + * + * @example + * const store = new SimpleStore({ + * cacheFind (mapperName, data, id, opts) { + * // Let's say for a particular Resource, we always want to pull fresh from the server + * if (mapperName === 'schedule') { + * // Return without saving an entry to SimpleStore#_completedQueries + * return; + * } + * // Otherwise perform default behavior + * return SimpleStore.prototype.cacheFind.call(this, mapperName, data, id, opts); + * } + * }); + * + * @example + * // Extend using ES2015 class syntax. + * class MyStore extends SimpleStore { + * cacheFind (mapperName, data, id, opts) { + * // Let's say for a particular Resource, we always want to pull fresh from the server + * if (mapperName === 'schedule') { + * // Return without saving an entry to SimpleStore#_completedQueries + * return; + * } + * // Otherwise perform default behavior + * return super.cacheFind(mapperName, data, id, opts); + * } + * } + * const store = new MyStore(); + * + * @method SimpleStore#cacheFind + * @param {string} name The `name` argument passed to {@link SimpleStore#find}. + * @param {*} data The result to cache. + * @param {(string|number)} id The `id` argument passed to {@link SimpleStore#find}. + * @param {object} opts The `opts` argument passed to {@link SimpleStore#find}. + * @since 3.0.0 + */ + cacheFind(name, data, id, opts) { + this._completedQueries[name][id] = (name, id, opts) => this.get(name, id); + } + /** + * Mark a {@link Mapper#findAll} result as cached by adding an entry to + * {@link SimpleStore#_completedQueries}. By default, once a `findAll` entry is + * added it means subsequent calls to the same Resource with the same `query` + * argument will immediately resolve with the result of calling + * {@link SimpleStore#filter} instead of delegating to {@link Mapper#findAll}. + * + * As part of implementing your own caching strategy, you may choose to + * override this method. + * + * @example + * const store = new SimpleStore({ + * cachedFindAll (mapperName, data, hash, opts) { + * // Let's say for a particular Resource, we always want to pull fresh from the server + * if (mapperName === 'schedule') { + * // Return without saving an entry to SimpleStore#_completedQueries + * return; + * } + * // Otherwise perform default behavior. + * return SimpleStore.prototype.cachedFindAll.call(this, mapperName, data, hash, opts); + * } + * }); + * + * @example + * // Extend using ES2015 class syntax. + * class MyStore extends SimpleStore { + * cachedFindAll (mapperName, data, hash, opts) { + * // Let's say for a particular Resource, we always want to pull fresh from the server + * if (mapperName === 'schedule') { + * // Return without saving an entry to SimpleStore#_completedQueries + * return; + * } + * // Otherwise perform default behavior. + * return super.cachedFindAll(mapperName, data, hash, opts); + * } + * } + * const store = new MyStore(); + * + * @method SimpleStore#cacheFindAll + * @param {string} name The `name` argument passed to {@link SimpleStore#findAll}. + * @param {*} data The result to cache. + * @param {string} hash The result of calling {@link SimpleStore#hashQuery} on + * the `query` argument passed to {@link SimpleStore#findAll}. + * @param {object} opts The `opts` argument passed to {@link SimpleStore#findAll}. + * @since 3.0.0 + */ + cacheFindAll(name, data, hash, opts) { + this._completedQueries[name][hash] = (name, hash, opts) => this.filter(name, utils.fromJson(hash)); + } + /** + * Remove __all__ records from the in-memory store and reset + * {@link SimpleStore#_completedQueries}. + * + * @method SimpleStore#clear + * @returns {Object} Object containing all records that were in the store. + * @see SimpleStore#remove + * @see SimpleStore#removeAll + * @since 3.0.0 + */ + clear() { + const removed = {}; + utils.forOwn(this._collections, (collection, name) => { + removed[name] = collection.removeAll(); + this._completedQueries[name] = {}; + }); + return removed; + } + /** + * Fired during {@link SimpleStore#create}. See + * {@link SimpleStore~beforeCreateListener} for how to listen for this event. + * + * @event SimpleStore#beforeCreate + * @see SimpleStore~beforeCreateListener + * @see SimpleStore#create + */ + /** + * Callback signature for the {@link SimpleStore#event:beforeCreate} event. + * + * @example + * function onBeforeCreate (mapperName, props, opts) { + * // do something + * } + * store.on('beforeCreate', onBeforeCreate); + * + * @callback SimpleStore~beforeCreateListener + * @param {string} name The `name` argument received by {@link Mapper#beforeCreate}. + * @param {object} props The `props` argument received by {@link Mapper#beforeCreate}. + * @param {object} opts The `opts` argument received by {@link Mapper#beforeCreate}. + * @see SimpleStore#event:beforeCreate + * @see SimpleStore#create + * @since 3.0.0 + */ + /** + * Fired during {@link SimpleStore#create}. See + * {@link SimpleStore~afterCreateListener} for how to listen for this event. + * + * @event SimpleStore#afterCreate + * @see SimpleStore~afterCreateListener + * @see SimpleStore#create + */ + /** + * Callback signature for the {@link SimpleStore#event:afterCreate} event. + * + * @example + * function onAfterCreate (mapperName, props, opts, result) { + * // do something + * } + * store.on('afterCreate', onAfterCreate); + * + * @callback SimpleStore~afterCreateListener + * @param {string} name The `name` argument received by {@link Mapper#afterCreate}. + * @param {object} props The `props` argument received by {@link Mapper#afterCreate}. + * @param {object} opts The `opts` argument received by {@link Mapper#afterCreate}. + * @param {object} result The `result` argument received by {@link Mapper#afterCreate}. + * @see SimpleStore#event:afterCreate + * @see SimpleStore#create + * @since 3.0.0 + */ + /** + * Wrapper for {@link Mapper#create}. Adds the created record to the store. + * + * @example + * import { SimpleStore } from 'js-data'; + * import { HttpAdapter } from 'js-data-http'; + * + * const store = new SimpleStore(); + * store.registerAdapter('http', new HttpAdapter(), { default: true }); + * + * store.defineMapper('book'); + * + * // Since this example uses the http adapter, we'll get something like: + * // + * // POST /book {"author_id":1234,...} + * store.create('book', { + * author_id: 1234, + * edition: 'First Edition', + * title: 'Respect your Data' + * }).then((book) => { + * console.log(book.id); // 120392 + * console.log(book.title); // "Respect your Data" + * }); + * + * @fires SimpleStore#beforeCreate + * @fires SimpleStore#afterCreate + * @fires SimpleStore#add + * @method SimpleStore#create + * @param {string} name Name of the {@link Mapper} to target. + * @param {object} record Passed to {@link Mapper#create}. + * @param {object} [opts] Passed to {@link Mapper#create}. See + * {@link Mapper#create} for more configuration options. + * @returns {Promise} Resolves with the result of the create. + * @since 3.0.0 + */ + create(name, record, opts = {}) { + return super.create(name, record, opts).then(result => this._end(name, result, opts)); + } + /** + * Fired during {@link SimpleStore#createMany}. See + * {@link SimpleStore~beforeCreateManyListener} for how to listen for this event. + * + * @event SimpleStore#beforeCreateMany + * @see SimpleStore~beforeCreateManyListener + * @see SimpleStore#createMany + */ + /** + * Callback signature for the {@link SimpleStore#event:beforeCreateMany} event. + * + * @example + * function onBeforeCreateMany (mapperName, records, opts) { + * // do something + * } + * store.on('beforeCreateMany', onBeforeCreateMany); + * + * @callback SimpleStore~beforeCreateManyListener + * @param {string} name The `name` argument received by {@link Mapper#beforeCreateMany}. + * @param {object} records The `records` argument received by {@link Mapper#beforeCreateMany}. + * @param {object} opts The `opts` argument received by {@link Mapper#beforeCreateMany}. + * @see SimpleStore#event:beforeCreateMany + * @see SimpleStore#createMany + * @since 3.0.0 + */ + /** + * Fired during {@link SimpleStore#createMany}. See + * {@link SimpleStore~afterCreateManyListener} for how to listen for this event. + * + * @event SimpleStore#afterCreateMany + * @see SimpleStore~afterCreateManyListener + * @see SimpleStore#createMany + */ + /** + * Callback signature for the {@link SimpleStore#event:afterCreateMany} event. + * + * @example + * function onAfterCreateMany (mapperName, records, opts, result) { + * // do something + * } + * store.on('afterCreateMany', onAfterCreateMany); + * + * @callback SimpleStore~afterCreateManyListener + * @param {string} name The `name` argument received by {@link Mapper#afterCreateMany}. + * @param {object} records The `records` argument received by {@link Mapper#afterCreateMany}. + * @param {object} opts The `opts` argument received by {@link Mapper#afterCreateMany}. + * @param {object} result The `result` argument received by {@link Mapper#afterCreateMany}. + * @see SimpleStore#event:afterCreateMany + * @see SimpleStore#createMany + * @since 3.0.0 + */ + /** + * Wrapper for {@link Mapper#createMany}. Adds the created records to the + * store. + * + * @example + * import { SimpleStore } from 'js-data'; + * import { HttpAdapter } from 'js-data-http'; + * + * const store = new SimpleStore(); + * store.registerAdapter('http', new HttpAdapter(), { default: true }); + * + * store.defineMapper('book'); + * + * // Since this example uses the http adapter, we'll get something like: + * // + * // POST /book [{"author_id":1234,...},{...}] + * store.createMany('book', [{ + * author_id: 1234, + * edition: 'First Edition', + * title: 'Respect your Data' + * }, { + * author_id: 1234, + * edition: 'Second Edition', + * title: 'Respect your Data' + * }]).then((books) => { + * console.log(books[0].id); // 142394 + * console.log(books[0].title); // "Respect your Data" + * }); + * + * @fires SimpleStore#beforeCreateMany + * @fires SimpleStore#afterCreateMany + * @fires SimpleStore#add + * @method SimpleStore#createMany + * @param {string} name Name of the {@link Mapper} to target. + * @param {array} records Passed to {@link Mapper#createMany}. + * @param {object} [opts] Passed to {@link Mapper#createMany}. See + * {@link Mapper#createMany} for more configuration options. + * @returns {Promise} Resolves with the result of the create. + * @since 3.0.0 + */ + createMany(name, records, opts = {}) { + return super.createMany(name, records, opts).then(result => this._end(name, result, opts)); + } + defineMapper(name, opts = {}) { + const self = this; + const mapper = super.defineMapper(name, opts); + self._pendingQueries[name] = {}; + self._completedQueries[name] = {}; + if (!mapper.relationList) + Object.defineProperty(mapper, 'relationList', { value: [] }); + const collectionOpts = { + // Make sure the collection has somewhere to store "added" timestamps + _added: {}, + // Give the collection a reference to this SimpleStore + datastore: this, + // The mapper tied to the collection + mapper + }; + if (opts && 'onConflict' in opts) { + collectionOpts.onConflict = opts.onConflict; + } + // The SimpleStore uses a subclass of Collection that is "SimpleStore-aware" + const collection = (self._collections[name] = new self.collectionClass(null, collectionOpts)); + const schema = mapper.schema || {}; + const properties = schema.properties || {}; + // TODO: Make it possible index nested properties? + utils.forOwn(properties, (opts, prop) => { + if (opts.indexed) { + collection.createIndex(prop); + } + }); + // Create a secondary index on the "added" timestamps of records in the + // collection + collection.createIndex('addedTimestamps', ['$'], { + fieldGetter(obj) { + return collection._added[collection.recordId(obj)]; + } + }); + collection.on('all', (...args) => { + self._onCollectionEvent(name, ...args); + }); + return mapper; + } + /** + * Fired during {@link SimpleStore#destroy}. See + * {@link SimpleStore~beforeDestroyListener} for how to listen for this event. + * + * @event SimpleStore#beforeDestroy + * @see SimpleStore~beforeDestroyListener + * @see SimpleStore#destroy + */ + /** + * Callback signature for the {@link SimpleStore#event:beforeDestroy} event. + * + * @example + * function onBeforeDestroy (mapperName, id, opts) { + * // do something + * } + * store.on('beforeDestroy', onBeforeDestroy); + * + * @callback SimpleStore~beforeDestroyListener + * @param {string} name The `name` argument received by {@link Mapper#beforeDestroy}. + * @param {string|number} id The `id` argument received by {@link Mapper#beforeDestroy}. + * @param {object} opts The `opts` argument received by {@link Mapper#beforeDestroy}. + * @see SimpleStore#event:beforeDestroy + * @see SimpleStore#destroy + * @since 3.0.0 + */ + /** + * Fired during {@link SimpleStore#destroy}. See + * {@link SimpleStore~afterDestroyListener} for how to listen for this event. + * + * @event SimpleStore#afterDestroy + * @see SimpleStore~afterDestroyListener + * @see SimpleStore#destroy + */ + /** + * Callback signature for the {@link SimpleStore#event:afterDestroy} event. + * + * @example + * function onAfterDestroy (mapperName, id, opts, result) { + * // do something + * } + * store.on('afterDestroy', onAfterDestroy); + * + * @callback SimpleStore~afterDestroyListener + * @param {string} name The `name` argument received by {@link Mapper#afterDestroy}. + * @param {string|number} id The `id` argument received by {@link Mapper#afterDestroy}. + * @param {object} opts The `opts` argument received by {@link Mapper#afterDestroy}. + * @param {object} result The `result` argument received by {@link Mapper#afterDestroy}. + * @see SimpleStore#event:afterDestroy + * @see SimpleStore#destroy + * @since 3.0.0 + */ + /** + * Wrapper for {@link Mapper#destroy}. Removes any destroyed record from the + * in-memory store. Clears out any {@link SimpleStore#_completedQueries} entries + * associated with the provided `id`. + * + * @example + * import { SimpleStore } from 'js-data'; + * import { HttpAdapter } from 'js-data-http'; + * + * const store = new SimpleStore(); + * store.registerAdapter('http', new HttpAdapter(), { default: true }); + * + * store.defineMapper('book'); + * + * store.add('book', { id: 1234, title: 'Data Management is Hard' }); + * + * // Since this example uses the http adapter, we'll get something like: + * // + * // DELETE /book/1234 + * store.destroy('book', 1234).then(() => { + * // The book record is no longer in the in-memory store + * console.log(store.get('book', 1234)); // undefined + * + * return store.find('book', 1234); + * }).then((book) { + * // The book was deleted from the database too + * console.log(book); // undefined + * }); + * + * @fires SimpleStore#beforeDestroy + * @fires SimpleStore#afterDestroy + * @fires SimpleStore#remove + * @method SimpleStore#destroy + * @param {string} name Name of the {@link Mapper} to target. + * @param {(string|number)} id Passed to {@link Mapper#destroy}. + * @param {object} [opts] Passed to {@link Mapper#destroy}. See + * {@link Mapper#destroy} for more configuration options. + * @returns {Promise} Resolves when the destroy operation completes. + * @since 3.0.0 + */ + destroy(name, id, opts = {}) { + return super.destroy(name, id, opts).then(result => { + const record = this.getCollection(name).remove(id, opts); + if (opts.raw) { + result.data = record; + } + else { + result = record; + } + delete this._pendingQueries[name][id]; + delete this._completedQueries[name][id]; + return result; + }); + } + /** + * Fired during {@link SimpleStore#destroyAll}. See + * {@link SimpleStore~beforeDestroyAllListener} for how to listen for this event. + * + * @event SimpleStore#beforeDestroyAll + * @see SimpleStore~beforeDestroyAllListener + * @see SimpleStore#destroyAll + */ + /** + * Callback signature for the {@link SimpleStore#event:beforeDestroyAll} event. + * + * @example + * function onBeforeDestroyAll (mapperName, query, opts) { + * // do something + * } + * store.on('beforeDestroyAll', onBeforeDestroyAll); + * + * @callback SimpleStore~beforeDestroyAllListener + * @param {string} name The `name` argument received by {@link Mapper#beforeDestroyAll}. + * @param {object} query The `query` argument received by {@link Mapper#beforeDestroyAll}. + * @param {object} opts The `opts` argument received by {@link Mapper#beforeDestroyAll}. + * @see SimpleStore#event:beforeDestroyAll + * @see SimpleStore#destroyAll + * @since 3.0.0 + */ + /** + * Fired during {@link SimpleStore#destroyAll}. See + * {@link SimpleStore~afterDestroyAllListener} for how to listen for this event. + * + * @event SimpleStore#afterDestroyAll + * @see SimpleStore~afterDestroyAllListener + * @see SimpleStore#destroyAll + */ + /** + * Callback signature for the {@link SimpleStore#event:afterDestroyAll} event. + * + * @example + * function onAfterDestroyAll (mapperName, query, opts, result) { + * // do something + * } + * store.on('afterDestroyAll', onAfterDestroyAll); + * + * @callback SimpleStore~afterDestroyAllListener + * @param {string} name The `name` argument received by {@link Mapper#afterDestroyAll}. + * @param {object} query The `query` argument received by {@link Mapper#afterDestroyAll}. + * @param {object} opts The `opts` argument received by {@link Mapper#afterDestroyAll}. + * @param {object} result The `result` argument received by {@link Mapper#afterDestroyAll}. + * @see SimpleStore#event:afterDestroyAll + * @see SimpleStore#destroyAll + * @since 3.0.0 + */ + /** + * Wrapper for {@link Mapper#destroyAll}. Removes any destroyed records from + * the in-memory store. + * + * @example + * import { SimpleStore } from 'js-data'; + * import { HttpAdapter } from 'js-data-http'; + * + * const store = new SimpleStore(); + * store.registerAdapter('http', new HttpAdapter(), { default: true }); + * + * store.defineMapper('book'); + * + * store.add('book', { id: 1234, title: 'Data Management is Hard' }); + * + * // Since this example uses the http adapter, we'll get something like: + * // + * // DELETE /book/1234 + * store.destroy('book', 1234).then(() => { + * // The book record is gone from the in-memory store + * console.log(store.get('book', 1234)); // undefined + * return store.find('book', 1234); + * }).then((book) { + * // The book was deleted from the database too + * console.log(book); // undefined + * }); + * + * @fires SimpleStore#beforeDestroyAll + * @fires SimpleStore#afterDestroyAll + * @fires SimpleStore#remove + * @method SimpleStore#destroyAll + * @param {string} name Name of the {@link Mapper} to target. + * @param {object} [query] Passed to {@link Mapper#destroyAll}. + * @param {object} [opts] Passed to {@link Mapper#destroyAll}. See + * {@link Mapper#destroyAll} for more configuration options. + * @returns {Promise} Resolves when the delete completes. + * @since 3.0.0 + */ + destroyAll(name, query, opts = {}) { + return super.destroyAll(name, query, opts).then(result => { + const records = this.getCollection(name).removeAll(query, opts); + if (opts.raw) { + result.data = records; + } + else { + result = records; + } + const hash = this.hashQuery(name, query, opts); + delete this._pendingQueries[name][hash]; + delete this._completedQueries[name][hash]; + return result; + }); + } + eject(name, id, opts) { + console.warn('DEPRECATED: "eject" is deprecated, use "remove" instead'); + return this.remove(name, id, opts); + } + ejectAll(name, query, opts) { + console.warn('DEPRECATED: "ejectAll" is deprecated, use "removeAll" instead'); + return this.removeAll(name, query, opts); + } + /** + * Fired during {@link SimpleStore#find}. See + * {@link SimpleStore~beforeFindListener} for how to listen for this event. + * + * @event SimpleStore#beforeFind + * @see SimpleStore~beforeFindListener + * @see SimpleStore#find + */ + /** + * Callback signature for the {@link SimpleStore#event:beforeFind} event. + * + * @example + * function onBeforeFind (mapperName, id, opts) { + * // do something + * } + * store.on('beforeFind', onBeforeFind); + * + * @callback SimpleStore~beforeFindListener + * @param {string} name The `name` argument received by {@link Mapper#beforeFind}. + * @param {string|number} id The `id` argument received by {@link Mapper#beforeFind}. + * @param {object} opts The `opts` argument received by {@link Mapper#beforeFind}. + * @see SimpleStore#event:beforeFind + * @see SimpleStore#find + * @since 3.0.0 + */ + /** + * Fired during {@link SimpleStore#find}. See + * {@link SimpleStore~afterFindListener} for how to listen for this event. + * + * @event SimpleStore#afterFind + * @see SimpleStore~afterFindListener + * @see SimpleStore#find + */ + /** + * Callback signature for the {@link SimpleStore#event:afterFind} event. + * + * @example + * function onAfterFind (mapperName, id, opts, result) { + * // do something + * } + * store.on('afterFind', onAfterFind); + * + * @callback SimpleStore~afterFindListener + * @param {string} name The `name` argument received by {@link Mapper#afterFind}. + * @param {string|number} id The `id` argument received by {@link Mapper#afterFind}. + * @param {object} opts The `opts` argument received by {@link Mapper#afterFind}. + * @param {object} result The `result` argument received by {@link Mapper#afterFind}. + * @see SimpleStore#event:afterFind + * @see SimpleStore#find + * @since 3.0.0 + */ + /** + * Wrapper for {@link Mapper#find}. Adds any found record to the store. + * + * @example + * import { SimpleStore } from 'js-data'; + * import { HttpAdapter } from 'js-data-http'; + * + * const store = new SimpleStore(); + * store.registerAdapter('http', new HttpAdapter(), { default: true }); + * + * store.defineMapper('book'); + * + * // Since this example uses the http adapter, we'll get something like: + * // + * // GET /book/1234 + * store.find('book', 1234).then((book) => { + * // The book record is now in the in-memory store + * console.log(store.get('book', 1234) === book); // true + * }); + * + * @fires SimpleStore#beforeFind + * @fires SimpleStore#afterFind + * @fires SimpleStore#add + * @method SimpleStore#find + * @param {string} name Name of the {@link Mapper} to target. + * @param {(string|number)} id Passed to {@link Mapper#find}. + * @param {object} [opts] Passed to {@link Mapper#find}. + * @param {boolean} [opts.force] Bypass cacheFind + * @param {boolean|Function} [opts.usePendingFind] See {@link SimpleStore#usePendingFind} + * @returns {Promise} Resolves with the result, if any. + * @since 3.0.0 + */ + find(name, id, opts = {}) { + const mapper = this.getMapper(name); + const pendingQuery = this._pendingQueries[name][id]; + const usePendingFind = opts.usePendingFind === undefined ? this.usePendingFind : opts.usePendingFind; + utils._(opts, mapper); + if (pendingQuery && + (utils.isFunction(usePendingFind) ? usePendingFind.call(this, name, id, opts) : usePendingFind)) { + return pendingQuery; + } + const item = this.cachedFind(name, id, opts); + if (opts.force || !item) { + const promise = (this._pendingQueries[name][id] = super.find(name, id, opts)); + return promise.then(result => { + delete this._pendingQueries[name][id]; + result = this._end(name, result, opts); + this.cacheFind(name, result, id, opts); + return result; + }, err => { + delete this._pendingQueries[name][id]; + return utils.reject(err); + }); + } + return utils.resolve(item); + } + /** + * Fired during {@link SimpleStore#findAll}. See + * {@link SimpleStore~beforeFindAllListener} for how to listen for this event. + * + * @event SimpleStore#beforeFindAll + * @see SimpleStore~beforeFindAllListener + * @see SimpleStore#findAll + */ + /** + * Callback signature for the {@link SimpleStore#event:beforeFindAll} event. + * + * @example + * function onBeforeFindAll (mapperName, query, opts) { + * // do something + * } + * store.on('beforeFindAll', onBeforeFindAll); + * + * @callback SimpleStore~beforeFindAllListener + * @param {string} name The `name` argument received by {@link Mapper#beforeFindAll}. + * @param {object} query The `query` argument received by {@link Mapper#beforeFindAll}. + * @param {object} opts The `opts` argument received by {@link Mapper#beforeFindAll}. + * @see SimpleStore#event:beforeFindAll + * @see SimpleStore#findAll + * @since 3.0.0 + */ + /** + * Fired during {@link SimpleStore#findAll}. See + * {@link SimpleStore~afterFindAllListener} for how to listen for this event. + * + * @event SimpleStore#afterFindAll + * @see SimpleStore~afterFindAllListener + * @see SimpleStore#findAll + */ + /** + * Callback signature for the {@link SimpleStore#event:afterFindAll} event. + * + * @example + * function onAfterFindAll (mapperName, query, opts, result) { + * // do something + * } + * store.on('afterFindAll', onAfterFindAll); + * + * @callback SimpleStore~afterFindAllListener + * @param {string} name The `name` argument received by {@link Mapper#afterFindAll}. + * @param {object} query The `query` argument received by {@link Mapper#afterFindAll}. + * @param {object} opts The `opts` argument received by {@link Mapper#afterFindAll}. + * @param {object} result The `result` argument received by {@link Mapper#afterFindAll}. + * @see SimpleStore#event:afterFindAll + * @see SimpleStore#findAll + * @since 3.0.0 + */ + /** + * Wrapper for {@link Mapper#findAll}. Adds any found records to the store. + * + * @example + * import { SimpleStore } from 'js-data'; + * import { HttpAdapter } from 'js-data-http'; + * + * const store = new SimpleStore(); + * store.registerAdapter('http', new HttpAdapter(), { default: true }); + * + * store.defineMapper('movie'); + * + * // Since this example uses the http adapter, we'll get something like: + * // + * // GET /movie?rating=PG + * store.find('movie', { rating: 'PG' }).then((movies) => { + * // The movie records are now in the in-memory store + * console.log(store.filter('movie')); + * }); + * + * @fires SimpleStore#beforeFindAll + * @fires SimpleStore#afterFindAll + * @fires SimpleStore#add + * @method SimpleStore#findAll + * @param {string} name Name of the {@link Mapper} to target. + * @param {object} [query] Passed to {@link Mapper.findAll}. + * @param {object} [opts] Passed to {@link Mapper.findAll}. + * @param {boolean} [opts.force] Bypass cacheFindAll + * @param {boolean|Function} [opts.usePendingFindAll] See {@link SimpleStore#usePendingFindAll} + * @returns {Promise} Resolves with the result, if any. + * @since 3.0.0 + */ + findAll(name, query, opts = {}) { + const mapper = this.getMapper(name); + const hash = this.hashQuery(name, query, opts); + const pendingQuery = this._pendingQueries[name][hash]; + const usePendingFindAll = opts.usePendingFindAll === undefined ? this.usePendingFindAll : opts.usePendingFindAll; + utils._(opts, mapper); + if (pendingQuery && + (utils.isFunction(usePendingFindAll) ? usePendingFindAll.call(this, name, query, opts) : usePendingFindAll)) { + return pendingQuery; + } + const items = this.cachedFindAll(name, hash, opts); + if (opts.force || !items) { + const promise = (this._pendingQueries[name][hash] = super.findAll(name, query, opts)); + return promise.then(result => { + delete this._pendingQueries[name][hash]; + result = this._end(name, result, opts); + this.cacheFindAll(name, result, hash, opts); + return result; + }, err => { + delete this._pendingQueries[name][hash]; + return utils.reject(err); + }); + } + return utils.resolve(items); + } + /** + * Return the {@link Collection} with the given name, if for some + * reason you need a direct reference to the collection. + * + * @param {string} name Name of the {@link Collection} to retrieve. + * @since 3.0.0 + * @throws {Error} Thrown if the specified {@link Collection} does not + * exist. + */ + getCollection(name) { + const collection = this._collections[name]; + if (!collection) { + throw utils.err(`${DOMAIN$8}#getCollection`, name)(404, 'collection'); + } + return collection; + } + /** + * Hashing function used to cache {@link SimpleStore#find} and + * {@link SimpleStore#findAll} requests. This method simply JSONifies the + * `query` argument passed to {@link SimpleStore#find} or + * {@link SimpleStore#findAll}. + * + * Override this method for custom hashing behavior. + * @method SimpleStore#hashQuery + * @param {string} name The `name` argument passed to {@link SimpleStore#find} + * or {@link SimpleStore#findAll}. + * @param {object} query The `query` argument passed to {@link SimpleStore#find} + * or {@link SimpleStore#findAll}. + * @returns {string} The JSONified `query`. + * @since 3.0.0 + */ + hashQuery(name, query, opts) { + return utils.toJson(query || {}); + } + inject(name, records, opts) { + console.warn('DEPRECATED: "inject" is deprecated, use "add" instead'); + return this.add(name, records, opts); + } + /** + * Wrapper for {@link Collection#remove}. Removes the specified + * {@link Record} from the store. + * + * @example SimpleStore#remove + * const JSData = require('js-data'); + * const { SimpleStore } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new SimpleStore(); + * store.defineMapper('book'); + * console.log(store.getAll('book').length); + * store.add('book', { id: 1234 }); + * console.log(store.getAll('book').length); + * store.remove('book', 1234); + * console.log(store.getAll('book').length); + * + * @fires SimpleStore#remove + * @method SimpleStore#remove + * @param {string} name The name of the {@link Collection} to target. + * @param {string|number} id The primary key of the {@link Record} to remove. + * @param {object} [opts] Configuration options. + * @param {string[]} [opts.with] Relations of the {@link Record} to also + * remove from the store. + * @returns {Record} The removed {@link Record}, if any. + * @see Collection#add + * @see Collection#add + * @since 3.0.0 + */ + remove(name, id, opts) { + const record = this.getCollection(name).remove(id, opts); + if (record) { + this.removeRelated(name, [record], opts); + } + return record; + } + /** + * Wrapper for {@link Collection#removeAll}. Removes the selected + * {@link Record}s from the store. + * + * @example SimpleStore#removeAll + * const JSData = require('js-data'); + * const { SimpleStore } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new SimpleStore(); + * store.defineMapper('movie'); + * console.log(store.getAll('movie').length); + * store.add('movie', [{ id: 3, rating: 'R' }, { id: 4, rating: 'PG-13' }); + * console.log(store.getAll('movie').length); + * store.removeAll('movie', { rating: 'R' }); + * console.log(store.getAll('movie').length); + * + * @fires SimpleStore#remove + * @method SimpleStore#removeAll + * @param {string} name The name of the {@link Collection} to target. + * @param {object} [query={}] Selection query. See {@link query}. + * @param {object} [query.where] See {@link query.where}. + * @param {number} [query.offset] See {@link query.offset}. + * @param {number} [query.limit] See {@link query.limit}. + * @param {string|Array[]} [query.orderBy] See {@link query.orderBy}. + * @param {object} [opts] Configuration options. + * @param {string[]} [opts.with] Relations of the {@link Record} to also + * remove from the store. + * @returns {Record} The removed {@link Record}s, if any. + * @see Collection#add + * @see Collection#add + * @since 3.0.0 + */ + removeAll(name, query, opts) { + if (!query || !Object.keys(query).length) { + this._completedQueries[name] = {}; + } + else { + this._completedQueries[name][this.hashQuery(name, query, opts)] = undefined; + } + const records = this.getCollection(name).removeAll(query, opts); + if (records.length) { + this.removeRelated(name, records, opts); + } + return records; + } + /** + * Remove from the store {@link Record}s that are related to the provided + * {@link Record}(s). + * + * @fires SimpleStore#remove + * @method SimpleStore#removeRelated + * @param {string} name The name of the {@link Collection} to target. + * @param {Record|Record[]} records {@link Record}s whose relations are to be + * removed. + * @param {object} [opts] Configuration options. + * @param {string[]} [opts.with] Relations of the {@link Record}(s) to remove + * from the store. + * @since 3.0.0 + */ + removeRelated(name, records, opts) { + if (!utils.isArray(records)) { + records = [records]; + } + utils.forEachRelation(this.getMapper(name), opts, (def, optsCopy) => { + records.forEach(record => { + let relatedData; + let query; + if (def.foreignKey && (def.type === hasOneType || def.type === hasManyType)) { + query = { [def.foreignKey]: def.getForeignKey(record) }; + } + else if (def.type === hasManyType && def.localKeys) { + query = { + where: { + [def.getRelation().idAttribute]: { + in: utils.get(record, def.localKeys) + } + } + }; + } + else if (def.type === hasManyType && def.foreignKeys) { + query = { + where: { + [def.foreignKeys]: { + contains: def.getForeignKey(record) + } + } + }; + } + else if (def.type === belongsToType) { + relatedData = this.remove(def.relation, def.getForeignKey(record), optsCopy); + } + if (query) { + relatedData = this.removeAll(def.relation, query, optsCopy); + } + if (relatedData) { + if (utils.isArray(relatedData) && !relatedData.length) { + return; + } + if (def.type === hasOneType) { + relatedData = relatedData[0]; + } + def.setLocalField(record, relatedData); + } + }); + }); + } + /** + * Fired during {@link SimpleStore#update}. See + * {@link SimpleStore~beforeUpdateListener} for how to listen for this event. + * + * @event SimpleStore#beforeUpdate + * @see SimpleStore~beforeUpdateListener + * @see SimpleStore#update + */ + /** + * Callback signature for the {@link SimpleStore#event:beforeUpdate} event. + * + * @example + * function onBeforeUpdate (mapperName, id, props, opts) { + * // do something + * } + * store.on('beforeUpdate', onBeforeUpdate); + * + * @callback SimpleStore~beforeUpdateListener + * @param {string} name The `name` argument received by {@link Mapper#beforeUpdate}. + * @param {string|number} id The `id` argument received by {@link Mapper#beforeUpdate}. + * @param {object} props The `props` argument received by {@link Mapper#beforeUpdate}. + * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdate}. + * @see SimpleStore#event:beforeUpdate + * @see SimpleStore#update + * @since 3.0.0 + */ + /** + * Fired during {@link SimpleStore#update}. See + * {@link SimpleStore~afterUpdateListener} for how to listen for this event. + * + * @event SimpleStore#afterUpdate + * @see SimpleStore~afterUpdateListener + * @see SimpleStore#update + */ + /** + * Callback signature for the {@link SimpleStore#event:afterUpdate} event. + * + * @example + * function onAfterUpdate (mapperName, id, props, opts, result) { + * // do something + * } + * store.on('afterUpdate', onAfterUpdate); + * + * @callback SimpleStore~afterUpdateListener + * @param {string} name The `name` argument received by {@link Mapper#afterUpdate}. + * @param {string|number} id The `id` argument received by {@link Mapper#afterUpdate}. + * @param {object} props The `props` argument received by {@link Mapper#afterUpdate}. + * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdate}. + * @param {object} result The `result` argument received by {@link Mapper#afterUpdate}. + * @see SimpleStore#event:afterUpdate + * @see SimpleStore#update + * @since 3.0.0 + */ + /** + * Wrapper for {@link Mapper#update}. Adds the updated {@link Record} to the + * store. + * + * @example + * import { SimpleStore } from 'js-data'; + * import { HttpAdapter } from 'js-data-http'; + * + * const store = new SimpleStore(); + * store.registerAdapter('http', new HttpAdapter(), { default: true }); + * + * store.defineMapper('post'); + * + * // Since this example uses the http adapter, we'll get something like: + * // + * // PUT /post/1234 {"status":"published"} + * store.update('post', 1, { status: 'published' }).then((post) => { + * // The post record has also been updated in the in-memory store + * console.log(store.get('post', 1234)); + * }); + * + * @fires SimpleStore#beforeUpdate + * @fires SimpleStore#afterUpdate + * @fires SimpleStore#add + * @method SimpleStore#update + * @param {string} name Name of the {@link Mapper} to target. + * @param {(string|number)} id Passed to {@link Mapper#update}. + * @param {object} record Passed to {@link Mapper#update}. + * @param {object} [opts] Passed to {@link Mapper#update}. See + * {@link Mapper#update} for more configuration options. + * @returns {Promise} Resolves with the result of the update. + * @since 3.0.0 + */ + update(name, id, record, opts = {}) { + return super.update(name, id, record, opts).then(result => this._end(name, result, opts)); + } + /** + * Fired during {@link SimpleStore#updateAll}. See + * {@link SimpleStore~beforeUpdateAllListener} for how to listen for this event. + * + * @event SimpleStore#beforeUpdateAll + * @see SimpleStore~beforeUpdateAllListener + * @see SimpleStore#updateAll + */ + /** + * Callback signature for the {@link SimpleStore#event:beforeUpdateAll} event. + * + * @example + * function onBeforeUpdateAll (mapperName, props, query, opts) { + * // do something + * } + * store.on('beforeUpdateAll', onBeforeUpdateAll); + * + * @callback SimpleStore~beforeUpdateAllListener + * @param {string} name The `name` argument received by {@link Mapper#beforeUpdateAll}. + * @param {object} props The `props` argument received by {@link Mapper#beforeUpdateAll}. + * @param {object} query The `query` argument received by {@link Mapper#beforeUpdateAll}. + * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdateAll}. + * @see SimpleStore#event:beforeUpdateAll + * @see SimpleStore#updateAll + * @since 3.0.0 + */ + /** + * Fired during {@link SimpleStore#updateAll}. See + * {@link SimpleStore~afterUpdateAllListener} for how to listen for this event. + * + * @event SimpleStore#afterUpdateAll + * @see SimpleStore~afterUpdateAllListener + * @see SimpleStore#updateAll + */ + /** + * Callback signature for the {@link SimpleStore#event:afterUpdateAll} event. + * + * @example + * function onAfterUpdateAll (mapperName, props, query, opts, result) { + * // do something + * } + * store.on('afterUpdateAll', onAfterUpdateAll); + * + * @callback SimpleStore~afterUpdateAllListener + * @param {string} name The `name` argument received by {@link Mapper#afterUpdateAll}. + * @param {object} props The `props` argument received by {@link Mapper#afterUpdateAll}. + * @param {object} query The `query` argument received by {@link Mapper#afterUpdateAll}. + * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdateAll}. + * @param {object} result The `result` argument received by {@link Mapper#afterUpdateAll}. + * @see SimpleStore#event:afterUpdateAll + * @see SimpleStore#updateAll + * @since 3.0.0 + */ + /** + * Wrapper for {@link Mapper#updateAll}. Adds the updated {@link Record}s to + * the store. + * + * @example + * import { SimpleStore } from 'js-data'; + * import { HttpAdapter } from 'js-data-http'; + * + * const store = new SimpleStore(); + * store.registerAdapter('http', new HttpAdapter(), { default: true }); + * + * store.defineMapper('post'); + * + * // Since this example uses the http adapter, we'll get something like: + * // + * // PUT /post?author_id=1234 {"status":"published"} + * store.updateAll('post', { author_id: 1234 }, { status: 'published' }).then((posts) => { + * // The post records have also been updated in the in-memory store + * console.log(store.filter('posts', { author_id: 1234 })); + * }); + * + * @fires SimpleStore#beforeUpdateAll + * @fires SimpleStore#afterUpdateAll + * @fires SimpleStore#add + * @method SimpleStore#updateAll + * @param {string} name Name of the {@link Mapper} to target. + * @param {object} props Passed to {@link Mapper#updateAll}. + * @param {object} [query] Passed to {@link Mapper#updateAll}. + * @param {object} [opts] Passed to {@link Mapper#updateAll}. See + * {@link Mapper#updateAll} for more configuration options. + * @returns {Promise} Resolves with the result of the update. + * @since 3.0.0 + */ + updateAll(name, props, query, opts = {}) { + return super.updateAll(name, props, query, opts).then(result => this._end(name, result, opts)); + } + /** + * Fired during {@link SimpleStore#updateMany}. See + * {@link SimpleStore~beforeUpdateManyListener} for how to listen for this event. + * + * @event SimpleStore#beforeUpdateMany + * @see SimpleStore~beforeUpdateManyListener + * @see SimpleStore#updateMany + */ + /** + * Callback signature for the {@link SimpleStore#event:beforeUpdateMany} event. + * + * @example + * function onBeforeUpdateMany (mapperName, records, opts) { + * // do something + * } + * store.on('beforeUpdateMany', onBeforeUpdateMany); + * + * @callback SimpleStore~beforeUpdateManyListener + * @param {string} name The `name` argument received by {@link Mapper#beforeUpdateMany}. + * @param {object} records The `records` argument received by {@link Mapper#beforeUpdateMany}. + * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdateMany}. + * @see SimpleStore#event:beforeUpdateMany + * @see SimpleStore#updateMany + * @since 3.0.0 + */ + /** + * Fired during {@link SimpleStore#updateMany}. See + * {@link SimpleStore~afterUpdateManyListener} for how to listen for this event. + * + * @event SimpleStore#afterUpdateMany + * @see SimpleStore~afterUpdateManyListener + * @see SimpleStore#updateMany + */ + /** + * Callback signature for the {@link SimpleStore#event:afterUpdateMany} event. + * + * @example + * function onAfterUpdateMany (mapperName, records, opts, result) { + * // do something + * } + * store.on('afterUpdateMany', onAfterUpdateMany); + * + * @callback SimpleStore~afterUpdateManyListener + * @param {string} name The `name` argument received by {@link Mapper#afterUpdateMany}. + * @param {object} records The `records` argument received by {@link Mapper#afterUpdateMany}. + * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdateMany}. + * @param {object} result The `result` argument received by {@link Mapper#afterUpdateMany}. + * @see SimpleStore#event:afterUpdateMany + * @see SimpleStore#updateMany + * @since 3.0.0 + */ + /** + * Wrapper for {@link Mapper#updateMany}. Adds the updated {@link Record}s to + * the store. + * + * @example + * import { SimpleStore } from 'js-data'; + * import { HttpAdapter } from 'js-data-http'; + * + * const store = new SimpleStore(); + * store.registerAdapter('http', new HttpAdapter(), { default: true }); + * + * store.defineMapper('post'); + * + * // Since this example uses the http adapter, we'll get something like: + * // + * // PUT /post [{"id":3,status":"published"},{"id":4,status":"published"}] + * store.updateMany('post', [ + * { id: 3, status: 'published' }, + * { id: 4, status: 'published' } + * ]).then((posts) => { + * // The post records have also been updated in the in-memory store + * console.log(store.getAll('post', 3, 4)); + * }); + * + * @fires SimpleStore#beforeUpdateMany + * @fires SimpleStore#afterUpdateMany + * @fires SimpleStore#add + * @method SimpleStore#updateMany + * @param {string} name Name of the {@link Mapper} to target. + * @param {(Object[]|Record[])} records Passed to {@link Mapper#updateMany}. + * @param {object} [opts] Passed to {@link Mapper#updateMany}. See + * {@link Mapper#updateMany} for more configuration options. + * @returns {Promise} Resolves with the result of the update. + * @since 3.0.0 + */ + updateMany(name, records, opts = {}) { + return super.updateMany(name, records, opts).then(result => this._end(name, result, opts)); + } + /** + * Wrapper for {@link Collection#add}. + * + * @example SimpleStore#add + * const JSData = require('js-data'); + * const { SimpleStore } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new SimpleStore(); + * store.defineMapper('book'); + * + * // Add one book to the in-memory store: + * store.add('book', { id: 1, title: 'Respect your Data' }); + * // Add multiple books to the in-memory store: + * store.add('book', [ + * { id: 2, title: 'Easy data recipes' }, + * { id: 3, title: 'Active Record 101' } + * ]); + * + * @fires SimpleStore#add + * @method SimpleStore#add + * @param {(string|number)} name Name of the {@link Mapper} to target. + * @param {(Object|Object[]|Record|Record[])} records See {@link Collection#add}. + * @param {object} [opts] Configuration options. See {@link Collection#add}. + * @returns {(Object|Object[]|Record|Record[])} See {@link Collection#add}. + * @see Collection#add + * @see Collection#add + * @since 3.0.0 + */ + add(name, records, opts) { + return this.getCollection(name).add(records, opts); + } + /** + * Wrapper for {@link Collection#between}. + * + * @example + * // Get all users ages 18 to 30 + * const users = store.between('user', 18, 30, { index: 'age' }); + * + * @example + * // Same as above + * const users = store.between('user', [18], [30], { index: 'age' }); + * + * @method SimpleStore#between + * @param {(string|number)} name Name of the {@link Mapper} to target. + * @param {array} leftKeys See {@link Collection#between}. + * @param {array} rightKeys See {@link Collection#between}. + * @param {object} [opts] Configuration options. See {@link Collection#between}. + * @returns {Object[]|Record[]} See {@link Collection#between}. + * @see Collection#between + * @see Collection#between + * @since 3.0.0 + */ + between(name, leftKeys, rightKeys, opts) { + return this.getCollection(name).between(leftKeys, rightKeys, opts); + } + /** + * Wrapper for {@link Collection#createIndex}. + * + * @example + * // Index users by age + * store.createIndex('user', 'age'); + * + * @example + * // Index users by status and role + * store.createIndex('user', 'statusAndRole', ['status', 'role']); + * + * @method SimpleStore#createIndex + * @param {(string|number)} name Name of the {@link Mapper} to target. + * @param {string} indexName See {@link Collection#createIndex}. + * @param {string[]} [fieldList] See {@link Collection#createIndex}. + * @param {object} [opts] Configuration options. See {@link Collection#between}. + * @see Collection#createIndex + * @see Collection#createIndex + * @since 3.0.0 + */ + createIndex(name, indexName, fieldList, opts) { + return this.getCollection(name).createIndex(indexName, fieldList, opts); + } + /** + * Wrapper for {@link Collection#filter}. + * + * @example SimpleStore#filter + * const JSData = require('js-data'); + * const { SimpleStore } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new SimpleStore(); + * store.defineMapper('post'); + * store.add('post', [ + * { id: 1, status: 'draft', created_at_timestamp: new Date().getTime() } + * ]); + * + * // Get the draft posts created less than three months ago + * let posts = store.filter('post', { + * where: { + * status: { + * '==': 'draft' + * }, + * created_at_timestamp: { + * '>=': (new Date().getTime() - (1000 \* 60 \* 60 \* 24 \* 30 \* 3)) // 3 months ago + * } + * } + * }); + * console.log(posts); + * + * // Use a custom filter function + * posts = store.filter('post', function (post) { return post.id % 2 === 0 }); + * + * @method SimpleStore#filter + * @param {(string|number)} name Name of the {@link Mapper} to target. + * @param {(Object|Function)} [queryOrFn={}] See {@link Collection#filter}. + * @param {object} [thisArg] See {@link Collection#filter}. + * @returns {Array} See {@link Collection#filter}. + * @see Collection#filter + * @see Collection#filter + * @since 3.0.0 + */ + filter(name, queryOrFn, thisArg) { + return this.getCollection(name).filter(queryOrFn, thisArg); + } + /** + * Wrapper for {@link Collection#get}. + * + * @example SimpleStore#get + * const JSData = require('js-data'); + * const { SimpleStore } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new SimpleStore(); + * store.defineMapper('post'); + * store.add('post', [ + * { id: 1, status: 'draft', created_at_timestamp: new Date().getTime() } + * ]); + * + * console.log(store.get('post', 1)); // {...} + * console.log(store.get('post', 2)); // undefined + * + * @method SimpleStore#get + * @param {(string|number)} name Name of the {@link Mapper} to target. + * @param {(string|number)} id See {@link Collection#get}. + * @returns {(Object|Record)} See {@link Collection#get}. + * @see Collection#get + * @see Collection#get + * @since 3.0.0 + */ + get(name, id) { + return this.getCollection(name).get(id); + } + /** + * Wrapper for {@link Collection#getAll}. + * + * @example + * // Get the posts where "status" is "draft" or "inReview" + * const posts = store.getAll('post', 'draft', 'inReview', { index: 'status' }); + * + * @example + * // Same as above + * const posts = store.getAll('post', ['draft'], ['inReview'], { index: 'status' }); + * + * @method SimpleStore#getAll + * @param {(string|number)} name Name of the {@link Mapper} to target. + * @param {...Array} [keyList] See {@link Collection#getAll}. + * @param {object} [opts] See {@link Collection#getAll}. + * @returns {Array} See {@link Collection#getAll}. + * @see Collection#getAll + * @see Collection#getAll + * @since 3.0.0 + */ + getAll(name, ...args) { + return this.getCollection(name).getAll(...args); + } + /** + * Wrapper for {@link Collection#prune}. + * + * @method SimpleStore#prune + * @param name + * @param {object} [opts] See {@link Collection#prune}. + * @returns {Array} See {@link Collection#prune}. + * @see Collection#prune + * @see Collection#prune + * @since 3.0.0 + */ + prune(name, opts) { + return this.getCollection(name).prune(opts); + } + /** + * Wrapper for {@link Collection#query}. + * + * @example + * // Grab page 2 of users between ages 18 and 30 + * store.query('user') + * .between(18, 30, { index: 'age' }) // between ages 18 and 30 + * .skip(10) // second page + * .limit(10) // page size + * .run(); + * + * @method SimpleStore#query + * @param {(string|number)} name Name of the {@link Mapper} to target. + * @returns {Query} See {@link Collection#query}. + * @see Collection#query + * @see Collection#query + * @since 3.0.0 + */ + query(name) { + return this.getCollection(name).query(); + } + /** + * Wrapper for {@link Collection#toJSON}. + * + * @example + * store.defineMapper('post', { + * schema: { + * properties: { + * id: { type: 'number' }, + * title: { type: 'string' } + * } + * } + * }); + * store.add('post', [ + * { id: 1, status: 'published', title: 'Respect your Data' }, + * { id: 2, status: 'draft', title: 'Connecting to a data source' } + * ]); + * console.log(store.toJSON('post')); + * const draftsJSON = store.query('post') + * .filter({ status: 'draft' }) + * .mapCall('toJSON') + * .run(); + * + * @method SimpleStore#toJSON + * @param {(string|number)} name Name of the {@link Mapper} to target. + * @param {object} [opts] See {@link Collection#toJSON}. + * @returns {Array} See {@link Collection#toJSON}. + * @see Collection#toJSON + * @see Collection#toJSON + * @since 3.0.0 + */ + toJSON(name, opts) { + return this.getCollection(name).toJSON(opts); + } + /** + * Wrapper for {@link Collection#unsaved}. + * + * @method SimpleStore#unsaved + * @returns {Array} See {@link Collection#unsaved}. + * @see Collection#unsaved + * @see Collection#unsaved + * @since 3.0.0 + */ + unsaved(name, opts) { + return this.getCollection(name).unsaved(opts); + } +} +/** + * Fired when a record changes. Only works for records that have tracked fields. + * See {@link SimpleStore~changeListener} on how to listen for this event. + * + * @event SimpleStore#change + * @see SimpleStore~changeListener + */ +/** + * Callback signature for the {@link SimpleStore#event:change} event. + * + * @example + * function onChange (mapperName, record, changes) { + * // do something + * } + * store.on('change', onChange); + * + * @callback SimpleStore~changeListener + * @param {string} name The name of the associated {@link Mapper}. + * @param {Record} record The Record that changed. + * @param {object} changes The changes. + * @see SimpleStore#event:change + * @since 3.0.0 + */ +/** + * Fired when one or more records are added to the in-memory store. See + * {@link SimpleStore~addListener} on how to listen for this event. + * + * @event SimpleStore#add + * @see SimpleStore~addListener + * @see SimpleStore#event:add + * @see SimpleStore#add + * @see SimpleStore#create + * @see SimpleStore#createMany + * @see SimpleStore#find + * @see SimpleStore#findAll + * @see SimpleStore#update + * @see SimpleStore#updateAll + * @see SimpleStore#updateMany + */ +/** + * Callback signature for the {@link SimpleStore#event:add} event. + * + * @example + * function onAdd (mapperName, recordOrRecords) { + * // do something + * } + * store.on('add', onAdd); + * + * @callback SimpleStore~addListener + * @param {string} name The name of the associated {@link Mapper}. + * @param {Record|Record[]} The Record or Records that were added. + * @see SimpleStore#event:add + * @see SimpleStore#add + * @see SimpleStore#create + * @see SimpleStore#createMany + * @see SimpleStore#find + * @see SimpleStore#findAll + * @see SimpleStore#update + * @see SimpleStore#updateAll + * @see SimpleStore#updateMany + * @since 3.0.0 + */ +/** + * Fired when one or more records are removed from the in-memory store. See + * {@link SimpleStore~removeListener} for how to listen for this event. + * + * @event SimpleStore#remove + * @see SimpleStore~removeListener + * @see SimpleStore#event:remove + * @see SimpleStore#clear + * @see SimpleStore#destroy + * @see SimpleStore#destroyAll + * @see SimpleStore#remove + * @see SimpleStore#removeAll + */ +/** + * Callback signature for the {@link SimpleStore#event:remove} event. + * + * @example + * function onRemove (mapperName, recordsOrRecords) { + * // do something + * } + * store.on('remove', onRemove); + * + * @callback SimpleStore~removeListener + * @param {string} name The name of the associated {@link Mapper}. + * @param {Record|Record[]} Record or Records that were removed. + * @see SimpleStore#event:remove + * @see SimpleStore#clear + * @see SimpleStore#destroy + * @see SimpleStore#destroyAll + * @see SimpleStore#remove + * @see SimpleStore#removeAll + * @since 3.0.0 + */ +/** + * Create a subclass of this SimpleStore: + * @example SimpleStore.extend + * const JSData = require('js-data'); + * const { SimpleStore } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * // Extend the class using ES2015 class syntax. + * class CustomSimpleStoreClass extends SimpleStore { + * foo () { return 'bar'; } + * static beep () { return 'boop'; } + * } + * const customSimpleStore = new CustomSimpleStoreClass(); + * console.log(customSimpleStore.foo()); + * console.log(CustomSimpleStoreClass.beep()); + * + * // Extend the class using alternate method. + * const OtherSimpleStoreClass = SimpleStore.extend({ + * foo () { return 'bar'; } + * }, { + * beep () { return 'boop'; } + * }) + * const otherSimpleStore = new OtherSimpleStoreClass(); + * console.log(otherSimpleStore.foo()); + * console.log(OtherSimpleStoreClass.beep()); + * + * // Extend the class, providing a custom constructor. + * function AnotherSimpleStoreClass () { + * SimpleStore.call(this) + * this.created_at = new Date().getTime() + * } + * SimpleStore.extend({ + * constructor: AnotherSimpleStoreClass, + * foo () { return 'bar'; } + * }, { + * beep () { return 'boop'; } + * }) + * const anotherSimpleStore = new AnotherSimpleStoreClass(); + * console.log(anotherSimpleStore.created_at); + * console.log(anotherSimpleStore.foo()); + * console.log(AnotherSimpleStoreClass.beep()); + * + * @method SimpleStore.extend + * @param {object} [props={}] Properties to add to the prototype of the + * subclass. + * @param {object} [props.constructor] Provide a custom constructor function + * to be used as the subclass itself. + * @param {object} [classProps={}] Static properties to add to the subclass. + * @returns {Constructor} Subclass of this SimpleStore class. + * @since 3.0.0 */ -utils.eventify(Component.prototype, function () { - return this._listeners; -}, function (value) { - this._listeners = value; -}); - -var DOMAIN$1 = 'Query'; -var INDEX_ERR = 'Index inaccessible after first operation'; // Reserved words used by JSData's Query Syntax - -var reserved = { - limit: '', - offset: '', - orderBy: '', - skip: '', - sort: '', - where: '' -}; // Used by our JavaScript implementation of the LIKE operator - -var escapeRegExp = /([.*+?^=!:${}()|[\]/\\])/g; -var percentRegExp = /%/g; -var underscoreRegExp = /_/g; - -var escape = function escape(pattern) { - return pattern.replace(escapeRegExp, '\\$1'); -}; -/** - * A class used by the {@link Collection} class to build queries to be executed - * against the collection's data. An instance of `Query` is returned by - * {@link Collection#query}. Query instances are typically short-lived, and you - * shouldn't have to create them yourself. Just use {@link Collection#query}. - * - * ```javascript - * import { Query } from 'js-data'; - * ``` - * - * @example Query intro - * const JSData = require('js-data'); - * const { DataStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new DataStore(); - * store.defineMapper('post'); - * const posts = [ - * { author: 'John', age: 30, status: 'published', id: 1 }, - * { author: 'Sally', age: 31, status: 'draft', id: 2 }, - * { author: 'Mike', age: 32, status: 'draft', id: 3 }, - * { author: 'Adam', age: 33, status: 'deleted', id: 4 }, - * { author: 'Adam', age: 33, status: 'draft', id: 5 } - * ] - * store.add('post', posts); - * const drafts = store.query('post').filter({ status: 'draft' }).limit(2).run(); - * console.log(drafts); - * - * @class Query - * @extends Component - * @param {Collection} collection The collection on which this query operates. - * @since 3.0.0 +const DOMAIN$9 = 'LinkedCollection'; +/** + * Extends {@link Collection}. Used by a {@link DataStore} to implement an + * Identity Map. + * + * @example + * import {LinkedCollection} from 'js-data'; + * + * // Extend the class using ES2015 class syntax. + * class CustomLinkedCollectionClass extends LinkedCollection { + * foo () { return 'bar'; } + * static beep () { return 'boop'; } + * } + * const customLinkedCollection = new CustomLinkedCollectionClass(); + * console.log(customLinkedCollection.foo()); + * console.log(CustomLinkedCollectionClass.beep()); + * + * @class LinkedCollection + * @extends Collection + * @param {array} [records] Initial set of records to insert into the + * collection. See {@link Collection}. + * @param {object} [opts] Configuration options. See {@link Collection}. + * @returns {Mapper} + */ +class LinkedCollection extends Collection { + constructor(records, opts) { + super(records, opts); + // Make sure this collection has a reference to a datastore + if (!this.datastore) { + throw utils.err(`new ${DOMAIN$9}`, 'opts.datastore')(400, 'DataStore', this.datastore); + } + } + _addMeta(record, timestamp) { + // Track when this record was added + this._added[this.recordId(record)] = timestamp; + if (utils.isFunction(record._set)) { + record._set('$', timestamp); + } + } + _clearMeta(record) { + delete this._added[this.recordId(record)]; + if (utils.isFunction(record._set)) { + record._set('$'); // unset + } + } + _onRecordEvent(...args) { + Collection.prototype._onRecordEvent.apply(this, args); + const event = args[0]; + // This is a very brute force method + // Lots of room for optimization + if (utils.isString(event) && event.indexOf('change') === 0) { + this.updateIndexes(args[1]); + } + } + add(records, opts) { + const mapper = this.mapper; + const timestamp = new Date().getTime(); + const singular = utils.isObject(records) && !utils.isArray(records); + if (singular) { + records = [records]; + } + records = super.add(records, opts); + if (mapper.relationList.length && records.length) { + // Check the currently visited record for relations that need to be + // inserted into their respective collections. + mapper.relationList.forEach(def => { + def.addLinkedRecords(records); + }); + } + records.forEach(record => this._addMeta(record, timestamp)); + return singular ? records[0] : records; + } + remove(idOrRecord, opts) { + const mapper = this.mapper; + const record = super.remove(idOrRecord, opts); + if (record) { + this._clearMeta(record); + } + if (mapper.relationList.length && record) { + mapper.relationList.forEach(def => { + def.removeLinkedRecords(mapper, [record]); + }); + } + return record; + } + removeAll(query, opts) { + const mapper = this.mapper; + const records = super.removeAll(query, opts); + records.forEach(this._clearMeta, this); + if (mapper.relationList.length && records.length) { + mapper.relationList.forEach(def => { + def.removeLinkedRecords(mapper, records); + }); + } + return records; + } +} +/** + * Create a subclass of this LinkedCollection: + * + * // Extend the class using alternate method. + * const OtherLinkedCollectionClass = LinkedCollection.extend({ + * foo () { return 'bar'; } + * }, { + * beep () { return 'boop'; } + * }); + * const otherLinkedCollection = new OtherLinkedCollectionClass(); + * console.log(otherLinkedCollection.foo()); + * console.log(OtherLinkedCollectionClass.beep()); + * + * // Extend the class, providing a custom constructor. + * function AnotherLinkedCollectionClass () { + * LinkedCollection.call(this); + * this.created_at = new Date().getTime(); + * } + * LinkedCollection.extend({ + * constructor: AnotherLinkedCollectionClass, + * foo () { return 'bar'; } + * }, { + * beep () { return 'boop'; } + * }); + * const anotherLinkedCollection = new AnotherLinkedCollectionClass(); + * console.log(anotherLinkedCollection.created_at); + * console.log(anotherLinkedCollection.foo()); + * console.log(AnotherLinkedCollectionClass.beep()); + * + * @method LinkedCollection.extend + * @param {object} [props={}] Properties to add to the prototype of the + * subclass. + * @param {object} [props.constructor] Provide a custom constructor function + * to be used as the subclass itself. + * @param {object} [classProps={}] Static properties to add to the subclass. + * @returns {Constructor} Subclass of this LinkedCollection class. + * @since 3.0.0 */ - -function Query(collection) { - utils.classCallCheck(this, Query); - /** - * The {@link Collection} on which this query operates. - * - * @name Query#collection - * @since 3.0.0 - * @type {Collection} - */ - - this.collection = collection; - /** - * The current data result of this query. - * - * @name Query#data - * @since 3.0.0 - * @type {Array} - */ - - this.data = null; +const DATASTORE_DEFAULTS = { + /** + * Whether in-memory relations should be unlinked from records after they are + * destroyed. + * + * @default true + * @name DataStore#unlinkOnDestroy + * @since 3.0.0 + * @type {boolean} + */ + unlinkOnDestroy: true, + collectionClass: LinkedCollection +}; +/** + * The `DataStore` class is an extension of {@link SimpleStore}. Not only does + * `DataStore` manage mappers and store data in collections, it uses the + * {@link LinkedCollection} class to link related records together in memory. + * + * ```javascript + * import { DataStore } from 'js-data'; + * ``` + * + * @example + * import { DataStore } from 'js-data'; + * import HttpAdapter from 'js-data-http'; + * const store = new DataStore(); + * + * // DataStore#defineMapper returns a direct reference to the newly created + * // Mapper. + * const UserMapper = store.defineMapper('user'); + * + * // DataStore#as returns the store scoped to a particular Mapper. + * const UserStore = store.as('user'); + * + * // Call "find" on "UserMapper" (Stateless ORM) + * UserMapper.find(1).then((user) => { + * // retrieved a "user" record via the http adapter, but that's it + * + * // Call "find" on "store" targeting "user" (Stateful DataStore) + * return store.find('user', 1); // same as "UserStore.find(1)" + * }).then((user) => { + * // not only was a "user" record retrieved, but it was added to the + * // store's "user" collection + * const cachedUser = store.getCollection('user').get(1); + * console.log(user === cachedUser); // true + * }); + * + * @class DataStore + * @extends SimpleStore + * @param {object} [opts] Configuration options. See {@link SimpleStore}. + * @param {boolean} [opts.collectionClass={@link LinkedCollection}] See {@link DataStore#collectionClass}. + * @param {boolean} [opts.debug=false] See {@link Component#debug}. + * @param {boolean} [opts.unlinkOnDestroy=true] See {@link DataStore#unlinkOnDestroy}. + * @param {boolean|Function} [opts.usePendingFind=true] See {@link DataStore#usePendingFind}. + * @param {boolean|Function} [opts.usePendingFindAll=true] See {@link DataStore#usePendingFindAll}. + * @returns {DataStore} + * @see SimpleStore + * @since 3.0.0 + * @tutorial ["http://www.js-data.io/v3.0/docs/components-of-jsdata#datastore","Components of JSData: DataStore"] + * @tutorial ["http://www.js-data.io/v3.0/docs/working-with-the-datastore","Working with the DataStore"] + * @tutorial ["http://www.js-data.io/v3.0/docs/jsdata-and-the-browser","Notes on using JSData in the Browser"] + */ +class DataStore extends SimpleStore { + constructor(opts = {}) { + // Fill in any missing options with the defaults + super(Object.assign(Object.assign({}, DATASTORE_DEFAULTS), opts)); + } + /** + * Creates a new [Mapper] with [name] from the [opts] + * @param {string} name + * @param {object} opts + * @returns {*} + */ + defineMapper(name, opts) { + // Complexity of this method is beyond simply using => functions to bind context + const self = this; + const mapper = super.defineMapper(name, opts); + const idAttribute = mapper.idAttribute; + const collection = this.getCollection(name); + mapper.relationList.forEach(def => { + const relation = def.relation; + const localField = def.localField; + const path = `links.${localField}`; + const foreignKey = def.foreignKey; + const type = def.type; + const updateOpts = { index: foreignKey }; + let descriptor; + const getter = function () { + return this._get(path); + }; + if (type === belongsToType) { + if (!collection.indexes[foreignKey]) { + collection.createIndex(foreignKey); + } + descriptor = { + get: getter, + // e.g. profile.user = someUser + // or comment.post = somePost + set(record) { + // e.g. const otherUser = profile.user + const currentParent = this._get(path); + // e.g. profile.user === someUser + if (record === currentParent) { + return currentParent; + } + const id = utils.get(this, idAttribute); + const inverseDef = def.getInverse(mapper); + // e.g. profile.user !== someUser + // or comment.post !== somePost + if (currentParent && inverseDef) { + this.removeInverseRelation(currentParent, id, inverseDef, idAttribute); + } + if (record) { + // e.g. profile.user = someUser + const relatedIdAttribute = def.getRelation().idAttribute; + const relatedId = utils.get(record, relatedIdAttribute); + // Prefer store record + if (relatedId !== undefined && this._get('$')) { + record = self.get(relation, relatedId) || record; + } + // Set locals + // e.g. profile.user = someUser + // or comment.post = somePost + safeSetLink(this, localField, record); + safeSetProp(this, foreignKey, relatedId); + collection.updateIndex(this, updateOpts); + if (inverseDef) { + this.setupInverseRelation(record, id, inverseDef, idAttribute); + } + } + else { + // Unset in-memory link only + // e.g. profile.user = undefined + // or comment.post = undefined + safeSetLink(this, localField, undefined); + } + return record; + } + }; + let foreignKeyDescriptor = Object.getOwnPropertyDescriptor(mapper.recordClass.prototype, foreignKey); + if (!foreignKeyDescriptor) { + foreignKeyDescriptor = { + enumerable: true + }; + } + const originalGet = foreignKeyDescriptor.get; + foreignKeyDescriptor.get = function () { + if (originalGet) { + return originalGet.call(this); + } + return this._get(`props.${foreignKey}`); + }; + const originalSet = foreignKeyDescriptor.set; + foreignKeyDescriptor.set = function (value) { + if (originalSet) { + originalSet.call(this, value); + } + const currentParent = utils.get(this, localField); + const id = utils.get(this, idAttribute); + const inverseDef = def.getInverse(mapper); + const currentParentId = currentParent ? utils.get(currentParent, def.getRelation().idAttribute) : undefined; + if (inverseDef && currentParent && currentParentId !== undefined && currentParentId !== value) { + if (inverseDef.type === hasOneType) { + safeSetLink(currentParent, inverseDef.localField, undefined); + } + else if (inverseDef.type === hasManyType) { + const children = utils.get(currentParent, inverseDef.localField); + if (id === undefined) { + utils.remove(children, child => child === this); + } + else { + utils.remove(children, child => child === this || id === utils.get(child, idAttribute)); + } + } + } + safeSetProp(this, foreignKey, value); + collection.updateIndex(this, updateOpts); + if (value === undefined || value === null) { + if (currentParentId !== undefined) { + // Unset locals + utils.set(this, localField, undefined); + } + } + else if (this._get('$')) { + const storeRecord = self.get(relation, value); + if (storeRecord) { + utils.set(this, localField, storeRecord); + } + } + }; + Object.defineProperty(mapper.recordClass.prototype, foreignKey, foreignKeyDescriptor); + } + else if (type === hasManyType) { + const localKeys = def.localKeys; + const foreignKeys = def.foreignKeys; + // TODO: Handle case when belongsTo relation isn't ever defined + if (self._collections[relation] && foreignKey && !self.getCollection(relation).indexes[foreignKey]) { + self.getCollection(relation).createIndex(foreignKey); + } + descriptor = { + get() { + const current = getter.call(this); + if (!current) { + this._set(path, []); + } + return getter.call(this); + }, + // e.g. post.comments = someComments + // or user.groups = someGroups + // or group.users = someUsers + set(records) { + if (records && !utils.isArray(records)) { + records = [records]; + } + const id = utils.get(this, idAttribute); + const relatedIdAttribute = def.getRelation().idAttribute; + const inverseDef = def.getInverse(mapper); + const inverseLocalField = inverseDef.localField; + const current = this._get(path) || []; + const toLink = []; + const toLinkIds = {}; + if (records) { + records.forEach(record => { + // e.g. comment.id + const relatedId = utils.get(record, relatedIdAttribute); + const currentParent = utils.get(record, inverseLocalField); + if (currentParent && currentParent !== this) { + const currentChildrenOfParent = utils.get(currentParent, localField); + // e.g. somePost.comments.remove(comment) + if (relatedId === undefined) { + utils.remove(currentChildrenOfParent, child => child === record); + } + else { + utils.remove(currentChildrenOfParent, child => child === record || relatedId === utils.get(child, relatedIdAttribute)); + } + } + if (relatedId !== undefined) { + if (this._get('$')) { + // Prefer store record + record = self.get(relation, relatedId) || record; + } + // e.g. toLinkIds[comment.id] = comment + toLinkIds[relatedId] = record; + } + toLink.push(record); + }); + } + // e.g. post.comments = someComments + if (foreignKey) { + current.forEach(record => { + // e.g. comment.id + const relatedId = utils.get(record, relatedIdAttribute); + if ((relatedId === undefined && toLink.indexOf(record) === -1) || + (relatedId !== undefined && !(relatedId in toLinkIds))) { + // Update (unset) inverse relation + if (records) { + // e.g. comment.post_id = undefined + safeSetProp(record, foreignKey, undefined); + // e.g. CommentCollection.updateIndex(comment, { index: 'post_id' }) + self.getCollection(relation).updateIndex(record, updateOpts); + } + // e.g. comment.post = undefined + safeSetLink(record, inverseLocalField, undefined); + } + }); + toLink.forEach(record => { + // Update (set) inverse relation + // e.g. comment.post_id = post.id + safeSetProp(record, foreignKey, id); + // e.g. CommentCollection.updateIndex(comment, { index: 'post_id' }) + self.getCollection(relation).updateIndex(record, updateOpts); + // e.g. comment.post = post + safeSetLink(record, inverseLocalField, this); + }); + } + else if (localKeys) { + // Update locals + // e.g. group.users = someUsers + // Update (set) inverse relation + const ids = toLink.map(child => utils.get(child, relatedIdAttribute)).filter(id => id !== undefined); + // e.g. group.user_ids = [1,2,3,...] + utils.set(this, localKeys, ids); + // Update (unset) inverse relation + if (inverseDef.foreignKeys) { + current.forEach(child => { + const relatedId = utils.get(child, relatedIdAttribute); + if ((relatedId === undefined && toLink.indexOf(child) === -1) || + (relatedId !== undefined && !(relatedId in toLinkIds))) { + // Update inverse relation + // safeSetLink(child, inverseLocalField, undefined) + const parents = utils.get(child, inverseLocalField) || []; + // e.g. someUser.groups.remove(group) + if (id === undefined) { + utils.remove(parents, parent => parent === this); + } + else { + utils.remove(parents, parent => parent === this || id === utils.get(parent, idAttribute)); + } + } + }); + toLink.forEach(child => { + // Update (set) inverse relation + const parents = utils.get(child, inverseLocalField); + // e.g. someUser.groups.push(group) + if (id === undefined) { + utils.noDupeAdd(parents, this, parent => parent === this); + } + else { + utils.noDupeAdd(parents, this, parent => parent === this || id === utils.get(parent, idAttribute)); + } + }); + } + } + else if (foreignKeys) { + // e.g. user.groups = someGroups + // Update (unset) inverse relation + current.forEach(parent => { + const ids = utils.get(parent, foreignKeys) || []; + // e.g. someGroup.user_ids.remove(user.id) + utils.remove(ids, _key => id === _key); + const children = utils.get(parent, inverseLocalField); + // e.g. someGroup.users.remove(user) + if (id === undefined) { + utils.remove(children, child => child === this); + } + else { + utils.remove(children, child => child === this || id === utils.get(child, idAttribute)); + } + }); + // Update (set) inverse relation + toLink.forEach(parent => { + const ids = utils.get(parent, foreignKeys) || []; + utils.noDupeAdd(ids, id, _key => id === _key); + const children = utils.get(parent, inverseLocalField); + if (id === undefined) { + utils.noDupeAdd(children, this, child => child === this); + } + else { + utils.noDupeAdd(children, this, child => child === this || id === utils.get(child, idAttribute)); + } + }); + } + this._set(path, toLink); + return toLink; + } + }; + } + else if (type === hasOneType) { + // TODO: Handle case when belongsTo relation isn't ever defined + if (self._collections[relation] && foreignKey && !self.getCollection(relation).indexes[foreignKey]) { + self.getCollection(relation).createIndex(foreignKey); + } + descriptor = { + get: getter, + // e.g. user.profile = someProfile + set(record) { + const current = this._get(path); + if (record === current) { + return current; + } + const inverseLocalField = def.getInverse(mapper).localField; + // Update (unset) inverse relation + if (current) { + safeSetProp(current, foreignKey, undefined); + self.getCollection(relation).updateIndex(current, updateOpts); + safeSetLink(current, inverseLocalField, undefined); + } + if (record) { + const relatedId = utils.get(record, def.getRelation().idAttribute); + // Prefer store record + if (relatedId !== undefined) { + record = self.get(relation, relatedId) || record; + } + // Set locals + safeSetLink(this, localField, record); + // Update (set) inverse relation + safeSetProp(record, foreignKey, utils.get(this, idAttribute)); + self.getCollection(relation).updateIndex(record, updateOpts); + safeSetLink(record, inverseLocalField, this); + } + else { + // Unset locals + safeSetLink(this, localField, undefined); + } + return record; + } + }; + } + if (descriptor) { + descriptor.enumerable = def.enumerable === undefined ? false : def.enumerable; + if (def.get) { + const origGet = descriptor.get; + descriptor.get = function () { + return def.get(def, this, (...args) => origGet.apply(this, args)); + }; + } + if (def.set) { + const origSet = descriptor.set; + descriptor.set = function (related) { + return def.set(def, this, related, value => origSet.call(this, value === undefined ? related : value)); + }; + } + Object.defineProperty(mapper.recordClass.prototype, localField, descriptor); + } + }); + return mapper; + } + destroy(name, id, opts = {}) { + return super.destroy(name, id, opts).then(result => { + let record; + if (opts.raw) { + record = result.data; + } + else { + record = result; + } + if (record && this.unlinkOnDestroy) { + const _opts = utils.plainCopy(opts); + _opts.withAll = true; + utils.forEachRelation(this.getMapper(name), _opts, def => { + utils.set(record, def.localField, undefined); + }); + } + return result; + }); + } + destroyAll(name, query, opts = {}) { + return super.destroyAll(name, query, opts).then(result => { + var _a; + let records; + if (opts.raw) { + records = result.data; + } + else { + records = result; + } + if (((_a = records) === null || _a === void 0 ? void 0 : _a.length) && this.unlinkOnDestroy) { + const _opts = utils.plainCopy(opts); + _opts.withAll = true; + utils.forEachRelation(this.getMapper(name), _opts, def => { + records.forEach(record => { + utils.set(record, def.localField, undefined); + }); + }); + } + return result; + }); + } } -var Query$1 = Component$1.extend({ - constructor: Query, - _applyWhereFromObject: function _applyWhereFromObject(where) { - var fields = []; - var ops = []; - var predicates = []; - utils.forOwn(where, function (clause, field) { - if (!utils.isObject(clause)) { - clause = { - '==': clause - }; - } - - utils.forOwn(clause, function (expr, op) { - fields.push(field); - ops.push(op); - predicates.push(expr); - }); - }); - return { - fields: fields, - ops: ops, - predicates: predicates - }; - }, - _applyWhereFromArray: function _applyWhereFromArray(where) { - var _this = this; - - var groups = []; - where.forEach(function (_where, i) { - if (utils.isString(_where)) { - return; - } - - var prev = where[i - 1]; - var parser = utils.isArray(_where) ? _this._applyWhereFromArray : _this._applyWhereFromObject; - var group = parser.call(_this, _where); - - if (prev === 'or') { - group.isOr = true; - } - - groups.push(group); - }); - groups.isArray = true; - return groups; - }, - _testObjectGroup: function _testObjectGroup(keep, first, group, item) { - var i; - var fields = group.fields; - var ops = group.ops; - var predicates = group.predicates; - var len = ops.length; - - for (i = 0; i < len; i++) { - var op = ops[i]; - var isOr = op.charAt(0) === '|'; - op = isOr ? op.substr(1) : op; - var expr = this.evaluate(utils.get(item, fields[i]), op, predicates[i]); - - if (expr !== undefined) { - keep = first ? expr : isOr ? keep || expr : keep && expr; - } - - first = false; - } - - return { - keep: keep, - first: first - }; - }, - _testArrayGroup: function _testArrayGroup(keep, first, groups, item) { - var i; - var len = groups.length; - - for (i = 0; i < len; i++) { - var group = groups[i]; - var parser = group.isArray ? this._testArrayGroup : this._testObjectGroup; - var result = parser.call(this, true, true, group, item); - - if (groups[i - 1]) { - if (group.isOr) { - keep = keep || result.keep; - } else { - keep = keep && result.keep; - } - } else { - keep = result.keep; - } - - first = result.first; - } - - return { - keep: keep, - first: first - }; - }, - - /** - * Find all entities between two boundaries. - * - * @example Get the users ages 18 to 30. - * const JSData = require('js-data'); - * const { DataStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new DataStore(); - * store.defineMapper('user'); - * const users = [ - * { name: 'Peter', age: 25, id: 1 }, - * { name: 'Jim', age: 19, id: 2 }, - * { name: 'Mike', age: 17, id: 3 }, - * { name: 'Alan', age: 29, id: 4 }, - * { name: 'Katie', age: 33, id: 5 } - * ]; - * store.add('user', users) - * const filteredUsers = store - * .query('user') - * .between(18, 30, { index: 'age' }) - * .run(); - * console.log(filteredUsers); - * - * @example Same as above. - * const JSData = require('js-data'); - * const { DataStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new DataStore(); - * store.defineMapper('user'); - * const users = [ - * { name: 'Peter', age: 25, id: 1 }, - * { name: 'Jim', age: 19, id: 2 }, - * { name: 'Mike', age: 17, id: 3 }, - * { name: 'Alan', age: 29, id: 4 }, - * { name: 'Katie', age: 33, id: 5 } - * ]; - * store.add('user', users) - * const filteredUsers = store - * .query('user') - * .between([18], [30], { index: 'age' }) - * .run(); - * console.log(filteredUsers); - * - * @method Query#between - * @param {array} leftKeys Keys defining the left boundary. - * @param {array} rightKeys Keys defining the right boundary. - * @param {object} [opts] Configuration options. - * @param {string} [opts.index] Name of the secondary index to use in the - * query. If no index is specified, the main index is used. - * @param {boolean} [opts.leftInclusive=true] Whether to include entities - * on the left boundary. - * @param {boolean} [opts.rightInclusive=false] Whether to include entities - * on the left boundary. - * @param {boolean} [opts.limit] Limit the result to a certain number. - * @param {boolean} [opts.offset] The number of resulting entities to skip. - * @returns {Query} A reference to itself for chaining. - * @since 3.0.0 - */ - between: function between(leftKeys, rightKeys, opts) { - opts || (opts = {}); - - if (this.data) { - throw utils.err("".concat(DOMAIN$1, "#between"))(500, 'Cannot access index'); - } - - this.data = this.collection.getIndex(opts.index).between(leftKeys, rightKeys, opts); - return this; - }, - - /** - * The comparison function used by the {@link Query} class. - * - * @method Query#compare - * @param {array} orderBy An orderBy clause used for sorting and sub-sorting. - * @param {number} index The index of the current orderBy clause being used. - * @param {*} a The first item in the comparison. - * @param {*} b The second item in the comparison. - * @returns {number} -1 if `b` should preceed `a`. 0 if `a` and `b` are equal. - * 1 if `a` should preceed `b`. - * @since 3.0.0 - */ - compare: function compare(orderBy, index, a, b) { - var def = orderBy[index]; - var cA = utils.get(a, def[0]); - var cB = utils.get(b, def[0]); - - if (cA && utils.isString(cA)) { - cA = cA.toUpperCase(); - } - - if (cB && utils.isString(cB)) { - cB = cB.toUpperCase(); - } - - if (a === undefined) { - a = null; - } - - if (b === undefined) { - b = null; - } - - if (def[1].toUpperCase() === 'DESC') { - var temp = cB; - cB = cA; - cA = temp; - } - - if (cA < cB) { - return -1; - } else if (cA > cB) { - return 1; - } else { - if (index < orderBy.length - 1) { - return this.compare(orderBy, index + 1, a, b); - } else { - return 0; - } - } - }, - - /** - * Predicate evaluation function used by the {@link Query} class. - * - * @method Query#evaluate - * @param {*} value The value to evaluate. - * @param {string} op The operator to use in this evaluation. - * @param {*} predicate The predicate to use in this evaluation. - * @returns {boolean} Whether the value passed the evaluation or not. - * @since 3.0.0 - */ - evaluate: function evaluate(value, op, predicate) { - var ops = this.constructor.ops; - - if (ops[op]) { - return ops[op](value, predicate); - } - - if (op.indexOf('like') === 0) { - return this.like(predicate, op.substr(4)).exec(value) !== null; - } else if (op.indexOf('notLike') === 0) { - return this.like(predicate, op.substr(7)).exec(value) === null; - } - }, - - /** - * Find the record or records that match the provided query or are accepted by - * the provided filter function. - * - * @example Get the draft posts by authors younger than 30 - * const JSData = require('js-data'); - * const { DataStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new DataStore(); - * store.defineMapper('post') - * const posts = [ - * { author: 'John', age: 30, status: 'published', id: 1 }, - * { author: 'Sally', age: 31, status: 'published', id: 2 }, - * { author: 'Mike', age: 32, status: 'draft', id: 3 }, - * { author: 'Adam', age: 33, status: 'deleted', id: 4 }, - * { author: 'Adam', age: 33, status: 'published', id: 5 } - * { author: 'Peter', age: 25, status: 'deleted', id: 6 }, - * { author: 'Sally', age: 21, status: 'draft', id: 7 }, - * { author: 'Jim', age: 27, status: 'draft', id: 8 }, - * { author: 'Jim', age: 27, status: 'published', id: 9 }, - * { author: 'Jason', age: 55, status: 'published', id: 10 } - * ]; - * store.add('post', posts); - * const results = store - * .query('post') - * .filter({ - * where: { - * status: { - * '==': 'draft' - * }, - * age: { - * '<': 30 - * } - * } - * }) - * .run(); - * console.log(results); - * - * @example Use a custom filter function - * const posts = query - * .filter(function (post) { - * return post.isReady(); - * }) - * .run(); - * - * @method Query#filter - * @param {(Object|Function)} [queryOrFn={}] Selection query or filter - * function. - * @param {Function} [thisArg] Context to which to bind `queryOrFn` if - * `queryOrFn` is a function. - * @returns {Query} A reference to itself for chaining. - * @since 3.0.0 - */ - filter: function filter(query, thisArg) { - var _this2 = this; - - /** - * Selection query as defined by JSData's [Query Syntax][querysyntax]. - * - * [querysyntax]: http://www.js-data.io/v3.0/docs/query-syntax - * - * @example Empty "findAll" query - * const JSData = require('js-data'); - * const { DataStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new DataStore(); - * store.defineMapper('post') - * store.findAll('post').then((posts) => { - * console.log(posts); // [...] - * }); - * - * @example Empty "filter" query - * const JSData = require('js-data'); - * const { DataStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new DataStore(); - * store.defineMapper('post'); - * const posts = store.filter('post'); - * console.log(posts); // [...] - * - * @example Complex "filter" query - * const JSData = require('js-data'); - * const { DataStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new DataStore(); - * const PAGE_SIZE = 2; - * let currentPage = 3; - * - * store.defineMapper('post'); - * const posts = [ - * { author: 'John', age: 30, status: 'published', id: 1 }, - * { author: 'Sally', age: 31, status: 'published', id: 2 }, - * { author: 'Mike', age: 32, status: 'draft', id: 3 }, - * { author: 'Adam', age: 33, status: 'deleted', id: 4 }, - * { author: 'Adam', age: 33, status: 'published', id: 5 } - * { author: 'Peter', age: 25, status: 'deleted', id: 6 }, - * { author: 'Sally', age: 21, status: 'draft', id: 7 }, - * { author: 'Jim', age: 27, status: 'draft', id: 8 }, - * { author: 'Jim', age: 27, status: 'published', id: 9 }, - * { author: 'Jason', age: 55, status: 'published', id: 10 } - * ]; - * store.add('post', posts); - * // Retrieve a filtered page of blog posts - * // Would typically replace filter with findAll - * const results = store.filter('post', { - * where: { - * status: { - * // WHERE status = 'published' - * '==': 'published' - * }, - * author: { - * // AND author IN ('bob', 'alice') - * 'in': ['bob', 'alice'], - * // OR author IN ('karen') - * '|in': ['karen'] - * } - * }, - * orderBy: [ - * // ORDER BY date_published DESC, - * ['date_published', 'DESC'], - * // ORDER BY title ASC - * ['title', 'ASC'] - * ], - * // LIMIT 2 - * limit: PAGE_SIZE, - * // SKIP 4 - * offset: PAGE_SIZE * (currentPage - 1) - * }); - * console.log(results); - * - * @namespace query - * @property {number} [limit] See {@link query.limit}. - * @property {number} [offset] See {@link query.offset}. - * @property {string|Array[]} [orderBy] See {@link query.orderBy}. - * @property {number} [skip] Alias for {@link query.offset}. - * @property {string|Array[]} [sort] Alias for {@link query.orderBy}. - * @property {Object} [where] See {@link query.where}. - * @since 3.0.0 - * @tutorial ["http://www.js-data.io/v3.0/docs/query-syntax","JSData's Query Syntax"] - */ - query || (query = {}); - this.getData(); - - if (utils.isObject(query)) { - var where = {}; - /** - * Filtering criteria. Records that do not meet this criteria will be exluded - * from the result. - * - * @example Return posts where author is at least 32 years old - * const JSData = require('js-data'); - * const { DataStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new DataStore(); - * store.defineMapper('post') - * const posts = [ - * { author: 'John', age: 30, id: 5 }, - * { author: 'Sally', age: 31, id: 6 }, - * { author: 'Mike', age: 32, id: 7 }, - * { author: 'Adam', age: 33, id: 8 }, - * { author: 'Adam', age: 33, id: 9 } - * ]; - * store.add('post', posts); - * const results = store.filter('post', { - * where: { - * age: { - * '>=': 30 - * } - * } - * }); - * console.log(results); - * - * @name query.where - * @type {Object} - * @see http://www.js-data.io/v3.0/docs/query-syntax - * @since 3.0.0 - */ - - if (utils.isObject(query.where) || utils.isArray(query.where)) { - where = query.where; - } - - utils.forOwn(query, function (value, key) { - if (!(key in reserved) && !(key in where)) { - where[key] = { - '==': value - }; - } - }); - var groups; // Apply filter for each field - - if (utils.isObject(where) && Object.keys(where).length !== 0) { - groups = this._applyWhereFromArray([where]); - } else if (utils.isArray(where)) { - groups = this._applyWhereFromArray(where); - } - - if (groups) { - this.data = this.data.filter(function (item, i) { - return _this2._testArrayGroup(true, true, groups, item).keep; - }); - } // Sort - - - var orderBy = query.orderBy || query.sort; - - if (utils.isString(orderBy)) { - orderBy = [[orderBy, 'ASC']]; - } - - if (!utils.isArray(orderBy)) { - orderBy = null; - } - /** - * Determines how records should be ordered in the result. - * - * @example Order posts by `author` then by `id` descending - * const JSData = require('js-data'); - * const { DataStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new DataStore(); - * store.defineMapper('post') - * const posts = [ - * { author: 'John', age: 30, id: 5 }, - * { author: 'Sally', age: 31, id: 6 }, - * { author: 'Mike', age: 32, id: 7 }, - * { author: 'Adam', age: 33, id: 8 }, - * { author: 'Adam', age: 33, id: 9 } - * ]; - * store.add('post', posts); - * const results = store.filter('post', { - * orderBy:[['author','ASC'],['id','DESC']] - * }); - * console.log(results); - * - * @name query.orderBy - * @type {string|Array[]} - * @see http://www.js-data.io/v3.0/docs/query-syntax - * @since 3.0.0 - */ - - - if (orderBy) { - var index = 0; - orderBy.forEach(function (def, i) { - if (utils.isString(def)) { - orderBy[i] = [def, 'ASC']; - } - }); - this.data.sort(function (a, b) { - return _this2.compare(orderBy, index, a, b); - }); - } - /** - * Number of records to skip. - * - * @example Retrieve the first "page" of blog posts using findAll - * const JSData = require('js-data'); - * const { DataStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new DataStore(); - * store.defineMapper('post'); - * const PAGE_SIZE = 10; - * let currentPage = 1; - * store.findAll('post', { - * offset: PAGE_SIZE * (currentPage 1) - * limit: PAGE_SIZE - * }); - * - * @example Retrieve the last "page" of blog posts using filter - * const JSData = require('js-data'); - * const { DataStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new DataStore(); - * - * const PAGE_SIZE = 5; - * let currentPage = 2; - * store.defineMapper('post'); - * const posts = [ - * { author: 'John', age: 30, id: 1 }, - * { author: 'Sally', age: 31, id: 2 }, - * { author: 'Mike', age: 32, id: 3 }, - * { author: 'Adam', age: 33, id: 4 }, - * { author: 'Adam', age: 33, id: 5 }, - * { author: 'Peter', age: 25, id: 6 }, - * { author: 'Sally', age: 21, id: 7 }, - * { author: 'Jim', age: 27, id: 8 }, - * { author: 'Jim', age: 27, id: 9 }, - * { author: 'Jason', age: 55, id: 10 } - * ]; - * store.add('post', posts); - * const results = store.filter('post', { - * offset: PAGE_SIZE * (currentPage 1) - * limit: PAGE_SIZE - * }); - * console.log(results) - * - * @name query.offset - * @type {number} - * @see http://www.js-data.io/v3.0/docs/query-syntax - * @since 3.0.0 - */ - - - if (utils.isNumber(query.skip)) { - this.skip(query.skip); - } else if (utils.isNumber(query.offset)) { - this.skip(query.offset); - } - /** - * Maximum number of records to retrieve. - * - * @example Retrieve the first "page" of blog posts using findAll - * const JSData = require('js-data'); - * const { DataStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new DataStore(); - * store.defineMapper('post'); - * - * const PAGE_SIZE = 10 - * let currentPage = 1 - * store.findAll('post', { - * offset: PAGE_SIZE * (currentPage 1) - * limit: PAGE_SIZE - * }); - * - * @example Retrieve the last "page" of blog posts using filter - * const JSData = require('js-data'); - * const { DataStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new DataStore(); - * - * const PAGE_SIZE = 5 - * let currentPage = 2 - * store.defineMapper('post') - * const posts = [ - * { author: 'John', age: 30, id: 1 }, - * { author: 'Sally', age: 31, id: 2 }, - * { author: 'Mike', age: 32, id: 3 }, - * { author: 'Adam', age: 33, id: 4 }, - * { author: 'Adam', age: 33, id: 5 }, - * { author: 'Peter', age: 25, id: 6 }, - * { author: 'Sally', age: 21, id: 7 }, - * { author: 'Jim', age: 27, id: 8 }, - * { author: 'Jim', age: 27, id: 9 }, - * { author: 'Jason', age: 55, id: 10 } - * ]; - * store.add('post', posts); - * const results = store.filter('post', { - * offset: PAGE_SIZE * (currentPage 1) - * limit: PAGE_SIZE - * }); - * console.log(results) - * - * @name query.limit - * @type {number} - * @see http://www.js-data.io/v3.0/docs/query-syntax - * @since 3.0.0 - */ - - - if (utils.isNumber(query.limit)) { - this.limit(query.limit); - } - } else if (utils.isFunction(query)) { - this.data = this.data.filter(query, thisArg); - } - - return this; - }, - - /** - * Iterate over all entities. - * - * @method Query#forEach - * @param {Function} forEachFn Iteration function. - * @param {*} [thisArg] Context to which to bind `forEachFn`. - * @returns {Query} A reference to itself for chaining. - * @since 3.0.0 - */ - forEach: function forEach(forEachFn, thisArg) { - this.getData().forEach(forEachFn, thisArg); - return this; - }, - - /** - * Find the entity or entities that match the provided key. - * - * @example Get the entity whose primary key is 25. - * const entities = query.get(25).run(); - * - * @example Same as above. - * const entities = query.get([25]).run(); - * - * @example Get all users who are active and have the "admin" role. - * const activeAdmins = query.get(['active', 'admin'], { - * index: 'activityAndRoles' - * }).run(); - * - * @example Get all entities that match a certain weather condition. - * const niceDays = query.get(['sunny', 'humid', 'calm'], { - * index: 'weatherConditions' - * }).run(); - * - * @method Query#get - * @param {array} keyList Key(s) defining the entity to retrieve. If - * `keyList` is not an array (i.e. for a single-value key), it will be - * wrapped in an array. - * @param {object} [opts] Configuration options. - * @param {string} [opts.string] Name of the secondary index to use in the - * query. If no index is specified, the main index is used. - * @returns {Query} A reference to itself for chaining. - * @since 3.0.0 - */ - get: function get(keyList, opts) { - keyList || (keyList = []); - opts || (opts = {}); - - if (this.data) { - throw utils.err("".concat(DOMAIN$1, "#get"))(500, INDEX_ERR); - } - - if (keyList && !utils.isArray(keyList)) { - keyList = [keyList]; - } - - if (!keyList.length) { - this.getData(); - return this; - } - - this.data = this.collection.getIndex(opts.index).get(keyList); - return this; - }, - - /** - * Find the entity or entities that match the provided keyLists. - * - * @example Get the posts where "status" is "draft" or "inReview". - * const posts = query.getAll('draft', 'inReview', { index: 'status' }).run(); - * - * @example Same as above. - * const posts = query.getAll(['draft'], ['inReview'], { index: 'status' }).run(); - * - * @method Query#getAll - * @param {...Array} [keyList] Provide one or more keyLists, and all - * entities matching each keyList will be retrieved. If no keyLists are - * provided, all entities will be returned. - * @param {object} [opts] Configuration options. - * @param {string} [opts.index] Name of the secondary index to use in the - * query. If no index is specified, the main index is used. - * @returns {Query} A reference to itself for chaining. - * @since 3.0.0 - */ - getAll: function getAll() { - var _this3 = this; - - var opts = {}; - - if (this.data) { - throw utils.err("".concat(DOMAIN$1, "#getAll"))(500, INDEX_ERR); - } - - for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { - args[_key] = arguments[_key]; - } - - if (!args.length || args.length === 1 && utils.isObject(args[0])) { - this.getData(); - return this; - } else if (args.length && utils.isObject(args[args.length - 1])) { - opts = args[args.length - 1]; - args.pop(); - } - - var collection = this.collection; - var index = collection.getIndex(opts.index); - this.data = []; - args.forEach(function (keyList) { - _this3.data = _this3.data.concat(index.get(keyList)); - }); - return this; - }, - - /** - * Return the current data result of this query. - * - * @method Query#getData - * @returns {Array} The data in this query. - * @since 3.0.0 - */ - getData: function getData() { - if (!this.data) { - this.data = this.collection.index.getAll(); - } - - return this.data; - }, - - /** - * Implementation used by the `like` operator. Takes a pattern and flags and - * returns a `RegExp` instance that can test strings. - * - * @method Query#like - * @param {string} pattern Testing pattern. - * @param {string} flags Flags for the regular expression. - * @returns {RegExp} Regular expression for testing strings. - * @since 3.0.0 - */ - like: function like(pattern, flags) { - return new RegExp("^".concat(escape(pattern).replace(percentRegExp, '.*').replace(underscoreRegExp, '.'), "$"), flags); - }, - - /** - * Limit the result. - * - * @example Get only the first 2 posts. - * const store = new JSData.DataStore(); - * store.defineMapper('post'); - * const posts = [ - * { author: 'John', age: 30, status: 'published', id: 1 }, - * { author: 'Sally', age: 31, status: 'draft', id: 2 }, - * { author: 'Mike', age: 32, status: 'draft', id: 3 }, - * { author: 'Adam', age: 33, status: 'deleted', id: 4 }, - * { author: 'Adam', age: 33, status: 'draft', id: 5 } - * ]; - * store.add('post', posts); - * const results = store.query('post').limit(2).run(); - * console.log(results); - * - * @method Query#limit - * @param {number} num The maximum number of entities to keep in the result. - * @returns {Query} A reference to itself for chaining. - * @since 3.0.0 - */ - limit: function limit(num) { - if (!utils.isNumber(num)) { - throw utils.err("".concat(DOMAIN$1, "#limit"), 'num')(400, 'number', num); - } - - var data = this.getData(); - this.data = data.slice(0, Math.min(data.length, num)); - return this; - }, - - /** - * Apply a mapping function to the result data. - * - * @example - * const JSData = require('js-data'); - * const { DataStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new DataStore(); - * store.defineMapper('user'); - * const users = [ - * { name: 'Peter', age: 25, id: 1 }, - * { name: 'Jim', age: 19, id: 2 }, - * { name: 'Mike', age: 17, id: 3 }, - * { name: 'Alan', age: 29, id: 4 }, - * { name: 'Katie', age: 33, id: 5 } - * ]; - * store.add('user', users); - * const ages = store - * .query('user') - * .map(function (user) { - * return user.age; - * }) - * .run(); - * console.log(ages); - * - * @method Query#map - * @param {Function} mapFn Mapping function. - * @param {*} [thisArg] Context to which to bind `mapFn`. - * @returns {Query} A reference to itself for chaining. - * @since 3.0.0 - */ - map: function map(mapFn, thisArg) { - this.data = this.getData().map(mapFn, thisArg); - return this; - }, - - /** - * Return the result of calling the specified function on each item in this - * collection's main index. - * - * @example - * const stringAges = UserCollection.query().mapCall('toString').run(); - * - * @method Query#mapCall - * @param {string} funcName Name of function to call - * @parama {...*} [args] Remaining arguments to be passed to the function. - * @returns {Query} A reference to itself for chaining. - * @since 3.0.0 - */ - mapCall: function mapCall(funcName) { - for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { - args[_key2 - 1] = arguments[_key2]; - } - - this.data = this.getData().map(function (item) { - return item[funcName].apply(item, args); - }); - return this; - }, - - /** - * Complete the execution of the query and return the resulting data. - * - * @method Query#run - * @returns {Array} The result of executing this query. - * @since 3.0.0 - */ - run: function run() { - var data = this.data; - this.data = null; - return data; - }, - - /** - * Skip a number of results. - * - * @example Get all but the first 2 posts. - * const JSData = require('js-data'); - * const { DataStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new DataStore(); - * store.defineMapper('post'); - * const posts = [ - * { author: 'John', age: 30, status: 'published', id: 1 }, - * { author: 'Sally', age: 31, status: 'draft', id: 2 }, - * { author: 'Mike', age: 32, status: 'draft', id: 3 }, - * { author: 'Adam', age: 33, status: 'deleted', id: 4 }, - * { author: 'Adam', age: 33, status: 'draft', id: 5 } - * ]; - * store.add('post', posts); - * const results = store.query('post').skip(2).run(); - * console.log(results); - * - * @method Query#skip - * @param {number} num The number of entities to skip. - * @returns {Query} A reference to itself for chaining. - * @since 3.0.0 - */ - skip: function skip(num) { - if (!utils.isNumber(num)) { - throw utils.err("".concat(DOMAIN$1, "#skip"), 'num')(400, 'number', num); - } - - var data = this.getData(); - - if (num < data.length) { - this.data = data.slice(num); - } else { - this.data = []; - } - - return this; - } -}, { - /** - * The filtering operators supported by {@link Query#filter}, and which are - * implemented by adapters (for the most part). - * - * @example Variant 1 - * const JSData = require('js-data'); - * const { DataStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new DataStore(); - * store.defineMapper('post'); - * const posts = [ - * { author: 'John', age: 30, status: 'published', id: 1 }, - * { author: 'Sally', age: 31, status: 'published', id: 2 }, - * { author: 'Mike', age: 32, status: 'published', id: 3 }, - * { author: 'Adam', age: 33, status: 'deleted', id: 4 }, - * { author: 'Adam', age: 33, status: 'published', id: 5 } - * ]; - * store.add('post', posts); - * const publishedPosts = store.filter('post', { - * status: 'published', - * limit: 2 - * }); - * console.log(publishedPosts); - * - * - * @example Variant 2 - * const JSData = require('js-data'); - * const { DataStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new DataStore(); - * store.defineMapper('post') - * const posts = [ - * { author: 'John', age: 30, status: 'published', id: 1 }, - * { author: 'Sally', age: 31, status: 'published', id: 2 }, - * { author: 'Mike', age: 32, status: 'published', id: 3 }, - * { author: 'Adam', age: 33, status: 'deleted', id: 4 }, - * { author: 'Adam', age: 33, status: 'published', id: 5 } - * ]; - * store.add('post', posts); - * const publishedPosts = store.filter('post', { - * where: { - * status: { - * '==': 'published' - * } - * }, - * limit: 2 - * }); - * console.log(publishedPosts); - * - * @example Variant 3 - * const JSData = require('js-data'); - * const { DataStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new DataStore(); - * store.defineMapper('post'); - * const posts = [ - * { author: 'John', age: 30, status: 'published', id: 1 }, - * { author: 'Sally', age: 31, status: 'published', id: 2 }, - * { author: 'Mike', age: 32, status: 'published', id: 3 }, - * { author: 'Adam', age: 33, status: 'deleted', id: 4 }, - * { author: 'Adam', age: 33, status: 'published', id: 5 } - * ]; - * store.add('post', posts); - * const publishedPosts = store - * .query('post') - * .filter({ status: 'published' }) - * .limit(2) - * .run(); - * console.log(publishedPosts); - * - * @example Variant 4 - * const JSData = require('js-data'); - * const { DataStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new DataStore(); - * store.defineMapper('post'); - * const posts = [ - * { author: 'John', age: 30, status: 'published', id: 1 }, - * { author: 'Sally', age: 31, status: 'published', id: 2 }, - * { author: 'Mike', age: 32, status: 'published', id: 3 }, - * { author: 'Adam', age: 33, status: 'deleted', id: 4 }, - * { author: 'Adam', age: 33, status: 'published', id: 5 } - * ]; - * store.add('post', posts); - * const publishedPosts = store - * .query('post') - * .filter({ - * where: { - * status: { - * '==': 'published' - * } - * } - * }) - * .limit(2) - * .run(); - * console.log(publishedPosts); - * - * @example Multiple operators - * const JSData = require('js-data'); - * const { DataStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new DataStore(); - * store.defineMapper('post'); - * const posts = [ - * { author: 'John', age: 30, status: 'published', id: 1 }, - * { author: 'Sally', age: 31, status: 'published', id: 2 }, - * { author: 'Mike', age: 32, status: 'published', id: 3 }, - * { author: 'Adam', age: 33, status: 'deleted', id: 4 }, - * { author: 'Adam', age: 33, status: 'published', id: 5 } - * ]; - * store.add('post', posts); - * - * const myPublishedPosts = store.filter('post', { - * where: { - * status: { - * '==': 'published' - * }, - * user_id: { - * '==': currentUser.id - * } - * } - * }); - * - * console.log(myPublishedPosts); - * - * @name Query.ops - * @property {Function} == Equality operator. - * @property {Function} != Inequality operator. - * @property {Function} > Greater than operator. - * @property {Function} >= Greater than (inclusive) operator. - * @property {Function} < Less than operator. - * @property {Function} <= Less than (inclusive) operator. - * @property {Function} isectEmpty Operator that asserts that the intersection - * between two arrays is empty. - * @property {Function} isectNotEmpty Operator that asserts that the - * intersection between two arrays is __not__ empty. - * @property {Function} in Operator that asserts whether a value is in an - * array. - * @property {Function} notIn Operator that asserts whether a value is __not__ - * in an array. - * @property {Function} contains Operator that asserts whether an array - * contains a value. - * @property {Function} notContains Operator that asserts whether an array - * does __not__ contain a value. - * @since 3.0.0 - * @type {Object} - */ - ops: { - '=': function _(value, predicate) { - return value == predicate; // eslint-disable-line - }, - '==': function _(value, predicate) { - return value == predicate; // eslint-disable-line - }, - '===': function _(value, predicate) { - return value === predicate; - }, - '!=': function _(value, predicate) { - return value != predicate; // eslint-disable-line - }, - '!==': function _(value, predicate) { - return value !== predicate; - }, - '>': function _(value, predicate) { - return value > predicate; - }, - '>=': function _(value, predicate) { - return value >= predicate; - }, - '<': function _(value, predicate) { - return value < predicate; - }, - '<=': function _(value, predicate) { - return value <= predicate; - }, - isectEmpty: function isectEmpty(value, predicate) { - return !utils.intersection(value || [], predicate || []).length; - }, - isectNotEmpty: function isectNotEmpty(value, predicate) { - return utils.intersection(value || [], predicate || []).length; - }, - in: function _in(value, predicate) { - return predicate.indexOf(value) !== -1; - }, - notIn: function notIn(value, predicate) { - return predicate.indexOf(value) === -1; - }, - contains: function contains(value, predicate) { - return (value || []).indexOf(predicate) !== -1; - }, - notContains: function notContains(value, predicate) { - return (value || []).indexOf(predicate) === -1; - } - } -}); -/** - * Create a subclass of this Query: - * @example Query.extend - * const JSData = require('js-data'); - * const { Query } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * // Extend the class using ES2015 class syntax. - * class CustomQueryClass extends Query { - * foo () { return 'bar'; } - * static beep () { return 'boop'; } - * } - * const customQuery = new CustomQueryClass(); - * console.log(customQuery.foo()); - * console.log(CustomQueryClass.beep()); - * - * // Extend the class using alternate method. - * const OtherQueryClass = Query.extend({ - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }); - * const otherQuery = new OtherQueryClass(); - * console.log(otherQuery.foo()); - * console.log(OtherQueryClass.beep()); - * - * // Extend the class, providing a custom constructor. - * function AnotherQueryClass (collection) { - * Query.call(this, collection); - * this.created_at = new Date().getTime(); - * } - * Query.extend({ - * constructor: AnotherQueryClass, - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }); - * const anotherQuery = new AnotherQueryClass(); - * console.log(anotherQuery.created_at); - * console.log(anotherQuery.foo()); - * console.log(AnotherQueryClass.beep()); - * - * @method Query.extend - * @param {object} [props={}] Properties to add to the prototype of the - * subclass. - * @param {object} [props.constructor] Provide a custom constructor function - * to be used as the subclass itself. - * @param {object} [classProps={}] Static properties to add to the subclass. - * @returns {Constructor} Subclass of this Query class. - * @since 3.0.0 - */ - -var belongsToType = 'belongsTo'; -var hasManyType = 'hasMany'; -var hasOneType = 'hasOne'; -var DOMAIN$2 = 'Relation'; -function Relation(relatedMapper) { - var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - utils.classCallCheck(this, Relation); - options.type = this.constructor.TYPE_NAME; - this.validateOptions(relatedMapper, options); - - if (_typeof(relatedMapper) === 'object') { - Object.defineProperty(this, 'relatedMapper', { - value: relatedMapper - }); - } - - Object.defineProperty(this, 'inverse', { - writable: true - }); - utils.fillIn(this, options); -} -Relation.extend = utils.extend; -utils.addHiddenPropsToTarget(Relation.prototype, { - get canAutoAddLinks() { - return this.add === undefined || !!this.add; - }, - - get relatedCollection() { - return this.mapper.datastore.getCollection(this.relation); - }, - - validateOptions: function validateOptions(related, opts) { - var DOMAIN_ERR = "new ".concat(DOMAIN$2); - var localField = opts.localField; - - if (!localField) { - throw utils.err(DOMAIN_ERR, 'opts.localField')(400, 'string', localField); - } - - var foreignKey = opts.foreignKey = opts.foreignKey || opts.localKey; - - if (!foreignKey && (opts.type === belongsToType || opts.type === hasOneType)) { - throw utils.err(DOMAIN_ERR, 'opts.foreignKey')(400, 'string', foreignKey); - } - - if (utils.isString(related)) { - opts.relation = related; - - if (!utils.isFunction(opts.getRelation)) { - throw utils.err(DOMAIN_ERR, 'opts.getRelation')(400, 'function', opts.getRelation); - } - } else if (related) { - opts.relation = related.name; - } else { - throw utils.err(DOMAIN_ERR, 'related')(400, 'Mapper or string', related); - } - }, - assignTo: function assignTo(mapper) { - this.name = mapper.name; - Object.defineProperty(this, 'mapper', { - value: mapper - }); - mapper.relationList || Object.defineProperty(mapper, 'relationList', { - value: [] - }); - mapper.relationFields || Object.defineProperty(mapper, 'relationFields', { - value: [] - }); - mapper.relationList.push(this); - mapper.relationFields.push(this.localField); - }, - canFindLinkFor: function canFindLinkFor() { - return !!(this.foreignKey || this.localKey); - }, - getRelation: function getRelation() { - return this.relatedMapper; - }, - getForeignKey: function getForeignKey(record) { - return utils.get(record, this.mapper.idAttribute); - }, - setForeignKey: function setForeignKey(record, relatedRecord) { - if (!record || !relatedRecord) { - return; - } - - this._setForeignKey(record, relatedRecord); - }, - _setForeignKey: function _setForeignKey(record, relatedRecords) { - var _this = this; - - var idAttribute = this.mapper.idAttribute; - - if (!utils.isArray(relatedRecords)) { - relatedRecords = [relatedRecords]; - } - - relatedRecords.forEach(function (relatedRecord) { - utils.set(relatedRecord, _this.foreignKey, utils.get(record, idAttribute)); - }); - }, - getLocalField: function getLocalField(record) { - return utils.get(record, this.localField); - }, - setLocalField: function setLocalField(record, relatedData) { - return utils.set(record, this.localField, relatedData); - }, - getInverse: function getInverse(mapper) { - if (!this.inverse) { - this.findInverseRelation(mapper); - } - - return this.inverse; - }, - findInverseRelation: function findInverseRelation(mapper) { - var _this2 = this; - - this.getRelation().relationList.forEach(function (def) { - if (def.getRelation() === mapper && _this2.isInversedTo(def) && _this2 !== def) { - _this2.inverse = def; - return true; - } - }); - }, - isInversedTo: function isInversedTo(def) { - return !def.foreignKey || def.foreignKey === this.foreignKey; - }, - addLinkedRecords: function addLinkedRecords(records) { - var _this3 = this; - - var datastore = this.mapper.datastore; - records.forEach(function (record) { - var relatedData = _this3.getLocalField(record); - - if (utils.isFunction(_this3.add)) { - relatedData = _this3.add(datastore, _this3, record); - } else if (relatedData) { - relatedData = _this3.linkRecord(record, relatedData); - } - - var isEmptyLinks = !relatedData || utils.isArray(relatedData) && !relatedData.length; - - if (isEmptyLinks && _this3.canFindLinkFor(record)) { - relatedData = _this3.findExistingLinksFor(record); - } - - if (relatedData) { - _this3.setLocalField(record, relatedData); - } - }); - }, - removeLinkedRecords: function removeLinkedRecords(relatedMapper, records) { - var localField = this.localField; - records.forEach(function (record) { - utils.set(record, localField, undefined); - }); - }, - linkRecord: function linkRecord(record, relatedRecord) { - var relatedId = utils.get(relatedRecord, this.mapper.idAttribute); - - if (relatedId === undefined) { - var unsaved = this.relatedCollection.unsaved(); - - if (unsaved.indexOf(relatedRecord) === -1) { - if (this.canAutoAddLinks) { - relatedRecord = this.relatedCollection.add(relatedRecord); - } - } - } else { - if (relatedRecord !== this.relatedCollection.get(relatedId)) { - this.setForeignKey(record, relatedRecord); - - if (this.canAutoAddLinks) { - relatedRecord = this.relatedCollection.add(relatedRecord); - } - } - } - - return relatedRecord; - }, - // e.g. user hasMany post via "foreignKey", so find all posts of user - findExistingLinksByForeignKey: function findExistingLinksByForeignKey(id) { - if (id === undefined || id === null) { - return; - } - - return this.relatedCollection.filter(_defineProperty({}, this.foreignKey, id)); - }, - ensureLinkedDataHasProperType: function ensureLinkedDataHasProperType(props, opts) { - var relatedMapper = this.getRelation(); - var relationData = this.getLocalField(props); - - if (utils.isArray(relationData) && (!relationData.length || relatedMapper.is(relationData[0]))) { - return; - } - - if (relationData && !relatedMapper.is(relationData)) { - utils.set(props, this.localField, relatedMapper.createRecord(relationData, opts)); - } - }, - isRequiresParentId: function isRequiresParentId() { - return false; - }, - isRequiresChildId: function isRequiresChildId() { - return false; - }, - createChildRecord: function createChildRecord(props, relationData, opts) { - var _this4 = this; - - this.setForeignKey(props, relationData); - return this.createLinked(relationData, opts).then(function (result) { - _this4.setLocalField(props, result); - }); - }, - createLinked: function createLinked(props, opts) { - var create = utils.isArray(props) ? 'createMany' : 'create'; - return this.getRelation()[create](props, opts); - } -}); - -var BelongsToRelation = Relation.extend({ - getForeignKey: function getForeignKey(record) { - return utils.get(record, this.foreignKey); - }, - _setForeignKey: function _setForeignKey(record, relatedRecord) { - utils.set(record, this.foreignKey, utils.get(relatedRecord, this.getRelation().idAttribute)); - }, - findExistingLinksFor: function findExistingLinksFor(record) { - // console.log('\tBelongsTo#findExistingLinksFor', record) - if (!record) { - return; - } - - var relatedId = utils.get(record, this.foreignKey); - - if (relatedId !== undefined && relatedId !== null) { - return this.relatedCollection.get(relatedId); - } - }, - isRequiresParentId: function isRequiresParentId() { - return true; - }, - createParentRecord: function createParentRecord(props, opts) { - var _this = this; - - var relationData = this.getLocalField(props); - return this.createLinked(relationData, opts).then(function (record) { - _this.setForeignKey(props, record); - }); - }, - createChildRecord: function createChildRecord() { - throw new Error('"BelongsTo" relation does not support child creation as it cannot have children.'); - } -}, { - TYPE_NAME: 'belongsTo' -}); - -var HasManyRelation = Relation.extend({ - validateOptions: function validateOptions(related, opts) { - Relation.prototype.validateOptions.call(this, related, opts); - var localKeys = opts.localKeys, - foreignKeys = opts.foreignKeys, - foreignKey = opts.foreignKey; - - if (!foreignKey && !localKeys && !foreignKeys) { - throw utils.err('new Relation', 'opts.')(400, 'string', foreignKey); - } - }, - canFindLinkFor: function canFindLinkFor(record) { - var hasForeignKeys = this.foreignKey || this.foreignKeys; - return !!(hasForeignKeys || this.localKeys && utils.get(record, this.localKeys)); - }, - linkRecord: function linkRecord(record, relatedRecords) { - var _this = this; - - var relatedCollection = this.relatedCollection; - var canAutoAddLinks = this.canAutoAddLinks; - var foreignKey = this.foreignKey; - var unsaved = this.relatedCollection.unsaved(); - return relatedRecords.map(function (relatedRecord) { - var relatedId = relatedCollection.recordId(relatedRecord); - - if (relatedId === undefined && unsaved.indexOf(relatedRecord) === -1 || relatedRecord !== relatedCollection.get(relatedId)) { - if (foreignKey) { - // TODO: slow, could be optimized? But user loses hook - _this.setForeignKey(record, relatedRecord); - } - - if (canAutoAddLinks) { - relatedRecord = relatedCollection.add(relatedRecord); - } - } - - return relatedRecord; - }); - }, - findExistingLinksFor: function findExistingLinksFor(record) { - var id = utils.get(record, this.mapper.idAttribute); - var ids = this.localKeys ? utils.get(record, this.localKeys) : null; - var records; - - if (id !== undefined && this.foreignKey) { - records = this.findExistingLinksByForeignKey(id); - } else if (this.localKeys && ids) { - records = this.findExistingLinksByLocalKeys(ids); - } else if (id !== undefined && this.foreignKeys) { - records = this.findExistingLinksByForeignKeys(id); - } - - if (records && records.length) { - return records; - } - }, - // e.g. user hasMany group via "foreignKeys", so find all users of a group - findExistingLinksByLocalKeys: function findExistingLinksByLocalKeys(ids) { - return this.relatedCollection.filter({ - where: _defineProperty({}, this.relatedCollection.mapper.idAttribute, { - in: ids - }) - }); - }, - // e.g. group hasMany user via "localKeys", so find all groups that own a user - findExistingLinksByForeignKeys: function findExistingLinksByForeignKeys(id) { - return this.relatedCollection.filter({ - where: _defineProperty({}, this.foreignKeys, { - contains: id - }) - }); - }, - isRequiresParentId: function isRequiresParentId() { - return !!this.localKeys && this.localKeys.length > 0; - }, - isRequiresChildId: function isRequiresChildId() { - return !!this.foreignKey; - }, - createParentRecord: function createParentRecord(props, opts) { - var _this2 = this; - - var relationData = this.getLocalField(props); - var foreignIdField = this.getRelation().idAttribute; - return this.createLinked(relationData, opts).then(function (records) { - utils.set(props, _this2.localKeys, records.map(function (record) { - return utils.get(record, foreignIdField); - })); - }); - }, - createLinked: function createLinked(props, opts) { - return this.getRelation().createMany(props, opts); - } -}, { - TYPE_NAME: 'hasMany' -}); - -var HasOneRelation = Relation.extend({ - findExistingLinksFor: function findExistingLinksFor(relatedMapper, record) { - var recordId = utils.get(record, relatedMapper.idAttribute); - var records = this.findExistingLinksByForeignKey(recordId); - - if (records && records.length) { - return records[0]; - } - }, - isRequiresChildId: function isRequiresChildId() { - return true; - } -}, { - TYPE_NAME: 'hasOne' -}); - -[BelongsToRelation, HasManyRelation, HasOneRelation].forEach(function (RelationType) { - Relation[RelationType.TYPE_NAME] = function (related, options) { - return new RelationType(related, options); - }; -}); - -/** - * BelongsTo relation decorator. You probably won't use this directly. - * - * @name module:js-data.belongsTo - * @method - * @param {Mapper} related The relation the target belongs to. - * @param {object} opts Configuration options. - * @param {string} opts.foreignKey The field that holds the primary key of the - * related record. - * @param {string} opts.localField The field that holds a reference to the - * related record object. - * @returns {Function} Invocation function, which accepts the target as the only - * parameter. - */ - -var belongsTo = function belongsTo(related, opts) { - return function (mapper) { - Relation.belongsTo(related, opts).assignTo(mapper); - }; -}; -/** - * HasMany relation decorator. You probably won't use this directly. - * - * @name module:js-data.hasMany - * @method - * @param {Mapper} related The relation of which the target has many. - * @param {object} opts Configuration options. - * @param {string} [opts.foreignKey] The field that holds the primary key of the - * related record. - * @param {string} opts.localField The field that holds a reference to the - * related record object. - * @returns {Function} Invocation function, which accepts the target as the only - * parameter. - */ - -var hasMany = function hasMany(related, opts) { - return function (mapper) { - Relation.hasMany(related, opts).assignTo(mapper); - }; -}; -/** - * HasOne relation decorator. You probably won't use this directly. - * - * @name module:js-data.hasOne - * @method - * @param {Mapper} related The relation of which the target has one. - * @param {object} opts Configuration options. - * @param {string} [opts.foreignKey] The field that holds the primary key of the - * related record. - * @param {string} opts.localField The field that holds a reference to the - * related record object. - * @returns {Function} Invocation function, which accepts the target as the only - * parameter. - */ - -var hasOne = function hasOne(related, opts) { - return function (mapper) { - Relation.hasOne(related, opts).assignTo(mapper); - }; -}; - -var DOMAIN$3 = 'Record'; - -var superMethod = function superMethod(mapper, name) { - var store = mapper.datastore; - - if (store && store[name]) { - return function () { - for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { - args[_key] = arguments[_key]; - } - - return store[name].apply(store, [mapper.name].concat(args)); - }; - } - - return mapper[name].bind(mapper); -}; // Cache these strings - - -var creatingPath = 'creating'; -var noValidatePath = 'noValidate'; -var keepChangeHistoryPath = 'keepChangeHistory'; -var previousPath = 'previous'; -/** - * js-data's Record class. An instance of `Record` corresponds to an in-memory - * representation of a single row or document in a database, Firebase, - * localstorage, etc. Basically, a `Record` instance represents whatever kind of - * entity in your persistence layer that has a primary key. - * - * ```javascript - * import {Record} from 'js-data' - * ``` - * - * @example Record#constructor - * const JSData = require('js-data'); - * const { Record } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * // Instantiate a plain record - * let record = new Record(); - * console.log('record: ' + JSON.stringify(record)); - * - * // You can supply properties on instantiation - * record = new Record({ name: 'John' }); - * console.log('record: ' + JSON.stringify(record)); - * - * @example Record#constructor2 - * const JSData = require('js-data'); - * const { Mapper } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * // Instantiate a record that's associated with a Mapper: - * const UserMapper = new Mapper({ name: 'user' }); - * const User = UserMapper.recordClass; - * const user = UserMapper.createRecord({ name: 'John' }); - * const user2 = new User({ name: 'Sally' }); - * console.log('user: ' + JSON.stringify(user)); - * console.log('user2: ' + JSON.stringify(user2)); - * - * @example Record#constructor3 - * const JSData = require('js-data'); - * const { Container } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new Container(); - * store.defineMapper('user'); - * - * // Instantiate a record that's associated with a store's Mapper - * const user = store.createRecord('user', { name: 'John' }); - * console.log('user: ' + JSON.stringify(user)); - * - * @example Record#constructor4 - * const JSData = require('js-data'); - * const { Container } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new Container(); - * store.defineMapper('user', { - * schema: { - * properties: { - * name: { type: 'string' } - * } - * } - * }); - * - * // Validate on instantiation - * const user = store.createRecord('user', { name: 1234 }); - * console.log('user: ' + JSON.stringify(user)); - * - * @example Record#constructor5 - * const JSData = require('js-data'); - * const { Container } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new Container(); - * store.defineMapper('user', { - * schema: { - * properties: { - * name: { type: 'string' } - * } - * } - * }); - * - * // Skip validation on instantiation - * const user = store.createRecord('user', { name: 1234 }, { noValidate: true }); - * console.log('user: ' + JSON.stringify(user)); - * console.log('user.isValid(): ' + user.isValid()); - * - * @class Record - * @extends Component - * @param {object} [props] The initial properties of the new Record instance. - * @param {object} [opts] Configuration options. - * @param {boolean} [opts.noValidate=false] Whether to skip validation on the - * initial properties. - * @param {boolean} [opts.validateOnSet=true] Whether to enable setter - * validation on properties after the Record has been initialized. - * @since 3.0.0 - */ - -function Record(props, opts) { - utils.classCallCheck(this, Record); - Settable.call(this); - props || (props = {}); - opts || (opts = {}); - var _set = this._set; - var mapper = this.constructor.mapper; - - _set(creatingPath, true); - - _set(noValidatePath, !!opts.noValidate); - - _set(keepChangeHistoryPath, opts.keepChangeHistory === undefined ? mapper ? mapper.keepChangeHistory : true : opts.keepChangeHistory); // Set the idAttribute value first, if it exists. - - - var id = mapper ? utils.get(props, mapper.idAttribute) : undefined; - - if (id !== undefined) { - utils.set(this, mapper.idAttribute, id); - } - - utils.fillIn(this, props); - - _set(creatingPath, false); - - if (opts.validateOnSet !== undefined) { - _set(noValidatePath, !opts.validateOnSet); - } else if (mapper && mapper.validateOnSet !== undefined) { - _set(noValidatePath, !mapper.validateOnSet); - } else { - _set(noValidatePath, false); - } - - _set(previousPath, mapper ? mapper.toJSON(props) : utils.plainCopy(props)); -} - -var Record$1 = Component$1.extend({ - constructor: Record, - - /** - * Returns the {@link Mapper} paired with this record's class, if any. - * - * @method Record#_mapper - * @returns {Mapper} The {@link Mapper} paired with this record's class, if any. - * @since 3.0.0 - */ - _mapper: function _mapper() { - var mapper = this.constructor.mapper; - - if (!mapper) { - throw utils.err("".concat(DOMAIN$3, "#_mapper"), '')(404, 'mapper'); - } - - return mapper; - }, - - /** - * Lifecycle hook. - * - * @method Record#afterLoadRelations - * @param {string[]} relations The `relations` argument passed to {@link Record#loadRelations}. - * @param {object} opts The `opts` argument passed to {@link Record#loadRelations}. - * @since 3.0.0 - */ - afterLoadRelations: function afterLoadRelations() {}, - - /** - * Lifecycle hook. - * - * @method Record#beforeLoadRelations - * @param {string[]} relations The `relations` argument passed to {@link Record#loadRelations}. - * @param {object} opts The `opts` argument passed to {@link Record#loadRelations}. - * @since 3.0.0 - */ - beforeLoadRelations: function beforeLoadRelations() {}, - - /** - * Return the change history of this record since it was instantiated or - * {@link Record#commit} was called. - * - * @method Record#changeHistory - * @since 3.0.0 - */ - changeHistory: function changeHistory() { - return (this._get('history') || []).slice(); - }, - - /** - * Return changes to this record since it was instantiated or - * {@link Record#commit} was called. - * - * @example Record#changes - * const JSData = require('js-data'); - * const { Container } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new Container(); - * store.defineMapper('user'); - * const user = store.createRecord('user'); - * console.log('user changes: ' + JSON.stringify(user.changes())); - * user.name = 'John'; - * console.log('user changes: ' + JSON.stringify(user.changes())); - * - * @method Record#changes - * @param [opts] Configuration options. - * @param {Function} [opts.equalsFn={@link utils.deepEqual}] Equality function. - * @param {array} [opts.ignore=[]] Array of strings or RegExp of fields to ignore. - * @returns {Object} Object describing the changes to this record since it was - * instantiated or its {@link Record#commit} method was last called. - * @since 3.0.0 - */ - changes: function changes(opts) { - opts || (opts = {}); - return utils.diffObjects(typeof this.toJSON === 'function' ? this.toJSON(opts) : this, this._get('previous'), opts); - }, - - /** - * Make the record's current in-memory state it's only state, with any - * previous property values being set to current values. - * - * @example Record#commit - * const JSData = require('js-data'); - * const { Container } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new Container(); - * store.defineMapper('user'); - * const user = store.createRecord('user'); - * console.log('user hasChanges: ' + user.hasChanges()); - * user.name = 'John'; - * console.log('user hasChanges: ' + user.hasChanges()); - * user.commit(); - * console.log('user hasChanges: ' + user.hasChanges()); - * - * @method Record#commit - * @param {object} [opts] Configuration options. Passed to {@link Record#toJSON}. - * @since 3.0.0 - */ - commit: function commit(opts) { - this._set('changed'); // unset - - - this._set('changing', false); - - this._set('history', []); // clear history - - - this._set('previous', this.toJSON(opts)); - }, - - /** - * Call {@link Mapper#destroy} using this record's primary key. - * - * @example - * import { Container } from 'js-data'; - * import { RethinkDBAdapter } from 'js-data-rethinkdb'; - * - * const store = new Container(); - * store.registerAdapter('rethink', new RethinkDBAdapter(), { default: true }); - * store.defineMapper('user'); - * store.find('user', 1234).then((user) => { - * console.log(user.id); // 1234 - * - * // Destroy this user from the database - * return user.destroy(); - * }); - * - * @method Record#destroy - * @param {object} [opts] Configuration options passed to {@link Mapper#destroy}. - * @returns {Promise} The result of calling {@link Mapper#destroy} with the - * primary key of this record. - * @since 3.0.0 - */ - destroy: function destroy(opts) { - opts || (opts = {}); - - var mapper = this._mapper(); - - return superMethod(mapper, 'destroy')(utils.get(this, mapper.idAttribute), opts); - }, - - /** - * Return the value at the given path for this instance. - * - * @example Record#get - * const JSData = require('js-data'); - * const { Container } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * const store = new Container(); - * store.defineMapper('user'); - * - * const user = store.createRecord('user', { name: 'Bob' }); - * console.log('user.get("name"): ' + user.get('name')); - * - * @method Record#get - * @param {string} key Path of value to retrieve. - * @returns {*} Value at path. - * @since 3.0.0 - */ - 'get': function get(key) { - return utils.get(this, key); - }, - - /** - * Return whether this record has changed since it was instantiated or - * {@link Record#commit} was called. - * - * @example Record#hasChanges - * const JSData = require('js-data'); - * const { Container } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * const store = new Container(); - * store.defineMapper('user'); - * const user = store.createRecord('user'); - * console.log('user hasChanges: ' + user.hasChanges()); - * user.name = 'John'; - * console.log('user hasChanges: ' + user.hasChanges()); - * user.commit(); - * console.log('user hasChanges: ' + user.hasChanges()); - * - * @method Record#hasChanges - * @param [opts] Configuration options. - * @param {Function} [opts.equalsFn={@link utils.deepEqual}] Equality function. - * @param {array} [opts.ignore=[]] Array of strings or RegExp of fields to ignore. - * @returns {boolean} Return whether the record has changed since it was - * instantiated or since its {@link Record#commit} method was called. - * @since 3.0.0 - */ - hasChanges: function hasChanges(opts) { - var quickHasChanges = !!(this._get('changed') || []).length; - return quickHasChanges || utils.areDifferent(typeof this.toJSON === 'function' ? this.toJSON(opts) : this, this._get('previous'), opts); - }, - - /** - * Return whether the record is unsaved. Records that have primary keys are - * considered "saved". Records without primary keys are considered "unsaved". - * - * @example Record#isNew - * const JSData = require('js-data'); - * const { Container } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * const store = new Container(); - * store.defineMapper('user'); - * const user = store.createRecord('user', { - * id: 1234 - * }); - * const user2 = store.createRecord('user'); - * console.log('user isNew: ' + user.isNew()); // false - * console.log('user2 isNew: ' + user2.isNew()); // true - * - * @method Record#isNew - * @returns {boolean} Whether the record is unsaved. - * @since 3.0.0 - */ - isNew: function isNew(opts) { - return utils.get(this, this._mapper().idAttribute) === undefined; - }, - - /** - * Return whether the record in its current state passes validation. - * - * @example Record#isValid - * const JSData = require('js-data'); - * const { Container } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * const store = new Container(); - * store.defineMapper('user', { - * schema: { - * properties: { - * name: { type: 'string' } - * } - * } - * }); - * const user = store.createRecord('user', { - * name: 1234 - * }, { - * noValidate: true // this allows us to put the record into an invalid state - * }); - * console.log('user isValid: ' + user.isValid()); - * user.name = 'John'; - * console.log('user isValid: ' + user.isValid()); - * - * @method Record#isValid - * @param {object} [opts] Configuration options. Passed to {@link Mapper#validate}. - * @returns {boolean} Whether the record in its current state passes - * validation. - * @since 3.0.0 - */ - isValid: function isValid(opts) { - return !this._mapper().validate(this, opts); - }, - removeInverseRelation: function removeInverseRelation(currentParent, id, inverseDef, idAttribute) { - var _this = this; - - if (inverseDef.type === hasOneType) { - safeSetLink(currentParent, inverseDef.localField, undefined); - } else if (inverseDef.type === hasManyType) { - // e.g. remove comment from otherPost.comments - var children = utils.get(currentParent, inverseDef.localField); - - if (id === undefined) { - utils.remove(children, function (child) { - return child === _this; - }); - } else { - utils.remove(children, function (child) { - return child === _this || id === utils.get(child, idAttribute); - }); - } - } - }, - setupInverseRelation: function setupInverseRelation(record, id, inverseDef, idAttribute) { - var _this2 = this; - - // Update (set) inverse relation - if (inverseDef.type === hasOneType) { - // e.g. someUser.profile = profile - safeSetLink(record, inverseDef.localField, this); - } else if (inverseDef.type === hasManyType) { - // e.g. add comment to somePost.comments - var children = utils.get(record, inverseDef.localField); - - if (id === undefined) { - utils.noDupeAdd(children, this, function (child) { - return child === _this2; - }); - } else { - utils.noDupeAdd(children, this, function (child) { - return child === _this2 || id === utils.get(child, idAttribute); - }); - } - } - }, - - /** - * Lazy load relations of this record, to be attached to the record once their - * loaded. - * - * @example - * import { Container } from 'js-data'; - * import { RethinkDBAdapter } from 'js-data-rethinkdb'; - * - * const store = new Container(); - * store.registerAdapter('rethink', new RethinkDBAdapter(), { default: true }); - * store.defineMapper('user', { - * relations: { - * hasMany: { - * post: { - * localField: 'posts', - * foreignKey: 'user_id' - * } - * } - * } - * }); - * store.defineMapper('post', { - * relations: { - * belongsTo: { - * user: { - * localField: 'user', - * foreignKey: 'user_id' - * } - * } - * } - * }); - * store.find('user', 1234).then((user) => { - * console.log(user.id); // 1234 - * - * // Load the user's post relations - * return user.loadRelations(['post']); - * }).then((user) => { - * console.log(user.posts); // [{...}, {...}, ...] - * }); - * - * @method Record#loadRelations - * @param {string[]} [relations] List of relations to load. Can use localField - * names or Mapper names to pick relations. - * @param {object} [opts] Configuration options. - * @returns {Promise} Resolves with the record, with the loaded relations now - * attached. - * @since 3.0.0 - */ - loadRelations: function loadRelations(relations, opts) { - var _this3 = this; - - var op; - - var mapper = this._mapper(); // Default values for arguments - - - relations || (relations = []); - - if (utils.isString(relations)) { - relations = [relations]; - } - - opts || (opts = {}); - opts.with = relations; // Fill in "opts" with the Model's configuration - - utils._(opts, mapper); - - opts.adapter = mapper.getAdapterName(opts); // beforeLoadRelations lifecycle hook - - op = opts.op = 'beforeLoadRelations'; - return utils.resolve(this[op](relations, opts)).then(function () { - // Now delegate to the adapter - op = opts.op = 'loadRelations'; - mapper.dbg(op, _this3, relations, opts); - var tasks = []; - var task; - utils.forEachRelation(mapper, opts, function (def, optsCopy) { - var relatedMapper = def.getRelation(); - optsCopy.raw = false; - - if (utils.isFunction(def.load)) { - task = def.load(mapper, def, _this3, opts); - } else if (def.type === 'hasMany' || def.type === 'hasOne') { - if (def.foreignKey) { - task = superMethod(relatedMapper, 'findAll')(_defineProperty({}, def.foreignKey, utils.get(_this3, mapper.idAttribute)), optsCopy).then(function (relatedData) { - if (def.type === 'hasOne') { - return relatedData.length ? relatedData[0] : undefined; - } - - return relatedData; - }); - } else if (def.localKeys) { - task = superMethod(relatedMapper, 'findAll')({ - where: _defineProperty({}, relatedMapper.idAttribute, { - in: utils.get(_this3, def.localKeys) - }) - }); - } else if (def.foreignKeys) { - task = superMethod(relatedMapper, 'findAll')({ - where: _defineProperty({}, def.foreignKeys, { - contains: utils.get(_this3, mapper.idAttribute) - }) - }, opts); - } - } else if (def.type === 'belongsTo') { - var key = utils.get(_this3, def.foreignKey); - - if (utils.isSorN(key)) { - task = superMethod(relatedMapper, 'find')(key, optsCopy); - } - } - - if (task) { - task = task.then(function (relatedData) { - def.setLocalField(_this3, relatedData); - }); - tasks.push(task); - } - }); - return Promise.all(tasks); - }).then(function () { - // afterLoadRelations lifecycle hook - op = opts.op = 'afterLoadRelations'; - return utils.resolve(_this3[op](relations, opts)).then(function () { - return _this3; - }); - }); - }, - - /** - * Return the properties with which this record was instantiated. - * - * @example Record#previous - * const JSData = require('js-data'); - * const { Container } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * const store = new Container(); - * store.defineMapper('user'); - * const user = store.createRecord('user', { - * name: 'William' - * }); - * console.log('user previous: ' + JSON.stringify(user.previous())); - * user.name = 'Bob'; - * console.log('user previous: ' + JSON.stringify(user.previous())); - * user.commit(); - * console.log('user previous: ' + JSON.stringify(user.previous())); - * - * @method Record#previous - * @param {string} [key] If specified, return just the initial value of the - * given key. - * @returns {Object} The initial properties of this record. - * @since 3.0.0 - */ - previous: function previous(key) { - if (key) { - return this._get("previous.".concat(key)); - } - - return this._get('previous'); - }, - - /** - * Revert changes to this record back to the properties it had when it was - * instantiated. - * - * @example Record#revert - * const JSData = require('js-data'); - * const { Container } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * const store = new Container(); - * store.defineMapper('user'); - * const user = store.createRecord('user', { - * name: 'William' - * }); - * console.log('user: ' + JSON.stringify(user)); - * user.name = 'Bob'; - * console.log('user: ' + JSON.stringify(user)); - * user.revert(); - * console.log('user: ' + JSON.stringify(user)); - * - * @method Record#revert - * @param {object} [opts] Configuration options. - * @param {string[]} [opts.preserve] Array of strings or Regular Expressions - * denoting properties that should not be reverted. - * @since 3.0.0 - */ - revert: function revert(opts) { - var _this4 = this; - - var previous = this._get('previous'); - - opts || (opts = {}); - opts.preserve || (opts.preserve = []); - utils.forOwn(this, function (value, key) { - if (key !== _this4._mapper().idAttribute && !Object.hasOwnProperty.call(previous, key) && Object.hasOwnProperty.call(_this4, key) && opts.preserve.indexOf(key) === -1) { - delete _this4[key]; - } - }); - utils.forOwn(previous, function (value, key) { - if (opts.preserve.indexOf(key) === -1) { - _this4[key] = value; - } - }); - this.commit(); - }, - - /** - * Delegates to {@link Mapper#create} or {@link Mapper#update}. - * - * @example - * import { Container } from 'js-data'; - * import { RethinkDBAdapter } from 'js-data-rethinkdb'; - * - * const store = new Container(); - * store.registerAdapter('rethink', new RethinkDBAdapter(), { default: true }); - * store.defineMapper('session'); - * const session = store.createRecord('session', { topic: 'Node.js' }); - * - * // Create a new record in the database - * session.save().then(() => { - * console.log(session.id); // 1234 - * - * session.skill_level = 'beginner'; - * - * // Update the record in the database - * return session.save(); - * }); - * - * @method Record#save - * @param {object} [opts] Configuration options. See {@link Mapper#create} and - * {@link Mapper#update}. - * @param {boolean} [opts.changesOnly] Equality function. Default uses `===`. - * @param {Function} [opts.equalsFn] Passed to {@link Record#changes} when - * `opts.changesOnly` is `true`. - * @param {array} [opts.ignore] Passed to {@link Record#changes} when - * `opts.changesOnly` is `true`. - * @returns {Promise} The result of calling {@link Mapper#create} or - * {@link Mapper#update}. - * @since 3.0.0 - */ - save: function save(opts) { - var _this5 = this; - - opts || (opts = {}); - - var mapper = this._mapper(); - - var id = utils.get(this, mapper.idAttribute); - var props = this; - - var postProcess = function postProcess(result) { - var record = opts.raw ? result.data : result; - - if (record) { - utils.deepMixIn(_this5, record); - - _this5.commit(); - } - - return result; - }; - - if (id === undefined) { - return superMethod(mapper, 'create')(props, opts).then(postProcess); - } - - if (opts.changesOnly) { - var changes = this.changes(opts); - props = {}; - utils.fillIn(props, changes.added); - utils.fillIn(props, changes.changed); - } - - return superMethod(mapper, 'update')(id, props, opts).then(postProcess); - }, - - /** - * Set the value for a given key, or the values for the given keys if "key" is - * an object. Triggers change events on those properties that have `track: true` - * in {@link Mapper#schema}. - * - * @example Record#set - * const JSData = require('js-data'); - * const { Container } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * const store = new Container(); - * store.defineMapper('user'); - * - * const user = store.createRecord('user'); - * console.log('user: ' + JSON.stringify(user)); - * - * user.set('name', 'Bob'); - * console.log('user: ' + JSON.stringify(user)); - * - * user.set({ age: 30, role: 'admin' }); - * console.log('user: ' + JSON.stringify(user)); - * - * @fires Record#change - * @method Record#set - * @param {(string|Object)} key Key to set or hash of key-value pairs to set. - * @param {*} [value] Value to set for the given key. - * @param {object} [opts] Configuration options. - * @param {boolean} [opts.silent=false] Whether to trigger change events. - * @since 3.0.0 - */ - 'set': function set(key, value, opts) { - if (utils.isObject(key)) { - opts = value; - } - - opts || (opts = {}); - - if (opts.silent) { - this._set('silent', true); - } - - utils.set(this, key, value); - - if (!this._get('eventId')) { - this._set('silent'); // unset - - } - }, - - /** - * Return a plain object representation of this record. If the class from - * which this record was created has a Mapper, then {@link Mapper#toJSON} will - * be called with this record instead. - * - * @example Record#toJSON - * const JSData = require('js-data'); - * const { Container } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * const store = new Container(); - * store.defineMapper('user', { - * schema: { - * properties: { - * name: { type: 'string' } - * } - * } - * }); - * - * const user = store.createRecord('user', { - * name: 'John', - * $$hashKey: '1234' - * }); - * console.log('user: ' + JSON.stringify(user.toJSON())); - * - * @method Record#toJSON - * @param {object} [opts] Configuration options. - * @param {string[]} [opts.with] Array of relation names or relation fields - * to include in the representation. Only available as an option if the class - * from which this record was created has a Mapper and this record resides in - * an instance of {@link DataStore}. - * @returns {Object} Plain object representation of this record. - * @since 3.0.0 - */ - toJSON: function toJSON(opts) { - var mapper = this.constructor.mapper; - - if (mapper) { - return mapper.toJSON(this, opts); - } else { - var json = {}; - utils.forOwn(this, function (prop, key) { - json[key] = utils.plainCopy(prop); - }); - return json; - } - }, - - /** - * Unset the value for a given key. Triggers change events on those properties - * that have `track: true` in {@link Mapper#schema}. - * - * @example Record#unset - * const JSData = require('js-data'); - * const { Container } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * const store = new Container(); - * store.defineMapper('user'); - * - * const user = store.createRecord('user', { - * name: 'John' - * }); - * console.log('user: ' + JSON.stringify(user)); - * - * user.unset('name'); - * console.log('user: ' + JSON.stringify(user)); - * - * @method Record#unset - * @param {string} key Key to unset. - * @param {object} [opts] Configuration options. - * @param {boolean} [opts.silent=false] Whether to trigger change events. - * @since 3.0.0 - */ - unset: function unset(key, opts) { - this.set(key, undefined, opts); - }, - - /** - * Validate this record based on its current properties. - * - * @example Record#validate - * const JSData = require('js-data'); - * const { Container } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * const store = new Container(); - * store.defineMapper('user', { - * schema: { - * properties: { - * name: { type: 'string' } - * } - * } - * }); - * const user = store.createRecord('user', { - * name: 1234 - * }, { - * noValidate: true // this allows us to put the record into an invalid state - * }); - * console.log('user validation: ' + JSON.stringify(user.validate())); - * user.name = 'John'; - * console.log('user validation: ' + user.validate()); - * - * @method Record#validate - * @param {object} [opts] Configuration options. Passed to {@link Mapper#validate}. - * @returns {*} Array of errors or `undefined` if no errors. - * @since 3.0.0 - */ - validate: function validate(opts) { - return this._mapper().validate(this, opts); - } -}, { - creatingPath: creatingPath, - noValidatePath: noValidatePath, - keepChangeHistoryPath: keepChangeHistoryPath, - previousPath: previousPath -}); -/** - * Allow records to emit events. - * - * An record's registered listeners are stored in the record's private data. - */ - -utils.eventify(Record.prototype, function () { - return this._get('events'); -}, function (value) { - this._set('events', value); -}); -/** - * Fired when a record changes. Only works for records that have tracked fields. - * See {@link Record~changeListener} on how to listen for this event. - * - * @event Record#change - * @see Record~changeListener - */ - -/** - * Callback signature for the {@link Record#event:change} event. - * - * @example - * function onChange (record, changes) { - * // do something - * } - * record.on('change', onChange); - * - * @callback Record~changeListener - * @param {Record} The Record that changed. - * @param {object} The changes. - * @see Record#event:change - * @since 3.0.0 - */ - -/** - * Create a subclass of this Record: - * @example Record.extend - * const JSData = require('js-data'); - * const { Record } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * // Extend the class using ES2015 class syntax. - * class CustomRecordClass extends Record { - * foo () { return 'bar'; } - * static beep () { return 'boop'; } - * } - * const customRecord = new CustomRecordClass(); - * console.log(customRecord.foo()); - * console.log(CustomRecordClass.beep()); - * - * // Extend the class using alternate method. - * const OtherRecordClass = Record.extend({ - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }); - * const otherRecord = new OtherRecordClass(); - * console.log(otherRecord.foo()); - * console.log(OtherRecordClass.beep()); - * - * // Extend the class, providing a custom constructor. - * function AnotherRecordClass () { - * Record.call(this); - * this.created_at = new Date().getTime(); - * } - * Record.extend({ - * constructor: AnotherRecordClass, - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }); - * const anotherRecord = new AnotherRecordClass(); - * console.log(anotherRecord.created_at); - * console.log(anotherRecord.foo()); - * console.log(AnotherRecordClass.beep()); - * - * @method Record.extend - * @param {object} [props={}] Properties to add to the prototype of the - * subclass. - * @param {object} [props.constructor] Provide a custom constructor function - * to be used as the subclass itself. - * @param {object} [classProps={}] Static properties to add to the subclass. - * @returns {Constructor} Subclass of this Record class. - * @since 3.0.0 - */ - -function sort(a, b, hashCode) { - // Short-circuit comparison if a and b are strictly equal - // This is absolutely necessary for indexed objects that - // don't have the idAttribute field - if (a === b) { - return 0; - } - - if (hashCode) { - a = hashCode(a); - b = hashCode(b); - } - - if (a === null && b === null || a === undefined && b === undefined) { - return -1; - } - - if (a === null || a === undefined) { - return -1; - } - - if (b === null || b === undefined) { - return 1; - } - - if (a < b) { - return -1; - } - - if (a > b) { - return 1; - } - - return 0; -} -function insertAt(array, index, value) { - array.splice(index, 0, value); - return array; -} -function removeAt(array, index) { - array.splice(index, 1); - return array; -} -function binarySearch(array, value, field) { - var lo = 0; - var hi = array.length; - var compared; - var mid; - - while (lo < hi) { - mid = (lo + hi) / 2 | 0; - compared = sort(value, array[mid], field); - - if (compared === 0) { - return { - found: true, - index: mid - }; - } else if (compared < 0) { - hi = mid; - } else { - lo = mid + 1; - } - } - - return { - found: false, - index: hi - }; -} - -// Copyright (c) 2015, InternalFX. -function Index(fieldList, opts) { - utils.classCallCheck(this, Index); - fieldList || (fieldList = []); - - if (!utils.isArray(fieldList)) { - throw new Error('fieldList must be an array.'); - } - - opts || (opts = {}); - this.fieldList = fieldList; - this.fieldGetter = opts.fieldGetter; - this.hashCode = opts.hashCode; - this.isIndex = true; - this.keys = []; - this.values = []; -} -utils.addHiddenPropsToTarget(Index.prototype, { - 'set': function set(keyList, value) { - if (!utils.isArray(keyList)) { - keyList = [keyList]; - } - - var key = keyList.shift() || undefined; - var pos = binarySearch(this.keys, key); - - if (keyList.length === 0) { - if (pos.found) { - var dataLocation = binarySearch(this.values[pos.index], value, this.hashCode); - - if (!dataLocation.found) { - insertAt(this.values[pos.index], dataLocation.index, value); - } - } else { - insertAt(this.keys, pos.index, key); - insertAt(this.values, pos.index, [value]); - } - } else { - if (pos.found) { - this.values[pos.index].set(keyList, value); - } else { - insertAt(this.keys, pos.index, key); - var newIndex = new Index([], { - hashCode: this.hashCode - }); - newIndex.set(keyList, value); - insertAt(this.values, pos.index, newIndex); - } - } - }, - 'get': function get(keyList) { - if (!utils.isArray(keyList)) { - keyList = [keyList]; - } - - var key = keyList.shift() || undefined; - var pos = binarySearch(this.keys, key); - - if (keyList.length === 0) { - if (pos.found) { - if (this.values[pos.index].isIndex) { - return this.values[pos.index].getAll(); - } else { - return this.values[pos.index].slice(); - } - } else { - return []; - } - } else { - if (pos.found) { - return this.values[pos.index].get(keyList); - } else { - return []; - } - } - }, - getAll: function getAll(opts) { - opts || (opts = {}); - var results = []; - var values = this.values; - - if (opts.order === 'desc') { - for (var i = values.length - 1; i >= 0; i--) { - var value = values[i]; - - if (value.isIndex) { - results = results.concat(value.getAll(opts)); - } else { - results = results.concat(value); - } - } - } else { - for (var _i = 0; _i < values.length; _i++) { - var _value = values[_i]; - - if (_value.isIndex) { - results = results.concat(_value.getAll(opts)); - } else { - results = results.concat(_value); - } - } - } - - return results; - }, - visitAll: function visitAll(cb, thisArg) { - this.values.forEach(function (value) { - if (value.isIndex) { - value.visitAll(cb, thisArg); - } else { - value.forEach(cb, thisArg); - } - }); - }, - between: function between(leftKeys, rightKeys, opts) { - opts || (opts = {}); - - if (!utils.isArray(leftKeys)) { - leftKeys = [leftKeys]; - } - - if (!utils.isArray(rightKeys)) { - rightKeys = [rightKeys]; - } - - utils.fillIn(opts, { - leftInclusive: true, - rightInclusive: false, - limit: undefined, - offset: 0 - }); - - var results = this._between(leftKeys, rightKeys, opts); - - if (opts.limit) { - return results.slice(opts.offset, opts.limit + opts.offset); - } else { - return results.slice(opts.offset); - } - }, - _between: function _between(leftKeys, rightKeys, opts) { - var results = []; - var leftKey = leftKeys.shift(); - var rightKey = rightKeys.shift(); - var pos; - - if (leftKey !== undefined) { - pos = binarySearch(this.keys, leftKey); - } else { - pos = { - found: false, - index: 0 - }; - } - - if (leftKeys.length === 0) { - if (pos.found && opts.leftInclusive === false) { - pos.index += 1; - } - - for (var i = pos.index; i < this.keys.length; i += 1) { - if (rightKey !== undefined) { - if (opts.rightInclusive) { - if (this.keys[i] > rightKey) { - break; - } - } else { - if (this.keys[i] >= rightKey) { - break; - } - } - } - - if (this.values[i].isIndex) { - results = results.concat(this.values[i].getAll()); - } else { - results = results.concat(this.values[i]); - } - - if (opts.limit) { - if (results.length >= opts.limit + opts.offset) { - break; - } - } - } - } else { - for (var _i2 = pos.index; _i2 < this.keys.length; _i2 += 1) { - var currKey = this.keys[_i2]; - - if (currKey > rightKey) { - break; - } - - if (this.values[_i2].isIndex) { - if (currKey === leftKey) { - results = results.concat(this.values[_i2]._between(utils.copy(leftKeys), rightKeys.map(function () { - return undefined; - }), opts)); - } else if (currKey === rightKey) { - results = results.concat(this.values[_i2]._between(leftKeys.map(function () { - return undefined; - }), utils.copy(rightKeys), opts)); - } else { - results = results.concat(this.values[_i2].getAll()); - } - } else { - results = results.concat(this.values[_i2]); - } - - if (opts.limit) { - if (results.length >= opts.limit + opts.offset) { - break; - } - } - } - } - - if (opts.limit) { - return results.slice(0, opts.limit + opts.offset); - } else { - return results; - } - }, - peek: function peek() { - if (this.values.length) { - if (this.values[0].isIndex) { - return this.values[0].peek(); - } else { - return this.values[0]; - } - } - - return []; - }, - clear: function clear() { - this.keys = []; - this.values = []; - }, - insertRecord: function insertRecord(data) { - var keyList = this.fieldList.map(function (field) { - if (utils.isFunction(field)) { - return field(data) || undefined; - } else { - return data[field] || undefined; - } - }); - this.set(keyList, data); - }, - removeRecord: function removeRecord(data) { - var _this = this; - - var removed; - var isUnique = this.hashCode(data) !== undefined; - this.values.forEach(function (value, i) { - if (value.isIndex) { - if (value.removeRecord(data)) { - if (value.keys.length === 0) { - removeAt(_this.keys, i); - removeAt(_this.values, i); - } - - removed = true; - return false; - } - } else { - var dataLocation = {}; - - if (_this.keys[i] === undefined || !isUnique) { - for (var j = value.length - 1; j >= 0; j--) { - if (value[j] === data) { - dataLocation = { - found: true, - index: j - }; - break; - } - } - } else if (isUnique) { - dataLocation = binarySearch(value, data, _this.hashCode); - } - - if (dataLocation.found) { - removeAt(value, dataLocation.index); - - if (value.length === 0) { - removeAt(_this.keys, i); - removeAt(_this.values, i); - } - - removed = true; - return false; - } - } - }); - return removed ? data : undefined; - }, - updateRecord: function updateRecord(data) { - var removed = this.removeRecord(data); - - if (removed !== undefined) { - this.insertRecord(data); - } - } -}); - -var noValidatePath$1 = Record$1.noValidatePath; -var DOMAIN$4 = 'Collection'; -var COLLECTION_DEFAULTS = { - /** - * Whether to call {@link Record#commit} on records that are added to the - * collection and already exist in the collection. - * - * @name Collection#commitOnMerge - * @type {boolean} - * @default true - */ - commitOnMerge: true, - - /** - * Whether record events should bubble up and be emitted by the collection. - * - * @name Collection#emitRecordEvents - * @type {boolean} - * @default true - */ - emitRecordEvents: true, - - /** - * Field to be used as the unique identifier for records in this collection. - * Defaults to `"id"` unless {@link Collection#mapper} is set, in which case - * this will default to {@link Mapper#idAttribute}. - * - * @name Collection#idAttribute - * @type {string} - * @default "id" - */ - idAttribute: 'id', - - /** - * What to do when inserting a record into this Collection that shares a - * primary key with a record already in this Collection. - * - * Possible values: - * merge - * replace - * skip - * - * Merge: - * - * Recursively shallow copy properties from the new record onto the existing - * record. - * - * Replace: - * - * Shallow copy top-level properties from the new record onto the existing - * record. Any top-level own properties of the existing record that are _not_ - * on the new record will be removed. - * - * Skip: - * - * Ignore new record, keep existing record. - * - * @name Collection#onConflict - * @type {string} - * @default "merge" - */ - onConflict: 'merge' -}; -/** - * An ordered set of {@link Record} instances. - * - * @example Collection#constructor - * // import { Collection, Record } from 'js-data'; - * const JSData = require('js-data'); - * const {Collection, Record} = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const user1 = new Record({ id: 1 }); - * const user2 = new Record({ id: 2 }); - * const UserCollection = new Collection([user1, user2]); - * console.log(UserCollection.get(1) === user1); - * - * @class Collection - * @extends Component - * @param {array} [records] Initial set of records to insert into the - * collection. - * @param {object} [opts] Configuration options. - * @param {string} [opts.commitOnMerge] See {@link Collection#commitOnMerge}. - * @param {string} [opts.idAttribute] See {@link Collection#idAttribute}. - * @param {string} [opts.onConflict="merge"] See {@link Collection#onConflict}. - * @param {string} [opts.mapper] See {@link Collection#mapper}. - * @since 3.0.0 - */ - -function Collection(records, opts) { - utils.classCallCheck(this, Collection); - Component$1.call(this, opts); - - if (records && !utils.isArray(records)) { - opts = records; - records = []; - } - - if (utils.isString(opts)) { - opts = { - idAttribute: opts - }; - } // Default values for arguments - - - records || (records = []); - opts || (opts = {}); - Object.defineProperties(this, { - /** - * Default Mapper for this collection. Optional. If a Mapper is provided, then - * the collection will use the {@link Mapper#idAttribute} setting, and will - * wrap records in {@link Mapper#recordClass}. - * - * @example Collection#mapper - * const JSData = require('js-data'); - * const {Collection, Mapper} = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * class MyMapperClass extends Mapper { - * foo () { return 'bar'; } - * } - * const myMapper = new MyMapperClass({ name: 'myMapper' }); - * const collection = new Collection(null, { mapper: myMapper }); - * - * @name Collection#mapper - * @type {Mapper} - * @default null - * @since 3.0.0 - */ - mapper: { - value: undefined, - writable: true - }, - // Query class used by this collection - queryClass: { - value: undefined, - writable: true - } - }); // Apply user-provided configuration - - utils.fillIn(this, opts); // Fill in any missing options with the defaults - - utils.fillIn(this, utils.copy(COLLECTION_DEFAULTS)); - - if (!this.queryClass) { - this.queryClass = Query$1; - } - - var idAttribute = this.recordId(); - Object.defineProperties(this, { - /** - * The main index, which uses @{link Collection#recordId} as the key. - * - * @name Collection#index - * @type {Index} - */ - index: { - value: new Index([idAttribute], { - hashCode: function hashCode(obj) { - return utils.get(obj, idAttribute); - } - }) - }, - - /** - * Object that holds the secondary indexes of this collection. - * - * @name Collection#indexes - * @type {Object.} - */ - indexes: { - value: {} - } - }); // Insert initial data into the collection - - if (utils.isObject(records) || utils.isArray(records) && records.length) { - this.add(records); - } -} - -var Collection$1 = Component$1.extend({ - constructor: Collection, - - /** - * Used to bind to events emitted by records in this Collection. - * - * @method Collection#_onRecordEvent - * @since 3.0.0 - * @private - * @param {...*} [arg] Args passed to {@link Collection#emit}. - */ - _onRecordEvent: function _onRecordEvent() { - if (this.emitRecordEvents) { - this.emit.apply(this, arguments); - } - }, - - /** - * Insert the provided record or records. - * - * If a record is already in the collection then the provided record will - * either merge with or replace the existing record based on the value of the - * `onConflict` option. - * - * The collection's secondary indexes will be updated as each record is - * visited. - * - * @method Collection#add - * @since 3.0.0 - * @param {(Object|Object[]|Record|Record[])} data The record or records to insert. - * @param {object} [opts] Configuration options. - * @param {boolean} [opts.commitOnMerge=true] See {@link Collection#commitOnMerge}. - * @param {boolean} [opts.noValidate] See {@link Record#noValidate}. - * @param {string} [opts.onConflict] See {@link Collection#onConflict}. - * @returns {(Object|Object[]|Record|Record[])} The added record or records. - */ - add: function add(records, opts) { - var _this = this; - - // Default values for arguments - opts || (opts = {}); // Fill in "opts" with the Collection's configuration - - utils._(opts, this); - - records = this.beforeAdd(records, opts) || records; // Track whether just one record or an array of records is being inserted - - var singular = false; - var idAttribute = this.recordId(); - - if (!utils.isArray(records)) { - if (utils.isObject(records)) { - records = [records]; - singular = true; - } else { - throw utils.err("".concat(DOMAIN$4, "#add"), 'records')(400, 'object or array', records); - } - } // Map the provided records to existing records. - // New records will be inserted. If any records map to existing records, - // they will be merged into the existing records according to the onConflict - // option. - - - records = records.map(function (record) { - var id = _this.recordId(record); // Grab existing record if there is one - - - var existing = id === undefined ? id : _this.get(id); // If the currently visited record is just a reference to an existing - // record, then there is nothing to be done. Exit early. - - if (record === existing) { - return existing; - } - - if (existing) { - // Here, the currently visited record corresponds to a record already - // in the collection, so we need to merge them - var onConflict = opts.onConflict || _this.onConflict; - - if (onConflict !== 'merge' && onConflict !== 'replace' && onConflict !== 'skip') { - throw utils.err("".concat(DOMAIN$4, "#add"), 'opts.onConflict')(400, 'one of (merge, replace, skip)', onConflict, true); - } - - var existingNoValidate = existing._get(noValidatePath$1); - - if (opts.noValidate) { - // Disable validation - existing._set(noValidatePath$1, true); - } - - if (onConflict === 'merge') { - utils.deepMixIn(existing, record); - } else if (onConflict === 'replace') { - utils.forOwn(existing, function (value, key) { - if (key !== idAttribute && record[key] === undefined) { - existing[key] = undefined; - } - }); - existing.set(record); - } // else if(onConflict === 'skip'){ do nothing } - - - if (opts.noValidate) { - // Restore previous `noValidate` value - existing._set(noValidatePath$1, existingNoValidate); - } - - record = existing; - - if (opts.commitOnMerge && utils.isFunction(record.commit)) { - record.commit(); - } // Update all indexes in the collection - - - _this.updateIndexes(record); - } else { - // Here, the currently visted record does not correspond to any record - // in the collection, so (optionally) instantiate this record and insert - // it into the collection - record = _this.mapper ? _this.mapper.createRecord(record, opts) : record; - - _this.index.insertRecord(record); - - utils.forOwn(_this.indexes, function (index, name) { - index.insertRecord(record); - }); - - if (record && utils.isFunction(record.on)) { - record.on('all', _this._onRecordEvent, _this); - } - } - - return record; - }); // Finally, return the inserted data - - var result = singular ? records[0] : records; - - if (!opts.silent) { - this.emit('add', result); - } - - return this.afterAdd(records, opts, result) || result; - }, - - /** - * Lifecycle hook called by {@link Collection#add}. If this method returns a - * value then {@link Collection#add} will return that same value. - * - * @method Collection#method - * @since 3.0.0 - * @param {(Object|Object[]|Record|Record[])} result The record or records - * that were added to this Collection by {@link Collection#add}. - * @param {object} opts The `opts` argument passed to {@link Collection#add}. - */ - afterAdd: function afterAdd() {}, - - /** - * Lifecycle hook called by {@link Collection#remove}. If this method returns - * a value then {@link Collection#remove} will return that same value. - * - * @method Collection#afterRemove - * @since 3.0.0 - * @param {(string|number)} id The `id` argument passed to {@link Collection#remove}. - * @param {object} opts The `opts` argument passed to {@link Collection#remove}. - * @param {object} record The result that will be returned by {@link Collection#remove}. - */ - afterRemove: function afterRemove() {}, - - /** - * Lifecycle hook called by {@link Collection#removeAll}. If this method - * returns a value then {@link Collection#removeAll} will return that same - * value. - * - * @method Collection#afterRemoveAll - * @since 3.0.0 - * @param {object} query The `query` argument passed to {@link Collection#removeAll}. - * @param {object} opts The `opts` argument passed to {@link Collection#removeAll}. - * @param {object} records The result that will be returned by {@link Collection#removeAll}. - */ - afterRemoveAll: function afterRemoveAll() {}, - - /** - * Lifecycle hook called by {@link Collection#add}. If this method returns a - * value then the `records` argument in {@link Collection#add} will be - * re-assigned to the returned value. - * - * @method Collection#beforeAdd - * @since 3.0.0 - * @param {(Object|Object[]|Record|Record[])} records The `records` argument passed to {@link Collection#add}. - * @param {object} opts The `opts` argument passed to {@link Collection#add}. - */ - beforeAdd: function beforeAdd() {}, - - /** - * Lifecycle hook called by {@link Collection#remove}. - * - * @method Collection#beforeRemove - * @since 3.0.0 - * @param {(string|number)} id The `id` argument passed to {@link Collection#remove}. - * @param {object} opts The `opts` argument passed to {@link Collection#remove}. - */ - beforeRemove: function beforeRemove() {}, - - /** - * Lifecycle hook called by {@link Collection#removeAll}. - * - * @method Collection#beforeRemoveAll - * @since 3.0.0 - * @param {object} query The `query` argument passed to {@link Collection#removeAll}. - * @param {object} opts The `opts` argument passed to {@link Collection#removeAll}. - */ - beforeRemoveAll: function beforeRemoveAll() {}, - - /** - * Find all records between two boundaries. - * - * Shortcut for `collection.query().between(18, 30, { index: 'age' }).run()` - * - * @example - * // Get all users ages 18 to 30 - * const users = collection.between(18, 30, { index: 'age' }); - * - * @example - * // Same as above - * const users = collection.between([18], [30], { index: 'age' }); - * - * @method Collection#between - * @since 3.0.0 - * @param {array} leftKeys Keys defining the left boundary. - * @param {array} rightKeys Keys defining the right boundary. - * @param {object} [opts] Configuration options. - * @param {string} [opts.index] Name of the secondary index to use in the - * query. If no index is specified, the main index is used. - * @param {boolean} [opts.leftInclusive=true] Whether to include records - * on the left boundary. - * @param {boolean} [opts.rightInclusive=false] Whether to include records - * on the left boundary. - * @param {boolean} [opts.limit] Limit the result to a certain number. - * @param {boolean} [opts.offset] The number of resulting records to skip. - * @returns {Object[]|Record[]} The result. - */ - between: function between(leftKeys, rightKeys, opts) { - return this.query().between(leftKeys, rightKeys, opts).run(); - }, - - /** - * Create a new secondary index on the contents of the collection. - * - * @example - * // Index users by age - * collection.createIndex('age'); - * - * @example - * // Index users by status and role - * collection.createIndex('statusAndRole', ['status', 'role']); - * - * @method Collection#createIndex - * @since 3.0.0 - * @param {string} name The name of the new secondary index. - * @param {string[]} [fieldList] Array of field names to use as the key or - * compound key of the new secondary index. If no fieldList is provided, then - * the name will also be the field that is used to index the collection. - */ - createIndex: function createIndex(name, fieldList, opts) { - var _this2 = this; - - if (utils.isString(name) && fieldList === undefined) { - fieldList = [name]; - } - - opts || (opts = {}); - opts.hashCode || (opts.hashCode = function (obj) { - return _this2.recordId(obj); - }); - var index = this.indexes[name] = new Index(fieldList, opts); - this.index.visitAll(index.insertRecord, index); - }, - - /** - * Find the record or records that match the provided query or pass the - * provided filter function. - * - * Shortcut for `collection.query().filter(queryOrFn[, thisArg]).run()` - * - * @example Collection#filter - * const JSData = require('js-data'); - * const { Collection } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const collection = new Collection([ - * { id: 1, status: 'draft', created_at_timestamp: new Date().getTime() } - * ]); - * - * // Get the draft posts created less than three months ago - * let posts = collection.filter({ - * where: { - * status: { - * '==': 'draft' - * }, - * created_at_timestamp: { - * '>=': (new Date().getTime() - (1000 \* 60 \* 60 \* 24 \* 30 \* 3)) // 3 months ago - * } - * } - * }); - * console.log(posts); - * - * // Use a custom filter function - * posts = collection.filter((post) => post.id % 2 === 0); - * - * @method Collection#filter - * @param {(Object|Function)} [queryOrFn={}] Selection query or filter - * function. - * @param {object} [thisArg] Context to which to bind `queryOrFn` if - * `queryOrFn` is a function. - * @returns {Array} The result. - * @see query - * @since 3.0.0 - */ - filter: function filter(query, thisArg) { - return this.query().filter(query, thisArg).run(); - }, - - /** - * Iterate over all records. - * - * @example - * collection.forEach(function (record) { - * // do something - * }); - * - * @method Collection#forEach - * @since 3.0.0 - * @param {Function} forEachFn Iteration function. - * @param {*} [thisArg] Context to which to bind `forEachFn`. - * @returns {Array} The result. - */ - forEach: function forEach(cb, thisArg) { - this.index.visitAll(cb, thisArg); - }, - - /** - * Get the record with the given id. - * - * @method Collection#get - * @since 3.0.0 - * @param {(string|number)} id The primary key of the record to get. - * @returns {(Object|Record)} The record with the given id. - */ - get: function get(id) { - var instances = id === undefined ? [] : this.query().get(id).run(); - return instances.length ? instances[0] : undefined; - }, - - /** - * Find the record or records that match the provided keyLists. - * - * Shortcut for `collection.query().getAll(keyList1, keyList2, ...).run()` - * - * @example - * // Get the posts where "status" is "draft" or "inReview" - * const posts = collection.getAll('draft', 'inReview', { index: 'status' }); - * - * @example - * // Same as above - * const posts = collection.getAll(['draft'], ['inReview'], { index: 'status' }); - * - * @method Collection#getAll - * @since 3.0.0 - * @param {...Array} [keyList] Provide one or more keyLists, and all - * records matching each keyList will be retrieved. If no keyLists are - * provided, all records will be returned. - * @param {object} [opts] Configuration options. - * @param {string} [opts.index] Name of the secondary index to use in the - * query. If no index is specified, the main index is used. - * @returns {Array} The result. - */ - getAll: function getAll() { - var _this$query; - - return (_this$query = this.query()).getAll.apply(_this$query, arguments).run(); - }, - - /** - * Return the index with the given name. If no name is provided, return the - * main index. Throws an error if the specified index does not exist. - * - * @method Collection#getIndex - * @since 3.0.0 - * @param {string} [name] The name of the index to retrieve. - */ - getIndex: function getIndex(name) { - var index = name ? this.indexes[name] : this.index; - - if (!index) { - throw utils.err("".concat(DOMAIN$4, "#getIndex"), name)(404, 'index'); - } - - return index; - }, - - /** - * Limit the result. - * - * Shortcut for `collection.query().limit(maximumNumber).run()` - * - * @example - * const posts = collection.limit(10); - * - * @method Collection#limit - * @since 3.0.0 - * @param {number} num The maximum number of records to keep in the result. - * @returns {Array} The result. - */ - limit: function limit(num) { - return this.query().limit(num).run(); - }, - - /** - * Apply a mapping function to all records. - * - * @example - * const names = collection.map((user) => user.name); - * - * @method Collection#map - * @since 3.0.0 - * @param {Function} mapFn Mapping function. - * @param {*} [thisArg] Context to which to bind `mapFn`. - * @returns {Array} The result of the mapping. - */ - map: function map(cb, thisArg) { - var data = []; - this.index.visitAll(function (value) { - data.push(cb.call(thisArg, value)); - }); - return data; - }, - - /** - * Return the result of calling the specified function on each record in this - * collection's main index. - * - * @method Collection#mapCall - * @since 3.0.0 - * @param {string} funcName Name of function to call - * @parama {...*} [args] Remaining arguments to be passed to the function. - * @returns {Array} The result. - */ - mapCall: function mapCall(funcName) { - for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { - args[_key - 1] = arguments[_key]; - } - - var data = []; - this.index.visitAll(function (record) { - data.push(record[funcName].apply(record, args)); - }); - return data; - }, - - /** - * Return all "unsaved" (not uniquely identifiable) records in this colleciton. - * - * @method Collection#prune - * @param {object} [opts] Configuration options, passed to {@link Collection#removeAll}. - * @since 3.0.0 - * @returns {Array} The removed records, if any. - */ - prune: function prune(opts) { - return this.removeAll(this.unsaved(), opts); - }, - - /** - * Create a new query to be executed against the contents of the collection. - * The result will be all or a subset of the contents of the collection. - * - * @example - * // Grab page 2 of users between ages 18 and 30 - * collection.query() - * .between(18, 30, { index: 'age' }) // between ages 18 and 30 - * .skip(10) // second page - * .limit(10) // page size - * .run(); - * - * @method Collection#query - * @since 3.0.0 - * @returns {Query} New query object. - */ - query: function query() { - var Ctor = this.queryClass; - return new Ctor(this); - }, - - /** - * Return the primary key of the given, or if no record is provided, return the - * name of the field that holds the primary key of records in this Collection. - * - * @method Collection#recordId - * @since 3.0.0 - * @param {(Object|Record)} [record] The record whose primary key is to be - * returned. - * @returns {(string|number)} Primary key or name of field that holds primary - * key. - */ - recordId: function recordId(record) { - if (record) { - return utils.get(record, this.recordId()); - } - - return this.mapper ? this.mapper.idAttribute : this.idAttribute; - }, - - /** - * Reduce the data in the collection to a single value and return the result. - * - * @example - * const totalVotes = collection.reduce((prev, record) => { - * return prev + record.upVotes + record.downVotes; - * }, 0); - * - * @method Collection#reduce - * @since 3.0.0 - * @param {Function} cb Reduction callback. - * @param {*} initialValue Initial value of the reduction. - * @returns {*} The result. - */ - reduce: function reduce(cb, initialValue) { - var data = this.getAll(); - return data.reduce(cb, initialValue); - }, - - /** - * Remove the record with the given id from this Collection. - * - * @method Collection#remove - * @since 3.0.0 - * @param {(string|number|object|Record)} idOrRecord The primary key of the - * record to be removed, or a reference to the record that is to be removed. - * @param {object} [opts] Configuration options. - * @returns {Object|Record} The removed record, if any. - */ - remove: function remove(idOrRecord, opts) { - // Default values for arguments - opts || (opts = {}); - this.beforeRemove(idOrRecord, opts); - var record = utils.isSorN(idOrRecord) ? this.get(idOrRecord) : idOrRecord; // The record is in the collection, remove it - - if (utils.isObject(record)) { - record = this.index.removeRecord(record); - - if (record) { - utils.forOwn(this.indexes, function (index, name) { - index.removeRecord(record); - }); - - if (utils.isFunction(record.off)) { - record.off('all', this._onRecordEvent, this); - } - - if (!opts.silent) { - this.emit('remove', record); - } - } - } - - return this.afterRemove(idOrRecord, opts, record) || record; - }, - - /** - * Remove from this collection the given records or the records selected by - * the given "query". - * - * @method Collection#removeAll - * @since 3.0.0 - * @param {Object|Object[]|Record[]} [queryOrRecords={}] Records to be removed or selection query. See {@link query}. - * @param {object} [queryOrRecords.where] See {@link query.where}. - * @param {number} [queryOrRecords.offset] See {@link query.offset}. - * @param {number} [queryOrRecords.limit] See {@link query.limit}. - * @param {string|Array[]} [queryOrRecords.orderBy] See {@link query.orderBy}. - * @param {object} [opts] Configuration options. - * @returns {(Object[]|Record[])} The removed records, if any. - */ - removeAll: function removeAll(queryOrRecords, opts) { - var _this3 = this; - - // Default values for arguments - opts || (opts = {}); - this.beforeRemoveAll(queryOrRecords, opts); - var records = utils.isArray(queryOrRecords) ? queryOrRecords.slice() : this.filter(queryOrRecords); // Remove each selected record from the collection - - var optsCopy = utils.plainCopy(opts); - optsCopy.silent = true; - records = records.map(function (record) { - return _this3.remove(record, optsCopy); - }).filter(function (record) { - return record; - }); - - if (!opts.silent) { - this.emit('remove', records); - } - - return this.afterRemoveAll(queryOrRecords, opts, records) || records; - }, - - /** - * Skip a number of results. - * - * Shortcut for `collection.query().skip(numberToSkip).run()` - * - * @example - * const posts = collection.skip(10); - * - * @method Collection#skip - * @since 3.0.0 - * @param {number} num The number of records to skip. - * @returns {Array} The result. - */ - skip: function skip(num) { - return this.query().skip(num).run(); - }, - - /** - * Return the plain JSON representation of all items in this collection. - * Assumes records in this collection have a toJSON method. - * - * @method Collection#toJSON - * @since 3.0.0 - * @param {object} [opts] Configuration options. - * @param {string[]} [opts.with] Array of relation names or relation fields - * to include in the representation. - * @returns {Array} The records. - */ - toJSON: function toJSON(opts) { - return this.mapCall('toJSON', opts); - }, - - /** - * Return all "unsaved" (not uniquely identifiable) records in this colleciton. - * - * @method Collection#unsaved - * @since 3.0.0 - * @returns {Array} The unsaved records, if any. - */ - unsaved: function unsaved(opts) { - return this.index.get(); - }, - - /** - * Update a record's position in a single index of this collection. See - * {@link Collection#updateIndexes} to update a record's position in all - * indexes at once. - * - * @method Collection#updateIndex - * @since 3.0.0 - * @param {object} record The record to update. - * @param {object} [opts] Configuration options. - * @param {string} [opts.index] The index in which to update the record's - * position. If you don't specify an index then the record will be updated - * in the main index. - */ - updateIndex: function updateIndex(record, opts) { - opts || (opts = {}); - this.getIndex(opts.index).updateRecord(record); - }, - - /** - * Updates all indexes in this collection for the provided record. Has no - * effect if the record is not in the collection. - * - * @method Collection#updateIndexes - * @since 3.0.0 - * @param {object} record TODO - */ - updateIndexes: function updateIndexes(record) { - this.index.updateRecord(record); - utils.forOwn(this.indexes, function (index, name) { - index.updateRecord(record); - }); - } -}); -/** - * Fired when a record changes. Only works for records that have tracked changes. - * See {@link Collection~changeListener} on how to listen for this event. - * - * @event Collection#change - * @see Collection~changeListener - */ - -/** - * Callback signature for the {@link Collection#event:change} event. - * - * @example - * function onChange (record, changes) { - * // do something - * } - * collection.on('change', onChange); - * - * @callback Collection~changeListener - * @param {Record} The Record that changed. - * @param {object} The changes. - * @see Collection#event:change - * @since 3.0.0 - */ - -/** - * Fired when one or more records are added to the Collection. See - * {@link Collection~addListener} on how to listen for this event. - * - * @event Collection#add - * @see Collection~addListener - * @see Collection#event:add - * @see Collection#add - */ - -/** - * Callback signature for the {@link Collection#event:add} event. - * - * @example - * function onAdd (recordOrRecords) { - * // do something - * } - * collection.on('add', onAdd); - * - * @callback Collection~addListener - * @param {Record|Record[]} The Record or Records that were added. - * @see Collection#event:add - * @see Collection#add - * @since 3.0.0 - */ - -/** - * Fired when one or more records are removed from the Collection. See - * {@link Collection~removeListener} for how to listen for this event. - * - * @event Collection#remove - * @see Collection~removeListener - * @see Collection#event:remove - * @see Collection#remove - * @see Collection#removeAll - */ - -/** - * Callback signature for the {@link Collection#event:remove} event. - * - * @example - * function onRemove (recordsOrRecords) { - * // do something - * } - * collection.on('remove', onRemove); - * - * @callback Collection~removeListener - * @param {Record|Record[]} Record or Records that were removed. - * @see Collection#event:remove - * @see Collection#remove - * @see Collection#removeAll - * @since 3.0.0 - */ - -/** - * Create a subclass of this Collection: - * @example Collection.extend - * const JSData = require('js-data'); - * const { Collection } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * // Extend the class using ES2015 class syntax. - * class CustomCollectionClass extends Collection { - * foo () { return 'bar'; } - * static beep () { return 'boop'; } - * } - * const customCollection = new CustomCollectionClass(); - * console.log(customCollection.foo()); - * console.log(CustomCollectionClass.beep()); - * - * // Extend the class using alternate method. - * const OtherCollectionClass = Collection.extend({ - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }); - * const otherCollection = new OtherCollectionClass(); - * console.log(otherCollection.foo()); - * console.log(OtherCollectionClass.beep()); - * - * // Extend the class, providing a custom constructor. - * function AnotherCollectionClass () { - * Collection.call(this); - * this.created_at = new Date().getTime(); - * } - * Collection.extend({ - * constructor: AnotherCollectionClass, - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }); - * const anotherCollection = new AnotherCollectionClass(); - * console.log(anotherCollection.created_at); - * console.log(anotherCollection.foo()); - * console.log(AnotherCollectionClass.beep()); - * - * @method Collection.extend - * @param {object} [props={}] Properties to add to the prototype of the - * subclass. - * @param {object} [props.constructor] Provide a custom constructor function - * to be used as the subclass itself. - * @param {object} [classProps={}] Static properties to add to the subclass. - * @returns {Constructor} Subclass of this Collection class. - * @since 3.0.0 - */ - -var DOMAIN$5 = 'Schema'; -/** - * A function map for each of the seven primitive JSON types defined by the core specification. - * Each function will check a given value and return true or false if the value is an instance of that type. - * ``` - * types.integer(1) // returns true - * types.string({}) // returns false - * ``` - * http://json-schema.org/latest/json-schema-core.html#anchor8 - * @name Schema.types - * @type {object} - */ - -var types = { - array: utils.isArray, - boolean: utils.isBoolean, - integer: utils.isInteger, - null: utils.isNull, - number: utils.isNumber, - object: utils.isObject, - string: utils.isString -}; -/** - * @ignore - */ - -var segmentToString = function segmentToString(segment, prev) { - var str = ''; - - if (segment) { - if (utils.isNumber(segment)) { - str += "[".concat(segment, "]"); - } else if (prev) { - str += ".".concat(segment); - } else { - str += "".concat(segment); - } - } - - return str; -}; -/** - * @ignore - */ - - -var makePath = function makePath(opts) { - opts || (opts = {}); - var path = ''; - var segments = opts.path || []; - segments.forEach(function (segment) { - path += segmentToString(segment, path); - }); - path += segmentToString(opts.prop, path); - return path; -}; -/** - * @ignore - */ - - -var makeError = function makeError(actual, expected, opts) { - return { - expected: expected, - actual: '' + actual, - path: makePath(opts) - }; -}; -/** - * @ignore - */ - - -var addError = function addError(actual, expected, opts, errors) { - errors.push(makeError(actual, expected, opts)); -}; -/** - * @ignore - */ - - -var maxLengthCommon = function maxLengthCommon(keyword, value, schema, opts) { - var max = schema[keyword]; - - if (value.length > max) { - return makeError(value.length, "length no more than ".concat(max), opts); - } -}; -/** - * @ignore - */ - - -var minLengthCommon = function minLengthCommon(keyword, value, schema, opts) { - var min = schema[keyword]; - - if (value.length < min) { - return makeError(value.length, "length no less than ".concat(min), opts); - } -}; -/** - * A map of all object member validation functions for each keyword defined in the JSON Schema. - * @name Schema.validationKeywords - * @type {object} - */ - - -var validationKeywords = { - /** - * Validates the provided value against all schemas defined in the Schemas `allOf` keyword. - * The instance is valid against if and only if it is valid against all the schemas declared in the Schema's value. - * - * The value of this keyword MUST be an array. This array MUST have at least one element. - * Each element of this array MUST be a valid JSON Schema. - * - * see http://json-schema.org/latest/json-schema-validation.html#anchor82 - * - * @name Schema.validationKeywords.allOf - * @method - * @param {*} value Value to be validated. - * @param {object} schema Schema containing the `allOf` keyword. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. - */ - allOf: function allOf(value, schema, opts) { - var allErrors = []; - schema.allOf.forEach(function (_schema) { - allErrors = allErrors.concat(_validate(value, _schema, opts) || []); - }); - return allErrors.length ? allErrors : undefined; - }, - - /** - * Validates the provided value against all schemas defined in the Schemas `anyOf` keyword. - * The instance is valid against this keyword if and only if it is valid against - * at least one of the schemas in this keyword's value. - * - * The value of this keyword MUST be an array. This array MUST have at least one element. - * Each element of this array MUST be an object, and each object MUST be a valid JSON Schema. - * see http://json-schema.org/latest/json-schema-validation.html#anchor85 - * - * @name Schema.validationKeywords.anyOf - * @method - * @param {*} value Value to be validated. - * @param {object} schema Schema containing the `anyOf` keyword. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. - */ - anyOf: function anyOf(value, schema, opts) { - var validated = false; - var allErrors = []; - schema.anyOf.forEach(function (_schema) { - var errors = _validate(value, _schema, opts); - - if (errors) { - allErrors = allErrors.concat(errors); - } else { - validated = true; - } - }); - return validated ? undefined : allErrors; - }, - - /** - * http://json-schema.org/latest/json-schema-validation.html#anchor70 - * - * @name Schema.validationKeywords.dependencies - * @method - * @param {*} value TODO - * @param {object} schema TODO - * @param {object} opts TODO - */ - dependencies: function dependencies(value, schema, opts) {// TODO - }, - - /** - * Validates the provided value against an array of possible values defined by the Schema's `enum` keyword - * Validation succeeds if the value is deeply equal to one of the values in the array. - * see http://json-schema.org/latest/json-schema-validation.html#anchor76 - * - * @name Schema.validationKeywords.enum - * @method - * @param {*} value Value to validate - * @param {object} schema Schema containing the `enum` keyword. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. - */ - enum: function _enum(value, schema, opts) { - var possibleValues = schema.enum; - - if (utils.findIndex(possibleValues, function (item) { - return utils.deepEqual(item, value); - }) === -1) { - return makeError(value, "one of (".concat(possibleValues.join(', '), ")"), opts); - } - }, - - /** - * Validates each of the provided array values against a schema or an array of schemas defined by the Schema's `items` keyword - * see http://json-schema.org/latest/json-schema-validation.html#anchor37 for validation rules. - * - * @name Schema.validationKeywords.items - * @method - * @param {*} value Array to be validated. - * @param {object} schema Schema containing the items keyword. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. - */ - items: function items(value, schema, opts) { - opts || (opts = {}); // TODO: additionalItems - - var items = schema.items; - var errors = []; - var checkingTuple = utils.isArray(items); - var length = value.length; - - for (var prop = 0; prop < length; prop++) { - if (checkingTuple) { - // Validating a tuple, instead of just checking each item against the - // same schema - items = schema.items[prop]; - } - - opts.prop = prop; - errors = errors.concat(_validate(value[prop], items, opts) || []); - } - - return errors.length ? errors : undefined; - }, - - /** - * Validates the provided number against a maximum value defined by the Schema's `maximum` keyword - * Validation succeeds if the value is a number, and is less than, or equal to, the value of this keyword. - * http://json-schema.org/latest/json-schema-validation.html#anchor17 - * - * @name Schema.validationKeywords.maximum - * @method - * @param {*} value Number to validate against the keyword. - * @param {object} schema Schema containing the `maximum` keyword. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. - */ - maximum: function maximum(value, schema, opts) { - // Must be a number - var maximum = schema.maximum; // Must be a boolean - // Depends on maximum - // default: false - - var exclusiveMaximum = schema.exclusiveMaximum; - - if (_typeof(value) === _typeof(maximum) && !(exclusiveMaximum ? maximum > value : maximum >= value)) { - return exclusiveMaximum ? makeError(value, "no more than nor equal to ".concat(maximum), opts) : makeError(value, "no more than ".concat(maximum), opts); - } - }, - - /** - * Validates the length of the provided array against a maximum value defined by the Schema's `maxItems` keyword. - * Validation succeeds if the length of the array is less than, or equal to the value of this keyword. - * see http://json-schema.org/latest/json-schema-validation.html#anchor42 - * - * @name Schema.validationKeywords.maxItems - * @method - * @param {*} value Array to be validated. - * @param {object} schema Schema containing the `maxItems` keyword. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. - */ - maxItems: function maxItems(value, schema, opts) { - if (utils.isArray(value)) { - return maxLengthCommon('maxItems', value, schema, opts); - } - }, - - /** - * Validates the length of the provided string against a maximum value defined in the Schema's `maxLength` keyword. - * Validation succeeds if the length of the string is less than, or equal to the value of this keyword. - * see http://json-schema.org/latest/json-schema-validation.html#anchor26 - * - * @name Schema.validationKeywords.maxLength - * @method - * @param {*} value String to be validated. - * @param {object} schema Schema containing the `maxLength` keyword. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. - */ - maxLength: function maxLength(value, schema, opts) { - return maxLengthCommon('maxLength', value, schema, opts); - }, - - /** - * Validates the count of the provided object's properties against a maximum value defined in the Schema's `maxProperties` keyword. - * Validation succeeds if the object's property count is less than, or equal to the value of this keyword. - * see http://json-schema.org/latest/json-schema-validation.html#anchor54 - * - * @name Schema.validationKeywords.maxProperties - * @method - * @param {*} value Object to be validated. - * @param {object} schema Schema containing the `maxProperties` keyword. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. - */ - maxProperties: function maxProperties(value, schema, opts) { - // validate only objects - if (!utils.isObject(value)) return; - var maxProperties = schema.maxProperties; - var length = Object.keys(value).length; - - if (length > maxProperties) { - return makeError(length, "no more than ".concat(maxProperties, " properties"), opts); - } - }, - - /** - * Validates the provided value against a minimum value defined by the Schema's `minimum` keyword - * Validation succeeds if the value is a number and is greater than, or equal to, the value of this keyword. - * http://json-schema.org/latest/json-schema-validation.html#anchor21 - * - * @name Schema.validationKeywords.minimum - * @method - * @param {*} value Number to validate against the keyword. - * @param {object} schema Schema containing the `minimum` keyword. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. - */ - minimum: function minimum(value, schema, opts) { - // Must be a number - var minimum = schema.minimum; // Must be a boolean - // Depends on minimum - // default: false - - var exclusiveMinimum = schema.exclusiveMinimum; - - if (_typeof(value) === _typeof(minimum) && !(exclusiveMinimum ? value > minimum : value >= minimum)) { - return exclusiveMinimum ? makeError(value, "no less than nor equal to ".concat(minimum), opts) : makeError(value, "no less than ".concat(minimum), opts); - } - }, - - /** - * Validates the length of the provided array against a minimum value defined by the Schema's `minItems` keyword. - * Validation succeeds if the length of the array is greater than, or equal to the value of this keyword. - * see http://json-schema.org/latest/json-schema-validation.html#anchor45 - * - * @name Schema.validationKeywords.minItems - * @method - * @param {*} value Array to be validated. - * @param {object} schema Schema containing the `minItems` keyword. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. - */ - minItems: function minItems(value, schema, opts) { - if (utils.isArray(value)) { - return minLengthCommon('minItems', value, schema, opts); - } - }, - - /** - * Validates the length of the provided string against a minimum value defined in the Schema's `minLength` keyword. - * Validation succeeds if the length of the string is greater than, or equal to the value of this keyword. - * see http://json-schema.org/latest/json-schema-validation.html#anchor29 - * - * @name Schema.validationKeywords.minLength - * @method - * @param {*} value String to be validated. - * @param {object} schema Schema containing the `minLength` keyword. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. - */ - minLength: function minLength(value, schema, opts) { - return minLengthCommon('minLength', value, schema, opts); - }, - - /** - * Validates the count of the provided object's properties against a minimum value defined in the Schema's `minProperties` keyword. - * Validation succeeds if the object's property count is greater than, or equal to the value of this keyword. - * see http://json-schema.org/latest/json-schema-validation.html#anchor57 - * - * @name Schema.validationKeywords.minProperties - * @method - * @param {*} value Object to be validated. - * @param {object} schema Schema containing the `minProperties` keyword. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. - */ - minProperties: function minProperties(value, schema, opts) { - // validate only objects - if (!utils.isObject(value)) return; - var minProperties = schema.minProperties; - var length = Object.keys(value).length; - - if (length < minProperties) { - return makeError(length, "no more than ".concat(minProperties, " properties"), opts); - } - }, - - /** - * Validates the provided number is a multiple of the number defined in the Schema's `multipleOf` keyword. - * Validation succeeds if the number can be divided equally into the value of this keyword. - * see http://json-schema.org/latest/json-schema-validation.html#anchor14 - * - * @name Schema.validationKeywords.multipleOf - * @method - * @param {*} value Number to be validated. - * @param {object} schema Schema containing the `multipleOf` keyword. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. - */ - multipleOf: function multipleOf(value, schema, opts) { - var multipleOf = schema.multipleOf; - - if (utils.isNumber(value)) { - if (value / multipleOf % 1 !== 0) { - return makeError(value, "multipleOf ".concat(multipleOf), opts); - } - } - }, - - /** - * Validates the provided value is not valid with any of the schemas defined in the Schema's `not` keyword. - * An instance is valid against this keyword if and only if it is NOT valid against the schemas in this keyword's value. - * - * see http://json-schema.org/latest/json-schema-validation.html#anchor91 - * @name Schema.validationKeywords.not - * @method - * @param {*} value to be checked. - * @param {object} schema Schema containing the not keyword. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. - */ - not: function not(value, schema, opts) { - if (!_validate(value, schema.not, opts)) { - // TODO: better messaging - return makeError('succeeded', 'should have failed', opts); - } - }, - - /** - * Validates the provided value is valid with one and only one of the schemas defined in the Schema's `oneOf` keyword. - * An instance is valid against this keyword if and only if it is valid against a single schemas in this keyword's value. - * - * see http://json-schema.org/latest/json-schema-validation.html#anchor88 - * @name Schema.validationKeywords.oneOf - * @method - * @param {*} value to be checked. - * @param {object} schema Schema containing the `oneOf` keyword. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. - */ - oneOf: function oneOf(value, schema, opts) { - var validated = false; - var allErrors = []; - schema.oneOf.forEach(function (_schema) { - var errors = _validate(value, _schema, opts); - - if (errors) { - allErrors = allErrors.concat(errors); - } else if (validated) { - allErrors = [makeError('valid against more than one', 'valid against only one', opts)]; - validated = false; - return false; - } else { - validated = true; - } - }); - return validated ? undefined : allErrors; - }, - - /** - * Validates the provided string matches a pattern defined in the Schema's `pattern` keyword. - * Validation succeeds if the string is a match of the regex value of this keyword. - * - * see http://json-schema.org/latest/json-schema-validation.html#anchor33 - * @name Schema.validationKeywords.pattern - * @method - * @param {*} value String to be validated. - * @param {object} schema Schema containing the `pattern` keyword. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. - */ - pattern: function pattern(value, schema, opts) { - var pattern = schema.pattern; - - if (utils.isString(value) && !value.match(pattern)) { - return makeError(value, pattern, opts); - } - }, - - /** - * Validates the provided object's properties against a map of values defined in the Schema's `properties` keyword. - * Validation succeeds if the object's property are valid with each of the schema's in the provided map. - * Validation also depends on the additionalProperties and or patternProperties. - * - * see http://json-schema.org/latest/json-schema-validation.html#anchor64 for more info. - * - * @name Schema.validationKeywords.properties - * @method - * @param {*} value Object to be validated. - * @param {object} schema Schema containing the `properties` keyword. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. - */ - properties: function properties(value, schema, opts) { - opts || (opts = {}); - - if (utils.isArray(value)) { - return; - } // Can be a boolean or an object - // Technically the default is an "empty schema", but here "true" is - // functionally the same - - - var additionalProperties = schema.additionalProperties === undefined ? true : schema.additionalProperties; - var validated = []; // "p": The property set from "properties". - // Default is an object - - var properties = schema.properties || {}; // "pp": The property set from "patternProperties". - // Default is an object - - var patternProperties = schema.patternProperties || {}; - var errors = []; - utils.forOwn(properties, function (_schema, prop) { - opts.prop = prop; - errors = errors.concat(_validate(value[prop], _schema, opts) || []); - validated.push(prop); - }); - var toValidate = utils.omit(value, validated); - utils.forOwn(patternProperties, function (_schema, pattern) { - utils.forOwn(toValidate, function (undef, prop) { - if (prop.match(pattern)) { - opts.prop = prop; - errors = errors.concat(_validate(value[prop], _schema, opts) || []); - validated.push(prop); - } - }); - }); - var keys = Object.keys(utils.omit(value, validated)); // If "s" is not empty, validation fails - - if (additionalProperties === false) { - if (keys.length) { - var origProp = opts.prop; - opts.prop = ''; - addError("extra fields: ".concat(keys.join(', ')), 'no extra fields', opts, errors); - opts.prop = origProp; - } - } else if (utils.isObject(additionalProperties)) { - // Otherwise, validate according to provided schema - keys.forEach(function (prop) { - opts.prop = prop; - errors = errors.concat(_validate(value[prop], additionalProperties, opts) || []); - }); - } - - return errors.length ? errors : undefined; - }, - - /** - * Validates the provided object's has all properties listed in the Schema's `properties` keyword array. - * Validation succeeds if the object contains all properties provided in the array value of this keyword. - * see http://json-schema.org/latest/json-schema-validation.html#anchor61 - * - * @name Schema.validationKeywords.required - * @method - * @param {*} value Object to be validated. - * @param {object} schema Schema containing the `required` keyword. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. - */ - required: function required(value, schema, opts) { - opts || (opts = {}); - var required = schema.required; - var errors = []; - - if (!opts.existingOnly) { - required.forEach(function (prop) { - if (utils.get(value, prop) === undefined) { - var prevProp = opts.prop; - opts.prop = prop; - addError(undefined, 'a value', opts, errors); - opts.prop = prevProp; - } - }); - } - - return errors.length ? errors : undefined; - }, - - /** - * Validates the provided value's type is equal to the type, or array of types, defined in the Schema's `type` keyword. - * see http://json-schema.org/latest/json-schema-validation.html#anchor79 - * - * @name Schema.validationKeywords.type - * @method - * @param {*} value Value to be validated. - * @param {object} schema Schema containing the `type` keyword. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. - */ - type: function type(value, schema, opts) { - var type = schema.type; - var validType; // Can be one of several types - - if (utils.isString(type)) { - type = [type]; - } // Try to match the value against an expected type - - - type.forEach(function (_type) { - // TODO: throw an error if type is not defined - if (types[_type](value, schema, opts)) { - // Matched a type - validType = _type; - return false; - } - }); // Value did not match any expected type - - if (!validType) { - return makeError(value !== undefined && value !== null ? _typeof(value) : '' + value, "one of (".concat(type.join(', '), ")"), opts); - } // Run keyword validators for matched type - // http://json-schema.org/latest/json-schema-validation.html#anchor12 - - - var validator = typeGroupValidators[validType]; - - if (validator) { - return validator(value, schema, opts); - } - }, - - /** - * Validates the provided array values are unique. - * Validation succeeds if the items in the array are unique, but only if the value of this keyword is true - * see http://json-schema.org/latest/json-schema-validation.html#anchor49 - * - * @name Schema.validationKeywords.uniqueItems - * @method - * @param {*} value Array to be validated. - * @param {object} schema Schema containing the `uniqueItems` keyword. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. - */ - uniqueItems: function uniqueItems(value, schema, opts) { - if (value && value.length && schema.uniqueItems) { - var length = value.length; - var item, i, j; // Check n - 1 items - - for (i = length - 1; i > 0; i--) { - item = value[i]; // Only compare against unchecked items - - for (j = i - 1; j >= 0; j--) { - // Found a duplicate - if (utils.deepEqual(item, value[j])) { - return makeError(item, 'no duplicates', opts); - } - } - } - } - } -}; -/** - * @ignore - */ - -var runOps = function runOps(ops, value, schema, opts) { - var errors = []; - ops.forEach(function (op) { - if (schema[op] !== undefined) { - errors = errors.concat(validationKeywords[op](value, schema, opts) || []); - } - }); - return errors.length ? errors : undefined; -}; -/** - * Validation keywords validated for any type: - * - * - `enum` - * - `type` - * - `allOf` - * - `anyOf` - * - `oneOf` - * - `not` - * - * @name Schema.ANY_OPS - * @type {string[]} - */ - - -var ANY_OPS = ['enum', 'type', 'allOf', 'anyOf', 'oneOf', 'not']; -/** - * Validation keywords validated for array types: - * - * - `items` - * - `maxItems` - * - `minItems` - * - `uniqueItems` - * - * @name Schema.ARRAY_OPS - * @type {string[]} - */ - -var ARRAY_OPS = ['items', 'maxItems', 'minItems', 'uniqueItems']; -/** - * Validation keywords validated for numeric (number and integer) types: - * - * - `multipleOf` - * - `maximum` - * - `minimum` - * - * @name Schema.NUMERIC_OPS - * @type {string[]} - */ - -var NUMERIC_OPS = ['multipleOf', 'maximum', 'minimum']; -/** - * Validation keywords validated for object types: - * - * - `maxProperties` - * - `minProperties` - * - `required` - * - `properties` - * - `dependencies` - * - * @name Schema.OBJECT_OPS - * @type {string[]} - */ - -var OBJECT_OPS = ['maxProperties', 'minProperties', 'required', 'properties', 'dependencies']; -/** - * Validation keywords validated for string types: - * - * - `maxLength` - * - `minLength` - * - `pattern` - * - * @name Schema.STRING_OPS - * @type {string[]} - */ - -var STRING_OPS = ['maxLength', 'minLength', 'pattern']; -/** - * http://json-schema.org/latest/json-schema-validation.html#anchor75 - * @ignore - */ - -var validateAny = function validateAny(value, schema, opts) { - return runOps(ANY_OPS, value, schema, opts); -}; -/** - * Validates the provided value against a given Schema according to the http://json-schema.org/ v4 specification. - * - * @name Schema.validate - * @method - * @param {*} value Value to be validated. - * @param {object} schema Valid Schema according to the http://json-schema.org/ v4 specification. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. - */ - - -var _validate = function validate(value, schema, opts) { - var errors = []; - opts || (opts = {}); - opts.ctx || (opts.ctx = { - value: value, - schema: schema - }); - var shouldPop; - var prevProp = opts.prop; - - if (schema === undefined) { - return; - } - - if (!utils.isObject(schema)) { - throw utils.err("".concat(DOMAIN$5, "#validate"))(500, "Invalid schema at path: \"".concat(opts.path, "\"")); - } - - if (opts.path === undefined) { - opts.path = []; - } // Track our location as we recurse - - - if (opts.prop !== undefined) { - shouldPop = true; - opts.path.push(opts.prop); - opts.prop = undefined; - } // Validate against parent schema - - - if (schema.extends) { - // opts.path = path - // opts.prop = prop - if (utils.isFunction(schema.extends.validate)) { - errors = errors.concat(schema.extends.validate(value, opts) || []); - } else { - errors = errors.concat(_validate(value, schema.extends, opts) || []); - } - } - - if (value === undefined) { - // Check if property is required - if (schema.required === true && !opts.existingOnly) { - addError(value, 'a value', opts, errors); - } - - if (shouldPop) { - opts.path.pop(); - opts.prop = prevProp; - } - - return errors.length ? errors : undefined; - } - - errors = errors.concat(validateAny(value, schema, opts) || []); - - if (shouldPop) { - opts.path.pop(); - opts.prop = prevProp; - } - - return errors.length ? errors : undefined; -}; // These strings are cached for optimal performance of the change detection -// boolean - Whether a Record is changing in the current execution frame - - -var changingPath = 'changing'; // string[] - Properties that have changed in the current execution frame - -var changedPath = 'changed'; // Object[] - History of change records - -var changeHistoryPath = 'history'; // boolean - Whether a Record is currently being instantiated - -var creatingPath$1 = 'creating'; // number - The setTimeout change event id of a Record, if any - -var eventIdPath = 'eventId'; // boolean - Whether to skip validation for a Record's currently changing property - -var noValidatePath$2 = 'noValidate'; // boolean - Whether to preserve Change History for a Record - -var keepChangeHistoryPath$1 = 'keepChangeHistory'; // boolean - Whether to skip change notification for a Record's currently -// changing property - -var silentPath = 'silent'; -var validationFailureMsg = 'validation failed'; -/** - * A map of validation functions grouped by type. - * - * @name Schema.typeGroupValidators - * @type {object} - */ - -var typeGroupValidators = { - /** - * Validates the provided value against the schema using all of the validation keywords specific to instances of an array. - * The validation keywords for the type `array` are: - *``` - * ['items', 'maxItems', 'minItems', 'uniqueItems'] - *``` - * see http://json-schema.org/latest/json-schema-validation.html#anchor25 - * - * @name Schema.typeGroupValidators.array - * @method - * @param {*} value Array to be validated. - * @param {object} schema Schema containing at least one array keyword. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. - */ - array: function array(value, schema, opts) { - return runOps(ARRAY_OPS, value, schema, opts); - }, - - /** - * Validates the provided value against the schema using all of the validation keywords specific to instances of an integer. - * The validation keywords for the type `integer` are: - *``` - * ['multipleOf', 'maximum', 'minimum'] - *``` - * @name Schema.typeGroupValidators.integer - * @method - * @param {*} value Number to be validated. - * @param {object} schema Schema containing at least one `integer` keyword. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. - */ - integer: function integer(value, schema, opts) { - // Additional validations for numerics are the same - return typeGroupValidators.numeric(value, schema, opts); - }, - - /** - * Validates the provided value against the schema using all of the validation keywords specific to instances of an number. - * The validation keywords for the type `number` are: - *``` - * ['multipleOf', 'maximum', 'minimum'] - *``` - * @name Schema.typeGroupValidators.number - * @method - * @param {*} value Number to be validated. - * @param {object} schema Schema containing at least one `number` keyword. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. - */ - number: function number(value, schema, opts) { - // Additional validations for numerics are the same - return typeGroupValidators.numeric(value, schema, opts); - }, - - /** - * Validates the provided value against the schema using all of the validation keywords specific to instances of a number or integer. - * The validation keywords for the type `numeric` are: - *``` - * ['multipleOf', 'maximum', 'minimum'] - *``` - * See http://json-schema.org/latest/json-schema-validation.html#anchor13. - * - * @name Schema.typeGroupValidators.numeric - * @method - * @param {*} value Number to be validated. - * @param {object} schema Schema containing at least one `numeric` keyword. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. - */ - numeric: function numeric(value, schema, opts) { - return runOps(NUMERIC_OPS, value, schema, opts); - }, - - /** - * Validates the provided value against the schema using all of the validation keywords specific to instances of an object. - * The validation keywords for the type `object` are: - *``` - * ['maxProperties', 'minProperties', 'required', 'properties', 'dependencies'] - *``` - * See http://json-schema.org/latest/json-schema-validation.html#anchor53. - * - * @name Schema.typeGroupValidators.object - * @method - * @param {*} value Object to be validated. - * @param {object} schema Schema containing at least one `object` keyword. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. - */ - object: function object(value, schema, opts) { - return runOps(OBJECT_OPS, value, schema, opts); - }, - - /** - * Validates the provided value against the schema using all of the validation keywords specific to instances of an string. - * The validation keywords for the type `string` are: - *``` - * ['maxLength', 'minLength', 'pattern'] - *``` - * See http://json-schema.org/latest/json-schema-validation.html#anchor25. - * - * @name Schema.typeGroupValidators.string - * @method - * @param {*} value String to be validated. - * @param {object} schema Schema containing at least one `string` keyword. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. - */ - string: function string(value, schema, opts) { - return runOps(STRING_OPS, value, schema, opts); - } -}; -/** - * js-data's Schema class. - * - * @example Schema#constructor - * const JSData = require('js-data'); - * const { Schema } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const PostSchema = new Schema({ - * type: 'object', - * properties: { - * title: { type: 'string' } - * } - * }); - * PostSchema.validate({ title: 1234 }); - * - * @class Schema - * @extends Component - * @param {object} definition Schema definition according to json-schema.org - */ - -function Schema(definition) { - var _this = this; - - definition || (definition = {}); // TODO: schema validation - - utils.fillIn(this, definition); - - if (this.type === 'object') { - this.properties = this.properties || {}; - utils.forOwn(this.properties, function (_definition, prop) { - if (!(_definition instanceof Schema)) { - _this.properties[prop] = new Schema(_definition); - } - }); - } else if (this.type === 'array' && this.items && !(this.items instanceof Schema)) { - this.items = new Schema(this.items); - } - - if (this.extends && !(this.extends instanceof Schema)) { - this.extends = new Schema(this.extends); - } - - ['allOf', 'anyOf', 'oneOf'].forEach(function (validationKeyword) { - if (_this[validationKeyword]) { - _this[validationKeyword].forEach(function (_definition, i) { - if (!(_definition instanceof Schema)) { - _this[validationKeyword][i] = new Schema(_definition); - } - }); - } - }); -} - -var Schema$1 = Component$1.extend({ - constructor: Schema, - - /** - * This adds ES5 getters/setters to the target based on the "properties" in - * this Schema, which makes possible change tracking and validation on - * property assignment. - * - * @name Schema#apply - * @method - * @param {object} target The prototype to which to apply this schema. - */ - apply: function apply(target, opts) { - var _this2 = this; - - opts || (opts = {}); - opts.getter || (opts.getter = '_get'); - opts.setter || (opts.setter = '_set'); - opts.unsetter || (opts.unsetter = '_unset'); - opts.track || (opts.track = this.track); - var properties = this.properties || {}; - utils.forOwn(properties, function (schema, prop) { - Object.defineProperty(target, prop, _this2.makeDescriptor(prop, schema, opts)); - }); - }, - - /** - * Apply default values to the target object for missing values. - * - * @name Schema#applyDefaults - * @method - * @param {object} target The target to which to apply values for missing values. - */ - applyDefaults: function applyDefaults(target) { - if (!target) { - return; - } - - var properties = this.properties || {}; - var hasSet = utils.isFunction(target.set) || utils.isFunction(target._set); - utils.forOwn(properties, function (schema, prop) { - if (Object.hasOwnProperty.call(schema, 'default') && utils.get(target, prop) === undefined) { - if (hasSet) { - target.set(prop, utils.plainCopy(schema.default), { - silent: true - }); - } else { - utils.set(target, prop, utils.plainCopy(schema.default)); - } - } - - if (schema.type === 'object' && schema.properties) { - if (hasSet) { - var orig = target._get('noValidate'); - - target._set('noValidate', true); - - utils.set(target, prop, utils.get(target, prop) || {}, { - silent: true - }); - - target._set('noValidate', orig); - } else { - utils.set(target, prop, utils.get(target, prop) || {}); - } - - schema.applyDefaults(utils.get(target, prop)); - } - }); - }, - - /** - * Assemble a property descriptor for tracking and validating changes to - * a property according to the given schema. This method is called when - * {@link Mapper#applySchema} is set to `true`. - * - * @name Schema#makeDescriptor - * @method - * @param {string} prop The property name. - * @param {(Schema|object)} schema The schema for the property. - * @param {object} [opts] Optional configuration. - * @param {function} [opts.getter] Custom getter function. - * @param {function} [opts.setter] Custom setter function. - * @param {function} [opts.track] Whether to track changes. - * @returns {object} A property descriptor for the given schema. - */ - makeDescriptor: function makeDescriptor(prop, schema, opts) { - var descriptor = { - // Better to allow configurability, but at the user's own risk - configurable: true, - // These properties are enumerable by default, but regardless of their - // enumerability, they won't be "own" properties of individual records - enumerable: schema.enumerable === undefined ? true : !!schema.enumerable - }; // Cache a few strings for optimal performance - - var keyPath = "props.".concat(prop); - var previousPath = "previous.".concat(prop); - var getter = opts.getter; - var setter = opts.setter; - var unsetter = opts.unsetter; - var track = utils.isBoolean(opts.track) ? opts.track : schema.track; - - descriptor.get = function () { - return this._get(keyPath); - }; - - if (utils.isFunction(schema.get)) { - var originalGet = descriptor.get; - - descriptor.get = function () { - return schema.get.call(this, originalGet); - }; - } - - descriptor.set = function (value) { - var _this3 = this; - - // These are accessed a lot - var _get = this[getter]; - var _set = this[setter]; - var _unset = this[unsetter]; // Optionally check that the new value passes validation - - if (!_get(noValidatePath$2)) { - var errors = schema.validate(value, { - path: [prop] - }); - - if (errors) { - // Immediately throw an error, preventing the record from getting into - // an invalid state - var error = new Error(validationFailureMsg); - error.errors = errors; - throw error; - } - } // TODO: Make it so tracking can be turned on for all properties instead of - // only per-property - - - if (track && !_get(creatingPath$1)) { - // previous is versioned on database commit - // props are versioned on set() - var previous = _get(previousPath); - - var current = _get(keyPath); - - var changing = _get(changingPath); - - var changed = _get(changedPath); - - if (!changing) { - // Track properties that are changing in the current event loop - changed = []; - } // Add changing properties to this array once at most - - - var index = changed.indexOf(prop); - - if (current !== value && index === -1) { - changed.push(prop); - } - - if (previous === value) { - if (index >= 0) { - changed.splice(index, 1); - } - } // No changes in current event loop - - - if (!changed.length) { - changing = false; - - _unset(changingPath); - - _unset(changedPath); // Cancel pending change event - - - if (_get(eventIdPath)) { - clearTimeout(_get(eventIdPath)); - - _unset(eventIdPath); - } - } // Changes detected in current event loop - - - if (!changing && changed.length) { - _set(changedPath, changed); - - _set(changingPath, true); // Saving the timeout id allows us to batch all changes in the same - // event loop into a single "change" - // TODO: Optimize - - - _set(eventIdPath, setTimeout(function () { - // Previous event loop where changes were gathered has ended, so - // notify any listeners of those changes and prepare for any new - // changes - _unset(changedPath); - - _unset(eventIdPath); - - _unset(changingPath); // TODO: Optimize - - - if (!_get(silentPath)) { - var i; - - for (i = 0; i < changed.length; i++) { - _this3.emit('change:' + changed[i], _this3, utils.get(_this3, changed[i])); - } - - var changes = utils.diffObjects(_defineProperty({}, prop, value), _defineProperty({}, prop, current)); - - if (_get(keepChangeHistoryPath$1)) { - var changeRecord = utils.plainCopy(changes); - changeRecord.timestamp = new Date().getTime(); - - var changeHistory = _get(changeHistoryPath); - - !changeHistory && _set(changeHistoryPath, changeHistory = []); - changeHistory.push(changeRecord); - } - - _this3.emit('change', _this3, changes); - } - - _unset(silentPath); - }, 0)); - } - } - - _set(keyPath, value); - - return value; - }; - - if (utils.isFunction(schema.set)) { - var originalSet = descriptor.set; - - descriptor.set = function (value) { - return schema.set.call(this, value, originalSet); - }; - } - - return descriptor; - }, - - /** - * Create a copy of the given value that contains only the properties defined - * in this schema. - * - * @name Schema#pick - * @method - * @param {*} value The value to copy. - * @returns {*} The copy. - */ - pick: function pick(value) { - var _this4 = this; - - if (value === undefined) { - return; - } - - if (this.type === 'object') { - var copy = {}; - var properties = this.properties; - - if (properties) { - utils.forOwn(properties, function (_definition, prop) { - copy[prop] = _definition.pick(value[prop]); - }); - } - - if (this.extends) { - utils.fillIn(copy, this.extends.pick(value)); - } // Conditionally copy properties not defined in "properties" - - - if (this.additionalProperties) { - for (var key in value) { - if (!properties[key]) { - copy[key] = utils.plainCopy(value[key]); - } - } - } - - return copy; - } else if (this.type === 'array') { - return value.map(function (item) { - var _copy = _this4.items ? _this4.items.pick(item) : {}; - - if (_this4.extends) { - utils.fillIn(_copy, _this4.extends.pick(item)); - } - - return _copy; - }); - } - - return utils.plainCopy(value); - }, - - /** - * Validate the provided value against this schema. - * - * @name Schema#validate - * @method - * @param {*} value Value to validate. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. - */ - validate: function validate(value, opts) { - return _validate(value, this, opts); - } -}, { - ANY_OPS: ANY_OPS, - ARRAY_OPS: ARRAY_OPS, - NUMERIC_OPS: NUMERIC_OPS, - OBJECT_OPS: OBJECT_OPS, - STRING_OPS: STRING_OPS, - typeGroupValidators: typeGroupValidators, - types: types, - validate: _validate, - validationKeywords: validationKeywords -}); -/** - * Create a subclass of this Schema: - * @example Schema.extend - * const JSData = require('js-data'); - * const { Schema } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * // Extend the class using ES2015 class syntax. - * class CustomSchemaClass extends Schema { - * foo () { return 'bar'; } - * static beep () { return 'boop'; } - * } - * const customSchema = new CustomSchemaClass(); - * console.log(customSchema.foo()); - * console.log(CustomSchemaClass.beep()); - * - * // Extend the class using alternate method. - * const OtherSchemaClass = Schema.extend({ - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }); - * const otherSchema = new OtherSchemaClass(); - * console.log(otherSchema.foo()); - * console.log(OtherSchemaClass.beep()); - * - * // Extend the class, providing a custom constructor. - * function AnotherSchemaClass () { - * Schema.call(this); - * this.created_at = new Date().getTime(); - * } - * Schema.extend({ - * constructor: AnotherSchemaClass, - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }); - * const anotherSchema = new AnotherSchemaClass(); - * console.log(anotherSchema.created_at); - * console.log(anotherSchema.foo()); - * console.log(AnotherSchemaClass.beep()); - * - * @method Schema.extend - * @param {object} [props={}] Properties to add to the prototype of the - * subclass. - * @param {object} [props.constructor] Provide a custom constructor function - * to be used as the subclass itself. - * @param {object} [classProps={}] Static properties to add to the subclass. - * @returns {Constructor} Subclass of this Schema class. - * @since 3.0.0 - */ - -var DOMAIN$6 = 'Mapper'; -var applyDefaultsHooks = ['beforeCreate', 'beforeCreateMany']; -var validatingHooks = ['beforeCreate', 'beforeCreateMany', 'beforeUpdate', 'beforeUpdateAll', 'beforeUpdateMany']; - -var makeNotify = function makeNotify(num) { - return function () { - var _this = this; - - for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { - args[_key] = arguments[_key]; - } - - var opts = args[args.length - num]; - var op = opts.op; - this.dbg.apply(this, [op].concat(args)); - - if (applyDefaultsHooks.indexOf(op) !== -1 && opts.applyDefaults !== false) { - var schema = this.getSchema(); - - if (schema && schema.applyDefaults) { - var toProcess = args[0]; - - if (!utils.isArray(toProcess)) { - toProcess = [toProcess]; - } - - toProcess.forEach(function (record) { - schema.applyDefaults(record); - }); - } - } // Automatic validation - - - if (validatingHooks.indexOf(op) !== -1 && !opts.noValidate) { - // Save current value of option - var originalExistingOnly = opts.existingOnly; // For updates, ignore required fields if they aren't present - - if (op.indexOf('beforeUpdate') === 0 && opts.existingOnly === undefined) { - opts.existingOnly = true; - } - - var errors = this.validate(args[op === 'beforeUpdate' ? 1 : 0], utils.pick(opts, ['existingOnly'])); // Restore option - - opts.existingOnly = originalExistingOnly; // Abort lifecycle due to validation errors - - if (errors) { - var err = new Error('validation failed'); - err.errors = errors; - return utils.reject(err); - } - } // Emit lifecycle event - - - if (opts.notify || opts.notify === undefined && this.notify) { - setTimeout(function () { - _this.emit.apply(_this, [op].concat(args)); - }); - } - }; -}; // These are the default implementations of all of the lifecycle hooks - - -var notify = makeNotify(1); -var notify2 = makeNotify(2); // This object provides meta information used by Mapper#crud to actually -// execute each lifecycle method - -var LIFECYCLE_METHODS = { - count: { - defaults: [{}, {}], - skip: true, - types: [] - }, - destroy: { - defaults: [{}, {}], - skip: true, - types: [] - }, - destroyAll: { - defaults: [{}, {}], - skip: true, - types: [] - }, - find: { - defaults: [undefined, {}], - types: [] - }, - findAll: { - defaults: [{}, {}], - types: [] - }, - sum: { - defaults: [undefined, {}, {}], - skip: true, - types: [] - }, - update: { - adapterArgs: function adapterArgs(mapper, id, props, opts) { - return [id, mapper.toJSON(props, opts), opts]; - }, - beforeAssign: 1, - defaults: [undefined, {}, {}], - types: [] - }, - updateAll: { - adapterArgs: function adapterArgs(mapper, props, query, opts) { - return [mapper.toJSON(props, opts), query, opts]; - }, - beforeAssign: 0, - defaults: [{}, {}, {}], - types: [] - }, - updateMany: { - adapterArgs: function adapterArgs(mapper, records, opts) { - return [records.map(function (record) { - return mapper.toJSON(record, opts); - }), opts]; - }, - beforeAssign: 0, - defaults: [[], {}], - types: [] - } -}; -var MAPPER_DEFAULTS = { - /** - * Hash of registered adapters. Don't modify directly. Use - * {@link Mapper#registerAdapter} instead. - * - * @default {} - * @name Mapper#_adapters - * @since 3.0.0 - * @tutorial ["http://www.js-data.io/v3.0/docs/connecting-to-a-data-source","Connecting to a data source"] - */ - _adapters: {}, - - /** - * Whether {@link Mapper#beforeCreate} and {@link Mapper#beforeCreateMany} - * should automatically receive default values according to the Mapper's schema. - * - * @default true - * @name Mapper#applyDefaults - * @since 3.0.0 - * @type {boolean} - */ - applyDefaults: true, - - /** - * Whether to augment {@link Mapper#recordClass} with ES5 getters and setters - * according to the properties defined in {@link Mapper#schema}. This makes - * possible validation and change tracking on individual properties - * when using the dot (e.g. `user.name = "Bob"`) operator to modify a - * property, and is `true` by default. - * - * @default true - * @name Mapper#applySchema - * @since 3.0.0 - * @type {boolean} - */ - applySchema: true, - - /** - * The name of the registered adapter that this Mapper should used by default. - * - * @default "http" - * @name Mapper#defaultAdapter - * @since 3.0.0 - * @tutorial ["http://www.js-data.io/v3.0/docs/connecting-to-a-data-source","Connecting to a data source"] - * @type {string} - */ - defaultAdapter: 'http', - - /** - * The field used as the unique identifier on records handled by this Mapper. - * - * @default id - * @name Mapper#idAttribute - * @since 3.0.0 - * @type {string} - */ - idAttribute: 'id', - - /** - * Whether records created from this mapper keep changeHistory on property changes. - * - * @default true - * @name Mapper#keepChangeHistory - * @since 3.0.0 - * @type {boolean} - */ - keepChangeHistory: true, - - /** - * Whether this Mapper should emit operational events. - * - * @default true - * @name Mapper#notify - * @since 3.0.0 - * @type {boolean} - */ - notify: true, - - /** - * Whether to skip validation when the Record instances are created. - * - * @default false - * @name Mapper#noValidate - * @since 3.0.0 - * @type {boolean} - */ - noValidate: false, - - /** - * Whether {@link Mapper#create}, {@link Mapper#createMany}, - * {@link Mapper#update}, {@link Mapper#updateAll}, {@link Mapper#updateMany}, - * {@link Mapper#find}, {@link Mapper#findAll}, {@link Mapper#destroy}, - * {@link Mapper#destroyAll}, {@link Mapper#count}, and {@link Mapper#sum} - * should return a raw result object that contains both the instance data - * returned by the adapter _and_ metadata about the operation. - * - * The default is to NOT return the result object, and instead return just the - * instance data. - * - * @default false - * @name Mapper#raw - * @since 3.0.0 - * @type {boolean} - */ - raw: false, - - /** - * Whether records created from this mapper automatically validate their properties - * when their properties are modified. - * - * @default true - * @name Mapper#validateOnSet - * @since 3.0.0 - * @type {boolean} - */ - validateOnSet: true -}; -/** - * The core of JSData's [ORM/ODM][orm] implementation. Given a minimum amout of - * meta information about a resource, a Mapper can perform generic CRUD - * operations against that resource. Apart from its configuration, a Mapper is - * stateless. The particulars of various persistence layers have been abstracted - * into adapters, which a Mapper uses to perform its operations. - * - * The term "Mapper" comes from the [Data Mapper Pattern][pattern] described in - * Martin Fowler's [Patterns of Enterprise Application Architecture][book]. A - * Data Mapper moves data between [in-memory object instances][record] and a - * relational or document-based database. JSData's Mapper can work with any - * persistence layer you can write an adapter for. - * - * _("Model" is a heavily overloaded term and is avoided in this documentation - * to prevent confusion.)_ - * - * [orm]: https://en.wikipedia.org/wiki/Object-relational_mapping - * - * @example - * [pattern]: https://en.wikipedia.org/wiki/Data_mapper_pattern - * [book]: http://martinfowler.com/books/eaa.html - * [record]: Record.html - * // Import and instantiate - * import { Mapper } from 'js-data'; - * const UserMapper = new Mapper({ name: 'user' }); - * - * @example - * // Define a Mapper using the Container component - * import { Container } from 'js-data'; - * const store = new Container(); - * store.defineMapper('user'); - * - * @class Mapper - * @extends Component - * @param {object} opts Configuration options. - * @param {boolean} [opts.applySchema=true] See {@link Mapper#applySchema}. - * @param {boolean} [opts.debug=false] See {@link Component#debug}. - * @param {string} [opts.defaultAdapter=http] See {@link Mapper#defaultAdapter}. - * @param {string} [opts.idAttribute=id] See {@link Mapper#idAttribute}. - * @param {object} [opts.methods] See {@link Mapper#methods}. - * @param {string} opts.name See {@link Mapper#name}. - * @param {boolean} [opts.notify] See {@link Mapper#notify}. - * @param {boolean} [opts.raw=false] See {@link Mapper#raw}. - * @param {Function|boolean} [opts.recordClass] See {@link Mapper#recordClass}. - * @param {Object|Schema} [opts.schema] See {@link Mapper#schema}. - * @returns {Mapper} A new {@link Mapper} instance. - * @see http://www.js-data.io/v3.0/docs/components-of-jsdata#mapper - * @since 3.0.0 - * @tutorial ["http://www.js-data.io/v3.0/docs/components-of-jsdata#mapper","Components of JSData: Mapper"] - * @tutorial ["http://www.js-data.io/v3.0/docs/modeling-your-data","Modeling your data"] - */ - -function Mapper(opts) { - utils.classCallCheck(this, Mapper); - Component$1.call(this); - opts || (opts = {}); // Prepare certain properties to be non-enumerable - - Object.defineProperties(this, { - _adapters: { - value: undefined, - writable: true - }, - - /** - * The {@link Container} that holds this Mapper. __Do not modify.__ - * - * @name Mapper#lifecycleMethods - * @since 3.0.0 - * @type {Object} - */ - datastore: { - value: undefined, - writable: true - }, - - /** - * The meta information describing this Mapper's available lifecycle - * methods. __Do not modify.__ - * - * @name Mapper#lifecycleMethods - * @since 3.0.0 - * @type {Object} - */ - lifecycleMethods: { - value: LIFECYCLE_METHODS - }, - - /** - * Set to `false` to force the Mapper to work with POJO objects only. - * - * @example - * // Use POJOs only. - * import { Mapper, Record } from 'js-data'; - * const UserMapper = new Mapper({ recordClass: false }); - * UserMapper.recordClass // false; - * const user = UserMapper.createRecord(); - * user instanceof Record; // false - * - * @example - * // Set to a custom class to have records wrapped in your custom class. - * import { Mapper, Record } from 'js-data'; - * // Custom class - * class User { - * constructor (props = {}) { - * for (var key in props) { - * if (props.hasOwnProperty(key)) { - * this[key] = props[key]; - * } - * } - * } - * } - * const UserMapper = new Mapper({ recordClass: User }); - * UserMapper.recordClass; // function User() {} - * const user = UserMapper.createRecord(); - * user instanceof Record; // false - * user instanceof User; // true - * - * - * @example - * // Extend the {@link Record} class. - * import { Mapper, Record } from 'js-data'; - * // Custom class - * class User extends Record { - * constructor () { - * super(props); - * } - * } - * const UserMapper = new Mapper({ recordClass: User }); - * UserMapper.recordClass; // function User() {} - * const user = UserMapper.createRecord(); - * user instanceof Record; // true - * user instanceof User; // true - * - * @name Mapper#recordClass - * @default {@link Record} - * @see Record - * @since 3.0.0 - */ - recordClass: { - value: undefined, - writable: true - }, - - /** - * This Mapper's {@link Schema}. - * - * @example Mapper#schema - * const JSData = require('js-data'); - * const { Mapper } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const UserMapper = new Mapper({ - * name: 'user', - * schema: { - * properties: { - * id: { type: 'number' }, - * first: { type: 'string', track: true }, - * last: { type: 'string', track: true }, - * role: { type: 'string', track: true, required: true }, - * age: { type: 'integer', track: true }, - * is_active: { type: 'number' } - * } - * } - * }); - * const user = UserMapper.createRecord({ - * id: 1, - * name: 'John', - * role: 'admin' - * }); - * user.on('change', function (user, changes) { - * console.log(changes); - * }); - * user.on('change:role', function (user, value) { - * console.log('change:role - ' + value); - * }); - * user.role = 'owner'; - * - * @name Mapper#schema - * @see Schema - * @since 3.0.0 - * @type {Schema} - */ - schema: { - value: undefined, - writable: true - } - }); // Apply user-provided configuration - - utils.fillIn(this, opts); // Fill in any missing options with the defaults - - utils.fillIn(this, utils.copy(MAPPER_DEFAULTS)); - /** - * The name for this Mapper. This is the minimum amount of meta information - * required for a Mapper to be able to execute CRUD operations for a - * Resource. - * - * @name Mapper#name - * @since 3.0.0 - * @type {string} - */ - - if (!this.name) { - throw utils.err("new ".concat(DOMAIN$6), 'opts.name')(400, 'string', this.name); - } // Setup schema, with an empty default schema if necessary - - - if (this.schema) { - this.schema.type || (this.schema.type = 'object'); - - if (!(this.schema instanceof Schema$1)) { - this.schema = new Schema$1(this.schema || { - type: 'object' - }); - } - } // Create a subclass of Record that's tied to this Mapper - - - if (this.recordClass === undefined) { - var superClass = Record$1; - this.recordClass = superClass.extend({ - constructor: function Record() { - var subClass = function Record(props, opts) { - utils.classCallCheck(this, subClass); - superClass.call(this, props, opts); - }; - - return subClass; - }() - }); - } - - if (this.recordClass) { - this.recordClass.mapper = this; - /** - * Functions that should be added to the prototype of {@link Mapper#recordClass}. - * - * @name Mapper#methods - * @since 3.0.0 - * @type {Object} - */ - - if (utils.isObject(this.methods)) { - utils.addHiddenPropsToTarget(this.recordClass.prototype, this.methods); - } // We can only apply the schema to the prototype of this.recordClass if the - // class extends Record - - - if (Object.isPrototypeOf.call(Record$1, this.recordClass) && this.schema && this.schema.apply && this.applySchema) { - this.schema.apply(this.recordClass.prototype); - } - } -} - -var Mapper$1 = Component$1.extend({ - constructor: Mapper, - - /** - * Mapper lifecycle hook called by {@link Mapper#count}. If this method - * returns a promise then {@link Mapper#count} will wait for the promise - * to resolve before continuing. - * - * @method Mapper#afterCount - * @param {object} query The `query` argument passed to {@link Mapper#count}. - * @param {object} opts The `opts` argument passed to {@link Mapper#count}. - * @param {*} result The result, if any. - * @since 3.0.0 - */ - afterCount: notify2, - - /** - * Mapper lifecycle hook called by {@link Mapper#create}. If this method - * returns a promise then {@link Mapper#create} will wait for the promise - * to resolve before continuing. - * - * @method Mapper#afterCreate - * @param {object} props The `props` argument passed to {@link Mapper#create}. - * @param {object} opts The `opts` argument passed to {@link Mapper#create}. - * @param {*} result The result, if any. - * @since 3.0.0 - */ - afterCreate: notify2, - - /** - * Mapper lifecycle hook called by {@link Mapper#createMany}. If this method - * returns a promise then {@link Mapper#createMany} will wait for the promise - * to resolve before continuing. - * - * @method Mapper#afterCreateMany - * @param {array} records The `records` argument passed to {@link Mapper#createMany}. - * @param {object} opts The `opts` argument passed to {@link Mapper#createMany}. - * @param {*} result The result, if any. - * @since 3.0.0 - */ - afterCreateMany: notify2, - - /** - * Mapper lifecycle hook called by {@link Mapper#destroy}. If this method - * returns a promise then {@link Mapper#destroy} will wait for the promise - * to resolve before continuing. - * - * @method Mapper#afterDestroy - * @param {(string|number)} id The `id` argument passed to {@link Mapper#destroy}. - * @param {object} opts The `opts` argument passed to {@link Mapper#destroy}. - * @param {*} result The result, if any. - * @since 3.0.0 - */ - afterDestroy: notify2, - - /** - * Mapper lifecycle hook called by {@link Mapper#destroyAll}. If this method - * returns a promise then {@link Mapper#destroyAll} will wait for the promise - * to resolve before continuing. - * - * @method Mapper#afterDestroyAll - * @param {*} data The `data` returned by the adapter. - * @param {query} query The `query` argument passed to {@link Mapper#destroyAll}. - * @param {object} opts The `opts` argument passed to {@link Mapper#destroyAll}. - * @param {*} result The result, if any. - * @since 3.0.0 - */ - afterDestroyAll: notify2, - - /** - * Mapper lifecycle hook called by {@link Mapper#find}. If this method - * returns a promise then {@link Mapper#find} will wait for the promise - * to resolve before continuing. - * - * @method Mapper#afterFind - * @param {(string|number)} id The `id` argument passed to {@link Mapper#find}. - * @param {object} opts The `opts` argument passed to {@link Mapper#find}. - * @param {*} result The result, if any. - * @since 3.0.0 - */ - afterFind: notify2, - - /** - * Mapper lifecycle hook called by {@link Mapper#findAll}. If this method - * returns a promise then {@link Mapper#findAll} will wait for the promise - * to resolve before continuing. - * - * @method Mapper#afterFindAll - * @param {object} query The `query` argument passed to {@link Mapper#findAll}. - * @param {object} opts The `opts` argument passed to {@link Mapper#findAll}. - * @param {*} result The result, if any. - * @since 3.0.0 - */ - afterFindAll: notify2, - - /** - * Mapper lifecycle hook called by {@link Mapper#sum}. If this method - * returns a promise then {@link Mapper#sum} will wait for the promise - * to resolve before continuing. - * - * @method Mapper#afterSum - * @param {object} query The `query` argument passed to {@link Mapper#sum}. - * @param {object} opts The `opts` argument passed to {@link Mapper#sum}. - * @param {*} result The result, if any. - * @since 3.0.0 - */ - afterSum: notify2, - - /** - * Mapper lifecycle hook called by {@link Mapper#update}. If this method - * returns a promise then {@link Mapper#update} will wait for the promise - * to resolve before continuing. - * - * @method Mapper#afterUpdate - * @param {(string|number)} id The `id` argument passed to {@link Mapper#update}. - * @param {props} props The `props` argument passed to {@link Mapper#update}. - * @param {object} opts The `opts` argument passed to {@link Mapper#update}. - * @param {*} result The result, if any. - * @since 3.0.0 - */ - afterUpdate: notify2, - - /** - * Mapper lifecycle hook called by {@link Mapper#updateAll}. If this method - * returns a promise then {@link Mapper#updateAll} will wait for the promise - * to resolve before continuing. - * - * @method Mapper#afterUpdateAll - * @param {object} props The `props` argument passed to {@link Mapper#updateAll}. - * @param {object} query The `query` argument passed to {@link Mapper#updateAll}. - * @param {object} opts The `opts` argument passed to {@link Mapper#updateAll}. - * @param {*} result The result, if any. - * @since 3.0.0 - */ - afterUpdateAll: notify2, - - /** - * Mapper lifecycle hook called by {@link Mapper#updateMany}. If this method - * returns a promise then {@link Mapper#updateMany} will wait for the promise - * to resolve before continuing. - * - * @method Mapper#afterUpdateMany - * @param {array} records The `records` argument passed to {@link Mapper#updateMany}. - * @param {object} opts The `opts` argument passed to {@link Mapper#updateMany}. - * @param {*} result The result, if any. - * @since 3.0.0 - */ - afterUpdateMany: notify2, - - /** - * Mapper lifecycle hook called by {@link Mapper#create}. If this method - * returns a promise then {@link Mapper#create} will wait for the promise - * to resolve before continuing. - * - * @method Mapper#beforeCreate - * @param {object} props The `props` argument passed to {@link Mapper#create}. - * @param {object} opts The `opts` argument passed to {@link Mapper#create}. - * @since 3.0.0 - */ - beforeCreate: notify, - - /** - * Mapper lifecycle hook called by {@link Mapper#createMany}. If this method - * returns a promise then {@link Mapper#createMany} will wait for the promise - * to resolve before continuing. - * - * @method Mapper#beforeCreateMany - * @param {array} records The `records` argument passed to {@link Mapper#createMany}. - * @param {object} opts The `opts` argument passed to {@link Mapper#createMany}. - * @since 3.0.0 - */ - beforeCreateMany: notify, - - /** - * Mapper lifecycle hook called by {@link Mapper#count}. If this method - * returns a promise then {@link Mapper#count} will wait for the promise - * to resolve before continuing. - * - * @method Mapper#beforeCount - * @param {object} query The `query` argument passed to {@link Mapper#count}. - * @param {object} opts The `opts` argument passed to {@link Mapper#count}. - * @since 3.0.0 - */ - beforeCount: notify, - - /** - * Mapper lifecycle hook called by {@link Mapper#destroy}. If this method - * returns a promise then {@link Mapper#destroy} will wait for the promise - * to resolve before continuing. - * - * @method Mapper#beforeDestroy - * @param {(string|number)} id The `id` argument passed to {@link Mapper#destroy}. - * @param {object} opts The `opts` argument passed to {@link Mapper#destroy}. - * @since 3.0.0 - */ - beforeDestroy: notify, - - /** - * Mapper lifecycle hook called by {@link Mapper#destroyAll}. If this method - * returns a promise then {@link Mapper#destroyAll} will wait for the promise - * to resolve before continuing. - * - * @method Mapper#beforeDestroyAll - * @param {query} query The `query` argument passed to {@link Mapper#destroyAll}. - * @param {object} opts The `opts` argument passed to {@link Mapper#destroyAll}. - * @since 3.0.0 - */ - beforeDestroyAll: notify, - - /** - * Mappers lifecycle hook called by {@link Mapper#find}. If this method - * returns a promise then {@link Mapper#find} will wait for the promise - * to resolve before continuing. - * - * @method Mapper#beforeFind - * @param {(string|number)} id The `id` argument passed to {@link Mapper#find}. - * @param {object} opts The `opts` argument passed to {@link Mapper#find}. - * @since 3.0.0 - */ - beforeFind: notify, - - /** - * Mapper lifecycle hook called by {@link Mapper#findAll}. If this method - * returns a promise then {@link Mapper#findAll} will wait for the promise - * to resolve before continuing. - * - * @method Mapper#beforeFindAll - * @param {object} query The `query` argument passed to {@link Mapper#findAll}. - * @param {object} opts The `opts` argument passed to {@link Mapper#findAll}. - * @since 3.0.0 - */ - beforeFindAll: notify, - - /** - * Mapper lifecycle hook called by {@link Mapper#sum}. If this method - * returns a promise then {@link Mapper#sum} will wait for the promise - * to resolve before continuing. - * - * @method Mapper#beforeSum - * @param {string} field The `field` argument passed to {@link Mapper#sum}. - * @param {object} query The `query` argument passed to {@link Mapper#sum}. - * @param {object} opts The `opts` argument passed to {@link Mapper#sum}. - * @since 3.0.0 - */ - beforeSum: notify, - - /** - * Mapper lifecycle hook called by {@link Mapper#update}. If this method - * returns a promise then {@link Mapper#update} will wait for the promise - * to resolve before continuing. - * - * @method Mapper#beforeUpdate - * @param {(string|number)} id The `id` argument passed to {@link Mapper#update}. - * @param {props} props The `props` argument passed to {@link Mapper#update}. - * @param {object} opts The `opts` argument passed to {@link Mapper#update}. - * @since 3.0.0 - */ - beforeUpdate: notify, - - /** - * Mapper lifecycle hook called by {@link Mapper#updateAll}. If this method - * returns a promise then {@link Mapper#updateAll} will wait for the promise - * to resolve before continuing. - * - * @method Mapper#beforeUpdateAll - * @param {object} props The `props` argument passed to {@link Mapper#updateAll}. - * @param {object} query The `query` argument passed to {@link Mapper#updateAll}. - * @param {object} opts The `opts` argument passed to {@link Mapper#updateAll}. - * @since 3.0.0 - */ - beforeUpdateAll: notify, - - /** - * Mapper lifecycle hook called by {@link Mapper#updateMany}. If this method - * returns a promise then {@link Mapper#updateMany} will wait for the promise - * to resolve before continuing. - * - * @method Mapper#beforeUpdateMany - * @param {array} records The `records` argument passed to {@link Mapper#updateMany}. - * @param {object} opts The `opts` argument passed to {@link Mapper#updateMany}. - * @since 3.0.0 - */ - beforeUpdateMany: notify, - - /** - * This method is called at the end of most lifecycle methods. It does the - * following: - * - * 1. If `opts.raw` is `true`, add this Mapper's configuration to the `opts` - * argument as metadata for the operation. - * 2. Wrap the result data appropriately using {@link Mapper#wrap}, which - * calls {@link Mapper#createRecord}. - * - * @method Mapper#_end - * @private - * @since 3.0.0 - */ - _end: function _end(result, opts, skip) { - if (opts.raw) { - utils._(result, opts); - } - - if (skip) { - return result; - } - - var _data = opts.raw ? result.data : result; - - if (_data && utils.isFunction(this.wrap)) { - _data = this.wrap(_data, opts); - - if (opts.raw) { - result.data = _data; - } else { - result = _data; - } - } - - return result; - }, - - /** - * Define a belongsTo relationship. Only useful if you're managing your - * Mappers manually and not using a Container or DataStore component. - * - * @example - * PostMapper.belongsTo(UserMapper, { - * // post.user_id points to user.id - * foreignKey: 'user_id' - * // user records will be attached to post records at "post.user" - * localField: 'user' - * }); - * - * CommentMapper.belongsTo(UserMapper, { - * // comment.user_id points to user.id - * foreignKey: 'user_id' - * // user records will be attached to comment records at "comment.user" - * localField: 'user' - * }); - * CommentMapper.belongsTo(PostMapper, { - * // comment.post_id points to post.id - * foreignKey: 'post_id' - * // post records will be attached to comment records at "comment.post" - * localField: 'post' - * }); - * - * @method Mapper#belongsTo - * @see http://www.js-data.io/v3.0/docs/relations - * @since 3.0.0 - */ - belongsTo: function belongsTo$1(relatedMapper, opts) { - return belongsTo(relatedMapper, opts)(this); - }, - - /** - * Select records according to the `query` argument and return the count. - * - * {@link Mapper#beforeCount} will be called before calling the adapter. - * {@link Mapper#afterCount} will be called after calling the adapter. - * - * @example - * // Get the number of published blog posts - * PostMapper.count({ status: 'published' }).then((numPublished) => { - * console.log(numPublished); // e.g. 45 - * }); - * - * @method Mapper#count - * @param {object} [query={}] Selection query. See {@link query}. - * @param {object} [query.where] See {@link query.where}. - * @param {number} [query.offset] See {@link query.offset}. - * @param {number} [query.limit] See {@link query.limit}. - * @param {string|Array[]} [query.orderBy] See {@link query.orderBy}. - * @param {object} [opts] Configuration options. Refer to the `count` method - * of whatever adapter you're using for more configuration options. - * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the - * adapter to use. - * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}. - * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}. - * @returns {Promise} Resolves with the count of the selected records. - * @since 3.0.0 - */ - count: function count(query, opts) { - return this.crud('count', query, opts); - }, - - /** - * Fired during {@link Mapper#create}. See - * {@link Mapper~beforeCreateListener} for how to listen for this event. - * - * @event Mapper#beforeCreate - * @see Mapper~beforeCreateListener - * @see Mapper#create - */ - - /** - * Callback signature for the {@link Mapper#event:beforeCreate} event. - * - * @example - * function onBeforeCreate (props, opts) { - * // do something - * } - * store.on('beforeCreate', onBeforeCreate); - * - * @callback Mapper~beforeCreateListener - * @param {object} props The `props` argument passed to {@link Mapper#beforeCreate}. - * @param {object} opts The `opts` argument passed to {@link Mapper#beforeCreate}. - * @see Mapper#event:beforeCreate - * @see Mapper#create - * @since 3.0.0 - */ - - /** - * Fired during {@link Mapper#create}. See - * {@link Mapper~afterCreateListener} for how to listen for this event. - * - * @event Mapper#afterCreate - * @see Mapper~afterCreateListener - * @see Mapper#create - */ - - /** - * Callback signature for the {@link Mapper#event:afterCreate} event. - * - * @example - * function onAfterCreate (props, opts, result) { - * // do something - * } - * store.on('afterCreate', onAfterCreate); - * - * @callback Mapper~afterCreateListener - * @param {object} props The `props` argument passed to {@link Mapper#afterCreate}. - * @param {object} opts The `opts` argument passed to {@link Mapper#afterCreate}. - * @param {object} result The `result` argument passed to {@link Mapper#afterCreate}. - * @see Mapper#event:afterCreate - * @see Mapper#create - * @since 3.0.0 - */ - - /** - * Create and save a new the record using the provided `props`. - * - * {@link Mapper#beforeCreate} will be called before calling the adapter. - * {@link Mapper#afterCreate} will be called after calling the adapter. - * - * @example - * // Create and save a new blog post - * PostMapper.create({ - * title: 'Modeling your data', - * status: 'draft' - * }).then((post) => { - * console.log(post); // { id: 1234, status: 'draft', ... } - * }); - * - * @fires Mapper#beforeCreate - * @fires Mapper#afterCreate - * @method Mapper#create - * @param {object} props The properties for the new record. - * @param {object} [opts] Configuration options. Refer to the `create` method - * of whatever adapter you're using for more configuration options. - * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the - * adapter to use. - * @param {boolean} [opts.noValidate={@link Mapper#noValidate}] See {@link Mapper#noValidate}. - * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}. - * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}. - * @param {string[]} [opts.with=[]] Relations to create in a cascading - * create if `props` contains nested relations. NOT performed in a - * transaction. Each nested create will result in another {@link Mapper#create} - * or {@link Mapper#createMany} call. - * @param {string[]} [opts.pass=[]] Relations to send to the adapter as part - * of the payload. Normally relations are not sent. - * @returns {Promise} Resolves with the created record. - * @since 3.0.0 - */ - create: function create(props, opts) { - var _this2 = this; - - // Default values for arguments - props || (props = {}); - opts || (opts = {}); - var originalRecord = props; - var parentRelationMap = {}; - var adapterResponse = {}; // Fill in "opts" with the Mapper's configuration - - utils._(opts, this); - - opts.adapter = this.getAdapterName(opts); - opts.op = 'beforeCreate'; - return this._runHook(opts.op, props, opts).then(function (props) { - opts.with || (opts.with = []); - return _this2._createParentRecordIfRequired(props, opts); - }).then(function (relationMap) { - parentRelationMap = relationMap; - }).then(function () { - opts.op = 'create'; - return _this2._invokeAdapterMethod(opts.op, props, opts); - }).then(function (result) { - adapterResponse = result; - }).then(function () { - var createdProps = opts.raw ? adapterResponse.data : adapterResponse; - return _this2._createOrAssignChildRecordIfRequired(createdProps, { - opts: opts, - parentRelationMap: parentRelationMap, - originalProps: props - }); - }).then(function (createdProps) { - return _this2._commitChanges(originalRecord, createdProps); - }).then(function (record) { - if (opts.raw) { - adapterResponse.data = record; - } else { - adapterResponse = record; - } - - var result = _this2._end(adapterResponse, opts); - - opts.op = 'afterCreate'; - return _this2._runHook(opts.op, props, opts, result); - }); - }, - _commitChanges: function _commitChanges(recordOrRecords, newValues) { - var _this3 = this; - - if (utils.isArray(recordOrRecords)) { - return recordOrRecords.map(function (record, i) { - return _this3._commitChanges(record, newValues[i]); - }); - } - - utils.set(recordOrRecords, newValues, { - silent: true - }); - - if (utils.isFunction(recordOrRecords.commit)) { - recordOrRecords.commit(); - } - - return recordOrRecords; - }, - - /** - * Use {@link Mapper#createRecord} instead. - * @deprecated - * @method Mapper#createInstance - * @param {Object|Array} props See {@link Mapper#createRecord}. - * @param {object} [opts] See {@link Mapper#createRecord}. - * @returns {Object|Array} See {@link Mapper#createRecord}. - * @see Mapper#createRecord - * @since 3.0.0 - */ - createInstance: function createInstance(props, opts) { - return this.createRecord(props, opts); - }, - - /** - * Creates parent record for relation types like BelongsTo or HasMany with localKeys - * in order to satisfy foreignKey dependency (so called child records). - * @param {object} props See {@link Mapper#create}. - * @param {object} opts See {@link Mapper#create}. - * @returns {Object} cached parent records map - * @see Mapper#create - * @since 3.0.0 - */ - _createParentRecordIfRequired: function _createParentRecordIfRequired(props, opts) { - var tasks = []; - var relations = []; - utils.forEachRelation(this, opts, function (def, optsCopy) { - if (!def.isRequiresParentId() || !def.getLocalField(props)) { - return; - } - - optsCopy.raw = false; - relations.push(def); - tasks.push(def.createParentRecord(props, optsCopy)); - }); - return utils.Promise.all(tasks).then(function (records) { - return relations.reduce(function (map, relation, index) { - relation.setLocalField(map, records[index]); - return map; - }, {}); - }); - }, - - /** - * Creates child record for relation types like HasOne or HasMany with foreignKey - * in order to satisfy foreignKey dependency (so called parent records). - * @param {object} props See {@link Mapper#create}. - * @param {object} context contains collected information. - * @param {object} context.opts See {@link Mapper#create}. - * @param {object} context.parentRelationMap contains parent records map - * @param {object} context.originalProps contains data passed into {@link Mapper#create} method - * @return {Promise} updated props - * @see Mapper#create - * @since 3.0.0 - */ - _createOrAssignChildRecordIfRequired: function _createOrAssignChildRecordIfRequired(props, context) { - var tasks = []; - utils.forEachRelation(this, context.opts, function (def, optsCopy) { - var relationData = def.getLocalField(context.originalProps); - - if (!relationData) { - return; - } - - optsCopy.raw = false; // Create hasMany and hasOne after the main create because we needed - // a generated id to attach to these items - - if (def.isRequiresChildId()) { - tasks.push(def.createChildRecord(props, relationData, optsCopy)); - } else if (def.isRequiresParentId()) { - var parent = def.getLocalField(context.parentRelationMap); - - if (parent) { - def.setLocalField(props, parent); - } - } - }); - return utils.Promise.all(tasks).then(function () { - return props; - }); - }, - - /** - * Fired during {@link Mapper#createMany}. See - * {@link Mapper~beforeCreateManyListener} for how to listen for this event. - * - * @event Mapper#beforeCreateMany - * @see Mapper~beforeCreateManyListener - * @see Mapper#createMany - */ - - /** - * Callback signature for the {@link Mapper#event:beforeCreateMany} event. - * - * @example - * function onBeforeCreateMany (records, opts) { - * // do something - * } - * store.on('beforeCreateMany', onBeforeCreateMany); - * - * @callback Mapper~beforeCreateManyListener - * @param {object} records The `records` argument received by {@link Mapper#beforeCreateMany}. - * @param {object} opts The `opts` argument received by {@link Mapper#beforeCreateMany}. - * @see Mapper#event:beforeCreateMany - * @see Mapper#createMany - * @since 3.0.0 - */ - - /** - * Fired during {@link Mapper#createMany}. See - * {@link Mapper~afterCreateManyListener} for how to listen for this event. - * - * @event Mapper#afterCreateMany - * @see Mapper~afterCreateManyListener - * @see Mapper#createMany - */ - - /** - * Callback signature for the {@link Mapper#event:afterCreateMany} event. - * - * @example - * function onAfterCreateMany (records, opts, result) { - * // do something - * } - * store.on('afterCreateMany', onAfterCreateMany); - * - * @callback Mapper~afterCreateManyListener - * @param {object} records The `records` argument received by {@link Mapper#afterCreateMany}. - * @param {object} opts The `opts` argument received by {@link Mapper#afterCreateMany}. - * @param {object} result The `result` argument received by {@link Mapper#afterCreateMany}. - * @see Mapper#event:afterCreateMany - * @see Mapper#createMany - * @since 3.0.0 - */ - - /** - * Given an array of records, batch create them via an adapter. - * - * {@link Mapper#beforeCreateMany} will be called before calling the adapter. - * {@link Mapper#afterCreateMany} will be called after calling the adapter. - * - * @example - * // Create and save several new blog posts - * PostMapper.createMany([{ - * title: 'Modeling your data', - * status: 'draft' - * }, { - * title: 'Reading data', - * status: 'draft' - * }]).then((posts) => { - * console.log(posts[0]); // { id: 1234, status: 'draft', ... } - * console.log(posts[1]); // { id: 1235, status: 'draft', ... } - * }); - * - * @fires Mapper#beforeCreate - * @fires Mapper#afterCreate - * @method Mapper#createMany - * @param {Record[]} records Array of records to be created in one batch. - * @param {object} [opts] Configuration options. Refer to the `createMany` - * method of whatever adapter you're using for more configuration options. - * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the - * adapter to use. - * @param {boolean} [opts.noValidate={@link Mapper#noValidate}] See {@link Mapper#noValidate}. - * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}. - * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}. - * @param {string[]} [opts.with=[]] Relations to create in a cascading - * create if `records` contains nested relations. NOT performed in a - * transaction. Each nested create will result in another {@link Mapper#createMany} - * call. - * @param {string[]} [opts.pass=[]] Relations to send to the adapter as part - * of the payload. Normally relations are not sent. - * @returns {Promise} Resolves with the created records. - * @since 3.0.0 - * @tutorial ["http://www.js-data.io/v3.0/docs/saving-data","Saving data"] - */ - createMany: function createMany(records, opts) { - var _this4 = this; - - // Default values for arguments - records || (records = []); - opts || (opts = {}); - var originalRecords = records; - var adapterResponse; // Fill in "opts" with the Mapper's configuration - - utils._(opts, this); - - opts.adapter = this.getAdapterName(opts); // beforeCreateMany lifecycle hook - - opts.op = 'beforeCreateMany'; - return this._runHook(opts.op, records, opts).then(function (records) { - // Deep pre-create belongsTo relations - var belongsToRelationData = {}; - opts.with || (opts.with = []); - var tasks = []; - utils.forEachRelation(_this4, opts, function (def, optsCopy) { - var relationData = records.map(function (record) { - return def.getLocalField(record); - }).filter(Boolean); - - if (def.type === belongsToType && relationData.length === records.length) { - // Create belongsTo relation first because we need a generated id to - // attach to the child - optsCopy.raw = false; - tasks.push(def.createLinked(relationData, optsCopy).then(function (relatedRecords) { - records.forEach(function (record, i) { - return def.setForeignKey(record, relatedRecords[i]); - }); - }).then(function (relatedRecords) { - def.setLocalField(belongsToRelationData, relatedRecords); - })); - } - }); - return utils.Promise.all(tasks).then(function () { - opts.op = 'createMany'; - return _this4._invokeAdapterMethod(opts.op, records, opts); - }).then(function (result) { - adapterResponse = result; - }).then(function () { - var createdRecordsData = opts.raw ? adapterResponse.data : adapterResponse; // Deep post-create hasOne relations - - tasks = []; - utils.forEachRelation(_this4, opts, function (def, optsCopy) { - var relationData = records.map(function (record) { - return def.getLocalField(record); - }).filter(Boolean); - - if (relationData.length !== records.length) { - return; - } - - optsCopy.raw = false; - var belongsToData = def.getLocalField(belongsToRelationData); - var task; // Create hasMany and hasOne after the main create because we needed - // a generated id to attach to these items - - if (def.type === hasManyType) { - // Not supported - _this4.log('warn', 'deep createMany of hasMany type not supported!'); - } else if (def.type === hasOneType) { - createdRecordsData.forEach(function (createdRecordData, i) { - def.setForeignKey(createdRecordData, relationData[i]); - }); - task = def.getRelation().createMany(relationData, optsCopy).then(function (relatedData) { - createdRecordsData.forEach(function (createdRecordData, i) { - def.setLocalField(createdRecordData, relatedData[i]); - }); - }); - } else if (def.type === belongsToType && belongsToData && belongsToData.length === createdRecordsData.length) { - createdRecordsData.forEach(function (createdRecordData, i) { - def.setLocalField(createdRecordData, belongsToData[i]); - }); - } - - if (task) { - tasks.push(task); - } - }); - return utils.Promise.all(tasks).then(function () { - return _this4._commitChanges(originalRecords, createdRecordsData); - }); - }); - }).then(function (records) { - if (opts.raw) { - adapterResponse.data = records; - } else { - adapterResponse = records; - } - - var result = _this4._end(adapterResponse, opts); - - opts.op = 'afterCreateMany'; - return _this4._runHook(opts.op, records, opts, result); - }); - }, - - /** - * Create an unsaved, uncached instance of this Mapper's - * {@link Mapper#recordClass}. - * - * Returns `props` if `props` is already an instance of - * {@link Mapper#recordClass}. - * - * __Note:__ This method does __not__ interact with any adapter, and does - * __not__ save any data. It only creates new objects in memory. - * - * @example - * // Create empty unsaved record instance - * const post = PostMapper.createRecord(); - * - * @example - * // Create an unsaved record instance with inital properties - * const post = PostMapper.createRecord({ - * title: 'Modeling your data', - * status: 'draft' - * }); - * - * @example - * // Create a record instance that corresponds to a saved record - * const post = PostMapper.createRecord({ - * // JSData thinks this record has been saved if it has a primary key - * id: 1234, - * title: 'Modeling your data', - * status: 'draft' - * }); - * - * @example - * // Create record instances from an array - * const posts = PostMapper.createRecord([{ - * title: 'Modeling your data', - * status: 'draft' - * }, { - * title: 'Reading data', - * status: 'draft' - * }]); - * - * @example - * // Records are validated by default - * import { Mapper } from 'js-data'; - * const PostMapper = new Mapper({ - * name: 'post', - * schema: { properties: { title: { type: 'string' } } } - * }); - * try { - * const post = PostMapper.createRecord({ - * title: 1234, - * }); - * } catch (err) { - * console.log(err.errors); // [{ expected: 'one of (string)', actual: 'number', path: 'title' }] - * } - * - * @example - * // Skip validation - * import { Mapper } from 'js-data'; - * const PostMapper = new Mapper({ - * name: 'post', - * schema: { properties: { title: { type: 'string' } } } - * }); - * const post = PostMapper.createRecord({ - * title: 1234, - * }, { noValidate: true }); - * console.log(post.isValid()); // false - * - * @method Mapper#createRecord - * @param {Object|Object[]} props The properties for the Record instance or an - * array of property objects for the Record instances. - * @param {object} [opts] Configuration options. - * @param {boolean} [opts.noValidate={@link Mapper#noValidate}] See {@link Mapper#noValidate}. - * @returns {Record|Record[]} The Record instance or Record instances. - * @since 3.0.0 - */ - createRecord: function createRecord(props, opts) { - var _this5 = this; - - props || (props = {}); - - if (utils.isArray(props)) { - return props.map(function (_props) { - return _this5.createRecord(_props, opts); - }); - } - - if (!utils.isObject(props)) { - throw utils.err("".concat(DOMAIN$6, "#createRecord"), 'props')(400, 'array or object', props); - } - - if (this.relationList) { - this.relationList.forEach(function (def) { - def.ensureLinkedDataHasProperType(props, opts); - }); - } - - var RecordCtor = this.recordClass; - return !RecordCtor || props instanceof RecordCtor ? props : new RecordCtor(props, opts); - }, - - /** - * Lifecycle invocation method. You probably won't call this method directly. - * - * @method Mapper#crud - * @param {string} method Name of the lifecycle method to invoke. - * @param {...*} args Arguments to pass to the lifecycle method. - * @returns {Promise} - * @since 3.0.0 - */ - crud: function crud(method) { - var _this6 = this; - - for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { - args[_key2 - 1] = arguments[_key2]; - } - - var config = this.lifecycleMethods[method]; - - if (!config) { - throw utils.err("".concat(DOMAIN$6, "#crud"), method)(404, 'method'); - } - - var upper = "".concat(method.charAt(0).toUpperCase()).concat(method.substr(1)); - var before = "before".concat(upper); - var after = "after".concat(upper); - var op; // Default values for arguments - - config.defaults.forEach(function (value, i) { - if (args[i] === undefined) { - args[i] = utils.copy(value); - } - }); - var opts = args[args.length - 1]; // Fill in "opts" with the Mapper's configuration - - utils._(opts, this); - - var adapter = opts.adapter = this.getAdapterName(opts); // before lifecycle hook - - op = opts.op = before; - return utils.resolve(this[op].apply(this, _toConsumableArray(args))).then(function (_value) { - var _this6$getAdapter; - - if (args[config.beforeAssign] !== undefined) { - // Allow for re-assignment from lifecycle hook - args[config.beforeAssign] = _value === undefined ? args[config.beforeAssign] : _value; - } // Now delegate to the adapter - - - op = opts.op = method; - args = config.adapterArgs ? config.adapterArgs.apply(config, [_this6].concat(_toConsumableArray(args))) : args; - - _this6.dbg.apply(_this6, [op].concat(_toConsumableArray(args))); - - return utils.resolve((_this6$getAdapter = _this6.getAdapter(adapter))[op].apply(_this6$getAdapter, [_this6].concat(_toConsumableArray(args)))); - }).then(function (result) { - // force noValidate on find/findAll - var noValidate = /find/.test(op) || opts.noValidate; - - var _opts = Object.assign({}, opts, { - noValidate: noValidate - }); - - result = _this6._end(result, _opts, !!config.skip); - args.push(result); // after lifecycle hook - - op = opts.op = after; - return utils.resolve(_this6[op].apply(_this6, _toConsumableArray(args))).then(function (_result) { - // Allow for re-assignment from lifecycle hook - return _result === undefined ? result : _result; - }); - }); - }, - - /** - * Fired during {@link Mapper#destroy}. See - * {@link Mapper~beforeDestroyListener} for how to listen for this event. - * - * @event Mapper#beforeDestroy - * @see Mapper~beforeDestroyListener - * @see Mapper#destroy - */ - - /** - * Callback signature for the {@link Mapper#event:beforeDestroy} event. - * - * @example - * function onBeforeDestroy (id, opts) { - * // do something - * } - * store.on('beforeDestroy', onBeforeDestroy); - * - * @callback Mapper~beforeDestroyListener - * @param {string|number} id The `id` argument passed to {@link Mapper#beforeDestroy}. - * @param {object} opts The `opts` argument passed to {@link Mapper#beforeDestroy}. - * @see Mapper#event:beforeDestroy - * @see Mapper#destroy - * @since 3.0.0 - */ - - /** - * Fired during {@link Mapper#destroy}. See - * {@link Mapper~afterDestroyListener} for how to listen for this event. - * - * @event Mapper#afterDestroy - * @see Mapper~afterDestroyListener - * @see Mapper#destroy - */ - - /** - * Callback signature for the {@link Mapper#event:afterDestroy} event. - * - * @example - * function onAfterDestroy (id, opts, result) { - * // do something - * } - * store.on('afterDestroy', onAfterDestroy); - * - * @callback Mapper~afterDestroyListener - * @param {string|number} id The `id` argument passed to {@link Mapper#afterDestroy}. - * @param {object} opts The `opts` argument passed to {@link Mapper#afterDestroy}. - * @param {object} result The `result` argument passed to {@link Mapper#afterDestroy}. - * @see Mapper#event:afterDestroy - * @see Mapper#destroy - * @since 3.0.0 - */ - - /** - * Using an adapter, destroy the record with the given primary key. - * - * {@link Mapper#beforeDestroy} will be called before destroying the record. - * {@link Mapper#afterDestroy} will be called after destroying the record. - * - * @example - * // Destroy a specific blog post - * PostMapper.destroy(1234).then(() => { - * // Blog post #1234 has been destroyed - * }); - * - * @example - * // Get full response - * PostMapper.destroy(1234, { raw: true }).then((result) => { - * console.log(result.deleted); e.g. 1 - * console.log(...); // etc., more metadata can be found on the result - * }); - * - * @fires Mapper#beforeDestroy - * @fires Mapper#afterDestroy - * @method Mapper#destroy - * @param {(string|number)} id The primary key of the record to destroy. - * @param {object} [opts] Configuration options. Refer to the `destroy` method - * of whatever adapter you're using for more configuration options. - * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the - * adapter to use. - * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}. - * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}. - * @returns {Promise} Resolves when the record has been destroyed. Resolves - * even if no record was found to be destroyed. - * @since 3.0.0 - * @tutorial ["http://www.js-data.io/v3.0/docs/saving-data","Saving data"] - */ - destroy: function destroy(id, opts) { - return this.crud('destroy', id, opts); - }, - - /** - * Fired during {@link Mapper#destroyAll}. See - * {@link Mapper~beforeDestroyAllListener} for how to listen for this event. - * - * @event Mapper#beforeDestroyAll - * @see Mapper~beforeDestroyAllListener - * @see Mapper#destroyAll - */ - - /** - * Callback signature for the {@link Mapper#event:beforeDestroyAll} event. - * - * @example - * function onBeforeDestroyAll (query, opts) { - * // do something - * } - * store.on('beforeDestroyAll', onBeforeDestroyAll); - * - * @callback Mapper~beforeDestroyAllListener - * @param {object} query The `query` argument passed to {@link Mapper#beforeDestroyAll}. - * @param {object} opts The `opts` argument passed to {@link Mapper#beforeDestroyAll}. - * @see Mapper#event:beforeDestroyAll - * @see Mapper#destroyAll - * @since 3.0.0 - */ - - /** - * Fired during {@link Mapper#destroyAll}. See - * {@link Mapper~afterDestroyAllListener} for how to listen for this event. - * - * @event Mapper#afterDestroyAll - * @see Mapper~afterDestroyAllListener - * @see Mapper#destroyAll - */ - - /** - * Callback signature for the {@link Mapper#event:afterDestroyAll} event. - * - * @example - * function onAfterDestroyAll (query, opts, result) { - * // do something - * } - * store.on('afterDestroyAll', onAfterDestroyAll); - * - * @callback Mapper~afterDestroyAllListener - * @param {object} query The `query` argument passed to {@link Mapper#afterDestroyAll}. - * @param {object} opts The `opts` argument passed to {@link Mapper#afterDestroyAll}. - * @param {object} result The `result` argument passed to {@link Mapper#afterDestroyAll}. - * @see Mapper#event:afterDestroyAll - * @see Mapper#destroyAll - * @since 3.0.0 - */ - - /** - * Destroy the records selected by `query` via an adapter. If no `query` is - * provided then all records will be destroyed. - * - * {@link Mapper#beforeDestroyAll} will be called before destroying the records. - * {@link Mapper#afterDestroyAll} will be called after destroying the records. - * - * @example - * // Destroy all blog posts - * PostMapper.destroyAll().then(() => { - * // All blog posts have been destroyed - * }); - * - * @example - * // Destroy all "draft" blog posts - * PostMapper.destroyAll({ status: 'draft' }).then(() => { - * // All "draft" blog posts have been destroyed - * }); - * - * @example - * // Get full response - * const query = null; - * const options = { raw: true }; - * PostMapper.destroyAll(query, options).then((result) => { - * console.log(result.deleted); e.g. 14 - * console.log(...); // etc., more metadata can be found on the result - * }); - * - * @fires Mapper#beforeDestroyAll - * @fires Mapper#afterDestroyAll - * @method Mapper#destroyAll - * @param {object} [query={}] Selection query. See {@link query}. - * @param {object} [query.where] See {@link query.where}. - * @param {number} [query.offset] See {@link query.offset}. - * @param {number} [query.limit] See {@link query.limit}. - * @param {string|Array[]} [query.orderBy] See {@link query.orderBy}. - * @param {object} [opts] Configuration options. Refer to the `destroyAll` - * method of whatever adapter you're using for more configuration options. - * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the - * adapter to use. - * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}. - * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}. - * @returns {Promise} Resolves when the records have been destroyed. Resolves - * even if no records were found to be destroyed. - * @see query - * @since 3.0.0 - * @tutorial ["http://www.js-data.io/v3.0/docs/saving-data","Saving data"] - */ - destroyAll: function destroyAll(query, opts) { - return this.crud('destroyAll', query, opts); - }, - - /** - * Fired during {@link Mapper#find}. See - * {@link Mapper~beforeFindListener} for how to listen for this event. - * - * @event Mapper#beforeFind - * @see Mapper~beforeFindListener - * @see Mapper#find - */ - - /** - * Callback signature for the {@link Mapper#event:beforeFind} event. - * - * @example - * function onBeforeFind (id, opts) { - * // do something - * } - * store.on('beforeFind', onBeforeFind); - * - * @callback Mapper~beforeFindListener - * @param {string|number} id The `id` argument passed to {@link Mapper#beforeFind}. - * @param {object} opts The `opts` argument passed to {@link Mapper#beforeFind}. - * @see Mapper#event:beforeFind - * @see Mapper#find - * @since 3.0.0 - */ - - /** - * Fired during {@link Mapper#find}. See - * {@link Mapper~afterFindListener} for how to listen for this event. - * - * @event Mapper#afterFind - * @see Mapper~afterFindListener - * @see Mapper#find - */ - - /** - * Callback signature for the {@link Mapper#event:afterFind} event. - * - * @example - * function onAfterFind (id, opts, result) { - * // do something - * } - * store.on('afterFind', onAfterFind); - * - * @callback Mapper~afterFindListener - * @param {string|number} id The `id` argument passed to {@link Mapper#afterFind}. - * @param {object} opts The `opts` argument passed to {@link Mapper#afterFind}. - * @param {object} result The `result` argument passed to {@link Mapper#afterFind}. - * @see Mapper#event:afterFind - * @see Mapper#find - * @since 3.0.0 - */ - - /** - * Retrieve via an adapter the record with the given primary key. - * - * {@link Mapper#beforeFind} will be called before calling the adapter. - * {@link Mapper#afterFind} will be called after calling the adapter. - * - * @example - * PostMapper.find(1).then((post) => { - * console.log(post); // { id: 1, ...} - * }); - * - * @example - * // Get full response - * PostMapper.find(1, { raw: true }).then((result) => { - * console.log(result.data); // { id: 1, ...} - * console.log(result.found); // 1 - * console.log(...); // etc., more metadata can be found on the result - * }); - * - * @fires Mapper#beforeFind - * @fires Mapper#afterFind - * @method Mapper#find - * @param {(string|number)} id The primary key of the record to retrieve. - * @param {object} [opts] Configuration options. Refer to the `find` method - * of whatever adapter you're using for more configuration options. - * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the - * adapter to use. - * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}. - * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}. - * @param {string[]} [opts.with=[]] Relations to eager load in the request. - * @returns {Promise} Resolves with the found record. Resolves with - * `undefined` if no record was found. - * @see http://www.js-data.io/v3.0/docs/reading-data - * @since 3.0.0 - * @tutorial ["http://www.js-data.io/v3.0/docs/reading-data","Reading data"] - */ - find: function find(id, opts) { - return this.crud('find', id, opts); - }, - - /** - * Fired during {@link Mapper#findAll}. See - * {@link Mapper~beforeFindAllListener} for how to listen for this event. - * - * @event Mapper#beforeFindAll - * @see Mapper~beforeFindAllListener - * @see Mapper#findAll - */ - - /** - * Callback signature for the {@link Mapper#event:beforeFindAll} event. - * - * @example - * function onBeforeFindAll (query, opts) { - * // do something - * } - * store.on('beforeFindAll', onBeforeFindAll); - * - * @callback Mapper~beforeFindAllListener - * @param {object} query The `query` argument passed to {@link Mapper#beforeFindAll}. - * @param {object} opts The `opts` argument passed to {@link Mapper#beforeFindAll}. - * @see Mapper#event:beforeFindAll - * @see Mapper#findAll - * @since 3.0.0 - */ - - /** - * Fired during {@link Mapper#findAll}. See - * {@link Mapper~afterFindAllListener} for how to listen for this event. - * - * @event Mapper#afterFindAll - * @see Mapper~afterFindAllListener - * @see Mapper#findAll - */ - - /** - * Callback signature for the {@link Mapper#event:afterFindAll} event. - * - * @example - * function onAfterFindAll (query, opts, result) { - * // do something - * } - * store.on('afterFindAll', onAfterFindAll); - * - * @callback Mapper~afterFindAllListener - * @param {object} query The `query` argument passed to {@link Mapper#afterFindAll}. - * @param {object} opts The `opts` argument passed to {@link Mapper#afterFindAll}. - * @param {object} result The `result` argument passed to {@link Mapper#afterFindAll}. - * @see Mapper#event:afterFindAll - * @see Mapper#findAll - * @since 3.0.0 - */ - - /** - * Using the `query` argument, select records to retrieve via an adapter. - * - * {@link Mapper#beforeFindAll} will be called before calling the adapter. - * {@link Mapper#afterFindAll} will be called after calling the adapter. - * - * @example - * // Find all "published" blog posts - * PostMapper.findAll({ status: 'published' }).then((posts) => { - * console.log(posts); // [{ id: 1, status: 'published', ...}, ...] - * }); - * - * @example - * // Get full response - * PostMapper.findAll({ status: 'published' }, { raw: true }).then((result) => { - * console.log(result.data); // [{ id: 1, status: 'published', ...}, ...] - * console.log(result.found); // e.g. 13 - * console.log(...); // etc., more metadata can be found on the result - * }); - * - * @fires Mapper#beforeFindAll - * @fires Mapper#afterFindAll - * @method Mapper#findAll - * @param {object} [query={}] Selection query. See {@link query}. - * @param {object} [query.where] See {@link query.where}. - * @param {number} [query.offset] See {@link query.offset}. - * @param {number} [query.limit] See {@link query.limit}. - * @param {string|Array[]} [query.orderBy] See {@link query.orderBy}. - * @param {object} [opts] Configuration options. Refer to the `findAll` method - * of whatever adapter you're using for more configuration options. - * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the - * adapter to use. - * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}. - * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}. - * @param {string[]} [opts.with=[]] Relations to eager load in the request. - * @returns {Promise} Resolves with the found records, if any. - * @see query - * @since 3.0.0 - * @tutorial ["http://www.js-data.io/v3.0/docs/reading-data","Reading data"] - */ - findAll: function findAll(query, opts) { - return this.crud('findAll', query, opts); - }, - - /** - * Return the registered adapter with the given name or the default adapter if - * no name is provided. - * - * @method Mapper#getAdapter - * @param {string} [name] The name of the adapter to retrieve. - * @returns {Adapter} The adapter. - * @since 3.0.0 - * @tutorial ["http://www.js-data.io/v3.0/docs/connecting-to-a-data-source","Connecting to a data source"] - */ - getAdapter: function getAdapter(name) { - this.dbg('getAdapter', 'name:', name); - var adapter = this.getAdapterName(name); - - if (!adapter) { - throw utils.err("".concat(DOMAIN$6, "#getAdapter"), 'name')(400, 'string', name); - } - - return this.getAdapters()[adapter]; - }, - - /** - * Return the name of a registered adapter based on the given name or options, - * or the name of the default adapter if no name provided. - * - * @method Mapper#getAdapterName - * @param {(Object|string)} [opts] The name of an adapter or options, if any. - * @returns {string} The name of the adapter. - * @since 3.0.0 - * @tutorial ["http://www.js-data.io/v3.0/docs/connecting-to-a-data-source","Connecting to a data source"] - */ - getAdapterName: function getAdapterName(opts) { - opts || (opts = {}); - - if (utils.isString(opts)) { - opts = { - adapter: opts - }; - } - - return opts.adapter || opts.defaultAdapter; - }, - - /** - * Get the object of registered adapters for this Mapper. - * - * @method Mapper#getAdapters - * @returns {Object} {@link Mapper#_adapters} - * @since 3.0.0 - * @tutorial ["http://www.js-data.io/v3.0/docs/connecting-to-a-data-source","Connecting to a data source"] - */ - getAdapters: function getAdapters() { - return this._adapters; - }, - - /** - * Returns this Mapper's {@link Schema}. - * - * @method Mapper#getSchema - * @returns {Schema} This Mapper's {@link Schema}. - * @see Mapper#schema - * @since 3.0.0 - */ - getSchema: function getSchema() { - return this.schema; - }, - - /** - * Defines a hasMany relationship. Only useful if you're managing your - * Mappers manually and not using a Container or DataStore component. - * - * @example - * UserMapper.hasMany(PostMapper, { - * // post.user_id points to user.id - * foreignKey: 'user_id' - * // post records will be attached to user records at "user.posts" - * localField: 'posts' - * }); - * - * @method Mapper#hasMany - * @see http://www.js-data.io/v3.0/docs/relations - * @since 3.0.0 - */ - hasMany: function hasMany$1(relatedMapper, opts) { - return hasMany(relatedMapper, opts)(this); - }, - - /** - * Defines a hasOne relationship. Only useful if you're managing your Mappers - * manually and not using a {@link Container} or {@link DataStore} component. - * - * @example - * UserMapper.hasOne(ProfileMapper, { - * // profile.user_id points to user.id - * foreignKey: 'user_id' - * // profile records will be attached to user records at "user.profile" - * localField: 'profile' - * }); - * - * @method Mapper#hasOne - * @see http://www.js-data.io/v3.0/docs/relations - * @since 3.0.0 - */ - hasOne: function hasOne$1(relatedMapper, opts) { - return hasOne(relatedMapper, opts)(this); - }, - - /** - * Return whether `record` is an instance of this Mapper's recordClass. - * - * @example - * const post = PostMapper.createRecord(); - * - * console.log(PostMapper.is(post)); // true - * // Equivalent to what's above - * console.log(post instanceof PostMapper.recordClass); // true - * - * @method Mapper#is - * @param {Object|Record} record The record to check. - * @returns {boolean} Whether `record` is an instance of this Mapper's - * {@link Mapper#recordClass}. - * @since 3.0.0 - */ - is: function is(record) { - var recordClass = this.recordClass; - return recordClass ? record instanceof recordClass : false; - }, - - /** - * Register an adapter on this Mapper under the given name. - * - * @method Mapper#registerAdapter - * @param {string} name The name of the adapter to register. - * @param {Adapter} adapter The adapter to register. - * @param {object} [opts] Configuration options. - * @param {boolean} [opts.default=false] Whether to make the adapter the - * default adapter for this Mapper. - * @since 3.0.0 - * @tutorial ["http://www.js-data.io/v3.0/docs/connecting-to-a-data-source","Connecting to a data source"] - */ - registerAdapter: function registerAdapter(name, adapter, opts) { - opts || (opts = {}); - this.getAdapters()[name] = adapter; // Optionally make it the default adapter for the target. - - if (opts === true || opts.default) { - this.defaultAdapter = name; - } - }, - _runHook: function _runHook(hookName) { - for (var _len3 = arguments.length, hookArgs = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) { - hookArgs[_key3 - 1] = arguments[_key3]; - } - - var defaultValueIndex = hookName.indexOf('after') === 0 ? hookArgs.length - 1 : 0; - return utils.resolve(this[hookName].apply(this, hookArgs)).then(function (overridenResult) { - return overridenResult === undefined ? hookArgs[defaultValueIndex] : overridenResult; - }); - }, - _invokeAdapterMethod: function _invokeAdapterMethod(method, propsOrRecords, opts) { - var _this7 = this; - - var conversionOptions = { - with: opts.pass || [] - }; - var object; - this.dbg(opts.op, propsOrRecords, opts); - - if (utils.isArray(propsOrRecords)) { - object = propsOrRecords.map(function (record) { - return _this7.toJSON(record, conversionOptions); - }); - } else { - object = this.toJSON(propsOrRecords, conversionOptions); - } - - return this.getAdapter(opts.adapter)[method](this, object, opts); - }, - - /** - * Select records according to the `query` argument, and aggregate the sum - * value of the property specified by `field`. - * - * {@link Mapper#beforeSum} will be called before calling the adapter. - * {@link Mapper#afterSum} will be called after calling the adapter. - * - * @example - * PurchaseOrderMapper.sum('amount', { status: 'paid' }).then((amountPaid) => { - * console.log(amountPaid); // e.g. 451125.34 - * }); - * - * @method Mapper#sum - * @param {string} field The field to sum. - * @param {object} [query={}] Selection query. See {@link query}. - * @param {object} [query.where] See {@link query.where}. - * @param {number} [query.offset] See {@link query.offset}. - * @param {number} [query.limit] See {@link query.limit}. - * @param {string|Array[]} [query.orderBy] See {@link query.orderBy}. - * @param {object} [opts] Configuration options. Refer to the `sum` method - * of whatever adapter you're using for more configuration options. - * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the - * adapter to use. - * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}. - * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}. - * @returns {Promise} Resolves with the aggregated sum. - * @since 3.0.0 - */ - sum: function sum(field, query, opts) { - return this.crud('sum', field, query, opts); - }, - - /** - * Return a plain object representation of the given record. Relations can - * be optionally be included. Non-schema properties can be excluded. - * - * @example - * import { Mapper, Schema } from 'js-data'; - * const PersonMapper = new Mapper({ - * name: 'person', - * schema: { - * properties: { - * name: { type: 'string' }, - * id: { type: 'string' } - * } - * } - * }); - * const person = PersonMapper.createRecord({ id: 1, name: 'John', foo: 'bar' }); - * // "foo" is stripped by toJSON() - * console.log(PersonMapper.toJSON(person)); // {"id":1,"name":"John"} - * - * const PersonRelaxedMapper = new Mapper({ - * name: 'personRelaxed', - * schema: { - * properties: { - * name: { type: 'string' }, - * id: { type: 'string' } - * }, - * additionalProperties: true - * } - * }); - * const person2 = PersonRelaxedMapper.createRecord({ id: 1, name: 'John', foo: 'bar' }); - * // "foo" is not stripped by toJSON - * console.log(PersonRelaxedMapper.toJSON(person2)); // {"id":1,"name":"John","foo":"bar"} - * - * @method Mapper#toJSON - * @param {Record|Record[]} records Record or records from which to create a - * POJO representation. - * @param {object} [opts] Configuration options. - * @param {string[]} [opts.with] Array of relation names or relation fields - * to include in the POJO representation. - * @param {boolean} [opts.withAll] Whether to simply include all relations in - * the representation. Overrides `opts.with`. - * @returns {Object|Object[]} POJO representation of the record or records. - * @since 3.0.0 - */ - toJSON: function toJSON(records, opts) { - var _this8 = this; - - var record; - opts || (opts = {}); - - if (utils.isArray(records)) { - return records.map(function (record) { - return _this8.toJSON(record, opts); - }); - } else { - record = records; - } - - var relationFields = (this ? this.relationFields : []) || []; - var json = {}; // Copy properties defined in the schema - - if (this && this.schema) { - json = this.schema.pick(record); - } else { - for (var key in record) { - if (relationFields.indexOf(key) === -1) { - json[key] = utils.plainCopy(record[key]); - } - } - } // The user wants to include relations in the resulting plain object representation - - - if (this && opts.withAll) { - opts.with = relationFields.slice(); - } - - if (this && opts.with) { - if (utils.isString(opts.with)) { - opts.with = [opts.with]; - } - - utils.forEachRelation(this, opts, function (def, optsCopy) { - var relationData = def.getLocalField(record); - - if (relationData) { - // The actual recursion - if (utils.isArray(relationData)) { - def.setLocalField(json, relationData.map(function (item) { - return def.getRelation().toJSON(item, optsCopy); - })); - } else { - def.setLocalField(json, def.getRelation().toJSON(relationData, optsCopy)); - } - } - }); - } - - return json; - }, - - /** - * Fired during {@link Mapper#update}. See - * {@link Mapper~beforeUpdateListener} for how to listen for this event. - * - * @event Mapper#beforeUpdate - * @see Mapper~beforeUpdateListener - * @see Mapper#update - */ - - /** - * Callback signature for the {@link Mapper#event:beforeUpdate} event. - * - * @example - * function onBeforeUpdate (id, props, opts) { - * // do something - * } - * store.on('beforeUpdate', onBeforeUpdate); - * - * @callback Mapper~beforeUpdateListener - * @param {string|number} id The `id` argument passed to {@link Mapper#beforeUpdate}. - * @param {object} props The `props` argument passed to {@link Mapper#beforeUpdate}. - * @param {object} opts The `opts` argument passed to {@link Mapper#beforeUpdate}. - * @see Mapper#event:beforeUpdate - * @see Mapper#update - * @since 3.0.0 - */ - - /** - * Fired during {@link Mapper#update}. See - * {@link Mapper~afterUpdateListener} for how to listen for this event. - * - * @event Mapper#afterUpdate - * @see Mapper~afterUpdateListener - * @see Mapper#update - */ - - /** - * Callback signature for the {@link Mapper#event:afterUpdate} event. - * - * @example - * function onAfterUpdate (id, props, opts, result) { - * // do something - * } - * store.on('afterUpdate', onAfterUpdate); - * - * @callback Mapper~afterUpdateListener - * @param {string|number} id The `id` argument passed to {@link Mapper#afterUpdate}. - * @param {object} props The `props` argument passed to {@link Mapper#afterUpdate}. - * @param {object} opts The `opts` argument passed to {@link Mapper#afterUpdate}. - * @param {object} result The `result` argument passed to {@link Mapper#afterUpdate}. - * @see Mapper#event:afterUpdate - * @see Mapper#update - * @since 3.0.0 - */ - - /** - * Using an adapter, update the record with the primary key specified by the - * `id` argument. - * - * {@link Mapper#beforeUpdate} will be called before updating the record. - * {@link Mapper#afterUpdate} will be called after updating the record. - * - * @example - * // Update a specific post - * PostMapper.update(1234, { - * status: 'published', - * published_at: new Date() - * }).then((post) => { - * console.log(post); // { id: 1234, status: 'published', ... } - * }); - * - * @fires Mapper#beforeUpdate - * @fires Mapper#afterUpdate - * @method Mapper#update - * @param {(string|number)} id The primary key of the record to update. - * @param {object} props The update to apply to the record. - * @param {object} [opts] Configuration options. Refer to the `update` method - * of whatever adapter you're using for more configuration options. - * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the - * adapter to use. - * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}. - * @param {boolean} [opts.noValidate={@link Mapper#noValidate}] See {@link Mapper#noValidate}. - * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}. - * transaction. - * @returns {Promise} Resolves with the updated record. Rejects if the record - * could not be found. - * @since 3.0.0 - * @tutorial ["http://www.js-data.io/v3.0/docs/saving-data","Saving data"] - */ - update: function update(id, props, opts) { - return this.crud('update', id, props, opts); - }, - - /** - * Fired during {@link Mapper#updateAll}. See - * {@link Mapper~beforeUpdateAllListener} for how to listen for this event. - * - * @event Mapper#beforeUpdateAll - * @see Mapper~beforeUpdateAllListener - * @see Mapper#updateAll - */ - - /** - * Callback signature for the {@link Mapper#event:beforeUpdateAll} event. - * - * @example - * function onBeforeUpdateAll (props, query, opts) { - * // do something - * } - * store.on('beforeUpdateAll', onBeforeUpdateAll); - * - * @callback Mapper~beforeUpdateAllListener - * @param {object} props The `props` argument received by {@link Mapper#beforeUpdateAll}. - * @param {object} query The `query` argument received by {@link Mapper#beforeUpdateAll}. - * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdateAll}. - * @see Mapper#event:beforeUpdateAll - * @see Mapper#updateAll - * @since 3.0.0 - */ - - /** - * Fired during {@link Mapper#updateAll}. See - * {@link Mapper~afterUpdateAllListener} for how to listen for this event. - * - * @event Mapper#afterUpdateAll - * @see Mapper~afterUpdateAllListener - * @see Mapper#updateAll - */ - - /** - * Callback signature for the {@link Mapper#event:afterUpdateAll} event. - * - * @example - * function onAfterUpdateAll (props, query, opts, result) { - * // do something - * } - * store.on('afterUpdateAll', onAfterUpdateAll); - * - * @callback Mapper~afterUpdateAllListener - * @param {object} props The `props` argument received by {@link Mapper#afterUpdateAll}. - * @param {object} query The `query` argument received by {@link Mapper#afterUpdateAll}. - * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdateAll}. - * @param {object} result The `result` argument received by {@link Mapper#afterUpdateAll}. - * @see Mapper#event:afterUpdateAll - * @see Mapper#updateAll - * @since 3.0.0 - */ - - /** - * Using the `query` argument, perform the a single updated to the selected - * records. - * - * {@link Mapper#beforeUpdateAll} will be called before making the update. - * {@link Mapper#afterUpdateAll} will be called after making the update. - * - * @example - * // Turn all of John's blog posts into drafts. - * const update = { status: draft: published_at: null }; - * const query = { userId: 1234 }; - * PostMapper.updateAll(update, query).then((posts) => { - * console.log(posts); // [...] - * }); - * - * @fires Mapper#beforeUpdateAll - * @fires Mapper#afterUpdateAll - * @method Mapper#updateAll - * @param {object} props Update to apply to selected records. - * @param {object} [query={}] Selection query. See {@link query}. - * @param {object} [query.where] See {@link query.where}. - * @param {number} [query.offset] See {@link query.offset}. - * @param {number} [query.limit] See {@link query.limit}. - * @param {string|Array[]} [query.orderBy] See {@link query.orderBy}. - * @param {object} [opts] Configuration options. Refer to the `updateAll` - * method of whatever adapter you're using for more configuration options. - * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the - * adapter to use. - * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}. - * @param {boolean} [opts.noValidate={@link Mapper#noValidate}] See {@link Mapper#noValidate}. - * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}. - * @returns {Promise} Resolves with the update records, if any. - * @see query - * @since 3.0.0 - * @tutorial ["http://www.js-data.io/v3.0/docs/saving-data","Saving data"] - */ - updateAll: function updateAll(props, query, opts) { - return this.crud('updateAll', props, query, opts); - }, - - /** - * Fired during {@link Mapper#updateMany}. See - * {@link Mapper~beforeUpdateManyListener} for how to listen for this event. - * - * @event Mapper#beforeUpdateMany - * @see Mapper~beforeUpdateManyListener - * @see Mapper#updateMany - */ - - /** - * Callback signature for the {@link Mapper#event:beforeUpdateMany} event. - * - * @example - * function onBeforeUpdateMany (records, opts) { - * // do something - * } - * store.on('beforeUpdateMany', onBeforeUpdateMany); - * - * @callback Mapper~beforeUpdateManyListener - * @param {object} records The `records` argument received by {@link Mapper#beforeUpdateMany}. - * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdateMany}. - * @see Mapper#event:beforeUpdateMany - * @see Mapper#updateMany - * @since 3.0.0 - */ - - /** - * Fired during {@link Mapper#updateMany}. See - * {@link Mapper~afterUpdateManyListener} for how to listen for this event. - * - * @event Mapper#afterUpdateMany - * @see Mapper~afterUpdateManyListener - * @see Mapper#updateMany - */ - - /** - * Callback signature for the {@link Mapper#event:afterUpdateMany} event. - * - * @example - * function onAfterUpdateMany (records, opts, result) { - * // do something - * } - * store.on('afterUpdateMany', onAfterUpdateMany); - * - * @callback Mapper~afterUpdateManyListener - * @param {object} records The `records` argument received by {@link Mapper#afterUpdateMany}. - * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdateMany}. - * @param {object} result The `result` argument received by {@link Mapper#afterUpdateMany}. - * @see Mapper#event:afterUpdateMany - * @see Mapper#updateMany - * @since 3.0.0 - */ - - /** - * Given an array of updates, perform each of the updates via an adapter. Each - * "update" is a hash of properties with which to update an record. Each - * update must contain the primary key of the record to be updated. - * - * {@link Mapper#beforeUpdateMany} will be called before making the update. - * {@link Mapper#afterUpdateMany} will be called after making the update. - * - * @example - * PostMapper.updateMany([ - * { id: 1234, status: 'draft' }, - * { id: 2468, status: 'published', published_at: new Date() } - * ]).then((posts) => { - * console.log(posts); // [...] - * }); - * - * @fires Mapper#beforeUpdateMany - * @fires Mapper#afterUpdateMany - * @method Mapper#updateMany - * @param {Record[]} records Array up record updates. - * @param {object} [opts] Configuration options. Refer to the `updateMany` - * method of whatever adapter you're using for more configuration options. - * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the - * adapter to use. - * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}. - * @param {boolean} [opts.noValidate={@link Mapper#noValidate}] See {@link Mapper#noValidate}. - * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}. - * @returns {Promise} Resolves with the updated records. Rejects if any of the - * records could be found. - * @since 3.0.0 - * @tutorial ["http://www.js-data.io/v3.0/docs/saving-data","Saving data"] - */ - updateMany: function updateMany(records, opts) { - return this.crud('updateMany', records, opts); - }, - - /** - * Validate the given record or records according to this Mapper's - * {@link Schema}. If there are no validation errors then the return value - * will be `undefined`. - * - * @example - * import {Mapper, Schema} from 'js-data' - * const PersonSchema = new Schema({ - * properties: { - * name: { type: 'string' }, - * id: { type: 'string' } - * } - * }); - * const PersonMapper = new Mapper({ - * name: 'person', - * schema: PersonSchema - * }); - * let errors = PersonMapper.validate({ name: 'John' }); - * console.log(errors); // undefined - * errors = PersonMapper.validate({ name: 123 }); - * console.log(errors); // [{ expected: 'one of (string)', actual: 'number', path: 'name' }] - * - * @method Mapper#validate - * @param {Object|Object[]} record The record or records to validate. - * @param {object} [opts] Configuration options. Passed to - * {@link Schema#validate}. - * @returns {Object[]} Array of errors or `undefined` if no errors. - * @since 3.0.0 - */ - validate: function validate(record, opts) { - opts || (opts = {}); - var schema = this.getSchema(); - - if (!schema) { - return; - } - - var _opts = utils.pick(opts, ['existingOnly']); - - if (utils.isArray(record)) { - var errors = record.map(function (_record) { - return schema.validate(_record, utils.pick(_opts, ['existingOnly'])); - }); - return errors.some(Boolean) ? errors : undefined; - } - - return schema.validate(record, _opts); - }, - - /** - * Method used to wrap data returned by an adapter with this Mapper's - * {@link Mapper#recordClass}. This method is used by all of a Mapper's CRUD - * methods. The provided implementation of this method assumes that the `data` - * passed to it is a record or records that need to be wrapped with - * {@link Mapper#createRecord}. Override with care. - * - * Provided implementation of {@link Mapper#wrap}: - * - * ``` - * function (data, opts) { - * return this.createRecord(data, opts); - * } - * ``` - * - * @example - * const PostMapper = new Mapper({ - * name: 'post', - * // Override to customize behavior - * wrap (data, opts) { - * const originalWrap = this.constructor.prototype.wrap; - * // Let's say "GET /post" doesn't return JSON quite like JSData expects, - * // but the actual post records are nested under a "posts" field. So, - * // we override Mapper#wrap to handle this special case. - * if (opts.op === 'findAll') { - * return originalWrap.call(this, data.posts, opts); - * } - * // Otherwise perform original behavior - * return originalWrap.call(this, data, opts); - * } - * }); - * - * @method Mapper#wrap - * @param {Object|Object[]} data The record or records to be wrapped. - * @param {object} [opts] Configuration options. Passed to {@link Mapper#createRecord}. - * @returns {Record|Record[]} The wrapped record or records. - * @since 3.0.0 - */ - wrap: function wrap(data, opts) { - return this.createRecord(data, opts); - }, - - /** - * @ignore - */ - defineRelations: function defineRelations() { - var _this9 = this; - - // Setup the mapper's relations, including generating Mapper#relationList - // and Mapper#relationFields - utils.forOwn(this.relations, function (group, type) { - utils.forOwn(group, function (relations, _name) { - if (utils.isObject(relations)) { - relations = [relations]; - } - - relations.forEach(function (def) { - var relatedMapper = _this9.datastore.getMapperByName(_name) || _name; - - def.getRelation = function () { - return _this9.datastore.getMapper(_name); - }; - - if (typeof Relation[type] !== 'function') { - throw utils.err(DOMAIN$6, 'defineRelations')(400, 'relation type (hasOne, hasMany, etc)', type, true); - } - - _this9[type](relatedMapper, def); - }); - }); - }); - } -}); -/** - * Create a subclass of this Mapper: - * - * @example Mapper.extend - * const JSData = require('js-data'); - * const { Mapper } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * // Extend the class using ES2015 class syntax. - * class CustomMapperClass extends Mapper { - * foo () { return 'bar'; } - * static beep () { return 'boop'; } - * }; - * const customMapper = new CustomMapperClass(); - * console.log(customMapper.foo()); - * console.log(CustomMapperClass.beep()); - * - * // Extend the class using alternate method. - * const OtherMapperClass = Mapper.extend({ - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }); - * const otherMapper = new OtherMapperClass(); - * console.log(otherMapper.foo()); - * console.log(OtherMapperClass.beep()); - * - * // Extend the class, providing a custom constructor. - * function AnotherMapperClass () { - * Mapper.call(this); - * this.created_at = new Date().getTime(); - * } - * Mapper.extend({ - * constructor: AnotherMapperClass, - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }) - * const anotherMapper = new AnotherMapperClass(); - * console.log(anotherMapper.created_at); - * console.log(anotherMapper.foo()); - * console.log(AnotherMapperClass.beep()); - * - * @method Mapper.extend - * @param {object} [props={}] Properties to add to the prototype of the - * subclass. - * @param {object} [props.constructor] Provide a custom constructor function - * to be used as the subclass itself. - * @param {object} [classProps={}] Static properties to add to the subclass. - * @returns {Constructor} Subclass of this Mapper class. - * @since 3.0.0 - */ - -var DOMAIN$7 = 'Container'; -var proxiedMapperMethods = [ -/** - * Wrapper for {@link Mapper#count}. - * - * @example - * // Get the number of published blog posts - * import { Container } from 'js-data'; - * import RethinkDBAdapter from 'js-data-rethinkdb'; - * const store = new Container(); - * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); - * store.defineMapper('post'); - * - * store.count('post', { status: 'published' }).then((numPublished) => { - * console.log(numPublished); // e.g. 45 - * }); - * - * @method Container#count - * @param {string} name Name of the {@link Mapper} to target. - * @param {object} [query] See {@link Mapper#count}. - * @param {object} [opts] See {@link Mapper#count}. - * @returns {Promise} See {@link Mapper#count}. - * @see Mapper#count - * @since 3.0.0 - */ -'count', -/** - * Fired during {@link Container#create}. See - * {@link Container~beforeCreateListener} for how to listen for this event. - * - * @event Container#beforeCreate - * @see Container~beforeCreateListener - * @see Container#create - */ - -/** - * Callback signature for the {@link Container#event:beforeCreate} event. - * - * @example - * function onBeforeCreate (mapperName, props, opts) { - * // do something - * } - * store.on('beforeCreate', onBeforeCreate); - * - * @callback Container~beforeCreateListener - * @param {string} name The `name` argument received by {@link Mapper#beforeCreate}. - * @param {object} props The `props` argument received by {@link Mapper#beforeCreate}. - * @param {object} opts The `opts` argument received by {@link Mapper#beforeCreate}. - * @see Container#event:beforeCreate - * @see Container#create - * @since 3.0.0 - */ - -/** - * Fired during {@link Container#create}. See - * {@link Container~afterCreateListener} for how to listen for this event. - * - * @event Container#afterCreate - * @see Container~afterCreateListener - * @see Container#create - */ - -/** - * Callback signature for the {@link Container#event:afterCreate} event. - * - * @example - * function onAfterCreate (mapperName, props, opts, result) { - * // do something - * } - * store.on('afterCreate', onAfterCreate); - * - * @callback Container~afterCreateListener - * @param {string} name The `name` argument received by {@link Mapper#afterCreate}. - * @param {object} props The `props` argument received by {@link Mapper#afterCreate}. - * @param {object} opts The `opts` argument received by {@link Mapper#afterCreate}. - * @param {object} result The `result` argument received by {@link Mapper#afterCreate}. - * @see Container#event:afterCreate - * @see Container#create - * @since 3.0.0 - */ - -/** - * Wrapper for {@link Mapper#create}. - * - * @example - * // Create and save a new blog post - * import { Container } from 'js-data'; - * import RethinkDBAdapter from 'js-data-rethinkdb'; - * const store = new Container(); - * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); - * store.defineMapper('post'); - * - * store.create('post', { - * title: 'Modeling your data', - * status: 'draft' - * }).then((post) => { - * console.log(post); // { id: 1234, status: 'draft', ... } - * }); - * - * @fires Container#beforeCreate - * @fires Container#afterCreate - * @method Container#create - * @param {string} name Name of the {@link Mapper} to target. - * @param {object} props See {@link Mapper#create}. - * @param {object} [opts] See {@link Mapper#create}. - * @returns {Promise} See {@link Mapper#create}. - * @see Mapper#create - * @since 3.0.0 - */ -'create', -/** - * Fired during {@link Container#createMany}. See - * {@link Container~beforeCreateManyListener} for how to listen for this event. - * - * @event Container#beforeCreateMany - * @see Container~beforeCreateManyListener - * @see Container#createMany - */ - -/** - * Callback signature for the {@link Container#event:beforeCreateMany} event. - * - * @example - * function onBeforeCreateMany (mapperName, records, opts) { - * // do something - * } - * store.on('beforeCreateMany', onBeforeCreateMany); - * - * @callback Container~beforeCreateManyListener - * @param {string} name The `name` argument received by {@link Mapper#beforeCreateMany}. - * @param {object} records The `records` argument received by {@link Mapper#beforeCreateMany}. - * @param {object} opts The `opts` argument received by {@link Mapper#beforeCreateMany}. - * @see Container#event:beforeCreateMany - * @see Container#createMany - * @since 3.0.0 - */ - -/** - * Fired during {@link Container#createMany}. See - * {@link Container~afterCreateManyListener} for how to listen for this event. - * - * @event Container#afterCreateMany - * @see Container~afterCreateManyListener - * @see Container#createMany - */ - -/** - * Callback signature for the {@link Container#event:afterCreateMany} event. - * - * @example - * function onAfterCreateMany (mapperName, records, opts, result) { - * // do something - * } - * store.on('afterCreateMany', onAfterCreateMany); - * - * @callback Container~afterCreateManyListener - * @param {string} name The `name` argument received by {@link Mapper#afterCreateMany}. - * @param {object} records The `records` argument received by {@link Mapper#afterCreateMany}. - * @param {object} opts The `opts` argument received by {@link Mapper#afterCreateMany}. - * @param {object} result The `result` argument received by {@link Mapper#afterCreateMany}. - * @see Container#event:afterCreateMany - * @see Container#createMany - * @since 3.0.0 - */ - -/** - * Wrapper for {@link Mapper#createMany}. - * - * @example - * // Create and save several new blog posts - * import { Container } from 'js-data'; - * import RethinkDBAdapter from 'js-data-rethinkdb'; - * const store = new Container(); - * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); - * store.defineMapper('post'); - * - * store.createMany('post', [{ - * title: 'Modeling your data', - * status: 'draft' - * }, { - * title: 'Reading data', - * status: 'draft' - * }]).then((posts) => { - * console.log(posts[0]); // { id: 1234, status: 'draft', ... } - * console.log(posts[1]); // { id: 1235, status: 'draft', ... } - * }); - * - * @fires Container#beforeCreateMany - * @fires Container#afterCreateMany - * @method Container#createMany - * @param {string} name Name of the {@link Mapper} to target. - * @param {Record[]} records See {@link Mapper#createMany}. - * @param {object} [opts] See {@link Mapper#createMany}. - * @returns {Promise} See {@link Mapper#createMany}. - * @see Mapper#createMany - * @since 3.0.0 - */ -'createMany', -/** - * Wrapper for {@link Mapper#createRecord}. - * - * __Note:__ This method does __not__ interact with any adapter, and does - * __not__ save any data. It only creates new objects in memory. - * - * @example - * // Create empty unsaved record instance - * import { Container } from 'js-data'; - * const store = new Container(); - * store.defineMapper('post'); - * const post = PostMapper.createRecord(); - * - * @method Container#createRecord - * @param {string} name Name of the {@link Mapper} to target. - * @param {Object|Object[]} props See {@link Mapper#createRecord}. - * @param {object} [opts] See {@link Mapper#createRecord}. - * @returns {Promise} See {@link Mapper#createRecord}. - * @see Mapper#createRecord - * @since 3.0.0 - */ -'createRecord', -/** - * Fired during {@link Container#destroy}. See - * {@link Container~beforeDestroyListener} for how to listen for this event. - * - * @event Container#beforeDestroy - * @see Container~beforeDestroyListener - * @see Container#destroy - */ - -/** - * Callback signature for the {@link Container#event:beforeDestroy} event. - * - * @example - * function onBeforeDestroy (mapperName, id, opts) { - * // do something - * } - * store.on('beforeDestroy', onBeforeDestroy); - * - * @callback Container~beforeDestroyListener - * @param {string} name The `name` argument received by {@link Mapper#beforeDestroy}. - * @param {string|number} id The `id` argument received by {@link Mapper#beforeDestroy}. - * @param {object} opts The `opts` argument received by {@link Mapper#beforeDestroy}. - * @see Container#event:beforeDestroy - * @see Container#destroy - * @since 3.0.0 - */ - -/** - * Fired during {@link Container#destroy}. See - * {@link Container~afterDestroyListener} for how to listen for this event. - * - * @event Container#afterDestroy - * @see Container~afterDestroyListener - * @see Container#destroy - */ - -/** - * Callback signature for the {@link Container#event:afterDestroy} event. - * - * @example - * function onAfterDestroy (mapperName, id, opts, result) { - * // do something - * } - * store.on('afterDestroy', onAfterDestroy); - * - * @callback Container~afterDestroyListener - * @param {string} name The `name` argument received by {@link Mapper#afterDestroy}. - * @param {string|number} id The `id` argument received by {@link Mapper#afterDestroy}. - * @param {object} opts The `opts` argument received by {@link Mapper#afterDestroy}. - * @param {object} result The `result` argument received by {@link Mapper#afterDestroy}. - * @see Container#event:afterDestroy - * @see Container#destroy - * @since 3.0.0 - */ - -/** - * Wrapper for {@link Mapper#destroy}. - * - * @example - * // Destroy a specific blog post - * import { Container } from 'js-data'; - * import RethinkDBAdapter from 'js-data-rethinkdb'; - * const store = new Container(); - * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); - * store.defineMapper('post'); - * - * store.destroy('post', 1234).then(() => { - * // Blog post #1234 has been destroyed - * }); - * - * @fires Container#beforeDestroy - * @fires Container#afterDestroy - * @method Container#destroy - * @param {string} name Name of the {@link Mapper} to target. - * @param {(string|number)} id See {@link Mapper#destroy}. - * @param {object} [opts] See {@link Mapper#destroy}. - * @returns {Promise} See {@link Mapper#destroy}. - * @see Mapper#destroy - * @since 3.0.0 - */ -'destroy', -/** - * Fired during {@link Container#destroyAll}. See - * {@link Container~beforeDestroyAllListener} for how to listen for this event. - * - * @event Container#beforeDestroyAll - * @see Container~beforeDestroyAllListener - * @see Container#destroyAll - */ - -/** - * Callback signature for the {@link Container#event:beforeDestroyAll} event. - * - * @example - * function onBeforeDestroyAll (mapperName, query, opts) { - * // do something - * } - * store.on('beforeDestroyAll', onBeforeDestroyAll); - * - * @callback Container~beforeDestroyAllListener - * @param {string} name The `name` argument received by {@link Mapper#beforeDestroyAll}. - * @param {object} query The `query` argument received by {@link Mapper#beforeDestroyAll}. - * @param {object} opts The `opts` argument received by {@link Mapper#beforeDestroyAll}. - * @see Container#event:beforeDestroyAll - * @see Container#destroyAll - * @since 3.0.0 - */ - -/** - * Fired during {@link Container#destroyAll}. See - * {@link Container~afterDestroyAllListener} for how to listen for this event. - * - * @event Container#afterDestroyAll - * @see Container~afterDestroyAllListener - * @see Container#destroyAll - */ - -/** - * Callback signature for the {@link Container#event:afterDestroyAll} event. - * - * @example - * function onAfterDestroyAll (mapperName, query, opts, result) { - * // do something - * } - * store.on('afterDestroyAll', onAfterDestroyAll); - * - * @callback Container~afterDestroyAllListener - * @param {string} name The `name` argument received by {@link Mapper#afterDestroyAll}. - * @param {object} query The `query` argument received by {@link Mapper#afterDestroyAll}. - * @param {object} opts The `opts` argument received by {@link Mapper#afterDestroyAll}. - * @param {object} result The `result` argument received by {@link Mapper#afterDestroyAll}. - * @see Container#event:afterDestroyAll - * @see Container#destroyAll - * @since 3.0.0 - */ - -/** - * Wrapper for {@link Mapper#destroyAll}. - * - * @example - * // Destroy all "draft" blog posts - * import { Container } from 'js-data'; - * import RethinkDBAdapter from 'js-data-rethinkdb'; - * const store = new Container(); - * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); - * store.defineMapper('post'); - * - * store.destroyAll('post', { status: 'draft' }).then(() => { - * // All "draft" blog posts have been destroyed - * }); - * - * @fires Container#beforeDestroyAll - * @fires Container#afterDestroyAll - * @method Container#destroyAll - * @param {string} name Name of the {@link Mapper} to target. - * @param {object} [query] See {@link Mapper#destroyAll}. - * @param {object} [opts] See {@link Mapper#destroyAll}. - * @returns {Promise} See {@link Mapper#destroyAll}. - * @see Mapper#destroyAll - * @since 3.0.0 - */ -'destroyAll', -/** - * Fired during {@link Container#find}. See - * {@link Container~beforeFindListener} for how to listen for this event. - * - * @event Container#beforeFind - * @see Container~beforeFindListener - * @see Container#find - */ - -/** - * Callback signature for the {@link Container#event:beforeFind} event. - * - * @example - * function onBeforeFind (mapperName, id, opts) { - * // do something - * } - * store.on('beforeFind', onBeforeFind); - * - * @callback Container~beforeFindListener - * @param {string} name The `name` argument received by {@link Mapper#beforeFind}. - * @param {string|number} id The `id` argument received by {@link Mapper#beforeFind}. - * @param {object} opts The `opts` argument received by {@link Mapper#beforeFind}. - * @see Container#event:beforeFind - * @see Container#find - * @since 3.0.0 - */ - -/** - * Fired during {@link Container#find}. See - * {@link Container~afterFindListener} for how to listen for this event. - * - * @event Container#afterFind - * @see Container~afterFindListener - * @see Container#find - */ - -/** - * Callback signature for the {@link Container#event:afterFind} event. - * - * @example - * function onAfterFind (mapperName, id, opts, result) { - * // do something - * } - * store.on('afterFind', onAfterFind); - * - * @callback Container~afterFindListener - * @param {string} name The `name` argument received by {@link Mapper#afterFind}. - * @param {string|number} id The `id` argument received by {@link Mapper#afterFind}. - * @param {object} opts The `opts` argument received by {@link Mapper#afterFind}. - * @param {object} result The `result` argument received by {@link Mapper#afterFind}. - * @see Container#event:afterFind - * @see Container#find - * @since 3.0.0 - */ - -/** - * Wrapper for {@link Mapper#find}. - * - * @example - * import { Container } from 'js-data'; - * import RethinkDBAdapter from 'js-data-rethinkdb'; - * const store = new Container(); - * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); - * store.defineMapper('post'); - * - * store.find('post', 1).then((post) => { - * console.log(post) // { id: 1, ...} - * }); - * - * @fires Container#beforeFind - * @fires Container#afterFind - * @method Container#find - * @param {string} name Name of the {@link Mapper} to target. - * @param {(string|number)} id See {@link Mapper#find}. - * @param {object} [opts] See {@link Mapper#find}. - * @returns {Promise} See {@link Mapper#find}. - * @see Mapper#find - * @since 3.0.0 - */ -'find', -/** - * Fired during {@link Container#findAll}. See - * {@link Container~beforeFindAllListener} for how to listen for this event. - * - * @event Container#beforeFindAll - * @see Container~beforeFindAllListener - * @see Container#findAll - */ - -/** - * Callback signature for the {@link Container#event:beforeFindAll} event. - * - * @example - * function onBeforeFindAll (mapperName, query, opts) { - * // do something - * } - * store.on('beforeFindAll', onBeforeFindAll); - * - * @callback Container~beforeFindAllListener - * @param {string} name The `name` argument received by {@link Mapper#beforeFindAll}. - * @param {object} query The `query` argument received by {@link Mapper#beforeFindAll}. - * @param {object} opts The `opts` argument received by {@link Mapper#beforeFindAll}. - * @see Container#event:beforeFindAll - * @see Container#findAll - * @since 3.0.0 - */ - -/** - * Fired during {@link Container#findAll}. See - * {@link Container~afterFindAllListener} for how to listen for this event. - * - * @event Container#afterFindAll - * @see Container~afterFindAllListener - * @see Container#findAll - */ - -/** - * Callback signature for the {@link Container#event:afterFindAll} event. - * - * @example - * function onAfterFindAll (mapperName, query, opts, result) { - * // do something - * } - * store.on('afterFindAll', onAfterFindAll); - * - * @callback Container~afterFindAllListener - * @param {string} name The `name` argument received by {@link Mapper#afterFindAll}. - * @param {object} query The `query` argument received by {@link Mapper#afterFindAll}. - * @param {object} opts The `opts` argument received by {@link Mapper#afterFindAll}. - * @param {object} result The `result` argument received by {@link Mapper#afterFindAll}. - * @see Container#event:afterFindAll - * @see Container#findAll - * @since 3.0.0 - */ - -/** - * Wrapper for {@link Mapper#createRecord}. - * - * @example - * // Find all "published" blog posts - * import { Container } from 'js-data'; - * import RethinkDBAdapter from 'js-data-rethinkdb'; - * const store = new Container(); - * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); - * store.defineMapper('post'); - * - * store.findAll('post', { status: 'published' }).then((posts) => { - * console.log(posts); // [{ id: 1, ...}, ...] - * }); - * - * @fires Container#beforeFindAll - * @fires Container#afterFindAll - * @method Container#findAll - * @param {string} name Name of the {@link Mapper} to target. - * @param {object} [query] See {@link Mapper#findAll}. - * @param {object} [opts] See {@link Mapper#findAll}. - * @returns {Promise} See {@link Mapper#findAll}. - * @see Mapper#findAll - * @since 3.0.0 - */ -'findAll', -/** - * Wrapper for {@link Mapper#getSchema}. - * - * @method Container#getSchema - * @param {string} name Name of the {@link Mapper} to target. - * @returns {Schema} See {@link Mapper#getSchema}. - * @see Mapper#getSchema - * @since 3.0.0 - */ -'getSchema', -/** - * Wrapper for {@link Mapper#is}. - * - * @example - * import { Container } from 'js-data'; - * const store = new Container(); - * store.defineMapper('post'); - * const post = store.createRecord(); - * - * console.log(store.is('post', post)); // true - * // Equivalent to what's above - * console.log(post instanceof store.getMapper('post').recordClass); // true - * - * @method Container#is - * @param {string} name Name of the {@link Mapper} to target. - * @param {Object|Record} record See {@link Mapper#is}. - * @returns {boolean} See {@link Mapper#is}. - * @see Mapper#is - * @since 3.0.0 - */ -'is', -/** - * Wrapper for {@link Mapper#sum}. - * - * @example - * import { Container } from 'js-data'; - * import RethinkDBAdapter from 'js-data-rethinkdb'; - * const store = new Container(); - * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); - * store.defineMapper('purchase_order'); - * - * store.sum('purchase_order', 'amount', { status: 'paid' }).then((amountPaid) => { - * console.log(amountPaid); // e.g. 451125.34 - * }); - * - * @method Container#sum - * @param {string} name Name of the {@link Mapper} to target. - * @param {string} field See {@link Mapper#sum}. - * @param {object} [query] See {@link Mapper#sum}. - * @param {object} [opts] See {@link Mapper#sum}. - * @returns {Promise} See {@link Mapper#sum}. - * @see Mapper#sum - * @since 3.0.0 - */ -'sum', -/** - * Wrapper for {@link Mapper#toJSON}. - * - * @example - * import { Container } from 'js-data'; - * import RethinkDBAdapter from 'js-data-rethinkdb'; - * const store = new Container(); - * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); - * store.defineMapper('person', { - * schema: { - * properties: { - * name: { type: 'string' }, - * id: { type: 'string' } - * } - * } - * }); - * const person = store.createRecord('person', { id: 1, name: 'John', foo: 'bar' }); - * // "foo" is stripped by toJSON() - * console.log(store.toJSON('person', person)); // {"id":1,"name":"John"} - * - * store.defineMapper('personRelaxed', { - * schema: { - * properties: { - * name: { type: 'string' }, - * id: { type: 'string' } - * }, - * additionalProperties: true - * } - * }); - * const person2 = store.createRecord('personRelaxed', { id: 1, name: 'John', foo: 'bar' }); - * // "foo" is not stripped by toJSON - * console.log(store.toJSON('personRelaxed', person2)); // {"id":1,"name":"John","foo":"bar"} - * - * @method Container#toJSON - * @param {string} name Name of the {@link Mapper} to target. - * @param {Record|Record[]} records See {@link Mapper#toJSON}. - * @param {object} [opts] See {@link Mapper#toJSON}. - * @returns {Object|Object[]} See {@link Mapper#toJSON}. - * @see Mapper#toJSON - * @since 3.0.0 - */ -'toJSON', -/** - * Fired during {@link Container#update}. See - * {@link Container~beforeUpdateListener} for how to listen for this event. - * - * @event Container#beforeUpdate - * @see Container~beforeUpdateListener - * @see Container#update - */ - -/** - * Callback signature for the {@link Container#event:beforeUpdate} event. - * - * @example - * function onBeforeUpdate (mapperName, id, props, opts) { - * // do something - * } - * store.on('beforeUpdate', onBeforeUpdate); - * - * @callback Container~beforeUpdateListener - * @param {string} name The `name` argument received by {@link Mapper#beforeUpdate}. - * @param {string|number} id The `id` argument received by {@link Mapper#beforeUpdate}. - * @param {object} props The `props` argument received by {@link Mapper#beforeUpdate}. - * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdate}. - * @see Container#event:beforeUpdate - * @see Container#update - * @since 3.0.0 - */ - -/** - * Fired during {@link Container#update}. See - * {@link Container~afterUpdateListener} for how to listen for this event. - * - * @event Container#afterUpdate - * @see Container~afterUpdateListener - * @see Container#update - */ - -/** - * Callback signature for the {@link Container#event:afterUpdate} event. - * - * @example - * function onAfterUpdate (mapperName, id, props, opts, result) { - * // do something - * } - * store.on('afterUpdate', onAfterUpdate); - * - * @callback Container~afterUpdateListener - * @param {string} name The `name` argument received by {@link Mapper#afterUpdate}. - * @param {string|number} id The `id` argument received by {@link Mapper#afterUpdate}. - * @param {object} props The `props` argument received by {@link Mapper#afterUpdate}. - * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdate}. - * @param {object} result The `result` argument received by {@link Mapper#afterUpdate}. - * @see Container#event:afterUpdate - * @see Container#update - * @since 3.0.0 - */ - -/** - * Wrapper for {@link Mapper#update}. - * - * @example - * import { Container } from 'js-data'; - * import RethinkDBAdapter from 'js-data-rethinkdb'; - * const store = new Container(); - * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); - * store.defineMapper('post'); - * - * store.update('post', 1234, { - * status: 'published', - * published_at: new Date() - * }).then((post) => { - * console.log(post); // { id: 1234, status: 'published', ... } - * }); - * - * @fires Container#beforeUpdate - * @fires Container#afterUpdate - * @method Container#update - * @param {string} name Name of the {@link Mapper} to target. - * @param {(string|number)} id See {@link Mapper#update}. - * @param {object} record See {@link Mapper#update}. - * @param {object} [opts] See {@link Mapper#update}. - * @returns {Promise} See {@link Mapper#update}. - * @see Mapper#update - * @since 3.0.0 - * @tutorial ["http://www.js-data.io/v3.0/docs/saving-data","Saving data"] - */ -'update', -/** - * Fired during {@link Container#updateAll}. See - * {@link Container~beforeUpdateAllListener} for how to listen for this event. - * - * @event Container#beforeUpdateAll - * @see Container~beforeUpdateAllListener - * @see Container#updateAll - */ - -/** - * Callback signature for the {@link Container#event:beforeUpdateAll} event. - * - * @example - * function onBeforeUpdateAll (mapperName, props, query, opts) { - * // do something - * } - * store.on('beforeUpdateAll', onBeforeUpdateAll); - * - * @callback Container~beforeUpdateAllListener - * @param {string} name The `name` argument received by {@link Mapper#beforeUpdateAll}. - * @param {object} props The `props` argument received by {@link Mapper#beforeUpdateAll}. - * @param {object} query The `query` argument received by {@link Mapper#beforeUpdateAll}. - * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdateAll}. - * @see Container#event:beforeUpdateAll - * @see Container#updateAll - * @since 3.0.0 - */ - -/** - * Fired during {@link Container#updateAll}. See - * {@link Container~afterUpdateAllListener} for how to listen for this event. - * - * @event Container#afterUpdateAll - * @see Container~afterUpdateAllListener - * @see Container#updateAll - */ - -/** - * Callback signature for the {@link Container#event:afterUpdateAll} event. - * - * @example - * function onAfterUpdateAll (mapperName, props, query, opts, result) { - * // do something - * } - * store.on('afterUpdateAll', onAfterUpdateAll); - * - * @callback Container~afterUpdateAllListener - * @param {string} name The `name` argument received by {@link Mapper#afterUpdateAll}. - * @param {object} props The `props` argument received by {@link Mapper#afterUpdateAll}. - * @param {object} query The `query` argument received by {@link Mapper#afterUpdateAll}. - * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdateAll}. - * @param {object} result The `result` argument received by {@link Mapper#afterUpdateAll}. - * @see Container#event:afterUpdateAll - * @see Container#updateAll - * @since 3.0.0 - */ - -/** - * Wrapper for {@link Mapper#updateAll}. - * - * @example - * // Turn all of John's blog posts into drafts. - * import { Container } from 'js-data'; - * import RethinkDBAdapter from 'js-data-rethinkdb'; - * const store = new Container(); - * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); - * store.defineMapper('post'); - * - * const update = { status: draft: published_at: null }; - * const query = { userId: 1234 }; - * store.updateAll('post', update, query).then((posts) => { - * console.log(posts); // [...] - * }); - * - * @fires Container#beforeUpdateAll - * @fires Container#afterUpdateAll - * @method Container#updateAll - * @param {string} name Name of the {@link Mapper} to target. - * @param {object} update See {@link Mapper#updateAll}. - * @param {object} [query] See {@link Mapper#updateAll}. - * @param {object} [opts] See {@link Mapper#updateAll}. - * @returns {Promise} See {@link Mapper#updateAll}. - * @see Mapper#updateAll - * @since 3.0.0 - */ -'updateAll', -/** - * Fired during {@link Container#updateMany}. See - * {@link Container~beforeUpdateManyListener} for how to listen for this event. - * - * @event Container#beforeUpdateMany - * @see Container~beforeUpdateManyListener - * @see Container#updateMany - */ - -/** - * Callback signature for the {@link Container#event:beforeUpdateMany} event. - * - * @example - * function onBeforeUpdateMany (mapperName, records, opts) { - * // do something - * } - * store.on('beforeUpdateMany', onBeforeUpdateMany); - * - * @callback Container~beforeUpdateManyListener - * @param {string} name The `name` argument received by {@link Mapper#beforeUpdateMany}. - * @param {object} records The `records` argument received by {@link Mapper#beforeUpdateMany}. - * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdateMany}. - * @see Container#event:beforeUpdateMany - * @see Container#updateMany - * @since 3.0.0 - */ - -/** - * Fired during {@link Container#updateMany}. See - * {@link Container~afterUpdateManyListener} for how to listen for this event. - * - * @event Container#afterUpdateMany - * @see Container~afterUpdateManyListener - * @see Container#updateMany - */ - -/** - * Callback signature for the {@link Container#event:afterUpdateMany} event. - * - * @example - * function onAfterUpdateMany (mapperName, records, opts, result) { - * // do something - * } - * store.on('afterUpdateMany', onAfterUpdateMany); - * - * @callback Container~afterUpdateManyListener - * @param {string} name The `name` argument received by {@link Mapper#afterUpdateMany}. - * @param {object} records The `records` argument received by {@link Mapper#afterUpdateMany}. - * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdateMany}. - * @param {object} result The `result` argument received by {@link Mapper#afterUpdateMany}. - * @see Container#event:afterUpdateMany - * @see Container#updateMany - * @since 3.0.0 - */ - -/** - * Wrapper for {@link Mapper#updateMany}. - * - * @example - * import { Container } from 'js-data'; - * import RethinkDBAdapter from 'js-data-rethinkdb'; - * const store = new Container(); - * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); - * store.defineMapper('post'); - * - * store.updateMany('post', [ - * { id: 1234, status: 'draft' }, - * { id: 2468, status: 'published', published_at: new Date() } - * ]).then((posts) => { - * console.log(posts); // [...] - * }); - * - * @fires Container#beforeUpdateMany - * @fires Container#afterUpdateMany - * @method Container#updateMany - * @param {string} name Name of the {@link Mapper} to target. - * @param {(Object[]|Record[])} records See {@link Mapper#updateMany}. - * @param {object} [opts] See {@link Mapper#updateMany}. - * @returns {Promise} See {@link Mapper#updateMany}. - * @see Mapper#updateMany - * @since 3.0.0 - */ -'updateMany', -/** - * Wrapper for {@link Mapper#validate}. - * - * @example - * import { Container } from 'js-data'; - * const store = new Container(); - * store.defineMapper('post', { - * schema: { - * properties: { - * name: { type: 'string' }, - * id: { type: 'string' } - * } - * } - * }); - * let errors = store.validate('post', { name: 'John' }); - * console.log(errors); // undefined - * errors = store.validate('post', { name: 123 }); - * console.log(errors); // [{ expected: 'one of (string)', actual: 'number', path: 'name' }] - * - * @method Container#validate - * @param {string} name Name of the {@link Mapper} to target. - * @param {(Object[]|Record[])} records See {@link Mapper#validate}. - * @param {object} [opts] See {@link Mapper#validate}. - * @returns {Promise} See {@link Mapper#validate}. - * @see Mapper#validate - * @since 3.0.0 - */ -'validate']; -/** - * The `Container` class is a place to define and store {@link Mapper} instances. - * - * `Container` makes it easy to manage your Mappers. Without a container, you - * need to manage Mappers yourself, including resolving circular dependencies - * among relations. All Mappers in a container share the same adapters, so you - * don't have to register adapters for every single Mapper. - * - * @example Container#constructor - * // import { Container } from 'js-data'; - * const JSData = require('js-data'); - * const {Container} = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new Container(); - * - * @class Container - * @extends Component - * @param {object} [opts] Configuration options. - * @param {boolean} [opts.debug=false] See {@link Component#debug}. - * @param {Constructor} [opts.mapperClass] See {@link Container#mapperClass}. - * @param {object} [opts.mapperDefaults] See {@link Container#mapperDefaults}. - * @since 3.0.0 - */ - -function Container(opts) { - utils.classCallCheck(this, Container); - Component$1.call(this); - opts || (opts = {}); - Object.defineProperties(this, { - /** - * The adapters registered with this Container, which are also shared by all - * Mappers in this Container. - * - * @name Container#_adapters - * @see Container#registerAdapter - * @since 3.0.0 - * @type {Object} - */ - _adapters: { - value: {} - }, - - /** - * The the mappers in this container - * - * @name Container#_mappers - * @see Mapper - * @since 3.0.0 - * @type {Object} - */ - _mappers: { - value: {} - }, - - /** - * Constructor function to use in {@link Container#defineMapper} to create new - * {@link Mapper} instances. {@link Container#mapperClass} should extend - * {@link Mapper}. By default {@link Mapper} is used to instantiate Mappers. - * - * @example Container#mapperClass - * // import { Container, Mapper } from 'js-data'; - * const JSData = require('js-data'); - * const { Container, Mapper } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * class MyMapperClass extends Mapper { - * foo () { return 'bar' } - * } - * const store = new Container({ - * mapperClass: MyMapperClass - * }); - * store.defineMapper('user'); - * console.log(store.getMapper('user').foo()); - * - * @name Container#mapperClass - * @see Mapper - * @since 3.0.0 - * @type {Constructor} - */ - mapperClass: { - value: undefined, - writable: true - } - }); // Apply options provided by the user - - utils.fillIn(this, opts); - /** - * Defaults options to pass to {@link Container#mapperClass} when creating a - * new {@link Mapper}. - * - * @example Container#mapperDefaults - * // import { Container } from 'js-data'; - * const JSData = require('js-data'); - * const { Container } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new Container({ - * mapperDefaults: { - * idAttribute: '_id' - * } - * }); - * store.defineMapper('user'); - * console.log(store.getMapper('user').idAttribute); - * - * @default {} - * @name Container#mapperDefaults - * @since 3.0.0 - * @type {Object} - */ - - this.mapperDefaults = this.mapperDefaults || {}; // Use the Mapper class if the user didn't provide a mapperClass - - this.mapperClass || (this.mapperClass = Mapper$1); -} -var props = { - constructor: Container, - - /** - * Register a new event listener on this Container. - * - * Proxy for {@link Component#on}. If an event was emitted by a {@link Mapper} - * in the Container, then the name of the {@link Mapper} will be prepended to - * the arugments passed to the listener. - * - * @example Container#on - * // import { Container } from 'js-data'; - * const JSData = require('js-data'); - * const { Container } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new Container(); - * store.on('foo', function (...args) { console.log(args.join(':')) }); - * store.defineMapper('user'); - * store.emit('foo', 'arg1', 'arg2'); - * store.getMapper('user').emit('foo', 'arg1', 'arg2'); - * - * @method Container#on - * @param {string} event Name of event to subsribe to. - * @param {Function} listener Listener function to handle the event. - * @param {*} [ctx] Optional content in which to invoke the listener. - * @since 3.0.0 - */ - - /** - * Used to bind to events emitted by mappers in this container. - * - * @method Container#_onMapperEvent - * @param {string} name Name of the mapper that emitted the event. - * @param {...*} [args] Args See {@link Mapper#emit}. - * @private - * @since 3.0.0 - */ - _onMapperEvent: function _onMapperEvent(name) { - for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { - args[_key - 1] = arguments[_key]; - } - - var type = args.shift(); - this.emit.apply(this, [type, name].concat(args)); - }, - - /** - * Return a container scoped to a particular mapper. - * - * @example Container#as - * // import { Container } from 'js-data'; - * const JSData = require('js-data'); - * const { Container } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new Container(); - * const UserMapper = store.defineMapper('user'); - * const UserStore = store.as('user'); - * - * const user1 = store.createRecord('user', { name: 'John' }); - * const user2 = UserStore.createRecord({ name: 'John' }); - * const user3 = UserMapper.createRecord({ name: 'John' }); - * console.log(user1 === user2); - * console.log(user2 === user3); - * console.log(user1 === user3); - * - * @method Container#as - * @param {string} name Name of the {@link Mapper}. - * @returns {Object} A container scoped to a particular mapper. - * @since 3.0.0 - */ - as: function as(name) { - var props = {}; - var original = this; - proxiedMapperMethods.forEach(function (method) { - props[method] = { - writable: true, - value: function value() { - for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { - args[_key2] = arguments[_key2]; - } - - return original[method].apply(original, [name].concat(args)); - } - }; - }); - props.getMapper = { - writable: true, - value: function value() { - return original.getMapper(name); - } - }; - return Object.create(this, props); - }, - - /** - * Create a new mapper and register it in this container. - * - * @example Container#defineMapper - * // import { Container } from 'js-data'; - * const JSData = require('js-data'); - * const { Container } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new Container({ - * mapperDefaults: { foo: 'bar' } - * }); - * // Container#defineMapper returns a direct reference to the newly created - * // Mapper. - * const UserMapper = store.defineMapper('user'); - * console.log(UserMapper === store.getMapper('user')); - * console.log(UserMapper === store.as('user').getMapper()); - * console.log(UserMapper.foo); - * - * @method Container#defineMapper - * @param {string} name Name under which to register the new {@link Mapper}. - * {@link Mapper#name} will be set to this value. - * @param {object} [opts] Configuration options. Passed to - * {@link Container#mapperClass} when creating the new {@link Mapper}. - * @returns {Mapper} The newly created instance of {@link Mapper}. - * @see Container#as - * @since 3.0.0 - */ - defineMapper: function defineMapper(name, opts) { - var _this = this; - - // For backwards compatibility with defineResource - if (utils.isObject(name)) { - opts = name; - name = opts.name; - } - - if (!utils.isString(name)) { - throw utils.err("".concat(DOMAIN$7, "#defineMapper"), 'name')(400, 'string', name); - } // Default values for arguments - - - opts || (opts = {}); // Set Mapper#name - - opts.name = name; - opts.relations || (opts.relations = {}); // Check if the user is overriding the datastore's default mapperClass - - var mapperClass = opts.mapperClass || this.mapperClass; - delete opts.mapperClass; // Apply the datastore's defaults to the options going into the mapper - - utils.fillIn(opts, this.mapperDefaults); // Instantiate a mapper - - var mapper = this._mappers[name] = new mapperClass(opts); // eslint-disable-line - - mapper.relations || (mapper.relations = {}); // Make sure the mapper's name is set - - mapper.name = name; // All mappers in this datastore will share adapters - - mapper._adapters = this.getAdapters(); - mapper.datastore = this; - mapper.on('all', function () { - for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { - args[_key3] = arguments[_key3]; - } - - return _this._onMapperEvent.apply(_this, [name].concat(args)); - }); - mapper.defineRelations(); - return mapper; - }, - defineResource: function defineResource(name, opts) { - console.warn('DEPRECATED: defineResource is deprecated, use defineMapper instead'); - return this.defineMapper(name, opts); - }, - - /** - * Return the registered adapter with the given name or the default adapter if - * no name is provided. - * - * @method Container#getAdapter - * @param {string} [name] The name of the adapter to retrieve. - * @returns {Adapter} The adapter. - * @since 3.0.0 - */ - getAdapter: function getAdapter(name) { - var adapter = this.getAdapterName(name); - - if (!adapter) { - throw utils.err("".concat(DOMAIN$7, "#getAdapter"), 'name')(400, 'string', name); - } - - return this.getAdapters()[adapter]; - }, - - /** - * Return the name of a registered adapter based on the given name or options, - * or the name of the default adapter if no name provided. - * - * @method Container#getAdapterName - * @param {(Object|string)} [opts] The name of an adapter or options, if any. - * @returns {string} The name of the adapter. - * @since 3.0.0 - */ - getAdapterName: function getAdapterName(opts) { - opts || (opts = {}); - - if (utils.isString(opts)) { - opts = { - adapter: opts - }; - } - - return opts.adapter || this.mapperDefaults.defaultAdapter; - }, - - /** - * Return the registered adapters of this container. - * - * @method Container#getAdapters - * @returns {Adapter} - * @since 3.0.0 - */ - getAdapters: function getAdapters() { - return this._adapters; - }, - - /** - * Return the mapper registered under the specified name. - * - * @example Container#getMapper - * // import { Container } from 'js-data'; - * const JSData = require('js-data'); - * const { Container } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new Container(); - * // Container#defineMapper returns a direct reference to the newly created - * // Mapper. - * const UserMapper = store.defineMapper('user'); - * console.log(UserMapper === store.getMapper('user')); - * console.log(UserMapper === store.as('user').getMapper()); - * store.getMapper('profile'); // throws Error, there is no mapper with name "profile" - * - * @method Container#getMapper - * @param {string} name {@link Mapper#name}. - * @returns {Mapper} - * @since 3.0.0 - */ - getMapper: function getMapper(name) { - var mapper = this.getMapperByName(name); - - if (!mapper) { - throw utils.err("".concat(DOMAIN$7, "#getMapper"), name)(404, 'mapper'); - } - - return mapper; - }, - - /** - * Return the mapper registered under the specified name. - * Doesn't throw error if mapper doesn't exist. - * - * @example Container#getMapperByName - * // import { Container } from 'js-data'; - * const JSData = require('js-data'); - * const { Container } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new Container(); - * // Container#defineMapper returns a direct reference to the newly created - * // Mapper. - * const UserMapper = store.defineMapper('user'); - * console.log(UserMapper === store.getMapper('user')); - * console.log(UserMapper === store.as('user').getMapper()); - * console.log(store.getMapper('profile')); // Does NOT throw an error - * - * @method Container#getMapperByName - * @param {string} name {@link Mapper#name}. - * @returns {Mapper} - * @since 3.0.0 - */ - getMapperByName: function getMapperByName(name) { - return this._mappers[name]; - }, - - /** - * Register an adapter on this container under the given name. Adapters - * registered on a container are shared by all mappers in the container. - * - * @example - * import { Container } from 'js-data'; - * import { RethinkDBAdapter } from 'js-data-rethinkdb'; - * const store = new Container(); - * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); - * - * @method Container#registerAdapter - * @param {string} name The name of the adapter to register. - * @param {Adapter} adapter The adapter to register. - * @param {object} [opts] Configuration options. - * @param {boolean} [opts.default=false] Whether to make the adapter the - * default adapter for all Mappers in this container. - * @since 3.0.0 - * @tutorial ["http://www.js-data.io/v3.0/docs/connecting-to-a-data-source","Connecting to a data source"] - */ - registerAdapter: function registerAdapter(name, adapter, opts) { - opts || (opts = {}); - this.getAdapters()[name] = adapter; // Optionally make it the default adapter for the target. - - if (opts === true || opts.default) { - this.mapperDefaults.defaultAdapter = name; - utils.forOwn(this._mappers, function (mapper) { - mapper.defaultAdapter = name; - }); - } - } -}; -proxiedMapperMethods.forEach(function (method) { - props[method] = function (name) { - var _this$getMapper; - - for (var _len4 = arguments.length, args = new Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) { - args[_key4 - 1] = arguments[_key4]; - } - - return (_this$getMapper = this.getMapper(name))[method].apply(_this$getMapper, args); - }; -}); -Component$1.extend(props); -/** - * Create a subclass of this Container: - * @example Container.extend - * const JSData = require('js-data'); - * const { Container } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * // Extend the class using ES2015 class syntax. - * class CustomContainerClass extends Container { - * foo () { return 'bar' } - * static beep () { return 'boop' } - * } - * const customContainer = new CustomContainerClass(); - * console.log(customContainer.foo()); - * console.log(CustomContainerClass.beep()); - * - * // Extend the class using alternate method. - * const OtherContainerClass = Container.extend({ - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }); - * const otherContainer = new OtherContainerClass(); - * console.log(otherContainer.foo()); - * console.log(OtherContainerClass.beep()); - * - * // Extend the class, providing a custom constructor. - * function AnotherContainerClass () { - * Container.call(this); - * this.created_at = new Date().getTime(); - * } - * Container.extend({ - * constructor: AnotherContainerClass, - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }) - * const anotherContainer = new AnotherContainerClass(); - * console.log(anotherContainer.created_at); - * console.log(anotherContainer.foo()); - * console.log(AnotherContainerClass.beep()); - * - * @method Container.extend - * @param {object} [props={}] Properties to add to the prototype of the - * subclass. - * @param {object} [props.constructor] Provide a custom constructor function - * to be used as the subclass itself. - * @param {object} [classProps={}] Static properties to add to the subclass. - * @returns {Constructor} Subclass of this Container class. - * @since 3.0.0 - */ - -var DOMAIN$8 = 'SimpleStore'; -var proxiedCollectionMethods = [ -/** - * Wrapper for {@link Collection#add}. - * - * @example SimpleStore#add - * const JSData = require('js-data'); - * const { SimpleStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new SimpleStore(); - * store.defineMapper('book'); - * - * // Add one book to the in-memory store: - * store.add('book', { id: 1, title: 'Respect your Data' }); - * // Add multiple books to the in-memory store: - * store.add('book', [ - * { id: 2, title: 'Easy data recipes' }, - * { id: 3, title: 'Active Record 101' } - * ]); - * - * @fires SimpleStore#add - * @method SimpleStore#add - * @param {(string|number)} name Name of the {@link Mapper} to target. - * @param {(Object|Object[]|Record|Record[])} data See {@link Collection#add}. - * @param {object} [opts] Configuration options. See {@link Collection#add}. - * @returns {(Object|Object[]|Record|Record[])} See {@link Collection#add}. - * @see Collection#add - * @see Collection#add - * @since 3.0.0 - */ -'add', -/** - * Wrapper for {@link Collection#between}. - * - * @example - * // Get all users ages 18 to 30 - * const users = store.between('user', 18, 30, { index: 'age' }); - * - * @example - * // Same as above - * const users = store.between('user', [18], [30], { index: 'age' }); - * - * @method SimpleStore#between - * @param {(string|number)} name Name of the {@link Mapper} to target. - * @param {array} leftKeys See {@link Collection#between}. - * @param {array} rightKeys See {@link Collection#between}. - * @param {object} [opts] Configuration options. See {@link Collection#between}. - * @returns {Object[]|Record[]} See {@link Collection#between}. - * @see Collection#between - * @see Collection#between - * @since 3.0.0 - */ -'between', -/** - * Wrapper for {@link Collection#createIndex}. - * - * @example - * // Index users by age - * store.createIndex('user', 'age'); - * - * @example - * // Index users by status and role - * store.createIndex('user', 'statusAndRole', ['status', 'role']); - * - * @method SimpleStore#createIndex - * @param {(string|number)} name Name of the {@link Mapper} to target. - * @param {string} name See {@link Collection#createIndex}. - * @param {string[]} [fieldList] See {@link Collection#createIndex}. - * @see Collection#createIndex - * @see Collection#createIndex - * @since 3.0.0 - */ -'createIndex', -/** - * Wrapper for {@link Collection#filter}. - * - * @example SimpleStore#filter - * const JSData = require('js-data'); - * const { SimpleStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new SimpleStore(); - * store.defineMapper('post'); - * store.add('post', [ - * { id: 1, status: 'draft', created_at_timestamp: new Date().getTime() } - * ]); - * - * // Get the draft posts created less than three months ago - * let posts = store.filter('post', { - * where: { - * status: { - * '==': 'draft' - * }, - * created_at_timestamp: { - * '>=': (new Date().getTime() - (1000 \* 60 \* 60 \* 24 \* 30 \* 3)) // 3 months ago - * } - * } - * }); - * console.log(posts); - * - * // Use a custom filter function - * posts = store.filter('post', function (post) { return post.id % 2 === 0 }); - * - * @method SimpleStore#filter - * @param {(string|number)} name Name of the {@link Mapper} to target. - * @param {(Object|Function)} [queryOrFn={}] See {@link Collection#filter}. - * @param {object} [thisArg] See {@link Collection#filter}. - * @returns {Array} See {@link Collection#filter}. - * @see Collection#filter - * @see Collection#filter - * @since 3.0.0 - */ -'filter', -/** - * Wrapper for {@link Collection#get}. - * - * @example SimpleStore#get - * const JSData = require('js-data'); - * const { SimpleStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new SimpleStore(); - * store.defineMapper('post'); - * store.add('post', [ - * { id: 1, status: 'draft', created_at_timestamp: new Date().getTime() } - * ]); - * - * console.log(store.get('post', 1)); // {...} - * console.log(store.get('post', 2)); // undefined - * - * @method SimpleStore#get - * @param {(string|number)} name Name of the {@link Mapper} to target. - * @param {(string|number)} id See {@link Collection#get}. - * @returns {(Object|Record)} See {@link Collection#get}. - * @see Collection#get - * @see Collection#get - * @since 3.0.0 - */ -'get', -/** - * Wrapper for {@link Collection#getAll}. - * - * @example - * // Get the posts where "status" is "draft" or "inReview" - * const posts = store.getAll('post', 'draft', 'inReview', { index: 'status' }); - * - * @example - * // Same as above - * const posts = store.getAll('post', ['draft'], ['inReview'], { index: 'status' }); - * - * @method SimpleStore#getAll - * @param {(string|number)} name Name of the {@link Mapper} to target. - * @param {...Array} [keyList] See {@link Collection#getAll}. - * @param {object} [opts] See {@link Collection#getAll}. - * @returns {Array} See {@link Collection#getAll}. - * @see Collection#getAll - * @see Collection#getAll - * @since 3.0.0 - */ -'getAll', -/** - * Wrapper for {@link Collection#prune}. - * - * @method SimpleStore#prune - * @param {object} [opts] See {@link Collection#prune}. - * @returns {Array} See {@link Collection#prune}. - * @see Collection#prune - * @see Collection#prune - * @since 3.0.0 - */ -'prune', -/** - * Wrapper for {@link Collection#query}. - * - * @example - * // Grab page 2 of users between ages 18 and 30 - * store.query('user') - * .between(18, 30, { index: 'age' }) // between ages 18 and 30 - * .skip(10) // second page - * .limit(10) // page size - * .run(); - * - * @method SimpleStore#query - * @param {(string|number)} name Name of the {@link Mapper} to target. - * @returns {Query} See {@link Collection#query}. - * @see Collection#query - * @see Collection#query - * @since 3.0.0 - */ -'query', -/** - * Wrapper for {@link Collection#toJSON}. - * - * @example - * store.defineMapper('post', { - * schema: { - * properties: { - * id: { type: 'number' }, - * title: { type: 'string' } - * } - * } - * }); - * store.add('post', [ - * { id: 1, status: 'published', title: 'Respect your Data' }, - * { id: 2, status: 'draft', title: 'Connecting to a data source' } - * ]); - * console.log(store.toJSON('post')); - * const draftsJSON = store.query('post') - * .filter({ status: 'draft' }) - * .mapCall('toJSON') - * .run(); - * - * @method SimpleStore#toJSON - * @param {(string|number)} name Name of the {@link Mapper} to target. - * @param {object} [opts] See {@link Collection#toJSON}. - * @returns {Array} See {@link Collection#toJSON}. - * @see Collection#toJSON - * @see Collection#toJSON - * @since 3.0.0 - */ -'toJSON', -/** - * Wrapper for {@link Collection#unsaved}. - * - * @method SimpleStore#unsaved - * @returns {Array} See {@link Collection#unsaved}. - * @see Collection#unsaved - * @see Collection#unsaved - * @since 3.0.0 - */ -'unsaved']; -var ownMethodsForScoping = ['addToCache', 'cachedFind', 'cachedFindAll', 'cacheFind', 'cacheFindAll', 'hashQuery']; - -var cachedFn = function cachedFn(name, hashOrId, opts) { - var cached = this._completedQueries[name][hashOrId]; - - if (utils.isFunction(cached)) { - return cached(name, hashOrId, opts); - } - - return cached; -}; - -var SIMPLESTORE_DEFAULTS = { - /** - * Whether to use the pending query if a `find` request for the specified - * record is currently underway. Can be set to `true`, `false`, or to a - * function that returns `true` or `false`. - * - * @default true - * @name SimpleStore#usePendingFind - * @since 3.0.0 - * @type {boolean|Function} - */ - usePendingFind: true, - - /** - * Whether to use the pending query if a `findAll` request for the given query - * is currently underway. Can be set to `true`, `false`, or to a function that - * returns `true` or `false`. - * - * @default true - * @name SimpleStore#usePendingFindAll - * @since 3.0.0 - * @type {boolean|Function} - */ - usePendingFindAll: true -}; -/** - * The `SimpleStore` class is an extension of {@link Container}. Not only does - * `SimpleStore` manage mappers, but also collections. `SimpleStore` implements the - * asynchronous {@link Mapper} methods, such as {@link Mapper#find} and - * {@link Mapper#create}. If you use the asynchronous `SimpleStore` methods - * instead of calling them directly on the mappers, then the results of the - * method calls will be inserted into the store's collections. You can think of - * a `SimpleStore` as an [Identity Map](https://en.wikipedia.org/wiki/Identity_map_pattern) - * for the [ORM](https://en.wikipedia.org/wiki/Object-relational_mapping) - * (the Mappers). - * - * ```javascript - * import { SimpleStore } from 'js-data'; - * ``` - * - * @example - * import { SimpleStore } from 'js-data'; - * import { HttpAdapter } from 'js-data-http'; - * const store = new SimpleStore(); - * - * // SimpleStore#defineMapper returns a direct reference to the newly created - * // Mapper. - * const UserMapper = store.defineMapper('user'); - * - * // SimpleStore#as returns the store scoped to a particular Mapper. - * const UserStore = store.as('user'); - * - * // Call "find" on "UserMapper" (Stateless ORM) - * UserMapper.find(1).then((user) => { - * // retrieved a "user" record via the http adapter, but that's it - * - * // Call "find" on "store" targeting "user" (Stateful SimpleStore) - * return store.find('user', 1); // same as "UserStore.find(1)" - * }).then((user) => { - * // not only was a "user" record retrieved, but it was added to the - * // store's "user" collection - * const cachedUser = store.getCollection('user').get(1); - * console.log(user === cachedUser); // true - * }); - * - * @class SimpleStore - * @extends Container - * @param {object} [opts] Configuration options. See {@link Container}. - * @param {boolean} [opts.collectionClass={@link Collection}] See {@link SimpleStore#collectionClass}. - * @param {boolean} [opts.debug=false] See {@link Component#debug}. - * @param {boolean|Function} [opts.usePendingFind=true] See {@link SimpleStore#usePendingFind}. - * @param {boolean|Function} [opts.usePendingFindAll=true] See {@link SimpleStore#usePendingFindAll}. - * @returns {SimpleStore} - * @see Container - * @since 3.0.0 - * @tutorial ["http://www.js-data.io/v3.0/docs/components-of-jsdata#SimpleStore","Components of JSData: SimpleStore"] - * @tutorial ["http://www.js-data.io/v3.0/docs/working-with-the-SimpleStore","Working with the SimpleStore"] - * @tutorial ["http://www.js-data.io/v3.0/docs/jsdata-and-the-browser","Notes on using JSData in the Browser"] - */ - -function SimpleStore(opts) { - utils.classCallCheck(this, SimpleStore); - opts || (opts = {}); // Fill in any missing options with the defaults - - utils.fillIn(opts, SIMPLESTORE_DEFAULTS); - Container.call(this, opts); - this.collectionClass = this.collectionClass || Collection$1; - this._collections = {}; - this._pendingQueries = {}; - this._completedQueries = {}; -} - -var props$1 = { - constructor: SimpleStore, - - /** - * Internal method used to handle Mapper responses. - * - * @method SimpleStore#_end - * @private - * @param {string} name Name of the {@link Collection} to which to - * add the data. - * @param {object} result The result from a Mapper. - * @param {object} [opts] Configuration options. - * @returns {(Object|Array)} Result. - */ - _end: function _end(name, result, opts) { - var data = opts.raw ? result.data : result; - - if (data && utils.isFunction(this.addToCache)) { - data = this.addToCache(name, data, opts); - - if (opts.raw) { - result.data = data; - } else { - result = data; - } - } - - return result; - }, - - /** - * Register a new event listener on this SimpleStore. - * - * Proxy for {@link Container#on}. If an event was emitted by a Mapper or - * Collection in the SimpleStore, then the name of the Mapper or Collection will - * be prepended to the arugments passed to the provided event handler. - * - * @example - * // Listen for all "afterCreate" events in a SimpleStore - * store.on('afterCreate', (mapperName, props, opts, result) => { - * console.log(mapperName); // "post" - * console.log(props.id); // undefined - * console.log(result.id); // 1234 - * }); - * store.create('post', { title: 'Modeling your data' }).then((post) => { - * console.log(post.id); // 1234 - * }); - * - * @example - * // Listen for the "add" event on a collection - * store.on('add', (mapperName, records) => { - * console.log(records); // [...] - * }); - * - * @example - * // Listen for "change" events on a record - * store.on('change', (mapperName, record, changes) => { - * console.log(changes); // { changed: { title: 'Modeling your data' } } - * }); - * post.title = 'Modeling your data'; - * - * @method SimpleStore#on - * @param {string} event Name of event to subsribe to. - * @param {Function} listener Listener function to handle the event. - * @param {*} [ctx] Optional content in which to invoke the listener. - */ - - /** - * Used to bind to events emitted by collections in this store. - * - * @method SimpleStore#_onCollectionEvent - * @private - * @param {string} name Name of the collection that emitted the event. - * @param {...*} [args] Args passed to {@link Collection#emit}. - */ - _onCollectionEvent: function _onCollectionEvent(name) { - for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { - args[_key - 1] = arguments[_key]; - } - - var type = args.shift(); - this.emit.apply(this, [type, name].concat(args)); - }, - - /** - * This method takes the data received from {@link SimpleStore#find}, - * {@link SimpleStore#findAll}, {@link SimpleStore#update}, etc., and adds the - * data to the store. _You don't need to call this method directly._ - * - * If you're using the http adapter and your response data is in an unexpected - * format, you may need to override this method so the right data gets added - * to the store. - * - * @example - * const store = new SimpleStore({ - * addToCache (mapperName, data, opts) { - * // Let's say for a particular Resource, response data is in a weird format - * if (name === 'comment') { - * // Re-assign the variable to add the correct records into the stores - * data = data.items; - * } - * // Now perform default behavior - * return SimpleStore.prototype.addToCache.call(this, mapperName, data, opts); - * } - * }); - * - * @example - * // Extend using ES2015 class syntax. - * class MyStore extends SimpleStore { - * addToCache (mapperName, data, opts) { - * // Let's say for a particular Resource, response data is in a weird format - * if (name === 'comment') { - * // Re-assign the variable to add the correct records into the stores - * data = data.items; - * } - * // Now perform default behavior - * return super.addToCache(mapperName, data, opts); - * } - * } - * const store = new MyStore(); - * - * @method SimpleStore#addToCache - * @param {string} name Name of the {@link Mapper} to target. - * @param {*} data Data from which data should be selected for add. - * @param {object} [opts] Configuration options. - */ - addToCache: function addToCache(name, data, opts) { - return this.getCollection(name).add(data, opts); - }, - - /** - * Return the store scoped to a particular mapper/collection pair. - * - * @example SimpleStore.as - * const JSData = require('js-data'); - * const { SimpleStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new SimpleStore(); - * const UserMapper = store.defineMapper('user'); - * const UserStore = store.as('user'); - * - * const user1 = store.createRecord('user', { name: 'John' }); - * const user2 = UserStore.createRecord({ name: 'John' }); - * const user3 = UserMapper.createRecord({ name: 'John' }); - * console.log(user1 === user2); - * console.log(user2 === user3); - * console.log(user1 === user3); - * - * @method SimpleStore#as - * @param {string} name Name of the {@link Mapper}. - * @returns {Object} The store, scoped to a particular Mapper/Collection pair. - * @since 3.0.0 - */ - as: function as(name) { - var props = {}; - var original = this; - var methods = ownMethodsForScoping.concat(proxiedMapperMethods).concat(proxiedCollectionMethods); - methods.forEach(function (method) { - props[method] = { - writable: true, - value: function value() { - for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { - args[_key2] = arguments[_key2]; - } - - return original[method].apply(original, [name].concat(args)); - } - }; - }); - props.getMapper = { - writable: true, - value: function value() { - return original.getMapper(name); - } - }; - props.getCollection = { - writable: true, - value: function value() { - return original.getCollection(name); - } - }; - return Object.create(this, props); - }, - - /** - * Retrieve a cached `find` result, if any. This method is called during - * {@link SimpleStore#find} to determine if {@link Mapper#find} needs to be - * called. If this method returns `undefined` then {@link Mapper#find} will - * be called. Otherwise {@link SimpleStore#find} will immediately resolve with - * the return value of this method. - * - * When using {@link SimpleStore} in the browser, you can override this method - * to implement your own cache-busting strategy. - * - * @example - * const store = new SimpleStore({ - * cachedFind (mapperName, id, opts) { - * // Let's say for a particular Resource, we always want to pull fresh from the server - * if (mapperName === 'schedule') { - * // Return undefined to trigger a Mapper#find call - * return; - * } - * // Otherwise perform default behavior - * return SimpleStore.prototype.cachedFind.call(this, mapperName, id, opts); - * } - * }); - * - * @example - * // Extend using ES2015 class syntax. - * class MyStore extends SimpleStore { - * cachedFind (mapperName, id, opts) { - * // Let's say for a particular Resource, we always want to pull fresh from the server - * if (mapperName === 'schedule') { - * // Return undefined to trigger a Mapper#find call - * return; - * } - * // Otherwise perform default behavior - * return super.cachedFind(mapperName, id, opts); - * } - * } - * const store = new MyStore(); - * - * @method SimpleStore#cachedFind - * @param {string} name The `name` argument passed to {@link SimpleStore#find}. - * @param {(string|number)} id The `id` argument passed to {@link SimpleStore#find}. - * @param {object} opts The `opts` argument passed to {@link SimpleStore#find}. - * @since 3.0.0 - */ - cachedFind: cachedFn, - - /** - * Retrieve a cached `findAll` result, if any. This method is called during - * {@link SimpleStore#findAll} to determine if {@link Mapper#findAll} needs to be - * called. If this method returns `undefined` then {@link Mapper#findAll} will - * be called. Otherwise {@link SimpleStore#findAll} will immediately resolve with - * the return value of this method. - * - * When using {@link SimpleStore} in the browser, you can override this method - * to implement your own cache-busting strategy. - * - * @example - * const store = new SimpleStore({ - * cachedFindAll (mapperName, hash, opts) { - * // Let's say for a particular Resource, we always want to pull fresh from the server - * if (mapperName === 'schedule') { - * // Return undefined to trigger a Mapper#findAll call - * return undefined; - * } - * // Otherwise perform default behavior - * return SimpleStore.prototype.cachedFindAll.call(this, mapperName, hash, opts); - * } - * }); - * - * @example - * // Extend using ES2015 class syntax. - * class MyStore extends SimpleStore { - * cachedFindAll (mapperName, hash, opts) { - * // Let's say for a particular Resource, we always want to pull fresh from the server - * if (mapperName === 'schedule') { - * // Return undefined to trigger a Mapper#findAll call - * return undefined; - * } - * // Otherwise perform default behavior - * return super.cachedFindAll(mapperName, hash, opts); - * } - * } - * const store = new MyStore(); - * - * @method SimpleStore#cachedFindAll - * @param {string} name The `name` argument passed to {@link SimpleStore#findAll}. - * @param {string} hash The result of calling {@link SimpleStore#hashQuery} on - * the `query` argument passed to {@link SimpleStore#findAll}. - * @param {object} opts The `opts` argument passed to {@link SimpleStore#findAll}. - * @since 3.0.0 - */ - cachedFindAll: cachedFn, - - /** - * Mark a {@link Mapper#find} result as cached by adding an entry to - * {@link SimpleStore#_completedQueries}. By default, once a `find` entry is - * added it means subsequent calls to the same Resource with the same `id` - * argument will immediately resolve with the result of calling - * {@link SimpleStore#get} instead of delegating to {@link Mapper#find}. - * - * As part of implementing your own caching strategy, you may choose to - * override this method. - * - * @example - * const store = new SimpleStore({ - * cacheFind (mapperName, data, id, opts) { - * // Let's say for a particular Resource, we always want to pull fresh from the server - * if (mapperName === 'schedule') { - * // Return without saving an entry to SimpleStore#_completedQueries - * return; - * } - * // Otherwise perform default behavior - * return SimpleStore.prototype.cacheFind.call(this, mapperName, data, id, opts); - * } - * }); - * - * @example - * // Extend using ES2015 class syntax. - * class MyStore extends SimpleStore { - * cacheFind (mapperName, data, id, opts) { - * // Let's say for a particular Resource, we always want to pull fresh from the server - * if (mapperName === 'schedule') { - * // Return without saving an entry to SimpleStore#_completedQueries - * return; - * } - * // Otherwise perform default behavior - * return super.cacheFind(mapperName, data, id, opts); - * } - * } - * const store = new MyStore(); - * - * @method SimpleStore#cacheFind - * @param {string} name The `name` argument passed to {@link SimpleStore#find}. - * @param {*} data The result to cache. - * @param {(string|number)} id The `id` argument passed to {@link SimpleStore#find}. - * @param {object} opts The `opts` argument passed to {@link SimpleStore#find}. - * @since 3.0.0 - */ - cacheFind: function cacheFind(name, data, id, opts) { - var _this = this; - - this._completedQueries[name][id] = function (name, id, opts) { - return _this.get(name, id); - }; - }, - - /** - * Mark a {@link Mapper#findAll} result as cached by adding an entry to - * {@link SimpleStore#_completedQueries}. By default, once a `findAll` entry is - * added it means subsequent calls to the same Resource with the same `query` - * argument will immediately resolve with the result of calling - * {@link SimpleStore#filter} instead of delegating to {@link Mapper#findAll}. - * - * As part of implementing your own caching strategy, you may choose to - * override this method. - * - * @example - * const store = new SimpleStore({ - * cachedFindAll (mapperName, data, hash, opts) { - * // Let's say for a particular Resource, we always want to pull fresh from the server - * if (mapperName === 'schedule') { - * // Return without saving an entry to SimpleStore#_completedQueries - * return; - * } - * // Otherwise perform default behavior. - * return SimpleStore.prototype.cachedFindAll.call(this, mapperName, data, hash, opts); - * } - * }); - * - * @example - * // Extend using ES2015 class syntax. - * class MyStore extends SimpleStore { - * cachedFindAll (mapperName, data, hash, opts) { - * // Let's say for a particular Resource, we always want to pull fresh from the server - * if (mapperName === 'schedule') { - * // Return without saving an entry to SimpleStore#_completedQueries - * return; - * } - * // Otherwise perform default behavior. - * return super.cachedFindAll(mapperName, data, hash, opts); - * } - * } - * const store = new MyStore(); - * - * @method SimpleStore#cacheFindAll - * @param {string} name The `name` argument passed to {@link SimpleStore#findAll}. - * @param {*} data The result to cache. - * @param {string} hash The result of calling {@link SimpleStore#hashQuery} on - * the `query` argument passed to {@link SimpleStore#findAll}. - * @param {object} opts The `opts` argument passed to {@link SimpleStore#findAll}. - * @since 3.0.0 - */ - cacheFindAll: function cacheFindAll(name, data, hash, opts) { - var _this2 = this; - - this._completedQueries[name][hash] = function (name, hash, opts) { - return _this2.filter(name, utils.fromJson(hash)); - }; - }, - - /** - * Remove __all__ records from the in-memory store and reset - * {@link SimpleStore#_completedQueries}. - * - * @method SimpleStore#clear - * @returns {Object} Object containing all records that were in the store. - * @see SimpleStore#remove - * @see SimpleStore#removeAll - * @since 3.0.0 - */ - clear: function clear() { - var _this3 = this; - - var removed = {}; - utils.forOwn(this._collections, function (collection, name) { - removed[name] = collection.removeAll(); - _this3._completedQueries[name] = {}; - }); - return removed; - }, - - /** - * Fired during {@link SimpleStore#create}. See - * {@link SimpleStore~beforeCreateListener} for how to listen for this event. - * - * @event SimpleStore#beforeCreate - * @see SimpleStore~beforeCreateListener - * @see SimpleStore#create - */ - - /** - * Callback signature for the {@link SimpleStore#event:beforeCreate} event. - * - * @example - * function onBeforeCreate (mapperName, props, opts) { - * // do something - * } - * store.on('beforeCreate', onBeforeCreate); - * - * @callback SimpleStore~beforeCreateListener - * @param {string} name The `name` argument received by {@link Mapper#beforeCreate}. - * @param {object} props The `props` argument received by {@link Mapper#beforeCreate}. - * @param {object} opts The `opts` argument received by {@link Mapper#beforeCreate}. - * @see SimpleStore#event:beforeCreate - * @see SimpleStore#create - * @since 3.0.0 - */ - - /** - * Fired during {@link SimpleStore#create}. See - * {@link SimpleStore~afterCreateListener} for how to listen for this event. - * - * @event SimpleStore#afterCreate - * @see SimpleStore~afterCreateListener - * @see SimpleStore#create - */ - - /** - * Callback signature for the {@link SimpleStore#event:afterCreate} event. - * - * @example - * function onAfterCreate (mapperName, props, opts, result) { - * // do something - * } - * store.on('afterCreate', onAfterCreate); - * - * @callback SimpleStore~afterCreateListener - * @param {string} name The `name` argument received by {@link Mapper#afterCreate}. - * @param {object} props The `props` argument received by {@link Mapper#afterCreate}. - * @param {object} opts The `opts` argument received by {@link Mapper#afterCreate}. - * @param {object} result The `result` argument received by {@link Mapper#afterCreate}. - * @see SimpleStore#event:afterCreate - * @see SimpleStore#create - * @since 3.0.0 - */ - - /** - * Wrapper for {@link Mapper#create}. Adds the created record to the store. - * - * @example - * import { SimpleStore } from 'js-data'; - * import { HttpAdapter } from 'js-data-http'; - * - * const store = new SimpleStore(); - * store.registerAdapter('http', new HttpAdapter(), { default: true }); - * - * store.defineMapper('book'); - * - * // Since this example uses the http adapter, we'll get something like: - * // - * // POST /book {"author_id":1234,...} - * store.create('book', { - * author_id: 1234, - * edition: 'First Edition', - * title: 'Respect your Data' - * }).then((book) => { - * console.log(book.id); // 120392 - * console.log(book.title); // "Respect your Data" - * }); - * - * @fires SimpleStore#beforeCreate - * @fires SimpleStore#afterCreate - * @fires SimpleStore#add - * @method SimpleStore#create - * @param {string} name Name of the {@link Mapper} to target. - * @param {object} record Passed to {@link Mapper#create}. - * @param {object} [opts] Passed to {@link Mapper#create}. See - * {@link Mapper#create} for more configuration options. - * @returns {Promise} Resolves with the result of the create. - * @since 3.0.0 - */ - create: function create(name, record, opts) { - var _this4 = this; - - opts || (opts = {}); - return Container.prototype.create.call(this, name, record, opts).then(function (result) { - return _this4._end(name, result, opts); - }); - }, - - /** - * Fired during {@link SimpleStore#createMany}. See - * {@link SimpleStore~beforeCreateManyListener} for how to listen for this event. - * - * @event SimpleStore#beforeCreateMany - * @see SimpleStore~beforeCreateManyListener - * @see SimpleStore#createMany - */ - - /** - * Callback signature for the {@link SimpleStore#event:beforeCreateMany} event. - * - * @example - * function onBeforeCreateMany (mapperName, records, opts) { - * // do something - * } - * store.on('beforeCreateMany', onBeforeCreateMany); - * - * @callback SimpleStore~beforeCreateManyListener - * @param {string} name The `name` argument received by {@link Mapper#beforeCreateMany}. - * @param {object} records The `records` argument received by {@link Mapper#beforeCreateMany}. - * @param {object} opts The `opts` argument received by {@link Mapper#beforeCreateMany}. - * @see SimpleStore#event:beforeCreateMany - * @see SimpleStore#createMany - * @since 3.0.0 - */ - - /** - * Fired during {@link SimpleStore#createMany}. See - * {@link SimpleStore~afterCreateManyListener} for how to listen for this event. - * - * @event SimpleStore#afterCreateMany - * @see SimpleStore~afterCreateManyListener - * @see SimpleStore#createMany - */ - - /** - * Callback signature for the {@link SimpleStore#event:afterCreateMany} event. - * - * @example - * function onAfterCreateMany (mapperName, records, opts, result) { - * // do something - * } - * store.on('afterCreateMany', onAfterCreateMany); - * - * @callback SimpleStore~afterCreateManyListener - * @param {string} name The `name` argument received by {@link Mapper#afterCreateMany}. - * @param {object} records The `records` argument received by {@link Mapper#afterCreateMany}. - * @param {object} opts The `opts` argument received by {@link Mapper#afterCreateMany}. - * @param {object} result The `result` argument received by {@link Mapper#afterCreateMany}. - * @see SimpleStore#event:afterCreateMany - * @see SimpleStore#createMany - * @since 3.0.0 - */ - - /** - * Wrapper for {@link Mapper#createMany}. Adds the created records to the - * store. - * - * @example - * import { SimpleStore } from 'js-data'; - * import { HttpAdapter } from 'js-data-http'; - * - * const store = new SimpleStore(); - * store.registerAdapter('http', new HttpAdapter(), { default: true }); - * - * store.defineMapper('book'); - * - * // Since this example uses the http adapter, we'll get something like: - * // - * // POST /book [{"author_id":1234,...},{...}] - * store.createMany('book', [{ - * author_id: 1234, - * edition: 'First Edition', - * title: 'Respect your Data' - * }, { - * author_id: 1234, - * edition: 'Second Edition', - * title: 'Respect your Data' - * }]).then((books) => { - * console.log(books[0].id); // 142394 - * console.log(books[0].title); // "Respect your Data" - * }); - * - * @fires SimpleStore#beforeCreateMany - * @fires SimpleStore#afterCreateMany - * @fires SimpleStore#add - * @method SimpleStore#createMany - * @param {string} name Name of the {@link Mapper} to target. - * @param {array} records Passed to {@link Mapper#createMany}. - * @param {object} [opts] Passed to {@link Mapper#createMany}. See - * {@link Mapper#createMany} for more configuration options. - * @returns {Promise} Resolves with the result of the create. - * @since 3.0.0 - */ - createMany: function createMany(name, records, opts) { - var _this5 = this; - - opts || (opts = {}); - return Container.prototype.createMany.call(this, name, records, opts).then(function (result) { - return _this5._end(name, result, opts); - }); - }, - defineMapper: function defineMapper(name, opts) { - var self = this; - var mapper = Container.prototype.defineMapper.call(self, name, opts); - self._pendingQueries[name] = {}; - self._completedQueries[name] = {}; - mapper.relationList || Object.defineProperty(mapper, 'relationList', { - value: [] - }); - var collectionOpts = { - // Make sure the collection has somewhere to store "added" timestamps - _added: {}, - // Give the collection a reference to this SimpleStore - datastore: self, - // The mapper tied to the collection - mapper: mapper - }; - - if (opts && 'onConflict' in opts) { - collectionOpts.onConflict = opts.onConflict; - } // The SimpleStore uses a subclass of Collection that is "SimpleStore-aware" - - - var collection = self._collections[name] = new self.collectionClass(null, collectionOpts); // eslint-disable-line - - var schema = mapper.schema || {}; - var properties = schema.properties || {}; // TODO: Make it possible index nested properties? - - utils.forOwn(properties, function (opts, prop) { - if (opts.indexed) { - collection.createIndex(prop); - } - }); // Create a secondary index on the "added" timestamps of records in the - // collection - - collection.createIndex('addedTimestamps', ['$'], { - fieldGetter: function fieldGetter(obj) { - return collection._added[collection.recordId(obj)]; - } - }); - collection.on('all', function () { - for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { - args[_key3] = arguments[_key3]; - } - - self._onCollectionEvent.apply(self, [name].concat(args)); - }); - return mapper; - }, - - /** - * Fired during {@link SimpleStore#destroy}. See - * {@link SimpleStore~beforeDestroyListener} for how to listen for this event. - * - * @event SimpleStore#beforeDestroy - * @see SimpleStore~beforeDestroyListener - * @see SimpleStore#destroy - */ - - /** - * Callback signature for the {@link SimpleStore#event:beforeDestroy} event. - * - * @example - * function onBeforeDestroy (mapperName, id, opts) { - * // do something - * } - * store.on('beforeDestroy', onBeforeDestroy); - * - * @callback SimpleStore~beforeDestroyListener - * @param {string} name The `name` argument received by {@link Mapper#beforeDestroy}. - * @param {string|number} id The `id` argument received by {@link Mapper#beforeDestroy}. - * @param {object} opts The `opts` argument received by {@link Mapper#beforeDestroy}. - * @see SimpleStore#event:beforeDestroy - * @see SimpleStore#destroy - * @since 3.0.0 - */ - - /** - * Fired during {@link SimpleStore#destroy}. See - * {@link SimpleStore~afterDestroyListener} for how to listen for this event. - * - * @event SimpleStore#afterDestroy - * @see SimpleStore~afterDestroyListener - * @see SimpleStore#destroy - */ - - /** - * Callback signature for the {@link SimpleStore#event:afterDestroy} event. - * - * @example - * function onAfterDestroy (mapperName, id, opts, result) { - * // do something - * } - * store.on('afterDestroy', onAfterDestroy); - * - * @callback SimpleStore~afterDestroyListener - * @param {string} name The `name` argument received by {@link Mapper#afterDestroy}. - * @param {string|number} id The `id` argument received by {@link Mapper#afterDestroy}. - * @param {object} opts The `opts` argument received by {@link Mapper#afterDestroy}. - * @param {object} result The `result` argument received by {@link Mapper#afterDestroy}. - * @see SimpleStore#event:afterDestroy - * @see SimpleStore#destroy - * @since 3.0.0 - */ - - /** - * Wrapper for {@link Mapper#destroy}. Removes any destroyed record from the - * in-memory store. Clears out any {@link SimpleStore#_completedQueries} entries - * associated with the provided `id`. - * - * @example - * import { SimpleStore } from 'js-data'; - * import { HttpAdapter } from 'js-data-http'; - * - * const store = new SimpleStore(); - * store.registerAdapter('http', new HttpAdapter(), { default: true }); - * - * store.defineMapper('book'); - * - * store.add('book', { id: 1234, title: 'Data Management is Hard' }); - * - * // Since this example uses the http adapter, we'll get something like: - * // - * // DELETE /book/1234 - * store.destroy('book', 1234).then(() => { - * // The book record is no longer in the in-memory store - * console.log(store.get('book', 1234)); // undefined - * - * return store.find('book', 1234); - * }).then((book) { - * // The book was deleted from the database too - * console.log(book); // undefined - * }); - * - * @fires SimpleStore#beforeDestroy - * @fires SimpleStore#afterDestroy - * @fires SimpleStore#remove - * @method SimpleStore#destroy - * @param {string} name Name of the {@link Mapper} to target. - * @param {(string|number)} id Passed to {@link Mapper#destroy}. - * @param {object} [opts] Passed to {@link Mapper#destroy}. See - * {@link Mapper#destroy} for more configuration options. - * @returns {Promise} Resolves when the destroy operation completes. - * @since 3.0.0 - */ - destroy: function destroy(name, id, opts) { - var _this6 = this; - - opts || (opts = {}); - return Container.prototype.destroy.call(this, name, id, opts).then(function (result) { - var record = _this6.getCollection(name).remove(id, opts); - - if (opts.raw) { - result.data = record; - } else { - result = record; - } - - delete _this6._pendingQueries[name][id]; - delete _this6._completedQueries[name][id]; - return result; - }); - }, - - /** - * Fired during {@link SimpleStore#destroyAll}. See - * {@link SimpleStore~beforeDestroyAllListener} for how to listen for this event. - * - * @event SimpleStore#beforeDestroyAll - * @see SimpleStore~beforeDestroyAllListener - * @see SimpleStore#destroyAll - */ - - /** - * Callback signature for the {@link SimpleStore#event:beforeDestroyAll} event. - * - * @example - * function onBeforeDestroyAll (mapperName, query, opts) { - * // do something - * } - * store.on('beforeDestroyAll', onBeforeDestroyAll); - * - * @callback SimpleStore~beforeDestroyAllListener - * @param {string} name The `name` argument received by {@link Mapper#beforeDestroyAll}. - * @param {object} query The `query` argument received by {@link Mapper#beforeDestroyAll}. - * @param {object} opts The `opts` argument received by {@link Mapper#beforeDestroyAll}. - * @see SimpleStore#event:beforeDestroyAll - * @see SimpleStore#destroyAll - * @since 3.0.0 - */ - - /** - * Fired during {@link SimpleStore#destroyAll}. See - * {@link SimpleStore~afterDestroyAllListener} for how to listen for this event. - * - * @event SimpleStore#afterDestroyAll - * @see SimpleStore~afterDestroyAllListener - * @see SimpleStore#destroyAll - */ - - /** - * Callback signature for the {@link SimpleStore#event:afterDestroyAll} event. - * - * @example - * function onAfterDestroyAll (mapperName, query, opts, result) { - * // do something - * } - * store.on('afterDestroyAll', onAfterDestroyAll); - * - * @callback SimpleStore~afterDestroyAllListener - * @param {string} name The `name` argument received by {@link Mapper#afterDestroyAll}. - * @param {object} query The `query` argument received by {@link Mapper#afterDestroyAll}. - * @param {object} opts The `opts` argument received by {@link Mapper#afterDestroyAll}. - * @param {object} result The `result` argument received by {@link Mapper#afterDestroyAll}. - * @see SimpleStore#event:afterDestroyAll - * @see SimpleStore#destroyAll - * @since 3.0.0 - */ - - /** - * Wrapper for {@link Mapper#destroyAll}. Removes any destroyed records from - * the in-memory store. - * - * @example - * import { SimpleStore } from 'js-data'; - * import { HttpAdapter } from 'js-data-http'; - * - * const store = new SimpleStore(); - * store.registerAdapter('http', new HttpAdapter(), { default: true }); - * - * store.defineMapper('book'); - * - * store.add('book', { id: 1234, title: 'Data Management is Hard' }); - * - * // Since this example uses the http adapter, we'll get something like: - * // - * // DELETE /book/1234 - * store.destroy('book', 1234).then(() => { - * // The book record is gone from the in-memory store - * console.log(store.get('book', 1234)); // undefined - * return store.find('book', 1234); - * }).then((book) { - * // The book was deleted from the database too - * console.log(book); // undefined - * }); - * - * @fires SimpleStore#beforeDestroyAll - * @fires SimpleStore#afterDestroyAll - * @fires SimpleStore#remove - * @method SimpleStore#destroyAll - * @param {string} name Name of the {@link Mapper} to target. - * @param {object} [query] Passed to {@link Mapper#destroyAll}. - * @param {object} [opts] Passed to {@link Mapper#destroyAll}. See - * {@link Mapper#destroyAll} for more configuration options. - * @returns {Promise} Resolves when the delete completes. - * @since 3.0.0 - */ - destroyAll: function destroyAll(name, query, opts) { - var _this7 = this; - - opts || (opts = {}); - return Container.prototype.destroyAll.call(this, name, query, opts).then(function (result) { - var records = _this7.getCollection(name).removeAll(query, opts); - - if (opts.raw) { - result.data = records; - } else { - result = records; - } - - var hash = _this7.hashQuery(name, query, opts); - - delete _this7._pendingQueries[name][hash]; - delete _this7._completedQueries[name][hash]; - return result; - }); - }, - eject: function eject(name, id, opts) { - console.warn('DEPRECATED: "eject" is deprecated, use "remove" instead'); - return this.remove(name, id, opts); - }, - ejectAll: function ejectAll(name, query, opts) { - console.warn('DEPRECATED: "ejectAll" is deprecated, use "removeAll" instead'); - return this.removeAll(name, query, opts); - }, - - /** - * Fired during {@link SimpleStore#find}. See - * {@link SimpleStore~beforeFindListener} for how to listen for this event. - * - * @event SimpleStore#beforeFind - * @see SimpleStore~beforeFindListener - * @see SimpleStore#find - */ - - /** - * Callback signature for the {@link SimpleStore#event:beforeFind} event. - * - * @example - * function onBeforeFind (mapperName, id, opts) { - * // do something - * } - * store.on('beforeFind', onBeforeFind); - * - * @callback SimpleStore~beforeFindListener - * @param {string} name The `name` argument received by {@link Mapper#beforeFind}. - * @param {string|number} id The `id` argument received by {@link Mapper#beforeFind}. - * @param {object} opts The `opts` argument received by {@link Mapper#beforeFind}. - * @see SimpleStore#event:beforeFind - * @see SimpleStore#find - * @since 3.0.0 - */ - - /** - * Fired during {@link SimpleStore#find}. See - * {@link SimpleStore~afterFindListener} for how to listen for this event. - * - * @event SimpleStore#afterFind - * @see SimpleStore~afterFindListener - * @see SimpleStore#find - */ - - /** - * Callback signature for the {@link SimpleStore#event:afterFind} event. - * - * @example - * function onAfterFind (mapperName, id, opts, result) { - * // do something - * } - * store.on('afterFind', onAfterFind); - * - * @callback SimpleStore~afterFindListener - * @param {string} name The `name` argument received by {@link Mapper#afterFind}. - * @param {string|number} id The `id` argument received by {@link Mapper#afterFind}. - * @param {object} opts The `opts` argument received by {@link Mapper#afterFind}. - * @param {object} result The `result` argument received by {@link Mapper#afterFind}. - * @see SimpleStore#event:afterFind - * @see SimpleStore#find - * @since 3.0.0 - */ - - /** - * Wrapper for {@link Mapper#find}. Adds any found record to the store. - * - * @example - * import { SimpleStore } from 'js-data'; - * import { HttpAdapter } from 'js-data-http'; - * - * const store = new SimpleStore(); - * store.registerAdapter('http', new HttpAdapter(), { default: true }); - * - * store.defineMapper('book'); - * - * // Since this example uses the http adapter, we'll get something like: - * // - * // GET /book/1234 - * store.find('book', 1234).then((book) => { - * // The book record is now in the in-memory store - * console.log(store.get('book', 1234) === book); // true - * }); - * - * @fires SimpleStore#beforeFind - * @fires SimpleStore#afterFind - * @fires SimpleStore#add - * @method SimpleStore#find - * @param {string} name Name of the {@link Mapper} to target. - * @param {(string|number)} id Passed to {@link Mapper#find}. - * @param {object} [opts] Passed to {@link Mapper#find}. - * @param {boolean} [opts.force] Bypass cacheFind - * @param {boolean|Function} [opts.usePendingFind] See {@link SimpleStore#usePendingFind} - * @returns {Promise} Resolves with the result, if any. - * @since 3.0.0 - */ - find: function find(name, id, opts) { - var _this8 = this; - - opts || (opts = {}); - var mapper = this.getMapper(name); - var pendingQuery = this._pendingQueries[name][id]; - var usePendingFind = opts.usePendingFind === undefined ? this.usePendingFind : opts.usePendingFind; - - utils._(opts, mapper); - - if (pendingQuery && (utils.isFunction(usePendingFind) ? usePendingFind.call(this, name, id, opts) : usePendingFind)) { - return pendingQuery; - } - - var item = this.cachedFind(name, id, opts); - - if (opts.force || !item) { - var promise = this._pendingQueries[name][id] = Container.prototype.find.call(this, name, id, opts); - return promise.then(function (result) { - delete _this8._pendingQueries[name][id]; - result = _this8._end(name, result, opts); - - _this8.cacheFind(name, result, id, opts); - - return result; - }, function (err) { - delete _this8._pendingQueries[name][id]; - return utils.reject(err); - }); - } - - return utils.resolve(item); - }, - - /** - * Fired during {@link SimpleStore#findAll}. See - * {@link SimpleStore~beforeFindAllListener} for how to listen for this event. - * - * @event SimpleStore#beforeFindAll - * @see SimpleStore~beforeFindAllListener - * @see SimpleStore#findAll - */ - - /** - * Callback signature for the {@link SimpleStore#event:beforeFindAll} event. - * - * @example - * function onBeforeFindAll (mapperName, query, opts) { - * // do something - * } - * store.on('beforeFindAll', onBeforeFindAll); - * - * @callback SimpleStore~beforeFindAllListener - * @param {string} name The `name` argument received by {@link Mapper#beforeFindAll}. - * @param {object} query The `query` argument received by {@link Mapper#beforeFindAll}. - * @param {object} opts The `opts` argument received by {@link Mapper#beforeFindAll}. - * @see SimpleStore#event:beforeFindAll - * @see SimpleStore#findAll - * @since 3.0.0 - */ - - /** - * Fired during {@link SimpleStore#findAll}. See - * {@link SimpleStore~afterFindAllListener} for how to listen for this event. - * - * @event SimpleStore#afterFindAll - * @see SimpleStore~afterFindAllListener - * @see SimpleStore#findAll - */ - - /** - * Callback signature for the {@link SimpleStore#event:afterFindAll} event. - * - * @example - * function onAfterFindAll (mapperName, query, opts, result) { - * // do something - * } - * store.on('afterFindAll', onAfterFindAll); - * - * @callback SimpleStore~afterFindAllListener - * @param {string} name The `name` argument received by {@link Mapper#afterFindAll}. - * @param {object} query The `query` argument received by {@link Mapper#afterFindAll}. - * @param {object} opts The `opts` argument received by {@link Mapper#afterFindAll}. - * @param {object} result The `result` argument received by {@link Mapper#afterFindAll}. - * @see SimpleStore#event:afterFindAll - * @see SimpleStore#findAll - * @since 3.0.0 - */ - - /** - * Wrapper for {@link Mapper#findAll}. Adds any found records to the store. - * - * @example - * import { SimpleStore } from 'js-data'; - * import { HttpAdapter } from 'js-data-http'; - * - * const store = new SimpleStore(); - * store.registerAdapter('http', new HttpAdapter(), { default: true }); - * - * store.defineMapper('movie'); - * - * // Since this example uses the http adapter, we'll get something like: - * // - * // GET /movie?rating=PG - * store.find('movie', { rating: 'PG' }).then((movies) => { - * // The movie records are now in the in-memory store - * console.log(store.filter('movie')); - * }); - * - * @fires SimpleStore#beforeFindAll - * @fires SimpleStore#afterFindAll - * @fires SimpleStore#add - * @method SimpleStore#findAll - * @param {string} name Name of the {@link Mapper} to target. - * @param {object} [query] Passed to {@link Mapper.findAll}. - * @param {object} [opts] Passed to {@link Mapper.findAll}. - * @param {boolean} [opts.force] Bypass cacheFindAll - * @param {boolean|Function} [opts.usePendingFindAll] See {@link SimpleStore#usePendingFindAll} - * @returns {Promise} Resolves with the result, if any. - * @since 3.0.0 - */ - findAll: function findAll(name, query, opts) { - var _this9 = this; - - opts || (opts = {}); - var mapper = this.getMapper(name); - var hash = this.hashQuery(name, query, opts); - var pendingQuery = this._pendingQueries[name][hash]; - var usePendingFindAll = opts.usePendingFindAll === undefined ? this.usePendingFindAll : opts.usePendingFindAll; - - utils._(opts, mapper); - - if (pendingQuery && (utils.isFunction(usePendingFindAll) ? usePendingFindAll.call(this, name, query, opts) : usePendingFindAll)) { - return pendingQuery; - } - - var items = this.cachedFindAll(name, hash, opts); - - if (opts.force || !items) { - var promise = this._pendingQueries[name][hash] = Container.prototype.findAll.call(this, name, query, opts); - return promise.then(function (result) { - delete _this9._pendingQueries[name][hash]; - result = _this9._end(name, result, opts); - - _this9.cacheFindAll(name, result, hash, opts); - - return result; - }, function (err) { - delete _this9._pendingQueries[name][hash]; - return utils.reject(err); - }); - } - - return utils.resolve(items); - }, - - /** - * Return the {@link Collection} with the given name, if for some - * reason you need a direct reference to the collection. - * - * @method SimpleStore#getCollection - * @param {string} name Name of the {@link Collection} to retrieve. - * @returns {Collection} - * @since 3.0.0 - * @throws {Error} Thrown if the specified {@link Collection} does not - * exist. - */ - getCollection: function getCollection(name) { - var collection = this._collections[name]; - - if (!collection) { - throw utils.err("".concat(DOMAIN$8, "#getCollection"), name)(404, 'collection'); - } - - return collection; - }, - - /** - * Hashing function used to cache {@link SimpleStore#find} and - * {@link SimpleStore#findAll} requests. This method simply JSONifies the - * `query` argument passed to {@link SimpleStore#find} or - * {@link SimpleStore#findAll}. - * - * Override this method for custom hashing behavior. - * @method SimpleStore#hashQuery - * @param {string} name The `name` argument passed to {@link SimpleStore#find} - * or {@link SimpleStore#findAll}. - * @param {object} query The `query` argument passed to {@link SimpleStore#find} - * or {@link SimpleStore#findAll}. - * @returns {string} The JSONified `query`. - * @since 3.0.0 - */ - hashQuery: function hashQuery(name, query, opts) { - return utils.toJson(query || {}); - }, - inject: function inject(name, records, opts) { - console.warn('DEPRECATED: "inject" is deprecated, use "add" instead'); - return this.add(name, records, opts); - }, - - /** - * Wrapper for {@link Collection#remove}. Removes the specified - * {@link Record} from the store. - * - * @example SimpleStore#remove - * const JSData = require('js-data'); - * const { SimpleStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new SimpleStore(); - * store.defineMapper('book'); - * console.log(store.getAll('book').length); - * store.add('book', { id: 1234 }); - * console.log(store.getAll('book').length); - * store.remove('book', 1234); - * console.log(store.getAll('book').length); - * - * @fires SimpleStore#remove - * @method SimpleStore#remove - * @param {string} name The name of the {@link Collection} to target. - * @param {string|number} id The primary key of the {@link Record} to remove. - * @param {object} [opts] Configuration options. - * @param {string[]} [opts.with] Relations of the {@link Record} to also - * remove from the store. - * @returns {Record} The removed {@link Record}, if any. - * @see Collection#add - * @see Collection#add - * @since 3.0.0 - */ - remove: function remove(name, id, opts) { - var record = this.getCollection(name).remove(id, opts); - - if (record) { - this.removeRelated(name, [record], opts); - } - - return record; - }, - - /** - * Wrapper for {@link Collection#removeAll}. Removes the selected - * {@link Record}s from the store. - * - * @example SimpleStore#removeAll - * const JSData = require('js-data'); - * const { SimpleStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new SimpleStore(); - * store.defineMapper('movie'); - * console.log(store.getAll('movie').length); - * store.add('movie', [{ id: 3, rating: 'R' }, { id: 4, rating: 'PG-13' }); - * console.log(store.getAll('movie').length); - * store.removeAll('movie', { rating: 'R' }); - * console.log(store.getAll('movie').length); - * - * @fires SimpleStore#remove - * @method SimpleStore#removeAll - * @param {string} name The name of the {@link Collection} to target. - * @param {object} [query={}] Selection query. See {@link query}. - * @param {object} [query.where] See {@link query.where}. - * @param {number} [query.offset] See {@link query.offset}. - * @param {number} [query.limit] See {@link query.limit}. - * @param {string|Array[]} [query.orderBy] See {@link query.orderBy}. - * @param {object} [opts] Configuration options. - * @param {string[]} [opts.with] Relations of the {@link Record} to also - * remove from the store. - * @returns {Record} The removed {@link Record}s, if any. - * @see Collection#add - * @see Collection#add - * @since 3.0.0 - */ - removeAll: function removeAll(name, query, opts) { - if (!query || !Object.keys(query).length) { - this._completedQueries[name] = {}; - } else { - this._completedQueries[name][this.hashQuery(name, query, opts)] = undefined; - } - - var records = this.getCollection(name).removeAll(query, opts); - - if (records.length) { - this.removeRelated(name, records, opts); - } - - return records; - }, - - /** - * Remove from the store {@link Record}s that are related to the provided - * {@link Record}(s). - * - * @fires SimpleStore#remove - * @method SimpleStore#removeRelated - * @param {string} name The name of the {@link Collection} to target. - * @param {Record|Record[]} records {@link Record}s whose relations are to be - * removed. - * @param {object} [opts] Configuration options. - * @param {string[]} [opts.with] Relations of the {@link Record}(s) to remove - * from the store. - * @since 3.0.0 - */ - removeRelated: function removeRelated(name, records, opts) { - var _this10 = this; - - if (!utils.isArray(records)) { - records = [records]; - } - - utils.forEachRelation(this.getMapper(name), opts, function (def, optsCopy) { - records.forEach(function (record) { - var relatedData; - var query; - - if (def.foreignKey && (def.type === hasOneType || def.type === hasManyType)) { - query = _defineProperty({}, def.foreignKey, def.getForeignKey(record)); - } else if (def.type === hasManyType && def.localKeys) { - query = { - where: _defineProperty({}, def.getRelation().idAttribute, { - in: utils.get(record, def.localKeys) - }) - }; - } else if (def.type === hasManyType && def.foreignKeys) { - query = { - where: _defineProperty({}, def.foreignKeys, { - contains: def.getForeignKey(record) - }) - }; - } else if (def.type === belongsToType) { - relatedData = _this10.remove(def.relation, def.getForeignKey(record), optsCopy); - } - - if (query) { - relatedData = _this10.removeAll(def.relation, query, optsCopy); - } - - if (relatedData) { - if (utils.isArray(relatedData) && !relatedData.length) { - return; - } - - if (def.type === hasOneType) { - relatedData = relatedData[0]; - } - - def.setLocalField(record, relatedData); - } - }); - }); - }, - - /** - * Fired during {@link SimpleStore#update}. See - * {@link SimpleStore~beforeUpdateListener} for how to listen for this event. - * - * @event SimpleStore#beforeUpdate - * @see SimpleStore~beforeUpdateListener - * @see SimpleStore#update - */ - - /** - * Callback signature for the {@link SimpleStore#event:beforeUpdate} event. - * - * @example - * function onBeforeUpdate (mapperName, id, props, opts) { - * // do something - * } - * store.on('beforeUpdate', onBeforeUpdate); - * - * @callback SimpleStore~beforeUpdateListener - * @param {string} name The `name` argument received by {@link Mapper#beforeUpdate}. - * @param {string|number} id The `id` argument received by {@link Mapper#beforeUpdate}. - * @param {object} props The `props` argument received by {@link Mapper#beforeUpdate}. - * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdate}. - * @see SimpleStore#event:beforeUpdate - * @see SimpleStore#update - * @since 3.0.0 - */ - - /** - * Fired during {@link SimpleStore#update}. See - * {@link SimpleStore~afterUpdateListener} for how to listen for this event. - * - * @event SimpleStore#afterUpdate - * @see SimpleStore~afterUpdateListener - * @see SimpleStore#update - */ - - /** - * Callback signature for the {@link SimpleStore#event:afterUpdate} event. - * - * @example - * function onAfterUpdate (mapperName, id, props, opts, result) { - * // do something - * } - * store.on('afterUpdate', onAfterUpdate); - * - * @callback SimpleStore~afterUpdateListener - * @param {string} name The `name` argument received by {@link Mapper#afterUpdate}. - * @param {string|number} id The `id` argument received by {@link Mapper#afterUpdate}. - * @param {object} props The `props` argument received by {@link Mapper#afterUpdate}. - * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdate}. - * @param {object} result The `result` argument received by {@link Mapper#afterUpdate}. - * @see SimpleStore#event:afterUpdate - * @see SimpleStore#update - * @since 3.0.0 - */ - - /** - * Wrapper for {@link Mapper#update}. Adds the updated {@link Record} to the - * store. - * - * @example - * import { SimpleStore } from 'js-data'; - * import { HttpAdapter } from 'js-data-http'; - * - * const store = new SimpleStore(); - * store.registerAdapter('http', new HttpAdapter(), { default: true }); - * - * store.defineMapper('post'); - * - * // Since this example uses the http adapter, we'll get something like: - * // - * // PUT /post/1234 {"status":"published"} - * store.update('post', 1, { status: 'published' }).then((post) => { - * // The post record has also been updated in the in-memory store - * console.log(store.get('post', 1234)); - * }); - * - * @fires SimpleStore#beforeUpdate - * @fires SimpleStore#afterUpdate - * @fires SimpleStore#add - * @method SimpleStore#update - * @param {string} name Name of the {@link Mapper} to target. - * @param {(string|number)} id Passed to {@link Mapper#update}. - * @param {object} record Passed to {@link Mapper#update}. - * @param {object} [opts] Passed to {@link Mapper#update}. See - * {@link Mapper#update} for more configuration options. - * @returns {Promise} Resolves with the result of the update. - * @since 3.0.0 - */ - update: function update(name, id, record, opts) { - var _this11 = this; - - opts || (opts = {}); - return Container.prototype.update.call(this, name, id, record, opts).then(function (result) { - return _this11._end(name, result, opts); - }); - }, - - /** - * Fired during {@link SimpleStore#updateAll}. See - * {@link SimpleStore~beforeUpdateAllListener} for how to listen for this event. - * - * @event SimpleStore#beforeUpdateAll - * @see SimpleStore~beforeUpdateAllListener - * @see SimpleStore#updateAll - */ - - /** - * Callback signature for the {@link SimpleStore#event:beforeUpdateAll} event. - * - * @example - * function onBeforeUpdateAll (mapperName, props, query, opts) { - * // do something - * } - * store.on('beforeUpdateAll', onBeforeUpdateAll); - * - * @callback SimpleStore~beforeUpdateAllListener - * @param {string} name The `name` argument received by {@link Mapper#beforeUpdateAll}. - * @param {object} props The `props` argument received by {@link Mapper#beforeUpdateAll}. - * @param {object} query The `query` argument received by {@link Mapper#beforeUpdateAll}. - * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdateAll}. - * @see SimpleStore#event:beforeUpdateAll - * @see SimpleStore#updateAll - * @since 3.0.0 - */ - - /** - * Fired during {@link SimpleStore#updateAll}. See - * {@link SimpleStore~afterUpdateAllListener} for how to listen for this event. - * - * @event SimpleStore#afterUpdateAll - * @see SimpleStore~afterUpdateAllListener - * @see SimpleStore#updateAll - */ - - /** - * Callback signature for the {@link SimpleStore#event:afterUpdateAll} event. - * - * @example - * function onAfterUpdateAll (mapperName, props, query, opts, result) { - * // do something - * } - * store.on('afterUpdateAll', onAfterUpdateAll); - * - * @callback SimpleStore~afterUpdateAllListener - * @param {string} name The `name` argument received by {@link Mapper#afterUpdateAll}. - * @param {object} props The `props` argument received by {@link Mapper#afterUpdateAll}. - * @param {object} query The `query` argument received by {@link Mapper#afterUpdateAll}. - * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdateAll}. - * @param {object} result The `result` argument received by {@link Mapper#afterUpdateAll}. - * @see SimpleStore#event:afterUpdateAll - * @see SimpleStore#updateAll - * @since 3.0.0 - */ - - /** - * Wrapper for {@link Mapper#updateAll}. Adds the updated {@link Record}s to - * the store. - * - * @example - * import { SimpleStore } from 'js-data'; - * import { HttpAdapter } from 'js-data-http'; - * - * const store = new SimpleStore(); - * store.registerAdapter('http', new HttpAdapter(), { default: true }); - * - * store.defineMapper('post'); - * - * // Since this example uses the http adapter, we'll get something like: - * // - * // PUT /post?author_id=1234 {"status":"published"} - * store.updateAll('post', { author_id: 1234 }, { status: 'published' }).then((posts) => { - * // The post records have also been updated in the in-memory store - * console.log(store.filter('posts', { author_id: 1234 })); - * }); - * - * @fires SimpleStore#beforeUpdateAll - * @fires SimpleStore#afterUpdateAll - * @fires SimpleStore#add - * @method SimpleStore#updateAll - * @param {string} name Name of the {@link Mapper} to target. - * @param {object} props Passed to {@link Mapper#updateAll}. - * @param {object} [query] Passed to {@link Mapper#updateAll}. - * @param {object} [opts] Passed to {@link Mapper#updateAll}. See - * {@link Mapper#updateAll} for more configuration options. - * @returns {Promise} Resolves with the result of the update. - * @since 3.0.0 - */ - updateAll: function updateAll(name, props, query, opts) { - var _this12 = this; - - opts || (opts = {}); - return Container.prototype.updateAll.call(this, name, props, query, opts).then(function (result) { - return _this12._end(name, result, opts); - }); - }, - - /** - * Fired during {@link SimpleStore#updateMany}. See - * {@link SimpleStore~beforeUpdateManyListener} for how to listen for this event. - * - * @event SimpleStore#beforeUpdateMany - * @see SimpleStore~beforeUpdateManyListener - * @see SimpleStore#updateMany - */ - - /** - * Callback signature for the {@link SimpleStore#event:beforeUpdateMany} event. - * - * @example - * function onBeforeUpdateMany (mapperName, records, opts) { - * // do something - * } - * store.on('beforeUpdateMany', onBeforeUpdateMany); - * - * @callback SimpleStore~beforeUpdateManyListener - * @param {string} name The `name` argument received by {@link Mapper#beforeUpdateMany}. - * @param {object} records The `records` argument received by {@link Mapper#beforeUpdateMany}. - * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdateMany}. - * @see SimpleStore#event:beforeUpdateMany - * @see SimpleStore#updateMany - * @since 3.0.0 - */ - - /** - * Fired during {@link SimpleStore#updateMany}. See - * {@link SimpleStore~afterUpdateManyListener} for how to listen for this event. - * - * @event SimpleStore#afterUpdateMany - * @see SimpleStore~afterUpdateManyListener - * @see SimpleStore#updateMany - */ - - /** - * Callback signature for the {@link SimpleStore#event:afterUpdateMany} event. - * - * @example - * function onAfterUpdateMany (mapperName, records, opts, result) { - * // do something - * } - * store.on('afterUpdateMany', onAfterUpdateMany); - * - * @callback SimpleStore~afterUpdateManyListener - * @param {string} name The `name` argument received by {@link Mapper#afterUpdateMany}. - * @param {object} records The `records` argument received by {@link Mapper#afterUpdateMany}. - * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdateMany}. - * @param {object} result The `result` argument received by {@link Mapper#afterUpdateMany}. - * @see SimpleStore#event:afterUpdateMany - * @see SimpleStore#updateMany - * @since 3.0.0 - */ - - /** - * Wrapper for {@link Mapper#updateMany}. Adds the updated {@link Record}s to - * the store. - * - * @example - * import { SimpleStore } from 'js-data'; - * import { HttpAdapter } from 'js-data-http'; - * - * const store = new SimpleStore(); - * store.registerAdapter('http', new HttpAdapter(), { default: true }); - * - * store.defineMapper('post'); - * - * // Since this example uses the http adapter, we'll get something like: - * // - * // PUT /post [{"id":3,status":"published"},{"id":4,status":"published"}] - * store.updateMany('post', [ - * { id: 3, status: 'published' }, - * { id: 4, status: 'published' } - * ]).then((posts) => { - * // The post records have also been updated in the in-memory store - * console.log(store.getAll('post', 3, 4)); - * }); - * - * @fires SimpleStore#beforeUpdateMany - * @fires SimpleStore#afterUpdateMany - * @fires SimpleStore#add - * @method SimpleStore#updateMany - * @param {string} name Name of the {@link Mapper} to target. - * @param {(Object[]|Record[])} records Passed to {@link Mapper#updateMany}. - * @param {object} [opts] Passed to {@link Mapper#updateMany}. See - * {@link Mapper#updateMany} for more configuration options. - * @returns {Promise} Resolves with the result of the update. - * @since 3.0.0 - */ - updateMany: function updateMany(name, records, opts) { - var _this13 = this; - - opts || (opts = {}); - return Container.prototype.updateMany.call(this, name, records, opts).then(function (result) { - return _this13._end(name, result, opts); - }); - } -}; -proxiedCollectionMethods.forEach(function (method) { - props$1[method] = function (name) { - var _this$getCollection; - - for (var _len4 = arguments.length, args = new Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) { - args[_key4 - 1] = arguments[_key4]; - } - - return (_this$getCollection = this.getCollection(name))[method].apply(_this$getCollection, args); - }; -}); -var SimpleStore$1 = Container.extend(props$1); -/** - * Fired when a record changes. Only works for records that have tracked fields. - * See {@link SimpleStore~changeListener} on how to listen for this event. - * - * @event SimpleStore#change - * @see SimpleStore~changeListener - */ - -/** - * Callback signature for the {@link SimpleStore#event:change} event. - * - * @example - * function onChange (mapperName, record, changes) { - * // do something - * } - * store.on('change', onChange); - * - * @callback SimpleStore~changeListener - * @param {string} name The name of the associated {@link Mapper}. - * @param {Record} record The Record that changed. - * @param {object} changes The changes. - * @see SimpleStore#event:change - * @since 3.0.0 - */ - -/** - * Fired when one or more records are added to the in-memory store. See - * {@link SimpleStore~addListener} on how to listen for this event. - * - * @event SimpleStore#add - * @see SimpleStore~addListener - * @see SimpleStore#event:add - * @see SimpleStore#add - * @see SimpleStore#create - * @see SimpleStore#createMany - * @see SimpleStore#find - * @see SimpleStore#findAll - * @see SimpleStore#update - * @see SimpleStore#updateAll - * @see SimpleStore#updateMany - */ - -/** - * Callback signature for the {@link SimpleStore#event:add} event. - * - * @example - * function onAdd (mapperName, recordOrRecords) { - * // do something - * } - * store.on('add', onAdd); - * - * @callback SimpleStore~addListener - * @param {string} name The name of the associated {@link Mapper}. - * @param {Record|Record[]} The Record or Records that were added. - * @see SimpleStore#event:add - * @see SimpleStore#add - * @see SimpleStore#create - * @see SimpleStore#createMany - * @see SimpleStore#find - * @see SimpleStore#findAll - * @see SimpleStore#update - * @see SimpleStore#updateAll - * @see SimpleStore#updateMany - * @since 3.0.0 - */ - -/** - * Fired when one or more records are removed from the in-memory store. See - * {@link SimpleStore~removeListener} for how to listen for this event. - * - * @event SimpleStore#remove - * @see SimpleStore~removeListener - * @see SimpleStore#event:remove - * @see SimpleStore#clear - * @see SimpleStore#destroy - * @see SimpleStore#destroyAll - * @see SimpleStore#remove - * @see SimpleStore#removeAll - */ - -/** - * Callback signature for the {@link SimpleStore#event:remove} event. - * - * @example - * function onRemove (mapperName, recordsOrRecords) { - * // do something - * } - * store.on('remove', onRemove); - * - * @callback SimpleStore~removeListener - * @param {string} name The name of the associated {@link Mapper}. - * @param {Record|Record[]} Record or Records that were removed. - * @see SimpleStore#event:remove - * @see SimpleStore#clear - * @see SimpleStore#destroy - * @see SimpleStore#destroyAll - * @see SimpleStore#remove - * @see SimpleStore#removeAll - * @since 3.0.0 - */ - -/** - * Create a subclass of this SimpleStore: - * @example SimpleStore.extend - * const JSData = require('js-data'); - * const { SimpleStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * // Extend the class using ES2015 class syntax. - * class CustomSimpleStoreClass extends SimpleStore { - * foo () { return 'bar'; } - * static beep () { return 'boop'; } - * } - * const customSimpleStore = new CustomSimpleStoreClass(); - * console.log(customSimpleStore.foo()); - * console.log(CustomSimpleStoreClass.beep()); - * - * // Extend the class using alternate method. - * const OtherSimpleStoreClass = SimpleStore.extend({ - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }) - * const otherSimpleStore = new OtherSimpleStoreClass(); - * console.log(otherSimpleStore.foo()); - * console.log(OtherSimpleStoreClass.beep()); - * - * // Extend the class, providing a custom constructor. - * function AnotherSimpleStoreClass () { - * SimpleStore.call(this) - * this.created_at = new Date().getTime() - * } - * SimpleStore.extend({ - * constructor: AnotherSimpleStoreClass, - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }) - * const anotherSimpleStore = new AnotherSimpleStoreClass(); - * console.log(anotherSimpleStore.created_at); - * console.log(anotherSimpleStore.foo()); - * console.log(AnotherSimpleStoreClass.beep()); - * - * @method SimpleStore.extend - * @param {object} [props={}] Properties to add to the prototype of the - * subclass. - * @param {object} [props.constructor] Provide a custom constructor function - * to be used as the subclass itself. - * @param {object} [classProps={}] Static properties to add to the subclass. - * @returns {Constructor} Subclass of this SimpleStore class. - * @since 3.0.0 - */ - -var DOMAIN$9 = 'LinkedCollection'; -/** - * Extends {@link Collection}. Used by a {@link DataStore} to implement an - * Identity Map. - * - * ```javascript - * import {LinkedCollection} from 'js-data' - * ``` - * - * @class LinkedCollection - * @extends Collection - * @param {array} [records] Initial set of records to insert into the - * collection. See {@link Collection}. - * @param {object} [opts] Configuration options. See {@link Collection}. - * @returns {Mapper} - */ - -function LinkedCollection(records, opts) { - utils.classCallCheck(this, LinkedCollection); // Make sure this collection has somewhere to store "added" timestamps - - Object.defineProperties(this, { - _added: { - value: {} - }, - datastore: { - writable: true, - value: undefined - } - }); - Collection$1.call(this, records, opts); // Make sure this collection has a reference to a datastore - - if (!this.datastore) { - throw utils.err("new ".concat(DOMAIN$9), 'opts.datastore')(400, 'DataStore', this.datastore); - } -} - -var LinkedCollection$1 = Collection$1.extend({ - constructor: LinkedCollection, - _addMeta: function _addMeta(record, timestamp) { - // Track when this record was added - this._added[this.recordId(record)] = timestamp; - - if (utils.isFunction(record._set)) { - record._set('$', timestamp); - } - }, - _clearMeta: function _clearMeta(record) { - delete this._added[this.recordId(record)]; - - if (utils.isFunction(record._set)) { - record._set('$'); // unset - - } - }, - _onRecordEvent: function _onRecordEvent() { - for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { - args[_key] = arguments[_key]; - } - - Collection$1.prototype._onRecordEvent.apply(this, args); - - var event = args[0]; // This is a very brute force method - // Lots of room for optimization - - if (utils.isString(event) && event.indexOf('change') === 0) { - this.updateIndexes(args[1]); - } - }, - add: function add(records, opts) { - var _this = this; - - var mapper = this.mapper; - var timestamp = new Date().getTime(); - var singular = utils.isObject(records) && !utils.isArray(records); - - if (singular) { - records = [records]; - } - - records = Collection$1.prototype.add.call(this, records, opts); - - if (mapper.relationList.length && records.length) { - // Check the currently visited record for relations that need to be - // inserted into their respective collections. - mapper.relationList.forEach(function (def) { - def.addLinkedRecords(records); - }); - } - - records.forEach(function (record) { - return _this._addMeta(record, timestamp); - }); - return singular ? records[0] : records; - }, - remove: function remove(idOrRecord, opts) { - var mapper = this.mapper; - var record = Collection$1.prototype.remove.call(this, idOrRecord, opts); - - if (record) { - this._clearMeta(record); - } - - if (mapper.relationList.length && record) { - mapper.relationList.forEach(function (def) { - def.removeLinkedRecords(mapper, [record]); - }); - } - - return record; - }, - removeAll: function removeAll(query, opts) { - var mapper = this.mapper; - var records = Collection$1.prototype.removeAll.call(this, query, opts); - records.forEach(this._clearMeta, this); - - if (mapper.relationList.length && records.length) { - mapper.relationList.forEach(function (def) { - def.removeLinkedRecords(mapper, records); - }); - } - - return records; - } -}); -/** - * Create a subclass of this LinkedCollection: - * - * @example LinkedCollection.extend - * const JSData = require('js-data'); - * const { LinkedCollection } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * // Extend the class using ES2015 class syntax. - * class CustomLinkedCollectionClass extends LinkedCollection { - * foo () { return 'bar'; } - * static beep () { return 'boop'; } - * } - * const customLinkedCollection = new CustomLinkedCollectionClass(); - * console.log(customLinkedCollection.foo()); - * console.log(CustomLinkedCollectionClass.beep()); - * - * // Extend the class using alternate method. - * const OtherLinkedCollectionClass = LinkedCollection.extend({ - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }); - * const otherLinkedCollection = new OtherLinkedCollectionClass(); - * console.log(otherLinkedCollection.foo()); - * console.log(OtherLinkedCollectionClass.beep()); - * - * // Extend the class, providing a custom constructor. - * function AnotherLinkedCollectionClass () { - * LinkedCollection.call(this); - * this.created_at = new Date().getTime(); - * } - * LinkedCollection.extend({ - * constructor: AnotherLinkedCollectionClass, - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }); - * const anotherLinkedCollection = new AnotherLinkedCollectionClass(); - * console.log(anotherLinkedCollection.created_at); - * console.log(anotherLinkedCollection.foo()); - * console.log(AnotherLinkedCollectionClass.beep()); - * - * @method LinkedCollection.extend - * @param {object} [props={}] Properties to add to the prototype of the - * subclass. - * @param {object} [props.constructor] Provide a custom constructor function - * to be used as the subclass itself. - * @param {object} [classProps={}] Static properties to add to the subclass. - * @returns {Constructor} Subclass of this LinkedCollection class. - * @since 3.0.0 - */ - -var DATASTORE_DEFAULTS = { - /** - * Whether in-memory relations should be unlinked from records after they are - * destroyed. - * - * @default true - * @name DataStore#unlinkOnDestroy - * @since 3.0.0 - * @type {boolean} - */ - unlinkOnDestroy: true -}; -/** - * The `DataStore` class is an extension of {@link SimpleStore}. Not only does - * `DataStore` manage mappers and store data in collections, it uses the - * {@link LinkedCollection} class to link related records together in memory. - * - * ```javascript - * import { DataStore } from 'js-data'; - * ``` - * - * @example - * import { DataStore } from 'js-data'; - * import HttpAdapter from 'js-data-http'; - * const store = new DataStore(); - * - * // DataStore#defineMapper returns a direct reference to the newly created - * // Mapper. - * const UserMapper = store.defineMapper('user'); - * - * // DataStore#as returns the store scoped to a particular Mapper. - * const UserStore = store.as('user'); - * - * // Call "find" on "UserMapper" (Stateless ORM) - * UserMapper.find(1).then((user) => { - * // retrieved a "user" record via the http adapter, but that's it - * - * // Call "find" on "store" targeting "user" (Stateful DataStore) - * return store.find('user', 1); // same as "UserStore.find(1)" - * }).then((user) => { - * // not only was a "user" record retrieved, but it was added to the - * // store's "user" collection - * const cachedUser = store.getCollection('user').get(1); - * console.log(user === cachedUser); // true - * }); - * - * @class DataStore - * @extends SimpleStore - * @param {object} [opts] Configuration options. See {@link SimpleStore}. - * @param {boolean} [opts.collectionClass={@link LinkedCollection}] See {@link DataStore#collectionClass}. - * @param {boolean} [opts.debug=false] See {@link Component#debug}. - * @param {boolean} [opts.unlinkOnDestroy=true] See {@link DataStore#unlinkOnDestroy}. - * @param {boolean|Function} [opts.usePendingFind=true] See {@link DataStore#usePendingFind}. - * @param {boolean|Function} [opts.usePendingFindAll=true] See {@link DataStore#usePendingFindAll}. - * @returns {DataStore} - * @see SimpleStore - * @since 3.0.0 - * @tutorial ["http://www.js-data.io/v3.0/docs/components-of-jsdata#datastore","Components of JSData: DataStore"] - * @tutorial ["http://www.js-data.io/v3.0/docs/working-with-the-datastore","Working with the DataStore"] - * @tutorial ["http://www.js-data.io/v3.0/docs/jsdata-and-the-browser","Notes on using JSData in the Browser"] - */ - -function DataStore(opts) { - utils.classCallCheck(this, DataStore); - opts || (opts = {}); // Fill in any missing options with the defaults - - utils.fillIn(opts, DATASTORE_DEFAULTS); - opts.collectionClass || (opts.collectionClass = LinkedCollection$1); - SimpleStore$1.call(this, opts); -} - -var props$2 = { - constructor: DataStore, - defineMapper: function defineMapper(name, opts) { - // Complexity of this method is beyond simply using => functions to bind context - var self = this; - var mapper = SimpleStore$1.prototype.defineMapper.call(self, name, opts); - var idAttribute = mapper.idAttribute; - var collection = this.getCollection(name); - mapper.relationList.forEach(function (def) { - var relation = def.relation; - var localField = def.localField; - var path = "links.".concat(localField); - var foreignKey = def.foreignKey; - var type = def.type; - var updateOpts = { - index: foreignKey - }; - var descriptor; - - var getter = function getter() { - return this._get(path); - }; - - if (type === belongsToType) { - if (!collection.indexes[foreignKey]) { - collection.createIndex(foreignKey); - } - - descriptor = { - get: getter, - // e.g. profile.user = someUser - // or comment.post = somePost - set: function set(record) { - // e.g. const otherUser = profile.user - var currentParent = this._get(path); // e.g. profile.user === someUser - - - if (record === currentParent) { - return currentParent; - } - - var id = utils.get(this, idAttribute); - var inverseDef = def.getInverse(mapper); // e.g. profile.user !== someUser - // or comment.post !== somePost - - if (currentParent && inverseDef) { - this.removeInverseRelation(currentParent, id, inverseDef, idAttribute); - } - - if (record) { - // e.g. profile.user = someUser - var relatedIdAttribute = def.getRelation().idAttribute; - var relatedId = utils.get(record, relatedIdAttribute); // Prefer store record - - if (relatedId !== undefined && this._get('$')) { - record = self.get(relation, relatedId) || record; - } // Set locals - // e.g. profile.user = someUser - // or comment.post = somePost - - - safeSetLink(this, localField, record); - safeSetProp(this, foreignKey, relatedId); - collection.updateIndex(this, updateOpts); - - if (inverseDef) { - this.setupInverseRelation(record, id, inverseDef, idAttribute); - } - } else { - // Unset in-memory link only - // e.g. profile.user = undefined - // or comment.post = undefined - safeSetLink(this, localField, undefined); - } - - return record; - } - }; - var foreignKeyDescriptor = Object.getOwnPropertyDescriptor(mapper.recordClass.prototype, foreignKey); - - if (!foreignKeyDescriptor) { - foreignKeyDescriptor = { - enumerable: true - }; - } - - var originalGet = foreignKeyDescriptor.get; - - foreignKeyDescriptor.get = function () { - if (originalGet) { - return originalGet.call(this); - } - - return this._get("props.".concat(foreignKey)); - }; - - var originalSet = foreignKeyDescriptor.set; - - foreignKeyDescriptor.set = function (value) { - var _this = this; - - if (originalSet) { - originalSet.call(this, value); - } - - var currentParent = utils.get(this, localField); - var id = utils.get(this, idAttribute); - var inverseDef = def.getInverse(mapper); - var currentParentId = currentParent ? utils.get(currentParent, def.getRelation().idAttribute) : undefined; - - if (inverseDef && currentParent && currentParentId !== undefined && currentParentId !== value) { - if (inverseDef.type === hasOneType) { - safeSetLink(currentParent, inverseDef.localField, undefined); - } else if (inverseDef.type === hasManyType) { - var children = utils.get(currentParent, inverseDef.localField); - - if (id === undefined) { - utils.remove(children, function (child) { - return child === _this; - }); - } else { - utils.remove(children, function (child) { - return child === _this || id === utils.get(child, idAttribute); - }); - } - } - } - - safeSetProp(this, foreignKey, value); - collection.updateIndex(this, updateOpts); - - if (value === undefined || value === null) { - if (currentParentId !== undefined) { - // Unset locals - utils.set(this, localField, undefined); - } - } else if (this._get('$')) { - var storeRecord = self.get(relation, value); - - if (storeRecord) { - utils.set(this, localField, storeRecord); - } - } - }; - - Object.defineProperty(mapper.recordClass.prototype, foreignKey, foreignKeyDescriptor); - } else if (type === hasManyType) { - var localKeys = def.localKeys; - var foreignKeys = def.foreignKeys; // TODO: Handle case when belongsTo relation isn't ever defined - - if (self._collections[relation] && foreignKey && !self.getCollection(relation).indexes[foreignKey]) { - self.getCollection(relation).createIndex(foreignKey); - } - - descriptor = { - get: function get() { - var current = getter.call(this); - - if (!current) { - this._set(path, []); - } - - return getter.call(this); - }, - // e.g. post.comments = someComments - // or user.groups = someGroups - // or group.users = someUsers - set: function set(records) { - var _this2 = this; - - if (records && !utils.isArray(records)) { - records = [records]; - } - - var id = utils.get(this, idAttribute); - var relatedIdAttribute = def.getRelation().idAttribute; - var inverseDef = def.getInverse(mapper); - var inverseLocalField = inverseDef.localField; - var current = this._get(path) || []; - var toLink = []; - var toLinkIds = {}; - - if (records) { - records.forEach(function (record) { - // e.g. comment.id - var relatedId = utils.get(record, relatedIdAttribute); - var currentParent = utils.get(record, inverseLocalField); - - if (currentParent && currentParent !== _this2) { - var currentChildrenOfParent = utils.get(currentParent, localField); // e.g. somePost.comments.remove(comment) - - if (relatedId === undefined) { - utils.remove(currentChildrenOfParent, function (child) { - return child === record; - }); - } else { - utils.remove(currentChildrenOfParent, function (child) { - return child === record || relatedId === utils.get(child, relatedIdAttribute); - }); - } - } - - if (relatedId !== undefined) { - if (_this2._get('$')) { - // Prefer store record - record = self.get(relation, relatedId) || record; - } // e.g. toLinkIds[comment.id] = comment - - - toLinkIds[relatedId] = record; - } - - toLink.push(record); - }); - } // e.g. post.comments = someComments - - - if (foreignKey) { - current.forEach(function (record) { - // e.g. comment.id - var relatedId = utils.get(record, relatedIdAttribute); - - if (relatedId === undefined && toLink.indexOf(record) === -1 || relatedId !== undefined && !(relatedId in toLinkIds)) { - // Update (unset) inverse relation - if (records) { - // e.g. comment.post_id = undefined - safeSetProp(record, foreignKey, undefined); // e.g. CommentCollection.updateIndex(comment, { index: 'post_id' }) - - self.getCollection(relation).updateIndex(record, updateOpts); - } // e.g. comment.post = undefined - - - safeSetLink(record, inverseLocalField, undefined); - } - }); - toLink.forEach(function (record) { - // Update (set) inverse relation - // e.g. comment.post_id = post.id - safeSetProp(record, foreignKey, id); // e.g. CommentCollection.updateIndex(comment, { index: 'post_id' }) - - self.getCollection(relation).updateIndex(record, updateOpts); // e.g. comment.post = post - - safeSetLink(record, inverseLocalField, _this2); - }); - } else if (localKeys) { - // Update locals - // e.g. group.users = someUsers - // Update (set) inverse relation - var ids = toLink.map(function (child) { - return utils.get(child, relatedIdAttribute); - }).filter(function (id) { - return id !== undefined; - }); // e.g. group.user_ids = [1,2,3,...] - - utils.set(this, localKeys, ids); // Update (unset) inverse relation - - if (inverseDef.foreignKeys) { - current.forEach(function (child) { - var relatedId = utils.get(child, relatedIdAttribute); - - if (relatedId === undefined && toLink.indexOf(child) === -1 || relatedId !== undefined && !(relatedId in toLinkIds)) { - // Update inverse relation - // safeSetLink(child, inverseLocalField, undefined) - var parents = utils.get(child, inverseLocalField) || []; // e.g. someUser.groups.remove(group) - - if (id === undefined) { - utils.remove(parents, function (parent) { - return parent === _this2; - }); - } else { - utils.remove(parents, function (parent) { - return parent === _this2 || id === utils.get(parent, idAttribute); - }); - } - } - }); - toLink.forEach(function (child) { - // Update (set) inverse relation - var parents = utils.get(child, inverseLocalField); // e.g. someUser.groups.push(group) - - if (id === undefined) { - utils.noDupeAdd(parents, _this2, function (parent) { - return parent === _this2; - }); - } else { - utils.noDupeAdd(parents, _this2, function (parent) { - return parent === _this2 || id === utils.get(parent, idAttribute); - }); - } - }); - } - } else if (foreignKeys) { - // e.g. user.groups = someGroups - // Update (unset) inverse relation - current.forEach(function (parent) { - var ids = utils.get(parent, foreignKeys) || []; // e.g. someGroup.user_ids.remove(user.id) - - utils.remove(ids, function (_key) { - return id === _key; - }); - var children = utils.get(parent, inverseLocalField); // e.g. someGroup.users.remove(user) - - if (id === undefined) { - utils.remove(children, function (child) { - return child === _this2; - }); - } else { - utils.remove(children, function (child) { - return child === _this2 || id === utils.get(child, idAttribute); - }); - } - }); // Update (set) inverse relation - - toLink.forEach(function (parent) { - var ids = utils.get(parent, foreignKeys) || []; - utils.noDupeAdd(ids, id, function (_key) { - return id === _key; - }); - var children = utils.get(parent, inverseLocalField); - - if (id === undefined) { - utils.noDupeAdd(children, _this2, function (child) { - return child === _this2; - }); - } else { - utils.noDupeAdd(children, _this2, function (child) { - return child === _this2 || id === utils.get(child, idAttribute); - }); - } - }); - } - - this._set(path, toLink); - - return toLink; - } - }; - } else if (type === hasOneType) { - // TODO: Handle case when belongsTo relation isn't ever defined - if (self._collections[relation] && foreignKey && !self.getCollection(relation).indexes[foreignKey]) { - self.getCollection(relation).createIndex(foreignKey); - } - - descriptor = { - get: getter, - // e.g. user.profile = someProfile - set: function set(record) { - var current = this._get(path); - - if (record === current) { - return current; - } - - var inverseLocalField = def.getInverse(mapper).localField; // Update (unset) inverse relation - - if (current) { - safeSetProp(current, foreignKey, undefined); - self.getCollection(relation).updateIndex(current, updateOpts); - safeSetLink(current, inverseLocalField, undefined); - } - - if (record) { - var relatedId = utils.get(record, def.getRelation().idAttribute); // Prefer store record - - if (relatedId !== undefined) { - record = self.get(relation, relatedId) || record; - } // Set locals - - - safeSetLink(this, localField, record); // Update (set) inverse relation - - safeSetProp(record, foreignKey, utils.get(this, idAttribute)); - self.getCollection(relation).updateIndex(record, updateOpts); - safeSetLink(record, inverseLocalField, this); - } else { - // Unset locals - safeSetLink(this, localField, undefined); - } - - return record; - } - }; - } - - if (descriptor) { - descriptor.enumerable = def.enumerable === undefined ? false : def.enumerable; - - if (def.get) { - var origGet = descriptor.get; - - descriptor.get = function () { - var _this3 = this; - - return def.get(def, this, function () { - for (var _len = arguments.length, args = new Array(_len), _key2 = 0; _key2 < _len; _key2++) { - args[_key2] = arguments[_key2]; - } - - return origGet.apply(_this3, args); - }); - }; - } - - if (def.set) { - var origSet = descriptor.set; - - descriptor.set = function (related) { - var _this4 = this; - - return def.set(def, this, related, function (value) { - return origSet.call(_this4, value === undefined ? related : value); - }); - }; - } - - Object.defineProperty(mapper.recordClass.prototype, localField, descriptor); - } - }); - return mapper; - }, - destroy: function destroy(name, id, opts) { - var _this5 = this; - - opts || (opts = {}); - return SimpleStore$1.prototype.destroy.call(this, name, id, opts).then(function (result) { - var record; - - if (opts.raw) { - record = result.data; - } else { - record = result; - } - - if (record && _this5.unlinkOnDestroy) { - var _opts = utils.plainCopy(opts); - - _opts.withAll = true; - utils.forEachRelation(_this5.getMapper(name), _opts, function (def) { - utils.set(record, def.localField, undefined); - }); - } - - return result; - }); - }, - destroyAll: function destroyAll(name, query, opts) { - var _this6 = this; - - opts || (opts = {}); - return SimpleStore$1.prototype.destroyAll.call(this, name, query, opts).then(function (result) { - var records; - - if (opts.raw) { - records = result.data; - } else { - records = result; - } - - if (records && records.length && _this6.unlinkOnDestroy) { - var _opts = utils.plainCopy(opts); - - _opts.withAll = true; - utils.forEachRelation(_this6.getMapper(name), _opts, function (def) { - records.forEach(function (record) { - utils.set(record, def.localField, undefined); - }); - }); - } - - return result; - }); - } -}; -var DataStore$1 = SimpleStore$1.extend(props$2); -/** - * Create a subclass of this DataStore: - * @example DataStore.extend - * const JSData = require('js-data'); - * const { DataStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * // Extend the class using ES2015 class syntax. - * class CustomDataStoreClass extends DataStore { - * foo () { return 'bar'; } - * static beep () { return 'boop'; } - * } - * const customDataStore = new CustomDataStoreClass(); - * console.log(customDataStore.foo()); - * console.log(CustomDataStoreClass.beep()); - * - * // Extend the class using alternate method. - * const OtherDataStoreClass = DataStore.extend({ - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }); - * const otherDataStore = new OtherDataStoreClass(); - * console.log(otherDataStore.foo()); - * console.log(OtherDataStoreClass.beep()); - * - * // Extend the class, providing a custom constructor. - * function AnotherDataStoreClass () { - * DataStore.call(this); - * this.created_at = new Date().getTime(); - * } - * DataStore.extend({ - * constructor: AnotherDataStoreClass, - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }); - * const anotherDataStore = new AnotherDataStoreClass(); - * console.log(anotherDataStore.created_at); - * console.log(anotherDataStore.foo()); - * console.log(AnotherDataStoreClass.beep()); - * - * @method DataStore.extend - * @param {object} [props={}] Properties to add to the prototype of the - * subclass. - * @param {object} [props.constructor] Provide a custom constructor function - * to be used as the subclass itself. - * @param {object} [classProps={}] Static properties to add to the subclass. - * @returns {Constructor} Subclass of this DataStore class. - * @since 3.0.0 - */ - -/** - * Registered as `js-data` in NPM and Bower. - * - * Also available from CDN.JS and JSDelivr. - * - * @module js-data - * - * @example Install from NPM - * npm i --save js-data@beta - * @example Install from Bower - * bower i --save js-data@3.0.0-beta.1 - * @example Install from CDN.JS - * - * @example Install from JSDelivr - * - * @example Load into your app via script tag - * - * - * @example Load into your app via CommonJS - * var JSData = require('js-data'); - * @example Load into your app via ES2015 Modules - * import * as JSData from 'js-data'; - * @example Load into your app via AMD - * define('myApp', ['js-data'], function (JSData) { ... }); - */ -/** - * Describes the version of this `JSData` object. - * - * @example - * console.log(JSData.version.full); // "3.0.0-beta.1" - * - * @name version - * @memberof module:js-data - * @property {string} full The full semver value. - * @property {number} major The major version number. - * @property {number} minor The minor version number. - * @property {number} patch The patch version number. - * @property {(string|boolean)} alpha The alpha version value, otherwise `false` - * if the current version is not alpha. - * @property {(string|boolean)} beta The beta version value, otherwise `false` - * if the current version is not beta. - * @since 2.0.0 - * @type {Object} - */ - -var version = { - full: '3.0.6', - major: 3, +/** + * Registered as `js-data` in NPM. + * + * @example Install from NPM + * npm i --save js-data + * @example Install from NPM + * yarn add js-data + * @example Load into your app via CommonJS + * var JSData = require('js-data'); + * @example Load into your app via ES2015 Modules + * import * as JSData from 'js-data'; + */ +/** + * Describes the version of this `JSData` object. + * + * @example + * console.log(JSData.version.full); // "3.0.0-beta.1" + * + * @name version + * @memberof module:js-data + * @property {string} full The full semver value. + * @property {number} major The major version number. + * @property {number} minor The minor version number. + * @property {number} patch The patch version number. + * @property {(string|boolean)} alpha The alpha version value, otherwise `false` + * if the current version is not alpha. + * @property {(string|boolean)} beta The beta version value, otherwise `false` + * if the current version is not beta. + * @since 2.0.0 + * @type {Object} + */ +const version = { + beta: 4, + full: '4.0.0-beta.4', + major: 4, minor: 0, - patch: 6 + patch: 0 }; -export { Collection$1 as Collection, Component$1 as Component, Container, DataStore$1 as DataStore, Index, LinkedCollection$1 as LinkedCollection, Mapper$1 as Mapper, Query$1 as Query, Record$1 as Record, Schema$1 as Schema, Settable, SimpleStore$1 as SimpleStore, belongsTo, belongsToType, hasMany, hasManyType, hasOne, hasOneType, utils, version }; +export { Collection, Component, Container, DataStore, Index, LinkedCollection, Mapper, Query, Record, Schema, Settable, SimpleStore, belongsTo, belongsToType, hasMany, hasManyType, hasOne, hasOneType, utils, version }; //# sourceMappingURL=js-data.es2015.js.map diff --git a/dist/js-data.es2015.js.map b/dist/js-data.es2015.js.map index c63187fb..27050b50 100644 --- a/dist/js-data.es2015.js.map +++ b/dist/js-data.es2015.js.map @@ -1 +1 @@ -{"version":3,"file":"js-data.es2015.js","sources":["../src/utils.js","../src/Settable.js","../src/Component.js","../src/Query.js","../src/Relation.js","../src/Relation/BelongsTo.js","../src/Relation/HasMany.js","../src/Relation/HasOne.js","../src/relations.js","../src/decorators.js","../src/Record.js","../lib/mindex/_utils.js","../lib/mindex/index.js","../src/Collection.js","../src/Schema.js","../src/Mapper.js","../src/Container.js","../src/SimpleStore.js","../src/LinkedCollection.js","../src/DataStore.js","../src/index.js"],"sourcesContent":["/**\n * Utility methods used by JSData.\n *\n * @example\n * import { utils } from 'js-data';\n * console.log(utils.isString('foo')); // true\n *\n * @namespace utils\n * @type {Object}\n */\n\nconst DOMAIN = 'utils'\n\nconst INFINITY = 1 / 0\nconst MAX_INTEGER = 1.7976931348623157e308\nconst BOOL_TAG = '[object Boolean]'\nconst DATE_TAG = '[object Date]'\nconst FUNC_TAG = '[object Function]'\nconst NUMBER_TAG = '[object Number]'\nconst OBJECT_TAG = '[object Object]'\nconst REGEXP_TAG = '[object RegExp]'\nconst STRING_TAG = '[object String]'\nconst objToString = Object.prototype.toString\nconst PATH = /^(.+)\\.(.+)$/\n\nconst ERRORS = {\n '400' () {\n return `expected: ${arguments[0]}, found: ${\n arguments[2] ? arguments[1] : typeof arguments[1]\n }`\n },\n '404' () {\n return `${arguments[0]} not found`\n }\n}\n\nconst toInteger = function (value) {\n if (!value) {\n return 0\n }\n // Coerce to number\n value = +value\n if (value === INFINITY || value === -INFINITY) {\n const sign = value < 0 ? -1 : 1\n return sign * MAX_INTEGER\n }\n const remainder = value % 1\n return value === value ? (remainder ? value - remainder : value) : 0 // eslint-disable-line\n}\n\nconst toStr = function (value) {\n return objToString.call(value)\n}\n\nconst isPlainObject = function (value) {\n return !!value && typeof value === 'object' && value.constructor === Object\n}\n\nconst mkdirP = function (object, path) {\n if (!path) {\n return object\n }\n const parts = path.split('.')\n parts.forEach(function (key) {\n if (!object[key]) {\n object[key] = {}\n }\n object = object[key]\n })\n return object\n}\n\nconst utils = {\n /**\n * Reference to the Promise constructor used by JSData. Defaults to\n * `window.Promise` or `global.Promise`.\n *\n * @example Make JSData use a different `Promise` constructor\n * import Promise from 'bluebird';\n * import { utils } from 'js-data';\n * utils.Promise = Promise;\n *\n * @name utils.Promise\n * @since 3.0.0\n * @type {Function}\n */\n Promise: Promise,\n\n /**\n * Shallow copy properties that meet the following criteria from `src` to\n * `dest`:\n *\n * - own enumerable\n * - not a function\n * - does not start with \"_\"\n *\n * @method utils._\n * @param {object} dest Destination object.\n * @param {object} src Source object.\n * @private\n * @since 3.0.0\n */\n _ (dest, src) {\n utils.forOwn(src, function (value, key) {\n if (\n key &&\n dest[key] === undefined &&\n !utils.isFunction(value) &&\n key.indexOf('_') !== 0\n ) {\n dest[key] = value\n }\n })\n },\n\n /**\n * Recursively iterates over relations found in `opts.with`.\n *\n * @method utils._forRelation\n * @param {object} opts Configuration options.\n * @param {Relation} def Relation definition.\n * @param {Function} fn Callback function.\n * @param {*} [thisArg] Execution context for the callback function.\n * @private\n * @since 3.0.0\n */\n _forRelation (opts, def, fn, thisArg) {\n const relationName = def.relation\n let containedName = null\n let index\n opts || (opts = {})\n opts.with || (opts.with = [])\n\n if ((index = utils._getIndex(opts.with, relationName)) >= 0) {\n containedName = relationName\n } else if ((index = utils._getIndex(opts.with, def.localField)) >= 0) {\n containedName = def.localField\n }\n\n if (opts.withAll) {\n fn.call(thisArg, def, {})\n return\n } else if (!containedName) {\n return\n }\n const optsCopy = {}\n utils.fillIn(optsCopy, def.getRelation())\n utils.fillIn(optsCopy, opts)\n optsCopy.with = opts.with.slice()\n optsCopy._activeWith = optsCopy.with.splice(index, 1)[0]\n optsCopy.with.forEach(function (relation, i) {\n if (\n relation &&\n relation.indexOf(containedName) === 0 &&\n relation.length >= containedName.length &&\n relation[containedName.length] === '.'\n ) {\n optsCopy.with[i] = relation.substr(containedName.length + 1)\n } else {\n optsCopy.with[i] = ''\n }\n })\n fn.call(thisArg, def, optsCopy)\n },\n\n /**\n * Find the index of a relation in the given list\n *\n * @method utils._getIndex\n * @param {string[]} list List to search.\n * @param {string} relation Relation to find.\n * @private\n * @returns {number}\n */\n _getIndex (list, relation) {\n let index = -1\n list.forEach(function (_relation, i) {\n if (_relation === relation) {\n index = i\n return false\n } else if (utils.isObject(_relation)) {\n if (_relation.relation === relation) {\n index = i\n return false\n }\n }\n })\n return index\n },\n\n /**\n * Define hidden (non-enumerable), writable properties on `target` from the\n * provided `props`.\n *\n * @example\n * import { utils } from 'js-data';\n * function Cat () {}\n * utils.addHiddenPropsToTarget(Cat.prototype, {\n * say () {\n * console.log('meow');\n * }\n * });\n * const cat = new Cat();\n * cat.say(); // \"meow\"\n *\n * @method utils.addHiddenPropsToTarget\n * @param {object} target That to which `props` should be added.\n * @param {object} props Properties to be added to `target`.\n * @since 3.0.0\n */\n addHiddenPropsToTarget (target, props) {\n const map = {}\n Object.keys(props).forEach(function (propName) {\n const descriptor = Object.getOwnPropertyDescriptor(props, propName)\n\n descriptor.enumerable = false\n map[propName] = descriptor\n })\n Object.defineProperties(target, map)\n },\n\n /**\n * Return whether the two objects are deeply different.\n *\n * @example\n * import { utils } from 'js-data';\n * utils.areDifferent({}, {}); // false\n * utils.areDifferent({ a: 1 }, { a: 1 }); // false\n * utils.areDifferent({ foo: 'bar' }, {}); // true\n *\n * @method utils.areDifferent\n * @param {object} a Base object.\n * @param {object} b Comparison object.\n * @param {object} [opts] Configuration options.\n * @param {Function} [opts.equalsFn={@link utils.deepEqual}] Equality function.\n * @param {array} [opts.ignore=[]] Array of strings or RegExp of fields to ignore.\n * @returns {boolean} Whether the two objects are deeply different.\n * @see utils.diffObjects\n * @since 3.0.0\n */\n areDifferent (newObject, oldObject, opts) {\n opts || (opts = {})\n const diff = utils.diffObjects(newObject, oldObject, opts)\n const diffCount =\n Object.keys(diff.added).length +\n Object.keys(diff.removed).length +\n Object.keys(diff.changed).length\n return diffCount > 0\n },\n\n /**\n * Verified that the given constructor is being invoked via `new`, as opposed\n * to just being called like a normal function.\n *\n * @example\n * import { utils } from 'js-data';\n * function Cat () {\n * utils.classCallCheck(this, Cat);\n * }\n * const cat = new Cat(); // this is ok\n * Cat(); // this throws an error\n *\n * @method utils.classCallCheck\n * @param {*} instance Instance that is being constructed.\n * @param {Constructor} ctor Constructor function used to construct the\n * instance.\n * @since 3.0.0\n * @throws {Error} Throws an error if the constructor is being improperly\n * invoked.\n */\n classCallCheck (instance, ctor) {\n if (!(instance instanceof ctor)) {\n throw utils.err(`${ctor.name}`)(500, 'Cannot call a class as a function')\n }\n },\n\n /**\n * Deep copy a value.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = { foo: { bar: 'baz' } };\n * const b = utils.copy(a);\n * a === b; // false\n * utils.areDifferent(a, b); // false\n *\n * @param {*} from Value to deep copy.\n * @param {*} [to] Destination object for the copy operation.\n * @param {*} [stackFrom] For internal use.\n * @param {*} [stackTo] For internal use.\n * @param {string[]|RegExp[]} [blacklist] List of strings or RegExp of\n * properties to skip.\n * @param {boolean} [plain] Whether to make a plain copy (don't try to use\n * original prototype).\n * @returns {*} Deep copy of `from`.\n * @since 3.0.0\n */\n copy (from, to, stackFrom, stackTo, blacklist, plain) {\n if (!to) {\n to = from\n if (from) {\n if (utils.isArray(from)) {\n to = utils.copy(from, [], stackFrom, stackTo, blacklist, plain)\n } else if (utils.isDate(from)) {\n to = new Date(from.getTime())\n } else if (utils.isRegExp(from)) {\n to = new RegExp(from.source, from.toString().match(/[^/]*$/)[0])\n to.lastIndex = from.lastIndex\n } else if (utils.isObject(from)) {\n if (plain) {\n to = utils.copy(from, {}, stackFrom, stackTo, blacklist, plain)\n } else {\n to = utils.copy(\n from,\n Object.create(Object.getPrototypeOf(from)),\n stackFrom,\n stackTo,\n blacklist,\n plain\n )\n }\n }\n }\n } else {\n if (from === to) {\n throw utils.err(`${DOMAIN}.copy`)(\n 500,\n 'Cannot copy! Source and destination are identical.'\n )\n }\n\n stackFrom = stackFrom || []\n stackTo = stackTo || []\n\n if (utils.isObject(from)) {\n const index = stackFrom.indexOf(from)\n if (index !== -1) {\n return stackTo[index]\n }\n\n stackFrom.push(from)\n stackTo.push(to)\n }\n\n let result\n if (utils.isArray(from)) {\n let i\n to.length = 0\n for (i = 0; i < from.length; i++) {\n result = utils.copy(\n from[i],\n null,\n stackFrom,\n stackTo,\n blacklist,\n plain\n )\n if (utils.isObject(from[i])) {\n stackFrom.push(from[i])\n stackTo.push(result)\n }\n to.push(result)\n }\n } else {\n if (utils.isArray(to)) {\n to.length = 0\n } else {\n utils.forOwn(to, function (value, key) {\n delete to[key]\n })\n }\n for (var key in from) {\n if (Object.hasOwnProperty.call(from, key)) {\n if (utils.isBlacklisted(key, blacklist)) {\n continue\n }\n result = utils.copy(\n from[key],\n null,\n stackFrom,\n stackTo,\n blacklist,\n plain\n )\n if (utils.isObject(from[key])) {\n stackFrom.push(from[key])\n stackTo.push(result)\n }\n to[key] = result\n }\n }\n }\n }\n return to\n },\n\n /**\n * Recursively shallow fill in own enumerable properties from `source` to\n * `dest`.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = { foo: { bar: 'baz' }, beep: 'boop' };\n * const b = { beep: 'bip' };\n * utils.deepFillIn(b, a);\n * console.log(b); // {\"foo\":{\"bar\":\"baz\"},\"beep\":\"bip\"}\n *\n * @method utils.deepFillIn\n * @param {object} dest The destination object.\n * @param {object} source The source object.\n * @see utils.fillIn\n * @see utils.deepMixIn\n * @since 3.0.0\n */\n deepFillIn (dest, source) {\n if (source) {\n utils.forOwn(source, function (value, key) {\n const existing = dest[key]\n if (isPlainObject(value) && isPlainObject(existing)) {\n utils.deepFillIn(existing, value)\n } else if (!Object.hasOwnProperty.call(dest, key) || dest[key] === undefined) {\n dest[key] = value\n }\n })\n }\n return dest\n },\n\n /**\n * Recursively shallow copy enumerable properties from `source` to `dest`.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = { foo: { bar: 'baz' }, beep: 'boop' };\n * const b = { beep: 'bip' };\n * utils.deepFillIn(b, a);\n * console.log(b); // {\"foo\":{\"bar\":\"baz\"},\"beep\":\"boop\"}\n *\n * @method utils.deepMixIn\n * @param {object} dest The destination object.\n * @param {object} source The source object.\n * @see utils.fillIn\n * @see utils.deepFillIn\n * @since 3.0.0\n */\n deepMixIn (dest, source) {\n if (source) {\n for (var key in source) {\n const value = source[key]\n const existing = dest[key]\n if (isPlainObject(value) && isPlainObject(existing)) {\n utils.deepMixIn(existing, value)\n } else {\n dest[key] = value\n }\n }\n }\n return dest\n },\n\n /**\n * Return a diff of the base object to the comparison object.\n *\n * @example\n * import { utils } from 'js-data';\n * const oldObject = { foo: 'bar', a: 1234 };\n * const newObject = { beep: 'boop', a: 5678 };\n * const diff = utils.diffObjects(oldObject, newObject);\n * console.log(diff.added); // {\"beep\":\"boop\"}\n * console.log(diff.changed); // {\"a\":5678}\n * console.log(diff.removed); // {\"foo\":undefined}\n *\n * @method utils.diffObjects\n * @param {object} newObject Comparison object.\n * @param {object} oldObject Base object.\n * @param {object} [opts] Configuration options.\n * @param {Function} [opts.equalsFn={@link utils.deepEqual}] Equality function.\n * @param {array} [opts.ignore=[]] Array of strings or RegExp of fields to ignore.\n * @returns {Object} The diff from the base object to the comparison object.\n * @see utils.areDifferent\n * @since 3.0.0\n */\n diffObjects (newObject, oldObject, opts) {\n opts || (opts = {})\n let equalsFn = opts.equalsFn\n const blacklist = opts.ignore\n const diff = {\n added: {},\n changed: {},\n removed: {}\n }\n if (!utils.isFunction(equalsFn)) {\n equalsFn = utils.deepEqual\n }\n\n const newKeys = Object.keys(newObject).filter(function (key) {\n return !utils.isBlacklisted(key, blacklist)\n })\n const oldKeys = Object.keys(oldObject).filter(function (key) {\n return !utils.isBlacklisted(key, blacklist)\n })\n\n // Check for properties that were added or changed\n newKeys.forEach(function (key) {\n const oldValue = oldObject[key]\n const newValue = newObject[key]\n if (equalsFn(oldValue, newValue)) {\n return\n }\n if (oldValue === undefined) {\n diff.added[key] = newValue\n } else {\n diff.changed[key] = newValue\n }\n })\n\n // Check for properties that were removed\n oldKeys.forEach(function (key) {\n const oldValue = oldObject[key]\n const newValue = newObject[key]\n if (newValue === undefined && oldValue !== undefined) {\n diff.removed[key] = undefined\n }\n })\n\n return diff\n },\n\n /**\n * Return whether the two values are equal according to the `==` operator.\n *\n * @example\n * import { utils } from 'js-data';\n * console.log(utils.equal(1,1)); // true\n * console.log(utils.equal(1,'1')); // true\n * console.log(utils.equal(93, 66)); // false\n *\n * @method utils.equal\n * @param {*} a First value in the comparison.\n * @param {*} b Second value in the comparison.\n * @returns {boolean} Whether the two values are equal according to `==`.\n * @since 3.0.0\n */\n equal (a, b) {\n return a == b // eslint-disable-line\n },\n\n /**\n * Produce a factory function for making Error objects with the provided\n * metadata. Used throughout the various js-data components.\n *\n * @example\n * import { utils } from 'js-data';\n * const errorFactory = utils.err('domain', 'target');\n * const error400 = errorFactory(400, 'expected type', 'actual type');\n * console.log(error400); // [Error: [domain:target] expected: expected type, found: string\nhttp://www.js-data.io/v3.0/docs/errors#400]\n * @method utils.err\n * @param {string} domain Namespace.\n * @param {string} target Target.\n * @returns {Function} Factory function.\n * @since 3.0.0\n */\n err (domain, target) {\n return function (code) {\n const prefix = `[${domain}:${target}] `\n let message = ERRORS[code].apply(\n null,\n Array.prototype.slice.call(arguments, 1)\n )\n message = `${prefix}${message}\nhttp://www.js-data.io/v3.0/docs/errors#${code}`\n return new Error(message)\n }\n },\n\n /**\n * Add eventing capabilities into the target object.\n *\n * @example\n * import { utils } from 'js-data';\n * const user = { name: 'John' };\n * utils.eventify(user);\n * user.on('foo', () => console.log(arguments));\n * user.emit('foo', 1, 'bar'); // should log to console values (1, \"bar\")\n *\n * @method utils.eventify\n * @param {object} target Target object.\n * @param {Function} [getter] Custom getter for retrieving the object's event\n * listeners.\n * @param {Function} [setter] Custom setter for setting the object's event\n * listeners.\n * @since 3.0.0\n */\n eventify (target, getter, setter) {\n target = target || this\n let _events = {}\n if (!getter && !setter) {\n getter = function () {\n return _events\n }\n setter = function (value) {\n _events = value\n }\n }\n Object.defineProperties(target, {\n emit: {\n value (...args) {\n const events = getter.call(this) || {}\n const type = args.shift()\n let listeners = events[type] || []\n let i\n for (i = 0; i < listeners.length; i++) {\n listeners[i].f.apply(listeners[i].c, args)\n }\n listeners = events.all || []\n args.unshift(type)\n for (i = 0; i < listeners.length; i++) {\n listeners[i].f.apply(listeners[i].c, args)\n }\n }\n },\n off: {\n value (type, func) {\n const events = getter.call(this)\n const listeners = events[type]\n if (!listeners) {\n setter.call(this, {})\n } else if (func) {\n for (let i = 0; i < listeners.length; i++) {\n if (listeners[i].f === func) {\n listeners.splice(i, 1)\n break\n }\n }\n } else {\n listeners.splice(0, listeners.length)\n }\n }\n },\n on: {\n value (type, func, thisArg) {\n if (!getter.call(this)) {\n setter.call(this, {})\n }\n const events = getter.call(this)\n events[type] = events[type] || []\n events[type].push({\n c: thisArg,\n f: func\n })\n }\n }\n })\n },\n\n /**\n * Used for sublcassing. Invoke this method in the context of a superclass to\n * to produce a subclass based on `props` and `classProps`.\n *\n * @example\n * import { utils } from 'js-data';\n * function Animal () {}\n * Animal.extend = utils.extend;\n * const Cat = Animal.extend({\n * say () {\n * console.log('meow');\n * }\n * });\n * const cat = new Cat();\n * cat instanceof Animal; // true\n * cat instanceof Cat; // true\n * cat.say(); // \"meow\"\n *\n * @method utils.extend\n * @param {object} props Instance properties for the subclass.\n * @param {object} [props.constructor] Provide a custom constructor function\n * to use as the subclass.\n * @param {object} props Static properties for the subclass.\n * @returns {Constructor} A new subclass.\n * @since 3.0.0\n */\n extend (props, classProps) {\n const superClass = this\n let subClass\n\n props || (props = {})\n classProps || (classProps = {})\n\n if (Object.hasOwnProperty.call(props, 'constructor')) {\n subClass = props.constructor\n delete props.constructor\n } else {\n subClass = function (...args) {\n utils.classCallCheck(this, subClass)\n superClass.apply(this, args)\n }\n }\n\n // Setup inheritance of instance members\n subClass.prototype = Object.create(superClass && superClass.prototype, {\n constructor: {\n configurable: true,\n enumerable: false,\n value: subClass,\n writable: true\n }\n })\n\n const obj = Object\n // Setup inheritance of static members\n if (obj.setPrototypeOf) {\n obj.setPrototypeOf(subClass, superClass)\n } else if (classProps.strictEs6Class) {\n subClass.__proto__ = superClass // eslint-disable-line\n } else {\n utils.forOwn(superClass, function (value, key) {\n subClass[key] = value\n })\n }\n if (!Object.hasOwnProperty.call(subClass, '__super__')) {\n Object.defineProperty(subClass, '__super__', {\n configurable: true,\n value: superClass\n })\n }\n\n utils.addHiddenPropsToTarget(subClass.prototype, props)\n utils.fillIn(subClass, classProps)\n\n return subClass\n },\n\n /**\n * Shallow copy own enumerable properties from `src` to `dest` that are on\n * `src` but are missing from `dest.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = { foo: 'bar', beep: 'boop' };\n * const b = { beep: 'bip' };\n * utils.fillIn(b, a);\n * console.log(b); // {\"foo\":\"bar\",\"beep\":\"bip\"}\n *\n * @method utils.fillIn\n * @param {object} dest The destination object.\n * @param {object} source The source object.\n * @see utils.deepFillIn\n * @see utils.deepMixIn\n * @since 3.0.0\n */\n fillIn (dest, src) {\n utils.forOwn(src, function (value, key) {\n if (!Object.hasOwnProperty.call(dest, key) || dest[key] === undefined) {\n dest[key] = value\n }\n })\n },\n\n /**\n * Find the last index of an item in an array according to the given checker function.\n *\n * @example\n * import { utils } from 'js-data';\n *\n * const john = { name: 'John', age: 20 };\n * const sara = { name: 'Sara', age: 25 };\n * const dan = { name: 'Dan', age: 20 };\n * const users = [john, sara, dan];\n *\n * console.log(utils.findIndex(users, (user) => user.age === 25)); // 1\n * console.log(utils.findIndex(users, (user) => user.age > 19)); // 2\n * console.log(utils.findIndex(users, (user) => user.name === 'John')); // 0\n * console.log(utils.findIndex(users, (user) => user.name === 'Jimmy')); // -1\n *\n * @method utils.findIndex\n * @param {array} array The array to search.\n * @param {Function} fn Checker function.\n * @returns {number} Index if found or -1 if not found.\n * @since 3.0.0\n */\n findIndex (array, fn) {\n let index = -1\n if (!array) {\n return index\n }\n array.forEach(function (record, i) {\n if (fn(record)) {\n index = i\n return false\n }\n })\n return index\n },\n\n /**\n * Recursively iterate over a {@link Mapper}'s relations according to\n * `opts.with`.\n *\n * @method utils.forEachRelation\n * @param {Mapper} mapper Mapper.\n * @param {object} opts Configuration options.\n * @param {Function} fn Callback function.\n * @param {*} thisArg Execution context for the callback function.\n * @since 3.0.0\n */\n forEachRelation (mapper, opts, fn, thisArg) {\n const relationList = mapper.relationList || []\n if (!relationList.length) {\n return\n }\n relationList.forEach(function (def) {\n utils._forRelation(opts, def, fn, thisArg)\n })\n },\n\n /**\n * Iterate over an object's own enumerable properties.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = { b: 1, c: 4 };\n * let sum = 0;\n * utils.forOwn(a, function (value, key) {\n * sum += value;\n * });\n * console.log(sum); // 5\n *\n * @method utils.forOwn\n * @param {object} object The object whose properties are to be enumerated.\n * @param {Function} fn Iteration function.\n * @param {object} [thisArg] Content to which to bind `fn`.\n * @since 3.0.0\n */\n forOwn (obj, fn, thisArg) {\n const keys = Object.keys(obj)\n const len = keys.length\n let i\n for (i = 0; i < len; i++) {\n if (fn.call(thisArg, obj[keys[i]], keys[i], obj) === false) {\n break\n }\n }\n },\n\n /**\n * Proxy for `JSON.parse`.\n *\n * @example\n * import { utils } from 'js-data';\n *\n * const a = utils.fromJson('{\"name\" : \"John\"}');\n * console.log(a); // { name: 'John' }\n *\n * @method utils.fromJson\n * @param {string} json JSON to parse.\n * @returns {Object} Parsed object.\n * @see utils.toJson\n * @since 3.0.0\n */\n fromJson (json) {\n return utils.isString(json) ? JSON.parse(json) : json\n },\n\n /**\n * Retrieve the specified property from the given object. Supports retrieving\n * nested properties.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = { foo: { bar: 'baz' }, beep: 'boop' };\n * console.log(utils.get(a, 'beep')); // \"boop\"\n * console.log(utils.get(a, 'foo.bar')); // \"baz\"\n *\n * @method utils.get\n * @param {object} object Object from which to retrieve a property's value.\n * @param {string} prop Property to retrieve.\n * @returns {*} Value of the specified property.\n * @see utils.set\n * @since 3.0.0\n */\n get: function (object, prop) {\n if (!prop) {\n return\n }\n const parts = prop.split('.')\n const last = parts.pop()\n\n while ((prop = parts.shift())) {\n // eslint-disable-line\n object = object[prop]\n if (object == null) {\n // eslint-disable-line\n return\n }\n }\n\n return object[last]\n },\n\n /**\n * Return the superclass for the given instance or subclass. If an instance is\n * provided, then finds the parent class of the instance's constructor.\n *\n * @example\n * import { utils } from 'js-data';\n * // using ES2015 classes\n * class Foo {}\n * class Bar extends Foo {}\n * const barInstance = new Bar();\n * let baseType = utils.getSuper(barInstance);\n * console.log(Foo === baseType); // true\n *\n * // using Function constructor with utils.extend\n * function Foo () {}\n * Foo.extend = utils.extend;\n * const Bar = Foo.extend();\n * const barInstance = new Bar();\n * let baseType = utils.getSuper(barInstance);\n * console.log(Foo === baseType); // true\n *\n * @method utils.getSuper\n * @param {Object|Function} instance Instance or constructor.\n * @param {boolean} [isCtor=false] Whether `instance` is a constructor.\n * @returns {Constructor} The superclass (grandparent constructor).\n * @since 3.0.0\n */\n getSuper (instance, isCtor) {\n const ctor = isCtor ? instance : instance.constructor\n if (Object.hasOwnProperty.call(ctor, '__super__')) {\n return ctor.__super__\n }\n return Object.getPrototypeOf(ctor) || ctor.__proto__ // eslint-disable-line\n },\n\n /**\n * Return the intersection of two arrays.\n *\n * @example\n * import { utils } from 'js-data';\n * const arrA = ['green', 'red', 'blue', 'red'];\n * const arrB = ['green', 'yellow', 'red'];\n * const intersected = utils.intersection(arrA, arrB);\n *\n * console.log(intersected); // ['green', 'red'])\n *\n * @method utils.intersection\n * @param {array} array1 First array.\n * @param {array} array2 Second array.\n * @returns {Array} Array of elements common to both arrays.\n * @since 3.0.0\n */\n intersection (array1, array2) {\n if (!array1 || !array2) {\n return []\n }\n array1 = Array.isArray(array1) ? array1 : [array1]\n array2 = Array.isArray(array2) ? array2 : [array2]\n const result = []\n let item\n let i\n const len = array1.length\n for (i = 0; i < len; i++) {\n item = array1[i]\n if (result.indexOf(item) !== -1) {\n continue\n }\n if (array2.indexOf(item) !== -1) {\n result.push(item)\n }\n }\n return result\n },\n\n /**\n * Proxy for `Array.isArray`.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = [1,2,3,4,5];\n * const b = { foo: \"bar\" };\n * console.log(utils.isArray(a)); // true\n * console.log(utils.isArray(b)); // false\n *\n * @method utils.isArray\n * @param {*} value The value to test.\n * @returns {boolean} Whether the provided value is an array.\n * @since 3.0.0\n */\n isArray: Array.isArray,\n\n /**\n * Return whether `prop` is matched by any string or regular expression in\n * `blacklist`.\n *\n * @example\n * import { utils } from 'js-data';\n * const blacklist = [/^\\$hashKey/g, /^_/g, 'id'];\n * console.log(utils.isBlacklisted(\"$hashKey\", blacklist)); // true\n * console.log(utils.isBlacklisted(\"id\", blacklist)); // true\n * console.log(utils.isBlacklisted(\"_myProp\", blacklist)); // true\n * console.log(utils.isBlacklisted(\"my_id\", blacklist)); // false\n *\n * @method utils.isBlacklisted\n * @param {string} prop The name of a property to check.\n * @param {array} blacklist Array of strings and regular expressions.\n * @returns {boolean} Whether `prop` was matched.\n * @since 3.0.0\n */\n isBlacklisted (prop, blacklist) {\n if (!blacklist || !blacklist.length) {\n return false\n }\n let matches\n for (var i = 0; i < blacklist.length; i++) {\n if (\n (toStr(blacklist[i]) === REGEXP_TAG && blacklist[i].test(prop)) ||\n blacklist[i] === prop\n ) {\n matches = prop\n return !!matches\n }\n }\n return !!matches\n },\n\n /**\n * Return whether the provided value is a boolean.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = true;\n * const b = { foo: \"bar\" };\n * console.log(utils.isBoolean(a)); // true\n * console.log(utils.isBoolean(b)); // false\n *\n * @method utils.isBoolean\n * @param {*} value The value to test.\n * @returns {boolean} Whether the provided value is a boolean.\n * @since 3.0.0\n */\n isBoolean (value) {\n return toStr(value) === BOOL_TAG\n },\n\n /**\n * Return whether the provided value is a date.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = new Date();\n * const b = { foo: \"bar\" };\n * console.log(utils.isDate(a)); // true\n * console.log(utils.isDate(b)); // false\n *\n * @method utils.isDate\n * @param {*} value The value to test.\n * @returns {Date} Whether the provided value is a date.\n * @since 3.0.0\n */\n isDate (value) {\n return value && typeof value === 'object' && toStr(value) === DATE_TAG\n },\n\n /**\n * Return whether the provided value is a function.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = function () { console.log('foo bar'); };\n * const b = { foo: \"bar\" };\n * console.log(utils.isFunction(a)); // true\n * console.log(utils.isFunction(b)); // false\n *\n * @method utils.isFunction\n * @param {*} value The value to test.\n * @returns {boolean} Whether the provided value is a function.\n * @since 3.0.0\n */\n isFunction (value) {\n return typeof value === 'function' || (value && toStr(value) === FUNC_TAG)\n },\n\n /**\n * Return whether the provided value is an integer.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = 1;\n * const b = 1.25;\n * const c = '1';\n * console.log(utils.isInteger(a)); // true\n * console.log(utils.isInteger(b)); // false\n * console.log(utils.isInteger(c)); // false\n *\n * @method utils.isInteger\n * @param {*} value The value to test.\n * @returns {boolean} Whether the provided value is an integer.\n * @since 3.0.0\n */\n isInteger (value) {\n return toStr(value) === NUMBER_TAG && value == toInteger(value) // eslint-disable-line\n },\n\n /**\n * Return whether the provided value is `null`.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = null;\n * const b = { foo: \"bar\" };\n * console.log(utils.isNull(a)); // true\n * console.log(utils.isNull(b)); // false\n *\n * @method utils.isNull\n * @param {*} value The value to test.\n * @returns {boolean} Whether the provided value is `null`.\n * @since 3.0.0\n */\n isNull (value) {\n return value === null\n },\n\n /**\n * Return whether the provided value is a number.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = 1;\n * const b = -1.25;\n * const c = '1';\n * console.log(utils.isNumber(a)); // true\n * console.log(utils.isNumber(b)); // true\n * console.log(utils.isNumber(c)); // false\n *\n * @method utils.isNumber\n * @param {*} value The value to test.\n * @returns {boolean} Whether the provided value is a number.\n * @since 3.0.0\n */\n isNumber (value) {\n const type = typeof value\n return (\n type === 'number' ||\n (value && type === 'object' && toStr(value) === NUMBER_TAG)\n )\n },\n\n /**\n * Return whether the provided value is an object.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = { foo: \"bar\" };\n * const b = 'foo bar';\n * console.log(utils.isObject(a)); // true\n * console.log(utils.isObject(b)); // false\n *\n * @method utils.isObject\n * @param {*} value The value to test.\n * @returns {boolean} Whether the provided value is an object.\n * @since 3.0.0\n */\n isObject (value) {\n return toStr(value) === OBJECT_TAG\n },\n\n /**\n * Return whether the provided value is a regular expression.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = /^\\$.+$/ig;\n * const b = new RegExp('^\\$.+$', 'ig');\n * const c = { foo: \"bar\" };\n * console.log(utils.isRegExp(a)); // true\n * console.log(utils.isRegExp(b)); // true\n * console.log(utils.isRegExp(c)); // false\n *\n * @method utils.isRegExp\n * @param {*} value The value to test.\n * @returns {boolean} Whether the provided value is a regular expression.\n * @since 3.0.0\n */\n isRegExp (value) {\n return toStr(value) === REGEXP_TAG\n },\n\n /**\n * Return whether the provided value is a string or a number.\n *\n * @example\n * import { utils } from 'js-data';\n * console.log(utils.isSorN('')); // true\n * console.log(utils.isSorN(-1.65)); // true\n * console.log(utils.isSorN('my string')); // true\n * console.log(utils.isSorN({})); // false\n * console.log(utils.isSorN([1,2,4])); // false\n *\n * @method utils.isSorN\n * @param {*} value The value to test.\n * @returns {boolean} Whether the provided value is a string or a number.\n * @since 3.0.0\n */\n isSorN (value) {\n return utils.isString(value) || utils.isNumber(value)\n },\n\n /**\n * Return whether the provided value is a string.\n *\n * @example\n * import { utils } from 'js-data';\n * console.log(utils.isString('')); // true\n * console.log(utils.isString('my string')); // true\n * console.log(utils.isString(100)); // false\n * console.log(utils.isString([1,2,4])); // false\n *\n * @method utils.isString\n * @param {*} value The value to test.\n * @returns {boolean} Whether the provided value is a string.\n * @since 3.0.0\n */\n isString (value) {\n return (\n typeof value === 'string' ||\n (value && typeof value === 'object' && toStr(value) === STRING_TAG)\n )\n },\n\n /**\n * Return whether the provided value is a `undefined`.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = undefined;\n * const b = { foo: \"bar\"};\n * console.log(utils.isUndefined(a)); // true\n * console.log(utils.isUndefined(b.baz)); // true\n * console.log(utils.isUndefined(b)); // false\n * console.log(utils.isUndefined(b.foo)); // false\n *\n * @method utils.isUndefined\n * @param {*} value The value to test.\n * @returns {boolean} Whether the provided value is a `undefined`.\n * @since 3.0.0\n */\n isUndefined (value) {\n return value === undefined\n },\n\n /**\n * Mix in logging capabilities to the target.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = { foo: \"bar\"};\n *\n * // Add standard logging to an object\n * utils.logify(a);\n * a.log('info', 'test log info'); // output 'test log info' to console.\n *\n * // Toggle debug output of an object\n * a.dbg('test debug output'); // does not output because debug is off.\n * a.debug = true;\n * a.dbg('test debug output'); // output 'test debug output' to console.\n *\n * @method utils.logify\n * @param {*} target The target.\n * @since 3.0.0\n */\n logify (target) {\n utils.addHiddenPropsToTarget(target, {\n dbg (...args) {\n if (utils.isFunction(this.log)) {\n this.log('debug', ...args)\n }\n },\n log (level, ...args) {\n if (level && !args.length) {\n args.push(level)\n level = 'debug'\n }\n if (level === 'debug' && !this.debug) {\n return\n }\n const prefix = `${level.toUpperCase()}: (${this.name ||\n this.constructor.name})`\n if (utils.isFunction(console[level])) {\n console[level](prefix, ...args)\n } else {\n console.log(prefix, ...args)\n }\n }\n })\n },\n\n /**\n * Adds the given record to the provided array only if it's not already in the\n * array.\n *\n * @example\n * import { utils } from 'js-data';\n * const colors = ['red', 'green', 'yellow'];\n *\n * console.log(colors.length); // 3\n * utils.noDupeAdd(colors, 'red');\n * console.log(colors.length); // 3, red already exists\n *\n * utils.noDupeAdd(colors, 'blue');\n * console.log(colors.length); // 4, blue was added\n *\n * @method utils.noDupeAdd\n * @param {array} array The array.\n * @param {*} record The value to add.\n * @param {Function} fn Callback function passed to {@link utils.findIndex}.\n * @since 3.0.0\n */\n noDupeAdd (array, record, fn) {\n if (!array) {\n return\n }\n const index = this.findIndex(array, fn)\n if (index < 0) {\n array.push(record)\n }\n },\n\n /**\n * Return a shallow copy of the provided object, minus the properties\n * specified in `keys`.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = { name: 'John', $hashKey: 1214910 };\n *\n * let b = utils.omit(a, ['$hashKey']);\n * console.log(b); // { name: 'John' }\n *\n * @method utils.omit\n * @param {object} props The object to copy.\n * @param {string[]} keys Array of strings, representing properties to skip.\n * @returns {Object} Shallow copy of `props`, minus `keys`.\n * @since 3.0.0\n */\n omit (props, keys) {\n const _props = {}\n utils.forOwn(props, function (value, key) {\n if (keys.indexOf(key) === -1) {\n _props[key] = value\n }\n })\n return _props\n },\n\n /**\n * Return a shallow copy of the provided object, but only include the\n * properties specified in `keys`.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = { name: 'John', $hashKey: 1214910 };\n *\n * let b = utils.pick(a, ['$hashKey']);\n * console.log(b); // { $hashKey: 1214910 }\n *\n * @method utils.pick\n * @param {object} props The object to copy.\n * @param {string[]} keys Array of strings, representing properties to keep.\n * @returns {Object} Shallow copy of `props`, but only including `keys`.\n * @since 3.0.0\n */\n pick (props, keys) {\n return keys.reduce((map, key) => {\n map[key] = props[key]\n return map\n }, {})\n },\n\n /**\n * Return a plain copy of the given value.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = { name: 'John' };\n * let b = utils.plainCopy(a);\n * console.log(a === b); // false\n *\n * @method utils.plainCopy\n * @param {*} value The value to copy.\n * @returns {*} Plain copy of `value`.\n * @see utils.copy\n * @since 3.0.0\n */\n plainCopy (value) {\n return utils.copy(value, undefined, undefined, undefined, undefined, true)\n },\n\n /**\n * Shortcut for `utils.Promise.reject(value)`.\n *\n * @example\n * import { utils } from 'js-data';\n *\n * utils.reject(\"Testing static reject\").then(function (data) {\n * // not called\n * }).catch(function (reason) {\n * console.log(reason); // \"Testing static reject\"\n * });\n *\n * @method utils.reject\n * @param {*} [value] Value with which to reject the Promise.\n * @returns {Promise} Promise reject with `value`.\n * @see utils.Promise\n * @since 3.0.0\n */\n reject (value) {\n return utils.Promise.reject(value)\n },\n\n /**\n * Remove the last item found in array according to the given checker function.\n *\n * @example\n * import { utils } from 'js-data';\n *\n * const colors = ['red', 'green', 'yellow', 'red'];\n * utils.remove(colors, (color) => color === 'red');\n * console.log(colors); // ['red', 'green', 'yellow']\n *\n * @method utils.remove\n * @param {array} array The array to search.\n * @param {Function} fn Checker function.\n */\n remove (array, fn) {\n if (!array || !array.length) {\n return\n }\n const index = this.findIndex(array, fn)\n if (index >= 0) {\n array.splice(index, 1) // todo should this be recursive?\n }\n },\n\n /**\n * Shortcut for `utils.Promise.resolve(value)`.\n *\n * @example\n * import { utils } from 'js-data';\n *\n * utils.resolve(\"Testing static resolve\").then(function (data) {\n * console.log(data); // \"Testing static resolve\"\n * }).catch(function (reason) {\n * // not called\n * });\n *\n * @param {*} [value] Value with which to resolve the Promise.\n * @returns {Promise} Promise resolved with `value`.\n * @see utils.Promise\n * @since 3.0.0\n */\n resolve (value) {\n return utils.Promise.resolve(value)\n },\n\n /**\n * Set the value at the provided key or path.\n *\n * @example\n * import { utils } from 'js-data';\n *\n * const john = {\n * name: 'John',\n * age: 25,\n * parent: {\n * name: 'John's Mom',\n * age: 50\n * }\n * };\n * // set value by key\n * utils.set(john, 'id', 98);\n * console.log(john.id); // 98\n *\n * // set value by path\n * utils.set(john, 'parent.id', 20);\n * console.log(john.parent.id); // 20\n *\n * // set value by path/value map\n * utils.set(john, {\n * 'id': 1098,\n * 'parent': { id: 1020 },\n * 'parent.age': '55'\n * });\n * console.log(john.id); // 1098\n * console.log(john.parent.id); // 1020\n * console.log(john.parent.age); // 55\n *\n * @method utils.set\n * @param {object} object The object on which to set a property.\n * @param {(string|Object)} path The key or path to the property. Can also\n * pass in an object of path/value pairs, which will all be set on the target\n * object.\n * @param {*} [value] The value to set.\n */\n set: function (object, path, value) {\n if (utils.isObject(path)) {\n utils.forOwn(path, function (value, _path) {\n utils.set(object, _path, value)\n })\n } else {\n const parts = PATH.exec(path)\n if (parts) {\n mkdirP(object, parts[1])[parts[2]] = value\n } else {\n object[path] = value\n }\n }\n },\n\n /**\n * Check whether the two provided objects are deeply equal.\n *\n * @example\n * import { utils } from 'js-data';\n *\n * const objA = {\n * name: 'John',\n * id: 27,\n * nested: {\n * item: 'item 1',\n * colors: ['red', 'green', 'blue']\n * }\n * };\n *\n * const objB = {\n * name: 'John',\n * id: 27,\n * nested: {\n * item: 'item 1',\n * colors: ['red', 'green', 'blue']\n * }\n * };\n *\n * console.log(utils.deepEqual(a,b)); // true\n * objB.nested.colors.add('yellow'); // make a change to a nested object's array\n * console.log(utils.deepEqual(a,b)); // false\n *\n * @method utils.deepEqual\n * @param {object} a First object in the comparison.\n * @param {object} b Second object in the comparison.\n * @returns {boolean} Whether the two provided objects are deeply equal.\n * @see utils.equal\n * @since 3.0.0\n */\n deepEqual (a, b) {\n if (a === b) {\n return true\n }\n let _equal = true\n if (utils.isArray(a) && utils.isArray(b)) {\n if (a.length !== b.length) {\n return false\n }\n for (let i = a.length; i--;) {\n if (!utils.deepEqual(a[i], b[i])) {\n // Exit loop early\n return false\n }\n }\n } else if (utils.isObject(a) && utils.isObject(b)) {\n utils.forOwn(a, function (value, key) {\n if (!(_equal = utils.deepEqual(value, b[key]))) {\n // Exit loop early\n return false\n }\n })\n if (_equal) {\n utils.forOwn(b, function (value, key) {\n if (!(_equal = utils.deepEqual(value, a[key]))) {\n // Exit loop early\n return false\n }\n })\n }\n } else {\n return false\n }\n return _equal\n },\n\n /**\n * Proxy for `JSON.stringify`.\n *\n * @example\n * import { utils } from 'js-data';\n *\n * const a = { name: 'John' };\n * let jsonVal = utils.toJson(a);\n * console.log(jsonVal); // '{\"name\" : \"John\"}'\n *\n * @method utils.toJson\n * @param {*} value Value to serialize to JSON.\n * @returns {string} JSON string.\n * @see utils.fromJson\n * @since 3.0.0\n */\n toJson: JSON.stringify,\n\n /**\n * Unset the value at the provided key or path.\n *\n * @example\n * import { utils } from 'js-data';\n *\n * const john = {\n * name: 'John',\n * age: 25,\n * parent: {\n * name: 'John's Mom',\n * age: 50\n * }\n * };\n *\n * utils.unset(john, age);\n * utils.unset(john, parent.age);\n *\n * console.log(john.age); // null\n * console.log(john.parent.age); // null\n *\n * @method utils.unset\n * @param {object} object The object from which to delete the property.\n * @param {string} path The key or path to the property.\n * @see utils.set\n * @since 3.0.0\n */\n unset (object, path) {\n const parts = path.split('.')\n const last = parts.pop()\n\n while ((path = parts.shift())) {\n // eslint-disable-line\n object = object[path]\n if (object == null) {\n // eslint-disable-line\n return\n }\n }\n\n object[last] = undefined\n }\n}\n\nexport const safeSetProp = function (record, field, value) {\n if (record && record._set) {\n record._set(`props.${field}`, value)\n } else {\n utils.set(record, field, value)\n }\n}\n\nexport const safeSetLink = function (record, field, value) {\n if (record && record._set) {\n record._set(`links.${field}`, value)\n } else {\n utils.set(record, field, value)\n }\n}\n\nexport default utils\n","import utils from './utils'\n\n/**\n * A base class which gives instances private properties.\n *\n * Typically you won't instantiate this class directly, but you may find it\n * useful as an abstract class for your own components.\n *\n * See {@link Settable.extend} for an example of using {@link Settable} as a\n * base class.\n *\n *```javascript\n * import {Settable} from 'js-data'\n * ```\n *\n * @class Settable\n * @returns {Settable} A new {@link Settable} instance.\n * @since 3.0.0\n */\nexport default function Settable () {\n const _props = {}\n Object.defineProperties(this, {\n /**\n * Get a private property of this instance.\n *\n * __Don't use the method unless you know what you're doing.__\n *\n * @method Settable#_get\n * @param {string} key The property to retrieve.\n * @returns {*} The value of the property.\n * @since 3.0.0\n */\n _get: { value (key) { return utils.get(_props, key) } },\n\n /**\n * Set a private property of this instance.\n *\n * __Don't use the method unless you know what you're doing.__\n *\n * @method __Don't use the method unless you know what you're doing.__#_set\n * @param {(string|Object)} key The key or path to the property. Can also\n * pass in an object of key/value pairs, which will all be set on the instance.\n * @param {*} [value] The value to set.\n * @since 3.0.0\n */\n _set: { value (key, value) { return utils.set(_props, key, value) } },\n\n /**\n * Unset a private property of this instance.\n *\n * __Don't use the method unless you know what you're doing.__\n *\n * @method __Don't use the method unless you know what you're doing.__#_unset\n * @param {string} key The property to unset.\n * @since 3.0.0\n */\n _unset: { value (key) { return utils.unset(_props, key) } }\n })\n}\n\n/**\n * Create a subclass of this Settable:\n *\n * @example Settable.extend\n * const JSData = require('js-data');\n * const { Settable } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * // Extend the class using ES2015 class syntax.\n * class CustomSettableClass extends Settable {\n * foo () { return 'bar'; }\n * static beep () { return 'boop'; }\n * }\n * const customSettable = new CustomSettableClass();\n * console.log(customSettable.foo());\n * console.log(CustomSettableClass.beep());\n *\n * // Extend the class using alternate method.\n * const OtherSettableClass = Settable.extend({\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * });\n * const otherSettable = new OtherSettableClass();\n * console.log(otherSettable.foo());\n * console.log(OtherSettableClass.beep());\n *\n * // Extend the class, providing a custom constructor.\n * function AnotherSettableClass () {\n * Settable.call(this);\n * this.created_at = new Date().getTime();\n * }\n * Settable.extend({\n * constructor: AnotherSettableClass,\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * })\n * const anotherSettable = new AnotherSettableClass();\n * console.log(anotherSettable.created_at);\n * console.log(anotherSettable.foo());\n * console.log(AnotherSettableClass.beep());\n *\n * @method Settable.extend\n * @param {object} [props={}] Properties to add to the prototype of the\n * subclass.\n * @param {object} [props.constructor] Provide a custom constructor function\n * to be used as the subclass itself.\n * @param {object} [classProps={}] Static properties to add to the subclass.\n * @returns {Constructor} Subclass of this Settable class.\n * @since 3.0.0\n */\nSettable.extend = utils.extend\n","import utils from './utils'\nimport Settable from './Settable'\n\n/**\n * The base class from which all JSData components inherit some basic\n * functionality.\n *\n * Typically you won't instantiate this class directly, but you may find it\n * useful as an abstract class for your own components.\n *\n * See {@link Component.extend} for an example of using {@link Component} as a\n * base class.\n *\n *```javascript\n * import {Component} from 'js-data'\n * ```\n *\n * @class Component\n * @param {object} [opts] Configuration options.\n * @param {boolean} [opts.debug=false] See {@link Component#debug}.\n * @returns {Component} A new {@link Component} instance.\n * @since 3.0.0\n */\nfunction Component (opts) {\n Settable.call(this)\n opts || (opts = {})\n\n /**\n * Whether to enable debug-level logs for this component. Anything that\n * extends `Component` inherits this option and the corresponding logging\n * functionality.\n *\n * @example Component#debug\n * const JSData = require('js-data');\n * const { Component } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const component = new Component();\n * component.log('debug', 'some message'); // nothing gets logged\n * // Display debug logs:\n * component.debug = true;\n * component.log('debug', 'other message'); // this DOES get logged\n *\n * @default false\n * @name Component#debug\n * @since 3.0.0\n * @type {boolean}\n */\n this.debug = Object.hasOwnProperty.call(opts, 'debug') ? !!opts.debug : false\n\n /**\n * Event listeners attached to this Component. __Do not modify.__ Use\n * {@link Component#on} and {@link Component#off} instead.\n *\n * @name Component#_listeners\n * @private\n * @instance\n * @since 3.0.0\n * @type {Object}\n */\n Object.defineProperty(this, '_listeners', { value: {}, writable: true })\n}\n\nexport default Settable.extend({\n constructor: Component\n})\n\n/**\n * Create a subclass of this Component:\n *\n * @example Component.extend\n * const JSData = require('js-data');\n * const { Component } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * // Extend the class using ES2015 class syntax.\n * class CustomComponentClass extends Component {\n * foo () { return 'bar'; }\n * static beep () { return 'boop'; }\n * }\n * const customComponent = new CustomComponentClass();\n * console.log(customComponent.foo());\n * console.log(CustomComponentClass.beep());\n *\n * // Extend the class using alternate method.\n * const OtherComponentClass = Component.extend({\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * });\n * const otherComponent = new OtherComponentClass();\n * console.log(otherComponent.foo());\n * console.log(OtherComponentClass.beep());\n *\n * // Extend the class, providing a custom constructor.\n * function AnotherComponentClass () {\n * Component.call(this);\n * this.created_at = new Date().getTime();\n * }\n * Component.extend({\n * constructor: AnotherComponentClass,\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * })\n * const anotherComponent = new AnotherComponentClass();\n * console.log(anotherComponent.created_at);\n * console.log(anotherComponent.foo());\n * console.log(AnotherComponentClass.beep());\n *\n * @method Component.extend\n * @param {object} [props={}] Properties to add to the prototype of the\n * subclass.\n * @param {object} [props.constructor] Provide a custom constructor function\n * to be used as the subclass itself.\n * @param {object} [classProps={}] Static properties to add to the subclass.\n * @returns {Constructor} Subclass of this Component class.\n * @since 3.0.0\n */\nComponent.extend = utils.extend\n\n/**\n * Log the provided values at the \"debug\" level. Debug-level logs are only\n * logged if {@link Component#debug} is `true`.\n *\n * `.dbg(...)` is shorthand for `.log('debug', ...)`.\n *\n * @method Component#dbg\n * @param {...*} [args] Values to log.\n * @since 3.0.0\n */\n/**\n * Log the provided values. By default sends values to `console[level]`.\n * Debug-level logs are only logged if {@link Component#debug} is `true`.\n *\n * Will attempt to use appropriate `console` methods if they are available.\n *\n * @method Component#log\n * @param {string} level Log level.\n * @param {...*} [args] Values to log.\n * @since 3.0.0\n */\nutils.logify(Component.prototype)\n\n/**\n * Register a new event listener on this Component.\n *\n * @example\n * // Listen for all \"afterCreate\" events in a DataStore\n * store.on('afterCreate', (mapperName, props, opts, result) => {\n * console.log(mapperName); // \"post\"\n * console.log(props.id); // undefined\n * console.log(result.id); // 1234\n * });\n * store.create('post', { title: 'Modeling your data' }).then((post) => {\n * console.log(post.id); // 1234\n * });\n *\n * @example\n * // Listen for the \"add\" event on a collection\n * collection.on('add', (records) => {\n * console.log(records); // [...]\n * });\n *\n * @example\n * // Listen for \"change\" events on a record\n * post.on('change', (record, changes) => {\n * console.log(changes); // { changed: { title: 'Modeling your data' } }\n * });\n * post.title = 'Modeling your data';\n *\n * @method Component#on\n * @param {string} event Name of event to subsribe to.\n * @param {Function} listener Listener function to handle the event.\n * @param {*} [ctx] Optional content in which to invoke the listener.\n * @since 3.0.0\n */\n/**\n * Remove an event listener from this Component. If no listener is provided,\n * then all listeners for the specified event will be removed. If no event is\n * specified then all listeners for all events will be removed.\n *\n * @example\n * // Remove a particular listener for a particular event\n * collection.off('add', handler);\n *\n * @example\n * // Remove all listeners for a particular event\n * record.off('change');\n *\n * @example\n * // Remove all listeners to all events\n * store.off();\n *\n * @method Component#off\n * @param {string} [event] Name of event to unsubsribe to.\n * @param {Function} [listener] Listener to remove.\n * @since 3.0.0\n */\n/**\n * Trigger an event on this Component.\n *\n * @example Component#emit\n * // import { Collection, DataStore } from 'js-data';\n * const JSData = require('js-data');\n * const { Collection, DataStore } = JSData;\n *\n * const collection = new Collection();\n * collection.on('foo', function (msg) {\n * console.log(msg);\n * });\n * collection.emit('foo', 'bar');\n *\n * const store = new DataStore();\n * store.on('beep', function (msg) {\n * console.log(msg);\n * });\n * store.emit('beep', 'boop');\n *\n * @method Component#emit\n * @param {string} event Name of event to emit.\n * @param {...*} [args] Arguments to pass to any listeners.\n * @since 3.0.0\n */\nutils.eventify(\n Component.prototype,\n function () {\n return this._listeners\n },\n function (value) {\n this._listeners = value\n }\n)\n","import utils from './utils'\nimport Component from './Component'\n\nconst DOMAIN = 'Query'\nconst INDEX_ERR = 'Index inaccessible after first operation'\n\n// Reserved words used by JSData's Query Syntax\nconst reserved = {\n limit: '',\n offset: '',\n orderBy: '',\n skip: '',\n sort: '',\n where: ''\n}\n\n// Used by our JavaScript implementation of the LIKE operator\nconst escapeRegExp = /([.*+?^=!:${}()|[\\]/\\\\])/g\nconst percentRegExp = /%/g\nconst underscoreRegExp = /_/g\nconst escape = function (pattern) {\n return pattern.replace(escapeRegExp, '\\\\$1')\n}\n\n/**\n * A class used by the {@link Collection} class to build queries to be executed\n * against the collection's data. An instance of `Query` is returned by\n * {@link Collection#query}. Query instances are typically short-lived, and you\n * shouldn't have to create them yourself. Just use {@link Collection#query}.\n *\n * ```javascript\n * import { Query } from 'js-data';\n * ```\n *\n * @example Query intro\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post');\n * const posts = [\n * { author: 'John', age: 30, status: 'published', id: 1 },\n * { author: 'Sally', age: 31, status: 'draft', id: 2 },\n * { author: 'Mike', age: 32, status: 'draft', id: 3 },\n * { author: 'Adam', age: 33, status: 'deleted', id: 4 },\n * { author: 'Adam', age: 33, status: 'draft', id: 5 }\n * ]\n * store.add('post', posts);\n * const drafts = store.query('post').filter({ status: 'draft' }).limit(2).run();\n * console.log(drafts);\n *\n * @class Query\n * @extends Component\n * @param {Collection} collection The collection on which this query operates.\n * @since 3.0.0\n */\nfunction Query (collection) {\n utils.classCallCheck(this, Query)\n\n /**\n * The {@link Collection} on which this query operates.\n *\n * @name Query#collection\n * @since 3.0.0\n * @type {Collection}\n */\n this.collection = collection\n\n /**\n * The current data result of this query.\n *\n * @name Query#data\n * @since 3.0.0\n * @type {Array}\n */\n this.data = null\n}\n\nexport default Component.extend({\n constructor: Query,\n\n _applyWhereFromObject (where) {\n const fields = []\n const ops = []\n const predicates = []\n utils.forOwn(where, (clause, field) => {\n if (!utils.isObject(clause)) {\n clause = {\n '==': clause\n }\n }\n utils.forOwn(clause, (expr, op) => {\n fields.push(field)\n ops.push(op)\n predicates.push(expr)\n })\n })\n return {\n fields,\n ops,\n predicates\n }\n },\n\n _applyWhereFromArray (where) {\n const groups = []\n where.forEach((_where, i) => {\n if (utils.isString(_where)) {\n return\n }\n const prev = where[i - 1]\n const parser = utils.isArray(_where) ? this._applyWhereFromArray : this._applyWhereFromObject\n const group = parser.call(this, _where)\n if (prev === 'or') {\n group.isOr = true\n }\n groups.push(group)\n })\n groups.isArray = true\n return groups\n },\n\n _testObjectGroup (keep, first, group, item) {\n let i\n const fields = group.fields\n const ops = group.ops\n const predicates = group.predicates\n const len = ops.length\n for (i = 0; i < len; i++) {\n let op = ops[i]\n const isOr = op.charAt(0) === '|'\n op = isOr ? op.substr(1) : op\n const expr = this.evaluate(utils.get(item, fields[i]), op, predicates[i])\n if (expr !== undefined) {\n keep = first ? expr : (isOr ? keep || expr : keep && expr)\n }\n first = false\n }\n return { keep, first }\n },\n\n _testArrayGroup (keep, first, groups, item) {\n let i\n const len = groups.length\n for (i = 0; i < len; i++) {\n const group = groups[i]\n const parser = group.isArray ? this._testArrayGroup : this._testObjectGroup\n const result = parser.call(this, true, true, group, item)\n if (groups[i - 1]) {\n if (group.isOr) {\n keep = keep || result.keep\n } else {\n keep = keep && result.keep\n }\n } else {\n keep = result.keep\n }\n first = result.first\n }\n return { keep, first }\n },\n\n /**\n * Find all entities between two boundaries.\n *\n * @example Get the users ages 18 to 30.\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('user');\n * const users = [\n * { name: 'Peter', age: 25, id: 1 },\n * { name: 'Jim', age: 19, id: 2 },\n * { name: 'Mike', age: 17, id: 3 },\n * { name: 'Alan', age: 29, id: 4 },\n * { name: 'Katie', age: 33, id: 5 }\n * ];\n * store.add('user', users)\n * const filteredUsers = store\n * .query('user')\n * .between(18, 30, { index: 'age' })\n * .run();\n * console.log(filteredUsers);\n *\n * @example Same as above.\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('user');\n * const users = [\n * { name: 'Peter', age: 25, id: 1 },\n * { name: 'Jim', age: 19, id: 2 },\n * { name: 'Mike', age: 17, id: 3 },\n * { name: 'Alan', age: 29, id: 4 },\n * { name: 'Katie', age: 33, id: 5 }\n * ];\n * store.add('user', users)\n * const filteredUsers = store\n * .query('user')\n * .between([18], [30], { index: 'age' })\n * .run();\n * console.log(filteredUsers);\n *\n * @method Query#between\n * @param {array} leftKeys Keys defining the left boundary.\n * @param {array} rightKeys Keys defining the right boundary.\n * @param {object} [opts] Configuration options.\n * @param {string} [opts.index] Name of the secondary index to use in the\n * query. If no index is specified, the main index is used.\n * @param {boolean} [opts.leftInclusive=true] Whether to include entities\n * on the left boundary.\n * @param {boolean} [opts.rightInclusive=false] Whether to include entities\n * on the left boundary.\n * @param {boolean} [opts.limit] Limit the result to a certain number.\n * @param {boolean} [opts.offset] The number of resulting entities to skip.\n * @returns {Query} A reference to itself for chaining.\n * @since 3.0.0\n */\n between (leftKeys, rightKeys, opts) {\n opts || (opts = {})\n if (this.data) {\n throw utils.err(`${DOMAIN}#between`)(500, 'Cannot access index')\n }\n this.data = this.collection.getIndex(opts.index).between(leftKeys, rightKeys, opts)\n return this\n },\n\n /**\n * The comparison function used by the {@link Query} class.\n *\n * @method Query#compare\n * @param {array} orderBy An orderBy clause used for sorting and sub-sorting.\n * @param {number} index The index of the current orderBy clause being used.\n * @param {*} a The first item in the comparison.\n * @param {*} b The second item in the comparison.\n * @returns {number} -1 if `b` should preceed `a`. 0 if `a` and `b` are equal.\n * 1 if `a` should preceed `b`.\n * @since 3.0.0\n */\n compare (orderBy, index, a, b) {\n const def = orderBy[index]\n let cA = utils.get(a, def[0])\n let cB = utils.get(b, def[0])\n if (cA && utils.isString(cA)) {\n cA = cA.toUpperCase()\n }\n if (cB && utils.isString(cB)) {\n cB = cB.toUpperCase()\n }\n if (a === undefined) {\n a = null\n }\n if (b === undefined) {\n b = null\n }\n if (def[1].toUpperCase() === 'DESC') {\n const temp = cB\n cB = cA\n cA = temp\n }\n if (cA < cB) {\n return -1\n } else if (cA > cB) {\n return 1\n } else {\n if (index < orderBy.length - 1) {\n return this.compare(orderBy, index + 1, a, b)\n } else {\n return 0\n }\n }\n },\n\n /**\n * Predicate evaluation function used by the {@link Query} class.\n *\n * @method Query#evaluate\n * @param {*} value The value to evaluate.\n * @param {string} op The operator to use in this evaluation.\n * @param {*} predicate The predicate to use in this evaluation.\n * @returns {boolean} Whether the value passed the evaluation or not.\n * @since 3.0.0\n */\n evaluate (value, op, predicate) {\n const ops = this.constructor.ops\n if (ops[op]) {\n return ops[op](value, predicate)\n }\n if (op.indexOf('like') === 0) {\n return this.like(predicate, op.substr(4)).exec(value) !== null\n } else if (op.indexOf('notLike') === 0) {\n return this.like(predicate, op.substr(7)).exec(value) === null\n }\n },\n\n /**\n * Find the record or records that match the provided query or are accepted by\n * the provided filter function.\n *\n * @example Get the draft posts by authors younger than 30\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post')\n * const posts = [\n * { author: 'John', age: 30, status: 'published', id: 1 },\n * { author: 'Sally', age: 31, status: 'published', id: 2 },\n * { author: 'Mike', age: 32, status: 'draft', id: 3 },\n * { author: 'Adam', age: 33, status: 'deleted', id: 4 },\n * { author: 'Adam', age: 33, status: 'published', id: 5 }\n * { author: 'Peter', age: 25, status: 'deleted', id: 6 },\n * { author: 'Sally', age: 21, status: 'draft', id: 7 },\n * { author: 'Jim', age: 27, status: 'draft', id: 8 },\n * { author: 'Jim', age: 27, status: 'published', id: 9 },\n * { author: 'Jason', age: 55, status: 'published', id: 10 }\n * ];\n * store.add('post', posts);\n * const results = store\n * .query('post')\n * .filter({\n * where: {\n * status: {\n * '==': 'draft'\n * },\n * age: {\n * '<': 30\n * }\n * }\n * })\n * .run();\n * console.log(results);\n *\n * @example Use a custom filter function\n * const posts = query\n * .filter(function (post) {\n * return post.isReady();\n * })\n * .run();\n *\n * @method Query#filter\n * @param {(Object|Function)} [queryOrFn={}] Selection query or filter\n * function.\n * @param {Function} [thisArg] Context to which to bind `queryOrFn` if\n * `queryOrFn` is a function.\n * @returns {Query} A reference to itself for chaining.\n * @since 3.0.0\n */\n filter (query, thisArg) {\n /**\n * Selection query as defined by JSData's [Query Syntax][querysyntax].\n *\n * [querysyntax]: http://www.js-data.io/v3.0/docs/query-syntax\n *\n * @example Empty \"findAll\" query\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post')\n * store.findAll('post').then((posts) => {\n * console.log(posts); // [...]\n * });\n *\n * @example Empty \"filter\" query\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post');\n * const posts = store.filter('post');\n * console.log(posts); // [...]\n *\n * @example Complex \"filter\" query\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * const PAGE_SIZE = 2;\n * let currentPage = 3;\n *\n * store.defineMapper('post');\n * const posts = [\n * { author: 'John', age: 30, status: 'published', id: 1 },\n * { author: 'Sally', age: 31, status: 'published', id: 2 },\n * { author: 'Mike', age: 32, status: 'draft', id: 3 },\n * { author: 'Adam', age: 33, status: 'deleted', id: 4 },\n * { author: 'Adam', age: 33, status: 'published', id: 5 }\n * { author: 'Peter', age: 25, status: 'deleted', id: 6 },\n * { author: 'Sally', age: 21, status: 'draft', id: 7 },\n * { author: 'Jim', age: 27, status: 'draft', id: 8 },\n * { author: 'Jim', age: 27, status: 'published', id: 9 },\n * { author: 'Jason', age: 55, status: 'published', id: 10 }\n * ];\n * store.add('post', posts);\n * // Retrieve a filtered page of blog posts\n * // Would typically replace filter with findAll\n * const results = store.filter('post', {\n * where: {\n * status: {\n * // WHERE status = 'published'\n * '==': 'published'\n * },\n * author: {\n * // AND author IN ('bob', 'alice')\n * 'in': ['bob', 'alice'],\n * // OR author IN ('karen')\n * '|in': ['karen']\n * }\n * },\n * orderBy: [\n * // ORDER BY date_published DESC,\n * ['date_published', 'DESC'],\n * // ORDER BY title ASC\n * ['title', 'ASC']\n * ],\n * // LIMIT 2\n * limit: PAGE_SIZE,\n * // SKIP 4\n * offset: PAGE_SIZE * (currentPage - 1)\n * });\n * console.log(results);\n *\n * @namespace query\n * @property {number} [limit] See {@link query.limit}.\n * @property {number} [offset] See {@link query.offset}.\n * @property {string|Array[]} [orderBy] See {@link query.orderBy}.\n * @property {number} [skip] Alias for {@link query.offset}.\n * @property {string|Array[]} [sort] Alias for {@link query.orderBy}.\n * @property {Object} [where] See {@link query.where}.\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/query-syntax\",\"JSData's Query Syntax\"]\n */\n query || (query = {})\n this.getData()\n if (utils.isObject(query)) {\n let where = {}\n\n /**\n * Filtering criteria. Records that do not meet this criteria will be exluded\n * from the result.\n *\n * @example Return posts where author is at least 32 years old\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post')\n * const posts = [\n * { author: 'John', age: 30, id: 5 },\n * { author: 'Sally', age: 31, id: 6 },\n * { author: 'Mike', age: 32, id: 7 },\n * { author: 'Adam', age: 33, id: 8 },\n * { author: 'Adam', age: 33, id: 9 }\n * ];\n * store.add('post', posts);\n * const results = store.filter('post', {\n * where: {\n * age: {\n * '>=': 30\n * }\n * }\n * });\n * console.log(results);\n *\n * @name query.where\n * @type {Object}\n * @see http://www.js-data.io/v3.0/docs/query-syntax\n * @since 3.0.0\n */\n if (utils.isObject(query.where) || utils.isArray(query.where)) {\n where = query.where\n }\n utils.forOwn(query, function (value, key) {\n if (!(key in reserved) && !(key in where)) {\n where[key] = {\n '==': value\n }\n }\n })\n let groups\n\n // Apply filter for each field\n if (utils.isObject(where) && Object.keys(where).length !== 0) {\n groups = this._applyWhereFromArray([where])\n } else if (utils.isArray(where)) {\n groups = this._applyWhereFromArray(where)\n }\n\n if (groups) {\n this.data = this.data.filter((item, i) => this._testArrayGroup(true, true, groups, item).keep)\n }\n\n // Sort\n let orderBy = query.orderBy || query.sort\n\n if (utils.isString(orderBy)) {\n orderBy = [\n [orderBy, 'ASC']\n ]\n }\n if (!utils.isArray(orderBy)) {\n orderBy = null\n }\n\n /**\n * Determines how records should be ordered in the result.\n *\n * @example Order posts by `author` then by `id` descending \n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post')\n * const posts = [\n * { author: 'John', age: 30, id: 5 },\n * { author: 'Sally', age: 31, id: 6 },\n * { author: 'Mike', age: 32, id: 7 },\n * { author: 'Adam', age: 33, id: 8 },\n * { author: 'Adam', age: 33, id: 9 }\n * ];\n * store.add('post', posts);\n * const results = store.filter('post', {\n * orderBy:[['author','ASC'],['id','DESC']]\n * });\n * console.log(results);\n *\n * @name query.orderBy\n * @type {string|Array[]}\n * @see http://www.js-data.io/v3.0/docs/query-syntax\n * @since 3.0.0\n */\n if (orderBy) {\n const index = 0\n orderBy.forEach(function (def, i) {\n if (utils.isString(def)) {\n orderBy[i] = [def, 'ASC']\n }\n })\n this.data.sort((a, b) => this.compare(orderBy, index, a, b))\n }\n\n /**\n * Number of records to skip.\n *\n * @example Retrieve the first \"page\" of blog posts using findAll\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post');\n * const PAGE_SIZE = 10;\n * let currentPage = 1;\n * store.findAll('post', {\n * offset: PAGE_SIZE * (currentPage 1)\n * limit: PAGE_SIZE\n * });\n *\n * @example Retrieve the last \"page\" of blog posts using filter\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n *\n * const PAGE_SIZE = 5;\n * let currentPage = 2;\n * store.defineMapper('post');\n * const posts = [\n * { author: 'John', age: 30, id: 1 },\n * { author: 'Sally', age: 31, id: 2 },\n * { author: 'Mike', age: 32, id: 3 },\n * { author: 'Adam', age: 33, id: 4 },\n * { author: 'Adam', age: 33, id: 5 },\n * { author: 'Peter', age: 25, id: 6 },\n * { author: 'Sally', age: 21, id: 7 },\n * { author: 'Jim', age: 27, id: 8 },\n * { author: 'Jim', age: 27, id: 9 },\n * { author: 'Jason', age: 55, id: 10 }\n * ];\n * store.add('post', posts);\n * const results = store.filter('post', {\n * offset: PAGE_SIZE * (currentPage 1)\n * limit: PAGE_SIZE\n * });\n * console.log(results)\n *\n * @name query.offset\n * @type {number}\n * @see http://www.js-data.io/v3.0/docs/query-syntax\n * @since 3.0.0\n */\n if (utils.isNumber(query.skip)) {\n this.skip(query.skip)\n } else if (utils.isNumber(query.offset)) {\n this.skip(query.offset)\n }\n\n /**\n * Maximum number of records to retrieve.\n *\n * @example Retrieve the first \"page\" of blog posts using findAll\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post');\n *\n * const PAGE_SIZE = 10\n * let currentPage = 1\n * store.findAll('post', {\n * offset: PAGE_SIZE * (currentPage 1)\n * limit: PAGE_SIZE\n * });\n *\n * @example Retrieve the last \"page\" of blog posts using filter\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n *\n * const PAGE_SIZE = 5\n * let currentPage = 2\n * store.defineMapper('post')\n * const posts = [\n * { author: 'John', age: 30, id: 1 },\n * { author: 'Sally', age: 31, id: 2 },\n * { author: 'Mike', age: 32, id: 3 },\n * { author: 'Adam', age: 33, id: 4 },\n * { author: 'Adam', age: 33, id: 5 },\n * { author: 'Peter', age: 25, id: 6 },\n * { author: 'Sally', age: 21, id: 7 },\n * { author: 'Jim', age: 27, id: 8 },\n * { author: 'Jim', age: 27, id: 9 },\n * { author: 'Jason', age: 55, id: 10 }\n * ];\n * store.add('post', posts);\n * const results = store.filter('post', {\n * offset: PAGE_SIZE * (currentPage 1)\n * limit: PAGE_SIZE\n * });\n * console.log(results)\n *\n * @name query.limit\n * @type {number}\n * @see http://www.js-data.io/v3.0/docs/query-syntax\n * @since 3.0.0\n */\n if (utils.isNumber(query.limit)) {\n this.limit(query.limit)\n }\n } else if (utils.isFunction(query)) {\n this.data = this.data.filter(query, thisArg)\n }\n return this\n },\n\n /**\n * Iterate over all entities.\n *\n * @method Query#forEach\n * @param {Function} forEachFn Iteration function.\n * @param {*} [thisArg] Context to which to bind `forEachFn`.\n * @returns {Query} A reference to itself for chaining.\n * @since 3.0.0\n */\n forEach (forEachFn, thisArg) {\n this.getData().forEach(forEachFn, thisArg)\n return this\n },\n\n /**\n * Find the entity or entities that match the provided key.\n *\n * @example Get the entity whose primary key is 25.\n * const entities = query.get(25).run();\n *\n * @example Same as above.\n * const entities = query.get([25]).run();\n *\n * @example Get all users who are active and have the \"admin\" role.\n * const activeAdmins = query.get(['active', 'admin'], {\n * index: 'activityAndRoles'\n * }).run();\n *\n * @example Get all entities that match a certain weather condition.\n * const niceDays = query.get(['sunny', 'humid', 'calm'], {\n * index: 'weatherConditions'\n * }).run();\n *\n * @method Query#get\n * @param {array} keyList Key(s) defining the entity to retrieve. If\n * `keyList` is not an array (i.e. for a single-value key), it will be\n * wrapped in an array.\n * @param {object} [opts] Configuration options.\n * @param {string} [opts.string] Name of the secondary index to use in the\n * query. If no index is specified, the main index is used.\n * @returns {Query} A reference to itself for chaining.\n * @since 3.0.0\n */\n get (keyList, opts) {\n keyList || (keyList = [])\n opts || (opts = {})\n if (this.data) {\n throw utils.err(`${DOMAIN}#get`)(500, INDEX_ERR)\n }\n if (keyList && !utils.isArray(keyList)) {\n keyList = [keyList]\n }\n if (!keyList.length) {\n this.getData()\n return this\n }\n this.data = this.collection.getIndex(opts.index).get(keyList)\n return this\n },\n\n /**\n * Find the entity or entities that match the provided keyLists.\n *\n * @example Get the posts where \"status\" is \"draft\" or \"inReview\".\n * const posts = query.getAll('draft', 'inReview', { index: 'status' }).run();\n *\n * @example Same as above.\n * const posts = query.getAll(['draft'], ['inReview'], { index: 'status' }).run();\n *\n * @method Query#getAll\n * @param {...Array} [keyList] Provide one or more keyLists, and all\n * entities matching each keyList will be retrieved. If no keyLists are\n * provided, all entities will be returned.\n * @param {object} [opts] Configuration options.\n * @param {string} [opts.index] Name of the secondary index to use in the\n * query. If no index is specified, the main index is used.\n * @returns {Query} A reference to itself for chaining.\n * @since 3.0.0\n */\n getAll (...args) {\n let opts = {}\n if (this.data) {\n throw utils.err(`${DOMAIN}#getAll`)(500, INDEX_ERR)\n }\n if (!args.length || (args.length === 1 && utils.isObject(args[0]))) {\n this.getData()\n return this\n } else if (args.length && utils.isObject(args[args.length - 1])) {\n opts = args[args.length - 1]\n args.pop()\n }\n const collection = this.collection\n const index = collection.getIndex(opts.index)\n this.data = []\n args.forEach((keyList) => {\n this.data = this.data.concat(index.get(keyList))\n })\n return this\n },\n\n /**\n * Return the current data result of this query.\n *\n * @method Query#getData\n * @returns {Array} The data in this query.\n * @since 3.0.0\n */\n getData () {\n if (!this.data) {\n this.data = this.collection.index.getAll()\n }\n return this.data\n },\n\n /**\n * Implementation used by the `like` operator. Takes a pattern and flags and\n * returns a `RegExp` instance that can test strings.\n *\n * @method Query#like\n * @param {string} pattern Testing pattern.\n * @param {string} flags Flags for the regular expression.\n * @returns {RegExp} Regular expression for testing strings.\n * @since 3.0.0\n */\n like (pattern, flags) {\n return new RegExp(`^${(escape(pattern).replace(percentRegExp, '.*').replace(underscoreRegExp, '.'))}$`, flags)\n },\n\n /**\n * Limit the result.\n *\n * @example Get only the first 2 posts.\n * const store = new JSData.DataStore();\n * store.defineMapper('post');\n * const posts = [\n * { author: 'John', age: 30, status: 'published', id: 1 },\n * { author: 'Sally', age: 31, status: 'draft', id: 2 },\n * { author: 'Mike', age: 32, status: 'draft', id: 3 },\n * { author: 'Adam', age: 33, status: 'deleted', id: 4 },\n * { author: 'Adam', age: 33, status: 'draft', id: 5 }\n * ];\n * store.add('post', posts);\n * const results = store.query('post').limit(2).run();\n * console.log(results);\n *\n * @method Query#limit\n * @param {number} num The maximum number of entities to keep in the result.\n * @returns {Query} A reference to itself for chaining.\n * @since 3.0.0\n */\n limit (num) {\n if (!utils.isNumber(num)) {\n throw utils.err(`${DOMAIN}#limit`, 'num')(400, 'number', num)\n }\n const data = this.getData()\n this.data = data.slice(0, Math.min(data.length, num))\n return this\n },\n\n /**\n * Apply a mapping function to the result data.\n *\n * @example\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('user');\n * const users = [\n * { name: 'Peter', age: 25, id: 1 },\n * { name: 'Jim', age: 19, id: 2 },\n * { name: 'Mike', age: 17, id: 3 },\n * { name: 'Alan', age: 29, id: 4 },\n * { name: 'Katie', age: 33, id: 5 }\n * ];\n * store.add('user', users);\n * const ages = store\n * .query('user')\n * .map(function (user) {\n * return user.age;\n * })\n * .run();\n * console.log(ages);\n *\n * @method Query#map\n * @param {Function} mapFn Mapping function.\n * @param {*} [thisArg] Context to which to bind `mapFn`.\n * @returns {Query} A reference to itself for chaining.\n * @since 3.0.0\n */\n map (mapFn, thisArg) {\n this.data = this.getData().map(mapFn, thisArg)\n return this\n },\n\n /**\n * Return the result of calling the specified function on each item in this\n * collection's main index.\n *\n * @example\n * const stringAges = UserCollection.query().mapCall('toString').run();\n *\n * @method Query#mapCall\n * @param {string} funcName Name of function to call\n * @parama {...*} [args] Remaining arguments to be passed to the function.\n * @returns {Query} A reference to itself for chaining.\n * @since 3.0.0\n */\n mapCall (funcName, ...args) {\n this.data = this.getData().map(function (item) {\n return item[funcName](...args)\n })\n return this\n },\n\n /**\n * Complete the execution of the query and return the resulting data.\n *\n * @method Query#run\n * @returns {Array} The result of executing this query.\n * @since 3.0.0\n */\n run () {\n const data = this.data\n this.data = null\n return data\n },\n\n /**\n * Skip a number of results.\n *\n * @example Get all but the first 2 posts.\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post');\n * const posts = [\n * { author: 'John', age: 30, status: 'published', id: 1 },\n * { author: 'Sally', age: 31, status: 'draft', id: 2 },\n * { author: 'Mike', age: 32, status: 'draft', id: 3 },\n * { author: 'Adam', age: 33, status: 'deleted', id: 4 },\n * { author: 'Adam', age: 33, status: 'draft', id: 5 }\n * ];\n * store.add('post', posts);\n * const results = store.query('post').skip(2).run();\n * console.log(results);\n *\n * @method Query#skip\n * @param {number} num The number of entities to skip.\n * @returns {Query} A reference to itself for chaining.\n * @since 3.0.0\n */\n skip (num) {\n if (!utils.isNumber(num)) {\n throw utils.err(`${DOMAIN}#skip`, 'num')(400, 'number', num)\n }\n const data = this.getData()\n if (num < data.length) {\n this.data = data.slice(num)\n } else {\n this.data = []\n }\n return this\n }\n}, {\n /**\n * The filtering operators supported by {@link Query#filter}, and which are\n * implemented by adapters (for the most part).\n *\n * @example Variant 1\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post');\n * const posts = [\n * { author: 'John', age: 30, status: 'published', id: 1 },\n * { author: 'Sally', age: 31, status: 'published', id: 2 },\n * { author: 'Mike', age: 32, status: 'published', id: 3 },\n * { author: 'Adam', age: 33, status: 'deleted', id: 4 },\n * { author: 'Adam', age: 33, status: 'published', id: 5 }\n * ];\n * store.add('post', posts);\n * const publishedPosts = store.filter('post', {\n * status: 'published',\n * limit: 2\n * });\n * console.log(publishedPosts);\n *\n *\n * @example Variant 2\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post')\n * const posts = [\n * { author: 'John', age: 30, status: 'published', id: 1 },\n * { author: 'Sally', age: 31, status: 'published', id: 2 },\n * { author: 'Mike', age: 32, status: 'published', id: 3 },\n * { author: 'Adam', age: 33, status: 'deleted', id: 4 },\n * { author: 'Adam', age: 33, status: 'published', id: 5 }\n * ];\n * store.add('post', posts);\n * const publishedPosts = store.filter('post', {\n * where: {\n * status: {\n * '==': 'published'\n * }\n * },\n * limit: 2\n * });\n * console.log(publishedPosts);\n *\n * @example Variant 3\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post');\n * const posts = [\n * { author: 'John', age: 30, status: 'published', id: 1 },\n * { author: 'Sally', age: 31, status: 'published', id: 2 },\n * { author: 'Mike', age: 32, status: 'published', id: 3 },\n * { author: 'Adam', age: 33, status: 'deleted', id: 4 },\n * { author: 'Adam', age: 33, status: 'published', id: 5 }\n * ];\n * store.add('post', posts);\n * const publishedPosts = store\n * .query('post')\n * .filter({ status: 'published' })\n * .limit(2)\n * .run();\n * console.log(publishedPosts);\n *\n * @example Variant 4\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post');\n * const posts = [\n * { author: 'John', age: 30, status: 'published', id: 1 },\n * { author: 'Sally', age: 31, status: 'published', id: 2 },\n * { author: 'Mike', age: 32, status: 'published', id: 3 },\n * { author: 'Adam', age: 33, status: 'deleted', id: 4 },\n * { author: 'Adam', age: 33, status: 'published', id: 5 }\n * ];\n * store.add('post', posts);\n * const publishedPosts = store\n * .query('post')\n * .filter({\n * where: {\n * status: {\n * '==': 'published'\n * }\n * }\n * })\n * .limit(2)\n * .run();\n * console.log(publishedPosts);\n *\n * @example Multiple operators\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post');\n * const posts = [\n * { author: 'John', age: 30, status: 'published', id: 1 },\n * { author: 'Sally', age: 31, status: 'published', id: 2 },\n * { author: 'Mike', age: 32, status: 'published', id: 3 },\n * { author: 'Adam', age: 33, status: 'deleted', id: 4 },\n * { author: 'Adam', age: 33, status: 'published', id: 5 }\n * ];\n * store.add('post', posts);\n *\n * const myPublishedPosts = store.filter('post', {\n * where: {\n * status: {\n * '==': 'published'\n * },\n * user_id: {\n * '==': currentUser.id\n * }\n * }\n * });\n *\n * console.log(myPublishedPosts);\n *\n * @name Query.ops\n * @property {Function} == Equality operator.\n * @property {Function} != Inequality operator.\n * @property {Function} > Greater than operator.\n * @property {Function} >= Greater than (inclusive) operator.\n * @property {Function} < Less than operator.\n * @property {Function} <= Less than (inclusive) operator.\n * @property {Function} isectEmpty Operator that asserts that the intersection\n * between two arrays is empty.\n * @property {Function} isectNotEmpty Operator that asserts that the\n * intersection between two arrays is __not__ empty.\n * @property {Function} in Operator that asserts whether a value is in an\n * array.\n * @property {Function} notIn Operator that asserts whether a value is __not__\n * in an array.\n * @property {Function} contains Operator that asserts whether an array\n * contains a value.\n * @property {Function} notContains Operator that asserts whether an array\n * does __not__ contain a value.\n * @since 3.0.0\n * @type {Object}\n */\n ops: {\n '=': function (value, predicate) {\n return value == predicate // eslint-disable-line\n },\n '==': function (value, predicate) {\n return value == predicate // eslint-disable-line\n },\n '===': function (value, predicate) {\n return value === predicate\n },\n '!=': function (value, predicate) {\n return value != predicate // eslint-disable-line\n },\n '!==': function (value, predicate) {\n return value !== predicate\n },\n '>': function (value, predicate) {\n return value > predicate\n },\n '>=': function (value, predicate) {\n return value >= predicate\n },\n '<': function (value, predicate) {\n return value < predicate\n },\n '<=': function (value, predicate) {\n return value <= predicate\n },\n isectEmpty: function (value, predicate) {\n return !utils.intersection((value || []), (predicate || [])).length\n },\n isectNotEmpty: function (value, predicate) {\n return utils.intersection((value || []), (predicate || [])).length\n },\n in: function (value, predicate) {\n return predicate.indexOf(value) !== -1\n },\n notIn: function (value, predicate) {\n return predicate.indexOf(value) === -1\n },\n contains: function (value, predicate) {\n return (value || []).indexOf(predicate) !== -1\n },\n notContains: function (value, predicate) {\n return (value || []).indexOf(predicate) === -1\n }\n }\n})\n\n/**\n * Create a subclass of this Query:\n * @example Query.extend\n * const JSData = require('js-data');\n * const { Query } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * // Extend the class using ES2015 class syntax.\n * class CustomQueryClass extends Query {\n * foo () { return 'bar'; }\n * static beep () { return 'boop'; }\n * }\n * const customQuery = new CustomQueryClass();\n * console.log(customQuery.foo());\n * console.log(CustomQueryClass.beep());\n *\n * // Extend the class using alternate method.\n * const OtherQueryClass = Query.extend({\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * });\n * const otherQuery = new OtherQueryClass();\n * console.log(otherQuery.foo());\n * console.log(OtherQueryClass.beep());\n *\n * // Extend the class, providing a custom constructor.\n * function AnotherQueryClass (collection) {\n * Query.call(this, collection);\n * this.created_at = new Date().getTime();\n * }\n * Query.extend({\n * constructor: AnotherQueryClass,\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * });\n * const anotherQuery = new AnotherQueryClass();\n * console.log(anotherQuery.created_at);\n * console.log(anotherQuery.foo());\n * console.log(AnotherQueryClass.beep());\n *\n * @method Query.extend\n * @param {object} [props={}] Properties to add to the prototype of the\n * subclass.\n * @param {object} [props.constructor] Provide a custom constructor function\n * to be used as the subclass itself.\n * @param {object} [classProps={}] Static properties to add to the subclass.\n * @returns {Constructor} Subclass of this Query class.\n * @since 3.0.0\n */\n","import utils from './utils'\n\n// TODO: remove this when the rest of the project is cleaned\nexport const belongsToType = 'belongsTo'\nexport const hasManyType = 'hasMany'\nexport const hasOneType = 'hasOne'\n\nconst DOMAIN = 'Relation'\n\nexport function Relation (relatedMapper, options = {}) {\n utils.classCallCheck(this, Relation)\n\n options.type = this.constructor.TYPE_NAME\n this.validateOptions(relatedMapper, options)\n\n if (typeof relatedMapper === 'object') {\n Object.defineProperty(this, 'relatedMapper', { value: relatedMapper })\n }\n\n Object.defineProperty(this, 'inverse', { writable: true })\n utils.fillIn(this, options)\n}\n\nRelation.extend = utils.extend\n\nutils.addHiddenPropsToTarget(Relation.prototype, {\n get canAutoAddLinks () {\n return this.add === undefined || !!this.add\n },\n\n get relatedCollection () {\n return this.mapper.datastore.getCollection(this.relation)\n },\n\n validateOptions (related, opts) {\n const DOMAIN_ERR = `new ${DOMAIN}`\n\n const localField = opts.localField\n if (!localField) {\n throw utils.err(DOMAIN_ERR, 'opts.localField')(400, 'string', localField)\n }\n\n const foreignKey = opts.foreignKey = opts.foreignKey || opts.localKey\n if (!foreignKey && (opts.type === belongsToType || opts.type === hasOneType)) {\n throw utils.err(DOMAIN_ERR, 'opts.foreignKey')(400, 'string', foreignKey)\n }\n\n if (utils.isString(related)) {\n opts.relation = related\n if (!utils.isFunction(opts.getRelation)) {\n throw utils.err(DOMAIN_ERR, 'opts.getRelation')(400, 'function', opts.getRelation)\n }\n } else if (related) {\n opts.relation = related.name\n } else {\n throw utils.err(DOMAIN_ERR, 'related')(400, 'Mapper or string', related)\n }\n },\n\n assignTo (mapper) {\n this.name = mapper.name\n Object.defineProperty(this, 'mapper', { value: mapper })\n\n mapper.relationList || Object.defineProperty(mapper, 'relationList', { value: [] })\n mapper.relationFields || Object.defineProperty(mapper, 'relationFields', { value: [] })\n mapper.relationList.push(this)\n mapper.relationFields.push(this.localField)\n },\n\n canFindLinkFor () {\n return !!(this.foreignKey || this.localKey)\n },\n\n getRelation () {\n return this.relatedMapper\n },\n\n getForeignKey (record) {\n return utils.get(record, this.mapper.idAttribute)\n },\n\n setForeignKey (record, relatedRecord) {\n if (!record || !relatedRecord) {\n return\n }\n\n this._setForeignKey(record, relatedRecord)\n },\n\n _setForeignKey (record, relatedRecords) {\n const idAttribute = this.mapper.idAttribute\n\n if (!utils.isArray(relatedRecords)) {\n relatedRecords = [relatedRecords]\n }\n\n relatedRecords.forEach((relatedRecord) => {\n utils.set(relatedRecord, this.foreignKey, utils.get(record, idAttribute))\n })\n },\n\n getLocalField (record) {\n return utils.get(record, this.localField)\n },\n\n setLocalField (record, relatedData) {\n return utils.set(record, this.localField, relatedData)\n },\n\n getInverse (mapper) {\n if (!this.inverse) {\n this.findInverseRelation(mapper)\n }\n\n return this.inverse\n },\n\n findInverseRelation (mapper) {\n this.getRelation().relationList.forEach((def) => {\n if (def.getRelation() === mapper && this.isInversedTo(def) && this !== def) {\n this.inverse = def\n return true\n }\n })\n },\n\n isInversedTo (def) {\n return !def.foreignKey || def.foreignKey === this.foreignKey\n },\n\n addLinkedRecords (records) {\n const datastore = this.mapper.datastore\n\n records.forEach((record) => {\n let relatedData = this.getLocalField(record)\n\n if (utils.isFunction(this.add)) {\n relatedData = this.add(datastore, this, record)\n } else if (relatedData) {\n relatedData = this.linkRecord(record, relatedData)\n }\n\n const isEmptyLinks = !relatedData || (utils.isArray(relatedData) && !relatedData.length)\n\n if (isEmptyLinks && this.canFindLinkFor(record)) {\n relatedData = this.findExistingLinksFor(record)\n }\n\n if (relatedData) {\n this.setLocalField(record, relatedData)\n }\n })\n },\n\n removeLinkedRecords (relatedMapper, records) {\n const localField = this.localField\n records.forEach((record) => {\n utils.set(record, localField, undefined)\n })\n },\n\n linkRecord (record, relatedRecord) {\n const relatedId = utils.get(relatedRecord, this.mapper.idAttribute)\n\n if (relatedId === undefined) {\n const unsaved = this.relatedCollection.unsaved()\n if (unsaved.indexOf(relatedRecord) === -1) {\n if (this.canAutoAddLinks) {\n relatedRecord = this.relatedCollection.add(relatedRecord)\n }\n }\n } else {\n if (relatedRecord !== this.relatedCollection.get(relatedId)) {\n this.setForeignKey(record, relatedRecord)\n\n if (this.canAutoAddLinks) {\n relatedRecord = this.relatedCollection.add(relatedRecord)\n }\n }\n }\n\n return relatedRecord\n },\n\n // e.g. user hasMany post via \"foreignKey\", so find all posts of user\n findExistingLinksByForeignKey (id) {\n if (id === undefined || id === null) {\n return\n }\n return this.relatedCollection.filter({\n [this.foreignKey]: id\n })\n },\n\n ensureLinkedDataHasProperType (props, opts) {\n const relatedMapper = this.getRelation()\n const relationData = this.getLocalField(props)\n\n if (utils.isArray(relationData) && (!relationData.length || relatedMapper.is(relationData[0]))) {\n return\n }\n\n if (relationData && !relatedMapper.is(relationData)) {\n utils.set(props, this.localField, relatedMapper.createRecord(relationData, opts))\n }\n },\n\n isRequiresParentId () {\n return false\n },\n\n isRequiresChildId () {\n return false\n },\n\n createChildRecord (props, relationData, opts) {\n this.setForeignKey(props, relationData)\n\n return this.createLinked(relationData, opts).then((result) => {\n this.setLocalField(props, result)\n })\n },\n\n createLinked (props, opts) {\n const create = utils.isArray(props) ? 'createMany' : 'create'\n\n return this.getRelation()[create](props, opts)\n }\n})\n","import utils from '../utils'\nimport { Relation } from '../Relation'\n\nexport const BelongsToRelation = Relation.extend({\n getForeignKey (record) {\n return utils.get(record, this.foreignKey)\n },\n\n _setForeignKey (record, relatedRecord) {\n utils.set(record, this.foreignKey, utils.get(relatedRecord, this.getRelation().idAttribute))\n },\n\n findExistingLinksFor (record) {\n // console.log('\\tBelongsTo#findExistingLinksFor', record)\n if (!record) {\n return\n }\n const relatedId = utils.get(record, this.foreignKey)\n if (relatedId !== undefined && relatedId !== null) {\n return this.relatedCollection.get(relatedId)\n }\n },\n\n isRequiresParentId () {\n return true\n },\n\n createParentRecord (props, opts) {\n const relationData = this.getLocalField(props)\n\n return this.createLinked(relationData, opts).then((record) => {\n this.setForeignKey(props, record)\n })\n },\n\n createChildRecord () {\n throw new Error('\"BelongsTo\" relation does not support child creation as it cannot have children.')\n }\n}, {\n TYPE_NAME: 'belongsTo'\n})\n","import utils from '../utils'\nimport { Relation } from '../Relation'\n\nexport const HasManyRelation = Relation.extend({\n validateOptions (related, opts) {\n Relation.prototype.validateOptions.call(this, related, opts)\n\n const { localKeys, foreignKeys, foreignKey } = opts\n\n if (!foreignKey && !localKeys && !foreignKeys) {\n throw utils.err('new Relation', 'opts.')(400, 'string', foreignKey)\n }\n },\n\n canFindLinkFor (record) {\n const hasForeignKeys = this.foreignKey || this.foreignKeys\n return !!(hasForeignKeys || (this.localKeys && utils.get(record, this.localKeys)))\n },\n\n linkRecord (record, relatedRecords) {\n const relatedCollection = this.relatedCollection\n const canAutoAddLinks = this.canAutoAddLinks\n const foreignKey = this.foreignKey\n const unsaved = this.relatedCollection.unsaved()\n\n return relatedRecords.map((relatedRecord) => {\n const relatedId = relatedCollection.recordId(relatedRecord)\n\n if ((relatedId === undefined && unsaved.indexOf(relatedRecord) === -1) || relatedRecord !== relatedCollection.get(relatedId)) {\n if (foreignKey) {\n // TODO: slow, could be optimized? But user loses hook\n this.setForeignKey(record, relatedRecord)\n }\n if (canAutoAddLinks) {\n relatedRecord = relatedCollection.add(relatedRecord)\n }\n }\n\n return relatedRecord\n })\n },\n\n findExistingLinksFor (record) {\n const id = utils.get(record, this.mapper.idAttribute)\n const ids = this.localKeys ? utils.get(record, this.localKeys) : null\n let records\n\n if (id !== undefined && this.foreignKey) {\n records = this.findExistingLinksByForeignKey(id)\n } else if (this.localKeys && ids) {\n records = this.findExistingLinksByLocalKeys(ids)\n } else if (id !== undefined && this.foreignKeys) {\n records = this.findExistingLinksByForeignKeys(id)\n }\n\n if (records && records.length) {\n return records\n }\n },\n\n // e.g. user hasMany group via \"foreignKeys\", so find all users of a group\n findExistingLinksByLocalKeys (ids) {\n return this.relatedCollection.filter({\n where: {\n [this.relatedCollection.mapper.idAttribute]: {\n in: ids\n }\n }\n })\n },\n\n // e.g. group hasMany user via \"localKeys\", so find all groups that own a user\n findExistingLinksByForeignKeys (id) {\n return this.relatedCollection.filter({\n where: {\n [this.foreignKeys]: {\n contains: id\n }\n }\n })\n },\n\n isRequiresParentId () {\n return !!this.localKeys && this.localKeys.length > 0\n },\n\n isRequiresChildId () {\n return !!this.foreignKey\n },\n\n createParentRecord (props, opts) {\n const relationData = this.getLocalField(props)\n const foreignIdField = this.getRelation().idAttribute\n\n return this.createLinked(relationData, opts).then((records) => {\n utils.set(props, this.localKeys, records.map((record) => utils.get(record, foreignIdField)))\n })\n },\n\n createLinked (props, opts) {\n return this.getRelation().createMany(props, opts)\n }\n}, {\n TYPE_NAME: 'hasMany'\n})\n","import utils from '../utils'\nimport { Relation } from '../Relation'\n\nexport const HasOneRelation = Relation.extend({\n findExistingLinksFor (relatedMapper, record) {\n const recordId = utils.get(record, relatedMapper.idAttribute)\n const records = this.findExistingLinksByForeignKey(recordId)\n\n if (records && records.length) {\n return records[0]\n }\n },\n\n isRequiresChildId () {\n return true\n }\n}, {\n TYPE_NAME: 'hasOne'\n})\n","import { Relation } from './Relation'\nimport { BelongsToRelation } from './Relation/BelongsTo'\nimport { HasManyRelation } from './Relation/HasMany'\nimport { HasOneRelation } from './Relation/HasOne'\n\n[BelongsToRelation, HasManyRelation, HasOneRelation].forEach(RelationType => {\n Relation[RelationType.TYPE_NAME] = (related, options) => new RelationType(related, options)\n})\n\nexport { belongsToType, hasManyType, hasOneType, Relation } from './Relation'\n","import { Relation } from './relations'\n\nexport { belongsToType, hasManyType, hasOneType } from './relations'\n/**\n * BelongsTo relation decorator. You probably won't use this directly.\n *\n * @name module:js-data.belongsTo\n * @method\n * @param {Mapper} related The relation the target belongs to.\n * @param {object} opts Configuration options.\n * @param {string} opts.foreignKey The field that holds the primary key of the\n * related record.\n * @param {string} opts.localField The field that holds a reference to the\n * related record object.\n * @returns {Function} Invocation function, which accepts the target as the only\n * parameter.\n */\nexport const belongsTo = function (related, opts) {\n return function (mapper) {\n Relation.belongsTo(related, opts).assignTo(mapper)\n }\n}\n\n/**\n * HasMany relation decorator. You probably won't use this directly.\n *\n * @name module:js-data.hasMany\n * @method\n * @param {Mapper} related The relation of which the target has many.\n * @param {object} opts Configuration options.\n * @param {string} [opts.foreignKey] The field that holds the primary key of the\n * related record.\n * @param {string} opts.localField The field that holds a reference to the\n * related record object.\n * @returns {Function} Invocation function, which accepts the target as the only\n * parameter.\n */\nexport const hasMany = function (related, opts) {\n return function (mapper) {\n Relation.hasMany(related, opts).assignTo(mapper)\n }\n}\n\n/**\n * HasOne relation decorator. You probably won't use this directly.\n *\n * @name module:js-data.hasOne\n * @method\n * @param {Mapper} related The relation of which the target has one.\n * @param {object} opts Configuration options.\n * @param {string} [opts.foreignKey] The field that holds the primary key of the\n * related record.\n * @param {string} opts.localField The field that holds a reference to the\n * related record object.\n * @returns {Function} Invocation function, which accepts the target as the only\n * parameter.\n */\nexport const hasOne = function (related, opts) {\n return function (mapper) {\n Relation.hasOne(related, opts).assignTo(mapper)\n }\n}\n","import utils, { safeSetLink } from './utils'\nimport Component from './Component'\nimport Settable from './Settable'\nimport {\n hasManyType,\n hasOneType\n} from './decorators'\n\nconst DOMAIN = 'Record'\n\nconst superMethod = function (mapper, name) {\n const store = mapper.datastore\n if (store && store[name]) {\n return function (...args) {\n return store[name](mapper.name, ...args)\n }\n }\n return mapper[name].bind(mapper)\n}\n\n// Cache these strings\nconst creatingPath = 'creating'\nconst noValidatePath = 'noValidate'\nconst keepChangeHistoryPath = 'keepChangeHistory'\nconst previousPath = 'previous'\n\n/**\n * js-data's Record class. An instance of `Record` corresponds to an in-memory\n * representation of a single row or document in a database, Firebase,\n * localstorage, etc. Basically, a `Record` instance represents whatever kind of\n * entity in your persistence layer that has a primary key.\n *\n * ```javascript\n * import {Record} from 'js-data'\n * ```\n *\n * @example Record#constructor\n * const JSData = require('js-data');\n * const { Record } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * // Instantiate a plain record\n * let record = new Record();\n * console.log('record: ' + JSON.stringify(record));\n *\n * // You can supply properties on instantiation\n * record = new Record({ name: 'John' });\n * console.log('record: ' + JSON.stringify(record));\n *\n * @example Record#constructor2\n * const JSData = require('js-data');\n * const { Mapper } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * // Instantiate a record that's associated with a Mapper:\n * const UserMapper = new Mapper({ name: 'user' });\n * const User = UserMapper.recordClass;\n * const user = UserMapper.createRecord({ name: 'John' });\n * const user2 = new User({ name: 'Sally' });\n * console.log('user: ' + JSON.stringify(user));\n * console.log('user2: ' + JSON.stringify(user2));\n *\n * @example Record#constructor3\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new Container();\n * store.defineMapper('user');\n *\n * // Instantiate a record that's associated with a store's Mapper\n * const user = store.createRecord('user', { name: 'John' });\n * console.log('user: ' + JSON.stringify(user));\n *\n * @example Record#constructor4\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new Container();\n * store.defineMapper('user', {\n * schema: {\n * properties: {\n * name: { type: 'string' }\n * }\n * }\n * });\n *\n * // Validate on instantiation\n * const user = store.createRecord('user', { name: 1234 });\n * console.log('user: ' + JSON.stringify(user));\n *\n * @example Record#constructor5\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new Container();\n * store.defineMapper('user', {\n * schema: {\n * properties: {\n * name: { type: 'string' }\n * }\n * }\n * });\n *\n * // Skip validation on instantiation\n * const user = store.createRecord('user', { name: 1234 }, { noValidate: true });\n * console.log('user: ' + JSON.stringify(user));\n * console.log('user.isValid(): ' + user.isValid());\n *\n * @class Record\n * @extends Component\n * @param {object} [props] The initial properties of the new Record instance.\n * @param {object} [opts] Configuration options.\n * @param {boolean} [opts.noValidate=false] Whether to skip validation on the\n * initial properties.\n * @param {boolean} [opts.validateOnSet=true] Whether to enable setter\n * validation on properties after the Record has been initialized.\n * @since 3.0.0\n */\nfunction Record (props, opts) {\n utils.classCallCheck(this, Record)\n Settable.call(this)\n props || (props = {})\n opts || (opts = {})\n const _set = this._set\n const mapper = this.constructor.mapper\n\n _set(creatingPath, true)\n _set(noValidatePath, !!opts.noValidate)\n _set(keepChangeHistoryPath, opts.keepChangeHistory === undefined ? (mapper ? mapper.keepChangeHistory : true) : opts.keepChangeHistory)\n\n // Set the idAttribute value first, if it exists.\n const id = mapper ? utils.get(props, mapper.idAttribute) : undefined\n if (id !== undefined) {\n utils.set(this, mapper.idAttribute, id)\n }\n\n utils.fillIn(this, props)\n _set(creatingPath, false)\n if (opts.validateOnSet !== undefined) {\n _set(noValidatePath, !opts.validateOnSet)\n } else if (mapper && mapper.validateOnSet !== undefined) {\n _set(noValidatePath, !mapper.validateOnSet)\n } else {\n _set(noValidatePath, false)\n }\n _set(previousPath, mapper ? mapper.toJSON(props) : utils.plainCopy(props))\n}\n\nexport default Component.extend({\n constructor: Record,\n\n /**\n * Returns the {@link Mapper} paired with this record's class, if any.\n *\n * @method Record#_mapper\n * @returns {Mapper} The {@link Mapper} paired with this record's class, if any.\n * @since 3.0.0\n */\n _mapper () {\n const mapper = this.constructor.mapper\n if (!mapper) {\n throw utils.err(`${DOMAIN}#_mapper`, '')(404, 'mapper')\n }\n return mapper\n },\n\n /**\n * Lifecycle hook.\n *\n * @method Record#afterLoadRelations\n * @param {string[]} relations The `relations` argument passed to {@link Record#loadRelations}.\n * @param {object} opts The `opts` argument passed to {@link Record#loadRelations}.\n * @since 3.0.0\n */\n afterLoadRelations () {},\n\n /**\n * Lifecycle hook.\n *\n * @method Record#beforeLoadRelations\n * @param {string[]} relations The `relations` argument passed to {@link Record#loadRelations}.\n * @param {object} opts The `opts` argument passed to {@link Record#loadRelations}.\n * @since 3.0.0\n */\n beforeLoadRelations () {},\n\n /**\n * Return the change history of this record since it was instantiated or\n * {@link Record#commit} was called.\n *\n * @method Record#changeHistory\n * @since 3.0.0\n */\n changeHistory () {\n return (this._get('history') || []).slice()\n },\n\n /**\n * Return changes to this record since it was instantiated or\n * {@link Record#commit} was called.\n *\n * @example Record#changes\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new Container();\n * store.defineMapper('user');\n * const user = store.createRecord('user');\n * console.log('user changes: ' + JSON.stringify(user.changes()));\n * user.name = 'John';\n * console.log('user changes: ' + JSON.stringify(user.changes()));\n *\n * @method Record#changes\n * @param [opts] Configuration options.\n * @param {Function} [opts.equalsFn={@link utils.deepEqual}] Equality function.\n * @param {array} [opts.ignore=[]] Array of strings or RegExp of fields to ignore.\n * @returns {Object} Object describing the changes to this record since it was\n * instantiated or its {@link Record#commit} method was last called.\n * @since 3.0.0\n */\n changes (opts) {\n opts || (opts = {})\n return utils.diffObjects(typeof this.toJSON === 'function' ? this.toJSON(opts) : this, this._get('previous'), opts)\n },\n\n /**\n * Make the record's current in-memory state it's only state, with any\n * previous property values being set to current values.\n *\n * @example Record#commit\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new Container();\n * store.defineMapper('user');\n * const user = store.createRecord('user');\n * console.log('user hasChanges: ' + user.hasChanges());\n * user.name = 'John';\n * console.log('user hasChanges: ' + user.hasChanges());\n * user.commit();\n * console.log('user hasChanges: ' + user.hasChanges());\n *\n * @method Record#commit\n * @param {object} [opts] Configuration options. Passed to {@link Record#toJSON}.\n * @since 3.0.0\n */\n commit (opts) {\n this._set('changed') // unset\n this._set('changing', false)\n this._set('history', []) // clear history\n this._set('previous', this.toJSON(opts))\n },\n\n /**\n * Call {@link Mapper#destroy} using this record's primary key.\n *\n * @example\n * import { Container } from 'js-data';\n * import { RethinkDBAdapter } from 'js-data-rethinkdb';\n *\n * const store = new Container();\n * store.registerAdapter('rethink', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('user');\n * store.find('user', 1234).then((user) => {\n * console.log(user.id); // 1234\n *\n * // Destroy this user from the database\n * return user.destroy();\n * });\n *\n * @method Record#destroy\n * @param {object} [opts] Configuration options passed to {@link Mapper#destroy}.\n * @returns {Promise} The result of calling {@link Mapper#destroy} with the\n * primary key of this record.\n * @since 3.0.0\n */\n destroy (opts) {\n opts || (opts = {})\n const mapper = this._mapper()\n return superMethod(mapper, 'destroy')(utils.get(this, mapper.idAttribute), opts)\n },\n\n /**\n * Return the value at the given path for this instance.\n *\n * @example Record#get\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n * const store = new Container();\n * store.defineMapper('user');\n *\n * const user = store.createRecord('user', { name: 'Bob' });\n * console.log('user.get(\"name\"): ' + user.get('name'));\n *\n * @method Record#get\n * @param {string} key Path of value to retrieve.\n * @returns {*} Value at path.\n * @since 3.0.0\n */\n 'get' (key) {\n return utils.get(this, key)\n },\n\n /**\n * Return whether this record has changed since it was instantiated or\n * {@link Record#commit} was called.\n *\n * @example Record#hasChanges\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n * const store = new Container();\n * store.defineMapper('user');\n * const user = store.createRecord('user');\n * console.log('user hasChanges: ' + user.hasChanges());\n * user.name = 'John';\n * console.log('user hasChanges: ' + user.hasChanges());\n * user.commit();\n * console.log('user hasChanges: ' + user.hasChanges());\n *\n * @method Record#hasChanges\n * @param [opts] Configuration options.\n * @param {Function} [opts.equalsFn={@link utils.deepEqual}] Equality function.\n * @param {array} [opts.ignore=[]] Array of strings or RegExp of fields to ignore.\n * @returns {boolean} Return whether the record has changed since it was\n * instantiated or since its {@link Record#commit} method was called.\n * @since 3.0.0\n */\n hasChanges (opts) {\n const quickHasChanges = !!(this._get('changed') || []).length\n return quickHasChanges || utils.areDifferent(typeof this.toJSON === 'function' ? this.toJSON(opts) : this, this._get('previous'), opts)\n },\n\n /**\n * Return whether the record is unsaved. Records that have primary keys are\n * considered \"saved\". Records without primary keys are considered \"unsaved\".\n *\n * @example Record#isNew\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n * const store = new Container();\n * store.defineMapper('user');\n * const user = store.createRecord('user', {\n * id: 1234\n * });\n * const user2 = store.createRecord('user');\n * console.log('user isNew: ' + user.isNew()); // false\n * console.log('user2 isNew: ' + user2.isNew()); // true\n *\n * @method Record#isNew\n * @returns {boolean} Whether the record is unsaved.\n * @since 3.0.0\n */\n isNew (opts) {\n return utils.get(this, this._mapper().idAttribute) === undefined\n },\n\n /**\n * Return whether the record in its current state passes validation.\n *\n * @example Record#isValid\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n * const store = new Container();\n * store.defineMapper('user', {\n * schema: {\n * properties: {\n * name: { type: 'string' }\n * }\n * }\n * });\n * const user = store.createRecord('user', {\n * name: 1234\n * }, {\n * noValidate: true // this allows us to put the record into an invalid state\n * });\n * console.log('user isValid: ' + user.isValid());\n * user.name = 'John';\n * console.log('user isValid: ' + user.isValid());\n *\n * @method Record#isValid\n * @param {object} [opts] Configuration options. Passed to {@link Mapper#validate}.\n * @returns {boolean} Whether the record in its current state passes\n * validation.\n * @since 3.0.0\n */\n isValid (opts) {\n return !this._mapper().validate(this, opts)\n },\n\n removeInverseRelation (currentParent, id, inverseDef, idAttribute) {\n if (inverseDef.type === hasOneType) {\n safeSetLink(currentParent, inverseDef.localField, undefined)\n } else if (inverseDef.type === hasManyType) {\n // e.g. remove comment from otherPost.comments\n const children = utils.get(currentParent, inverseDef.localField)\n if (id === undefined) {\n utils.remove(children, (child) => child === this)\n } else {\n utils.remove(children, (child) => child === this || id === utils.get(child, idAttribute))\n }\n }\n },\n\n setupInverseRelation (record, id, inverseDef, idAttribute) {\n // Update (set) inverse relation\n if (inverseDef.type === hasOneType) {\n // e.g. someUser.profile = profile\n safeSetLink(record, inverseDef.localField, this)\n } else if (inverseDef.type === hasManyType) {\n // e.g. add comment to somePost.comments\n const children = utils.get(record, inverseDef.localField)\n if (id === undefined) {\n utils.noDupeAdd(children, this, (child) => child === this)\n } else {\n utils.noDupeAdd(children, this, (child) => child === this || id === utils.get(child, idAttribute))\n }\n }\n },\n\n /**\n * Lazy load relations of this record, to be attached to the record once their\n * loaded.\n *\n * @example\n * import { Container } from 'js-data';\n * import { RethinkDBAdapter } from 'js-data-rethinkdb';\n *\n * const store = new Container();\n * store.registerAdapter('rethink', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('user', {\n * relations: {\n * hasMany: {\n * post: {\n * localField: 'posts',\n * foreignKey: 'user_id'\n * }\n * }\n * }\n * });\n * store.defineMapper('post', {\n * relations: {\n * belongsTo: {\n * user: {\n * localField: 'user',\n * foreignKey: 'user_id'\n * }\n * }\n * }\n * });\n * store.find('user', 1234).then((user) => {\n * console.log(user.id); // 1234\n *\n * // Load the user's post relations\n * return user.loadRelations(['post']);\n * }).then((user) => {\n * console.log(user.posts); // [{...}, {...}, ...]\n * });\n *\n * @method Record#loadRelations\n * @param {string[]} [relations] List of relations to load. Can use localField\n * names or Mapper names to pick relations.\n * @param {object} [opts] Configuration options.\n * @returns {Promise} Resolves with the record, with the loaded relations now\n * attached.\n * @since 3.0.0\n */\n loadRelations (relations, opts) {\n let op\n const mapper = this._mapper()\n\n // Default values for arguments\n relations || (relations = [])\n if (utils.isString(relations)) {\n relations = [relations]\n }\n opts || (opts = {})\n opts.with = relations\n\n // Fill in \"opts\" with the Model's configuration\n utils._(opts, mapper)\n opts.adapter = mapper.getAdapterName(opts)\n\n // beforeLoadRelations lifecycle hook\n op = opts.op = 'beforeLoadRelations'\n return utils.resolve(this[op](relations, opts)).then(() => {\n // Now delegate to the adapter\n op = opts.op = 'loadRelations'\n mapper.dbg(op, this, relations, opts)\n const tasks = []\n let task\n utils.forEachRelation(mapper, opts, (def, optsCopy) => {\n const relatedMapper = def.getRelation()\n optsCopy.raw = false\n if (utils.isFunction(def.load)) {\n task = def.load(mapper, def, this, opts)\n } else if (def.type === 'hasMany' || def.type === 'hasOne') {\n if (def.foreignKey) {\n task = superMethod(relatedMapper, 'findAll')({\n [def.foreignKey]: utils.get(this, mapper.idAttribute)\n }, optsCopy).then(function (relatedData) {\n if (def.type === 'hasOne') {\n return relatedData.length ? relatedData[0] : undefined\n }\n return relatedData\n })\n } else if (def.localKeys) {\n task = superMethod(relatedMapper, 'findAll')({\n where: {\n [relatedMapper.idAttribute]: {\n in: utils.get(this, def.localKeys)\n }\n }\n })\n } else if (def.foreignKeys) {\n task = superMethod(relatedMapper, 'findAll')({\n where: {\n [def.foreignKeys]: {\n contains: utils.get(this, mapper.idAttribute)\n }\n }\n }, opts)\n }\n } else if (def.type === 'belongsTo') {\n const key = utils.get(this, def.foreignKey)\n if (utils.isSorN(key)) {\n task = superMethod(relatedMapper, 'find')(key, optsCopy)\n }\n }\n if (task) {\n task = task.then((relatedData) => {\n def.setLocalField(this, relatedData)\n })\n tasks.push(task)\n }\n })\n return Promise.all(tasks)\n }).then(() => {\n // afterLoadRelations lifecycle hook\n op = opts.op = 'afterLoadRelations'\n return utils.resolve(this[op](relations, opts)).then(() => this)\n })\n },\n\n /**\n * Return the properties with which this record was instantiated.\n *\n * @example Record#previous\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n * const store = new Container();\n * store.defineMapper('user');\n * const user = store.createRecord('user', {\n * name: 'William'\n * });\n * console.log('user previous: ' + JSON.stringify(user.previous()));\n * user.name = 'Bob';\n * console.log('user previous: ' + JSON.stringify(user.previous()));\n * user.commit();\n * console.log('user previous: ' + JSON.stringify(user.previous()));\n *\n * @method Record#previous\n * @param {string} [key] If specified, return just the initial value of the\n * given key.\n * @returns {Object} The initial properties of this record.\n * @since 3.0.0\n */\n previous (key) {\n if (key) {\n return this._get(`previous.${key}`)\n }\n return this._get('previous')\n },\n\n /**\n * Revert changes to this record back to the properties it had when it was\n * instantiated.\n *\n * @example Record#revert\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n * const store = new Container();\n * store.defineMapper('user');\n * const user = store.createRecord('user', {\n * name: 'William'\n * });\n * console.log('user: ' + JSON.stringify(user));\n * user.name = 'Bob';\n * console.log('user: ' + JSON.stringify(user));\n * user.revert();\n * console.log('user: ' + JSON.stringify(user));\n *\n * @method Record#revert\n * @param {object} [opts] Configuration options.\n * @param {string[]} [opts.preserve] Array of strings or Regular Expressions\n * denoting properties that should not be reverted.\n * @since 3.0.0\n */\n revert (opts) {\n const previous = this._get('previous')\n opts || (opts = {})\n opts.preserve || (opts.preserve = [])\n utils.forOwn(this, (value, key) => {\n if (key !== this._mapper().idAttribute && !Object.hasOwnProperty.call(previous, key) && Object.hasOwnProperty.call(this, key) && opts.preserve.indexOf(key) === -1) {\n delete this[key]\n }\n })\n utils.forOwn(previous, (value, key) => {\n if (opts.preserve.indexOf(key) === -1) {\n this[key] = value\n }\n })\n this.commit()\n },\n\n /**\n * Delegates to {@link Mapper#create} or {@link Mapper#update}.\n *\n * @example\n * import { Container } from 'js-data';\n * import { RethinkDBAdapter } from 'js-data-rethinkdb';\n *\n * const store = new Container();\n * store.registerAdapter('rethink', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('session');\n * const session = store.createRecord('session', { topic: 'Node.js' });\n *\n * // Create a new record in the database\n * session.save().then(() => {\n * console.log(session.id); // 1234\n *\n * session.skill_level = 'beginner';\n *\n * // Update the record in the database\n * return session.save();\n * });\n *\n * @method Record#save\n * @param {object} [opts] Configuration options. See {@link Mapper#create} and\n * {@link Mapper#update}.\n * @param {boolean} [opts.changesOnly] Equality function. Default uses `===`.\n * @param {Function} [opts.equalsFn] Passed to {@link Record#changes} when\n * `opts.changesOnly` is `true`.\n * @param {array} [opts.ignore] Passed to {@link Record#changes} when\n * `opts.changesOnly` is `true`.\n * @returns {Promise} The result of calling {@link Mapper#create} or\n * {@link Mapper#update}.\n * @since 3.0.0\n */\n save (opts) {\n opts || (opts = {})\n const mapper = this._mapper()\n const id = utils.get(this, mapper.idAttribute)\n let props = this\n\n const postProcess = (result) => {\n const record = opts.raw ? result.data : result\n if (record) {\n utils.deepMixIn(this, record)\n this.commit()\n }\n return result\n }\n\n if (id === undefined) {\n return superMethod(mapper, 'create')(props, opts).then(postProcess)\n }\n if (opts.changesOnly) {\n const changes = this.changes(opts)\n props = {}\n utils.fillIn(props, changes.added)\n utils.fillIn(props, changes.changed)\n }\n return superMethod(mapper, 'update')(id, props, opts).then(postProcess)\n },\n\n /**\n * Set the value for a given key, or the values for the given keys if \"key\" is\n * an object. Triggers change events on those properties that have `track: true`\n * in {@link Mapper#schema}.\n *\n * @example Record#set\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n * const store = new Container();\n * store.defineMapper('user');\n *\n * const user = store.createRecord('user');\n * console.log('user: ' + JSON.stringify(user));\n *\n * user.set('name', 'Bob');\n * console.log('user: ' + JSON.stringify(user));\n *\n * user.set({ age: 30, role: 'admin' });\n * console.log('user: ' + JSON.stringify(user));\n *\n * @fires Record#change\n * @method Record#set\n * @param {(string|Object)} key Key to set or hash of key-value pairs to set.\n * @param {*} [value] Value to set for the given key.\n * @param {object} [opts] Configuration options.\n * @param {boolean} [opts.silent=false] Whether to trigger change events.\n * @since 3.0.0\n */\n 'set' (key, value, opts) {\n if (utils.isObject(key)) {\n opts = value\n }\n opts || (opts = {})\n if (opts.silent) {\n this._set('silent', true)\n }\n utils.set(this, key, value)\n if (!this._get('eventId')) {\n this._set('silent') // unset\n }\n },\n\n /**\n * Return a plain object representation of this record. If the class from\n * which this record was created has a Mapper, then {@link Mapper#toJSON} will\n * be called with this record instead.\n *\n * @example Record#toJSON\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n * const store = new Container();\n * store.defineMapper('user', {\n * schema: {\n * properties: {\n * name: { type: 'string' }\n * }\n * }\n * });\n *\n * const user = store.createRecord('user', {\n * name: 'John',\n * $$hashKey: '1234'\n * });\n * console.log('user: ' + JSON.stringify(user.toJSON()));\n *\n * @method Record#toJSON\n * @param {object} [opts] Configuration options.\n * @param {string[]} [opts.with] Array of relation names or relation fields\n * to include in the representation. Only available as an option if the class\n * from which this record was created has a Mapper and this record resides in\n * an instance of {@link DataStore}.\n * @returns {Object} Plain object representation of this record.\n * @since 3.0.0\n */\n toJSON (opts) {\n const mapper = this.constructor.mapper\n if (mapper) {\n return mapper.toJSON(this, opts)\n } else {\n const json = {}\n utils.forOwn(this, (prop, key) => {\n json[key] = utils.plainCopy(prop)\n })\n return json\n }\n },\n\n /**\n * Unset the value for a given key. Triggers change events on those properties\n * that have `track: true` in {@link Mapper#schema}.\n *\n * @example Record#unset\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n * const store = new Container();\n * store.defineMapper('user');\n *\n * const user = store.createRecord('user', {\n * name: 'John'\n * });\n * console.log('user: ' + JSON.stringify(user));\n *\n * user.unset('name');\n * console.log('user: ' + JSON.stringify(user));\n *\n * @method Record#unset\n * @param {string} key Key to unset.\n * @param {object} [opts] Configuration options.\n * @param {boolean} [opts.silent=false] Whether to trigger change events.\n * @since 3.0.0\n */\n unset (key, opts) {\n this.set(key, undefined, opts)\n },\n\n /**\n * Validate this record based on its current properties.\n *\n * @example Record#validate\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n * const store = new Container();\n * store.defineMapper('user', {\n * schema: {\n * properties: {\n * name: { type: 'string' }\n * }\n * }\n * });\n * const user = store.createRecord('user', {\n * name: 1234\n * }, {\n * noValidate: true // this allows us to put the record into an invalid state\n * });\n * console.log('user validation: ' + JSON.stringify(user.validate()));\n * user.name = 'John';\n * console.log('user validation: ' + user.validate());\n *\n * @method Record#validate\n * @param {object} [opts] Configuration options. Passed to {@link Mapper#validate}.\n * @returns {*} Array of errors or `undefined` if no errors.\n * @since 3.0.0\n */\n validate (opts) {\n return this._mapper().validate(this, opts)\n }\n}, {\n creatingPath,\n noValidatePath,\n keepChangeHistoryPath,\n previousPath\n})\n\n/**\n * Allow records to emit events.\n *\n * An record's registered listeners are stored in the record's private data.\n */\nutils.eventify(\n Record.prototype,\n function () {\n return this._get('events')\n },\n function (value) {\n this._set('events', value)\n }\n)\n\n/**\n * Fired when a record changes. Only works for records that have tracked fields.\n * See {@link Record~changeListener} on how to listen for this event.\n *\n * @event Record#change\n * @see Record~changeListener\n */\n\n/**\n * Callback signature for the {@link Record#event:change} event.\n *\n * @example\n * function onChange (record, changes) {\n * // do something\n * }\n * record.on('change', onChange);\n *\n * @callback Record~changeListener\n * @param {Record} The Record that changed.\n * @param {object} The changes.\n * @see Record#event:change\n * @since 3.0.0\n */\n\n/**\n * Create a subclass of this Record:\n * @example Record.extend\n * const JSData = require('js-data');\n * const { Record } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * // Extend the class using ES2015 class syntax.\n * class CustomRecordClass extends Record {\n * foo () { return 'bar'; }\n * static beep () { return 'boop'; }\n * }\n * const customRecord = new CustomRecordClass();\n * console.log(customRecord.foo());\n * console.log(CustomRecordClass.beep());\n *\n * // Extend the class using alternate method.\n * const OtherRecordClass = Record.extend({\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * });\n * const otherRecord = new OtherRecordClass();\n * console.log(otherRecord.foo());\n * console.log(OtherRecordClass.beep());\n *\n * // Extend the class, providing a custom constructor.\n * function AnotherRecordClass () {\n * Record.call(this);\n * this.created_at = new Date().getTime();\n * }\n * Record.extend({\n * constructor: AnotherRecordClass,\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * });\n * const anotherRecord = new AnotherRecordClass();\n * console.log(anotherRecord.created_at);\n * console.log(anotherRecord.foo());\n * console.log(AnotherRecordClass.beep());\n *\n * @method Record.extend\n * @param {object} [props={}] Properties to add to the prototype of the\n * subclass.\n * @param {object} [props.constructor] Provide a custom constructor function\n * to be used as the subclass itself.\n * @param {object} [classProps={}] Static properties to add to the subclass.\n * @returns {Constructor} Subclass of this Record class.\n * @since 3.0.0\n */\n","export function sort (a, b, hashCode) {\n // Short-circuit comparison if a and b are strictly equal\n // This is absolutely necessary for indexed objects that\n // don't have the idAttribute field\n if (a === b) {\n return 0\n }\n if (hashCode) {\n a = hashCode(a)\n b = hashCode(b)\n }\n if ((a === null && b === null) || (a === undefined && b === undefined)) {\n return -1\n }\n\n if (a === null || a === undefined) {\n return -1\n }\n\n if (b === null || b === undefined) {\n return 1\n }\n\n if (a < b) {\n return -1\n }\n\n if (a > b) {\n return 1\n }\n\n return 0\n}\n\nexport function insertAt (array, index, value) {\n array.splice(index, 0, value)\n return array\n}\n\nexport function removeAt (array, index) {\n array.splice(index, 1)\n return array\n}\n\nexport function binarySearch (array, value, field) {\n let lo = 0\n let hi = array.length\n let compared\n let mid\n\n while (lo < hi) {\n mid = ((lo + hi) / 2) | 0\n compared = sort(value, array[mid], field)\n if (compared === 0) {\n return {\n found: true,\n index: mid\n }\n } else if (compared < 0) {\n hi = mid\n } else {\n lo = mid + 1\n }\n }\n\n return {\n found: false,\n index: hi\n }\n}\n","// Copyright (c) 2015, InternalFX.\n\n// Permission to use, copy, modify, and/or distribute this software for any purpose with or\n// without fee is hereby granted, provided that the above copyright notice and this permission\n// notice appear in all copies.\n\n// THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO\n// THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT\n// SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR\n// ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION\n// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE\n// USE OR PERFORMANCE OF THIS SOFTWARE.\n\n// Modifications\n// Copyright 2015-2016 Jason Dobry\n//\n// Summary of modifications:\n// Reworked dependencies so as to re-use code already in js-data\n// Removed unused code\nimport utils from '../../src/utils'\nimport { binarySearch, insertAt, removeAt } from './_utils'\n\nexport default function Index (fieldList, opts) {\n utils.classCallCheck(this, Index)\n fieldList || (fieldList = [])\n\n if (!utils.isArray(fieldList)) {\n throw new Error('fieldList must be an array.')\n }\n\n opts || (opts = {})\n this.fieldList = fieldList\n this.fieldGetter = opts.fieldGetter\n this.hashCode = opts.hashCode\n this.isIndex = true\n this.keys = []\n this.values = []\n}\n\nutils.addHiddenPropsToTarget(Index.prototype, {\n 'set' (keyList, value) {\n if (!utils.isArray(keyList)) {\n keyList = [keyList]\n }\n\n const key = keyList.shift() || undefined\n const pos = binarySearch(this.keys, key)\n\n if (keyList.length === 0) {\n if (pos.found) {\n const dataLocation = binarySearch(this.values[pos.index], value, this.hashCode)\n if (!dataLocation.found) {\n insertAt(this.values[pos.index], dataLocation.index, value)\n }\n } else {\n insertAt(this.keys, pos.index, key)\n insertAt(this.values, pos.index, [value])\n }\n } else {\n if (pos.found) {\n this.values[pos.index].set(keyList, value)\n } else {\n insertAt(this.keys, pos.index, key)\n const newIndex = new Index([], { hashCode: this.hashCode })\n newIndex.set(keyList, value)\n insertAt(this.values, pos.index, newIndex)\n }\n }\n },\n\n 'get' (keyList) {\n if (!utils.isArray(keyList)) {\n keyList = [keyList]\n }\n\n const key = keyList.shift() || undefined\n const pos = binarySearch(this.keys, key)\n\n if (keyList.length === 0) {\n if (pos.found) {\n if (this.values[pos.index].isIndex) {\n return this.values[pos.index].getAll()\n } else {\n return this.values[pos.index].slice()\n }\n } else {\n return []\n }\n } else {\n if (pos.found) {\n return this.values[pos.index].get(keyList)\n } else {\n return []\n }\n }\n },\n\n getAll (opts) {\n opts || (opts = {})\n let results = []\n const values = this.values\n if (opts.order === 'desc') {\n for (let i = values.length - 1; i >= 0; i--) {\n const value = values[i]\n if (value.isIndex) {\n results = results.concat(value.getAll(opts))\n } else {\n results = results.concat(value)\n }\n }\n } else {\n for (let i = 0; i < values.length; i++) {\n const value = values[i]\n if (value.isIndex) {\n results = results.concat(value.getAll(opts))\n } else {\n results = results.concat(value)\n }\n }\n }\n return results\n },\n\n visitAll (cb, thisArg) {\n this.values.forEach(function (value) {\n if (value.isIndex) {\n value.visitAll(cb, thisArg)\n } else {\n value.forEach(cb, thisArg)\n }\n })\n },\n\n between (leftKeys, rightKeys, opts) {\n opts || (opts = {})\n if (!utils.isArray(leftKeys)) {\n leftKeys = [leftKeys]\n }\n if (!utils.isArray(rightKeys)) {\n rightKeys = [rightKeys]\n }\n utils.fillIn(opts, {\n leftInclusive: true,\n rightInclusive: false,\n limit: undefined,\n offset: 0\n })\n\n const results = this._between(leftKeys, rightKeys, opts)\n\n if (opts.limit) {\n return results.slice(opts.offset, opts.limit + opts.offset)\n } else {\n return results.slice(opts.offset)\n }\n },\n\n _between (leftKeys, rightKeys, opts) {\n let results = []\n\n const leftKey = leftKeys.shift()\n const rightKey = rightKeys.shift()\n\n let pos\n\n if (leftKey !== undefined) {\n pos = binarySearch(this.keys, leftKey)\n } else {\n pos = {\n found: false,\n index: 0\n }\n }\n\n if (leftKeys.length === 0) {\n if (pos.found && opts.leftInclusive === false) {\n pos.index += 1\n }\n\n for (let i = pos.index; i < this.keys.length; i += 1) {\n if (rightKey !== undefined) {\n if (opts.rightInclusive) {\n if (this.keys[i] > rightKey) { break }\n } else {\n if (this.keys[i] >= rightKey) { break }\n }\n }\n\n if (this.values[i].isIndex) {\n results = results.concat(this.values[i].getAll())\n } else {\n results = results.concat(this.values[i])\n }\n\n if (opts.limit) {\n if (results.length >= (opts.limit + opts.offset)) {\n break\n }\n }\n }\n } else {\n for (let i = pos.index; i < this.keys.length; i += 1) {\n const currKey = this.keys[i]\n if (currKey > rightKey) { break }\n\n if (this.values[i].isIndex) {\n if (currKey === leftKey) {\n results = results.concat(this.values[i]._between(utils.copy(leftKeys), rightKeys.map(function () { return undefined }), opts))\n } else if (currKey === rightKey) {\n results = results.concat(this.values[i]._between(leftKeys.map(function () { return undefined }), utils.copy(rightKeys), opts))\n } else {\n results = results.concat(this.values[i].getAll())\n }\n } else {\n results = results.concat(this.values[i])\n }\n\n if (opts.limit) {\n if (results.length >= (opts.limit + opts.offset)) {\n break\n }\n }\n }\n }\n\n if (opts.limit) {\n return results.slice(0, opts.limit + opts.offset)\n } else {\n return results\n }\n },\n\n peek () {\n if (this.values.length) {\n if (this.values[0].isIndex) {\n return this.values[0].peek()\n } else {\n return this.values[0]\n }\n }\n return []\n },\n\n clear () {\n this.keys = []\n this.values = []\n },\n\n insertRecord (data) {\n const keyList = this.fieldList.map(function (field) {\n if (utils.isFunction(field)) {\n return field(data) || undefined\n } else {\n return data[field] || undefined\n }\n })\n this.set(keyList, data)\n },\n\n removeRecord (data) {\n let removed\n const isUnique = this.hashCode(data) !== undefined\n this.values.forEach((value, i) => {\n if (value.isIndex) {\n if (value.removeRecord(data)) {\n if (value.keys.length === 0) {\n removeAt(this.keys, i)\n removeAt(this.values, i)\n }\n removed = true\n return false\n }\n } else {\n let dataLocation = {}\n if (this.keys[i] === undefined || !isUnique) {\n for (let j = value.length - 1; j >= 0; j--) {\n if (value[j] === data) {\n dataLocation = {\n found: true,\n index: j\n }\n break\n }\n }\n } else if (isUnique) {\n dataLocation = binarySearch(value, data, this.hashCode)\n }\n if (dataLocation.found) {\n removeAt(value, dataLocation.index)\n if (value.length === 0) {\n removeAt(this.keys, i)\n removeAt(this.values, i)\n }\n removed = true\n return false\n }\n }\n })\n return removed ? data : undefined\n },\n\n updateRecord (data) {\n const removed = this.removeRecord(data)\n if (removed !== undefined) {\n this.insertRecord(data)\n }\n }\n})\n","import utils from './utils'\nimport Component from './Component'\nimport Query from './Query'\nimport Record from './Record'\nimport Index from '../lib/mindex/index'\n\nconst { noValidatePath } = Record\n\nconst DOMAIN = 'Collection'\n\nconst COLLECTION_DEFAULTS = {\n /**\n * Whether to call {@link Record#commit} on records that are added to the\n * collection and already exist in the collection.\n *\n * @name Collection#commitOnMerge\n * @type {boolean}\n * @default true\n */\n commitOnMerge: true,\n\n /**\n * Whether record events should bubble up and be emitted by the collection.\n *\n * @name Collection#emitRecordEvents\n * @type {boolean}\n * @default true\n */\n emitRecordEvents: true,\n\n /**\n * Field to be used as the unique identifier for records in this collection.\n * Defaults to `\"id\"` unless {@link Collection#mapper} is set, in which case\n * this will default to {@link Mapper#idAttribute}.\n *\n * @name Collection#idAttribute\n * @type {string}\n * @default \"id\"\n */\n idAttribute: 'id',\n\n /**\n * What to do when inserting a record into this Collection that shares a\n * primary key with a record already in this Collection.\n *\n * Possible values:\n * merge\n * replace\n * skip\n *\n * Merge:\n *\n * Recursively shallow copy properties from the new record onto the existing\n * record.\n *\n * Replace:\n *\n * Shallow copy top-level properties from the new record onto the existing\n * record. Any top-level own properties of the existing record that are _not_\n * on the new record will be removed.\n *\n * Skip:\n *\n * Ignore new record, keep existing record.\n *\n * @name Collection#onConflict\n * @type {string}\n * @default \"merge\"\n */\n onConflict: 'merge'\n}\n\n/**\n * An ordered set of {@link Record} instances.\n *\n * @example Collection#constructor\n * // import { Collection, Record } from 'js-data';\n * const JSData = require('js-data');\n * const {Collection, Record} = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const user1 = new Record({ id: 1 });\n * const user2 = new Record({ id: 2 });\n * const UserCollection = new Collection([user1, user2]);\n * console.log(UserCollection.get(1) === user1);\n *\n * @class Collection\n * @extends Component\n * @param {array} [records] Initial set of records to insert into the\n * collection.\n * @param {object} [opts] Configuration options.\n * @param {string} [opts.commitOnMerge] See {@link Collection#commitOnMerge}.\n * @param {string} [opts.idAttribute] See {@link Collection#idAttribute}.\n * @param {string} [opts.onConflict=\"merge\"] See {@link Collection#onConflict}.\n * @param {string} [opts.mapper] See {@link Collection#mapper}.\n * @since 3.0.0\n */\nfunction Collection (records, opts) {\n utils.classCallCheck(this, Collection)\n Component.call(this, opts)\n\n if (records && !utils.isArray(records)) {\n opts = records\n records = []\n }\n if (utils.isString(opts)) {\n opts = { idAttribute: opts }\n }\n\n // Default values for arguments\n records || (records = [])\n opts || (opts = {})\n\n Object.defineProperties(this, {\n /**\n * Default Mapper for this collection. Optional. If a Mapper is provided, then\n * the collection will use the {@link Mapper#idAttribute} setting, and will\n * wrap records in {@link Mapper#recordClass}.\n *\n * @example Collection#mapper\n * const JSData = require('js-data');\n * const {Collection, Mapper} = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * class MyMapperClass extends Mapper {\n * foo () { return 'bar'; }\n * }\n * const myMapper = new MyMapperClass({ name: 'myMapper' });\n * const collection = new Collection(null, { mapper: myMapper });\n *\n * @name Collection#mapper\n * @type {Mapper}\n * @default null\n * @since 3.0.0\n */\n mapper: {\n value: undefined,\n writable: true\n },\n // Query class used by this collection\n queryClass: {\n value: undefined,\n writable: true\n }\n })\n\n // Apply user-provided configuration\n utils.fillIn(this, opts)\n // Fill in any missing options with the defaults\n utils.fillIn(this, utils.copy(COLLECTION_DEFAULTS))\n\n if (!this.queryClass) {\n this.queryClass = Query\n }\n\n const idAttribute = this.recordId()\n\n Object.defineProperties(this, {\n /**\n * The main index, which uses @{link Collection#recordId} as the key.\n *\n * @name Collection#index\n * @type {Index}\n */\n index: {\n value: new Index([idAttribute], {\n hashCode (obj) {\n return utils.get(obj, idAttribute)\n }\n })\n },\n\n /**\n * Object that holds the secondary indexes of this collection.\n *\n * @name Collection#indexes\n * @type {Object.}\n */\n indexes: {\n value: {}\n }\n })\n\n // Insert initial data into the collection\n if (utils.isObject(records) || (utils.isArray(records) && records.length)) {\n this.add(records)\n }\n}\n\nexport default Component.extend({\n constructor: Collection,\n\n /**\n * Used to bind to events emitted by records in this Collection.\n *\n * @method Collection#_onRecordEvent\n * @since 3.0.0\n * @private\n * @param {...*} [arg] Args passed to {@link Collection#emit}.\n */\n _onRecordEvent (...args) {\n if (this.emitRecordEvents) {\n this.emit(...args)\n }\n },\n\n /**\n * Insert the provided record or records.\n *\n * If a record is already in the collection then the provided record will\n * either merge with or replace the existing record based on the value of the\n * `onConflict` option.\n *\n * The collection's secondary indexes will be updated as each record is\n * visited.\n *\n * @method Collection#add\n * @since 3.0.0\n * @param {(Object|Object[]|Record|Record[])} data The record or records to insert.\n * @param {object} [opts] Configuration options.\n * @param {boolean} [opts.commitOnMerge=true] See {@link Collection#commitOnMerge}.\n * @param {boolean} [opts.noValidate] See {@link Record#noValidate}.\n * @param {string} [opts.onConflict] See {@link Collection#onConflict}.\n * @returns {(Object|Object[]|Record|Record[])} The added record or records.\n */\n add (records, opts) {\n // Default values for arguments\n opts || (opts = {})\n\n // Fill in \"opts\" with the Collection's configuration\n utils._(opts, this)\n records = this.beforeAdd(records, opts) || records\n\n // Track whether just one record or an array of records is being inserted\n let singular = false\n const idAttribute = this.recordId()\n if (!utils.isArray(records)) {\n if (utils.isObject(records)) {\n records = [records]\n singular = true\n } else {\n throw utils.err(`${DOMAIN}#add`, 'records')(\n 400,\n 'object or array',\n records\n )\n }\n }\n\n // Map the provided records to existing records.\n // New records will be inserted. If any records map to existing records,\n // they will be merged into the existing records according to the onConflict\n // option.\n records = records.map(record => {\n const id = this.recordId(record)\n // Grab existing record if there is one\n const existing = id === undefined ? id : this.get(id)\n // If the currently visited record is just a reference to an existing\n // record, then there is nothing to be done. Exit early.\n if (record === existing) {\n return existing\n }\n\n if (existing) {\n // Here, the currently visited record corresponds to a record already\n // in the collection, so we need to merge them\n const onConflict = opts.onConflict || this.onConflict\n if (\n onConflict !== 'merge' &&\n onConflict !== 'replace' &&\n onConflict !== 'skip'\n ) {\n throw utils.err(`${DOMAIN}#add`, 'opts.onConflict')(\n 400,\n 'one of (merge, replace, skip)',\n onConflict,\n true\n )\n }\n const existingNoValidate = existing._get(noValidatePath)\n if (opts.noValidate) {\n // Disable validation\n existing._set(noValidatePath, true)\n }\n if (onConflict === 'merge') {\n utils.deepMixIn(existing, record)\n } else if (onConflict === 'replace') {\n utils.forOwn(existing, (value, key) => {\n if (key !== idAttribute && record[key] === undefined) {\n existing[key] = undefined\n }\n })\n existing.set(record)\n } // else if(onConflict === 'skip'){ do nothing }\n\n if (opts.noValidate) {\n // Restore previous `noValidate` value\n existing._set(noValidatePath, existingNoValidate)\n }\n record = existing\n if (opts.commitOnMerge && utils.isFunction(record.commit)) {\n record.commit()\n }\n // Update all indexes in the collection\n this.updateIndexes(record)\n } else {\n // Here, the currently visted record does not correspond to any record\n // in the collection, so (optionally) instantiate this record and insert\n // it into the collection\n record = this.mapper ? this.mapper.createRecord(record, opts) : record\n this.index.insertRecord(record)\n utils.forOwn(this.indexes, function (index, name) {\n index.insertRecord(record)\n })\n if (record && utils.isFunction(record.on)) {\n record.on('all', this._onRecordEvent, this)\n }\n }\n return record\n })\n // Finally, return the inserted data\n const result = singular ? records[0] : records\n if (!opts.silent) {\n this.emit('add', result)\n }\n return this.afterAdd(records, opts, result) || result\n },\n\n /**\n * Lifecycle hook called by {@link Collection#add}. If this method returns a\n * value then {@link Collection#add} will return that same value.\n *\n * @method Collection#method\n * @since 3.0.0\n * @param {(Object|Object[]|Record|Record[])} result The record or records\n * that were added to this Collection by {@link Collection#add}.\n * @param {object} opts The `opts` argument passed to {@link Collection#add}.\n */\n afterAdd () {},\n\n /**\n * Lifecycle hook called by {@link Collection#remove}. If this method returns\n * a value then {@link Collection#remove} will return that same value.\n *\n * @method Collection#afterRemove\n * @since 3.0.0\n * @param {(string|number)} id The `id` argument passed to {@link Collection#remove}.\n * @param {object} opts The `opts` argument passed to {@link Collection#remove}.\n * @param {object} record The result that will be returned by {@link Collection#remove}.\n */\n afterRemove () {},\n\n /**\n * Lifecycle hook called by {@link Collection#removeAll}. If this method\n * returns a value then {@link Collection#removeAll} will return that same\n * value.\n *\n * @method Collection#afterRemoveAll\n * @since 3.0.0\n * @param {object} query The `query` argument passed to {@link Collection#removeAll}.\n * @param {object} opts The `opts` argument passed to {@link Collection#removeAll}.\n * @param {object} records The result that will be returned by {@link Collection#removeAll}.\n */\n afterRemoveAll () {},\n\n /**\n * Lifecycle hook called by {@link Collection#add}. If this method returns a\n * value then the `records` argument in {@link Collection#add} will be\n * re-assigned to the returned value.\n *\n * @method Collection#beforeAdd\n * @since 3.0.0\n * @param {(Object|Object[]|Record|Record[])} records The `records` argument passed to {@link Collection#add}.\n * @param {object} opts The `opts` argument passed to {@link Collection#add}.\n */\n beforeAdd () {},\n\n /**\n * Lifecycle hook called by {@link Collection#remove}.\n *\n * @method Collection#beforeRemove\n * @since 3.0.0\n * @param {(string|number)} id The `id` argument passed to {@link Collection#remove}.\n * @param {object} opts The `opts` argument passed to {@link Collection#remove}.\n */\n beforeRemove () {},\n\n /**\n * Lifecycle hook called by {@link Collection#removeAll}.\n *\n * @method Collection#beforeRemoveAll\n * @since 3.0.0\n * @param {object} query The `query` argument passed to {@link Collection#removeAll}.\n * @param {object} opts The `opts` argument passed to {@link Collection#removeAll}.\n */\n beforeRemoveAll () {},\n\n /**\n * Find all records between two boundaries.\n *\n * Shortcut for `collection.query().between(18, 30, { index: 'age' }).run()`\n *\n * @example\n * // Get all users ages 18 to 30\n * const users = collection.between(18, 30, { index: 'age' });\n *\n * @example\n * // Same as above\n * const users = collection.between([18], [30], { index: 'age' });\n *\n * @method Collection#between\n * @since 3.0.0\n * @param {array} leftKeys Keys defining the left boundary.\n * @param {array} rightKeys Keys defining the right boundary.\n * @param {object} [opts] Configuration options.\n * @param {string} [opts.index] Name of the secondary index to use in the\n * query. If no index is specified, the main index is used.\n * @param {boolean} [opts.leftInclusive=true] Whether to include records\n * on the left boundary.\n * @param {boolean} [opts.rightInclusive=false] Whether to include records\n * on the left boundary.\n * @param {boolean} [opts.limit] Limit the result to a certain number.\n * @param {boolean} [opts.offset] The number of resulting records to skip.\n * @returns {Object[]|Record[]} The result.\n */\n between (leftKeys, rightKeys, opts) {\n return this.query()\n .between(leftKeys, rightKeys, opts)\n .run()\n },\n\n /**\n * Create a new secondary index on the contents of the collection.\n *\n * @example\n * // Index users by age\n * collection.createIndex('age');\n *\n * @example\n * // Index users by status and role\n * collection.createIndex('statusAndRole', ['status', 'role']);\n *\n * @method Collection#createIndex\n * @since 3.0.0\n * @param {string} name The name of the new secondary index.\n * @param {string[]} [fieldList] Array of field names to use as the key or\n * compound key of the new secondary index. If no fieldList is provided, then\n * the name will also be the field that is used to index the collection.\n */\n createIndex (name, fieldList, opts) {\n if (utils.isString(name) && fieldList === undefined) {\n fieldList = [name]\n }\n opts || (opts = {})\n opts.hashCode || (opts.hashCode = obj => this.recordId(obj))\n const index = (this.indexes[name] = new Index(fieldList, opts))\n this.index.visitAll(index.insertRecord, index)\n },\n\n /**\n * Find the record or records that match the provided query or pass the\n * provided filter function.\n *\n * Shortcut for `collection.query().filter(queryOrFn[, thisArg]).run()`\n *\n * @example Collection#filter\n * const JSData = require('js-data');\n * const { Collection } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const collection = new Collection([\n * { id: 1, status: 'draft', created_at_timestamp: new Date().getTime() }\n * ]);\n *\n * // Get the draft posts created less than three months ago\n * let posts = collection.filter({\n * where: {\n * status: {\n * '==': 'draft'\n * },\n * created_at_timestamp: {\n * '>=': (new Date().getTime() - (1000 \\* 60 \\* 60 \\* 24 \\* 30 \\* 3)) // 3 months ago\n * }\n * }\n * });\n * console.log(posts);\n *\n * // Use a custom filter function\n * posts = collection.filter((post) => post.id % 2 === 0);\n *\n * @method Collection#filter\n * @param {(Object|Function)} [queryOrFn={}] Selection query or filter\n * function.\n * @param {object} [thisArg] Context to which to bind `queryOrFn` if\n * `queryOrFn` is a function.\n * @returns {Array} The result.\n * @see query\n * @since 3.0.0\n */\n filter (query, thisArg) {\n return this.query()\n .filter(query, thisArg)\n .run()\n },\n\n /**\n * Iterate over all records.\n *\n * @example\n * collection.forEach(function (record) {\n * // do something\n * });\n *\n * @method Collection#forEach\n * @since 3.0.0\n * @param {Function} forEachFn Iteration function.\n * @param {*} [thisArg] Context to which to bind `forEachFn`.\n * @returns {Array} The result.\n */\n forEach (cb, thisArg) {\n this.index.visitAll(cb, thisArg)\n },\n\n /**\n * Get the record with the given id.\n *\n * @method Collection#get\n * @since 3.0.0\n * @param {(string|number)} id The primary key of the record to get.\n * @returns {(Object|Record)} The record with the given id.\n */\n get (id) {\n const instances =\n id === undefined\n ? []\n : this.query()\n .get(id)\n .run()\n return instances.length ? instances[0] : undefined\n },\n\n /**\n * Find the record or records that match the provided keyLists.\n *\n * Shortcut for `collection.query().getAll(keyList1, keyList2, ...).run()`\n *\n * @example\n * // Get the posts where \"status\" is \"draft\" or \"inReview\"\n * const posts = collection.getAll('draft', 'inReview', { index: 'status' });\n *\n * @example\n * // Same as above\n * const posts = collection.getAll(['draft'], ['inReview'], { index: 'status' });\n *\n * @method Collection#getAll\n * @since 3.0.0\n * @param {...Array} [keyList] Provide one or more keyLists, and all\n * records matching each keyList will be retrieved. If no keyLists are\n * provided, all records will be returned.\n * @param {object} [opts] Configuration options.\n * @param {string} [opts.index] Name of the secondary index to use in the\n * query. If no index is specified, the main index is used.\n * @returns {Array} The result.\n */\n getAll (...args) {\n return this.query()\n .getAll(...args)\n .run()\n },\n\n /**\n * Return the index with the given name. If no name is provided, return the\n * main index. Throws an error if the specified index does not exist.\n *\n * @method Collection#getIndex\n * @since 3.0.0\n * @param {string} [name] The name of the index to retrieve.\n */\n getIndex (name) {\n const index = name ? this.indexes[name] : this.index\n if (!index) {\n throw utils.err(`${DOMAIN}#getIndex`, name)(404, 'index')\n }\n return index\n },\n\n /**\n * Limit the result.\n *\n * Shortcut for `collection.query().limit(maximumNumber).run()`\n *\n * @example\n * const posts = collection.limit(10);\n *\n * @method Collection#limit\n * @since 3.0.0\n * @param {number} num The maximum number of records to keep in the result.\n * @returns {Array} The result.\n */\n limit (num) {\n return this.query()\n .limit(num)\n .run()\n },\n\n /**\n * Apply a mapping function to all records.\n *\n * @example\n * const names = collection.map((user) => user.name);\n *\n * @method Collection#map\n * @since 3.0.0\n * @param {Function} mapFn Mapping function.\n * @param {*} [thisArg] Context to which to bind `mapFn`.\n * @returns {Array} The result of the mapping.\n */\n map (cb, thisArg) {\n const data = []\n this.index.visitAll(function (value) {\n data.push(cb.call(thisArg, value))\n })\n return data\n },\n\n /**\n * Return the result of calling the specified function on each record in this\n * collection's main index.\n *\n * @method Collection#mapCall\n * @since 3.0.0\n * @param {string} funcName Name of function to call\n * @parama {...*} [args] Remaining arguments to be passed to the function.\n * @returns {Array} The result.\n */\n mapCall (funcName, ...args) {\n const data = []\n this.index.visitAll(function (record) {\n data.push(record[funcName](...args))\n })\n return data\n },\n\n /**\n * Return all \"unsaved\" (not uniquely identifiable) records in this colleciton.\n *\n * @method Collection#prune\n * @param {object} [opts] Configuration options, passed to {@link Collection#removeAll}.\n * @since 3.0.0\n * @returns {Array} The removed records, if any.\n */\n prune (opts) {\n return this.removeAll(this.unsaved(), opts)\n },\n\n /**\n * Create a new query to be executed against the contents of the collection.\n * The result will be all or a subset of the contents of the collection.\n *\n * @example\n * // Grab page 2 of users between ages 18 and 30\n * collection.query()\n * .between(18, 30, { index: 'age' }) // between ages 18 and 30\n * .skip(10) // second page\n * .limit(10) // page size\n * .run();\n *\n * @method Collection#query\n * @since 3.0.0\n * @returns {Query} New query object.\n */\n query () {\n const Ctor = this.queryClass\n return new Ctor(this)\n },\n\n /**\n * Return the primary key of the given, or if no record is provided, return the\n * name of the field that holds the primary key of records in this Collection.\n *\n * @method Collection#recordId\n * @since 3.0.0\n * @param {(Object|Record)} [record] The record whose primary key is to be\n * returned.\n * @returns {(string|number)} Primary key or name of field that holds primary\n * key.\n */\n recordId (record) {\n if (record) {\n return utils.get(record, this.recordId())\n }\n return this.mapper ? this.mapper.idAttribute : this.idAttribute\n },\n\n /**\n * Reduce the data in the collection to a single value and return the result.\n *\n * @example\n * const totalVotes = collection.reduce((prev, record) => {\n * return prev + record.upVotes + record.downVotes;\n * }, 0);\n *\n * @method Collection#reduce\n * @since 3.0.0\n * @param {Function} cb Reduction callback.\n * @param {*} initialValue Initial value of the reduction.\n * @returns {*} The result.\n */\n reduce (cb, initialValue) {\n const data = this.getAll()\n return data.reduce(cb, initialValue)\n },\n\n /**\n * Remove the record with the given id from this Collection.\n *\n * @method Collection#remove\n * @since 3.0.0\n * @param {(string|number|object|Record)} idOrRecord The primary key of the\n * record to be removed, or a reference to the record that is to be removed.\n * @param {object} [opts] Configuration options.\n * @returns {Object|Record} The removed record, if any.\n */\n remove (idOrRecord, opts) {\n // Default values for arguments\n opts || (opts = {})\n this.beforeRemove(idOrRecord, opts)\n let record = utils.isSorN(idOrRecord) ? this.get(idOrRecord) : idOrRecord\n\n // The record is in the collection, remove it\n if (utils.isObject(record)) {\n record = this.index.removeRecord(record)\n if (record) {\n utils.forOwn(this.indexes, function (index, name) {\n index.removeRecord(record)\n })\n if (utils.isFunction(record.off)) {\n record.off('all', this._onRecordEvent, this)\n }\n if (!opts.silent) {\n this.emit('remove', record)\n }\n }\n }\n return this.afterRemove(idOrRecord, opts, record) || record\n },\n\n /**\n * Remove from this collection the given records or the records selected by\n * the given \"query\".\n *\n * @method Collection#removeAll\n * @since 3.0.0\n * @param {Object|Object[]|Record[]} [queryOrRecords={}] Records to be removed or selection query. See {@link query}.\n * @param {object} [queryOrRecords.where] See {@link query.where}.\n * @param {number} [queryOrRecords.offset] See {@link query.offset}.\n * @param {number} [queryOrRecords.limit] See {@link query.limit}.\n * @param {string|Array[]} [queryOrRecords.orderBy] See {@link query.orderBy}.\n * @param {object} [opts] Configuration options.\n * @returns {(Object[]|Record[])} The removed records, if any.\n */\n removeAll (queryOrRecords, opts) {\n // Default values for arguments\n opts || (opts = {})\n this.beforeRemoveAll(queryOrRecords, opts)\n let records = utils.isArray(queryOrRecords)\n ? queryOrRecords.slice()\n : this.filter(queryOrRecords)\n\n // Remove each selected record from the collection\n const optsCopy = utils.plainCopy(opts)\n optsCopy.silent = true\n records = records\n .map(record => this.remove(record, optsCopy))\n .filter(record => record)\n if (!opts.silent) {\n this.emit('remove', records)\n }\n return this.afterRemoveAll(queryOrRecords, opts, records) || records\n },\n\n /**\n * Skip a number of results.\n *\n * Shortcut for `collection.query().skip(numberToSkip).run()`\n *\n * @example\n * const posts = collection.skip(10);\n *\n * @method Collection#skip\n * @since 3.0.0\n * @param {number} num The number of records to skip.\n * @returns {Array} The result.\n */\n skip (num) {\n return this.query()\n .skip(num)\n .run()\n },\n\n /**\n * Return the plain JSON representation of all items in this collection.\n * Assumes records in this collection have a toJSON method.\n *\n * @method Collection#toJSON\n * @since 3.0.0\n * @param {object} [opts] Configuration options.\n * @param {string[]} [opts.with] Array of relation names or relation fields\n * to include in the representation.\n * @returns {Array} The records.\n */\n toJSON (opts) {\n return this.mapCall('toJSON', opts)\n },\n\n /**\n * Return all \"unsaved\" (not uniquely identifiable) records in this colleciton.\n *\n * @method Collection#unsaved\n * @since 3.0.0\n * @returns {Array} The unsaved records, if any.\n */\n unsaved (opts) {\n return this.index.get()\n },\n\n /**\n * Update a record's position in a single index of this collection. See\n * {@link Collection#updateIndexes} to update a record's position in all\n * indexes at once.\n *\n * @method Collection#updateIndex\n * @since 3.0.0\n * @param {object} record The record to update.\n * @param {object} [opts] Configuration options.\n * @param {string} [opts.index] The index in which to update the record's\n * position. If you don't specify an index then the record will be updated\n * in the main index.\n */\n updateIndex (record, opts) {\n opts || (opts = {})\n this.getIndex(opts.index).updateRecord(record)\n },\n\n /**\n * Updates all indexes in this collection for the provided record. Has no\n * effect if the record is not in the collection.\n *\n * @method Collection#updateIndexes\n * @since 3.0.0\n * @param {object} record TODO\n */\n updateIndexes (record) {\n this.index.updateRecord(record)\n utils.forOwn(this.indexes, function (index, name) {\n index.updateRecord(record)\n })\n }\n})\n\n/**\n * Fired when a record changes. Only works for records that have tracked changes.\n * See {@link Collection~changeListener} on how to listen for this event.\n *\n * @event Collection#change\n * @see Collection~changeListener\n */\n\n/**\n * Callback signature for the {@link Collection#event:change} event.\n *\n * @example\n * function onChange (record, changes) {\n * // do something\n * }\n * collection.on('change', onChange);\n *\n * @callback Collection~changeListener\n * @param {Record} The Record that changed.\n * @param {object} The changes.\n * @see Collection#event:change\n * @since 3.0.0\n */\n\n/**\n * Fired when one or more records are added to the Collection. See\n * {@link Collection~addListener} on how to listen for this event.\n *\n * @event Collection#add\n * @see Collection~addListener\n * @see Collection#event:add\n * @see Collection#add\n */\n\n/**\n * Callback signature for the {@link Collection#event:add} event.\n *\n * @example\n * function onAdd (recordOrRecords) {\n * // do something\n * }\n * collection.on('add', onAdd);\n *\n * @callback Collection~addListener\n * @param {Record|Record[]} The Record or Records that were added.\n * @see Collection#event:add\n * @see Collection#add\n * @since 3.0.0\n */\n\n/**\n * Fired when one or more records are removed from the Collection. See\n * {@link Collection~removeListener} for how to listen for this event.\n *\n * @event Collection#remove\n * @see Collection~removeListener\n * @see Collection#event:remove\n * @see Collection#remove\n * @see Collection#removeAll\n */\n\n/**\n * Callback signature for the {@link Collection#event:remove} event.\n *\n * @example\n * function onRemove (recordsOrRecords) {\n * // do something\n * }\n * collection.on('remove', onRemove);\n *\n * @callback Collection~removeListener\n * @param {Record|Record[]} Record or Records that were removed.\n * @see Collection#event:remove\n * @see Collection#remove\n * @see Collection#removeAll\n * @since 3.0.0\n */\n\n/**\n * Create a subclass of this Collection:\n * @example Collection.extend\n * const JSData = require('js-data');\n * const { Collection } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * // Extend the class using ES2015 class syntax.\n * class CustomCollectionClass extends Collection {\n * foo () { return 'bar'; }\n * static beep () { return 'boop'; }\n * }\n * const customCollection = new CustomCollectionClass();\n * console.log(customCollection.foo());\n * console.log(CustomCollectionClass.beep());\n *\n * // Extend the class using alternate method.\n * const OtherCollectionClass = Collection.extend({\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * });\n * const otherCollection = new OtherCollectionClass();\n * console.log(otherCollection.foo());\n * console.log(OtherCollectionClass.beep());\n *\n * // Extend the class, providing a custom constructor.\n * function AnotherCollectionClass () {\n * Collection.call(this);\n * this.created_at = new Date().getTime();\n * }\n * Collection.extend({\n * constructor: AnotherCollectionClass,\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * });\n * const anotherCollection = new AnotherCollectionClass();\n * console.log(anotherCollection.created_at);\n * console.log(anotherCollection.foo());\n * console.log(AnotherCollectionClass.beep());\n *\n * @method Collection.extend\n * @param {object} [props={}] Properties to add to the prototype of the\n * subclass.\n * @param {object} [props.constructor] Provide a custom constructor function\n * to be used as the subclass itself.\n * @param {object} [classProps={}] Static properties to add to the subclass.\n * @returns {Constructor} Subclass of this Collection class.\n * @since 3.0.0\n */\n","import utils from './utils'\nimport Component from './Component'\n\nconst DOMAIN = 'Schema'\n\n/**\n * A function map for each of the seven primitive JSON types defined by the core specification.\n * Each function will check a given value and return true or false if the value is an instance of that type.\n * ```\n * types.integer(1) // returns true\n * types.string({}) // returns false\n * ```\n * http://json-schema.org/latest/json-schema-core.html#anchor8\n * @name Schema.types\n * @type {object}\n */\nconst types = {\n array: utils.isArray,\n boolean: utils.isBoolean,\n integer: utils.isInteger,\n null: utils.isNull,\n number: utils.isNumber,\n object: utils.isObject,\n string: utils.isString\n}\n\n/**\n * @ignore\n */\nconst segmentToString = function (segment, prev) {\n let str = ''\n if (segment) {\n if (utils.isNumber(segment)) {\n str += `[${segment}]`\n } else if (prev) {\n str += `.${segment}`\n } else {\n str += `${segment}`\n }\n }\n return str\n}\n\n/**\n * @ignore\n */\nconst makePath = function (opts) {\n opts || (opts = {})\n let path = ''\n const segments = opts.path || []\n segments.forEach(function (segment) {\n path += segmentToString(segment, path)\n })\n path += segmentToString(opts.prop, path)\n return path\n}\n\n/**\n * @ignore\n */\nconst makeError = function (actual, expected, opts) {\n return {\n expected,\n actual: '' + actual,\n path: makePath(opts)\n }\n}\n\n/**\n * @ignore\n */\nconst addError = function (actual, expected, opts, errors) {\n errors.push(makeError(actual, expected, opts))\n}\n\n/**\n * @ignore\n */\nconst maxLengthCommon = function (keyword, value, schema, opts) {\n const max = schema[keyword]\n if (value.length > max) {\n return makeError(value.length, `length no more than ${max}`, opts)\n }\n}\n\n/**\n * @ignore\n */\nconst minLengthCommon = function (keyword, value, schema, opts) {\n const min = schema[keyword]\n if (value.length < min) {\n return makeError(value.length, `length no less than ${min}`, opts)\n }\n}\n\n/**\n * A map of all object member validation functions for each keyword defined in the JSON Schema.\n * @name Schema.validationKeywords\n * @type {object}\n */\nconst validationKeywords = {\n /**\n * Validates the provided value against all schemas defined in the Schemas `allOf` keyword.\n * The instance is valid against if and only if it is valid against all the schemas declared in the Schema's value.\n *\n * The value of this keyword MUST be an array. This array MUST have at least one element.\n * Each element of this array MUST be a valid JSON Schema.\n *\n * see http://json-schema.org/latest/json-schema-validation.html#anchor82\n *\n * @name Schema.validationKeywords.allOf\n * @method\n * @param {*} value Value to be validated.\n * @param {object} schema Schema containing the `allOf` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n allOf (value, schema, opts) {\n let allErrors = []\n schema.allOf.forEach(function (_schema) {\n allErrors = allErrors.concat(validate(value, _schema, opts) || [])\n })\n return allErrors.length ? allErrors : undefined\n },\n\n /**\n * Validates the provided value against all schemas defined in the Schemas `anyOf` keyword.\n * The instance is valid against this keyword if and only if it is valid against\n * at least one of the schemas in this keyword's value.\n *\n * The value of this keyword MUST be an array. This array MUST have at least one element.\n * Each element of this array MUST be an object, and each object MUST be a valid JSON Schema.\n * see http://json-schema.org/latest/json-schema-validation.html#anchor85\n *\n * @name Schema.validationKeywords.anyOf\n * @method\n * @param {*} value Value to be validated.\n * @param {object} schema Schema containing the `anyOf` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n anyOf (value, schema, opts) {\n let validated = false\n let allErrors = []\n schema.anyOf.forEach(function (_schema) {\n const errors = validate(value, _schema, opts)\n if (errors) {\n allErrors = allErrors.concat(errors)\n } else {\n validated = true\n }\n })\n return validated ? undefined : allErrors\n },\n\n /**\n * http://json-schema.org/latest/json-schema-validation.html#anchor70\n *\n * @name Schema.validationKeywords.dependencies\n * @method\n * @param {*} value TODO\n * @param {object} schema TODO\n * @param {object} opts TODO\n */\n dependencies (value, schema, opts) {\n // TODO\n },\n\n /**\n * Validates the provided value against an array of possible values defined by the Schema's `enum` keyword\n * Validation succeeds if the value is deeply equal to one of the values in the array.\n * see http://json-schema.org/latest/json-schema-validation.html#anchor76\n *\n * @name Schema.validationKeywords.enum\n * @method\n * @param {*} value Value to validate\n * @param {object} schema Schema containing the `enum` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n enum (value, schema, opts) {\n const possibleValues = schema.enum\n if (utils.findIndex(possibleValues, (item) => utils.deepEqual(item, value)) === -1) {\n return makeError(value, `one of (${possibleValues.join(', ')})`, opts)\n }\n },\n\n /**\n * Validates each of the provided array values against a schema or an array of schemas defined by the Schema's `items` keyword\n * see http://json-schema.org/latest/json-schema-validation.html#anchor37 for validation rules.\n *\n * @name Schema.validationKeywords.items\n * @method\n * @param {*} value Array to be validated.\n * @param {object} schema Schema containing the items keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n items (value, schema, opts) {\n opts || (opts = {})\n // TODO: additionalItems\n let items = schema.items\n let errors = []\n const checkingTuple = utils.isArray(items)\n const length = value.length\n for (var prop = 0; prop < length; prop++) {\n if (checkingTuple) {\n // Validating a tuple, instead of just checking each item against the\n // same schema\n items = schema.items[prop]\n }\n opts.prop = prop\n errors = errors.concat(validate(value[prop], items, opts) || [])\n }\n return errors.length ? errors : undefined\n },\n\n /**\n * Validates the provided number against a maximum value defined by the Schema's `maximum` keyword\n * Validation succeeds if the value is a number, and is less than, or equal to, the value of this keyword.\n * http://json-schema.org/latest/json-schema-validation.html#anchor17\n *\n * @name Schema.validationKeywords.maximum\n * @method\n * @param {*} value Number to validate against the keyword.\n * @param {object} schema Schema containing the `maximum` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n maximum (value, schema, opts) {\n // Must be a number\n const maximum = schema.maximum\n // Must be a boolean\n // Depends on maximum\n // default: false\n const exclusiveMaximum = schema.exclusiveMaximum\n if (typeof value === typeof maximum && !(exclusiveMaximum ? maximum > value : maximum >= value)) {\n return exclusiveMaximum\n ? makeError(value, `no more than nor equal to ${maximum}`, opts)\n : makeError(value, `no more than ${maximum}`, opts)\n }\n },\n\n /**\n * Validates the length of the provided array against a maximum value defined by the Schema's `maxItems` keyword.\n * Validation succeeds if the length of the array is less than, or equal to the value of this keyword.\n * see http://json-schema.org/latest/json-schema-validation.html#anchor42\n *\n * @name Schema.validationKeywords.maxItems\n * @method\n * @param {*} value Array to be validated.\n * @param {object} schema Schema containing the `maxItems` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n maxItems (value, schema, opts) {\n if (utils.isArray(value)) {\n return maxLengthCommon('maxItems', value, schema, opts)\n }\n },\n\n /**\n * Validates the length of the provided string against a maximum value defined in the Schema's `maxLength` keyword.\n * Validation succeeds if the length of the string is less than, or equal to the value of this keyword.\n * see http://json-schema.org/latest/json-schema-validation.html#anchor26\n *\n * @name Schema.validationKeywords.maxLength\n * @method\n * @param {*} value String to be validated.\n * @param {object} schema Schema containing the `maxLength` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n maxLength (value, schema, opts) {\n return maxLengthCommon('maxLength', value, schema, opts)\n },\n\n /**\n * Validates the count of the provided object's properties against a maximum value defined in the Schema's `maxProperties` keyword.\n * Validation succeeds if the object's property count is less than, or equal to the value of this keyword.\n * see http://json-schema.org/latest/json-schema-validation.html#anchor54\n *\n * @name Schema.validationKeywords.maxProperties\n * @method\n * @param {*} value Object to be validated.\n * @param {object} schema Schema containing the `maxProperties` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n maxProperties (value, schema, opts) {\n // validate only objects\n if (!utils.isObject(value)) return\n const maxProperties = schema.maxProperties\n const length = Object.keys(value).length\n if (length > maxProperties) {\n return makeError(length, `no more than ${maxProperties} properties`, opts)\n }\n },\n\n /**\n * Validates the provided value against a minimum value defined by the Schema's `minimum` keyword\n * Validation succeeds if the value is a number and is greater than, or equal to, the value of this keyword.\n * http://json-schema.org/latest/json-schema-validation.html#anchor21\n *\n * @name Schema.validationKeywords.minimum\n * @method\n * @param {*} value Number to validate against the keyword.\n * @param {object} schema Schema containing the `minimum` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n minimum (value, schema, opts) {\n // Must be a number\n const minimum = schema.minimum\n // Must be a boolean\n // Depends on minimum\n // default: false\n const exclusiveMinimum = schema.exclusiveMinimum\n if (typeof value === typeof minimum && !(exclusiveMinimum ? value > minimum : value >= minimum)) {\n return exclusiveMinimum\n ? makeError(value, `no less than nor equal to ${minimum}`, opts)\n : makeError(value, `no less than ${minimum}`, opts)\n }\n },\n\n /**\n * Validates the length of the provided array against a minimum value defined by the Schema's `minItems` keyword.\n * Validation succeeds if the length of the array is greater than, or equal to the value of this keyword.\n * see http://json-schema.org/latest/json-schema-validation.html#anchor45\n *\n * @name Schema.validationKeywords.minItems\n * @method\n * @param {*} value Array to be validated.\n * @param {object} schema Schema containing the `minItems` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n minItems (value, schema, opts) {\n if (utils.isArray(value)) {\n return minLengthCommon('minItems', value, schema, opts)\n }\n },\n\n /**\n * Validates the length of the provided string against a minimum value defined in the Schema's `minLength` keyword.\n * Validation succeeds if the length of the string is greater than, or equal to the value of this keyword.\n * see http://json-schema.org/latest/json-schema-validation.html#anchor29\n *\n * @name Schema.validationKeywords.minLength\n * @method\n * @param {*} value String to be validated.\n * @param {object} schema Schema containing the `minLength` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n minLength (value, schema, opts) {\n return minLengthCommon('minLength', value, schema, opts)\n },\n\n /**\n * Validates the count of the provided object's properties against a minimum value defined in the Schema's `minProperties` keyword.\n * Validation succeeds if the object's property count is greater than, or equal to the value of this keyword.\n * see http://json-schema.org/latest/json-schema-validation.html#anchor57\n *\n * @name Schema.validationKeywords.minProperties\n * @method\n * @param {*} value Object to be validated.\n * @param {object} schema Schema containing the `minProperties` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n minProperties (value, schema, opts) {\n // validate only objects\n if (!utils.isObject(value)) return\n const minProperties = schema.minProperties\n const length = Object.keys(value).length\n if (length < minProperties) {\n return makeError(length, `no more than ${minProperties} properties`, opts)\n }\n },\n\n /**\n * Validates the provided number is a multiple of the number defined in the Schema's `multipleOf` keyword.\n * Validation succeeds if the number can be divided equally into the value of this keyword.\n * see http://json-schema.org/latest/json-schema-validation.html#anchor14\n *\n * @name Schema.validationKeywords.multipleOf\n * @method\n * @param {*} value Number to be validated.\n * @param {object} schema Schema containing the `multipleOf` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n multipleOf (value, schema, opts) {\n const multipleOf = schema.multipleOf\n if (utils.isNumber(value)) {\n if ((value / multipleOf) % 1 !== 0) {\n return makeError(value, `multipleOf ${multipleOf}`, opts)\n }\n }\n },\n\n /**\n * Validates the provided value is not valid with any of the schemas defined in the Schema's `not` keyword.\n * An instance is valid against this keyword if and only if it is NOT valid against the schemas in this keyword's value.\n *\n * see http://json-schema.org/latest/json-schema-validation.html#anchor91\n * @name Schema.validationKeywords.not\n * @method\n * @param {*} value to be checked.\n * @param {object} schema Schema containing the not keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n not (value, schema, opts) {\n if (!validate(value, schema.not, opts)) {\n // TODO: better messaging\n return makeError('succeeded', 'should have failed', opts)\n }\n },\n\n /**\n * Validates the provided value is valid with one and only one of the schemas defined in the Schema's `oneOf` keyword.\n * An instance is valid against this keyword if and only if it is valid against a single schemas in this keyword's value.\n *\n * see http://json-schema.org/latest/json-schema-validation.html#anchor88\n * @name Schema.validationKeywords.oneOf\n * @method\n * @param {*} value to be checked.\n * @param {object} schema Schema containing the `oneOf` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n oneOf (value, schema, opts) {\n let validated = false\n let allErrors = []\n schema.oneOf.forEach(function (_schema) {\n const errors = validate(value, _schema, opts)\n if (errors) {\n allErrors = allErrors.concat(errors)\n } else if (validated) {\n allErrors = [makeError('valid against more than one', 'valid against only one', opts)]\n validated = false\n return false\n } else {\n validated = true\n }\n })\n return validated ? undefined : allErrors\n },\n\n /**\n * Validates the provided string matches a pattern defined in the Schema's `pattern` keyword.\n * Validation succeeds if the string is a match of the regex value of this keyword.\n *\n * see http://json-schema.org/latest/json-schema-validation.html#anchor33\n * @name Schema.validationKeywords.pattern\n * @method\n * @param {*} value String to be validated.\n * @param {object} schema Schema containing the `pattern` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n pattern (value, schema, opts) {\n const pattern = schema.pattern\n if (utils.isString(value) && !value.match(pattern)) {\n return makeError(value, pattern, opts)\n }\n },\n\n /**\n * Validates the provided object's properties against a map of values defined in the Schema's `properties` keyword.\n * Validation succeeds if the object's property are valid with each of the schema's in the provided map.\n * Validation also depends on the additionalProperties and or patternProperties.\n *\n * see http://json-schema.org/latest/json-schema-validation.html#anchor64 for more info.\n *\n * @name Schema.validationKeywords.properties\n * @method\n * @param {*} value Object to be validated.\n * @param {object} schema Schema containing the `properties` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n properties (value, schema, opts) {\n opts || (opts = {})\n\n if (utils.isArray(value)) {\n return\n }\n\n // Can be a boolean or an object\n // Technically the default is an \"empty schema\", but here \"true\" is\n // functionally the same\n const additionalProperties = schema.additionalProperties === undefined ? true : schema.additionalProperties\n const validated = []\n // \"p\": The property set from \"properties\".\n // Default is an object\n const properties = schema.properties || {}\n // \"pp\": The property set from \"patternProperties\".\n // Default is an object\n const patternProperties = schema.patternProperties || {}\n let errors = []\n\n utils.forOwn(properties, function (_schema, prop) {\n opts.prop = prop\n errors = errors.concat(validate(value[prop], _schema, opts) || [])\n validated.push(prop)\n })\n\n const toValidate = utils.omit(value, validated)\n utils.forOwn(patternProperties, function (_schema, pattern) {\n utils.forOwn(toValidate, function (undef, prop) {\n if (prop.match(pattern)) {\n opts.prop = prop\n errors = errors.concat(validate(value[prop], _schema, opts) || [])\n validated.push(prop)\n }\n })\n })\n const keys = Object.keys(utils.omit(value, validated))\n // If \"s\" is not empty, validation fails\n if (additionalProperties === false) {\n if (keys.length) {\n const origProp = opts.prop\n opts.prop = ''\n addError(`extra fields: ${keys.join(', ')}`, 'no extra fields', opts, errors)\n opts.prop = origProp\n }\n } else if (utils.isObject(additionalProperties)) {\n // Otherwise, validate according to provided schema\n keys.forEach(function (prop) {\n opts.prop = prop\n errors = errors.concat(validate(value[prop], additionalProperties, opts) || [])\n })\n }\n return errors.length ? errors : undefined\n },\n\n /**\n * Validates the provided object's has all properties listed in the Schema's `properties` keyword array.\n * Validation succeeds if the object contains all properties provided in the array value of this keyword.\n * see http://json-schema.org/latest/json-schema-validation.html#anchor61\n *\n * @name Schema.validationKeywords.required\n * @method\n * @param {*} value Object to be validated.\n * @param {object} schema Schema containing the `required` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n required (value, schema, opts) {\n opts || (opts = {})\n const required = schema.required\n const errors = []\n if (!opts.existingOnly) {\n required.forEach(function (prop) {\n if (utils.get(value, prop) === undefined) {\n const prevProp = opts.prop\n opts.prop = prop\n addError(undefined, 'a value', opts, errors)\n opts.prop = prevProp\n }\n })\n }\n return errors.length ? errors : undefined\n },\n\n /**\n * Validates the provided value's type is equal to the type, or array of types, defined in the Schema's `type` keyword.\n * see http://json-schema.org/latest/json-schema-validation.html#anchor79\n *\n * @name Schema.validationKeywords.type\n * @method\n * @param {*} value Value to be validated.\n * @param {object} schema Schema containing the `type` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n type (value, schema, opts) {\n let type = schema.type\n let validType\n // Can be one of several types\n if (utils.isString(type)) {\n type = [type]\n }\n // Try to match the value against an expected type\n type.forEach(function (_type) {\n // TODO: throw an error if type is not defined\n if (types[_type](value, schema, opts)) {\n // Matched a type\n validType = _type\n return false\n }\n })\n // Value did not match any expected type\n if (!validType) {\n return makeError(value !== undefined && value !== null ? typeof value : '' + value, `one of (${type.join(', ')})`, opts)\n }\n // Run keyword validators for matched type\n // http://json-schema.org/latest/json-schema-validation.html#anchor12\n const validator = typeGroupValidators[validType]\n if (validator) {\n return validator(value, schema, opts)\n }\n },\n\n /**\n * Validates the provided array values are unique.\n * Validation succeeds if the items in the array are unique, but only if the value of this keyword is true\n * see http://json-schema.org/latest/json-schema-validation.html#anchor49\n *\n * @name Schema.validationKeywords.uniqueItems\n * @method\n * @param {*} value Array to be validated.\n * @param {object} schema Schema containing the `uniqueItems` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n uniqueItems (value, schema, opts) {\n if (value && value.length && schema.uniqueItems) {\n const length = value.length\n let item, i, j\n // Check n - 1 items\n for (i = length - 1; i > 0; i--) {\n item = value[i]\n // Only compare against unchecked items\n for (j = i - 1; j >= 0; j--) {\n // Found a duplicate\n if (utils.deepEqual(item, value[j])) {\n return makeError(item, 'no duplicates', opts)\n }\n }\n }\n }\n }\n}\n\n/**\n * @ignore\n */\nconst runOps = function (ops, value, schema, opts) {\n let errors = []\n ops.forEach(function (op) {\n if (schema[op] !== undefined) {\n errors = errors.concat(validationKeywords[op](value, schema, opts) || [])\n }\n })\n return errors.length ? errors : undefined\n}\n\n/**\n * Validation keywords validated for any type:\n *\n * - `enum`\n * - `type`\n * - `allOf`\n * - `anyOf`\n * - `oneOf`\n * - `not`\n *\n * @name Schema.ANY_OPS\n * @type {string[]}\n */\nconst ANY_OPS = ['enum', 'type', 'allOf', 'anyOf', 'oneOf', 'not']\n\n/**\n * Validation keywords validated for array types:\n *\n * - `items`\n * - `maxItems`\n * - `minItems`\n * - `uniqueItems`\n *\n * @name Schema.ARRAY_OPS\n * @type {string[]}\n */\nconst ARRAY_OPS = ['items', 'maxItems', 'minItems', 'uniqueItems']\n\n/**\n * Validation keywords validated for numeric (number and integer) types:\n *\n * - `multipleOf`\n * - `maximum`\n * - `minimum`\n *\n * @name Schema.NUMERIC_OPS\n * @type {string[]}\n */\nconst NUMERIC_OPS = ['multipleOf', 'maximum', 'minimum']\n\n/**\n * Validation keywords validated for object types:\n *\n * - `maxProperties`\n * - `minProperties`\n * - `required`\n * - `properties`\n * - `dependencies`\n *\n * @name Schema.OBJECT_OPS\n * @type {string[]}\n */\nconst OBJECT_OPS = ['maxProperties', 'minProperties', 'required', 'properties', 'dependencies']\n\n/**\n * Validation keywords validated for string types:\n *\n * - `maxLength`\n * - `minLength`\n * - `pattern`\n *\n * @name Schema.STRING_OPS\n * @type {string[]}\n */\nconst STRING_OPS = ['maxLength', 'minLength', 'pattern']\n\n/**\n * http://json-schema.org/latest/json-schema-validation.html#anchor75\n * @ignore\n */\nconst validateAny = function (value, schema, opts) {\n return runOps(ANY_OPS, value, schema, opts)\n}\n\n/**\n * Validates the provided value against a given Schema according to the http://json-schema.org/ v4 specification.\n *\n * @name Schema.validate\n * @method\n * @param {*} value Value to be validated.\n * @param {object} schema Valid Schema according to the http://json-schema.org/ v4 specification.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\nconst validate = function (value, schema, opts) {\n let errors = []\n opts || (opts = {})\n opts.ctx || (opts.ctx = { value, schema })\n let shouldPop\n const prevProp = opts.prop\n if (schema === undefined) {\n return\n }\n if (!utils.isObject(schema)) {\n throw utils.err(`${DOMAIN}#validate`)(500, `Invalid schema at path: \"${opts.path}\"`)\n }\n if (opts.path === undefined) {\n opts.path = []\n }\n // Track our location as we recurse\n if (opts.prop !== undefined) {\n shouldPop = true\n opts.path.push(opts.prop)\n opts.prop = undefined\n }\n // Validate against parent schema\n if (schema.extends) {\n // opts.path = path\n // opts.prop = prop\n if (utils.isFunction(schema.extends.validate)) {\n errors = errors.concat(schema.extends.validate(value, opts) || [])\n } else {\n errors = errors.concat(validate(value, schema.extends, opts) || [])\n }\n }\n if (value === undefined) {\n // Check if property is required\n if (schema.required === true && !opts.existingOnly) {\n addError(value, 'a value', opts, errors)\n }\n if (shouldPop) {\n opts.path.pop()\n opts.prop = prevProp\n }\n return errors.length ? errors : undefined\n }\n\n errors = errors.concat(validateAny(value, schema, opts) || [])\n if (shouldPop) {\n opts.path.pop()\n opts.prop = prevProp\n }\n return errors.length ? errors : undefined\n}\n\n// These strings are cached for optimal performance of the change detection\n// boolean - Whether a Record is changing in the current execution frame\nconst changingPath = 'changing'\n// string[] - Properties that have changed in the current execution frame\nconst changedPath = 'changed'\n// Object[] - History of change records\nconst changeHistoryPath = 'history'\n// boolean - Whether a Record is currently being instantiated\nconst creatingPath = 'creating'\n// number - The setTimeout change event id of a Record, if any\nconst eventIdPath = 'eventId'\n// boolean - Whether to skip validation for a Record's currently changing property\nconst noValidatePath = 'noValidate'\n// boolean - Whether to preserve Change History for a Record\nconst keepChangeHistoryPath = 'keepChangeHistory'\n// boolean - Whether to skip change notification for a Record's currently\n// changing property\nconst silentPath = 'silent'\nconst validationFailureMsg = 'validation failed'\n\n/**\n * A map of validation functions grouped by type.\n *\n * @name Schema.typeGroupValidators\n * @type {object}\n */\nconst typeGroupValidators = {\n /**\n * Validates the provided value against the schema using all of the validation keywords specific to instances of an array.\n * The validation keywords for the type `array` are:\n *```\n * ['items', 'maxItems', 'minItems', 'uniqueItems']\n *```\n * see http://json-schema.org/latest/json-schema-validation.html#anchor25\n *\n * @name Schema.typeGroupValidators.array\n * @method\n * @param {*} value Array to be validated.\n * @param {object} schema Schema containing at least one array keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n array: function (value, schema, opts) {\n return runOps(ARRAY_OPS, value, schema, opts)\n },\n\n /**\n * Validates the provided value against the schema using all of the validation keywords specific to instances of an integer.\n * The validation keywords for the type `integer` are:\n *```\n * ['multipleOf', 'maximum', 'minimum']\n *```\n * @name Schema.typeGroupValidators.integer\n * @method\n * @param {*} value Number to be validated.\n * @param {object} schema Schema containing at least one `integer` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n integer: function (value, schema, opts) {\n // Additional validations for numerics are the same\n return typeGroupValidators.numeric(value, schema, opts)\n },\n\n /**\n * Validates the provided value against the schema using all of the validation keywords specific to instances of an number.\n * The validation keywords for the type `number` are:\n *```\n * ['multipleOf', 'maximum', 'minimum']\n *```\n * @name Schema.typeGroupValidators.number\n * @method\n * @param {*} value Number to be validated.\n * @param {object} schema Schema containing at least one `number` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n number: function (value, schema, opts) {\n // Additional validations for numerics are the same\n return typeGroupValidators.numeric(value, schema, opts)\n },\n\n /**\n * Validates the provided value against the schema using all of the validation keywords specific to instances of a number or integer.\n * The validation keywords for the type `numeric` are:\n *```\n * ['multipleOf', 'maximum', 'minimum']\n *```\n * See http://json-schema.org/latest/json-schema-validation.html#anchor13.\n *\n * @name Schema.typeGroupValidators.numeric\n * @method\n * @param {*} value Number to be validated.\n * @param {object} schema Schema containing at least one `numeric` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n numeric: function (value, schema, opts) {\n return runOps(NUMERIC_OPS, value, schema, opts)\n },\n\n /**\n * Validates the provided value against the schema using all of the validation keywords specific to instances of an object.\n * The validation keywords for the type `object` are:\n *```\n * ['maxProperties', 'minProperties', 'required', 'properties', 'dependencies']\n *```\n * See http://json-schema.org/latest/json-schema-validation.html#anchor53.\n *\n * @name Schema.typeGroupValidators.object\n * @method\n * @param {*} value Object to be validated.\n * @param {object} schema Schema containing at least one `object` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n object: function (value, schema, opts) {\n return runOps(OBJECT_OPS, value, schema, opts)\n },\n\n /**\n * Validates the provided value against the schema using all of the validation keywords specific to instances of an string.\n * The validation keywords for the type `string` are:\n *```\n * ['maxLength', 'minLength', 'pattern']\n *```\n * See http://json-schema.org/latest/json-schema-validation.html#anchor25.\n *\n * @name Schema.typeGroupValidators.string\n * @method\n * @param {*} value String to be validated.\n * @param {object} schema Schema containing at least one `string` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n string: function (value, schema, opts) {\n return runOps(STRING_OPS, value, schema, opts)\n }\n}\n\n/**\n * js-data's Schema class.\n *\n * @example Schema#constructor\n * const JSData = require('js-data');\n * const { Schema } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const PostSchema = new Schema({\n * type: 'object',\n * properties: {\n * title: { type: 'string' }\n * }\n * });\n * PostSchema.validate({ title: 1234 });\n *\n * @class Schema\n * @extends Component\n * @param {object} definition Schema definition according to json-schema.org\n */\nfunction Schema (definition) {\n definition || (definition = {})\n // TODO: schema validation\n utils.fillIn(this, definition)\n\n if (this.type === 'object') {\n this.properties = this.properties || {}\n utils.forOwn(this.properties, (_definition, prop) => {\n if (!(_definition instanceof Schema)) {\n this.properties[prop] = new Schema(_definition)\n }\n })\n } else if (this.type === 'array' && this.items && !(this.items instanceof Schema)) {\n this.items = new Schema(this.items)\n }\n if (this.extends && !(this.extends instanceof Schema)) {\n this.extends = new Schema(this.extends)\n }\n ['allOf', 'anyOf', 'oneOf'].forEach((validationKeyword) => {\n if (this[validationKeyword]) {\n this[validationKeyword].forEach((_definition, i) => {\n if (!(_definition instanceof Schema)) {\n this[validationKeyword][i] = new Schema(_definition)\n }\n })\n }\n })\n}\n\nexport default Component.extend({\n constructor: Schema,\n\n /**\n * This adds ES5 getters/setters to the target based on the \"properties\" in\n * this Schema, which makes possible change tracking and validation on\n * property assignment.\n *\n * @name Schema#apply\n * @method\n * @param {object} target The prototype to which to apply this schema.\n */\n apply (target, opts) {\n opts || (opts = {})\n opts.getter || (opts.getter = '_get')\n opts.setter || (opts.setter = '_set')\n opts.unsetter || (opts.unsetter = '_unset')\n opts.track || (opts.track = this.track)\n const properties = this.properties || {}\n utils.forOwn(properties, (schema, prop) => {\n Object.defineProperty(\n target,\n prop,\n this.makeDescriptor(prop, schema, opts)\n )\n })\n },\n\n /**\n * Apply default values to the target object for missing values.\n *\n * @name Schema#applyDefaults\n * @method\n * @param {object} target The target to which to apply values for missing values.\n */\n applyDefaults (target) {\n if (!target) {\n return\n }\n const properties = this.properties || {}\n const hasSet = utils.isFunction(target.set) || utils.isFunction(target._set)\n utils.forOwn(properties, function (schema, prop) {\n if (Object.hasOwnProperty.call(schema, 'default') && utils.get(target, prop) === undefined) {\n if (hasSet) {\n target.set(prop, utils.plainCopy(schema.default), { silent: true })\n } else {\n utils.set(target, prop, utils.plainCopy(schema.default))\n }\n }\n if (schema.type === 'object' && schema.properties) {\n if (hasSet) {\n const orig = target._get('noValidate')\n target._set('noValidate', true)\n utils.set(target, prop, utils.get(target, prop) || {}, { silent: true })\n target._set('noValidate', orig)\n } else {\n utils.set(target, prop, utils.get(target, prop) || {})\n }\n schema.applyDefaults(utils.get(target, prop))\n }\n })\n },\n\n /**\n * Assemble a property descriptor for tracking and validating changes to\n * a property according to the given schema. This method is called when\n * {@link Mapper#applySchema} is set to `true`.\n *\n * @name Schema#makeDescriptor\n * @method\n * @param {string} prop The property name.\n * @param {(Schema|object)} schema The schema for the property.\n * @param {object} [opts] Optional configuration.\n * @param {function} [opts.getter] Custom getter function.\n * @param {function} [opts.setter] Custom setter function.\n * @param {function} [opts.track] Whether to track changes.\n * @returns {object} A property descriptor for the given schema.\n */\n makeDescriptor (prop, schema, opts) {\n const descriptor = {\n // Better to allow configurability, but at the user's own risk\n configurable: true,\n // These properties are enumerable by default, but regardless of their\n // enumerability, they won't be \"own\" properties of individual records\n enumerable: schema.enumerable === undefined ? true : !!schema.enumerable\n }\n // Cache a few strings for optimal performance\n const keyPath = `props.${prop}`\n const previousPath = `previous.${prop}`\n const getter = opts.getter\n const setter = opts.setter\n const unsetter = opts.unsetter\n const track = utils.isBoolean(opts.track) ? opts.track : schema.track\n\n descriptor.get = function () {\n return this._get(keyPath)\n }\n\n if (utils.isFunction(schema.get)) {\n const originalGet = descriptor.get\n descriptor.get = function () {\n return schema.get.call(this, originalGet)\n }\n }\n\n descriptor.set = function (value) {\n // These are accessed a lot\n const _get = this[getter]\n const _set = this[setter]\n const _unset = this[unsetter]\n // Optionally check that the new value passes validation\n if (!_get(noValidatePath)) {\n const errors = schema.validate(value, { path: [prop] })\n if (errors) {\n // Immediately throw an error, preventing the record from getting into\n // an invalid state\n const error = new Error(validationFailureMsg)\n error.errors = errors\n throw error\n }\n }\n // TODO: Make it so tracking can be turned on for all properties instead of\n // only per-property\n if (track && !_get(creatingPath)) {\n // previous is versioned on database commit\n // props are versioned on set()\n const previous = _get(previousPath)\n const current = _get(keyPath)\n let changing = _get(changingPath)\n let changed = _get(changedPath)\n\n if (!changing) {\n // Track properties that are changing in the current event loop\n changed = []\n }\n\n // Add changing properties to this array once at most\n const index = changed.indexOf(prop)\n if (current !== value && index === -1) {\n changed.push(prop)\n }\n if (previous === value) {\n if (index >= 0) {\n changed.splice(index, 1)\n }\n }\n // No changes in current event loop\n if (!changed.length) {\n changing = false\n _unset(changingPath)\n _unset(changedPath)\n // Cancel pending change event\n if (_get(eventIdPath)) {\n clearTimeout(_get(eventIdPath))\n _unset(eventIdPath)\n }\n }\n // Changes detected in current event loop\n if (!changing && changed.length) {\n _set(changedPath, changed)\n _set(changingPath, true)\n // Saving the timeout id allows us to batch all changes in the same\n // event loop into a single \"change\"\n // TODO: Optimize\n _set(eventIdPath, setTimeout(() => {\n // Previous event loop where changes were gathered has ended, so\n // notify any listeners of those changes and prepare for any new\n // changes\n _unset(changedPath)\n _unset(eventIdPath)\n _unset(changingPath)\n // TODO: Optimize\n if (!_get(silentPath)) {\n let i\n for (i = 0; i < changed.length; i++) {\n this.emit('change:' + changed[i], this, utils.get(this, changed[i]))\n }\n\n const changes = utils.diffObjects({ [prop]: value }, { [prop]: current })\n\n if (_get(keepChangeHistoryPath)) {\n const changeRecord = utils.plainCopy(changes)\n changeRecord.timestamp = new Date().getTime()\n let changeHistory = _get(changeHistoryPath)\n !changeHistory && _set(changeHistoryPath, (changeHistory = []))\n changeHistory.push(changeRecord)\n }\n this.emit('change', this, changes)\n }\n _unset(silentPath)\n }, 0))\n }\n }\n _set(keyPath, value)\n return value\n }\n\n if (utils.isFunction(schema.set)) {\n const originalSet = descriptor.set\n descriptor.set = function (value) {\n return schema.set.call(this, value, originalSet)\n }\n }\n\n return descriptor\n },\n\n /**\n * Create a copy of the given value that contains only the properties defined\n * in this schema.\n *\n * @name Schema#pick\n * @method\n * @param {*} value The value to copy.\n * @returns {*} The copy.\n */\n pick (value) {\n if (value === undefined) {\n return\n }\n if (this.type === 'object') {\n const copy = {}\n const properties = this.properties\n if (properties) {\n utils.forOwn(properties, (_definition, prop) => {\n copy[prop] = _definition.pick(value[prop])\n })\n }\n if (this.extends) {\n utils.fillIn(copy, this.extends.pick(value))\n }\n // Conditionally copy properties not defined in \"properties\"\n if (this.additionalProperties) {\n for (var key in value) {\n if (!properties[key]) {\n copy[key] = utils.plainCopy(value[key])\n }\n }\n }\n return copy\n } else if (this.type === 'array') {\n return value.map((item) => {\n const _copy = this.items ? this.items.pick(item) : {}\n if (this.extends) {\n utils.fillIn(_copy, this.extends.pick(item))\n }\n return _copy\n })\n }\n return utils.plainCopy(value)\n },\n\n /**\n * Validate the provided value against this schema.\n *\n * @name Schema#validate\n * @method\n * @param {*} value Value to validate.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n validate (value, opts) {\n return validate(value, this, opts)\n }\n}, {\n ANY_OPS,\n ARRAY_OPS,\n NUMERIC_OPS,\n OBJECT_OPS,\n STRING_OPS,\n typeGroupValidators,\n types,\n validate,\n validationKeywords\n})\n\n/**\n * Create a subclass of this Schema:\n * @example Schema.extend\n * const JSData = require('js-data');\n * const { Schema } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * // Extend the class using ES2015 class syntax.\n * class CustomSchemaClass extends Schema {\n * foo () { return 'bar'; }\n * static beep () { return 'boop'; }\n * }\n * const customSchema = new CustomSchemaClass();\n * console.log(customSchema.foo());\n * console.log(CustomSchemaClass.beep());\n *\n * // Extend the class using alternate method.\n * const OtherSchemaClass = Schema.extend({\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * });\n * const otherSchema = new OtherSchemaClass();\n * console.log(otherSchema.foo());\n * console.log(OtherSchemaClass.beep());\n *\n * // Extend the class, providing a custom constructor.\n * function AnotherSchemaClass () {\n * Schema.call(this);\n * this.created_at = new Date().getTime();\n * }\n * Schema.extend({\n * constructor: AnotherSchemaClass,\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * });\n * const anotherSchema = new AnotherSchemaClass();\n * console.log(anotherSchema.created_at);\n * console.log(anotherSchema.foo());\n * console.log(AnotherSchemaClass.beep());\n *\n * @method Schema.extend\n * @param {object} [props={}] Properties to add to the prototype of the\n * subclass.\n * @param {object} [props.constructor] Provide a custom constructor function\n * to be used as the subclass itself.\n * @param {object} [classProps={}] Static properties to add to the subclass.\n * @returns {Constructor} Subclass of this Schema class.\n * @since 3.0.0\n */\n","import utils from './utils'\nimport Component from './Component'\nimport Record from './Record'\nimport Schema from './Schema'\nimport { Relation } from './relations'\nimport {\n belongsTo,\n belongsToType,\n hasMany,\n hasManyType,\n hasOne,\n hasOneType\n} from './decorators'\n\nconst DOMAIN = 'Mapper'\nconst applyDefaultsHooks = [\n 'beforeCreate',\n 'beforeCreateMany'\n]\nconst validatingHooks = [\n 'beforeCreate',\n 'beforeCreateMany',\n 'beforeUpdate',\n 'beforeUpdateAll',\n 'beforeUpdateMany'\n]\nconst makeNotify = function (num) {\n return function (...args) {\n const opts = args[args.length - num]\n const op = opts.op\n this.dbg(op, ...args)\n\n if (applyDefaultsHooks.indexOf(op) !== -1 && opts.applyDefaults !== false) {\n const schema = this.getSchema()\n if (schema && schema.applyDefaults) {\n let toProcess = args[0]\n if (!utils.isArray(toProcess)) {\n toProcess = [toProcess]\n }\n toProcess.forEach((record) => {\n schema.applyDefaults(record)\n })\n }\n }\n\n // Automatic validation\n if (validatingHooks.indexOf(op) !== -1 && !opts.noValidate) {\n // Save current value of option\n const originalExistingOnly = opts.existingOnly\n\n // For updates, ignore required fields if they aren't present\n if (op.indexOf('beforeUpdate') === 0 && opts.existingOnly === undefined) {\n opts.existingOnly = true\n }\n const errors = this.validate(args[op === 'beforeUpdate' ? 1 : 0], utils.pick(opts, ['existingOnly']))\n\n // Restore option\n opts.existingOnly = originalExistingOnly\n\n // Abort lifecycle due to validation errors\n if (errors) {\n const err = new Error('validation failed')\n err.errors = errors\n return utils.reject(err)\n }\n }\n\n // Emit lifecycle event\n if (opts.notify || (opts.notify === undefined && this.notify)) {\n setTimeout(() => {\n this.emit(op, ...args)\n })\n }\n }\n}\n\n// These are the default implementations of all of the lifecycle hooks\nconst notify = makeNotify(1)\nconst notify2 = makeNotify(2)\n\n// This object provides meta information used by Mapper#crud to actually\n// execute each lifecycle method\nconst LIFECYCLE_METHODS = {\n count: {\n defaults: [{}, {}],\n skip: true,\n types: []\n },\n destroy: {\n defaults: [{}, {}],\n skip: true,\n types: []\n },\n destroyAll: {\n defaults: [{}, {}],\n skip: true,\n types: []\n },\n find: {\n defaults: [undefined, {}],\n types: []\n },\n findAll: {\n defaults: [{}, {}],\n types: []\n },\n sum: {\n defaults: [undefined, {}, {}],\n skip: true,\n types: []\n },\n update: {\n adapterArgs (mapper, id, props, opts) {\n return [id, mapper.toJSON(props, opts), opts]\n },\n beforeAssign: 1,\n defaults: [undefined, {}, {}],\n types: []\n },\n updateAll: {\n adapterArgs (mapper, props, query, opts) {\n return [mapper.toJSON(props, opts), query, opts]\n },\n beforeAssign: 0,\n defaults: [{}, {}, {}],\n types: []\n },\n updateMany: {\n adapterArgs (mapper, records, opts) {\n return [records.map((record) => mapper.toJSON(record, opts)), opts]\n },\n beforeAssign: 0,\n defaults: [[], {}],\n types: []\n }\n}\n\nconst MAPPER_DEFAULTS = {\n /**\n * Hash of registered adapters. Don't modify directly. Use\n * {@link Mapper#registerAdapter} instead.\n *\n * @default {}\n * @name Mapper#_adapters\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/connecting-to-a-data-source\",\"Connecting to a data source\"]\n */\n _adapters: {},\n\n /**\n * Whether {@link Mapper#beforeCreate} and {@link Mapper#beforeCreateMany}\n * should automatically receive default values according to the Mapper's schema.\n *\n * @default true\n * @name Mapper#applyDefaults\n * @since 3.0.0\n * @type {boolean}\n */\n applyDefaults: true,\n\n /**\n * Whether to augment {@link Mapper#recordClass} with ES5 getters and setters\n * according to the properties defined in {@link Mapper#schema}. This makes\n * possible validation and change tracking on individual properties\n * when using the dot (e.g. `user.name = \"Bob\"`) operator to modify a\n * property, and is `true` by default.\n *\n * @default true\n * @name Mapper#applySchema\n * @since 3.0.0\n * @type {boolean}\n */\n applySchema: true,\n\n /**\n * The name of the registered adapter that this Mapper should used by default.\n *\n * @default \"http\"\n * @name Mapper#defaultAdapter\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/connecting-to-a-data-source\",\"Connecting to a data source\"]\n * @type {string}\n */\n defaultAdapter: 'http',\n\n /**\n * The field used as the unique identifier on records handled by this Mapper.\n *\n * @default id\n * @name Mapper#idAttribute\n * @since 3.0.0\n * @type {string}\n */\n idAttribute: 'id',\n\n /**\n * Whether records created from this mapper keep changeHistory on property changes.\n *\n * @default true\n * @name Mapper#keepChangeHistory\n * @since 3.0.0\n * @type {boolean}\n */\n keepChangeHistory: true,\n\n /**\n * Whether this Mapper should emit operational events.\n *\n * @default true\n * @name Mapper#notify\n * @since 3.0.0\n * @type {boolean}\n */\n notify: true,\n\n /**\n * Whether to skip validation when the Record instances are created.\n *\n * @default false\n * @name Mapper#noValidate\n * @since 3.0.0\n * @type {boolean}\n */\n noValidate: false,\n\n /**\n * Whether {@link Mapper#create}, {@link Mapper#createMany},\n * {@link Mapper#update}, {@link Mapper#updateAll}, {@link Mapper#updateMany},\n * {@link Mapper#find}, {@link Mapper#findAll}, {@link Mapper#destroy},\n * {@link Mapper#destroyAll}, {@link Mapper#count}, and {@link Mapper#sum}\n * should return a raw result object that contains both the instance data\n * returned by the adapter _and_ metadata about the operation.\n *\n * The default is to NOT return the result object, and instead return just the\n * instance data.\n *\n * @default false\n * @name Mapper#raw\n * @since 3.0.0\n * @type {boolean}\n */\n raw: false,\n\n /**\n * Whether records created from this mapper automatically validate their properties\n * when their properties are modified.\n *\n * @default true\n * @name Mapper#validateOnSet\n * @since 3.0.0\n * @type {boolean}\n */\n validateOnSet: true\n}\n\n/**\n * The core of JSData's [ORM/ODM][orm] implementation. Given a minimum amout of\n * meta information about a resource, a Mapper can perform generic CRUD\n * operations against that resource. Apart from its configuration, a Mapper is\n * stateless. The particulars of various persistence layers have been abstracted\n * into adapters, which a Mapper uses to perform its operations.\n *\n * The term \"Mapper\" comes from the [Data Mapper Pattern][pattern] described in\n * Martin Fowler's [Patterns of Enterprise Application Architecture][book]. A\n * Data Mapper moves data between [in-memory object instances][record] and a\n * relational or document-based database. JSData's Mapper can work with any\n * persistence layer you can write an adapter for.\n *\n * _(\"Model\" is a heavily overloaded term and is avoided in this documentation\n * to prevent confusion.)_\n *\n * [orm]: https://en.wikipedia.org/wiki/Object-relational_mapping\n *\n * @example\n * [pattern]: https://en.wikipedia.org/wiki/Data_mapper_pattern\n * [book]: http://martinfowler.com/books/eaa.html\n * [record]: Record.html\n * // Import and instantiate\n * import { Mapper } from 'js-data';\n * const UserMapper = new Mapper({ name: 'user' });\n *\n * @example\n * // Define a Mapper using the Container component\n * import { Container } from 'js-data';\n * const store = new Container();\n * store.defineMapper('user');\n *\n * @class Mapper\n * @extends Component\n * @param {object} opts Configuration options.\n * @param {boolean} [opts.applySchema=true] See {@link Mapper#applySchema}.\n * @param {boolean} [opts.debug=false] See {@link Component#debug}.\n * @param {string} [opts.defaultAdapter=http] See {@link Mapper#defaultAdapter}.\n * @param {string} [opts.idAttribute=id] See {@link Mapper#idAttribute}.\n * @param {object} [opts.methods] See {@link Mapper#methods}.\n * @param {string} opts.name See {@link Mapper#name}.\n * @param {boolean} [opts.notify] See {@link Mapper#notify}.\n * @param {boolean} [opts.raw=false] See {@link Mapper#raw}.\n * @param {Function|boolean} [opts.recordClass] See {@link Mapper#recordClass}.\n * @param {Object|Schema} [opts.schema] See {@link Mapper#schema}.\n * @returns {Mapper} A new {@link Mapper} instance.\n * @see http://www.js-data.io/v3.0/docs/components-of-jsdata#mapper\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/components-of-jsdata#mapper\",\"Components of JSData: Mapper\"]\n * @tutorial [\"http://www.js-data.io/v3.0/docs/modeling-your-data\",\"Modeling your data\"]\n */\nfunction Mapper (opts) {\n utils.classCallCheck(this, Mapper)\n Component.call(this)\n opts || (opts = {})\n\n // Prepare certain properties to be non-enumerable\n Object.defineProperties(this, {\n _adapters: {\n value: undefined,\n writable: true\n },\n\n /**\n * The {@link Container} that holds this Mapper. __Do not modify.__\n *\n * @name Mapper#lifecycleMethods\n * @since 3.0.0\n * @type {Object}\n */\n datastore: {\n value: undefined,\n writable: true\n },\n\n /**\n * The meta information describing this Mapper's available lifecycle\n * methods. __Do not modify.__\n *\n * @name Mapper#lifecycleMethods\n * @since 3.0.0\n * @type {Object}\n */\n lifecycleMethods: {\n value: LIFECYCLE_METHODS\n },\n\n /**\n * Set to `false` to force the Mapper to work with POJO objects only.\n *\n * @example\n * // Use POJOs only.\n * import { Mapper, Record } from 'js-data';\n * const UserMapper = new Mapper({ recordClass: false });\n * UserMapper.recordClass // false;\n * const user = UserMapper.createRecord();\n * user instanceof Record; // false\n *\n * @example\n * // Set to a custom class to have records wrapped in your custom class.\n * import { Mapper, Record } from 'js-data';\n * // Custom class\n * class User {\n * constructor (props = {}) {\n * for (var key in props) {\n * if (props.hasOwnProperty(key)) {\n * this[key] = props[key];\n * }\n * }\n * }\n * }\n * const UserMapper = new Mapper({ recordClass: User });\n * UserMapper.recordClass; // function User() {}\n * const user = UserMapper.createRecord();\n * user instanceof Record; // false\n * user instanceof User; // true\n *\n *\n * @example\n * // Extend the {@link Record} class.\n * import { Mapper, Record } from 'js-data';\n * // Custom class\n * class User extends Record {\n * constructor () {\n * super(props);\n * }\n * }\n * const UserMapper = new Mapper({ recordClass: User });\n * UserMapper.recordClass; // function User() {}\n * const user = UserMapper.createRecord();\n * user instanceof Record; // true\n * user instanceof User; // true\n *\n * @name Mapper#recordClass\n * @default {@link Record}\n * @see Record\n * @since 3.0.0\n */\n recordClass: {\n value: undefined,\n writable: true\n },\n\n /**\n * This Mapper's {@link Schema}.\n *\n * @example Mapper#schema\n * const JSData = require('js-data');\n * const { Mapper } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const UserMapper = new Mapper({\n * name: 'user',\n * schema: {\n * properties: {\n * id: { type: 'number' },\n * first: { type: 'string', track: true },\n * last: { type: 'string', track: true },\n * role: { type: 'string', track: true, required: true },\n * age: { type: 'integer', track: true },\n * is_active: { type: 'number' }\n * }\n * }\n * });\n * const user = UserMapper.createRecord({\n * id: 1,\n * name: 'John',\n * role: 'admin'\n * });\n * user.on('change', function (user, changes) {\n * console.log(changes);\n * });\n * user.on('change:role', function (user, value) {\n * console.log('change:role - ' + value);\n * });\n * user.role = 'owner';\n *\n * @name Mapper#schema\n * @see Schema\n * @since 3.0.0\n * @type {Schema}\n */\n schema: {\n value: undefined,\n writable: true\n }\n })\n\n // Apply user-provided configuration\n utils.fillIn(this, opts)\n // Fill in any missing options with the defaults\n utils.fillIn(this, utils.copy(MAPPER_DEFAULTS))\n\n /**\n * The name for this Mapper. This is the minimum amount of meta information\n * required for a Mapper to be able to execute CRUD operations for a\n * Resource.\n *\n * @name Mapper#name\n * @since 3.0.0\n * @type {string}\n */\n if (!this.name) {\n throw utils.err(`new ${DOMAIN}`, 'opts.name')(400, 'string', this.name)\n }\n\n // Setup schema, with an empty default schema if necessary\n if (this.schema) {\n this.schema.type || (this.schema.type = 'object')\n if (!(this.schema instanceof Schema)) {\n this.schema = new Schema(this.schema || { type: 'object' })\n }\n }\n\n // Create a subclass of Record that's tied to this Mapper\n if (this.recordClass === undefined) {\n const superClass = Record\n this.recordClass = superClass.extend({\n constructor: (function Record () {\n var subClass = function Record (props, opts) {\n utils.classCallCheck(this, subClass)\n superClass.call(this, props, opts)\n }\n return subClass\n })()\n })\n }\n\n if (this.recordClass) {\n this.recordClass.mapper = this\n\n /**\n * Functions that should be added to the prototype of {@link Mapper#recordClass}.\n *\n * @name Mapper#methods\n * @since 3.0.0\n * @type {Object}\n */\n if (utils.isObject(this.methods)) {\n utils.addHiddenPropsToTarget(this.recordClass.prototype, this.methods)\n }\n\n // We can only apply the schema to the prototype of this.recordClass if the\n // class extends Record\n if (Object.isPrototypeOf.call(Record, this.recordClass) && this.schema && this.schema.apply && this.applySchema) {\n this.schema.apply(this.recordClass.prototype)\n }\n }\n}\n\nexport default Component.extend({\n constructor: Mapper,\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#count}. If this method\n * returns a promise then {@link Mapper#count} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#afterCount\n * @param {object} query The `query` argument passed to {@link Mapper#count}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#count}.\n * @param {*} result The result, if any.\n * @since 3.0.0\n */\n afterCount: notify2,\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#create}. If this method\n * returns a promise then {@link Mapper#create} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#afterCreate\n * @param {object} props The `props` argument passed to {@link Mapper#create}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#create}.\n * @param {*} result The result, if any.\n * @since 3.0.0\n */\n afterCreate: notify2,\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#createMany}. If this method\n * returns a promise then {@link Mapper#createMany} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#afterCreateMany\n * @param {array} records The `records` argument passed to {@link Mapper#createMany}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#createMany}.\n * @param {*} result The result, if any.\n * @since 3.0.0\n */\n afterCreateMany: notify2,\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#destroy}. If this method\n * returns a promise then {@link Mapper#destroy} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#afterDestroy\n * @param {(string|number)} id The `id` argument passed to {@link Mapper#destroy}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#destroy}.\n * @param {*} result The result, if any.\n * @since 3.0.0\n */\n afterDestroy: notify2,\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#destroyAll}. If this method\n * returns a promise then {@link Mapper#destroyAll} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#afterDestroyAll\n * @param {*} data The `data` returned by the adapter.\n * @param {query} query The `query` argument passed to {@link Mapper#destroyAll}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#destroyAll}.\n * @param {*} result The result, if any.\n * @since 3.0.0\n */\n afterDestroyAll: notify2,\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#find}. If this method\n * returns a promise then {@link Mapper#find} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#afterFind\n * @param {(string|number)} id The `id` argument passed to {@link Mapper#find}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#find}.\n * @param {*} result The result, if any.\n * @since 3.0.0\n */\n afterFind: notify2,\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#findAll}. If this method\n * returns a promise then {@link Mapper#findAll} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#afterFindAll\n * @param {object} query The `query` argument passed to {@link Mapper#findAll}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#findAll}.\n * @param {*} result The result, if any.\n * @since 3.0.0\n */\n afterFindAll: notify2,\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#sum}. If this method\n * returns a promise then {@link Mapper#sum} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#afterSum\n * @param {object} query The `query` argument passed to {@link Mapper#sum}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#sum}.\n * @param {*} result The result, if any.\n * @since 3.0.0\n */\n afterSum: notify2,\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#update}. If this method\n * returns a promise then {@link Mapper#update} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#afterUpdate\n * @param {(string|number)} id The `id` argument passed to {@link Mapper#update}.\n * @param {props} props The `props` argument passed to {@link Mapper#update}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#update}.\n * @param {*} result The result, if any.\n * @since 3.0.0\n */\n afterUpdate: notify2,\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#updateAll}. If this method\n * returns a promise then {@link Mapper#updateAll} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#afterUpdateAll\n * @param {object} props The `props` argument passed to {@link Mapper#updateAll}.\n * @param {object} query The `query` argument passed to {@link Mapper#updateAll}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#updateAll}.\n * @param {*} result The result, if any.\n * @since 3.0.0\n */\n afterUpdateAll: notify2,\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#updateMany}. If this method\n * returns a promise then {@link Mapper#updateMany} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#afterUpdateMany\n * @param {array} records The `records` argument passed to {@link Mapper#updateMany}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#updateMany}.\n * @param {*} result The result, if any.\n * @since 3.0.0\n */\n afterUpdateMany: notify2,\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#create}. If this method\n * returns a promise then {@link Mapper#create} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#beforeCreate\n * @param {object} props The `props` argument passed to {@link Mapper#create}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#create}.\n * @since 3.0.0\n */\n beforeCreate: notify,\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#createMany}. If this method\n * returns a promise then {@link Mapper#createMany} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#beforeCreateMany\n * @param {array} records The `records` argument passed to {@link Mapper#createMany}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#createMany}.\n * @since 3.0.0\n */\n beforeCreateMany: notify,\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#count}. If this method\n * returns a promise then {@link Mapper#count} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#beforeCount\n * @param {object} query The `query` argument passed to {@link Mapper#count}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#count}.\n * @since 3.0.0\n */\n beforeCount: notify,\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#destroy}. If this method\n * returns a promise then {@link Mapper#destroy} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#beforeDestroy\n * @param {(string|number)} id The `id` argument passed to {@link Mapper#destroy}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#destroy}.\n * @since 3.0.0\n */\n beforeDestroy: notify,\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#destroyAll}. If this method\n * returns a promise then {@link Mapper#destroyAll} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#beforeDestroyAll\n * @param {query} query The `query` argument passed to {@link Mapper#destroyAll}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#destroyAll}.\n * @since 3.0.0\n */\n beforeDestroyAll: notify,\n\n /**\n * Mappers lifecycle hook called by {@link Mapper#find}. If this method\n * returns a promise then {@link Mapper#find} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#beforeFind\n * @param {(string|number)} id The `id` argument passed to {@link Mapper#find}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#find}.\n * @since 3.0.0\n */\n beforeFind: notify,\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#findAll}. If this method\n * returns a promise then {@link Mapper#findAll} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#beforeFindAll\n * @param {object} query The `query` argument passed to {@link Mapper#findAll}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#findAll}.\n * @since 3.0.0\n */\n beforeFindAll: notify,\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#sum}. If this method\n * returns a promise then {@link Mapper#sum} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#beforeSum\n * @param {string} field The `field` argument passed to {@link Mapper#sum}.\n * @param {object} query The `query` argument passed to {@link Mapper#sum}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#sum}.\n * @since 3.0.0\n */\n beforeSum: notify,\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#update}. If this method\n * returns a promise then {@link Mapper#update} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#beforeUpdate\n * @param {(string|number)} id The `id` argument passed to {@link Mapper#update}.\n * @param {props} props The `props` argument passed to {@link Mapper#update}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#update}.\n * @since 3.0.0\n */\n beforeUpdate: notify,\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#updateAll}. If this method\n * returns a promise then {@link Mapper#updateAll} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#beforeUpdateAll\n * @param {object} props The `props` argument passed to {@link Mapper#updateAll}.\n * @param {object} query The `query` argument passed to {@link Mapper#updateAll}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#updateAll}.\n * @since 3.0.0\n */\n beforeUpdateAll: notify,\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#updateMany}. If this method\n * returns a promise then {@link Mapper#updateMany} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#beforeUpdateMany\n * @param {array} records The `records` argument passed to {@link Mapper#updateMany}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#updateMany}.\n * @since 3.0.0\n */\n beforeUpdateMany: notify,\n\n /**\n * This method is called at the end of most lifecycle methods. It does the\n * following:\n *\n * 1. If `opts.raw` is `true`, add this Mapper's configuration to the `opts`\n * argument as metadata for the operation.\n * 2. Wrap the result data appropriately using {@link Mapper#wrap}, which\n * calls {@link Mapper#createRecord}.\n *\n * @method Mapper#_end\n * @private\n * @since 3.0.0\n */\n _end (result, opts, skip) {\n if (opts.raw) {\n utils._(result, opts)\n }\n if (skip) {\n return result\n }\n let _data = opts.raw ? result.data : result\n if (_data && utils.isFunction(this.wrap)) {\n _data = this.wrap(_data, opts)\n if (opts.raw) {\n result.data = _data\n } else {\n result = _data\n }\n }\n return result\n },\n\n /**\n * Define a belongsTo relationship. Only useful if you're managing your\n * Mappers manually and not using a Container or DataStore component.\n *\n * @example\n * PostMapper.belongsTo(UserMapper, {\n * // post.user_id points to user.id\n * foreignKey: 'user_id'\n * // user records will be attached to post records at \"post.user\"\n * localField: 'user'\n * });\n *\n * CommentMapper.belongsTo(UserMapper, {\n * // comment.user_id points to user.id\n * foreignKey: 'user_id'\n * // user records will be attached to comment records at \"comment.user\"\n * localField: 'user'\n * });\n * CommentMapper.belongsTo(PostMapper, {\n * // comment.post_id points to post.id\n * foreignKey: 'post_id'\n * // post records will be attached to comment records at \"comment.post\"\n * localField: 'post'\n * });\n *\n * @method Mapper#belongsTo\n * @see http://www.js-data.io/v3.0/docs/relations\n * @since 3.0.0\n */\n belongsTo (relatedMapper, opts) {\n return belongsTo(relatedMapper, opts)(this)\n },\n\n /**\n * Select records according to the `query` argument and return the count.\n *\n * {@link Mapper#beforeCount} will be called before calling the adapter.\n * {@link Mapper#afterCount} will be called after calling the adapter.\n *\n * @example\n * // Get the number of published blog posts\n * PostMapper.count({ status: 'published' }).then((numPublished) => {\n * console.log(numPublished); // e.g. 45\n * });\n *\n * @method Mapper#count\n * @param {object} [query={}] Selection query. See {@link query}.\n * @param {object} [query.where] See {@link query.where}.\n * @param {number} [query.offset] See {@link query.offset}.\n * @param {number} [query.limit] See {@link query.limit}.\n * @param {string|Array[]} [query.orderBy] See {@link query.orderBy}.\n * @param {object} [opts] Configuration options. Refer to the `count` method\n * of whatever adapter you're using for more configuration options.\n * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the\n * adapter to use.\n * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}.\n * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}.\n * @returns {Promise} Resolves with the count of the selected records.\n * @since 3.0.0\n */\n count (query, opts) {\n return this.crud('count', query, opts)\n },\n\n /**\n * Fired during {@link Mapper#create}. See\n * {@link Mapper~beforeCreateListener} for how to listen for this event.\n *\n * @event Mapper#beforeCreate\n * @see Mapper~beforeCreateListener\n * @see Mapper#create\n */\n /**\n * Callback signature for the {@link Mapper#event:beforeCreate} event.\n *\n * @example\n * function onBeforeCreate (props, opts) {\n * // do something\n * }\n * store.on('beforeCreate', onBeforeCreate);\n *\n * @callback Mapper~beforeCreateListener\n * @param {object} props The `props` argument passed to {@link Mapper#beforeCreate}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#beforeCreate}.\n * @see Mapper#event:beforeCreate\n * @see Mapper#create\n * @since 3.0.0\n */\n /**\n * Fired during {@link Mapper#create}. See\n * {@link Mapper~afterCreateListener} for how to listen for this event.\n *\n * @event Mapper#afterCreate\n * @see Mapper~afterCreateListener\n * @see Mapper#create\n */\n /**\n * Callback signature for the {@link Mapper#event:afterCreate} event.\n *\n * @example\n * function onAfterCreate (props, opts, result) {\n * // do something\n * }\n * store.on('afterCreate', onAfterCreate);\n *\n * @callback Mapper~afterCreateListener\n * @param {object} props The `props` argument passed to {@link Mapper#afterCreate}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#afterCreate}.\n * @param {object} result The `result` argument passed to {@link Mapper#afterCreate}.\n * @see Mapper#event:afterCreate\n * @see Mapper#create\n * @since 3.0.0\n */\n /**\n * Create and save a new the record using the provided `props`.\n *\n * {@link Mapper#beforeCreate} will be called before calling the adapter.\n * {@link Mapper#afterCreate} will be called after calling the adapter.\n *\n * @example\n * // Create and save a new blog post\n * PostMapper.create({\n * title: 'Modeling your data',\n * status: 'draft'\n * }).then((post) => {\n * console.log(post); // { id: 1234, status: 'draft', ... }\n * });\n *\n * @fires Mapper#beforeCreate\n * @fires Mapper#afterCreate\n * @method Mapper#create\n * @param {object} props The properties for the new record.\n * @param {object} [opts] Configuration options. Refer to the `create` method\n * of whatever adapter you're using for more configuration options.\n * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the\n * adapter to use.\n * @param {boolean} [opts.noValidate={@link Mapper#noValidate}] See {@link Mapper#noValidate}.\n * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}.\n * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}.\n * @param {string[]} [opts.with=[]] Relations to create in a cascading\n * create if `props` contains nested relations. NOT performed in a\n * transaction. Each nested create will result in another {@link Mapper#create}\n * or {@link Mapper#createMany} call.\n * @param {string[]} [opts.pass=[]] Relations to send to the adapter as part\n * of the payload. Normally relations are not sent.\n * @returns {Promise} Resolves with the created record.\n * @since 3.0.0\n */\n create (props, opts) {\n // Default values for arguments\n props || (props = {})\n opts || (opts = {})\n const originalRecord = props\n let parentRelationMap = {}\n let adapterResponse = {}\n\n // Fill in \"opts\" with the Mapper's configuration\n utils._(opts, this)\n opts.adapter = this.getAdapterName(opts)\n\n opts.op = 'beforeCreate'\n return this._runHook(opts.op, props, opts).then((props) => {\n opts.with || (opts.with = [])\n return this._createParentRecordIfRequired(props, opts)\n }).then((relationMap) => {\n parentRelationMap = relationMap\n }).then(() => {\n opts.op = 'create'\n return this._invokeAdapterMethod(opts.op, props, opts)\n }).then((result) => {\n adapterResponse = result\n }).then(() => {\n const createdProps = opts.raw ? adapterResponse.data : adapterResponse\n\n return this._createOrAssignChildRecordIfRequired(createdProps, {\n opts,\n parentRelationMap,\n originalProps: props\n })\n }).then((createdProps) => {\n return this._commitChanges(originalRecord, createdProps)\n }).then((record) => {\n if (opts.raw) {\n adapterResponse.data = record\n } else {\n adapterResponse = record\n }\n const result = this._end(adapterResponse, opts)\n opts.op = 'afterCreate'\n return this._runHook(opts.op, props, opts, result)\n })\n },\n\n _commitChanges (recordOrRecords, newValues) {\n if (utils.isArray(recordOrRecords)) {\n return recordOrRecords.map((record, i) => this._commitChanges(record, newValues[i]))\n }\n\n utils.set(recordOrRecords, newValues, { silent: true })\n\n if (utils.isFunction(recordOrRecords.commit)) {\n recordOrRecords.commit()\n }\n\n return recordOrRecords\n },\n\n /**\n * Use {@link Mapper#createRecord} instead.\n * @deprecated\n * @method Mapper#createInstance\n * @param {Object|Array} props See {@link Mapper#createRecord}.\n * @param {object} [opts] See {@link Mapper#createRecord}.\n * @returns {Object|Array} See {@link Mapper#createRecord}.\n * @see Mapper#createRecord\n * @since 3.0.0\n */\n createInstance (props, opts) {\n return this.createRecord(props, opts)\n },\n\n /**\n * Creates parent record for relation types like BelongsTo or HasMany with localKeys\n * in order to satisfy foreignKey dependency (so called child records).\n * @param {object} props See {@link Mapper#create}.\n * @param {object} opts See {@link Mapper#create}.\n * @returns {Object} cached parent records map\n * @see Mapper#create\n * @since 3.0.0\n */\n _createParentRecordIfRequired (props, opts) {\n const tasks = []\n const relations = []\n\n utils.forEachRelation(this, opts, (def, optsCopy) => {\n if (!def.isRequiresParentId() || !def.getLocalField(props)) {\n return\n }\n\n optsCopy.raw = false\n relations.push(def)\n tasks.push(def.createParentRecord(props, optsCopy))\n })\n\n return utils.Promise.all(tasks).then(records => {\n return relations.reduce((map, relation, index) => {\n relation.setLocalField(map, records[index])\n return map\n }, {})\n })\n },\n\n /**\n * Creates child record for relation types like HasOne or HasMany with foreignKey\n * in order to satisfy foreignKey dependency (so called parent records).\n * @param {object} props See {@link Mapper#create}.\n * @param {object} context contains collected information.\n * @param {object} context.opts See {@link Mapper#create}.\n * @param {object} context.parentRelationMap contains parent records map\n * @param {object} context.originalProps contains data passed into {@link Mapper#create} method\n * @return {Promise} updated props\n * @see Mapper#create\n * @since 3.0.0\n */\n _createOrAssignChildRecordIfRequired (props, context) {\n const tasks = []\n\n utils.forEachRelation(this, context.opts, (def, optsCopy) => {\n const relationData = def.getLocalField(context.originalProps)\n\n if (!relationData) {\n return\n }\n\n optsCopy.raw = false\n // Create hasMany and hasOne after the main create because we needed\n // a generated id to attach to these items\n if (def.isRequiresChildId()) {\n tasks.push(def.createChildRecord(props, relationData, optsCopy))\n } else if (def.isRequiresParentId()) {\n const parent = def.getLocalField(context.parentRelationMap)\n\n if (parent) {\n def.setLocalField(props, parent)\n }\n }\n })\n\n return utils.Promise.all(tasks)\n .then(() => props)\n },\n\n /**\n * Fired during {@link Mapper#createMany}. See\n * {@link Mapper~beforeCreateManyListener} for how to listen for this event.\n *\n * @event Mapper#beforeCreateMany\n * @see Mapper~beforeCreateManyListener\n * @see Mapper#createMany\n */\n /**\n * Callback signature for the {@link Mapper#event:beforeCreateMany} event.\n *\n * @example\n * function onBeforeCreateMany (records, opts) {\n * // do something\n * }\n * store.on('beforeCreateMany', onBeforeCreateMany);\n *\n * @callback Mapper~beforeCreateManyListener\n * @param {object} records The `records` argument received by {@link Mapper#beforeCreateMany}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeCreateMany}.\n * @see Mapper#event:beforeCreateMany\n * @see Mapper#createMany\n * @since 3.0.0\n */\n /**\n * Fired during {@link Mapper#createMany}. See\n * {@link Mapper~afterCreateManyListener} for how to listen for this event.\n *\n * @event Mapper#afterCreateMany\n * @see Mapper~afterCreateManyListener\n * @see Mapper#createMany\n */\n /**\n * Callback signature for the {@link Mapper#event:afterCreateMany} event.\n *\n * @example\n * function onAfterCreateMany (records, opts, result) {\n * // do something\n * }\n * store.on('afterCreateMany', onAfterCreateMany);\n *\n * @callback Mapper~afterCreateManyListener\n * @param {object} records The `records` argument received by {@link Mapper#afterCreateMany}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterCreateMany}.\n * @param {object} result The `result` argument received by {@link Mapper#afterCreateMany}.\n * @see Mapper#event:afterCreateMany\n * @see Mapper#createMany\n * @since 3.0.0\n */\n /**\n * Given an array of records, batch create them via an adapter.\n *\n * {@link Mapper#beforeCreateMany} will be called before calling the adapter.\n * {@link Mapper#afterCreateMany} will be called after calling the adapter.\n *\n * @example\n * // Create and save several new blog posts\n * PostMapper.createMany([{\n * title: 'Modeling your data',\n * status: 'draft'\n * }, {\n * title: 'Reading data',\n * status: 'draft'\n * }]).then((posts) => {\n * console.log(posts[0]); // { id: 1234, status: 'draft', ... }\n * console.log(posts[1]); // { id: 1235, status: 'draft', ... }\n * });\n *\n * @fires Mapper#beforeCreate\n * @fires Mapper#afterCreate\n * @method Mapper#createMany\n * @param {Record[]} records Array of records to be created in one batch.\n * @param {object} [opts] Configuration options. Refer to the `createMany`\n * method of whatever adapter you're using for more configuration options.\n * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the\n * adapter to use.\n * @param {boolean} [opts.noValidate={@link Mapper#noValidate}] See {@link Mapper#noValidate}.\n * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}.\n * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}.\n * @param {string[]} [opts.with=[]] Relations to create in a cascading\n * create if `records` contains nested relations. NOT performed in a\n * transaction. Each nested create will result in another {@link Mapper#createMany}\n * call.\n * @param {string[]} [opts.pass=[]] Relations to send to the adapter as part\n * of the payload. Normally relations are not sent.\n * @returns {Promise} Resolves with the created records.\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/saving-data\",\"Saving data\"]\n */\n createMany (records, opts) {\n // Default values for arguments\n records || (records = [])\n opts || (opts = {})\n const originalRecords = records\n let adapterResponse\n\n // Fill in \"opts\" with the Mapper's configuration\n utils._(opts, this)\n opts.adapter = this.getAdapterName(opts)\n\n // beforeCreateMany lifecycle hook\n opts.op = 'beforeCreateMany'\n return this._runHook(opts.op, records, opts).then((records) => {\n // Deep pre-create belongsTo relations\n const belongsToRelationData = {}\n opts.with || (opts.with = [])\n let tasks = []\n utils.forEachRelation(this, opts, (def, optsCopy) => {\n const relationData = records\n .map((record) => def.getLocalField(record))\n .filter(Boolean)\n if (def.type === belongsToType && relationData.length === records.length) {\n // Create belongsTo relation first because we need a generated id to\n // attach to the child\n optsCopy.raw = false\n tasks.push(def.createLinked(relationData, optsCopy).then((relatedRecords) => {\n records.forEach((record, i) => def.setForeignKey(record, relatedRecords[i]))\n }).then((relatedRecords) => {\n def.setLocalField(belongsToRelationData, relatedRecords)\n }))\n }\n })\n return utils.Promise.all(tasks).then(() => {\n opts.op = 'createMany'\n return this._invokeAdapterMethod(opts.op, records, opts)\n }).then((result) => {\n adapterResponse = result\n }).then(() => {\n const createdRecordsData = opts.raw ? adapterResponse.data : adapterResponse\n\n // Deep post-create hasOne relations\n tasks = []\n utils.forEachRelation(this, opts, (def, optsCopy) => {\n const relationData = records\n .map((record) => def.getLocalField(record))\n .filter(Boolean)\n if (relationData.length !== records.length) {\n return\n }\n\n optsCopy.raw = false\n const belongsToData = def.getLocalField(belongsToRelationData)\n let task\n // Create hasMany and hasOne after the main create because we needed\n // a generated id to attach to these items\n if (def.type === hasManyType) {\n // Not supported\n this.log('warn', 'deep createMany of hasMany type not supported!')\n } else if (def.type === hasOneType) {\n createdRecordsData.forEach((createdRecordData, i) => {\n def.setForeignKey(createdRecordData, relationData[i])\n })\n task = def.getRelation().createMany(relationData, optsCopy).then((relatedData) => {\n createdRecordsData.forEach((createdRecordData, i) => {\n def.setLocalField(createdRecordData, relatedData[i])\n })\n })\n } else if (def.type === belongsToType && belongsToData && belongsToData.length === createdRecordsData.length) {\n createdRecordsData.forEach((createdRecordData, i) => {\n def.setLocalField(createdRecordData, belongsToData[i])\n })\n }\n if (task) {\n tasks.push(task)\n }\n })\n return utils.Promise.all(tasks).then(() => {\n return this._commitChanges(originalRecords, createdRecordsData)\n })\n })\n }).then((records) => {\n if (opts.raw) {\n adapterResponse.data = records\n } else {\n adapterResponse = records\n }\n const result = this._end(adapterResponse, opts)\n opts.op = 'afterCreateMany'\n return this._runHook(opts.op, records, opts, result)\n })\n },\n\n /**\n * Create an unsaved, uncached instance of this Mapper's\n * {@link Mapper#recordClass}.\n *\n * Returns `props` if `props` is already an instance of\n * {@link Mapper#recordClass}.\n *\n * __Note:__ This method does __not__ interact with any adapter, and does\n * __not__ save any data. It only creates new objects in memory.\n *\n * @example\n * // Create empty unsaved record instance\n * const post = PostMapper.createRecord();\n *\n * @example\n * // Create an unsaved record instance with inital properties\n * const post = PostMapper.createRecord({\n * title: 'Modeling your data',\n * status: 'draft'\n * });\n *\n * @example\n * // Create a record instance that corresponds to a saved record\n * const post = PostMapper.createRecord({\n * // JSData thinks this record has been saved if it has a primary key\n * id: 1234,\n * title: 'Modeling your data',\n * status: 'draft'\n * });\n *\n * @example\n * // Create record instances from an array\n * const posts = PostMapper.createRecord([{\n * title: 'Modeling your data',\n * status: 'draft'\n * }, {\n * title: 'Reading data',\n * status: 'draft'\n * }]);\n *\n * @example\n * // Records are validated by default\n * import { Mapper } from 'js-data';\n * const PostMapper = new Mapper({\n * name: 'post',\n * schema: { properties: { title: { type: 'string' } } }\n * });\n * try {\n * const post = PostMapper.createRecord({\n * title: 1234,\n * });\n * } catch (err) {\n * console.log(err.errors); // [{ expected: 'one of (string)', actual: 'number', path: 'title' }]\n * }\n *\n * @example\n * // Skip validation\n * import { Mapper } from 'js-data';\n * const PostMapper = new Mapper({\n * name: 'post',\n * schema: { properties: { title: { type: 'string' } } }\n * });\n * const post = PostMapper.createRecord({\n * title: 1234,\n * }, { noValidate: true });\n * console.log(post.isValid()); // false\n *\n * @method Mapper#createRecord\n * @param {Object|Object[]} props The properties for the Record instance or an\n * array of property objects for the Record instances.\n * @param {object} [opts] Configuration options.\n * @param {boolean} [opts.noValidate={@link Mapper#noValidate}] See {@link Mapper#noValidate}.\n * @returns {Record|Record[]} The Record instance or Record instances.\n * @since 3.0.0\n */\n createRecord (props, opts) {\n props || (props = {})\n if (utils.isArray(props)) {\n return props.map((_props) => this.createRecord(_props, opts))\n }\n if (!utils.isObject(props)) {\n throw utils.err(`${DOMAIN}#createRecord`, 'props')(400, 'array or object', props)\n }\n\n if (this.relationList) {\n this.relationList.forEach(function (def) {\n def.ensureLinkedDataHasProperType(props, opts)\n })\n }\n const RecordCtor = this.recordClass\n\n return (!RecordCtor || props instanceof RecordCtor) ? props : new RecordCtor(props, opts)\n },\n\n /**\n * Lifecycle invocation method. You probably won't call this method directly.\n *\n * @method Mapper#crud\n * @param {string} method Name of the lifecycle method to invoke.\n * @param {...*} args Arguments to pass to the lifecycle method.\n * @returns {Promise}\n * @since 3.0.0\n */\n crud (method, ...args) {\n const config = this.lifecycleMethods[method]\n if (!config) {\n throw utils.err(`${DOMAIN}#crud`, method)(404, 'method')\n }\n\n const upper = `${method.charAt(0).toUpperCase()}${method.substr(1)}`\n const before = `before${upper}`\n const after = `after${upper}`\n\n let op\n\n // Default values for arguments\n config.defaults.forEach((value, i) => {\n if (args[i] === undefined) {\n args[i] = utils.copy(value)\n }\n })\n\n const opts = args[args.length - 1]\n\n // Fill in \"opts\" with the Mapper's configuration\n utils._(opts, this)\n const adapter = opts.adapter = this.getAdapterName(opts)\n\n // before lifecycle hook\n op = opts.op = before\n return utils.resolve(this[op](...args)).then((_value) => {\n if (args[config.beforeAssign] !== undefined) {\n // Allow for re-assignment from lifecycle hook\n args[config.beforeAssign] = _value === undefined ? args[config.beforeAssign] : _value\n }\n // Now delegate to the adapter\n op = opts.op = method\n args = config.adapterArgs ? config.adapterArgs(this, ...args) : args\n this.dbg(op, ...args)\n return utils.resolve(this.getAdapter(adapter)[op](this, ...args))\n }).then((result) => {\n // force noValidate on find/findAll\n const noValidate = /find/.test(op) || opts.noValidate\n const _opts = Object.assign({}, opts, { noValidate })\n\n result = this._end(result, _opts, !!config.skip)\n args.push(result)\n // after lifecycle hook\n op = opts.op = after\n return utils.resolve(this[op](...args)).then((_result) => {\n // Allow for re-assignment from lifecycle hook\n return _result === undefined ? result : _result\n })\n })\n },\n\n /**\n * Fired during {@link Mapper#destroy}. See\n * {@link Mapper~beforeDestroyListener} for how to listen for this event.\n *\n * @event Mapper#beforeDestroy\n * @see Mapper~beforeDestroyListener\n * @see Mapper#destroy\n */\n /**\n * Callback signature for the {@link Mapper#event:beforeDestroy} event.\n *\n * @example\n * function onBeforeDestroy (id, opts) {\n * // do something\n * }\n * store.on('beforeDestroy', onBeforeDestroy);\n *\n * @callback Mapper~beforeDestroyListener\n * @param {string|number} id The `id` argument passed to {@link Mapper#beforeDestroy}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#beforeDestroy}.\n * @see Mapper#event:beforeDestroy\n * @see Mapper#destroy\n * @since 3.0.0\n */\n /**\n * Fired during {@link Mapper#destroy}. See\n * {@link Mapper~afterDestroyListener} for how to listen for this event.\n *\n * @event Mapper#afterDestroy\n * @see Mapper~afterDestroyListener\n * @see Mapper#destroy\n */\n /**\n * Callback signature for the {@link Mapper#event:afterDestroy} event.\n *\n * @example\n * function onAfterDestroy (id, opts, result) {\n * // do something\n * }\n * store.on('afterDestroy', onAfterDestroy);\n *\n * @callback Mapper~afterDestroyListener\n * @param {string|number} id The `id` argument passed to {@link Mapper#afterDestroy}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#afterDestroy}.\n * @param {object} result The `result` argument passed to {@link Mapper#afterDestroy}.\n * @see Mapper#event:afterDestroy\n * @see Mapper#destroy\n * @since 3.0.0\n */\n /**\n * Using an adapter, destroy the record with the given primary key.\n *\n * {@link Mapper#beforeDestroy} will be called before destroying the record.\n * {@link Mapper#afterDestroy} will be called after destroying the record.\n *\n * @example\n * // Destroy a specific blog post\n * PostMapper.destroy(1234).then(() => {\n * // Blog post #1234 has been destroyed\n * });\n *\n * @example\n * // Get full response\n * PostMapper.destroy(1234, { raw: true }).then((result) => {\n * console.log(result.deleted); e.g. 1\n * console.log(...); // etc., more metadata can be found on the result\n * });\n *\n * @fires Mapper#beforeDestroy\n * @fires Mapper#afterDestroy\n * @method Mapper#destroy\n * @param {(string|number)} id The primary key of the record to destroy.\n * @param {object} [opts] Configuration options. Refer to the `destroy` method\n * of whatever adapter you're using for more configuration options.\n * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the\n * adapter to use.\n * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}.\n * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}.\n * @returns {Promise} Resolves when the record has been destroyed. Resolves\n * even if no record was found to be destroyed.\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/saving-data\",\"Saving data\"]\n */\n destroy (id, opts) {\n return this.crud('destroy', id, opts)\n },\n\n /**\n * Fired during {@link Mapper#destroyAll}. See\n * {@link Mapper~beforeDestroyAllListener} for how to listen for this event.\n *\n * @event Mapper#beforeDestroyAll\n * @see Mapper~beforeDestroyAllListener\n * @see Mapper#destroyAll\n */\n /**\n * Callback signature for the {@link Mapper#event:beforeDestroyAll} event.\n *\n * @example\n * function onBeforeDestroyAll (query, opts) {\n * // do something\n * }\n * store.on('beforeDestroyAll', onBeforeDestroyAll);\n *\n * @callback Mapper~beforeDestroyAllListener\n * @param {object} query The `query` argument passed to {@link Mapper#beforeDestroyAll}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#beforeDestroyAll}.\n * @see Mapper#event:beforeDestroyAll\n * @see Mapper#destroyAll\n * @since 3.0.0\n */\n /**\n * Fired during {@link Mapper#destroyAll}. See\n * {@link Mapper~afterDestroyAllListener} for how to listen for this event.\n *\n * @event Mapper#afterDestroyAll\n * @see Mapper~afterDestroyAllListener\n * @see Mapper#destroyAll\n */\n /**\n * Callback signature for the {@link Mapper#event:afterDestroyAll} event.\n *\n * @example\n * function onAfterDestroyAll (query, opts, result) {\n * // do something\n * }\n * store.on('afterDestroyAll', onAfterDestroyAll);\n *\n * @callback Mapper~afterDestroyAllListener\n * @param {object} query The `query` argument passed to {@link Mapper#afterDestroyAll}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#afterDestroyAll}.\n * @param {object} result The `result` argument passed to {@link Mapper#afterDestroyAll}.\n * @see Mapper#event:afterDestroyAll\n * @see Mapper#destroyAll\n * @since 3.0.0\n */\n /**\n * Destroy the records selected by `query` via an adapter. If no `query` is\n * provided then all records will be destroyed.\n *\n * {@link Mapper#beforeDestroyAll} will be called before destroying the records.\n * {@link Mapper#afterDestroyAll} will be called after destroying the records.\n *\n * @example\n * // Destroy all blog posts\n * PostMapper.destroyAll().then(() => {\n * // All blog posts have been destroyed\n * });\n *\n * @example\n * // Destroy all \"draft\" blog posts\n * PostMapper.destroyAll({ status: 'draft' }).then(() => {\n * // All \"draft\" blog posts have been destroyed\n * });\n *\n * @example\n * // Get full response\n * const query = null;\n * const options = { raw: true };\n * PostMapper.destroyAll(query, options).then((result) => {\n * console.log(result.deleted); e.g. 14\n * console.log(...); // etc., more metadata can be found on the result\n * });\n *\n * @fires Mapper#beforeDestroyAll\n * @fires Mapper#afterDestroyAll\n * @method Mapper#destroyAll\n * @param {object} [query={}] Selection query. See {@link query}.\n * @param {object} [query.where] See {@link query.where}.\n * @param {number} [query.offset] See {@link query.offset}.\n * @param {number} [query.limit] See {@link query.limit}.\n * @param {string|Array[]} [query.orderBy] See {@link query.orderBy}.\n * @param {object} [opts] Configuration options. Refer to the `destroyAll`\n * method of whatever adapter you're using for more configuration options.\n * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the\n * adapter to use.\n * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}.\n * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}.\n * @returns {Promise} Resolves when the records have been destroyed. Resolves\n * even if no records were found to be destroyed.\n * @see query\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/saving-data\",\"Saving data\"]\n */\n destroyAll (query, opts) {\n return this.crud('destroyAll', query, opts)\n },\n\n /**\n * Fired during {@link Mapper#find}. See\n * {@link Mapper~beforeFindListener} for how to listen for this event.\n *\n * @event Mapper#beforeFind\n * @see Mapper~beforeFindListener\n * @see Mapper#find\n */\n /**\n * Callback signature for the {@link Mapper#event:beforeFind} event.\n *\n * @example\n * function onBeforeFind (id, opts) {\n * // do something\n * }\n * store.on('beforeFind', onBeforeFind);\n *\n * @callback Mapper~beforeFindListener\n * @param {string|number} id The `id` argument passed to {@link Mapper#beforeFind}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#beforeFind}.\n * @see Mapper#event:beforeFind\n * @see Mapper#find\n * @since 3.0.0\n */\n /**\n * Fired during {@link Mapper#find}. See\n * {@link Mapper~afterFindListener} for how to listen for this event.\n *\n * @event Mapper#afterFind\n * @see Mapper~afterFindListener\n * @see Mapper#find\n */\n /**\n * Callback signature for the {@link Mapper#event:afterFind} event.\n *\n * @example\n * function onAfterFind (id, opts, result) {\n * // do something\n * }\n * store.on('afterFind', onAfterFind);\n *\n * @callback Mapper~afterFindListener\n * @param {string|number} id The `id` argument passed to {@link Mapper#afterFind}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#afterFind}.\n * @param {object} result The `result` argument passed to {@link Mapper#afterFind}.\n * @see Mapper#event:afterFind\n * @see Mapper#find\n * @since 3.0.0\n */\n /**\n * Retrieve via an adapter the record with the given primary key.\n *\n * {@link Mapper#beforeFind} will be called before calling the adapter.\n * {@link Mapper#afterFind} will be called after calling the adapter.\n *\n * @example\n * PostMapper.find(1).then((post) => {\n * console.log(post); // { id: 1, ...}\n * });\n *\n * @example\n * // Get full response\n * PostMapper.find(1, { raw: true }).then((result) => {\n * console.log(result.data); // { id: 1, ...}\n * console.log(result.found); // 1\n * console.log(...); // etc., more metadata can be found on the result\n * });\n *\n * @fires Mapper#beforeFind\n * @fires Mapper#afterFind\n * @method Mapper#find\n * @param {(string|number)} id The primary key of the record to retrieve.\n * @param {object} [opts] Configuration options. Refer to the `find` method\n * of whatever adapter you're using for more configuration options.\n * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the\n * adapter to use.\n * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}.\n * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}.\n * @param {string[]} [opts.with=[]] Relations to eager load in the request.\n * @returns {Promise} Resolves with the found record. Resolves with\n * `undefined` if no record was found.\n * @see http://www.js-data.io/v3.0/docs/reading-data\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/reading-data\",\"Reading data\"]\n */\n find (id, opts) {\n return this.crud('find', id, opts)\n },\n\n /**\n * Fired during {@link Mapper#findAll}. See\n * {@link Mapper~beforeFindAllListener} for how to listen for this event.\n *\n * @event Mapper#beforeFindAll\n * @see Mapper~beforeFindAllListener\n * @see Mapper#findAll\n */\n /**\n * Callback signature for the {@link Mapper#event:beforeFindAll} event.\n *\n * @example\n * function onBeforeFindAll (query, opts) {\n * // do something\n * }\n * store.on('beforeFindAll', onBeforeFindAll);\n *\n * @callback Mapper~beforeFindAllListener\n * @param {object} query The `query` argument passed to {@link Mapper#beforeFindAll}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#beforeFindAll}.\n * @see Mapper#event:beforeFindAll\n * @see Mapper#findAll\n * @since 3.0.0\n */\n /**\n * Fired during {@link Mapper#findAll}. See\n * {@link Mapper~afterFindAllListener} for how to listen for this event.\n *\n * @event Mapper#afterFindAll\n * @see Mapper~afterFindAllListener\n * @see Mapper#findAll\n */\n /**\n * Callback signature for the {@link Mapper#event:afterFindAll} event.\n *\n * @example\n * function onAfterFindAll (query, opts, result) {\n * // do something\n * }\n * store.on('afterFindAll', onAfterFindAll);\n *\n * @callback Mapper~afterFindAllListener\n * @param {object} query The `query` argument passed to {@link Mapper#afterFindAll}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#afterFindAll}.\n * @param {object} result The `result` argument passed to {@link Mapper#afterFindAll}.\n * @see Mapper#event:afterFindAll\n * @see Mapper#findAll\n * @since 3.0.0\n */\n /**\n * Using the `query` argument, select records to retrieve via an adapter.\n *\n * {@link Mapper#beforeFindAll} will be called before calling the adapter.\n * {@link Mapper#afterFindAll} will be called after calling the adapter.\n *\n * @example\n * // Find all \"published\" blog posts\n * PostMapper.findAll({ status: 'published' }).then((posts) => {\n * console.log(posts); // [{ id: 1, status: 'published', ...}, ...]\n * });\n *\n * @example\n * // Get full response\n * PostMapper.findAll({ status: 'published' }, { raw: true }).then((result) => {\n * console.log(result.data); // [{ id: 1, status: 'published', ...}, ...]\n * console.log(result.found); // e.g. 13\n * console.log(...); // etc., more metadata can be found on the result\n * });\n *\n * @fires Mapper#beforeFindAll\n * @fires Mapper#afterFindAll\n * @method Mapper#findAll\n * @param {object} [query={}] Selection query. See {@link query}.\n * @param {object} [query.where] See {@link query.where}.\n * @param {number} [query.offset] See {@link query.offset}.\n * @param {number} [query.limit] See {@link query.limit}.\n * @param {string|Array[]} [query.orderBy] See {@link query.orderBy}.\n * @param {object} [opts] Configuration options. Refer to the `findAll` method\n * of whatever adapter you're using for more configuration options.\n * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the\n * adapter to use.\n * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}.\n * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}.\n * @param {string[]} [opts.with=[]] Relations to eager load in the request.\n * @returns {Promise} Resolves with the found records, if any.\n * @see query\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/reading-data\",\"Reading data\"]\n */\n findAll (query, opts) {\n return this.crud('findAll', query, opts)\n },\n\n /**\n * Return the registered adapter with the given name or the default adapter if\n * no name is provided.\n *\n * @method Mapper#getAdapter\n * @param {string} [name] The name of the adapter to retrieve.\n * @returns {Adapter} The adapter.\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/connecting-to-a-data-source\",\"Connecting to a data source\"]\n */\n getAdapter (name) {\n this.dbg('getAdapter', 'name:', name)\n const adapter = this.getAdapterName(name)\n if (!adapter) {\n throw utils.err(`${DOMAIN}#getAdapter`, 'name')(400, 'string', name)\n }\n return this.getAdapters()[adapter]\n },\n\n /**\n * Return the name of a registered adapter based on the given name or options,\n * or the name of the default adapter if no name provided.\n *\n * @method Mapper#getAdapterName\n * @param {(Object|string)} [opts] The name of an adapter or options, if any.\n * @returns {string} The name of the adapter.\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/connecting-to-a-data-source\",\"Connecting to a data source\"]\n */\n getAdapterName (opts) {\n opts || (opts = {})\n if (utils.isString(opts)) {\n opts = { adapter: opts }\n }\n return opts.adapter || opts.defaultAdapter\n },\n\n /**\n * Get the object of registered adapters for this Mapper.\n *\n * @method Mapper#getAdapters\n * @returns {Object} {@link Mapper#_adapters}\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/connecting-to-a-data-source\",\"Connecting to a data source\"]\n */\n getAdapters () {\n return this._adapters\n },\n\n /**\n * Returns this Mapper's {@link Schema}.\n *\n * @method Mapper#getSchema\n * @returns {Schema} This Mapper's {@link Schema}.\n * @see Mapper#schema\n * @since 3.0.0\n */\n getSchema () {\n return this.schema\n },\n\n /**\n * Defines a hasMany relationship. Only useful if you're managing your\n * Mappers manually and not using a Container or DataStore component.\n *\n * @example\n * UserMapper.hasMany(PostMapper, {\n * // post.user_id points to user.id\n * foreignKey: 'user_id'\n * // post records will be attached to user records at \"user.posts\"\n * localField: 'posts'\n * });\n *\n * @method Mapper#hasMany\n * @see http://www.js-data.io/v3.0/docs/relations\n * @since 3.0.0\n */\n hasMany (relatedMapper, opts) {\n return hasMany(relatedMapper, opts)(this)\n },\n\n /**\n * Defines a hasOne relationship. Only useful if you're managing your Mappers\n * manually and not using a {@link Container} or {@link DataStore} component.\n *\n * @example\n * UserMapper.hasOne(ProfileMapper, {\n * // profile.user_id points to user.id\n * foreignKey: 'user_id'\n * // profile records will be attached to user records at \"user.profile\"\n * localField: 'profile'\n * });\n *\n * @method Mapper#hasOne\n * @see http://www.js-data.io/v3.0/docs/relations\n * @since 3.0.0\n */\n hasOne (relatedMapper, opts) {\n return hasOne(relatedMapper, opts)(this)\n },\n\n /**\n * Return whether `record` is an instance of this Mapper's recordClass.\n *\n * @example\n * const post = PostMapper.createRecord();\n *\n * console.log(PostMapper.is(post)); // true\n * // Equivalent to what's above\n * console.log(post instanceof PostMapper.recordClass); // true\n *\n * @method Mapper#is\n * @param {Object|Record} record The record to check.\n * @returns {boolean} Whether `record` is an instance of this Mapper's\n * {@link Mapper#recordClass}.\n * @since 3.0.0\n */\n is (record) {\n const recordClass = this.recordClass\n return recordClass ? record instanceof recordClass : false\n },\n\n /**\n * Register an adapter on this Mapper under the given name.\n *\n * @method Mapper#registerAdapter\n * @param {string} name The name of the adapter to register.\n * @param {Adapter} adapter The adapter to register.\n * @param {object} [opts] Configuration options.\n * @param {boolean} [opts.default=false] Whether to make the adapter the\n * default adapter for this Mapper.\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/connecting-to-a-data-source\",\"Connecting to a data source\"]\n */\n registerAdapter (name, adapter, opts) {\n opts || (opts = {})\n this.getAdapters()[name] = adapter\n // Optionally make it the default adapter for the target.\n if (opts === true || opts.default) {\n this.defaultAdapter = name\n }\n },\n\n _runHook (hookName, ...hookArgs) {\n const defaultValueIndex = hookName.indexOf('after') === 0 ? hookArgs.length - 1 : 0\n\n return utils.resolve(this[hookName](...hookArgs))\n .then((overridenResult) => overridenResult === undefined ? hookArgs[defaultValueIndex] : overridenResult)\n },\n\n _invokeAdapterMethod (method, propsOrRecords, opts) {\n const conversionOptions = { with: opts.pass || [] }\n let object\n\n this.dbg(opts.op, propsOrRecords, opts)\n\n if (utils.isArray(propsOrRecords)) {\n object = propsOrRecords.map(record => this.toJSON(record, conversionOptions))\n } else {\n object = this.toJSON(propsOrRecords, conversionOptions)\n }\n\n return this.getAdapter(opts.adapter)[method](this, object, opts)\n },\n\n /**\n * Select records according to the `query` argument, and aggregate the sum\n * value of the property specified by `field`.\n *\n * {@link Mapper#beforeSum} will be called before calling the adapter.\n * {@link Mapper#afterSum} will be called after calling the adapter.\n *\n * @example\n * PurchaseOrderMapper.sum('amount', { status: 'paid' }).then((amountPaid) => {\n * console.log(amountPaid); // e.g. 451125.34\n * });\n *\n * @method Mapper#sum\n * @param {string} field The field to sum.\n * @param {object} [query={}] Selection query. See {@link query}.\n * @param {object} [query.where] See {@link query.where}.\n * @param {number} [query.offset] See {@link query.offset}.\n * @param {number} [query.limit] See {@link query.limit}.\n * @param {string|Array[]} [query.orderBy] See {@link query.orderBy}.\n * @param {object} [opts] Configuration options. Refer to the `sum` method\n * of whatever adapter you're using for more configuration options.\n * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the\n * adapter to use.\n * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}.\n * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}.\n * @returns {Promise} Resolves with the aggregated sum.\n * @since 3.0.0\n */\n sum (field, query, opts) {\n return this.crud('sum', field, query, opts)\n },\n\n /**\n * Return a plain object representation of the given record. Relations can\n * be optionally be included. Non-schema properties can be excluded.\n *\n * @example\n * import { Mapper, Schema } from 'js-data';\n * const PersonMapper = new Mapper({\n * name: 'person',\n * schema: {\n * properties: {\n * name: { type: 'string' },\n * id: { type: 'string' }\n * }\n * }\n * });\n * const person = PersonMapper.createRecord({ id: 1, name: 'John', foo: 'bar' });\n * // \"foo\" is stripped by toJSON()\n * console.log(PersonMapper.toJSON(person)); // {\"id\":1,\"name\":\"John\"}\n *\n * const PersonRelaxedMapper = new Mapper({\n * name: 'personRelaxed',\n * schema: {\n * properties: {\n * name: { type: 'string' },\n * id: { type: 'string' }\n * },\n * additionalProperties: true\n * }\n * });\n * const person2 = PersonRelaxedMapper.createRecord({ id: 1, name: 'John', foo: 'bar' });\n * // \"foo\" is not stripped by toJSON\n * console.log(PersonRelaxedMapper.toJSON(person2)); // {\"id\":1,\"name\":\"John\",\"foo\":\"bar\"}\n *\n * @method Mapper#toJSON\n * @param {Record|Record[]} records Record or records from which to create a\n * POJO representation.\n * @param {object} [opts] Configuration options.\n * @param {string[]} [opts.with] Array of relation names or relation fields\n * to include in the POJO representation.\n * @param {boolean} [opts.withAll] Whether to simply include all relations in\n * the representation. Overrides `opts.with`.\n * @returns {Object|Object[]} POJO representation of the record or records.\n * @since 3.0.0\n */\n toJSON (records, opts) {\n let record\n opts || (opts = {})\n if (utils.isArray(records)) {\n return records.map((record) => this.toJSON(record, opts))\n } else {\n record = records\n }\n const relationFields = (this ? this.relationFields : []) || []\n let json = {}\n\n // Copy properties defined in the schema\n if (this && this.schema) {\n json = this.schema.pick(record)\n } else {\n for (var key in record) {\n if (relationFields.indexOf(key) === -1) {\n json[key] = utils.plainCopy(record[key])\n }\n }\n }\n\n // The user wants to include relations in the resulting plain object representation\n if (this && opts.withAll) {\n opts.with = relationFields.slice()\n }\n if (this && opts.with) {\n if (utils.isString(opts.with)) {\n opts.with = [opts.with]\n }\n utils.forEachRelation(this, opts, (def, optsCopy) => {\n const relationData = def.getLocalField(record)\n if (relationData) {\n // The actual recursion\n if (utils.isArray(relationData)) {\n def.setLocalField(json, relationData.map((item) => {\n return def.getRelation().toJSON(item, optsCopy)\n }))\n } else {\n def.setLocalField(json, def.getRelation().toJSON(relationData, optsCopy))\n }\n }\n })\n }\n return json\n },\n\n /**\n * Fired during {@link Mapper#update}. See\n * {@link Mapper~beforeUpdateListener} for how to listen for this event.\n *\n * @event Mapper#beforeUpdate\n * @see Mapper~beforeUpdateListener\n * @see Mapper#update\n */\n /**\n * Callback signature for the {@link Mapper#event:beforeUpdate} event.\n *\n * @example\n * function onBeforeUpdate (id, props, opts) {\n * // do something\n * }\n * store.on('beforeUpdate', onBeforeUpdate);\n *\n * @callback Mapper~beforeUpdateListener\n * @param {string|number} id The `id` argument passed to {@link Mapper#beforeUpdate}.\n * @param {object} props The `props` argument passed to {@link Mapper#beforeUpdate}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#beforeUpdate}.\n * @see Mapper#event:beforeUpdate\n * @see Mapper#update\n * @since 3.0.0\n */\n /**\n * Fired during {@link Mapper#update}. See\n * {@link Mapper~afterUpdateListener} for how to listen for this event.\n *\n * @event Mapper#afterUpdate\n * @see Mapper~afterUpdateListener\n * @see Mapper#update\n */\n /**\n * Callback signature for the {@link Mapper#event:afterUpdate} event.\n *\n * @example\n * function onAfterUpdate (id, props, opts, result) {\n * // do something\n * }\n * store.on('afterUpdate', onAfterUpdate);\n *\n * @callback Mapper~afterUpdateListener\n * @param {string|number} id The `id` argument passed to {@link Mapper#afterUpdate}.\n * @param {object} props The `props` argument passed to {@link Mapper#afterUpdate}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#afterUpdate}.\n * @param {object} result The `result` argument passed to {@link Mapper#afterUpdate}.\n * @see Mapper#event:afterUpdate\n * @see Mapper#update\n * @since 3.0.0\n */\n /**\n * Using an adapter, update the record with the primary key specified by the\n * `id` argument.\n *\n * {@link Mapper#beforeUpdate} will be called before updating the record.\n * {@link Mapper#afterUpdate} will be called after updating the record.\n *\n * @example\n * // Update a specific post\n * PostMapper.update(1234, {\n * status: 'published',\n * published_at: new Date()\n * }).then((post) => {\n * console.log(post); // { id: 1234, status: 'published', ... }\n * });\n *\n * @fires Mapper#beforeUpdate\n * @fires Mapper#afterUpdate\n * @method Mapper#update\n * @param {(string|number)} id The primary key of the record to update.\n * @param {object} props The update to apply to the record.\n * @param {object} [opts] Configuration options. Refer to the `update` method\n * of whatever adapter you're using for more configuration options.\n * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the\n * adapter to use.\n * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}.\n * @param {boolean} [opts.noValidate={@link Mapper#noValidate}] See {@link Mapper#noValidate}.\n * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}.\n * transaction.\n * @returns {Promise} Resolves with the updated record. Rejects if the record\n * could not be found.\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/saving-data\",\"Saving data\"]\n */\n update (id, props, opts) {\n return this.crud('update', id, props, opts)\n },\n\n /**\n * Fired during {@link Mapper#updateAll}. See\n * {@link Mapper~beforeUpdateAllListener} for how to listen for this event.\n *\n * @event Mapper#beforeUpdateAll\n * @see Mapper~beforeUpdateAllListener\n * @see Mapper#updateAll\n */\n /**\n * Callback signature for the {@link Mapper#event:beforeUpdateAll} event.\n *\n * @example\n * function onBeforeUpdateAll (props, query, opts) {\n * // do something\n * }\n * store.on('beforeUpdateAll', onBeforeUpdateAll);\n *\n * @callback Mapper~beforeUpdateAllListener\n * @param {object} props The `props` argument received by {@link Mapper#beforeUpdateAll}.\n * @param {object} query The `query` argument received by {@link Mapper#beforeUpdateAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdateAll}.\n * @see Mapper#event:beforeUpdateAll\n * @see Mapper#updateAll\n * @since 3.0.0\n */\n /**\n * Fired during {@link Mapper#updateAll}. See\n * {@link Mapper~afterUpdateAllListener} for how to listen for this event.\n *\n * @event Mapper#afterUpdateAll\n * @see Mapper~afterUpdateAllListener\n * @see Mapper#updateAll\n */\n /**\n * Callback signature for the {@link Mapper#event:afterUpdateAll} event.\n *\n * @example\n * function onAfterUpdateAll (props, query, opts, result) {\n * // do something\n * }\n * store.on('afterUpdateAll', onAfterUpdateAll);\n *\n * @callback Mapper~afterUpdateAllListener\n * @param {object} props The `props` argument received by {@link Mapper#afterUpdateAll}.\n * @param {object} query The `query` argument received by {@link Mapper#afterUpdateAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdateAll}.\n * @param {object} result The `result` argument received by {@link Mapper#afterUpdateAll}.\n * @see Mapper#event:afterUpdateAll\n * @see Mapper#updateAll\n * @since 3.0.0\n */\n /**\n * Using the `query` argument, perform the a single updated to the selected\n * records.\n *\n * {@link Mapper#beforeUpdateAll} will be called before making the update.\n * {@link Mapper#afterUpdateAll} will be called after making the update.\n *\n * @example\n * // Turn all of John's blog posts into drafts.\n * const update = { status: draft: published_at: null };\n * const query = { userId: 1234 };\n * PostMapper.updateAll(update, query).then((posts) => {\n * console.log(posts); // [...]\n * });\n *\n * @fires Mapper#beforeUpdateAll\n * @fires Mapper#afterUpdateAll\n * @method Mapper#updateAll\n * @param {object} props Update to apply to selected records.\n * @param {object} [query={}] Selection query. See {@link query}.\n * @param {object} [query.where] See {@link query.where}.\n * @param {number} [query.offset] See {@link query.offset}.\n * @param {number} [query.limit] See {@link query.limit}.\n * @param {string|Array[]} [query.orderBy] See {@link query.orderBy}.\n * @param {object} [opts] Configuration options. Refer to the `updateAll`\n * method of whatever adapter you're using for more configuration options.\n * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the\n * adapter to use.\n * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}.\n * @param {boolean} [opts.noValidate={@link Mapper#noValidate}] See {@link Mapper#noValidate}.\n * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}.\n * @returns {Promise} Resolves with the update records, if any.\n * @see query\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/saving-data\",\"Saving data\"]\n */\n updateAll (props, query, opts) {\n return this.crud('updateAll', props, query, opts)\n },\n\n /**\n * Fired during {@link Mapper#updateMany}. See\n * {@link Mapper~beforeUpdateManyListener} for how to listen for this event.\n *\n * @event Mapper#beforeUpdateMany\n * @see Mapper~beforeUpdateManyListener\n * @see Mapper#updateMany\n */\n /**\n * Callback signature for the {@link Mapper#event:beforeUpdateMany} event.\n *\n * @example\n * function onBeforeUpdateMany (records, opts) {\n * // do something\n * }\n * store.on('beforeUpdateMany', onBeforeUpdateMany);\n *\n * @callback Mapper~beforeUpdateManyListener\n * @param {object} records The `records` argument received by {@link Mapper#beforeUpdateMany}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdateMany}.\n * @see Mapper#event:beforeUpdateMany\n * @see Mapper#updateMany\n * @since 3.0.0\n */\n /**\n * Fired during {@link Mapper#updateMany}. See\n * {@link Mapper~afterUpdateManyListener} for how to listen for this event.\n *\n * @event Mapper#afterUpdateMany\n * @see Mapper~afterUpdateManyListener\n * @see Mapper#updateMany\n */\n /**\n * Callback signature for the {@link Mapper#event:afterUpdateMany} event.\n *\n * @example\n * function onAfterUpdateMany (records, opts, result) {\n * // do something\n * }\n * store.on('afterUpdateMany', onAfterUpdateMany);\n *\n * @callback Mapper~afterUpdateManyListener\n * @param {object} records The `records` argument received by {@link Mapper#afterUpdateMany}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdateMany}.\n * @param {object} result The `result` argument received by {@link Mapper#afterUpdateMany}.\n * @see Mapper#event:afterUpdateMany\n * @see Mapper#updateMany\n * @since 3.0.0\n */\n /**\n * Given an array of updates, perform each of the updates via an adapter. Each\n * \"update\" is a hash of properties with which to update an record. Each\n * update must contain the primary key of the record to be updated.\n *\n * {@link Mapper#beforeUpdateMany} will be called before making the update.\n * {@link Mapper#afterUpdateMany} will be called after making the update.\n *\n * @example\n * PostMapper.updateMany([\n * { id: 1234, status: 'draft' },\n * { id: 2468, status: 'published', published_at: new Date() }\n * ]).then((posts) => {\n * console.log(posts); // [...]\n * });\n *\n * @fires Mapper#beforeUpdateMany\n * @fires Mapper#afterUpdateMany\n * @method Mapper#updateMany\n * @param {Record[]} records Array up record updates.\n * @param {object} [opts] Configuration options. Refer to the `updateMany`\n * method of whatever adapter you're using for more configuration options.\n * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the\n * adapter to use.\n * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}.\n * @param {boolean} [opts.noValidate={@link Mapper#noValidate}] See {@link Mapper#noValidate}.\n * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}.\n * @returns {Promise} Resolves with the updated records. Rejects if any of the\n * records could be found.\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/saving-data\",\"Saving data\"]\n */\n updateMany (records, opts) {\n return this.crud('updateMany', records, opts)\n },\n\n /**\n * Validate the given record or records according to this Mapper's\n * {@link Schema}. If there are no validation errors then the return value\n * will be `undefined`.\n *\n * @example\n * import {Mapper, Schema} from 'js-data'\n * const PersonSchema = new Schema({\n * properties: {\n * name: { type: 'string' },\n * id: { type: 'string' }\n * }\n * });\n * const PersonMapper = new Mapper({\n * name: 'person',\n * schema: PersonSchema\n * });\n * let errors = PersonMapper.validate({ name: 'John' });\n * console.log(errors); // undefined\n * errors = PersonMapper.validate({ name: 123 });\n * console.log(errors); // [{ expected: 'one of (string)', actual: 'number', path: 'name' }]\n *\n * @method Mapper#validate\n * @param {Object|Object[]} record The record or records to validate.\n * @param {object} [opts] Configuration options. Passed to\n * {@link Schema#validate}.\n * @returns {Object[]} Array of errors or `undefined` if no errors.\n * @since 3.0.0\n */\n validate (record, opts) {\n opts || (opts = {})\n const schema = this.getSchema()\n if (!schema) {\n return\n }\n const _opts = utils.pick(opts, ['existingOnly'])\n if (utils.isArray(record)) {\n const errors = record.map((_record) => schema.validate(_record, utils.pick(_opts, ['existingOnly'])))\n\n return errors.some(Boolean) ? errors : undefined\n }\n return schema.validate(record, _opts)\n },\n\n /**\n * Method used to wrap data returned by an adapter with this Mapper's\n * {@link Mapper#recordClass}. This method is used by all of a Mapper's CRUD\n * methods. The provided implementation of this method assumes that the `data`\n * passed to it is a record or records that need to be wrapped with\n * {@link Mapper#createRecord}. Override with care.\n *\n * Provided implementation of {@link Mapper#wrap}:\n *\n * ```\n * function (data, opts) {\n * return this.createRecord(data, opts);\n * }\n * ```\n *\n * @example\n * const PostMapper = new Mapper({\n * name: 'post',\n * // Override to customize behavior\n * wrap (data, opts) {\n * const originalWrap = this.constructor.prototype.wrap;\n * // Let's say \"GET /post\" doesn't return JSON quite like JSData expects,\n * // but the actual post records are nested under a \"posts\" field. So,\n * // we override Mapper#wrap to handle this special case.\n * if (opts.op === 'findAll') {\n * return originalWrap.call(this, data.posts, opts);\n * }\n * // Otherwise perform original behavior\n * return originalWrap.call(this, data, opts);\n * }\n * });\n *\n * @method Mapper#wrap\n * @param {Object|Object[]} data The record or records to be wrapped.\n * @param {object} [opts] Configuration options. Passed to {@link Mapper#createRecord}.\n * @returns {Record|Record[]} The wrapped record or records.\n * @since 3.0.0\n */\n wrap (data, opts) {\n return this.createRecord(data, opts)\n },\n\n /**\n * @ignore\n */\n defineRelations () {\n // Setup the mapper's relations, including generating Mapper#relationList\n // and Mapper#relationFields\n utils.forOwn(this.relations, (group, type) => {\n utils.forOwn(group, (relations, _name) => {\n if (utils.isObject(relations)) {\n relations = [relations]\n }\n relations.forEach((def) => {\n const relatedMapper = this.datastore.getMapperByName(_name) || _name\n def.getRelation = () => this.datastore.getMapper(_name)\n\n if (typeof Relation[type] !== 'function') {\n throw utils.err(DOMAIN, 'defineRelations')(400, 'relation type (hasOne, hasMany, etc)', type, true)\n }\n\n this[type](relatedMapper, def)\n })\n })\n })\n }\n})\n\n/**\n * Create a subclass of this Mapper:\n *\n * @example Mapper.extend\n * const JSData = require('js-data');\n * const { Mapper } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * // Extend the class using ES2015 class syntax.\n * class CustomMapperClass extends Mapper {\n * foo () { return 'bar'; }\n * static beep () { return 'boop'; }\n * };\n * const customMapper = new CustomMapperClass();\n * console.log(customMapper.foo());\n * console.log(CustomMapperClass.beep());\n *\n * // Extend the class using alternate method.\n * const OtherMapperClass = Mapper.extend({\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * });\n * const otherMapper = new OtherMapperClass();\n * console.log(otherMapper.foo());\n * console.log(OtherMapperClass.beep());\n *\n * // Extend the class, providing a custom constructor.\n * function AnotherMapperClass () {\n * Mapper.call(this);\n * this.created_at = new Date().getTime();\n * }\n * Mapper.extend({\n * constructor: AnotherMapperClass,\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * })\n * const anotherMapper = new AnotherMapperClass();\n * console.log(anotherMapper.created_at);\n * console.log(anotherMapper.foo());\n * console.log(AnotherMapperClass.beep());\n *\n * @method Mapper.extend\n * @param {object} [props={}] Properties to add to the prototype of the\n * subclass.\n * @param {object} [props.constructor] Provide a custom constructor function\n * to be used as the subclass itself.\n * @param {object} [classProps={}] Static properties to add to the subclass.\n * @returns {Constructor} Subclass of this Mapper class.\n * @since 3.0.0\n */\n","import utils from './utils'\nimport Component from './Component'\nimport Mapper from './Mapper'\n\nconst DOMAIN = 'Container'\n\nexport const proxiedMapperMethods = [\n /**\n * Wrapper for {@link Mapper#count}.\n *\n * @example\n * // Get the number of published blog posts\n * import { Container } from 'js-data';\n * import RethinkDBAdapter from 'js-data-rethinkdb';\n * const store = new Container();\n * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('post');\n *\n * store.count('post', { status: 'published' }).then((numPublished) => {\n * console.log(numPublished); // e.g. 45\n * });\n *\n * @method Container#count\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {object} [query] See {@link Mapper#count}.\n * @param {object} [opts] See {@link Mapper#count}.\n * @returns {Promise} See {@link Mapper#count}.\n * @see Mapper#count\n * @since 3.0.0\n */\n 'count',\n\n /**\n * Fired during {@link Container#create}. See\n * {@link Container~beforeCreateListener} for how to listen for this event.\n *\n * @event Container#beforeCreate\n * @see Container~beforeCreateListener\n * @see Container#create\n */\n /**\n * Callback signature for the {@link Container#event:beforeCreate} event.\n *\n * @example\n * function onBeforeCreate (mapperName, props, opts) {\n * // do something\n * }\n * store.on('beforeCreate', onBeforeCreate);\n *\n * @callback Container~beforeCreateListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeCreate}.\n * @param {object} props The `props` argument received by {@link Mapper#beforeCreate}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeCreate}.\n * @see Container#event:beforeCreate\n * @see Container#create\n * @since 3.0.0\n */\n /**\n * Fired during {@link Container#create}. See\n * {@link Container~afterCreateListener} for how to listen for this event.\n *\n * @event Container#afterCreate\n * @see Container~afterCreateListener\n * @see Container#create\n */\n /**\n * Callback signature for the {@link Container#event:afterCreate} event.\n *\n * @example\n * function onAfterCreate (mapperName, props, opts, result) {\n * // do something\n * }\n * store.on('afterCreate', onAfterCreate);\n *\n * @callback Container~afterCreateListener\n * @param {string} name The `name` argument received by {@link Mapper#afterCreate}.\n * @param {object} props The `props` argument received by {@link Mapper#afterCreate}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterCreate}.\n * @param {object} result The `result` argument received by {@link Mapper#afterCreate}.\n * @see Container#event:afterCreate\n * @see Container#create\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#create}.\n *\n * @example\n * // Create and save a new blog post\n * import { Container } from 'js-data';\n * import RethinkDBAdapter from 'js-data-rethinkdb';\n * const store = new Container();\n * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('post');\n *\n * store.create('post', {\n * title: 'Modeling your data',\n * status: 'draft'\n * }).then((post) => {\n * console.log(post); // { id: 1234, status: 'draft', ... }\n * });\n *\n * @fires Container#beforeCreate\n * @fires Container#afterCreate\n * @method Container#create\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {object} props See {@link Mapper#create}.\n * @param {object} [opts] See {@link Mapper#create}.\n * @returns {Promise} See {@link Mapper#create}.\n * @see Mapper#create\n * @since 3.0.0\n */\n 'create',\n\n /**\n * Fired during {@link Container#createMany}. See\n * {@link Container~beforeCreateManyListener} for how to listen for this event.\n *\n * @event Container#beforeCreateMany\n * @see Container~beforeCreateManyListener\n * @see Container#createMany\n */\n /**\n * Callback signature for the {@link Container#event:beforeCreateMany} event.\n *\n * @example\n * function onBeforeCreateMany (mapperName, records, opts) {\n * // do something\n * }\n * store.on('beforeCreateMany', onBeforeCreateMany);\n *\n * @callback Container~beforeCreateManyListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeCreateMany}.\n * @param {object} records The `records` argument received by {@link Mapper#beforeCreateMany}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeCreateMany}.\n * @see Container#event:beforeCreateMany\n * @see Container#createMany\n * @since 3.0.0\n */\n /**\n * Fired during {@link Container#createMany}. See\n * {@link Container~afterCreateManyListener} for how to listen for this event.\n *\n * @event Container#afterCreateMany\n * @see Container~afterCreateManyListener\n * @see Container#createMany\n */\n /**\n * Callback signature for the {@link Container#event:afterCreateMany} event.\n *\n * @example\n * function onAfterCreateMany (mapperName, records, opts, result) {\n * // do something\n * }\n * store.on('afterCreateMany', onAfterCreateMany);\n *\n * @callback Container~afterCreateManyListener\n * @param {string} name The `name` argument received by {@link Mapper#afterCreateMany}.\n * @param {object} records The `records` argument received by {@link Mapper#afterCreateMany}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterCreateMany}.\n * @param {object} result The `result` argument received by {@link Mapper#afterCreateMany}.\n * @see Container#event:afterCreateMany\n * @see Container#createMany\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#createMany}.\n *\n * @example\n * // Create and save several new blog posts\n * import { Container } from 'js-data';\n * import RethinkDBAdapter from 'js-data-rethinkdb';\n * const store = new Container();\n * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('post');\n *\n * store.createMany('post', [{\n * title: 'Modeling your data',\n * status: 'draft'\n * }, {\n * title: 'Reading data',\n * status: 'draft'\n * }]).then((posts) => {\n * console.log(posts[0]); // { id: 1234, status: 'draft', ... }\n * console.log(posts[1]); // { id: 1235, status: 'draft', ... }\n * });\n *\n * @fires Container#beforeCreateMany\n * @fires Container#afterCreateMany\n * @method Container#createMany\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {Record[]} records See {@link Mapper#createMany}.\n * @param {object} [opts] See {@link Mapper#createMany}.\n * @returns {Promise} See {@link Mapper#createMany}.\n * @see Mapper#createMany\n * @since 3.0.0\n */\n 'createMany',\n\n /**\n * Wrapper for {@link Mapper#createRecord}.\n *\n * __Note:__ This method does __not__ interact with any adapter, and does\n * __not__ save any data. It only creates new objects in memory.\n *\n * @example\n * // Create empty unsaved record instance\n * import { Container } from 'js-data';\n * const store = new Container();\n * store.defineMapper('post');\n * const post = PostMapper.createRecord();\n *\n * @method Container#createRecord\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {Object|Object[]} props See {@link Mapper#createRecord}.\n * @param {object} [opts] See {@link Mapper#createRecord}.\n * @returns {Promise} See {@link Mapper#createRecord}.\n * @see Mapper#createRecord\n * @since 3.0.0\n */\n 'createRecord',\n\n /**\n * Fired during {@link Container#destroy}. See\n * {@link Container~beforeDestroyListener} for how to listen for this event.\n *\n * @event Container#beforeDestroy\n * @see Container~beforeDestroyListener\n * @see Container#destroy\n */\n /**\n * Callback signature for the {@link Container#event:beforeDestroy} event.\n *\n * @example\n * function onBeforeDestroy (mapperName, id, opts) {\n * // do something\n * }\n * store.on('beforeDestroy', onBeforeDestroy);\n *\n * @callback Container~beforeDestroyListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeDestroy}.\n * @param {string|number} id The `id` argument received by {@link Mapper#beforeDestroy}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeDestroy}.\n * @see Container#event:beforeDestroy\n * @see Container#destroy\n * @since 3.0.0\n */\n /**\n * Fired during {@link Container#destroy}. See\n * {@link Container~afterDestroyListener} for how to listen for this event.\n *\n * @event Container#afterDestroy\n * @see Container~afterDestroyListener\n * @see Container#destroy\n */\n /**\n * Callback signature for the {@link Container#event:afterDestroy} event.\n *\n * @example\n * function onAfterDestroy (mapperName, id, opts, result) {\n * // do something\n * }\n * store.on('afterDestroy', onAfterDestroy);\n *\n * @callback Container~afterDestroyListener\n * @param {string} name The `name` argument received by {@link Mapper#afterDestroy}.\n * @param {string|number} id The `id` argument received by {@link Mapper#afterDestroy}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterDestroy}.\n * @param {object} result The `result` argument received by {@link Mapper#afterDestroy}.\n * @see Container#event:afterDestroy\n * @see Container#destroy\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#destroy}.\n *\n * @example\n * // Destroy a specific blog post\n * import { Container } from 'js-data';\n * import RethinkDBAdapter from 'js-data-rethinkdb';\n * const store = new Container();\n * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('post');\n *\n * store.destroy('post', 1234).then(() => {\n * // Blog post #1234 has been destroyed\n * });\n *\n * @fires Container#beforeDestroy\n * @fires Container#afterDestroy\n * @method Container#destroy\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {(string|number)} id See {@link Mapper#destroy}.\n * @param {object} [opts] See {@link Mapper#destroy}.\n * @returns {Promise} See {@link Mapper#destroy}.\n * @see Mapper#destroy\n * @since 3.0.0\n */\n 'destroy',\n\n /**\n * Fired during {@link Container#destroyAll}. See\n * {@link Container~beforeDestroyAllListener} for how to listen for this event.\n *\n * @event Container#beforeDestroyAll\n * @see Container~beforeDestroyAllListener\n * @see Container#destroyAll\n */\n /**\n * Callback signature for the {@link Container#event:beforeDestroyAll} event.\n *\n * @example\n * function onBeforeDestroyAll (mapperName, query, opts) {\n * // do something\n * }\n * store.on('beforeDestroyAll', onBeforeDestroyAll);\n *\n * @callback Container~beforeDestroyAllListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeDestroyAll}.\n * @param {object} query The `query` argument received by {@link Mapper#beforeDestroyAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeDestroyAll}.\n * @see Container#event:beforeDestroyAll\n * @see Container#destroyAll\n * @since 3.0.0\n */\n /**\n * Fired during {@link Container#destroyAll}. See\n * {@link Container~afterDestroyAllListener} for how to listen for this event.\n *\n * @event Container#afterDestroyAll\n * @see Container~afterDestroyAllListener\n * @see Container#destroyAll\n */\n /**\n * Callback signature for the {@link Container#event:afterDestroyAll} event.\n *\n * @example\n * function onAfterDestroyAll (mapperName, query, opts, result) {\n * // do something\n * }\n * store.on('afterDestroyAll', onAfterDestroyAll);\n *\n * @callback Container~afterDestroyAllListener\n * @param {string} name The `name` argument received by {@link Mapper#afterDestroyAll}.\n * @param {object} query The `query` argument received by {@link Mapper#afterDestroyAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterDestroyAll}.\n * @param {object} result The `result` argument received by {@link Mapper#afterDestroyAll}.\n * @see Container#event:afterDestroyAll\n * @see Container#destroyAll\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#destroyAll}.\n *\n * @example\n * // Destroy all \"draft\" blog posts\n * import { Container } from 'js-data';\n * import RethinkDBAdapter from 'js-data-rethinkdb';\n * const store = new Container();\n * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('post');\n *\n * store.destroyAll('post', { status: 'draft' }).then(() => {\n * // All \"draft\" blog posts have been destroyed\n * });\n *\n * @fires Container#beforeDestroyAll\n * @fires Container#afterDestroyAll\n * @method Container#destroyAll\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {object} [query] See {@link Mapper#destroyAll}.\n * @param {object} [opts] See {@link Mapper#destroyAll}.\n * @returns {Promise} See {@link Mapper#destroyAll}.\n * @see Mapper#destroyAll\n * @since 3.0.0\n */\n 'destroyAll',\n\n /**\n * Fired during {@link Container#find}. See\n * {@link Container~beforeFindListener} for how to listen for this event.\n *\n * @event Container#beforeFind\n * @see Container~beforeFindListener\n * @see Container#find\n */\n /**\n * Callback signature for the {@link Container#event:beforeFind} event.\n *\n * @example\n * function onBeforeFind (mapperName, id, opts) {\n * // do something\n * }\n * store.on('beforeFind', onBeforeFind);\n *\n * @callback Container~beforeFindListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeFind}.\n * @param {string|number} id The `id` argument received by {@link Mapper#beforeFind}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeFind}.\n * @see Container#event:beforeFind\n * @see Container#find\n * @since 3.0.0\n */\n /**\n * Fired during {@link Container#find}. See\n * {@link Container~afterFindListener} for how to listen for this event.\n *\n * @event Container#afterFind\n * @see Container~afterFindListener\n * @see Container#find\n */\n /**\n * Callback signature for the {@link Container#event:afterFind} event.\n *\n * @example\n * function onAfterFind (mapperName, id, opts, result) {\n * // do something\n * }\n * store.on('afterFind', onAfterFind);\n *\n * @callback Container~afterFindListener\n * @param {string} name The `name` argument received by {@link Mapper#afterFind}.\n * @param {string|number} id The `id` argument received by {@link Mapper#afterFind}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterFind}.\n * @param {object} result The `result` argument received by {@link Mapper#afterFind}.\n * @see Container#event:afterFind\n * @see Container#find\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#find}.\n *\n * @example\n * import { Container } from 'js-data';\n * import RethinkDBAdapter from 'js-data-rethinkdb';\n * const store = new Container();\n * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('post');\n *\n * store.find('post', 1).then((post) => {\n * console.log(post) // { id: 1, ...}\n * });\n *\n * @fires Container#beforeFind\n * @fires Container#afterFind\n * @method Container#find\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {(string|number)} id See {@link Mapper#find}.\n * @param {object} [opts] See {@link Mapper#find}.\n * @returns {Promise} See {@link Mapper#find}.\n * @see Mapper#find\n * @since 3.0.0\n */\n 'find',\n\n /**\n * Fired during {@link Container#findAll}. See\n * {@link Container~beforeFindAllListener} for how to listen for this event.\n *\n * @event Container#beforeFindAll\n * @see Container~beforeFindAllListener\n * @see Container#findAll\n */\n /**\n * Callback signature for the {@link Container#event:beforeFindAll} event.\n *\n * @example\n * function onBeforeFindAll (mapperName, query, opts) {\n * // do something\n * }\n * store.on('beforeFindAll', onBeforeFindAll);\n *\n * @callback Container~beforeFindAllListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeFindAll}.\n * @param {object} query The `query` argument received by {@link Mapper#beforeFindAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeFindAll}.\n * @see Container#event:beforeFindAll\n * @see Container#findAll\n * @since 3.0.0\n */\n /**\n * Fired during {@link Container#findAll}. See\n * {@link Container~afterFindAllListener} for how to listen for this event.\n *\n * @event Container#afterFindAll\n * @see Container~afterFindAllListener\n * @see Container#findAll\n */\n /**\n * Callback signature for the {@link Container#event:afterFindAll} event.\n *\n * @example\n * function onAfterFindAll (mapperName, query, opts, result) {\n * // do something\n * }\n * store.on('afterFindAll', onAfterFindAll);\n *\n * @callback Container~afterFindAllListener\n * @param {string} name The `name` argument received by {@link Mapper#afterFindAll}.\n * @param {object} query The `query` argument received by {@link Mapper#afterFindAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterFindAll}.\n * @param {object} result The `result` argument received by {@link Mapper#afterFindAll}.\n * @see Container#event:afterFindAll\n * @see Container#findAll\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#createRecord}.\n *\n * @example\n * // Find all \"published\" blog posts\n * import { Container } from 'js-data';\n * import RethinkDBAdapter from 'js-data-rethinkdb';\n * const store = new Container();\n * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('post');\n *\n * store.findAll('post', { status: 'published' }).then((posts) => {\n * console.log(posts); // [{ id: 1, ...}, ...]\n * });\n *\n * @fires Container#beforeFindAll\n * @fires Container#afterFindAll\n * @method Container#findAll\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {object} [query] See {@link Mapper#findAll}.\n * @param {object} [opts] See {@link Mapper#findAll}.\n * @returns {Promise} See {@link Mapper#findAll}.\n * @see Mapper#findAll\n * @since 3.0.0\n */\n 'findAll',\n\n /**\n * Wrapper for {@link Mapper#getSchema}.\n *\n * @method Container#getSchema\n * @param {string} name Name of the {@link Mapper} to target.\n * @returns {Schema} See {@link Mapper#getSchema}.\n * @see Mapper#getSchema\n * @since 3.0.0\n */\n 'getSchema',\n\n /**\n * Wrapper for {@link Mapper#is}.\n *\n * @example\n * import { Container } from 'js-data';\n * const store = new Container();\n * store.defineMapper('post');\n * const post = store.createRecord();\n *\n * console.log(store.is('post', post)); // true\n * // Equivalent to what's above\n * console.log(post instanceof store.getMapper('post').recordClass); // true\n *\n * @method Container#is\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {Object|Record} record See {@link Mapper#is}.\n * @returns {boolean} See {@link Mapper#is}.\n * @see Mapper#is\n * @since 3.0.0\n */\n 'is',\n\n /**\n * Wrapper for {@link Mapper#sum}.\n *\n * @example\n * import { Container } from 'js-data';\n * import RethinkDBAdapter from 'js-data-rethinkdb';\n * const store = new Container();\n * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('purchase_order');\n *\n * store.sum('purchase_order', 'amount', { status: 'paid' }).then((amountPaid) => {\n * console.log(amountPaid); // e.g. 451125.34\n * });\n *\n * @method Container#sum\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {string} field See {@link Mapper#sum}.\n * @param {object} [query] See {@link Mapper#sum}.\n * @param {object} [opts] See {@link Mapper#sum}.\n * @returns {Promise} See {@link Mapper#sum}.\n * @see Mapper#sum\n * @since 3.0.0\n */\n 'sum',\n\n /**\n * Wrapper for {@link Mapper#toJSON}.\n *\n * @example\n * import { Container } from 'js-data';\n * import RethinkDBAdapter from 'js-data-rethinkdb';\n * const store = new Container();\n * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('person', {\n * schema: {\n * properties: {\n * name: { type: 'string' },\n * id: { type: 'string' }\n * }\n * }\n * });\n * const person = store.createRecord('person', { id: 1, name: 'John', foo: 'bar' });\n * // \"foo\" is stripped by toJSON()\n * console.log(store.toJSON('person', person)); // {\"id\":1,\"name\":\"John\"}\n *\n * store.defineMapper('personRelaxed', {\n * schema: {\n * properties: {\n * name: { type: 'string' },\n * id: { type: 'string' }\n * },\n * additionalProperties: true\n * }\n * });\n * const person2 = store.createRecord('personRelaxed', { id: 1, name: 'John', foo: 'bar' });\n * // \"foo\" is not stripped by toJSON\n * console.log(store.toJSON('personRelaxed', person2)); // {\"id\":1,\"name\":\"John\",\"foo\":\"bar\"}\n *\n * @method Container#toJSON\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {Record|Record[]} records See {@link Mapper#toJSON}.\n * @param {object} [opts] See {@link Mapper#toJSON}.\n * @returns {Object|Object[]} See {@link Mapper#toJSON}.\n * @see Mapper#toJSON\n * @since 3.0.0\n */\n 'toJSON',\n\n /**\n * Fired during {@link Container#update}. See\n * {@link Container~beforeUpdateListener} for how to listen for this event.\n *\n * @event Container#beforeUpdate\n * @see Container~beforeUpdateListener\n * @see Container#update\n */\n /**\n * Callback signature for the {@link Container#event:beforeUpdate} event.\n *\n * @example\n * function onBeforeUpdate (mapperName, id, props, opts) {\n * // do something\n * }\n * store.on('beforeUpdate', onBeforeUpdate);\n *\n * @callback Container~beforeUpdateListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeUpdate}.\n * @param {string|number} id The `id` argument received by {@link Mapper#beforeUpdate}.\n * @param {object} props The `props` argument received by {@link Mapper#beforeUpdate}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdate}.\n * @see Container#event:beforeUpdate\n * @see Container#update\n * @since 3.0.0\n */\n /**\n * Fired during {@link Container#update}. See\n * {@link Container~afterUpdateListener} for how to listen for this event.\n *\n * @event Container#afterUpdate\n * @see Container~afterUpdateListener\n * @see Container#update\n */\n /**\n * Callback signature for the {@link Container#event:afterUpdate} event.\n *\n * @example\n * function onAfterUpdate (mapperName, id, props, opts, result) {\n * // do something\n * }\n * store.on('afterUpdate', onAfterUpdate);\n *\n * @callback Container~afterUpdateListener\n * @param {string} name The `name` argument received by {@link Mapper#afterUpdate}.\n * @param {string|number} id The `id` argument received by {@link Mapper#afterUpdate}.\n * @param {object} props The `props` argument received by {@link Mapper#afterUpdate}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdate}.\n * @param {object} result The `result` argument received by {@link Mapper#afterUpdate}.\n * @see Container#event:afterUpdate\n * @see Container#update\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#update}.\n *\n * @example\n * import { Container } from 'js-data';\n * import RethinkDBAdapter from 'js-data-rethinkdb';\n * const store = new Container();\n * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('post');\n *\n * store.update('post', 1234, {\n * status: 'published',\n * published_at: new Date()\n * }).then((post) => {\n * console.log(post); // { id: 1234, status: 'published', ... }\n * });\n *\n * @fires Container#beforeUpdate\n * @fires Container#afterUpdate\n * @method Container#update\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {(string|number)} id See {@link Mapper#update}.\n * @param {object} record See {@link Mapper#update}.\n * @param {object} [opts] See {@link Mapper#update}.\n * @returns {Promise} See {@link Mapper#update}.\n * @see Mapper#update\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/saving-data\",\"Saving data\"]\n */\n 'update',\n\n /**\n * Fired during {@link Container#updateAll}. See\n * {@link Container~beforeUpdateAllListener} for how to listen for this event.\n *\n * @event Container#beforeUpdateAll\n * @see Container~beforeUpdateAllListener\n * @see Container#updateAll\n */\n /**\n * Callback signature for the {@link Container#event:beforeUpdateAll} event.\n *\n * @example\n * function onBeforeUpdateAll (mapperName, props, query, opts) {\n * // do something\n * }\n * store.on('beforeUpdateAll', onBeforeUpdateAll);\n *\n * @callback Container~beforeUpdateAllListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeUpdateAll}.\n * @param {object} props The `props` argument received by {@link Mapper#beforeUpdateAll}.\n * @param {object} query The `query` argument received by {@link Mapper#beforeUpdateAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdateAll}.\n * @see Container#event:beforeUpdateAll\n * @see Container#updateAll\n * @since 3.0.0\n */\n /**\n * Fired during {@link Container#updateAll}. See\n * {@link Container~afterUpdateAllListener} for how to listen for this event.\n *\n * @event Container#afterUpdateAll\n * @see Container~afterUpdateAllListener\n * @see Container#updateAll\n */\n /**\n * Callback signature for the {@link Container#event:afterUpdateAll} event.\n *\n * @example\n * function onAfterUpdateAll (mapperName, props, query, opts, result) {\n * // do something\n * }\n * store.on('afterUpdateAll', onAfterUpdateAll);\n *\n * @callback Container~afterUpdateAllListener\n * @param {string} name The `name` argument received by {@link Mapper#afterUpdateAll}.\n * @param {object} props The `props` argument received by {@link Mapper#afterUpdateAll}.\n * @param {object} query The `query` argument received by {@link Mapper#afterUpdateAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdateAll}.\n * @param {object} result The `result` argument received by {@link Mapper#afterUpdateAll}.\n * @see Container#event:afterUpdateAll\n * @see Container#updateAll\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#updateAll}.\n *\n * @example\n * // Turn all of John's blog posts into drafts.\n * import { Container } from 'js-data';\n * import RethinkDBAdapter from 'js-data-rethinkdb';\n * const store = new Container();\n * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('post');\n *\n * const update = { status: draft: published_at: null };\n * const query = { userId: 1234 };\n * store.updateAll('post', update, query).then((posts) => {\n * console.log(posts); // [...]\n * });\n *\n * @fires Container#beforeUpdateAll\n * @fires Container#afterUpdateAll\n * @method Container#updateAll\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {object} update See {@link Mapper#updateAll}.\n * @param {object} [query] See {@link Mapper#updateAll}.\n * @param {object} [opts] See {@link Mapper#updateAll}.\n * @returns {Promise} See {@link Mapper#updateAll}.\n * @see Mapper#updateAll\n * @since 3.0.0\n */\n 'updateAll',\n\n /**\n * Fired during {@link Container#updateMany}. See\n * {@link Container~beforeUpdateManyListener} for how to listen for this event.\n *\n * @event Container#beforeUpdateMany\n * @see Container~beforeUpdateManyListener\n * @see Container#updateMany\n */\n /**\n * Callback signature for the {@link Container#event:beforeUpdateMany} event.\n *\n * @example\n * function onBeforeUpdateMany (mapperName, records, opts) {\n * // do something\n * }\n * store.on('beforeUpdateMany', onBeforeUpdateMany);\n *\n * @callback Container~beforeUpdateManyListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeUpdateMany}.\n * @param {object} records The `records` argument received by {@link Mapper#beforeUpdateMany}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdateMany}.\n * @see Container#event:beforeUpdateMany\n * @see Container#updateMany\n * @since 3.0.0\n */\n /**\n * Fired during {@link Container#updateMany}. See\n * {@link Container~afterUpdateManyListener} for how to listen for this event.\n *\n * @event Container#afterUpdateMany\n * @see Container~afterUpdateManyListener\n * @see Container#updateMany\n */\n /**\n * Callback signature for the {@link Container#event:afterUpdateMany} event.\n *\n * @example\n * function onAfterUpdateMany (mapperName, records, opts, result) {\n * // do something\n * }\n * store.on('afterUpdateMany', onAfterUpdateMany);\n *\n * @callback Container~afterUpdateManyListener\n * @param {string} name The `name` argument received by {@link Mapper#afterUpdateMany}.\n * @param {object} records The `records` argument received by {@link Mapper#afterUpdateMany}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdateMany}.\n * @param {object} result The `result` argument received by {@link Mapper#afterUpdateMany}.\n * @see Container#event:afterUpdateMany\n * @see Container#updateMany\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#updateMany}.\n *\n * @example\n * import { Container } from 'js-data';\n * import RethinkDBAdapter from 'js-data-rethinkdb';\n * const store = new Container();\n * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('post');\n *\n * store.updateMany('post', [\n * { id: 1234, status: 'draft' },\n * { id: 2468, status: 'published', published_at: new Date() }\n * ]).then((posts) => {\n * console.log(posts); // [...]\n * });\n *\n * @fires Container#beforeUpdateMany\n * @fires Container#afterUpdateMany\n * @method Container#updateMany\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {(Object[]|Record[])} records See {@link Mapper#updateMany}.\n * @param {object} [opts] See {@link Mapper#updateMany}.\n * @returns {Promise} See {@link Mapper#updateMany}.\n * @see Mapper#updateMany\n * @since 3.0.0\n */\n 'updateMany',\n\n /**\n * Wrapper for {@link Mapper#validate}.\n *\n * @example\n * import { Container } from 'js-data';\n * const store = new Container();\n * store.defineMapper('post', {\n * schema: {\n * properties: {\n * name: { type: 'string' },\n * id: { type: 'string' }\n * }\n * }\n * });\n * let errors = store.validate('post', { name: 'John' });\n * console.log(errors); // undefined\n * errors = store.validate('post', { name: 123 });\n * console.log(errors); // [{ expected: 'one of (string)', actual: 'number', path: 'name' }]\n *\n * @method Container#validate\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {(Object[]|Record[])} records See {@link Mapper#validate}.\n * @param {object} [opts] See {@link Mapper#validate}.\n * @returns {Promise} See {@link Mapper#validate}.\n * @see Mapper#validate\n * @since 3.0.0\n */\n 'validate'\n]\n\n/**\n * The `Container` class is a place to define and store {@link Mapper} instances.\n *\n * `Container` makes it easy to manage your Mappers. Without a container, you\n * need to manage Mappers yourself, including resolving circular dependencies\n * among relations. All Mappers in a container share the same adapters, so you\n * don't have to register adapters for every single Mapper.\n *\n * @example Container#constructor\n * // import { Container } from 'js-data';\n * const JSData = require('js-data');\n * const {Container} = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new Container();\n *\n * @class Container\n * @extends Component\n * @param {object} [opts] Configuration options.\n * @param {boolean} [opts.debug=false] See {@link Component#debug}.\n * @param {Constructor} [opts.mapperClass] See {@link Container#mapperClass}.\n * @param {object} [opts.mapperDefaults] See {@link Container#mapperDefaults}.\n * @since 3.0.0\n */\nexport function Container (opts) {\n utils.classCallCheck(this, Container)\n Component.call(this)\n opts || (opts = {})\n\n Object.defineProperties(this, {\n /**\n * The adapters registered with this Container, which are also shared by all\n * Mappers in this Container.\n *\n * @name Container#_adapters\n * @see Container#registerAdapter\n * @since 3.0.0\n * @type {Object}\n */\n _adapters: {\n value: {}\n },\n\n /**\n * The the mappers in this container\n *\n * @name Container#_mappers\n * @see Mapper\n * @since 3.0.0\n * @type {Object}\n */\n _mappers: {\n value: {}\n },\n\n /**\n * Constructor function to use in {@link Container#defineMapper} to create new\n * {@link Mapper} instances. {@link Container#mapperClass} should extend\n * {@link Mapper}. By default {@link Mapper} is used to instantiate Mappers.\n *\n * @example Container#mapperClass\n * // import { Container, Mapper } from 'js-data';\n * const JSData = require('js-data');\n * const { Container, Mapper } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * class MyMapperClass extends Mapper {\n * foo () { return 'bar' }\n * }\n * const store = new Container({\n * mapperClass: MyMapperClass\n * });\n * store.defineMapper('user');\n * console.log(store.getMapper('user').foo());\n *\n * @name Container#mapperClass\n * @see Mapper\n * @since 3.0.0\n * @type {Constructor}\n */\n mapperClass: {\n value: undefined,\n writable: true\n }\n })\n\n // Apply options provided by the user\n utils.fillIn(this, opts)\n\n /**\n * Defaults options to pass to {@link Container#mapperClass} when creating a\n * new {@link Mapper}.\n *\n * @example Container#mapperDefaults\n * // import { Container } from 'js-data';\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new Container({\n * mapperDefaults: {\n * idAttribute: '_id'\n * }\n * });\n * store.defineMapper('user');\n * console.log(store.getMapper('user').idAttribute);\n *\n * @default {}\n * @name Container#mapperDefaults\n * @since 3.0.0\n * @type {Object}\n */\n this.mapperDefaults = this.mapperDefaults || {}\n\n // Use the Mapper class if the user didn't provide a mapperClass\n this.mapperClass || (this.mapperClass = Mapper)\n}\n\nconst props = {\n constructor: Container,\n\n /**\n * Register a new event listener on this Container.\n *\n * Proxy for {@link Component#on}. If an event was emitted by a {@link Mapper}\n * in the Container, then the name of the {@link Mapper} will be prepended to\n * the arugments passed to the listener.\n *\n * @example Container#on\n * // import { Container } from 'js-data';\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new Container();\n * store.on('foo', function (...args) { console.log(args.join(':')) });\n * store.defineMapper('user');\n * store.emit('foo', 'arg1', 'arg2');\n * store.getMapper('user').emit('foo', 'arg1', 'arg2');\n *\n * @method Container#on\n * @param {string} event Name of event to subsribe to.\n * @param {Function} listener Listener function to handle the event.\n * @param {*} [ctx] Optional content in which to invoke the listener.\n * @since 3.0.0\n */\n\n /**\n * Used to bind to events emitted by mappers in this container.\n *\n * @method Container#_onMapperEvent\n * @param {string} name Name of the mapper that emitted the event.\n * @param {...*} [args] Args See {@link Mapper#emit}.\n * @private\n * @since 3.0.0\n */\n _onMapperEvent (name, ...args) {\n const type = args.shift()\n this.emit(type, name, ...args)\n },\n\n /**\n * Return a container scoped to a particular mapper.\n *\n * @example Container#as\n * // import { Container } from 'js-data';\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new Container();\n * const UserMapper = store.defineMapper('user');\n * const UserStore = store.as('user');\n *\n * const user1 = store.createRecord('user', { name: 'John' });\n * const user2 = UserStore.createRecord({ name: 'John' });\n * const user3 = UserMapper.createRecord({ name: 'John' });\n * console.log(user1 === user2);\n * console.log(user2 === user3);\n * console.log(user1 === user3);\n *\n * @method Container#as\n * @param {string} name Name of the {@link Mapper}.\n * @returns {Object} A container scoped to a particular mapper.\n * @since 3.0.0\n */\n as (name) {\n const props = {}\n const original = this\n proxiedMapperMethods.forEach(function (method) {\n props[method] = {\n writable: true,\n value (...args) {\n return original[method](name, ...args)\n }\n }\n })\n props.getMapper = {\n writable: true,\n value () {\n return original.getMapper(name)\n }\n }\n return Object.create(this, props)\n },\n\n /**\n * Create a new mapper and register it in this container.\n *\n * @example Container#defineMapper\n * // import { Container } from 'js-data';\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new Container({\n * mapperDefaults: { foo: 'bar' }\n * });\n * // Container#defineMapper returns a direct reference to the newly created\n * // Mapper.\n * const UserMapper = store.defineMapper('user');\n * console.log(UserMapper === store.getMapper('user'));\n * console.log(UserMapper === store.as('user').getMapper());\n * console.log(UserMapper.foo);\n *\n * @method Container#defineMapper\n * @param {string} name Name under which to register the new {@link Mapper}.\n * {@link Mapper#name} will be set to this value.\n * @param {object} [opts] Configuration options. Passed to\n * {@link Container#mapperClass} when creating the new {@link Mapper}.\n * @returns {Mapper} The newly created instance of {@link Mapper}.\n * @see Container#as\n * @since 3.0.0\n */\n defineMapper (name, opts) {\n // For backwards compatibility with defineResource\n if (utils.isObject(name)) {\n opts = name\n name = opts.name\n }\n if (!utils.isString(name)) {\n throw utils.err(`${DOMAIN}#defineMapper`, 'name')(400, 'string', name)\n }\n\n // Default values for arguments\n opts || (opts = {})\n // Set Mapper#name\n opts.name = name\n opts.relations || (opts.relations = {})\n\n // Check if the user is overriding the datastore's default mapperClass\n const mapperClass = opts.mapperClass || this.mapperClass\n delete opts.mapperClass\n\n // Apply the datastore's defaults to the options going into the mapper\n utils.fillIn(opts, this.mapperDefaults)\n\n // Instantiate a mapper\n const mapper = this._mappers[name] = new mapperClass(opts) // eslint-disable-line\n mapper.relations || (mapper.relations = {})\n // Make sure the mapper's name is set\n mapper.name = name\n // All mappers in this datastore will share adapters\n mapper._adapters = this.getAdapters()\n\n mapper.datastore = this\n\n mapper.on('all', (...args) => this._onMapperEvent(name, ...args))\n mapper.defineRelations()\n\n return mapper\n },\n\n defineResource (name, opts) {\n console.warn('DEPRECATED: defineResource is deprecated, use defineMapper instead')\n return this.defineMapper(name, opts)\n },\n\n /**\n * Return the registered adapter with the given name or the default adapter if\n * no name is provided.\n *\n * @method Container#getAdapter\n * @param {string} [name] The name of the adapter to retrieve.\n * @returns {Adapter} The adapter.\n * @since 3.0.0\n */\n getAdapter (name) {\n const adapter = this.getAdapterName(name)\n if (!adapter) {\n throw utils.err(`${DOMAIN}#getAdapter`, 'name')(400, 'string', name)\n }\n return this.getAdapters()[adapter]\n },\n\n /**\n * Return the name of a registered adapter based on the given name or options,\n * or the name of the default adapter if no name provided.\n *\n * @method Container#getAdapterName\n * @param {(Object|string)} [opts] The name of an adapter or options, if any.\n * @returns {string} The name of the adapter.\n * @since 3.0.0\n */\n getAdapterName (opts) {\n opts || (opts = {})\n if (utils.isString(opts)) {\n opts = { adapter: opts }\n }\n return opts.adapter || this.mapperDefaults.defaultAdapter\n },\n\n /**\n * Return the registered adapters of this container.\n *\n * @method Container#getAdapters\n * @returns {Adapter}\n * @since 3.0.0\n */\n getAdapters () {\n return this._adapters\n },\n\n /**\n * Return the mapper registered under the specified name.\n *\n * @example Container#getMapper\n * // import { Container } from 'js-data';\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new Container();\n * // Container#defineMapper returns a direct reference to the newly created\n * // Mapper.\n * const UserMapper = store.defineMapper('user');\n * console.log(UserMapper === store.getMapper('user'));\n * console.log(UserMapper === store.as('user').getMapper());\n * store.getMapper('profile'); // throws Error, there is no mapper with name \"profile\"\n *\n * @method Container#getMapper\n * @param {string} name {@link Mapper#name}.\n * @returns {Mapper}\n * @since 3.0.0\n */\n getMapper (name) {\n const mapper = this.getMapperByName(name)\n if (!mapper) {\n throw utils.err(`${DOMAIN}#getMapper`, name)(404, 'mapper')\n }\n return mapper\n },\n\n /**\n * Return the mapper registered under the specified name.\n * Doesn't throw error if mapper doesn't exist.\n *\n * @example Container#getMapperByName\n * // import { Container } from 'js-data';\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new Container();\n * // Container#defineMapper returns a direct reference to the newly created\n * // Mapper.\n * const UserMapper = store.defineMapper('user');\n * console.log(UserMapper === store.getMapper('user'));\n * console.log(UserMapper === store.as('user').getMapper());\n * console.log(store.getMapper('profile')); // Does NOT throw an error\n *\n * @method Container#getMapperByName\n * @param {string} name {@link Mapper#name}.\n * @returns {Mapper}\n * @since 3.0.0\n */\n getMapperByName (name) {\n return this._mappers[name]\n },\n\n /**\n * Register an adapter on this container under the given name. Adapters\n * registered on a container are shared by all mappers in the container.\n *\n * @example\n * import { Container } from 'js-data';\n * import { RethinkDBAdapter } from 'js-data-rethinkdb';\n * const store = new Container();\n * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true });\n *\n * @method Container#registerAdapter\n * @param {string} name The name of the adapter to register.\n * @param {Adapter} adapter The adapter to register.\n * @param {object} [opts] Configuration options.\n * @param {boolean} [opts.default=false] Whether to make the adapter the\n * default adapter for all Mappers in this container.\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/connecting-to-a-data-source\",\"Connecting to a data source\"]\n */\n registerAdapter (name, adapter, opts) {\n opts || (opts = {})\n this.getAdapters()[name] = adapter\n // Optionally make it the default adapter for the target.\n if (opts === true || opts.default) {\n this.mapperDefaults.defaultAdapter = name\n utils.forOwn(this._mappers, function (mapper) {\n mapper.defaultAdapter = name\n })\n }\n }\n}\n\nproxiedMapperMethods.forEach(function (method) {\n props[method] = function (name, ...args) {\n return this.getMapper(name)[method](...args)\n }\n})\n\nComponent.extend(props)\n\n/**\n * Create a subclass of this Container:\n * @example Container.extend\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * // Extend the class using ES2015 class syntax.\n * class CustomContainerClass extends Container {\n * foo () { return 'bar' }\n * static beep () { return 'boop' }\n * }\n * const customContainer = new CustomContainerClass();\n * console.log(customContainer.foo());\n * console.log(CustomContainerClass.beep());\n *\n * // Extend the class using alternate method.\n * const OtherContainerClass = Container.extend({\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * });\n * const otherContainer = new OtherContainerClass();\n * console.log(otherContainer.foo());\n * console.log(OtherContainerClass.beep());\n *\n * // Extend the class, providing a custom constructor.\n * function AnotherContainerClass () {\n * Container.call(this);\n * this.created_at = new Date().getTime();\n * }\n * Container.extend({\n * constructor: AnotherContainerClass,\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * })\n * const anotherContainer = new AnotherContainerClass();\n * console.log(anotherContainer.created_at);\n * console.log(anotherContainer.foo());\n * console.log(AnotherContainerClass.beep());\n *\n * @method Container.extend\n * @param {object} [props={}] Properties to add to the prototype of the\n * subclass.\n * @param {object} [props.constructor] Provide a custom constructor function\n * to be used as the subclass itself.\n * @param {object} [classProps={}] Static properties to add to the subclass.\n * @returns {Constructor} Subclass of this Container class.\n * @since 3.0.0\n */\n","import utils from './utils'\n\nimport {\n belongsToType,\n hasManyType,\n hasOneType\n} from './decorators'\nimport { proxiedMapperMethods, Container } from './Container'\nimport Collection from './Collection'\n\nconst DOMAIN = 'SimpleStore'\nconst proxiedCollectionMethods = [\n /**\n * Wrapper for {@link Collection#add}.\n *\n * @example SimpleStore#add\n * const JSData = require('js-data');\n * const { SimpleStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new SimpleStore();\n * store.defineMapper('book');\n *\n * // Add one book to the in-memory store:\n * store.add('book', { id: 1, title: 'Respect your Data' });\n * // Add multiple books to the in-memory store:\n * store.add('book', [\n * { id: 2, title: 'Easy data recipes' },\n * { id: 3, title: 'Active Record 101' }\n * ]);\n *\n * @fires SimpleStore#add\n * @method SimpleStore#add\n * @param {(string|number)} name Name of the {@link Mapper} to target.\n * @param {(Object|Object[]|Record|Record[])} data See {@link Collection#add}.\n * @param {object} [opts] Configuration options. See {@link Collection#add}.\n * @returns {(Object|Object[]|Record|Record[])} See {@link Collection#add}.\n * @see Collection#add\n * @see Collection#add\n * @since 3.0.0\n */\n 'add',\n\n /**\n * Wrapper for {@link Collection#between}.\n *\n * @example\n * // Get all users ages 18 to 30\n * const users = store.between('user', 18, 30, { index: 'age' });\n *\n * @example\n * // Same as above\n * const users = store.between('user', [18], [30], { index: 'age' });\n *\n * @method SimpleStore#between\n * @param {(string|number)} name Name of the {@link Mapper} to target.\n * @param {array} leftKeys See {@link Collection#between}.\n * @param {array} rightKeys See {@link Collection#between}.\n * @param {object} [opts] Configuration options. See {@link Collection#between}.\n * @returns {Object[]|Record[]} See {@link Collection#between}.\n * @see Collection#between\n * @see Collection#between\n * @since 3.0.0\n */\n 'between',\n\n /**\n * Wrapper for {@link Collection#createIndex}.\n *\n * @example\n * // Index users by age\n * store.createIndex('user', 'age');\n *\n * @example\n * // Index users by status and role\n * store.createIndex('user', 'statusAndRole', ['status', 'role']);\n *\n * @method SimpleStore#createIndex\n * @param {(string|number)} name Name of the {@link Mapper} to target.\n * @param {string} name See {@link Collection#createIndex}.\n * @param {string[]} [fieldList] See {@link Collection#createIndex}.\n * @see Collection#createIndex\n * @see Collection#createIndex\n * @since 3.0.0\n */\n 'createIndex',\n\n /**\n * Wrapper for {@link Collection#filter}.\n *\n * @example SimpleStore#filter\n * const JSData = require('js-data');\n * const { SimpleStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new SimpleStore();\n * store.defineMapper('post');\n * store.add('post', [\n * { id: 1, status: 'draft', created_at_timestamp: new Date().getTime() }\n * ]);\n *\n * // Get the draft posts created less than three months ago\n * let posts = store.filter('post', {\n * where: {\n * status: {\n * '==': 'draft'\n * },\n * created_at_timestamp: {\n * '>=': (new Date().getTime() - (1000 \\* 60 \\* 60 \\* 24 \\* 30 \\* 3)) // 3 months ago\n * }\n * }\n * });\n * console.log(posts);\n *\n * // Use a custom filter function\n * posts = store.filter('post', function (post) { return post.id % 2 === 0 });\n *\n * @method SimpleStore#filter\n * @param {(string|number)} name Name of the {@link Mapper} to target.\n * @param {(Object|Function)} [queryOrFn={}] See {@link Collection#filter}.\n * @param {object} [thisArg] See {@link Collection#filter}.\n * @returns {Array} See {@link Collection#filter}.\n * @see Collection#filter\n * @see Collection#filter\n * @since 3.0.0\n */\n 'filter',\n\n /**\n * Wrapper for {@link Collection#get}.\n *\n * @example SimpleStore#get\n * const JSData = require('js-data');\n * const { SimpleStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new SimpleStore();\n * store.defineMapper('post');\n * store.add('post', [\n * { id: 1, status: 'draft', created_at_timestamp: new Date().getTime() }\n * ]);\n *\n * console.log(store.get('post', 1)); // {...}\n * console.log(store.get('post', 2)); // undefined\n *\n * @method SimpleStore#get\n * @param {(string|number)} name Name of the {@link Mapper} to target.\n * @param {(string|number)} id See {@link Collection#get}.\n * @returns {(Object|Record)} See {@link Collection#get}.\n * @see Collection#get\n * @see Collection#get\n * @since 3.0.0\n */\n 'get',\n\n /**\n * Wrapper for {@link Collection#getAll}.\n *\n * @example\n * // Get the posts where \"status\" is \"draft\" or \"inReview\"\n * const posts = store.getAll('post', 'draft', 'inReview', { index: 'status' });\n *\n * @example\n * // Same as above\n * const posts = store.getAll('post', ['draft'], ['inReview'], { index: 'status' });\n *\n * @method SimpleStore#getAll\n * @param {(string|number)} name Name of the {@link Mapper} to target.\n * @param {...Array} [keyList] See {@link Collection#getAll}.\n * @param {object} [opts] See {@link Collection#getAll}.\n * @returns {Array} See {@link Collection#getAll}.\n * @see Collection#getAll\n * @see Collection#getAll\n * @since 3.0.0\n */\n 'getAll',\n\n /**\n * Wrapper for {@link Collection#prune}.\n *\n * @method SimpleStore#prune\n * @param {object} [opts] See {@link Collection#prune}.\n * @returns {Array} See {@link Collection#prune}.\n * @see Collection#prune\n * @see Collection#prune\n * @since 3.0.0\n */\n 'prune',\n\n /**\n * Wrapper for {@link Collection#query}.\n *\n * @example\n * // Grab page 2 of users between ages 18 and 30\n * store.query('user')\n * .between(18, 30, { index: 'age' }) // between ages 18 and 30\n * .skip(10) // second page\n * .limit(10) // page size\n * .run();\n *\n * @method SimpleStore#query\n * @param {(string|number)} name Name of the {@link Mapper} to target.\n * @returns {Query} See {@link Collection#query}.\n * @see Collection#query\n * @see Collection#query\n * @since 3.0.0\n */\n 'query',\n\n /**\n * Wrapper for {@link Collection#toJSON}.\n *\n * @example\n * store.defineMapper('post', {\n * schema: {\n * properties: {\n * id: { type: 'number' },\n * title: { type: 'string' }\n * }\n * }\n * });\n * store.add('post', [\n * { id: 1, status: 'published', title: 'Respect your Data' },\n * { id: 2, status: 'draft', title: 'Connecting to a data source' }\n * ]);\n * console.log(store.toJSON('post'));\n * const draftsJSON = store.query('post')\n * .filter({ status: 'draft' })\n * .mapCall('toJSON')\n * .run();\n *\n * @method SimpleStore#toJSON\n * @param {(string|number)} name Name of the {@link Mapper} to target.\n * @param {object} [opts] See {@link Collection#toJSON}.\n * @returns {Array} See {@link Collection#toJSON}.\n * @see Collection#toJSON\n * @see Collection#toJSON\n * @since 3.0.0\n */\n 'toJSON',\n\n /**\n * Wrapper for {@link Collection#unsaved}.\n *\n * @method SimpleStore#unsaved\n * @returns {Array} See {@link Collection#unsaved}.\n * @see Collection#unsaved\n * @see Collection#unsaved\n * @since 3.0.0\n */\n 'unsaved'\n]\nconst ownMethodsForScoping = [\n 'addToCache',\n 'cachedFind',\n 'cachedFindAll',\n 'cacheFind',\n 'cacheFindAll',\n 'hashQuery'\n]\n\nconst cachedFn = function (name, hashOrId, opts) {\n const cached = this._completedQueries[name][hashOrId]\n if (utils.isFunction(cached)) {\n return cached(name, hashOrId, opts)\n }\n return cached\n}\n\nconst SIMPLESTORE_DEFAULTS = {\n /**\n * Whether to use the pending query if a `find` request for the specified\n * record is currently underway. Can be set to `true`, `false`, or to a\n * function that returns `true` or `false`.\n *\n * @default true\n * @name SimpleStore#usePendingFind\n * @since 3.0.0\n * @type {boolean|Function}\n */\n usePendingFind: true,\n\n /**\n * Whether to use the pending query if a `findAll` request for the given query\n * is currently underway. Can be set to `true`, `false`, or to a function that\n * returns `true` or `false`.\n *\n * @default true\n * @name SimpleStore#usePendingFindAll\n * @since 3.0.0\n * @type {boolean|Function}\n */\n usePendingFindAll: true\n}\n\n/**\n * The `SimpleStore` class is an extension of {@link Container}. Not only does\n * `SimpleStore` manage mappers, but also collections. `SimpleStore` implements the\n * asynchronous {@link Mapper} methods, such as {@link Mapper#find} and\n * {@link Mapper#create}. If you use the asynchronous `SimpleStore` methods\n * instead of calling them directly on the mappers, then the results of the\n * method calls will be inserted into the store's collections. You can think of\n * a `SimpleStore` as an [Identity Map](https://en.wikipedia.org/wiki/Identity_map_pattern)\n * for the [ORM](https://en.wikipedia.org/wiki/Object-relational_mapping)\n * (the Mappers).\n *\n * ```javascript\n * import { SimpleStore } from 'js-data';\n * ```\n *\n * @example\n * import { SimpleStore } from 'js-data';\n * import { HttpAdapter } from 'js-data-http';\n * const store = new SimpleStore();\n *\n * // SimpleStore#defineMapper returns a direct reference to the newly created\n * // Mapper.\n * const UserMapper = store.defineMapper('user');\n *\n * // SimpleStore#as returns the store scoped to a particular Mapper.\n * const UserStore = store.as('user');\n *\n * // Call \"find\" on \"UserMapper\" (Stateless ORM)\n * UserMapper.find(1).then((user) => {\n * // retrieved a \"user\" record via the http adapter, but that's it\n *\n * // Call \"find\" on \"store\" targeting \"user\" (Stateful SimpleStore)\n * return store.find('user', 1); // same as \"UserStore.find(1)\"\n * }).then((user) => {\n * // not only was a \"user\" record retrieved, but it was added to the\n * // store's \"user\" collection\n * const cachedUser = store.getCollection('user').get(1);\n * console.log(user === cachedUser); // true\n * });\n *\n * @class SimpleStore\n * @extends Container\n * @param {object} [opts] Configuration options. See {@link Container}.\n * @param {boolean} [opts.collectionClass={@link Collection}] See {@link SimpleStore#collectionClass}.\n * @param {boolean} [opts.debug=false] See {@link Component#debug}.\n * @param {boolean|Function} [opts.usePendingFind=true] See {@link SimpleStore#usePendingFind}.\n * @param {boolean|Function} [opts.usePendingFindAll=true] See {@link SimpleStore#usePendingFindAll}.\n * @returns {SimpleStore}\n * @see Container\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/components-of-jsdata#SimpleStore\",\"Components of JSData: SimpleStore\"]\n * @tutorial [\"http://www.js-data.io/v3.0/docs/working-with-the-SimpleStore\",\"Working with the SimpleStore\"]\n * @tutorial [\"http://www.js-data.io/v3.0/docs/jsdata-and-the-browser\",\"Notes on using JSData in the Browser\"]\n */\nfunction SimpleStore (opts) {\n utils.classCallCheck(this, SimpleStore)\n\n opts || (opts = {})\n // Fill in any missing options with the defaults\n utils.fillIn(opts, SIMPLESTORE_DEFAULTS)\n Container.call(this, opts)\n\n this.collectionClass = this.collectionClass || Collection\n this._collections = {}\n this._pendingQueries = {}\n this._completedQueries = {}\n}\n\nconst props = {\n constructor: SimpleStore,\n\n /**\n * Internal method used to handle Mapper responses.\n *\n * @method SimpleStore#_end\n * @private\n * @param {string} name Name of the {@link Collection} to which to\n * add the data.\n * @param {object} result The result from a Mapper.\n * @param {object} [opts] Configuration options.\n * @returns {(Object|Array)} Result.\n */\n _end (name, result, opts) {\n let data = opts.raw ? result.data : result\n if (data && utils.isFunction(this.addToCache)) {\n data = this.addToCache(name, data, opts)\n if (opts.raw) {\n result.data = data\n } else {\n result = data\n }\n }\n return result\n },\n\n /**\n * Register a new event listener on this SimpleStore.\n *\n * Proxy for {@link Container#on}. If an event was emitted by a Mapper or\n * Collection in the SimpleStore, then the name of the Mapper or Collection will\n * be prepended to the arugments passed to the provided event handler.\n *\n * @example\n * // Listen for all \"afterCreate\" events in a SimpleStore\n * store.on('afterCreate', (mapperName, props, opts, result) => {\n * console.log(mapperName); // \"post\"\n * console.log(props.id); // undefined\n * console.log(result.id); // 1234\n * });\n * store.create('post', { title: 'Modeling your data' }).then((post) => {\n * console.log(post.id); // 1234\n * });\n *\n * @example\n * // Listen for the \"add\" event on a collection\n * store.on('add', (mapperName, records) => {\n * console.log(records); // [...]\n * });\n *\n * @example\n * // Listen for \"change\" events on a record\n * store.on('change', (mapperName, record, changes) => {\n * console.log(changes); // { changed: { title: 'Modeling your data' } }\n * });\n * post.title = 'Modeling your data';\n *\n * @method SimpleStore#on\n * @param {string} event Name of event to subsribe to.\n * @param {Function} listener Listener function to handle the event.\n * @param {*} [ctx] Optional content in which to invoke the listener.\n */\n\n /**\n * Used to bind to events emitted by collections in this store.\n *\n * @method SimpleStore#_onCollectionEvent\n * @private\n * @param {string} name Name of the collection that emitted the event.\n * @param {...*} [args] Args passed to {@link Collection#emit}.\n */\n _onCollectionEvent (name, ...args) {\n const type = args.shift()\n this.emit(type, name, ...args)\n },\n\n /**\n * This method takes the data received from {@link SimpleStore#find},\n * {@link SimpleStore#findAll}, {@link SimpleStore#update}, etc., and adds the\n * data to the store. _You don't need to call this method directly._\n *\n * If you're using the http adapter and your response data is in an unexpected\n * format, you may need to override this method so the right data gets added\n * to the store.\n *\n * @example\n * const store = new SimpleStore({\n * addToCache (mapperName, data, opts) {\n * // Let's say for a particular Resource, response data is in a weird format\n * if (name === 'comment') {\n * // Re-assign the variable to add the correct records into the stores\n * data = data.items;\n * }\n * // Now perform default behavior\n * return SimpleStore.prototype.addToCache.call(this, mapperName, data, opts);\n * }\n * });\n *\n * @example\n * // Extend using ES2015 class syntax.\n * class MyStore extends SimpleStore {\n * addToCache (mapperName, data, opts) {\n * // Let's say for a particular Resource, response data is in a weird format\n * if (name === 'comment') {\n * // Re-assign the variable to add the correct records into the stores\n * data = data.items;\n * }\n * // Now perform default behavior\n * return super.addToCache(mapperName, data, opts);\n * }\n * }\n * const store = new MyStore();\n *\n * @method SimpleStore#addToCache\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {*} data Data from which data should be selected for add.\n * @param {object} [opts] Configuration options.\n */\n addToCache (name, data, opts) {\n return this.getCollection(name).add(data, opts)\n },\n\n /**\n * Return the store scoped to a particular mapper/collection pair.\n *\n * @example SimpleStore.as\n * const JSData = require('js-data');\n * const { SimpleStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new SimpleStore();\n * const UserMapper = store.defineMapper('user');\n * const UserStore = store.as('user');\n *\n * const user1 = store.createRecord('user', { name: 'John' });\n * const user2 = UserStore.createRecord({ name: 'John' });\n * const user3 = UserMapper.createRecord({ name: 'John' });\n * console.log(user1 === user2);\n * console.log(user2 === user3);\n * console.log(user1 === user3);\n *\n * @method SimpleStore#as\n * @param {string} name Name of the {@link Mapper}.\n * @returns {Object} The store, scoped to a particular Mapper/Collection pair.\n * @since 3.0.0\n */\n as (name) {\n const props = {}\n const original = this\n const methods = ownMethodsForScoping\n .concat(proxiedMapperMethods)\n .concat(proxiedCollectionMethods)\n\n methods.forEach(function (method) {\n props[method] = {\n writable: true,\n value (...args) {\n return original[method](name, ...args)\n }\n }\n })\n props.getMapper = {\n writable: true,\n value () {\n return original.getMapper(name)\n }\n }\n props.getCollection = {\n writable: true,\n value () {\n return original.getCollection(name)\n }\n }\n return Object.create(this, props)\n },\n\n /**\n * Retrieve a cached `find` result, if any. This method is called during\n * {@link SimpleStore#find} to determine if {@link Mapper#find} needs to be\n * called. If this method returns `undefined` then {@link Mapper#find} will\n * be called. Otherwise {@link SimpleStore#find} will immediately resolve with\n * the return value of this method.\n *\n * When using {@link SimpleStore} in the browser, you can override this method\n * to implement your own cache-busting strategy.\n *\n * @example\n * const store = new SimpleStore({\n * cachedFind (mapperName, id, opts) {\n * // Let's say for a particular Resource, we always want to pull fresh from the server\n * if (mapperName === 'schedule') {\n * // Return undefined to trigger a Mapper#find call\n * return;\n * }\n * // Otherwise perform default behavior\n * return SimpleStore.prototype.cachedFind.call(this, mapperName, id, opts);\n * }\n * });\n *\n * @example\n * // Extend using ES2015 class syntax.\n * class MyStore extends SimpleStore {\n * cachedFind (mapperName, id, opts) {\n * // Let's say for a particular Resource, we always want to pull fresh from the server\n * if (mapperName === 'schedule') {\n * // Return undefined to trigger a Mapper#find call\n * return;\n * }\n * // Otherwise perform default behavior\n * return super.cachedFind(mapperName, id, opts);\n * }\n * }\n * const store = new MyStore();\n *\n * @method SimpleStore#cachedFind\n * @param {string} name The `name` argument passed to {@link SimpleStore#find}.\n * @param {(string|number)} id The `id` argument passed to {@link SimpleStore#find}.\n * @param {object} opts The `opts` argument passed to {@link SimpleStore#find}.\n * @since 3.0.0\n */\n cachedFind: cachedFn,\n\n /**\n * Retrieve a cached `findAll` result, if any. This method is called during\n * {@link SimpleStore#findAll} to determine if {@link Mapper#findAll} needs to be\n * called. If this method returns `undefined` then {@link Mapper#findAll} will\n * be called. Otherwise {@link SimpleStore#findAll} will immediately resolve with\n * the return value of this method.\n *\n * When using {@link SimpleStore} in the browser, you can override this method\n * to implement your own cache-busting strategy.\n *\n * @example\n * const store = new SimpleStore({\n * cachedFindAll (mapperName, hash, opts) {\n * // Let's say for a particular Resource, we always want to pull fresh from the server\n * if (mapperName === 'schedule') {\n * // Return undefined to trigger a Mapper#findAll call\n * return undefined;\n * }\n * // Otherwise perform default behavior\n * return SimpleStore.prototype.cachedFindAll.call(this, mapperName, hash, opts);\n * }\n * });\n *\n * @example\n * // Extend using ES2015 class syntax.\n * class MyStore extends SimpleStore {\n * cachedFindAll (mapperName, hash, opts) {\n * // Let's say for a particular Resource, we always want to pull fresh from the server\n * if (mapperName === 'schedule') {\n * // Return undefined to trigger a Mapper#findAll call\n * return undefined;\n * }\n * // Otherwise perform default behavior\n * return super.cachedFindAll(mapperName, hash, opts);\n * }\n * }\n * const store = new MyStore();\n *\n * @method SimpleStore#cachedFindAll\n * @param {string} name The `name` argument passed to {@link SimpleStore#findAll}.\n * @param {string} hash The result of calling {@link SimpleStore#hashQuery} on\n * the `query` argument passed to {@link SimpleStore#findAll}.\n * @param {object} opts The `opts` argument passed to {@link SimpleStore#findAll}.\n * @since 3.0.0\n */\n cachedFindAll: cachedFn,\n\n /**\n * Mark a {@link Mapper#find} result as cached by adding an entry to\n * {@link SimpleStore#_completedQueries}. By default, once a `find` entry is\n * added it means subsequent calls to the same Resource with the same `id`\n * argument will immediately resolve with the result of calling\n * {@link SimpleStore#get} instead of delegating to {@link Mapper#find}.\n *\n * As part of implementing your own caching strategy, you may choose to\n * override this method.\n *\n * @example\n * const store = new SimpleStore({\n * cacheFind (mapperName, data, id, opts) {\n * // Let's say for a particular Resource, we always want to pull fresh from the server\n * if (mapperName === 'schedule') {\n * // Return without saving an entry to SimpleStore#_completedQueries\n * return;\n * }\n * // Otherwise perform default behavior\n * return SimpleStore.prototype.cacheFind.call(this, mapperName, data, id, opts);\n * }\n * });\n *\n * @example\n * // Extend using ES2015 class syntax.\n * class MyStore extends SimpleStore {\n * cacheFind (mapperName, data, id, opts) {\n * // Let's say for a particular Resource, we always want to pull fresh from the server\n * if (mapperName === 'schedule') {\n * // Return without saving an entry to SimpleStore#_completedQueries\n * return;\n * }\n * // Otherwise perform default behavior\n * return super.cacheFind(mapperName, data, id, opts);\n * }\n * }\n * const store = new MyStore();\n *\n * @method SimpleStore#cacheFind\n * @param {string} name The `name` argument passed to {@link SimpleStore#find}.\n * @param {*} data The result to cache.\n * @param {(string|number)} id The `id` argument passed to {@link SimpleStore#find}.\n * @param {object} opts The `opts` argument passed to {@link SimpleStore#find}.\n * @since 3.0.0\n */\n cacheFind (name, data, id, opts) {\n this._completedQueries[name][id] = (name, id, opts) => this.get(name, id)\n },\n\n /**\n * Mark a {@link Mapper#findAll} result as cached by adding an entry to\n * {@link SimpleStore#_completedQueries}. By default, once a `findAll` entry is\n * added it means subsequent calls to the same Resource with the same `query`\n * argument will immediately resolve with the result of calling\n * {@link SimpleStore#filter} instead of delegating to {@link Mapper#findAll}.\n *\n * As part of implementing your own caching strategy, you may choose to\n * override this method.\n *\n * @example\n * const store = new SimpleStore({\n * cachedFindAll (mapperName, data, hash, opts) {\n * // Let's say for a particular Resource, we always want to pull fresh from the server\n * if (mapperName === 'schedule') {\n * // Return without saving an entry to SimpleStore#_completedQueries\n * return;\n * }\n * // Otherwise perform default behavior.\n * return SimpleStore.prototype.cachedFindAll.call(this, mapperName, data, hash, opts);\n * }\n * });\n *\n * @example\n * // Extend using ES2015 class syntax.\n * class MyStore extends SimpleStore {\n * cachedFindAll (mapperName, data, hash, opts) {\n * // Let's say for a particular Resource, we always want to pull fresh from the server\n * if (mapperName === 'schedule') {\n * // Return without saving an entry to SimpleStore#_completedQueries\n * return;\n * }\n * // Otherwise perform default behavior.\n * return super.cachedFindAll(mapperName, data, hash, opts);\n * }\n * }\n * const store = new MyStore();\n *\n * @method SimpleStore#cacheFindAll\n * @param {string} name The `name` argument passed to {@link SimpleStore#findAll}.\n * @param {*} data The result to cache.\n * @param {string} hash The result of calling {@link SimpleStore#hashQuery} on\n * the `query` argument passed to {@link SimpleStore#findAll}.\n * @param {object} opts The `opts` argument passed to {@link SimpleStore#findAll}.\n * @since 3.0.0\n */\n cacheFindAll (name, data, hash, opts) {\n this._completedQueries[name][hash] = (name, hash, opts) => this.filter(name, utils.fromJson(hash))\n },\n\n /**\n * Remove __all__ records from the in-memory store and reset\n * {@link SimpleStore#_completedQueries}.\n *\n * @method SimpleStore#clear\n * @returns {Object} Object containing all records that were in the store.\n * @see SimpleStore#remove\n * @see SimpleStore#removeAll\n * @since 3.0.0\n */\n clear () {\n const removed = {}\n utils.forOwn(this._collections, (collection, name) => {\n removed[name] = collection.removeAll()\n this._completedQueries[name] = {}\n })\n return removed\n },\n\n /**\n * Fired during {@link SimpleStore#create}. See\n * {@link SimpleStore~beforeCreateListener} for how to listen for this event.\n *\n * @event SimpleStore#beforeCreate\n * @see SimpleStore~beforeCreateListener\n * @see SimpleStore#create\n */\n /**\n * Callback signature for the {@link SimpleStore#event:beforeCreate} event.\n *\n * @example\n * function onBeforeCreate (mapperName, props, opts) {\n * // do something\n * }\n * store.on('beforeCreate', onBeforeCreate);\n *\n * @callback SimpleStore~beforeCreateListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeCreate}.\n * @param {object} props The `props` argument received by {@link Mapper#beforeCreate}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeCreate}.\n * @see SimpleStore#event:beforeCreate\n * @see SimpleStore#create\n * @since 3.0.0\n */\n /**\n * Fired during {@link SimpleStore#create}. See\n * {@link SimpleStore~afterCreateListener} for how to listen for this event.\n *\n * @event SimpleStore#afterCreate\n * @see SimpleStore~afterCreateListener\n * @see SimpleStore#create\n */\n /**\n * Callback signature for the {@link SimpleStore#event:afterCreate} event.\n *\n * @example\n * function onAfterCreate (mapperName, props, opts, result) {\n * // do something\n * }\n * store.on('afterCreate', onAfterCreate);\n *\n * @callback SimpleStore~afterCreateListener\n * @param {string} name The `name` argument received by {@link Mapper#afterCreate}.\n * @param {object} props The `props` argument received by {@link Mapper#afterCreate}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterCreate}.\n * @param {object} result The `result` argument received by {@link Mapper#afterCreate}.\n * @see SimpleStore#event:afterCreate\n * @see SimpleStore#create\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#create}. Adds the created record to the store.\n *\n * @example\n * import { SimpleStore } from 'js-data';\n * import { HttpAdapter } from 'js-data-http';\n *\n * const store = new SimpleStore();\n * store.registerAdapter('http', new HttpAdapter(), { default: true });\n *\n * store.defineMapper('book');\n *\n * // Since this example uses the http adapter, we'll get something like:\n * //\n * // POST /book {\"author_id\":1234,...}\n * store.create('book', {\n * author_id: 1234,\n * edition: 'First Edition',\n * title: 'Respect your Data'\n * }).then((book) => {\n * console.log(book.id); // 120392\n * console.log(book.title); // \"Respect your Data\"\n * });\n *\n * @fires SimpleStore#beforeCreate\n * @fires SimpleStore#afterCreate\n * @fires SimpleStore#add\n * @method SimpleStore#create\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {object} record Passed to {@link Mapper#create}.\n * @param {object} [opts] Passed to {@link Mapper#create}. See\n * {@link Mapper#create} for more configuration options.\n * @returns {Promise} Resolves with the result of the create.\n * @since 3.0.0\n */\n create (name, record, opts) {\n opts || (opts = {})\n return Container.prototype.create.call(this, name, record, opts)\n .then((result) => this._end(name, result, opts))\n },\n\n /**\n * Fired during {@link SimpleStore#createMany}. See\n * {@link SimpleStore~beforeCreateManyListener} for how to listen for this event.\n *\n * @event SimpleStore#beforeCreateMany\n * @see SimpleStore~beforeCreateManyListener\n * @see SimpleStore#createMany\n */\n /**\n * Callback signature for the {@link SimpleStore#event:beforeCreateMany} event.\n *\n * @example\n * function onBeforeCreateMany (mapperName, records, opts) {\n * // do something\n * }\n * store.on('beforeCreateMany', onBeforeCreateMany);\n *\n * @callback SimpleStore~beforeCreateManyListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeCreateMany}.\n * @param {object} records The `records` argument received by {@link Mapper#beforeCreateMany}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeCreateMany}.\n * @see SimpleStore#event:beforeCreateMany\n * @see SimpleStore#createMany\n * @since 3.0.0\n */\n /**\n * Fired during {@link SimpleStore#createMany}. See\n * {@link SimpleStore~afterCreateManyListener} for how to listen for this event.\n *\n * @event SimpleStore#afterCreateMany\n * @see SimpleStore~afterCreateManyListener\n * @see SimpleStore#createMany\n */\n /**\n * Callback signature for the {@link SimpleStore#event:afterCreateMany} event.\n *\n * @example\n * function onAfterCreateMany (mapperName, records, opts, result) {\n * // do something\n * }\n * store.on('afterCreateMany', onAfterCreateMany);\n *\n * @callback SimpleStore~afterCreateManyListener\n * @param {string} name The `name` argument received by {@link Mapper#afterCreateMany}.\n * @param {object} records The `records` argument received by {@link Mapper#afterCreateMany}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterCreateMany}.\n * @param {object} result The `result` argument received by {@link Mapper#afterCreateMany}.\n * @see SimpleStore#event:afterCreateMany\n * @see SimpleStore#createMany\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#createMany}. Adds the created records to the\n * store.\n *\n * @example\n * import { SimpleStore } from 'js-data';\n * import { HttpAdapter } from 'js-data-http';\n *\n * const store = new SimpleStore();\n * store.registerAdapter('http', new HttpAdapter(), { default: true });\n *\n * store.defineMapper('book');\n *\n * // Since this example uses the http adapter, we'll get something like:\n * //\n * // POST /book [{\"author_id\":1234,...},{...}]\n * store.createMany('book', [{\n * author_id: 1234,\n * edition: 'First Edition',\n * title: 'Respect your Data'\n * }, {\n * author_id: 1234,\n * edition: 'Second Edition',\n * title: 'Respect your Data'\n * }]).then((books) => {\n * console.log(books[0].id); // 142394\n * console.log(books[0].title); // \"Respect your Data\"\n * });\n *\n * @fires SimpleStore#beforeCreateMany\n * @fires SimpleStore#afterCreateMany\n * @fires SimpleStore#add\n * @method SimpleStore#createMany\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {array} records Passed to {@link Mapper#createMany}.\n * @param {object} [opts] Passed to {@link Mapper#createMany}. See\n * {@link Mapper#createMany} for more configuration options.\n * @returns {Promise} Resolves with the result of the create.\n * @since 3.0.0\n */\n createMany (name, records, opts) {\n opts || (opts = {})\n return Container.prototype.createMany.call(this, name, records, opts)\n .then((result) => this._end(name, result, opts))\n },\n\n defineMapper (name, opts) {\n const self = this\n const mapper = Container.prototype.defineMapper.call(self, name, opts)\n self._pendingQueries[name] = {}\n self._completedQueries[name] = {}\n mapper.relationList || Object.defineProperty(mapper, 'relationList', { value: [] })\n\n const collectionOpts = {\n // Make sure the collection has somewhere to store \"added\" timestamps\n _added: {},\n // Give the collection a reference to this SimpleStore\n datastore: self,\n // The mapper tied to the collection\n mapper\n }\n\n if (opts && ('onConflict' in opts)) {\n collectionOpts.onConflict = opts.onConflict\n }\n\n // The SimpleStore uses a subclass of Collection that is \"SimpleStore-aware\"\n const collection = self._collections[name] = new self.collectionClass(null, collectionOpts) // eslint-disable-line\n\n const schema = mapper.schema || {}\n const properties = schema.properties || {}\n // TODO: Make it possible index nested properties?\n utils.forOwn(properties, function (opts, prop) {\n if (opts.indexed) {\n collection.createIndex(prop)\n }\n })\n\n // Create a secondary index on the \"added\" timestamps of records in the\n // collection\n collection.createIndex('addedTimestamps', ['$'], {\n fieldGetter (obj) {\n return collection._added[collection.recordId(obj)]\n }\n })\n\n collection.on('all', function (...args) {\n self._onCollectionEvent(name, ...args)\n })\n\n return mapper\n },\n\n /**\n * Fired during {@link SimpleStore#destroy}. See\n * {@link SimpleStore~beforeDestroyListener} for how to listen for this event.\n *\n * @event SimpleStore#beforeDestroy\n * @see SimpleStore~beforeDestroyListener\n * @see SimpleStore#destroy\n */\n /**\n * Callback signature for the {@link SimpleStore#event:beforeDestroy} event.\n *\n * @example\n * function onBeforeDestroy (mapperName, id, opts) {\n * // do something\n * }\n * store.on('beforeDestroy', onBeforeDestroy);\n *\n * @callback SimpleStore~beforeDestroyListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeDestroy}.\n * @param {string|number} id The `id` argument received by {@link Mapper#beforeDestroy}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeDestroy}.\n * @see SimpleStore#event:beforeDestroy\n * @see SimpleStore#destroy\n * @since 3.0.0\n */\n /**\n * Fired during {@link SimpleStore#destroy}. See\n * {@link SimpleStore~afterDestroyListener} for how to listen for this event.\n *\n * @event SimpleStore#afterDestroy\n * @see SimpleStore~afterDestroyListener\n * @see SimpleStore#destroy\n */\n /**\n * Callback signature for the {@link SimpleStore#event:afterDestroy} event.\n *\n * @example\n * function onAfterDestroy (mapperName, id, opts, result) {\n * // do something\n * }\n * store.on('afterDestroy', onAfterDestroy);\n *\n * @callback SimpleStore~afterDestroyListener\n * @param {string} name The `name` argument received by {@link Mapper#afterDestroy}.\n * @param {string|number} id The `id` argument received by {@link Mapper#afterDestroy}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterDestroy}.\n * @param {object} result The `result` argument received by {@link Mapper#afterDestroy}.\n * @see SimpleStore#event:afterDestroy\n * @see SimpleStore#destroy\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#destroy}. Removes any destroyed record from the\n * in-memory store. Clears out any {@link SimpleStore#_completedQueries} entries\n * associated with the provided `id`.\n *\n * @example\n * import { SimpleStore } from 'js-data';\n * import { HttpAdapter } from 'js-data-http';\n *\n * const store = new SimpleStore();\n * store.registerAdapter('http', new HttpAdapter(), { default: true });\n *\n * store.defineMapper('book');\n *\n * store.add('book', { id: 1234, title: 'Data Management is Hard' });\n *\n * // Since this example uses the http adapter, we'll get something like:\n * //\n * // DELETE /book/1234\n * store.destroy('book', 1234).then(() => {\n * // The book record is no longer in the in-memory store\n * console.log(store.get('book', 1234)); // undefined\n *\n * return store.find('book', 1234);\n * }).then((book) {\n * // The book was deleted from the database too\n * console.log(book); // undefined\n * });\n *\n * @fires SimpleStore#beforeDestroy\n * @fires SimpleStore#afterDestroy\n * @fires SimpleStore#remove\n * @method SimpleStore#destroy\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {(string|number)} id Passed to {@link Mapper#destroy}.\n * @param {object} [opts] Passed to {@link Mapper#destroy}. See\n * {@link Mapper#destroy} for more configuration options.\n * @returns {Promise} Resolves when the destroy operation completes.\n * @since 3.0.0\n */\n destroy (name, id, opts) {\n opts || (opts = {})\n return Container.prototype.destroy.call(this, name, id, opts).then((result) => {\n const record = this.getCollection(name).remove(id, opts)\n\n if (opts.raw) {\n result.data = record\n } else {\n result = record\n }\n delete this._pendingQueries[name][id]\n delete this._completedQueries[name][id]\n return result\n })\n },\n\n /**\n * Fired during {@link SimpleStore#destroyAll}. See\n * {@link SimpleStore~beforeDestroyAllListener} for how to listen for this event.\n *\n * @event SimpleStore#beforeDestroyAll\n * @see SimpleStore~beforeDestroyAllListener\n * @see SimpleStore#destroyAll\n */\n /**\n * Callback signature for the {@link SimpleStore#event:beforeDestroyAll} event.\n *\n * @example\n * function onBeforeDestroyAll (mapperName, query, opts) {\n * // do something\n * }\n * store.on('beforeDestroyAll', onBeforeDestroyAll);\n *\n * @callback SimpleStore~beforeDestroyAllListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeDestroyAll}.\n * @param {object} query The `query` argument received by {@link Mapper#beforeDestroyAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeDestroyAll}.\n * @see SimpleStore#event:beforeDestroyAll\n * @see SimpleStore#destroyAll\n * @since 3.0.0\n */\n /**\n * Fired during {@link SimpleStore#destroyAll}. See\n * {@link SimpleStore~afterDestroyAllListener} for how to listen for this event.\n *\n * @event SimpleStore#afterDestroyAll\n * @see SimpleStore~afterDestroyAllListener\n * @see SimpleStore#destroyAll\n */\n /**\n * Callback signature for the {@link SimpleStore#event:afterDestroyAll} event.\n *\n * @example\n * function onAfterDestroyAll (mapperName, query, opts, result) {\n * // do something\n * }\n * store.on('afterDestroyAll', onAfterDestroyAll);\n *\n * @callback SimpleStore~afterDestroyAllListener\n * @param {string} name The `name` argument received by {@link Mapper#afterDestroyAll}.\n * @param {object} query The `query` argument received by {@link Mapper#afterDestroyAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterDestroyAll}.\n * @param {object} result The `result` argument received by {@link Mapper#afterDestroyAll}.\n * @see SimpleStore#event:afterDestroyAll\n * @see SimpleStore#destroyAll\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#destroyAll}. Removes any destroyed records from\n * the in-memory store.\n *\n * @example\n * import { SimpleStore } from 'js-data';\n * import { HttpAdapter } from 'js-data-http';\n *\n * const store = new SimpleStore();\n * store.registerAdapter('http', new HttpAdapter(), { default: true });\n *\n * store.defineMapper('book');\n *\n * store.add('book', { id: 1234, title: 'Data Management is Hard' });\n *\n * // Since this example uses the http adapter, we'll get something like:\n * //\n * // DELETE /book/1234\n * store.destroy('book', 1234).then(() => {\n * // The book record is gone from the in-memory store\n * console.log(store.get('book', 1234)); // undefined\n * return store.find('book', 1234);\n * }).then((book) {\n * // The book was deleted from the database too\n * console.log(book); // undefined\n * });\n *\n * @fires SimpleStore#beforeDestroyAll\n * @fires SimpleStore#afterDestroyAll\n * @fires SimpleStore#remove\n * @method SimpleStore#destroyAll\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {object} [query] Passed to {@link Mapper#destroyAll}.\n * @param {object} [opts] Passed to {@link Mapper#destroyAll}. See\n * {@link Mapper#destroyAll} for more configuration options.\n * @returns {Promise} Resolves when the delete completes.\n * @since 3.0.0\n */\n destroyAll (name, query, opts) {\n opts || (opts = {})\n return Container.prototype.destroyAll.call(this, name, query, opts).then((result) => {\n const records = this.getCollection(name).removeAll(query, opts)\n\n if (opts.raw) {\n result.data = records\n } else {\n result = records\n }\n const hash = this.hashQuery(name, query, opts)\n delete this._pendingQueries[name][hash]\n delete this._completedQueries[name][hash]\n return result\n })\n },\n\n eject (name, id, opts) {\n console.warn('DEPRECATED: \"eject\" is deprecated, use \"remove\" instead')\n return this.remove(name, id, opts)\n },\n\n ejectAll (name, query, opts) {\n console.warn('DEPRECATED: \"ejectAll\" is deprecated, use \"removeAll\" instead')\n return this.removeAll(name, query, opts)\n },\n\n /**\n * Fired during {@link SimpleStore#find}. See\n * {@link SimpleStore~beforeFindListener} for how to listen for this event.\n *\n * @event SimpleStore#beforeFind\n * @see SimpleStore~beforeFindListener\n * @see SimpleStore#find\n */\n /**\n * Callback signature for the {@link SimpleStore#event:beforeFind} event.\n *\n * @example\n * function onBeforeFind (mapperName, id, opts) {\n * // do something\n * }\n * store.on('beforeFind', onBeforeFind);\n *\n * @callback SimpleStore~beforeFindListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeFind}.\n * @param {string|number} id The `id` argument received by {@link Mapper#beforeFind}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeFind}.\n * @see SimpleStore#event:beforeFind\n * @see SimpleStore#find\n * @since 3.0.0\n */\n /**\n * Fired during {@link SimpleStore#find}. See\n * {@link SimpleStore~afterFindListener} for how to listen for this event.\n *\n * @event SimpleStore#afterFind\n * @see SimpleStore~afterFindListener\n * @see SimpleStore#find\n */\n /**\n * Callback signature for the {@link SimpleStore#event:afterFind} event.\n *\n * @example\n * function onAfterFind (mapperName, id, opts, result) {\n * // do something\n * }\n * store.on('afterFind', onAfterFind);\n *\n * @callback SimpleStore~afterFindListener\n * @param {string} name The `name` argument received by {@link Mapper#afterFind}.\n * @param {string|number} id The `id` argument received by {@link Mapper#afterFind}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterFind}.\n * @param {object} result The `result` argument received by {@link Mapper#afterFind}.\n * @see SimpleStore#event:afterFind\n * @see SimpleStore#find\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#find}. Adds any found record to the store.\n *\n * @example\n * import { SimpleStore } from 'js-data';\n * import { HttpAdapter } from 'js-data-http';\n *\n * const store = new SimpleStore();\n * store.registerAdapter('http', new HttpAdapter(), { default: true });\n *\n * store.defineMapper('book');\n *\n * // Since this example uses the http adapter, we'll get something like:\n * //\n * // GET /book/1234\n * store.find('book', 1234).then((book) => {\n * // The book record is now in the in-memory store\n * console.log(store.get('book', 1234) === book); // true\n * });\n *\n * @fires SimpleStore#beforeFind\n * @fires SimpleStore#afterFind\n * @fires SimpleStore#add\n * @method SimpleStore#find\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {(string|number)} id Passed to {@link Mapper#find}.\n * @param {object} [opts] Passed to {@link Mapper#find}.\n * @param {boolean} [opts.force] Bypass cacheFind\n * @param {boolean|Function} [opts.usePendingFind] See {@link SimpleStore#usePendingFind}\n * @returns {Promise} Resolves with the result, if any.\n * @since 3.0.0\n */\n find (name, id, opts) {\n opts || (opts = {})\n const mapper = this.getMapper(name)\n const pendingQuery = this._pendingQueries[name][id]\n const usePendingFind = opts.usePendingFind === undefined ? this.usePendingFind : opts.usePendingFind\n utils._(opts, mapper)\n\n if (pendingQuery && (utils.isFunction(usePendingFind) ? usePendingFind.call(this, name, id, opts) : usePendingFind)) {\n return pendingQuery\n }\n const item = this.cachedFind(name, id, opts)\n\n if (opts.force || !item) {\n const promise = this._pendingQueries[name][id] = Container.prototype.find.call(this, name, id, opts)\n return promise\n .then((result) => {\n delete this._pendingQueries[name][id]\n result = this._end(name, result, opts)\n this.cacheFind(name, result, id, opts)\n return result\n }, (err) => {\n delete this._pendingQueries[name][id]\n return utils.reject(err)\n })\n }\n\n return utils.resolve(item)\n },\n\n /**\n * Fired during {@link SimpleStore#findAll}. See\n * {@link SimpleStore~beforeFindAllListener} for how to listen for this event.\n *\n * @event SimpleStore#beforeFindAll\n * @see SimpleStore~beforeFindAllListener\n * @see SimpleStore#findAll\n */\n /**\n * Callback signature for the {@link SimpleStore#event:beforeFindAll} event.\n *\n * @example\n * function onBeforeFindAll (mapperName, query, opts) {\n * // do something\n * }\n * store.on('beforeFindAll', onBeforeFindAll);\n *\n * @callback SimpleStore~beforeFindAllListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeFindAll}.\n * @param {object} query The `query` argument received by {@link Mapper#beforeFindAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeFindAll}.\n * @see SimpleStore#event:beforeFindAll\n * @see SimpleStore#findAll\n * @since 3.0.0\n */\n /**\n * Fired during {@link SimpleStore#findAll}. See\n * {@link SimpleStore~afterFindAllListener} for how to listen for this event.\n *\n * @event SimpleStore#afterFindAll\n * @see SimpleStore~afterFindAllListener\n * @see SimpleStore#findAll\n */\n /**\n * Callback signature for the {@link SimpleStore#event:afterFindAll} event.\n *\n * @example\n * function onAfterFindAll (mapperName, query, opts, result) {\n * // do something\n * }\n * store.on('afterFindAll', onAfterFindAll);\n *\n * @callback SimpleStore~afterFindAllListener\n * @param {string} name The `name` argument received by {@link Mapper#afterFindAll}.\n * @param {object} query The `query` argument received by {@link Mapper#afterFindAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterFindAll}.\n * @param {object} result The `result` argument received by {@link Mapper#afterFindAll}.\n * @see SimpleStore#event:afterFindAll\n * @see SimpleStore#findAll\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#findAll}. Adds any found records to the store.\n *\n * @example\n * import { SimpleStore } from 'js-data';\n * import { HttpAdapter } from 'js-data-http';\n *\n * const store = new SimpleStore();\n * store.registerAdapter('http', new HttpAdapter(), { default: true });\n *\n * store.defineMapper('movie');\n *\n * // Since this example uses the http adapter, we'll get something like:\n * //\n * // GET /movie?rating=PG\n * store.find('movie', { rating: 'PG' }).then((movies) => {\n * // The movie records are now in the in-memory store\n * console.log(store.filter('movie'));\n * });\n *\n * @fires SimpleStore#beforeFindAll\n * @fires SimpleStore#afterFindAll\n * @fires SimpleStore#add\n * @method SimpleStore#findAll\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {object} [query] Passed to {@link Mapper.findAll}.\n * @param {object} [opts] Passed to {@link Mapper.findAll}.\n * @param {boolean} [opts.force] Bypass cacheFindAll\n * @param {boolean|Function} [opts.usePendingFindAll] See {@link SimpleStore#usePendingFindAll}\n * @returns {Promise} Resolves with the result, if any.\n * @since 3.0.0\n */\n findAll (name, query, opts) {\n opts || (opts = {})\n const mapper = this.getMapper(name)\n const hash = this.hashQuery(name, query, opts)\n const pendingQuery = this._pendingQueries[name][hash]\n const usePendingFindAll = opts.usePendingFindAll === undefined ? this.usePendingFindAll : opts.usePendingFindAll\n utils._(opts, mapper)\n\n if (pendingQuery && (utils.isFunction(usePendingFindAll) ? usePendingFindAll.call(this, name, query, opts) : usePendingFindAll)) {\n return pendingQuery\n }\n\n const items = this.cachedFindAll(name, hash, opts)\n\n if (opts.force || !items) {\n const promise = this._pendingQueries[name][hash] = Container.prototype.findAll.call(this, name, query, opts)\n return promise\n .then((result) => {\n delete this._pendingQueries[name][hash]\n result = this._end(name, result, opts)\n this.cacheFindAll(name, result, hash, opts)\n return result\n }, (err) => {\n delete this._pendingQueries[name][hash]\n return utils.reject(err)\n })\n }\n\n return utils.resolve(items)\n },\n\n /**\n * Return the {@link Collection} with the given name, if for some\n * reason you need a direct reference to the collection.\n *\n * @method SimpleStore#getCollection\n * @param {string} name Name of the {@link Collection} to retrieve.\n * @returns {Collection}\n * @since 3.0.0\n * @throws {Error} Thrown if the specified {@link Collection} does not\n * exist.\n */\n getCollection (name) {\n const collection = this._collections[name]\n if (!collection) {\n throw utils.err(`${DOMAIN}#getCollection`, name)(404, 'collection')\n }\n return collection\n },\n\n /**\n * Hashing function used to cache {@link SimpleStore#find} and\n * {@link SimpleStore#findAll} requests. This method simply JSONifies the\n * `query` argument passed to {@link SimpleStore#find} or\n * {@link SimpleStore#findAll}.\n *\n * Override this method for custom hashing behavior.\n * @method SimpleStore#hashQuery\n * @param {string} name The `name` argument passed to {@link SimpleStore#find}\n * or {@link SimpleStore#findAll}.\n * @param {object} query The `query` argument passed to {@link SimpleStore#find}\n * or {@link SimpleStore#findAll}.\n * @returns {string} The JSONified `query`.\n * @since 3.0.0\n */\n hashQuery (name, query, opts) {\n return utils.toJson(query || {})\n },\n\n inject (name, records, opts) {\n console.warn('DEPRECATED: \"inject\" is deprecated, use \"add\" instead')\n return this.add(name, records, opts)\n },\n\n /**\n * Wrapper for {@link Collection#remove}. Removes the specified\n * {@link Record} from the store.\n *\n * @example SimpleStore#remove\n * const JSData = require('js-data');\n * const { SimpleStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new SimpleStore();\n * store.defineMapper('book');\n * console.log(store.getAll('book').length);\n * store.add('book', { id: 1234 });\n * console.log(store.getAll('book').length);\n * store.remove('book', 1234);\n * console.log(store.getAll('book').length);\n *\n * @fires SimpleStore#remove\n * @method SimpleStore#remove\n * @param {string} name The name of the {@link Collection} to target.\n * @param {string|number} id The primary key of the {@link Record} to remove.\n * @param {object} [opts] Configuration options.\n * @param {string[]} [opts.with] Relations of the {@link Record} to also\n * remove from the store.\n * @returns {Record} The removed {@link Record}, if any.\n * @see Collection#add\n * @see Collection#add\n * @since 3.0.0\n */\n remove (name, id, opts) {\n const record = this.getCollection(name).remove(id, opts)\n if (record) {\n this.removeRelated(name, [record], opts)\n }\n return record\n },\n\n /**\n * Wrapper for {@link Collection#removeAll}. Removes the selected\n * {@link Record}s from the store.\n *\n * @example SimpleStore#removeAll\n * const JSData = require('js-data');\n * const { SimpleStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new SimpleStore();\n * store.defineMapper('movie');\n * console.log(store.getAll('movie').length);\n * store.add('movie', [{ id: 3, rating: 'R' }, { id: 4, rating: 'PG-13' });\n * console.log(store.getAll('movie').length);\n * store.removeAll('movie', { rating: 'R' });\n * console.log(store.getAll('movie').length);\n *\n * @fires SimpleStore#remove\n * @method SimpleStore#removeAll\n * @param {string} name The name of the {@link Collection} to target.\n * @param {object} [query={}] Selection query. See {@link query}.\n * @param {object} [query.where] See {@link query.where}.\n * @param {number} [query.offset] See {@link query.offset}.\n * @param {number} [query.limit] See {@link query.limit}.\n * @param {string|Array[]} [query.orderBy] See {@link query.orderBy}.\n * @param {object} [opts] Configuration options.\n * @param {string[]} [opts.with] Relations of the {@link Record} to also\n * remove from the store.\n * @returns {Record} The removed {@link Record}s, if any.\n * @see Collection#add\n * @see Collection#add\n * @since 3.0.0\n */\n removeAll (name, query, opts) {\n if (!query || !Object.keys(query).length) {\n this._completedQueries[name] = {}\n } else {\n this._completedQueries[name][this.hashQuery(name, query, opts)] = undefined\n }\n const records = this.getCollection(name).removeAll(query, opts)\n if (records.length) {\n this.removeRelated(name, records, opts)\n }\n return records\n },\n\n /**\n * Remove from the store {@link Record}s that are related to the provided\n * {@link Record}(s).\n *\n * @fires SimpleStore#remove\n * @method SimpleStore#removeRelated\n * @param {string} name The name of the {@link Collection} to target.\n * @param {Record|Record[]} records {@link Record}s whose relations are to be\n * removed.\n * @param {object} [opts] Configuration options.\n * @param {string[]} [opts.with] Relations of the {@link Record}(s) to remove\n * from the store.\n * @since 3.0.0\n */\n removeRelated (name, records, opts) {\n if (!utils.isArray(records)) {\n records = [records]\n }\n utils.forEachRelation(this.getMapper(name), opts, (def, optsCopy) => {\n records.forEach((record) => {\n let relatedData\n let query\n if (def.foreignKey && (def.type === hasOneType || def.type === hasManyType)) {\n query = { [def.foreignKey]: def.getForeignKey(record) }\n } else if (def.type === hasManyType && def.localKeys) {\n query = {\n where: {\n [def.getRelation().idAttribute]: {\n in: utils.get(record, def.localKeys)\n }\n }\n }\n } else if (def.type === hasManyType && def.foreignKeys) {\n query = {\n where: {\n [def.foreignKeys]: {\n contains: def.getForeignKey(record)\n }\n }\n }\n } else if (def.type === belongsToType) {\n relatedData = this.remove(def.relation, def.getForeignKey(record), optsCopy)\n }\n if (query) {\n relatedData = this.removeAll(def.relation, query, optsCopy)\n }\n if (relatedData) {\n if (utils.isArray(relatedData) && !relatedData.length) {\n return\n }\n if (def.type === hasOneType) {\n relatedData = relatedData[0]\n }\n def.setLocalField(record, relatedData)\n }\n })\n })\n },\n\n /**\n * Fired during {@link SimpleStore#update}. See\n * {@link SimpleStore~beforeUpdateListener} for how to listen for this event.\n *\n * @event SimpleStore#beforeUpdate\n * @see SimpleStore~beforeUpdateListener\n * @see SimpleStore#update\n */\n /**\n * Callback signature for the {@link SimpleStore#event:beforeUpdate} event.\n *\n * @example\n * function onBeforeUpdate (mapperName, id, props, opts) {\n * // do something\n * }\n * store.on('beforeUpdate', onBeforeUpdate);\n *\n * @callback SimpleStore~beforeUpdateListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeUpdate}.\n * @param {string|number} id The `id` argument received by {@link Mapper#beforeUpdate}.\n * @param {object} props The `props` argument received by {@link Mapper#beforeUpdate}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdate}.\n * @see SimpleStore#event:beforeUpdate\n * @see SimpleStore#update\n * @since 3.0.0\n */\n /**\n * Fired during {@link SimpleStore#update}. See\n * {@link SimpleStore~afterUpdateListener} for how to listen for this event.\n *\n * @event SimpleStore#afterUpdate\n * @see SimpleStore~afterUpdateListener\n * @see SimpleStore#update\n */\n /**\n * Callback signature for the {@link SimpleStore#event:afterUpdate} event.\n *\n * @example\n * function onAfterUpdate (mapperName, id, props, opts, result) {\n * // do something\n * }\n * store.on('afterUpdate', onAfterUpdate);\n *\n * @callback SimpleStore~afterUpdateListener\n * @param {string} name The `name` argument received by {@link Mapper#afterUpdate}.\n * @param {string|number} id The `id` argument received by {@link Mapper#afterUpdate}.\n * @param {object} props The `props` argument received by {@link Mapper#afterUpdate}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdate}.\n * @param {object} result The `result` argument received by {@link Mapper#afterUpdate}.\n * @see SimpleStore#event:afterUpdate\n * @see SimpleStore#update\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#update}. Adds the updated {@link Record} to the\n * store.\n *\n * @example\n * import { SimpleStore } from 'js-data';\n * import { HttpAdapter } from 'js-data-http';\n *\n * const store = new SimpleStore();\n * store.registerAdapter('http', new HttpAdapter(), { default: true });\n *\n * store.defineMapper('post');\n *\n * // Since this example uses the http adapter, we'll get something like:\n * //\n * // PUT /post/1234 {\"status\":\"published\"}\n * store.update('post', 1, { status: 'published' }).then((post) => {\n * // The post record has also been updated in the in-memory store\n * console.log(store.get('post', 1234));\n * });\n *\n * @fires SimpleStore#beforeUpdate\n * @fires SimpleStore#afterUpdate\n * @fires SimpleStore#add\n * @method SimpleStore#update\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {(string|number)} id Passed to {@link Mapper#update}.\n * @param {object} record Passed to {@link Mapper#update}.\n * @param {object} [opts] Passed to {@link Mapper#update}. See\n * {@link Mapper#update} for more configuration options.\n * @returns {Promise} Resolves with the result of the update.\n * @since 3.0.0\n */\n update (name, id, record, opts) {\n opts || (opts = {})\n return Container.prototype.update.call(this, name, id, record, opts)\n .then((result) => this._end(name, result, opts))\n },\n\n /**\n * Fired during {@link SimpleStore#updateAll}. See\n * {@link SimpleStore~beforeUpdateAllListener} for how to listen for this event.\n *\n * @event SimpleStore#beforeUpdateAll\n * @see SimpleStore~beforeUpdateAllListener\n * @see SimpleStore#updateAll\n */\n /**\n * Callback signature for the {@link SimpleStore#event:beforeUpdateAll} event.\n *\n * @example\n * function onBeforeUpdateAll (mapperName, props, query, opts) {\n * // do something\n * }\n * store.on('beforeUpdateAll', onBeforeUpdateAll);\n *\n * @callback SimpleStore~beforeUpdateAllListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeUpdateAll}.\n * @param {object} props The `props` argument received by {@link Mapper#beforeUpdateAll}.\n * @param {object} query The `query` argument received by {@link Mapper#beforeUpdateAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdateAll}.\n * @see SimpleStore#event:beforeUpdateAll\n * @see SimpleStore#updateAll\n * @since 3.0.0\n */\n /**\n * Fired during {@link SimpleStore#updateAll}. See\n * {@link SimpleStore~afterUpdateAllListener} for how to listen for this event.\n *\n * @event SimpleStore#afterUpdateAll\n * @see SimpleStore~afterUpdateAllListener\n * @see SimpleStore#updateAll\n */\n /**\n * Callback signature for the {@link SimpleStore#event:afterUpdateAll} event.\n *\n * @example\n * function onAfterUpdateAll (mapperName, props, query, opts, result) {\n * // do something\n * }\n * store.on('afterUpdateAll', onAfterUpdateAll);\n *\n * @callback SimpleStore~afterUpdateAllListener\n * @param {string} name The `name` argument received by {@link Mapper#afterUpdateAll}.\n * @param {object} props The `props` argument received by {@link Mapper#afterUpdateAll}.\n * @param {object} query The `query` argument received by {@link Mapper#afterUpdateAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdateAll}.\n * @param {object} result The `result` argument received by {@link Mapper#afterUpdateAll}.\n * @see SimpleStore#event:afterUpdateAll\n * @see SimpleStore#updateAll\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#updateAll}. Adds the updated {@link Record}s to\n * the store.\n *\n * @example\n * import { SimpleStore } from 'js-data';\n * import { HttpAdapter } from 'js-data-http';\n *\n * const store = new SimpleStore();\n * store.registerAdapter('http', new HttpAdapter(), { default: true });\n *\n * store.defineMapper('post');\n *\n * // Since this example uses the http adapter, we'll get something like:\n * //\n * // PUT /post?author_id=1234 {\"status\":\"published\"}\n * store.updateAll('post', { author_id: 1234 }, { status: 'published' }).then((posts) => {\n * // The post records have also been updated in the in-memory store\n * console.log(store.filter('posts', { author_id: 1234 }));\n * });\n *\n * @fires SimpleStore#beforeUpdateAll\n * @fires SimpleStore#afterUpdateAll\n * @fires SimpleStore#add\n * @method SimpleStore#updateAll\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {object} props Passed to {@link Mapper#updateAll}.\n * @param {object} [query] Passed to {@link Mapper#updateAll}.\n * @param {object} [opts] Passed to {@link Mapper#updateAll}. See\n * {@link Mapper#updateAll} for more configuration options.\n * @returns {Promise} Resolves with the result of the update.\n * @since 3.0.0\n */\n updateAll (name, props, query, opts) {\n opts || (opts = {})\n return Container.prototype.updateAll.call(this, name, props, query, opts)\n .then((result) => this._end(name, result, opts))\n },\n\n /**\n * Fired during {@link SimpleStore#updateMany}. See\n * {@link SimpleStore~beforeUpdateManyListener} for how to listen for this event.\n *\n * @event SimpleStore#beforeUpdateMany\n * @see SimpleStore~beforeUpdateManyListener\n * @see SimpleStore#updateMany\n */\n /**\n * Callback signature for the {@link SimpleStore#event:beforeUpdateMany} event.\n *\n * @example\n * function onBeforeUpdateMany (mapperName, records, opts) {\n * // do something\n * }\n * store.on('beforeUpdateMany', onBeforeUpdateMany);\n *\n * @callback SimpleStore~beforeUpdateManyListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeUpdateMany}.\n * @param {object} records The `records` argument received by {@link Mapper#beforeUpdateMany}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdateMany}.\n * @see SimpleStore#event:beforeUpdateMany\n * @see SimpleStore#updateMany\n * @since 3.0.0\n */\n /**\n * Fired during {@link SimpleStore#updateMany}. See\n * {@link SimpleStore~afterUpdateManyListener} for how to listen for this event.\n *\n * @event SimpleStore#afterUpdateMany\n * @see SimpleStore~afterUpdateManyListener\n * @see SimpleStore#updateMany\n */\n /**\n * Callback signature for the {@link SimpleStore#event:afterUpdateMany} event.\n *\n * @example\n * function onAfterUpdateMany (mapperName, records, opts, result) {\n * // do something\n * }\n * store.on('afterUpdateMany', onAfterUpdateMany);\n *\n * @callback SimpleStore~afterUpdateManyListener\n * @param {string} name The `name` argument received by {@link Mapper#afterUpdateMany}.\n * @param {object} records The `records` argument received by {@link Mapper#afterUpdateMany}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdateMany}.\n * @param {object} result The `result` argument received by {@link Mapper#afterUpdateMany}.\n * @see SimpleStore#event:afterUpdateMany\n * @see SimpleStore#updateMany\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#updateMany}. Adds the updated {@link Record}s to\n * the store.\n *\n * @example\n * import { SimpleStore } from 'js-data';\n * import { HttpAdapter } from 'js-data-http';\n *\n * const store = new SimpleStore();\n * store.registerAdapter('http', new HttpAdapter(), { default: true });\n *\n * store.defineMapper('post');\n *\n * // Since this example uses the http adapter, we'll get something like:\n * //\n * // PUT /post [{\"id\":3,status\":\"published\"},{\"id\":4,status\":\"published\"}]\n * store.updateMany('post', [\n * { id: 3, status: 'published' },\n * { id: 4, status: 'published' }\n * ]).then((posts) => {\n * // The post records have also been updated in the in-memory store\n * console.log(store.getAll('post', 3, 4));\n * });\n *\n * @fires SimpleStore#beforeUpdateMany\n * @fires SimpleStore#afterUpdateMany\n * @fires SimpleStore#add\n * @method SimpleStore#updateMany\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {(Object[]|Record[])} records Passed to {@link Mapper#updateMany}.\n * @param {object} [opts] Passed to {@link Mapper#updateMany}. See\n * {@link Mapper#updateMany} for more configuration options.\n * @returns {Promise} Resolves with the result of the update.\n * @since 3.0.0\n */\n updateMany (name, records, opts) {\n opts || (opts = {})\n return Container.prototype.updateMany.call(this, name, records, opts)\n .then((result) => this._end(name, result, opts))\n }\n}\n\nproxiedCollectionMethods.forEach(function (method) {\n props[method] = function (name, ...args) {\n return this.getCollection(name)[method](...args)\n }\n})\n\nexport default Container.extend(props)\n\n/**\n * Fired when a record changes. Only works for records that have tracked fields.\n * See {@link SimpleStore~changeListener} on how to listen for this event.\n *\n * @event SimpleStore#change\n * @see SimpleStore~changeListener\n */\n\n/**\n * Callback signature for the {@link SimpleStore#event:change} event.\n *\n * @example\n * function onChange (mapperName, record, changes) {\n * // do something\n * }\n * store.on('change', onChange);\n *\n * @callback SimpleStore~changeListener\n * @param {string} name The name of the associated {@link Mapper}.\n * @param {Record} record The Record that changed.\n * @param {object} changes The changes.\n * @see SimpleStore#event:change\n * @since 3.0.0\n */\n\n/**\n * Fired when one or more records are added to the in-memory store. See\n * {@link SimpleStore~addListener} on how to listen for this event.\n *\n * @event SimpleStore#add\n * @see SimpleStore~addListener\n * @see SimpleStore#event:add\n * @see SimpleStore#add\n * @see SimpleStore#create\n * @see SimpleStore#createMany\n * @see SimpleStore#find\n * @see SimpleStore#findAll\n * @see SimpleStore#update\n * @see SimpleStore#updateAll\n * @see SimpleStore#updateMany\n */\n\n/**\n * Callback signature for the {@link SimpleStore#event:add} event.\n *\n * @example\n * function onAdd (mapperName, recordOrRecords) {\n * // do something\n * }\n * store.on('add', onAdd);\n *\n * @callback SimpleStore~addListener\n * @param {string} name The name of the associated {@link Mapper}.\n * @param {Record|Record[]} The Record or Records that were added.\n * @see SimpleStore#event:add\n * @see SimpleStore#add\n * @see SimpleStore#create\n * @see SimpleStore#createMany\n * @see SimpleStore#find\n * @see SimpleStore#findAll\n * @see SimpleStore#update\n * @see SimpleStore#updateAll\n * @see SimpleStore#updateMany\n * @since 3.0.0\n */\n\n/**\n * Fired when one or more records are removed from the in-memory store. See\n * {@link SimpleStore~removeListener} for how to listen for this event.\n *\n * @event SimpleStore#remove\n * @see SimpleStore~removeListener\n * @see SimpleStore#event:remove\n * @see SimpleStore#clear\n * @see SimpleStore#destroy\n * @see SimpleStore#destroyAll\n * @see SimpleStore#remove\n * @see SimpleStore#removeAll\n */\n\n/**\n * Callback signature for the {@link SimpleStore#event:remove} event.\n *\n * @example\n * function onRemove (mapperName, recordsOrRecords) {\n * // do something\n * }\n * store.on('remove', onRemove);\n *\n * @callback SimpleStore~removeListener\n * @param {string} name The name of the associated {@link Mapper}.\n * @param {Record|Record[]} Record or Records that were removed.\n * @see SimpleStore#event:remove\n * @see SimpleStore#clear\n * @see SimpleStore#destroy\n * @see SimpleStore#destroyAll\n * @see SimpleStore#remove\n * @see SimpleStore#removeAll\n * @since 3.0.0\n */\n\n/**\n * Create a subclass of this SimpleStore:\n * @example SimpleStore.extend\n * const JSData = require('js-data');\n * const { SimpleStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * // Extend the class using ES2015 class syntax.\n * class CustomSimpleStoreClass extends SimpleStore {\n * foo () { return 'bar'; }\n * static beep () { return 'boop'; }\n * }\n * const customSimpleStore = new CustomSimpleStoreClass();\n * console.log(customSimpleStore.foo());\n * console.log(CustomSimpleStoreClass.beep());\n *\n * // Extend the class using alternate method.\n * const OtherSimpleStoreClass = SimpleStore.extend({\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * })\n * const otherSimpleStore = new OtherSimpleStoreClass();\n * console.log(otherSimpleStore.foo());\n * console.log(OtherSimpleStoreClass.beep());\n *\n * // Extend the class, providing a custom constructor.\n * function AnotherSimpleStoreClass () {\n * SimpleStore.call(this)\n * this.created_at = new Date().getTime()\n * }\n * SimpleStore.extend({\n * constructor: AnotherSimpleStoreClass,\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * })\n * const anotherSimpleStore = new AnotherSimpleStoreClass();\n * console.log(anotherSimpleStore.created_at);\n * console.log(anotherSimpleStore.foo());\n * console.log(AnotherSimpleStoreClass.beep());\n *\n * @method SimpleStore.extend\n * @param {object} [props={}] Properties to add to the prototype of the\n * subclass.\n * @param {object} [props.constructor] Provide a custom constructor function\n * to be used as the subclass itself.\n * @param {object} [classProps={}] Static properties to add to the subclass.\n * @returns {Constructor} Subclass of this SimpleStore class.\n * @since 3.0.0\n */\n","import utils from './utils'\nimport './decorators'\nimport Collection from './Collection'\n\nconst DOMAIN = 'LinkedCollection'\n\n/**\n * Extends {@link Collection}. Used by a {@link DataStore} to implement an\n * Identity Map.\n *\n * ```javascript\n * import {LinkedCollection} from 'js-data'\n * ```\n *\n * @class LinkedCollection\n * @extends Collection\n * @param {array} [records] Initial set of records to insert into the\n * collection. See {@link Collection}.\n * @param {object} [opts] Configuration options. See {@link Collection}.\n * @returns {Mapper}\n */\nfunction LinkedCollection (records, opts) {\n utils.classCallCheck(this, LinkedCollection)\n // Make sure this collection has somewhere to store \"added\" timestamps\n Object.defineProperties(this, {\n _added: {\n value: {}\n },\n datastore: {\n writable: true,\n value: undefined\n }\n })\n\n Collection.call(this, records, opts)\n\n // Make sure this collection has a reference to a datastore\n if (!this.datastore) {\n throw utils.err(`new ${DOMAIN}`, 'opts.datastore')(400, 'DataStore', this.datastore)\n }\n}\n\nexport default Collection.extend({\n constructor: LinkedCollection,\n\n _addMeta (record, timestamp) {\n // Track when this record was added\n this._added[this.recordId(record)] = timestamp\n\n if (utils.isFunction(record._set)) {\n record._set('$', timestamp)\n }\n },\n\n _clearMeta (record) {\n delete this._added[this.recordId(record)]\n if (utils.isFunction(record._set)) {\n record._set('$') // unset\n }\n },\n\n _onRecordEvent (...args) {\n Collection.prototype._onRecordEvent.apply(this, args)\n const event = args[0]\n // This is a very brute force method\n // Lots of room for optimization\n if (utils.isString(event) && event.indexOf('change') === 0) {\n this.updateIndexes(args[1])\n }\n },\n\n add (records, opts) {\n const mapper = this.mapper\n const timestamp = new Date().getTime()\n const singular = utils.isObject(records) && !utils.isArray(records)\n\n if (singular) {\n records = [records]\n }\n records = Collection.prototype.add.call(this, records, opts)\n\n if (mapper.relationList.length && records.length) {\n // Check the currently visited record for relations that need to be\n // inserted into their respective collections.\n mapper.relationList.forEach(function (def) {\n def.addLinkedRecords(records)\n })\n }\n\n records.forEach((record) => this._addMeta(record, timestamp))\n\n return singular ? records[0] : records\n },\n\n remove (idOrRecord, opts) {\n const mapper = this.mapper\n const record = Collection.prototype.remove.call(this, idOrRecord, opts)\n if (record) {\n this._clearMeta(record)\n }\n\n if (mapper.relationList.length && record) {\n mapper.relationList.forEach(function (def) {\n def.removeLinkedRecords(mapper, [record])\n })\n }\n\n return record\n },\n\n removeAll (query, opts) {\n const mapper = this.mapper\n const records = Collection.prototype.removeAll.call(this, query, opts)\n records.forEach(this._clearMeta, this)\n\n if (mapper.relationList.length && records.length) {\n mapper.relationList.forEach(function (def) {\n def.removeLinkedRecords(mapper, records)\n })\n }\n\n return records\n }\n})\n\n/**\n * Create a subclass of this LinkedCollection:\n *\n * @example LinkedCollection.extend\n * const JSData = require('js-data');\n * const { LinkedCollection } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * // Extend the class using ES2015 class syntax.\n * class CustomLinkedCollectionClass extends LinkedCollection {\n * foo () { return 'bar'; }\n * static beep () { return 'boop'; }\n * }\n * const customLinkedCollection = new CustomLinkedCollectionClass();\n * console.log(customLinkedCollection.foo());\n * console.log(CustomLinkedCollectionClass.beep());\n *\n * // Extend the class using alternate method.\n * const OtherLinkedCollectionClass = LinkedCollection.extend({\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * });\n * const otherLinkedCollection = new OtherLinkedCollectionClass();\n * console.log(otherLinkedCollection.foo());\n * console.log(OtherLinkedCollectionClass.beep());\n *\n * // Extend the class, providing a custom constructor.\n * function AnotherLinkedCollectionClass () {\n * LinkedCollection.call(this);\n * this.created_at = new Date().getTime();\n * }\n * LinkedCollection.extend({\n * constructor: AnotherLinkedCollectionClass,\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * });\n * const anotherLinkedCollection = new AnotherLinkedCollectionClass();\n * console.log(anotherLinkedCollection.created_at);\n * console.log(anotherLinkedCollection.foo());\n * console.log(AnotherLinkedCollectionClass.beep());\n *\n * @method LinkedCollection.extend\n * @param {object} [props={}] Properties to add to the prototype of the\n * subclass.\n * @param {object} [props.constructor] Provide a custom constructor function\n * to be used as the subclass itself.\n * @param {object} [classProps={}] Static properties to add to the subclass.\n * @returns {Constructor} Subclass of this LinkedCollection class.\n * @since 3.0.0\n */\n","import utils, { safeSetLink, safeSetProp } from './utils'\n\nimport {\n belongsToType,\n hasManyType,\n hasOneType\n} from './decorators'\nimport SimpleStore from './SimpleStore'\nimport LinkedCollection from './LinkedCollection'\n\nconst DATASTORE_DEFAULTS = {\n /**\n * Whether in-memory relations should be unlinked from records after they are\n * destroyed.\n *\n * @default true\n * @name DataStore#unlinkOnDestroy\n * @since 3.0.0\n * @type {boolean}\n */\n unlinkOnDestroy: true\n}\n\n/**\n * The `DataStore` class is an extension of {@link SimpleStore}. Not only does\n * `DataStore` manage mappers and store data in collections, it uses the\n * {@link LinkedCollection} class to link related records together in memory.\n *\n * ```javascript\n * import { DataStore } from 'js-data';\n * ```\n *\n * @example\n * import { DataStore } from 'js-data';\n * import HttpAdapter from 'js-data-http';\n * const store = new DataStore();\n *\n * // DataStore#defineMapper returns a direct reference to the newly created\n * // Mapper.\n * const UserMapper = store.defineMapper('user');\n *\n * // DataStore#as returns the store scoped to a particular Mapper.\n * const UserStore = store.as('user');\n *\n * // Call \"find\" on \"UserMapper\" (Stateless ORM)\n * UserMapper.find(1).then((user) => {\n * // retrieved a \"user\" record via the http adapter, but that's it\n *\n * // Call \"find\" on \"store\" targeting \"user\" (Stateful DataStore)\n * return store.find('user', 1); // same as \"UserStore.find(1)\"\n * }).then((user) => {\n * // not only was a \"user\" record retrieved, but it was added to the\n * // store's \"user\" collection\n * const cachedUser = store.getCollection('user').get(1);\n * console.log(user === cachedUser); // true\n * });\n *\n * @class DataStore\n * @extends SimpleStore\n * @param {object} [opts] Configuration options. See {@link SimpleStore}.\n * @param {boolean} [opts.collectionClass={@link LinkedCollection}] See {@link DataStore#collectionClass}.\n * @param {boolean} [opts.debug=false] See {@link Component#debug}.\n * @param {boolean} [opts.unlinkOnDestroy=true] See {@link DataStore#unlinkOnDestroy}.\n * @param {boolean|Function} [opts.usePendingFind=true] See {@link DataStore#usePendingFind}.\n * @param {boolean|Function} [opts.usePendingFindAll=true] See {@link DataStore#usePendingFindAll}.\n * @returns {DataStore}\n * @see SimpleStore\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/components-of-jsdata#datastore\",\"Components of JSData: DataStore\"]\n * @tutorial [\"http://www.js-data.io/v3.0/docs/working-with-the-datastore\",\"Working with the DataStore\"]\n * @tutorial [\"http://www.js-data.io/v3.0/docs/jsdata-and-the-browser\",\"Notes on using JSData in the Browser\"]\n */\nfunction DataStore (opts) {\n utils.classCallCheck(this, DataStore)\n\n opts || (opts = {})\n // Fill in any missing options with the defaults\n utils.fillIn(opts, DATASTORE_DEFAULTS)\n opts.collectionClass || (opts.collectionClass = LinkedCollection)\n SimpleStore.call(this, opts)\n}\n\nconst props = {\n constructor: DataStore,\n\n defineMapper (name, opts) {\n // Complexity of this method is beyond simply using => functions to bind context\n const self = this\n const mapper = SimpleStore.prototype.defineMapper.call(self, name, opts)\n const idAttribute = mapper.idAttribute\n const collection = this.getCollection(name)\n\n mapper.relationList.forEach(function (def) {\n const relation = def.relation\n const localField = def.localField\n const path = `links.${localField}`\n const foreignKey = def.foreignKey\n const type = def.type\n const updateOpts = { index: foreignKey }\n let descriptor\n\n const getter = function () { return this._get(path) }\n\n if (type === belongsToType) {\n if (!collection.indexes[foreignKey]) {\n collection.createIndex(foreignKey)\n }\n\n descriptor = {\n get: getter,\n // e.g. profile.user = someUser\n // or comment.post = somePost\n set (record) {\n // e.g. const otherUser = profile.user\n const currentParent = this._get(path)\n // e.g. profile.user === someUser\n if (record === currentParent) {\n return currentParent\n }\n const id = utils.get(this, idAttribute)\n const inverseDef = def.getInverse(mapper)\n\n // e.g. profile.user !== someUser\n // or comment.post !== somePost\n if (currentParent && inverseDef) {\n this.removeInverseRelation(currentParent, id, inverseDef, idAttribute)\n }\n if (record) {\n // e.g. profile.user = someUser\n const relatedIdAttribute = def.getRelation().idAttribute\n const relatedId = utils.get(record, relatedIdAttribute)\n\n // Prefer store record\n if (relatedId !== undefined && this._get('$')) {\n record = self.get(relation, relatedId) || record\n }\n\n // Set locals\n // e.g. profile.user = someUser\n // or comment.post = somePost\n safeSetLink(this, localField, record)\n safeSetProp(this, foreignKey, relatedId)\n collection.updateIndex(this, updateOpts)\n\n if (inverseDef) {\n this.setupInverseRelation(record, id, inverseDef, idAttribute)\n }\n } else {\n // Unset in-memory link only\n // e.g. profile.user = undefined\n // or comment.post = undefined\n safeSetLink(this, localField, undefined)\n }\n return record\n }\n }\n\n let foreignKeyDescriptor = Object.getOwnPropertyDescriptor(mapper.recordClass.prototype, foreignKey)\n if (!foreignKeyDescriptor) {\n foreignKeyDescriptor = {\n enumerable: true\n }\n }\n const originalGet = foreignKeyDescriptor.get\n foreignKeyDescriptor.get = function () {\n if (originalGet) {\n return originalGet.call(this)\n }\n return this._get(`props.${foreignKey}`)\n }\n const originalSet = foreignKeyDescriptor.set\n foreignKeyDescriptor.set = function (value) {\n if (originalSet) {\n originalSet.call(this, value)\n }\n const currentParent = utils.get(this, localField)\n const id = utils.get(this, idAttribute)\n const inverseDef = def.getInverse(mapper)\n const currentParentId = currentParent ? utils.get(currentParent, def.getRelation().idAttribute) : undefined\n\n if (inverseDef && currentParent && currentParentId !== undefined && currentParentId !== value) {\n if (inverseDef.type === hasOneType) {\n safeSetLink(currentParent, inverseDef.localField, undefined)\n } else if (inverseDef.type === hasManyType) {\n const children = utils.get(currentParent, inverseDef.localField)\n if (id === undefined) {\n utils.remove(children, (child) => child === this)\n } else {\n utils.remove(children, (child) => child === this || id === utils.get(child, idAttribute))\n }\n }\n }\n\n safeSetProp(this, foreignKey, value)\n collection.updateIndex(this, updateOpts)\n\n if ((value === undefined || value === null)) {\n if (currentParentId !== undefined) {\n // Unset locals\n utils.set(this, localField, undefined)\n }\n } else if (this._get('$')) {\n const storeRecord = self.get(relation, value)\n if (storeRecord) {\n utils.set(this, localField, storeRecord)\n }\n }\n }\n Object.defineProperty(mapper.recordClass.prototype, foreignKey, foreignKeyDescriptor)\n } else if (type === hasManyType) {\n const localKeys = def.localKeys\n const foreignKeys = def.foreignKeys\n\n // TODO: Handle case when belongsTo relation isn't ever defined\n if (self._collections[relation] && foreignKey && !self.getCollection(relation).indexes[foreignKey]) {\n self.getCollection(relation).createIndex(foreignKey)\n }\n\n descriptor = {\n get () {\n const current = getter.call(this)\n if (!current) {\n this._set(path, [])\n }\n return getter.call(this)\n },\n // e.g. post.comments = someComments\n // or user.groups = someGroups\n // or group.users = someUsers\n set (records) {\n if (records && !utils.isArray(records)) {\n records = [records]\n }\n const id = utils.get(this, idAttribute)\n const relatedIdAttribute = def.getRelation().idAttribute\n const inverseDef = def.getInverse(mapper)\n const inverseLocalField = inverseDef.localField\n const current = this._get(path) || []\n const toLink = []\n const toLinkIds = {}\n\n if (records) {\n records.forEach((record) => {\n // e.g. comment.id\n const relatedId = utils.get(record, relatedIdAttribute)\n const currentParent = utils.get(record, inverseLocalField)\n if (currentParent && currentParent !== this) {\n const currentChildrenOfParent = utils.get(currentParent, localField)\n // e.g. somePost.comments.remove(comment)\n if (relatedId === undefined) {\n utils.remove(currentChildrenOfParent, (child) => child === record)\n } else {\n utils.remove(currentChildrenOfParent, (child) => child === record || relatedId === utils.get(child, relatedIdAttribute))\n }\n }\n if (relatedId !== undefined) {\n if (this._get('$')) {\n // Prefer store record\n record = self.get(relation, relatedId) || record\n }\n // e.g. toLinkIds[comment.id] = comment\n toLinkIds[relatedId] = record\n }\n toLink.push(record)\n })\n }\n\n // e.g. post.comments = someComments\n if (foreignKey) {\n current.forEach((record) => {\n // e.g. comment.id\n const relatedId = utils.get(record, relatedIdAttribute)\n if ((relatedId === undefined && toLink.indexOf(record) === -1) || (relatedId !== undefined && !(relatedId in toLinkIds))) {\n // Update (unset) inverse relation\n if (records) {\n // e.g. comment.post_id = undefined\n safeSetProp(record, foreignKey, undefined)\n // e.g. CommentCollection.updateIndex(comment, { index: 'post_id' })\n self.getCollection(relation).updateIndex(record, updateOpts)\n }\n // e.g. comment.post = undefined\n safeSetLink(record, inverseLocalField, undefined)\n }\n })\n toLink.forEach((record) => {\n // Update (set) inverse relation\n // e.g. comment.post_id = post.id\n safeSetProp(record, foreignKey, id)\n // e.g. CommentCollection.updateIndex(comment, { index: 'post_id' })\n self.getCollection(relation).updateIndex(record, updateOpts)\n // e.g. comment.post = post\n safeSetLink(record, inverseLocalField, this)\n })\n } else if (localKeys) {\n // Update locals\n // e.g. group.users = someUsers\n // Update (set) inverse relation\n const ids = toLink.map((child) => utils.get(child, relatedIdAttribute)).filter((id) => id !== undefined)\n // e.g. group.user_ids = [1,2,3,...]\n utils.set(this, localKeys, ids)\n // Update (unset) inverse relation\n if (inverseDef.foreignKeys) {\n current.forEach((child) => {\n const relatedId = utils.get(child, relatedIdAttribute)\n if ((relatedId === undefined && toLink.indexOf(child) === -1) || (relatedId !== undefined && !(relatedId in toLinkIds))) {\n // Update inverse relation\n // safeSetLink(child, inverseLocalField, undefined)\n const parents = utils.get(child, inverseLocalField) || []\n // e.g. someUser.groups.remove(group)\n if (id === undefined) {\n utils.remove(parents, (parent) => parent === this)\n } else {\n utils.remove(parents, (parent) => parent === this || id === utils.get(parent, idAttribute))\n }\n }\n })\n toLink.forEach((child) => {\n // Update (set) inverse relation\n const parents = utils.get(child, inverseLocalField)\n // e.g. someUser.groups.push(group)\n if (id === undefined) {\n utils.noDupeAdd(parents, this, (parent) => parent === this)\n } else {\n utils.noDupeAdd(parents, this, (parent) => parent === this || id === utils.get(parent, idAttribute))\n }\n })\n }\n } else if (foreignKeys) {\n // e.g. user.groups = someGroups\n // Update (unset) inverse relation\n current.forEach((parent) => {\n const ids = utils.get(parent, foreignKeys) || []\n // e.g. someGroup.user_ids.remove(user.id)\n utils.remove(ids, (_key) => id === _key)\n const children = utils.get(parent, inverseLocalField)\n // e.g. someGroup.users.remove(user)\n if (id === undefined) {\n utils.remove(children, (child) => child === this)\n } else {\n utils.remove(children, (child) => child === this || id === utils.get(child, idAttribute))\n }\n })\n // Update (set) inverse relation\n toLink.forEach((parent) => {\n const ids = utils.get(parent, foreignKeys) || []\n utils.noDupeAdd(ids, id, (_key) => id === _key)\n const children = utils.get(parent, inverseLocalField)\n if (id === undefined) {\n utils.noDupeAdd(children, this, (child) => child === this)\n } else {\n utils.noDupeAdd(children, this, (child) => child === this || id === utils.get(child, idAttribute))\n }\n })\n }\n\n this._set(path, toLink)\n return toLink\n }\n }\n } else if (type === hasOneType) {\n // TODO: Handle case when belongsTo relation isn't ever defined\n if (self._collections[relation] && foreignKey && !self.getCollection(relation).indexes[foreignKey]) {\n self.getCollection(relation).createIndex(foreignKey)\n }\n descriptor = {\n get: getter,\n // e.g. user.profile = someProfile\n set (record) {\n const current = this._get(path)\n if (record === current) {\n return current\n }\n const inverseLocalField = def.getInverse(mapper).localField\n // Update (unset) inverse relation\n if (current) {\n safeSetProp(current, foreignKey, undefined)\n self.getCollection(relation).updateIndex(current, updateOpts)\n safeSetLink(current, inverseLocalField, undefined)\n }\n if (record) {\n const relatedId = utils.get(record, def.getRelation().idAttribute)\n // Prefer store record\n if (relatedId !== undefined) {\n record = self.get(relation, relatedId) || record\n }\n\n // Set locals\n safeSetLink(this, localField, record)\n\n // Update (set) inverse relation\n safeSetProp(record, foreignKey, utils.get(this, idAttribute))\n self.getCollection(relation).updateIndex(record, updateOpts)\n safeSetLink(record, inverseLocalField, this)\n } else {\n // Unset locals\n safeSetLink(this, localField, undefined)\n }\n return record\n }\n }\n }\n\n if (descriptor) {\n descriptor.enumerable = def.enumerable === undefined ? false : def.enumerable\n if (def.get) {\n const origGet = descriptor.get\n descriptor.get = function () {\n return def.get(def, this, (...args) => origGet.apply(this, args))\n }\n }\n if (def.set) {\n const origSet = descriptor.set\n descriptor.set = function (related) {\n return def.set(def, this, related, (value) => origSet.call(this, value === undefined ? related : value))\n }\n }\n Object.defineProperty(mapper.recordClass.prototype, localField, descriptor)\n }\n })\n\n return mapper\n },\n\n destroy (name, id, opts) {\n opts || (opts = {})\n return SimpleStore.prototype.destroy.call(this, name, id, opts).then((result) => {\n let record\n if (opts.raw) {\n record = result.data\n } else {\n record = result\n }\n\n if (record && this.unlinkOnDestroy) {\n const _opts = utils.plainCopy(opts)\n _opts.withAll = true\n utils.forEachRelation(this.getMapper(name), _opts, (def) => {\n utils.set(record, def.localField, undefined)\n })\n }\n return result\n })\n },\n\n destroyAll (name, query, opts) {\n opts || (opts = {})\n return SimpleStore.prototype.destroyAll.call(this, name, query, opts).then((result) => {\n let records\n if (opts.raw) {\n records = result.data\n } else {\n records = result\n }\n\n if (records && records.length && this.unlinkOnDestroy) {\n const _opts = utils.plainCopy(opts)\n _opts.withAll = true\n utils.forEachRelation(this.getMapper(name), _opts, (def) => {\n records.forEach((record) => {\n utils.set(record, def.localField, undefined)\n })\n })\n }\n return result\n })\n }\n}\n\nexport default SimpleStore.extend(props)\n\n/**\n * Create a subclass of this DataStore:\n * @example DataStore.extend\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * // Extend the class using ES2015 class syntax.\n * class CustomDataStoreClass extends DataStore {\n * foo () { return 'bar'; }\n * static beep () { return 'boop'; }\n * }\n * const customDataStore = new CustomDataStoreClass();\n * console.log(customDataStore.foo());\n * console.log(CustomDataStoreClass.beep());\n *\n * // Extend the class using alternate method.\n * const OtherDataStoreClass = DataStore.extend({\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * });\n * const otherDataStore = new OtherDataStoreClass();\n * console.log(otherDataStore.foo());\n * console.log(OtherDataStoreClass.beep());\n *\n * // Extend the class, providing a custom constructor.\n * function AnotherDataStoreClass () {\n * DataStore.call(this);\n * this.created_at = new Date().getTime();\n * }\n * DataStore.extend({\n * constructor: AnotherDataStoreClass,\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * });\n * const anotherDataStore = new AnotherDataStoreClass();\n * console.log(anotherDataStore.created_at);\n * console.log(anotherDataStore.foo());\n * console.log(AnotherDataStoreClass.beep());\n *\n * @method DataStore.extend\n * @param {object} [props={}] Properties to add to the prototype of the\n * subclass.\n * @param {object} [props.constructor] Provide a custom constructor function\n * to be used as the subclass itself.\n * @param {object} [classProps={}] Static properties to add to the subclass.\n * @returns {Constructor} Subclass of this DataStore class.\n * @since 3.0.0\n */\n","/**\n * Registered as `js-data` in NPM and Bower.\n *\n * Also available from CDN.JS and JSDelivr.\n *\n * @module js-data\n *\n * @example Install from NPM\n * npm i --save js-data@beta\n * @example Install from Bower\n * bower i --save js-data@3.0.0-beta.1\n * @example Install from CDN.JS\n * \n * @example Install from JSDelivr\n * \n * @example Load into your app via script tag\n * \n * \n * @example Load into your app via CommonJS\n * var JSData = require('js-data');\n * @example Load into your app via ES2015 Modules\n * import * as JSData from 'js-data';\n * @example Load into your app via AMD\n * define('myApp', ['js-data'], function (JSData) { ... });\n */\n\n/**\n * JSData's utility methods.\n *\n * @example\n * import { utils } from 'js-data';\n * console.log(utils.isString('foo')); // true\n *\n * @name module:js-data.utils\n * @property {Function} Promise See {@link utils.Promise}.\n * @see utils\n * @since 3.0.0\n * @type {Object}\n */\nimport utils from './utils'\n\n/**\n * JSData's {@link Collection} class.\n *\n * @example\n * import { Collection } from 'js-data';\n * const collection = new Collection();\n *\n * @name module:js-data.Collection\n * @see Collection\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/components-of-jsdata#collection\",\"Components of JSData: Collection\"]\n * @type {Constructor}\n */\nimport Collection from './Collection'\n\n/**\n * JSData's {@link Component} class. Most components in JSData extend this\n * class.\n *\n * @example\n * import { Component } from 'js-data';\n * // Make a custom component.\n * const MyComponent = Component.extend({\n * myMethod (someArg) { ... }\n * });\n *\n * @name module:js-data.Component\n * @see Component\n * @since 3.0.0\n * @type {Constructor}\n */\nimport Component from './Component'\n\n/**\n * JSData's {@link Container} class. Defines and manages {@link Mapper}s. Used\n * in Node.js and in the browser, though in the browser you may want to use\n * {@link DataStore} instead.\n *\n * @example\n * import { Container } from 'js-data';\n * const store = new Container();\n *\n * @name module:js-data.Container\n * @see Container\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/components-of-jsdata#container\",\"Components of JSData: Container\"]\n * @type {Constructor}\n */\nimport { Container } from './Container'\n\n/**\n * JSData's {@link DataStore} class. Primarily for use in the browser. In\n * Node.js you probably want to use {@link Container} instead.\n *\n * @example\n * import { DataStore } from 'js-data';\n * const store = new DataStore();\n *\n * @name module:js-data.DataStore\n * @see DataStore\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/components-of-jsdata#datastore\",\"Components of JSData: DataStore\"]\n * @type {Constructor}\n */\nimport DataStore from './DataStore'\n\n/**\n * JSData's {@link Index} class, based on [mindex]{@link https://github.com/internalfx/mindex}.\n *\n * @name module:js-data.Index\n * @see Index\n * @since 3.0.0\n * @type {Constructor}\n */\nimport Index from '../lib/mindex/index'\n\n/**\n * JSData's {@link LinkedCollection} class. Used by the {@link DataStore}\n * component. If you need to create a collection manually, you should probably\n * use the {@link Collection} class.\n *\n * @name module:js-data.LinkedCollection\n * @see DataStore\n * @see LinkedCollection\n * @since 3.0.0\n * @type {Constructor}\n */\nimport LinkedCollection from './LinkedCollection'\n\n/**\n * JSData's {@link Mapper} class. The core of the ORM.\n *\n * @example Recommended use\n * import { Container } from 'js-data';\n * const store = new Container();\n * store.defineMapper('user');\n *\n * @example Create Mapper manually\n * import { Mapper } from 'js-data';\n * const UserMapper = new Mapper({ name: 'user' });\n *\n * @name module:js-data.Mapper\n * @see Container\n * @see Mapper\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/modeling-your-data\",\"Modeling your data\"]\n * @tutorial [\"http://www.js-data.io/v3.0/docs/components-of-jsdata#mapper\",\"Components of JSData: Mapper\"]\n * @type {Constructor}\n */\nimport Mapper from './Mapper'\n\n/**\n * JSData's {@link Query} class. Used by the {@link Collection} component.\n *\n * @name module:js-data.Query\n * @see Query\n * @since 3.0.0\n * @type {Constructor}\n */\nimport Query from './Query'\n\n/**\n * JSData's {@link Record} class.\n *\n * @example\n * import { Container } from 'js-data';\n * const store = new Container();\n * store.defineMapper('user');\n * const user = store.createRecord('user');\n *\n * @name module:js-data.Record\n * @see Record\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/components-of-jsdata#record\",\"Components of JSData: Record\"]\n * @type {Constructor}\n */\nimport Record from './Record'\n\n/**\n * JSData's {@link Schema} class. Implements http://json-schema.org/draft-04.\n *\n * @example\n * import { Container, Schema } from 'js-data';\n * const userSchema = new Schema({\n * properties: {\n * id: { type: 'string' },\n * name: { type: 'string' }\n * }\n * });\n * const store = new Container();\n * store.defineMapper('user', {\n * schema: userSchema\n * });\n *\n * @name module:js-data.Schema\n * @see Schema\n * @see http://json-schema.org/\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/components-of-jsdata#schema\",\"Components of JSData: schema\"]\n * @tutorial [\"http://www.js-data.io/v3.0/docs/schemas\",\"JSData's Schema Syntax\"]\n * @type {Constructor}\n */\nimport Schema from './Schema'\n\n/**\n * JSData's {@link Settable} class.\n *\n * @example\n * import { Settable } from 'js-data';\n * const obj = new Settable();\n * obj.set('secret', 'value');\n * console.log(JSON.stringify(obj)); // {}\n *\n * @name module:js-data.Settable\n * @see Settable\n * @since 3.0.0\n * @type {Constructor}\n */\nimport Settable from './Settable'\n\n/**\n * JSData's {@link SimpleStore} class. Primarily for use in the browser. In\n * Node.js you probably want to use {@link Container} instead.\n *\n * @example\n * import { SimpleStore } from 'js-data';\n * const store = new SimpleStore();\n *\n * @name module:js-data.SimpleStore\n * @see SimpleStore\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/components-of-jsdata#SimpleStore\",\"Components of JSData: SimpleStore\"]\n * @type {Constructor}\n */\nimport SimpleStore from './SimpleStore'\n\n/**\n * Describes the version of this `JSData` object.\n *\n * @example\n * console.log(JSData.version.full); // \"3.0.0-beta.1\"\n *\n * @name version\n * @memberof module:js-data\n * @property {string} full The full semver value.\n * @property {number} major The major version number.\n * @property {number} minor The minor version number.\n * @property {number} patch The patch version number.\n * @property {(string|boolean)} alpha The alpha version value, otherwise `false`\n * if the current version is not alpha.\n * @property {(string|boolean)} beta The beta version value, otherwise `false`\n * if the current version is not beta.\n * @since 2.0.0\n * @type {Object}\n */\nexport const version = '<%= version %>'\n\nexport * from './decorators'\n\nexport {\n Collection,\n Component,\n Container,\n DataStore,\n Index,\n LinkedCollection,\n Mapper,\n Query,\n Record,\n Schema,\n Settable,\n SimpleStore,\n utils\n}\n"],"names":["DOMAIN","INFINITY","MAX_INTEGER","BOOL_TAG","DATE_TAG","FUNC_TAG","NUMBER_TAG","OBJECT_TAG","REGEXP_TAG","STRING_TAG","objToString","Object","prototype","toString","PATH","ERRORS","arguments","toInteger","value","sign","remainder","toStr","call","isPlainObject","constructor","mkdirP","object","path","parts","split","forEach","key","utils","Promise","_","dest","src","forOwn","undefined","isFunction","indexOf","_forRelation","opts","def","fn","thisArg","relationName","relation","containedName","index","with","_getIndex","localField","withAll","optsCopy","fillIn","getRelation","slice","_activeWith","splice","i","length","substr","list","_relation","isObject","addHiddenPropsToTarget","target","props","map","keys","propName","descriptor","getOwnPropertyDescriptor","enumerable","defineProperties","areDifferent","newObject","oldObject","diff","diffObjects","diffCount","added","removed","changed","classCallCheck","instance","ctor","err","name","copy","from","to","stackFrom","stackTo","blacklist","plain","isArray","isDate","Date","getTime","isRegExp","RegExp","source","match","lastIndex","create","getPrototypeOf","push","result","hasOwnProperty","isBlacklisted","deepFillIn","existing","deepMixIn","equalsFn","ignore","deepEqual","newKeys","filter","oldKeys","oldValue","newValue","equal","a","b","domain","code","prefix","message","apply","Array","Error","eventify","getter","setter","_events","emit","events","args","type","shift","listeners","f","c","all","unshift","off","func","on","extend","classProps","superClass","subClass","configurable","writable","obj","setPrototypeOf","strictEs6Class","__proto__","defineProperty","findIndex","array","record","forEachRelation","mapper","relationList","len","fromJson","json","isString","JSON","parse","get","prop","last","pop","getSuper","isCtor","__super__","intersection","array1","array2","item","matches","test","isBoolean","isInteger","isNull","isNumber","isSorN","isUndefined","logify","dbg","log","level","debug","toUpperCase","console","noDupeAdd","omit","_props","pick","reduce","plainCopy","reject","remove","resolve","set","_path","exec","_equal","toJson","stringify","unset","safeSetProp","field","_set","safeSetLink","Settable","_get","_unset","Component","_listeners","INDEX_ERR","reserved","limit","offset","orderBy","skip","sort","where","escapeRegExp","percentRegExp","underscoreRegExp","escape","pattern","replace","Query","collection","data","_applyWhereFromObject","fields","ops","predicates","clause","expr","op","_applyWhereFromArray","groups","_where","prev","parser","group","isOr","_testObjectGroup","keep","first","charAt","evaluate","_testArrayGroup","between","leftKeys","rightKeys","getIndex","compare","cA","cB","temp","predicate","like","query","getData","forEachFn","keyList","getAll","concat","flags","num","Math","min","mapFn","mapCall","funcName","run","isectEmpty","isectNotEmpty","in","notIn","contains","notContains","belongsToType","hasManyType","hasOneType","Relation","relatedMapper","options","TYPE_NAME","validateOptions","canAutoAddLinks","add","relatedCollection","datastore","getCollection","related","DOMAIN_ERR","foreignKey","localKey","assignTo","relationFields","canFindLinkFor","getForeignKey","idAttribute","setForeignKey","relatedRecord","_setForeignKey","relatedRecords","getLocalField","setLocalField","relatedData","getInverse","inverse","findInverseRelation","isInversedTo","addLinkedRecords","records","linkRecord","isEmptyLinks","findExistingLinksFor","removeLinkedRecords","relatedId","unsaved","findExistingLinksByForeignKey","id","ensureLinkedDataHasProperType","relationData","is","createRecord","isRequiresParentId","isRequiresChildId","createChildRecord","createLinked","then","BelongsToRelation","createParentRecord","HasManyRelation","localKeys","foreignKeys","hasForeignKeys","recordId","ids","findExistingLinksByLocalKeys","findExistingLinksByForeignKeys","foreignIdField","createMany","HasOneRelation","RelationType","belongsTo","hasMany","hasOne","superMethod","store","bind","creatingPath","noValidatePath","keepChangeHistoryPath","previousPath","Record","noValidate","keepChangeHistory","validateOnSet","toJSON","_mapper","afterLoadRelations","beforeLoadRelations","changeHistory","changes","commit","destroy","hasChanges","quickHasChanges","isNew","isValid","validate","removeInverseRelation","currentParent","inverseDef","children","child","setupInverseRelation","loadRelations","relations","adapter","getAdapterName","tasks","task","raw","load","previous","revert","preserve","save","postProcess","changesOnly","silent","hashCode","insertAt","removeAt","binarySearch","lo","hi","compared","mid","found","Index","fieldList","fieldGetter","isIndex","values","pos","dataLocation","newIndex","results","order","visitAll","cb","leftInclusive","rightInclusive","_between","leftKey","rightKey","currKey","peek","clear","insertRecord","removeRecord","isUnique","j","updateRecord","COLLECTION_DEFAULTS","commitOnMerge","emitRecordEvents","onConflict","Collection","queryClass","indexes","_onRecordEvent","beforeAdd","singular","existingNoValidate","updateIndexes","afterAdd","afterRemove","afterRemoveAll","beforeRemove","beforeRemoveAll","createIndex","instances","prune","removeAll","Ctor","initialValue","idOrRecord","queryOrRecords","updateIndex","types","boolean","integer","null","number","string","segmentToString","segment","str","makePath","segments","makeError","actual","expected","addError","errors","maxLengthCommon","keyword","schema","max","minLengthCommon","validationKeywords","allOf","allErrors","_schema","anyOf","validated","dependencies","enum","possibleValues","join","items","checkingTuple","maximum","exclusiveMaximum","maxItems","maxLength","maxProperties","minimum","exclusiveMinimum","minItems","minLength","minProperties","multipleOf","not","oneOf","properties","additionalProperties","patternProperties","toValidate","undef","origProp","required","existingOnly","prevProp","validType","_type","validator","typeGroupValidators","uniqueItems","runOps","ANY_OPS","ARRAY_OPS","NUMERIC_OPS","OBJECT_OPS","STRING_OPS","validateAny","ctx","shouldPop","extends","changingPath","changedPath","changeHistoryPath","eventIdPath","silentPath","validationFailureMsg","numeric","Schema","definition","_definition","validationKeyword","unsetter","track","makeDescriptor","applyDefaults","hasSet","default","orig","keyPath","originalGet","error","current","changing","clearTimeout","setTimeout","changeRecord","timestamp","originalSet","_copy","applyDefaultsHooks","validatingHooks","makeNotify","getSchema","toProcess","originalExistingOnly","notify","notify2","LIFECYCLE_METHODS","count","defaults","destroyAll","find","findAll","sum","update","adapterArgs","beforeAssign","updateAll","updateMany","MAPPER_DEFAULTS","_adapters","applySchema","defaultAdapter","Mapper","lifecycleMethods","recordClass","methods","isPrototypeOf","afterCount","afterCreate","afterCreateMany","afterDestroy","afterDestroyAll","afterFind","afterFindAll","afterSum","afterUpdate","afterUpdateAll","afterUpdateMany","beforeCreate","beforeCreateMany","beforeCount","beforeDestroy","beforeDestroyAll","beforeFind","beforeFindAll","beforeSum","beforeUpdate","beforeUpdateAll","beforeUpdateMany","_end","_data","wrap","crud","originalRecord","parentRelationMap","adapterResponse","_runHook","_createParentRecordIfRequired","relationMap","_invokeAdapterMethod","createdProps","_createOrAssignChildRecordIfRequired","originalProps","_commitChanges","recordOrRecords","newValues","createInstance","context","parent","originalRecords","belongsToRelationData","Boolean","createdRecordsData","belongsToData","createdRecordData","RecordCtor","method","config","upper","before","after","_value","getAdapter","_opts","assign","_result","getAdapters","registerAdapter","hookName","hookArgs","defaultValueIndex","overridenResult","propsOrRecords","conversionOptions","pass","_record","some","defineRelations","_name","getMapperByName","getMapper","proxiedMapperMethods","Container","_mappers","mapperClass","mapperDefaults","_onMapperEvent","as","original","defineMapper","defineResource","warn","proxiedCollectionMethods","ownMethodsForScoping","cachedFn","hashOrId","cached","_completedQueries","SIMPLESTORE_DEFAULTS","usePendingFind","usePendingFindAll","SimpleStore","collectionClass","_collections","_pendingQueries","addToCache","_onCollectionEvent","cachedFind","cachedFindAll","cacheFind","cacheFindAll","hash","self","collectionOpts","_added","indexed","hashQuery","eject","ejectAll","pendingQuery","force","promise","inject","removeRelated","LinkedCollection","_addMeta","_clearMeta","event","DATASTORE_DEFAULTS","unlinkOnDestroy","DataStore","updateOpts","relatedIdAttribute","foreignKeyDescriptor","currentParentId","storeRecord","inverseLocalField","toLink","toLinkIds","currentChildrenOfParent","parents","_key","origGet","origSet","version"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"js-data.es2015.js","sources":["../src/utils.ts","../src/Settable.ts","../src/Component.ts","../src/Query.ts","../src/Relation.ts","../src/Record.ts","../src/mindex/_utils.ts","../src/mindex/index.ts","../src/Collection.ts","../src/TsDataError.ts","../src/Schema.ts","../src/Relation/BelongsTo.ts","../src/Relation/HasMany.ts","../src/Relation/HasOne.ts","../src/relations.ts","../src/decorators.ts","../src/Mapper.ts","../src/Container.ts","../src/SimpleStore.ts","../src/LinkedCollection.ts","../src/DataStore.ts","../src/index.ts"],"sourcesContent":["/**\n * Utility methods used by JSData.\n *\n * @example\n * import { utils } from 'js-data';\n * console.log(utils.isString('foo')); // true\n *\n * @namespace utils\n * @type {Object}\n */\n\nconst DOMAIN = 'utils'\n\nconst INFINITY = 1 / 0\nconst MAX_INTEGER = 1.7976931348623157e308\nconst BOOL_TAG = '[object Boolean]'\nconst DATE_TAG = '[object Date]'\nconst FUNC_TAG = '[object Function]'\nconst NUMBER_TAG = '[object Number]'\nconst OBJECT_TAG = '[object Object]'\nconst REGEXP_TAG = '[object RegExp]'\nconst STRING_TAG = '[object String]'\nconst objToString = Object.prototype.toString\nconst PATH = /^(.+)\\.(.+)$/\n\nconst ERRORS = {\n '400' (...args) {\n return `expected: ${args[0]}, found: ${args[2] ? args[1] : typeof args[1]}`\n },\n '404' (...args) {\n return `${args[0]} not found`\n }\n}\n\nconst toInteger = value => {\n if (!value) {\n return 0\n }\n // Coerce to number\n value = +value\n if (value === INFINITY || value === -INFINITY) {\n const sign = value < 0 ? -1 : 1\n return sign * MAX_INTEGER\n }\n const remainder = value % 1\n return value === value ? (remainder ? value - remainder : value) : 0; // eslint-disable-line\n}\n\nconst toStr = value => objToString.call(value)\n\nconst isPlainObject = value => !!value && typeof value === 'object' && value.constructor === Object\n\nconst mkdirP = (object, path) => {\n if (!path) {\n return object\n }\n const parts = path.split('.')\n parts.forEach(key => {\n if (!object[key]) {\n object[key] = {}\n }\n object = object[key]\n })\n return object\n}\n\nconst utils = {\n /**\n * Shallow copy properties that meet the following criteria from `src` to\n * `dest`:\n *\n * - own enumerable\n * - not a function\n * - does not start with \"_\"\n *\n * @method utils._\n * @param {object} dest Destination object.\n * @param {object} src Source object.\n * @private\n * @since 3.0.0\n */\n _ (dest, src) {\n utils.forOwn(src, (value, key) => {\n if (key && dest[key] === undefined && !utils.isFunction(value) && key.indexOf('_') !== 0) {\n dest[key] = value\n }\n })\n },\n\n /**\n * Recursively iterates over relations found in `opts.with`.\n *\n * @method utils._forRelation\n * @param {object} opts Configuration options.\n * @param {Relation} def Relation definition.\n * @param {Function} fn Callback function.\n * @param {*} [thisArg] Execution context for the callback function.\n * @private\n * @since 3.0.0\n */\n _forRelation (opts: any = {}, def, fn, thisArg) {\n const relationName = def.relation\n let containedName = null\n let index\n opts.with = opts.with || []\n\n if ((index = utils._getIndex(opts.with, relationName)) >= 0) {\n containedName = relationName\n } else if ((index = utils._getIndex(opts.with, def.localField)) >= 0) {\n containedName = def.localField\n }\n\n if (opts.withAll) {\n fn.call(thisArg, def, {})\n return\n } else if (!containedName) {\n return\n }\n const optsCopy: any = {}\n utils.fillIn(optsCopy, def.getRelation())\n utils.fillIn(optsCopy, opts)\n optsCopy.with = opts.with.slice()\n optsCopy._activeWith = optsCopy.with.splice(index, 1)[0]\n optsCopy.with.forEach((relation, i) => {\n if (\n relation &&\n relation.indexOf(containedName) === 0 &&\n relation.length >= containedName.length &&\n relation[containedName.length] === '.'\n ) {\n optsCopy.with[i] = relation.substr(containedName.length + 1)\n } else {\n optsCopy.with[i] = ''\n }\n })\n fn.call(thisArg, def, optsCopy)\n },\n\n /**\n * Find the index of a relation in the given list\n *\n * @method utils._getIndex\n * @param {string[]} list List to search.\n * @param {string} relation Relation to find.\n * @private\n * @returns {number}\n */\n _getIndex (list, relation) {\n let index = -1\n list.forEach((_relation, i) => {\n if (_relation === relation) {\n index = i\n return false\n } else if (utils.isObject(_relation)) {\n if (_relation.relation === relation) {\n index = i\n return false\n }\n }\n })\n return index\n },\n\n /**\n * Define hidden (non-enumerable), writable properties on `target` from the\n * provided `props`.\n *\n * @example\n * import { utils } from 'js-data';\n * function Cat () {}\n * utils.addHiddenPropsToTarget(Cat.prototype, {\n * say () {\n * console.log('meow');\n * }\n * });\n * const cat = new Cat();\n * cat.say(); // \"meow\"\n *\n * @method utils.addHiddenPropsToTarget\n * @param {object} target That to which `props` should be added.\n * @param {object} props Properties to be added to `target`.\n * @since 3.0.0\n */\n addHiddenPropsToTarget (target, props) {\n const map = {}\n Object.keys(props).forEach(propName => {\n const descriptor = Object.getOwnPropertyDescriptor(props, propName)\n\n descriptor.enumerable = false\n map[propName] = descriptor\n })\n Object.defineProperties(target, map)\n },\n\n /**\n * Return whether the two objects are deeply different.\n *\n * @example\n * import { utils } from 'js-data';\n * utils.areDifferent({}, {}); // false\n * utils.areDifferent({ a: 1 }, { a: 1 }); // false\n * utils.areDifferent({ foo: 'bar' }, {}); // true\n *\n * @method utils.areDifferent\n * @param newObject\n * @param oldObject\n * @param {object} [opts] Configuration options.\n * @param {Function} [opts.equalsFn={@link utils.deepEqual}] Equality function.\n * @param {array} [opts.ignore=[]] Array of strings or RegExp of fields to ignore.\n * @returns {boolean} Whether the two objects are deeply different.\n * @see utils.diffObjects\n * @since 3.0.0\n */\n areDifferent (newObject, oldObject, opts: any = {}) {\n const diff = utils.diffObjects(newObject, oldObject, opts)\n const diffCount =\n Object.keys(diff.added).length + Object.keys(diff.removed).length + Object.keys(diff.changed).length\n return diffCount > 0\n },\n\n /**\n * Deep copy a value.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = { foo: { bar: 'baz' } };\n * const b = utils.copy(a);\n * a === b; // false\n * utils.areDifferent(a, b); // false\n *\n * @param {*} from Value to deep copy.\n * @param {*} [to] Destination object for the copy operation.\n * @param {*} [stackFrom] For internal use.\n * @param {*} [stackTo] For internal use.\n * @param {string[]|RegExp[]} [blacklist] List of strings or RegExp of\n * properties to skip.\n * @param {boolean} [plain] Whether to make a plain copy (don't try to use\n * original prototype).\n * @returns {*} Deep copy of `from`.\n * @since 3.0.0\n */\n copy (from, to?, stackFrom?, stackTo?, blacklist?, plain?) {\n if (!to) {\n to = from\n if (from) {\n if (utils.isArray(from)) {\n to = utils.copy(from, [], stackFrom, stackTo, blacklist, plain)\n } else if (utils.isDate(from)) {\n to = new Date(from.getTime())\n } else if (utils.isRegExp(from)) {\n to = new RegExp(from.source, from.toString().match(/[^/]*$/)[0])\n to.lastIndex = from.lastIndex\n } else if (utils.isObject(from)) {\n if (plain) {\n to = utils.copy(from, {}, stackFrom, stackTo, blacklist, plain)\n } else {\n to = utils.copy(from, Object.create(Object.getPrototypeOf(from)), stackFrom, stackTo, blacklist, plain)\n }\n }\n }\n } else {\n if (from === to) {\n throw utils.err(`${DOMAIN}.copy`)(500, 'Cannot copy! Source and destination are identical.')\n }\n\n stackFrom = stackFrom || []\n stackTo = stackTo || []\n\n if (utils.isObject(from)) {\n const index = stackFrom.indexOf(from)\n if (index !== -1) {\n return stackTo[index]\n }\n\n stackFrom.push(from)\n stackTo.push(to)\n }\n\n let result\n if (utils.isArray(from)) {\n let i\n to.length = 0\n for (i = 0; i < from.length; i++) {\n result = utils.copy(from[i], null, stackFrom, stackTo, blacklist, plain)\n if (utils.isObject(from[i])) {\n stackFrom.push(from[i])\n stackTo.push(result)\n }\n to.push(result)\n }\n } else {\n if (utils.isArray(to)) {\n to.length = 0\n } else {\n utils.forOwn(to, (value, key) => {\n delete to[key]\n })\n }\n for (const key in from) {\n if (from.hasOwnProperty(key)) {\n if (utils.isBlacklisted(key, blacklist)) {\n continue\n }\n result = utils.copy(from[key], null, stackFrom, stackTo, blacklist, plain)\n if (utils.isObject(from[key])) {\n stackFrom.push(from[key])\n stackTo.push(result)\n }\n to[key] = result\n }\n }\n }\n }\n return to\n },\n\n /**\n * Recursively shallow fill in own enumerable properties from `source` to\n * `dest`.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = { foo: { bar: 'baz' }, beep: 'boop' };\n * const b = { beep: 'bip' };\n * utils.deepFillIn(b, a);\n * console.log(b); // {\"foo\":{\"bar\":\"baz\"},\"beep\":\"bip\"}\n *\n * @method utils.deepFillIn\n * @param {object} dest The destination object.\n * @param {object} source The source object.\n * @see utils.fillIn\n * @see utils.deepMixIn\n * @since 3.0.0\n */\n deepFillIn (dest, source?) {\n if (source) {\n utils.forOwn(source, (value, key) => {\n const existing = dest[key]\n if (isPlainObject(value) && isPlainObject(existing)) {\n utils.deepFillIn(existing, value)\n } else if (!dest.hasOwnProperty(key) || dest[key] === undefined) {\n dest[key] = value\n }\n })\n }\n return dest\n },\n\n /**\n * Recursively shallow copy enumerable properties from `source` to `dest`.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = { foo: { bar: 'baz' }, beep: 'boop' };\n * const b = { beep: 'bip' };\n * utils.deepFillIn(b, a);\n * console.log(b); // {\"foo\":{\"bar\":\"baz\"},\"beep\":\"boop\"}\n *\n * @method utils.deepMixIn\n * @param {object} dest The destination object.\n * @param {object} source The source object.\n * @see utils.fillIn\n * @see utils.deepFillIn\n * @since 3.0.0\n */\n deepMixIn (dest, source?) {\n if (source) {\n // tslint:disable-next-line:forin\n for (const key in source) {\n const value = source[key]\n const existing = dest[key]\n if (isPlainObject(value) && isPlainObject(existing)) {\n utils.deepMixIn(existing, value)\n } else {\n dest[key] = value\n }\n }\n }\n return dest\n },\n\n /**\n * Return a diff of the base object to the comparison object.\n *\n * @example\n * import { utils } from 'js-data';\n * const oldObject = { foo: 'bar', a: 1234 };\n * const newObject = { beep: 'boop', a: 5678 };\n * const diff = utils.diffObjects(oldObject, newObject);\n * console.log(diff.added); // {\"beep\":\"boop\"}\n * console.log(diff.changed); // {\"a\":5678}\n * console.log(diff.removed); // {\"foo\":undefined}\n *\n * @method utils.diffObjects\n * @param {object} newObject Comparison object.\n * @param {object} oldObject Base object.\n * @param {object} [opts] Configuration options.\n * @param {Function} [opts.equalsFn={@link utils.deepEqual}] Equality function.\n * @param {array} [opts.ignore=[]] Array of strings or RegExp of fields to ignore.\n * @returns {Object} The diff from the base object to the comparison object.\n * @see utils.areDifferent\n * @since 3.0.0\n */\n diffObjects (newObject, oldObject, opts: any = {}) {\n let equalsFn = opts.equalsFn\n const blacklist = opts.ignore\n const diff = {\n added: {},\n changed: {},\n removed: {}\n }\n if (!utils.isFunction(equalsFn)) {\n equalsFn = utils.deepEqual\n }\n\n const newKeys = Object.keys(newObject).filter(key => !utils.isBlacklisted(key, blacklist))\n const oldKeys = Object.keys(oldObject).filter(key => !utils.isBlacklisted(key, blacklist))\n\n // Check for properties that were added or changed\n newKeys.forEach(key => {\n const oldValue = oldObject[key]\n const newValue = newObject[key]\n if (equalsFn(oldValue, newValue)) {\n return\n }\n if (oldValue === undefined) {\n diff.added[key] = newValue\n } else {\n diff.changed[key] = newValue\n }\n })\n\n // Check for properties that were removed\n oldKeys.forEach(key => {\n const oldValue = oldObject[key]\n const newValue = newObject[key]\n if (newValue === undefined && oldValue !== undefined) {\n diff.removed[key] = undefined\n }\n })\n\n return diff\n },\n\n /**\n * Return whether the two values are equal according to the `==` operator.\n *\n * @example\n * import { utils } from 'js-data';\n * console.log(utils.equal(1,1)); // true\n * console.log(utils.equal(1,'1')); // true\n * console.log(utils.equal(93, 66)); // false\n *\n * @method utils.equal\n * @param {*} a First value in the comparison.\n * @param {*} b Second value in the comparison.\n * @returns {boolean} Whether the two values are equal according to `==`.\n * @since 3.0.0\n */\n equal (a, b) {\n // tslint:disable-next-line:triple-equals\n return a == b; // eslint-disable-line\n },\n\n /**\n * Produce a factory function for making Error objects with the provided\n * metadata. Used throughout the various js-data components.\n *\n * @example\n * import { utils } from 'js-data';\n * const errorFactory = utils.err('domain', 'target');\n * const error400 = errorFactory(400, 'expected type', 'actual type');\n * console.log(error400); // [Error: [domain:target] expected: expected type, found: string\n * http://www.js-data.io/v3.0/docs/errors#400]\n * @method utils.err\n * @param {string} domain Namespace.\n * @param {string} target Target.\n * @returns {Function} Factory function.\n * @since 3.0.0\n */\n err (domain, target?) {\n return (code, ...args) => {\n const prefix = `[${domain}:${target}] `\n let message = ERRORS[code].apply(null, args)\n message = `${prefix}${message}\nhttp://www.js-data.io/v3.0/docs/errors#${code}`\n return new Error(message)\n }\n },\n\n /**\n * Add eventing capabilities into the target object.\n *\n * @example\n * import { utils } from 'js-data';\n * const user = { name: 'John' };\n * utils.eventify(user);\n * user.on('foo', () => console.log(arguments));\n * user.emit('foo', 1, 'bar'); // should log to console values (1, \"bar\")\n *\n * @method utils.eventify\n * @param {object} target Target object.\n * @param {Function} [getter] Custom getter for retrieving the object's event\n * listeners.\n * @param {Function} [setter] Custom setter for setting the object's event\n * listeners.\n * @since 3.0.0\n */\n eventify (target, getter?, setter?) {\n target = target || this\n let _events = {}\n if (!getter && !setter) {\n getter = () => _events\n setter = value => (_events = value)\n }\n Object.defineProperties(target, {\n emit: {\n value (...args) {\n const events = getter.call(this) || {}\n const type = args.shift()\n let listeners = events[type] || []\n let i\n for (i = 0; i < listeners.length; i++) {\n listeners[i].f.apply(listeners[i].c, args)\n }\n listeners = events.all || []\n args.unshift(type)\n for (i = 0; i < listeners.length; i++) {\n listeners[i].f.apply(listeners[i].c, args)\n }\n }\n },\n off: {\n value (type, func) {\n const events = getter.call(this)\n const listeners = events[type]\n if (!listeners) {\n setter.call(this, {})\n } else if (func) {\n for (let i = 0; i < listeners.length; i++) {\n if (listeners[i].f === func) {\n listeners.splice(i, 1)\n break\n }\n }\n } else {\n listeners.splice(0, listeners.length)\n }\n }\n },\n on: {\n value (type, func, thisArg) {\n if (!getter.call(this)) {\n setter.call(this, {})\n }\n const events = getter.call(this)\n events[type] = events[type] || []\n events[type].push({\n c: thisArg,\n f: func\n })\n }\n }\n })\n },\n\n /**\n * Shallow copy own enumerable properties from `src` to `dest` that are on\n * `src` but are missing from `dest.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = { foo: 'bar', beep: 'boop' };\n * const b = { beep: 'bip' };\n * utils.fillIn(b, a);\n * console.log(b); // {\"foo\":\"bar\",\"beep\":\"bip\"}\n *\n * @method utils.fillIn\n * @param {object} dest The destination object.\n * @param src\n * @see utils.deepFillIn\n * @see utils.deepMixIn\n * @since 3.0.0\n */\n fillIn (dest, src) {\n utils.forOwn(src, (value, key) => {\n if (!dest.hasOwnProperty(key) || dest[key] === undefined) {\n dest[key] = value\n }\n })\n },\n\n /**\n * Find the last index of an item in an array according to the given checker function.\n *\n * @example\n * import { utils } from 'js-data';\n *\n * const john = { name: 'John', age: 20 };\n * const sara = { name: 'Sara', age: 25 };\n * const dan = { name: 'Dan', age: 20 };\n * const users = [john, sara, dan];\n *\n * console.log(utils.findIndex(users, (user) => user.age === 25)); // 1\n * console.log(utils.findIndex(users, (user) => user.age > 19)); // 2\n * console.log(utils.findIndex(users, (user) => user.name === 'John')); // 0\n * console.log(utils.findIndex(users, (user) => user.name === 'Jimmy')); // -1\n *\n * @method utils.findIndex\n * @param {array} array The array to search.\n * @param {Function} fn Checker function.\n * @returns {number} Index if found or -1 if not found.\n * @since 3.0.0\n */\n findIndex (array, fn) {\n let index = -1\n if (!array) {\n return index\n }\n array.forEach((record, i) => {\n if (fn(record)) {\n index = i\n return false\n }\n })\n return index\n },\n\n /**\n * Recursively iterate over a {@link Mapper}'s relations according to\n * `opts.with`.\n *\n * @method utils.forEachRelation\n * @param {Mapper} mapper Mapper.\n * @param {object} opts Configuration options.\n * @param {Function} fn Callback function.\n * @param {*} thisArg Execution context for the callback function.\n * @since 3.0.0\n */\n forEachRelation (mapper, opts, fn, thisArg?) {\n const relationList = mapper.relationList || []\n if (!relationList.length) {\n return\n }\n relationList.forEach(def => {\n utils._forRelation(opts, def, fn, thisArg)\n })\n },\n\n /**\n * Iterate over an object's own enumerable properties.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = { b: 1, c: 4 };\n * let sum = 0;\n * utils.forOwn(a, function (value, key) {\n * sum += value;\n * });\n * console.log(sum); // 5\n *\n * @method utils.forOwn\n * @param obj\n * @param {Function} fn Iteration function.\n * @param {object} [thisArg] Content to which to bind `fn`.\n * @since 3.0.0\n */\n forOwn (obj, fn, thisArg?) {\n const keys = Object.keys(obj)\n const len = keys.length\n let i\n for (i = 0; i < len; i++) {\n if (fn.call(thisArg, obj[keys[i]], keys[i], obj) === false) {\n break\n }\n }\n },\n\n /**\n * Proxy for `JSON.parse`.\n *\n * @example\n * import { utils } from 'js-data';\n *\n * const a = utils.fromJson('{\"name\" : \"John\"}');\n * console.log(a); // { name: 'John' }\n *\n * @method utils.fromJson\n * @param {string} json JSON to parse.\n * @returns {Object} Parsed object.\n * @see utils.toJson\n * @since 3.0.0\n */\n fromJson (json) {\n return utils.isString(json) ? JSON.parse(json) : json\n },\n\n /**\n * Retrieve the specified property from the given object. Supports retrieving\n * nested properties.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = { foo: { bar: 'baz' }, beep: 'boop' };\n * console.log(utils.get(a, 'beep')); // \"boop\"\n * console.log(utils.get(a, 'foo.bar')); // \"baz\"\n *\n * @method utils.get\n * @param {object} object Object from which to retrieve a property's value.\n * @param {string} prop Property to retrieve.\n * @returns {*} Value of the specified property.\n * @see utils.set\n * @since 3.0.0\n */\n get (object, prop) {\n if (!prop) {\n return\n }\n /* if prop is function, get the property by calling a function, passing an object as a parameter */\n if (utils.isFunction(prop)) {\n return prop(object)\n }\n const parts = prop.split('.')\n const last = parts.pop()\n\n while ((prop = parts.shift())) {\n // eslint-disable-line\n object = object[prop]\n if (object == null) {\n // eslint-disable-line\n return\n }\n }\n\n return object[last]\n },\n\n /**\n * Return the superclass for the given instance or subclass. If an instance is\n * provided, then finds the parent class of the instance's constructor.\n *\n * @example\n * import { utils } from 'js-data';\n * // using ES2015 classes\n * class Foo {}\n * class Bar extends Foo {}\n * const barInstance = new Bar();\n * let baseType = utils.getSuper(barInstance);\n * console.log(Foo === baseType); // true\n *\n * // using Function constructor with utils.extend\n * function Foo () {}\n * Foo.extend = utils.extend;\n * const Bar = Foo.extend();\n * const barInstance = new Bar();\n * let baseType = utils.getSuper(barInstance);\n * console.log(Foo === baseType); // true\n *\n * @method utils.getSuper\n * @param {Object|Function} instance Instance or constructor.\n * @param {boolean} [isCtor=false] Whether `instance` is a constructor.\n * @returns {Constructor} The superclass (grandparent constructor).\n * @since 3.0.0\n */\n getSuper (instance, isCtor?) {\n const ctor = isCtor ? instance : instance.constructor\n if (ctor.hasOwnProperty('__super__')) {\n return ctor.__super__\n }\n return Object.getPrototypeOf(ctor) || ctor.__proto__; // eslint-disable-line\n },\n\n /**\n * Return the intersection of two arrays.\n *\n * @example\n * import { utils } from 'js-data';\n * const arrA = ['green', 'red', 'blue', 'red'];\n * const arrB = ['green', 'yellow', 'red'];\n * const intersected = utils.intersection(arrA, arrB);\n *\n * console.log(intersected); // ['green', 'red'])\n *\n * @method utils.intersection\n * @param {array} array1 First array.\n * @param {array} array2 Second array.\n * @returns {Array} Array of elements common to both arrays.\n * @since 3.0.0\n */\n intersection (array1, array2) {\n if (!array1 || !array2) {\n return []\n }\n array1 = Array.isArray(array1) ? array1 : [array1]\n array2 = Array.isArray(array2) ? array2 : [array2]\n const result = []\n let item\n let i\n const len = array1.length\n for (i = 0; i < len; i++) {\n item = array1[i]\n if (result.indexOf(item) !== -1) {\n continue\n }\n if (array2.indexOf(item) !== -1) {\n result.push(item)\n }\n }\n return result\n },\n\n /**\n * Proxy for `Array.isArray`.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = [1,2,3,4,5];\n * const b = { foo: \"bar\" };\n * console.log(utils.isArray(a)); // true\n * console.log(utils.isArray(b)); // false\n *\n * @method utils.isArray\n * @param {*} value The value to test.\n * @returns {boolean} Whether the provided value is an array.\n * @since 3.0.0\n */\n isArray: Array.isArray,\n\n /**\n * Return whether `prop` is matched by any string or regular expression in\n * `blacklist`.\n *\n * @example\n * import { utils } from 'js-data';\n * const blacklist = [/^\\$hashKey/g, /^_/g, 'id'];\n * console.log(utils.isBlacklisted(\"$hashKey\", blacklist)); // true\n * console.log(utils.isBlacklisted(\"id\", blacklist)); // true\n * console.log(utils.isBlacklisted(\"_myProp\", blacklist)); // true\n * console.log(utils.isBlacklisted(\"my_id\", blacklist)); // false\n *\n * @method utils.isBlacklisted\n * @param {string} prop The name of a property to check.\n * @param {array} blacklist Array of strings and regular expressions.\n * @returns {boolean} Whether `prop` was matched.\n * @since 3.0.0\n */\n isBlacklisted (prop, blacklist) {\n if (!blacklist || !blacklist.length) {\n return false\n }\n let matches\n for (const item of blacklist) {\n if ((toStr(item) === REGEXP_TAG && item.test(prop)) || item === prop) {\n matches = prop\n return !!matches\n }\n }\n return !!matches\n },\n\n /**\n * Return whether the provided value is a boolean.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = true;\n * const b = { foo: \"bar\" };\n * console.log(utils.isBoolean(a)); // true\n * console.log(utils.isBoolean(b)); // false\n *\n * @method utils.isBoolean\n * @param {*} value The value to test.\n * @returns {boolean} Whether the provided value is a boolean.\n * @since 3.0.0\n */\n isBoolean (value) {\n return toStr(value) === BOOL_TAG\n },\n\n /**\n * Return whether the provided value is a date.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = new Date();\n * const b = { foo: \"bar\" };\n * console.log(utils.isDate(a)); // true\n * console.log(utils.isDate(b)); // false\n *\n * @method utils.isDate\n * @param {*} value The value to test.\n * @returns {Date} Whether the provided value is a date.\n * @since 3.0.0\n */\n isDate (value) {\n return value && typeof value === 'object' && toStr(value) === DATE_TAG\n },\n\n /**\n * Return whether the provided value is a function.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = function () { console.log('foo bar'); };\n * const b = { foo: \"bar\" };\n * console.log(utils.isFunction(a)); // true\n * console.log(utils.isFunction(b)); // false\n *\n * @method utils.isFunction\n * @param {*} value The value to test.\n * @returns {boolean} Whether the provided value is a function.\n * @since 3.0.0\n */\n isFunction (value) {\n return typeof value === 'function' || (value && toStr(value) === FUNC_TAG)\n },\n\n /**\n * Return whether the provided value is an integer.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = 1;\n * const b = 1.25;\n * const c = '1';\n * console.log(utils.isInteger(a)); // true\n * console.log(utils.isInteger(b)); // false\n * console.log(utils.isInteger(c)); // false\n *\n * @method utils.isInteger\n * @param {*} value The value to test.\n * @returns {boolean} Whether the provided value is an integer.\n * @since 3.0.0\n */\n isInteger (value) {\n // tslint:disable-next-line:triple-equals\n return toStr(value) === NUMBER_TAG && value == toInteger(value); // eslint-disable-line\n },\n\n /**\n * Return whether the provided value is `null`.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = null;\n * const b = { foo: \"bar\" };\n * console.log(utils.isNull(a)); // true\n * console.log(utils.isNull(b)); // false\n *\n * @method utils.isNull\n * @param {*} value The value to test.\n * @returns {boolean} Whether the provided value is `null`.\n * @since 3.0.0\n */\n isNull (value) {\n return value === null\n },\n\n /**\n * Return whether the provided value is a number.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = 1;\n * const b = -1.25;\n * const c = '1';\n * console.log(utils.isNumber(a)); // true\n * console.log(utils.isNumber(b)); // true\n * console.log(utils.isNumber(c)); // false\n *\n * @method utils.isNumber\n * @param {*} value The value to test.\n * @returns {boolean} Whether the provided value is a number.\n * @since 3.0.0\n */\n isNumber (value) {\n const type = typeof value\n return type === 'number' || (value && type === 'object' && toStr(value) === NUMBER_TAG)\n },\n\n /**\n * Return whether the provided value is an object.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = { foo: \"bar\" };\n * const b = 'foo bar';\n * console.log(utils.isObject(a)); // true\n * console.log(utils.isObject(b)); // false\n *\n * @method utils.isObject\n * @param {*} value The value to test.\n * @returns {boolean} Whether the provided value is an object.\n * @since 3.0.0\n */\n isObject (value) {\n return toStr(value) === OBJECT_TAG\n },\n\n /**\n * Return whether the provided value is a regular expression.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = /^\\$.+$/ig;\n * const b = new RegExp('^\\$.+$', 'ig');\n * const c = { foo: \"bar\" };\n * console.log(utils.isRegExp(a)); // true\n * console.log(utils.isRegExp(b)); // true\n * console.log(utils.isRegExp(c)); // false\n *\n * @method utils.isRegExp\n * @param {*} value The value to test.\n * @returns {boolean} Whether the provided value is a regular expression.\n * @since 3.0.0\n */\n isRegExp (value) {\n return toStr(value) === REGEXP_TAG\n },\n\n /**\n * Return whether the provided value is a string or a number.\n *\n * @example\n * import { utils } from 'js-data';\n * console.log(utils.isSorN('')); // true\n * console.log(utils.isSorN(-1.65)); // true\n * console.log(utils.isSorN('my string')); // true\n * console.log(utils.isSorN({})); // false\n * console.log(utils.isSorN([1,2,4])); // false\n *\n * @method utils.isSorN\n * @param {*} value The value to test.\n * @returns {boolean} Whether the provided value is a string or a number.\n * @since 3.0.0\n */\n isSorN (value) {\n return utils.isString(value) || utils.isNumber(value)\n },\n\n /**\n * Return whether the provided value is a string.\n *\n * @example\n * import { utils } from 'js-data';\n * console.log(utils.isString('')); // true\n * console.log(utils.isString('my string')); // true\n * console.log(utils.isString(100)); // false\n * console.log(utils.isString([1,2,4])); // false\n *\n * @method utils.isString\n * @param {*} value The value to test.\n * @returns {boolean} Whether the provided value is a string.\n * @since 3.0.0\n */\n isString (value) {\n return typeof value === 'string' || (value && typeof value === 'object' && toStr(value) === STRING_TAG)\n },\n\n /**\n * Return whether the provided value is a `undefined`.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = undefined;\n * const b = { foo: \"bar\"};\n * console.log(utils.isUndefined(a)); // true\n * console.log(utils.isUndefined(b.baz)); // true\n * console.log(utils.isUndefined(b)); // false\n * console.log(utils.isUndefined(b.foo)); // false\n *\n * @method utils.isUndefined\n * @param {*} value The value to test.\n * @returns {boolean} Whether the provided value is a `undefined`.\n * @since 3.0.0\n */\n isUndefined (value) {\n return value === undefined\n },\n\n /**\n * Mix in logging capabilities to the target.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = { foo: \"bar\"};\n *\n * // Add standard logging to an object\n * utils.logify(a);\n * a.log('info', 'test log info'); // output 'test log info' to console.\n *\n * // Toggle debug output of an object\n * a.dbg('test debug output'); // does not output because debug is off.\n * a.debug = true;\n * a.dbg('test debug output'); // output 'test debug output' to console.\n *\n * @method utils.logify\n * @param {*} target The target.\n * @since 3.0.0\n */\n logify (target) {\n utils.addHiddenPropsToTarget(target, {\n dbg (...args) {\n if (utils.isFunction(this.log)) {\n this.log('debug', ...args)\n }\n },\n log (level, ...args) {\n if (level && !args.length) {\n args.push(level)\n level = 'debug'\n }\n if (level === 'debug' && !this.debug) {\n return\n }\n const prefix = `${level.toUpperCase()}: (${this.name || this.constructor.name})`\n if (utils.isFunction(console[level])) {\n console[level](prefix, ...args)\n } else {\n console.log(prefix, ...args)\n }\n }\n })\n },\n\n /**\n * Adds the given record to the provided array only if it's not already in the\n * array.\n *\n * @example\n * import { utils } from 'js-data';\n * const colors = ['red', 'green', 'yellow'];\n *\n * console.log(colors.length); // 3\n * utils.noDupeAdd(colors, 'red');\n * console.log(colors.length); // 3, red already exists\n *\n * utils.noDupeAdd(colors, 'blue');\n * console.log(colors.length); // 4, blue was added\n *\n * @method utils.noDupeAdd\n * @param {array} array The array.\n * @param {*} record The value to add.\n * @param {Function} fn Callback function passed to {@link utils.findIndex}.\n * @since 3.0.0\n */\n noDupeAdd (array, record?, fn?) {\n if (!array) {\n return\n }\n const index = this.findIndex(array, fn)\n if (index < 0) {\n array.push(record)\n }\n },\n\n /**\n * Return a shallow copy of the provided object, minus the properties\n * specified in `keys`.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = { name: 'John', $hashKey: 1214910 };\n *\n * let b = utils.omit(a, ['$hashKey']);\n * console.log(b); // { name: 'John' }\n *\n * @method utils.omit\n * @param {object} props The object to copy.\n * @param {string[]} keys Array of strings, representing properties to skip.\n * @returns {Object} Shallow copy of `props`, minus `keys`.\n * @since 3.0.0\n */\n omit (props, keys) {\n const _props = {}\n utils.forOwn(props, (value, key) => {\n if (keys.indexOf(key) === -1) {\n _props[key] = value\n }\n })\n return _props\n },\n\n /**\n * Return a shallow copy of the provided object, but only include the\n * properties specified in `keys`.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = { name: 'John', $hashKey: 1214910 };\n *\n * let b = utils.pick(a, ['$hashKey']);\n * console.log(b); // { $hashKey: 1214910 }\n *\n * @method utils.pick\n * @param {object} props The object to copy.\n * @param {string[]} keys Array of strings, representing properties to keep.\n * @returns {Object} Shallow copy of `props`, but only including `keys`.\n * @since 3.0.0\n */\n pick (props, keys) {\n return keys.reduce((map, key) => {\n map[key] = props[key]\n return map\n }, {})\n },\n\n /**\n * Return a plain copy of the given value.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = { name: 'John' };\n * let b = utils.plainCopy(a);\n * console.log(a === b); // false\n *\n * @method utils.plainCopy\n * @param {*} value The value to copy.\n * @returns {*} Plain copy of `value`.\n * @see utils.copy\n * @since 3.0.0\n */\n plainCopy (value) {\n return utils.copy(value, undefined, undefined, undefined, undefined, true)\n },\n\n /**\n * Shortcut for `utils.Promise.reject(value)`.\n *\n * @example\n * import { utils } from 'js-data';\n *\n * utils.reject(\"Testing static reject\").then(function (data) {\n * // not called\n * }).catch(function (reason) {\n * console.log(reason); // \"Testing static reject\"\n * });\n *\n * @method utils.reject\n * @param {*} [value] Value with which to reject the Promise.\n * @returns {Promise} Promise reject with `value`.\n */\n reject (value) {\n return Promise.reject(value)\n },\n\n /**\n * Remove the last item found in array according to the given checker function.\n *\n * @example\n * import { utils } from 'js-data';\n *\n * const colors = ['red', 'green', 'yellow', 'red'];\n * utils.remove(colors, (color) => color === 'red');\n * console.log(colors); // ['red', 'green', 'yellow']\n *\n * @method utils.remove\n * @param {array} array The array to search.\n * @param {Function} fn Checker function.\n */\n remove (array, fn?) {\n if (!array || !array.length) {\n return\n }\n const index = this.findIndex(array, fn)\n if (index >= 0) {\n array.splice(index, 1) // todo should this be recursive?\n }\n },\n\n /**\n * Shortcut for `utils.Promise.resolve(value)`.\n *\n * @example\n * import { utils } from 'js-data';\n *\n * utils.resolve(\"Testing static resolve\").then(function (data) {\n * console.log(data); // \"Testing static resolve\"\n * }).catch(function (reason) {\n * // not called\n * });\n *\n * @param {*} [value] Value with which to resolve the Promise.\n * @returns {Promise} Promise resolved with `value`.\n */\n resolve (value?) {\n return Promise.resolve(value)\n },\n\n /**\n * Set the value at the provided key or path.\n *\n * @example\n * import { utils } from 'js-data';\n *\n * const john = {\n * name: 'John',\n * age: 25,\n * parent: {\n * name: 'John's Mom',\n * age: 50\n * }\n * };\n * // set value by key\n * utils.set(john, 'id', 98);\n * console.log(john.id); // 98\n *\n * // set value by path\n * utils.set(john, 'parent.id', 20);\n * console.log(john.parent.id); // 20\n *\n * // set value by path/value map\n * utils.set(john, {\n * 'id': 1098,\n * 'parent': { id: 1020 },\n * 'parent.age': '55'\n * });\n * console.log(john.id); // 1098\n * console.log(john.parent.id); // 1020\n * console.log(john.parent.age); // 55\n *\n * @method utils.set\n * @param {object} object The object on which to set a property.\n * @param {(string|Object)} path The key or path to the property. Can also\n * pass in an object of path/value pairs, which will all be set on the target\n * object.\n * @param {*} [value] The value to set.\n */\n set (object, path, value?, opts?) {\n if (utils.isObject(path)) {\n utils.forOwn(path, (value, _path) => {\n utils.set(object, _path, value)\n })\n } else {\n const parts = PATH.exec(path)\n if (parts) {\n mkdirP(object, parts[1])[parts[2]] = value\n } else {\n object[path] = value\n }\n }\n },\n\n /**\n * Check whether the two provided objects are deeply equal.\n *\n * @example\n * import { utils } from 'js-data';\n *\n * const objA = {\n * name: 'John',\n * id: 27,\n * nested: {\n * item: 'item 1',\n * colors: ['red', 'green', 'blue']\n * }\n * };\n *\n * const objB = {\n * name: 'John',\n * id: 27,\n * nested: {\n * item: 'item 1',\n * colors: ['red', 'green', 'blue']\n * }\n * };\n *\n * console.log(utils.deepEqual(a,b)); // true\n * objB.nested.colors.add('yellow'); // make a change to a nested object's array\n * console.log(utils.deepEqual(a,b)); // false\n *\n * @method utils.deepEqual\n * @param {object} a First object in the comparison.\n * @param {object} b Second object in the comparison.\n * @returns {boolean} Whether the two provided objects are deeply equal.\n * @see utils.equal\n * @since 3.0.0\n */\n deepEqual (a, b) {\n if (a === b) {\n return true\n }\n let _equal = true\n if (utils.isArray(a) && utils.isArray(b)) {\n if (a.length !== b.length) {\n return false\n }\n for (let i = a.length; i--;) {\n if (!utils.deepEqual(a[i], b[i])) {\n // Exit loop early\n return false\n }\n }\n } else if (utils.isObject(a) && utils.isObject(b)) {\n utils.forOwn(a, (value, key) => {\n if (!(_equal = utils.deepEqual(value, b[key]))) {\n // Exit loop early\n return false\n }\n })\n if (_equal) {\n utils.forOwn(b, (value, key) => {\n if (!(_equal = utils.deepEqual(value, a[key]))) {\n // Exit loop early\n return false\n }\n })\n }\n } else {\n return false\n }\n return _equal\n },\n\n /**\n * Proxy for `JSON.stringify`.\n *\n * @example\n * import { utils } from 'js-data';\n *\n * const a = { name: 'John' };\n * let jsonVal = utils.toJson(a);\n * console.log(jsonVal); // '{\"name\" : \"John\"}'\n *\n * @method utils.toJson\n * @param {*} value Value to serialize to JSON.\n * @returns {string} JSON string.\n * @see utils.fromJson\n * @since 3.0.0\n */\n toJson: JSON.stringify,\n\n /**\n * Unset the value at the provided key or path.\n *\n * @example\n * import { utils } from 'js-data';\n *\n * const john = {\n * name: 'John',\n * age: 25,\n * parent: {\n * name: 'John's Mom',\n * age: 50\n * }\n * };\n *\n * utils.unset(john, age);\n * utils.unset(john, parent.age);\n *\n * console.log(john.age); // null\n * console.log(john.parent.age); // null\n *\n * @method utils.unset\n * @param {object} object The object from which to delete the property.\n * @param {string} path The key or path to the property.\n * @see utils.set\n * @since 3.0.0\n */\n unset (object, path: string) {\n const parts = path.split('.')\n const last = parts.pop()\n\n while ((path = parts.shift())) {\n // eslint-disable-line\n object = object[path]\n if (object == null) {\n // eslint-disable-line\n return\n }\n }\n\n object[last] = undefined\n },\n /**\n * Gets default locale for the js-data context.\n *\n * @example\n * import { utils } from 'js-data';\n *\n *\n * utils.getDefaultLocale();\n *\n * @method utils.getDefaultLocale\n * @since 4.0.0\n */\n getDefaultLocale () {\n return 'en'\n }\n}\n\nexport const safeSetProp = (record, field, value) => {\n if (record?._set) {\n record._set(`props.${field}`, value)\n } else {\n utils.set(record, field, value)\n }\n}\n\nexport const safeSetLink = (record, field, value) => {\n if (record?._set) {\n record._set(`links.${field}`, value)\n } else {\n utils.set(record, field, value)\n }\n}\n\nexport default utils\n","import utils from './utils'\n\n/**\n * A base class which gives instances private properties.\n *\n * Typically you won't instantiate this class directly, but you may find it\n * useful as an abstract class for your own components.\n *\n * @example\n * import {Settable} from 'js-data';\n *\n * class CustomSettableClass extends Settable {\n * foo () { return 'bar'; }\n * static beep () { return 'boop'; }\n * }\n *\n * const customSettable = new CustomSettableClass();\n * console.log(customSettable.foo());\n * console.log(CustomSettableClass.beep());\n *\n * @since 3.0.0\n */\nexport default class Settable {\n [customAttr: string]: any;\n\n /**\n * Get a private property of this instance.\n *\n * __Don't use the method unless you know what you're doing.__\n *\n * @method Settable#_get\n * @param {string} key The property to retrieve.\n * @returns {*} The value of the property.\n * @since 3.0.0\n */\n protected _get: (key: string) => any;\n\n /**\n * Set a private property of this instance.\n *\n * __Don't use the method unless you know what you're doing.__\n *\n * @method __Don't use the method unless you know what you're doing.__#_set\n * @param {(string|Object)} key The key or path to the property. Can also\n * pass in an object of key/value pairs, which will all be set on the instance.\n * @param {*} [value] The value to set.\n * @since 3.0.0\n */\n protected _set: (key, value?) => any;\n\n /**\n * Unset a private property of this instance.\n *\n * __Don't use the method unless you know what you're doing.__\n *\n * @method __Don't use the method unless you know what you're doing.__#_unset\n * @param {string} key The property to unset.\n * @since 3.0.0\n */\n protected _unset: (key) => any;\n\n constructor () {\n const _props = {}\n\n Object.defineProperties(this, {\n _get: {\n value (key) {\n return utils.get(_props, key)\n }\n },\n _set: {\n value (key, value) {\n return utils.set(_props, key, value)\n }\n },\n _unset: {\n value (key) {\n return utils.unset(_props, key)\n }\n }\n })\n }\n}\n","import utils from './utils'\nimport Settable from './Settable'\n\nexport interface ComponentOpts {\n debug?: boolean\n}\n\n/**\n * The base class from which all JSData components inherit some basic\n * functionality.\n *\n * Typically you won't instantiate this class directly, but you may find it\n * useful as an abstract class for your own components.\n *\n * @example\n * import {Component} from 'js-data'\n *\n * class CustomComponentClass extends Component {\n * foo () { return 'bar'; }\n * static beep () { return 'boop'; }\n * }\n * const customComponent = new CustomComponentClass();\n * console.log(customComponent.foo());\n * console.log(CustomComponentClass.beep());\n * ```\n *\n * @param {object} [opts] Configuration options.\n * @param {boolean} [opts.debug=false] See {@link Component#debug}.\n * @returns {Component} A new {@link Component} instance.\n * @since 3.0.0\n */\nexport default class Component extends Settable {\n /**\n * Whether to enable debug-level logs for this component. Anything that\n * extends `Component` inherits this option and the corresponding logging\n * functionality.\n *\n * @example Component#debug\n * const JSData = require('js-data');\n * const { Component } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const component = new Component();\n * component.log('debug', 'some message'); // nothing gets logged\n * // Display debug logs:\n * component.debug = true;\n * component.log('debug', 'other message'); // this DOES get logged\n *\n * @default false\n * @name Component#debug\n * @since 3.0.0\n * @type {boolean}\n */\n protected debug: boolean;\n\n /**\n * Event listeners attached to this Component. __Do not modify.__ Use\n * {@link Component#on} and {@link Component#off} instead.\n *\n * @name Component#_listeners\n * @private\n * @instance\n * @since 3.0.0\n * @type {Object}\n */\n _listeners = {};\n\n /**\n * Log the provided values at the \"debug\" level. Debug-level logs are only\n * logged if {@link Component#debug} is `true`.\n *\n * `.dbg(...)` is shorthand for `.log('debug', ...)`.\n *\n * @method Component#dbg\n * @param {...*} [args] Values to log.\n * @since 3.0.0\n */\n dbg: (...args) => void;\n\n /**\n * Log the provided values. By default sends values to `console[level]`.\n * Debug-level logs are only logged if {@link Component#debug} is `true`.\n *\n * Will attempt to use appropriate `console` methods if they are available.\n *\n * @method Component#log\n * @param {string} level Log level.\n * @param {...*} [args] Values to log.\n * @since 3.0.0\n */\n log: (...args) => void;\n\n /**\n * Register a new event listener on this Component.\n *\n * @example\n * // Listen for all \"afterCreate\" events in a DataStore\n * store.on('afterCreate', (mapperName, props, opts, result) => {\n * console.log(mapperName); // \"post\"\n * console.log(props.id); // undefined\n * console.log(result.id); // 1234\n * });\n * store.create('post', { title: 'Modeling your data' }).then((post) => {\n * console.log(post.id); // 1234\n * });\n *\n * @example\n * // Listen for the \"add\" event on a collection\n * collection.on('add', (records) => {\n * console.log(records); // [...]\n * });\n *\n * @example\n * // Listen for \"change\" events on a record\n * post.on('change', (record, changes) => {\n * console.log(changes); // { changed: { title: 'Modeling your data' } }\n * });\n * post.title = 'Modeling your data';\n *\n * @method Component#on\n * @param {string} event Name of event to subscribe to.\n * @param {Function} listener Listener function to handle the event.\n * @param {*} [ctx] Optional content in which to invoke the listener.\n * @since 3.0.0\n */\n on: (name: string, listener: Function, ctx?) => void;\n\n /**\n * Remove an event listener from this Component. If no listener is provided,\n * then all listeners for the specified event will be removed. If no event is\n * specified then all listeners for all events will be removed.\n *\n * @example\n * // Remove a particular listener for a particular event\n * collection.off('add', handler);\n *\n * @example\n * // Remove all listeners for a particular event\n * record.off('change');\n *\n * @example\n * // Remove all listeners to all events\n * store.off();\n *\n * @method Component#off\n * @param {string} [event] Name of event to unsubscribe to.\n * @param {Function} [listener] Listener to remove.\n * @since 3.0.0\n */\n off: (event: string, listener?: Function, thisArg?) => void;\n\n /**\n * Trigger an event on this Component.\n *\n * @example Component#emit\n * // import { Collection, DataStore } from 'js-data';\n * const JSData = require('js-data');\n * const { Collection, DataStore } = JSData;\n *\n * const collection = new Collection();\n * collection.on('foo', function (msg) {\n * console.log(msg);\n * });\n * collection.emit('foo', 'bar');\n *\n * const store = new DataStore();\n * store.on('beep', function (msg) {\n * console.log(msg);\n * });\n * store.emit('beep', 'boop');\n *\n * @method Component#emit\n * @param {string} event Name of event to emit.\n * @param {...*} [args] Arguments to pass to any listeners.\n * @since 3.0.0\n */\n emit: (event: string, ...args) => void;\n\n constructor (opts: ComponentOpts | any = {}) {\n super()\n this.debug = opts.debug ?? false\n }\n}\n\nutils.logify(Component.prototype)\n\nutils.eventify(\n Component.prototype,\n function () {\n return this._listeners\n },\n function (value) {\n this._listeners = value\n }\n)\n","import utils from './utils'\nimport Component from './Component'\n\nconst DOMAIN = 'Query'\nconst INDEX_ERR = 'Index inaccessible after first operation'\n\n// Reserved words used by JSData's Query Syntax\nconst reserved = {\n limit: '',\n offset: '',\n orderBy: '',\n skip: '',\n sort: '',\n where: '',\n locale: ''\n}\n\n// Used by our JavaScript implementation of the LIKE operator\nconst escapeRegExp = /([.*+?^=!:${}()|[\\]/\\\\])/g\nconst percentRegExp = /%/g\nconst underscoreRegExp = /_/g\n\nfunction escape (pattern) {\n return pattern.replace(escapeRegExp, '\\\\$1')\n}\n\nexport interface QueryDefinition {\n [attr: string]: any\n where?: any\n orderBy?: any\n sort?: any\n skip?: number\n limit?: number\n offset?: number\n}\n\n/**\n * A class used by the {@link Collection} class to build queries to be executed\n * against the collection's data. An instance of `Query` is returned by\n * {@link Collection#query}. Query instances are typically short-lived, and you\n * shouldn't have to create them yourself. Just use {@link Collection#query}.\n *\n * ```javascript\n * import { Query } from 'js-data';\n * ```\n *\n * @example Query intro\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post');\n * const posts = [\n * { author: 'John', age: 30, status: 'published', id: 1 },\n * { author: 'Sally', age: 31, status: 'draft', id: 2 },\n * { author: 'Mike', age: 32, status: 'draft', id: 3 },\n * { author: 'Adam', age: 33, status: 'deleted', id: 4 },\n * { author: 'Adam', age: 33, status: 'draft', id: 5 }\n * ]\n * store.add('post', posts);\n * const drafts = store.query('post').filter({ status: 'draft' }).limit(2).run();\n * console.log(drafts);\n *\n * @class Query\n * @extends Component\n * @param {Collection} collection The collection on which this query operates.\n * @since 3.0.0\n */\nexport default class Query extends Component {\n /**\n * The current data result of this query.\n *\n * @name Query#data\n * @since 3.0.0\n * @type {Array}\n */\n private data = null;\n\n constructor (public collection?) {\n super()\n }\n\n _applyWhereFromObject (where) {\n const fields = []\n const ops = []\n const predicates = []\n utils.forOwn(where, (clause, field) => {\n if (!utils.isObject(clause)) {\n clause = {\n '==': clause\n }\n }\n utils.forOwn(clause, (expr, op) => {\n fields.push(field)\n ops.push(op)\n predicates.push(expr)\n })\n })\n return {\n fields,\n ops,\n predicates\n }\n }\n\n _applyWhereFromArray (where) {\n const groups: any = []\n where.forEach((_where, i) => {\n if (utils.isString(_where)) {\n return\n }\n const prev = where[i - 1]\n const parser = utils.isArray(_where) ? this._applyWhereFromArray : this._applyWhereFromObject\n const group = parser.call(this, _where)\n if (prev === 'or') {\n group.isOr = true\n }\n groups.push(group)\n })\n groups.isArray = true\n return groups\n }\n\n _testObjectGroup (keep, first, group, item) {\n let i\n const fields = group.fields\n const ops = group.ops\n const predicates = group.predicates\n const len = ops.length\n for (i = 0; i < len; i++) {\n let op = ops[i]\n const isOr = op.charAt(0) === '|'\n op = isOr ? op.substr(1) : op\n const expr = this.evaluate(utils.get(item, fields[i]), op, predicates[i])\n if (expr !== undefined) {\n keep = first ? expr : isOr ? keep || expr : keep && expr\n }\n first = false\n }\n return { keep, first }\n }\n\n _testArrayGroup (keep, first, groups, item) {\n let i\n const len = groups.length\n for (i = 0; i < len; i++) {\n const group = groups[i]\n const parser = group.isArray ? this._testArrayGroup : this._testObjectGroup\n const result = parser.call(this, true, true, group, item)\n if (groups[i - 1]) {\n if (group.isOr) {\n keep = keep || result.keep\n } else {\n keep = keep && result.keep\n }\n } else {\n keep = result.keep\n }\n first = result.first\n }\n return { keep, first }\n }\n\n /**\n * Find all entities between two boundaries.\n *\n * @example Get the users ages 18 to 30.\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('user');\n * const users = [\n * { name: 'Peter', age: 25, id: 1 },\n * { name: 'Jim', age: 19, id: 2 },\n * { name: 'Mike', age: 17, id: 3 },\n * { name: 'Alan', age: 29, id: 4 },\n * { name: 'Katie', age: 33, id: 5 }\n * ];\n * store.add('user', users)\n * const filteredUsers = store\n * .query('user')\n * .between(18, 30, { index: 'age' })\n * .run();\n * console.log(filteredUsers);\n *\n * @example Same as above.\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('user');\n * const users = [\n * { name: 'Peter', age: 25, id: 1 },\n * { name: 'Jim', age: 19, id: 2 },\n * { name: 'Mike', age: 17, id: 3 },\n * { name: 'Alan', age: 29, id: 4 },\n * { name: 'Katie', age: 33, id: 5 }\n * ];\n * store.add('user', users)\n * const filteredUsers = store\n * .query('user')\n * .between([18], [30], { index: 'age' })\n * .run();\n * console.log(filteredUsers);\n *\n * @method Query#between\n * @param {array} leftKeys Keys defining the left boundary.\n * @param {array} rightKeys Keys defining the right boundary.\n * @param {object} [opts] Configuration options.\n * @param {string} [opts.index] Name of the secondary index to use in the\n * query. If no index is specified, the main index is used.\n * @param {boolean} [opts.leftInclusive=true] Whether to include entities\n * on the left boundary.\n * @param {boolean} [opts.rightInclusive=false] Whether to include entities\n * on the left boundary.\n * @param {boolean} [opts.limit] Limit the result to a certain number.\n * @param {boolean} [opts.offset] The number of resulting entities to skip.\n * @returns {Query} A reference to itself for chaining.\n * @since 3.0.0\n */\n between (leftKeys?, rightKeys?, opts: any = {}) {\n if (this.data) {\n throw utils.err(`${DOMAIN}#between`)(500, 'Cannot access index')\n }\n this.data = this.collection.getIndex(opts.index).between(leftKeys, rightKeys, opts)\n return this\n }\n\n /**\n * The comparison function used by the {@link Query} class.\n *\n * @method Query#compare\n * @param {array} orderBy An orderBy clause used for sorting and sub-sorting.\n * @param {number} index The index of the current orderBy clause being used.\n * @param {*} a The first item in the comparison.\n * @param {*} b The second item in the comparison.\n * @returns {number} -1 if `b` should preceed `a`. 0 if `a` and `b` are equal.\n * 1 if `a` should preceed `b`.\n * @since 3.0.0\n */\n compare (orderBy, index, a, b, compare) {\n const def = orderBy[index]\n let cA = utils.get(a, def[0])\n let cB = utils.get(b, def[0])\n if (cA && utils.isString(cA)) {\n cA = cA.toUpperCase()\n }\n if (cB && utils.isString(cB)) {\n cB = cB.toUpperCase()\n }\n if (a === undefined) {\n a = null\n }\n if (b === undefined) {\n b = null\n }\n if (def[1].toUpperCase() === 'DESC') {\n const temp = cB\n cB = cA\n cA = temp\n }\n /* Fix: compare by using collator */\n // let isNumeric = false\n // if (utils.isNumber(cA) || utils.isNumber(cB)) {\n // isNumeric = true\n // }\n const n = compare(cA, cB)\n if (n === -1 || n === 1) {\n return n\n } else {\n if (index < orderBy.length - 1) {\n return this.compare(orderBy, index + 1, a, b, compare)\n } else {\n return 0\n }\n }\n }\n\n /**\n * Predicate evaluation function used by the {@link Query} class.\n *\n * @method Query#evaluate\n * @param {*} value The value to evaluate.\n * @param {string} op The operator to use in this evaluation.\n * @param {*} predicate The predicate to use in this evaluation.\n * @returns {boolean} Whether the value passed the evaluation or not.\n * @since 3.0.0\n */\n evaluate (value, op, predicate) {\n const ops = Query.ops\n if (ops[op]) {\n return ops[op](value, predicate)\n }\n if (op.indexOf('like') === 0) {\n return this.like(predicate, op.substr(4)).exec(value) !== null\n } else if (op.indexOf('notLike') === 0) {\n return this.like(predicate, op.substr(7)).exec(value) === null\n }\n }\n\n /**\n * Find the record or records that match the provided query or are accepted by\n * the provided filter function.\n *\n * @example Get the draft posts by authors younger than 30\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post')\n * const posts = [\n * { author: 'John', age: 30, status: 'published', id: 1 },\n * { author: 'Sally', age: 31, status: 'published', id: 2 },\n * { author: 'Mike', age: 32, status: 'draft', id: 3 },\n * { author: 'Adam', age: 33, status: 'deleted', id: 4 },\n * { author: 'Adam', age: 33, status: 'published', id: 5 }\n * { author: 'Peter', age: 25, status: 'deleted', id: 6 },\n * { author: 'Sally', age: 21, status: 'draft', id: 7 },\n * { author: 'Jim', age: 27, status: 'draft', id: 8 },\n * { author: 'Jim', age: 27, status: 'published', id: 9 },\n * { author: 'Jason', age: 55, status: 'published', id: 10 }\n * ];\n * store.add('post', posts);\n * const results = store\n * .query('post')\n * .filter({\n * where: {\n * status: {\n * '==': 'draft'\n * },\n * age: {\n * '<': 30\n * }\n * }\n * })\n * .run();\n * console.log(results);\n *\n * @example Use a custom filter function\n * const posts = query\n * .filter(function (post) {\n * return post.isReady();\n * })\n * .run();\n *\n * @method Query#filter\n * @param {(Object|Function)} [query={}] Selection query or filter\n * function.\n * @param {Function} [thisArg] Context to which to bind `queryOrFn` if\n * `queryOrFn` is a function.\n * @returns {Query} A reference to itself for chaining.\n * @since 3.0.0\n */\n filter (query: QueryDefinition = {}, thisArg?: Function): Query {\n /**\n * Selection query as defined by JSData's [Query Syntax][querysyntax].\n *\n * [querysyntax]: http://www.js-data.io/v3.0/docs/query-syntax\n *\n * @example Empty \"findAll\" query\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post')\n * store.findAll('post').then((posts) => {\n * console.log(posts); // [...]\n * });\n *\n * @example Empty \"filter\" query\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post');\n * const posts = store.filter('post');\n * console.log(posts); // [...]\n *\n * @example Complex \"filter\" query\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * const PAGE_SIZE = 2;\n * let currentPage = 3;\n *\n * store.defineMapper('post');\n * const posts = [\n * { author: 'John', age: 30, status: 'published', id: 1 },\n * { author: 'Sally', age: 31, status: 'published', id: 2 },\n * { author: 'Mike', age: 32, status: 'draft', id: 3 },\n * { author: 'Adam', age: 33, status: 'deleted', id: 4 },\n * { author: 'Adam', age: 33, status: 'published', id: 5 }\n * { author: 'Peter', age: 25, status: 'deleted', id: 6 },\n * { author: 'Sally', age: 21, status: 'draft', id: 7 },\n * { author: 'Jim', age: 27, status: 'draft', id: 8 },\n * { author: 'Jim', age: 27, status: 'published', id: 9 },\n * { author: 'Jason', age: 55, status: 'published', id: 10 }\n * ];\n * store.add('post', posts);\n * // Retrieve a filtered page of blog posts\n * // Would typically replace filter with findAll\n * const results = store.filter('post', {\n * where: {\n * status: {\n * // WHERE status = 'published'\n * '==': 'published'\n * },\n * author: {\n * // AND author IN ('bob', 'alice')\n * 'in': ['bob', 'alice'],\n * // OR author IN ('karen')\n * '|in': ['karen']\n * }\n * },\n * orderBy: [\n * // ORDER BY date_published DESC,\n * ['date_published', 'DESC'],\n * // ORDER BY title ASC\n * ['title', 'ASC']\n * ],\n * // LIMIT 2\n * limit: PAGE_SIZE,\n * // SKIP 4\n * offset: PAGE_SIZE * (currentPage - 1)\n * });\n * console.log(results);\n *\n * @namespace query\n * @property {number} [limit] See {@link query.limit}.\n * @property {number} [offset] See {@link query.offset}.\n * @property {string|Array[]} [orderBy] See {@link query.orderBy}.\n * @property {number} [skip] Alias for {@link query.offset}.\n * @property {string|Array[]} [sort] Alias for {@link query.orderBy}.\n * @property {Object} [where] See {@link query.where}.\n * @property {String} [locale] See {@link query.locale}.\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/query-syntax\",\"JSData's Query Syntax\"]\n */\n this.getData()\n if (utils.isObject(query)) {\n let where = {}\n\n /**\n * Filtering criteria. Records that do not meet this criteria will be exluded\n * from the result.\n *\n * @example Return posts where author is at least 32 years old\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post')\n * const posts = [\n * { author: 'John', age: 30, id: 5 },\n * { author: 'Sally', age: 31, id: 6 },\n * { author: 'Mike', age: 32, id: 7 },\n * { author: 'Adam', age: 33, id: 8 },\n * { author: 'Adam', age: 33, id: 9 }\n * ];\n * store.add('post', posts);\n * const results = store.filter('post', {\n * where: {\n * age: {\n * '>=': 30\n * }\n * }\n * });\n * console.log(results);\n *\n * @name query.where\n * @type {Object}\n * @see http://www.js-data.io/v3.0/docs/query-syntax\n * @since 3.0.0\n */\n if (utils.isObject(query.where) || utils.isArray(query.where)) {\n where = query.where\n }\n utils.forOwn(query, (value, key) => {\n if (!(key in reserved) && !(key in where)) {\n where[key] = {\n '==': value\n }\n }\n })\n let groups\n\n // Apply filter for each field\n if (utils.isObject(where) && Object.keys(where).length !== 0) {\n groups = this._applyWhereFromArray([where])\n } else if (utils.isArray(where)) {\n groups = this._applyWhereFromArray(where)\n }\n\n if (groups) {\n this.data = this.data.filter(item => this._testArrayGroup(true, true, groups, item).keep)\n }\n\n // Sort\n let orderBy = query.orderBy || query.sort\n\n if (utils.isString(orderBy)) {\n orderBy = [[orderBy, 'ASC']]\n }\n if (!utils.isArray(orderBy)) {\n orderBy = null\n }\n\n /**\n * Determines how records should be ordered in the result.\n *\n * @example Order posts by `author` then by `id` descending \n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post')\n * const posts = [\n * { author: 'John', age: 30, id: 5 },\n * { author: 'Sally', age: 31, id: 6 },\n * { author: 'Mike', age: 32, id: 7 },\n * { author: 'Adam', age: 33, id: 8 },\n * { author: 'Adam', age: 33, id: 9 }\n * ];\n * store.add('post', posts);\n * const results = store.filter('post', {\n * orderBy:[['author','ASC'],['id','DESC']]\n * });\n * console.log(results);\n *\n * @name query.orderBy\n * @type {string|Array[]}\n * @see http://www.js-data.io/v3.0/docs/query-syntax\n * @since 3.0.0\n */\n if (orderBy) {\n const index = 0\n orderBy.forEach((def, i) => {\n if (utils.isString(def)) {\n orderBy[i] = [def, 'ASC']\n }\n })\n let locale: string = utils.getDefaultLocale()\n if (utils.isString(query.locale)) {\n locale = query.locale\n }\n /** The locale params has to be explicitly set for the collator.compare to work.\n *\n * @example Order posts with specific locale, defaults to 'en'\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post')\n * const posts = [\n * { author: 'คลอน', age: 30, id: 5 },\n * { author: 'กลอน', age: 31, id: 6 },\n * { author: 'สาระ', age: 32, id: 7 },\n * { author: 'ศาลา', age: 33, id: 8 },\n * { author: 'จักรพรรณ', age: 33, id: 9 }\n * ];\n * store.add('post', posts);\n * const results = store.filter('post', {\n * orderBy:[['author','ASC'],['id','DESC']],\n * locale: 'th'\n * });\n * console.log(results);\n *\n * @name query.locale\n * @type {string}\n * @see http://www.js-data.io/v4.0/docs/query-syntax\n * @since 4.0.0\n */\n const collator = new Intl.Collator(locale, {\n numeric: true\n })\n\n this.data.sort((a, b) => this.compare(orderBy, index, a, b, collator.compare))\n }\n\n /**\n * Number of records to skip.\n *\n * @example Retrieve the first \"page\" of blog posts using findAll\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post');\n * const PAGE_SIZE = 10;\n * let currentPage = 1;\n * store.findAll('post', {\n * offset: PAGE_SIZE * (currentPage 1)\n * limit: PAGE_SIZE\n * });\n *\n * @example Retrieve the last \"page\" of blog posts using filter\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n *\n * const PAGE_SIZE = 5;\n * let currentPage = 2;\n * store.defineMapper('post');\n * const posts = [\n * { author: 'John', age: 30, id: 1 },\n * { author: 'Sally', age: 31, id: 2 },\n * { author: 'Mike', age: 32, id: 3 },\n * { author: 'Adam', age: 33, id: 4 },\n * { author: 'Adam', age: 33, id: 5 },\n * { author: 'Peter', age: 25, id: 6 },\n * { author: 'Sally', age: 21, id: 7 },\n * { author: 'Jim', age: 27, id: 8 },\n * { author: 'Jim', age: 27, id: 9 },\n * { author: 'Jason', age: 55, id: 10 }\n * ];\n * store.add('post', posts);\n * const results = store.filter('post', {\n * offset: PAGE_SIZE * (currentPage 1)\n * limit: PAGE_SIZE\n * });\n * console.log(results)\n *\n * @name query.offset\n * @type {number}\n * @see http://www.js-data.io/v3.0/docs/query-syntax\n * @since 3.0.0\n */\n if (utils.isNumber(query.skip)) {\n this.skip(query.skip)\n } else if (utils.isNumber(query.offset)) {\n this.skip(query.offset)\n }\n\n /**\n * Maximum number of records to retrieve.\n *\n * @example Retrieve the first \"page\" of blog posts using findAll\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post');\n *\n * const PAGE_SIZE = 10\n * let currentPage = 1\n * store.findAll('post', {\n * offset: PAGE_SIZE * (currentPage 1)\n * limit: PAGE_SIZE\n * });\n *\n * @example Retrieve the last \"page\" of blog posts using filter\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n *\n * const PAGE_SIZE = 5\n * let currentPage = 2\n * store.defineMapper('post')\n * const posts = [\n * { author: 'John', age: 30, id: 1 },\n * { author: 'Sally', age: 31, id: 2 },\n * { author: 'Mike', age: 32, id: 3 },\n * { author: 'Adam', age: 33, id: 4 },\n * { author: 'Adam', age: 33, id: 5 },\n * { author: 'Peter', age: 25, id: 6 },\n * { author: 'Sally', age: 21, id: 7 },\n * { author: 'Jim', age: 27, id: 8 },\n * { author: 'Jim', age: 27, id: 9 },\n * { author: 'Jason', age: 55, id: 10 }\n * ];\n * store.add('post', posts);\n * const results = store.filter('post', {\n * offset: PAGE_SIZE * (currentPage 1)\n * limit: PAGE_SIZE\n * });\n * console.log(results)\n *\n * @name query.limit\n * @type {number}\n * @see http://www.js-data.io/v3.0/docs/query-syntax\n * @since 3.0.0\n */\n if (utils.isNumber(query.limit)) {\n this.limit(query.limit)\n }\n } else if (utils.isFunction(query)) {\n this.data = this.data.filter(query, thisArg)\n }\n return this\n }\n\n /**\n * Iterate over all entities.\n *\n * @method Query#forEach\n * @param {Function} forEachFn Iteration function.\n * @param {*} [thisArg] Context to which to bind `forEachFn`.\n * @returns {Query} A reference to itself for chaining.\n * @since 3.0.0\n */\n forEach (forEachFn: Function, thisArg?) {\n this.getData().forEach(forEachFn, thisArg)\n return this\n }\n\n /**\n * Find the entity or entities that match the provided key.\n *\n * @example Get the entity whose primary key is 25.\n * const entities = query.get(25).run();\n *\n * @example Same as above.\n * const entities = query.get([25]).run();\n *\n * @example Get all users who are active and have the \"admin\" role.\n * const activeAdmins = query.get(['active', 'admin'], {\n * index: 'activityAndRoles'\n * }).run();\n *\n * @example Get all entities that match a certain weather condition.\n * const niceDays = query.get(['sunny', 'humid', 'calm'], {\n * index: 'weatherConditions'\n * }).run();\n *\n * @method Query#get\n * @param {array} keyList Key(s) defining the entity to retrieve. If\n * `keyList` is not an array (i.e. for a single-value key), it will be\n * wrapped in an array.\n * @param {object} [opts] Configuration options.\n * @param {string} [opts.string] Name of the secondary index to use in the\n * query. If no index is specified, the main index is used.\n * @returns {Query} A reference to itself for chaining.\n * @since 3.0.0\n */\n get (keyList = [], opts: any = {}) {\n if (this.data) {\n throw utils.err(`${DOMAIN}#get`)(500, INDEX_ERR)\n }\n if (keyList && !utils.isArray(keyList)) {\n keyList = [keyList]\n }\n if (!keyList.length) {\n this.getData()\n return this\n }\n this.data = this.collection.getIndex(opts.index).get(keyList)\n return this\n }\n\n /**\n * Find the entity or entities that match the provided keyLists.\n *\n * @example Get the posts where \"status\" is \"draft\" or \"inReview\".\n * const posts = query.getAll('draft', 'inReview', { index: 'status' }).run();\n *\n * @example Same as above.\n * const posts = query.getAll(['draft'], ['inReview'], { index: 'status' }).run();\n *\n * @method Query#getAll\n * @param {...Array} [keyList] Provide one or more keyLists, and all\n * entities matching each keyList will be retrieved. If no keyLists are\n * provided, all entities will be returned.\n * @param {object} [opts] Configuration options.\n * @param {string} [opts.index] Name of the secondary index to use in the\n * query. If no index is specified, the main index is used.\n * @returns {Query} A reference to itself for chaining.\n * @since 3.0.0\n */\n getAll(keyList?: [], opts?);\n getAll (...args) {\n let opts: any = {}\n if (this.data) {\n throw utils.err(`${DOMAIN}#getAll`)(500, INDEX_ERR)\n }\n if (!args.length || (args.length === 1 && utils.isObject(args[0]))) {\n this.getData()\n return this\n } else if (args.length && utils.isObject(args[args.length - 1])) {\n opts = args[args.length - 1]\n args.pop()\n }\n const index = this.collection.getIndex(opts.index)\n this.data = []\n args.forEach(keyList => {\n this.data = this.data.concat(index.get(keyList))\n })\n return this\n }\n\n /**\n * Return the current data result of this query.\n *\n * @method Query#getData\n * @returns {Array} The data in this query.\n * @since 3.0.0\n */\n getData () {\n if (!this.data) {\n this.data = this.collection.index.getAll()\n }\n return this.data\n }\n\n /**\n * Implementation used by the `like` operator. Takes a pattern and flags and\n * returns a `RegExp` instance that can test strings.\n *\n * @method Query#like\n * @param {string} pattern Testing pattern.\n * @param {string} flags Flags for the regular expression.\n * @returns {RegExp} Regular expression for testing strings.\n * @since 3.0.0\n */\n like (pattern, flags) {\n return new RegExp(\n `^${escape(pattern)\n .replace(percentRegExp, '.*')\n .replace(underscoreRegExp, '.')}$`,\n flags\n )\n }\n\n /**\n * Limit the result.\n *\n * @example Get only the first 2 posts.\n * const store = new JSData.DataStore();\n * store.defineMapper('post');\n * const posts = [\n * { author: 'John', age: 30, status: 'published', id: 1 },\n * { author: 'Sally', age: 31, status: 'draft', id: 2 },\n * { author: 'Mike', age: 32, status: 'draft', id: 3 },\n * { author: 'Adam', age: 33, status: 'deleted', id: 4 },\n * { author: 'Adam', age: 33, status: 'draft', id: 5 }\n * ];\n * store.add('post', posts);\n * const results = store.query('post').limit(2).run();\n * console.log(results);\n *\n * @method Query#limit\n * @param {number} num The maximum number of entities to keep in the result.\n * @returns {Query} A reference to itself for chaining.\n * @since 3.0.0\n */\n limit (num) {\n if (!utils.isNumber(num)) {\n throw utils.err(`${DOMAIN}#limit`, 'num')(400, 'number', num)\n }\n const data = this.getData()\n this.data = data.slice(0, Math.min(data.length, num))\n return this\n }\n\n /**\n * Apply a mapping function to the result data.\n *\n * @example\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('user');\n * const users = [\n * { name: 'Peter', age: 25, id: 1 },\n * { name: 'Jim', age: 19, id: 2 },\n * { name: 'Mike', age: 17, id: 3 },\n * { name: 'Alan', age: 29, id: 4 },\n * { name: 'Katie', age: 33, id: 5 }\n * ];\n * store.add('user', users);\n * const ages = store\n * .query('user')\n * .map(function (user) {\n * return user.age;\n * })\n * .run();\n * console.log(ages);\n *\n * @method Query#map\n * @param {Function} mapFn Mapping function.\n * @param {*} [thisArg] Context to which to bind `mapFn`.\n * @returns {Query} A reference to itself for chaining.\n * @since 3.0.0\n */\n map (mapFn, thisArg?) {\n this.data = this.getData().map(mapFn, thisArg)\n return this\n }\n\n /**\n * Return the result of calling the specified function on each item in this\n * collection's main index.\n *\n * @example\n * const stringAges = UserCollection.query().mapCall('toString').run();\n *\n * @method Query#mapCall\n * @param {string} funcName Name of function to call\n * @param args Remaining arguments to be passed to the function.\n * @returns {Query} A reference to itself for chaining.\n * @since 3.0.0\n */\n mapCall (funcName, ...args) {\n this.data = this.getData().map(item => item[funcName](...args))\n return this\n }\n\n /**\n * Complete the execution of the query and return the resulting data.\n *\n * @method Query#run\n * @returns {Array} The result of executing this query.\n * @since 3.0.0\n */\n run () {\n const data = this.data\n this.data = null\n return data\n }\n\n /**\n * Skip a number of results.\n *\n * @example Get all but the first 2 posts.\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post');\n * const posts = [\n * { author: 'John', age: 30, status: 'published', id: 1 },\n * { author: 'Sally', age: 31, status: 'draft', id: 2 },\n * { author: 'Mike', age: 32, status: 'draft', id: 3 },\n * { author: 'Adam', age: 33, status: 'deleted', id: 4 },\n * { author: 'Adam', age: 33, status: 'draft', id: 5 }\n * ];\n * store.add('post', posts);\n * const results = store.query('post').skip(2).run();\n * console.log(results);\n *\n * @method Query#skip\n * @param {number} num The number of entities to skip.\n * @returns {Query} A reference to itself for chaining.\n * @since 3.0.0\n */\n skip (num) {\n if (!utils.isNumber(num)) {\n throw utils.err(`${DOMAIN}#skip`, 'num')(400, 'number', num)\n }\n const data = this.getData()\n if (num < data.length) {\n this.data = data.slice(num)\n } else {\n this.data = []\n }\n return this\n }\n\n /**\n * The filtering operators supported by {@link Query#filter}, and which are\n * implemented by adapters (for the most part).\n *\n * @example Variant 1\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post');\n * const posts = [\n * { author: 'John', age: 30, status: 'published', id: 1 },\n * { author: 'Sally', age: 31, status: 'published', id: 2 },\n * { author: 'Mike', age: 32, status: 'published', id: 3 },\n * { author: 'Adam', age: 33, status: 'deleted', id: 4 },\n * { author: 'Adam', age: 33, status: 'published', id: 5 }\n * ];\n * store.add('post', posts);\n * const publishedPosts = store.filter('post', {\n * status: 'published',\n * limit: 2\n * });\n * console.log(publishedPosts);\n *\n *\n * @example Variant 2\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post')\n * const posts = [\n * { author: 'John', age: 30, status: 'published', id: 1 },\n * { author: 'Sally', age: 31, status: 'published', id: 2 },\n * { author: 'Mike', age: 32, status: 'published', id: 3 },\n * { author: 'Adam', age: 33, status: 'deleted', id: 4 },\n * { author: 'Adam', age: 33, status: 'published', id: 5 }\n * ];\n * store.add('post', posts);\n * const publishedPosts = store.filter('post', {\n * where: {\n * status: {\n * '==': 'published'\n * }\n * },\n * limit: 2\n * });\n * console.log(publishedPosts);\n *\n * @example Variant 3\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post');\n * const posts = [\n * { author: 'John', age: 30, status: 'published', id: 1 },\n * { author: 'Sally', age: 31, status: 'published', id: 2 },\n * { author: 'Mike', age: 32, status: 'published', id: 3 },\n * { author: 'Adam', age: 33, status: 'deleted', id: 4 },\n * { author: 'Adam', age: 33, status: 'published', id: 5 }\n * ];\n * store.add('post', posts);\n * const publishedPosts = store\n * .query('post')\n * .filter({ status: 'published' })\n * .limit(2)\n * .run();\n * console.log(publishedPosts);\n *\n * @example Variant 4\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post');\n * const posts = [\n * { author: 'John', age: 30, status: 'published', id: 1 },\n * { author: 'Sally', age: 31, status: 'published', id: 2 },\n * { author: 'Mike', age: 32, status: 'published', id: 3 },\n * { author: 'Adam', age: 33, status: 'deleted', id: 4 },\n * { author: 'Adam', age: 33, status: 'published', id: 5 }\n * ];\n * store.add('post', posts);\n * const publishedPosts = store\n * .query('post')\n * .filter({\n * where: {\n * status: {\n * '==': 'published'\n * }\n * }\n * })\n * .limit(2)\n * .run();\n * console.log(publishedPosts);\n *\n * @example Multiple operators\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post');\n * const posts = [\n * { author: 'John', age: 30, status: 'published', id: 1 },\n * { author: 'Sally', age: 31, status: 'published', id: 2 },\n * { author: 'Mike', age: 32, status: 'published', id: 3 },\n * { author: 'Adam', age: 33, status: 'deleted', id: 4 },\n * { author: 'Adam', age: 33, status: 'published', id: 5 }\n * ];\n * store.add('post', posts);\n *\n * const myPublishedPosts = store.filter('post', {\n * where: {\n * status: {\n * '==': 'published'\n * },\n * user_id: {\n * '==': currentUser.id\n * }\n * }\n * });\n *\n * console.log(myPublishedPosts);\n *\n * @name Query.ops\n * @property {Function} == Equality operator.\n * @property {Function} != Inequality operator.\n * @property {Function} > Greater than operator.\n * @property {Function} >= Greater than (inclusive) operator.\n * @property {Function} < Less than operator.\n * @property {Function} <= Less than (inclusive) operator.\n * @property {Function} isectEmpty Operator that asserts that the intersection\n * between two arrays is empty.\n * @property {Function} isectNotEmpty Operator that asserts that the\n * intersection between two arrays is __not__ empty.\n * @property {Function} in Operator that asserts whether a value is in an\n * array.\n * @property {Function} notIn Operator that asserts whether a value is __not__\n * in an array.\n * @property {Function} contains Operator that asserts whether an array\n * contains a value.\n * @property {Function} notContains Operator that asserts whether an array\n * does __not__ contain a value.\n * @since 3.0.0\n * @type {Object}\n */\n static ops = {\n '=' (value, predicate) {\n // tslint:disable-next-line:triple-equals\n return value == predicate; // eslint-disable-line\n },\n '==' (value, predicate) {\n // tslint:disable-next-line:triple-equals\n return value == predicate; // eslint-disable-line\n },\n '===' (value, predicate) {\n return value === predicate\n },\n '!=' (value, predicate) {\n // tslint:disable-next-line:triple-equals\n return value != predicate; // eslint-disable-line\n },\n '!==' (value, predicate) {\n return value !== predicate\n },\n '>' (value, predicate) {\n return value > predicate\n },\n '>=' (value, predicate) {\n return value >= predicate\n },\n '<' (value, predicate) {\n return value < predicate\n },\n '<=' (value, predicate) {\n return value <= predicate\n },\n isectEmpty (value, predicate) {\n return !utils.intersection(value || [], predicate || []).length\n },\n isectNotEmpty (value, predicate) {\n return utils.intersection(value || [], predicate || []).length\n },\n in (value, predicate) {\n return predicate.indexOf(value) !== -1\n },\n notIn (value, predicate) {\n return predicate.indexOf(value) === -1\n },\n contains (value, predicate) {\n return (value || []).indexOf(predicate) !== -1\n },\n notContains (value, predicate) {\n return (value || []).indexOf(predicate) === -1\n }\n };\n}\n","import utils from './utils'\n\n// TODO: remove this when the rest of the project is cleaned\nexport const belongsToType = 'belongsTo'\nexport const hasManyType = 'hasMany'\nexport const hasOneType = 'hasOne'\n\nconst DOMAIN = 'Relation'\n\nexport interface RelationOpts {\n type?: string\n}\n\nexport abstract class Relation {\n protected TYPE_NAME = DOMAIN;\n protected add;\n protected mapper;\n protected relation;\n name: string;\n private readonly localField;\n private readonly localKey;\n protected foreignKey;\n protected relatedMapper;\n protected inverse;\n\n constructor (relatedMapper, options: RelationOpts = {}) {\n options.type = (this.constructor as any).TYPE_NAME\n this.validateOptions(relatedMapper, options)\n\n if (typeof relatedMapper === 'object') {\n this.relatedMapper = relatedMapper\n }\n\n utils.fillIn(this, options)\n }\n\n get canAutoAddLinks () {\n return this.add === undefined || !!this.add\n }\n\n get relatedCollection () {\n return this.mapper.datastore.getCollection(this.relation)\n }\n\n validateOptions (related, opts) {\n const DOMAIN_ERR = `new ${DOMAIN}`\n\n const localField = opts.localField\n if (!localField) {\n throw utils.err(DOMAIN_ERR, 'opts.localField')(400, 'string', localField)\n }\n\n const foreignKey = (opts.foreignKey = opts.foreignKey || opts.localKey)\n if (!foreignKey && (opts.type === belongsToType || opts.type === hasOneType)) {\n throw utils.err(DOMAIN_ERR, 'opts.foreignKey')(400, 'string', foreignKey)\n }\n\n if (utils.isString(related)) {\n opts.relation = related\n if (!utils.isFunction(opts.getRelation)) {\n throw utils.err(DOMAIN_ERR, 'opts.getRelation')(400, 'function', opts.getRelation)\n }\n } else if (related) {\n opts.relation = related.name\n } else {\n throw utils.err(DOMAIN_ERR, 'related')(400, 'Mapper or string', related)\n }\n }\n\n assignTo (mapper) {\n this.name = mapper.name\n Object.defineProperty(this, 'mapper', { value: mapper })\n\n if (!mapper.relationList) Object.defineProperty(mapper, 'relationList', { value: [] })\n if (!mapper.relationFields) Object.defineProperty(mapper, 'relationFields', { value: [] })\n mapper.relationList.push(this)\n mapper.relationFields.push(this.localField)\n }\n\n canFindLinkFor (record?) {\n return !!(this.foreignKey || this.localKey)\n }\n\n getRelation () {\n return this.relatedMapper\n }\n\n getForeignKey (record) {\n return utils.get(record, this.mapper.idAttribute)\n }\n\n setForeignKey (record, relatedRecord) {\n if (!record || !relatedRecord) {\n return\n }\n\n this._setForeignKey(record, relatedRecord)\n }\n\n _setForeignKey (record, relatedRecords) {\n const idAttribute = this.mapper.idAttribute\n\n if (!utils.isArray(relatedRecords)) {\n relatedRecords = [relatedRecords]\n }\n\n relatedRecords.forEach(relatedRecord => {\n utils.set(relatedRecord, this.foreignKey, utils.get(record, idAttribute))\n })\n }\n\n getLocalField (record) {\n return utils.get(record, this.localField)\n }\n\n setLocalField (record, relatedData) {\n return utils.set(record, this.localField, relatedData)\n }\n\n getInverse (mapper) {\n if (!this.inverse) {\n this.findInverseRelation(mapper)\n }\n\n return this.inverse\n }\n\n findInverseRelation (mapper) {\n this.getRelation().relationList.forEach(def => {\n if (def.getRelation() === mapper && this.isInversedTo(def) && this !== def) {\n this.inverse = def\n return true\n }\n })\n }\n\n isInversedTo (def) {\n return !def.foreignKey || def.foreignKey === this.foreignKey\n }\n\n addLinkedRecords (records) {\n const datastore = this.mapper.datastore\n\n records.forEach(record => {\n let relatedData = this.getLocalField(record)\n\n if (utils.isFunction(this.add)) {\n relatedData = this.add(datastore, this, record)\n } else if (relatedData) {\n relatedData = this.linkRecord(record, relatedData)\n }\n\n const isEmptyLinks = !relatedData || (utils.isArray(relatedData) && !relatedData.length)\n\n if (isEmptyLinks && this.canFindLinkFor(record)) {\n relatedData = this.findExistingLinksFor(record)\n }\n\n if (relatedData) {\n this.setLocalField(record, relatedData)\n }\n })\n }\n\n removeLinkedRecords (relatedMapper, records) {\n const localField = this.localField\n records.forEach(record => {\n utils.set(record, localField, undefined)\n })\n }\n\n linkRecord (record, relatedRecord) {\n const relatedId = utils.get(relatedRecord, this.mapper.idAttribute)\n\n if (relatedId === undefined) {\n const unsaved = this.relatedCollection.unsaved()\n if (unsaved.indexOf(relatedRecord) === -1) {\n if (this.canAutoAddLinks) {\n relatedRecord = this.relatedCollection.add(relatedRecord)\n }\n }\n } else {\n if (relatedRecord !== this.relatedCollection.get(relatedId)) {\n this.setForeignKey(record, relatedRecord)\n\n if (this.canAutoAddLinks) {\n relatedRecord = this.relatedCollection.add(relatedRecord)\n }\n }\n }\n\n return relatedRecord\n }\n\n // e.g. user hasMany post via \"foreignKey\", so find all posts of user\n findExistingLinksByForeignKey (id) {\n if (id === undefined || id === null) {\n return\n }\n return this.relatedCollection.filter({\n [this.foreignKey]: id\n })\n }\n\n ensureLinkedDataHasProperType (props, opts) {\n const relatedMapper = this.getRelation()\n const relationData = this.getLocalField(props)\n\n if (utils.isArray(relationData) && (!relationData.length || relatedMapper.is(relationData[0]))) {\n return\n }\n\n if (relationData && !relatedMapper.is(relationData)) {\n utils.set(props, this.localField, relatedMapper.createRecord(relationData, opts))\n }\n }\n\n isRequiresParentId () {\n return false\n }\n\n isRequiresChildId () {\n return false\n }\n\n createChildRecord (props, relationData, opts) {\n this.setForeignKey(props, relationData)\n\n return this.createLinked(relationData, opts).then(result => {\n this.setLocalField(props, result)\n })\n }\n\n createLinked (props, opts) {\n const create = utils.isArray(props) ? 'createMany' : 'create'\n\n return this.getRelation()[create](props, opts)\n }\n\n abstract findExistingLinksFor(relatedMapper, record);\n abstract findExistingLinksFor(...record);\n\n static belongsTo;\n static hasMany;\n static hasOne;\n}\n","import utils, { safeSetLink } from './utils'\nimport Settable from './Settable'\nimport { hasManyType, hasOneType } from './Relation'\nimport Mapper from './Mapper'\n\nconst DOMAIN = 'Record'\n\nfunction superMethod (mapper, name) {\n const store = mapper.datastore\n if (store?.[name]) {\n return (...args) => store[name](mapper.name, ...args)\n }\n return mapper[name].bind(mapper)\n}\n\n// Cache these strings\nconst creatingPath = 'creating'\nconst noValidatePath = 'noValidate'\nconst keepChangeHistoryPath = 'keepChangeHistory'\nconst previousPath = 'previous'\n\n/**\n * js-data's Record class. An instance of `Record` corresponds to an in-memory\n * representation of a single row or document in a database, Firebase,\n * localstorage, etc. Basically, a `Record` instance represents whatever kind of\n * entity in your persistence layer that has a primary key.\n *\n * ```javascript\n * import {Record} from 'js-data'\n * ```\n *\n * @example Record#constructor\n * const JSData = require('js-data');\n * const { Record } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * // Instantiate a plain record\n * let record = new Record();\n * console.log('record: ' + JSON.stringify(record));\n *\n * // You can supply properties on instantiation\n * record = new Record({ name: 'John' });\n * console.log('record: ' + JSON.stringify(record));\n *\n * @example Record#constructor2\n * const JSData = require('js-data');\n * const { Mapper } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * // Instantiate a record that's associated with a Mapper:\n * const UserMapper = new Mapper({ name: 'user' });\n * const User = UserMapper.recordClass;\n * const user = UserMapper.createRecord({ name: 'John' });\n * const user2 = new User({ name: 'Sally' });\n * console.log('user: ' + JSON.stringify(user));\n * console.log('user2: ' + JSON.stringify(user2));\n *\n * @example Record#constructor3\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new Container();\n * store.defineMapper('user');\n *\n * // Instantiate a record that's associated with a store's Mapper\n * const user = store.createRecord('user', { name: 'John' });\n * console.log('user: ' + JSON.stringify(user));\n *\n * @example Record#constructor4\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new Container();\n * store.defineMapper('user', {\n * schema: {\n * properties: {\n * name: { type: 'string' }\n * }\n * }\n * });\n *\n * // Validate on instantiation\n * const user = store.createRecord('user', { name: 1234 });\n * console.log('user: ' + JSON.stringify(user));\n *\n * @example Record#constructor5\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new Container();\n * store.defineMapper('user', {\n * schema: {\n * properties: {\n * name: { type: 'string' }\n * }\n * }\n * });\n *\n * // Skip validation on instantiation\n * const user = store.createRecord('user', { name: 1234 }, { noValidate: true });\n * console.log('user: ' + JSON.stringify(user));\n * console.log('user.isValid(): ' + user.isValid());\n *\n * @class Record\n * @extends Settable\n * @param {object} [props] The initial properties of the new Record instance.\n * @param {object} [opts] Configuration options.\n * @param {boolean} [opts.noValidate=false] Whether to skip validation on the\n * initial properties.\n * @param {boolean} [opts.validateOnSet=true] Whether to enable setter\n * validation on properties after the Record has been initialized.\n * @since 3.0.0\n */\nexport default class Record extends Settable {\n static mapper: Mapper;\n\n constructor (props: any = {}, opts: any = {}) {\n super()\n const _set = this._set\n const mapper = (this.constructor as any).mapper\n\n _set(creatingPath, true)\n _set(noValidatePath, !!opts.noValidate)\n _set(\n keepChangeHistoryPath,\n opts.keepChangeHistory === undefined ? (mapper ? mapper.keepChangeHistory : true) : opts.keepChangeHistory\n )\n\n // Set the idAttribute value first, if it exists.\n const id = mapper ? utils.get(props, mapper.idAttribute) : undefined\n if (id !== undefined) {\n utils.set(this, mapper.idAttribute, id)\n }\n\n utils.fillIn(this, props)\n _set(creatingPath, false)\n if (opts.validateOnSet !== undefined) {\n _set(noValidatePath, !opts.validateOnSet)\n } else if (mapper?.validateOnSet !== undefined) {\n _set(noValidatePath, !mapper.validateOnSet)\n } else {\n _set(noValidatePath, false)\n }\n _set(previousPath, mapper ? mapper.toJSON(props) : utils.plainCopy(props))\n }\n\n /**\n * Returns the {@link Mapper} paired with this record's class, if any.\n *\n * @method Record#_mapper\n * @returns {Mapper} The {@link Mapper} paired with this record's class, if any.\n * @since 3.0.0\n */\n _mapper () {\n const mapper = (this.constructor as any).mapper\n if (!mapper) {\n throw utils.err(`${DOMAIN}#_mapper`, '')(404, 'mapper')\n }\n return mapper\n }\n\n /**\n * Lifecycle hook.\n *\n * @method Record#afterLoadRelations\n * @param {string[]} relations The `relations` argument passed to {@link Record#loadRelations}.\n * @param {object} opts The `opts` argument passed to {@link Record#loadRelations}.\n * @since 3.0.0\n */\n afterLoadRelations (relations: string[], opts?) {}\n\n /**\n * Lifecycle hook.\n *\n * @method Record#beforeLoadRelations\n * @param {string[]} relations The `relations` argument passed to {@link Record#loadRelations}.\n * @param {object} opts The `opts` argument passed to {@link Record#loadRelations}.\n * @since 3.0.0\n */\n beforeLoadRelations (relations: string[], opts?) {}\n\n /**\n * Return the change history of this record since it was instantiated or\n * {@link Record#commit} was called.\n *\n * @method Record#changeHistory\n * @since 3.0.0\n */\n changeHistory () {\n return (this._get('history') || []).slice()\n }\n\n /**\n * Return changes to this record since it was instantiated or\n * {@link Record#commit} was called.\n *\n * @example Record#changes\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new Container();\n * store.defineMapper('user');\n * const user = store.createRecord('user');\n * console.log('user changes: ' + JSON.stringify(user.changes()));\n * user.name = 'John';\n * console.log('user changes: ' + JSON.stringify(user.changes()));\n *\n * @method Record#changes\n * @param [opts] Configuration options.\n * @param {Function} [opts.equalsFn={@link utils.deepEqual}] Equality function.\n * @param {array} [opts.ignore=[]] Array of strings or RegExp of fields to ignore.\n * @returns {Object} Object describing the changes to this record since it was\n * instantiated or its {@link Record#commit} method was last called.\n * @since 3.0.0\n */\n changes (opts: any = {}) {\n return utils.diffObjects(typeof this.toJSON === 'function' ? this.toJSON(opts) : this, this._get('previous'), opts)\n }\n\n /**\n * Make the record's current in-memory state it's only state, with any\n * previous property values being set to current values.\n *\n * @example Record#commit\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new Container();\n * store.defineMapper('user');\n * const user = store.createRecord('user');\n * console.log('user hasChanges: ' + user.hasChanges());\n * user.name = 'John';\n * console.log('user hasChanges: ' + user.hasChanges());\n * user.commit();\n * console.log('user hasChanges: ' + user.hasChanges());\n *\n * @method Record#commit\n * @param {object} [opts] Configuration options. Passed to {@link Record#toJSON}.\n * @since 3.0.0\n */\n commit (opts?) {\n this._set('changed') // unset\n this._set('changing', false)\n this._set('history', []) // clear history\n this._set('previous', this.toJSON(opts))\n }\n\n /**\n * Call {@link Mapper#destroy} using this record's primary key.\n *\n * @example\n * import { Container } from 'js-data';\n * import { RethinkDBAdapter } from 'js-data-rethinkdb';\n *\n * const store = new Container();\n * store.registerAdapter('rethink', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('user');\n * store.find('user', 1234).then((user) => {\n * console.log(user.id); // 1234\n *\n * // Destroy this user from the database\n * return user.destroy();\n * });\n *\n * @method Record#destroy\n * @param {object} [opts] Configuration options passed to {@link Mapper#destroy}.\n * @returns {Promise} The result of calling {@link Mapper#destroy} with the\n * primary key of this record.\n * @since 3.0.0\n */\n destroy (opts: any = {}) {\n const mapper = this._mapper()\n return superMethod(mapper, 'destroy')(utils.get(this, mapper.idAttribute), opts)\n }\n\n /**\n * Return the value at the given path for this instance.\n *\n * @example Record#get\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n * const store = new Container();\n * store.defineMapper('user');\n *\n * const user = store.createRecord('user', { name: 'Bob' });\n * console.log('user.get(\"name\"): ' + user.get('name'));\n *\n * @method Record#get\n * @param {string} key Path of value to retrieve.\n * @returns {*} Value at path.\n * @since 3.0.0\n */\n get (key) {\n return utils.get(this, key)\n }\n\n /**\n * Return whether this record has changed since it was instantiated or\n * {@link Record#commit} was called.\n *\n * @example Record#hasChanges\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n * const store = new Container();\n * store.defineMapper('user');\n * const user = store.createRecord('user');\n * console.log('user hasChanges: ' + user.hasChanges());\n * user.name = 'John';\n * console.log('user hasChanges: ' + user.hasChanges());\n * user.commit();\n * console.log('user hasChanges: ' + user.hasChanges());\n *\n * @method Record#hasChanges\n * @param [opts] Configuration options.\n * @param {Function} [opts.equalsFn={@link utils.deepEqual}] Equality function.\n * @param {array} [opts.ignore=[]] Array of strings or RegExp of fields to ignore.\n * @returns {boolean} Return whether the record has changed since it was\n * instantiated or since its {@link Record#commit} method was called.\n * @since 3.0.0\n */\n hasChanges (opts?) {\n const quickHasChanges = !!(this._get('changed') || []).length\n return (\n quickHasChanges ||\n utils.areDifferent(typeof this.toJSON === 'function' ? this.toJSON(opts) : this, this._get('previous'), opts)\n )\n }\n\n /**\n * Return whether the record is unsaved. Records that have primary keys are\n * considered \"saved\". Records without primary keys are considered \"unsaved\".\n *\n * @example Record#isNew\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n * const store = new Container();\n * store.defineMapper('user');\n * const user = store.createRecord('user', {\n * id: 1234\n * });\n * const user2 = store.createRecord('user');\n * console.log('user isNew: ' + user.isNew()); // false\n * console.log('user2 isNew: ' + user2.isNew()); // true\n *\n * @method Record#isNew\n * @returns {boolean} Whether the record is unsaved.\n * @since 3.0.0\n */\n isNew (opts?) {\n return utils.get(this, this._mapper().idAttribute) === undefined\n }\n\n /**\n * Return whether the record in its current state passes validation.\n *\n * @example Record#isValid\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n * const store = new Container();\n * store.defineMapper('user', {\n * schema: {\n * properties: {\n * name: { type: 'string' }\n * }\n * }\n * });\n * const user = store.createRecord('user', {\n * name: 1234\n * }, {\n * noValidate: true // this allows us to put the record into an invalid state\n * });\n * console.log('user isValid: ' + user.isValid());\n * user.name = 'John';\n * console.log('user isValid: ' + user.isValid());\n *\n * @method Record#isValid\n * @param {object} [opts] Configuration options. Passed to {@link Mapper#validate}.\n * @returns {boolean} Whether the record in its current state passes\n * validation.\n * @since 3.0.0\n */\n isValid (opts) {\n return !this._mapper().validate(this, opts)\n }\n\n removeInverseRelation (currentParent, id, inverseDef, idAttribute) {\n if (inverseDef.type === hasOneType) {\n safeSetLink(currentParent, inverseDef.localField, undefined)\n } else if (inverseDef.type === hasManyType) {\n // e.g. remove comment from otherPost.comments\n const children = utils.get(currentParent, inverseDef.localField)\n if (id === undefined) {\n utils.remove(children, child => child === this)\n } else {\n utils.remove(children, child => child === this || id === utils.get(child, idAttribute))\n }\n }\n }\n\n setupInverseRelation (record, id, inverseDef, idAttribute) {\n // Update (set) inverse relation\n if (inverseDef.type === hasOneType) {\n // e.g. someUser.profile = profile\n safeSetLink(record, inverseDef.localField, this)\n } else if (inverseDef.type === hasManyType) {\n // e.g. add comment to somePost.comments\n const children = utils.get(record, inverseDef.localField)\n if (id === undefined) {\n utils.noDupeAdd(children, this, child => child === this)\n } else {\n utils.noDupeAdd(children, this, child => child === this || id === utils.get(child, idAttribute))\n }\n }\n }\n\n /**\n * Lazy load relations of this record, to be attached to the record once their\n * loaded.\n *\n * @example\n * import { Container } from 'js-data';\n * import { RethinkDBAdapter } from 'js-data-rethinkdb';\n *\n * const store = new Container();\n * store.registerAdapter('rethink', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('user', {\n * relations: {\n * hasMany: {\n * post: {\n * localField: 'posts',\n * foreignKey: 'user_id'\n * }\n * }\n * }\n * });\n * store.defineMapper('post', {\n * relations: {\n * belongsTo: {\n * user: {\n * localField: 'user',\n * foreignKey: 'user_id'\n * }\n * }\n * }\n * });\n * store.find('user', 1234).then((user) => {\n * console.log(user.id); // 1234\n *\n * // Load the user's post relations\n * return user.loadRelations(['post']);\n * }).then((user) => {\n * console.log(user.posts); // [{...}, {...}, ...]\n * });\n *\n * @method Record#loadRelations\n * @param {string[]} [relations] List of relations to load. Can use localField\n * names or Mapper names to pick relations.\n * @param {object} [opts] Configuration options.\n * @returns {Promise} Resolves with the record, with the loaded relations now\n * attached.\n * @since 3.0.0\n */\n loadRelations (relations: string[] | string | any = [], opts: any = {}) {\n let op\n const mapper = this._mapper()\n\n if (utils.isString(relations)) {\n relations = [relations]\n }\n opts.with = relations\n\n // Fill in \"opts\" with the Model's configuration\n utils._(opts, mapper)\n opts.adapter = mapper.getAdapterName(opts)\n\n // beforeLoadRelations lifecycle hook\n op = opts.op = 'beforeLoadRelations'\n return utils\n .resolve(this[op](relations, opts))\n .then(() => {\n // Now delegate to the adapter\n op = opts.op = 'loadRelations'\n mapper.dbg(op, this, relations, opts)\n const tasks = []\n let task\n utils.forEachRelation(mapper, opts, (def, optsCopy) => {\n const relatedMapper = def.getRelation()\n optsCopy.raw = false\n if (utils.isFunction(def.load)) {\n task = def.load(mapper, def, this, opts)\n } else if (def.type === 'hasMany' || def.type === 'hasOne') {\n if (def.foreignKey) {\n task = superMethod(relatedMapper, 'findAll')(\n {\n [def.foreignKey]: utils.get(this, mapper.idAttribute)\n },\n optsCopy\n ).then(relatedData =>\n def.type === 'hasOne' ? (relatedData.length ? relatedData[0] : undefined) : relatedData\n )\n } else if (def.localKeys) {\n task = superMethod(\n relatedMapper,\n 'findAll'\n )({\n where: {\n [relatedMapper.idAttribute]: {\n in: utils.get(this, def.localKeys)\n }\n }\n })\n } else if (def.foreignKeys) {\n task = superMethod(relatedMapper, 'findAll')(\n {\n where: {\n [def.foreignKeys]: {\n contains: utils.get(this, mapper.idAttribute)\n }\n }\n },\n opts\n )\n }\n } else if (def.type === 'belongsTo') {\n const key = utils.get(this, def.foreignKey)\n if (utils.isSorN(key)) {\n task = superMethod(relatedMapper, 'find')(key, optsCopy)\n }\n }\n if (task) {\n task = task.then(relatedData => {\n def.setLocalField(this, relatedData)\n })\n tasks.push(task)\n }\n })\n return Promise.all(tasks)\n })\n .then(() => {\n // afterLoadRelations lifecycle hook\n op = opts.op = 'afterLoadRelations'\n return utils.resolve(this[op](relations, opts)).then(() => this)\n })\n }\n\n /**\n * Return the properties with which this record was instantiated.\n *\n * @example Record#previous\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n * const store = new Container();\n * store.defineMapper('user');\n * const user = store.createRecord('user', {\n * name: 'William'\n * });\n * console.log('user previous: ' + JSON.stringify(user.previous()));\n * user.name = 'Bob';\n * console.log('user previous: ' + JSON.stringify(user.previous()));\n * user.commit();\n * console.log('user previous: ' + JSON.stringify(user.previous()));\n *\n * @method Record#previous\n * @param {string} [key] If specified, return just the initial value of the\n * given key.\n * @returns {Object} The initial properties of this record.\n * @since 3.0.0\n */\n previous (key) {\n if (key) {\n return this._get(`previous.${key}`)\n }\n return this._get('previous')\n }\n\n /**\n * Revert changes to this record back to the properties it had when it was\n * instantiated.\n *\n * @example Record#revert\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n * const store = new Container();\n * store.defineMapper('user');\n * const user = store.createRecord('user', {\n * name: 'William'\n * });\n * console.log('user: ' + JSON.stringify(user));\n * user.name = 'Bob';\n * console.log('user: ' + JSON.stringify(user));\n * user.revert();\n * console.log('user: ' + JSON.stringify(user));\n *\n * @method Record#revert\n * @param {object} [opts] Configuration options.\n * @param {string[]} [opts.preserve] Array of strings or Regular Expressions\n * denoting properties that should not be reverted.\n * @since 3.0.0\n */\n revert (opts: any = {}) {\n const previous = this._get('previous')\n opts.preserve = opts.preserve || []\n utils.forOwn(this, (value, key) => {\n if (\n key !== this._mapper().idAttribute &&\n !previous.hasOwnProperty(key) &&\n this.hasOwnProperty(key) &&\n opts.preserve.indexOf(key) === -1\n ) {\n delete this[key]\n }\n })\n utils.forOwn(previous, (value, key) => {\n if (opts.preserve.indexOf(key) === -1) {\n this[key] = value\n }\n })\n this.commit()\n }\n\n /**\n * Delegates to {@link Mapper#create} or {@link Mapper#update}.\n *\n * @example\n * import { Container } from 'js-data';\n * import { RethinkDBAdapter } from 'js-data-rethinkdb';\n *\n * const store = new Container();\n * store.registerAdapter('rethink', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('session');\n * const session = store.createRecord('session', { topic: 'Node.js' });\n *\n * // Create a new record in the database\n * session.save().then(() => {\n * console.log(session.id); // 1234\n *\n * session.skill_level = 'beginner';\n *\n * // Update the record in the database\n * return session.save();\n * });\n *\n * @method Record#save\n * @param {object} [opts] Configuration options. See {@link Mapper#create} and\n * {@link Mapper#update}.\n * @param {boolean} [opts.changesOnly] Equality function. Default uses `===`.\n * @param {Function} [opts.equalsFn] Passed to {@link Record#changes} when\n * `opts.changesOnly` is `true`.\n * @param {array} [opts.ignore] Passed to {@link Record#changes} when\n * `opts.changesOnly` is `true`.\n * @returns {Promise} The result of calling {@link Mapper#create} or\n * {@link Mapper#update}.\n * @since 3.0.0\n */\n save (opts: any = {}) {\n const mapper = this._mapper()\n const id = utils.get(this, mapper.idAttribute)\n let props: any = this\n\n const postProcess = result => {\n const record = opts.raw ? result.data : result\n if (record) {\n utils.deepMixIn(this, record)\n this.commit()\n }\n return result\n }\n\n if (id === undefined) {\n return superMethod(mapper, 'create')(props, opts).then(postProcess)\n }\n if (opts.changesOnly) {\n const changes = this.changes(opts)\n props = {}\n utils.fillIn(props, changes.added)\n utils.fillIn(props, changes.changed)\n }\n return superMethod(mapper, 'update')(id, props, opts).then(postProcess)\n }\n\n /**\n * Set the value for a given key, or the values for the given keys if \"key\" is\n * an object. Triggers change events on those properties that have `track: true`\n * in {@link Mapper#schema}.\n *\n * @example Record#set\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n * const store = new Container();\n * store.defineMapper('user');\n *\n * const user = store.createRecord('user');\n * console.log('user: ' + JSON.stringify(user));\n *\n * user.set('name', 'Bob');\n * console.log('user: ' + JSON.stringify(user));\n *\n * user.set({ age: 30, role: 'admin' });\n * console.log('user: ' + JSON.stringify(user));\n *\n * @fires Record#change\n * @method Record#set\n * @param {(string|Object)} key Key to set or hash of key-value pairs to set.\n * @param {*} [value] Value to set for the given key.\n * @param {object} [opts] Configuration options.\n * @param {boolean} [opts.silent=false] Whether to trigger change events.\n * @since 3.0.0\n */\n set (key: string | any, value?, opts?) {\n if (utils.isObject(key)) {\n opts = value\n }\n opts = opts || {}\n if (opts.silent) {\n this._set('silent', true)\n }\n utils.set(this, key, value)\n if (!this._get('eventId')) {\n this._set('silent') // unset\n }\n }\n\n /**\n * Return a plain object representation of this record. If the class from\n * which this record was created has a Mapper, then {@link Mapper#toJSON} will\n * be called with this record instead.\n *\n * @example Record#toJSON\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n * const store = new Container();\n * store.defineMapper('user', {\n * schema: {\n * properties: {\n * name: { type: 'string' }\n * }\n * }\n * });\n *\n * const user = store.createRecord('user', {\n * name: 'John',\n * $$hashKey: '1234'\n * });\n * console.log('user: ' + JSON.stringify(user.toJSON()));\n *\n * @method Record#toJSON\n * @param {object} [opts] Configuration options.\n * @param {string[]} [opts.with] Array of relation names or relation fields\n * to include in the representation. Only available as an option if the class\n * from which this record was created has a Mapper and this record resides in\n * an instance of {@link DataStore}.\n * @returns {Object} Plain object representation of this record.\n * @since 3.0.0\n */\n toJSON (opts?) {\n const mapper = (this.constructor as typeof Record).mapper\n if (mapper) {\n return mapper.toJSON(this, opts)\n } else {\n const json = {}\n utils.forOwn(this, (prop, key) => {\n json[key] = utils.plainCopy(prop)\n })\n return json\n }\n }\n\n /**\n * Unset the value for a given key. Triggers change events on those properties\n * that have `track: true` in {@link Mapper#schema}.\n *\n * @example Record#unset\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n * const store = new Container();\n * store.defineMapper('user');\n *\n * const user = store.createRecord('user', {\n * name: 'John'\n * });\n * console.log('user: ' + JSON.stringify(user));\n *\n * user.unset('name');\n * console.log('user: ' + JSON.stringify(user));\n *\n * @method Record#unset\n * @param {string} key Key to unset.\n * @param {object} [opts] Configuration options.\n * @param {boolean} [opts.silent=false] Whether to trigger change events.\n * @since 3.0.0\n */\n unset (key: string, opts?) {\n this.set(key, undefined, opts)\n }\n\n /**\n * Validate this record based on its current properties.\n *\n * @example Record#validate\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n * const store = new Container();\n * store.defineMapper('user', {\n * schema: {\n * properties: {\n * name: { type: 'string' }\n * }\n * }\n * });\n * const user = store.createRecord('user', {\n * name: 1234\n * }, {\n * noValidate: true // this allows us to put the record into an invalid state\n * });\n * console.log('user validation: ' + JSON.stringify(user.validate()));\n * user.name = 'John';\n * console.log('user validation: ' + user.validate());\n *\n * @method Record#validate\n * @param {object} [opts] Configuration options. Passed to {@link Mapper#validate}.\n * @returns {*} Array of errors or `undefined` if no errors.\n * @since 3.0.0\n */\n validate (opts) {\n return this._mapper().validate(this, opts)\n }\n\n static creatingPath = creatingPath;\n static noValidatePath = noValidatePath;\n static keepChangeHistoryPath = keepChangeHistoryPath;\n static previousPath = previousPath;\n}\n\n/**\n * Allow records to emit events.\n *\n * An record's registered listeners are stored in the record's private data.\n */\nutils.eventify(\n Record.prototype,\n function () {\n return this._get('events')\n },\n function (value) {\n this._set('events', value)\n }\n)\n\n/**\n * Fired when a record changes. Only works for records that have tracked fields.\n * See {@link Record~changeListener} on how to listen for this event.\n *\n * @event Record#change\n * @see Record~changeListener\n */\n\n/**\n * Callback signature for the {@link Record#event:change} event.\n *\n * @example\n * function onChange (record, changes) {\n * // do something\n * }\n * record.on('change', onChange);\n *\n * @callback Record~changeListener\n * @param {Record} The Record that changed.\n * @param {object} The changes.\n * @see Record#event:change\n * @since 3.0.0\n */\n\n/**\n * Create a subclass of this Record:\n * @example Record.extend\n * const JSData = require('js-data');\n * const { Record } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * // Extend the class using ES2015 class syntax.\n * class CustomRecordClass extends Record {\n * foo () { return 'bar'; }\n * static beep () { return 'boop'; }\n * }\n * const customRecord = new CustomRecordClass();\n * console.log(customRecord.foo());\n * console.log(CustomRecordClass.beep());\n *\n * // Extend the class using alternate method.\n * const OtherRecordClass = Record.extend({\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * });\n * const otherRecord = new OtherRecordClass();\n * console.log(otherRecord.foo());\n * console.log(OtherRecordClass.beep());\n *\n * // Extend the class, providing a custom constructor.\n * function AnotherRecordClass () {\n * Record.call(this);\n * this.created_at = new Date().getTime();\n * }\n * Record.extend({\n * constructor: AnotherRecordClass,\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * });\n * const anotherRecord = new AnotherRecordClass();\n * console.log(anotherRecord.created_at);\n * console.log(anotherRecord.foo());\n * console.log(AnotherRecordClass.beep());\n *\n * @method Record.extend\n * @param {object} [props={}] Properties to add to the prototype of the\n * subclass.\n * @param {object} [props.constructor] Provide a custom constructor function\n * to be used as the subclass itself.\n * @param {object} [classProps={}] Static properties to add to the subclass.\n * @returns {Constructor} Subclass of this Record class.\n * @since 3.0.0\n */\n","export function sort (a, b, hashCode) {\n // Short-circuit comparison if a and b are strictly equal\n // This is absolutely necessary for indexed objects that\n // don't have the idAttribute field\n if (a === b) {\n return 0\n } else if (hashCode) {\n a = hashCode(a)\n b = hashCode(b)\n }\n return (a === null && b === null) || (a === undefined && b === undefined)\n ? -1\n : a === null || a === undefined\n ? -1\n : b === null || b === undefined\n ? 1\n : a < b\n ? -1\n : a > b\n ? 1\n : 0\n}\n\nexport function insertAt (array, index, value) {\n array.splice(index, 0, value)\n return array\n}\n\nexport function removeAt (array, index) {\n array.splice(index, 1)\n return array\n}\n\nexport function binarySearch (array, value, field?) {\n let lo = 0\n let hi = array.length\n let compared\n let mid\n\n while (lo < hi) {\n // tslint:disable-next-line:no-bitwise\n mid = ((lo + hi) / 2) | 0\n compared = sort(value, array[mid], field)\n if (compared === 0) {\n return {\n found: true,\n index: mid\n }\n } else if (compared < 0) {\n hi = mid\n } else {\n lo = mid + 1\n }\n }\n\n return {\n found: false,\n index: hi\n }\n}\n","// Copyright (c) 2015, InternalFX.\n\n// Permission to use, copy, modify, and/or distribute this software for any purpose with or\n// without fee is hereby granted, provided that the above copyright notice and this permission\n// notice appear in all copies.\n\n// THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO\n// THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT\n// SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR\n// ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION\n// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE\n// USE OR PERFORMANCE OF THIS SOFTWARE.\n\n// Modifications\n// Copyright 2015-2016 Jason Dobry\n//\n// Summary of modifications:\n// Reworked dependencies so as to re-use code already in js-data\n// Removed unused code\nimport utils from '../../src/utils'\nimport { binarySearch, insertAt, removeAt } from './_utils'\n\nexport interface IndexOpts {\n fieldGetter?\n hashCode?\n}\n\nexport default class Index {\n fieldList: any[];\n fieldGetter: any;\n hashCode: any;\n isIndex: boolean;\n keys: any[];\n values: any[];\n\n constructor (fieldList = [], opts: IndexOpts = {}) {\n if (!utils.isArray(fieldList)) {\n throw new Error('fieldList must be an array.')\n }\n\n this.fieldList = fieldList\n this.fieldGetter = opts.fieldGetter\n this.hashCode = opts.hashCode\n this.isIndex = true\n this.keys = []\n this.values = []\n }\n\n set (keyList, value) {\n if (!utils.isArray(keyList)) {\n keyList = [keyList]\n }\n\n const key = keyList.shift() || undefined\n const pos = binarySearch(this.keys, key)\n\n if (keyList.length === 0) {\n if (pos.found) {\n const dataLocation = binarySearch(this.values[pos.index], value, this.hashCode)\n if (!dataLocation.found) {\n insertAt(this.values[pos.index], dataLocation.index, value)\n }\n } else {\n insertAt(this.keys, pos.index, key)\n insertAt(this.values, pos.index, [value])\n }\n } else {\n if (pos.found) {\n this.values[pos.index].set(keyList, value)\n } else {\n insertAt(this.keys, pos.index, key)\n const newIndex = new Index([], { hashCode: this.hashCode })\n newIndex.set(keyList, value)\n insertAt(this.values, pos.index, newIndex)\n }\n }\n }\n\n get (keyList?) {\n if (!utils.isArray(keyList)) {\n keyList = [keyList]\n }\n\n const key = keyList.shift() || undefined\n const pos = binarySearch(this.keys, key)\n\n if (keyList.length === 0) {\n if (pos.found) {\n if (this.values[pos.index].isIndex) {\n return this.values[pos.index].getAll()\n } else {\n return this.values[pos.index].slice()\n }\n } else {\n return []\n }\n } else {\n if (pos.found) {\n return this.values[pos.index].get(keyList)\n } else {\n return []\n }\n }\n }\n\n getAll (opts: any = {}) {\n let results = []\n const values = this.values\n if (opts.order === 'desc') {\n for (let i = values.length - 1; i >= 0; i--) {\n const value = values[i]\n if (value.isIndex) {\n results = results.concat(value.getAll(opts))\n } else {\n results = results.concat(value)\n }\n }\n } else {\n for (const value of values) {\n if (value.isIndex) {\n results = results.concat(value.getAll(opts))\n } else {\n results = results.concat(value)\n }\n }\n }\n return results\n }\n\n visitAll (cb, thisArg?) {\n this.values.forEach(value => {\n if (value.isIndex) {\n value.visitAll(cb, thisArg)\n } else {\n value.forEach(cb, thisArg)\n }\n })\n }\n\n between (leftKeys, rightKeys, opts: any = {}) {\n if (!utils.isArray(leftKeys)) {\n leftKeys = [leftKeys]\n }\n if (!utils.isArray(rightKeys)) {\n rightKeys = [rightKeys]\n }\n utils.fillIn(opts, {\n leftInclusive: true,\n rightInclusive: false,\n limit: undefined,\n offset: 0\n })\n\n const results = this._between(leftKeys, rightKeys, opts)\n\n if (opts.limit) {\n return results.slice(opts.offset, opts.limit + opts.offset)\n } else {\n return results.slice(opts.offset)\n }\n }\n\n _between (leftKeys, rightKeys, opts) {\n let results = []\n\n const leftKey = leftKeys.shift()\n const rightKey = rightKeys.shift()\n\n let pos\n\n if (leftKey !== undefined) {\n pos = binarySearch(this.keys, leftKey)\n } else {\n pos = {\n found: false,\n index: 0\n }\n }\n\n if (leftKeys.length === 0) {\n if (pos.found && opts.leftInclusive === false) {\n pos.index += 1\n }\n\n for (let i = pos.index; i < this.keys.length; i += 1) {\n if (rightKey !== undefined) {\n if (opts.rightInclusive) {\n if (this.keys[i] > rightKey) {\n break\n }\n } else {\n if (this.keys[i] >= rightKey) {\n break\n }\n }\n }\n\n if (this.values[i].isIndex) {\n results = results.concat(this.values[i].getAll())\n } else {\n results = results.concat(this.values[i])\n }\n\n if (opts.limit) {\n if (results.length >= opts.limit + opts.offset) {\n break\n }\n }\n }\n } else {\n for (let i = pos.index; i < this.keys.length; i += 1) {\n const currKey = this.keys[i]\n if (currKey > rightKey) {\n break\n }\n\n if (this.values[i].isIndex) {\n if (currKey === leftKey) {\n results = results.concat(\n this.values[i]._between(\n utils.copy(leftKeys),\n rightKeys.map(() => undefined),\n opts\n )\n )\n } else if (currKey === rightKey) {\n results = results.concat(\n this.values[i]._between(\n leftKeys.map(() => undefined),\n utils.copy(rightKeys),\n opts\n )\n )\n } else {\n results = results.concat(this.values[i].getAll())\n }\n } else {\n results = results.concat(this.values[i])\n }\n\n if (opts.limit) {\n if (results.length >= opts.limit + opts.offset) {\n break\n }\n }\n }\n }\n\n if (opts.limit) {\n return results.slice(0, opts.limit + opts.offset)\n } else {\n return results\n }\n }\n\n peek () {\n return this.values.length ? (this.values[0].isIndex ? this.values[0].peek() : this.values[0]) : []\n }\n\n clear () {\n this.keys = []\n this.values = []\n }\n\n insertRecord (data) {\n const keyList = this.fieldList.map(field =>\n utils.isFunction(field) ? field(data) || undefined : data[field] || undefined\n )\n this.set(keyList, data)\n }\n\n removeRecord (data) {\n let removed\n const isUnique = this.hashCode(data) !== undefined\n this.values.forEach((value, i) => {\n if (value.isIndex) {\n if (value.removeRecord(data)) {\n if (value.keys.length === 0) {\n removeAt(this.keys, i)\n removeAt(this.values, i)\n }\n removed = true\n return false\n }\n } else {\n let dataLocation: any = {}\n if (this.keys[i] === undefined || !isUnique) {\n for (let j = value.length - 1; j >= 0; j--) {\n if (value[j] === data) {\n dataLocation = {\n found: true,\n index: j\n }\n break\n }\n }\n } else if (isUnique) {\n dataLocation = binarySearch(value, data, this.hashCode)\n }\n if (dataLocation.found) {\n removeAt(value, dataLocation.index)\n if (value.length === 0) {\n removeAt(this.keys, i)\n removeAt(this.values, i)\n }\n removed = true\n return false\n }\n }\n })\n return removed ? data : undefined\n }\n\n updateRecord (data) {\n const removed = this.removeRecord(data)\n if (removed !== undefined) {\n this.insertRecord(data)\n }\n }\n}\n","import utils from './utils'\nimport Component, { ComponentOpts } from './Component'\nimport Query from './Query'\nimport Record from './Record'\nimport Index from './mindex'\n\nconst { noValidatePath } = Record\n\nconst DOMAIN = 'Collection'\n\nexport interface CollectionOpts extends ComponentOpts {\n /**\n * Whether to call {@link Record#commit} on records that are added to the\n * collection and already exist in the collection.\n *\n * @name Collection#commitOnMerge\n * @type {boolean}\n * @default true\n */\n commitOnMerge?: boolean\n\n /**\n * Whether record events should bubble up and be emitted by the collection.\n *\n * @name Collection#emitRecordEvents\n * @type {boolean}\n * @default true\n */\n emitRecordEvents?: boolean\n\n /**\n * Field to be used as the unique identifier for records in this collection.\n * Defaults to `\"id\"` unless {@link Collection#mapper} is set, in which case\n * this will default to {@link Mapper#idAttribute}.\n *\n * @name Collection#idAttribute\n * @type {string}\n * @default \"id\"\n */\n idAttribute?: string\n\n /**\n * What to do when inserting a record into this Collection that shares a\n * primary key with a record already in this Collection.\n *\n * Possible values:\n * merge\n * replace\n * skip\n *\n * Merge:\n *\n * Recursively shallow copy properties from the new record onto the existing\n * record.\n *\n * Replace:\n *\n * Shallow copy top-level properties from the new record onto the existing\n * record. Any top-level own properties of the existing record that are _not_\n * on the new record will be removed.\n *\n * Skip:\n *\n * Ignore new record, keep existing record.\n *\n * @default \"merge\"\n */\n onConflict?: 'merge' | 'replace' | 'skip'\n}\n\nconst COLLECTION_DEFAULTS: CollectionOpts = {\n commitOnMerge: true,\n emitRecordEvents: true,\n idAttribute: 'id',\n onConflict: 'merge'\n}\n\n/**\n * An ordered set of {@link Record} instances.\n *\n * @example Collection#constructor\n * // import { Collection, Record } from 'js-data';\n * const JSData = require('js-data');\n * const {Collection, Record} = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const user1 = new Record({ id: 1 });\n * const user2 = new Record({ id: 2 });\n * const UserCollection = new Collection([user1, user2]);\n * console.log(UserCollection.get(1) === user1);\n *\n * @class Collection\n * @extends Component\n * @param {array} [records] Initial set of records to insert into the\n * collection.\n * @param {object} [opts] Configuration options.\n * @param {string} [opts.commitOnMerge] See {@link Collection#commitOnMerge}.\n * @param {string} [opts.idAttribute] See {@link Collection#idAttribute}.\n * @param {string} [opts.onConflict=\"merge\"] See {@link Collection#onConflict}.\n * @param {string} [opts.mapper] See {@link Collection#mapper}.\n * @since 3.0.0\n */\nexport default class Collection extends Component {\n queryClass\n emitRecordEvents: any\n onConflict: string\n /**\n * Default Mapper for this collection. Optional. If a Mapper is provided, then\n * the collection will use the {@link Mapper#idAttribute} setting, and will\n * wrap records in {@link Mapper#recordClass}.\n *\n * @example Collection#mapper\n * const JSData = require('js-data');\n * const {Collection, Mapper} = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * class MyMapperClass extends Mapper {\n * foo () { return 'bar'; }\n * }\n * const myMapper = new MyMapperClass({ name: 'myMapper' });\n * const collection = new Collection(null, { mapper: myMapper });\n *\n * @name Collection#mapper\n * @type {Mapper}\n * @default null\n * @since 3.0.0\n */\n mapper: any\n /**\n * The main index, which uses @{link Collection#recordId} as the key.\n *\n * @name Collection#index\n * @type {Index}\n */\n index: Index\n /**\n * Object that holds the secondary indexes of this collection.\n *\n * @name Collection#indexes\n * @type {Object.}\n */\n indexes: { [key: string]: Index } = {}\n idAttribute: any\n _added = {}\n emit: any\n\n constructor (records: any = {}, opts: CollectionOpts | string | any = {}) {\n super(opts)\n\n if (records && !utils.isArray(records)) {\n opts = records\n records = []\n }\n if (utils.isString(opts)) {\n opts = { idAttribute: opts }\n }\n\n // Apply user-provided configuration\n utils.fillIn(this, opts)\n // Fill in any missing options with the defaults\n utils.fillIn(this, utils.copy(COLLECTION_DEFAULTS))\n\n if (!this.queryClass) {\n this.queryClass = Query\n }\n\n const idAttribute = this.recordId()\n\n this.index = new Index([idAttribute], {\n hashCode (obj) {\n return utils.get(obj, idAttribute)\n }\n })\n\n // Insert initial data into the collection\n if (utils.isObject(records) || (utils.isArray(records) && records.length)) {\n this.add(records)\n }\n }\n\n /**\n * Used to bind to events emitted by records in this Collection.\n *\n * @method Collection#_onRecordEvent\n * @since 3.0.0\n * @private\n * @param {...*} [args] Args passed to {@link Collection#emit}.\n */\n _onRecordEvent (...args) {\n if (this.emitRecordEvents) {\n this.emit(...args)\n }\n }\n\n /**\n * Insert the provided record or records.\n *\n * If a record is already in the collection then the provided record will\n * either merge with or replace the existing record based on the value of the\n * `onConflict` option.\n *\n * The collection's secondary indexes will be updated as each record is\n * visited.\n *\n * @method Collection#add\n * @since 3.0.0\n * @param {(Object|Object[]|Record|Record[])} records The record or records to insert.\n * @param {object} [opts] Configuration options.\n * @param {boolean} [opts.commitOnMerge=true] See {@link Collection#commitOnMerge}.\n * @param {boolean} [opts.noValidate] See {@link Record#noValidate}.\n * @param {string} [opts.onConflict] See {@link Collection#onConflict}.\n * @returns {(Object|Object[]|Record|Record[])} The added record or records.\n */\n add (records, opts: any = {}) {\n // Fill in \"opts\" with the Collection's configuration\n utils._(opts, this)\n records = this.beforeAdd(records, opts) || records\n\n // Track whether just one record or an array of records is being inserted\n let singular = false\n const idAttribute = this.recordId()\n if (!utils.isArray(records)) {\n if (utils.isObject(records)) {\n records = [records]\n singular = true\n } else {\n throw utils.err(`${DOMAIN}#add`, 'records')(\n 400,\n 'object or array',\n records\n )\n }\n }\n\n // Map the provided records to existing records.\n // New records will be inserted. If any records map to existing records,\n // they will be merged into the existing records according to the onConflict\n // option.\n records = records.map(record => {\n const id = this.recordId(record)\n // Grab existing record if there is one\n const existing = id === undefined ? id : this.get(id)\n // If the currently visited record is just a reference to an existing\n // record, then there is nothing to be done. Exit early.\n if (record === existing) {\n return existing\n }\n\n if (existing) {\n // Here, the currently visited record corresponds to a record already\n // in the collection, so we need to merge them\n const onConflict = opts.onConflict || this.onConflict\n if (\n onConflict !== 'merge' &&\n onConflict !== 'replace' &&\n onConflict !== 'skip'\n ) {\n throw utils.err(`${DOMAIN}#add`, 'opts.onConflict')(\n 400,\n 'one of (merge, replace, skip)',\n onConflict,\n true\n )\n }\n const existingNoValidate = existing._get(noValidatePath)\n if (opts.noValidate) {\n // Disable validation\n existing._set(noValidatePath, true)\n }\n if (onConflict === 'merge') {\n utils.deepMixIn(existing, record)\n } else if (onConflict === 'replace') {\n utils.forOwn(existing, (value, key) => {\n if (key !== idAttribute && record[key] === undefined) {\n existing[key] = undefined\n }\n })\n existing.set(record)\n } // else if(onConflict === 'skip'){ do nothing }\n\n if (opts.noValidate) {\n // Restore previous `noValidate` value\n existing._set(noValidatePath, existingNoValidate)\n }\n record = existing\n if (opts.commitOnMerge && utils.isFunction(record.commit)) {\n record.commit()\n }\n // Update all indexes in the collection\n this.updateIndexes(record)\n } else {\n // Here, the currently visited record does not correspond to any record\n // in the collection, so (optionally) instantiate this record and insert\n // it into the collection\n record = this.mapper ? this.mapper.createRecord(record, opts) : record\n this.index.insertRecord(record)\n utils.forOwn(this.indexes, (index, name) => {\n index.insertRecord(record)\n })\n if (record && utils.isFunction(record.on)) {\n record.on('all', this._onRecordEvent, this)\n }\n }\n return record\n })\n // Finally, return the inserted data\n const result = singular ? records[0] : records\n if (!opts.silent) {\n this.emit('add', result)\n }\n return this.afterAdd(records, opts, result) || result\n }\n\n /**\n * Lifecycle hook called by {@link Collection#add}. If this method returns a\n * value then {@link Collection#add} will return that same value.\n *\n * @method Collection#method\n * @since 3.0.0\n * @param {(Object|Object[]|Record|Record[])} record The record or records\n * that were added to this Collection by {@link Collection#add}.\n * @param {object} opts The `opts` argument passed to {@link Collection#add}.\n * @param result\n */\n afterAdd (record, opts, result) {\n return null\n }\n\n /**\n * Lifecycle hook called by {@link Collection#remove}. If this method returns\n * a value then {@link Collection#remove} will return that same value.\n *\n * @method Collection#afterRemove\n * @since 3.0.0\n * @param {(string|number)} id The `id` argument passed to {@link Collection#remove}.\n * @param {object} opts The `opts` argument passed to {@link Collection#remove}.\n * @param {object} record The result that will be returned by {@link Collection#remove}.\n */\n afterRemove (id, opts, record) {\n return null\n }\n\n /**\n * Lifecycle hook called by {@link Collection#removeAll}. If this method\n * returns a value then {@link Collection#removeAll} will return that same\n * value.\n *\n * @method Collection#afterRemoveAll\n * @since 3.0.0\n * @param {object} query The `query` argument passed to {@link Collection#removeAll}.\n * @param {object} opts The `opts` argument passed to {@link Collection#removeAll}.\n * @param {object} records The result that will be returned by {@link Collection#removeAll}.\n */\n afterRemoveAll (query, opts, records) {\n return null\n }\n\n /**\n * Lifecycle hook called by {@link Collection#add}. If this method returns a\n * value then the `records` argument in {@link Collection#add} will be\n * re-assigned to the returned value.\n *\n * @method Collection#beforeAdd\n * @since 3.0.0\n * @param {(Object|Object[]|Record|Record[])} records The `records` argument passed to {@link Collection#add}.\n * @param {object} opts The `opts` argument passed to {@link Collection#add}.\n */\n beforeAdd (records, opts) {\n return null\n }\n\n /**\n * Lifecycle hook called by {@link Collection#remove}.\n *\n * @method Collection#beforeRemove\n * @since 3.0.0\n * @param {(string|number)} id The `id` argument passed to {@link Collection#remove}.\n * @param {object} opts The `opts` argument passed to {@link Collection#remove}.\n */\n beforeRemove (id, opts) {\n return null\n }\n\n /**\n * Lifecycle hook called by {@link Collection#removeAll}.\n *\n * @method Collection#beforeRemoveAll\n * @since 3.0.0\n * @param {object} query The `query` argument passed to {@link Collection#removeAll}.\n * @param {object} opts The `opts` argument passed to {@link Collection#removeAll}.\n */\n beforeRemoveAll (query, opts) {\n return null\n }\n\n /**\n * Find all records between two boundaries.\n *\n * Shortcut for `collection.query().between(18, 30, { index: 'age' }).run()`\n *\n * @example\n * // Get all users ages 18 to 30\n * const users = collection.between(18, 30, { index: 'age' });\n *\n * @example\n * // Same as above\n * const users = collection.between([18], [30], { index: 'age' });\n *\n * @method Collection#between\n * @since 3.0.0\n * @param {array} leftKeys Keys defining the left boundary.\n * @param {array} rightKeys Keys defining the right boundary.\n * @param {object} [opts] Configuration options.\n * @param {string} [opts.index] Name of the secondary index to use in the\n * query. If no index is specified, the main index is used.\n * @param {boolean} [opts.leftInclusive=true] Whether to include records\n * on the left boundary.\n * @param {boolean} [opts.rightInclusive=false] Whether to include records\n * on the left boundary.\n * @param {boolean} [opts.limit] Limit the result to a certain number.\n * @param {boolean} [opts.offset] The number of resulting records to skip.\n * @returns {Object[]|Record[]} The result.\n */\n between (leftKeys, rightKeys, opts) {\n return this.query()\n .between(leftKeys, rightKeys, opts)\n .run()\n }\n\n /**\n * Create a new secondary index on the contents of the collection.\n *\n * @example\n * // Index users by age\n * collection.createIndex('age');\n *\n * @example\n * // Index users by status and role\n * collection.createIndex('statusAndRole', ['status', 'role']);\n *\n * @method Collection#createIndex\n * @since 3.0.0\n * @param {string} name The name of the new secondary index.\n * @param {string[]} [fieldList] Array of field names to use as the key or\n * compound key of the new secondary index. If no fieldList is provided, then\n * the name will also be the field that is used to index the collection.\n * @param opts\n */\n createIndex (name, fieldList?, opts: any = {}) {\n if (utils.isString(name) && fieldList === undefined) {\n fieldList = [name]\n }\n opts.hashCode = opts.hashCode || (obj => this.recordId(obj))\n const index = (this.indexes[name] = new Index(fieldList, opts))\n this.index.visitAll(index.insertRecord, index)\n }\n\n /**\n * Find the record or records that match the provided query or pass the\n * provided filter function.\n *\n * Shortcut for `collection.query().filter(queryOrFn[, thisArg]).run()`\n *\n * @example Collection#filter\n * const JSData = require('js-data');\n * const { Collection } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const collection = new Collection([\n * { id: 1, status: 'draft', created_at_timestamp: new Date().getTime() }\n * ]);\n *\n * // Get the draft posts created less than three months ago\n * let posts = collection.filter({\n * where: {\n * status: {\n * '==': 'draft'\n * },\n * created_at_timestamp: {\n * '>=': (new Date().getTime() - (1000 \\* 60 \\* 60 \\* 24 \\* 30 \\* 3)) // 3 months ago\n * }\n * }\n * });\n * console.log(posts);\n *\n * // Use a custom filter function\n * posts = collection.filter((post) => post.id % 2 === 0);\n *\n * @method Collection#filter\n * @param {(Object|Function)} [queryOrFn={}] Selection query or filter\n * function.\n * @param {object} [thisArg] Context to which to bind `queryOrFn` if\n * `queryOrFn` is a function.\n * @returns {Array} The result.\n * @see query\n * @since 3.0.0\n */\n filter (queryOrFn, thisArg?) {\n return this.query()\n .filter(queryOrFn, thisArg)\n .run()\n }\n\n /**\n * Iterate over all records.\n *\n * @example\n * collection.forEach(function (record) {\n * // do something\n * });\n *\n * @method Collection#forEach\n * @since 3.0.0\n * @param {Function} forEachFn Iteration function.\n * @param {*} [thisArg] Context to which to bind `forEachFn`.\n * @returns {Array} The result.\n */\n forEach (forEachFn, thisArg?) {\n this.index.visitAll(forEachFn, thisArg)\n }\n\n /**\n * Get the record with the given id.\n *\n * @method Collection#get\n * @since 3.0.0\n * @param {(string|number)} id The primary key of the record to get.\n * @returns {(Object|Record)} The record with the given id.\n */\n get (id) {\n const instances =\n id === undefined\n ? []\n : this.query()\n .get(id)\n .run()\n return instances.length ? instances[0] : undefined\n }\n\n /**\n * Find the record or records that match the provided keyLists.\n *\n * Shortcut for `collection.query().getAll(keyList1, keyList2, ...).run()`\n *\n * @example\n * // Get the posts where \"status\" is \"draft\" or \"inReview\"\n * const posts = collection.getAll('draft', 'inReview', { index: 'status' });\n *\n * @example\n * // Same as above\n * const posts = collection.getAll(['draft'], ['inReview'], { index: 'status' });\n *\n * @method Collection#getAll\n * @since 3.0.0\n * @param {...Array} [keyList] Provide one or more keyLists, and all\n * records matching each keyList will be retrieved. If no keyLists are\n * provided, all records will be returned.\n * @param {object} [opts] Configuration options.\n * @param {string} [opts.index] Name of the secondary index to use in the\n * query. If no index is specified, the main index is used.\n * @returns {Array} The result.\n */\n getAll(keyList?: Array | string | number, opts?)\n getAll(keyList?: Array | string | number, ...args)\n getAll (...args) {\n return this.query()\n .getAll(...args)\n .run()\n }\n\n /**\n * Return the index with the given name. If no name is provided, return the\n * main index. Throws an error if the specified index does not exist.\n *\n * @method Collection#getIndex\n * @since 3.0.0\n * @param {string} [name] The name of the index to retrieve.\n */\n getIndex (name): Index {\n const index = name ? this.indexes[name] : this.index\n if (!index) {\n throw utils.err(`${DOMAIN}#getIndex`, name)(404, 'index')\n }\n return index\n }\n\n /**\n * Limit the result.\n *\n * Shortcut for `collection.query().limit(maximumNumber).run()`\n *\n * @example\n * const posts = collection.limit(10);\n *\n * @method Collection#limit\n * @since 3.0.0\n * @param {number} num The maximum number of records to keep in the result.\n * @returns {Array} The result.\n */\n limit (num) {\n return this.query()\n .limit(num)\n .run()\n }\n\n /**\n * Apply a mapping function to all records.\n *\n * @example\n * const names = collection.map((user) => user.name);\n *\n * @method Collection#map\n * @since 3.0.0\n * @param {Function} mapFn Mapping function.\n * @param {*} [thisArg] Context to which to bind `mapFn`.\n * @returns {Array} The result of the mapping.\n */\n map (cb, thisArg) {\n const data = []\n this.index.visitAll(value => {\n data.push(cb.call(thisArg, value))\n })\n return data\n }\n\n /**\n * Return the result of calling the specified function on each record in this\n * collection's main index.\n *\n * @method Collection#mapCall\n * @since 3.0.0\n * @param {string} funcName Name of function to call\n * @param {...*} [args] Remaining arguments to be passed to the function.\n * @returns {Array} The result.\n */\n mapCall (funcName, ...args) {\n const data = []\n this.index.visitAll(record => {\n data.push(record[funcName](...args))\n })\n return data\n }\n\n /**\n * Return all \"unsaved\" (not uniquely identifiable) records in this colleciton.\n *\n * @method Collection#prune\n * @param {object} [opts] Configuration options, passed to {@link Collection#removeAll}.\n * @since 3.0.0\n * @returns {Array} The removed records, if any.\n */\n prune (opts) {\n return this.removeAll(this.unsaved(), opts)\n }\n\n /**\n * Create a new query to be executed against the contents of the collection.\n * The result will be all or a subset of the contents of the collection.\n *\n * @example\n * // Grab page 2 of users between ages 18 and 30\n * collection.query()\n * .between(18, 30, { index: 'age' }) // between ages 18 and 30\n * .skip(10) // second page\n * .limit(10) // page size\n * .run();\n *\n * @method Collection#query\n * @since 3.0.0\n * @returns {Query} New query object.\n */\n query (): Query {\n const Ctor = this.queryClass\n return new Ctor(this)\n }\n\n /**\n * Return the primary key of the given, or if no record is provided, return the\n * name of the field that holds the primary key of records in this Collection.\n *\n * @method Collection#recordId\n * @since 3.0.0\n * @param {(Object|Record)} [record] The record whose primary key is to be\n * returned.\n * @returns {(string|number)} Primary key or name of field that holds primary\n * key.\n */\n recordId (record?) {\n if (record) {\n return utils.get(record, this.recordId())\n }\n return this.mapper ? this.mapper.idAttribute : this.idAttribute\n }\n\n /**\n * Reduce the data in the collection to a single value and return the result.\n *\n * @example\n * const totalVotes = collection.reduce((prev, record) => {\n * return prev + record.upVotes + record.downVotes;\n * }, 0);\n *\n * @method Collection#reduce\n * @since 3.0.0\n * @param {Function} cb Reduction callback.\n * @param {*} initialValue Initial value of the reduction.\n * @returns {*} The result.\n */\n reduce (cb, initialValue) {\n const data = this.getAll()\n return data.reduce(cb, initialValue)\n }\n\n /**\n * Remove the record with the given id from this Collection.\n *\n * @method Collection#remove\n * @since 3.0.0\n * @param {(string|number|object|Record)} idOrRecord The primary key of the\n * record to be removed, or a reference to the record that is to be removed.\n * @param {object} [opts] Configuration options.\n * @returns {Object|Record} The removed record, if any.\n */\n remove (idOrRecord, opts: any = {}) {\n this.beforeRemove(idOrRecord, opts)\n let record = utils.isSorN(idOrRecord) ? this.get(idOrRecord) : idOrRecord\n\n // The record is in the collection, remove it\n if (utils.isObject(record)) {\n record = this.index.removeRecord(record)\n if (record) {\n utils.forOwn(this.indexes, (index, name) => {\n index.removeRecord(record)\n })\n if (utils.isFunction(record.off)) {\n record.off('all', this._onRecordEvent, this)\n }\n if (!opts.silent) {\n this.emit('remove', record)\n }\n }\n }\n return this.afterRemove(idOrRecord, opts, record) || record\n }\n\n /**\n * Remove from this collection the given records or the records selected by\n * the given \"query\".\n *\n * @method Collection#removeAll\n * @since 3.0.0\n * @param {Object|Object[]|Record[]} [queryOrRecords={}] Records to be removed or selection query. See {@link query}.\n * @param {object} [queryOrRecords.where] See {@link query.where}.\n * @param {number} [queryOrRecords.offset] See {@link query.offset}.\n * @param {number} [queryOrRecords.limit] See {@link query.limit}.\n * @param {string|Array[]} [queryOrRecords.orderBy] See {@link query.orderBy}.\n * @param {object} [opts] Configuration options.\n * @returns {(Object[]|Record[])} The removed records, if any.\n */\n removeAll (queryOrRecords, opts: any = {}) {\n this.beforeRemoveAll(queryOrRecords, opts)\n let records = utils.isArray(queryOrRecords)\n ? queryOrRecords.slice()\n : this.filter(queryOrRecords)\n\n // Remove each selected record from the collection\n const optsCopy = utils.plainCopy(opts)\n optsCopy.silent = true\n records = records\n .map(record => this.remove(record, optsCopy))\n .filter(record => record)\n if (!opts.silent) {\n this.emit('remove', records)\n }\n return this.afterRemoveAll(queryOrRecords, opts, records) || records\n }\n\n /**\n * Skip a number of results.\n *\n * Shortcut for `collection.query().skip(numberToSkip).run()`\n *\n * @example\n * const posts = collection.skip(10);\n *\n * @method Collection#skip\n * @since 3.0.0\n * @param {number} num The number of records to skip.\n * @returns {Array} The result.\n */\n skip (num) {\n return this.query()\n .skip(num)\n .run()\n }\n\n /**\n * Return the plain JSON representation of all items in this collection.\n * Assumes records in this collection have a toJSON method.\n *\n * @method Collection#toJSON\n * @since 3.0.0\n * @param {object} [opts] Configuration options.\n * @param {string[]} [opts.with] Array of relation names or relation fields\n * to include in the representation.\n * @returns {Array} The records.\n */\n toJSON (opts?) {\n return this.mapCall('toJSON', opts)\n }\n\n /**\n * Return all \"unsaved\" (not uniquely identifiable) records in this colleciton.\n *\n * @method Collection#unsaved\n * @since 3.0.0\n * @returns {Array} The unsaved records, if any.\n */\n unsaved (opts?) {\n return this.index.get()\n }\n\n /**\n * Update a record's position in a single index of this collection. See\n * {@link Collection#updateIndexes} to update a record's position in all\n * indexes at once.\n *\n * @method Collection#updateIndex\n * @since 3.0.0\n * @param {object} record The record to update.\n * @param {object} [opts] Configuration options.\n * @param {string} [opts.index] The index in which to update the record's\n * position. If you don't specify an index then the record will be updated\n * in the main index.\n */\n updateIndex (record, opts: { index?: string } = {}) {\n this.getIndex(opts.index).updateRecord(record)\n }\n\n /**\n * Updates all indexes in this collection for the provided record. Has no\n * effect if the record is not in the collection.\n *\n * @method Collection#updateIndexes\n * @since 3.0.0\n * @param {object} record TODO\n */\n updateIndexes (record) {\n this.index.updateRecord(record)\n utils.forOwn(this.indexes, index => index.updateRecord(record))\n }\n}\n\n/**\n * Fired when a record changes. Only works for records that have tracked changes.\n * See {@link Collection~changeListener} on how to listen for this event.\n *\n * @event Collection#change\n * @see Collection~changeListener\n */\n\n/**\n * Callback signature for the {@link Collection#event:change} event.\n *\n * @example\n * function onChange (record, changes) {\n * // do something\n * }\n * collection.on('change', onChange);\n *\n * @callback Collection~changeListener\n * @param {Record} The Record that changed.\n * @param {object} The changes.\n * @see Collection#event:change\n * @since 3.0.0\n */\n\n/**\n * Fired when one or more records are added to the Collection. See\n * {@link Collection~addListener} on how to listen for this event.\n *\n * @event Collection#add\n * @see Collection~addListener\n * @see Collection#event:add\n * @see Collection#add\n */\n\n/**\n * Callback signature for the {@link Collection#event:add} event.\n *\n * @example\n * function onAdd (recordOrRecords) {\n * // do something\n * }\n * collection.on('add', onAdd);\n *\n * @callback Collection~addListener\n * @param {Record|Record[]} The Record or Records that were added.\n * @see Collection#event:add\n * @see Collection#add\n * @since 3.0.0\n */\n\n/**\n * Fired when one or more records are removed from the Collection. See\n * {@link Collection~removeListener} for how to listen for this event.\n *\n * @event Collection#remove\n * @see Collection~removeListener\n * @see Collection#event:remove\n * @see Collection#remove\n * @see Collection#removeAll\n */\n\n/**\n * Callback signature for the {@link Collection#event:remove} event.\n *\n * @example\n * function onRemove (recordsOrRecords) {\n * // do something\n * }\n * collection.on('remove', onRemove);\n *\n * @callback Collection~removeListener\n * @param {Record|Record[]} Record or Records that were removed.\n * @see Collection#event:remove\n * @see Collection#remove\n * @see Collection#removeAll\n * @since 3.0.0\n */\n\n/**\n * Create a subclass of this Collection:\n * @example Collection.extend\n * const JSData = require('js-data');\n * const { Collection } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * // Extend the class using ES2015 class syntax.\n * class CustomCollectionClass extends Collection {\n * foo () { return 'bar'; }\n * static beep () { return 'boop'; }\n * }\n * const customCollection = new CustomCollectionClass();\n * console.log(customCollection.foo());\n * console.log(CustomCollectionClass.beep());\n *\n * // Extend the class using alternate method.\n * const OtherCollectionClass = Collection.extend({\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * });\n * const otherCollection = new OtherCollectionClass();\n * console.log(otherCollection.foo());\n * console.log(OtherCollectionClass.beep());\n *\n * // Extend the class, providing a custom constructor.\n * function AnotherCollectionClass () {\n * Collection.call(this);\n * this.created_at = new Date().getTime();\n * }\n * Collection.extend({\n * constructor: AnotherCollectionClass,\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * });\n * const anotherCollection = new AnotherCollectionClass();\n * console.log(anotherCollection.created_at);\n * console.log(anotherCollection.foo());\n * console.log(AnotherCollectionClass.beep());\n *\n * @method Collection.extend\n * @param {object} [props={}] Properties to add to the prototype of the\n * subclass.\n * @param {object} [props.constructor] Provide a custom constructor function\n * to be used as the subclass itself.\n * @param {object} [classProps={}] Static properties to add to the subclass.\n * @returns {Constructor} Subclass of this Collection class.\n * @since 3.0.0\n */\n","export class TsDataError extends Error {\n errors: any;\n}\n","import utils from './utils'\nimport Component from './Component'\nimport { TsDataError } from './TsDataError'\n\nconst DOMAIN = 'Schema'\n\n/**\n * A function map for each of the seven primitive JSON types defined by the core specification.\n * Each function will check a given value and return true or false if the value is an instance of that type.\n * ```\n * types.integer(1) // returns true\n * types.string({}) // returns false\n * ```\n * http://json-schema.org/latest/json-schema-core.html#anchor8\n * @name Schema.types\n * @type {object}\n */\nconst types = {\n array: utils.isArray,\n boolean: utils.isBoolean,\n integer: utils.isInteger,\n null: utils.isNull,\n number: utils.isNumber,\n object: utils.isObject,\n string: utils.isString\n}\n\n/**\n * @ignore\n */\nfunction segmentToString (segment, prev) {\n let str = ''\n if (segment) {\n if (utils.isNumber(segment)) {\n str += `[${segment}]`\n } else if (prev) {\n str += `.${segment}`\n } else {\n str += `${segment}`\n }\n }\n return str\n}\n\n/**\n * @ignore\n */\nfunction makePath (opts: any = {}) {\n let path = ''\n const segments = opts.path || []\n segments.forEach(segment => {\n path += segmentToString(segment, path)\n })\n path += segmentToString(opts.prop, path)\n return path\n}\n\n/**\n * @ignore\n */\nfunction makeError (actual, expected, opts) {\n return {\n expected,\n actual: '' + actual,\n path: makePath(opts)\n }\n}\n\n/**\n * @ignore\n */\nfunction addError (actual, expected, opts, errors) {\n errors.push(makeError(actual, expected, opts))\n}\n\n/**\n * @ignore\n */\nfunction maxLengthCommon (keyword, value, schema, opts) {\n const max = schema[keyword]\n if (value.length > max) {\n return makeError(value.length, `length no more than ${max}`, opts)\n }\n}\n\n/**\n * @ignore\n */\nfunction minLengthCommon (keyword, value, schema, opts) {\n const min = schema[keyword]\n if (value.length < min) {\n return makeError(value.length, `length no less than ${min}`, opts)\n }\n}\n\n/**\n * A map of all object member validation functions for each keyword defined in the JSON Schema.\n * @name Schema.validationKeywords\n * @type {object}\n */\nconst validationKeywords = {\n /**\n * Validates the provided value against all schemas defined in the Schemas `allOf` keyword.\n * The instance is valid against if and only if it is valid against all the schemas declared in the Schema's value.\n *\n * The value of this keyword MUST be an array. This array MUST have at least one element.\n * Each element of this array MUST be a valid JSON Schema.\n *\n * see http://json-schema.org/latest/json-schema-validation.html#anchor82\n *\n * @name Schema.validationKeywords.allOf\n * @method\n * @param {*} value Value to be validated.\n * @param {object} schema Schema containing the `allOf` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n allOf (value, schema, opts) {\n let allErrors = []\n schema.allOf.forEach(_schema => {\n allErrors = allErrors.concat(validate(value, _schema, opts) || [])\n })\n return allErrors.length ? allErrors : undefined\n },\n\n /**\n * Validates the provided value against all schemas defined in the Schemas `anyOf` keyword.\n * The instance is valid against this keyword if and only if it is valid against\n * at least one of the schemas in this keyword's value.\n *\n * The value of this keyword MUST be an array. This array MUST have at least one element.\n * Each element of this array MUST be an object, and each object MUST be a valid JSON Schema.\n * see http://json-schema.org/latest/json-schema-validation.html#anchor85\n *\n * @name Schema.validationKeywords.anyOf\n * @method\n * @param {*} value Value to be validated.\n * @param {object} schema Schema containing the `anyOf` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n anyOf (value, schema, opts) {\n let validated = false\n let allErrors = []\n schema.anyOf.forEach(_schema => {\n const errors = validate(value, _schema, opts)\n if (errors) {\n allErrors = allErrors.concat(errors)\n } else {\n validated = true\n }\n })\n return validated ? undefined : allErrors\n },\n\n /**\n * http://json-schema.org/latest/json-schema-validation.html#anchor70\n *\n * @name Schema.validationKeywords.dependencies\n * @method\n * @param {*} value TODO\n * @param {object} schema TODO\n * @param {object} opts TODO\n */\n dependencies (value, schema, opts) {\n // TODO\n },\n\n /**\n * Validates the provided value against an array of possible values defined by the Schema's `enum` keyword\n * Validation succeeds if the value is deeply equal to one of the values in the array.\n * see http://json-schema.org/latest/json-schema-validation.html#anchor76\n *\n * @name Schema.validationKeywords.enum\n * @method\n * @param {*} value Value to validate\n * @param {object} schema Schema containing the `enum` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n enum (value, schema, opts) {\n const possibleValues = schema.enum\n if (utils.findIndex(possibleValues, item => utils.deepEqual(item, value)) === -1) {\n return makeError(value, `one of (${possibleValues.join(', ')})`, opts)\n }\n },\n\n /**\n * Validates each of the provided array values against a schema or an array of schemas defined by the Schema's\n * `items` keyword\n * see http://json-schema.org/latest/json-schema-validation.html#anchor37 for validation rules.\n *\n * @name Schema.validationKeywords.items\n * @method\n * @param {*} value Array to be validated.\n * @param {object} schema Schema containing the items keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n items (value, schema, opts: any = {}) {\n // TODO: additionalItems\n let items = schema.items\n let errors = []\n const checkingTuple = utils.isArray(items)\n const length = value.length\n for (let prop = 0; prop < length; prop++) {\n if (checkingTuple) {\n // Validating a tuple, instead of just checking each item against the\n // same schema\n items = schema.items[prop]\n }\n opts.prop = prop\n errors = errors.concat(validate(value[prop], items, opts) || [])\n }\n return errors.length ? errors : undefined\n },\n\n /**\n * Validates the provided number against a maximum value defined by the Schema's `maximum` keyword\n * Validation succeeds if the value is a number, and is less than, or equal to, the value of this keyword.\n * http://json-schema.org/latest/json-schema-validation.html#anchor17\n *\n * @name Schema.validationKeywords.maximum\n * @method\n * @param {*} value Number to validate against the keyword.\n * @param {object} schema Schema containing the `maximum` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n maximum (value, schema, opts) {\n // Must be a number\n const maximum = schema.maximum\n // Must be a boolean\n // Depends on maximum\n // default: false\n const exclusiveMaximum = schema.exclusiveMaximum\n if (typeof value === typeof maximum && !(exclusiveMaximum ? maximum > value : maximum >= value)) {\n return exclusiveMaximum\n ? makeError(value, `no more than nor equal to ${maximum}`, opts)\n : makeError(value, `no more than ${maximum}`, opts)\n }\n },\n\n /**\n * Validates the length of the provided array against a maximum value defined by the Schema's `maxItems` keyword.\n * Validation succeeds if the length of the array is less than, or equal to the value of this keyword.\n * see http://json-schema.org/latest/json-schema-validation.html#anchor42\n *\n * @name Schema.validationKeywords.maxItems\n * @method\n * @param {*} value Array to be validated.\n * @param {object} schema Schema containing the `maxItems` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n maxItems (value, schema, opts) {\n if (utils.isArray(value)) {\n return maxLengthCommon('maxItems', value, schema, opts)\n }\n },\n\n /**\n * Validates the length of the provided string against a maximum value defined in the Schema's `maxLength` keyword.\n * Validation succeeds if the length of the string is less than, or equal to the value of this keyword.\n * see http://json-schema.org/latest/json-schema-validation.html#anchor26\n *\n * @name Schema.validationKeywords.maxLength\n * @method\n * @param {*} value String to be validated.\n * @param {object} schema Schema containing the `maxLength` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n maxLength (value, schema, opts) {\n return maxLengthCommon('maxLength', value, schema, opts)\n },\n\n /**\n * Validates the count of the provided object's properties against a maximum value defined in the Schema's\n * `maxProperties` keyword.\n * Validation succeeds if the object's property count is less than, or equal to the value of this keyword.\n * see http://json-schema.org/latest/json-schema-validation.html#anchor54\n *\n * @name Schema.validationKeywords.maxProperties\n * @method\n * @param {*} value Object to be validated.\n * @param {object} schema Schema containing the `maxProperties` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n maxProperties (value, schema, opts) {\n // validate only objects\n if (!utils.isObject(value)) return\n const maxProperties = schema.maxProperties\n const length = Object.keys(value).length\n if (length > maxProperties) {\n return makeError(length, `no more than ${maxProperties} properties`, opts)\n }\n },\n\n /**\n * Validates the provided value against a minimum value defined by the Schema's `minimum` keyword\n * Validation succeeds if the value is a number and is greater than, or equal to, the value of this keyword.\n * http://json-schema.org/latest/json-schema-validation.html#anchor21\n *\n * @name Schema.validationKeywords.minimum\n * @method\n * @param {*} value Number to validate against the keyword.\n * @param {object} schema Schema containing the `minimum` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n minimum (value, schema, opts) {\n // Must be a number\n const minimum = schema.minimum\n // Must be a boolean\n // Depends on minimum\n // default: false\n const exclusiveMinimum = schema.exclusiveMinimum\n if (typeof value === typeof minimum && !(exclusiveMinimum ? value > minimum : value >= minimum)) {\n return exclusiveMinimum\n ? makeError(value, `no less than nor equal to ${minimum}`, opts)\n : makeError(value, `no less than ${minimum}`, opts)\n }\n },\n\n /**\n * Validates the length of the provided array against a minimum value defined by the Schema's `minItems` keyword.\n * Validation succeeds if the length of the array is greater than, or equal to the value of this keyword.\n * see http://json-schema.org/latest/json-schema-validation.html#anchor45\n *\n * @name Schema.validationKeywords.minItems\n * @method\n * @param {*} value Array to be validated.\n * @param {object} schema Schema containing the `minItems` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n minItems (value, schema, opts) {\n if (utils.isArray(value)) {\n return minLengthCommon('minItems', value, schema, opts)\n }\n },\n\n /**\n * Validates the length of the provided string against a minimum value defined in the Schema's `minLength` keyword.\n * Validation succeeds if the length of the string is greater than, or equal to the value of this keyword.\n * see http://json-schema.org/latest/json-schema-validation.html#anchor29\n *\n * @name Schema.validationKeywords.minLength\n * @method\n * @param {*} value String to be validated.\n * @param {object} schema Schema containing the `minLength` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n minLength (value, schema, opts) {\n return minLengthCommon('minLength', value, schema, opts)\n },\n\n /**\n * Validates the count of the provided object's properties against a minimum value defined in the Schema's\n * `minProperties` keyword.\n * Validation succeeds if the object's property count is greater than, or equal to the value of this keyword.\n * see http://json-schema.org/latest/json-schema-validation.html#anchor57\n *\n * @name Schema.validationKeywords.minProperties\n * @method\n * @param {*} value Object to be validated.\n * @param {object} schema Schema containing the `minProperties` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n minProperties (value, schema, opts) {\n // validate only objects\n if (!utils.isObject(value)) return\n const minProperties = schema.minProperties\n const length = Object.keys(value).length\n if (length < minProperties) {\n return makeError(length, `no more than ${minProperties} properties`, opts)\n }\n },\n\n /**\n * Validates the provided number is a multiple of the number defined in the Schema's `multipleOf` keyword.\n * Validation succeeds if the number can be divided equally into the value of this keyword.\n * see http://json-schema.org/latest/json-schema-validation.html#anchor14\n *\n * @name Schema.validationKeywords.multipleOf\n * @method\n * @param {*} value Number to be validated.\n * @param {object} schema Schema containing the `multipleOf` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n multipleOf (value, schema, opts) {\n const multipleOf = schema.multipleOf\n if (utils.isNumber(value)) {\n if ((value / multipleOf) % 1 !== 0) {\n return makeError(value, `multipleOf ${multipleOf}`, opts)\n }\n }\n },\n\n /**\n * Validates the provided value is not valid with any of the schemas defined in the Schema's `not` keyword.\n * An instance is valid against this keyword if and only if it is NOT valid against the schemas in this keyword's\n * value.\n *\n * see http://json-schema.org/latest/json-schema-validation.html#anchor91\n * @name Schema.validationKeywords.not\n * @method\n * @param {*} value to be checked.\n * @param {object} schema Schema containing the not keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n not (value, schema, opts) {\n if (!validate(value, schema.not, opts)) {\n // TODO: better messaging\n return makeError('succeeded', 'should have failed', opts)\n }\n },\n\n /**\n * Validates the provided value is valid with one and only one of the schemas defined in the Schema's `oneOf` keyword.\n * An instance is valid against this keyword if and only if it is valid against a single schemas in this keyword's\n * value.\n *\n * see http://json-schema.org/latest/json-schema-validation.html#anchor88\n * @name Schema.validationKeywords.oneOf\n * @method\n * @param {*} value to be checked.\n * @param {object} schema Schema containing the `oneOf` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n oneOf (value, schema, opts) {\n let validated = false\n let allErrors = []\n schema.oneOf.forEach(_schema => {\n const errors = validate(value, _schema, opts)\n if (errors) {\n allErrors = allErrors.concat(errors)\n } else if (validated) {\n allErrors = [makeError('valid against more than one', 'valid against only one', opts)]\n validated = false\n return false\n } else {\n validated = true\n }\n })\n return validated ? undefined : allErrors\n },\n\n /**\n * Validates the provided string matches a pattern defined in the Schema's `pattern` keyword.\n * Validation succeeds if the string is a match of the regex value of this keyword.\n *\n * see http://json-schema.org/latest/json-schema-validation.html#anchor33\n * @name Schema.validationKeywords.pattern\n * @method\n * @param {*} value String to be validated.\n * @param {object} schema Schema containing the `pattern` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n pattern (value, schema, opts) {\n const pattern = schema.pattern\n if (utils.isString(value) && !value.match(pattern)) {\n return makeError(value, pattern, opts)\n }\n },\n\n /**\n * Validates the provided object's properties against a map of values defined in the Schema's `properties` keyword.\n * Validation succeeds if the object's property are valid with each of the schema's in the provided map.\n * Validation also depends on the additionalProperties and or patternProperties.\n *\n * see http://json-schema.org/latest/json-schema-validation.html#anchor64 for more info.\n *\n * @name Schema.validationKeywords.properties\n * @method\n * @param {*} value Object to be validated.\n * @param {object} schema Schema containing the `properties` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n properties (value, schema, opts: any = {}) {\n if (utils.isArray(value)) {\n return\n }\n\n // Can be a boolean or an object\n // Technically the default is an \"empty schema\", but here \"true\" is\n // functionally the same\n const additionalProperties = schema.additionalProperties === undefined ? true : schema.additionalProperties\n const validated = []\n // \"p\": The property set from \"properties\".\n // Default is an object\n const properties = schema.properties || {}\n // \"pp\": The property set from \"patternProperties\".\n // Default is an object\n const patternProperties = schema.patternProperties || {}\n let errors = []\n\n utils.forOwn(properties, (_schema, prop) => {\n opts.prop = prop\n errors = errors.concat(validate(value[prop], _schema, opts) || [])\n validated.push(prop)\n })\n\n const toValidate = utils.omit(value, validated)\n utils.forOwn(patternProperties, (_schema, pattern) => {\n utils.forOwn(toValidate, (undef, prop) => {\n if (prop.match(pattern)) {\n opts.prop = prop\n errors = errors.concat(validate(value[prop], _schema, opts) || [])\n validated.push(prop)\n }\n })\n })\n const keys = Object.keys(utils.omit(value, validated))\n // If \"s\" is not empty, validation fails\n if (additionalProperties === false) {\n if (keys.length) {\n const origProp = opts.prop\n opts.prop = ''\n addError(`extra fields: ${keys.join(', ')}`, 'no extra fields', opts, errors)\n opts.prop = origProp\n }\n } else if (utils.isObject(additionalProperties)) {\n // Otherwise, validate according to provided schema\n keys.forEach(prop => {\n opts.prop = prop\n errors = errors.concat(validate(value[prop], additionalProperties, opts) || [])\n })\n }\n return errors.length ? errors : undefined\n },\n\n /**\n * Validates the provided object's has all properties listed in the Schema's `properties` keyword array.\n * Validation succeeds if the object contains all properties provided in the array value of this keyword.\n * see http://json-schema.org/latest/json-schema-validation.html#anchor61\n *\n * @name Schema.validationKeywords.required\n * @method\n * @param {*} value Object to be validated.\n * @param {object} schema Schema containing the `required` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n required (value, schema, opts: any = {}) {\n const required = schema.required\n const errors = []\n if (!opts.existingOnly) {\n required.forEach(prop => {\n if (utils.get(value, prop) === undefined) {\n const prevProp = opts.prop\n opts.prop = prop\n addError(undefined, 'a value', opts, errors)\n opts.prop = prevProp\n }\n })\n }\n return errors.length ? errors : undefined\n },\n\n /**\n * Validates the provided value's type is equal to the type, or array of types, defined in the Schema's `type`\n * keyword.\n * see http://json-schema.org/latest/json-schema-validation.html#anchor79\n *\n * @name Schema.validationKeywords.type\n * @method\n * @param {*} value Value to be validated.\n * @param {object} schema Schema containing the `type` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n type (value, schema, opts) {\n let type = schema.type\n let validType\n // Can be one of several types\n if (utils.isString(type)) {\n type = [type]\n }\n // Try to match the value against an expected type\n type.forEach(_type => {\n // TODO: throw an error if type is not defined\n if (types[_type](value, schema, opts)) {\n // Matched a type\n validType = _type\n return false\n }\n })\n // Value did not match any expected type\n if (!validType) {\n return makeError(\n value !== undefined && value !== null ? typeof value : '' + value,\n `one of (${type.join(', ')})`,\n opts\n )\n }\n // Run keyword validators for matched type\n // http://json-schema.org/latest/json-schema-validation.html#anchor12\n const validator = typeGroupValidators[validType]\n if (validator) {\n return validator(value, schema, opts)\n }\n },\n\n /**\n * Validates the provided array values are unique.\n * Validation succeeds if the items in the array are unique, but only if the value of this keyword is true\n * see http://json-schema.org/latest/json-schema-validation.html#anchor49\n *\n * @name Schema.validationKeywords.uniqueItems\n * @method\n * @param {*} value Array to be validated.\n * @param {object} schema Schema containing the `uniqueItems` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n uniqueItems (value, schema, opts) {\n if (value?.length && schema.uniqueItems) {\n const length = value.length\n let item, i, j\n // Check n - 1 items\n for (i = length - 1; i > 0; i--) {\n item = value[i]\n // Only compare against unchecked items\n for (j = i - 1; j >= 0; j--) {\n // Found a duplicate\n if (utils.deepEqual(item, value[j])) {\n return makeError(item, 'no duplicates', opts)\n }\n }\n }\n }\n }\n}\n\n/**\n * @ignore\n */\nfunction runOps (ops, value, schema, opts) {\n let errors = []\n ops.forEach(op => {\n if (schema[op] !== undefined) {\n errors = errors.concat(validationKeywords[op](value, schema, opts) || [])\n }\n })\n return errors.length ? errors : undefined\n}\n\n/**\n * Validation keywords validated for any type:\n *\n * - `enum`\n * - `type`\n * - `allOf`\n * - `anyOf`\n * - `oneOf`\n * - `not`\n *\n * @name Schema.ANY_OPS\n * @type {string[]}\n */\nconst ANY_OPS = ['enum', 'type', 'allOf', 'anyOf', 'oneOf', 'not']\n\n/**\n * Validation keywords validated for array types:\n *\n * - `items`\n * - `maxItems`\n * - `minItems`\n * - `uniqueItems`\n *\n * @name Schema.ARRAY_OPS\n * @type {string[]}\n */\nconst ARRAY_OPS = ['items', 'maxItems', 'minItems', 'uniqueItems']\n\n/**\n * Validation keywords validated for numeric (number and integer) types:\n *\n * - `multipleOf`\n * - `maximum`\n * - `minimum`\n *\n * @name Schema.NUMERIC_OPS\n * @type {string[]}\n */\nconst NUMERIC_OPS = ['multipleOf', 'maximum', 'minimum']\n\n/**\n * Validation keywords validated for object types:\n *\n * - `maxProperties`\n * - `minProperties`\n * - `required`\n * - `properties`\n * - `dependencies`\n *\n * @name Schema.OBJECT_OPS\n * @type {string[]}\n */\nconst OBJECT_OPS = ['maxProperties', 'minProperties', 'required', 'properties', 'dependencies']\n\n/**\n * Validation keywords validated for string types:\n *\n * - `maxLength`\n * - `minLength`\n * - `pattern`\n *\n * @name Schema.STRING_OPS\n * @type {string[]}\n */\nconst STRING_OPS = ['maxLength', 'minLength', 'pattern']\n\n/**\n * http://json-schema.org/latest/json-schema-validation.html#anchor75\n * @ignore\n */\nconst validateAny = (value, schema, opts) => runOps(ANY_OPS, value, schema, opts)\n\n/**\n * Validates the provided value against a given Schema according to the http://json-schema.org/ v4 specification.\n *\n * @name Schema.validate\n * @method\n * @param {*} value Value to be validated.\n * @param {object} schema Valid Schema according to the http://json-schema.org/ v4 specification.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\nconst validate = (value, schema, opts: any = {}) => {\n let errors = []\n opts.ctx = opts.ctx || { value, schema }\n let shouldPop\n const prevProp = opts.prop\n if (schema === undefined) {\n return\n }\n if (!utils.isObject(schema)) {\n throw utils.err(`${DOMAIN}#validate`)(500, `Invalid schema at path: \"${opts.path}\"`)\n }\n if (opts.path === undefined) {\n opts.path = []\n }\n // Track our location as we recurse\n if (opts.prop !== undefined) {\n shouldPop = true\n opts.path.push(opts.prop)\n opts.prop = undefined\n }\n // Validate against parent schema\n if (schema.extends) {\n // opts.path = path\n // opts.prop = prop\n if (utils.isFunction(schema.extends.validate)) {\n errors = errors.concat(schema.extends.validate(value, opts) || [])\n } else {\n errors = errors.concat(validate(value, schema.extends, opts) || [])\n }\n }\n if (value === undefined) {\n // Check if property is required\n if (schema.required === true && !opts.existingOnly) {\n addError(value, 'a value', opts, errors)\n }\n if (shouldPop) {\n opts.path.pop()\n opts.prop = prevProp\n }\n return errors.length ? errors : undefined\n }\n\n errors = errors.concat(validateAny(value, schema, opts) || [])\n if (shouldPop) {\n opts.path.pop()\n opts.prop = prevProp\n }\n return errors.length ? errors : undefined\n}\n\n// These strings are cached for optimal performance of the change detection\n// boolean - Whether a Record is changing in the current execution frame\nconst changingPath = 'changing'\n// string[] - Properties that have changed in the current execution frame\nconst changedPath = 'changed'\n// Object[] - History of change records\nconst changeHistoryPath = 'history'\n// boolean - Whether a Record is currently being instantiated\nconst creatingPath = 'creating'\n// number - The setTimeout change event id of a Record, if any\nconst eventIdPath = 'eventId'\n// boolean - Whether to skip validation for a Record's currently changing property\nconst noValidatePath = 'noValidate'\n// boolean - Whether to preserve Change History for a Record\nconst keepChangeHistoryPath = 'keepChangeHistory'\n// boolean - Whether to skip change notification for a Record's currently\n// changing property\nconst silentPath = 'silent'\nconst validationFailureMsg = 'validation failed'\n\n/**\n * A map of validation functions grouped by type.\n *\n * @name Schema.typeGroupValidators\n * @type {object}\n */\nconst typeGroupValidators = {\n /**\n * Validates the provided value against the schema using all of the validation keywords specific to instances of an\n * array.\n * The validation keywords for the type `array` are:\n * ```\n * ['items', 'maxItems', 'minItems', 'uniqueItems']\n * ```\n * see http://json-schema.org/latest/json-schema-validation.html#anchor25\n *\n * @name Schema.typeGroupValidators.array\n * @method\n * @param {*} value Array to be validated.\n * @param {object} schema Schema containing at least one array keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n array: (value, schema, opts?) => runOps(ARRAY_OPS, value, schema, opts),\n\n /**\n * Validates the provided value against the schema using all of the validation keywords specific to instances of an\n * integer.\n * The validation keywords for the type `integer` are:\n * ```\n * ['multipleOf', 'maximum', 'minimum']\n * ```\n * @name Schema.typeGroupValidators.integer\n * @method\n * @param {*} value Number to be validated.\n * @param {object} schema Schema containing at least one `integer` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n integer: (value, schema, opts) =>\n // Additional validations for numerics are the same\n typeGroupValidators.numeric(value, schema, opts),\n\n /**\n * Validates the provided value against the schema using all of the validation keywords specific to instances of an\n * number.\n * The validation keywords for the type `number` are:\n * ```\n * ['multipleOf', 'maximum', 'minimum']\n * ```\n * @name Schema.typeGroupValidators.number\n * @method\n * @param {*} value Number to be validated.\n * @param {object} schema Schema containing at least one `number` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n number: (value, schema, opts) =>\n // Additional validations for numerics are the same\n typeGroupValidators.numeric(value, schema, opts),\n\n /**\n * Validates the provided value against the schema using all of the validation keywords specific to instances of a\n * number or integer.\n * The validation keywords for the type `numeric` are:\n * ```\n * ['multipleOf', 'maximum', 'minimum']\n * ```\n * See http://json-schema.org/latest/json-schema-validation.html#anchor13.\n *\n * @name Schema.typeGroupValidators.numeric\n * @method\n * @param {*} value Number to be validated.\n * @param {object} schema Schema containing at least one `numeric` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n numeric: (value, schema, opts) => runOps(NUMERIC_OPS, value, schema, opts),\n\n /**\n * Validates the provided value against the schema using all of the validation keywords specific to instances of an\n * object.\n * The validation keywords for the type `object` are:\n * ```\n * ['maxProperties', 'minProperties', 'required', 'properties', 'dependencies']\n * ```\n * See http://json-schema.org/latest/json-schema-validation.html#anchor53.\n *\n * @name Schema.typeGroupValidators.object\n * @method\n * @param {*} value Object to be validated.\n * @param {object} schema Schema containing at least one `object` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n object: (value, schema, opts) => runOps(OBJECT_OPS, value, schema, opts),\n\n /**\n * Validates the provided value against the schema using all of the validation keywords specific to instances of an\n * string.\n * The validation keywords for the type `string` are:\n * ```\n * ['maxLength', 'minLength', 'pattern']\n * ```\n * See http://json-schema.org/latest/json-schema-validation.html#anchor25.\n *\n * @name Schema.typeGroupValidators.string\n * @method\n * @param {*} value String to be validated.\n * @param {object} schema Schema containing at least one `string` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n string: (value, schema, opts?) => runOps(STRING_OPS, value, schema, opts)\n}\n\nexport interface PropertyDefinition {\n type: string | string[]\n track?: boolean\n description?: string\n indexed?: boolean\n items?: PropertyDefinition\n minItems?: number\n uniqueItems?: boolean\n extends?: Schema\n get?: Function\n properties?: { [name: string]: PropertyDefinition }\n required?: string[] | boolean\n maximum?: number\n exclusiveMaximum?: boolean\n minimum?: number\n exclusiveMinimum?: boolean\n additionalProperties?: boolean\n}\n\nexport interface SchemaDefinition {\n type?: string\n description?: string\n $schema?: string\n title?: string\n properties?: { [name: string]: PropertyDefinition | any }\n extends?: SchemaDefinition | Schema\n items?: SchemaDefinition | Schema\n track?: boolean\n additionalProperties?\n required?: string[]\n}\n\n/**\n * js-data's Schema class.\n *\n * @example Schema#constructor\n * const JSData = require('js-data');\n * const { Schema } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const PostSchema = new Schema({\n * type: 'object',\n * properties: {\n * title: { type: 'string' }\n * }\n * });\n * PostSchema.validate({ title: 1234 });\n *\n * @example\n * const JSData = require('js-data');\n * const { Schema } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * class CustomSchemaClass extends Schema {\n * foo () { return 'bar'; }\n * static beep () { return 'boop'; }\n * }\n * const customSchema = new CustomSchemaClass();\n * console.log(customSchema.foo());\n * console.log(CustomSchemaClass.beep());\n *\n * @class Schema\n * @extends Component\n * @param {object} definition Schema definition according to json-schema.org\n */\nexport default class Schema extends Component {\n type: string;\n properties: any;\n private readonly extends: Schema;\n private readonly items: Schema;\n private readonly track: any;\n private readonly additionalProperties: any;\n\n constructor (definition: SchemaDefinition = {}) {\n super()\n // TODO: schema validation\n utils.fillIn(this, definition)\n\n if (this.type === 'object') {\n this.properties = this.properties || {}\n utils.forOwn(this.properties, (_definition, prop) => {\n if (!(_definition instanceof Schema)) {\n this.properties[prop] = new Schema(_definition)\n }\n })\n } else if (this.type === 'array' && this.items && !(this.items instanceof Schema)) {\n this.items = new Schema(this.items)\n }\n if (this.extends && !(this.extends instanceof Schema)) {\n this.extends = new Schema(this.extends)\n }\n ['allOf', 'anyOf', 'oneOf'].forEach(validationKeyword => {\n if (this[validationKeyword]) {\n this[validationKeyword].forEach((_definition, i) => {\n if (!(_definition instanceof Schema)) {\n this[validationKeyword][i] = new Schema(_definition)\n }\n })\n }\n })\n }\n\n /**\n * This adds ES5 getters/setters to the target based on the \"properties\" in\n * this Schema, which makes possible change tracking and validation on\n * property assignment.\n *\n * @name Schema#apply\n * @method\n * @param {object} target The prototype to which to apply this schema.\n * @param opts\n */\n apply (target, opts: any = {}) {\n opts.getter = opts.getter || '_get'\n opts.setter = opts.setter || '_set'\n opts.unsetter = opts.unsetter || '_unset'\n opts.track = opts.track || this.track\n const properties = this.properties || {}\n utils.forOwn(properties, (schema, prop) => {\n Object.defineProperty(target, prop, this.makeDescriptor(prop, schema, opts))\n })\n }\n\n /**\n * Apply default values to the target object for missing values.\n *\n * @name Schema#applyDefaults\n * @method\n * @param {object} target The target to which to apply values for missing values.\n */\n applyDefaults (target) {\n if (!target) {\n return\n }\n const properties = this.properties || {}\n const hasSet = utils.isFunction(target.set) || utils.isFunction(target._set)\n utils.forOwn(properties, (schema, prop) => {\n if (schema.hasOwnProperty('default') && utils.get(target, prop) === undefined) {\n if (hasSet) {\n target.set(prop, utils.plainCopy(schema.default), { silent: true })\n } else {\n utils.set(target, prop, utils.plainCopy(schema.default))\n }\n }\n if (schema.type === 'object' && schema.properties) {\n if (hasSet) {\n const orig = target._get('noValidate')\n target._set('noValidate', true)\n utils.set(target, prop, utils.get(target, prop) || {}, { silent: true })\n target._set('noValidate', orig)\n } else {\n utils.set(target, prop, utils.get(target, prop) || {})\n }\n schema.applyDefaults(utils.get(target, prop))\n }\n })\n }\n\n /**\n * Assemble a property descriptor for tracking and validating changes to\n * a property according to the given schema. This method is called when\n * {@link Mapper#applySchema} is set to `true`.\n *\n * @name Schema#makeDescriptor\n * @method\n * @param {string} prop The property name.\n * @param {(Schema|object)} schema The schema for the property.\n * @param {object} [opts] Optional configuration.\n * @param {function} [opts.getter] Custom getter function.\n * @param {function} [opts.setter] Custom setter function.\n * @param {function} [opts.track] Whether to track changes.\n * @returns {object} A property descriptor for the given schema.\n */\n makeDescriptor (prop, schema, opts) {\n const descriptor: any = {\n // Better to allow configurability, but at the user's own risk\n configurable: true,\n // These properties are enumerable by default, but regardless of their\n // enumerability, they won't be \"own\" properties of individual records\n enumerable: schema.enumerable === undefined ? true : !!schema.enumerable,\n get () {\n return this._get(keyPath)\n },\n set (value) {\n // These are accessed a lot\n const _get = this[getter]\n const _set = this[setter]\n const _unset = this[unsetter]\n // Optionally check that the new value passes validation\n if (!_get(noValidatePath)) {\n const errors = schema.validate(value, { path: [prop] })\n if (errors) {\n // Immediately throw an error, preventing the record from getting into\n // an invalid state\n const error = new TsDataError(validationFailureMsg)\n error.errors = errors\n throw error\n }\n }\n // TODO: Make it so tracking can be turned on for all properties instead of\n // only per-property\n if (track && !_get(creatingPath)) {\n // previous is versioned on database commit\n // props are versioned on set()\n const previous = _get(previousPath)\n const current = _get(keyPath)\n let changing = _get(changingPath)\n let changed = _get(changedPath)\n\n if (!changing) {\n // Track properties that are changing in the current event loop\n changed = []\n }\n\n // Add changing properties to this array once at most\n const index = changed.indexOf(prop)\n if (current !== value && index === -1) {\n changed.push(prop)\n }\n if (previous === value) {\n if (index >= 0) {\n changed.splice(index, 1)\n }\n }\n // No changes in current event loop\n if (!changed.length) {\n changing = false\n _unset(changingPath)\n _unset(changedPath)\n // Cancel pending change event\n if (_get(eventIdPath)) {\n clearTimeout(_get(eventIdPath))\n _unset(eventIdPath)\n }\n }\n // Changes detected in current event loop\n if (!changing && changed.length) {\n _set(changedPath, changed)\n _set(changingPath, true)\n // Saving the timeout id allows us to batch all changes in the same\n // event loop into a single \"change\"\n // TODO: Optimize\n _set(\n eventIdPath,\n setTimeout(() => {\n // Previous event loop where changes were gathered has ended, so\n // notify any listeners of those changes and prepare for any new\n // changes\n _unset(changedPath)\n _unset(eventIdPath)\n _unset(changingPath)\n // TODO: Optimize\n if (!_get(silentPath)) {\n let i\n for (i = 0; i < changed.length; i++) {\n this.emit('change:' + changed[i], this, utils.get(this, changed[i]))\n }\n\n const changes = utils.diffObjects({ [prop]: value }, { [prop]: current })\n\n if (_get(keepChangeHistoryPath)) {\n const changeRecord = utils.plainCopy(changes)\n changeRecord.timestamp = new Date().getTime()\n let changeHistory = _get(changeHistoryPath)\n if (!changeHistory) _set(changeHistoryPath, (changeHistory = []))\n changeHistory.push(changeRecord)\n }\n this.emit('change', this, changes)\n }\n _unset(silentPath)\n }, 0)\n )\n }\n }\n _set(keyPath, value)\n return value\n }\n }\n // Cache a few strings for optimal performance\n const keyPath = `props.${prop}`\n const previousPath = `previous.${prop}`\n const getter = opts.getter\n const setter = opts.setter\n const unsetter = opts.unsetter\n const track = utils.isBoolean(opts.track) ? opts.track : schema.track\n\n if (utils.isFunction(schema.get)) {\n const originalGet = descriptor.get\n descriptor.get = function () {\n return schema.get.call(this, originalGet)\n }\n }\n\n if (utils.isFunction(schema.set)) {\n const originalSet = descriptor.set\n descriptor.set = function (value) {\n return schema.set.call(this, value, originalSet)\n }\n }\n\n return descriptor\n }\n\n /**\n * Create a copy of the given value that contains only the properties defined\n * in this schema.\n *\n * @name Schema#pick\n * @method\n * @param {*} value The value to copy.\n * @returns {*} The copy.\n */\n pick (value, opts?) {\n if (value === undefined) {\n return\n }\n if (this.type === 'object') {\n const copy = {}\n const properties = this.properties\n if (properties) {\n utils.forOwn(properties, (_definition, prop) => {\n copy[prop] = _definition.pick(value[prop])\n })\n }\n if (this.extends) {\n utils.fillIn(copy, this.extends.pick(value))\n }\n // Conditionally copy properties not defined in \"properties\"\n if (this.additionalProperties) {\n for (const key in value) {\n if (!properties[key]) {\n copy[key] = utils.plainCopy(value[key])\n }\n }\n }\n return copy\n } else if (this.type === 'array') {\n return value.map(item => {\n const _copy = this.items ? this.items.pick(item) : {}\n if (this.extends) {\n utils.fillIn(_copy, this.extends.pick(item))\n }\n return _copy\n })\n }\n return utils.plainCopy(value)\n }\n\n /**\n * Validate the provided value against this schema.\n *\n * @name Schema#validate\n * @method\n * @param {*} value Value to validate.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n validate (value, opts?) {\n return validate(value, this, opts)\n }\n\n static ANY_OPS = ANY_OPS;\n static ARRAY_OPS = ARRAY_OPS;\n static NUMERIC_OPS = NUMERIC_OPS;\n static OBJECT_OPS = OBJECT_OPS;\n static STRING_OPS = STRING_OPS;\n static typeGroupValidators = typeGroupValidators;\n static types = types;\n static validate = validate;\n static validationKeywords: any = validationKeywords;\n}\n","import utils from '../utils'\nimport { Relation } from '../Relation'\n\nexport class BelongsToRelation extends Relation {\n getForeignKey (record) {\n return utils.get(record, this.foreignKey)\n }\n\n _setForeignKey (record, relatedRecord) {\n utils.set(record, this.foreignKey, utils.get(relatedRecord, this.getRelation().idAttribute))\n }\n\n findExistingLinksFor (record) {\n // console.log('\\tBelongsTo#findExistingLinksFor', record)\n if (!record) {\n return\n }\n const relatedId = utils.get(record, this.foreignKey)\n if (relatedId !== undefined && relatedId !== null) {\n return this.relatedCollection.get(relatedId)\n }\n }\n\n isRequiresParentId () {\n return true\n }\n\n createParentRecord (props, opts) {\n const relationData = this.getLocalField(props)\n\n return this.createLinked(relationData, opts).then(record => {\n this.setForeignKey(props, record)\n })\n }\n\n createChildRecord () {\n throw new Error('\"BelongsTo\" relation does not support child creation as it cannot have children.')\n }\n\n static TYPE_NAME = 'belongsTo';\n}\n","import utils from '../utils'\nimport { Relation } from '../Relation'\n\nexport class HasManyRelation extends Relation {\n foreignKeys: any;\n localKeys: any;\n validateOptions (related, opts) {\n super.validateOptions(related, opts)\n\n const { localKeys, foreignKeys, foreignKey } = opts\n\n if (!foreignKey && !localKeys && !foreignKeys) {\n throw utils.err('new Relation', 'opts.')(400, 'string', foreignKey)\n }\n }\n\n canFindLinkFor (record) {\n const hasForeignKeys = this.foreignKey || this.foreignKeys\n return !!(hasForeignKeys || (this.localKeys && utils.get(record, this.localKeys)))\n }\n\n linkRecord (record, relatedRecords) {\n const relatedCollection = this.relatedCollection\n const canAutoAddLinks = this.canAutoAddLinks\n const foreignKey = this.foreignKey\n const unsaved = this.relatedCollection.unsaved()\n\n return relatedRecords.map(relatedRecord => {\n const relatedId = relatedCollection.recordId(relatedRecord)\n\n if (\n (relatedId === undefined && unsaved.indexOf(relatedRecord) === -1) ||\n relatedRecord !== relatedCollection.get(relatedId)\n ) {\n if (foreignKey) {\n // TODO: slow, could be optimized? But user loses hook\n this.setForeignKey(record, relatedRecord)\n }\n if (canAutoAddLinks) {\n relatedRecord = relatedCollection.add(relatedRecord)\n }\n }\n\n return relatedRecord\n })\n }\n\n findExistingLinksFor (record) {\n const id = utils.get(record, this.mapper.idAttribute)\n const ids = this.localKeys ? utils.get(record, this.localKeys) : null\n let records\n\n if (id !== undefined && this.foreignKey) {\n records = this.findExistingLinksByForeignKey(id)\n } else if (this.localKeys && ids) {\n records = this.findExistingLinksByLocalKeys(ids)\n } else if (id !== undefined && this.foreignKeys) {\n records = this.findExistingLinksByForeignKeys(id)\n }\n\n if (records?.length) {\n return records\n }\n }\n\n // e.g. user hasMany group via \"foreignKeys\", so find all users of a group\n findExistingLinksByLocalKeys (ids) {\n return this.relatedCollection.filter({\n where: {\n [this.relatedCollection.mapper.idAttribute]: {\n in: ids\n }\n }\n })\n }\n\n // e.g. group hasMany user via \"localKeys\", so find all groups that own a user\n findExistingLinksByForeignKeys (id) {\n return this.relatedCollection.filter({\n where: {\n [this.foreignKeys]: {\n contains: id\n }\n }\n })\n }\n\n isRequiresParentId () {\n return !!this.localKeys && this.localKeys.length > 0\n }\n\n isRequiresChildId () {\n return !!this.foreignKey\n }\n\n createParentRecord (props, opts) {\n const relationData = this.getLocalField(props)\n const foreignIdField = this.getRelation().idAttribute\n\n return this.createLinked(relationData, opts).then(records => {\n utils.set(\n props,\n this.localKeys,\n records.map(record => utils.get(record, foreignIdField))\n )\n })\n }\n\n createLinked (props, opts) {\n return this.getRelation().createMany(props, opts)\n }\n\n static TYPE_NAME = 'hasMany';\n}\n","import utils from '../utils'\nimport { Relation } from '../Relation'\n\nexport class HasOneRelation extends Relation {\n findExistingLinksFor (relatedMapper, record) {\n const recordId = utils.get(record, relatedMapper.idAttribute)\n const records = this.findExistingLinksByForeignKey(recordId)\n\n if (records?.length) {\n return records[0]\n }\n }\n\n isRequiresChildId () {\n return true\n }\n\n static TYPE_NAME = 'hasOne';\n}\n","import { Relation } from './Relation'\nimport { BelongsToRelation } from './Relation/BelongsTo'\nimport { HasManyRelation } from './Relation/HasMany'\nimport { HasOneRelation } from './Relation/HasOne';\n\n[BelongsToRelation, HasManyRelation, HasOneRelation].forEach(RelationType => {\n Relation[RelationType.TYPE_NAME] = (related, options) => new RelationType(related, options)\n})\n\nexport { belongsToType, hasManyType, hasOneType, Relation } from './Relation'\n","import { Relation } from './relations'\n\nexport { belongsToType, hasManyType, hasOneType } from './relations'\n\n/**\n * BelongsTo relation decorator. You probably won't use this directly.\n *\n * @method\n * @param {Mapper} related The relation the target belongs to.\n * @param {object} opts Configuration options.\n * @param {string} opts.foreignKey The field that holds the primary key of the\n * related record.\n * @param {string} opts.localField The field that holds a reference to the\n * related record object.\n * @returns {Function} Invocation function, which accepts the target as the only\n * parameter.\n */\nexport function belongsTo (related, opts) {\n return mapper => {\n Relation.belongsTo(related, opts).assignTo(mapper)\n }\n}\n\n/**\n * HasMany relation decorator. You probably won't use this directly.\n *\n * @method\n * @param {Mapper} related The relation of which the target has many.\n * @param {object} opts Configuration options.\n * @param {string} [opts.foreignKey] The field that holds the primary key of the\n * related record.\n * @param {string} opts.localField The field that holds a reference to the\n * related record object.\n * @returns {Function} Invocation function, which accepts the target as the only\n * parameter.\n */\nexport function hasMany (related, opts) {\n return mapper => {\n Relation.hasMany(related, opts).assignTo(mapper)\n }\n}\n\n/**\n * HasOne relation decorator. You probably won't use this directly.\n *\n * @method\n * @param {Mapper} related The relation of which the target has one.\n * @param {object} opts Configuration options.\n * @param {string} [opts.foreignKey] The field that holds the primary key of the\n * related record.\n * @param {string} opts.localField The field that holds a reference to the\n * related record object.\n * @returns {Function} Invocation function, which accepts the target as the only\n * parameter.\n */\nexport function hasOne (related, opts) {\n return mapper => {\n Relation.hasOne(related, opts).assignTo(mapper)\n }\n}\n","import utils from './utils'\nimport Component from './Component'\nimport Record from './Record'\nimport Schema, { PropertyDefinition, SchemaDefinition } from './Schema'\nimport { Relation } from './Relation'\nimport { belongsTo, belongsToType, hasMany, hasManyType, hasOne, hasOneType } from './decorators'\nimport { TsDataError } from './TsDataError'\nimport { QueryDefinition } from './Query'\n\nconst DOMAIN = 'Mapper'\nconst applyDefaultsHooks = ['beforeCreate', 'beforeCreateMany']\nconst validatingHooks = ['beforeCreate', 'beforeCreateMany', 'beforeUpdate', 'beforeUpdateAll', 'beforeUpdateMany']\n\nfunction makeNotify (num) {\n return function (...args) {\n const opts = args[args.length - num]\n const op = opts.op\n this.dbg(op, ...args)\n\n if (applyDefaultsHooks.indexOf(op) !== -1 && opts.applyDefaults !== false) {\n const schema = this.getSchema()\n if (schema?.applyDefaults) {\n let toProcess = args[0]\n if (!utils.isArray(toProcess)) {\n toProcess = [toProcess]\n }\n toProcess.forEach(record => {\n schema.applyDefaults(record)\n })\n }\n }\n\n // Automatic validation\n if (validatingHooks.indexOf(op) !== -1 && !opts.noValidate) {\n // Save current value of option\n const originalExistingOnly = opts.existingOnly\n\n // For updates, ignore required fields if they aren't present\n if (op.indexOf('beforeUpdate') === 0 && opts.existingOnly === undefined) {\n opts.existingOnly = true\n }\n const errors = this.validate(args[op === 'beforeUpdate' ? 1 : 0], utils.pick(opts, ['existingOnly']))\n\n // Restore option\n opts.existingOnly = originalExistingOnly\n\n // Abort lifecycle due to validation errors\n if (errors) {\n const err = new TsDataError('validation failed')\n err.errors = errors\n return utils.reject(err)\n }\n }\n\n // Emit lifecycle event\n if (opts.notify || (opts.notify === undefined && this.notify)) {\n setTimeout(() => {\n this.emit(op, ...args)\n })\n }\n }\n}\n\n// These are the default implementations of all of the lifecycle hooks\nconst notify = makeNotify(1)\nconst notify2 = makeNotify(2)\n\n// This object provides meta information used by Mapper#crud to actually\n// execute each lifecycle method\nconst LIFECYCLE_METHODS = {\n count: {\n defaults: [{}, {}],\n skip: true,\n types: []\n },\n destroy: {\n defaults: [{}, {}],\n skip: true,\n types: []\n },\n destroyAll: {\n defaults: [{}, {}],\n skip: true,\n types: []\n },\n find: {\n defaults: [undefined, {}],\n types: []\n },\n findAll: {\n defaults: [{}, {}],\n types: []\n },\n sum: {\n defaults: [undefined, {}, {}],\n skip: true,\n types: []\n },\n update: {\n adapterArgs (mapper, id, props, opts) {\n return [id, mapper.toJSON(props, opts), opts]\n },\n beforeAssign: 1,\n defaults: [undefined, {}, {}],\n types: []\n },\n updateAll: {\n adapterArgs (mapper, props, query, opts) {\n return [mapper.toJSON(props, opts), query, opts]\n },\n beforeAssign: 0,\n defaults: [{}, {}, {}],\n types: []\n },\n updateMany: {\n adapterArgs (mapper, records, opts) {\n return [records.map(record => mapper.toJSON(record, opts)), opts]\n },\n beforeAssign: 0,\n defaults: [[], {}],\n types: []\n }\n}\n\nexport interface MapperOpts {\n name?: string\n\n [customAttr: string]: any\n\n endpoint?: string\n\n onConflict?: 'skip'\n\n relations?: any\n\n type?: string\n\n schema?: SchemaDefinition | Schema\n\n recordClass?: typeof Record | boolean\n\n wrap?: boolean\n\n methods?: { [name: string]: Function }\n\n scopes?: any\n\n mapperClass?: typeof Mapper\n\n /**\n * Hash of registered adapters. Don't modify directly. Use\n * {@link Mapper#registerAdapter} instead.\n *\n * @default {}\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/connecting-to-a-data-source\",\"Connecting to a data source\"]\n */\n _adapters?: {}\n\n /**\n * Whether {@link Mapper#beforeCreate} and {@link Mapper#beforeCreateMany}\n * should automatically receive default values according to the Mapper's schema.\n *\n * @default true\n * @since 3.0.0\n */\n applyDefaults?: boolean\n\n /**\n * Whether to augment {@link Mapper#recordClass} with ES5 getters and setters\n * according to the properties defined in {@link Mapper#schema}. This makes\n * possible validation and change tracking on individual properties\n * when using the dot (e.g. `user.name = \"Bob\"`) operator to modify a\n * property, and is `true` by default.\n *\n * @default true\n * @since 3.0.0\n */\n applySchema?: boolean\n\n /**\n * The name of the registered adapter that this Mapper should used by default.\n *\n * @default \"http\"\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/connecting-to-a-data-source\",\"Connecting to a data source\"]\n */\n defaultAdapter?: string\n\n /**\n * The field used as the unique identifier on records handled by this Mapper.\n *\n * @default id\n * @since 3.0.0\n */\n idAttribute?: string\n\n properties?: { [name: string]: PropertyDefinition }\n\n /**\n * Whether records created from this mapper keep changeHistory on property changes.\n *\n * @default true\n * @since 3.0.0\n */\n keepChangeHistory?: boolean\n\n /**\n * Whether this Mapper should emit operational events.\n *\n * @default true\n * @since 3.0.0\n */\n notify?: boolean\n\n /**\n * Whether to skip validation when the Record instances are created.\n *\n * @default false\n * @since 3.0.0\n */\n noValidate?: boolean\n\n /**\n * Whether {@link Mapper#create}, {@link Mapper#createMany},\n * {@link Mapper#update}, {@link Mapper#updateAll}, {@link Mapper#updateMany},\n * {@link Mapper#find}, {@link Mapper#findAll}, {@link Mapper#destroy},\n * {@link Mapper#destroyAll}, {@link Mapper#count}, and {@link Mapper#sum}\n * should return a raw result object that contains both the instance data\n * returned by the adapter _and_ metadata about the operation.\n *\n * The default is to NOT return the result object, and instead return just the\n * instance data.\n *\n * @default false\n * @since 3.0.0\n */\n raw?: boolean\n\n /**\n * Whether records created from this mapper automatically validate their properties\n * when their properties are modified.\n *\n * @default true\n * @since 3.0.0\n */\n validateOnSet?: boolean\n}\n\nconst MAPPER_DEFAULTS: MapperOpts = {\n _adapters: {},\n applyDefaults: true,\n applySchema: true,\n defaultAdapter: 'http',\n idAttribute: 'id',\n keepChangeHistory: true,\n notify: true,\n noValidate: false,\n raw: false,\n validateOnSet: true\n}\n\n/**\n * The core of JSData's [ORM/ODM][orm] implementation. Given a minimum amount of\n * meta information about a resource, a Mapper can perform generic CRUD\n * operations against that resource. Apart from its configuration, a Mapper is\n * stateless. The particulars of various persistence layers have been abstracted\n * into adapters, which a Mapper uses to perform its operations.\n *\n * The term \"Mapper\" comes from the [Data Mapper Pattern][pattern] described in\n * Martin Fowler's [Patterns of Enterprise Application Architecture][book]. A\n * Data Mapper moves data between [in-memory object instances][record] and a\n * relational or document-based database. JSData's Mapper can work with any\n * persistence layer you can write an adapter for.\n *\n * _(\"Model\" is a heavily overloaded term and is avoided in this documentation\n * to prevent confusion.)_\n *\n * [orm]: https://en.wikipedia.org/wiki/Object-relational_mapping\n *\n * @example\n * [pattern]: https://en.wikipedia.org/wiki/Data_mapper_pattern\n * [book]: http://martinfowler.com/books/eaa.html\n * [record]: Record.html\n * // Import and instantiate\n * import { Mapper } from 'js-data';\n * const UserMapper = new Mapper({ name: 'user' });\n *\n * @example\n * // Define a Mapper using the Container component\n * import { Container } from 'js-data';\n * const store = new Container();\n * store.defineMapper('user');\n *\n * @class Mapper\n * @extends Component\n * @param {object} opts Configuration options.\n * @param {boolean} [opts.applySchema=true] See {@link Mapper#applySchema}.\n * @param {boolean} [opts.debug=false] See {@link Component#debug}.\n * @param {string} [opts.defaultAdapter=http] See {@link Mapper#defaultAdapter}.\n * @param {string} [opts.idAttribute=id] See {@link Mapper#idAttribute}.\n * @param {object} [opts.methods] See {@link Mapper#methods}.\n * @param {string} opts.name See {@link Mapper#name}.\n * @param {boolean} [opts.notify] See {@link Mapper#notify}.\n * @param {boolean} [opts.raw=false] See {@link Mapper#raw}.\n * @param {Function|boolean} [opts.recordClass] See {@link Mapper#recordClass}.\n * @param {Object|Schema} [opts.schema] See {@link Mapper#schema}.\n * @returns {Mapper} A new {@link Mapper} instance.\n * @see http://www.js-data.io/v3.0/docs/components-of-jsdata#mapper\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/components-of-jsdata#mapper\",\"Components of JSData: Mapper\"]\n * @tutorial [\"http://www.js-data.io/v3.0/docs/modeling-your-data\",\"Modeling your data\"]\n */\nexport default class Mapper extends Component {\n idAttribute: string;\n\n name: string;\n /**\n * This Mapper's {@link Schema}.\n *\n * @example Mapper#schema\n * const JSData = require('js-data');\n * const { Mapper } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const UserMapper = new Mapper({\n * name: 'user',\n * schema: {\n * properties: {\n * id: { type: 'number' },\n * first: { type: 'string', track: true },\n * last: { type: 'string', track: true },\n * role: { type: 'string', track: true, required: true },\n * age: { type: 'integer', track: true },\n * is_active: { type: 'number' }\n * }\n * }\n * });\n * const user = UserMapper.createRecord({\n * id: 1,\n * name: 'John',\n * role: 'admin'\n * });\n * user.on('change', function (user, changes) {\n * console.log(changes);\n * });\n * user.on('change:role', function (user, value) {\n * console.log('change:role - ' + value);\n * });\n * user.role = 'owner';\n *\n * @name Mapper#schema\n * @see Schema\n * @since 3.0.0\n * @type {Schema}\n */\n schema: Schema;\n /**\n * Set to `false` to force the Mapper to work with POJO objects only.\n *\n * @example\n * // Use POJOs only.\n * import { Mapper, Record } from 'js-data';\n * const UserMapper = new Mapper({ recordClass: false });\n * UserMapper.recordClass // false;\n * const user = UserMapper.createRecord();\n * user instanceof Record; // false\n *\n * @example\n * // Set to a custom class to have records wrapped in your custom class.\n * import { Mapper, Record } from 'js-data';\n * // Custom class\n * class User {\n * constructor (props = {}) {\n * for (var key in props) {\n * if (props.hasOwnProperty(key)) {\n * this[key] = props[key];\n * }\n * }\n * }\n * }\n * const UserMapper = new Mapper({ recordClass: User });\n * UserMapper.recordClass; // function User() {}\n * const user = UserMapper.createRecord();\n * user instanceof Record; // false\n * user instanceof User; // true\n *\n *\n * @example\n * // Extend the {@link Record} class.\n * import { Mapper, Record } from 'js-data';\n * // Custom class\n * class User extends Record {\n * constructor () {\n * super(props);\n * }\n * }\n * const UserMapper = new Mapper({ recordClass: User });\n * UserMapper.recordClass; // function User() {}\n * const user = UserMapper.createRecord();\n * user instanceof Record; // true\n * user instanceof User; // true\n *\n * @name Mapper#recordClass\n * @default {@link Record}\n * @see Record\n * @since 3.0.0\n */\n recordClass: typeof Record | Function | false | any;\n methods: any;\n applySchema: any;\n relationList: any;\n defaultAdapter: any;\n relationFields: any;\n _adapters: any;\n relations: any;\n /**\n * The meta information describing this Mapper's available lifecycle\n * methods. __Do not modify.__\n *\n * @name Mapper#lifecycleMethods\n * @since 3.0.0\n * @type {Object}\n */\n lifecycleMethods = LIFECYCLE_METHODS;\n\n /**\n * The {@link Container} that holds this Mapper. __Do not modify.__\n *\n * @name Mapper#lifecycleMethods\n * @since 3.0.0\n * @type {Object}\n */\n datastore: any;\n validateOnSet: any;\n keepChangeHistory: any;\n\n constructor (opts: MapperOpts = {}) {\n super()\n\n // Apply user-provided configuration\n utils.fillIn(this, opts)\n // Fill in any missing options with the defaults\n utils.fillIn(this, utils.copy(MAPPER_DEFAULTS))\n\n /**\n * The name for this Mapper. This is the minimum amount of meta information\n * required for a Mapper to be able to execute CRUD operations for a\n * Resource.\n *\n * @name Mapper#name\n * @since 3.0.0\n * @type {string}\n */\n if (!this.name) {\n throw utils.err(`new ${DOMAIN}`, 'opts.name')(400, 'string', this.name)\n }\n\n // Setup schema, with an empty default schema if necessary\n if (this.schema) {\n this.schema.type = this.schema.type || 'object'\n if (!(this.schema instanceof Schema)) {\n this.schema = new Schema(this.schema || { type: 'object' })\n }\n }\n\n // Create a subclass of Record that's tied to this Mapper\n if (this.recordClass === undefined) {\n // tslint:disable-next-line:max-classes-per-file\n this.recordClass = class TiedRecord extends Record {}\n }\n\n if (this.recordClass) {\n this.recordClass.mapper = this\n\n /**\n * Functions that should be added to the prototype of {@link Mapper#recordClass}.\n *\n * @name Mapper#methods\n * @since 3.0.0\n * @type {Object}\n */\n if (utils.isObject(this.methods)) {\n utils.addHiddenPropsToTarget(this.recordClass.prototype, this.methods)\n }\n\n // We can only apply the schema to the prototype of this.recordClass if the\n // class extends Record\n if (\n Record.prototype.isPrototypeOf(Object.create(this.recordClass.prototype)) &&\n this.schema &&\n this.schema.apply &&\n this.applySchema\n ) {\n this.schema.apply(this.recordClass.prototype)\n }\n }\n }\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#count}. If this method\n * returns a promise then {@link Mapper#count} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#afterCount\n * @param {object} query The `query` argument passed to {@link Mapper#count}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#count}.\n * @param {*} result The result, if any.\n * @since 3.0.0\n */\n afterCount = notify2;\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#create}. If this method\n * returns a promise then {@link Mapper#create} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#afterCreate\n * @param {object} props The `props` argument passed to {@link Mapper#create}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#create}.\n * @param {*} result The result, if any.\n * @since 3.0.0\n */\n afterCreate = notify2;\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#createMany}. If this method\n * returns a promise then {@link Mapper#createMany} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#afterCreateMany\n * @param {array} records The `records` argument passed to {@link Mapper#createMany}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#createMany}.\n * @param {*} result The result, if any.\n * @since 3.0.0\n */\n afterCreateMany = notify2;\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#destroy}. If this method\n * returns a promise then {@link Mapper#destroy} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#afterDestroy\n * @param {(string|number)} id The `id` argument passed to {@link Mapper#destroy}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#destroy}.\n * @param {*} result The result, if any.\n * @since 3.0.0\n */\n afterDestroy = notify2;\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#destroyAll}. If this method\n * returns a promise then {@link Mapper#destroyAll} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#afterDestroyAll\n * @param {*} data The `data` returned by the adapter.\n * @param {query} query The `query` argument passed to {@link Mapper#destroyAll}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#destroyAll}.\n * @param {*} result The result, if any.\n * @since 3.0.0\n */\n afterDestroyAll = notify2;\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#find}. If this method\n * returns a promise then {@link Mapper#find} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#afterFind\n * @param {(string|number)} id The `id` argument passed to {@link Mapper#find}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#find}.\n * @param {*} result The result, if any.\n * @since 3.0.0\n */\n afterFind = notify2;\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#findAll}. If this method\n * returns a promise then {@link Mapper#findAll} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#afterFindAll\n * @param {object} query The `query` argument passed to {@link Mapper#findAll}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#findAll}.\n * @param {*} result The result, if any.\n * @since 3.0.0\n */\n afterFindAll = notify2;\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#sum}. If this method\n * returns a promise then {@link Mapper#sum} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#afterSum\n * @param {object} query The `query` argument passed to {@link Mapper#sum}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#sum}.\n * @param {*} result The result, if any.\n * @since 3.0.0\n */\n afterSum = notify2;\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#update}. If this method\n * returns a promise then {@link Mapper#update} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#afterUpdate\n * @param {(string|number)} id The `id` argument passed to {@link Mapper#update}.\n * @param {props} props The `props` argument passed to {@link Mapper#update}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#update}.\n * @param {*} result The result, if any.\n * @since 3.0.0\n */\n afterUpdate = notify2;\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#updateAll}. If this method\n * returns a promise then {@link Mapper#updateAll} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#afterUpdateAll\n * @param {object} props The `props` argument passed to {@link Mapper#updateAll}.\n * @param {object} query The `query` argument passed to {@link Mapper#updateAll}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#updateAll}.\n * @param {*} result The result, if any.\n * @since 3.0.0\n */\n afterUpdateAll = notify2;\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#updateMany}. If this method\n * returns a promise then {@link Mapper#updateMany} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#afterUpdateMany\n * @param {array} records The `records` argument passed to {@link Mapper#updateMany}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#updateMany}.\n * @param {*} result The result, if any.\n * @since 3.0.0\n */\n afterUpdateMany = notify2;\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#create}. If this method\n * returns a promise then {@link Mapper#create} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#beforeCreate\n * @param {object} props The `props` argument passed to {@link Mapper#create}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#create}.\n * @since 3.0.0\n */\n beforeCreate = notify;\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#createMany}. If this method\n * returns a promise then {@link Mapper#createMany} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#beforeCreateMany\n * @param {array} records The `records` argument passed to {@link Mapper#createMany}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#createMany}.\n * @since 3.0.0\n */\n beforeCreateMany = notify;\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#count}. If this method\n * returns a promise then {@link Mapper#count} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#beforeCount\n * @param {object} query The `query` argument passed to {@link Mapper#count}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#count}.\n * @since 3.0.0\n */\n beforeCount = notify;\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#destroy}. If this method\n * returns a promise then {@link Mapper#destroy} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#beforeDestroy\n * @param {(string|number)} id The `id` argument passed to {@link Mapper#destroy}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#destroy}.\n * @since 3.0.0\n */\n beforeDestroy = notify;\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#destroyAll}. If this method\n * returns a promise then {@link Mapper#destroyAll} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#beforeDestroyAll\n * @param {query} query The `query` argument passed to {@link Mapper#destroyAll}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#destroyAll}.\n * @since 3.0.0\n */\n beforeDestroyAll = notify;\n\n /**\n * Mappers lifecycle hook called by {@link Mapper#find}. If this method\n * returns a promise then {@link Mapper#find} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#beforeFind\n * @param {(string|number)} id The `id` argument passed to {@link Mapper#find}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#find}.\n * @since 3.0.0\n */\n beforeFind = notify;\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#findAll}. If this method\n * returns a promise then {@link Mapper#findAll} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#beforeFindAll\n * @param {object} query The `query` argument passed to {@link Mapper#findAll}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#findAll}.\n * @since 3.0.0\n */\n beforeFindAll = notify;\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#sum}. If this method\n * returns a promise then {@link Mapper#sum} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#beforeSum\n * @param {string} field The `field` argument passed to {@link Mapper#sum}.\n * @param {object} query The `query` argument passed to {@link Mapper#sum}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#sum}.\n * @since 3.0.0\n */\n beforeSum = notify;\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#update}. If this method\n * returns a promise then {@link Mapper#update} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#beforeUpdate\n * @param {(string|number)} id The `id` argument passed to {@link Mapper#update}.\n * @param {props} props The `props` argument passed to {@link Mapper#update}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#update}.\n * @since 3.0.0\n */\n beforeUpdate = notify;\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#updateAll}. If this method\n * returns a promise then {@link Mapper#updateAll} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#beforeUpdateAll\n * @param {object} props The `props` argument passed to {@link Mapper#updateAll}.\n * @param {object} query The `query` argument passed to {@link Mapper#updateAll}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#updateAll}.\n * @since 3.0.0\n */\n beforeUpdateAll = notify;\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#updateMany}. If this method\n * returns a promise then {@link Mapper#updateMany} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#beforeUpdateMany\n * @param {array} records The `records` argument passed to {@link Mapper#updateMany}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#updateMany}.\n * @since 3.0.0\n */\n beforeUpdateMany = notify;\n\n /**\n * This method is called at the end of most lifecycle methods. It does the\n * following:\n *\n * 1. If `opts.raw` is `true`, add this Mapper's configuration to the `opts`\n * argument as metadata for the operation.\n * 2. Wrap the result data appropriately using {@link Mapper#wrap}, which\n * calls {@link Mapper#createRecord}.\n *\n * @method Mapper#_end\n * @private\n * @since 3.0.0\n */\n _end (result, opts, skip = false) {\n if (opts.raw) {\n utils._(result, opts)\n }\n if (skip) {\n return result\n }\n let _data = opts.raw ? result.data : result\n if (_data && utils.isFunction(this.wrap)) {\n _data = this.wrap(_data, opts)\n if (opts.raw) {\n result.data = _data\n } else {\n result = _data\n }\n }\n return result\n }\n\n /**\n * Define a belongsTo relationship. Only useful if you're managing your\n * Mappers manually and not using a Container or DataStore component.\n *\n * @example\n * PostMapper.belongsTo(UserMapper, {\n * // post.user_id points to user.id\n * foreignKey: 'user_id'\n * // user records will be attached to post records at \"post.user\"\n * localField: 'user'\n * });\n *\n * CommentMapper.belongsTo(UserMapper, {\n * // comment.user_id points to user.id\n * foreignKey: 'user_id'\n * // user records will be attached to comment records at \"comment.user\"\n * localField: 'user'\n * });\n * CommentMapper.belongsTo(PostMapper, {\n * // comment.post_id points to post.id\n * foreignKey: 'post_id'\n * // post records will be attached to comment records at \"comment.post\"\n * localField: 'post'\n * });\n *\n * @method Mapper#belongsTo\n * @see http://www.js-data.io/v3.0/docs/relations\n * @since 3.0.0\n */\n belongsTo (relatedMapper, opts) {\n return belongsTo(relatedMapper, opts)(this)\n }\n\n /**\n * Select records according to the `query` argument and return the count.\n *\n * {@link Mapper#beforeCount} will be called before calling the adapter.\n * {@link Mapper#afterCount} will be called after calling the adapter.\n *\n * @example\n * // Get the number of published blog posts\n * PostMapper.count({ status: 'published' }).then((numPublished) => {\n * console.log(numPublished); // e.g. 45\n * });\n *\n * @method Mapper#count\n * @param {object} [query={}] Selection query. See {@link query}.\n * @param {object} [query.where] See {@link query.where}.\n * @param {number} [query.offset] See {@link query.offset}.\n * @param {number} [query.limit] See {@link query.limit}.\n * @param {string|Array[]} [query.orderBy] See {@link query.orderBy}.\n * @param {object} [opts] Configuration options. Refer to the `count` method\n * of whatever adapter you're using for more configuration options.\n * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the\n * adapter to use.\n * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}.\n * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}.\n * @returns {Promise} Resolves with the count of the selected records.\n * @since 3.0.0\n */\n count (query, opts?) {\n return this.crud('count', query, opts)\n }\n\n /**\n * Fired during {@link Mapper#create}. See\n * {@link Mapper~beforeCreateListener} for how to listen for this event.\n *\n * @event Mapper#beforeCreate\n * @see Mapper~beforeCreateListener\n * @see Mapper#create\n */\n /**\n * Callback signature for the {@link Mapper#event:beforeCreate} event.\n *\n * @example\n * function onBeforeCreate (props, opts) {\n * // do something\n * }\n * store.on('beforeCreate', onBeforeCreate);\n *\n * @callback Mapper~beforeCreateListener\n * @param {object} props The `props` argument passed to {@link Mapper#beforeCreate}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#beforeCreate}.\n * @see Mapper#event:beforeCreate\n * @see Mapper#create\n * @since 3.0.0\n */\n /**\n * Fired during {@link Mapper#create}. See\n * {@link Mapper~afterCreateListener} for how to listen for this event.\n *\n * @event Mapper#afterCreate\n * @see Mapper~afterCreateListener\n * @see Mapper#create\n */\n\n /**\n * Callback signature for the {@link Mapper#event:afterCreate} event.\n *\n * @example\n * function onAfterCreate (props, opts, result) {\n * // do something\n * }\n * store.on('afterCreate', onAfterCreate);\n *\n * @callback Mapper~afterCreateListener\n * @param {object} props The `props` argument passed to {@link Mapper#afterCreate}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#afterCreate}.\n * @param {object} result The `result` argument passed to {@link Mapper#afterCreate}.\n * @see Mapper#event:afterCreate\n * @see Mapper#create\n * @since 3.0.0\n */\n /**\n * Create and save a new the record using the provided `props`.\n *\n * {@link Mapper#beforeCreate} will be called before calling the adapter.\n * {@link Mapper#afterCreate} will be called after calling the adapter.\n *\n * @example\n * // Create and save a new blog post\n * PostMapper.create({\n * title: 'Modeling your data',\n * status: 'draft'\n * }).then((post) => {\n * console.log(post); // { id: 1234, status: 'draft', ... }\n * });\n *\n * @fires Mapper#beforeCreate\n * @fires Mapper#afterCreate\n * @method Mapper#create\n * @param {object} props The properties for the new record.\n * @param {object} [opts] Configuration options. Refer to the `create` method\n * of whatever adapter you're using for more configuration options.\n * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the\n * adapter to use.\n * @param {boolean} [opts.noValidate={@link Mapper#noValidate}] See {@link Mapper#noValidate}.\n * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}.\n * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}.\n * @param {string[]} [opts.with=[]] Relations to create in a cascading\n * create if `props` contains nested relations. NOT performed in a\n * transaction. Each nested create will result in another {@link Mapper#create}\n * or {@link Mapper#createMany} call.\n * @param {string[]} [opts.pass=[]] Relations to send to the adapter as part\n * of the payload. Normally relations are not sent.\n * @returns {Promise} Resolves with the created record.\n * @since 3.0.0\n */\n create (props: any = {}, opts: any = {}) {\n const originalRecord = props\n let parentRelationMap = {}\n let adapterResponse: any = {}\n\n // Fill in \"opts\" with the Mapper's configuration\n utils._(opts, this)\n opts.adapter = this.getAdapterName(opts)\n\n opts.op = 'beforeCreate'\n return this._runHook(opts.op, props, opts)\n .then(props => {\n opts.with = opts.with || []\n return this._createParentRecordIfRequired(props, opts)\n })\n .then(relationMap => {\n parentRelationMap = relationMap\n })\n .then(() => {\n opts.op = 'create'\n return this._invokeAdapterMethod(opts.op, props, opts)\n })\n .then(result => {\n adapterResponse = result\n })\n .then(() => {\n const createdProps = opts.raw ? adapterResponse.data : adapterResponse\n\n return this._createOrAssignChildRecordIfRequired(createdProps, {\n opts,\n parentRelationMap,\n originalProps: props\n })\n })\n .then(createdProps => {\n return this._commitChanges(originalRecord, createdProps)\n })\n .then(record => {\n if (opts.raw) {\n adapterResponse.data = record\n } else {\n adapterResponse = record\n }\n const result = this._end(adapterResponse, opts)\n opts.op = 'afterCreate'\n return this._runHook(opts.op, props, opts, result)\n })\n }\n\n _commitChanges (recordOrRecords, newValues) {\n if (utils.isArray(recordOrRecords)) {\n return recordOrRecords.map((record, i) => this._commitChanges(record, newValues[i]))\n }\n\n utils.set(recordOrRecords, newValues, { silent: true })\n\n if (utils.isFunction(recordOrRecords.commit)) {\n recordOrRecords.commit()\n }\n\n return recordOrRecords\n }\n\n /**\n * Use {@link Mapper#createRecord} instead.\n * @deprecated\n * @method Mapper#createInstance\n * @param {Object|Array} props See {@link Mapper#createRecord}.\n * @param {object} [opts] See {@link Mapper#createRecord}.\n * @returns {Object|Array} See {@link Mapper#createRecord}.\n * @see Mapper#createRecord\n * @since 3.0.0\n */\n createInstance (props, opts?) {\n return this.createRecord(props, opts)\n }\n\n /**\n * Creates parent record for relation types like BelongsTo or HasMany with localKeys\n * in order to satisfy foreignKey dependency (so called child records).\n * @param {object} props See {@link Mapper#create}.\n * @param {object} opts See {@link Mapper#create}.\n * @returns {Object} cached parent records map\n * @see Mapper#create\n * @since 3.0.0\n */\n _createParentRecordIfRequired (props, opts) {\n const tasks = []\n const relations = []\n\n utils.forEachRelation(this, opts, (def, optsCopy) => {\n if (!def.isRequiresParentId() || !def.getLocalField(props)) {\n return\n }\n\n optsCopy.raw = false\n relations.push(def)\n tasks.push(def.createParentRecord(props, optsCopy))\n })\n\n return Promise.all(tasks).then(records => {\n return relations.reduce((map, relation, index) => {\n relation.setLocalField(map, records[index])\n return map\n }, {})\n })\n }\n\n /**\n * Creates child record for relation types like HasOne or HasMany with foreignKey\n * in order to satisfy foreignKey dependency (so called parent records).\n * @param {object} props See {@link Mapper#create}.\n * @param {object} context contains collected information.\n * @param {object} context.opts See {@link Mapper#create}.\n * @param {object} context.parentRelationMap contains parent records map\n * @param {object} context.originalProps contains data passed into {@link Mapper#create} method\n * @return {Promise} updated props\n * @see Mapper#create\n * @since 3.0.0\n */\n _createOrAssignChildRecordIfRequired (props, context) {\n const tasks = []\n\n utils.forEachRelation(this, context.opts, (def, optsCopy) => {\n const relationData = def.getLocalField(context.originalProps)\n\n if (!relationData) {\n return\n }\n\n optsCopy.raw = false\n // Create hasMany and hasOne after the main create because we needed\n // a generated id to attach to these items\n if (def.isRequiresChildId()) {\n tasks.push(def.createChildRecord(props, relationData, optsCopy))\n } else if (def.isRequiresParentId()) {\n const parent = def.getLocalField(context.parentRelationMap)\n\n if (parent) {\n def.setLocalField(props, parent)\n }\n }\n })\n\n return Promise.all(tasks).then(() => props)\n }\n\n /**\n * Fired during {@link Mapper#createMany}. See\n * {@link Mapper~beforeCreateManyListener} for how to listen for this event.\n *\n * @event Mapper#beforeCreateMany\n * @see Mapper~beforeCreateManyListener\n * @see Mapper#createMany\n */\n /**\n * Callback signature for the {@link Mapper#event:beforeCreateMany} event.\n *\n * @example\n * function onBeforeCreateMany (records, opts) {\n * // do something\n * }\n * store.on('beforeCreateMany', onBeforeCreateMany);\n *\n * @callback Mapper~beforeCreateManyListener\n * @param {object} records The `records` argument received by {@link Mapper#beforeCreateMany}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeCreateMany}.\n * @see Mapper#event:beforeCreateMany\n * @see Mapper#createMany\n * @since 3.0.0\n */\n /**\n * Fired during {@link Mapper#createMany}. See\n * {@link Mapper~afterCreateManyListener} for how to listen for this event.\n *\n * @event Mapper#afterCreateMany\n * @see Mapper~afterCreateManyListener\n * @see Mapper#createMany\n */\n\n /**\n * Callback signature for the {@link Mapper#event:afterCreateMany} event.\n *\n * @example\n * function onAfterCreateMany (records, opts, result) {\n * // do something\n * }\n * store.on('afterCreateMany', onAfterCreateMany);\n *\n * @callback Mapper~afterCreateManyListener\n * @param {object} records The `records` argument received by {@link Mapper#afterCreateMany}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterCreateMany}.\n * @param {object} result The `result` argument received by {@link Mapper#afterCreateMany}.\n * @see Mapper#event:afterCreateMany\n * @see Mapper#createMany\n * @since 3.0.0\n */\n /**\n * Given an array of records, batch create them via an adapter.\n *\n * {@link Mapper#beforeCreateMany} will be called before calling the adapter.\n * {@link Mapper#afterCreateMany} will be called after calling the adapter.\n *\n * @example\n * // Create and save several new blog posts\n * PostMapper.createMany([{\n * title: 'Modeling your data',\n * status: 'draft'\n * }, {\n * title: 'Reading data',\n * status: 'draft'\n * }]).then((posts) => {\n * console.log(posts[0]); // { id: 1234, status: 'draft', ... }\n * console.log(posts[1]); // { id: 1235, status: 'draft', ... }\n * });\n *\n * @fires Mapper#beforeCreate\n * @fires Mapper#afterCreate\n * @method Mapper#createMany\n * @param {Record[]} records Array of records to be created in one batch.\n * @param {object} [opts] Configuration options. Refer to the `createMany`\n * method of whatever adapter you're using for more configuration options.\n * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the\n * adapter to use.\n * @param {boolean} [opts.noValidate={@link Mapper#noValidate}] See {@link Mapper#noValidate}.\n * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}.\n * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}.\n * @param {string[]} [opts.with=[]] Relations to create in a cascading\n * create if `records` contains nested relations. NOT performed in a\n * transaction. Each nested create will result in another {@link Mapper#createMany}\n * call.\n * @param {string[]} [opts.pass=[]] Relations to send to the adapter as part\n * of the payload. Normally relations are not sent.\n * @returns {Promise} Resolves with the created records.\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/saving-data\",\"Saving data\"]\n */\n createMany (records = [], opts: any = {}) {\n // Default values for arguments\n const originalRecords = records\n let adapterResponse\n\n // Fill in \"opts\" with the Mapper's configuration\n utils._(opts, this)\n opts.adapter = this.getAdapterName(opts)\n\n // beforeCreateMany lifecycle hook\n opts.op = 'beforeCreateMany'\n return this._runHook(opts.op, records, opts)\n .then(records => {\n // Deep pre-create belongsTo relations\n const belongsToRelationData = {}\n opts.with = opts.with || []\n let tasks = []\n utils.forEachRelation(this, opts, (def, optsCopy) => {\n const relationData = records.map(record => def.getLocalField(record)).filter(Boolean)\n if (def.type === belongsToType && relationData.length === records.length) {\n // Create belongsTo relation first because we need a generated id to\n // attach to the child\n optsCopy.raw = false\n tasks.push(\n def\n .createLinked(relationData, optsCopy)\n .then(relatedRecords => {\n records.forEach((record, i) => def.setForeignKey(record, relatedRecords[i]))\n })\n .then(relatedRecords => {\n def.setLocalField(belongsToRelationData, relatedRecords)\n })\n )\n }\n })\n return Promise.all(tasks)\n .then(() => {\n opts.op = 'createMany'\n return this._invokeAdapterMethod(opts.op, records, opts)\n })\n .then(result => {\n adapterResponse = result\n })\n .then(() => {\n const createdRecordsData = opts.raw ? adapterResponse.data : adapterResponse\n\n // Deep post-create hasOne relations\n tasks = []\n utils.forEachRelation(this, opts, (def, optsCopy) => {\n const relationData = records.map(record => def.getLocalField(record)).filter(Boolean)\n if (relationData.length !== records.length) {\n return\n }\n\n optsCopy.raw = false\n const belongsToData = def.getLocalField(belongsToRelationData)\n let task\n // Create hasMany and hasOne after the main create because we needed\n // a generated id to attach to these items\n if (def.type === hasManyType) {\n // Not supported\n this.log('warn', 'deep createMany of hasMany type not supported!')\n } else if (def.type === hasOneType) {\n createdRecordsData.forEach((createdRecordData, i) => {\n def.setForeignKey(createdRecordData, relationData[i])\n })\n task = def\n .getRelation()\n .createMany(relationData, optsCopy)\n .then(relatedData => {\n createdRecordsData.forEach((createdRecordData, i) => {\n def.setLocalField(createdRecordData, relatedData[i])\n })\n })\n } else if (\n def.type === belongsToType &&\n belongsToData &&\n belongsToData.length === createdRecordsData.length\n ) {\n createdRecordsData.forEach((createdRecordData, i) => {\n def.setLocalField(createdRecordData, belongsToData[i])\n })\n }\n if (task) {\n tasks.push(task)\n }\n })\n return Promise.all(tasks).then(() => {\n return this._commitChanges(originalRecords, createdRecordsData)\n })\n })\n })\n .then(records => {\n if (opts.raw) {\n adapterResponse.data = records\n } else {\n adapterResponse = records\n }\n const result = this._end(adapterResponse, opts)\n opts.op = 'afterCreateMany'\n return this._runHook(opts.op, records, opts, result)\n })\n }\n\n /**\n * Create an unsaved, uncached instance of this Mapper's\n * {@link Mapper#recordClass}.\n *\n * Returns `props` if `props` is already an instance of\n * {@link Mapper#recordClass}.\n *\n * __Note:__ This method does __not__ interact with any adapter, and does\n * __not__ save any data. It only creates new objects in memory.\n *\n * @example\n * // Create empty unsaved record instance\n * const post = PostMapper.createRecord();\n *\n * @example\n * // Create an unsaved record instance with inital properties\n * const post = PostMapper.createRecord({\n * title: 'Modeling your data',\n * status: 'draft'\n * });\n *\n * @example\n * // Create a record instance that corresponds to a saved record\n * const post = PostMapper.createRecord({\n * // JSData thinks this record has been saved if it has a primary key\n * id: 1234,\n * title: 'Modeling your data',\n * status: 'draft'\n * });\n *\n * @example\n * // Create record instances from an array\n * const posts = PostMapper.createRecord([{\n * title: 'Modeling your data',\n * status: 'draft'\n * }, {\n * title: 'Reading data',\n * status: 'draft'\n * }]);\n *\n * @example\n * // Records are validated by default\n * import { Mapper } from 'js-data';\n * const PostMapper = new Mapper({\n * name: 'post',\n * schema: { properties: { title: { type: 'string' } } }\n * });\n * try {\n * const post = PostMapper.createRecord({\n * title: 1234,\n * });\n * } catch (err) {\n * console.log(err.errors); // [{ expected: 'one of (string)', actual: 'number', path: 'title' }]\n * }\n *\n * @example\n * // Skip validation\n * import { Mapper } from 'js-data';\n * const PostMapper = new Mapper({\n * name: 'post',\n * schema: { properties: { title: { type: 'string' } } }\n * });\n * const post = PostMapper.createRecord({\n * title: 1234,\n * }, { noValidate: true });\n * console.log(post.isValid()); // false\n *\n * @method Mapper#createRecord\n * @param {Object|Object[]} props The properties for the Record instance or an\n * array of property objects for the Record instances.\n * @param {object} [opts] Configuration options.\n * @param {boolean} [opts.noValidate={@link Mapper#noValidate}] See {@link Mapper#noValidate}.\n * @returns {Record|Record[]} The Record instance or Record instances.\n * @since 3.0.0\n */\n createRecord (props: any = {}, opts?): Record | Record[] | any {\n if (utils.isArray(props)) {\n return props.map(_props => this.createRecord(_props, opts))\n }\n if (!utils.isObject(props)) {\n throw utils.err(`${DOMAIN}#createRecord`, 'props')(400, 'array or object', props)\n }\n\n if (this.relationList) {\n this.relationList.forEach(def => {\n def.ensureLinkedDataHasProperType(props, opts)\n })\n }\n const RecordCtor = this.recordClass\n\n const result = !RecordCtor || props instanceof RecordCtor ? props : new RecordCtor(props, opts)\n return result\n // Record.mapper = this;\n // return new Record(props);\n }\n\n /**\n * Lifecycle invocation method. You probably won't call this method directly.\n *\n * @method Mapper#crud\n * @param {string} method Name of the lifecycle method to invoke.\n * @param {...*} args Arguments to pass to the lifecycle method.\n * @returns {Promise}\n * @since 3.0.0\n */\n crud (method, ...args) {\n const config = this.lifecycleMethods[method]\n if (!config) {\n throw utils.err(`${DOMAIN}#crud`, method)(404, 'method')\n }\n\n const upper = `${method.charAt(0).toUpperCase()}${method.substr(1)}`\n const before = `before${upper}`\n const after = `after${upper}`\n\n let op\n\n // Default values for arguments\n config.defaults.forEach((value, i) => {\n if (args[i] === undefined) {\n args[i] = utils.copy(value)\n }\n })\n\n const opts = args[args.length - 1]\n\n // Fill in \"opts\" with the Mapper's configuration\n utils._(opts, this)\n const adapter = opts.adapter = this.getAdapterName(opts)\n\n // before lifecycle hook\n op = opts.op = before\n return utils\n .resolve(this[op](...args))\n .then(_value => {\n if (args[config.beforeAssign] !== undefined) {\n // Allow for re-assignment from lifecycle hook\n args[config.beforeAssign] = _value === undefined ? args[config.beforeAssign] : _value\n }\n // Now delegate to the adapter\n op = opts.op = method\n args = config.adapterArgs ? config.adapterArgs(this, ...args) : args\n this.dbg(op, ...args)\n return utils.resolve(this.getAdapter(adapter)[op](this, ...args))\n })\n .then(result => {\n // force noValidate on find/findAll\n const noValidate = /find/.test(op) || opts.noValidate\n const _opts = Object.assign({}, opts, { noValidate })\n\n result = this._end(result, _opts, !!config.skip)\n args.push(result)\n // after lifecycle hook\n op = opts.op = after\n return utils.resolve(this[op](...args)).then(_result => {\n // Allow for re-assignment from lifecycle hook\n return _result === undefined ? result : _result\n })\n })\n }\n\n /**\n * Fired during {@link Mapper#destroy}. See\n * {@link Mapper~beforeDestroyListener} for how to listen for this event.\n *\n * @event Mapper#beforeDestroy\n * @see Mapper~beforeDestroyListener\n * @see Mapper#destroy\n */\n /**\n * Callback signature for the {@link Mapper#event:beforeDestroy} event.\n *\n * @example\n * function onBeforeDestroy (id, opts) {\n * // do something\n * }\n * store.on('beforeDestroy', onBeforeDestroy);\n *\n * @callback Mapper~beforeDestroyListener\n * @param {string|number} id The `id` argument passed to {@link Mapper#beforeDestroy}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#beforeDestroy}.\n * @see Mapper#event:beforeDestroy\n * @see Mapper#destroy\n * @since 3.0.0\n */\n /**\n * Fired during {@link Mapper#destroy}. See\n * {@link Mapper~afterDestroyListener} for how to listen for this event.\n *\n * @event Mapper#afterDestroy\n * @see Mapper~afterDestroyListener\n * @see Mapper#destroy\n */\n\n /**\n * Callback signature for the {@link Mapper#event:afterDestroy} event.\n *\n * @example\n * function onAfterDestroy (id, opts, result) {\n * // do something\n * }\n * store.on('afterDestroy', onAfterDestroy);\n *\n * @callback Mapper~afterDestroyListener\n * @param {string|number} id The `id` argument passed to {@link Mapper#afterDestroy}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#afterDestroy}.\n * @param {object} result The `result` argument passed to {@link Mapper#afterDestroy}.\n * @see Mapper#event:afterDestroy\n * @see Mapper#destroy\n * @since 3.0.0\n */\n /**\n * Using an adapter, destroy the record with the given primary key.\n *\n * {@link Mapper#beforeDestroy} will be called before destroying the record.\n * {@link Mapper#afterDestroy} will be called after destroying the record.\n *\n * @example\n * // Destroy a specific blog post\n * PostMapper.destroy(1234).then(() => {\n * // Blog post #1234 has been destroyed\n * });\n *\n * @example\n * // Get full response\n * PostMapper.destroy(1234, { raw: true }).then((result) => {\n * console.log(result.deleted); e.g. 1\n * console.log(...); // etc., more metadata can be found on the result\n * });\n *\n * @fires Mapper#beforeDestroy\n * @fires Mapper#afterDestroy\n * @method Mapper#destroy\n * @param {(string|number)} id The primary key of the record to destroy.\n * @param {object} [opts] Configuration options. Refer to the `destroy` method\n * of whatever adapter you're using for more configuration options.\n * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the\n * adapter to use.\n * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}.\n * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}.\n * @returns {Promise} Resolves when the record has been destroyed. Resolves\n * even if no record was found to be destroyed.\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/saving-data\",\"Saving data\"]\n */\n destroy (id: string | number, opts?) {\n return this.crud('destroy', id, opts)\n }\n\n /**\n * Fired during {@link Mapper#destroyAll}. See\n * {@link Mapper~beforeDestroyAllListener} for how to listen for this event.\n *\n * @event Mapper#beforeDestroyAll\n * @see Mapper~beforeDestroyAllListener\n * @see Mapper#destroyAll\n */\n /**\n * Callback signature for the {@link Mapper#event:beforeDestroyAll} event.\n *\n * @example\n * function onBeforeDestroyAll (query, opts) {\n * // do something\n * }\n * store.on('beforeDestroyAll', onBeforeDestroyAll);\n *\n * @callback Mapper~beforeDestroyAllListener\n * @param {object} query The `query` argument passed to {@link Mapper#beforeDestroyAll}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#beforeDestroyAll}.\n * @see Mapper#event:beforeDestroyAll\n * @see Mapper#destroyAll\n * @since 3.0.0\n */\n /**\n * Fired during {@link Mapper#destroyAll}. See\n * {@link Mapper~afterDestroyAllListener} for how to listen for this event.\n *\n * @event Mapper#afterDestroyAll\n * @see Mapper~afterDestroyAllListener\n * @see Mapper#destroyAll\n */\n\n /**\n * Callback signature for the {@link Mapper#event:afterDestroyAll} event.\n *\n * @example\n * function onAfterDestroyAll (query, opts, result) {\n * // do something\n * }\n * store.on('afterDestroyAll', onAfterDestroyAll);\n *\n * @callback Mapper~afterDestroyAllListener\n * @param {object} query The `query` argument passed to {@link Mapper#afterDestroyAll}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#afterDestroyAll}.\n * @param {object} result The `result` argument passed to {@link Mapper#afterDestroyAll}.\n * @see Mapper#event:afterDestroyAll\n * @see Mapper#destroyAll\n * @since 3.0.0\n */\n /**\n * Destroy the records selected by `query` via an adapter. If no `query` is\n * provided then all records will be destroyed.\n *\n * {@link Mapper#beforeDestroyAll} will be called before destroying the records.\n * {@link Mapper#afterDestroyAll} will be called after destroying the records.\n *\n * @example\n * // Destroy all blog posts\n * PostMapper.destroyAll().then(() => {\n * // All blog posts have been destroyed\n * });\n *\n * @example\n * // Destroy all \"draft\" blog posts\n * PostMapper.destroyAll({ status: 'draft' }).then(() => {\n * // All \"draft\" blog posts have been destroyed\n * });\n *\n * @example\n * // Get full response\n * const query = null;\n * const options = { raw: true };\n * PostMapper.destroyAll(query, options).then((result) => {\n * console.log(result.deleted); e.g. 14\n * console.log(...); // etc., more metadata can be found on the result\n * });\n *\n * @fires Mapper#beforeDestroyAll\n * @fires Mapper#afterDestroyAll\n * @method Mapper#destroyAll\n * @param {object} [query={}] Selection query. See {@link query}.\n * @param {object} [query.where] See {@link query.where}.\n * @param {number} [query.offset] See {@link query.offset}.\n * @param {number} [query.limit] See {@link query.limit}.\n * @param {string|Array[]} [query.orderBy] See {@link query.orderBy}.\n * @param {object} [opts] Configuration options. Refer to the `destroyAll`\n * method of whatever adapter you're using for more configuration options.\n * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the\n * adapter to use.\n * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}.\n * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}.\n * @returns {Promise} Resolves when the records have been destroyed. Resolves\n * even if no records were found to be destroyed.\n * @see query\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/saving-data\",\"Saving data\"]\n */\n destroyAll (query?, opts?) {\n return this.crud('destroyAll', query, opts)\n }\n\n /**\n * Fired during {@link Mapper#find}. See\n * {@link Mapper~beforeFindListener} for how to listen for this event.\n *\n * @event Mapper#beforeFind\n * @see Mapper~beforeFindListener\n * @see Mapper#find\n */\n /**\n * Callback signature for the {@link Mapper#event:beforeFind} event.\n *\n * @example\n * function onBeforeFind (id, opts) {\n * // do something\n * }\n * store.on('beforeFind', onBeforeFind);\n *\n * @callback Mapper~beforeFindListener\n * @param {string|number} id The `id` argument passed to {@link Mapper#beforeFind}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#beforeFind}.\n * @see Mapper#event:beforeFind\n * @see Mapper#find\n * @since 3.0.0\n */\n /**\n * Fired during {@link Mapper#find}. See\n * {@link Mapper~afterFindListener} for how to listen for this event.\n *\n * @event Mapper#afterFind\n * @see Mapper~afterFindListener\n * @see Mapper#find\n */\n\n /**\n * Callback signature for the {@link Mapper#event:afterFind} event.\n *\n * @example\n * function onAfterFind (id, opts, result) {\n * // do something\n * }\n * store.on('afterFind', onAfterFind);\n *\n * @callback Mapper~afterFindListener\n * @param {string|number} id The `id` argument passed to {@link Mapper#afterFind}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#afterFind}.\n * @param {object} result The `result` argument passed to {@link Mapper#afterFind}.\n * @see Mapper#event:afterFind\n * @see Mapper#find\n * @since 3.0.0\n */\n /**\n * Retrieve via an adapter the record with the given primary key.\n *\n * {@link Mapper#beforeFind} will be called before calling the adapter.\n * {@link Mapper#afterFind} will be called after calling the adapter.\n *\n * @example\n * PostMapper.find(1).then((post) => {\n * console.log(post); // { id: 1, ...}\n * });\n *\n * @example\n * // Get full response\n * PostMapper.find(1, { raw: true }).then((result) => {\n * console.log(result.data); // { id: 1, ...}\n * console.log(result.found); // 1\n * console.log(...); // etc., more metadata can be found on the result\n * });\n *\n * @fires Mapper#beforeFind\n * @fires Mapper#afterFind\n * @method Mapper#find\n * @param {(string|number)} id The primary key of the record to retrieve.\n * @param {object} [opts] Configuration options. Refer to the `find` method\n * of whatever adapter you're using for more configuration options.\n * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the\n * adapter to use.\n * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}.\n * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}.\n * @param {string[]} [opts.with=[]] Relations to eager load in the request.\n * @returns {Promise} Resolves with the found record. Resolves with\n * `undefined` if no record was found.\n * @see http://www.js-data.io/v3.0/docs/reading-data\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/reading-data\",\"Reading data\"]\n */\n find (id: string | number, opts?) {\n return this.crud('find', id, opts)\n }\n\n /**\n * Fired during {@link Mapper#findAll}. See\n * {@link Mapper~beforeFindAllListener} for how to listen for this event.\n *\n * @event Mapper#beforeFindAll\n * @see Mapper~beforeFindAllListener\n * @see Mapper#findAll\n */\n /**\n * Callback signature for the {@link Mapper#event:beforeFindAll} event.\n *\n * @example\n * function onBeforeFindAll (query, opts) {\n * // do something\n * }\n * store.on('beforeFindAll', onBeforeFindAll);\n *\n * @callback Mapper~beforeFindAllListener\n * @param {object} query The `query` argument passed to {@link Mapper#beforeFindAll}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#beforeFindAll}.\n * @see Mapper#event:beforeFindAll\n * @see Mapper#findAll\n * @since 3.0.0\n */\n /**\n * Fired during {@link Mapper#findAll}. See\n * {@link Mapper~afterFindAllListener} for how to listen for this event.\n *\n * @event Mapper#afterFindAll\n * @see Mapper~afterFindAllListener\n * @see Mapper#findAll\n */\n\n /**\n * Callback signature for the {@link Mapper#event:afterFindAll} event.\n *\n * @example\n * function onAfterFindAll (query, opts, result) {\n * // do something\n * }\n * store.on('afterFindAll', onAfterFindAll);\n *\n * @callback Mapper~afterFindAllListener\n * @param {object} query The `query` argument passed to {@link Mapper#afterFindAll}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#afterFindAll}.\n * @param {object} result The `result` argument passed to {@link Mapper#afterFindAll}.\n * @see Mapper#event:afterFindAll\n * @see Mapper#findAll\n * @since 3.0.0\n */\n /**\n * Using the `query` argument, select records to retrieve via an adapter.\n *\n * {@link Mapper#beforeFindAll} will be called before calling the adapter.\n * {@link Mapper#afterFindAll} will be called after calling the adapter.\n *\n * @example\n * // Find all \"published\" blog posts\n * PostMapper.findAll({ status: 'published' }).then((posts) => {\n * console.log(posts); // [{ id: 1, status: 'published', ...}, ...]\n * });\n *\n * @example\n * // Get full response\n * PostMapper.findAll({ status: 'published' }, { raw: true }).then((result) => {\n * console.log(result.data); // [{ id: 1, status: 'published', ...}, ...]\n * console.log(result.found); // e.g. 13\n * console.log(...); // etc., more metadata can be found on the result\n * });\n *\n * @fires Mapper#beforeFindAll\n * @fires Mapper#afterFindAll\n * @method Mapper#findAll\n * @param {object} [query={}] Selection query. See {@link query}.\n * @param {object} [query.where] See {@link query.where}.\n * @param {number} [query.offset] See {@link query.offset}.\n * @param {number} [query.limit] See {@link query.limit}.\n * @param {string|Array[]} [query.orderBy] See {@link query.orderBy}.\n * @param {object} [opts] Configuration options. Refer to the `findAll` method\n * of whatever adapter you're using for more configuration options.\n * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the\n * adapter to use.\n * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}.\n * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}.\n * @param {string[]} [opts.with=[]] Relations to eager load in the request.\n * @returns {Promise} Resolves with the found records, if any.\n * @see query\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/reading-data\",\"Reading data\"]\n */\n findAll (query, opts?) {\n return this.crud('findAll', query, opts)\n }\n\n /**\n * Return the registered adapter with the given name or the default adapter if\n * no name is provided.\n *\n * @method Mapper#getAdapter\n * @param {string} [name] The name of the adapter to retrieve.\n * @returns {Adapter} The adapter.\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/connecting-to-a-data-source\",\"Connecting to a data source\"]\n */\n getAdapter (name?: string) {\n this.dbg('getAdapter', 'name:', name)\n const adapter = this.getAdapterName(name)\n if (!adapter) {\n throw utils.err(`${DOMAIN}#getAdapter`, 'name')(400, 'string', name)\n }\n return this.getAdapters()[adapter]\n }\n\n /**\n * Return the name of a registered adapter based on the given name or options,\n * or the name of the default adapter if no name provided.\n *\n * @method Mapper#getAdapterName\n * @param {(Object|string)} [opts] The name of an adapter or options, if any.\n * @returns {string} The name of the adapter.\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/connecting-to-a-data-source\",\"Connecting to a data source\"]\n */\n getAdapterName (opts: any = {}) {\n if (utils.isString(opts)) {\n opts = { adapter: opts }\n }\n return opts.adapter || opts.defaultAdapter\n }\n\n /**\n * Get the object of registered adapters for this Mapper.\n *\n * @method Mapper#getAdapters\n * @returns {Object} {@link Mapper#_adapters}\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/connecting-to-a-data-source\",\"Connecting to a data source\"]\n */\n getAdapters () {\n return this._adapters\n }\n\n /**\n * Returns this Mapper's {@link Schema}.\n *\n * @method Mapper#getSchema\n * @returns {Schema} This Mapper's {@link Schema}.\n * @see Mapper#schema\n * @since 3.0.0\n */\n getSchema () {\n return this.schema\n }\n\n /**\n * Defines a hasMany relationship. Only useful if you're managing your\n * Mappers manually and not using a Container or DataStore component.\n *\n * @example\n * UserMapper.hasMany(PostMapper, {\n * // post.user_id points to user.id\n * foreignKey: 'user_id'\n * // post records will be attached to user records at \"user.posts\"\n * localField: 'posts'\n * });\n *\n * @method Mapper#hasMany\n * @see http://www.js-data.io/v3.0/docs/relations\n * @since 3.0.0\n */\n hasMany (relatedMapper, opts) {\n return hasMany(relatedMapper, opts)(this)\n }\n\n /**\n * Defines a hasOne relationship. Only useful if you're managing your Mappers\n * manually and not using a {@link Container} or {@link DataStore} component.\n *\n * @example\n * UserMapper.hasOne(ProfileMapper, {\n * // profile.user_id points to user.id\n * foreignKey: 'user_id'\n * // profile records will be attached to user records at \"user.profile\"\n * localField: 'profile'\n * });\n *\n * @method Mapper#hasOne\n * @see http://www.js-data.io/v3.0/docs/relations\n * @since 3.0.0\n */\n hasOne (relatedMapper, opts) {\n return hasOne(relatedMapper, opts)(this)\n }\n\n /**\n * Return whether `record` is an instance of this Mapper's recordClass.\n *\n * @example\n * const post = PostMapper.createRecord();\n *\n * console.log(PostMapper.is(post)); // true\n * // Equivalent to what's above\n * console.log(post instanceof PostMapper.recordClass); // true\n *\n * @method Mapper#is\n * @param {Object|Record} record The record to check.\n * @returns {boolean} Whether `record` is an instance of this Mapper's\n * {@link Mapper#recordClass}.\n * @since 3.0.0\n */\n is (record) {\n const recordClass = this.recordClass\n return recordClass ? record instanceof recordClass : false\n }\n\n /**\n * Register an adapter on this Mapper under the given name.\n *\n * @method Mapper#registerAdapter\n * @param {string} name The name of the adapter to register.\n * @param {Adapter} adapter The adapter to register.\n * @param {object} [opts] Configuration options.\n * @param {boolean} [opts.default=false] Whether to make the adapter the\n * default adapter for this Mapper.\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/connecting-to-a-data-source\",\"Connecting to a data source\"]\n */\n registerAdapter (name, adapter, opts: any = {}) {\n this.getAdapters()[name] = adapter\n // Optionally make it the default adapter for the target.\n if (opts === true || opts.default) {\n this.defaultAdapter = name\n }\n }\n\n _runHook (hookName, ...hookArgs) {\n const defaultValueIndex = hookName.indexOf('after') === 0 ? hookArgs.length - 1 : 0\n\n return utils\n .resolve(this[hookName](...hookArgs))\n .then(overridenResult => (overridenResult === undefined ? hookArgs[defaultValueIndex] : overridenResult))\n }\n\n _invokeAdapterMethod (method, propsOrRecords, opts) {\n const conversionOptions = { with: opts.pass || [] }\n let object\n\n this.dbg(opts.op, propsOrRecords, opts)\n\n if (utils.isArray(propsOrRecords)) {\n object = propsOrRecords.map(record => this.toJSON(record, conversionOptions))\n } else {\n object = this.toJSON(propsOrRecords, conversionOptions)\n }\n\n return this.getAdapter(opts.adapter)[method](this, object, opts)\n }\n\n /**\n * Select records according to the `query` argument, and aggregate the sum\n * value of the property specified by `field`.\n *\n * {@link Mapper#beforeSum} will be called before calling the adapter.\n * {@link Mapper#afterSum} will be called after calling the adapter.\n *\n * @example\n * PurchaseOrderMapper.sum('amount', { status: 'paid' }).then((amountPaid) => {\n * console.log(amountPaid); // e.g. 451125.34\n * });\n *\n * @method Mapper#sum\n * @param {string} field The field to sum.\n * @param {object} [query={}] Selection query. See {@link query}.\n * @param {object} [query.where] See {@link query.where}.\n * @param {number} [query.offset] See {@link query.offset}.\n * @param {number} [query.limit] See {@link query.limit}.\n * @param {string|Array[]} [query.orderBy] See {@link query.orderBy}.\n * @param {object} [opts] Configuration options. Refer to the `sum` method\n * of whatever adapter you're using for more configuration options.\n * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the\n * adapter to use.\n * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}.\n * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}.\n * @returns {Promise} Resolves with the aggregated sum.\n * @since 3.0.0\n */\n sum (field, query: QueryDefinition, opts?) {\n return this.crud('sum', field, query, opts)\n }\n\n /**\n * Return a plain object representation of the given record. Relations can\n * be optionally be included. Non-schema properties can be excluded.\n *\n * @example\n * import { Mapper, Schema } from 'js-data';\n * const PersonMapper = new Mapper({\n * name: 'person',\n * schema: {\n * properties: {\n * name: { type: 'string' },\n * id: { type: 'string' }\n * }\n * }\n * });\n * const person = PersonMapper.createRecord({ id: 1, name: 'John', foo: 'bar' });\n * // \"foo\" is stripped by toJSON()\n * console.log(PersonMapper.toJSON(person)); // {\"id\":1,\"name\":\"John\"}\n *\n * const PersonRelaxedMapper = new Mapper({\n * name: 'personRelaxed',\n * schema: {\n * properties: {\n * name: { type: 'string' },\n * id: { type: 'string' }\n * },\n * additionalProperties: true\n * }\n * });\n * const person2 = PersonRelaxedMapper.createRecord({ id: 1, name: 'John', foo: 'bar' });\n * // \"foo\" is not stripped by toJSON\n * console.log(PersonRelaxedMapper.toJSON(person2)); // {\"id\":1,\"name\":\"John\",\"foo\":\"bar\"}\n *\n * @method Mapper#toJSON\n * @param {Record|Record[]} records Record or records from which to create a\n * POJO representation.\n * @param {object} [opts] Configuration options.\n * @param {string[]} [opts.with] Array of relation names or relation fields\n * to include in the POJO representation.\n * @param {boolean} [opts.withAll] Whether to simply include all relations in\n * the representation. Overrides `opts.with`.\n * @returns {Object|Object[]} POJO representation of the record or records.\n * @since 3.0.0\n */\n toJSON (records, opts: any = {}) {\n let record\n if (utils.isArray(records)) {\n return records.map(record => this.toJSON(record, opts))\n } else {\n record = records\n }\n const relationFields = (this ? this.relationFields : []) || []\n let json = {}\n\n // Copy properties defined in the schema\n if (this && this.schema) {\n json = this.schema.pick(record)\n } else {\n for (const key in record) {\n if (relationFields.indexOf(key) === -1) {\n json[key] = utils.plainCopy(record[key])\n }\n }\n }\n\n // The user wants to include relations in the resulting plain object representation\n if (this && opts.withAll) {\n opts.with = relationFields.slice()\n }\n if (this && opts.with) {\n if (utils.isString(opts.with)) {\n opts.with = [opts.with]\n }\n utils.forEachRelation(this, opts, (def, optsCopy) => {\n const relationData = def.getLocalField(record)\n if (relationData) {\n // The actual recursion\n if (utils.isArray(relationData)) {\n def.setLocalField(\n json,\n relationData.map(item => {\n return def.getRelation().toJSON(item, optsCopy)\n })\n )\n } else {\n def.setLocalField(json, def.getRelation().toJSON(relationData, optsCopy))\n }\n }\n })\n }\n return json\n }\n\n /**\n * Fired during {@link Mapper#update}. See\n * {@link Mapper~beforeUpdateListener} for how to listen for this event.\n *\n * @event Mapper#beforeUpdate\n * @see Mapper~beforeUpdateListener\n * @see Mapper#update\n */\n /**\n * Callback signature for the {@link Mapper#event:beforeUpdate} event.\n *\n * @example\n * function onBeforeUpdate (id, props, opts) {\n * // do something\n * }\n * store.on('beforeUpdate', onBeforeUpdate);\n *\n * @callback Mapper~beforeUpdateListener\n * @param {string|number} id The `id` argument passed to {@link Mapper#beforeUpdate}.\n * @param {object} props The `props` argument passed to {@link Mapper#beforeUpdate}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#beforeUpdate}.\n * @see Mapper#event:beforeUpdate\n * @see Mapper#update\n * @since 3.0.0\n */\n /**\n * Fired during {@link Mapper#update}. See\n * {@link Mapper~afterUpdateListener} for how to listen for this event.\n *\n * @event Mapper#afterUpdate\n * @see Mapper~afterUpdateListener\n * @see Mapper#update\n */\n\n /**\n * Callback signature for the {@link Mapper#event:afterUpdate} event.\n *\n * @example\n * function onAfterUpdate (id, props, opts, result) {\n * // do something\n * }\n * store.on('afterUpdate', onAfterUpdate);\n *\n * @callback Mapper~afterUpdateListener\n * @param {string|number} id The `id` argument passed to {@link Mapper#afterUpdate}.\n * @param {object} props The `props` argument passed to {@link Mapper#afterUpdate}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#afterUpdate}.\n * @param {object} result The `result` argument passed to {@link Mapper#afterUpdate}.\n * @see Mapper#event:afterUpdate\n * @see Mapper#update\n * @since 3.0.0\n */\n /**\n * Using an adapter, update the record with the primary key specified by the\n * `id` argument.\n *\n * {@link Mapper#beforeUpdate} will be called before updating the record.\n * {@link Mapper#afterUpdate} will be called after updating the record.\n *\n * @example\n * // Update a specific post\n * PostMapper.update(1234, {\n * status: 'published',\n * published_at: new Date()\n * }).then((post) => {\n * console.log(post); // { id: 1234, status: 'published', ... }\n * });\n *\n * @fires Mapper#beforeUpdate\n * @fires Mapper#afterUpdate\n * @method Mapper#update\n * @param {(string|number)} id The primary key of the record to update.\n * @param {object} props The update to apply to the record.\n * @param {object} [opts] Configuration options. Refer to the `update` method\n * of whatever adapter you're using for more configuration options.\n * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the\n * adapter to use.\n * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}.\n * @param {boolean} [opts.noValidate={@link Mapper#noValidate}] See {@link Mapper#noValidate}.\n * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}.\n * transaction.\n * @returns {Promise} Resolves with the updated record. Rejects if the record\n * could not be found.\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/saving-data\",\"Saving data\"]\n */\n update (id, props, opts?) {\n return this.crud('update', id, props, opts)\n }\n\n /**\n * Fired during {@link Mapper#updateAll}. See\n * {@link Mapper~beforeUpdateAllListener} for how to listen for this event.\n *\n * @event Mapper#beforeUpdateAll\n * @see Mapper~beforeUpdateAllListener\n * @see Mapper#updateAll\n */\n /**\n * Callback signature for the {@link Mapper#event:beforeUpdateAll} event.\n *\n * @example\n * function onBeforeUpdateAll (props, query, opts) {\n * // do something\n * }\n * store.on('beforeUpdateAll', onBeforeUpdateAll);\n *\n * @callback Mapper~beforeUpdateAllListener\n * @param {object} props The `props` argument received by {@link Mapper#beforeUpdateAll}.\n * @param {object} query The `query` argument received by {@link Mapper#beforeUpdateAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdateAll}.\n * @see Mapper#event:beforeUpdateAll\n * @see Mapper#updateAll\n * @since 3.0.0\n */\n /**\n * Fired during {@link Mapper#updateAll}. See\n * {@link Mapper~afterUpdateAllListener} for how to listen for this event.\n *\n * @event Mapper#afterUpdateAll\n * @see Mapper~afterUpdateAllListener\n * @see Mapper#updateAll\n */\n\n /**\n * Callback signature for the {@link Mapper#event:afterUpdateAll} event.\n *\n * @example\n * function onAfterUpdateAll (props, query, opts, result) {\n * // do something\n * }\n * store.on('afterUpdateAll', onAfterUpdateAll);\n *\n * @callback Mapper~afterUpdateAllListener\n * @param {object} props The `props` argument received by {@link Mapper#afterUpdateAll}.\n * @param {object} query The `query` argument received by {@link Mapper#afterUpdateAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdateAll}.\n * @param {object} result The `result` argument received by {@link Mapper#afterUpdateAll}.\n * @see Mapper#event:afterUpdateAll\n * @see Mapper#updateAll\n * @since 3.0.0\n */\n /**\n * Using the `query` argument, perform the a single updated to the selected\n * records.\n *\n * {@link Mapper#beforeUpdateAll} will be called before making the update.\n * {@link Mapper#afterUpdateAll} will be called after making the update.\n *\n * @example\n * // Turn all of John's blog posts into drafts.\n * const update = { status: draft: published_at: null };\n * const query = { userId: 1234 };\n * PostMapper.updateAll(update, query).then((posts) => {\n * console.log(posts); // [...]\n * });\n *\n * @fires Mapper#beforeUpdateAll\n * @fires Mapper#afterUpdateAll\n * @method Mapper#updateAll\n * @param {object} props Update to apply to selected records.\n * @param {object} [query={}] Selection query. See {@link query}.\n * @param {object} [query.where] See {@link query.where}.\n * @param {number} [query.offset] See {@link query.offset}.\n * @param {number} [query.limit] See {@link query.limit}.\n * @param {string|Array[]} [query.orderBy] See {@link query.orderBy}.\n * @param {object} [opts] Configuration options. Refer to the `updateAll`\n * method of whatever adapter you're using for more configuration options.\n * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the\n * adapter to use.\n * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}.\n * @param {boolean} [opts.noValidate={@link Mapper#noValidate}] See {@link Mapper#noValidate}.\n * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}.\n * @returns {Promise} Resolves with the update records, if any.\n * @see query\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/saving-data\",\"Saving data\"]\n */\n updateAll (props, query?: QueryDefinition, opts?) {\n return this.crud('updateAll', props, query, opts)\n }\n\n /**\n * Fired during {@link Mapper#updateMany}. See\n * {@link Mapper~beforeUpdateManyListener} for how to listen for this event.\n *\n * @event Mapper#beforeUpdateMany\n * @see Mapper~beforeUpdateManyListener\n * @see Mapper#updateMany\n */\n /**\n * Callback signature for the {@link Mapper#event:beforeUpdateMany} event.\n *\n * @example\n * function onBeforeUpdateMany (records, opts) {\n * // do something\n * }\n * store.on('beforeUpdateMany', onBeforeUpdateMany);\n *\n * @callback Mapper~beforeUpdateManyListener\n * @param {object} records The `records` argument received by {@link Mapper#beforeUpdateMany}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdateMany}.\n * @see Mapper#event:beforeUpdateMany\n * @see Mapper#updateMany\n * @since 3.0.0\n */\n /**\n * Fired during {@link Mapper#updateMany}. See\n * {@link Mapper~afterUpdateManyListener} for how to listen for this event.\n *\n * @event Mapper#afterUpdateMany\n * @see Mapper~afterUpdateManyListener\n * @see Mapper#updateMany\n */\n\n /**\n * Callback signature for the {@link Mapper#event:afterUpdateMany} event.\n *\n * @example\n * function onAfterUpdateMany (records, opts, result) {\n * // do something\n * }\n * store.on('afterUpdateMany', onAfterUpdateMany);\n *\n * @callback Mapper~afterUpdateManyListener\n * @param {object} records The `records` argument received by {@link Mapper#afterUpdateMany}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdateMany}.\n * @param {object} result The `result` argument received by {@link Mapper#afterUpdateMany}.\n * @see Mapper#event:afterUpdateMany\n * @see Mapper#updateMany\n * @since 3.0.0\n */\n /**\n * Given an array of updates, perform each of the updates via an adapter. Each\n * \"update\" is a hash of properties with which to update an record. Each\n * update must contain the primary key of the record to be updated.\n *\n * {@link Mapper#beforeUpdateMany} will be called before making the update.\n * {@link Mapper#afterUpdateMany} will be called after making the update.\n *\n * @example\n * PostMapper.updateMany([\n * { id: 1234, status: 'draft' },\n * { id: 2468, status: 'published', published_at: new Date() }\n * ]).then((posts) => {\n * console.log(posts); // [...]\n * });\n *\n * @fires Mapper#beforeUpdateMany\n * @fires Mapper#afterUpdateMany\n * @method Mapper#updateMany\n * @param {Record[]} records Array up record updates.\n * @param {object} [opts] Configuration options. Refer to the `updateMany`\n * method of whatever adapter you're using for more configuration options.\n * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the\n * adapter to use.\n * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}.\n * @param {boolean} [opts.noValidate={@link Mapper#noValidate}] See {@link Mapper#noValidate}.\n * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}.\n * @returns {Promise} Resolves with the updated records. Rejects if any of the\n * records could be found.\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/saving-data\",\"Saving data\"]\n */\n updateMany (records, opts?) {\n return this.crud('updateMany', records, opts)\n }\n\n /**\n * Validate the given record or records according to this Mapper's\n * {@link Schema}. If there are no validation errors then the return value\n * will be `undefined`.\n *\n * @example\n * import {Mapper, Schema} from 'js-data'\n * const PersonSchema = new Schema({\n * properties: {\n * name: { type: 'string' },\n * id: { type: 'string' }\n * }\n * });\n * const PersonMapper = new Mapper({\n * name: 'person',\n * schema: PersonSchema\n * });\n * let errors = PersonMapper.validate({ name: 'John' });\n * console.log(errors); // undefined\n * errors = PersonMapper.validate({ name: 123 });\n * console.log(errors); // [{ expected: 'one of (string)', actual: 'number', path: 'name' }]\n *\n * @method Mapper#validate\n * @param {Object|Object[]} record The record or records to validate.\n * @param {object} [opts] Configuration options. Passed to\n * {@link Schema#validate}.\n * @returns {Object[]} Array of errors or `undefined` if no errors.\n * @since 3.0.0\n */\n validate (record, opts: any = {}) {\n const schema = this.getSchema()\n if (!schema) {\n return\n }\n const _opts = utils.pick(opts, ['existingOnly'])\n if (utils.isArray(record)) {\n const errors = record.map(_record => schema.validate(_record, utils.pick(_opts, ['existingOnly'])))\n\n return errors.some(Boolean) ? errors : undefined\n }\n return schema.validate(record, _opts)\n }\n\n /**\n * Method used to wrap data returned by an adapter with this Mapper's\n * {@link Mapper#recordClass}. This method is used by all of a Mapper's CRUD\n * methods. The provided implementation of this method assumes that the `data`\n * passed to it is a record or records that need to be wrapped with\n * {@link Mapper#createRecord}. Override with care.\n *\n * Provided implementation of {@link Mapper#wrap}:\n *\n * ```\n * function (data, opts) {\n * return this.createRecord(data, opts);\n * }\n * ```\n *\n * @example\n * const PostMapper = new Mapper({\n * name: 'post',\n * // Override to customize behavior\n * wrap (data, opts) {\n * const originalWrap = this.constructor.prototype.wrap;\n * // Let's say \"GET /post\" doesn't return JSON quite like JSData expects,\n * // but the actual post records are nested under a \"posts\" field. So,\n * // we override Mapper#wrap to handle this special case.\n * if (opts.op === 'findAll') {\n * return originalWrap.call(this, data.posts, opts);\n * }\n * // Otherwise perform original behavior\n * return originalWrap.call(this, data, opts);\n * }\n * });\n *\n * @method Mapper#wrap\n * @param {Object|Object[]} data The record or records to be wrapped.\n * @param {object} [opts] Configuration options. Passed to {@link Mapper#createRecord}.\n * @returns {Record|Record[]} The wrapped record or records.\n * @since 3.0.0\n */\n wrap (data, opts) {\n return this.createRecord(data, opts)\n }\n\n /**\n * @ignore\n */\n defineRelations () {\n // Setup the mapper's relations, including generating Mapper#relationList\n // and Mapper#relationFields\n utils.forOwn(this.relations, (group, type) => {\n utils.forOwn(group, (relations, _name) => {\n if (utils.isObject(relations)) {\n relations = [relations]\n }\n relations.forEach(def => {\n const relatedMapper = this.datastore.getMapperByName(_name) || _name\n def.getRelation = () => this.datastore.getMapper(_name)\n\n if (typeof Relation[type] !== 'function') {\n throw utils.err(DOMAIN, 'defineRelations')(400, 'relation type (hasOne, hasMany, etc)', type, true)\n }\n\n this[type](relatedMapper, def)\n })\n })\n })\n }\n}\n\n/**\n * Create a subclass of this Mapper:\n *\n * @example Mapper.extend\n * const JSData = require('js-data');\n * const { Mapper } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * // Extend the class using ES2015 class syntax.\n * class CustomMapperClass extends Mapper {\n * foo () { return 'bar'; }\n * static beep () { return 'boop'; }\n * };\n * const customMapper = new CustomMapperClass();\n * console.log(customMapper.foo());\n * console.log(CustomMapperClass.beep());\n *\n * // Extend the class using alternate method.\n * const OtherMapperClass = Mapper.extend({\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * });\n * const otherMapper = new OtherMapperClass();\n * console.log(otherMapper.foo());\n * console.log(OtherMapperClass.beep());\n *\n * // Extend the class, providing a custom constructor.\n * function AnotherMapperClass () {\n * Mapper.call(this);\n * this.created_at = new Date().getTime();\n * }\n * Mapper.extend({\n * constructor: AnotherMapperClass,\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * })\n * const anotherMapper = new AnotherMapperClass();\n * console.log(anotherMapper.created_at);\n * console.log(anotherMapper.foo());\n * console.log(AnotherMapperClass.beep());\n *\n * @method Mapper.extend\n * @param {object} [props={}] Properties to add to the prototype of the\n * subclass.\n * @param {object} [props.constructor] Provide a custom constructor function\n * to be used as the subclass itself.\n * @param {object} [classProps={}] Static properties to add to the subclass.\n * @returns {Constructor} Subclass of this Mapper class.\n * @since 3.0.0\n */\n","import utils from './utils'\nimport Component from './Component'\nimport Mapper, { MapperOpts } from './Mapper'\nimport Record from './Record'\n\nconst DOMAIN = 'Container'\n\nexport const proxiedMapperMethods = [\n 'count',\n 'create',\n 'createMany',\n 'createRecord',\n 'destroy',\n 'destroyAll',\n 'find',\n 'findAll',\n 'getSchema',\n 'is',\n 'sum',\n 'toJSON',\n 'update',\n 'updateAll',\n 'updateMany',\n 'validate'\n]\n\n/**\n * The `Container` class is a place to define and store {@link Mapper} instances.\n *\n * `Container` makes it easy to manage your Mappers. Without a container, you\n * need to manage Mappers yourself, including resolving circular dependencies\n * among relations. All Mappers in a container share the same adapters, so you\n * don't have to register adapters for every single Mapper.\n *\n * @example Container#constructor\n * // import { Container } from 'js-data';\n * const JSData = require('js-data');\n * const {Container} = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new Container();\n *\n * @class Container\n * @extends Component\n * @param {object} [opts] Configuration options.\n * @param {boolean} [opts.debug=false] See {@link Component#debug}.\n * @param {Constructor} [opts.mapperClass] See {@link Container#mapperClass}.\n * @param {object} [opts.mapperDefaults] See {@link Container#mapperDefaults}.\n * @since 3.0.0\n */\nexport class Container extends Component {\n mapperDefaults: any;\n mapperClass: typeof Mapper;\n _adapters: any;\n _mappers: { [name: string]: Mapper };\n\n constructor (opts = {}) {\n super()\n\n Object.defineProperties(this, {\n /**\n * The adapters registered with this Container, which are also shared by all\n * Mappers in this Container.\n *\n * @name Container#_adapters\n * @see Container#registerAdapter\n * @since 3.0.0\n * @type {Object}\n */\n _adapters: {\n value: {}\n },\n\n /**\n * The the mappers in this container\n *\n * @name Container#_mappers\n * @see Mapper\n * @since 3.0.0\n * @type {Object}\n */\n _mappers: {\n value: {}\n },\n\n /**\n * Constructor function to use in {@link Container#defineMapper} to create new\n * {@link Mapper} instances. {@link Container#mapperClass} should extend\n * {@link Mapper}. By default {@link Mapper} is used to instantiate Mappers.\n *\n * @example Container#mapperClass\n * // import { Container, Mapper } from 'js-data';\n * const JSData = require('js-data');\n * const { Container, Mapper } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * class MyMapperClass extends Mapper {\n * foo () { return 'bar' }\n * }\n * const store = new Container({\n * mapperClass: MyMapperClass\n * });\n * store.defineMapper('user');\n * console.log(store.getMapper('user').foo());\n *\n * @name Container#mapperClass\n * @see Mapper\n * @since 3.0.0\n * @type {Constructor}\n */\n mapperClass: {\n value: undefined,\n writable: true\n }\n })\n\n // Apply options provided by the user\n utils.fillIn(this, opts)\n\n /**\n * Defaults options to pass to {@link Container#mapperClass} when creating a\n * new {@link Mapper}.\n *\n * @example Container#mapperDefaults\n * // import { Container } from 'js-data';\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new Container({\n * mapperDefaults: {\n * idAttribute: '_id'\n * }\n * });\n * store.defineMapper('user');\n * console.log(store.getMapper('user').idAttribute);\n *\n * @default {}\n * @name Container#mapperDefaults\n * @since 3.0.0\n * @type {Object}\n */\n this.mapperDefaults = this.mapperDefaults || {}\n\n // Use the Mapper class if the user didn't provide a mapperClass\n this.mapperClass = this.mapperClass || Mapper\n }\n\n /**\n * Register a new event listener on this Container.\n *\n * Proxy for {@link Component#on}. If an event was emitted by a {@link Mapper}\n * in the Container, then the name of the {@link Mapper} will be prepended to\n * the arugments passed to the listener.\n *\n * @example Container#on\n * // import { Container } from 'js-data';\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new Container();\n * store.on('foo', function (...args) { console.log(args.join(':')) });\n * store.defineMapper('user');\n * store.emit('foo', 'arg1', 'arg2');\n * store.getMapper('user').emit('foo', 'arg1', 'arg2');\n *\n * @method Container#on\n * @param {string} event Name of event to subsribe to.\n * @param {Function} listener Listener function to handle the event.\n * @param {*} [ctx] Optional content in which to invoke the listener.\n * @since 3.0.0\n */\n\n /**\n * Used to bind to events emitted by mappers in this container.\n *\n * @method Container#_onMapperEvent\n * @param {string} name Name of the mapper that emitted the event.\n * @param {...*} [args] Args See {@link Mapper#emit}.\n * @private\n * @since 3.0.0\n */\n _onMapperEvent (name, ...args) {\n const type = args.shift()\n this.emit(type, name, ...args)\n }\n\n /**\n * Return a container scoped to a particular mapper.\n *\n * @example Container#as\n * // import { Container } from 'js-data';\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new Container();\n * const UserMapper = store.defineMapper('user');\n * const UserStore = store.as('user');\n *\n * const user1 = store.createRecord('user', { name: 'John' });\n * const user2 = UserStore.createRecord({ name: 'John' });\n * const user3 = UserMapper.createRecord({ name: 'John' });\n * console.log(user1 === user2);\n * console.log(user2 === user3);\n * console.log(user1 === user3);\n *\n * @method Container#as\n * @param {string} name Name of the {@link Mapper}.\n * @returns {Object} A container scoped to a particular mapper.\n * @since 3.0.0\n */\n as (name) {\n const props: any = {}\n const original = this\n proxiedMapperMethods.forEach(method => {\n props[method] = {\n writable: true,\n value (...args) {\n return original[method](name, ...args)\n }\n }\n })\n props.getMapper = {\n writable: true,\n value () {\n return original.getMapper(name)\n }\n }\n return Object.create(this, props)\n }\n\n /**\n * Create a new mapper and register it in this container.\n *\n * @example Container#defineMapper\n * // import { Container } from 'js-data';\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new Container({\n * mapperDefaults: { foo: 'bar' }\n * });\n * // Container#defineMapper returns a direct reference to the newly created\n * // Mapper.\n * const UserMapper = store.defineMapper('user');\n * console.log(UserMapper === store.getMapper('user'));\n * console.log(UserMapper === store.as('user').getMapper());\n * console.log(UserMapper.foo);\n *\n * @method Container#defineMapper\n * @param {string} name Name under which to register the new {@link Mapper}.\n * {@link Mapper#name} will be set to this value.\n * @param {object} [opts] Configuration options. Passed to\n * {@link Container#mapperClass} when creating the new {@link Mapper}.\n * @returns {Mapper} The newly created instance of {@link Mapper}.\n * @see Container#as\n * @since 3.0.0\n */\n defineMapper (name?: string | MapperOpts | any, opts?: MapperOpts) {\n // For backwards compatibility with defineResource\n if (utils.isObject(name)) {\n opts = name\n name = opts.name\n }\n if (!utils.isString(name)) {\n throw utils.err(`${DOMAIN}#defineMapper`, 'name')(400, 'string', name)\n }\n\n // Default values for arguments\n opts = opts || {}\n // Set Mapper#name\n opts.name = name\n opts.relations = opts.relations || {}\n\n // Check if the user is overriding the datastore's default mapperClass\n const mapperClass = opts.mapperClass || this.mapperClass\n delete opts.mapperClass\n\n // Apply the datastore's defaults to the options going into the mapper\n utils.fillIn(opts, this.mapperDefaults)\n\n // Instantiate a mapper\n const mapper = (this._mappers[name] = new mapperClass(opts)); // eslint-disable-line\n mapper.relations = mapper.relations || {}\n // Make sure the mapper's name is set\n mapper.name = name\n // All mappers in this datastore will share adapters\n mapper._adapters = this.getAdapters()\n\n mapper.datastore = this\n\n mapper.on('all', (...args) => this._onMapperEvent(name, ...args))\n mapper.defineRelations()\n\n return mapper\n }\n\n defineResource (name, opts) {\n console.warn('DEPRECATED: defineResource is deprecated, use defineMapper instead')\n return this.defineMapper(name, opts)\n }\n\n /**\n * Return the registered adapter with the given name or the default adapter if\n * no name is provided.\n *\n * @method Container#getAdapter\n * @param {string} [name] The name of the adapter to retrieve.\n * @returns {Adapter} The adapter.\n * @since 3.0.0\n */\n getAdapter (name?) {\n const adapter = this.getAdapterName(name)\n if (!adapter) {\n throw utils.err(`${DOMAIN}#getAdapter`, 'name')(400, 'string', name)\n }\n return this.getAdapters()[adapter]\n }\n\n /**\n * Return the name of a registered adapter based on the given name or options,\n * or the name of the default adapter if no name provided.\n *\n * @method Container#getAdapterName\n * @param {(Object|string)} [opts] The name of an adapter or options, if any.\n * @returns {string} The name of the adapter.\n * @since 3.0.0\n */\n getAdapterName (opts: any = {}) {\n if (utils.isString(opts)) {\n opts = { adapter: opts }\n }\n return opts.adapter || this.mapperDefaults.defaultAdapter\n }\n\n /**\n * Return the registered adapters of this container.\n *\n * @method Container#getAdapters\n * @returns {Adapter}\n * @since 3.0.0\n */\n getAdapters () {\n return this._adapters\n }\n\n /**\n * Return the mapper registered under the specified name.\n *\n * @example Container#getMapper\n * // import { Container } from 'js-data';\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new Container();\n * // Container#defineMapper returns a direct reference to the newly created\n * // Mapper.\n * const UserMapper = store.defineMapper('user');\n * console.log(UserMapper === store.getMapper('user'));\n * console.log(UserMapper === store.as('user').getMapper());\n * store.getMapper('profile'); // throws Error, there is no mapper with name \"profile\"\n *\n * @method Container#getMapper\n * @param {string} name {@link Mapper#name}.\n * @returns {Mapper}\n * @since 3.0.0\n */\n getMapper (name: string): Mapper {\n const mapper = this.getMapperByName(name)\n if (!mapper) {\n throw utils.err(`${DOMAIN}#getMapper`, name)(404, 'mapper')\n }\n return mapper\n }\n\n /**\n * Return the mapper registered under the specified name.\n * Doesn't throw error if mapper doesn't exist.\n *\n * @example Container#getMapperByName\n * // import { Container } from 'js-data';\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new Container();\n * // Container#defineMapper returns a direct reference to the newly created\n * // Mapper.\n * const UserMapper = store.defineMapper('user');\n * console.log(UserMapper === store.getMapper('user'));\n * console.log(UserMapper === store.as('user').getMapper());\n * console.log(store.getMapper('profile')); // Does NOT throw an error\n *\n * @method Container#getMapperByName\n * @param {string} name {@link Mapper#name}.\n * @returns {Mapper}\n * @since 3.0.0\n */\n getMapperByName (name) {\n return this._mappers[name]\n }\n\n /**\n * Register an adapter on this container under the given name. Adapters\n * registered on a container are shared by all mappers in the container.\n *\n * @example\n * import { Container } from 'js-data';\n * import { RethinkDBAdapter } from 'js-data-rethinkdb';\n * const store = new Container();\n * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true });\n *\n * @method Container#registerAdapter\n * @param {string} name The name of the adapter to register.\n * @param {Adapter} adapter The adapter to register.\n * @param {object} [opts] Configuration options.\n * @param {boolean} [opts.default=false] Whether to make the adapter the\n * default adapter for all Mappers in this container.\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/connecting-to-a-data-source\",\"Connecting to a data source\"]\n */\n registerAdapter (name, adapter, opts: any = {}) {\n this.getAdapters()[name] = adapter\n // Optionally make it the default adapter for the target.\n if (opts === true || opts.default) {\n this.mapperDefaults.defaultAdapter = name\n utils.forOwn(this._mappers, mapper => {\n mapper.defaultAdapter = name\n })\n }\n }\n\n /**\n * Wrapper for {@link Mapper#count}.\n *\n * @example\n * // Get the number of published blog posts\n * import { Container } from 'js-data';\n * import RethinkDBAdapter from 'js-data-rethinkdb';\n * const store = new Container();\n * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('post');\n *\n * store.count('post', { status: 'published' }).then((numPublished) => {\n * console.log(numPublished); // e.g. 45\n * });\n *\n * @method Container#count\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {object} [query] See {@link Mapper#count}.\n * @param {object} [opts] See {@link Mapper#count}.\n * @returns {Promise} See {@link Mapper#count}.\n * @see Mapper#count\n * @since 3.0.0\n */\n count (name, query, opts?) {\n return this.getMapper(name).count(query, opts)\n }\n\n /**\n * Fired during {@link Container#create}. See\n * {@link Container~beforeCreateListener} for how to listen for this event.\n *\n * @event Container#beforeCreate\n * @see Container~beforeCreateListener\n * @see Container#create\n */\n /**\n * Callback signature for the {@link Container#event:beforeCreate} event.\n *\n * @example\n * function onBeforeCreate (mapperName, props, opts) {\n * // do something\n * }\n * store.on('beforeCreate', onBeforeCreate);\n *\n * @callback Container~beforeCreateListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeCreate}.\n * @param {object} props The `props` argument received by {@link Mapper#beforeCreate}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeCreate}.\n * @see Container#event:beforeCreate\n * @see Container#create\n * @since 3.0.0\n */\n /**\n * Fired during {@link Container#create}. See\n * {@link Container~afterCreateListener} for how to listen for this event.\n *\n * @event Container#afterCreate\n * @see Container~afterCreateListener\n * @see Container#create\n */\n\n /**\n * Callback signature for the {@link Container#event:afterCreate} event.\n *\n * @example\n * function onAfterCreate (mapperName, props, opts, result) {\n * // do something\n * }\n * store.on('afterCreate', onAfterCreate);\n *\n * @callback Container~afterCreateListener\n * @param {string} name The `name` argument received by {@link Mapper#afterCreate}.\n * @param {object} props The `props` argument received by {@link Mapper#afterCreate}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterCreate}.\n * @param {object} result The `result` argument received by {@link Mapper#afterCreate}.\n * @see Container#event:afterCreate\n * @see Container#create\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#create}.\n *\n * @example\n * // Create and save a new blog post\n * import { Container } from 'js-data';\n * import RethinkDBAdapter from 'js-data-rethinkdb';\n * const store = new Container();\n * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('post');\n *\n * store.create('post', {\n * title: 'Modeling your data',\n * status: 'draft'\n * }).then((post) => {\n * console.log(post); // { id: 1234, status: 'draft', ... }\n * });\n *\n * @fires Container#beforeCreate\n * @fires Container#afterCreate\n * @method Container#create\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {object} props See {@link Mapper#create}.\n * @param {object} [opts] See {@link Mapper#create}.\n * @returns {Promise} See {@link Mapper#create}.\n * @see Mapper#create\n * @since 3.0.0\n */\n create (name, props, opts) {\n return this.getMapper(name).create(props, opts)\n }\n\n /**\n * Fired during {@link Container#createMany}. See\n * {@link Container~beforeCreateManyListener} for how to listen for this event.\n *\n * @event Container#beforeCreateMany\n * @see Container~beforeCreateManyListener\n * @see Container#createMany\n */\n /**\n * Callback signature for the {@link Container#event:beforeCreateMany} event.\n *\n * @example\n * function onBeforeCreateMany (mapperName, records, opts) {\n * // do something\n * }\n * store.on('beforeCreateMany', onBeforeCreateMany);\n *\n * @callback Container~beforeCreateManyListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeCreateMany}.\n * @param {object} records The `records` argument received by {@link Mapper#beforeCreateMany}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeCreateMany}.\n * @see Container#event:beforeCreateMany\n * @see Container#createMany\n * @since 3.0.0\n */\n /**\n * Fired during {@link Container#createMany}. See\n * {@link Container~afterCreateManyListener} for how to listen for this event.\n *\n * @event Container#afterCreateMany\n * @see Container~afterCreateManyListener\n * @see Container#createMany\n */\n\n /**\n * Callback signature for the {@link Container#event:afterCreateMany} event.\n *\n * @example\n * function onAfterCreateMany (mapperName, records, opts, result) {\n * // do something\n * }\n * store.on('afterCreateMany', onAfterCreateMany);\n *\n * @callback Container~afterCreateManyListener\n * @param {string} name The `name` argument received by {@link Mapper#afterCreateMany}.\n * @param {object} records The `records` argument received by {@link Mapper#afterCreateMany}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterCreateMany}.\n * @param {object} result The `result` argument received by {@link Mapper#afterCreateMany}.\n * @see Container#event:afterCreateMany\n * @see Container#createMany\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#createMany}.\n *\n * @example\n * // Create and save several new blog posts\n * import { Container } from 'js-data';\n * import RethinkDBAdapter from 'js-data-rethinkdb';\n * const store = new Container();\n * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('post');\n *\n * store.createMany('post', [{\n * title: 'Modeling your data',\n * status: 'draft'\n * }, {\n * title: 'Reading data',\n * status: 'draft'\n * }]).then((posts) => {\n * console.log(posts[0]); // { id: 1234, status: 'draft', ... }\n * console.log(posts[1]); // { id: 1235, status: 'draft', ... }\n * });\n *\n * @fires Container#beforeCreateMany\n * @fires Container#afterCreateMany\n * @method Container#createMany\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {Record[]} records See {@link Mapper#createMany}.\n * @param {object} [opts] See {@link Mapper#createMany}.\n * @returns {Promise} See {@link Mapper#createMany}.\n * @see Mapper#createMany\n * @since 3.0.0\n */\n createMany (name, records, opts) {\n return this.getMapper(name).createMany(records, opts)\n }\n\n /**\n * Wrapper for {@link Mapper#createRecord}.\n *\n * __Note:__ This method does __not__ interact with any adapter, and does\n * __not__ save any data. It only creates new objects in memory.\n *\n * @example\n * // Create empty unsaved record instance\n * import { Container } from 'js-data';\n * const store = new Container();\n * store.defineMapper('post');\n * const post = PostMapper.createRecord();\n *\n * @method Container#createRecord\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {Object|Object[]} props See {@link Mapper#createRecord}.\n * @param {object} [opts] See {@link Mapper#createRecord}.\n * @returns {Promise} See {@link Mapper#createRecord}.\n * @see Mapper#createRecord\n * @since 3.0.0\n */\n createRecord (name, props?, opts?) {\n return this.getMapper(name).createRecord(props, opts)\n }\n\n /**\n * Fired during {@link Container#destroy}. See\n * {@link Container~beforeDestroyListener} for how to listen for this event.\n *\n * @event Container#beforeDestroy\n * @see Container~beforeDestroyListener\n * @see Container#destroy\n */\n /**\n * Callback signature for the {@link Container#event:beforeDestroy} event.\n *\n * @example\n * function onBeforeDestroy (mapperName, id, opts) {\n * // do something\n * }\n * store.on('beforeDestroy', onBeforeDestroy);\n *\n * @callback Container~beforeDestroyListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeDestroy}.\n * @param {string|number} id The `id` argument received by {@link Mapper#beforeDestroy}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeDestroy}.\n * @see Container#event:beforeDestroy\n * @see Container#destroy\n * @since 3.0.0\n */\n /**\n * Fired during {@link Container#destroy}. See\n * {@link Container~afterDestroyListener} for how to listen for this event.\n *\n * @event Container#afterDestroy\n * @see Container~afterDestroyListener\n * @see Container#destroy\n */\n\n /**\n * Callback signature for the {@link Container#event:afterDestroy} event.\n *\n * @example\n * function onAfterDestroy (mapperName, id, opts, result) {\n * // do something\n * }\n * store.on('afterDestroy', onAfterDestroy);\n *\n * @callback Container~afterDestroyListener\n * @param {string} name The `name` argument received by {@link Mapper#afterDestroy}.\n * @param {string|number} id The `id` argument received by {@link Mapper#afterDestroy}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterDestroy}.\n * @param {object} result The `result` argument received by {@link Mapper#afterDestroy}.\n * @see Container#event:afterDestroy\n * @see Container#destroy\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#destroy}.\n *\n * @example\n * // Destroy a specific blog post\n * import { Container } from 'js-data';\n * import RethinkDBAdapter from 'js-data-rethinkdb';\n * const store = new Container();\n * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('post');\n *\n * store.destroy('post', 1234).then(() => {\n * // Blog post #1234 has been destroyed\n * });\n *\n * @fires Container#beforeDestroy\n * @fires Container#afterDestroy\n * @method Container#destroy\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {(string|number)} id See {@link Mapper#destroy}.\n * @param {object} [opts] See {@link Mapper#destroy}.\n * @returns {Promise} See {@link Mapper#destroy}.\n * @see Mapper#destroy\n * @since 3.0.0\n */\n destroy (name, id, opts) {\n return this.getMapper(name).destroy(id, opts)\n }\n\n /**\n * Fired during {@link Container#destroyAll}. See\n * {@link Container~beforeDestroyAllListener} for how to listen for this event.\n *\n * @event Container#beforeDestroyAll\n * @see Container~beforeDestroyAllListener\n * @see Container#destroyAll\n */\n /**\n * Callback signature for the {@link Container#event:beforeDestroyAll} event.\n *\n * @example\n * function onBeforeDestroyAll (mapperName, query, opts) {\n * // do something\n * }\n * store.on('beforeDestroyAll', onBeforeDestroyAll);\n *\n * @callback Container~beforeDestroyAllListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeDestroyAll}.\n * @param {object} query The `query` argument received by {@link Mapper#beforeDestroyAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeDestroyAll}.\n * @see Container#event:beforeDestroyAll\n * @see Container#destroyAll\n * @since 3.0.0\n */\n /**\n * Fired during {@link Container#destroyAll}. See\n * {@link Container~afterDestroyAllListener} for how to listen for this event.\n *\n * @event Container#afterDestroyAll\n * @see Container~afterDestroyAllListener\n * @see Container#destroyAll\n */\n\n /**\n * Callback signature for the {@link Container#event:afterDestroyAll} event.\n *\n * @example\n * function onAfterDestroyAll (mapperName, query, opts, result) {\n * // do something\n * }\n * store.on('afterDestroyAll', onAfterDestroyAll);\n *\n * @callback Container~afterDestroyAllListener\n * @param {string} name The `name` argument received by {@link Mapper#afterDestroyAll}.\n * @param {object} query The `query` argument received by {@link Mapper#afterDestroyAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterDestroyAll}.\n * @param {object} result The `result` argument received by {@link Mapper#afterDestroyAll}.\n * @see Container#event:afterDestroyAll\n * @see Container#destroyAll\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#destroyAll}.\n *\n * @example\n * // Destroy all \"draft\" blog posts\n * import { Container } from 'js-data';\n * import RethinkDBAdapter from 'js-data-rethinkdb';\n * const store = new Container();\n * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('post');\n *\n * store.destroyAll('post', { status: 'draft' }).then(() => {\n * // All \"draft\" blog posts have been destroyed\n * });\n *\n * @fires Container#beforeDestroyAll\n * @fires Container#afterDestroyAll\n * @method Container#destroyAll\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {object} [query] See {@link Mapper#destroyAll}.\n * @param {object} [opts] See {@link Mapper#destroyAll}.\n * @returns {Promise} See {@link Mapper#destroyAll}.\n * @see Mapper#destroyAll\n * @since 3.0.0\n */\n destroyAll (name, query, opts) {\n return this.getMapper(name).destroyAll(query, opts)\n }\n\n /**\n * Fired during {@link Container#find}. See\n * {@link Container~beforeFindListener} for how to listen for this event.\n *\n * @event Container#beforeFind\n * @see Container~beforeFindListener\n * @see Container#find\n */\n /**\n * Callback signature for the {@link Container#event:beforeFind} event.\n *\n * @example\n * function onBeforeFind (mapperName, id, opts) {\n * // do something\n * }\n * store.on('beforeFind', onBeforeFind);\n *\n * @callback Container~beforeFindListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeFind}.\n * @param {string|number} id The `id` argument received by {@link Mapper#beforeFind}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeFind}.\n * @see Container#event:beforeFind\n * @see Container#find\n * @since 3.0.0\n */\n /**\n * Fired during {@link Container#find}. See\n * {@link Container~afterFindListener} for how to listen for this event.\n *\n * @event Container#afterFind\n * @see Container~afterFindListener\n * @see Container#find\n */\n\n /**\n * Callback signature for the {@link Container#event:afterFind} event.\n *\n * @example\n * function onAfterFind (mapperName, id, opts, result) {\n * // do something\n * }\n * store.on('afterFind', onAfterFind);\n *\n * @callback Container~afterFindListener\n * @param {string} name The `name` argument received by {@link Mapper#afterFind}.\n * @param {string|number} id The `id` argument received by {@link Mapper#afterFind}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterFind}.\n * @param {object} result The `result` argument received by {@link Mapper#afterFind}.\n * @see Container#event:afterFind\n * @see Container#find\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#find}.\n *\n * @example\n * import { Container } from 'js-data';\n * import RethinkDBAdapter from 'js-data-rethinkdb';\n * const store = new Container();\n * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('post');\n *\n * store.find('post', 1).then((post) => {\n * console.log(post) // { id: 1, ...}\n * });\n *\n * @fires Container#beforeFind\n * @fires Container#afterFind\n * @method Container#find\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {(string|number)} id See {@link Mapper#find}.\n * @param {object} [opts] See {@link Mapper#find}.\n * @returns {Promise} See {@link Mapper#find}.\n * @see Mapper#find\n * @since 3.0.0\n */\n find (name, id, opts) {\n return this.getMapper(name).find(id, opts)\n }\n\n /**\n * Fired during {@link Container#findAll}. See\n * {@link Container~beforeFindAllListener} for how to listen for this event.\n *\n * @event Container#beforeFindAll\n * @see Container~beforeFindAllListener\n * @see Container#findAll\n */\n /**\n * Callback signature for the {@link Container#event:beforeFindAll} event.\n *\n * @example\n * function onBeforeFindAll (mapperName, query, opts) {\n * // do something\n * }\n * store.on('beforeFindAll', onBeforeFindAll);\n *\n * @callback Container~beforeFindAllListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeFindAll}.\n * @param {object} query The `query` argument received by {@link Mapper#beforeFindAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeFindAll}.\n * @see Container#event:beforeFindAll\n * @see Container#findAll\n * @since 3.0.0\n */\n /**\n * Fired during {@link Container#findAll}. See\n * {@link Container~afterFindAllListener} for how to listen for this event.\n *\n * @event Container#afterFindAll\n * @see Container~afterFindAllListener\n * @see Container#findAll\n */\n\n /**\n * Callback signature for the {@link Container#event:afterFindAll} event.\n *\n * @example\n * function onAfterFindAll (mapperName, query, opts, result) {\n * // do something\n * }\n * store.on('afterFindAll', onAfterFindAll);\n *\n * @callback Container~afterFindAllListener\n * @param {string} name The `name` argument received by {@link Mapper#afterFindAll}.\n * @param {object} query The `query` argument received by {@link Mapper#afterFindAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterFindAll}.\n * @param {object} result The `result` argument received by {@link Mapper#afterFindAll}.\n * @see Container#event:afterFindAll\n * @see Container#findAll\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#createRecord}.\n *\n * @example\n * // Find all \"published\" blog posts\n * import { Container } from 'js-data';\n * import RethinkDBAdapter from 'js-data-rethinkdb';\n * const store = new Container();\n * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('post');\n *\n * store.findAll('post', { status: 'published' }).then((posts) => {\n * console.log(posts); // [{ id: 1, ...}, ...]\n * });\n *\n * @fires Container#beforeFindAll\n * @fires Container#afterFindAll\n * @method Container#findAll\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {object} [query] See {@link Mapper#findAll}.\n * @param {object} [opts] See {@link Mapper#findAll}.\n * @returns {Promise} See {@link Mapper#findAll}.\n * @see Mapper#findAll\n * @since 3.0.0\n */\n findAll (name, query, opts) {\n return this.getMapper(name).findAll(query, opts)\n }\n\n /**\n * Wrapper for {@link Mapper#getSchema}.\n *\n * @method Container#getSchema\n * @param {string} name Name of the {@link Mapper} to target.\n * @returns {Schema} See {@link Mapper#getSchema}.\n * @see Mapper#getSchema\n * @since 3.0.0\n */\n getSchema (name) {\n return this.getMapper(name).getSchema()\n }\n\n /**\n * Wrapper for {@link Mapper#is}.\n *\n * @example\n * import { Container } from 'js-data';\n * const store = new Container();\n * store.defineMapper('post');\n * const post = store.createRecord();\n *\n * console.log(store.is('post', post)); // true\n * // Equivalent to what's above\n * console.log(post instanceof store.getMapper('post').recordClass); // true\n *\n * @method Container#is\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {Object|Record} record See {@link Mapper#is}.\n * @returns {boolean} See {@link Mapper#is}.\n * @see Mapper#is\n * @since 3.0.0\n */\n is (name, record) {\n return this.getMapper(name).is(record)\n }\n\n /**\n * Wrapper for {@link Mapper#sum}.\n *\n * @example\n * import { Container } from 'js-data';\n * import RethinkDBAdapter from 'js-data-rethinkdb';\n * const store = new Container();\n * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('purchase_order');\n *\n * store.sum('purchase_order', 'amount', { status: 'paid' }).then((amountPaid) => {\n * console.log(amountPaid); // e.g. 451125.34\n * });\n *\n * @method Container#sum\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {string} field See {@link Mapper#sum}.\n * @param {object} [query] See {@link Mapper#sum}.\n * @param {object} [opts] See {@link Mapper#sum}.\n * @returns {Promise} See {@link Mapper#sum}.\n * @see Mapper#sum\n * @since 3.0.0\n */\n sum (name, field, query, opts) {\n return this.getMapper(name).sum(field, query, opts)\n }\n\n /**\n * Wrapper for {@link Mapper#toJSON}.\n *\n * @example\n * import { Container } from 'js-data';\n * import RethinkDBAdapter from 'js-data-rethinkdb';\n * const store = new Container();\n * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('person', {\n * schema: {\n * properties: {\n * name: { type: 'string' },\n * id: { type: 'string' }\n * }\n * }\n * });\n * const person = store.createRecord('person', { id: 1, name: 'John', foo: 'bar' });\n * // \"foo\" is stripped by toJSON()\n * console.log(store.toJSON('person', person)); // {\"id\":1,\"name\":\"John\"}\n *\n * store.defineMapper('personRelaxed', {\n * schema: {\n * properties: {\n * name: { type: 'string' },\n * id: { type: 'string' }\n * },\n * additionalProperties: true\n * }\n * });\n * const person2 = store.createRecord('personRelaxed', { id: 1, name: 'John', foo: 'bar' });\n * // \"foo\" is not stripped by toJSON\n * console.log(store.toJSON('personRelaxed', person2)); // {\"id\":1,\"name\":\"John\",\"foo\":\"bar\"}\n *\n * @method Container#toJSON\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {Record|Record[]} records See {@link Mapper#toJSON}.\n * @param {object} [opts] See {@link Mapper#toJSON}.\n * @returns {Object|Object[]} See {@link Mapper#toJSON}.\n * @see Mapper#toJSON\n * @since 3.0.0\n */\n toJSON (name, records, opts?) {\n return this.getMapper(name).toJSON(records, opts)\n }\n\n /**\n * Fired during {@link Container#update}. See\n * {@link Container~beforeUpdateListener} for how to listen for this event.\n *\n * @event Container#beforeUpdate\n * @see Container~beforeUpdateListener\n * @see Container#update\n */\n /**\n * Callback signature for the {@link Container#event:beforeUpdate} event.\n *\n * @example\n * function onBeforeUpdate (mapperName, id, props, opts) {\n * // do something\n * }\n * store.on('beforeUpdate', onBeforeUpdate);\n *\n * @callback Container~beforeUpdateListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeUpdate}.\n * @param {string|number} id The `id` argument received by {@link Mapper#beforeUpdate}.\n * @param {object} props The `props` argument received by {@link Mapper#beforeUpdate}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdate}.\n * @see Container#event:beforeUpdate\n * @see Container#update\n * @since 3.0.0\n */\n /**\n * Fired during {@link Container#update}. See\n * {@link Container~afterUpdateListener} for how to listen for this event.\n *\n * @event Container#afterUpdate\n * @see Container~afterUpdateListener\n * @see Container#update\n */\n\n /**\n * Callback signature for the {@link Container#event:afterUpdate} event.\n *\n * @example\n * function onAfterUpdate (mapperName, id, props, opts, result) {\n * // do something\n * }\n * store.on('afterUpdate', onAfterUpdate);\n *\n * @callback Container~afterUpdateListener\n * @param {string} name The `name` argument received by {@link Mapper#afterUpdate}.\n * @param {string|number} id The `id` argument received by {@link Mapper#afterUpdate}.\n * @param {object} props The `props` argument received by {@link Mapper#afterUpdate}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdate}.\n * @param {object} result The `result` argument received by {@link Mapper#afterUpdate}.\n * @see Container#event:afterUpdate\n * @see Container#update\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#update}.\n *\n * @example\n * import { Container } from 'js-data';\n * import RethinkDBAdapter from 'js-data-rethinkdb';\n * const store = new Container();\n * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('post');\n *\n * store.update('post', 1234, {\n * status: 'published',\n * published_at: new Date()\n * }).then((post) => {\n * console.log(post); // { id: 1234, status: 'published', ... }\n * });\n *\n * @fires Container#beforeUpdate\n * @fires Container#afterUpdate\n * @method Container#update\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {(string|number)} id See {@link Mapper#update}.\n * @param {object} props See {@link Mapper#update}.\n * @param {object} [opts] See {@link Mapper#update}.\n * @returns {Promise} See {@link Mapper#update}.\n * @see Mapper#update\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/saving-data\",\"Saving data\"]\n */\n update (name, id, props, opts) {\n return this.getMapper(name).update(id, props, opts)\n }\n\n /**\n * Fired during {@link Container#updateAll}. See\n * {@link Container~beforeUpdateAllListener} for how to listen for this event.\n *\n * @event Container#beforeUpdateAll\n * @see Container~beforeUpdateAllListener\n * @see Container#updateAll\n */\n /**\n * Callback signature for the {@link Container#event:beforeUpdateAll} event.\n *\n * @example\n * function onBeforeUpdateAll (mapperName, props, query, opts) {\n * // do something\n * }\n * store.on('beforeUpdateAll', onBeforeUpdateAll);\n *\n * @callback Container~beforeUpdateAllListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeUpdateAll}.\n * @param {object} props The `props` argument received by {@link Mapper#beforeUpdateAll}.\n * @param {object} query The `query` argument received by {@link Mapper#beforeUpdateAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdateAll}.\n * @see Container#event:beforeUpdateAll\n * @see Container#updateAll\n * @since 3.0.0\n */\n /**\n * Fired during {@link Container#updateAll}. See\n * {@link Container~afterUpdateAllListener} for how to listen for this event.\n *\n * @event Container#afterUpdateAll\n * @see Container~afterUpdateAllListener\n * @see Container#updateAll\n */\n\n /**\n * Callback signature for the {@link Container#event:afterUpdateAll} event.\n *\n * @example\n * function onAfterUpdateAll (mapperName, props, query, opts, result) {\n * // do something\n * }\n * store.on('afterUpdateAll', onAfterUpdateAll);\n *\n * @callback Container~afterUpdateAllListener\n * @param {string} name The `name` argument received by {@link Mapper#afterUpdateAll}.\n * @param {object} props The `props` argument received by {@link Mapper#afterUpdateAll}.\n * @param {object} query The `query` argument received by {@link Mapper#afterUpdateAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdateAll}.\n * @param {object} result The `result` argument received by {@link Mapper#afterUpdateAll}.\n * @see Container#event:afterUpdateAll\n * @see Container#updateAll\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#updateAll}.\n *\n * @example\n * // Turn all of John's blog posts into drafts.\n * import { Container } from 'js-data';\n * import RethinkDBAdapter from 'js-data-rethinkdb';\n * const store = new Container();\n * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('post');\n *\n * const update = { status: draft: published_at: null };\n * const query = { userId: 1234 };\n * store.updateAll('post', update, query).then((posts) => {\n * console.log(posts); // [...]\n * });\n *\n * @fires Container#beforeUpdateAll\n * @fires Container#afterUpdateAll\n * @method Container#updateAll\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {object} props See {@link Mapper#updateAll}.\n * @param {object} [query] See {@link Mapper#updateAll}.\n * @param {object} [opts] See {@link Mapper#updateAll}.\n * @returns {Promise} See {@link Mapper#updateAll}.\n * @see Mapper#updateAll\n * @since 3.0.0\n */\n updateAll (name, props, query, opts) {\n return this.getMapper(name).updateAll(props, query, opts)\n }\n\n /**\n * Fired during {@link Container#updateMany}. See\n * {@link Container~beforeUpdateManyListener} for how to listen for this event.\n *\n * @event Container#beforeUpdateMany\n * @see Container~beforeUpdateManyListener\n * @see Container#updateMany\n */\n /**\n * Callback signature for the {@link Container#event:beforeUpdateMany} event.\n *\n * @example\n * function onBeforeUpdateMany (mapperName, records, opts) {\n * // do something\n * }\n * store.on('beforeUpdateMany', onBeforeUpdateMany);\n *\n * @callback Container~beforeUpdateManyListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeUpdateMany}.\n * @param {object} records The `records` argument received by {@link Mapper#beforeUpdateMany}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdateMany}.\n * @see Container#event:beforeUpdateMany\n * @see Container#updateMany\n * @since 3.0.0\n */\n /**\n * Fired during {@link Container#updateMany}. See\n * {@link Container~afterUpdateManyListener} for how to listen for this event.\n *\n * @event Container#afterUpdateMany\n * @see Container~afterUpdateManyListener\n * @see Container#updateMany\n */\n\n /**\n * Callback signature for the {@link Container#event:afterUpdateMany} event.\n *\n * @example\n * function onAfterUpdateMany (mapperName, records, opts, result) {\n * // do something\n * }\n * store.on('afterUpdateMany', onAfterUpdateMany);\n *\n * @callback Container~afterUpdateManyListener\n * @param {string} name The `name` argument received by {@link Mapper#afterUpdateMany}.\n * @param {object} records The `records` argument received by {@link Mapper#afterUpdateMany}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdateMany}.\n * @param {object} result The `result` argument received by {@link Mapper#afterUpdateMany}.\n * @see Container#event:afterUpdateMany\n * @see Container#updateMany\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#updateMany}.\n *\n * @example\n * import { Container } from 'js-data';\n * import RethinkDBAdapter from 'js-data-rethinkdb';\n * const store = new Container();\n * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('post');\n *\n * store.updateMany('post', [\n * { id: 1234, status: 'draft' },\n * { id: 2468, status: 'published', published_at: new Date() }\n * ]).then((posts) => {\n * console.log(posts); // [...]\n * });\n *\n * @fires Container#beforeUpdateMany\n * @fires Container#afterUpdateMany\n * @method Container#updateMany\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {(Object[]|Record[])} records See {@link Mapper#updateMany}.\n * @param {object} [opts] See {@link Mapper#updateMany}.\n * @returns {Promise} See {@link Mapper#updateMany}.\n * @see Mapper#updateMany\n * @since 3.0.0\n */\n updateMany (name, record, opts) {\n return this.getMapper(name).updateMany(record, opts)\n }\n\n /**\n * Wrapper for {@link Mapper#validate}.\n *\n * @example\n * import { Container } from 'js-data';\n * const store = new Container();\n * store.defineMapper('post', {\n * schema: {\n * properties: {\n * name: { type: 'string' },\n * id: { type: 'string' }\n * }\n * }\n * });\n * let errors = store.validate('post', { name: 'John' });\n * console.log(errors); // undefined\n * errors = store.validate('post', { name: 123 });\n * console.log(errors); // [{ expected: 'one of (string)', actual: 'number', path: 'name' }]\n *\n * @method Container#validate\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {(Object[]|Record[])} records See {@link Mapper#validate}.\n * @param {object} [opts] See {@link Mapper#validate}.\n * @returns {Promise} See {@link Mapper#validate}.\n * @see Mapper#validate\n * @since 3.0.0\n */\n validate (name, record, opts) {\n return this.getMapper(name).validate(record, opts)\n }\n}\n","import utils from './utils'\n\nimport { belongsToType, hasManyType, hasOneType } from './decorators'\nimport { Container, proxiedMapperMethods } from './Container'\nimport Collection from './Collection'\nimport { MapperOpts } from './Mapper'\nimport Schema from './Schema'\n\nconst DOMAIN = 'SimpleStore'\nconst proxiedCollectionMethods = [\n 'add',\n 'between',\n 'createIndex',\n 'filter',\n 'get',\n 'getAll',\n 'prune',\n 'query',\n 'toJSON',\n 'unsaved'\n]\nconst ownMethodsForScoping = ['addToCache', 'cachedFind', 'cachedFindAll', 'cacheFind', 'cacheFindAll', 'hashQuery']\n\nconst cachedFn = function (name, hashOrId, opts) {\n const cached = this._completedQueries[name][hashOrId]\n if (utils.isFunction(cached)) {\n return cached(name, hashOrId, opts)\n }\n return cached\n}\n\nexport interface SimpleStoreOpts {\n /**\n * Whether to use the pending query if a `find` request for the specified\n * record is currently underway. Can be set to `true`, `false`, or to a\n * function that returns `true` or `false`.\n *\n * @default true\n * @name SimpleStore#usePendingFind\n * @since 3.0.0\n * @type {boolean|Function}\n */\n usePendingFind?: boolean | Function\n\n /**\n * Whether to use the pending query if a `findAll` request for the given query\n * is currently underway. Can be set to `true`, `false`, or to a function that\n * returns `true` or `false`.\n *\n * @default true\n * @name SimpleStore#usePendingFindAll\n * @since 3.0.0\n * @type {boolean|Function}\n */\n usePendingFindAll?: boolean | Function\n}\n\nconst SIMPLESTORE_DEFAULTS = {\n /**\n * Whether to use the pending query if a `find` request for the specified\n * record is currently underway. Can be set to `true`, `false`, or to a\n * function that returns `true` or `false`.\n *\n * @default true\n * @name SimpleStore#usePendingFind\n * @since 3.0.0\n * @type {boolean|Function}\n */\n usePendingFind: true,\n\n /**\n * Whether to use the pending query if a `findAll` request for the given query\n * is currently underway. Can be set to `true`, `false`, or to a function that\n * returns `true` or `false`.\n *\n * @default true\n * @name SimpleStore#usePendingFindAll\n * @since 3.0.0\n * @type {boolean|Function}\n */\n usePendingFindAll: true\n}\n\n/**\n * The `SimpleStore` class is an extension of {@link Container}. Not only does\n * `SimpleStore` manage mappers, but also collections. `SimpleStore` implements the\n * asynchronous {@link Mapper} methods, such as {@link Mapper#find} and\n * {@link Mapper#create}. If you use the asynchronous `SimpleStore` methods\n * instead of calling them directly on the mappers, then the results of the\n * method calls will be inserted into the store's collections. You can think of\n * a `SimpleStore` as an [Identity Map](https://en.wikipedia.org/wiki/Identity_map_pattern)\n * for the [ORM](https://en.wikipedia.org/wiki/Object-relational_mapping)\n * (the Mappers).\n *\n * ```javascript\n * import { SimpleStore } from 'js-data';\n * ```\n *\n * @example\n * import { SimpleStore } from 'js-data';\n * import { HttpAdapter } from 'js-data-http';\n * const store = new SimpleStore();\n *\n * // SimpleStore#defineMapper returns a direct reference to the newly created\n * // Mapper.\n * const UserMapper = store.defineMapper('user');\n *\n * // SimpleStore#as returns the store scoped to a particular Mapper.\n * const UserStore = store.as('user');\n *\n * // Call \"find\" on \"UserMapper\" (Stateless ORM)\n * UserMapper.find(1).then((user) => {\n * // retrieved a \"user\" record via the http adapter, but that's it\n *\n * // Call \"find\" on \"store\" targeting \"user\" (Stateful SimpleStore)\n * return store.find('user', 1); // same as \"UserStore.find(1)\"\n * }).then((user) => {\n * // not only was a \"user\" record retrieved, but it was added to the\n * // store's \"user\" collection\n * const cachedUser = store.getCollection('user').get(1);\n * console.log(user === cachedUser); // true\n * });\n *\n * @class SimpleStore\n * @extends Container\n * @param {object} [opts] Configuration options. See {@link Container}.\n * @param {boolean} [opts.collectionClass={@link Collection}] See {@link SimpleStore#collectionClass}.\n * @param {boolean} [opts.debug=false] See {@link Component#debug}.\n * @param {boolean|Function} [opts.usePendingFind=true] See {@link SimpleStore#usePendingFind}.\n * @param {boolean|Function} [opts.usePendingFindAll=true] See {@link SimpleStore#usePendingFindAll}.\n * @returns {SimpleStore}\n * @see Container\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/components-of-jsdata#SimpleStore\",\"Components of JSData: SimpleStore\"]\n * @tutorial [\"http://www.js-data.io/v3.0/docs/working-with-the-SimpleStore\",\"Working with the SimpleStore\"]\n * @tutorial [\"http://www.js-data.io/v3.0/docs/jsdata-and-the-browser\",\"Notes on using JSData in the Browser\"]\n */\nexport default class SimpleStore extends Container {\n collectionClass: typeof Collection;\n _collections: { [name: string]: Collection } = {};\n _completedQueries = {};\n _pendingQueries = {};\n usePendingFind: boolean;\n usePendingFindAll: boolean;\n\n constructor (opts: SimpleStoreOpts = {}) {\n super({ ...SIMPLESTORE_DEFAULTS, ...opts })\n this.collectionClass = this.collectionClass || Collection\n }\n\n /**\n * Internal method used to handle Mapper responses.\n *\n * @method SimpleStore#_end\n * @private\n * @param {string} name Name of the {@link Collection} to which to\n * add the data.\n * @param {object} result The result from a Mapper.\n * @param {object} [opts] Configuration options.\n * @returns {(Object|Array)} Result.\n */\n _end (name, result, opts) {\n let data = opts.raw ? result.data : result\n if (data && utils.isFunction(this.addToCache)) {\n data = this.addToCache(name, data, opts)\n if (opts.raw) {\n result.data = data\n } else {\n result = data\n }\n }\n return result\n }\n\n /**\n * Register a new event listener on this SimpleStore.\n *\n * Proxy for {@link Container#on}. If an event was emitted by a Mapper or\n * Collection in the SimpleStore, then the name of the Mapper or Collection will\n * be prepended to the arugments passed to the provided event handler.\n *\n * @example\n * // Listen for all \"afterCreate\" events in a SimpleStore\n * store.on('afterCreate', (mapperName, props, opts, result) => {\n * console.log(mapperName); // \"post\"\n * console.log(props.id); // undefined\n * console.log(result.id); // 1234\n * });\n * store.create('post', { title: 'Modeling your data' }).then((post) => {\n * console.log(post.id); // 1234\n * });\n *\n * @example\n * // Listen for the \"add\" event on a collection\n * store.on('add', (mapperName, records) => {\n * console.log(records); // [...]\n * });\n *\n * @example\n * // Listen for \"change\" events on a record\n * store.on('change', (mapperName, record, changes) => {\n * console.log(changes); // { changed: { title: 'Modeling your data' } }\n * });\n * post.title = 'Modeling your data';\n *\n * @method SimpleStore#on\n * @param {string} event Name of event to subsribe to.\n * @param {Function} listener Listener function to handle the event.\n * @param {*} [ctx] Optional content in which to invoke the listener.\n */\n\n /**\n * Used to bind to events emitted by collections in this store.\n *\n * @method SimpleStore#_onCollectionEvent\n * @private\n * @param {string} name Name of the collection that emitted the event.\n * @param {...*} [args] Args passed to {@link Collection#emit}.\n */\n _onCollectionEvent (name, ...args) {\n const type = args.shift()\n this.emit(type, name, ...args)\n }\n\n /**\n * This method takes the data received from {@link SimpleStore#find},\n * {@link SimpleStore#findAll}, {@link SimpleStore#update}, etc., and adds the\n * data to the store. _You don't need to call this method directly._\n *\n * If you're using the http adapter and your response data is in an unexpected\n * format, you may need to override this method so the right data gets added\n * to the store.\n *\n * @example\n * const store = new SimpleStore({\n * addToCache (mapperName, data, opts) {\n * // Let's say for a particular Resource, response data is in a weird format\n * if (name === 'comment') {\n * // Re-assign the variable to add the correct records into the stores\n * data = data.items;\n * }\n * // Now perform default behavior\n * return SimpleStore.prototype.addToCache.call(this, mapperName, data, opts);\n * }\n * });\n *\n * @example\n * // Extend using ES2015 class syntax.\n * class MyStore extends SimpleStore {\n * addToCache (mapperName, data, opts) {\n * // Let's say for a particular Resource, response data is in a weird format\n * if (name === 'comment') {\n * // Re-assign the variable to add the correct records into the stores\n * data = data.items;\n * }\n * // Now perform default behavior\n * return super.addToCache(mapperName, data, opts);\n * }\n * }\n * const store = new MyStore();\n *\n * @method SimpleStore#addToCache\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {*} data Data from which data should be selected for add.\n * @param {object} [opts] Configuration options.\n */\n addToCache (name, data, opts) {\n return this.getCollection(name).add(data, opts)\n }\n\n /**\n * Return the store scoped to a particular mapper/collection pair.\n *\n * @example SimpleStore.as\n * const JSData = require('js-data');\n * const { SimpleStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new SimpleStore();\n * const UserMapper = store.defineMapper('user');\n * const UserStore = store.as('user');\n *\n * const user1 = store.createRecord('user', { name: 'John' });\n * const user2 = UserStore.createRecord({ name: 'John' });\n * const user3 = UserMapper.createRecord({ name: 'John' });\n * console.log(user1 === user2);\n * console.log(user2 === user3);\n * console.log(user1 === user3);\n *\n * @method SimpleStore#as\n * @param {string} name Name of the {@link Mapper}.\n * @returns {Object} The store, scoped to a particular Mapper/Collection pair.\n * @since 3.0.0\n */\n as (name) {\n const props: any = {}\n const original = this\n const methods = ownMethodsForScoping.concat(proxiedMapperMethods).concat(proxiedCollectionMethods)\n\n methods.forEach(method => {\n props[method] = {\n writable: true,\n value (...args) {\n return original[method](name, ...args)\n }\n }\n })\n props.getMapper = {\n writable: true,\n value () {\n return original.getMapper(name)\n }\n }\n props.getCollection = {\n writable: true,\n value () {\n return original.getCollection(name)\n }\n }\n return Object.create(this, props)\n }\n\n /**\n * Retrieve a cached `find` result, if any. This method is called during\n * {@link SimpleStore#find} to determine if {@link Mapper#find} needs to be\n * called. If this method returns `undefined` then {@link Mapper#find} will\n * be called. Otherwise {@link SimpleStore#find} will immediately resolve with\n * the return value of this method.\n *\n * When using {@link SimpleStore} in the browser, you can override this method\n * to implement your own cache-busting strategy.\n *\n * @example\n * const store = new SimpleStore({\n * cachedFind (mapperName, id, opts) {\n * // Let's say for a particular Resource, we always want to pull fresh from the server\n * if (mapperName === 'schedule') {\n * // Return undefined to trigger a Mapper#find call\n * return;\n * }\n * // Otherwise perform default behavior\n * return SimpleStore.prototype.cachedFind.call(this, mapperName, id, opts);\n * }\n * });\n *\n * @example\n * // Extend using ES2015 class syntax.\n * class MyStore extends SimpleStore {\n * cachedFind (mapperName, id, opts) {\n * // Let's say for a particular Resource, we always want to pull fresh from the server\n * if (mapperName === 'schedule') {\n * // Return undefined to trigger a Mapper#find call\n * return;\n * }\n * // Otherwise perform default behavior\n * return super.cachedFind(mapperName, id, opts);\n * }\n * }\n * const store = new MyStore();\n *\n * @method SimpleStore#cachedFind\n * @param {string} name The `name` argument passed to {@link SimpleStore#find}.\n * @param {(string|number)} id The `id` argument passed to {@link SimpleStore#find}.\n * @param {object} opts The `opts` argument passed to {@link SimpleStore#find}.\n * @since 3.0.0\n */\n cachedFind = cachedFn\n\n /**\n * Retrieve a cached `findAll` result, if any. This method is called during\n * {@link SimpleStore#findAll} to determine if {@link Mapper#findAll} needs to be\n * called. If this method returns `undefined` then {@link Mapper#findAll} will\n * be called. Otherwise {@link SimpleStore#findAll} will immediately resolve with\n * the return value of this method.\n *\n * When using {@link SimpleStore} in the browser, you can override this method\n * to implement your own cache-busting strategy.\n *\n * @example\n * const store = new SimpleStore({\n * cachedFindAll (mapperName, hash, opts) {\n * // Let's say for a particular Resource, we always want to pull fresh from the server\n * if (mapperName === 'schedule') {\n * // Return undefined to trigger a Mapper#findAll call\n * return undefined;\n * }\n * // Otherwise perform default behavior\n * return SimpleStore.prototype.cachedFindAll.call(this, mapperName, hash, opts);\n * }\n * });\n *\n * @example\n * // Extend using ES2015 class syntax.\n * class MyStore extends SimpleStore {\n * cachedFindAll (mapperName, hash, opts) {\n * // Let's say for a particular Resource, we always want to pull fresh from the server\n * if (mapperName === 'schedule') {\n * // Return undefined to trigger a Mapper#findAll call\n * return undefined;\n * }\n * // Otherwise perform default behavior\n * return super.cachedFindAll(mapperName, hash, opts);\n * }\n * }\n * const store = new MyStore();\n *\n * @method SimpleStore#cachedFindAll\n * @param {string} name The `name` argument passed to {@link SimpleStore#findAll}.\n * @param {string} hash The result of calling {@link SimpleStore#hashQuery} on\n * the `query` argument passed to {@link SimpleStore#findAll}.\n * @param {object} opts The `opts` argument passed to {@link SimpleStore#findAll}.\n * @since 3.0.0\n */\n cachedFindAll = cachedFn\n\n /**\n * Mark a {@link Mapper#find} result as cached by adding an entry to\n * {@link SimpleStore#_completedQueries}. By default, once a `find` entry is\n * added it means subsequent calls to the same Resource with the same `id`\n * argument will immediately resolve with the result of calling\n * {@link SimpleStore#get} instead of delegating to {@link Mapper#find}.\n *\n * As part of implementing your own caching strategy, you may choose to\n * override this method.\n *\n * @example\n * const store = new SimpleStore({\n * cacheFind (mapperName, data, id, opts) {\n * // Let's say for a particular Resource, we always want to pull fresh from the server\n * if (mapperName === 'schedule') {\n * // Return without saving an entry to SimpleStore#_completedQueries\n * return;\n * }\n * // Otherwise perform default behavior\n * return SimpleStore.prototype.cacheFind.call(this, mapperName, data, id, opts);\n * }\n * });\n *\n * @example\n * // Extend using ES2015 class syntax.\n * class MyStore extends SimpleStore {\n * cacheFind (mapperName, data, id, opts) {\n * // Let's say for a particular Resource, we always want to pull fresh from the server\n * if (mapperName === 'schedule') {\n * // Return without saving an entry to SimpleStore#_completedQueries\n * return;\n * }\n * // Otherwise perform default behavior\n * return super.cacheFind(mapperName, data, id, opts);\n * }\n * }\n * const store = new MyStore();\n *\n * @method SimpleStore#cacheFind\n * @param {string} name The `name` argument passed to {@link SimpleStore#find}.\n * @param {*} data The result to cache.\n * @param {(string|number)} id The `id` argument passed to {@link SimpleStore#find}.\n * @param {object} opts The `opts` argument passed to {@link SimpleStore#find}.\n * @since 3.0.0\n */\n cacheFind (name, data, id, opts) {\n this._completedQueries[name][id] = (name, id, opts) => this.get(name, id)\n }\n\n /**\n * Mark a {@link Mapper#findAll} result as cached by adding an entry to\n * {@link SimpleStore#_completedQueries}. By default, once a `findAll` entry is\n * added it means subsequent calls to the same Resource with the same `query`\n * argument will immediately resolve with the result of calling\n * {@link SimpleStore#filter} instead of delegating to {@link Mapper#findAll}.\n *\n * As part of implementing your own caching strategy, you may choose to\n * override this method.\n *\n * @example\n * const store = new SimpleStore({\n * cachedFindAll (mapperName, data, hash, opts) {\n * // Let's say for a particular Resource, we always want to pull fresh from the server\n * if (mapperName === 'schedule') {\n * // Return without saving an entry to SimpleStore#_completedQueries\n * return;\n * }\n * // Otherwise perform default behavior.\n * return SimpleStore.prototype.cachedFindAll.call(this, mapperName, data, hash, opts);\n * }\n * });\n *\n * @example\n * // Extend using ES2015 class syntax.\n * class MyStore extends SimpleStore {\n * cachedFindAll (mapperName, data, hash, opts) {\n * // Let's say for a particular Resource, we always want to pull fresh from the server\n * if (mapperName === 'schedule') {\n * // Return without saving an entry to SimpleStore#_completedQueries\n * return;\n * }\n * // Otherwise perform default behavior.\n * return super.cachedFindAll(mapperName, data, hash, opts);\n * }\n * }\n * const store = new MyStore();\n *\n * @method SimpleStore#cacheFindAll\n * @param {string} name The `name` argument passed to {@link SimpleStore#findAll}.\n * @param {*} data The result to cache.\n * @param {string} hash The result of calling {@link SimpleStore#hashQuery} on\n * the `query` argument passed to {@link SimpleStore#findAll}.\n * @param {object} opts The `opts` argument passed to {@link SimpleStore#findAll}.\n * @since 3.0.0\n */\n cacheFindAll (name, data, hash, opts) {\n this._completedQueries[name][hash] = (name, hash, opts) => this.filter(name, utils.fromJson(hash))\n }\n\n /**\n * Remove __all__ records from the in-memory store and reset\n * {@link SimpleStore#_completedQueries}.\n *\n * @method SimpleStore#clear\n * @returns {Object} Object containing all records that were in the store.\n * @see SimpleStore#remove\n * @see SimpleStore#removeAll\n * @since 3.0.0\n */\n clear () {\n const removed = {}\n utils.forOwn(this._collections, (collection, name) => {\n removed[name] = collection.removeAll()\n this._completedQueries[name] = {}\n })\n return removed\n }\n\n /**\n * Fired during {@link SimpleStore#create}. See\n * {@link SimpleStore~beforeCreateListener} for how to listen for this event.\n *\n * @event SimpleStore#beforeCreate\n * @see SimpleStore~beforeCreateListener\n * @see SimpleStore#create\n */\n /**\n * Callback signature for the {@link SimpleStore#event:beforeCreate} event.\n *\n * @example\n * function onBeforeCreate (mapperName, props, opts) {\n * // do something\n * }\n * store.on('beforeCreate', onBeforeCreate);\n *\n * @callback SimpleStore~beforeCreateListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeCreate}.\n * @param {object} props The `props` argument received by {@link Mapper#beforeCreate}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeCreate}.\n * @see SimpleStore#event:beforeCreate\n * @see SimpleStore#create\n * @since 3.0.0\n */\n /**\n * Fired during {@link SimpleStore#create}. See\n * {@link SimpleStore~afterCreateListener} for how to listen for this event.\n *\n * @event SimpleStore#afterCreate\n * @see SimpleStore~afterCreateListener\n * @see SimpleStore#create\n */\n\n /**\n * Callback signature for the {@link SimpleStore#event:afterCreate} event.\n *\n * @example\n * function onAfterCreate (mapperName, props, opts, result) {\n * // do something\n * }\n * store.on('afterCreate', onAfterCreate);\n *\n * @callback SimpleStore~afterCreateListener\n * @param {string} name The `name` argument received by {@link Mapper#afterCreate}.\n * @param {object} props The `props` argument received by {@link Mapper#afterCreate}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterCreate}.\n * @param {object} result The `result` argument received by {@link Mapper#afterCreate}.\n * @see SimpleStore#event:afterCreate\n * @see SimpleStore#create\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#create}. Adds the created record to the store.\n *\n * @example\n * import { SimpleStore } from 'js-data';\n * import { HttpAdapter } from 'js-data-http';\n *\n * const store = new SimpleStore();\n * store.registerAdapter('http', new HttpAdapter(), { default: true });\n *\n * store.defineMapper('book');\n *\n * // Since this example uses the http adapter, we'll get something like:\n * //\n * // POST /book {\"author_id\":1234,...}\n * store.create('book', {\n * author_id: 1234,\n * edition: 'First Edition',\n * title: 'Respect your Data'\n * }).then((book) => {\n * console.log(book.id); // 120392\n * console.log(book.title); // \"Respect your Data\"\n * });\n *\n * @fires SimpleStore#beforeCreate\n * @fires SimpleStore#afterCreate\n * @fires SimpleStore#add\n * @method SimpleStore#create\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {object} record Passed to {@link Mapper#create}.\n * @param {object} [opts] Passed to {@link Mapper#create}. See\n * {@link Mapper#create} for more configuration options.\n * @returns {Promise} Resolves with the result of the create.\n * @since 3.0.0\n */\n create (name, record, opts: any = {}) {\n return super.create(name, record, opts).then(result => this._end(name, result, opts))\n }\n\n /**\n * Fired during {@link SimpleStore#createMany}. See\n * {@link SimpleStore~beforeCreateManyListener} for how to listen for this event.\n *\n * @event SimpleStore#beforeCreateMany\n * @see SimpleStore~beforeCreateManyListener\n * @see SimpleStore#createMany\n */\n /**\n * Callback signature for the {@link SimpleStore#event:beforeCreateMany} event.\n *\n * @example\n * function onBeforeCreateMany (mapperName, records, opts) {\n * // do something\n * }\n * store.on('beforeCreateMany', onBeforeCreateMany);\n *\n * @callback SimpleStore~beforeCreateManyListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeCreateMany}.\n * @param {object} records The `records` argument received by {@link Mapper#beforeCreateMany}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeCreateMany}.\n * @see SimpleStore#event:beforeCreateMany\n * @see SimpleStore#createMany\n * @since 3.0.0\n */\n /**\n * Fired during {@link SimpleStore#createMany}. See\n * {@link SimpleStore~afterCreateManyListener} for how to listen for this event.\n *\n * @event SimpleStore#afterCreateMany\n * @see SimpleStore~afterCreateManyListener\n * @see SimpleStore#createMany\n */\n\n /**\n * Callback signature for the {@link SimpleStore#event:afterCreateMany} event.\n *\n * @example\n * function onAfterCreateMany (mapperName, records, opts, result) {\n * // do something\n * }\n * store.on('afterCreateMany', onAfterCreateMany);\n *\n * @callback SimpleStore~afterCreateManyListener\n * @param {string} name The `name` argument received by {@link Mapper#afterCreateMany}.\n * @param {object} records The `records` argument received by {@link Mapper#afterCreateMany}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterCreateMany}.\n * @param {object} result The `result` argument received by {@link Mapper#afterCreateMany}.\n * @see SimpleStore#event:afterCreateMany\n * @see SimpleStore#createMany\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#createMany}. Adds the created records to the\n * store.\n *\n * @example\n * import { SimpleStore } from 'js-data';\n * import { HttpAdapter } from 'js-data-http';\n *\n * const store = new SimpleStore();\n * store.registerAdapter('http', new HttpAdapter(), { default: true });\n *\n * store.defineMapper('book');\n *\n * // Since this example uses the http adapter, we'll get something like:\n * //\n * // POST /book [{\"author_id\":1234,...},{...}]\n * store.createMany('book', [{\n * author_id: 1234,\n * edition: 'First Edition',\n * title: 'Respect your Data'\n * }, {\n * author_id: 1234,\n * edition: 'Second Edition',\n * title: 'Respect your Data'\n * }]).then((books) => {\n * console.log(books[0].id); // 142394\n * console.log(books[0].title); // \"Respect your Data\"\n * });\n *\n * @fires SimpleStore#beforeCreateMany\n * @fires SimpleStore#afterCreateMany\n * @fires SimpleStore#add\n * @method SimpleStore#createMany\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {array} records Passed to {@link Mapper#createMany}.\n * @param {object} [opts] Passed to {@link Mapper#createMany}. See\n * {@link Mapper#createMany} for more configuration options.\n * @returns {Promise} Resolves with the result of the create.\n * @since 3.0.0\n */\n createMany (name, records, opts: any = {}) {\n return super.createMany(name, records, opts).then(result => this._end(name, result, opts))\n }\n\n defineMapper (name, opts: MapperOpts = {}) {\n const self = this\n const mapper = super.defineMapper(name, opts)\n self._pendingQueries[name] = {}\n self._completedQueries[name] = {}\n if (!mapper.relationList) Object.defineProperty(mapper, 'relationList', { value: [] })\n\n const collectionOpts: any = {\n // Make sure the collection has somewhere to store \"added\" timestamps\n _added: {},\n // Give the collection a reference to this SimpleStore\n datastore: this,\n // The mapper tied to the collection\n mapper\n }\n\n if (opts && 'onConflict' in opts) {\n collectionOpts.onConflict = opts.onConflict\n }\n\n // The SimpleStore uses a subclass of Collection that is \"SimpleStore-aware\"\n const collection = (self._collections[name] = new self.collectionClass(null, collectionOpts))\n\n const schema = mapper.schema || ({} as Schema)\n const properties = schema.properties || {}\n // TODO: Make it possible index nested properties?\n utils.forOwn(properties, (opts, prop) => {\n if (opts.indexed) {\n collection.createIndex(prop)\n }\n })\n\n // Create a secondary index on the \"added\" timestamps of records in the\n // collection\n collection.createIndex('addedTimestamps', ['$'], {\n fieldGetter (obj) {\n return collection._added[collection.recordId(obj)]\n }\n })\n\n collection.on('all', (...args) => {\n self._onCollectionEvent(name, ...args)\n })\n\n return mapper\n }\n\n /**\n * Fired during {@link SimpleStore#destroy}. See\n * {@link SimpleStore~beforeDestroyListener} for how to listen for this event.\n *\n * @event SimpleStore#beforeDestroy\n * @see SimpleStore~beforeDestroyListener\n * @see SimpleStore#destroy\n */\n /**\n * Callback signature for the {@link SimpleStore#event:beforeDestroy} event.\n *\n * @example\n * function onBeforeDestroy (mapperName, id, opts) {\n * // do something\n * }\n * store.on('beforeDestroy', onBeforeDestroy);\n *\n * @callback SimpleStore~beforeDestroyListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeDestroy}.\n * @param {string|number} id The `id` argument received by {@link Mapper#beforeDestroy}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeDestroy}.\n * @see SimpleStore#event:beforeDestroy\n * @see SimpleStore#destroy\n * @since 3.0.0\n */\n /**\n * Fired during {@link SimpleStore#destroy}. See\n * {@link SimpleStore~afterDestroyListener} for how to listen for this event.\n *\n * @event SimpleStore#afterDestroy\n * @see SimpleStore~afterDestroyListener\n * @see SimpleStore#destroy\n */\n\n /**\n * Callback signature for the {@link SimpleStore#event:afterDestroy} event.\n *\n * @example\n * function onAfterDestroy (mapperName, id, opts, result) {\n * // do something\n * }\n * store.on('afterDestroy', onAfterDestroy);\n *\n * @callback SimpleStore~afterDestroyListener\n * @param {string} name The `name` argument received by {@link Mapper#afterDestroy}.\n * @param {string|number} id The `id` argument received by {@link Mapper#afterDestroy}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterDestroy}.\n * @param {object} result The `result` argument received by {@link Mapper#afterDestroy}.\n * @see SimpleStore#event:afterDestroy\n * @see SimpleStore#destroy\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#destroy}. Removes any destroyed record from the\n * in-memory store. Clears out any {@link SimpleStore#_completedQueries} entries\n * associated with the provided `id`.\n *\n * @example\n * import { SimpleStore } from 'js-data';\n * import { HttpAdapter } from 'js-data-http';\n *\n * const store = new SimpleStore();\n * store.registerAdapter('http', new HttpAdapter(), { default: true });\n *\n * store.defineMapper('book');\n *\n * store.add('book', { id: 1234, title: 'Data Management is Hard' });\n *\n * // Since this example uses the http adapter, we'll get something like:\n * //\n * // DELETE /book/1234\n * store.destroy('book', 1234).then(() => {\n * // The book record is no longer in the in-memory store\n * console.log(store.get('book', 1234)); // undefined\n *\n * return store.find('book', 1234);\n * }).then((book) {\n * // The book was deleted from the database too\n * console.log(book); // undefined\n * });\n *\n * @fires SimpleStore#beforeDestroy\n * @fires SimpleStore#afterDestroy\n * @fires SimpleStore#remove\n * @method SimpleStore#destroy\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {(string|number)} id Passed to {@link Mapper#destroy}.\n * @param {object} [opts] Passed to {@link Mapper#destroy}. See\n * {@link Mapper#destroy} for more configuration options.\n * @returns {Promise} Resolves when the destroy operation completes.\n * @since 3.0.0\n */\n destroy (name, id, opts: any = {}) {\n return super.destroy(name, id, opts).then(result => {\n const record = this.getCollection(name).remove(id, opts)\n\n if (opts.raw) {\n result.data = record\n } else {\n result = record\n }\n delete this._pendingQueries[name][id]\n delete this._completedQueries[name][id]\n return result\n })\n }\n\n /**\n * Fired during {@link SimpleStore#destroyAll}. See\n * {@link SimpleStore~beforeDestroyAllListener} for how to listen for this event.\n *\n * @event SimpleStore#beforeDestroyAll\n * @see SimpleStore~beforeDestroyAllListener\n * @see SimpleStore#destroyAll\n */\n /**\n * Callback signature for the {@link SimpleStore#event:beforeDestroyAll} event.\n *\n * @example\n * function onBeforeDestroyAll (mapperName, query, opts) {\n * // do something\n * }\n * store.on('beforeDestroyAll', onBeforeDestroyAll);\n *\n * @callback SimpleStore~beforeDestroyAllListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeDestroyAll}.\n * @param {object} query The `query` argument received by {@link Mapper#beforeDestroyAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeDestroyAll}.\n * @see SimpleStore#event:beforeDestroyAll\n * @see SimpleStore#destroyAll\n * @since 3.0.0\n */\n /**\n * Fired during {@link SimpleStore#destroyAll}. See\n * {@link SimpleStore~afterDestroyAllListener} for how to listen for this event.\n *\n * @event SimpleStore#afterDestroyAll\n * @see SimpleStore~afterDestroyAllListener\n * @see SimpleStore#destroyAll\n */\n\n /**\n * Callback signature for the {@link SimpleStore#event:afterDestroyAll} event.\n *\n * @example\n * function onAfterDestroyAll (mapperName, query, opts, result) {\n * // do something\n * }\n * store.on('afterDestroyAll', onAfterDestroyAll);\n *\n * @callback SimpleStore~afterDestroyAllListener\n * @param {string} name The `name` argument received by {@link Mapper#afterDestroyAll}.\n * @param {object} query The `query` argument received by {@link Mapper#afterDestroyAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterDestroyAll}.\n * @param {object} result The `result` argument received by {@link Mapper#afterDestroyAll}.\n * @see SimpleStore#event:afterDestroyAll\n * @see SimpleStore#destroyAll\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#destroyAll}. Removes any destroyed records from\n * the in-memory store.\n *\n * @example\n * import { SimpleStore } from 'js-data';\n * import { HttpAdapter } from 'js-data-http';\n *\n * const store = new SimpleStore();\n * store.registerAdapter('http', new HttpAdapter(), { default: true });\n *\n * store.defineMapper('book');\n *\n * store.add('book', { id: 1234, title: 'Data Management is Hard' });\n *\n * // Since this example uses the http adapter, we'll get something like:\n * //\n * // DELETE /book/1234\n * store.destroy('book', 1234).then(() => {\n * // The book record is gone from the in-memory store\n * console.log(store.get('book', 1234)); // undefined\n * return store.find('book', 1234);\n * }).then((book) {\n * // The book was deleted from the database too\n * console.log(book); // undefined\n * });\n *\n * @fires SimpleStore#beforeDestroyAll\n * @fires SimpleStore#afterDestroyAll\n * @fires SimpleStore#remove\n * @method SimpleStore#destroyAll\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {object} [query] Passed to {@link Mapper#destroyAll}.\n * @param {object} [opts] Passed to {@link Mapper#destroyAll}. See\n * {@link Mapper#destroyAll} for more configuration options.\n * @returns {Promise} Resolves when the delete completes.\n * @since 3.0.0\n */\n destroyAll (name, query, opts: any = {}) {\n return super.destroyAll(name, query, opts).then(result => {\n const records = this.getCollection(name).removeAll(query, opts)\n\n if (opts.raw) {\n result.data = records\n } else {\n result = records\n }\n const hash = this.hashQuery(name, query, opts)\n delete this._pendingQueries[name][hash]\n delete this._completedQueries[name][hash]\n return result\n })\n }\n\n eject (name, id, opts) {\n console.warn('DEPRECATED: \"eject\" is deprecated, use \"remove\" instead')\n return this.remove(name, id, opts)\n }\n\n ejectAll (name, query, opts) {\n console.warn('DEPRECATED: \"ejectAll\" is deprecated, use \"removeAll\" instead')\n return this.removeAll(name, query, opts)\n }\n\n /**\n * Fired during {@link SimpleStore#find}. See\n * {@link SimpleStore~beforeFindListener} for how to listen for this event.\n *\n * @event SimpleStore#beforeFind\n * @see SimpleStore~beforeFindListener\n * @see SimpleStore#find\n */\n /**\n * Callback signature for the {@link SimpleStore#event:beforeFind} event.\n *\n * @example\n * function onBeforeFind (mapperName, id, opts) {\n * // do something\n * }\n * store.on('beforeFind', onBeforeFind);\n *\n * @callback SimpleStore~beforeFindListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeFind}.\n * @param {string|number} id The `id` argument received by {@link Mapper#beforeFind}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeFind}.\n * @see SimpleStore#event:beforeFind\n * @see SimpleStore#find\n * @since 3.0.0\n */\n /**\n * Fired during {@link SimpleStore#find}. See\n * {@link SimpleStore~afterFindListener} for how to listen for this event.\n *\n * @event SimpleStore#afterFind\n * @see SimpleStore~afterFindListener\n * @see SimpleStore#find\n */\n\n /**\n * Callback signature for the {@link SimpleStore#event:afterFind} event.\n *\n * @example\n * function onAfterFind (mapperName, id, opts, result) {\n * // do something\n * }\n * store.on('afterFind', onAfterFind);\n *\n * @callback SimpleStore~afterFindListener\n * @param {string} name The `name` argument received by {@link Mapper#afterFind}.\n * @param {string|number} id The `id` argument received by {@link Mapper#afterFind}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterFind}.\n * @param {object} result The `result` argument received by {@link Mapper#afterFind}.\n * @see SimpleStore#event:afterFind\n * @see SimpleStore#find\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#find}. Adds any found record to the store.\n *\n * @example\n * import { SimpleStore } from 'js-data';\n * import { HttpAdapter } from 'js-data-http';\n *\n * const store = new SimpleStore();\n * store.registerAdapter('http', new HttpAdapter(), { default: true });\n *\n * store.defineMapper('book');\n *\n * // Since this example uses the http adapter, we'll get something like:\n * //\n * // GET /book/1234\n * store.find('book', 1234).then((book) => {\n * // The book record is now in the in-memory store\n * console.log(store.get('book', 1234) === book); // true\n * });\n *\n * @fires SimpleStore#beforeFind\n * @fires SimpleStore#afterFind\n * @fires SimpleStore#add\n * @method SimpleStore#find\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {(string|number)} id Passed to {@link Mapper#find}.\n * @param {object} [opts] Passed to {@link Mapper#find}.\n * @param {boolean} [opts.force] Bypass cacheFind\n * @param {boolean|Function} [opts.usePendingFind] See {@link SimpleStore#usePendingFind}\n * @returns {Promise} Resolves with the result, if any.\n * @since 3.0.0\n */\n find (name, id, opts: any = {}) {\n const mapper = this.getMapper(name)\n const pendingQuery = this._pendingQueries[name][id]\n const usePendingFind = opts.usePendingFind === undefined ? this.usePendingFind : opts.usePendingFind\n utils._(opts, mapper)\n\n if (\n pendingQuery &&\n (utils.isFunction(usePendingFind) ? usePendingFind.call(this, name, id, opts) : usePendingFind)\n ) {\n return pendingQuery\n }\n const item = this.cachedFind(name, id, opts)\n\n if (opts.force || !item) {\n const promise = (this._pendingQueries[name][id] = super.find(name, id, opts))\n return promise.then(\n result => {\n delete this._pendingQueries[name][id]\n result = this._end(name, result, opts)\n this.cacheFind(name, result, id, opts)\n return result\n },\n err => {\n delete this._pendingQueries[name][id]\n return utils.reject(err)\n }\n )\n }\n\n return utils.resolve(item)\n }\n\n /**\n * Fired during {@link SimpleStore#findAll}. See\n * {@link SimpleStore~beforeFindAllListener} for how to listen for this event.\n *\n * @event SimpleStore#beforeFindAll\n * @see SimpleStore~beforeFindAllListener\n * @see SimpleStore#findAll\n */\n /**\n * Callback signature for the {@link SimpleStore#event:beforeFindAll} event.\n *\n * @example\n * function onBeforeFindAll (mapperName, query, opts) {\n * // do something\n * }\n * store.on('beforeFindAll', onBeforeFindAll);\n *\n * @callback SimpleStore~beforeFindAllListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeFindAll}.\n * @param {object} query The `query` argument received by {@link Mapper#beforeFindAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeFindAll}.\n * @see SimpleStore#event:beforeFindAll\n * @see SimpleStore#findAll\n * @since 3.0.0\n */\n /**\n * Fired during {@link SimpleStore#findAll}. See\n * {@link SimpleStore~afterFindAllListener} for how to listen for this event.\n *\n * @event SimpleStore#afterFindAll\n * @see SimpleStore~afterFindAllListener\n * @see SimpleStore#findAll\n */\n\n /**\n * Callback signature for the {@link SimpleStore#event:afterFindAll} event.\n *\n * @example\n * function onAfterFindAll (mapperName, query, opts, result) {\n * // do something\n * }\n * store.on('afterFindAll', onAfterFindAll);\n *\n * @callback SimpleStore~afterFindAllListener\n * @param {string} name The `name` argument received by {@link Mapper#afterFindAll}.\n * @param {object} query The `query` argument received by {@link Mapper#afterFindAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterFindAll}.\n * @param {object} result The `result` argument received by {@link Mapper#afterFindAll}.\n * @see SimpleStore#event:afterFindAll\n * @see SimpleStore#findAll\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#findAll}. Adds any found records to the store.\n *\n * @example\n * import { SimpleStore } from 'js-data';\n * import { HttpAdapter } from 'js-data-http';\n *\n * const store = new SimpleStore();\n * store.registerAdapter('http', new HttpAdapter(), { default: true });\n *\n * store.defineMapper('movie');\n *\n * // Since this example uses the http adapter, we'll get something like:\n * //\n * // GET /movie?rating=PG\n * store.find('movie', { rating: 'PG' }).then((movies) => {\n * // The movie records are now in the in-memory store\n * console.log(store.filter('movie'));\n * });\n *\n * @fires SimpleStore#beforeFindAll\n * @fires SimpleStore#afterFindAll\n * @fires SimpleStore#add\n * @method SimpleStore#findAll\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {object} [query] Passed to {@link Mapper.findAll}.\n * @param {object} [opts] Passed to {@link Mapper.findAll}.\n * @param {boolean} [opts.force] Bypass cacheFindAll\n * @param {boolean|Function} [opts.usePendingFindAll] See {@link SimpleStore#usePendingFindAll}\n * @returns {Promise} Resolves with the result, if any.\n * @since 3.0.0\n */\n findAll (name, query, opts: any = {}) {\n const mapper = this.getMapper(name)\n const hash = this.hashQuery(name, query, opts)\n const pendingQuery = this._pendingQueries[name][hash]\n const usePendingFindAll = opts.usePendingFindAll === undefined ? this.usePendingFindAll : opts.usePendingFindAll\n utils._(opts, mapper)\n\n if (\n pendingQuery &&\n (utils.isFunction(usePendingFindAll) ? usePendingFindAll.call(this, name, query, opts) : usePendingFindAll)\n ) {\n return pendingQuery\n }\n\n const items = this.cachedFindAll(name, hash, opts)\n\n if (opts.force || !items) {\n const promise = (this._pendingQueries[name][hash] = super.findAll(name, query, opts))\n return promise.then(\n result => {\n delete this._pendingQueries[name][hash]\n result = this._end(name, result, opts)\n this.cacheFindAll(name, result, hash, opts)\n return result\n },\n err => {\n delete this._pendingQueries[name][hash]\n return utils.reject(err)\n }\n )\n }\n\n return utils.resolve(items)\n }\n\n /**\n * Return the {@link Collection} with the given name, if for some\n * reason you need a direct reference to the collection.\n *\n * @param {string} name Name of the {@link Collection} to retrieve.\n * @since 3.0.0\n * @throws {Error} Thrown if the specified {@link Collection} does not\n * exist.\n */\n getCollection (name): Collection {\n const collection = this._collections[name]\n if (!collection) {\n throw utils.err(`${DOMAIN}#getCollection`, name)(404, 'collection')\n }\n return collection\n }\n\n /**\n * Hashing function used to cache {@link SimpleStore#find} and\n * {@link SimpleStore#findAll} requests. This method simply JSONifies the\n * `query` argument passed to {@link SimpleStore#find} or\n * {@link SimpleStore#findAll}.\n *\n * Override this method for custom hashing behavior.\n * @method SimpleStore#hashQuery\n * @param {string} name The `name` argument passed to {@link SimpleStore#find}\n * or {@link SimpleStore#findAll}.\n * @param {object} query The `query` argument passed to {@link SimpleStore#find}\n * or {@link SimpleStore#findAll}.\n * @returns {string} The JSONified `query`.\n * @since 3.0.0\n */\n hashQuery (name, query, opts) {\n return utils.toJson(query || {})\n }\n\n inject (name, records, opts) {\n console.warn('DEPRECATED: \"inject\" is deprecated, use \"add\" instead')\n return this.add(name, records, opts)\n }\n\n /**\n * Wrapper for {@link Collection#remove}. Removes the specified\n * {@link Record} from the store.\n *\n * @example SimpleStore#remove\n * const JSData = require('js-data');\n * const { SimpleStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new SimpleStore();\n * store.defineMapper('book');\n * console.log(store.getAll('book').length);\n * store.add('book', { id: 1234 });\n * console.log(store.getAll('book').length);\n * store.remove('book', 1234);\n * console.log(store.getAll('book').length);\n *\n * @fires SimpleStore#remove\n * @method SimpleStore#remove\n * @param {string} name The name of the {@link Collection} to target.\n * @param {string|number} id The primary key of the {@link Record} to remove.\n * @param {object} [opts] Configuration options.\n * @param {string[]} [opts.with] Relations of the {@link Record} to also\n * remove from the store.\n * @returns {Record} The removed {@link Record}, if any.\n * @see Collection#add\n * @see Collection#add\n * @since 3.0.0\n */\n remove (name, id, opts?) {\n const record = this.getCollection(name).remove(id, opts)\n if (record) {\n this.removeRelated(name, [record], opts)\n }\n return record\n }\n\n /**\n * Wrapper for {@link Collection#removeAll}. Removes the selected\n * {@link Record}s from the store.\n *\n * @example SimpleStore#removeAll\n * const JSData = require('js-data');\n * const { SimpleStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new SimpleStore();\n * store.defineMapper('movie');\n * console.log(store.getAll('movie').length);\n * store.add('movie', [{ id: 3, rating: 'R' }, { id: 4, rating: 'PG-13' });\n * console.log(store.getAll('movie').length);\n * store.removeAll('movie', { rating: 'R' });\n * console.log(store.getAll('movie').length);\n *\n * @fires SimpleStore#remove\n * @method SimpleStore#removeAll\n * @param {string} name The name of the {@link Collection} to target.\n * @param {object} [query={}] Selection query. See {@link query}.\n * @param {object} [query.where] See {@link query.where}.\n * @param {number} [query.offset] See {@link query.offset}.\n * @param {number} [query.limit] See {@link query.limit}.\n * @param {string|Array[]} [query.orderBy] See {@link query.orderBy}.\n * @param {object} [opts] Configuration options.\n * @param {string[]} [opts.with] Relations of the {@link Record} to also\n * remove from the store.\n * @returns {Record} The removed {@link Record}s, if any.\n * @see Collection#add\n * @see Collection#add\n * @since 3.0.0\n */\n removeAll (name, query, opts) {\n if (!query || !Object.keys(query).length) {\n this._completedQueries[name] = {}\n } else {\n this._completedQueries[name][this.hashQuery(name, query, opts)] = undefined\n }\n const records = this.getCollection(name).removeAll(query, opts)\n if (records.length) {\n this.removeRelated(name, records, opts)\n }\n return records\n }\n\n /**\n * Remove from the store {@link Record}s that are related to the provided\n * {@link Record}(s).\n *\n * @fires SimpleStore#remove\n * @method SimpleStore#removeRelated\n * @param {string} name The name of the {@link Collection} to target.\n * @param {Record|Record[]} records {@link Record}s whose relations are to be\n * removed.\n * @param {object} [opts] Configuration options.\n * @param {string[]} [opts.with] Relations of the {@link Record}(s) to remove\n * from the store.\n * @since 3.0.0\n */\n removeRelated (name, records, opts) {\n if (!utils.isArray(records)) {\n records = [records]\n }\n utils.forEachRelation(this.getMapper(name), opts, (def, optsCopy) => {\n records.forEach(record => {\n let relatedData\n let query\n if (def.foreignKey && (def.type === hasOneType || def.type === hasManyType)) {\n query = { [def.foreignKey]: def.getForeignKey(record) }\n } else if (def.type === hasManyType && def.localKeys) {\n query = {\n where: {\n [def.getRelation().idAttribute]: {\n in: utils.get(record, def.localKeys)\n }\n }\n }\n } else if (def.type === hasManyType && def.foreignKeys) {\n query = {\n where: {\n [def.foreignKeys]: {\n contains: def.getForeignKey(record)\n }\n }\n }\n } else if (def.type === belongsToType) {\n relatedData = this.remove(def.relation, def.getForeignKey(record), optsCopy)\n }\n if (query) {\n relatedData = this.removeAll(def.relation, query, optsCopy)\n }\n if (relatedData) {\n if (utils.isArray(relatedData) && !relatedData.length) {\n return\n }\n if (def.type === hasOneType) {\n relatedData = relatedData[0]\n }\n def.setLocalField(record, relatedData)\n }\n })\n })\n }\n\n /**\n * Fired during {@link SimpleStore#update}. See\n * {@link SimpleStore~beforeUpdateListener} for how to listen for this event.\n *\n * @event SimpleStore#beforeUpdate\n * @see SimpleStore~beforeUpdateListener\n * @see SimpleStore#update\n */\n /**\n * Callback signature for the {@link SimpleStore#event:beforeUpdate} event.\n *\n * @example\n * function onBeforeUpdate (mapperName, id, props, opts) {\n * // do something\n * }\n * store.on('beforeUpdate', onBeforeUpdate);\n *\n * @callback SimpleStore~beforeUpdateListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeUpdate}.\n * @param {string|number} id The `id` argument received by {@link Mapper#beforeUpdate}.\n * @param {object} props The `props` argument received by {@link Mapper#beforeUpdate}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdate}.\n * @see SimpleStore#event:beforeUpdate\n * @see SimpleStore#update\n * @since 3.0.0\n */\n /**\n * Fired during {@link SimpleStore#update}. See\n * {@link SimpleStore~afterUpdateListener} for how to listen for this event.\n *\n * @event SimpleStore#afterUpdate\n * @see SimpleStore~afterUpdateListener\n * @see SimpleStore#update\n */\n\n /**\n * Callback signature for the {@link SimpleStore#event:afterUpdate} event.\n *\n * @example\n * function onAfterUpdate (mapperName, id, props, opts, result) {\n * // do something\n * }\n * store.on('afterUpdate', onAfterUpdate);\n *\n * @callback SimpleStore~afterUpdateListener\n * @param {string} name The `name` argument received by {@link Mapper#afterUpdate}.\n * @param {string|number} id The `id` argument received by {@link Mapper#afterUpdate}.\n * @param {object} props The `props` argument received by {@link Mapper#afterUpdate}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdate}.\n * @param {object} result The `result` argument received by {@link Mapper#afterUpdate}.\n * @see SimpleStore#event:afterUpdate\n * @see SimpleStore#update\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#update}. Adds the updated {@link Record} to the\n * store.\n *\n * @example\n * import { SimpleStore } from 'js-data';\n * import { HttpAdapter } from 'js-data-http';\n *\n * const store = new SimpleStore();\n * store.registerAdapter('http', new HttpAdapter(), { default: true });\n *\n * store.defineMapper('post');\n *\n * // Since this example uses the http adapter, we'll get something like:\n * //\n * // PUT /post/1234 {\"status\":\"published\"}\n * store.update('post', 1, { status: 'published' }).then((post) => {\n * // The post record has also been updated in the in-memory store\n * console.log(store.get('post', 1234));\n * });\n *\n * @fires SimpleStore#beforeUpdate\n * @fires SimpleStore#afterUpdate\n * @fires SimpleStore#add\n * @method SimpleStore#update\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {(string|number)} id Passed to {@link Mapper#update}.\n * @param {object} record Passed to {@link Mapper#update}.\n * @param {object} [opts] Passed to {@link Mapper#update}. See\n * {@link Mapper#update} for more configuration options.\n * @returns {Promise} Resolves with the result of the update.\n * @since 3.0.0\n */\n update (name, id, record, opts: any = {}) {\n return super.update(name, id, record, opts).then(result => this._end(name, result, opts))\n }\n\n /**\n * Fired during {@link SimpleStore#updateAll}. See\n * {@link SimpleStore~beforeUpdateAllListener} for how to listen for this event.\n *\n * @event SimpleStore#beforeUpdateAll\n * @see SimpleStore~beforeUpdateAllListener\n * @see SimpleStore#updateAll\n */\n /**\n * Callback signature for the {@link SimpleStore#event:beforeUpdateAll} event.\n *\n * @example\n * function onBeforeUpdateAll (mapperName, props, query, opts) {\n * // do something\n * }\n * store.on('beforeUpdateAll', onBeforeUpdateAll);\n *\n * @callback SimpleStore~beforeUpdateAllListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeUpdateAll}.\n * @param {object} props The `props` argument received by {@link Mapper#beforeUpdateAll}.\n * @param {object} query The `query` argument received by {@link Mapper#beforeUpdateAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdateAll}.\n * @see SimpleStore#event:beforeUpdateAll\n * @see SimpleStore#updateAll\n * @since 3.0.0\n */\n /**\n * Fired during {@link SimpleStore#updateAll}. See\n * {@link SimpleStore~afterUpdateAllListener} for how to listen for this event.\n *\n * @event SimpleStore#afterUpdateAll\n * @see SimpleStore~afterUpdateAllListener\n * @see SimpleStore#updateAll\n */\n\n /**\n * Callback signature for the {@link SimpleStore#event:afterUpdateAll} event.\n *\n * @example\n * function onAfterUpdateAll (mapperName, props, query, opts, result) {\n * // do something\n * }\n * store.on('afterUpdateAll', onAfterUpdateAll);\n *\n * @callback SimpleStore~afterUpdateAllListener\n * @param {string} name The `name` argument received by {@link Mapper#afterUpdateAll}.\n * @param {object} props The `props` argument received by {@link Mapper#afterUpdateAll}.\n * @param {object} query The `query` argument received by {@link Mapper#afterUpdateAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdateAll}.\n * @param {object} result The `result` argument received by {@link Mapper#afterUpdateAll}.\n * @see SimpleStore#event:afterUpdateAll\n * @see SimpleStore#updateAll\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#updateAll}. Adds the updated {@link Record}s to\n * the store.\n *\n * @example\n * import { SimpleStore } from 'js-data';\n * import { HttpAdapter } from 'js-data-http';\n *\n * const store = new SimpleStore();\n * store.registerAdapter('http', new HttpAdapter(), { default: true });\n *\n * store.defineMapper('post');\n *\n * // Since this example uses the http adapter, we'll get something like:\n * //\n * // PUT /post?author_id=1234 {\"status\":\"published\"}\n * store.updateAll('post', { author_id: 1234 }, { status: 'published' }).then((posts) => {\n * // The post records have also been updated in the in-memory store\n * console.log(store.filter('posts', { author_id: 1234 }));\n * });\n *\n * @fires SimpleStore#beforeUpdateAll\n * @fires SimpleStore#afterUpdateAll\n * @fires SimpleStore#add\n * @method SimpleStore#updateAll\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {object} props Passed to {@link Mapper#updateAll}.\n * @param {object} [query] Passed to {@link Mapper#updateAll}.\n * @param {object} [opts] Passed to {@link Mapper#updateAll}. See\n * {@link Mapper#updateAll} for more configuration options.\n * @returns {Promise} Resolves with the result of the update.\n * @since 3.0.0\n */\n updateAll (name, props, query, opts: any = {}) {\n return super.updateAll(name, props, query, opts).then(result => this._end(name, result, opts))\n }\n\n /**\n * Fired during {@link SimpleStore#updateMany}. See\n * {@link SimpleStore~beforeUpdateManyListener} for how to listen for this event.\n *\n * @event SimpleStore#beforeUpdateMany\n * @see SimpleStore~beforeUpdateManyListener\n * @see SimpleStore#updateMany\n */\n /**\n * Callback signature for the {@link SimpleStore#event:beforeUpdateMany} event.\n *\n * @example\n * function onBeforeUpdateMany (mapperName, records, opts) {\n * // do something\n * }\n * store.on('beforeUpdateMany', onBeforeUpdateMany);\n *\n * @callback SimpleStore~beforeUpdateManyListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeUpdateMany}.\n * @param {object} records The `records` argument received by {@link Mapper#beforeUpdateMany}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdateMany}.\n * @see SimpleStore#event:beforeUpdateMany\n * @see SimpleStore#updateMany\n * @since 3.0.0\n */\n /**\n * Fired during {@link SimpleStore#updateMany}. See\n * {@link SimpleStore~afterUpdateManyListener} for how to listen for this event.\n *\n * @event SimpleStore#afterUpdateMany\n * @see SimpleStore~afterUpdateManyListener\n * @see SimpleStore#updateMany\n */\n\n /**\n * Callback signature for the {@link SimpleStore#event:afterUpdateMany} event.\n *\n * @example\n * function onAfterUpdateMany (mapperName, records, opts, result) {\n * // do something\n * }\n * store.on('afterUpdateMany', onAfterUpdateMany);\n *\n * @callback SimpleStore~afterUpdateManyListener\n * @param {string} name The `name` argument received by {@link Mapper#afterUpdateMany}.\n * @param {object} records The `records` argument received by {@link Mapper#afterUpdateMany}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdateMany}.\n * @param {object} result The `result` argument received by {@link Mapper#afterUpdateMany}.\n * @see SimpleStore#event:afterUpdateMany\n * @see SimpleStore#updateMany\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#updateMany}. Adds the updated {@link Record}s to\n * the store.\n *\n * @example\n * import { SimpleStore } from 'js-data';\n * import { HttpAdapter } from 'js-data-http';\n *\n * const store = new SimpleStore();\n * store.registerAdapter('http', new HttpAdapter(), { default: true });\n *\n * store.defineMapper('post');\n *\n * // Since this example uses the http adapter, we'll get something like:\n * //\n * // PUT /post [{\"id\":3,status\":\"published\"},{\"id\":4,status\":\"published\"}]\n * store.updateMany('post', [\n * { id: 3, status: 'published' },\n * { id: 4, status: 'published' }\n * ]).then((posts) => {\n * // The post records have also been updated in the in-memory store\n * console.log(store.getAll('post', 3, 4));\n * });\n *\n * @fires SimpleStore#beforeUpdateMany\n * @fires SimpleStore#afterUpdateMany\n * @fires SimpleStore#add\n * @method SimpleStore#updateMany\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {(Object[]|Record[])} records Passed to {@link Mapper#updateMany}.\n * @param {object} [opts] Passed to {@link Mapper#updateMany}. See\n * {@link Mapper#updateMany} for more configuration options.\n * @returns {Promise} Resolves with the result of the update.\n * @since 3.0.0\n */\n updateMany (name, records, opts: any = {}) {\n return super.updateMany(name, records, opts).then(result => this._end(name, result, opts))\n }\n\n /**\n * Wrapper for {@link Collection#add}.\n *\n * @example SimpleStore#add\n * const JSData = require('js-data');\n * const { SimpleStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new SimpleStore();\n * store.defineMapper('book');\n *\n * // Add one book to the in-memory store:\n * store.add('book', { id: 1, title: 'Respect your Data' });\n * // Add multiple books to the in-memory store:\n * store.add('book', [\n * { id: 2, title: 'Easy data recipes' },\n * { id: 3, title: 'Active Record 101' }\n * ]);\n *\n * @fires SimpleStore#add\n * @method SimpleStore#add\n * @param {(string|number)} name Name of the {@link Mapper} to target.\n * @param {(Object|Object[]|Record|Record[])} records See {@link Collection#add}.\n * @param {object} [opts] Configuration options. See {@link Collection#add}.\n * @returns {(Object|Object[]|Record|Record[])} See {@link Collection#add}.\n * @see Collection#add\n * @see Collection#add\n * @since 3.0.0\n */\n add (name, records, opts?) {\n return this.getCollection(name).add(records, opts)\n }\n\n /**\n * Wrapper for {@link Collection#between}.\n *\n * @example\n * // Get all users ages 18 to 30\n * const users = store.between('user', 18, 30, { index: 'age' });\n *\n * @example\n * // Same as above\n * const users = store.between('user', [18], [30], { index: 'age' });\n *\n * @method SimpleStore#between\n * @param {(string|number)} name Name of the {@link Mapper} to target.\n * @param {array} leftKeys See {@link Collection#between}.\n * @param {array} rightKeys See {@link Collection#between}.\n * @param {object} [opts] Configuration options. See {@link Collection#between}.\n * @returns {Object[]|Record[]} See {@link Collection#between}.\n * @see Collection#between\n * @see Collection#between\n * @since 3.0.0\n */\n between (name, leftKeys, rightKeys, opts) {\n return this.getCollection(name).between(leftKeys, rightKeys, opts)\n }\n\n /**\n * Wrapper for {@link Collection#createIndex}.\n *\n * @example\n * // Index users by age\n * store.createIndex('user', 'age');\n *\n * @example\n * // Index users by status and role\n * store.createIndex('user', 'statusAndRole', ['status', 'role']);\n *\n * @method SimpleStore#createIndex\n * @param {(string|number)} name Name of the {@link Mapper} to target.\n * @param {string} indexName See {@link Collection#createIndex}.\n * @param {string[]} [fieldList] See {@link Collection#createIndex}.\n * @param {object} [opts] Configuration options. See {@link Collection#between}.\n * @see Collection#createIndex\n * @see Collection#createIndex\n * @since 3.0.0\n */\n createIndex (name: string | number, indexName: string, fieldList?: string[], opts?) {\n return this.getCollection(name).createIndex(indexName, fieldList, opts)\n }\n\n /**\n * Wrapper for {@link Collection#filter}.\n *\n * @example SimpleStore#filter\n * const JSData = require('js-data');\n * const { SimpleStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new SimpleStore();\n * store.defineMapper('post');\n * store.add('post', [\n * { id: 1, status: 'draft', created_at_timestamp: new Date().getTime() }\n * ]);\n *\n * // Get the draft posts created less than three months ago\n * let posts = store.filter('post', {\n * where: {\n * status: {\n * '==': 'draft'\n * },\n * created_at_timestamp: {\n * '>=': (new Date().getTime() - (1000 \\* 60 \\* 60 \\* 24 \\* 30 \\* 3)) // 3 months ago\n * }\n * }\n * });\n * console.log(posts);\n *\n * // Use a custom filter function\n * posts = store.filter('post', function (post) { return post.id % 2 === 0 });\n *\n * @method SimpleStore#filter\n * @param {(string|number)} name Name of the {@link Mapper} to target.\n * @param {(Object|Function)} [queryOrFn={}] See {@link Collection#filter}.\n * @param {object} [thisArg] See {@link Collection#filter}.\n * @returns {Array} See {@link Collection#filter}.\n * @see Collection#filter\n * @see Collection#filter\n * @since 3.0.0\n */\n filter (name, queryOrFn?, thisArg?) {\n return this.getCollection(name).filter(queryOrFn, thisArg)\n }\n\n /**\n * Wrapper for {@link Collection#get}.\n *\n * @example SimpleStore#get\n * const JSData = require('js-data');\n * const { SimpleStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new SimpleStore();\n * store.defineMapper('post');\n * store.add('post', [\n * { id: 1, status: 'draft', created_at_timestamp: new Date().getTime() }\n * ]);\n *\n * console.log(store.get('post', 1)); // {...}\n * console.log(store.get('post', 2)); // undefined\n *\n * @method SimpleStore#get\n * @param {(string|number)} name Name of the {@link Mapper} to target.\n * @param {(string|number)} id See {@link Collection#get}.\n * @returns {(Object|Record)} See {@link Collection#get}.\n * @see Collection#get\n * @see Collection#get\n * @since 3.0.0\n */\n get (name, id) {\n return this.getCollection(name).get(id)\n }\n\n /**\n * Wrapper for {@link Collection#getAll}.\n *\n * @example\n * // Get the posts where \"status\" is \"draft\" or \"inReview\"\n * const posts = store.getAll('post', 'draft', 'inReview', { index: 'status' });\n *\n * @example\n * // Same as above\n * const posts = store.getAll('post', ['draft'], ['inReview'], { index: 'status' });\n *\n * @method SimpleStore#getAll\n * @param {(string|number)} name Name of the {@link Mapper} to target.\n * @param {...Array} [keyList] See {@link Collection#getAll}.\n * @param {object} [opts] See {@link Collection#getAll}.\n * @returns {Array} See {@link Collection#getAll}.\n * @see Collection#getAll\n * @see Collection#getAll\n * @since 3.0.0\n */\n getAll (name, ...args) {\n return this.getCollection(name).getAll(...args)\n }\n\n /**\n * Wrapper for {@link Collection#prune}.\n *\n * @method SimpleStore#prune\n * @param name\n * @param {object} [opts] See {@link Collection#prune}.\n * @returns {Array} See {@link Collection#prune}.\n * @see Collection#prune\n * @see Collection#prune\n * @since 3.0.0\n */\n prune (name: string, opts?) {\n return this.getCollection(name).prune(opts)\n }\n\n /**\n * Wrapper for {@link Collection#query}.\n *\n * @example\n * // Grab page 2 of users between ages 18 and 30\n * store.query('user')\n * .between(18, 30, { index: 'age' }) // between ages 18 and 30\n * .skip(10) // second page\n * .limit(10) // page size\n * .run();\n *\n * @method SimpleStore#query\n * @param {(string|number)} name Name of the {@link Mapper} to target.\n * @returns {Query} See {@link Collection#query}.\n * @see Collection#query\n * @see Collection#query\n * @since 3.0.0\n */\n query (name) {\n return this.getCollection(name).query()\n }\n\n /**\n * Wrapper for {@link Collection#toJSON}.\n *\n * @example\n * store.defineMapper('post', {\n * schema: {\n * properties: {\n * id: { type: 'number' },\n * title: { type: 'string' }\n * }\n * }\n * });\n * store.add('post', [\n * { id: 1, status: 'published', title: 'Respect your Data' },\n * { id: 2, status: 'draft', title: 'Connecting to a data source' }\n * ]);\n * console.log(store.toJSON('post'));\n * const draftsJSON = store.query('post')\n * .filter({ status: 'draft' })\n * .mapCall('toJSON')\n * .run();\n *\n * @method SimpleStore#toJSON\n * @param {(string|number)} name Name of the {@link Mapper} to target.\n * @param {object} [opts] See {@link Collection#toJSON}.\n * @returns {Array} See {@link Collection#toJSON}.\n * @see Collection#toJSON\n * @see Collection#toJSON\n * @since 3.0.0\n */\n toJSON (name, opts) {\n return this.getCollection(name).toJSON(opts)\n }\n\n /**\n * Wrapper for {@link Collection#unsaved}.\n *\n * @method SimpleStore#unsaved\n * @returns {Array} See {@link Collection#unsaved}.\n * @see Collection#unsaved\n * @see Collection#unsaved\n * @since 3.0.0\n */\n unsaved (name, opts?) {\n return this.getCollection(name).unsaved(opts)\n }\n}\n\n/**\n * Fired when a record changes. Only works for records that have tracked fields.\n * See {@link SimpleStore~changeListener} on how to listen for this event.\n *\n * @event SimpleStore#change\n * @see SimpleStore~changeListener\n */\n\n/**\n * Callback signature for the {@link SimpleStore#event:change} event.\n *\n * @example\n * function onChange (mapperName, record, changes) {\n * // do something\n * }\n * store.on('change', onChange);\n *\n * @callback SimpleStore~changeListener\n * @param {string} name The name of the associated {@link Mapper}.\n * @param {Record} record The Record that changed.\n * @param {object} changes The changes.\n * @see SimpleStore#event:change\n * @since 3.0.0\n */\n\n/**\n * Fired when one or more records are added to the in-memory store. See\n * {@link SimpleStore~addListener} on how to listen for this event.\n *\n * @event SimpleStore#add\n * @see SimpleStore~addListener\n * @see SimpleStore#event:add\n * @see SimpleStore#add\n * @see SimpleStore#create\n * @see SimpleStore#createMany\n * @see SimpleStore#find\n * @see SimpleStore#findAll\n * @see SimpleStore#update\n * @see SimpleStore#updateAll\n * @see SimpleStore#updateMany\n */\n\n/**\n * Callback signature for the {@link SimpleStore#event:add} event.\n *\n * @example\n * function onAdd (mapperName, recordOrRecords) {\n * // do something\n * }\n * store.on('add', onAdd);\n *\n * @callback SimpleStore~addListener\n * @param {string} name The name of the associated {@link Mapper}.\n * @param {Record|Record[]} The Record or Records that were added.\n * @see SimpleStore#event:add\n * @see SimpleStore#add\n * @see SimpleStore#create\n * @see SimpleStore#createMany\n * @see SimpleStore#find\n * @see SimpleStore#findAll\n * @see SimpleStore#update\n * @see SimpleStore#updateAll\n * @see SimpleStore#updateMany\n * @since 3.0.0\n */\n\n/**\n * Fired when one or more records are removed from the in-memory store. See\n * {@link SimpleStore~removeListener} for how to listen for this event.\n *\n * @event SimpleStore#remove\n * @see SimpleStore~removeListener\n * @see SimpleStore#event:remove\n * @see SimpleStore#clear\n * @see SimpleStore#destroy\n * @see SimpleStore#destroyAll\n * @see SimpleStore#remove\n * @see SimpleStore#removeAll\n */\n\n/**\n * Callback signature for the {@link SimpleStore#event:remove} event.\n *\n * @example\n * function onRemove (mapperName, recordsOrRecords) {\n * // do something\n * }\n * store.on('remove', onRemove);\n *\n * @callback SimpleStore~removeListener\n * @param {string} name The name of the associated {@link Mapper}.\n * @param {Record|Record[]} Record or Records that were removed.\n * @see SimpleStore#event:remove\n * @see SimpleStore#clear\n * @see SimpleStore#destroy\n * @see SimpleStore#destroyAll\n * @see SimpleStore#remove\n * @see SimpleStore#removeAll\n * @since 3.0.0\n */\n\n/**\n * Create a subclass of this SimpleStore:\n * @example SimpleStore.extend\n * const JSData = require('js-data');\n * const { SimpleStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * // Extend the class using ES2015 class syntax.\n * class CustomSimpleStoreClass extends SimpleStore {\n * foo () { return 'bar'; }\n * static beep () { return 'boop'; }\n * }\n * const customSimpleStore = new CustomSimpleStoreClass();\n * console.log(customSimpleStore.foo());\n * console.log(CustomSimpleStoreClass.beep());\n *\n * // Extend the class using alternate method.\n * const OtherSimpleStoreClass = SimpleStore.extend({\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * })\n * const otherSimpleStore = new OtherSimpleStoreClass();\n * console.log(otherSimpleStore.foo());\n * console.log(OtherSimpleStoreClass.beep());\n *\n * // Extend the class, providing a custom constructor.\n * function AnotherSimpleStoreClass () {\n * SimpleStore.call(this)\n * this.created_at = new Date().getTime()\n * }\n * SimpleStore.extend({\n * constructor: AnotherSimpleStoreClass,\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * })\n * const anotherSimpleStore = new AnotherSimpleStoreClass();\n * console.log(anotherSimpleStore.created_at);\n * console.log(anotherSimpleStore.foo());\n * console.log(AnotherSimpleStoreClass.beep());\n *\n * @method SimpleStore.extend\n * @param {object} [props={}] Properties to add to the prototype of the\n * subclass.\n * @param {object} [props.constructor] Provide a custom constructor function\n * to be used as the subclass itself.\n * @param {object} [classProps={}] Static properties to add to the subclass.\n * @returns {Constructor} Subclass of this SimpleStore class.\n * @since 3.0.0\n */\n","import utils from './utils'\nimport './decorators'\nimport Collection from './Collection'\n\nconst DOMAIN = 'LinkedCollection'\n\n/**\n * Extends {@link Collection}. Used by a {@link DataStore} to implement an\n * Identity Map.\n *\n * @example\n * import {LinkedCollection} from 'js-data';\n *\n * // Extend the class using ES2015 class syntax.\n * class CustomLinkedCollectionClass extends LinkedCollection {\n * foo () { return 'bar'; }\n * static beep () { return 'boop'; }\n * }\n * const customLinkedCollection = new CustomLinkedCollectionClass();\n * console.log(customLinkedCollection.foo());\n * console.log(CustomLinkedCollectionClass.beep());\n *\n * @class LinkedCollection\n * @extends Collection\n * @param {array} [records] Initial set of records to insert into the\n * collection. See {@link Collection}.\n * @param {object} [opts] Configuration options. See {@link Collection}.\n * @returns {Mapper}\n */\nexport default class LinkedCollection extends Collection {\n datastore: any;\n\n constructor (records, opts) {\n super(records, opts)\n\n // Make sure this collection has a reference to a datastore\n if (!this.datastore) {\n throw utils.err(`new ${DOMAIN}`, 'opts.datastore')(400, 'DataStore', this.datastore)\n }\n }\n\n _addMeta (record, timestamp) {\n // Track when this record was added\n this._added[this.recordId(record)] = timestamp\n\n if (utils.isFunction(record._set)) {\n record._set('$', timestamp)\n }\n }\n\n _clearMeta (record) {\n delete this._added[this.recordId(record)]\n if (utils.isFunction(record._set)) {\n record._set('$') // unset\n }\n }\n\n _onRecordEvent (...args) {\n Collection.prototype._onRecordEvent.apply(this, args)\n const event = args[0]\n // This is a very brute force method\n // Lots of room for optimization\n if (utils.isString(event) && event.indexOf('change') === 0) {\n this.updateIndexes(args[1])\n }\n }\n\n add (records, opts) {\n const mapper = this.mapper\n const timestamp = new Date().getTime()\n const singular = utils.isObject(records) && !utils.isArray(records)\n\n if (singular) {\n records = [records]\n }\n records = super.add(records, opts)\n\n if (mapper.relationList.length && records.length) {\n // Check the currently visited record for relations that need to be\n // inserted into their respective collections.\n mapper.relationList.forEach(def => {\n def.addLinkedRecords(records)\n })\n }\n\n records.forEach(record => this._addMeta(record, timestamp))\n\n return singular ? records[0] : records\n }\n\n remove (idOrRecord, opts) {\n const mapper = this.mapper\n const record = super.remove(idOrRecord, opts)\n if (record) {\n this._clearMeta(record)\n }\n\n if (mapper.relationList.length && record) {\n mapper.relationList.forEach(def => {\n def.removeLinkedRecords(mapper, [record])\n })\n }\n\n return record\n }\n\n removeAll (query, opts) {\n const mapper = this.mapper\n const records = super.removeAll(query, opts)\n records.forEach(this._clearMeta, this)\n\n if (mapper.relationList.length && records.length) {\n mapper.relationList.forEach(def => {\n def.removeLinkedRecords(mapper, records)\n })\n }\n\n return records\n }\n}\n\n/**\n * Create a subclass of this LinkedCollection:\n *\n * // Extend the class using alternate method.\n * const OtherLinkedCollectionClass = LinkedCollection.extend({\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * });\n * const otherLinkedCollection = new OtherLinkedCollectionClass();\n * console.log(otherLinkedCollection.foo());\n * console.log(OtherLinkedCollectionClass.beep());\n *\n * // Extend the class, providing a custom constructor.\n * function AnotherLinkedCollectionClass () {\n * LinkedCollection.call(this);\n * this.created_at = new Date().getTime();\n * }\n * LinkedCollection.extend({\n * constructor: AnotherLinkedCollectionClass,\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * });\n * const anotherLinkedCollection = new AnotherLinkedCollectionClass();\n * console.log(anotherLinkedCollection.created_at);\n * console.log(anotherLinkedCollection.foo());\n * console.log(AnotherLinkedCollectionClass.beep());\n *\n * @method LinkedCollection.extend\n * @param {object} [props={}] Properties to add to the prototype of the\n * subclass.\n * @param {object} [props.constructor] Provide a custom constructor function\n * to be used as the subclass itself.\n * @param {object} [classProps={}] Static properties to add to the subclass.\n * @returns {Constructor} Subclass of this LinkedCollection class.\n * @since 3.0.0\n */\n","import utils, { safeSetLink, safeSetProp } from './utils'\n\nimport { belongsToType, hasManyType, hasOneType } from './decorators'\nimport SimpleStore, { SimpleStoreOpts } from './SimpleStore'\nimport LinkedCollection from './LinkedCollection'\nimport { MapperOpts } from './Mapper'\n\nexport interface DataStoreOpts extends SimpleStoreOpts {\n [customAttr: string]: any\n\n linkRelations?: boolean\n unlinkOnDestroy?: boolean\n collectionClass /*: typeof Collection */?\n mapperClass?\n scopes?: any\n}\n\nconst DATASTORE_DEFAULTS: DataStoreOpts = {\n /**\n * Whether in-memory relations should be unlinked from records after they are\n * destroyed.\n *\n * @default true\n * @name DataStore#unlinkOnDestroy\n * @since 3.0.0\n * @type {boolean}\n */\n unlinkOnDestroy: true,\n\n collectionClass: LinkedCollection\n}\n\n/**\n * The `DataStore` class is an extension of {@link SimpleStore}. Not only does\n * `DataStore` manage mappers and store data in collections, it uses the\n * {@link LinkedCollection} class to link related records together in memory.\n *\n * ```javascript\n * import { DataStore } from 'js-data';\n * ```\n *\n * @example\n * import { DataStore } from 'js-data';\n * import HttpAdapter from 'js-data-http';\n * const store = new DataStore();\n *\n * // DataStore#defineMapper returns a direct reference to the newly created\n * // Mapper.\n * const UserMapper = store.defineMapper('user');\n *\n * // DataStore#as returns the store scoped to a particular Mapper.\n * const UserStore = store.as('user');\n *\n * // Call \"find\" on \"UserMapper\" (Stateless ORM)\n * UserMapper.find(1).then((user) => {\n * // retrieved a \"user\" record via the http adapter, but that's it\n *\n * // Call \"find\" on \"store\" targeting \"user\" (Stateful DataStore)\n * return store.find('user', 1); // same as \"UserStore.find(1)\"\n * }).then((user) => {\n * // not only was a \"user\" record retrieved, but it was added to the\n * // store's \"user\" collection\n * const cachedUser = store.getCollection('user').get(1);\n * console.log(user === cachedUser); // true\n * });\n *\n * @class DataStore\n * @extends SimpleStore\n * @param {object} [opts] Configuration options. See {@link SimpleStore}.\n * @param {boolean} [opts.collectionClass={@link LinkedCollection}] See {@link DataStore#collectionClass}.\n * @param {boolean} [opts.debug=false] See {@link Component#debug}.\n * @param {boolean} [opts.unlinkOnDestroy=true] See {@link DataStore#unlinkOnDestroy}.\n * @param {boolean|Function} [opts.usePendingFind=true] See {@link DataStore#usePendingFind}.\n * @param {boolean|Function} [opts.usePendingFindAll=true] See {@link DataStore#usePendingFindAll}.\n * @returns {DataStore}\n * @see SimpleStore\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/components-of-jsdata#datastore\",\"Components of JSData: DataStore\"]\n * @tutorial [\"http://www.js-data.io/v3.0/docs/working-with-the-datastore\",\"Working with the DataStore\"]\n * @tutorial [\"http://www.js-data.io/v3.0/docs/jsdata-and-the-browser\",\"Notes on using JSData in the Browser\"]\n */\nexport default class DataStore extends SimpleStore {\n unlinkOnDestroy: any;\n\n constructor (opts: DataStoreOpts = {}) {\n // Fill in any missing options with the defaults\n super({ ...DATASTORE_DEFAULTS, ...opts })\n }\n\n /**\n * Creates a new [Mapper] with [name] from the [opts]\n * @param {string} name\n * @param {object} opts\n * @returns {*}\n */\n defineMapper (name, opts?: MapperOpts) {\n // Complexity of this method is beyond simply using => functions to bind context\n const self = this\n const mapper = super.defineMapper(name, opts)\n const idAttribute = mapper.idAttribute\n const collection = this.getCollection(name)\n\n mapper.relationList.forEach(def => {\n const relation = def.relation\n const localField = def.localField\n const path = `links.${localField}`\n const foreignKey = def.foreignKey\n const type = def.type\n const updateOpts = { index: foreignKey }\n let descriptor\n\n const getter = function () {\n return this._get(path)\n }\n\n if (type === belongsToType) {\n if (!collection.indexes[foreignKey]) {\n collection.createIndex(foreignKey)\n }\n\n descriptor = {\n get: getter,\n // e.g. profile.user = someUser\n // or comment.post = somePost\n set (record) {\n // e.g. const otherUser = profile.user\n const currentParent = this._get(path)\n // e.g. profile.user === someUser\n if (record === currentParent) {\n return currentParent\n }\n const id = utils.get(this, idAttribute)\n const inverseDef = def.getInverse(mapper)\n\n // e.g. profile.user !== someUser\n // or comment.post !== somePost\n if (currentParent && inverseDef) {\n this.removeInverseRelation(currentParent, id, inverseDef, idAttribute)\n }\n if (record) {\n // e.g. profile.user = someUser\n const relatedIdAttribute = def.getRelation().idAttribute\n const relatedId = utils.get(record, relatedIdAttribute)\n\n // Prefer store record\n if (relatedId !== undefined && this._get('$')) {\n record = self.get(relation, relatedId) || record\n }\n\n // Set locals\n // e.g. profile.user = someUser\n // or comment.post = somePost\n safeSetLink(this, localField, record)\n safeSetProp(this, foreignKey, relatedId)\n collection.updateIndex(this, updateOpts)\n\n if (inverseDef) {\n this.setupInverseRelation(record, id, inverseDef, idAttribute)\n }\n } else {\n // Unset in-memory link only\n // e.g. profile.user = undefined\n // or comment.post = undefined\n safeSetLink(this, localField, undefined)\n }\n return record\n }\n }\n\n let foreignKeyDescriptor = Object.getOwnPropertyDescriptor(mapper.recordClass.prototype, foreignKey)\n if (!foreignKeyDescriptor) {\n foreignKeyDescriptor = {\n enumerable: true\n }\n }\n const originalGet = foreignKeyDescriptor.get\n foreignKeyDescriptor.get = function () {\n if (originalGet) {\n return originalGet.call(this)\n }\n return this._get(`props.${foreignKey}`)\n }\n const originalSet = foreignKeyDescriptor.set\n foreignKeyDescriptor.set = function (value) {\n if (originalSet) {\n originalSet.call(this, value)\n }\n const currentParent = utils.get(this, localField)\n const id = utils.get(this, idAttribute)\n const inverseDef = def.getInverse(mapper)\n const currentParentId = currentParent ? utils.get(currentParent, def.getRelation().idAttribute) : undefined\n\n if (inverseDef && currentParent && currentParentId !== undefined && currentParentId !== value) {\n if (inverseDef.type === hasOneType) {\n safeSetLink(currentParent, inverseDef.localField, undefined)\n } else if (inverseDef.type === hasManyType) {\n const children = utils.get(currentParent, inverseDef.localField)\n if (id === undefined) {\n utils.remove(children, child => child === this)\n } else {\n utils.remove(children, child => child === this || id === utils.get(child, idAttribute))\n }\n }\n }\n\n safeSetProp(this, foreignKey, value)\n collection.updateIndex(this, updateOpts)\n\n if (value === undefined || value === null) {\n if (currentParentId !== undefined) {\n // Unset locals\n utils.set(this, localField, undefined)\n }\n } else if (this._get('$')) {\n const storeRecord = self.get(relation, value)\n if (storeRecord) {\n utils.set(this, localField, storeRecord)\n }\n }\n }\n Object.defineProperty(mapper.recordClass.prototype, foreignKey, foreignKeyDescriptor)\n } else if (type === hasManyType) {\n const localKeys = def.localKeys\n const foreignKeys = def.foreignKeys\n\n // TODO: Handle case when belongsTo relation isn't ever defined\n if (self._collections[relation] && foreignKey && !self.getCollection(relation).indexes[foreignKey]) {\n self.getCollection(relation).createIndex(foreignKey)\n }\n\n descriptor = {\n get () {\n const current = getter.call(this)\n if (!current) {\n this._set(path, [])\n }\n return getter.call(this)\n },\n // e.g. post.comments = someComments\n // or user.groups = someGroups\n // or group.users = someUsers\n set (records) {\n if (records && !utils.isArray(records)) {\n records = [records]\n }\n const id = utils.get(this, idAttribute)\n const relatedIdAttribute = def.getRelation().idAttribute\n const inverseDef = def.getInverse(mapper)\n const inverseLocalField = inverseDef.localField\n const current = this._get(path) || []\n const toLink = []\n const toLinkIds = {}\n\n if (records) {\n records.forEach(record => {\n // e.g. comment.id\n const relatedId = utils.get(record, relatedIdAttribute)\n const currentParent = utils.get(record, inverseLocalField)\n if (currentParent && currentParent !== this) {\n const currentChildrenOfParent = utils.get(currentParent, localField)\n // e.g. somePost.comments.remove(comment)\n if (relatedId === undefined) {\n utils.remove(currentChildrenOfParent, child => child === record)\n } else {\n utils.remove(\n currentChildrenOfParent,\n child => child === record || relatedId === utils.get(child, relatedIdAttribute)\n )\n }\n }\n if (relatedId !== undefined) {\n if (this._get('$')) {\n // Prefer store record\n record = self.get(relation, relatedId) || record\n }\n // e.g. toLinkIds[comment.id] = comment\n toLinkIds[relatedId] = record\n }\n toLink.push(record)\n })\n }\n\n // e.g. post.comments = someComments\n if (foreignKey) {\n current.forEach(record => {\n // e.g. comment.id\n const relatedId = utils.get(record, relatedIdAttribute)\n if (\n (relatedId === undefined && toLink.indexOf(record) === -1) ||\n (relatedId !== undefined && !(relatedId in toLinkIds))\n ) {\n // Update (unset) inverse relation\n if (records) {\n // e.g. comment.post_id = undefined\n safeSetProp(record, foreignKey, undefined)\n // e.g. CommentCollection.updateIndex(comment, { index: 'post_id' })\n self.getCollection(relation).updateIndex(record, updateOpts)\n }\n // e.g. comment.post = undefined\n safeSetLink(record, inverseLocalField, undefined)\n }\n })\n toLink.forEach(record => {\n // Update (set) inverse relation\n // e.g. comment.post_id = post.id\n safeSetProp(record, foreignKey, id)\n // e.g. CommentCollection.updateIndex(comment, { index: 'post_id' })\n self.getCollection(relation).updateIndex(record, updateOpts)\n // e.g. comment.post = post\n safeSetLink(record, inverseLocalField, this)\n })\n } else if (localKeys) {\n // Update locals\n // e.g. group.users = someUsers\n // Update (set) inverse relation\n const ids = toLink.map(child => utils.get(child, relatedIdAttribute)).filter(id => id !== undefined)\n // e.g. group.user_ids = [1,2,3,...]\n utils.set(this, localKeys, ids)\n // Update (unset) inverse relation\n if (inverseDef.foreignKeys) {\n current.forEach(child => {\n const relatedId = utils.get(child, relatedIdAttribute)\n if (\n (relatedId === undefined && toLink.indexOf(child) === -1) ||\n (relatedId !== undefined && !(relatedId in toLinkIds))\n ) {\n // Update inverse relation\n // safeSetLink(child, inverseLocalField, undefined)\n const parents = utils.get(child, inverseLocalField) || []\n // e.g. someUser.groups.remove(group)\n if (id === undefined) {\n utils.remove(parents, parent => parent === this)\n } else {\n utils.remove(parents, parent => parent === this || id === utils.get(parent, idAttribute))\n }\n }\n })\n toLink.forEach(child => {\n // Update (set) inverse relation\n const parents = utils.get(child, inverseLocalField)\n // e.g. someUser.groups.push(group)\n if (id === undefined) {\n utils.noDupeAdd(parents, this, parent => parent === this)\n } else {\n utils.noDupeAdd(parents, this, parent => parent === this || id === utils.get(parent, idAttribute))\n }\n })\n }\n } else if (foreignKeys) {\n // e.g. user.groups = someGroups\n // Update (unset) inverse relation\n current.forEach(parent => {\n const ids = utils.get(parent, foreignKeys) || []\n // e.g. someGroup.user_ids.remove(user.id)\n utils.remove(ids, _key => id === _key)\n const children = utils.get(parent, inverseLocalField)\n // e.g. someGroup.users.remove(user)\n if (id === undefined) {\n utils.remove(children, child => child === this)\n } else {\n utils.remove(children, child => child === this || id === utils.get(child, idAttribute))\n }\n })\n // Update (set) inverse relation\n toLink.forEach(parent => {\n const ids = utils.get(parent, foreignKeys) || []\n utils.noDupeAdd(ids, id, _key => id === _key)\n const children = utils.get(parent, inverseLocalField)\n if (id === undefined) {\n utils.noDupeAdd(children, this, child => child === this)\n } else {\n utils.noDupeAdd(children, this, child => child === this || id === utils.get(child, idAttribute))\n }\n })\n }\n\n this._set(path, toLink)\n return toLink\n }\n }\n } else if (type === hasOneType) {\n // TODO: Handle case when belongsTo relation isn't ever defined\n if (self._collections[relation] && foreignKey && !self.getCollection(relation).indexes[foreignKey]) {\n self.getCollection(relation).createIndex(foreignKey)\n }\n descriptor = {\n get: getter,\n // e.g. user.profile = someProfile\n set (record) {\n const current = this._get(path)\n if (record === current) {\n return current\n }\n const inverseLocalField = def.getInverse(mapper).localField\n // Update (unset) inverse relation\n if (current) {\n safeSetProp(current, foreignKey, undefined)\n self.getCollection(relation).updateIndex(current, updateOpts)\n safeSetLink(current, inverseLocalField, undefined)\n }\n if (record) {\n const relatedId = utils.get(record, def.getRelation().idAttribute)\n // Prefer store record\n if (relatedId !== undefined) {\n record = self.get(relation, relatedId) || record\n }\n\n // Set locals\n safeSetLink(this, localField, record)\n\n // Update (set) inverse relation\n safeSetProp(record, foreignKey, utils.get(this, idAttribute))\n self.getCollection(relation).updateIndex(record, updateOpts)\n safeSetLink(record, inverseLocalField, this)\n } else {\n // Unset locals\n safeSetLink(this, localField, undefined)\n }\n return record\n }\n }\n }\n\n if (descriptor) {\n descriptor.enumerable = def.enumerable === undefined ? false : def.enumerable\n if (def.get) {\n const origGet = descriptor.get\n descriptor.get = function () {\n return def.get(def, this, (...args) => origGet.apply(this, args))\n }\n }\n if (def.set) {\n const origSet = descriptor.set\n descriptor.set = function (related) {\n return def.set(def, this, related, value => origSet.call(this, value === undefined ? related : value))\n }\n }\n Object.defineProperty(mapper.recordClass.prototype, localField, descriptor)\n }\n })\n\n return mapper\n }\n\n destroy (name, id, opts: any = {}) {\n return super.destroy(name, id, opts).then(result => {\n let record\n if (opts.raw) {\n record = result.data\n } else {\n record = result\n }\n\n if (record && this.unlinkOnDestroy) {\n const _opts = utils.plainCopy(opts)\n _opts.withAll = true\n utils.forEachRelation(this.getMapper(name), _opts, def => {\n utils.set(record, def.localField, undefined)\n })\n }\n return result\n })\n }\n\n destroyAll (name, query, opts: any = {}) {\n return super.destroyAll(name, query, opts).then(result => {\n let records\n if (opts.raw) {\n records = result.data\n } else {\n records = result\n }\n\n if (records?.length && this.unlinkOnDestroy) {\n const _opts = utils.plainCopy(opts)\n _opts.withAll = true\n utils.forEachRelation(this.getMapper(name), _opts, def => {\n records.forEach(record => {\n utils.set(record, def.localField, undefined)\n })\n })\n }\n return result\n })\n }\n}\n","/**\n * Registered as `js-data` in NPM.\n *\n * @example Install from NPM\n * npm i --save js-data\n * @example Install from NPM\n * yarn add js-data\n * @example Load into your app via CommonJS\n * var JSData = require('js-data');\n * @example Load into your app via ES2015 Modules\n * import * as JSData from 'js-data';\n */\n\n/**\n * JSData's utility methods.\n *\n * @example\n * import { utils } from 'js-data';\n * console.log(utils.isString('foo')); // true\n *\n * @name module:js-data.utils\n * @property {Function} Promise See {@link utils.Promise}.\n * @see utils\n * @since 3.0.0\n * @type {Object}\n */\nimport utils from './utils'\n\n/**\n * JSData's {@link Collection} class.\n *\n * @example\n * import { Collection } from 'js-data';\n * const collection = new Collection();\n *\n * @name module:js-data.Collection\n * @see Collection\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/components-of-jsdata#collection\",\"Components of JSData: Collection\"]\n * @type {Constructor}\n */\nimport Collection from './Collection'\n\n/**\n * JSData's {@link Component} class. Most components in JSData extend this\n * class.\n *\n * @example\n * import { Component } from 'js-data';\n * // Make a custom component.\n * const MyComponent = Component.extend({\n * myMethod (someArg) { ... }\n * });\n *\n * @name module:js-data.Component\n * @see Component\n * @since 3.0.0\n * @type {Constructor}\n */\nimport Component from './Component'\n\n/**\n * JSData's {@link Container} class. Defines and manages {@link Mapper}s. Used\n * in Node.js and in the browser, though in the browser you may want to use\n * {@link DataStore} instead.\n *\n * @example\n * import { Container } from 'js-data';\n * const store = new Container();\n *\n * @name module:js-data.Container\n * @see Container\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/components-of-jsdata#container\",\"Components of JSData: Container\"]\n * @type {Constructor}\n */\nimport { Container } from './Container'\n\n/**\n * JSData's {@link DataStore} class. Primarily for use in the browser. In\n * Node.js you probably want to use {@link Container} instead.\n *\n * @example\n * import { DataStore } from 'js-data';\n * const store = new DataStore();\n *\n * @name module:js-data.DataStore\n * @see DataStore\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/components-of-jsdata#datastore\",\"Components of JSData: DataStore\"]\n * @type {Constructor}\n */\nimport DataStore from './DataStore'\n\n/**\n * JSData's {@link Index} class, based on [mindex]{@link https://github.com/internalfx/mindex}.\n *\n * @name module:js-data.Index\n * @see Index\n * @since 3.0.0\n * @type {Constructor}\n */\nimport Index from './mindex'\n\n/**\n * JSData's {@link LinkedCollection} class. Used by the {@link DataStore}\n * component. If you need to create a collection manually, you should probably\n * use the {@link Collection} class.\n *\n * @name module:js-data.LinkedCollection\n * @see DataStore\n * @see LinkedCollection\n * @since 3.0.0\n * @type {Constructor}\n */\nimport LinkedCollection from './LinkedCollection'\n\n/**\n * JSData's {@link Mapper} class. The core of the ORM.\n *\n * @example Recommended use\n * import { Container } from 'js-data';\n * const store = new Container();\n * store.defineMapper('user');\n *\n * @example Create Mapper manually\n * import { Mapper } from 'js-data';\n * const UserMapper = new Mapper({ name: 'user' });\n *\n * @name module:js-data.Mapper\n * @see Container\n * @see Mapper\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/modeling-your-data\",\"Modeling your data\"]\n * @tutorial [\"http://www.js-data.io/v3.0/docs/components-of-jsdata#mapper\",\"Components of JSData: Mapper\"]\n * @type {Constructor}\n */\nimport Mapper from './Mapper'\n\n/**\n * JSData's {@link Query} class. Used by the {@link Collection} component.\n *\n * @name module:js-data.Query\n * @see Query\n * @since 3.0.0\n * @type {Constructor}\n */\nimport Query from './Query'\n\n/**\n * JSData's {@link Record} class.\n *\n * @example\n * import { Container } from 'js-data';\n * const store = new Container();\n * store.defineMapper('user');\n * const user = store.createRecord('user');\n *\n * @name module:js-data.Record\n * @see Record\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/components-of-jsdata#record\",\"Components of JSData: Record\"]\n * @type {Constructor}\n */\nimport Record from './Record'\n\n/**\n * JSData's {@link Schema} class. Implements http://json-schema.org/draft-04.\n *\n * @example\n * import { Container, Schema } from 'js-data';\n * const userSchema = new Schema({\n * properties: {\n * id: { type: 'string' },\n * name: { type: 'string' }\n * }\n * });\n * const store = new Container();\n * store.defineMapper('user', {\n * schema: userSchema\n * });\n *\n * @name module:js-data.Schema\n * @see Schema\n * @see http://json-schema.org/\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/components-of-jsdata#schema\",\"Components of JSData: schema\"]\n * @tutorial [\"http://www.js-data.io/v3.0/docs/schemas\",\"JSData's Schema Syntax\"]\n * @type {Constructor}\n */\nimport Schema from './Schema'\n\n/**\n * JSData's {@link Settable} class.\n *\n * @example\n * import { Settable } from 'js-data';\n * const obj = new Settable();\n * obj.set('secret', 'value');\n * console.log(JSON.stringify(obj)); // {}\n *\n * @name module:js-data.Settable\n * @see Settable\n * @since 3.0.0\n * @type {Constructor}\n */\nimport Settable from './Settable'\n\n/**\n * JSData's {@link SimpleStore} class. Primarily for use in the browser. In\n * Node.js you probably want to use {@link Container} instead.\n *\n * @example\n * import { SimpleStore } from 'js-data';\n * const store = new SimpleStore();\n *\n * @name module:js-data.SimpleStore\n * @see SimpleStore\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/components-of-jsdata#SimpleStore\",\"Components of JSData: SimpleStore\"]\n * @type {Constructor}\n */\nimport SimpleStore from './SimpleStore'\n\n/**\n * Describes the version of this `JSData` object.\n *\n * @example\n * console.log(JSData.version.full); // \"3.0.0-beta.1\"\n *\n * @name version\n * @memberof module:js-data\n * @property {string} full The full semver value.\n * @property {number} major The major version number.\n * @property {number} minor The minor version number.\n * @property {number} patch The patch version number.\n * @property {(string|boolean)} alpha The alpha version value, otherwise `false`\n * if the current version is not alpha.\n * @property {(string|boolean)} beta The beta version value, otherwise `false`\n * if the current version is not beta.\n * @since 2.0.0\n * @type {Object}\n */\nexport const version = '<%= version %>'\n\nexport * from './decorators'\n\nexport {\n Collection,\n Component,\n Container,\n DataStore,\n Index,\n LinkedCollection,\n Mapper,\n Query,\n Record,\n Schema,\n Settable,\n SimpleStore,\n utils\n}\n"],"names":["DOMAIN","noValidatePath","creatingPath","keepChangeHistoryPath"],"mappings":"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"} \ No newline at end of file diff --git a/dist/js-data.js b/dist/js-data.js index caf4f7fe..b0f51265 100644 --- a/dist/js-data.js +++ b/dist/js-data.js @@ -1,6 +1,6 @@ /*! * js-data -* @version 3.0.6 - Homepage +* @version 4.0.0-beta.4 - Homepage * @author js-data project authors * @copyright (c) 2014-2016 js-data project authors * @license MIT @@ -14,6 +14,8 @@ }(this, (function (exports) { 'use strict'; function _typeof(obj) { + "@babel/helpers - typeof"; + if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function (obj) { return typeof obj; @@ -27,6 +29,28 @@ return _typeof(obj); } + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + + function _defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + + function _createClass(Constructor, protoProps, staticProps) { + if (protoProps) _defineProperties(Constructor.prototype, protoProps); + if (staticProps) _defineProperties(Constructor, staticProps); + return Constructor; + } + function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { @@ -42,6 +66,151 @@ return obj; } + function _inherits(subClass, superClass) { + if (typeof superClass !== "function" && superClass !== null) { + throw new TypeError("Super expression must either be null or a function"); + } + + subClass.prototype = Object.create(superClass && superClass.prototype, { + constructor: { + value: subClass, + writable: true, + configurable: true + } + }); + if (superClass) _setPrototypeOf(subClass, superClass); + } + + function _getPrototypeOf(o) { + _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { + return o.__proto__ || Object.getPrototypeOf(o); + }; + return _getPrototypeOf(o); + } + + function _setPrototypeOf(o, p) { + _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { + o.__proto__ = p; + return o; + }; + + return _setPrototypeOf(o, p); + } + + function isNativeReflectConstruct() { + if (typeof Reflect === "undefined" || !Reflect.construct) return false; + if (Reflect.construct.sham) return false; + if (typeof Proxy === "function") return true; + + try { + Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); + return true; + } catch (e) { + return false; + } + } + + function _construct(Parent, args, Class) { + if (isNativeReflectConstruct()) { + _construct = Reflect.construct; + } else { + _construct = function _construct(Parent, args, Class) { + var a = [null]; + a.push.apply(a, args); + var Constructor = Function.bind.apply(Parent, a); + var instance = new Constructor(); + if (Class) _setPrototypeOf(instance, Class.prototype); + return instance; + }; + } + + return _construct.apply(null, arguments); + } + + function _isNativeFunction(fn) { + return Function.toString.call(fn).indexOf("[native code]") !== -1; + } + + function _wrapNativeSuper(Class) { + var _cache = typeof Map === "function" ? new Map() : undefined; + + _wrapNativeSuper = function _wrapNativeSuper(Class) { + if (Class === null || !_isNativeFunction(Class)) return Class; + + if (typeof Class !== "function") { + throw new TypeError("Super expression must either be null or a function"); + } + + if (typeof _cache !== "undefined") { + if (_cache.has(Class)) return _cache.get(Class); + + _cache.set(Class, Wrapper); + } + + function Wrapper() { + return _construct(Class, arguments, _getPrototypeOf(this).constructor); + } + + Wrapper.prototype = Object.create(Class.prototype, { + constructor: { + value: Wrapper, + enumerable: false, + writable: true, + configurable: true + } + }); + return _setPrototypeOf(Wrapper, Class); + }; + + return _wrapNativeSuper(Class); + } + + function _assertThisInitialized(self) { + if (self === void 0) { + throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + } + + return self; + } + + function _possibleConstructorReturn(self, call) { + if (call && (typeof call === "object" || typeof call === "function")) { + return call; + } + + return _assertThisInitialized(self); + } + + function _superPropBase(object, property) { + while (!Object.prototype.hasOwnProperty.call(object, property)) { + object = _getPrototypeOf(object); + if (object === null) break; + } + + return object; + } + + function _get(target, property, receiver) { + if (typeof Reflect !== "undefined" && Reflect.get) { + _get = Reflect.get; + } else { + _get = function _get(target, property, receiver) { + var base = _superPropBase(target, property); + + if (!base) return; + var desc = Object.getOwnPropertyDescriptor(base, property); + + if (desc.get) { + return desc.get.call(receiver); + } + + return desc.value; + }; + } + + return _get(target, property, receiver || target); + } + function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); } @@ -62,15 +231,15 @@ throw new TypeError("Invalid attempt to spread non-iterable instance"); } - /** - * Utility methods used by JSData. - * - * @example - * import { utils } from 'js-data'; - * console.log(utils.isString('foo')); // true - * - * @namespace utils - * @type {Object} + /** + * Utility methods used by JSData. + * + * @example + * import { utils } from 'js-data'; + * console.log(utils.isString('foo')); // true + * + * @namespace utils + * @type {Object} */ var DOMAIN = 'utils'; var INFINITY = 1 / 0; @@ -86,10 +255,10 @@ var PATH = /^(.+)\.(.+)$/; var ERRORS = { '400': function _() { - return "expected: ".concat(arguments[0], ", found: ").concat(arguments[2] ? arguments[1] : _typeof(arguments[1])); + return "expected: ".concat(arguments.length <= 0 ? undefined : arguments[0], ", found: ").concat((arguments.length <= 2 ? undefined : arguments[2]) ? arguments.length <= 1 ? undefined : arguments[1] : _typeof(arguments.length <= 1 ? undefined : arguments[1])); }, '404': function _() { - return "".concat(arguments[0], " not found"); + return "".concat(arguments.length <= 0 ? undefined : arguments[0], " not found"); } }; @@ -135,34 +304,19 @@ }; var utils = { - /** - * Reference to the Promise constructor used by JSData. Defaults to - * `window.Promise` or `global.Promise`. - * - * @example Make JSData use a different `Promise` constructor - * import Promise from 'bluebird'; - * import { utils } from 'js-data'; - * utils.Promise = Promise; - * - * @name utils.Promise - * @since 3.0.0 - * @type {Function} - */ - Promise: Promise, - - /** - * Shallow copy properties that meet the following criteria from `src` to - * `dest`: - * - * - own enumerable - * - not a function - * - does not start with "_" - * - * @method utils._ - * @param {object} dest Destination object. - * @param {object} src Source object. - * @private - * @since 3.0.0 + /** + * Shallow copy properties that meet the following criteria from `src` to + * `dest`: + * + * - own enumerable + * - not a function + * - does not start with "_" + * + * @method utils._ + * @param {object} dest Destination object. + * @param {object} src Source object. + * @private + * @since 3.0.0 */ _: function _(dest, src) { utils.forOwn(src, function (value, key) { @@ -172,27 +326,30 @@ }); }, - /** - * Recursively iterates over relations found in `opts.with`. - * - * @method utils._forRelation - * @param {object} opts Configuration options. - * @param {Relation} def Relation definition. - * @param {Function} fn Callback function. - * @param {*} [thisArg] Execution context for the callback function. - * @private - * @since 3.0.0 - */ - _forRelation: function _forRelation(opts, def, fn, thisArg) { + /** + * Recursively iterates over relations found in `opts.with`. + * + * @method utils._forRelation + * @param {object} opts Configuration options. + * @param {Relation} def Relation definition. + * @param {Function} fn Callback function. + * @param {*} [thisArg] Execution context for the callback function. + * @private + * @since 3.0.0 + */ + _forRelation: function _forRelation() { + var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + var def = arguments.length > 1 ? arguments[1] : undefined; + var fn = arguments.length > 2 ? arguments[2] : undefined; + var thisArg = arguments.length > 3 ? arguments[3] : undefined; var relationName = def.relation; var containedName = null; var index; - opts || (opts = {}); - opts.with || (opts.with = []); + opts["with"] = opts["with"] || []; - if ((index = utils._getIndex(opts.with, relationName)) >= 0) { + if ((index = utils._getIndex(opts["with"], relationName)) >= 0) { containedName = relationName; - } else if ((index = utils._getIndex(opts.with, def.localField)) >= 0) { + } else if ((index = utils._getIndex(opts["with"], def.localField)) >= 0) { containedName = def.localField; } @@ -206,26 +363,26 @@ var optsCopy = {}; utils.fillIn(optsCopy, def.getRelation()); utils.fillIn(optsCopy, opts); - optsCopy.with = opts.with.slice(); - optsCopy._activeWith = optsCopy.with.splice(index, 1)[0]; - optsCopy.with.forEach(function (relation, i) { + optsCopy["with"] = opts["with"].slice(); + optsCopy._activeWith = optsCopy["with"].splice(index, 1)[0]; + optsCopy["with"].forEach(function (relation, i) { if (relation && relation.indexOf(containedName) === 0 && relation.length >= containedName.length && relation[containedName.length] === '.') { - optsCopy.with[i] = relation.substr(containedName.length + 1); + optsCopy["with"][i] = relation.substr(containedName.length + 1); } else { - optsCopy.with[i] = ''; + optsCopy["with"][i] = ''; } }); fn.call(thisArg, def, optsCopy); }, - /** - * Find the index of a relation in the given list - * - * @method utils._getIndex - * @param {string[]} list List to search. - * @param {string} relation Relation to find. - * @private - * @returns {number} + /** + * Find the index of a relation in the given list + * + * @method utils._getIndex + * @param {string[]} list List to search. + * @param {string} relation Relation to find. + * @private + * @returns {number} */ _getIndex: function _getIndex(list, relation) { var index = -1; @@ -243,25 +400,25 @@ return index; }, - /** - * Define hidden (non-enumerable), writable properties on `target` from the - * provided `props`. - * - * @example - * import { utils } from 'js-data'; - * function Cat () {} - * utils.addHiddenPropsToTarget(Cat.prototype, { - * say () { - * console.log('meow'); - * } - * }); - * const cat = new Cat(); - * cat.say(); // "meow" - * - * @method utils.addHiddenPropsToTarget - * @param {object} target That to which `props` should be added. - * @param {object} props Properties to be added to `target`. - * @since 3.0.0 + /** + * Define hidden (non-enumerable), writable properties on `target` from the + * provided `props`. + * + * @example + * import { utils } from 'js-data'; + * function Cat () {} + * utils.addHiddenPropsToTarget(Cat.prototype, { + * say () { + * console.log('meow'); + * } + * }); + * const cat = new Cat(); + * cat.say(); // "meow" + * + * @method utils.addHiddenPropsToTarget + * @param {object} target That to which `props` should be added. + * @param {object} props Properties to be added to `target`. + * @since 3.0.0 */ addHiddenPropsToTarget: function addHiddenPropsToTarget(target, props) { var map = {}; @@ -273,78 +430,52 @@ Object.defineProperties(target, map); }, - /** - * Return whether the two objects are deeply different. - * - * @example - * import { utils } from 'js-data'; - * utils.areDifferent({}, {}); // false - * utils.areDifferent({ a: 1 }, { a: 1 }); // false - * utils.areDifferent({ foo: 'bar' }, {}); // true - * - * @method utils.areDifferent - * @param {object} a Base object. - * @param {object} b Comparison object. - * @param {object} [opts] Configuration options. - * @param {Function} [opts.equalsFn={@link utils.deepEqual}] Equality function. - * @param {array} [opts.ignore=[]] Array of strings or RegExp of fields to ignore. - * @returns {boolean} Whether the two objects are deeply different. - * @see utils.diffObjects - * @since 3.0.0 - */ - areDifferent: function areDifferent(newObject, oldObject, opts) { - opts || (opts = {}); + /** + * Return whether the two objects are deeply different. + * + * @example + * import { utils } from 'js-data'; + * utils.areDifferent({}, {}); // false + * utils.areDifferent({ a: 1 }, { a: 1 }); // false + * utils.areDifferent({ foo: 'bar' }, {}); // true + * + * @method utils.areDifferent + * @param newObject + * @param oldObject + * @param {object} [opts] Configuration options. + * @param {Function} [opts.equalsFn={@link utils.deepEqual}] Equality function. + * @param {array} [opts.ignore=[]] Array of strings or RegExp of fields to ignore. + * @returns {boolean} Whether the two objects are deeply different. + * @see utils.diffObjects + * @since 3.0.0 + */ + areDifferent: function areDifferent(newObject, oldObject) { + var opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; var diff = utils.diffObjects(newObject, oldObject, opts); var diffCount = Object.keys(diff.added).length + Object.keys(diff.removed).length + Object.keys(diff.changed).length; return diffCount > 0; }, - /** - * Verified that the given constructor is being invoked via `new`, as opposed - * to just being called like a normal function. - * - * @example - * import { utils } from 'js-data'; - * function Cat () { - * utils.classCallCheck(this, Cat); - * } - * const cat = new Cat(); // this is ok - * Cat(); // this throws an error - * - * @method utils.classCallCheck - * @param {*} instance Instance that is being constructed. - * @param {Constructor} ctor Constructor function used to construct the - * instance. - * @since 3.0.0 - * @throws {Error} Throws an error if the constructor is being improperly - * invoked. - */ - classCallCheck: function classCallCheck(instance, ctor) { - if (!(instance instanceof ctor)) { - throw utils.err("".concat(ctor.name))(500, 'Cannot call a class as a function'); - } - }, - - /** - * Deep copy a value. - * - * @example - * import { utils } from 'js-data'; - * const a = { foo: { bar: 'baz' } }; - * const b = utils.copy(a); - * a === b; // false - * utils.areDifferent(a, b); // false - * - * @param {*} from Value to deep copy. - * @param {*} [to] Destination object for the copy operation. - * @param {*} [stackFrom] For internal use. - * @param {*} [stackTo] For internal use. - * @param {string[]|RegExp[]} [blacklist] List of strings or RegExp of - * properties to skip. - * @param {boolean} [plain] Whether to make a plain copy (don't try to use - * original prototype). - * @returns {*} Deep copy of `from`. - * @since 3.0.0 + /** + * Deep copy a value. + * + * @example + * import { utils } from 'js-data'; + * const a = { foo: { bar: 'baz' } }; + * const b = utils.copy(a); + * a === b; // false + * utils.areDifferent(a, b); // false + * + * @param {*} from Value to deep copy. + * @param {*} [to] Destination object for the copy operation. + * @param {*} [stackFrom] For internal use. + * @param {*} [stackTo] For internal use. + * @param {string[]|RegExp[]} [blacklist] List of strings or RegExp of + * properties to skip. + * @param {boolean} [plain] Whether to make a plain copy (don't try to use + * original prototype). + * @returns {*} Deep copy of `from`. + * @since 3.0.0 */ copy: function copy(from, to, stackFrom, stackTo, blacklist, plain) { if (!to) { @@ -411,7 +542,7 @@ } for (var key in from) { - if (Object.hasOwnProperty.call(from, key)) { + if (from.hasOwnProperty(key)) { if (utils.isBlacklisted(key, blacklist)) { continue; } @@ -432,23 +563,23 @@ return to; }, - /** - * Recursively shallow fill in own enumerable properties from `source` to - * `dest`. - * - * @example - * import { utils } from 'js-data'; - * const a = { foo: { bar: 'baz' }, beep: 'boop' }; - * const b = { beep: 'bip' }; - * utils.deepFillIn(b, a); - * console.log(b); // {"foo":{"bar":"baz"},"beep":"bip"} - * - * @method utils.deepFillIn - * @param {object} dest The destination object. - * @param {object} source The source object. - * @see utils.fillIn - * @see utils.deepMixIn - * @since 3.0.0 + /** + * Recursively shallow fill in own enumerable properties from `source` to + * `dest`. + * + * @example + * import { utils } from 'js-data'; + * const a = { foo: { bar: 'baz' }, beep: 'boop' }; + * const b = { beep: 'bip' }; + * utils.deepFillIn(b, a); + * console.log(b); // {"foo":{"bar":"baz"},"beep":"bip"} + * + * @method utils.deepFillIn + * @param {object} dest The destination object. + * @param {object} source The source object. + * @see utils.fillIn + * @see utils.deepMixIn + * @since 3.0.0 */ deepFillIn: function deepFillIn(dest, source) { if (source) { @@ -457,7 +588,7 @@ if (isPlainObject(value) && isPlainObject(existing)) { utils.deepFillIn(existing, value); - } else if (!Object.hasOwnProperty.call(dest, key) || dest[key] === undefined) { + } else if (!dest.hasOwnProperty(key) || dest[key] === undefined) { dest[key] = value; } }); @@ -466,25 +597,26 @@ return dest; }, - /** - * Recursively shallow copy enumerable properties from `source` to `dest`. - * - * @example - * import { utils } from 'js-data'; - * const a = { foo: { bar: 'baz' }, beep: 'boop' }; - * const b = { beep: 'bip' }; - * utils.deepFillIn(b, a); - * console.log(b); // {"foo":{"bar":"baz"},"beep":"boop"} - * - * @method utils.deepMixIn - * @param {object} dest The destination object. - * @param {object} source The source object. - * @see utils.fillIn - * @see utils.deepFillIn - * @since 3.0.0 + /** + * Recursively shallow copy enumerable properties from `source` to `dest`. + * + * @example + * import { utils } from 'js-data'; + * const a = { foo: { bar: 'baz' }, beep: 'boop' }; + * const b = { beep: 'bip' }; + * utils.deepFillIn(b, a); + * console.log(b); // {"foo":{"bar":"baz"},"beep":"boop"} + * + * @method utils.deepMixIn + * @param {object} dest The destination object. + * @param {object} source The source object. + * @see utils.fillIn + * @see utils.deepFillIn + * @since 3.0.0 */ deepMixIn: function deepMixIn(dest, source) { if (source) { + // tslint:disable-next-line:forin for (var key in source) { var value = source[key]; var existing = dest[key]; @@ -500,30 +632,30 @@ return dest; }, - /** - * Return a diff of the base object to the comparison object. - * - * @example - * import { utils } from 'js-data'; - * const oldObject = { foo: 'bar', a: 1234 }; - * const newObject = { beep: 'boop', a: 5678 }; - * const diff = utils.diffObjects(oldObject, newObject); - * console.log(diff.added); // {"beep":"boop"} - * console.log(diff.changed); // {"a":5678} - * console.log(diff.removed); // {"foo":undefined} - * - * @method utils.diffObjects - * @param {object} newObject Comparison object. - * @param {object} oldObject Base object. - * @param {object} [opts] Configuration options. - * @param {Function} [opts.equalsFn={@link utils.deepEqual}] Equality function. - * @param {array} [opts.ignore=[]] Array of strings or RegExp of fields to ignore. - * @returns {Object} The diff from the base object to the comparison object. - * @see utils.areDifferent - * @since 3.0.0 - */ - diffObjects: function diffObjects(newObject, oldObject, opts) { - opts || (opts = {}); + /** + * Return a diff of the base object to the comparison object. + * + * @example + * import { utils } from 'js-data'; + * const oldObject = { foo: 'bar', a: 1234 }; + * const newObject = { beep: 'boop', a: 5678 }; + * const diff = utils.diffObjects(oldObject, newObject); + * console.log(diff.added); // {"beep":"boop"} + * console.log(diff.changed); // {"a":5678} + * console.log(diff.removed); // {"foo":undefined} + * + * @method utils.diffObjects + * @param {object} newObject Comparison object. + * @param {object} oldObject Base object. + * @param {object} [opts] Configuration options. + * @param {Function} [opts.equalsFn={@link utils.deepEqual}] Equality function. + * @param {array} [opts.ignore=[]] Array of strings or RegExp of fields to ignore. + * @returns {Object} The diff from the base object to the comparison object. + * @see utils.areDifferent + * @since 3.0.0 + */ + diffObjects: function diffObjects(newObject, oldObject) { + var opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; var equalsFn = opts.equalsFn; var blacklist = opts.ignore; var diff = { @@ -569,67 +701,73 @@ return diff; }, - /** - * Return whether the two values are equal according to the `==` operator. - * - * @example - * import { utils } from 'js-data'; - * console.log(utils.equal(1,1)); // true - * console.log(utils.equal(1,'1')); // true - * console.log(utils.equal(93, 66)); // false - * - * @method utils.equal - * @param {*} a First value in the comparison. - * @param {*} b Second value in the comparison. - * @returns {boolean} Whether the two values are equal according to `==`. - * @since 3.0.0 + /** + * Return whether the two values are equal according to the `==` operator. + * + * @example + * import { utils } from 'js-data'; + * console.log(utils.equal(1,1)); // true + * console.log(utils.equal(1,'1')); // true + * console.log(utils.equal(93, 66)); // false + * + * @method utils.equal + * @param {*} a First value in the comparison. + * @param {*} b Second value in the comparison. + * @returns {boolean} Whether the two values are equal according to `==`. + * @since 3.0.0 */ equal: function equal(a, b) { + // tslint:disable-next-line:triple-equals return a == b; // eslint-disable-line }, - /** - * Produce a factory function for making Error objects with the provided - * metadata. Used throughout the various js-data components. - * - * @example - * import { utils } from 'js-data'; - * const errorFactory = utils.err('domain', 'target'); - * const error400 = errorFactory(400, 'expected type', 'actual type'); - * console.log(error400); // [Error: [domain:target] expected: expected type, found: string - http://www.js-data.io/v3.0/docs/errors#400] - * @method utils.err - * @param {string} domain Namespace. - * @param {string} target Target. - * @returns {Function} Factory function. - * @since 3.0.0 + /** + * Produce a factory function for making Error objects with the provided + * metadata. Used throughout the various js-data components. + * + * @example + * import { utils } from 'js-data'; + * const errorFactory = utils.err('domain', 'target'); + * const error400 = errorFactory(400, 'expected type', 'actual type'); + * console.log(error400); // [Error: [domain:target] expected: expected type, found: string + * http://www.js-data.io/v3.0/docs/errors#400] + * @method utils.err + * @param {string} domain Namespace. + * @param {string} target Target. + * @returns {Function} Factory function. + * @since 3.0.0 */ err: function err(domain, target) { return function (code) { var prefix = "[".concat(domain, ":").concat(target, "] "); - var message = ERRORS[code].apply(null, Array.prototype.slice.call(arguments, 1)); + + for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + args[_key - 1] = arguments[_key]; + } + + var message = ERRORS[code].apply(null, args); message = "".concat(prefix).concat(message, "\nhttp://www.js-data.io/v3.0/docs/errors#").concat(code); return new Error(message); }; }, - /** - * Add eventing capabilities into the target object. - * - * @example - * import { utils } from 'js-data'; - * const user = { name: 'John' }; - * utils.eventify(user); - * user.on('foo', () => console.log(arguments)); - * user.emit('foo', 1, 'bar'); // should log to console values (1, "bar") - * - * @method utils.eventify - * @param {object} target Target object. - * @param {Function} [getter] Custom getter for retrieving the object's event - * listeners. - * @param {Function} [setter] Custom setter for setting the object's event - * listeners. - * @since 3.0.0 + /** + * Add eventing capabilities into the target object. + * + * @example + * import { utils } from 'js-data'; + * const user = { name: 'John' }; + * utils.eventify(user); + * user.on('foo', () => console.log(arguments)); + * user.emit('foo', 1, 'bar'); // should log to console values (1, "bar") + * + * @method utils.eventify + * @param {object} target Target object. + * @param {Function} [getter] Custom getter for retrieving the object's event + * listeners. + * @param {Function} [setter] Custom setter for setting the object's event + * listeners. + * @since 3.0.0 */ eventify: function eventify(target, getter, setter) { target = target || this; @@ -641,7 +779,7 @@ }; setter = function setter(value) { - _events = value; + return _events = value; }; } @@ -650,8 +788,8 @@ value: function value() { var events = getter.call(this) || {}; - for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { - args[_key] = arguments[_key]; + for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { + args[_key2] = arguments[_key2]; } var type = args.shift(); @@ -706,135 +844,53 @@ }); }, - /** - * Used for sublcassing. Invoke this method in the context of a superclass to - * to produce a subclass based on `props` and `classProps`. - * - * @example - * import { utils } from 'js-data'; - * function Animal () {} - * Animal.extend = utils.extend; - * const Cat = Animal.extend({ - * say () { - * console.log('meow'); - * } - * }); - * const cat = new Cat(); - * cat instanceof Animal; // true - * cat instanceof Cat; // true - * cat.say(); // "meow" - * - * @method utils.extend - * @param {object} props Instance properties for the subclass. - * @param {object} [props.constructor] Provide a custom constructor function - * to use as the subclass. - * @param {object} props Static properties for the subclass. - * @returns {Constructor} A new subclass. - * @since 3.0.0 - */ - extend: function extend(props, classProps) { - var superClass = this; - - var _subClass; - - props || (props = {}); - classProps || (classProps = {}); - - if (Object.hasOwnProperty.call(props, 'constructor')) { - _subClass = props.constructor; - delete props.constructor; - } else { - _subClass = function subClass() { - utils.classCallCheck(this, _subClass); - - for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { - args[_key2] = arguments[_key2]; - } - - superClass.apply(this, args); - }; - } // Setup inheritance of instance members - - - _subClass.prototype = Object.create(superClass && superClass.prototype, { - constructor: { - configurable: true, - enumerable: false, - value: _subClass, - writable: true - } - }); - var obj = Object; // Setup inheritance of static members - - if (obj.setPrototypeOf) { - obj.setPrototypeOf(_subClass, superClass); - } else if (classProps.strictEs6Class) { - _subClass.__proto__ = superClass; // eslint-disable-line - } else { - utils.forOwn(superClass, function (value, key) { - _subClass[key] = value; - }); - } - - if (!Object.hasOwnProperty.call(_subClass, '__super__')) { - Object.defineProperty(_subClass, '__super__', { - configurable: true, - value: superClass - }); - } - - utils.addHiddenPropsToTarget(_subClass.prototype, props); - utils.fillIn(_subClass, classProps); - return _subClass; - }, - - /** - * Shallow copy own enumerable properties from `src` to `dest` that are on - * `src` but are missing from `dest. - * - * @example - * import { utils } from 'js-data'; - * const a = { foo: 'bar', beep: 'boop' }; - * const b = { beep: 'bip' }; - * utils.fillIn(b, a); - * console.log(b); // {"foo":"bar","beep":"bip"} - * - * @method utils.fillIn - * @param {object} dest The destination object. - * @param {object} source The source object. - * @see utils.deepFillIn - * @see utils.deepMixIn - * @since 3.0.0 + /** + * Shallow copy own enumerable properties from `src` to `dest` that are on + * `src` but are missing from `dest. + * + * @example + * import { utils } from 'js-data'; + * const a = { foo: 'bar', beep: 'boop' }; + * const b = { beep: 'bip' }; + * utils.fillIn(b, a); + * console.log(b); // {"foo":"bar","beep":"bip"} + * + * @method utils.fillIn + * @param {object} dest The destination object. + * @param src + * @see utils.deepFillIn + * @see utils.deepMixIn + * @since 3.0.0 */ fillIn: function fillIn(dest, src) { utils.forOwn(src, function (value, key) { - if (!Object.hasOwnProperty.call(dest, key) || dest[key] === undefined) { + if (!dest.hasOwnProperty(key) || dest[key] === undefined) { dest[key] = value; } }); }, - /** - * Find the last index of an item in an array according to the given checker function. - * - * @example - * import { utils } from 'js-data'; - * - * const john = { name: 'John', age: 20 }; - * const sara = { name: 'Sara', age: 25 }; - * const dan = { name: 'Dan', age: 20 }; - * const users = [john, sara, dan]; - * - * console.log(utils.findIndex(users, (user) => user.age === 25)); // 1 - * console.log(utils.findIndex(users, (user) => user.age > 19)); // 2 - * console.log(utils.findIndex(users, (user) => user.name === 'John')); // 0 - * console.log(utils.findIndex(users, (user) => user.name === 'Jimmy')); // -1 - * - * @method utils.findIndex - * @param {array} array The array to search. - * @param {Function} fn Checker function. - * @returns {number} Index if found or -1 if not found. - * @since 3.0.0 + /** + * Find the last index of an item in an array according to the given checker function. + * + * @example + * import { utils } from 'js-data'; + * + * const john = { name: 'John', age: 20 }; + * const sara = { name: 'Sara', age: 25 }; + * const dan = { name: 'Dan', age: 20 }; + * const users = [john, sara, dan]; + * + * console.log(utils.findIndex(users, (user) => user.age === 25)); // 1 + * console.log(utils.findIndex(users, (user) => user.age > 19)); // 2 + * console.log(utils.findIndex(users, (user) => user.name === 'John')); // 0 + * console.log(utils.findIndex(users, (user) => user.name === 'Jimmy')); // -1 + * + * @method utils.findIndex + * @param {array} array The array to search. + * @param {Function} fn Checker function. + * @returns {number} Index if found or -1 if not found. + * @since 3.0.0 */ findIndex: function findIndex(array, fn) { var index = -1; @@ -852,16 +908,16 @@ return index; }, - /** - * Recursively iterate over a {@link Mapper}'s relations according to - * `opts.with`. - * - * @method utils.forEachRelation - * @param {Mapper} mapper Mapper. - * @param {object} opts Configuration options. - * @param {Function} fn Callback function. - * @param {*} thisArg Execution context for the callback function. - * @since 3.0.0 + /** + * Recursively iterate over a {@link Mapper}'s relations according to + * `opts.with`. + * + * @method utils.forEachRelation + * @param {Mapper} mapper Mapper. + * @param {object} opts Configuration options. + * @param {Function} fn Callback function. + * @param {*} thisArg Execution context for the callback function. + * @since 3.0.0 */ forEachRelation: function forEachRelation(mapper, opts, fn, thisArg) { var relationList = mapper.relationList || []; @@ -875,23 +931,23 @@ }); }, - /** - * Iterate over an object's own enumerable properties. - * - * @example - * import { utils } from 'js-data'; - * const a = { b: 1, c: 4 }; - * let sum = 0; - * utils.forOwn(a, function (value, key) { - * sum += value; - * }); - * console.log(sum); // 5 - * - * @method utils.forOwn - * @param {object} object The object whose properties are to be enumerated. - * @param {Function} fn Iteration function. - * @param {object} [thisArg] Content to which to bind `fn`. - * @since 3.0.0 + /** + * Iterate over an object's own enumerable properties. + * + * @example + * import { utils } from 'js-data'; + * const a = { b: 1, c: 4 }; + * let sum = 0; + * utils.forOwn(a, function (value, key) { + * sum += value; + * }); + * console.log(sum); // 5 + * + * @method utils.forOwn + * @param obj + * @param {Function} fn Iteration function. + * @param {object} [thisArg] Content to which to bind `fn`. + * @since 3.0.0 */ forOwn: function forOwn(obj, fn, thisArg) { var keys = Object.keys(obj); @@ -905,46 +961,52 @@ } }, - /** - * Proxy for `JSON.parse`. - * - * @example - * import { utils } from 'js-data'; - * - * const a = utils.fromJson('{"name" : "John"}'); - * console.log(a); // { name: 'John' } - * - * @method utils.fromJson - * @param {string} json JSON to parse. - * @returns {Object} Parsed object. - * @see utils.toJson - * @since 3.0.0 + /** + * Proxy for `JSON.parse`. + * + * @example + * import { utils } from 'js-data'; + * + * const a = utils.fromJson('{"name" : "John"}'); + * console.log(a); // { name: 'John' } + * + * @method utils.fromJson + * @param {string} json JSON to parse. + * @returns {Object} Parsed object. + * @see utils.toJson + * @since 3.0.0 */ fromJson: function fromJson(json) { return utils.isString(json) ? JSON.parse(json) : json; }, - /** - * Retrieve the specified property from the given object. Supports retrieving - * nested properties. - * - * @example - * import { utils } from 'js-data'; - * const a = { foo: { bar: 'baz' }, beep: 'boop' }; - * console.log(utils.get(a, 'beep')); // "boop" - * console.log(utils.get(a, 'foo.bar')); // "baz" - * - * @method utils.get - * @param {object} object Object from which to retrieve a property's value. - * @param {string} prop Property to retrieve. - * @returns {*} Value of the specified property. - * @see utils.set - * @since 3.0.0 + /** + * Retrieve the specified property from the given object. Supports retrieving + * nested properties. + * + * @example + * import { utils } from 'js-data'; + * const a = { foo: { bar: 'baz' }, beep: 'boop' }; + * console.log(utils.get(a, 'beep')); // "boop" + * console.log(utils.get(a, 'foo.bar')); // "baz" + * + * @method utils.get + * @param {object} object Object from which to retrieve a property's value. + * @param {string} prop Property to retrieve. + * @returns {*} Value of the specified property. + * @see utils.set + * @since 3.0.0 */ get: function get(object, prop) { if (!prop) { return; } + /* if prop is function, get the property by calling a function, passing an object as a parameter */ + + + if (utils.isFunction(prop)) { + return prop(object); + } var parts = prop.split('.'); var last = parts.pop(); @@ -962,59 +1024,59 @@ return object[last]; }, - /** - * Return the superclass for the given instance or subclass. If an instance is - * provided, then finds the parent class of the instance's constructor. - * - * @example - * import { utils } from 'js-data'; - * // using ES2015 classes - * class Foo {} - * class Bar extends Foo {} - * const barInstance = new Bar(); - * let baseType = utils.getSuper(barInstance); - * console.log(Foo === baseType); // true - * - * // using Function constructor with utils.extend - * function Foo () {} - * Foo.extend = utils.extend; - * const Bar = Foo.extend(); - * const barInstance = new Bar(); - * let baseType = utils.getSuper(barInstance); - * console.log(Foo === baseType); // true - * - * @method utils.getSuper - * @param {Object|Function} instance Instance or constructor. - * @param {boolean} [isCtor=false] Whether `instance` is a constructor. - * @returns {Constructor} The superclass (grandparent constructor). - * @since 3.0.0 + /** + * Return the superclass for the given instance or subclass. If an instance is + * provided, then finds the parent class of the instance's constructor. + * + * @example + * import { utils } from 'js-data'; + * // using ES2015 classes + * class Foo {} + * class Bar extends Foo {} + * const barInstance = new Bar(); + * let baseType = utils.getSuper(barInstance); + * console.log(Foo === baseType); // true + * + * // using Function constructor with utils.extend + * function Foo () {} + * Foo.extend = utils.extend; + * const Bar = Foo.extend(); + * const barInstance = new Bar(); + * let baseType = utils.getSuper(barInstance); + * console.log(Foo === baseType); // true + * + * @method utils.getSuper + * @param {Object|Function} instance Instance or constructor. + * @param {boolean} [isCtor=false] Whether `instance` is a constructor. + * @returns {Constructor} The superclass (grandparent constructor). + * @since 3.0.0 */ getSuper: function getSuper(instance, isCtor) { var ctor = isCtor ? instance : instance.constructor; - if (Object.hasOwnProperty.call(ctor, '__super__')) { + if (ctor.hasOwnProperty('__super__')) { return ctor.__super__; } return Object.getPrototypeOf(ctor) || ctor.__proto__; // eslint-disable-line }, - /** - * Return the intersection of two arrays. - * - * @example - * import { utils } from 'js-data'; - * const arrA = ['green', 'red', 'blue', 'red']; - * const arrB = ['green', 'yellow', 'red']; - * const intersected = utils.intersection(arrA, arrB); - * - * console.log(intersected); // ['green', 'red']) - * - * @method utils.intersection - * @param {array} array1 First array. - * @param {array} array2 Second array. - * @returns {Array} Array of elements common to both arrays. - * @since 3.0.0 + /** + * Return the intersection of two arrays. + * + * @example + * import { utils } from 'js-data'; + * const arrA = ['green', 'red', 'blue', 'red']; + * const arrB = ['green', 'yellow', 'red']; + * const intersected = utils.intersection(arrA, arrB); + * + * console.log(intersected); // ['green', 'red']) + * + * @method utils.intersection + * @param {array} array1 First array. + * @param {array} array2 Second array. + * @returns {Array} Array of elements common to both arrays. + * @since 3.0.0 */ intersection: function intersection(array1, array2) { if (!array1 || !array2) { @@ -1043,40 +1105,40 @@ return result; }, - /** - * Proxy for `Array.isArray`. - * - * @example - * import { utils } from 'js-data'; - * const a = [1,2,3,4,5]; - * const b = { foo: "bar" }; - * console.log(utils.isArray(a)); // true - * console.log(utils.isArray(b)); // false - * - * @method utils.isArray - * @param {*} value The value to test. - * @returns {boolean} Whether the provided value is an array. - * @since 3.0.0 + /** + * Proxy for `Array.isArray`. + * + * @example + * import { utils } from 'js-data'; + * const a = [1,2,3,4,5]; + * const b = { foo: "bar" }; + * console.log(utils.isArray(a)); // true + * console.log(utils.isArray(b)); // false + * + * @method utils.isArray + * @param {*} value The value to test. + * @returns {boolean} Whether the provided value is an array. + * @since 3.0.0 */ isArray: Array.isArray, - /** - * Return whether `prop` is matched by any string or regular expression in - * `blacklist`. - * - * @example - * import { utils } from 'js-data'; - * const blacklist = [/^\$hashKey/g, /^_/g, 'id']; - * console.log(utils.isBlacklisted("$hashKey", blacklist)); // true - * console.log(utils.isBlacklisted("id", blacklist)); // true - * console.log(utils.isBlacklisted("_myProp", blacklist)); // true - * console.log(utils.isBlacklisted("my_id", blacklist)); // false - * - * @method utils.isBlacklisted - * @param {string} prop The name of a property to check. - * @param {array} blacklist Array of strings and regular expressions. - * @returns {boolean} Whether `prop` was matched. - * @since 3.0.0 + /** + * Return whether `prop` is matched by any string or regular expression in + * `blacklist`. + * + * @example + * import { utils } from 'js-data'; + * const blacklist = [/^\$hashKey/g, /^_/g, 'id']; + * console.log(utils.isBlacklisted("$hashKey", blacklist)); // true + * console.log(utils.isBlacklisted("id", blacklist)); // true + * console.log(utils.isBlacklisted("_myProp", blacklist)); // true + * console.log(utils.isBlacklisted("my_id", blacklist)); // false + * + * @method utils.isBlacklisted + * @param {string} prop The name of a property to check. + * @param {array} blacklist Array of strings and regular expressions. + * @returns {boolean} Whether `prop` was matched. + * @since 3.0.0 */ isBlacklisted: function isBlacklisted(prop, blacklist) { if (!blacklist || !blacklist.length) { @@ -1084,130 +1146,151 @@ } var matches; + var _iteratorNormalCompletion = true; + var _didIteratorError = false; + var _iteratorError = undefined; - for (var i = 0; i < blacklist.length; i++) { - if (toStr(blacklist[i]) === REGEXP_TAG && blacklist[i].test(prop) || blacklist[i] === prop) { - matches = prop; - return !!matches; + try { + for (var _iterator = blacklist[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { + var item = _step.value; + + if (toStr(item) === REGEXP_TAG && item.test(prop) || item === prop) { + matches = prop; + return !!matches; + } + } + } catch (err) { + _didIteratorError = true; + _iteratorError = err; + } finally { + try { + if (!_iteratorNormalCompletion && _iterator["return"] != null) { + _iterator["return"](); + } + } finally { + if (_didIteratorError) { + throw _iteratorError; + } } } return !!matches; }, - /** - * Return whether the provided value is a boolean. - * - * @example - * import { utils } from 'js-data'; - * const a = true; - * const b = { foo: "bar" }; - * console.log(utils.isBoolean(a)); // true - * console.log(utils.isBoolean(b)); // false - * - * @method utils.isBoolean - * @param {*} value The value to test. - * @returns {boolean} Whether the provided value is a boolean. - * @since 3.0.0 + /** + * Return whether the provided value is a boolean. + * + * @example + * import { utils } from 'js-data'; + * const a = true; + * const b = { foo: "bar" }; + * console.log(utils.isBoolean(a)); // true + * console.log(utils.isBoolean(b)); // false + * + * @method utils.isBoolean + * @param {*} value The value to test. + * @returns {boolean} Whether the provided value is a boolean. + * @since 3.0.0 */ isBoolean: function isBoolean(value) { return toStr(value) === BOOL_TAG; }, - /** - * Return whether the provided value is a date. - * - * @example - * import { utils } from 'js-data'; - * const a = new Date(); - * const b = { foo: "bar" }; - * console.log(utils.isDate(a)); // true - * console.log(utils.isDate(b)); // false - * - * @method utils.isDate - * @param {*} value The value to test. - * @returns {Date} Whether the provided value is a date. - * @since 3.0.0 + /** + * Return whether the provided value is a date. + * + * @example + * import { utils } from 'js-data'; + * const a = new Date(); + * const b = { foo: "bar" }; + * console.log(utils.isDate(a)); // true + * console.log(utils.isDate(b)); // false + * + * @method utils.isDate + * @param {*} value The value to test. + * @returns {Date} Whether the provided value is a date. + * @since 3.0.0 */ isDate: function isDate(value) { return value && _typeof(value) === 'object' && toStr(value) === DATE_TAG; }, - /** - * Return whether the provided value is a function. - * - * @example - * import { utils } from 'js-data'; - * const a = function () { console.log('foo bar'); }; - * const b = { foo: "bar" }; - * console.log(utils.isFunction(a)); // true - * console.log(utils.isFunction(b)); // false - * - * @method utils.isFunction - * @param {*} value The value to test. - * @returns {boolean} Whether the provided value is a function. - * @since 3.0.0 + /** + * Return whether the provided value is a function. + * + * @example + * import { utils } from 'js-data'; + * const a = function () { console.log('foo bar'); }; + * const b = { foo: "bar" }; + * console.log(utils.isFunction(a)); // true + * console.log(utils.isFunction(b)); // false + * + * @method utils.isFunction + * @param {*} value The value to test. + * @returns {boolean} Whether the provided value is a function. + * @since 3.0.0 */ isFunction: function isFunction(value) { return typeof value === 'function' || value && toStr(value) === FUNC_TAG; }, - /** - * Return whether the provided value is an integer. - * - * @example - * import { utils } from 'js-data'; - * const a = 1; - * const b = 1.25; - * const c = '1'; - * console.log(utils.isInteger(a)); // true - * console.log(utils.isInteger(b)); // false - * console.log(utils.isInteger(c)); // false - * - * @method utils.isInteger - * @param {*} value The value to test. - * @returns {boolean} Whether the provided value is an integer. - * @since 3.0.0 + /** + * Return whether the provided value is an integer. + * + * @example + * import { utils } from 'js-data'; + * const a = 1; + * const b = 1.25; + * const c = '1'; + * console.log(utils.isInteger(a)); // true + * console.log(utils.isInteger(b)); // false + * console.log(utils.isInteger(c)); // false + * + * @method utils.isInteger + * @param {*} value The value to test. + * @returns {boolean} Whether the provided value is an integer. + * @since 3.0.0 */ isInteger: function isInteger(value) { + // tslint:disable-next-line:triple-equals return toStr(value) === NUMBER_TAG && value == toInteger(value); // eslint-disable-line }, - /** - * Return whether the provided value is `null`. - * - * @example - * import { utils } from 'js-data'; - * const a = null; - * const b = { foo: "bar" }; - * console.log(utils.isNull(a)); // true - * console.log(utils.isNull(b)); // false - * - * @method utils.isNull - * @param {*} value The value to test. - * @returns {boolean} Whether the provided value is `null`. - * @since 3.0.0 + /** + * Return whether the provided value is `null`. + * + * @example + * import { utils } from 'js-data'; + * const a = null; + * const b = { foo: "bar" }; + * console.log(utils.isNull(a)); // true + * console.log(utils.isNull(b)); // false + * + * @method utils.isNull + * @param {*} value The value to test. + * @returns {boolean} Whether the provided value is `null`. + * @since 3.0.0 */ isNull: function isNull(value) { return value === null; }, - /** - * Return whether the provided value is a number. - * - * @example - * import { utils } from 'js-data'; - * const a = 1; - * const b = -1.25; - * const c = '1'; - * console.log(utils.isNumber(a)); // true - * console.log(utils.isNumber(b)); // true - * console.log(utils.isNumber(c)); // false - * - * @method utils.isNumber - * @param {*} value The value to test. - * @returns {boolean} Whether the provided value is a number. - * @since 3.0.0 + /** + * Return whether the provided value is a number. + * + * @example + * import { utils } from 'js-data'; + * const a = 1; + * const b = -1.25; + * const c = '1'; + * console.log(utils.isNumber(a)); // true + * console.log(utils.isNumber(b)); // true + * console.log(utils.isNumber(c)); // false + * + * @method utils.isNumber + * @param {*} value The value to test. + * @returns {boolean} Whether the provided value is a number. + * @since 3.0.0 */ isNumber: function isNumber(value) { var type = _typeof(value); @@ -1215,125 +1298,125 @@ return type === 'number' || value && type === 'object' && toStr(value) === NUMBER_TAG; }, - /** - * Return whether the provided value is an object. - * - * @example - * import { utils } from 'js-data'; - * const a = { foo: "bar" }; - * const b = 'foo bar'; - * console.log(utils.isObject(a)); // true - * console.log(utils.isObject(b)); // false - * - * @method utils.isObject - * @param {*} value The value to test. - * @returns {boolean} Whether the provided value is an object. - * @since 3.0.0 + /** + * Return whether the provided value is an object. + * + * @example + * import { utils } from 'js-data'; + * const a = { foo: "bar" }; + * const b = 'foo bar'; + * console.log(utils.isObject(a)); // true + * console.log(utils.isObject(b)); // false + * + * @method utils.isObject + * @param {*} value The value to test. + * @returns {boolean} Whether the provided value is an object. + * @since 3.0.0 */ isObject: function isObject(value) { return toStr(value) === OBJECT_TAG; }, - /** - * Return whether the provided value is a regular expression. - * - * @example - * import { utils } from 'js-data'; - * const a = /^\$.+$/ig; - * const b = new RegExp('^\$.+$', 'ig'); - * const c = { foo: "bar" }; - * console.log(utils.isRegExp(a)); // true - * console.log(utils.isRegExp(b)); // true - * console.log(utils.isRegExp(c)); // false - * - * @method utils.isRegExp - * @param {*} value The value to test. - * @returns {boolean} Whether the provided value is a regular expression. - * @since 3.0.0 + /** + * Return whether the provided value is a regular expression. + * + * @example + * import { utils } from 'js-data'; + * const a = /^\$.+$/ig; + * const b = new RegExp('^\$.+$', 'ig'); + * const c = { foo: "bar" }; + * console.log(utils.isRegExp(a)); // true + * console.log(utils.isRegExp(b)); // true + * console.log(utils.isRegExp(c)); // false + * + * @method utils.isRegExp + * @param {*} value The value to test. + * @returns {boolean} Whether the provided value is a regular expression. + * @since 3.0.0 */ isRegExp: function isRegExp(value) { return toStr(value) === REGEXP_TAG; }, - /** - * Return whether the provided value is a string or a number. - * - * @example - * import { utils } from 'js-data'; - * console.log(utils.isSorN('')); // true - * console.log(utils.isSorN(-1.65)); // true - * console.log(utils.isSorN('my string')); // true - * console.log(utils.isSorN({})); // false - * console.log(utils.isSorN([1,2,4])); // false - * - * @method utils.isSorN - * @param {*} value The value to test. - * @returns {boolean} Whether the provided value is a string or a number. - * @since 3.0.0 + /** + * Return whether the provided value is a string or a number. + * + * @example + * import { utils } from 'js-data'; + * console.log(utils.isSorN('')); // true + * console.log(utils.isSorN(-1.65)); // true + * console.log(utils.isSorN('my string')); // true + * console.log(utils.isSorN({})); // false + * console.log(utils.isSorN([1,2,4])); // false + * + * @method utils.isSorN + * @param {*} value The value to test. + * @returns {boolean} Whether the provided value is a string or a number. + * @since 3.0.0 */ isSorN: function isSorN(value) { return utils.isString(value) || utils.isNumber(value); }, - /** - * Return whether the provided value is a string. - * - * @example - * import { utils } from 'js-data'; - * console.log(utils.isString('')); // true - * console.log(utils.isString('my string')); // true - * console.log(utils.isString(100)); // false - * console.log(utils.isString([1,2,4])); // false - * - * @method utils.isString - * @param {*} value The value to test. - * @returns {boolean} Whether the provided value is a string. - * @since 3.0.0 + /** + * Return whether the provided value is a string. + * + * @example + * import { utils } from 'js-data'; + * console.log(utils.isString('')); // true + * console.log(utils.isString('my string')); // true + * console.log(utils.isString(100)); // false + * console.log(utils.isString([1,2,4])); // false + * + * @method utils.isString + * @param {*} value The value to test. + * @returns {boolean} Whether the provided value is a string. + * @since 3.0.0 */ isString: function isString(value) { return typeof value === 'string' || value && _typeof(value) === 'object' && toStr(value) === STRING_TAG; }, - /** - * Return whether the provided value is a `undefined`. - * - * @example - * import { utils } from 'js-data'; - * const a = undefined; - * const b = { foo: "bar"}; - * console.log(utils.isUndefined(a)); // true - * console.log(utils.isUndefined(b.baz)); // true - * console.log(utils.isUndefined(b)); // false - * console.log(utils.isUndefined(b.foo)); // false - * - * @method utils.isUndefined - * @param {*} value The value to test. - * @returns {boolean} Whether the provided value is a `undefined`. - * @since 3.0.0 + /** + * Return whether the provided value is a `undefined`. + * + * @example + * import { utils } from 'js-data'; + * const a = undefined; + * const b = { foo: "bar"}; + * console.log(utils.isUndefined(a)); // true + * console.log(utils.isUndefined(b.baz)); // true + * console.log(utils.isUndefined(b)); // false + * console.log(utils.isUndefined(b.foo)); // false + * + * @method utils.isUndefined + * @param {*} value The value to test. + * @returns {boolean} Whether the provided value is a `undefined`. + * @since 3.0.0 */ isUndefined: function isUndefined(value) { return value === undefined; }, - /** - * Mix in logging capabilities to the target. - * - * @example - * import { utils } from 'js-data'; - * const a = { foo: "bar"}; - * - * // Add standard logging to an object - * utils.logify(a); - * a.log('info', 'test log info'); // output 'test log info' to console. - * - * // Toggle debug output of an object - * a.dbg('test debug output'); // does not output because debug is off. - * a.debug = true; - * a.dbg('test debug output'); // output 'test debug output' to console. - * - * @method utils.logify - * @param {*} target The target. - * @since 3.0.0 + /** + * Mix in logging capabilities to the target. + * + * @example + * import { utils } from 'js-data'; + * const a = { foo: "bar"}; + * + * // Add standard logging to an object + * utils.logify(a); + * a.log('info', 'test log info'); // output 'test log info' to console. + * + * // Toggle debug output of an object + * a.dbg('test debug output'); // does not output because debug is off. + * a.debug = true; + * a.dbg('test debug output'); // output 'test debug output' to console. + * + * @method utils.logify + * @param {*} target The target. + * @since 3.0.0 */ logify: function logify(target) { utils.addHiddenPropsToTarget(target, { @@ -1375,26 +1458,26 @@ }); }, - /** - * Adds the given record to the provided array only if it's not already in the - * array. - * - * @example - * import { utils } from 'js-data'; - * const colors = ['red', 'green', 'yellow']; - * - * console.log(colors.length); // 3 - * utils.noDupeAdd(colors, 'red'); - * console.log(colors.length); // 3, red already exists - * - * utils.noDupeAdd(colors, 'blue'); - * console.log(colors.length); // 4, blue was added - * - * @method utils.noDupeAdd - * @param {array} array The array. - * @param {*} record The value to add. - * @param {Function} fn Callback function passed to {@link utils.findIndex}. - * @since 3.0.0 + /** + * Adds the given record to the provided array only if it's not already in the + * array. + * + * @example + * import { utils } from 'js-data'; + * const colors = ['red', 'green', 'yellow']; + * + * console.log(colors.length); // 3 + * utils.noDupeAdd(colors, 'red'); + * console.log(colors.length); // 3, red already exists + * + * utils.noDupeAdd(colors, 'blue'); + * console.log(colors.length); // 4, blue was added + * + * @method utils.noDupeAdd + * @param {array} array The array. + * @param {*} record The value to add. + * @param {Function} fn Callback function passed to {@link utils.findIndex}. + * @since 3.0.0 */ noDupeAdd: function noDupeAdd(array, record, fn) { if (!array) { @@ -1408,22 +1491,22 @@ } }, - /** - * Return a shallow copy of the provided object, minus the properties - * specified in `keys`. - * - * @example - * import { utils } from 'js-data'; - * const a = { name: 'John', $hashKey: 1214910 }; - * - * let b = utils.omit(a, ['$hashKey']); - * console.log(b); // { name: 'John' } - * - * @method utils.omit - * @param {object} props The object to copy. - * @param {string[]} keys Array of strings, representing properties to skip. - * @returns {Object} Shallow copy of `props`, minus `keys`. - * @since 3.0.0 + /** + * Return a shallow copy of the provided object, minus the properties + * specified in `keys`. + * + * @example + * import { utils } from 'js-data'; + * const a = { name: 'John', $hashKey: 1214910 }; + * + * let b = utils.omit(a, ['$hashKey']); + * console.log(b); // { name: 'John' } + * + * @method utils.omit + * @param {object} props The object to copy. + * @param {string[]} keys Array of strings, representing properties to skip. + * @returns {Object} Shallow copy of `props`, minus `keys`. + * @since 3.0.0 */ omit: function omit(props, keys) { var _props = {}; @@ -1435,22 +1518,22 @@ return _props; }, - /** - * Return a shallow copy of the provided object, but only include the - * properties specified in `keys`. - * - * @example - * import { utils } from 'js-data'; - * const a = { name: 'John', $hashKey: 1214910 }; - * - * let b = utils.pick(a, ['$hashKey']); - * console.log(b); // { $hashKey: 1214910 } - * - * @method utils.pick - * @param {object} props The object to copy. - * @param {string[]} keys Array of strings, representing properties to keep. - * @returns {Object} Shallow copy of `props`, but only including `keys`. - * @since 3.0.0 + /** + * Return a shallow copy of the provided object, but only include the + * properties specified in `keys`. + * + * @example + * import { utils } from 'js-data'; + * const a = { name: 'John', $hashKey: 1214910 }; + * + * let b = utils.pick(a, ['$hashKey']); + * console.log(b); // { $hashKey: 1214910 } + * + * @method utils.pick + * @param {object} props The object to copy. + * @param {string[]} keys Array of strings, representing properties to keep. + * @returns {Object} Shallow copy of `props`, but only including `keys`. + * @since 3.0.0 */ pick: function pick(props, keys) { return keys.reduce(function (map, key) { @@ -1459,60 +1542,58 @@ }, {}); }, - /** - * Return a plain copy of the given value. - * - * @example - * import { utils } from 'js-data'; - * const a = { name: 'John' }; - * let b = utils.plainCopy(a); - * console.log(a === b); // false - * - * @method utils.plainCopy - * @param {*} value The value to copy. - * @returns {*} Plain copy of `value`. - * @see utils.copy - * @since 3.0.0 + /** + * Return a plain copy of the given value. + * + * @example + * import { utils } from 'js-data'; + * const a = { name: 'John' }; + * let b = utils.plainCopy(a); + * console.log(a === b); // false + * + * @method utils.plainCopy + * @param {*} value The value to copy. + * @returns {*} Plain copy of `value`. + * @see utils.copy + * @since 3.0.0 */ plainCopy: function plainCopy(value) { return utils.copy(value, undefined, undefined, undefined, undefined, true); }, - /** - * Shortcut for `utils.Promise.reject(value)`. - * - * @example - * import { utils } from 'js-data'; - * - * utils.reject("Testing static reject").then(function (data) { - * // not called - * }).catch(function (reason) { - * console.log(reason); // "Testing static reject" - * }); - * - * @method utils.reject - * @param {*} [value] Value with which to reject the Promise. - * @returns {Promise} Promise reject with `value`. - * @see utils.Promise - * @since 3.0.0 + /** + * Shortcut for `utils.Promise.reject(value)`. + * + * @example + * import { utils } from 'js-data'; + * + * utils.reject("Testing static reject").then(function (data) { + * // not called + * }).catch(function (reason) { + * console.log(reason); // "Testing static reject" + * }); + * + * @method utils.reject + * @param {*} [value] Value with which to reject the Promise. + * @returns {Promise} Promise reject with `value`. */ reject: function reject(value) { - return utils.Promise.reject(value); - }, - - /** - * Remove the last item found in array according to the given checker function. - * - * @example - * import { utils } from 'js-data'; - * - * const colors = ['red', 'green', 'yellow', 'red']; - * utils.remove(colors, (color) => color === 'red'); - * console.log(colors); // ['red', 'green', 'yellow'] - * - * @method utils.remove - * @param {array} array The array to search. - * @param {Function} fn Checker function. + return Promise.reject(value); + }, + + /** + * Remove the last item found in array according to the given checker function. + * + * @example + * import { utils } from 'js-data'; + * + * const colors = ['red', 'green', 'yellow', 'red']; + * utils.remove(colors, (color) => color === 'red'); + * console.log(colors); // ['red', 'green', 'yellow'] + * + * @method utils.remove + * @param {array} array The array to search. + * @param {Function} fn Checker function. */ remove: function remove(array, fn) { if (!array || !array.length) { @@ -1526,67 +1607,65 @@ } }, - /** - * Shortcut for `utils.Promise.resolve(value)`. - * - * @example - * import { utils } from 'js-data'; - * - * utils.resolve("Testing static resolve").then(function (data) { - * console.log(data); // "Testing static resolve" - * }).catch(function (reason) { - * // not called - * }); - * - * @param {*} [value] Value with which to resolve the Promise. - * @returns {Promise} Promise resolved with `value`. - * @see utils.Promise - * @since 3.0.0 + /** + * Shortcut for `utils.Promise.resolve(value)`. + * + * @example + * import { utils } from 'js-data'; + * + * utils.resolve("Testing static resolve").then(function (data) { + * console.log(data); // "Testing static resolve" + * }).catch(function (reason) { + * // not called + * }); + * + * @param {*} [value] Value with which to resolve the Promise. + * @returns {Promise} Promise resolved with `value`. */ resolve: function resolve(value) { - return utils.Promise.resolve(value); - }, - - /** - * Set the value at the provided key or path. - * - * @example - * import { utils } from 'js-data'; - * - * const john = { - * name: 'John', - * age: 25, - * parent: { - * name: 'John's Mom', - * age: 50 - * } - * }; - * // set value by key - * utils.set(john, 'id', 98); - * console.log(john.id); // 98 - * - * // set value by path - * utils.set(john, 'parent.id', 20); - * console.log(john.parent.id); // 20 - * - * // set value by path/value map - * utils.set(john, { - * 'id': 1098, - * 'parent': { id: 1020 }, - * 'parent.age': '55' - * }); - * console.log(john.id); // 1098 - * console.log(john.parent.id); // 1020 - * console.log(john.parent.age); // 55 - * - * @method utils.set - * @param {object} object The object on which to set a property. - * @param {(string|Object)} path The key or path to the property. Can also - * pass in an object of path/value pairs, which will all be set on the target - * object. - * @param {*} [value] The value to set. - */ - set: function set(object, path, value) { + return Promise.resolve(value); + }, + + /** + * Set the value at the provided key or path. + * + * @example + * import { utils } from 'js-data'; + * + * const john = { + * name: 'John', + * age: 25, + * parent: { + * name: 'John's Mom', + * age: 50 + * } + * }; + * // set value by key + * utils.set(john, 'id', 98); + * console.log(john.id); // 98 + * + * // set value by path + * utils.set(john, 'parent.id', 20); + * console.log(john.parent.id); // 20 + * + * // set value by path/value map + * utils.set(john, { + * 'id': 1098, + * 'parent': { id: 1020 }, + * 'parent.age': '55' + * }); + * console.log(john.id); // 1098 + * console.log(john.parent.id); // 1020 + * console.log(john.parent.age); // 55 + * + * @method utils.set + * @param {object} object The object on which to set a property. + * @param {(string|Object)} path The key or path to the property. Can also + * pass in an object of path/value pairs, which will all be set on the target + * object. + * @param {*} [value] The value to set. + */ + set: function set(object, path, value, opts) { if (utils.isObject(path)) { utils.forOwn(path, function (value, _path) { utils.set(object, _path, value); @@ -1602,40 +1681,40 @@ } }, - /** - * Check whether the two provided objects are deeply equal. - * - * @example - * import { utils } from 'js-data'; - * - * const objA = { - * name: 'John', - * id: 27, - * nested: { - * item: 'item 1', - * colors: ['red', 'green', 'blue'] - * } - * }; - * - * const objB = { - * name: 'John', - * id: 27, - * nested: { - * item: 'item 1', - * colors: ['red', 'green', 'blue'] - * } - * }; - * - * console.log(utils.deepEqual(a,b)); // true - * objB.nested.colors.add('yellow'); // make a change to a nested object's array - * console.log(utils.deepEqual(a,b)); // false - * - * @method utils.deepEqual - * @param {object} a First object in the comparison. - * @param {object} b Second object in the comparison. - * @returns {boolean} Whether the two provided objects are deeply equal. - * @see utils.equal - * @since 3.0.0 + /** + * Check whether the two provided objects are deeply equal. + * + * @example + * import { utils } from 'js-data'; + * + * const objA = { + * name: 'John', + * id: 27, + * nested: { + * item: 'item 1', + * colors: ['red', 'green', 'blue'] + * } + * }; + * + * const objB = { + * name: 'John', + * id: 27, + * nested: { + * item: 'item 1', + * colors: ['red', 'green', 'blue'] + * } + * }; + * + * console.log(utils.deepEqual(a,b)); // true + * objB.nested.colors.add('yellow'); // make a change to a nested object's array + * console.log(utils.deepEqual(a,b)); // false + * + * @method utils.deepEqual + * @param {object} a First object in the comparison. + * @param {object} b Second object in the comparison. + * @returns {boolean} Whether the two provided objects are deeply equal. + * @see utils.equal + * @since 3.0.0 */ deepEqual: function deepEqual(a, b) { if (a === b) { @@ -1678,50 +1757,50 @@ return _equal; }, - /** - * Proxy for `JSON.stringify`. - * - * @example - * import { utils } from 'js-data'; - * - * const a = { name: 'John' }; - * let jsonVal = utils.toJson(a); - * console.log(jsonVal); // '{"name" : "John"}' - * - * @method utils.toJson - * @param {*} value Value to serialize to JSON. - * @returns {string} JSON string. - * @see utils.fromJson - * @since 3.0.0 + /** + * Proxy for `JSON.stringify`. + * + * @example + * import { utils } from 'js-data'; + * + * const a = { name: 'John' }; + * let jsonVal = utils.toJson(a); + * console.log(jsonVal); // '{"name" : "John"}' + * + * @method utils.toJson + * @param {*} value Value to serialize to JSON. + * @returns {string} JSON string. + * @see utils.fromJson + * @since 3.0.0 */ toJson: JSON.stringify, - /** - * Unset the value at the provided key or path. - * - * @example - * import { utils } from 'js-data'; - * - * const john = { - * name: 'John', - * age: 25, - * parent: { - * name: 'John's Mom', - * age: 50 - * } - * }; - * - * utils.unset(john, age); - * utils.unset(john, parent.age); - * - * console.log(john.age); // null - * console.log(john.parent.age); // null - * - * @method utils.unset - * @param {object} object The object from which to delete the property. - * @param {string} path The key or path to the property. - * @see utils.set - * @since 3.0.0 + /** + * Unset the value at the provided key or path. + * + * @example + * import { utils } from 'js-data'; + * + * const john = { + * name: 'John', + * age: 25, + * parent: { + * name: 'John's Mom', + * age: 50 + * } + * }; + * + * utils.unset(john, age); + * utils.unset(john, parent.age); + * + * console.log(john.age); // null + * console.log(john.parent.age); // null + * + * @method utils.unset + * @param {object} object The object from which to delete the property. + * @param {string} path The key or path to the property. + * @see utils.set + * @since 3.0.0 */ unset: function unset(object, path) { var parts = path.split('.'); @@ -1738,376 +1817,146 @@ } object[last] = undefined; + }, + + /** + * Gets default locale for the js-data context. + * + * @example + * import { utils } from 'js-data'; + * + * + * utils.getDefaultLocale(); + * + * @method utils.getDefaultLocale + * @since 4.0.0 + */ + getDefaultLocale: function getDefaultLocale() { + return 'en'; } }; var safeSetProp = function safeSetProp(record, field, value) { - if (record && record._set) { + var _a; + + if ((_a = record) === null || _a === void 0 ? void 0 : _a._set) { record._set("props.".concat(field), value); } else { utils.set(record, field, value); } }; var safeSetLink = function safeSetLink(record, field, value) { - if (record && record._set) { + var _a; + + if ((_a = record) === null || _a === void 0 ? void 0 : _a._set) { record._set("links.".concat(field), value); } else { utils.set(record, field, value); } }; - /** - * A base class which gives instances private properties. - * - * Typically you won't instantiate this class directly, but you may find it - * useful as an abstract class for your own components. - * - * See {@link Settable.extend} for an example of using {@link Settable} as a - * base class. - * - *```javascript - * import {Settable} from 'js-data' - * ``` - * - * @class Settable - * @returns {Settable} A new {@link Settable} instance. - * @since 3.0.0 + /** + * A base class which gives instances private properties. + * + * Typically you won't instantiate this class directly, but you may find it + * useful as an abstract class for your own components. + * + * @example + * import {Settable} from 'js-data'; + * + * class CustomSettableClass extends Settable { + * foo () { return 'bar'; } + * static beep () { return 'boop'; } + * } + * + * const customSettable = new CustomSettableClass(); + * console.log(customSettable.foo()); + * console.log(CustomSettableClass.beep()); + * + * @since 3.0.0 */ - function Settable() { + var Settable = function Settable() { + _classCallCheck(this, Settable); + var _props = {}; Object.defineProperties(this, { - /** - * Get a private property of this instance. - * - * __Don't use the method unless you know what you're doing.__ - * - * @method Settable#_get - * @param {string} key The property to retrieve. - * @returns {*} The value of the property. - * @since 3.0.0 - */ _get: { value: function value(key) { return utils.get(_props, key); } }, - - /** - * Set a private property of this instance. - * - * __Don't use the method unless you know what you're doing.__ - * - * @method __Don't use the method unless you know what you're doing.__#_set - * @param {(string|Object)} key The key or path to the property. Can also - * pass in an object of key/value pairs, which will all be set on the instance. - * @param {*} [value] The value to set. - * @since 3.0.0 - */ _set: { value: function value(key, _value) { return utils.set(_props, key, _value); } }, - - /** - * Unset a private property of this instance. - * - * __Don't use the method unless you know what you're doing.__ - * - * @method __Don't use the method unless you know what you're doing.__#_unset - * @param {string} key The property to unset. - * @since 3.0.0 - */ _unset: { value: function value(key) { return utils.unset(_props, key); } } }); - } - /** - * Create a subclass of this Settable: - * - * @example Settable.extend - * const JSData = require('js-data'); - * const { Settable } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * // Extend the class using ES2015 class syntax. - * class CustomSettableClass extends Settable { - * foo () { return 'bar'; } - * static beep () { return 'boop'; } - * } - * const customSettable = new CustomSettableClass(); - * console.log(customSettable.foo()); - * console.log(CustomSettableClass.beep()); - * - * // Extend the class using alternate method. - * const OtherSettableClass = Settable.extend({ - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }); - * const otherSettable = new OtherSettableClass(); - * console.log(otherSettable.foo()); - * console.log(OtherSettableClass.beep()); - * - * // Extend the class, providing a custom constructor. - * function AnotherSettableClass () { - * Settable.call(this); - * this.created_at = new Date().getTime(); - * } - * Settable.extend({ - * constructor: AnotherSettableClass, - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }) - * const anotherSettable = new AnotherSettableClass(); - * console.log(anotherSettable.created_at); - * console.log(anotherSettable.foo()); - * console.log(AnotherSettableClass.beep()); - * - * @method Settable.extend - * @param {object} [props={}] Properties to add to the prototype of the - * subclass. - * @param {object} [props.constructor] Provide a custom constructor function - * to be used as the subclass itself. - * @param {object} [classProps={}] Static properties to add to the subclass. - * @returns {Constructor} Subclass of this Settable class. - * @since 3.0.0 - */ + }; - Settable.extend = utils.extend; - - /** - * The base class from which all JSData components inherit some basic - * functionality. - * - * Typically you won't instantiate this class directly, but you may find it - * useful as an abstract class for your own components. - * - * See {@link Component.extend} for an example of using {@link Component} as a - * base class. - * - *```javascript - * import {Component} from 'js-data' - * ``` - * - * @class Component - * @param {object} [opts] Configuration options. - * @param {boolean} [opts.debug=false] See {@link Component#debug}. - * @returns {Component} A new {@link Component} instance. - * @since 3.0.0 + /** + * The base class from which all JSData components inherit some basic + * functionality. + * + * Typically you won't instantiate this class directly, but you may find it + * useful as an abstract class for your own components. + * + * @example + * import {Component} from 'js-data' + * + * class CustomComponentClass extends Component { + * foo () { return 'bar'; } + * static beep () { return 'boop'; } + * } + * const customComponent = new CustomComponentClass(); + * console.log(customComponent.foo()); + * console.log(CustomComponentClass.beep()); + * ``` + * + * @param {object} [opts] Configuration options. + * @param {boolean} [opts.debug=false] See {@link Component#debug}. + * @returns {Component} A new {@link Component} instance. + * @since 3.0.0 */ - function Component(opts) { - Settable.call(this); - opts || (opts = {}); - /** - * Whether to enable debug-level logs for this component. Anything that - * extends `Component` inherits this option and the corresponding logging - * functionality. - * - * @example Component#debug - * const JSData = require('js-data'); - * const { Component } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const component = new Component(); - * component.log('debug', 'some message'); // nothing gets logged - * // Display debug logs: - * component.debug = true; - * component.log('debug', 'other message'); // this DOES get logged - * - * @default false - * @name Component#debug - * @since 3.0.0 - * @type {boolean} - */ - - this.debug = Object.hasOwnProperty.call(opts, 'debug') ? !!opts.debug : false; - /** - * Event listeners attached to this Component. __Do not modify.__ Use - * {@link Component#on} and {@link Component#off} instead. - * - * @name Component#_listeners - * @private - * @instance - * @since 3.0.0 - * @type {Object} - */ - - Object.defineProperty(this, '_listeners', { - value: {}, - writable: true - }); - } + var Component = + /*#__PURE__*/ + function (_Settable) { + _inherits(Component, _Settable); - var Component$1 = Settable.extend({ - constructor: Component - }); - /** - * Create a subclass of this Component: - * - * @example Component.extend - * const JSData = require('js-data'); - * const { Component } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * // Extend the class using ES2015 class syntax. - * class CustomComponentClass extends Component { - * foo () { return 'bar'; } - * static beep () { return 'boop'; } - * } - * const customComponent = new CustomComponentClass(); - * console.log(customComponent.foo()); - * console.log(CustomComponentClass.beep()); - * - * // Extend the class using alternate method. - * const OtherComponentClass = Component.extend({ - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }); - * const otherComponent = new OtherComponentClass(); - * console.log(otherComponent.foo()); - * console.log(OtherComponentClass.beep()); - * - * // Extend the class, providing a custom constructor. - * function AnotherComponentClass () { - * Component.call(this); - * this.created_at = new Date().getTime(); - * } - * Component.extend({ - * constructor: AnotherComponentClass, - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }) - * const anotherComponent = new AnotherComponentClass(); - * console.log(anotherComponent.created_at); - * console.log(anotherComponent.foo()); - * console.log(AnotherComponentClass.beep()); - * - * @method Component.extend - * @param {object} [props={}] Properties to add to the prototype of the - * subclass. - * @param {object} [props.constructor] Provide a custom constructor function - * to be used as the subclass itself. - * @param {object} [classProps={}] Static properties to add to the subclass. - * @returns {Constructor} Subclass of this Component class. - * @since 3.0.0 - */ + function Component() { + var _this; - Component.extend = utils.extend; - /** - * Log the provided values at the "debug" level. Debug-level logs are only - * logged if {@link Component#debug} is `true`. - * - * `.dbg(...)` is shorthand for `.log('debug', ...)`. - * - * @method Component#dbg - * @param {...*} [args] Values to log. - * @since 3.0.0 - */ + var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - /** - * Log the provided values. By default sends values to `console[level]`. - * Debug-level logs are only logged if {@link Component#debug} is `true`. - * - * Will attempt to use appropriate `console` methods if they are available. - * - * @method Component#log - * @param {string} level Log level. - * @param {...*} [args] Values to log. - * @since 3.0.0 - */ + _classCallCheck(this, Component); - utils.logify(Component.prototype); - /** - * Register a new event listener on this Component. - * - * @example - * // Listen for all "afterCreate" events in a DataStore - * store.on('afterCreate', (mapperName, props, opts, result) => { - * console.log(mapperName); // "post" - * console.log(props.id); // undefined - * console.log(result.id); // 1234 - * }); - * store.create('post', { title: 'Modeling your data' }).then((post) => { - * console.log(post.id); // 1234 - * }); - * - * @example - * // Listen for the "add" event on a collection - * collection.on('add', (records) => { - * console.log(records); // [...] - * }); - * - * @example - * // Listen for "change" events on a record - * post.on('change', (record, changes) => { - * console.log(changes); // { changed: { title: 'Modeling your data' } } - * }); - * post.title = 'Modeling your data'; - * - * @method Component#on - * @param {string} event Name of event to subsribe to. - * @param {Function} listener Listener function to handle the event. - * @param {*} [ctx] Optional content in which to invoke the listener. - * @since 3.0.0 - */ + var _a; - /** - * Remove an event listener from this Component. If no listener is provided, - * then all listeners for the specified event will be removed. If no event is - * specified then all listeners for all events will be removed. - * - * @example - * // Remove a particular listener for a particular event - * collection.off('add', handler); - * - * @example - * // Remove all listeners for a particular event - * record.off('change'); - * - * @example - * // Remove all listeners to all events - * store.off(); - * - * @method Component#off - * @param {string} [event] Name of event to unsubsribe to. - * @param {Function} [listener] Listener to remove. - * @since 3.0.0 - */ + _this = _possibleConstructorReturn(this, _getPrototypeOf(Component).call(this)); + /** + * Event listeners attached to this Component. __Do not modify.__ Use + * {@link Component#on} and {@link Component#off} instead. + * + * @name Component#_listeners + * @private + * @instance + * @since 3.0.0 + * @type {Object} + */ - /** - * Trigger an event on this Component. - * - * @example Component#emit - * // import { Collection, DataStore } from 'js-data'; - * const JSData = require('js-data'); - * const { Collection, DataStore } = JSData; - * - * const collection = new Collection(); - * collection.on('foo', function (msg) { - * console.log(msg); - * }); - * collection.emit('foo', 'bar'); - * - * const store = new DataStore(); - * store.on('beep', function (msg) { - * console.log(msg); - * }); - * store.emit('beep', 'boop'); - * - * @method Component#emit - * @param {string} event Name of event to emit. - * @param {...*} [args] Arguments to pass to any listeners. - * @since 3.0.0 - */ + _this._listeners = {}; + _this.debug = (_a = opts.debug, _a !== null && _a !== void 0 ? _a : false); + return _this; + } + return Component; + }(Settable); + utils.logify(Component.prototype); utils.eventify(Component.prototype, function () { return this._listeners; }, function (value) { @@ -2123,1684 +1972,1382 @@ orderBy: '', skip: '', sort: '', - where: '' + where: '', + locale: '' }; // Used by our JavaScript implementation of the LIKE operator var escapeRegExp = /([.*+?^=!:${}()|[\]/\\])/g; var percentRegExp = /%/g; var underscoreRegExp = /_/g; - var escape = function escape(pattern) { + function escape(pattern) { return pattern.replace(escapeRegExp, '\\$1'); - }; - /** - * A class used by the {@link Collection} class to build queries to be executed - * against the collection's data. An instance of `Query` is returned by - * {@link Collection#query}. Query instances are typically short-lived, and you - * shouldn't have to create them yourself. Just use {@link Collection#query}. - * - * ```javascript - * import { Query } from 'js-data'; - * ``` - * - * @example Query intro - * const JSData = require('js-data'); - * const { DataStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new DataStore(); - * store.defineMapper('post'); - * const posts = [ - * { author: 'John', age: 30, status: 'published', id: 1 }, - * { author: 'Sally', age: 31, status: 'draft', id: 2 }, - * { author: 'Mike', age: 32, status: 'draft', id: 3 }, - * { author: 'Adam', age: 33, status: 'deleted', id: 4 }, - * { author: 'Adam', age: 33, status: 'draft', id: 5 } - * ] - * store.add('post', posts); - * const drafts = store.query('post').filter({ status: 'draft' }).limit(2).run(); - * console.log(drafts); - * - * @class Query - * @extends Component - * @param {Collection} collection The collection on which this query operates. - * @since 3.0.0 + } + /** + * A class used by the {@link Collection} class to build queries to be executed + * against the collection's data. An instance of `Query` is returned by + * {@link Collection#query}. Query instances are typically short-lived, and you + * shouldn't have to create them yourself. Just use {@link Collection#query}. + * + * ```javascript + * import { Query } from 'js-data'; + * ``` + * + * @example Query intro + * const JSData = require('js-data'); + * const { DataStore } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new DataStore(); + * store.defineMapper('post'); + * const posts = [ + * { author: 'John', age: 30, status: 'published', id: 1 }, + * { author: 'Sally', age: 31, status: 'draft', id: 2 }, + * { author: 'Mike', age: 32, status: 'draft', id: 3 }, + * { author: 'Adam', age: 33, status: 'deleted', id: 4 }, + * { author: 'Adam', age: 33, status: 'draft', id: 5 } + * ] + * store.add('post', posts); + * const drafts = store.query('post').filter({ status: 'draft' }).limit(2).run(); + * console.log(drafts); + * + * @class Query + * @extends Component + * @param {Collection} collection The collection on which this query operates. + * @since 3.0.0 */ - function Query(collection) { - utils.classCallCheck(this, Query); - /** - * The {@link Collection} on which this query operates. - * - * @name Query#collection - * @since 3.0.0 - * @type {Collection} - */ + var Query = + /*#__PURE__*/ + function (_Component) { + _inherits(Query, _Component); - this.collection = collection; - /** - * The current data result of this query. - * - * @name Query#data - * @since 3.0.0 - * @type {Array} - */ + function Query(collection) { + var _this; - this.data = null; - } + _classCallCheck(this, Query); - var Query$1 = Component$1.extend({ - constructor: Query, - _applyWhereFromObject: function _applyWhereFromObject(where) { - var fields = []; - var ops = []; - var predicates = []; - utils.forOwn(where, function (clause, field) { - if (!utils.isObject(clause)) { - clause = { - '==': clause - }; - } + _this = _possibleConstructorReturn(this, _getPrototypeOf(Query).call(this)); + _this.collection = collection; + /** + * The current data result of this query. + * + * @name Query#data + * @since 3.0.0 + * @type {Array} + */ - utils.forOwn(clause, function (expr, op) { - fields.push(field); - ops.push(op); - predicates.push(expr); - }); - }); - return { - fields: fields, - ops: ops, - predicates: predicates - }; - }, - _applyWhereFromArray: function _applyWhereFromArray(where) { - var _this = this; + _this.data = null; + return _this; + } - var groups = []; - where.forEach(function (_where, i) { - if (utils.isString(_where)) { - return; - } + _createClass(Query, [{ + key: "_applyWhereFromObject", + value: function _applyWhereFromObject(where) { + var fields = []; + var ops = []; + var predicates = []; + utils.forOwn(where, function (clause, field) { + if (!utils.isObject(clause)) { + clause = { + '==': clause + }; + } - var prev = where[i - 1]; - var parser = utils.isArray(_where) ? _this._applyWhereFromArray : _this._applyWhereFromObject; - var group = parser.call(_this, _where); + utils.forOwn(clause, function (expr, op) { + fields.push(field); + ops.push(op); + predicates.push(expr); + }); + }); + return { + fields: fields, + ops: ops, + predicates: predicates + }; + } + }, { + key: "_applyWhereFromArray", + value: function _applyWhereFromArray(where) { + var _this2 = this; - if (prev === 'or') { - group.isOr = true; - } + var groups = []; + where.forEach(function (_where, i) { + if (utils.isString(_where)) { + return; + } - groups.push(group); - }); - groups.isArray = true; - return groups; - }, - _testObjectGroup: function _testObjectGroup(keep, first, group, item) { - var i; - var fields = group.fields; - var ops = group.ops; - var predicates = group.predicates; - var len = ops.length; + var prev = where[i - 1]; + var parser = utils.isArray(_where) ? _this2._applyWhereFromArray : _this2._applyWhereFromObject; + var group = parser.call(_this2, _where); - for (i = 0; i < len; i++) { - var op = ops[i]; - var isOr = op.charAt(0) === '|'; - op = isOr ? op.substr(1) : op; - var expr = this.evaluate(utils.get(item, fields[i]), op, predicates[i]); + if (prev === 'or') { + group.isOr = true; + } + + groups.push(group); + }); + groups.isArray = true; + return groups; + } + }, { + key: "_testObjectGroup", + value: function _testObjectGroup(keep, first, group, item) { + var i; + var fields = group.fields; + var ops = group.ops; + var predicates = group.predicates; + var len = ops.length; + + for (i = 0; i < len; i++) { + var op = ops[i]; + var isOr = op.charAt(0) === '|'; + op = isOr ? op.substr(1) : op; + var expr = this.evaluate(utils.get(item, fields[i]), op, predicates[i]); + + if (expr !== undefined) { + keep = first ? expr : isOr ? keep || expr : keep && expr; + } - if (expr !== undefined) { - keep = first ? expr : isOr ? keep || expr : keep && expr; + first = false; } - first = false; + return { + keep: keep, + first: first + }; } + }, { + key: "_testArrayGroup", + value: function _testArrayGroup(keep, first, groups, item) { + var i; + var len = groups.length; - return { - keep: keep, - first: first - }; - }, - _testArrayGroup: function _testArrayGroup(keep, first, groups, item) { - var i; - var len = groups.length; - - for (i = 0; i < len; i++) { - var group = groups[i]; - var parser = group.isArray ? this._testArrayGroup : this._testObjectGroup; - var result = parser.call(this, true, true, group, item); + for (i = 0; i < len; i++) { + var group = groups[i]; + var parser = group.isArray ? this._testArrayGroup : this._testObjectGroup; + var result = parser.call(this, true, true, group, item); - if (groups[i - 1]) { - if (group.isOr) { - keep = keep || result.keep; + if (groups[i - 1]) { + if (group.isOr) { + keep = keep || result.keep; + } else { + keep = keep && result.keep; + } } else { - keep = keep && result.keep; + keep = result.keep; } - } else { - keep = result.keep; + + first = result.first; } - first = result.first; + return { + keep: keep, + first: first + }; } + /** + * Find all entities between two boundaries. + * + * @example Get the users ages 18 to 30. + * const JSData = require('js-data'); + * const { DataStore } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new DataStore(); + * store.defineMapper('user'); + * const users = [ + * { name: 'Peter', age: 25, id: 1 }, + * { name: 'Jim', age: 19, id: 2 }, + * { name: 'Mike', age: 17, id: 3 }, + * { name: 'Alan', age: 29, id: 4 }, + * { name: 'Katie', age: 33, id: 5 } + * ]; + * store.add('user', users) + * const filteredUsers = store + * .query('user') + * .between(18, 30, { index: 'age' }) + * .run(); + * console.log(filteredUsers); + * + * @example Same as above. + * const JSData = require('js-data'); + * const { DataStore } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new DataStore(); + * store.defineMapper('user'); + * const users = [ + * { name: 'Peter', age: 25, id: 1 }, + * { name: 'Jim', age: 19, id: 2 }, + * { name: 'Mike', age: 17, id: 3 }, + * { name: 'Alan', age: 29, id: 4 }, + * { name: 'Katie', age: 33, id: 5 } + * ]; + * store.add('user', users) + * const filteredUsers = store + * .query('user') + * .between([18], [30], { index: 'age' }) + * .run(); + * console.log(filteredUsers); + * + * @method Query#between + * @param {array} leftKeys Keys defining the left boundary. + * @param {array} rightKeys Keys defining the right boundary. + * @param {object} [opts] Configuration options. + * @param {string} [opts.index] Name of the secondary index to use in the + * query. If no index is specified, the main index is used. + * @param {boolean} [opts.leftInclusive=true] Whether to include entities + * on the left boundary. + * @param {boolean} [opts.rightInclusive=false] Whether to include entities + * on the left boundary. + * @param {boolean} [opts.limit] Limit the result to a certain number. + * @param {boolean} [opts.offset] The number of resulting entities to skip. + * @returns {Query} A reference to itself for chaining. + * @since 3.0.0 + */ - return { - keep: keep, - first: first - }; - }, + }, { + key: "between", + value: function between(leftKeys, rightKeys) { + var opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; - /** - * Find all entities between two boundaries. - * - * @example Get the users ages 18 to 30. - * const JSData = require('js-data'); - * const { DataStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new DataStore(); - * store.defineMapper('user'); - * const users = [ - * { name: 'Peter', age: 25, id: 1 }, - * { name: 'Jim', age: 19, id: 2 }, - * { name: 'Mike', age: 17, id: 3 }, - * { name: 'Alan', age: 29, id: 4 }, - * { name: 'Katie', age: 33, id: 5 } - * ]; - * store.add('user', users) - * const filteredUsers = store - * .query('user') - * .between(18, 30, { index: 'age' }) - * .run(); - * console.log(filteredUsers); - * - * @example Same as above. - * const JSData = require('js-data'); - * const { DataStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new DataStore(); - * store.defineMapper('user'); - * const users = [ - * { name: 'Peter', age: 25, id: 1 }, - * { name: 'Jim', age: 19, id: 2 }, - * { name: 'Mike', age: 17, id: 3 }, - * { name: 'Alan', age: 29, id: 4 }, - * { name: 'Katie', age: 33, id: 5 } - * ]; - * store.add('user', users) - * const filteredUsers = store - * .query('user') - * .between([18], [30], { index: 'age' }) - * .run(); - * console.log(filteredUsers); - * - * @method Query#between - * @param {array} leftKeys Keys defining the left boundary. - * @param {array} rightKeys Keys defining the right boundary. - * @param {object} [opts] Configuration options. - * @param {string} [opts.index] Name of the secondary index to use in the - * query. If no index is specified, the main index is used. - * @param {boolean} [opts.leftInclusive=true] Whether to include entities - * on the left boundary. - * @param {boolean} [opts.rightInclusive=false] Whether to include entities - * on the left boundary. - * @param {boolean} [opts.limit] Limit the result to a certain number. - * @param {boolean} [opts.offset] The number of resulting entities to skip. - * @returns {Query} A reference to itself for chaining. - * @since 3.0.0 - */ - between: function between(leftKeys, rightKeys, opts) { - opts || (opts = {}); + if (this.data) { + throw utils.err("".concat(DOMAIN$1, "#between"))(500, 'Cannot access index'); + } - if (this.data) { - throw utils.err("".concat(DOMAIN$1, "#between"))(500, 'Cannot access index'); + this.data = this.collection.getIndex(opts.index).between(leftKeys, rightKeys, opts); + return this; } + /** + * The comparison function used by the {@link Query} class. + * + * @method Query#compare + * @param {array} orderBy An orderBy clause used for sorting and sub-sorting. + * @param {number} index The index of the current orderBy clause being used. + * @param {*} a The first item in the comparison. + * @param {*} b The second item in the comparison. + * @returns {number} -1 if `b` should preceed `a`. 0 if `a` and `b` are equal. + * 1 if `a` should preceed `b`. + * @since 3.0.0 + */ - this.data = this.collection.getIndex(opts.index).between(leftKeys, rightKeys, opts); - return this; - }, + }, { + key: "compare", + value: function compare(orderBy, index, a, b, _compare) { + var def = orderBy[index]; + var cA = utils.get(a, def[0]); + var cB = utils.get(b, def[0]); - /** - * The comparison function used by the {@link Query} class. - * - * @method Query#compare - * @param {array} orderBy An orderBy clause used for sorting and sub-sorting. - * @param {number} index The index of the current orderBy clause being used. - * @param {*} a The first item in the comparison. - * @param {*} b The second item in the comparison. - * @returns {number} -1 if `b` should preceed `a`. 0 if `a` and `b` are equal. - * 1 if `a` should preceed `b`. - * @since 3.0.0 - */ - compare: function compare(orderBy, index, a, b) { - var def = orderBy[index]; - var cA = utils.get(a, def[0]); - var cB = utils.get(b, def[0]); + if (cA && utils.isString(cA)) { + cA = cA.toUpperCase(); + } - if (cA && utils.isString(cA)) { - cA = cA.toUpperCase(); - } + if (cB && utils.isString(cB)) { + cB = cB.toUpperCase(); + } - if (cB && utils.isString(cB)) { - cB = cB.toUpperCase(); - } + if (a === undefined) { + a = null; + } - if (a === undefined) { - a = null; - } + if (b === undefined) { + b = null; + } - if (b === undefined) { - b = null; - } + if (def[1].toUpperCase() === 'DESC') { + var temp = cB; + cB = cA; + cA = temp; + } + /* Fix: compare by using collator */ + // let isNumeric = false + // if (utils.isNumber(cA) || utils.isNumber(cB)) { + // isNumeric = true + // } - if (def[1].toUpperCase() === 'DESC') { - var temp = cB; - cB = cA; - cA = temp; - } - if (cA < cB) { - return -1; - } else if (cA > cB) { - return 1; - } else { - if (index < orderBy.length - 1) { - return this.compare(orderBy, index + 1, a, b); + var n = _compare(cA, cB); + + if (n === -1 || n === 1) { + return n; } else { - return 0; + if (index < orderBy.length - 1) { + return this.compare(orderBy, index + 1, a, b, _compare); + } else { + return 0; + } } } - }, + /** + * Predicate evaluation function used by the {@link Query} class. + * + * @method Query#evaluate + * @param {*} value The value to evaluate. + * @param {string} op The operator to use in this evaluation. + * @param {*} predicate The predicate to use in this evaluation. + * @returns {boolean} Whether the value passed the evaluation or not. + * @since 3.0.0 + */ - /** - * Predicate evaluation function used by the {@link Query} class. - * - * @method Query#evaluate - * @param {*} value The value to evaluate. - * @param {string} op The operator to use in this evaluation. - * @param {*} predicate The predicate to use in this evaluation. - * @returns {boolean} Whether the value passed the evaluation or not. - * @since 3.0.0 - */ - evaluate: function evaluate(value, op, predicate) { - var ops = this.constructor.ops; + }, { + key: "evaluate", + value: function evaluate(value, op, predicate) { + var ops = Query.ops; - if (ops[op]) { - return ops[op](value, predicate); - } + if (ops[op]) { + return ops[op](value, predicate); + } - if (op.indexOf('like') === 0) { - return this.like(predicate, op.substr(4)).exec(value) !== null; - } else if (op.indexOf('notLike') === 0) { - return this.like(predicate, op.substr(7)).exec(value) === null; + if (op.indexOf('like') === 0) { + return this.like(predicate, op.substr(4)).exec(value) !== null; + } else if (op.indexOf('notLike') === 0) { + return this.like(predicate, op.substr(7)).exec(value) === null; + } } - }, + /** + * Find the record or records that match the provided query or are accepted by + * the provided filter function. + * + * @example Get the draft posts by authors younger than 30 + * const JSData = require('js-data'); + * const { DataStore } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new DataStore(); + * store.defineMapper('post') + * const posts = [ + * { author: 'John', age: 30, status: 'published', id: 1 }, + * { author: 'Sally', age: 31, status: 'published', id: 2 }, + * { author: 'Mike', age: 32, status: 'draft', id: 3 }, + * { author: 'Adam', age: 33, status: 'deleted', id: 4 }, + * { author: 'Adam', age: 33, status: 'published', id: 5 } + * { author: 'Peter', age: 25, status: 'deleted', id: 6 }, + * { author: 'Sally', age: 21, status: 'draft', id: 7 }, + * { author: 'Jim', age: 27, status: 'draft', id: 8 }, + * { author: 'Jim', age: 27, status: 'published', id: 9 }, + * { author: 'Jason', age: 55, status: 'published', id: 10 } + * ]; + * store.add('post', posts); + * const results = store + * .query('post') + * .filter({ + * where: { + * status: { + * '==': 'draft' + * }, + * age: { + * '<': 30 + * } + * } + * }) + * .run(); + * console.log(results); + * + * @example Use a custom filter function + * const posts = query + * .filter(function (post) { + * return post.isReady(); + * }) + * .run(); + * + * @method Query#filter + * @param {(Object|Function)} [query={}] Selection query or filter + * function. + * @param {Function} [thisArg] Context to which to bind `queryOrFn` if + * `queryOrFn` is a function. + * @returns {Query} A reference to itself for chaining. + * @since 3.0.0 + */ - /** - * Find the record or records that match the provided query or are accepted by - * the provided filter function. - * - * @example Get the draft posts by authors younger than 30 - * const JSData = require('js-data'); - * const { DataStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new DataStore(); - * store.defineMapper('post') - * const posts = [ - * { author: 'John', age: 30, status: 'published', id: 1 }, - * { author: 'Sally', age: 31, status: 'published', id: 2 }, - * { author: 'Mike', age: 32, status: 'draft', id: 3 }, - * { author: 'Adam', age: 33, status: 'deleted', id: 4 }, - * { author: 'Adam', age: 33, status: 'published', id: 5 } - * { author: 'Peter', age: 25, status: 'deleted', id: 6 }, - * { author: 'Sally', age: 21, status: 'draft', id: 7 }, - * { author: 'Jim', age: 27, status: 'draft', id: 8 }, - * { author: 'Jim', age: 27, status: 'published', id: 9 }, - * { author: 'Jason', age: 55, status: 'published', id: 10 } - * ]; - * store.add('post', posts); - * const results = store - * .query('post') - * .filter({ - * where: { - * status: { - * '==': 'draft' - * }, - * age: { - * '<': 30 - * } - * } - * }) - * .run(); - * console.log(results); - * - * @example Use a custom filter function - * const posts = query - * .filter(function (post) { - * return post.isReady(); - * }) - * .run(); - * - * @method Query#filter - * @param {(Object|Function)} [queryOrFn={}] Selection query or filter - * function. - * @param {Function} [thisArg] Context to which to bind `queryOrFn` if - * `queryOrFn` is a function. - * @returns {Query} A reference to itself for chaining. - * @since 3.0.0 - */ - filter: function filter(query, thisArg) { - var _this2 = this; - - /** - * Selection query as defined by JSData's [Query Syntax][querysyntax]. - * - * [querysyntax]: http://www.js-data.io/v3.0/docs/query-syntax - * - * @example Empty "findAll" query - * const JSData = require('js-data'); - * const { DataStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new DataStore(); - * store.defineMapper('post') - * store.findAll('post').then((posts) => { - * console.log(posts); // [...] - * }); - * - * @example Empty "filter" query - * const JSData = require('js-data'); - * const { DataStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new DataStore(); - * store.defineMapper('post'); - * const posts = store.filter('post'); - * console.log(posts); // [...] - * - * @example Complex "filter" query - * const JSData = require('js-data'); - * const { DataStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new DataStore(); - * const PAGE_SIZE = 2; - * let currentPage = 3; - * - * store.defineMapper('post'); - * const posts = [ - * { author: 'John', age: 30, status: 'published', id: 1 }, - * { author: 'Sally', age: 31, status: 'published', id: 2 }, - * { author: 'Mike', age: 32, status: 'draft', id: 3 }, - * { author: 'Adam', age: 33, status: 'deleted', id: 4 }, - * { author: 'Adam', age: 33, status: 'published', id: 5 } - * { author: 'Peter', age: 25, status: 'deleted', id: 6 }, - * { author: 'Sally', age: 21, status: 'draft', id: 7 }, - * { author: 'Jim', age: 27, status: 'draft', id: 8 }, - * { author: 'Jim', age: 27, status: 'published', id: 9 }, - * { author: 'Jason', age: 55, status: 'published', id: 10 } - * ]; - * store.add('post', posts); - * // Retrieve a filtered page of blog posts - * // Would typically replace filter with findAll - * const results = store.filter('post', { - * where: { - * status: { - * // WHERE status = 'published' - * '==': 'published' - * }, - * author: { - * // AND author IN ('bob', 'alice') - * 'in': ['bob', 'alice'], - * // OR author IN ('karen') - * '|in': ['karen'] - * } - * }, - * orderBy: [ - * // ORDER BY date_published DESC, - * ['date_published', 'DESC'], - * // ORDER BY title ASC - * ['title', 'ASC'] - * ], - * // LIMIT 2 - * limit: PAGE_SIZE, - * // SKIP 4 - * offset: PAGE_SIZE * (currentPage - 1) - * }); - * console.log(results); - * - * @namespace query - * @property {number} [limit] See {@link query.limit}. - * @property {number} [offset] See {@link query.offset}. - * @property {string|Array[]} [orderBy] See {@link query.orderBy}. - * @property {number} [skip] Alias for {@link query.offset}. - * @property {string|Array[]} [sort] Alias for {@link query.orderBy}. - * @property {Object} [where] See {@link query.where}. - * @since 3.0.0 - * @tutorial ["http://www.js-data.io/v3.0/docs/query-syntax","JSData's Query Syntax"] - */ - query || (query = {}); - this.getData(); - - if (utils.isObject(query)) { - var where = {}; - /** - * Filtering criteria. Records that do not meet this criteria will be exluded - * from the result. - * - * @example Return posts where author is at least 32 years old - * const JSData = require('js-data'); - * const { DataStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new DataStore(); - * store.defineMapper('post') - * const posts = [ - * { author: 'John', age: 30, id: 5 }, - * { author: 'Sally', age: 31, id: 6 }, - * { author: 'Mike', age: 32, id: 7 }, - * { author: 'Adam', age: 33, id: 8 }, - * { author: 'Adam', age: 33, id: 9 } - * ]; - * store.add('post', posts); - * const results = store.filter('post', { - * where: { - * age: { - * '>=': 30 - * } - * } - * }); - * console.log(results); - * - * @name query.where - * @type {Object} - * @see http://www.js-data.io/v3.0/docs/query-syntax - * @since 3.0.0 + }, { + key: "filter", + value: function filter() { + var _this3 = this; + + var query = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + var thisArg = arguments.length > 1 ? arguments[1] : undefined; + + /** + * Selection query as defined by JSData's [Query Syntax][querysyntax]. + * + * [querysyntax]: http://www.js-data.io/v3.0/docs/query-syntax + * + * @example Empty "findAll" query + * const JSData = require('js-data'); + * const { DataStore } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new DataStore(); + * store.defineMapper('post') + * store.findAll('post').then((posts) => { + * console.log(posts); // [...] + * }); + * + * @example Empty "filter" query + * const JSData = require('js-data'); + * const { DataStore } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new DataStore(); + * store.defineMapper('post'); + * const posts = store.filter('post'); + * console.log(posts); // [...] + * + * @example Complex "filter" query + * const JSData = require('js-data'); + * const { DataStore } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new DataStore(); + * const PAGE_SIZE = 2; + * let currentPage = 3; + * + * store.defineMapper('post'); + * const posts = [ + * { author: 'John', age: 30, status: 'published', id: 1 }, + * { author: 'Sally', age: 31, status: 'published', id: 2 }, + * { author: 'Mike', age: 32, status: 'draft', id: 3 }, + * { author: 'Adam', age: 33, status: 'deleted', id: 4 }, + * { author: 'Adam', age: 33, status: 'published', id: 5 } + * { author: 'Peter', age: 25, status: 'deleted', id: 6 }, + * { author: 'Sally', age: 21, status: 'draft', id: 7 }, + * { author: 'Jim', age: 27, status: 'draft', id: 8 }, + * { author: 'Jim', age: 27, status: 'published', id: 9 }, + * { author: 'Jason', age: 55, status: 'published', id: 10 } + * ]; + * store.add('post', posts); + * // Retrieve a filtered page of blog posts + * // Would typically replace filter with findAll + * const results = store.filter('post', { + * where: { + * status: { + * // WHERE status = 'published' + * '==': 'published' + * }, + * author: { + * // AND author IN ('bob', 'alice') + * 'in': ['bob', 'alice'], + * // OR author IN ('karen') + * '|in': ['karen'] + * } + * }, + * orderBy: [ + * // ORDER BY date_published DESC, + * ['date_published', 'DESC'], + * // ORDER BY title ASC + * ['title', 'ASC'] + * ], + * // LIMIT 2 + * limit: PAGE_SIZE, + * // SKIP 4 + * offset: PAGE_SIZE * (currentPage - 1) + * }); + * console.log(results); + * + * @namespace query + * @property {number} [limit] See {@link query.limit}. + * @property {number} [offset] See {@link query.offset}. + * @property {string|Array[]} [orderBy] See {@link query.orderBy}. + * @property {number} [skip] Alias for {@link query.offset}. + * @property {string|Array[]} [sort] Alias for {@link query.orderBy}. + * @property {Object} [where] See {@link query.where}. + * @property {String} [locale] See {@link query.locale}. + * @since 3.0.0 + * @tutorial ["http://www.js-data.io/v3.0/docs/query-syntax","JSData's Query Syntax"] */ + this.getData(); - if (utils.isObject(query.where) || utils.isArray(query.where)) { - where = query.where; - } + if (utils.isObject(query)) { + var where = {}; + /** + * Filtering criteria. Records that do not meet this criteria will be exluded + * from the result. + * + * @example Return posts where author is at least 32 years old + * const JSData = require('js-data'); + * const { DataStore } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new DataStore(); + * store.defineMapper('post') + * const posts = [ + * { author: 'John', age: 30, id: 5 }, + * { author: 'Sally', age: 31, id: 6 }, + * { author: 'Mike', age: 32, id: 7 }, + * { author: 'Adam', age: 33, id: 8 }, + * { author: 'Adam', age: 33, id: 9 } + * ]; + * store.add('post', posts); + * const results = store.filter('post', { + * where: { + * age: { + * '>=': 30 + * } + * } + * }); + * console.log(results); + * + * @name query.where + * @type {Object} + * @see http://www.js-data.io/v3.0/docs/query-syntax + * @since 3.0.0 + */ + + if (utils.isObject(query.where) || utils.isArray(query.where)) { + where = query.where; + } - utils.forOwn(query, function (value, key) { - if (!(key in reserved) && !(key in where)) { - where[key] = { - '==': value - }; + utils.forOwn(query, function (value, key) { + if (!(key in reserved) && !(key in where)) { + where[key] = { + '==': value + }; + } + }); + var groups; // Apply filter for each field + + if (utils.isObject(where) && Object.keys(where).length !== 0) { + groups = this._applyWhereFromArray([where]); + } else if (utils.isArray(where)) { + groups = this._applyWhereFromArray(where); } - }); - var groups; // Apply filter for each field - if (utils.isObject(where) && Object.keys(where).length !== 0) { - groups = this._applyWhereFromArray([where]); - } else if (utils.isArray(where)) { - groups = this._applyWhereFromArray(where); - } + if (groups) { + this.data = this.data.filter(function (item) { + return _this3._testArrayGroup(true, true, groups, item).keep; + }); + } // Sort - if (groups) { - this.data = this.data.filter(function (item, i) { - return _this2._testArrayGroup(true, true, groups, item).keep; - }); - } // Sort - - - var orderBy = query.orderBy || query.sort; - - if (utils.isString(orderBy)) { - orderBy = [[orderBy, 'ASC']]; - } - - if (!utils.isArray(orderBy)) { - orderBy = null; - } - /** - * Determines how records should be ordered in the result. - * - * @example Order posts by `author` then by `id` descending - * const JSData = require('js-data'); - * const { DataStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new DataStore(); - * store.defineMapper('post') - * const posts = [ - * { author: 'John', age: 30, id: 5 }, - * { author: 'Sally', age: 31, id: 6 }, - * { author: 'Mike', age: 32, id: 7 }, - * { author: 'Adam', age: 33, id: 8 }, - * { author: 'Adam', age: 33, id: 9 } - * ]; - * store.add('post', posts); - * const results = store.filter('post', { - * orderBy:[['author','ASC'],['id','DESC']] - * }); - * console.log(results); - * - * @name query.orderBy - * @type {string|Array[]} - * @see http://www.js-data.io/v3.0/docs/query-syntax - * @since 3.0.0 - */ + var orderBy = query.orderBy || query.sort; - if (orderBy) { - var index = 0; - orderBy.forEach(function (def, i) { - if (utils.isString(def)) { - orderBy[i] = [def, 'ASC']; - } - }); - this.data.sort(function (a, b) { - return _this2.compare(orderBy, index, a, b); - }); - } - /** - * Number of records to skip. - * - * @example Retrieve the first "page" of blog posts using findAll - * const JSData = require('js-data'); - * const { DataStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new DataStore(); - * store.defineMapper('post'); - * const PAGE_SIZE = 10; - * let currentPage = 1; - * store.findAll('post', { - * offset: PAGE_SIZE * (currentPage 1) - * limit: PAGE_SIZE - * }); - * - * @example Retrieve the last "page" of blog posts using filter - * const JSData = require('js-data'); - * const { DataStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new DataStore(); - * - * const PAGE_SIZE = 5; - * let currentPage = 2; - * store.defineMapper('post'); - * const posts = [ - * { author: 'John', age: 30, id: 1 }, - * { author: 'Sally', age: 31, id: 2 }, - * { author: 'Mike', age: 32, id: 3 }, - * { author: 'Adam', age: 33, id: 4 }, - * { author: 'Adam', age: 33, id: 5 }, - * { author: 'Peter', age: 25, id: 6 }, - * { author: 'Sally', age: 21, id: 7 }, - * { author: 'Jim', age: 27, id: 8 }, - * { author: 'Jim', age: 27, id: 9 }, - * { author: 'Jason', age: 55, id: 10 } - * ]; - * store.add('post', posts); - * const results = store.filter('post', { - * offset: PAGE_SIZE * (currentPage 1) - * limit: PAGE_SIZE - * }); - * console.log(results) - * - * @name query.offset - * @type {number} - * @see http://www.js-data.io/v3.0/docs/query-syntax - * @since 3.0.0 - */ - - - if (utils.isNumber(query.skip)) { - this.skip(query.skip); - } else if (utils.isNumber(query.offset)) { - this.skip(query.offset); - } - /** - * Maximum number of records to retrieve. - * - * @example Retrieve the first "page" of blog posts using findAll - * const JSData = require('js-data'); - * const { DataStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new DataStore(); - * store.defineMapper('post'); - * - * const PAGE_SIZE = 10 - * let currentPage = 1 - * store.findAll('post', { - * offset: PAGE_SIZE * (currentPage 1) - * limit: PAGE_SIZE - * }); - * - * @example Retrieve the last "page" of blog posts using filter - * const JSData = require('js-data'); - * const { DataStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new DataStore(); - * - * const PAGE_SIZE = 5 - * let currentPage = 2 - * store.defineMapper('post') - * const posts = [ - * { author: 'John', age: 30, id: 1 }, - * { author: 'Sally', age: 31, id: 2 }, - * { author: 'Mike', age: 32, id: 3 }, - * { author: 'Adam', age: 33, id: 4 }, - * { author: 'Adam', age: 33, id: 5 }, - * { author: 'Peter', age: 25, id: 6 }, - * { author: 'Sally', age: 21, id: 7 }, - * { author: 'Jim', age: 27, id: 8 }, - * { author: 'Jim', age: 27, id: 9 }, - * { author: 'Jason', age: 55, id: 10 } - * ]; - * store.add('post', posts); - * const results = store.filter('post', { - * offset: PAGE_SIZE * (currentPage 1) - * limit: PAGE_SIZE - * }); - * console.log(results) - * - * @name query.limit - * @type {number} - * @see http://www.js-data.io/v3.0/docs/query-syntax - * @since 3.0.0 - */ + if (utils.isString(orderBy)) { + orderBy = [[orderBy, 'ASC']]; + } + if (!utils.isArray(orderBy)) { + orderBy = null; + } + /** + * Determines how records should be ordered in the result. + * + * @example Order posts by `author` then by `id` descending + * const JSData = require('js-data'); + * const { DataStore } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new DataStore(); + * store.defineMapper('post') + * const posts = [ + * { author: 'John', age: 30, id: 5 }, + * { author: 'Sally', age: 31, id: 6 }, + * { author: 'Mike', age: 32, id: 7 }, + * { author: 'Adam', age: 33, id: 8 }, + * { author: 'Adam', age: 33, id: 9 } + * ]; + * store.add('post', posts); + * const results = store.filter('post', { + * orderBy:[['author','ASC'],['id','DESC']] + * }); + * console.log(results); + * + * @name query.orderBy + * @type {string|Array[]} + * @see http://www.js-data.io/v3.0/docs/query-syntax + * @since 3.0.0 + */ + + + if (orderBy) { + var index = 0; + orderBy.forEach(function (def, i) { + if (utils.isString(def)) { + orderBy[i] = [def, 'ASC']; + } + }); + var locale = utils.getDefaultLocale(); - if (utils.isNumber(query.limit)) { - this.limit(query.limit); + if (utils.isString(query.locale)) { + locale = query.locale; + } + /** The locale params has to be explicitly set for the collator.compare to work. + * + * @example Order posts with specific locale, defaults to 'en' + * const JSData = require('js-data'); + * const { DataStore } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new DataStore(); + * store.defineMapper('post') + * const posts = [ + * { author: 'คลอน', age: 30, id: 5 }, + * { author: 'กลอน', age: 31, id: 6 }, + * { author: 'สาระ', age: 32, id: 7 }, + * { author: 'ศาลา', age: 33, id: 8 }, + * { author: 'จักรพรรณ', age: 33, id: 9 } + * ]; + * store.add('post', posts); + * const results = store.filter('post', { + * orderBy:[['author','ASC'],['id','DESC']], + * locale: 'th' + * }); + * console.log(results); + * + * @name query.locale + * @type {string} + * @see http://www.js-data.io/v4.0/docs/query-syntax + * @since 4.0.0 + */ + + + var collator = new Intl.Collator(locale, { + numeric: true + }); + this.data.sort(function (a, b) { + return _this3.compare(orderBy, index, a, b, collator.compare); + }); + } + /** + * Number of records to skip. + * + * @example Retrieve the first "page" of blog posts using findAll + * const JSData = require('js-data'); + * const { DataStore } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new DataStore(); + * store.defineMapper('post'); + * const PAGE_SIZE = 10; + * let currentPage = 1; + * store.findAll('post', { + * offset: PAGE_SIZE * (currentPage 1) + * limit: PAGE_SIZE + * }); + * + * @example Retrieve the last "page" of blog posts using filter + * const JSData = require('js-data'); + * const { DataStore } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new DataStore(); + * + * const PAGE_SIZE = 5; + * let currentPage = 2; + * store.defineMapper('post'); + * const posts = [ + * { author: 'John', age: 30, id: 1 }, + * { author: 'Sally', age: 31, id: 2 }, + * { author: 'Mike', age: 32, id: 3 }, + * { author: 'Adam', age: 33, id: 4 }, + * { author: 'Adam', age: 33, id: 5 }, + * { author: 'Peter', age: 25, id: 6 }, + * { author: 'Sally', age: 21, id: 7 }, + * { author: 'Jim', age: 27, id: 8 }, + * { author: 'Jim', age: 27, id: 9 }, + * { author: 'Jason', age: 55, id: 10 } + * ]; + * store.add('post', posts); + * const results = store.filter('post', { + * offset: PAGE_SIZE * (currentPage 1) + * limit: PAGE_SIZE + * }); + * console.log(results) + * + * @name query.offset + * @type {number} + * @see http://www.js-data.io/v3.0/docs/query-syntax + * @since 3.0.0 + */ + + + if (utils.isNumber(query.skip)) { + this.skip(query.skip); + } else if (utils.isNumber(query.offset)) { + this.skip(query.offset); + } + /** + * Maximum number of records to retrieve. + * + * @example Retrieve the first "page" of blog posts using findAll + * const JSData = require('js-data'); + * const { DataStore } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new DataStore(); + * store.defineMapper('post'); + * + * const PAGE_SIZE = 10 + * let currentPage = 1 + * store.findAll('post', { + * offset: PAGE_SIZE * (currentPage 1) + * limit: PAGE_SIZE + * }); + * + * @example Retrieve the last "page" of blog posts using filter + * const JSData = require('js-data'); + * const { DataStore } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new DataStore(); + * + * const PAGE_SIZE = 5 + * let currentPage = 2 + * store.defineMapper('post') + * const posts = [ + * { author: 'John', age: 30, id: 1 }, + * { author: 'Sally', age: 31, id: 2 }, + * { author: 'Mike', age: 32, id: 3 }, + * { author: 'Adam', age: 33, id: 4 }, + * { author: 'Adam', age: 33, id: 5 }, + * { author: 'Peter', age: 25, id: 6 }, + * { author: 'Sally', age: 21, id: 7 }, + * { author: 'Jim', age: 27, id: 8 }, + * { author: 'Jim', age: 27, id: 9 }, + * { author: 'Jason', age: 55, id: 10 } + * ]; + * store.add('post', posts); + * const results = store.filter('post', { + * offset: PAGE_SIZE * (currentPage 1) + * limit: PAGE_SIZE + * }); + * console.log(results) + * + * @name query.limit + * @type {number} + * @see http://www.js-data.io/v3.0/docs/query-syntax + * @since 3.0.0 + */ + + + if (utils.isNumber(query.limit)) { + this.limit(query.limit); + } + } else if (utils.isFunction(query)) { + this.data = this.data.filter(query, thisArg); } - } else if (utils.isFunction(query)) { - this.data = this.data.filter(query, thisArg); - } - - return this; - }, - - /** - * Iterate over all entities. - * - * @method Query#forEach - * @param {Function} forEachFn Iteration function. - * @param {*} [thisArg] Context to which to bind `forEachFn`. - * @returns {Query} A reference to itself for chaining. - * @since 3.0.0 - */ - forEach: function forEach(forEachFn, thisArg) { - this.getData().forEach(forEachFn, thisArg); - return this; - }, - - /** - * Find the entity or entities that match the provided key. - * - * @example Get the entity whose primary key is 25. - * const entities = query.get(25).run(); - * - * @example Same as above. - * const entities = query.get([25]).run(); - * - * @example Get all users who are active and have the "admin" role. - * const activeAdmins = query.get(['active', 'admin'], { - * index: 'activityAndRoles' - * }).run(); - * - * @example Get all entities that match a certain weather condition. - * const niceDays = query.get(['sunny', 'humid', 'calm'], { - * index: 'weatherConditions' - * }).run(); - * - * @method Query#get - * @param {array} keyList Key(s) defining the entity to retrieve. If - * `keyList` is not an array (i.e. for a single-value key), it will be - * wrapped in an array. - * @param {object} [opts] Configuration options. - * @param {string} [opts.string] Name of the secondary index to use in the - * query. If no index is specified, the main index is used. - * @returns {Query} A reference to itself for chaining. - * @since 3.0.0 - */ - get: function get(keyList, opts) { - keyList || (keyList = []); - opts || (opts = {}); - - if (this.data) { - throw utils.err("".concat(DOMAIN$1, "#get"))(500, INDEX_ERR); - } - if (keyList && !utils.isArray(keyList)) { - keyList = [keyList]; + return this; } + /** + * Iterate over all entities. + * + * @method Query#forEach + * @param {Function} forEachFn Iteration function. + * @param {*} [thisArg] Context to which to bind `forEachFn`. + * @returns {Query} A reference to itself for chaining. + * @since 3.0.0 + */ - if (!keyList.length) { - this.getData(); + }, { + key: "forEach", + value: function forEach(forEachFn, thisArg) { + this.getData().forEach(forEachFn, thisArg); return this; } + /** + * Find the entity or entities that match the provided key. + * + * @example Get the entity whose primary key is 25. + * const entities = query.get(25).run(); + * + * @example Same as above. + * const entities = query.get([25]).run(); + * + * @example Get all users who are active and have the "admin" role. + * const activeAdmins = query.get(['active', 'admin'], { + * index: 'activityAndRoles' + * }).run(); + * + * @example Get all entities that match a certain weather condition. + * const niceDays = query.get(['sunny', 'humid', 'calm'], { + * index: 'weatherConditions' + * }).run(); + * + * @method Query#get + * @param {array} keyList Key(s) defining the entity to retrieve. If + * `keyList` is not an array (i.e. for a single-value key), it will be + * wrapped in an array. + * @param {object} [opts] Configuration options. + * @param {string} [opts.string] Name of the secondary index to use in the + * query. If no index is specified, the main index is used. + * @returns {Query} A reference to itself for chaining. + * @since 3.0.0 + */ - this.data = this.collection.getIndex(opts.index).get(keyList); - return this; - }, - - /** - * Find the entity or entities that match the provided keyLists. - * - * @example Get the posts where "status" is "draft" or "inReview". - * const posts = query.getAll('draft', 'inReview', { index: 'status' }).run(); - * - * @example Same as above. - * const posts = query.getAll(['draft'], ['inReview'], { index: 'status' }).run(); - * - * @method Query#getAll - * @param {...Array} [keyList] Provide one or more keyLists, and all - * entities matching each keyList will be retrieved. If no keyLists are - * provided, all entities will be returned. - * @param {object} [opts] Configuration options. - * @param {string} [opts.index] Name of the secondary index to use in the - * query. If no index is specified, the main index is used. - * @returns {Query} A reference to itself for chaining. - * @since 3.0.0 - */ - getAll: function getAll() { - var _this3 = this; + }, { + key: "get", + value: function get() { + var keyList = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - var opts = {}; + if (this.data) { + throw utils.err("".concat(DOMAIN$1, "#get"))(500, INDEX_ERR); + } - if (this.data) { - throw utils.err("".concat(DOMAIN$1, "#getAll"))(500, INDEX_ERR); - } + if (keyList && !utils.isArray(keyList)) { + keyList = [keyList]; + } - for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { - args[_key] = arguments[_key]; - } + if (!keyList.length) { + this.getData(); + return this; + } - if (!args.length || args.length === 1 && utils.isObject(args[0])) { - this.getData(); + this.data = this.collection.getIndex(opts.index).get(keyList); return this; - } else if (args.length && utils.isObject(args[args.length - 1])) { - opts = args[args.length - 1]; - args.pop(); } + }, { + key: "getAll", + value: function getAll() { + var _this4 = this; - var collection = this.collection; - var index = collection.getIndex(opts.index); - this.data = []; - args.forEach(function (keyList) { - _this3.data = _this3.data.concat(index.get(keyList)); - }); - return this; - }, + var opts = {}; - /** - * Return the current data result of this query. - * - * @method Query#getData - * @returns {Array} The data in this query. - * @since 3.0.0 - */ - getData: function getData() { - if (!this.data) { - this.data = this.collection.index.getAll(); - } - - return this.data; - }, - - /** - * Implementation used by the `like` operator. Takes a pattern and flags and - * returns a `RegExp` instance that can test strings. - * - * @method Query#like - * @param {string} pattern Testing pattern. - * @param {string} flags Flags for the regular expression. - * @returns {RegExp} Regular expression for testing strings. - * @since 3.0.0 - */ - like: function like(pattern, flags) { - return new RegExp("^".concat(escape(pattern).replace(percentRegExp, '.*').replace(underscoreRegExp, '.'), "$"), flags); - }, - - /** - * Limit the result. - * - * @example Get only the first 2 posts. - * const store = new JSData.DataStore(); - * store.defineMapper('post'); - * const posts = [ - * { author: 'John', age: 30, status: 'published', id: 1 }, - * { author: 'Sally', age: 31, status: 'draft', id: 2 }, - * { author: 'Mike', age: 32, status: 'draft', id: 3 }, - * { author: 'Adam', age: 33, status: 'deleted', id: 4 }, - * { author: 'Adam', age: 33, status: 'draft', id: 5 } - * ]; - * store.add('post', posts); - * const results = store.query('post').limit(2).run(); - * console.log(results); - * - * @method Query#limit - * @param {number} num The maximum number of entities to keep in the result. - * @returns {Query} A reference to itself for chaining. - * @since 3.0.0 - */ - limit: function limit(num) { - if (!utils.isNumber(num)) { - throw utils.err("".concat(DOMAIN$1, "#limit"), 'num')(400, 'number', num); - } + if (this.data) { + throw utils.err("".concat(DOMAIN$1, "#getAll"))(500, INDEX_ERR); + } - var data = this.getData(); - this.data = data.slice(0, Math.min(data.length, num)); - return this; - }, + for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } - /** - * Apply a mapping function to the result data. - * - * @example - * const JSData = require('js-data'); - * const { DataStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new DataStore(); - * store.defineMapper('user'); - * const users = [ - * { name: 'Peter', age: 25, id: 1 }, - * { name: 'Jim', age: 19, id: 2 }, - * { name: 'Mike', age: 17, id: 3 }, - * { name: 'Alan', age: 29, id: 4 }, - * { name: 'Katie', age: 33, id: 5 } - * ]; - * store.add('user', users); - * const ages = store - * .query('user') - * .map(function (user) { - * return user.age; - * }) - * .run(); - * console.log(ages); - * - * @method Query#map - * @param {Function} mapFn Mapping function. - * @param {*} [thisArg] Context to which to bind `mapFn`. - * @returns {Query} A reference to itself for chaining. - * @since 3.0.0 - */ - map: function map(mapFn, thisArg) { - this.data = this.getData().map(mapFn, thisArg); - return this; - }, + if (!args.length || args.length === 1 && utils.isObject(args[0])) { + this.getData(); + return this; + } else if (args.length && utils.isObject(args[args.length - 1])) { + opts = args[args.length - 1]; + args.pop(); + } - /** - * Return the result of calling the specified function on each item in this - * collection's main index. - * - * @example - * const stringAges = UserCollection.query().mapCall('toString').run(); - * - * @method Query#mapCall - * @param {string} funcName Name of function to call - * @parama {...*} [args] Remaining arguments to be passed to the function. - * @returns {Query} A reference to itself for chaining. - * @since 3.0.0 - */ - mapCall: function mapCall(funcName) { - for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { - args[_key2 - 1] = arguments[_key2]; + var index = this.collection.getIndex(opts.index); + this.data = []; + args.forEach(function (keyList) { + _this4.data = _this4.data.concat(index.get(keyList)); + }); + return this; } + /** + * Return the current data result of this query. + * + * @method Query#getData + * @returns {Array} The data in this query. + * @since 3.0.0 + */ - this.data = this.getData().map(function (item) { - return item[funcName].apply(item, args); - }); - return this; - }, + }, { + key: "getData", + value: function getData() { + if (!this.data) { + this.data = this.collection.index.getAll(); + } - /** - * Complete the execution of the query and return the resulting data. - * - * @method Query#run - * @returns {Array} The result of executing this query. - * @since 3.0.0 - */ - run: function run() { - var data = this.data; - this.data = null; - return data; - }, + return this.data; + } + /** + * Implementation used by the `like` operator. Takes a pattern and flags and + * returns a `RegExp` instance that can test strings. + * + * @method Query#like + * @param {string} pattern Testing pattern. + * @param {string} flags Flags for the regular expression. + * @returns {RegExp} Regular expression for testing strings. + * @since 3.0.0 + */ - /** - * Skip a number of results. - * - * @example Get all but the first 2 posts. - * const JSData = require('js-data'); - * const { DataStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new DataStore(); - * store.defineMapper('post'); - * const posts = [ - * { author: 'John', age: 30, status: 'published', id: 1 }, - * { author: 'Sally', age: 31, status: 'draft', id: 2 }, - * { author: 'Mike', age: 32, status: 'draft', id: 3 }, - * { author: 'Adam', age: 33, status: 'deleted', id: 4 }, - * { author: 'Adam', age: 33, status: 'draft', id: 5 } - * ]; - * store.add('post', posts); - * const results = store.query('post').skip(2).run(); - * console.log(results); - * - * @method Query#skip - * @param {number} num The number of entities to skip. - * @returns {Query} A reference to itself for chaining. - * @since 3.0.0 - */ - skip: function skip(num) { - if (!utils.isNumber(num)) { - throw utils.err("".concat(DOMAIN$1, "#skip"), 'num')(400, 'number', num); - } + }, { + key: "like", + value: function like(pattern, flags) { + return new RegExp("^".concat(escape(pattern).replace(percentRegExp, '.*').replace(underscoreRegExp, '.'), "$"), flags); + } + /** + * Limit the result. + * + * @example Get only the first 2 posts. + * const store = new JSData.DataStore(); + * store.defineMapper('post'); + * const posts = [ + * { author: 'John', age: 30, status: 'published', id: 1 }, + * { author: 'Sally', age: 31, status: 'draft', id: 2 }, + * { author: 'Mike', age: 32, status: 'draft', id: 3 }, + * { author: 'Adam', age: 33, status: 'deleted', id: 4 }, + * { author: 'Adam', age: 33, status: 'draft', id: 5 } + * ]; + * store.add('post', posts); + * const results = store.query('post').limit(2).run(); + * console.log(results); + * + * @method Query#limit + * @param {number} num The maximum number of entities to keep in the result. + * @returns {Query} A reference to itself for chaining. + * @since 3.0.0 + */ - var data = this.getData(); + }, { + key: "limit", + value: function limit(num) { + if (!utils.isNumber(num)) { + throw utils.err("".concat(DOMAIN$1, "#limit"), 'num')(400, 'number', num); + } - if (num < data.length) { - this.data = data.slice(num); - } else { - this.data = []; + var data = this.getData(); + this.data = data.slice(0, Math.min(data.length, num)); + return this; } + /** + * Apply a mapping function to the result data. + * + * @example + * const JSData = require('js-data'); + * const { DataStore } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new DataStore(); + * store.defineMapper('user'); + * const users = [ + * { name: 'Peter', age: 25, id: 1 }, + * { name: 'Jim', age: 19, id: 2 }, + * { name: 'Mike', age: 17, id: 3 }, + * { name: 'Alan', age: 29, id: 4 }, + * { name: 'Katie', age: 33, id: 5 } + * ]; + * store.add('user', users); + * const ages = store + * .query('user') + * .map(function (user) { + * return user.age; + * }) + * .run(); + * console.log(ages); + * + * @method Query#map + * @param {Function} mapFn Mapping function. + * @param {*} [thisArg] Context to which to bind `mapFn`. + * @returns {Query} A reference to itself for chaining. + * @since 3.0.0 + */ - return this; - } - }, { - /** - * The filtering operators supported by {@link Query#filter}, and which are - * implemented by adapters (for the most part). - * - * @example Variant 1 - * const JSData = require('js-data'); - * const { DataStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new DataStore(); - * store.defineMapper('post'); - * const posts = [ - * { author: 'John', age: 30, status: 'published', id: 1 }, - * { author: 'Sally', age: 31, status: 'published', id: 2 }, - * { author: 'Mike', age: 32, status: 'published', id: 3 }, - * { author: 'Adam', age: 33, status: 'deleted', id: 4 }, - * { author: 'Adam', age: 33, status: 'published', id: 5 } - * ]; - * store.add('post', posts); - * const publishedPosts = store.filter('post', { - * status: 'published', - * limit: 2 - * }); - * console.log(publishedPosts); - * - * - * @example Variant 2 - * const JSData = require('js-data'); - * const { DataStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new DataStore(); - * store.defineMapper('post') - * const posts = [ - * { author: 'John', age: 30, status: 'published', id: 1 }, - * { author: 'Sally', age: 31, status: 'published', id: 2 }, - * { author: 'Mike', age: 32, status: 'published', id: 3 }, - * { author: 'Adam', age: 33, status: 'deleted', id: 4 }, - * { author: 'Adam', age: 33, status: 'published', id: 5 } - * ]; - * store.add('post', posts); - * const publishedPosts = store.filter('post', { - * where: { - * status: { - * '==': 'published' - * } - * }, - * limit: 2 - * }); - * console.log(publishedPosts); - * - * @example Variant 3 - * const JSData = require('js-data'); - * const { DataStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new DataStore(); - * store.defineMapper('post'); - * const posts = [ - * { author: 'John', age: 30, status: 'published', id: 1 }, - * { author: 'Sally', age: 31, status: 'published', id: 2 }, - * { author: 'Mike', age: 32, status: 'published', id: 3 }, - * { author: 'Adam', age: 33, status: 'deleted', id: 4 }, - * { author: 'Adam', age: 33, status: 'published', id: 5 } - * ]; - * store.add('post', posts); - * const publishedPosts = store - * .query('post') - * .filter({ status: 'published' }) - * .limit(2) - * .run(); - * console.log(publishedPosts); - * - * @example Variant 4 - * const JSData = require('js-data'); - * const { DataStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new DataStore(); - * store.defineMapper('post'); - * const posts = [ - * { author: 'John', age: 30, status: 'published', id: 1 }, - * { author: 'Sally', age: 31, status: 'published', id: 2 }, - * { author: 'Mike', age: 32, status: 'published', id: 3 }, - * { author: 'Adam', age: 33, status: 'deleted', id: 4 }, - * { author: 'Adam', age: 33, status: 'published', id: 5 } - * ]; - * store.add('post', posts); - * const publishedPosts = store - * .query('post') - * .filter({ - * where: { - * status: { - * '==': 'published' - * } - * } - * }) - * .limit(2) - * .run(); - * console.log(publishedPosts); - * - * @example Multiple operators - * const JSData = require('js-data'); - * const { DataStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new DataStore(); - * store.defineMapper('post'); - * const posts = [ - * { author: 'John', age: 30, status: 'published', id: 1 }, - * { author: 'Sally', age: 31, status: 'published', id: 2 }, - * { author: 'Mike', age: 32, status: 'published', id: 3 }, - * { author: 'Adam', age: 33, status: 'deleted', id: 4 }, - * { author: 'Adam', age: 33, status: 'published', id: 5 } - * ]; - * store.add('post', posts); - * - * const myPublishedPosts = store.filter('post', { - * where: { - * status: { - * '==': 'published' - * }, - * user_id: { - * '==': currentUser.id - * } - * } - * }); - * - * console.log(myPublishedPosts); - * - * @name Query.ops - * @property {Function} == Equality operator. - * @property {Function} != Inequality operator. - * @property {Function} > Greater than operator. - * @property {Function} >= Greater than (inclusive) operator. - * @property {Function} < Less than operator. - * @property {Function} <= Less than (inclusive) operator. - * @property {Function} isectEmpty Operator that asserts that the intersection - * between two arrays is empty. - * @property {Function} isectNotEmpty Operator that asserts that the - * intersection between two arrays is __not__ empty. - * @property {Function} in Operator that asserts whether a value is in an - * array. - * @property {Function} notIn Operator that asserts whether a value is __not__ - * in an array. - * @property {Function} contains Operator that asserts whether an array - * contains a value. - * @property {Function} notContains Operator that asserts whether an array - * does __not__ contain a value. - * @since 3.0.0 - * @type {Object} - */ - ops: { - '=': function _(value, predicate) { - return value == predicate; // eslint-disable-line - }, - '==': function _(value, predicate) { - return value == predicate; // eslint-disable-line - }, - '===': function _(value, predicate) { - return value === predicate; - }, - '!=': function _(value, predicate) { - return value != predicate; // eslint-disable-line - }, - '!==': function _(value, predicate) { - return value !== predicate; - }, - '>': function _(value, predicate) { - return value > predicate; - }, - '>=': function _(value, predicate) { - return value >= predicate; - }, - '<': function _(value, predicate) { - return value < predicate; - }, - '<=': function _(value, predicate) { - return value <= predicate; - }, - isectEmpty: function isectEmpty(value, predicate) { - return !utils.intersection(value || [], predicate || []).length; - }, - isectNotEmpty: function isectNotEmpty(value, predicate) { - return utils.intersection(value || [], predicate || []).length; - }, - in: function _in(value, predicate) { - return predicate.indexOf(value) !== -1; - }, - notIn: function notIn(value, predicate) { - return predicate.indexOf(value) === -1; - }, - contains: function contains(value, predicate) { - return (value || []).indexOf(predicate) !== -1; - }, - notContains: function notContains(value, predicate) { - return (value || []).indexOf(predicate) === -1; + }, { + key: "map", + value: function map(mapFn, thisArg) { + this.data = this.getData().map(mapFn, thisArg); + return this; } - } - }); - /** - * Create a subclass of this Query: - * @example Query.extend - * const JSData = require('js-data'); - * const { Query } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * // Extend the class using ES2015 class syntax. - * class CustomQueryClass extends Query { - * foo () { return 'bar'; } - * static beep () { return 'boop'; } - * } - * const customQuery = new CustomQueryClass(); - * console.log(customQuery.foo()); - * console.log(CustomQueryClass.beep()); - * - * // Extend the class using alternate method. - * const OtherQueryClass = Query.extend({ - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }); - * const otherQuery = new OtherQueryClass(); - * console.log(otherQuery.foo()); - * console.log(OtherQueryClass.beep()); - * - * // Extend the class, providing a custom constructor. - * function AnotherQueryClass (collection) { - * Query.call(this, collection); - * this.created_at = new Date().getTime(); - * } - * Query.extend({ - * constructor: AnotherQueryClass, - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }); - * const anotherQuery = new AnotherQueryClass(); - * console.log(anotherQuery.created_at); - * console.log(anotherQuery.foo()); - * console.log(AnotherQueryClass.beep()); - * - * @method Query.extend - * @param {object} [props={}] Properties to add to the prototype of the - * subclass. - * @param {object} [props.constructor] Provide a custom constructor function - * to be used as the subclass itself. - * @param {object} [classProps={}] Static properties to add to the subclass. - * @returns {Constructor} Subclass of this Query class. - * @since 3.0.0 - */ - - var belongsToType = 'belongsTo'; - var hasManyType = 'hasMany'; - var hasOneType = 'hasOne'; - var DOMAIN$2 = 'Relation'; - function Relation(relatedMapper) { - var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - utils.classCallCheck(this, Relation); - options.type = this.constructor.TYPE_NAME; - this.validateOptions(relatedMapper, options); - - if (_typeof(relatedMapper) === 'object') { - Object.defineProperty(this, 'relatedMapper', { - value: relatedMapper - }); - } - - Object.defineProperty(this, 'inverse', { - writable: true - }); - utils.fillIn(this, options); - } - Relation.extend = utils.extend; - utils.addHiddenPropsToTarget(Relation.prototype, { - get canAutoAddLinks() { - return this.add === undefined || !!this.add; - }, - - get relatedCollection() { - return this.mapper.datastore.getCollection(this.relation); - }, + /** + * Return the result of calling the specified function on each item in this + * collection's main index. + * + * @example + * const stringAges = UserCollection.query().mapCall('toString').run(); + * + * @method Query#mapCall + * @param {string} funcName Name of function to call + * @param args Remaining arguments to be passed to the function. + * @returns {Query} A reference to itself for chaining. + * @since 3.0.0 + */ - validateOptions: function validateOptions(related, opts) { - var DOMAIN_ERR = "new ".concat(DOMAIN$2); - var localField = opts.localField; + }, { + key: "mapCall", + value: function mapCall(funcName) { + for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { + args[_key2 - 1] = arguments[_key2]; + } - if (!localField) { - throw utils.err(DOMAIN_ERR, 'opts.localField')(400, 'string', localField); + this.data = this.getData().map(function (item) { + return item[funcName].apply(item, args); + }); + return this; } + /** + * Complete the execution of the query and return the resulting data. + * + * @method Query#run + * @returns {Array} The result of executing this query. + * @since 3.0.0 + */ - var foreignKey = opts.foreignKey = opts.foreignKey || opts.localKey; + }, { + key: "run", + value: function run() { + var data = this.data; + this.data = null; + return data; + } + /** + * Skip a number of results. + * + * @example Get all but the first 2 posts. + * const JSData = require('js-data'); + * const { DataStore } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new DataStore(); + * store.defineMapper('post'); + * const posts = [ + * { author: 'John', age: 30, status: 'published', id: 1 }, + * { author: 'Sally', age: 31, status: 'draft', id: 2 }, + * { author: 'Mike', age: 32, status: 'draft', id: 3 }, + * { author: 'Adam', age: 33, status: 'deleted', id: 4 }, + * { author: 'Adam', age: 33, status: 'draft', id: 5 } + * ]; + * store.add('post', posts); + * const results = store.query('post').skip(2).run(); + * console.log(results); + * + * @method Query#skip + * @param {number} num The number of entities to skip. + * @returns {Query} A reference to itself for chaining. + * @since 3.0.0 + */ - if (!foreignKey && (opts.type === belongsToType || opts.type === hasOneType)) { - throw utils.err(DOMAIN_ERR, 'opts.foreignKey')(400, 'string', foreignKey); - } + }, { + key: "skip", + value: function skip(num) { + if (!utils.isNumber(num)) { + throw utils.err("".concat(DOMAIN$1, "#skip"), 'num')(400, 'number', num); + } - if (utils.isString(related)) { - opts.relation = related; + var data = this.getData(); - if (!utils.isFunction(opts.getRelation)) { - throw utils.err(DOMAIN_ERR, 'opts.getRelation')(400, 'function', opts.getRelation); + if (num < data.length) { + this.data = data.slice(num); + } else { + this.data = []; } - } else if (related) { - opts.relation = related.name; - } else { - throw utils.err(DOMAIN_ERR, 'related')(400, 'Mapper or string', related); + + return this; } + }]); + + return Query; + }(Component); + Query.ops = { + '=': function _(value, predicate) { + // tslint:disable-next-line:triple-equals + return value == predicate; // eslint-disable-line }, - assignTo: function assignTo(mapper) { - this.name = mapper.name; - Object.defineProperty(this, 'mapper', { - value: mapper - }); - mapper.relationList || Object.defineProperty(mapper, 'relationList', { - value: [] - }); - mapper.relationFields || Object.defineProperty(mapper, 'relationFields', { - value: [] - }); - mapper.relationList.push(this); - mapper.relationFields.push(this.localField); + '==': function _(value, predicate) { + // tslint:disable-next-line:triple-equals + return value == predicate; // eslint-disable-line }, - canFindLinkFor: function canFindLinkFor() { - return !!(this.foreignKey || this.localKey); + '===': function _(value, predicate) { + return value === predicate; }, - getRelation: function getRelation() { - return this.relatedMapper; + '!=': function _(value, predicate) { + // tslint:disable-next-line:triple-equals + return value != predicate; // eslint-disable-line }, - getForeignKey: function getForeignKey(record) { - return utils.get(record, this.mapper.idAttribute); + '!==': function _(value, predicate) { + return value !== predicate; }, - setForeignKey: function setForeignKey(record, relatedRecord) { - if (!record || !relatedRecord) { - return; - } - - this._setForeignKey(record, relatedRecord); + '>': function _(value, predicate) { + return value > predicate; }, - _setForeignKey: function _setForeignKey(record, relatedRecords) { - var _this = this; - - var idAttribute = this.mapper.idAttribute; - - if (!utils.isArray(relatedRecords)) { - relatedRecords = [relatedRecords]; - } - - relatedRecords.forEach(function (relatedRecord) { - utils.set(relatedRecord, _this.foreignKey, utils.get(record, idAttribute)); - }); + '>=': function _(value, predicate) { + return value >= predicate; }, - getLocalField: function getLocalField(record) { - return utils.get(record, this.localField); + '<': function _(value, predicate) { + return value < predicate; }, - setLocalField: function setLocalField(record, relatedData) { - return utils.set(record, this.localField, relatedData); + '<=': function _(value, predicate) { + return value <= predicate; }, - getInverse: function getInverse(mapper) { - if (!this.inverse) { - this.findInverseRelation(mapper); - } - - return this.inverse; + isectEmpty: function isectEmpty(value, predicate) { + return !utils.intersection(value || [], predicate || []).length; }, - findInverseRelation: function findInverseRelation(mapper) { - var _this2 = this; - - this.getRelation().relationList.forEach(function (def) { - if (def.getRelation() === mapper && _this2.isInversedTo(def) && _this2 !== def) { - _this2.inverse = def; - return true; - } - }); + isectNotEmpty: function isectNotEmpty(value, predicate) { + return utils.intersection(value || [], predicate || []).length; }, - isInversedTo: function isInversedTo(def) { - return !def.foreignKey || def.foreignKey === this.foreignKey; + "in": function _in(value, predicate) { + return predicate.indexOf(value) !== -1; }, - addLinkedRecords: function addLinkedRecords(records) { - var _this3 = this; + notIn: function notIn(value, predicate) { + return predicate.indexOf(value) === -1; + }, + contains: function contains(value, predicate) { + return (value || []).indexOf(predicate) !== -1; + }, + notContains: function notContains(value, predicate) { + return (value || []).indexOf(predicate) === -1; + } + }; - var datastore = this.mapper.datastore; - records.forEach(function (record) { - var relatedData = _this3.getLocalField(record); + var belongsToType = 'belongsTo'; + var hasManyType = 'hasMany'; + var hasOneType = 'hasOne'; + var DOMAIN$2 = 'Relation'; + var Relation = + /*#__PURE__*/ + function () { + function Relation(relatedMapper) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - if (utils.isFunction(_this3.add)) { - relatedData = _this3.add(datastore, _this3, record); - } else if (relatedData) { - relatedData = _this3.linkRecord(record, relatedData); - } + _classCallCheck(this, Relation); - var isEmptyLinks = !relatedData || utils.isArray(relatedData) && !relatedData.length; + this.TYPE_NAME = DOMAIN$2; + options.type = this.constructor.TYPE_NAME; + this.validateOptions(relatedMapper, options); - if (isEmptyLinks && _this3.canFindLinkFor(record)) { - relatedData = _this3.findExistingLinksFor(record); - } + if (_typeof(relatedMapper) === 'object') { + this.relatedMapper = relatedMapper; + } + + utils.fillIn(this, options); + } - if (relatedData) { - _this3.setLocalField(record, relatedData); + _createClass(Relation, [{ + key: "validateOptions", + value: function validateOptions(related, opts) { + var DOMAIN_ERR = "new ".concat(DOMAIN$2); + var localField = opts.localField; + + if (!localField) { + throw utils.err(DOMAIN_ERR, 'opts.localField')(400, 'string', localField); } - }); - }, - removeLinkedRecords: function removeLinkedRecords(relatedMapper, records) { - var localField = this.localField; - records.forEach(function (record) { - utils.set(record, localField, undefined); - }); - }, - linkRecord: function linkRecord(record, relatedRecord) { - var relatedId = utils.get(relatedRecord, this.mapper.idAttribute); - if (relatedId === undefined) { - var unsaved = this.relatedCollection.unsaved(); + var foreignKey = opts.foreignKey = opts.foreignKey || opts.localKey; - if (unsaved.indexOf(relatedRecord) === -1) { - if (this.canAutoAddLinks) { - relatedRecord = this.relatedCollection.add(relatedRecord); - } + if (!foreignKey && (opts.type === belongsToType || opts.type === hasOneType)) { + throw utils.err(DOMAIN_ERR, 'opts.foreignKey')(400, 'string', foreignKey); } - } else { - if (relatedRecord !== this.relatedCollection.get(relatedId)) { - this.setForeignKey(record, relatedRecord); - if (this.canAutoAddLinks) { - relatedRecord = this.relatedCollection.add(relatedRecord); + if (utils.isString(related)) { + opts.relation = related; + + if (!utils.isFunction(opts.getRelation)) { + throw utils.err(DOMAIN_ERR, 'opts.getRelation')(400, 'function', opts.getRelation); } + } else if (related) { + opts.relation = related.name; + } else { + throw utils.err(DOMAIN_ERR, 'related')(400, 'Mapper or string', related); } } + }, { + key: "assignTo", + value: function assignTo(mapper) { + this.name = mapper.name; + Object.defineProperty(this, 'mapper', { + value: mapper + }); + if (!mapper.relationList) Object.defineProperty(mapper, 'relationList', { + value: [] + }); + if (!mapper.relationFields) Object.defineProperty(mapper, 'relationFields', { + value: [] + }); + mapper.relationList.push(this); + mapper.relationFields.push(this.localField); + } + }, { + key: "canFindLinkFor", + value: function canFindLinkFor(record) { + return !!(this.foreignKey || this.localKey); + } + }, { + key: "getRelation", + value: function getRelation() { + return this.relatedMapper; + } + }, { + key: "getForeignKey", + value: function getForeignKey(record) { + return utils.get(record, this.mapper.idAttribute); + } + }, { + key: "setForeignKey", + value: function setForeignKey(record, relatedRecord) { + if (!record || !relatedRecord) { + return; + } - return relatedRecord; - }, - // e.g. user hasMany post via "foreignKey", so find all posts of user - findExistingLinksByForeignKey: function findExistingLinksByForeignKey(id) { - if (id === undefined || id === null) { - return; + this._setForeignKey(record, relatedRecord); } + }, { + key: "_setForeignKey", + value: function _setForeignKey(record, relatedRecords) { + var _this = this; - return this.relatedCollection.filter(_defineProperty({}, this.foreignKey, id)); - }, - ensureLinkedDataHasProperType: function ensureLinkedDataHasProperType(props, opts) { - var relatedMapper = this.getRelation(); - var relationData = this.getLocalField(props); + var idAttribute = this.mapper.idAttribute; - if (utils.isArray(relationData) && (!relationData.length || relatedMapper.is(relationData[0]))) { - return; - } + if (!utils.isArray(relatedRecords)) { + relatedRecords = [relatedRecords]; + } - if (relationData && !relatedMapper.is(relationData)) { - utils.set(props, this.localField, relatedMapper.createRecord(relationData, opts)); + relatedRecords.forEach(function (relatedRecord) { + utils.set(relatedRecord, _this.foreignKey, utils.get(record, idAttribute)); + }); } - }, - isRequiresParentId: function isRequiresParentId() { - return false; - }, - isRequiresChildId: function isRequiresChildId() { - return false; - }, - createChildRecord: function createChildRecord(props, relationData, opts) { - var _this4 = this; + }, { + key: "getLocalField", + value: function getLocalField(record) { + return utils.get(record, this.localField); + } + }, { + key: "setLocalField", + value: function setLocalField(record, relatedData) { + return utils.set(record, this.localField, relatedData); + } + }, { + key: "getInverse", + value: function getInverse(mapper) { + if (!this.inverse) { + this.findInverseRelation(mapper); + } - this.setForeignKey(props, relationData); - return this.createLinked(relationData, opts).then(function (result) { - _this4.setLocalField(props, result); - }); - }, - createLinked: function createLinked(props, opts) { - var create = utils.isArray(props) ? 'createMany' : 'create'; - return this.getRelation()[create](props, opts); - } - }); + return this.inverse; + } + }, { + key: "findInverseRelation", + value: function findInverseRelation(mapper) { + var _this2 = this; - var BelongsToRelation = Relation.extend({ - getForeignKey: function getForeignKey(record) { - return utils.get(record, this.foreignKey); - }, - _setForeignKey: function _setForeignKey(record, relatedRecord) { - utils.set(record, this.foreignKey, utils.get(relatedRecord, this.getRelation().idAttribute)); - }, - findExistingLinksFor: function findExistingLinksFor(record) { - // console.log('\tBelongsTo#findExistingLinksFor', record) - if (!record) { - return; + this.getRelation().relationList.forEach(function (def) { + if (def.getRelation() === mapper && _this2.isInversedTo(def) && _this2 !== def) { + _this2.inverse = def; + return true; + } + }); + } + }, { + key: "isInversedTo", + value: function isInversedTo(def) { + return !def.foreignKey || def.foreignKey === this.foreignKey; } + }, { + key: "addLinkedRecords", + value: function addLinkedRecords(records) { + var _this3 = this; - var relatedId = utils.get(record, this.foreignKey); + var datastore = this.mapper.datastore; + records.forEach(function (record) { + var relatedData = _this3.getLocalField(record); - if (relatedId !== undefined && relatedId !== null) { - return this.relatedCollection.get(relatedId); - } - }, - isRequiresParentId: function isRequiresParentId() { - return true; - }, - createParentRecord: function createParentRecord(props, opts) { - var _this = this; + if (utils.isFunction(_this3.add)) { + relatedData = _this3.add(datastore, _this3, record); + } else if (relatedData) { + relatedData = _this3.linkRecord(record, relatedData); + } - var relationData = this.getLocalField(props); - return this.createLinked(relationData, opts).then(function (record) { - _this.setForeignKey(props, record); - }); - }, - createChildRecord: function createChildRecord() { - throw new Error('"BelongsTo" relation does not support child creation as it cannot have children.'); - } - }, { - TYPE_NAME: 'belongsTo' - }); + var isEmptyLinks = !relatedData || utils.isArray(relatedData) && !relatedData.length; - var HasManyRelation = Relation.extend({ - validateOptions: function validateOptions(related, opts) { - Relation.prototype.validateOptions.call(this, related, opts); - var localKeys = opts.localKeys, - foreignKeys = opts.foreignKeys, - foreignKey = opts.foreignKey; + if (isEmptyLinks && _this3.canFindLinkFor(record)) { + relatedData = _this3.findExistingLinksFor(record); + } - if (!foreignKey && !localKeys && !foreignKeys) { - throw utils.err('new Relation', 'opts.')(400, 'string', foreignKey); + if (relatedData) { + _this3.setLocalField(record, relatedData); + } + }); } - }, - canFindLinkFor: function canFindLinkFor(record) { - var hasForeignKeys = this.foreignKey || this.foreignKeys; - return !!(hasForeignKeys || this.localKeys && utils.get(record, this.localKeys)); - }, - linkRecord: function linkRecord(record, relatedRecords) { - var _this = this; + }, { + key: "removeLinkedRecords", + value: function removeLinkedRecords(relatedMapper, records) { + var localField = this.localField; + records.forEach(function (record) { + utils.set(record, localField, undefined); + }); + } + }, { + key: "linkRecord", + value: function linkRecord(record, relatedRecord) { + var relatedId = utils.get(relatedRecord, this.mapper.idAttribute); + + if (relatedId === undefined) { + var unsaved = this.relatedCollection.unsaved(); - var relatedCollection = this.relatedCollection; - var canAutoAddLinks = this.canAutoAddLinks; - var foreignKey = this.foreignKey; - var unsaved = this.relatedCollection.unsaved(); - return relatedRecords.map(function (relatedRecord) { - var relatedId = relatedCollection.recordId(relatedRecord); - - if (relatedId === undefined && unsaved.indexOf(relatedRecord) === -1 || relatedRecord !== relatedCollection.get(relatedId)) { - if (foreignKey) { - // TODO: slow, could be optimized? But user loses hook - _this.setForeignKey(record, relatedRecord); + if (unsaved.indexOf(relatedRecord) === -1) { + if (this.canAutoAddLinks) { + relatedRecord = this.relatedCollection.add(relatedRecord); + } } + } else { + if (relatedRecord !== this.relatedCollection.get(relatedId)) { + this.setForeignKey(record, relatedRecord); - if (canAutoAddLinks) { - relatedRecord = relatedCollection.add(relatedRecord); + if (this.canAutoAddLinks) { + relatedRecord = this.relatedCollection.add(relatedRecord); + } } } return relatedRecord; - }); - }, - findExistingLinksFor: function findExistingLinksFor(record) { - var id = utils.get(record, this.mapper.idAttribute); - var ids = this.localKeys ? utils.get(record, this.localKeys) : null; - var records; + } // e.g. user hasMany post via "foreignKey", so find all posts of user - if (id !== undefined && this.foreignKey) { - records = this.findExistingLinksByForeignKey(id); - } else if (this.localKeys && ids) { - records = this.findExistingLinksByLocalKeys(ids); - } else if (id !== undefined && this.foreignKeys) { - records = this.findExistingLinksByForeignKeys(id); - } + }, { + key: "findExistingLinksByForeignKey", + value: function findExistingLinksByForeignKey(id) { + if (id === undefined || id === null) { + return; + } - if (records && records.length) { - return records; + return this.relatedCollection.filter(_defineProperty({}, this.foreignKey, id)); } - }, - // e.g. user hasMany group via "foreignKeys", so find all users of a group - findExistingLinksByLocalKeys: function findExistingLinksByLocalKeys(ids) { - return this.relatedCollection.filter({ - where: _defineProperty({}, this.relatedCollection.mapper.idAttribute, { - in: ids - }) - }); - }, - // e.g. group hasMany user via "localKeys", so find all groups that own a user - findExistingLinksByForeignKeys: function findExistingLinksByForeignKeys(id) { - return this.relatedCollection.filter({ - where: _defineProperty({}, this.foreignKeys, { - contains: id - }) - }); - }, - isRequiresParentId: function isRequiresParentId() { - return !!this.localKeys && this.localKeys.length > 0; - }, - isRequiresChildId: function isRequiresChildId() { - return !!this.foreignKey; - }, - createParentRecord: function createParentRecord(props, opts) { - var _this2 = this; - - var relationData = this.getLocalField(props); - var foreignIdField = this.getRelation().idAttribute; - return this.createLinked(relationData, opts).then(function (records) { - utils.set(props, _this2.localKeys, records.map(function (record) { - return utils.get(record, foreignIdField); - })); - }); - }, - createLinked: function createLinked(props, opts) { - return this.getRelation().createMany(props, opts); - } - }, { - TYPE_NAME: 'hasMany' - }); + }, { + key: "ensureLinkedDataHasProperType", + value: function ensureLinkedDataHasProperType(props, opts) { + var relatedMapper = this.getRelation(); + var relationData = this.getLocalField(props); - var HasOneRelation = Relation.extend({ - findExistingLinksFor: function findExistingLinksFor(relatedMapper, record) { - var recordId = utils.get(record, relatedMapper.idAttribute); - var records = this.findExistingLinksByForeignKey(recordId); + if (utils.isArray(relationData) && (!relationData.length || relatedMapper.is(relationData[0]))) { + return; + } - if (records && records.length) { - return records[0]; + if (relationData && !relatedMapper.is(relationData)) { + utils.set(props, this.localField, relatedMapper.createRecord(relationData, opts)); + } } - }, - isRequiresChildId: function isRequiresChildId() { - return true; - } - }, { - TYPE_NAME: 'hasOne' - }); - - [BelongsToRelation, HasManyRelation, HasOneRelation].forEach(function (RelationType) { - Relation[RelationType.TYPE_NAME] = function (related, options) { - return new RelationType(related, options); - }; - }); - - /** - * BelongsTo relation decorator. You probably won't use this directly. - * - * @name module:js-data.belongsTo - * @method - * @param {Mapper} related The relation the target belongs to. - * @param {object} opts Configuration options. - * @param {string} opts.foreignKey The field that holds the primary key of the - * related record. - * @param {string} opts.localField The field that holds a reference to the - * related record object. - * @returns {Function} Invocation function, which accepts the target as the only - * parameter. - */ - - var belongsTo = function belongsTo(related, opts) { - return function (mapper) { - Relation.belongsTo(related, opts).assignTo(mapper); - }; - }; - /** - * HasMany relation decorator. You probably won't use this directly. - * - * @name module:js-data.hasMany - * @method - * @param {Mapper} related The relation of which the target has many. - * @param {object} opts Configuration options. - * @param {string} [opts.foreignKey] The field that holds the primary key of the - * related record. - * @param {string} opts.localField The field that holds a reference to the - * related record object. - * @returns {Function} Invocation function, which accepts the target as the only - * parameter. - */ + }, { + key: "isRequiresParentId", + value: function isRequiresParentId() { + return false; + } + }, { + key: "isRequiresChildId", + value: function isRequiresChildId() { + return false; + } + }, { + key: "createChildRecord", + value: function createChildRecord(props, relationData, opts) { + var _this4 = this; - var hasMany = function hasMany(related, opts) { - return function (mapper) { - Relation.hasMany(related, opts).assignTo(mapper); - }; - }; - /** - * HasOne relation decorator. You probably won't use this directly. - * - * @name module:js-data.hasOne - * @method - * @param {Mapper} related The relation of which the target has one. - * @param {object} opts Configuration options. - * @param {string} [opts.foreignKey] The field that holds the primary key of the - * related record. - * @param {string} opts.localField The field that holds a reference to the - * related record object. - * @returns {Function} Invocation function, which accepts the target as the only - * parameter. - */ + this.setForeignKey(props, relationData); + return this.createLinked(relationData, opts).then(function (result) { + _this4.setLocalField(props, result); + }); + } + }, { + key: "createLinked", + value: function createLinked(props, opts) { + var create = utils.isArray(props) ? 'createMany' : 'create'; + return this.getRelation()[create](props, opts); + } + }, { + key: "canAutoAddLinks", + get: function get() { + return this.add === undefined || !!this.add; + } + }, { + key: "relatedCollection", + get: function get() { + return this.mapper.datastore.getCollection(this.relation); + } + }]); - var hasOne = function hasOne(related, opts) { - return function (mapper) { - Relation.hasOne(related, opts).assignTo(mapper); - }; - }; + return Relation; + }(); var DOMAIN$3 = 'Record'; - var superMethod = function superMethod(mapper, name) { + function superMethod(mapper, name) { + var _a; + var store = mapper.datastore; - if (store && store[name]) { + if ((_a = store) === null || _a === void 0 ? void 0 : _a[name]) { return function () { for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; @@ -3811,884 +3358,934 @@ } return mapper[name].bind(mapper); - }; // Cache these strings + } // Cache these strings var creatingPath = 'creating'; var noValidatePath = 'noValidate'; var keepChangeHistoryPath = 'keepChangeHistory'; var previousPath = 'previous'; - /** - * js-data's Record class. An instance of `Record` corresponds to an in-memory - * representation of a single row or document in a database, Firebase, - * localstorage, etc. Basically, a `Record` instance represents whatever kind of - * entity in your persistence layer that has a primary key. - * - * ```javascript - * import {Record} from 'js-data' - * ``` - * - * @example Record#constructor - * const JSData = require('js-data'); - * const { Record } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * // Instantiate a plain record - * let record = new Record(); - * console.log('record: ' + JSON.stringify(record)); - * - * // You can supply properties on instantiation - * record = new Record({ name: 'John' }); - * console.log('record: ' + JSON.stringify(record)); - * - * @example Record#constructor2 - * const JSData = require('js-data'); - * const { Mapper } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * // Instantiate a record that's associated with a Mapper: - * const UserMapper = new Mapper({ name: 'user' }); - * const User = UserMapper.recordClass; - * const user = UserMapper.createRecord({ name: 'John' }); - * const user2 = new User({ name: 'Sally' }); - * console.log('user: ' + JSON.stringify(user)); - * console.log('user2: ' + JSON.stringify(user2)); - * - * @example Record#constructor3 - * const JSData = require('js-data'); - * const { Container } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new Container(); - * store.defineMapper('user'); - * - * // Instantiate a record that's associated with a store's Mapper - * const user = store.createRecord('user', { name: 'John' }); - * console.log('user: ' + JSON.stringify(user)); - * - * @example Record#constructor4 - * const JSData = require('js-data'); - * const { Container } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new Container(); - * store.defineMapper('user', { - * schema: { - * properties: { - * name: { type: 'string' } - * } - * } - * }); - * - * // Validate on instantiation - * const user = store.createRecord('user', { name: 1234 }); - * console.log('user: ' + JSON.stringify(user)); - * - * @example Record#constructor5 - * const JSData = require('js-data'); - * const { Container } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new Container(); - * store.defineMapper('user', { - * schema: { - * properties: { - * name: { type: 'string' } - * } - * } - * }); - * - * // Skip validation on instantiation - * const user = store.createRecord('user', { name: 1234 }, { noValidate: true }); - * console.log('user: ' + JSON.stringify(user)); - * console.log('user.isValid(): ' + user.isValid()); - * - * @class Record - * @extends Component - * @param {object} [props] The initial properties of the new Record instance. - * @param {object} [opts] Configuration options. - * @param {boolean} [opts.noValidate=false] Whether to skip validation on the - * initial properties. - * @param {boolean} [opts.validateOnSet=true] Whether to enable setter - * validation on properties after the Record has been initialized. - * @since 3.0.0 + /** + * js-data's Record class. An instance of `Record` corresponds to an in-memory + * representation of a single row or document in a database, Firebase, + * localstorage, etc. Basically, a `Record` instance represents whatever kind of + * entity in your persistence layer that has a primary key. + * + * ```javascript + * import {Record} from 'js-data' + * ``` + * + * @example Record#constructor + * const JSData = require('js-data'); + * const { Record } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * // Instantiate a plain record + * let record = new Record(); + * console.log('record: ' + JSON.stringify(record)); + * + * // You can supply properties on instantiation + * record = new Record({ name: 'John' }); + * console.log('record: ' + JSON.stringify(record)); + * + * @example Record#constructor2 + * const JSData = require('js-data'); + * const { Mapper } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * // Instantiate a record that's associated with a Mapper: + * const UserMapper = new Mapper({ name: 'user' }); + * const User = UserMapper.recordClass; + * const user = UserMapper.createRecord({ name: 'John' }); + * const user2 = new User({ name: 'Sally' }); + * console.log('user: ' + JSON.stringify(user)); + * console.log('user2: ' + JSON.stringify(user2)); + * + * @example Record#constructor3 + * const JSData = require('js-data'); + * const { Container } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new Container(); + * store.defineMapper('user'); + * + * // Instantiate a record that's associated with a store's Mapper + * const user = store.createRecord('user', { name: 'John' }); + * console.log('user: ' + JSON.stringify(user)); + * + * @example Record#constructor4 + * const JSData = require('js-data'); + * const { Container } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new Container(); + * store.defineMapper('user', { + * schema: { + * properties: { + * name: { type: 'string' } + * } + * } + * }); + * + * // Validate on instantiation + * const user = store.createRecord('user', { name: 1234 }); + * console.log('user: ' + JSON.stringify(user)); + * + * @example Record#constructor5 + * const JSData = require('js-data'); + * const { Container } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new Container(); + * store.defineMapper('user', { + * schema: { + * properties: { + * name: { type: 'string' } + * } + * } + * }); + * + * // Skip validation on instantiation + * const user = store.createRecord('user', { name: 1234 }, { noValidate: true }); + * console.log('user: ' + JSON.stringify(user)); + * console.log('user.isValid(): ' + user.isValid()); + * + * @class Record + * @extends Settable + * @param {object} [props] The initial properties of the new Record instance. + * @param {object} [opts] Configuration options. + * @param {boolean} [opts.noValidate=false] Whether to skip validation on the + * initial properties. + * @param {boolean} [opts.validateOnSet=true] Whether to enable setter + * validation on properties after the Record has been initialized. + * @since 3.0.0 */ - function Record(props, opts) { - utils.classCallCheck(this, Record); - Settable.call(this); - props || (props = {}); - opts || (opts = {}); - var _set = this._set; - var mapper = this.constructor.mapper; + var Record = + /*#__PURE__*/ + function (_Settable) { + _inherits(Record, _Settable); - _set(creatingPath, true); + function Record() { + var _this; - _set(noValidatePath, !!opts.noValidate); + var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - _set(keepChangeHistoryPath, opts.keepChangeHistory === undefined ? mapper ? mapper.keepChangeHistory : true : opts.keepChangeHistory); // Set the idAttribute value first, if it exists. + _classCallCheck(this, Record); + var _a; - var id = mapper ? utils.get(props, mapper.idAttribute) : undefined; + _this = _possibleConstructorReturn(this, _getPrototypeOf(Record).call(this)); + var _set = _this._set; + var mapper = _this.constructor.mapper; - if (id !== undefined) { - utils.set(this, mapper.idAttribute, id); - } + _set(creatingPath, true); - utils.fillIn(this, props); + _set(noValidatePath, !!opts.noValidate); - _set(creatingPath, false); + _set(keepChangeHistoryPath, opts.keepChangeHistory === undefined ? mapper ? mapper.keepChangeHistory : true : opts.keepChangeHistory); // Set the idAttribute value first, if it exists. - if (opts.validateOnSet !== undefined) { - _set(noValidatePath, !opts.validateOnSet); - } else if (mapper && mapper.validateOnSet !== undefined) { - _set(noValidatePath, !mapper.validateOnSet); - } else { - _set(noValidatePath, false); - } - - _set(previousPath, mapper ? mapper.toJSON(props) : utils.plainCopy(props)); - } - var Record$1 = Component$1.extend({ - constructor: Record, + var id = mapper ? utils.get(props, mapper.idAttribute) : undefined; - /** - * Returns the {@link Mapper} paired with this record's class, if any. - * - * @method Record#_mapper - * @returns {Mapper} The {@link Mapper} paired with this record's class, if any. - * @since 3.0.0 - */ - _mapper: function _mapper() { - var mapper = this.constructor.mapper; - - if (!mapper) { - throw utils.err("".concat(DOMAIN$3, "#_mapper"), '')(404, 'mapper'); + if (id !== undefined) { + utils.set(_assertThisInitialized(_this), mapper.idAttribute, id); } - return mapper; - }, + utils.fillIn(_assertThisInitialized(_this), props); - /** - * Lifecycle hook. - * - * @method Record#afterLoadRelations - * @param {string[]} relations The `relations` argument passed to {@link Record#loadRelations}. - * @param {object} opts The `opts` argument passed to {@link Record#loadRelations}. - * @since 3.0.0 - */ - afterLoadRelations: function afterLoadRelations() {}, - - /** - * Lifecycle hook. - * - * @method Record#beforeLoadRelations - * @param {string[]} relations The `relations` argument passed to {@link Record#loadRelations}. - * @param {object} opts The `opts` argument passed to {@link Record#loadRelations}. - * @since 3.0.0 - */ - beforeLoadRelations: function beforeLoadRelations() {}, - - /** - * Return the change history of this record since it was instantiated or - * {@link Record#commit} was called. - * - * @method Record#changeHistory - * @since 3.0.0 - */ - changeHistory: function changeHistory() { - return (this._get('history') || []).slice(); - }, + _set(creatingPath, false); - /** - * Return changes to this record since it was instantiated or - * {@link Record#commit} was called. - * - * @example Record#changes - * const JSData = require('js-data'); - * const { Container } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new Container(); - * store.defineMapper('user'); - * const user = store.createRecord('user'); - * console.log('user changes: ' + JSON.stringify(user.changes())); - * user.name = 'John'; - * console.log('user changes: ' + JSON.stringify(user.changes())); - * - * @method Record#changes - * @param [opts] Configuration options. - * @param {Function} [opts.equalsFn={@link utils.deepEqual}] Equality function. - * @param {array} [opts.ignore=[]] Array of strings or RegExp of fields to ignore. - * @returns {Object} Object describing the changes to this record since it was - * instantiated or its {@link Record#commit} method was last called. - * @since 3.0.0 - */ - changes: function changes(opts) { - opts || (opts = {}); - return utils.diffObjects(typeof this.toJSON === 'function' ? this.toJSON(opts) : this, this._get('previous'), opts); - }, + if (opts.validateOnSet !== undefined) { + _set(noValidatePath, !opts.validateOnSet); + } else if (((_a = mapper) === null || _a === void 0 ? void 0 : _a.validateOnSet) !== undefined) { + _set(noValidatePath, !mapper.validateOnSet); + } else { + _set(noValidatePath, false); + } + + _set(previousPath, mapper ? mapper.toJSON(props) : utils.plainCopy(props)); - /** - * Make the record's current in-memory state it's only state, with any - * previous property values being set to current values. - * - * @example Record#commit - * const JSData = require('js-data'); - * const { Container } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new Container(); - * store.defineMapper('user'); - * const user = store.createRecord('user'); - * console.log('user hasChanges: ' + user.hasChanges()); - * user.name = 'John'; - * console.log('user hasChanges: ' + user.hasChanges()); - * user.commit(); - * console.log('user hasChanges: ' + user.hasChanges()); - * - * @method Record#commit - * @param {object} [opts] Configuration options. Passed to {@link Record#toJSON}. - * @since 3.0.0 + return _this; + } + /** + * Returns the {@link Mapper} paired with this record's class, if any. + * + * @method Record#_mapper + * @returns {Mapper} The {@link Mapper} paired with this record's class, if any. + * @since 3.0.0 */ - commit: function commit(opts) { - this._set('changed'); // unset - this._set('changing', false); + _createClass(Record, [{ + key: "_mapper", + value: function _mapper() { + var mapper = this.constructor.mapper; - this._set('history', []); // clear history + if (!mapper) { + throw utils.err("".concat(DOMAIN$3, "#_mapper"), '')(404, 'mapper'); + } + return mapper; + } + /** + * Lifecycle hook. + * + * @method Record#afterLoadRelations + * @param {string[]} relations The `relations` argument passed to {@link Record#loadRelations}. + * @param {object} opts The `opts` argument passed to {@link Record#loadRelations}. + * @since 3.0.0 + */ - this._set('previous', this.toJSON(opts)); - }, + }, { + key: "afterLoadRelations", + value: function afterLoadRelations(relations, opts) {} + /** + * Lifecycle hook. + * + * @method Record#beforeLoadRelations + * @param {string[]} relations The `relations` argument passed to {@link Record#loadRelations}. + * @param {object} opts The `opts` argument passed to {@link Record#loadRelations}. + * @since 3.0.0 + */ - /** - * Call {@link Mapper#destroy} using this record's primary key. - * - * @example - * import { Container } from 'js-data'; - * import { RethinkDBAdapter } from 'js-data-rethinkdb'; - * - * const store = new Container(); - * store.registerAdapter('rethink', new RethinkDBAdapter(), { default: true }); - * store.defineMapper('user'); - * store.find('user', 1234).then((user) => { - * console.log(user.id); // 1234 - * - * // Destroy this user from the database - * return user.destroy(); - * }); - * - * @method Record#destroy - * @param {object} [opts] Configuration options passed to {@link Mapper#destroy}. - * @returns {Promise} The result of calling {@link Mapper#destroy} with the - * primary key of this record. - * @since 3.0.0 - */ - destroy: function destroy(opts) { - opts || (opts = {}); + }, { + key: "beforeLoadRelations", + value: function beforeLoadRelations(relations, opts) {} + /** + * Return the change history of this record since it was instantiated or + * {@link Record#commit} was called. + * + * @method Record#changeHistory + * @since 3.0.0 + */ - var mapper = this._mapper(); + }, { + key: "changeHistory", + value: function changeHistory() { + return (this._get('history') || []).slice(); + } + /** + * Return changes to this record since it was instantiated or + * {@link Record#commit} was called. + * + * @example Record#changes + * const JSData = require('js-data'); + * const { Container } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new Container(); + * store.defineMapper('user'); + * const user = store.createRecord('user'); + * console.log('user changes: ' + JSON.stringify(user.changes())); + * user.name = 'John'; + * console.log('user changes: ' + JSON.stringify(user.changes())); + * + * @method Record#changes + * @param [opts] Configuration options. + * @param {Function} [opts.equalsFn={@link utils.deepEqual}] Equality function. + * @param {array} [opts.ignore=[]] Array of strings or RegExp of fields to ignore. + * @returns {Object} Object describing the changes to this record since it was + * instantiated or its {@link Record#commit} method was last called. + * @since 3.0.0 + */ - return superMethod(mapper, 'destroy')(utils.get(this, mapper.idAttribute), opts); - }, + }, { + key: "changes", + value: function changes() { + var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + return utils.diffObjects(typeof this.toJSON === 'function' ? this.toJSON(opts) : this, this._get('previous'), opts); + } + /** + * Make the record's current in-memory state it's only state, with any + * previous property values being set to current values. + * + * @example Record#commit + * const JSData = require('js-data'); + * const { Container } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new Container(); + * store.defineMapper('user'); + * const user = store.createRecord('user'); + * console.log('user hasChanges: ' + user.hasChanges()); + * user.name = 'John'; + * console.log('user hasChanges: ' + user.hasChanges()); + * user.commit(); + * console.log('user hasChanges: ' + user.hasChanges()); + * + * @method Record#commit + * @param {object} [opts] Configuration options. Passed to {@link Record#toJSON}. + * @since 3.0.0 + */ - /** - * Return the value at the given path for this instance. - * - * @example Record#get - * const JSData = require('js-data'); - * const { Container } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * const store = new Container(); - * store.defineMapper('user'); - * - * const user = store.createRecord('user', { name: 'Bob' }); - * console.log('user.get("name"): ' + user.get('name')); - * - * @method Record#get - * @param {string} key Path of value to retrieve. - * @returns {*} Value at path. - * @since 3.0.0 - */ - 'get': function get(key) { - return utils.get(this, key); - }, + }, { + key: "commit", + value: function commit(opts) { + this._set('changed'); // unset + + + this._set('changing', false); + + this._set('history', []); // clear history + + + this._set('previous', this.toJSON(opts)); + } + /** + * Call {@link Mapper#destroy} using this record's primary key. + * + * @example + * import { Container } from 'js-data'; + * import { RethinkDBAdapter } from 'js-data-rethinkdb'; + * + * const store = new Container(); + * store.registerAdapter('rethink', new RethinkDBAdapter(), { default: true }); + * store.defineMapper('user'); + * store.find('user', 1234).then((user) => { + * console.log(user.id); // 1234 + * + * // Destroy this user from the database + * return user.destroy(); + * }); + * + * @method Record#destroy + * @param {object} [opts] Configuration options passed to {@link Mapper#destroy}. + * @returns {Promise} The result of calling {@link Mapper#destroy} with the + * primary key of this record. + * @since 3.0.0 + */ - /** - * Return whether this record has changed since it was instantiated or - * {@link Record#commit} was called. - * - * @example Record#hasChanges - * const JSData = require('js-data'); - * const { Container } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * const store = new Container(); - * store.defineMapper('user'); - * const user = store.createRecord('user'); - * console.log('user hasChanges: ' + user.hasChanges()); - * user.name = 'John'; - * console.log('user hasChanges: ' + user.hasChanges()); - * user.commit(); - * console.log('user hasChanges: ' + user.hasChanges()); - * - * @method Record#hasChanges - * @param [opts] Configuration options. - * @param {Function} [opts.equalsFn={@link utils.deepEqual}] Equality function. - * @param {array} [opts.ignore=[]] Array of strings or RegExp of fields to ignore. - * @returns {boolean} Return whether the record has changed since it was - * instantiated or since its {@link Record#commit} method was called. - * @since 3.0.0 - */ - hasChanges: function hasChanges(opts) { - var quickHasChanges = !!(this._get('changed') || []).length; - return quickHasChanges || utils.areDifferent(typeof this.toJSON === 'function' ? this.toJSON(opts) : this, this._get('previous'), opts); - }, + }, { + key: "destroy", + value: function destroy() { + var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + + var mapper = this._mapper(); + + return superMethod(mapper, 'destroy')(utils.get(this, mapper.idAttribute), opts); + } + /** + * Return the value at the given path for this instance. + * + * @example Record#get + * const JSData = require('js-data'); + * const { Container } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * const store = new Container(); + * store.defineMapper('user'); + * + * const user = store.createRecord('user', { name: 'Bob' }); + * console.log('user.get("name"): ' + user.get('name')); + * + * @method Record#get + * @param {string} key Path of value to retrieve. + * @returns {*} Value at path. + * @since 3.0.0 + */ - /** - * Return whether the record is unsaved. Records that have primary keys are - * considered "saved". Records without primary keys are considered "unsaved". - * - * @example Record#isNew - * const JSData = require('js-data'); - * const { Container } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * const store = new Container(); - * store.defineMapper('user'); - * const user = store.createRecord('user', { - * id: 1234 - * }); - * const user2 = store.createRecord('user'); - * console.log('user isNew: ' + user.isNew()); // false - * console.log('user2 isNew: ' + user2.isNew()); // true - * - * @method Record#isNew - * @returns {boolean} Whether the record is unsaved. - * @since 3.0.0 - */ - isNew: function isNew(opts) { - return utils.get(this, this._mapper().idAttribute) === undefined; - }, + }, { + key: "get", + value: function get(key) { + return utils.get(this, key); + } + /** + * Return whether this record has changed since it was instantiated or + * {@link Record#commit} was called. + * + * @example Record#hasChanges + * const JSData = require('js-data'); + * const { Container } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * const store = new Container(); + * store.defineMapper('user'); + * const user = store.createRecord('user'); + * console.log('user hasChanges: ' + user.hasChanges()); + * user.name = 'John'; + * console.log('user hasChanges: ' + user.hasChanges()); + * user.commit(); + * console.log('user hasChanges: ' + user.hasChanges()); + * + * @method Record#hasChanges + * @param [opts] Configuration options. + * @param {Function} [opts.equalsFn={@link utils.deepEqual}] Equality function. + * @param {array} [opts.ignore=[]] Array of strings or RegExp of fields to ignore. + * @returns {boolean} Return whether the record has changed since it was + * instantiated or since its {@link Record#commit} method was called. + * @since 3.0.0 + */ - /** - * Return whether the record in its current state passes validation. - * - * @example Record#isValid - * const JSData = require('js-data'); - * const { Container } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * const store = new Container(); - * store.defineMapper('user', { - * schema: { - * properties: { - * name: { type: 'string' } - * } - * } - * }); - * const user = store.createRecord('user', { - * name: 1234 - * }, { - * noValidate: true // this allows us to put the record into an invalid state - * }); - * console.log('user isValid: ' + user.isValid()); - * user.name = 'John'; - * console.log('user isValid: ' + user.isValid()); - * - * @method Record#isValid - * @param {object} [opts] Configuration options. Passed to {@link Mapper#validate}. - * @returns {boolean} Whether the record in its current state passes - * validation. - * @since 3.0.0 - */ - isValid: function isValid(opts) { - return !this._mapper().validate(this, opts); - }, - removeInverseRelation: function removeInverseRelation(currentParent, id, inverseDef, idAttribute) { - var _this = this; + }, { + key: "hasChanges", + value: function hasChanges(opts) { + var quickHasChanges = !!(this._get('changed') || []).length; + return quickHasChanges || utils.areDifferent(typeof this.toJSON === 'function' ? this.toJSON(opts) : this, this._get('previous'), opts); + } + /** + * Return whether the record is unsaved. Records that have primary keys are + * considered "saved". Records without primary keys are considered "unsaved". + * + * @example Record#isNew + * const JSData = require('js-data'); + * const { Container } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * const store = new Container(); + * store.defineMapper('user'); + * const user = store.createRecord('user', { + * id: 1234 + * }); + * const user2 = store.createRecord('user'); + * console.log('user isNew: ' + user.isNew()); // false + * console.log('user2 isNew: ' + user2.isNew()); // true + * + * @method Record#isNew + * @returns {boolean} Whether the record is unsaved. + * @since 3.0.0 + */ - if (inverseDef.type === hasOneType) { - safeSetLink(currentParent, inverseDef.localField, undefined); - } else if (inverseDef.type === hasManyType) { - // e.g. remove comment from otherPost.comments - var children = utils.get(currentParent, inverseDef.localField); + }, { + key: "isNew", + value: function isNew(opts) { + return utils.get(this, this._mapper().idAttribute) === undefined; + } + /** + * Return whether the record in its current state passes validation. + * + * @example Record#isValid + * const JSData = require('js-data'); + * const { Container } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * const store = new Container(); + * store.defineMapper('user', { + * schema: { + * properties: { + * name: { type: 'string' } + * } + * } + * }); + * const user = store.createRecord('user', { + * name: 1234 + * }, { + * noValidate: true // this allows us to put the record into an invalid state + * }); + * console.log('user isValid: ' + user.isValid()); + * user.name = 'John'; + * console.log('user isValid: ' + user.isValid()); + * + * @method Record#isValid + * @param {object} [opts] Configuration options. Passed to {@link Mapper#validate}. + * @returns {boolean} Whether the record in its current state passes + * validation. + * @since 3.0.0 + */ - if (id === undefined) { - utils.remove(children, function (child) { - return child === _this; - }); - } else { - utils.remove(children, function (child) { - return child === _this || id === utils.get(child, idAttribute); - }); + }, { + key: "isValid", + value: function isValid(opts) { + return !this._mapper().validate(this, opts); + } + }, { + key: "removeInverseRelation", + value: function removeInverseRelation(currentParent, id, inverseDef, idAttribute) { + var _this2 = this; + + if (inverseDef.type === hasOneType) { + safeSetLink(currentParent, inverseDef.localField, undefined); + } else if (inverseDef.type === hasManyType) { + // e.g. remove comment from otherPost.comments + var children = utils.get(currentParent, inverseDef.localField); + + if (id === undefined) { + utils.remove(children, function (child) { + return child === _this2; + }); + } else { + utils.remove(children, function (child) { + return child === _this2 || id === utils.get(child, idAttribute); + }); + } } } - }, - setupInverseRelation: function setupInverseRelation(record, id, inverseDef, idAttribute) { - var _this2 = this; - - // Update (set) inverse relation - if (inverseDef.type === hasOneType) { - // e.g. someUser.profile = profile - safeSetLink(record, inverseDef.localField, this); - } else if (inverseDef.type === hasManyType) { - // e.g. add comment to somePost.comments - var children = utils.get(record, inverseDef.localField); + }, { + key: "setupInverseRelation", + value: function setupInverseRelation(record, id, inverseDef, idAttribute) { + var _this3 = this; - if (id === undefined) { - utils.noDupeAdd(children, this, function (child) { - return child === _this2; - }); - } else { - utils.noDupeAdd(children, this, function (child) { - return child === _this2 || id === utils.get(child, idAttribute); - }); + // Update (set) inverse relation + if (inverseDef.type === hasOneType) { + // e.g. someUser.profile = profile + safeSetLink(record, inverseDef.localField, this); + } else if (inverseDef.type === hasManyType) { + // e.g. add comment to somePost.comments + var children = utils.get(record, inverseDef.localField); + + if (id === undefined) { + utils.noDupeAdd(children, this, function (child) { + return child === _this3; + }); + } else { + utils.noDupeAdd(children, this, function (child) { + return child === _this3 || id === utils.get(child, idAttribute); + }); + } } } - }, - - /** - * Lazy load relations of this record, to be attached to the record once their - * loaded. - * - * @example - * import { Container } from 'js-data'; - * import { RethinkDBAdapter } from 'js-data-rethinkdb'; - * - * const store = new Container(); - * store.registerAdapter('rethink', new RethinkDBAdapter(), { default: true }); - * store.defineMapper('user', { - * relations: { - * hasMany: { - * post: { - * localField: 'posts', - * foreignKey: 'user_id' - * } - * } - * } - * }); - * store.defineMapper('post', { - * relations: { - * belongsTo: { - * user: { - * localField: 'user', - * foreignKey: 'user_id' - * } - * } - * } - * }); - * store.find('user', 1234).then((user) => { - * console.log(user.id); // 1234 - * - * // Load the user's post relations - * return user.loadRelations(['post']); - * }).then((user) => { - * console.log(user.posts); // [{...}, {...}, ...] - * }); - * - * @method Record#loadRelations - * @param {string[]} [relations] List of relations to load. Can use localField - * names or Mapper names to pick relations. - * @param {object} [opts] Configuration options. - * @returns {Promise} Resolves with the record, with the loaded relations now - * attached. - * @since 3.0.0 - */ - loadRelations: function loadRelations(relations, opts) { - var _this3 = this; - - var op; + /** + * Lazy load relations of this record, to be attached to the record once their + * loaded. + * + * @example + * import { Container } from 'js-data'; + * import { RethinkDBAdapter } from 'js-data-rethinkdb'; + * + * const store = new Container(); + * store.registerAdapter('rethink', new RethinkDBAdapter(), { default: true }); + * store.defineMapper('user', { + * relations: { + * hasMany: { + * post: { + * localField: 'posts', + * foreignKey: 'user_id' + * } + * } + * } + * }); + * store.defineMapper('post', { + * relations: { + * belongsTo: { + * user: { + * localField: 'user', + * foreignKey: 'user_id' + * } + * } + * } + * }); + * store.find('user', 1234).then((user) => { + * console.log(user.id); // 1234 + * + * // Load the user's post relations + * return user.loadRelations(['post']); + * }).then((user) => { + * console.log(user.posts); // [{...}, {...}, ...] + * }); + * + * @method Record#loadRelations + * @param {string[]} [relations] List of relations to load. Can use localField + * names or Mapper names to pick relations. + * @param {object} [opts] Configuration options. + * @returns {Promise} Resolves with the record, with the loaded relations now + * attached. + * @since 3.0.0 + */ - var mapper = this._mapper(); // Default values for arguments + }, { + key: "loadRelations", + value: function loadRelations() { + var _this4 = this; + var relations = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var op; - relations || (relations = []); + var mapper = this._mapper(); - if (utils.isString(relations)) { - relations = [relations]; - } + if (utils.isString(relations)) { + relations = [relations]; + } - opts || (opts = {}); - opts.with = relations; // Fill in "opts" with the Model's configuration + opts["with"] = relations; // Fill in "opts" with the Model's configuration - utils._(opts, mapper); + utils._(opts, mapper); - opts.adapter = mapper.getAdapterName(opts); // beforeLoadRelations lifecycle hook + opts.adapter = mapper.getAdapterName(opts); // beforeLoadRelations lifecycle hook - op = opts.op = 'beforeLoadRelations'; - return utils.resolve(this[op](relations, opts)).then(function () { - // Now delegate to the adapter - op = opts.op = 'loadRelations'; - mapper.dbg(op, _this3, relations, opts); - var tasks = []; - var task; - utils.forEachRelation(mapper, opts, function (def, optsCopy) { - var relatedMapper = def.getRelation(); - optsCopy.raw = false; + op = opts.op = 'beforeLoadRelations'; + return utils.resolve(this[op](relations, opts)).then(function () { + // Now delegate to the adapter + op = opts.op = 'loadRelations'; + mapper.dbg(op, _this4, relations, opts); + var tasks = []; + var task; + utils.forEachRelation(mapper, opts, function (def, optsCopy) { + var relatedMapper = def.getRelation(); + optsCopy.raw = false; - if (utils.isFunction(def.load)) { - task = def.load(mapper, def, _this3, opts); - } else if (def.type === 'hasMany' || def.type === 'hasOne') { - if (def.foreignKey) { - task = superMethod(relatedMapper, 'findAll')(_defineProperty({}, def.foreignKey, utils.get(_this3, mapper.idAttribute)), optsCopy).then(function (relatedData) { - if (def.type === 'hasOne') { - return relatedData.length ? relatedData[0] : undefined; - } + if (utils.isFunction(def.load)) { + task = def.load(mapper, def, _this4, opts); + } else if (def.type === 'hasMany' || def.type === 'hasOne') { + if (def.foreignKey) { + task = superMethod(relatedMapper, 'findAll')(_defineProperty({}, def.foreignKey, utils.get(_this4, mapper.idAttribute)), optsCopy).then(function (relatedData) { + return def.type === 'hasOne' ? relatedData.length ? relatedData[0] : undefined : relatedData; + }); + } else if (def.localKeys) { + task = superMethod(relatedMapper, 'findAll')({ + where: _defineProperty({}, relatedMapper.idAttribute, { + "in": utils.get(_this4, def.localKeys) + }) + }); + } else if (def.foreignKeys) { + task = superMethod(relatedMapper, 'findAll')({ + where: _defineProperty({}, def.foreignKeys, { + contains: utils.get(_this4, mapper.idAttribute) + }) + }, opts); + } + } else if (def.type === 'belongsTo') { + var key = utils.get(_this4, def.foreignKey); - return relatedData; - }); - } else if (def.localKeys) { - task = superMethod(relatedMapper, 'findAll')({ - where: _defineProperty({}, relatedMapper.idAttribute, { - in: utils.get(_this3, def.localKeys) - }) - }); - } else if (def.foreignKeys) { - task = superMethod(relatedMapper, 'findAll')({ - where: _defineProperty({}, def.foreignKeys, { - contains: utils.get(_this3, mapper.idAttribute) - }) - }, opts); + if (utils.isSorN(key)) { + task = superMethod(relatedMapper, 'find')(key, optsCopy); + } } - } else if (def.type === 'belongsTo') { - var key = utils.get(_this3, def.foreignKey); - if (utils.isSorN(key)) { - task = superMethod(relatedMapper, 'find')(key, optsCopy); + if (task) { + task = task.then(function (relatedData) { + def.setLocalField(_this4, relatedData); + }); + tasks.push(task); } - } - - if (task) { - task = task.then(function (relatedData) { - def.setLocalField(_this3, relatedData); - }); - tasks.push(task); - } - }); - return Promise.all(tasks); - }).then(function () { - // afterLoadRelations lifecycle hook - op = opts.op = 'afterLoadRelations'; - return utils.resolve(_this3[op](relations, opts)).then(function () { - return _this3; + }); + return Promise.all(tasks); + }).then(function () { + // afterLoadRelations lifecycle hook + op = opts.op = 'afterLoadRelations'; + return utils.resolve(_this4[op](relations, opts)).then(function () { + return _this4; + }); }); - }); - }, - - /** - * Return the properties with which this record was instantiated. - * - * @example Record#previous - * const JSData = require('js-data'); - * const { Container } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * const store = new Container(); - * store.defineMapper('user'); - * const user = store.createRecord('user', { - * name: 'William' - * }); - * console.log('user previous: ' + JSON.stringify(user.previous())); - * user.name = 'Bob'; - * console.log('user previous: ' + JSON.stringify(user.previous())); - * user.commit(); - * console.log('user previous: ' + JSON.stringify(user.previous())); - * - * @method Record#previous - * @param {string} [key] If specified, return just the initial value of the - * given key. - * @returns {Object} The initial properties of this record. - * @since 3.0.0 - */ - previous: function previous(key) { - if (key) { - return this._get("previous.".concat(key)); } + /** + * Return the properties with which this record was instantiated. + * + * @example Record#previous + * const JSData = require('js-data'); + * const { Container } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * const store = new Container(); + * store.defineMapper('user'); + * const user = store.createRecord('user', { + * name: 'William' + * }); + * console.log('user previous: ' + JSON.stringify(user.previous())); + * user.name = 'Bob'; + * console.log('user previous: ' + JSON.stringify(user.previous())); + * user.commit(); + * console.log('user previous: ' + JSON.stringify(user.previous())); + * + * @method Record#previous + * @param {string} [key] If specified, return just the initial value of the + * given key. + * @returns {Object} The initial properties of this record. + * @since 3.0.0 + */ - return this._get('previous'); - }, + }, { + key: "previous", + value: function previous(key) { + if (key) { + return this._get("previous.".concat(key)); + } - /** - * Revert changes to this record back to the properties it had when it was - * instantiated. - * - * @example Record#revert - * const JSData = require('js-data'); - * const { Container } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * const store = new Container(); - * store.defineMapper('user'); - * const user = store.createRecord('user', { - * name: 'William' - * }); - * console.log('user: ' + JSON.stringify(user)); - * user.name = 'Bob'; - * console.log('user: ' + JSON.stringify(user)); - * user.revert(); - * console.log('user: ' + JSON.stringify(user)); - * - * @method Record#revert - * @param {object} [opts] Configuration options. - * @param {string[]} [opts.preserve] Array of strings or Regular Expressions - * denoting properties that should not be reverted. - * @since 3.0.0 - */ - revert: function revert(opts) { - var _this4 = this; + return this._get('previous'); + } + /** + * Revert changes to this record back to the properties it had when it was + * instantiated. + * + * @example Record#revert + * const JSData = require('js-data'); + * const { Container } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * const store = new Container(); + * store.defineMapper('user'); + * const user = store.createRecord('user', { + * name: 'William' + * }); + * console.log('user: ' + JSON.stringify(user)); + * user.name = 'Bob'; + * console.log('user: ' + JSON.stringify(user)); + * user.revert(); + * console.log('user: ' + JSON.stringify(user)); + * + * @method Record#revert + * @param {object} [opts] Configuration options. + * @param {string[]} [opts.preserve] Array of strings or Regular Expressions + * denoting properties that should not be reverted. + * @since 3.0.0 + */ - var previous = this._get('previous'); + }, { + key: "revert", + value: function revert() { + var _this5 = this; - opts || (opts = {}); - opts.preserve || (opts.preserve = []); - utils.forOwn(this, function (value, key) { - if (key !== _this4._mapper().idAttribute && !Object.hasOwnProperty.call(previous, key) && Object.hasOwnProperty.call(_this4, key) && opts.preserve.indexOf(key) === -1) { - delete _this4[key]; - } - }); - utils.forOwn(previous, function (value, key) { - if (opts.preserve.indexOf(key) === -1) { - _this4[key] = value; - } - }); - this.commit(); - }, + var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - /** - * Delegates to {@link Mapper#create} or {@link Mapper#update}. - * - * @example - * import { Container } from 'js-data'; - * import { RethinkDBAdapter } from 'js-data-rethinkdb'; - * - * const store = new Container(); - * store.registerAdapter('rethink', new RethinkDBAdapter(), { default: true }); - * store.defineMapper('session'); - * const session = store.createRecord('session', { topic: 'Node.js' }); - * - * // Create a new record in the database - * session.save().then(() => { - * console.log(session.id); // 1234 - * - * session.skill_level = 'beginner'; - * - * // Update the record in the database - * return session.save(); - * }); - * - * @method Record#save - * @param {object} [opts] Configuration options. See {@link Mapper#create} and - * {@link Mapper#update}. - * @param {boolean} [opts.changesOnly] Equality function. Default uses `===`. - * @param {Function} [opts.equalsFn] Passed to {@link Record#changes} when - * `opts.changesOnly` is `true`. - * @param {array} [opts.ignore] Passed to {@link Record#changes} when - * `opts.changesOnly` is `true`. - * @returns {Promise} The result of calling {@link Mapper#create} or - * {@link Mapper#update}. - * @since 3.0.0 - */ - save: function save(opts) { - var _this5 = this; + var previous = this._get('previous'); - opts || (opts = {}); + opts.preserve = opts.preserve || []; + utils.forOwn(this, function (value, key) { + if (key !== _this5._mapper().idAttribute && !previous.hasOwnProperty(key) && _this5.hasOwnProperty(key) && opts.preserve.indexOf(key) === -1) { + delete _this5[key]; + } + }); + utils.forOwn(previous, function (value, key) { + if (opts.preserve.indexOf(key) === -1) { + _this5[key] = value; + } + }); + this.commit(); + } + /** + * Delegates to {@link Mapper#create} or {@link Mapper#update}. + * + * @example + * import { Container } from 'js-data'; + * import { RethinkDBAdapter } from 'js-data-rethinkdb'; + * + * const store = new Container(); + * store.registerAdapter('rethink', new RethinkDBAdapter(), { default: true }); + * store.defineMapper('session'); + * const session = store.createRecord('session', { topic: 'Node.js' }); + * + * // Create a new record in the database + * session.save().then(() => { + * console.log(session.id); // 1234 + * + * session.skill_level = 'beginner'; + * + * // Update the record in the database + * return session.save(); + * }); + * + * @method Record#save + * @param {object} [opts] Configuration options. See {@link Mapper#create} and + * {@link Mapper#update}. + * @param {boolean} [opts.changesOnly] Equality function. Default uses `===`. + * @param {Function} [opts.equalsFn] Passed to {@link Record#changes} when + * `opts.changesOnly` is `true`. + * @param {array} [opts.ignore] Passed to {@link Record#changes} when + * `opts.changesOnly` is `true`. + * @returns {Promise} The result of calling {@link Mapper#create} or + * {@link Mapper#update}. + * @since 3.0.0 + */ - var mapper = this._mapper(); + }, { + key: "save", + value: function save() { + var _this6 = this; - var id = utils.get(this, mapper.idAttribute); - var props = this; + var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - var postProcess = function postProcess(result) { - var record = opts.raw ? result.data : result; + var mapper = this._mapper(); - if (record) { - utils.deepMixIn(_this5, record); + var id = utils.get(this, mapper.idAttribute); + var props = this; - _this5.commit(); - } + var postProcess = function postProcess(result) { + var record = opts.raw ? result.data : result; - return result; - }; + if (record) { + utils.deepMixIn(_this6, record); - if (id === undefined) { - return superMethod(mapper, 'create')(props, opts).then(postProcess); - } + _this6.commit(); + } - if (opts.changesOnly) { - var changes = this.changes(opts); - props = {}; - utils.fillIn(props, changes.added); - utils.fillIn(props, changes.changed); - } + return result; + }; - return superMethod(mapper, 'update')(id, props, opts).then(postProcess); - }, + if (id === undefined) { + return superMethod(mapper, 'create')(props, opts).then(postProcess); + } - /** - * Set the value for a given key, or the values for the given keys if "key" is - * an object. Triggers change events on those properties that have `track: true` - * in {@link Mapper#schema}. - * - * @example Record#set - * const JSData = require('js-data'); - * const { Container } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * const store = new Container(); - * store.defineMapper('user'); - * - * const user = store.createRecord('user'); - * console.log('user: ' + JSON.stringify(user)); - * - * user.set('name', 'Bob'); - * console.log('user: ' + JSON.stringify(user)); - * - * user.set({ age: 30, role: 'admin' }); - * console.log('user: ' + JSON.stringify(user)); - * - * @fires Record#change - * @method Record#set - * @param {(string|Object)} key Key to set or hash of key-value pairs to set. - * @param {*} [value] Value to set for the given key. - * @param {object} [opts] Configuration options. - * @param {boolean} [opts.silent=false] Whether to trigger change events. - * @since 3.0.0 - */ - 'set': function set(key, value, opts) { - if (utils.isObject(key)) { - opts = value; - } + if (opts.changesOnly) { + var changes = this.changes(opts); + props = {}; + utils.fillIn(props, changes.added); + utils.fillIn(props, changes.changed); + } - opts || (opts = {}); + return superMethod(mapper, 'update')(id, props, opts).then(postProcess); + } + /** + * Set the value for a given key, or the values for the given keys if "key" is + * an object. Triggers change events on those properties that have `track: true` + * in {@link Mapper#schema}. + * + * @example Record#set + * const JSData = require('js-data'); + * const { Container } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * const store = new Container(); + * store.defineMapper('user'); + * + * const user = store.createRecord('user'); + * console.log('user: ' + JSON.stringify(user)); + * + * user.set('name', 'Bob'); + * console.log('user: ' + JSON.stringify(user)); + * + * user.set({ age: 30, role: 'admin' }); + * console.log('user: ' + JSON.stringify(user)); + * + * @fires Record#change + * @method Record#set + * @param {(string|Object)} key Key to set or hash of key-value pairs to set. + * @param {*} [value] Value to set for the given key. + * @param {object} [opts] Configuration options. + * @param {boolean} [opts.silent=false] Whether to trigger change events. + * @since 3.0.0 + */ - if (opts.silent) { - this._set('silent', true); - } + }, { + key: "set", + value: function set(key, value, opts) { + if (utils.isObject(key)) { + opts = value; + } + + opts = opts || {}; - utils.set(this, key, value); + if (opts.silent) { + this._set('silent', true); + } + + utils.set(this, key, value); - if (!this._get('eventId')) { - this._set('silent'); // unset + if (!this._get('eventId')) { + this._set('silent'); // unset + } } - }, + /** + * Return a plain object representation of this record. If the class from + * which this record was created has a Mapper, then {@link Mapper#toJSON} will + * be called with this record instead. + * + * @example Record#toJSON + * const JSData = require('js-data'); + * const { Container } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * const store = new Container(); + * store.defineMapper('user', { + * schema: { + * properties: { + * name: { type: 'string' } + * } + * } + * }); + * + * const user = store.createRecord('user', { + * name: 'John', + * $$hashKey: '1234' + * }); + * console.log('user: ' + JSON.stringify(user.toJSON())); + * + * @method Record#toJSON + * @param {object} [opts] Configuration options. + * @param {string[]} [opts.with] Array of relation names or relation fields + * to include in the representation. Only available as an option if the class + * from which this record was created has a Mapper and this record resides in + * an instance of {@link DataStore}. + * @returns {Object} Plain object representation of this record. + * @since 3.0.0 + */ - /** - * Return a plain object representation of this record. If the class from - * which this record was created has a Mapper, then {@link Mapper#toJSON} will - * be called with this record instead. - * - * @example Record#toJSON - * const JSData = require('js-data'); - * const { Container } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * const store = new Container(); - * store.defineMapper('user', { - * schema: { - * properties: { - * name: { type: 'string' } - * } - * } - * }); - * - * const user = store.createRecord('user', { - * name: 'John', - * $$hashKey: '1234' - * }); - * console.log('user: ' + JSON.stringify(user.toJSON())); - * - * @method Record#toJSON - * @param {object} [opts] Configuration options. - * @param {string[]} [opts.with] Array of relation names or relation fields - * to include in the representation. Only available as an option if the class - * from which this record was created has a Mapper and this record resides in - * an instance of {@link DataStore}. - * @returns {Object} Plain object representation of this record. - * @since 3.0.0 - */ - toJSON: function toJSON(opts) { - var mapper = this.constructor.mapper; + }, { + key: "toJSON", + value: function toJSON(opts) { + var mapper = this.constructor.mapper; - if (mapper) { - return mapper.toJSON(this, opts); - } else { - var json = {}; - utils.forOwn(this, function (prop, key) { - json[key] = utils.plainCopy(prop); - }); - return json; + if (mapper) { + return mapper.toJSON(this, opts); + } else { + var json = {}; + utils.forOwn(this, function (prop, key) { + json[key] = utils.plainCopy(prop); + }); + return json; + } } - }, + /** + * Unset the value for a given key. Triggers change events on those properties + * that have `track: true` in {@link Mapper#schema}. + * + * @example Record#unset + * const JSData = require('js-data'); + * const { Container } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * const store = new Container(); + * store.defineMapper('user'); + * + * const user = store.createRecord('user', { + * name: 'John' + * }); + * console.log('user: ' + JSON.stringify(user)); + * + * user.unset('name'); + * console.log('user: ' + JSON.stringify(user)); + * + * @method Record#unset + * @param {string} key Key to unset. + * @param {object} [opts] Configuration options. + * @param {boolean} [opts.silent=false] Whether to trigger change events. + * @since 3.0.0 + */ - /** - * Unset the value for a given key. Triggers change events on those properties - * that have `track: true` in {@link Mapper#schema}. - * - * @example Record#unset - * const JSData = require('js-data'); - * const { Container } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * const store = new Container(); - * store.defineMapper('user'); - * - * const user = store.createRecord('user', { - * name: 'John' - * }); - * console.log('user: ' + JSON.stringify(user)); - * - * user.unset('name'); - * console.log('user: ' + JSON.stringify(user)); - * - * @method Record#unset - * @param {string} key Key to unset. - * @param {object} [opts] Configuration options. - * @param {boolean} [opts.silent=false] Whether to trigger change events. - * @since 3.0.0 - */ - unset: function unset(key, opts) { - this.set(key, undefined, opts); - }, + }, { + key: "unset", + value: function unset(key, opts) { + this.set(key, undefined, opts); + } + /** + * Validate this record based on its current properties. + * + * @example Record#validate + * const JSData = require('js-data'); + * const { Container } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * const store = new Container(); + * store.defineMapper('user', { + * schema: { + * properties: { + * name: { type: 'string' } + * } + * } + * }); + * const user = store.createRecord('user', { + * name: 1234 + * }, { + * noValidate: true // this allows us to put the record into an invalid state + * }); + * console.log('user validation: ' + JSON.stringify(user.validate())); + * user.name = 'John'; + * console.log('user validation: ' + user.validate()); + * + * @method Record#validate + * @param {object} [opts] Configuration options. Passed to {@link Mapper#validate}. + * @returns {*} Array of errors or `undefined` if no errors. + * @since 3.0.0 + */ - /** - * Validate this record based on its current properties. - * - * @example Record#validate - * const JSData = require('js-data'); - * const { Container } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * const store = new Container(); - * store.defineMapper('user', { - * schema: { - * properties: { - * name: { type: 'string' } - * } - * } - * }); - * const user = store.createRecord('user', { - * name: 1234 - * }, { - * noValidate: true // this allows us to put the record into an invalid state - * }); - * console.log('user validation: ' + JSON.stringify(user.validate())); - * user.name = 'John'; - * console.log('user validation: ' + user.validate()); - * - * @method Record#validate - * @param {object} [opts] Configuration options. Passed to {@link Mapper#validate}. - * @returns {*} Array of errors or `undefined` if no errors. - * @since 3.0.0 - */ - validate: function validate(opts) { - return this._mapper().validate(this, opts); - } - }, { - creatingPath: creatingPath, - noValidatePath: noValidatePath, - keepChangeHistoryPath: keepChangeHistoryPath, - previousPath: previousPath - }); - /** - * Allow records to emit events. - * - * An record's registered listeners are stored in the record's private data. + }, { + key: "validate", + value: function validate(opts) { + return this._mapper().validate(this, opts); + } + }]); + + return Record; + }(Settable); + Record.creatingPath = creatingPath; + Record.noValidatePath = noValidatePath; + Record.keepChangeHistoryPath = keepChangeHistoryPath; + Record.previousPath = previousPath; + /** + * Allow records to emit events. + * + * An record's registered listeners are stored in the record's private data. */ utils.eventify(Record.prototype, function () { @@ -4696,80 +4293,80 @@ }, function (value) { this._set('events', value); }); - /** - * Fired when a record changes. Only works for records that have tracked fields. - * See {@link Record~changeListener} on how to listen for this event. - * - * @event Record#change - * @see Record~changeListener + /** + * Fired when a record changes. Only works for records that have tracked fields. + * See {@link Record~changeListener} on how to listen for this event. + * + * @event Record#change + * @see Record~changeListener */ - /** - * Callback signature for the {@link Record#event:change} event. - * - * @example - * function onChange (record, changes) { - * // do something - * } - * record.on('change', onChange); - * - * @callback Record~changeListener - * @param {Record} The Record that changed. - * @param {object} The changes. - * @see Record#event:change - * @since 3.0.0 + /** + * Callback signature for the {@link Record#event:change} event. + * + * @example + * function onChange (record, changes) { + * // do something + * } + * record.on('change', onChange); + * + * @callback Record~changeListener + * @param {Record} The Record that changed. + * @param {object} The changes. + * @see Record#event:change + * @since 3.0.0 */ - /** - * Create a subclass of this Record: - * @example Record.extend - * const JSData = require('js-data'); - * const { Record } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * // Extend the class using ES2015 class syntax. - * class CustomRecordClass extends Record { - * foo () { return 'bar'; } - * static beep () { return 'boop'; } - * } - * const customRecord = new CustomRecordClass(); - * console.log(customRecord.foo()); - * console.log(CustomRecordClass.beep()); - * - * // Extend the class using alternate method. - * const OtherRecordClass = Record.extend({ - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }); - * const otherRecord = new OtherRecordClass(); - * console.log(otherRecord.foo()); - * console.log(OtherRecordClass.beep()); - * - * // Extend the class, providing a custom constructor. - * function AnotherRecordClass () { - * Record.call(this); - * this.created_at = new Date().getTime(); - * } - * Record.extend({ - * constructor: AnotherRecordClass, - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }); - * const anotherRecord = new AnotherRecordClass(); - * console.log(anotherRecord.created_at); - * console.log(anotherRecord.foo()); - * console.log(AnotherRecordClass.beep()); - * - * @method Record.extend - * @param {object} [props={}] Properties to add to the prototype of the - * subclass. - * @param {object} [props.constructor] Provide a custom constructor function - * to be used as the subclass itself. - * @param {object} [classProps={}] Static properties to add to the subclass. - * @returns {Constructor} Subclass of this Record class. - * @since 3.0.0 + /** + * Create a subclass of this Record: + * @example Record.extend + * const JSData = require('js-data'); + * const { Record } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * // Extend the class using ES2015 class syntax. + * class CustomRecordClass extends Record { + * foo () { return 'bar'; } + * static beep () { return 'boop'; } + * } + * const customRecord = new CustomRecordClass(); + * console.log(customRecord.foo()); + * console.log(CustomRecordClass.beep()); + * + * // Extend the class using alternate method. + * const OtherRecordClass = Record.extend({ + * foo () { return 'bar'; } + * }, { + * beep () { return 'boop'; } + * }); + * const otherRecord = new OtherRecordClass(); + * console.log(otherRecord.foo()); + * console.log(OtherRecordClass.beep()); + * + * // Extend the class, providing a custom constructor. + * function AnotherRecordClass () { + * Record.call(this); + * this.created_at = new Date().getTime(); + * } + * Record.extend({ + * constructor: AnotherRecordClass, + * foo () { return 'bar'; } + * }, { + * beep () { return 'boop'; } + * }); + * const anotherRecord = new AnotherRecordClass(); + * console.log(anotherRecord.created_at); + * console.log(anotherRecord.foo()); + * console.log(AnotherRecordClass.beep()); + * + * @method Record.extend + * @param {object} [props={}] Properties to add to the prototype of the + * subclass. + * @param {object} [props.constructor] Provide a custom constructor function + * to be used as the subclass itself. + * @param {object} [classProps={}] Static properties to add to the subclass. + * @returns {Constructor} Subclass of this Record class. + * @since 3.0.0 */ function sort(a, b, hashCode) { @@ -4778,34 +4375,12 @@ // don't have the idAttribute field if (a === b) { return 0; - } - - if (hashCode) { + } else if (hashCode) { a = hashCode(a); b = hashCode(b); } - if (a === null && b === null || a === undefined && b === undefined) { - return -1; - } - - if (a === null || a === undefined) { - return -1; - } - - if (b === null || b === undefined) { - return 1; - } - - if (a < b) { - return -1; - } - - if (a > b) { - return 1; - } - - return 0; + return a === null && b === null || a === undefined && b === undefined ? -1 : a === null || a === undefined ? -1 : b === null || b === undefined ? 1 : a < b ? -1 : a > b ? 1 : 0; } function insertAt(array, index, value) { array.splice(index, 0, value); @@ -4822,6 +4397,7 @@ var mid; while (lo < hi) { + // tslint:disable-next-line:no-bitwise mid = (lo + hi) / 2 | 0; compared = sort(value, array[mid], field); @@ -4843,1327 +4419,1209 @@ }; } - // Copyright (c) 2015, InternalFX. - function Index(fieldList, opts) { - utils.classCallCheck(this, Index); - fieldList || (fieldList = []); + var Index = + /*#__PURE__*/ + function () { + function Index() { + var fieldList = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - if (!utils.isArray(fieldList)) { - throw new Error('fieldList must be an array.'); - } + _classCallCheck(this, Index); - opts || (opts = {}); - this.fieldList = fieldList; - this.fieldGetter = opts.fieldGetter; - this.hashCode = opts.hashCode; - this.isIndex = true; - this.keys = []; - this.values = []; - } - utils.addHiddenPropsToTarget(Index.prototype, { - 'set': function set(keyList, value) { - if (!utils.isArray(keyList)) { - keyList = [keyList]; + if (!utils.isArray(fieldList)) { + throw new Error('fieldList must be an array.'); } - var key = keyList.shift() || undefined; - var pos = binarySearch(this.keys, key); + this.fieldList = fieldList; + this.fieldGetter = opts.fieldGetter; + this.hashCode = opts.hashCode; + this.isIndex = true; + this.keys = []; + this.values = []; + } + + _createClass(Index, [{ + key: "set", + value: function set(keyList, value) { + if (!utils.isArray(keyList)) { + keyList = [keyList]; + } + + var key = keyList.shift() || undefined; + var pos = binarySearch(this.keys, key); - if (keyList.length === 0) { - if (pos.found) { - var dataLocation = binarySearch(this.values[pos.index], value, this.hashCode); + if (keyList.length === 0) { + if (pos.found) { + var dataLocation = binarySearch(this.values[pos.index], value, this.hashCode); - if (!dataLocation.found) { - insertAt(this.values[pos.index], dataLocation.index, value); + if (!dataLocation.found) { + insertAt(this.values[pos.index], dataLocation.index, value); + } + } else { + insertAt(this.keys, pos.index, key); + insertAt(this.values, pos.index, [value]); } } else { - insertAt(this.keys, pos.index, key); - insertAt(this.values, pos.index, [value]); - } - } else { - if (pos.found) { - this.values[pos.index].set(keyList, value); - } else { - insertAt(this.keys, pos.index, key); - var newIndex = new Index([], { - hashCode: this.hashCode - }); - newIndex.set(keyList, value); - insertAt(this.values, pos.index, newIndex); + if (pos.found) { + this.values[pos.index].set(keyList, value); + } else { + insertAt(this.keys, pos.index, key); + var newIndex = new Index([], { + hashCode: this.hashCode + }); + newIndex.set(keyList, value); + insertAt(this.values, pos.index, newIndex); + } } } - }, - 'get': function get(keyList) { - if (!utils.isArray(keyList)) { - keyList = [keyList]; - } + }, { + key: "get", + value: function get(keyList) { + if (!utils.isArray(keyList)) { + keyList = [keyList]; + } - var key = keyList.shift() || undefined; - var pos = binarySearch(this.keys, key); + var key = keyList.shift() || undefined; + var pos = binarySearch(this.keys, key); - if (keyList.length === 0) { - if (pos.found) { - if (this.values[pos.index].isIndex) { - return this.values[pos.index].getAll(); + if (keyList.length === 0) { + if (pos.found) { + if (this.values[pos.index].isIndex) { + return this.values[pos.index].getAll(); + } else { + return this.values[pos.index].slice(); + } } else { - return this.values[pos.index].slice(); + return []; } } else { - return []; - } - } else { - if (pos.found) { - return this.values[pos.index].get(keyList); - } else { - return []; + if (pos.found) { + return this.values[pos.index].get(keyList); + } else { + return []; + } } } - }, - getAll: function getAll(opts) { - opts || (opts = {}); - var results = []; - var values = this.values; + }, { + key: "getAll", + value: function getAll() { + var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + var results = []; + var values = this.values; - if (opts.order === 'desc') { - for (var i = values.length - 1; i >= 0; i--) { - var value = values[i]; + if (opts.order === 'desc') { + for (var i = values.length - 1; i >= 0; i--) { + var value = values[i]; - if (value.isIndex) { - results = results.concat(value.getAll(opts)); - } else { - results = results.concat(value); + if (value.isIndex) { + results = results.concat(value.getAll(opts)); + } else { + results = results.concat(value); + } + } + } else { + var _iteratorNormalCompletion = true; + var _didIteratorError = false; + var _iteratorError = undefined; + + try { + for (var _iterator = values[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { + var _value = _step.value; + + if (_value.isIndex) { + results = results.concat(_value.getAll(opts)); + } else { + results = results.concat(_value); + } + } + } catch (err) { + _didIteratorError = true; + _iteratorError = err; + } finally { + try { + if (!_iteratorNormalCompletion && _iterator["return"] != null) { + _iterator["return"](); + } + } finally { + if (_didIteratorError) { + throw _iteratorError; + } + } } } - } else { - for (var _i = 0; _i < values.length; _i++) { - var _value = values[_i]; - if (_value.isIndex) { - results = results.concat(_value.getAll(opts)); + return results; + } + }, { + key: "visitAll", + value: function visitAll(cb, thisArg) { + this.values.forEach(function (value) { + if (value.isIndex) { + value.visitAll(cb, thisArg); } else { - results = results.concat(_value); + value.forEach(cb, thisArg); } - } + }); } + }, { + key: "between", + value: function between(leftKeys, rightKeys) { + var opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; - return results; - }, - visitAll: function visitAll(cb, thisArg) { - this.values.forEach(function (value) { - if (value.isIndex) { - value.visitAll(cb, thisArg); - } else { - value.forEach(cb, thisArg); + if (!utils.isArray(leftKeys)) { + leftKeys = [leftKeys]; } - }); - }, - between: function between(leftKeys, rightKeys, opts) { - opts || (opts = {}); - if (!utils.isArray(leftKeys)) { - leftKeys = [leftKeys]; - } - - if (!utils.isArray(rightKeys)) { - rightKeys = [rightKeys]; - } + if (!utils.isArray(rightKeys)) { + rightKeys = [rightKeys]; + } - utils.fillIn(opts, { - leftInclusive: true, - rightInclusive: false, - limit: undefined, - offset: 0 - }); + utils.fillIn(opts, { + leftInclusive: true, + rightInclusive: false, + limit: undefined, + offset: 0 + }); - var results = this._between(leftKeys, rightKeys, opts); + var results = this._between(leftKeys, rightKeys, opts); - if (opts.limit) { - return results.slice(opts.offset, opts.limit + opts.offset); - } else { - return results.slice(opts.offset); - } - }, - _between: function _between(leftKeys, rightKeys, opts) { - var results = []; - var leftKey = leftKeys.shift(); - var rightKey = rightKeys.shift(); - var pos; - - if (leftKey !== undefined) { - pos = binarySearch(this.keys, leftKey); - } else { - pos = { - found: false, - index: 0 - }; + if (opts.limit) { + return results.slice(opts.offset, opts.limit + opts.offset); + } else { + return results.slice(opts.offset); + } } + }, { + key: "_between", + value: function _between(leftKeys, rightKeys, opts) { + var results = []; + var leftKey = leftKeys.shift(); + var rightKey = rightKeys.shift(); + var pos; - if (leftKeys.length === 0) { - if (pos.found && opts.leftInclusive === false) { - pos.index += 1; + if (leftKey !== undefined) { + pos = binarySearch(this.keys, leftKey); + } else { + pos = { + found: false, + index: 0 + }; } - for (var i = pos.index; i < this.keys.length; i += 1) { - if (rightKey !== undefined) { - if (opts.rightInclusive) { - if (this.keys[i] > rightKey) { - break; + if (leftKeys.length === 0) { + if (pos.found && opts.leftInclusive === false) { + pos.index += 1; + } + + for (var i = pos.index; i < this.keys.length; i += 1) { + if (rightKey !== undefined) { + if (opts.rightInclusive) { + if (this.keys[i] > rightKey) { + break; + } + } else { + if (this.keys[i] >= rightKey) { + break; + } } + } + + if (this.values[i].isIndex) { + results = results.concat(this.values[i].getAll()); } else { - if (this.keys[i] >= rightKey) { + results = results.concat(this.values[i]); + } + + if (opts.limit) { + if (results.length >= opts.limit + opts.offset) { break; } } } + } else { + for (var _i = pos.index; _i < this.keys.length; _i += 1) { + var currKey = this.keys[_i]; - if (this.values[i].isIndex) { - results = results.concat(this.values[i].getAll()); - } else { - results = results.concat(this.values[i]); - } - - if (opts.limit) { - if (results.length >= opts.limit + opts.offset) { + if (currKey > rightKey) { break; } - } - } - } else { - for (var _i2 = pos.index; _i2 < this.keys.length; _i2 += 1) { - var currKey = this.keys[_i2]; - - if (currKey > rightKey) { - break; - } - if (this.values[_i2].isIndex) { - if (currKey === leftKey) { - results = results.concat(this.values[_i2]._between(utils.copy(leftKeys), rightKeys.map(function () { - return undefined; - }), opts)); - } else if (currKey === rightKey) { - results = results.concat(this.values[_i2]._between(leftKeys.map(function () { - return undefined; - }), utils.copy(rightKeys), opts)); + if (this.values[_i].isIndex) { + if (currKey === leftKey) { + results = results.concat(this.values[_i]._between(utils.copy(leftKeys), rightKeys.map(function () { + return undefined; + }), opts)); + } else if (currKey === rightKey) { + results = results.concat(this.values[_i]._between(leftKeys.map(function () { + return undefined; + }), utils.copy(rightKeys), opts)); + } else { + results = results.concat(this.values[_i].getAll()); + } } else { - results = results.concat(this.values[_i2].getAll()); + results = results.concat(this.values[_i]); } - } else { - results = results.concat(this.values[_i2]); - } - if (opts.limit) { - if (results.length >= opts.limit + opts.offset) { - break; + if (opts.limit) { + if (results.length >= opts.limit + opts.offset) { + break; + } } } } - } - if (opts.limit) { - return results.slice(0, opts.limit + opts.offset); - } else { - return results; - } - }, - peek: function peek() { - if (this.values.length) { - if (this.values[0].isIndex) { - return this.values[0].peek(); + if (opts.limit) { + return results.slice(0, opts.limit + opts.offset); } else { - return this.values[0]; + return results; } } + }, { + key: "peek", + value: function peek() { + return this.values.length ? this.values[0].isIndex ? this.values[0].peek() : this.values[0] : []; + } + }, { + key: "clear", + value: function clear() { + this.keys = []; + this.values = []; + } + }, { + key: "insertRecord", + value: function insertRecord(data) { + var keyList = this.fieldList.map(function (field) { + return utils.isFunction(field) ? field(data) || undefined : data[field] || undefined; + }); + this.set(keyList, data); + } + }, { + key: "removeRecord", + value: function removeRecord(data) { + var _this = this; - return []; - }, - clear: function clear() { - this.keys = []; - this.values = []; - }, - insertRecord: function insertRecord(data) { - var keyList = this.fieldList.map(function (field) { - if (utils.isFunction(field)) { - return field(data) || undefined; - } else { - return data[field] || undefined; - } - }); - this.set(keyList, data); - }, - removeRecord: function removeRecord(data) { - var _this = this; + var removed; + var isUnique = this.hashCode(data) !== undefined; + this.values.forEach(function (value, i) { + if (value.isIndex) { + if (value.removeRecord(data)) { + if (value.keys.length === 0) { + removeAt(_this.keys, i); + removeAt(_this.values, i); + } - var removed; - var isUnique = this.hashCode(data) !== undefined; - this.values.forEach(function (value, i) { - if (value.isIndex) { - if (value.removeRecord(data)) { - if (value.keys.length === 0) { - removeAt(_this.keys, i); - removeAt(_this.values, i); + removed = true; + return false; } - - removed = true; - return false; - } - } else { - var dataLocation = {}; - - if (_this.keys[i] === undefined || !isUnique) { - for (var j = value.length - 1; j >= 0; j--) { - if (value[j] === data) { - dataLocation = { - found: true, - index: j - }; - break; + } else { + var dataLocation = {}; + + if (_this.keys[i] === undefined || !isUnique) { + for (var j = value.length - 1; j >= 0; j--) { + if (value[j] === data) { + dataLocation = { + found: true, + index: j + }; + break; + } } + } else if (isUnique) { + dataLocation = binarySearch(value, data, _this.hashCode); } - } else if (isUnique) { - dataLocation = binarySearch(value, data, _this.hashCode); - } - if (dataLocation.found) { - removeAt(value, dataLocation.index); + if (dataLocation.found) { + removeAt(value, dataLocation.index); - if (value.length === 0) { - removeAt(_this.keys, i); - removeAt(_this.values, i); - } + if (value.length === 0) { + removeAt(_this.keys, i); + removeAt(_this.values, i); + } - removed = true; - return false; + removed = true; + return false; + } } - } - }); - return removed ? data : undefined; - }, - updateRecord: function updateRecord(data) { - var removed = this.removeRecord(data); + }); + return removed ? data : undefined; + } + }, { + key: "updateRecord", + value: function updateRecord(data) { + var removed = this.removeRecord(data); - if (removed !== undefined) { - this.insertRecord(data); + if (removed !== undefined) { + this.insertRecord(data); + } } - } - }); + }]); - var noValidatePath$1 = Record$1.noValidatePath; + return Index; + }(); + + var noValidatePath$1 = Record.noValidatePath; var DOMAIN$4 = 'Collection'; var COLLECTION_DEFAULTS = { - /** - * Whether to call {@link Record#commit} on records that are added to the - * collection and already exist in the collection. - * - * @name Collection#commitOnMerge - * @type {boolean} - * @default true - */ commitOnMerge: true, - - /** - * Whether record events should bubble up and be emitted by the collection. - * - * @name Collection#emitRecordEvents - * @type {boolean} - * @default true - */ emitRecordEvents: true, - - /** - * Field to be used as the unique identifier for records in this collection. - * Defaults to `"id"` unless {@link Collection#mapper} is set, in which case - * this will default to {@link Mapper#idAttribute}. - * - * @name Collection#idAttribute - * @type {string} - * @default "id" - */ idAttribute: 'id', - - /** - * What to do when inserting a record into this Collection that shares a - * primary key with a record already in this Collection. - * - * Possible values: - * merge - * replace - * skip - * - * Merge: - * - * Recursively shallow copy properties from the new record onto the existing - * record. - * - * Replace: - * - * Shallow copy top-level properties from the new record onto the existing - * record. Any top-level own properties of the existing record that are _not_ - * on the new record will be removed. - * - * Skip: - * - * Ignore new record, keep existing record. - * - * @name Collection#onConflict - * @type {string} - * @default "merge" - */ onConflict: 'merge' }; - /** - * An ordered set of {@link Record} instances. - * - * @example Collection#constructor - * // import { Collection, Record } from 'js-data'; - * const JSData = require('js-data'); - * const {Collection, Record} = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const user1 = new Record({ id: 1 }); - * const user2 = new Record({ id: 2 }); - * const UserCollection = new Collection([user1, user2]); - * console.log(UserCollection.get(1) === user1); - * - * @class Collection - * @extends Component - * @param {array} [records] Initial set of records to insert into the - * collection. - * @param {object} [opts] Configuration options. - * @param {string} [opts.commitOnMerge] See {@link Collection#commitOnMerge}. - * @param {string} [opts.idAttribute] See {@link Collection#idAttribute}. - * @param {string} [opts.onConflict="merge"] See {@link Collection#onConflict}. - * @param {string} [opts.mapper] See {@link Collection#mapper}. - * @since 3.0.0 + /** + * An ordered set of {@link Record} instances. + * + * @example Collection#constructor + * // import { Collection, Record } from 'js-data'; + * const JSData = require('js-data'); + * const {Collection, Record} = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const user1 = new Record({ id: 1 }); + * const user2 = new Record({ id: 2 }); + * const UserCollection = new Collection([user1, user2]); + * console.log(UserCollection.get(1) === user1); + * + * @class Collection + * @extends Component + * @param {array} [records] Initial set of records to insert into the + * collection. + * @param {object} [opts] Configuration options. + * @param {string} [opts.commitOnMerge] See {@link Collection#commitOnMerge}. + * @param {string} [opts.idAttribute] See {@link Collection#idAttribute}. + * @param {string} [opts.onConflict="merge"] See {@link Collection#onConflict}. + * @param {string} [opts.mapper] See {@link Collection#mapper}. + * @since 3.0.0 */ - function Collection(records, opts) { - utils.classCallCheck(this, Collection); - Component$1.call(this, opts); + var Collection = + /*#__PURE__*/ + function (_Component) { + _inherits(Collection, _Component); - if (records && !utils.isArray(records)) { - opts = records; - records = []; - } + function Collection() { + var _this; - if (utils.isString(opts)) { - opts = { - idAttribute: opts - }; - } // Default values for arguments + var records = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + _classCallCheck(this, Collection); - records || (records = []); - opts || (opts = {}); - Object.defineProperties(this, { - /** - * Default Mapper for this collection. Optional. If a Mapper is provided, then - * the collection will use the {@link Mapper#idAttribute} setting, and will - * wrap records in {@link Mapper#recordClass}. - * - * @example Collection#mapper - * const JSData = require('js-data'); - * const {Collection, Mapper} = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * class MyMapperClass extends Mapper { - * foo () { return 'bar'; } - * } - * const myMapper = new MyMapperClass({ name: 'myMapper' }); - * const collection = new Collection(null, { mapper: myMapper }); - * - * @name Collection#mapper - * @type {Mapper} - * @default null - * @since 3.0.0 - */ - mapper: { - value: undefined, - writable: true - }, - // Query class used by this collection - queryClass: { - value: undefined, - writable: true + _this = _possibleConstructorReturn(this, _getPrototypeOf(Collection).call(this, opts)); + /** + * Object that holds the secondary indexes of this collection. + * + * @name Collection#indexes + * @type {Object.} + */ + + _this.indexes = {}; + _this._added = {}; + + if (records && !utils.isArray(records)) { + opts = records; + records = []; } - }); // Apply user-provided configuration - utils.fillIn(this, opts); // Fill in any missing options with the defaults + if (utils.isString(opts)) { + opts = { + idAttribute: opts + }; + } // Apply user-provided configuration - utils.fillIn(this, utils.copy(COLLECTION_DEFAULTS)); - if (!this.queryClass) { - this.queryClass = Query$1; - } + utils.fillIn(_assertThisInitialized(_this), opts); // Fill in any missing options with the defaults - var idAttribute = this.recordId(); - Object.defineProperties(this, { - /** - * The main index, which uses @{link Collection#recordId} as the key. - * - * @name Collection#index - * @type {Index} - */ - index: { - value: new Index([idAttribute], { - hashCode: function hashCode(obj) { - return utils.get(obj, idAttribute); - } - }) - }, + utils.fillIn(_assertThisInitialized(_this), utils.copy(COLLECTION_DEFAULTS)); - /** - * Object that holds the secondary indexes of this collection. - * - * @name Collection#indexes - * @type {Object.} - */ - indexes: { - value: {} + if (!_this.queryClass) { + _this.queryClass = Query; } - }); // Insert initial data into the collection - if (utils.isObject(records) || utils.isArray(records) && records.length) { - this.add(records); - } - } + var idAttribute = _this.recordId(); - var Collection$1 = Component$1.extend({ - constructor: Collection, + _this.index = new Index([idAttribute], { + hashCode: function hashCode(obj) { + return utils.get(obj, idAttribute); + } + }); // Insert initial data into the collection - /** - * Used to bind to events emitted by records in this Collection. - * - * @method Collection#_onRecordEvent - * @since 3.0.0 - * @private - * @param {...*} [arg] Args passed to {@link Collection#emit}. - */ - _onRecordEvent: function _onRecordEvent() { - if (this.emitRecordEvents) { - this.emit.apply(this, arguments); + if (utils.isObject(records) || utils.isArray(records) && records.length) { + _this.add(records); } - }, - /** - * Insert the provided record or records. - * - * If a record is already in the collection then the provided record will - * either merge with or replace the existing record based on the value of the - * `onConflict` option. - * - * The collection's secondary indexes will be updated as each record is - * visited. - * - * @method Collection#add - * @since 3.0.0 - * @param {(Object|Object[]|Record|Record[])} data The record or records to insert. - * @param {object} [opts] Configuration options. - * @param {boolean} [opts.commitOnMerge=true] See {@link Collection#commitOnMerge}. - * @param {boolean} [opts.noValidate] See {@link Record#noValidate}. - * @param {string} [opts.onConflict] See {@link Collection#onConflict}. - * @returns {(Object|Object[]|Record|Record[])} The added record or records. + return _this; + } + /** + * Used to bind to events emitted by records in this Collection. + * + * @method Collection#_onRecordEvent + * @since 3.0.0 + * @private + * @param {...*} [args] Args passed to {@link Collection#emit}. */ - add: function add(records, opts) { - var _this = this; - // Default values for arguments - opts || (opts = {}); // Fill in "opts" with the Collection's configuration - utils._(opts, this); + _createClass(Collection, [{ + key: "_onRecordEvent", + value: function _onRecordEvent() { + if (this.emitRecordEvents) { + this.emit.apply(this, arguments); + } + } + /** + * Insert the provided record or records. + * + * If a record is already in the collection then the provided record will + * either merge with or replace the existing record based on the value of the + * `onConflict` option. + * + * The collection's secondary indexes will be updated as each record is + * visited. + * + * @method Collection#add + * @since 3.0.0 + * @param {(Object|Object[]|Record|Record[])} records The record or records to insert. + * @param {object} [opts] Configuration options. + * @param {boolean} [opts.commitOnMerge=true] See {@link Collection#commitOnMerge}. + * @param {boolean} [opts.noValidate] See {@link Record#noValidate}. + * @param {string} [opts.onConflict] See {@link Collection#onConflict}. + * @returns {(Object|Object[]|Record|Record[])} The added record or records. + */ - records = this.beforeAdd(records, opts) || records; // Track whether just one record or an array of records is being inserted + }, { + key: "add", + value: function add(records) { + var _this2 = this; - var singular = false; - var idAttribute = this.recordId(); + var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - if (!utils.isArray(records)) { - if (utils.isObject(records)) { - records = [records]; - singular = true; - } else { - throw utils.err("".concat(DOMAIN$4, "#add"), 'records')(400, 'object or array', records); - } - } // Map the provided records to existing records. - // New records will be inserted. If any records map to existing records, - // they will be merged into the existing records according to the onConflict - // option. + // Fill in "opts" with the Collection's configuration + utils._(opts, this); + records = this.beforeAdd(records, opts) || records; // Track whether just one record or an array of records is being inserted - records = records.map(function (record) { - var id = _this.recordId(record); // Grab existing record if there is one + var singular = false; + var idAttribute = this.recordId(); + + if (!utils.isArray(records)) { + if (utils.isObject(records)) { + records = [records]; + singular = true; + } else { + throw utils.err("".concat(DOMAIN$4, "#add"), 'records')(400, 'object or array', records); + } + } // Map the provided records to existing records. + // New records will be inserted. If any records map to existing records, + // they will be merged into the existing records according to the onConflict + // option. - var existing = id === undefined ? id : _this.get(id); // If the currently visited record is just a reference to an existing - // record, then there is nothing to be done. Exit early. + records = records.map(function (record) { + var id = _this2.recordId(record); // Grab existing record if there is one - if (record === existing) { - return existing; - } - if (existing) { - // Here, the currently visited record corresponds to a record already - // in the collection, so we need to merge them - var onConflict = opts.onConflict || _this.onConflict; + var existing = id === undefined ? id : _this2.get(id); // If the currently visited record is just a reference to an existing + // record, then there is nothing to be done. Exit early. - if (onConflict !== 'merge' && onConflict !== 'replace' && onConflict !== 'skip') { - throw utils.err("".concat(DOMAIN$4, "#add"), 'opts.onConflict')(400, 'one of (merge, replace, skip)', onConflict, true); + if (record === existing) { + return existing; } - var existingNoValidate = existing._get(noValidatePath$1); + if (existing) { + // Here, the currently visited record corresponds to a record already + // in the collection, so we need to merge them + var onConflict = opts.onConflict || _this2.onConflict; - if (opts.noValidate) { - // Disable validation - existing._set(noValidatePath$1, true); - } + if (onConflict !== 'merge' && onConflict !== 'replace' && onConflict !== 'skip') { + throw utils.err("".concat(DOMAIN$4, "#add"), 'opts.onConflict')(400, 'one of (merge, replace, skip)', onConflict, true); + } - if (onConflict === 'merge') { - utils.deepMixIn(existing, record); - } else if (onConflict === 'replace') { - utils.forOwn(existing, function (value, key) { - if (key !== idAttribute && record[key] === undefined) { - existing[key] = undefined; - } - }); - existing.set(record); - } // else if(onConflict === 'skip'){ do nothing } + var existingNoValidate = existing._get(noValidatePath$1); + if (opts.noValidate) { + // Disable validation + existing._set(noValidatePath$1, true); + } - if (opts.noValidate) { - // Restore previous `noValidate` value - existing._set(noValidatePath$1, existingNoValidate); - } + if (onConflict === 'merge') { + utils.deepMixIn(existing, record); + } else if (onConflict === 'replace') { + utils.forOwn(existing, function (value, key) { + if (key !== idAttribute && record[key] === undefined) { + existing[key] = undefined; + } + }); + existing.set(record); + } // else if(onConflict === 'skip'){ do nothing } - record = existing; - if (opts.commitOnMerge && utils.isFunction(record.commit)) { - record.commit(); - } // Update all indexes in the collection + if (opts.noValidate) { + // Restore previous `noValidate` value + existing._set(noValidatePath$1, existingNoValidate); + } + record = existing; - _this.updateIndexes(record); - } else { - // Here, the currently visted record does not correspond to any record - // in the collection, so (optionally) instantiate this record and insert - // it into the collection - record = _this.mapper ? _this.mapper.createRecord(record, opts) : record; + if (opts.commitOnMerge && utils.isFunction(record.commit)) { + record.commit(); + } // Update all indexes in the collection - _this.index.insertRecord(record); - utils.forOwn(_this.indexes, function (index, name) { - index.insertRecord(record); - }); + _this2.updateIndexes(record); + } else { + // Here, the currently visited record does not correspond to any record + // in the collection, so (optionally) instantiate this record and insert + // it into the collection + record = _this2.mapper ? _this2.mapper.createRecord(record, opts) : record; + + _this2.index.insertRecord(record); + + utils.forOwn(_this2.indexes, function (index, name) { + index.insertRecord(record); + }); - if (record && utils.isFunction(record.on)) { - record.on('all', _this._onRecordEvent, _this); + if (record && utils.isFunction(record.on)) { + record.on('all', _this2._onRecordEvent, _this2); + } } + + return record; + }); // Finally, return the inserted data + + var result = singular ? records[0] : records; + + if (!opts.silent) { + this.emit('add', result); } - return record; - }); // Finally, return the inserted data + return this.afterAdd(records, opts, result) || result; + } + /** + * Lifecycle hook called by {@link Collection#add}. If this method returns a + * value then {@link Collection#add} will return that same value. + * + * @method Collection#method + * @since 3.0.0 + * @param {(Object|Object[]|Record|Record[])} record The record or records + * that were added to this Collection by {@link Collection#add}. + * @param {object} opts The `opts` argument passed to {@link Collection#add}. + * @param result + */ - var result = singular ? records[0] : records; + }, { + key: "afterAdd", + value: function afterAdd(record, opts, result) { + return null; + } + /** + * Lifecycle hook called by {@link Collection#remove}. If this method returns + * a value then {@link Collection#remove} will return that same value. + * + * @method Collection#afterRemove + * @since 3.0.0 + * @param {(string|number)} id The `id` argument passed to {@link Collection#remove}. + * @param {object} opts The `opts` argument passed to {@link Collection#remove}. + * @param {object} record The result that will be returned by {@link Collection#remove}. + */ - if (!opts.silent) { - this.emit('add', result); - } + }, { + key: "afterRemove", + value: function afterRemove(id, opts, record) { + return null; + } + /** + * Lifecycle hook called by {@link Collection#removeAll}. If this method + * returns a value then {@link Collection#removeAll} will return that same + * value. + * + * @method Collection#afterRemoveAll + * @since 3.0.0 + * @param {object} query The `query` argument passed to {@link Collection#removeAll}. + * @param {object} opts The `opts` argument passed to {@link Collection#removeAll}. + * @param {object} records The result that will be returned by {@link Collection#removeAll}. + */ - return this.afterAdd(records, opts, result) || result; - }, + }, { + key: "afterRemoveAll", + value: function afterRemoveAll(query, opts, records) { + return null; + } + /** + * Lifecycle hook called by {@link Collection#add}. If this method returns a + * value then the `records` argument in {@link Collection#add} will be + * re-assigned to the returned value. + * + * @method Collection#beforeAdd + * @since 3.0.0 + * @param {(Object|Object[]|Record|Record[])} records The `records` argument passed to {@link Collection#add}. + * @param {object} opts The `opts` argument passed to {@link Collection#add}. + */ - /** - * Lifecycle hook called by {@link Collection#add}. If this method returns a - * value then {@link Collection#add} will return that same value. - * - * @method Collection#method - * @since 3.0.0 - * @param {(Object|Object[]|Record|Record[])} result The record or records - * that were added to this Collection by {@link Collection#add}. - * @param {object} opts The `opts` argument passed to {@link Collection#add}. - */ - afterAdd: function afterAdd() {}, - - /** - * Lifecycle hook called by {@link Collection#remove}. If this method returns - * a value then {@link Collection#remove} will return that same value. - * - * @method Collection#afterRemove - * @since 3.0.0 - * @param {(string|number)} id The `id` argument passed to {@link Collection#remove}. - * @param {object} opts The `opts` argument passed to {@link Collection#remove}. - * @param {object} record The result that will be returned by {@link Collection#remove}. - */ - afterRemove: function afterRemove() {}, - - /** - * Lifecycle hook called by {@link Collection#removeAll}. If this method - * returns a value then {@link Collection#removeAll} will return that same - * value. - * - * @method Collection#afterRemoveAll - * @since 3.0.0 - * @param {object} query The `query` argument passed to {@link Collection#removeAll}. - * @param {object} opts The `opts` argument passed to {@link Collection#removeAll}. - * @param {object} records The result that will be returned by {@link Collection#removeAll}. - */ - afterRemoveAll: function afterRemoveAll() {}, - - /** - * Lifecycle hook called by {@link Collection#add}. If this method returns a - * value then the `records` argument in {@link Collection#add} will be - * re-assigned to the returned value. - * - * @method Collection#beforeAdd - * @since 3.0.0 - * @param {(Object|Object[]|Record|Record[])} records The `records` argument passed to {@link Collection#add}. - * @param {object} opts The `opts` argument passed to {@link Collection#add}. - */ - beforeAdd: function beforeAdd() {}, - - /** - * Lifecycle hook called by {@link Collection#remove}. - * - * @method Collection#beforeRemove - * @since 3.0.0 - * @param {(string|number)} id The `id` argument passed to {@link Collection#remove}. - * @param {object} opts The `opts` argument passed to {@link Collection#remove}. - */ - beforeRemove: function beforeRemove() {}, - - /** - * Lifecycle hook called by {@link Collection#removeAll}. - * - * @method Collection#beforeRemoveAll - * @since 3.0.0 - * @param {object} query The `query` argument passed to {@link Collection#removeAll}. - * @param {object} opts The `opts` argument passed to {@link Collection#removeAll}. - */ - beforeRemoveAll: function beforeRemoveAll() {}, - - /** - * Find all records between two boundaries. - * - * Shortcut for `collection.query().between(18, 30, { index: 'age' }).run()` - * - * @example - * // Get all users ages 18 to 30 - * const users = collection.between(18, 30, { index: 'age' }); - * - * @example - * // Same as above - * const users = collection.between([18], [30], { index: 'age' }); - * - * @method Collection#between - * @since 3.0.0 - * @param {array} leftKeys Keys defining the left boundary. - * @param {array} rightKeys Keys defining the right boundary. - * @param {object} [opts] Configuration options. - * @param {string} [opts.index] Name of the secondary index to use in the - * query. If no index is specified, the main index is used. - * @param {boolean} [opts.leftInclusive=true] Whether to include records - * on the left boundary. - * @param {boolean} [opts.rightInclusive=false] Whether to include records - * on the left boundary. - * @param {boolean} [opts.limit] Limit the result to a certain number. - * @param {boolean} [opts.offset] The number of resulting records to skip. - * @returns {Object[]|Record[]} The result. - */ - between: function between(leftKeys, rightKeys, opts) { - return this.query().between(leftKeys, rightKeys, opts).run(); - }, + }, { + key: "beforeAdd", + value: function beforeAdd(records, opts) { + return null; + } + /** + * Lifecycle hook called by {@link Collection#remove}. + * + * @method Collection#beforeRemove + * @since 3.0.0 + * @param {(string|number)} id The `id` argument passed to {@link Collection#remove}. + * @param {object} opts The `opts` argument passed to {@link Collection#remove}. + */ - /** - * Create a new secondary index on the contents of the collection. - * - * @example - * // Index users by age - * collection.createIndex('age'); - * - * @example - * // Index users by status and role - * collection.createIndex('statusAndRole', ['status', 'role']); - * - * @method Collection#createIndex - * @since 3.0.0 - * @param {string} name The name of the new secondary index. - * @param {string[]} [fieldList] Array of field names to use as the key or - * compound key of the new secondary index. If no fieldList is provided, then - * the name will also be the field that is used to index the collection. - */ - createIndex: function createIndex(name, fieldList, opts) { - var _this2 = this; + }, { + key: "beforeRemove", + value: function beforeRemove(id, opts) { + return null; + } + /** + * Lifecycle hook called by {@link Collection#removeAll}. + * + * @method Collection#beforeRemoveAll + * @since 3.0.0 + * @param {object} query The `query` argument passed to {@link Collection#removeAll}. + * @param {object} opts The `opts` argument passed to {@link Collection#removeAll}. + */ - if (utils.isString(name) && fieldList === undefined) { - fieldList = [name]; - } + }, { + key: "beforeRemoveAll", + value: function beforeRemoveAll(query, opts) { + return null; + } + /** + * Find all records between two boundaries. + * + * Shortcut for `collection.query().between(18, 30, { index: 'age' }).run()` + * + * @example + * // Get all users ages 18 to 30 + * const users = collection.between(18, 30, { index: 'age' }); + * + * @example + * // Same as above + * const users = collection.between([18], [30], { index: 'age' }); + * + * @method Collection#between + * @since 3.0.0 + * @param {array} leftKeys Keys defining the left boundary. + * @param {array} rightKeys Keys defining the right boundary. + * @param {object} [opts] Configuration options. + * @param {string} [opts.index] Name of the secondary index to use in the + * query. If no index is specified, the main index is used. + * @param {boolean} [opts.leftInclusive=true] Whether to include records + * on the left boundary. + * @param {boolean} [opts.rightInclusive=false] Whether to include records + * on the left boundary. + * @param {boolean} [opts.limit] Limit the result to a certain number. + * @param {boolean} [opts.offset] The number of resulting records to skip. + * @returns {Object[]|Record[]} The result. + */ - opts || (opts = {}); - opts.hashCode || (opts.hashCode = function (obj) { - return _this2.recordId(obj); - }); - var index = this.indexes[name] = new Index(fieldList, opts); - this.index.visitAll(index.insertRecord, index); - }, + }, { + key: "between", + value: function between(leftKeys, rightKeys, opts) { + return this.query().between(leftKeys, rightKeys, opts).run(); + } + /** + * Create a new secondary index on the contents of the collection. + * + * @example + * // Index users by age + * collection.createIndex('age'); + * + * @example + * // Index users by status and role + * collection.createIndex('statusAndRole', ['status', 'role']); + * + * @method Collection#createIndex + * @since 3.0.0 + * @param {string} name The name of the new secondary index. + * @param {string[]} [fieldList] Array of field names to use as the key or + * compound key of the new secondary index. If no fieldList is provided, then + * the name will also be the field that is used to index the collection. + * @param opts + */ - /** - * Find the record or records that match the provided query or pass the - * provided filter function. - * - * Shortcut for `collection.query().filter(queryOrFn[, thisArg]).run()` - * - * @example Collection#filter - * const JSData = require('js-data'); - * const { Collection } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const collection = new Collection([ - * { id: 1, status: 'draft', created_at_timestamp: new Date().getTime() } - * ]); - * - * // Get the draft posts created less than three months ago - * let posts = collection.filter({ - * where: { - * status: { - * '==': 'draft' - * }, - * created_at_timestamp: { - * '>=': (new Date().getTime() - (1000 \* 60 \* 60 \* 24 \* 30 \* 3)) // 3 months ago - * } - * } - * }); - * console.log(posts); - * - * // Use a custom filter function - * posts = collection.filter((post) => post.id % 2 === 0); - * - * @method Collection#filter - * @param {(Object|Function)} [queryOrFn={}] Selection query or filter - * function. - * @param {object} [thisArg] Context to which to bind `queryOrFn` if - * `queryOrFn` is a function. - * @returns {Array} The result. - * @see query - * @since 3.0.0 - */ - filter: function filter(query, thisArg) { - return this.query().filter(query, thisArg).run(); - }, + }, { + key: "createIndex", + value: function createIndex(name, fieldList) { + var _this3 = this; - /** - * Iterate over all records. - * - * @example - * collection.forEach(function (record) { - * // do something - * }); - * - * @method Collection#forEach - * @since 3.0.0 - * @param {Function} forEachFn Iteration function. - * @param {*} [thisArg] Context to which to bind `forEachFn`. - * @returns {Array} The result. - */ - forEach: function forEach(cb, thisArg) { - this.index.visitAll(cb, thisArg); - }, + var opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; - /** - * Get the record with the given id. - * - * @method Collection#get - * @since 3.0.0 - * @param {(string|number)} id The primary key of the record to get. - * @returns {(Object|Record)} The record with the given id. - */ - get: function get(id) { - var instances = id === undefined ? [] : this.query().get(id).run(); - return instances.length ? instances[0] : undefined; - }, + if (utils.isString(name) && fieldList === undefined) { + fieldList = [name]; + } - /** - * Find the record or records that match the provided keyLists. - * - * Shortcut for `collection.query().getAll(keyList1, keyList2, ...).run()` - * - * @example - * // Get the posts where "status" is "draft" or "inReview" - * const posts = collection.getAll('draft', 'inReview', { index: 'status' }); - * - * @example - * // Same as above - * const posts = collection.getAll(['draft'], ['inReview'], { index: 'status' }); - * - * @method Collection#getAll - * @since 3.0.0 - * @param {...Array} [keyList] Provide one or more keyLists, and all - * records matching each keyList will be retrieved. If no keyLists are - * provided, all records will be returned. - * @param {object} [opts] Configuration options. - * @param {string} [opts.index] Name of the secondary index to use in the - * query. If no index is specified, the main index is used. - * @returns {Array} The result. - */ - getAll: function getAll() { - var _this$query; + opts.hashCode = opts.hashCode || function (obj) { + return _this3.recordId(obj); + }; - return (_this$query = this.query()).getAll.apply(_this$query, arguments).run(); - }, + var index = this.indexes[name] = new Index(fieldList, opts); + this.index.visitAll(index.insertRecord, index); + } + /** + * Find the record or records that match the provided query or pass the + * provided filter function. + * + * Shortcut for `collection.query().filter(queryOrFn[, thisArg]).run()` + * + * @example Collection#filter + * const JSData = require('js-data'); + * const { Collection } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const collection = new Collection([ + * { id: 1, status: 'draft', created_at_timestamp: new Date().getTime() } + * ]); + * + * // Get the draft posts created less than three months ago + * let posts = collection.filter({ + * where: { + * status: { + * '==': 'draft' + * }, + * created_at_timestamp: { + * '>=': (new Date().getTime() - (1000 \* 60 \* 60 \* 24 \* 30 \* 3)) // 3 months ago + * } + * } + * }); + * console.log(posts); + * + * // Use a custom filter function + * posts = collection.filter((post) => post.id % 2 === 0); + * + * @method Collection#filter + * @param {(Object|Function)} [queryOrFn={}] Selection query or filter + * function. + * @param {object} [thisArg] Context to which to bind `queryOrFn` if + * `queryOrFn` is a function. + * @returns {Array} The result. + * @see query + * @since 3.0.0 + */ - /** - * Return the index with the given name. If no name is provided, return the - * main index. Throws an error if the specified index does not exist. - * - * @method Collection#getIndex - * @since 3.0.0 - * @param {string} [name] The name of the index to retrieve. - */ - getIndex: function getIndex(name) { - var index = name ? this.indexes[name] : this.index; + }, { + key: "filter", + value: function filter(queryOrFn, thisArg) { + return this.query().filter(queryOrFn, thisArg).run(); + } + /** + * Iterate over all records. + * + * @example + * collection.forEach(function (record) { + * // do something + * }); + * + * @method Collection#forEach + * @since 3.0.0 + * @param {Function} forEachFn Iteration function. + * @param {*} [thisArg] Context to which to bind `forEachFn`. + * @returns {Array} The result. + */ + + }, { + key: "forEach", + value: function forEach(forEachFn, thisArg) { + this.index.visitAll(forEachFn, thisArg); + } + /** + * Get the record with the given id. + * + * @method Collection#get + * @since 3.0.0 + * @param {(string|number)} id The primary key of the record to get. + * @returns {(Object|Record)} The record with the given id. + */ + + }, { + key: "get", + value: function get(id) { + var instances = id === undefined ? [] : this.query().get(id).run(); + return instances.length ? instances[0] : undefined; + } + }, { + key: "getAll", + value: function getAll() { + var _this$query; + + return (_this$query = this.query()).getAll.apply(_this$query, arguments).run(); + } + /** + * Return the index with the given name. If no name is provided, return the + * main index. Throws an error if the specified index does not exist. + * + * @method Collection#getIndex + * @since 3.0.0 + * @param {string} [name] The name of the index to retrieve. + */ + + }, { + key: "getIndex", + value: function getIndex(name) { + var index = name ? this.indexes[name] : this.index; + + if (!index) { + throw utils.err("".concat(DOMAIN$4, "#getIndex"), name)(404, 'index'); + } - if (!index) { - throw utils.err("".concat(DOMAIN$4, "#getIndex"), name)(404, 'index'); + return index; } + /** + * Limit the result. + * + * Shortcut for `collection.query().limit(maximumNumber).run()` + * + * @example + * const posts = collection.limit(10); + * + * @method Collection#limit + * @since 3.0.0 + * @param {number} num The maximum number of records to keep in the result. + * @returns {Array} The result. + */ - return index; - }, - - /** - * Limit the result. - * - * Shortcut for `collection.query().limit(maximumNumber).run()` - * - * @example - * const posts = collection.limit(10); - * - * @method Collection#limit - * @since 3.0.0 - * @param {number} num The maximum number of records to keep in the result. - * @returns {Array} The result. - */ - limit: function limit(num) { - return this.query().limit(num).run(); - }, + }, { + key: "limit", + value: function limit(num) { + return this.query().limit(num).run(); + } + /** + * Apply a mapping function to all records. + * + * @example + * const names = collection.map((user) => user.name); + * + * @method Collection#map + * @since 3.0.0 + * @param {Function} mapFn Mapping function. + * @param {*} [thisArg] Context to which to bind `mapFn`. + * @returns {Array} The result of the mapping. + */ - /** - * Apply a mapping function to all records. - * - * @example - * const names = collection.map((user) => user.name); - * - * @method Collection#map - * @since 3.0.0 - * @param {Function} mapFn Mapping function. - * @param {*} [thisArg] Context to which to bind `mapFn`. - * @returns {Array} The result of the mapping. - */ - map: function map(cb, thisArg) { - var data = []; - this.index.visitAll(function (value) { - data.push(cb.call(thisArg, value)); - }); - return data; - }, + }, { + key: "map", + value: function map(cb, thisArg) { + var data = []; + this.index.visitAll(function (value) { + data.push(cb.call(thisArg, value)); + }); + return data; + } + /** + * Return the result of calling the specified function on each record in this + * collection's main index. + * + * @method Collection#mapCall + * @since 3.0.0 + * @param {string} funcName Name of function to call + * @param {...*} [args] Remaining arguments to be passed to the function. + * @returns {Array} The result. + */ - /** - * Return the result of calling the specified function on each record in this - * collection's main index. - * - * @method Collection#mapCall - * @since 3.0.0 - * @param {string} funcName Name of function to call - * @parama {...*} [args] Remaining arguments to be passed to the function. - * @returns {Array} The result. - */ - mapCall: function mapCall(funcName) { - for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { - args[_key - 1] = arguments[_key]; - } + }, { + key: "mapCall", + value: function mapCall(funcName) { + for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + args[_key - 1] = arguments[_key]; + } - var data = []; - this.index.visitAll(function (record) { - data.push(record[funcName].apply(record, args)); - }); - return data; - }, + var data = []; + this.index.visitAll(function (record) { + data.push(record[funcName].apply(record, args)); + }); + return data; + } + /** + * Return all "unsaved" (not uniquely identifiable) records in this colleciton. + * + * @method Collection#prune + * @param {object} [opts] Configuration options, passed to {@link Collection#removeAll}. + * @since 3.0.0 + * @returns {Array} The removed records, if any. + */ - /** - * Return all "unsaved" (not uniquely identifiable) records in this colleciton. - * - * @method Collection#prune - * @param {object} [opts] Configuration options, passed to {@link Collection#removeAll}. - * @since 3.0.0 - * @returns {Array} The removed records, if any. - */ - prune: function prune(opts) { - return this.removeAll(this.unsaved(), opts); - }, + }, { + key: "prune", + value: function prune(opts) { + return this.removeAll(this.unsaved(), opts); + } + /** + * Create a new query to be executed against the contents of the collection. + * The result will be all or a subset of the contents of the collection. + * + * @example + * // Grab page 2 of users between ages 18 and 30 + * collection.query() + * .between(18, 30, { index: 'age' }) // between ages 18 and 30 + * .skip(10) // second page + * .limit(10) // page size + * .run(); + * + * @method Collection#query + * @since 3.0.0 + * @returns {Query} New query object. + */ - /** - * Create a new query to be executed against the contents of the collection. - * The result will be all or a subset of the contents of the collection. - * - * @example - * // Grab page 2 of users between ages 18 and 30 - * collection.query() - * .between(18, 30, { index: 'age' }) // between ages 18 and 30 - * .skip(10) // second page - * .limit(10) // page size - * .run(); - * - * @method Collection#query - * @since 3.0.0 - * @returns {Query} New query object. - */ - query: function query() { - var Ctor = this.queryClass; - return new Ctor(this); - }, + }, { + key: "query", + value: function query() { + var Ctor = this.queryClass; + return new Ctor(this); + } + /** + * Return the primary key of the given, or if no record is provided, return the + * name of the field that holds the primary key of records in this Collection. + * + * @method Collection#recordId + * @since 3.0.0 + * @param {(Object|Record)} [record] The record whose primary key is to be + * returned. + * @returns {(string|number)} Primary key or name of field that holds primary + * key. + */ - /** - * Return the primary key of the given, or if no record is provided, return the - * name of the field that holds the primary key of records in this Collection. - * - * @method Collection#recordId - * @since 3.0.0 - * @param {(Object|Record)} [record] The record whose primary key is to be - * returned. - * @returns {(string|number)} Primary key or name of field that holds primary - * key. - */ - recordId: function recordId(record) { - if (record) { - return utils.get(record, this.recordId()); - } + }, { + key: "recordId", + value: function recordId(record) { + if (record) { + return utils.get(record, this.recordId()); + } - return this.mapper ? this.mapper.idAttribute : this.idAttribute; - }, + return this.mapper ? this.mapper.idAttribute : this.idAttribute; + } + /** + * Reduce the data in the collection to a single value and return the result. + * + * @example + * const totalVotes = collection.reduce((prev, record) => { + * return prev + record.upVotes + record.downVotes; + * }, 0); + * + * @method Collection#reduce + * @since 3.0.0 + * @param {Function} cb Reduction callback. + * @param {*} initialValue Initial value of the reduction. + * @returns {*} The result. + */ - /** - * Reduce the data in the collection to a single value and return the result. - * - * @example - * const totalVotes = collection.reduce((prev, record) => { - * return prev + record.upVotes + record.downVotes; - * }, 0); - * - * @method Collection#reduce - * @since 3.0.0 - * @param {Function} cb Reduction callback. - * @param {*} initialValue Initial value of the reduction. - * @returns {*} The result. - */ - reduce: function reduce(cb, initialValue) { - var data = this.getAll(); - return data.reduce(cb, initialValue); - }, + }, { + key: "reduce", + value: function reduce(cb, initialValue) { + var data = this.getAll(); + return data.reduce(cb, initialValue); + } + /** + * Remove the record with the given id from this Collection. + * + * @method Collection#remove + * @since 3.0.0 + * @param {(string|number|object|Record)} idOrRecord The primary key of the + * record to be removed, or a reference to the record that is to be removed. + * @param {object} [opts] Configuration options. + * @returns {Object|Record} The removed record, if any. + */ - /** - * Remove the record with the given id from this Collection. - * - * @method Collection#remove - * @since 3.0.0 - * @param {(string|number|object|Record)} idOrRecord The primary key of the - * record to be removed, or a reference to the record that is to be removed. - * @param {object} [opts] Configuration options. - * @returns {Object|Record} The removed record, if any. - */ - remove: function remove(idOrRecord, opts) { - // Default values for arguments - opts || (opts = {}); - this.beforeRemove(idOrRecord, opts); - var record = utils.isSorN(idOrRecord) ? this.get(idOrRecord) : idOrRecord; // The record is in the collection, remove it + }, { + key: "remove", + value: function remove(idOrRecord) { + var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + this.beforeRemove(idOrRecord, opts); + var record = utils.isSorN(idOrRecord) ? this.get(idOrRecord) : idOrRecord; // The record is in the collection, remove it - if (utils.isObject(record)) { - record = this.index.removeRecord(record); + if (utils.isObject(record)) { + record = this.index.removeRecord(record); - if (record) { - utils.forOwn(this.indexes, function (index, name) { - index.removeRecord(record); - }); + if (record) { + utils.forOwn(this.indexes, function (index, name) { + index.removeRecord(record); + }); - if (utils.isFunction(record.off)) { - record.off('all', this._onRecordEvent, this); - } + if (utils.isFunction(record.off)) { + record.off('all', this._onRecordEvent, this); + } - if (!opts.silent) { - this.emit('remove', record); + if (!opts.silent) { + this.emit('remove', record); + } } } - } - return this.afterRemove(idOrRecord, opts, record) || record; - }, - - /** - * Remove from this collection the given records or the records selected by - * the given "query". - * - * @method Collection#removeAll - * @since 3.0.0 - * @param {Object|Object[]|Record[]} [queryOrRecords={}] Records to be removed or selection query. See {@link query}. - * @param {object} [queryOrRecords.where] See {@link query.where}. - * @param {number} [queryOrRecords.offset] See {@link query.offset}. - * @param {number} [queryOrRecords.limit] See {@link query.limit}. - * @param {string|Array[]} [queryOrRecords.orderBy] See {@link query.orderBy}. - * @param {object} [opts] Configuration options. - * @returns {(Object[]|Record[])} The removed records, if any. - */ - removeAll: function removeAll(queryOrRecords, opts) { - var _this3 = this; - - // Default values for arguments - opts || (opts = {}); - this.beforeRemoveAll(queryOrRecords, opts); - var records = utils.isArray(queryOrRecords) ? queryOrRecords.slice() : this.filter(queryOrRecords); // Remove each selected record from the collection - - var optsCopy = utils.plainCopy(opts); - optsCopy.silent = true; - records = records.map(function (record) { - return _this3.remove(record, optsCopy); - }).filter(function (record) { - return record; - }); + return this.afterRemove(idOrRecord, opts, record) || record; + } + /** + * Remove from this collection the given records or the records selected by + * the given "query". + * + * @method Collection#removeAll + * @since 3.0.0 + * @param {Object|Object[]|Record[]} [queryOrRecords={}] Records to be removed or selection query. See {@link query}. + * @param {object} [queryOrRecords.where] See {@link query.where}. + * @param {number} [queryOrRecords.offset] See {@link query.offset}. + * @param {number} [queryOrRecords.limit] See {@link query.limit}. + * @param {string|Array[]} [queryOrRecords.orderBy] See {@link query.orderBy}. + * @param {object} [opts] Configuration options. + * @returns {(Object[]|Record[])} The removed records, if any. + */ - if (!opts.silent) { - this.emit('remove', records); - } + }, { + key: "removeAll", + value: function removeAll(queryOrRecords) { + var _this4 = this; + + var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + this.beforeRemoveAll(queryOrRecords, opts); + var records = utils.isArray(queryOrRecords) ? queryOrRecords.slice() : this.filter(queryOrRecords); // Remove each selected record from the collection + + var optsCopy = utils.plainCopy(opts); + optsCopy.silent = true; + records = records.map(function (record) { + return _this4.remove(record, optsCopy); + }).filter(function (record) { + return record; + }); - return this.afterRemoveAll(queryOrRecords, opts, records) || records; - }, + if (!opts.silent) { + this.emit('remove', records); + } - /** - * Skip a number of results. - * - * Shortcut for `collection.query().skip(numberToSkip).run()` - * - * @example - * const posts = collection.skip(10); - * - * @method Collection#skip - * @since 3.0.0 - * @param {number} num The number of records to skip. - * @returns {Array} The result. - */ - skip: function skip(num) { - return this.query().skip(num).run(); - }, + return this.afterRemoveAll(queryOrRecords, opts, records) || records; + } + /** + * Skip a number of results. + * + * Shortcut for `collection.query().skip(numberToSkip).run()` + * + * @example + * const posts = collection.skip(10); + * + * @method Collection#skip + * @since 3.0.0 + * @param {number} num The number of records to skip. + * @returns {Array} The result. + */ - /** - * Return the plain JSON representation of all items in this collection. - * Assumes records in this collection have a toJSON method. - * - * @method Collection#toJSON - * @since 3.0.0 - * @param {object} [opts] Configuration options. - * @param {string[]} [opts.with] Array of relation names or relation fields - * to include in the representation. - * @returns {Array} The records. - */ - toJSON: function toJSON(opts) { - return this.mapCall('toJSON', opts); - }, + }, { + key: "skip", + value: function skip(num) { + return this.query().skip(num).run(); + } + /** + * Return the plain JSON representation of all items in this collection. + * Assumes records in this collection have a toJSON method. + * + * @method Collection#toJSON + * @since 3.0.0 + * @param {object} [opts] Configuration options. + * @param {string[]} [opts.with] Array of relation names or relation fields + * to include in the representation. + * @returns {Array} The records. + */ - /** - * Return all "unsaved" (not uniquely identifiable) records in this colleciton. - * - * @method Collection#unsaved - * @since 3.0.0 - * @returns {Array} The unsaved records, if any. - */ - unsaved: function unsaved(opts) { - return this.index.get(); - }, + }, { + key: "toJSON", + value: function toJSON(opts) { + return this.mapCall('toJSON', opts); + } + /** + * Return all "unsaved" (not uniquely identifiable) records in this colleciton. + * + * @method Collection#unsaved + * @since 3.0.0 + * @returns {Array} The unsaved records, if any. + */ - /** - * Update a record's position in a single index of this collection. See - * {@link Collection#updateIndexes} to update a record's position in all - * indexes at once. - * - * @method Collection#updateIndex - * @since 3.0.0 - * @param {object} record The record to update. - * @param {object} [opts] Configuration options. - * @param {string} [opts.index] The index in which to update the record's - * position. If you don't specify an index then the record will be updated - * in the main index. - */ - updateIndex: function updateIndex(record, opts) { - opts || (opts = {}); - this.getIndex(opts.index).updateRecord(record); - }, + }, { + key: "unsaved", + value: function unsaved(opts) { + return this.index.get(); + } + /** + * Update a record's position in a single index of this collection. See + * {@link Collection#updateIndexes} to update a record's position in all + * indexes at once. + * + * @method Collection#updateIndex + * @since 3.0.0 + * @param {object} record The record to update. + * @param {object} [opts] Configuration options. + * @param {string} [opts.index] The index in which to update the record's + * position. If you don't specify an index then the record will be updated + * in the main index. + */ - /** - * Updates all indexes in this collection for the provided record. Has no - * effect if the record is not in the collection. - * - * @method Collection#updateIndexes - * @since 3.0.0 - * @param {object} record TODO - */ - updateIndexes: function updateIndexes(record) { - this.index.updateRecord(record); - utils.forOwn(this.indexes, function (index, name) { - index.updateRecord(record); - }); - } - }); - /** - * Fired when a record changes. Only works for records that have tracked changes. - * See {@link Collection~changeListener} on how to listen for this event. - * - * @event Collection#change - * @see Collection~changeListener - */ + }, { + key: "updateIndex", + value: function updateIndex(record) { + var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + this.getIndex(opts.index).updateRecord(record); + } + /** + * Updates all indexes in this collection for the provided record. Has no + * effect if the record is not in the collection. + * + * @method Collection#updateIndexes + * @since 3.0.0 + * @param {object} record TODO + */ - /** - * Callback signature for the {@link Collection#event:change} event. - * - * @example - * function onChange (record, changes) { - * // do something - * } - * collection.on('change', onChange); - * - * @callback Collection~changeListener - * @param {Record} The Record that changed. - * @param {object} The changes. - * @see Collection#event:change - * @since 3.0.0 - */ + }, { + key: "updateIndexes", + value: function updateIndexes(record) { + this.index.updateRecord(record); + utils.forOwn(this.indexes, function (index) { + return index.updateRecord(record); + }); + } + }]); - /** - * Fired when one or more records are added to the Collection. See - * {@link Collection~addListener} on how to listen for this event. - * - * @event Collection#add - * @see Collection~addListener - * @see Collection#event:add - * @see Collection#add - */ + return Collection; + }(Component); - /** - * Callback signature for the {@link Collection#event:add} event. - * - * @example - * function onAdd (recordOrRecords) { - * // do something - * } - * collection.on('add', onAdd); - * - * @callback Collection~addListener - * @param {Record|Record[]} The Record or Records that were added. - * @see Collection#event:add - * @see Collection#add - * @since 3.0.0 - */ + var TsDataError = + /*#__PURE__*/ + function (_Error) { + _inherits(TsDataError, _Error); - /** - * Fired when one or more records are removed from the Collection. See - * {@link Collection~removeListener} for how to listen for this event. - * - * @event Collection#remove - * @see Collection~removeListener - * @see Collection#event:remove - * @see Collection#remove - * @see Collection#removeAll - */ + function TsDataError() { + _classCallCheck(this, TsDataError); - /** - * Callback signature for the {@link Collection#event:remove} event. - * - * @example - * function onRemove (recordsOrRecords) { - * // do something - * } - * collection.on('remove', onRemove); - * - * @callback Collection~removeListener - * @param {Record|Record[]} Record or Records that were removed. - * @see Collection#event:remove - * @see Collection#remove - * @see Collection#removeAll - * @since 3.0.0 - */ + return _possibleConstructorReturn(this, _getPrototypeOf(TsDataError).apply(this, arguments)); + } - /** - * Create a subclass of this Collection: - * @example Collection.extend - * const JSData = require('js-data'); - * const { Collection } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * // Extend the class using ES2015 class syntax. - * class CustomCollectionClass extends Collection { - * foo () { return 'bar'; } - * static beep () { return 'boop'; } - * } - * const customCollection = new CustomCollectionClass(); - * console.log(customCollection.foo()); - * console.log(CustomCollectionClass.beep()); - * - * // Extend the class using alternate method. - * const OtherCollectionClass = Collection.extend({ - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }); - * const otherCollection = new OtherCollectionClass(); - * console.log(otherCollection.foo()); - * console.log(OtherCollectionClass.beep()); - * - * // Extend the class, providing a custom constructor. - * function AnotherCollectionClass () { - * Collection.call(this); - * this.created_at = new Date().getTime(); - * } - * Collection.extend({ - * constructor: AnotherCollectionClass, - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }); - * const anotherCollection = new AnotherCollectionClass(); - * console.log(anotherCollection.created_at); - * console.log(anotherCollection.foo()); - * console.log(AnotherCollectionClass.beep()); - * - * @method Collection.extend - * @param {object} [props={}] Properties to add to the prototype of the - * subclass. - * @param {object} [props.constructor] Provide a custom constructor function - * to be used as the subclass itself. - * @param {object} [classProps={}] Static properties to add to the subclass. - * @returns {Constructor} Subclass of this Collection class. - * @since 3.0.0 - */ + return TsDataError; + }(_wrapNativeSuper(Error)); var DOMAIN$5 = 'Schema'; - /** - * A function map for each of the seven primitive JSON types defined by the core specification. - * Each function will check a given value and return true or false if the value is an instance of that type. - * ``` - * types.integer(1) // returns true - * types.string({}) // returns false - * ``` - * http://json-schema.org/latest/json-schema-core.html#anchor8 - * @name Schema.types - * @type {object} + /** + * A function map for each of the seven primitive JSON types defined by the core specification. + * Each function will check a given value and return true or false if the value is an instance of that type. + * ``` + * types.integer(1) // returns true + * types.string({}) // returns false + * ``` + * http://json-schema.org/latest/json-schema-core.html#anchor8 + * @name Schema.types + * @type {object} */ var types = { array: utils.isArray, - boolean: utils.isBoolean, + "boolean": utils.isBoolean, integer: utils.isInteger, - null: utils.isNull, + "null": utils.isNull, number: utils.isNumber, object: utils.isObject, string: utils.isString }; - /** - * @ignore + /** + * @ignore */ - var segmentToString = function segmentToString(segment, prev) { + function segmentToString(segment, prev) { var str = ''; if (segment) { @@ -6177,14 +5635,14 @@ } return str; - }; - /** - * @ignore + } + /** + * @ignore */ - var makePath = function makePath(opts) { - opts || (opts = {}); + function makePath() { + var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var path = ''; var segments = opts.path || []; segments.forEach(function (segment) { @@ -6192,74 +5650,74 @@ }); path += segmentToString(opts.prop, path); return path; - }; - /** - * @ignore + } + /** + * @ignore */ - var makeError = function makeError(actual, expected, opts) { + function makeError(actual, expected, opts) { return { expected: expected, actual: '' + actual, path: makePath(opts) }; - }; - /** - * @ignore + } + /** + * @ignore */ - var addError = function addError(actual, expected, opts, errors) { + function addError(actual, expected, opts, errors) { errors.push(makeError(actual, expected, opts)); - }; - /** - * @ignore + } + /** + * @ignore */ - var maxLengthCommon = function maxLengthCommon(keyword, value, schema, opts) { + function maxLengthCommon(keyword, value, schema, opts) { var max = schema[keyword]; if (value.length > max) { return makeError(value.length, "length no more than ".concat(max), opts); } - }; - /** - * @ignore + } + /** + * @ignore */ - var minLengthCommon = function minLengthCommon(keyword, value, schema, opts) { + function minLengthCommon(keyword, value, schema, opts) { var min = schema[keyword]; if (value.length < min) { return makeError(value.length, "length no less than ".concat(min), opts); } - }; - /** - * A map of all object member validation functions for each keyword defined in the JSON Schema. - * @name Schema.validationKeywords - * @type {object} + } + /** + * A map of all object member validation functions for each keyword defined in the JSON Schema. + * @name Schema.validationKeywords + * @type {object} */ var validationKeywords = { - /** - * Validates the provided value against all schemas defined in the Schemas `allOf` keyword. - * The instance is valid against if and only if it is valid against all the schemas declared in the Schema's value. - * - * The value of this keyword MUST be an array. This array MUST have at least one element. - * Each element of this array MUST be a valid JSON Schema. - * - * see http://json-schema.org/latest/json-schema-validation.html#anchor82 - * - * @name Schema.validationKeywords.allOf - * @method - * @param {*} value Value to be validated. - * @param {object} schema Schema containing the `allOf` keyword. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. + /** + * Validates the provided value against all schemas defined in the Schemas `allOf` keyword. + * The instance is valid against if and only if it is valid against all the schemas declared in the Schema's value. + * + * The value of this keyword MUST be an array. This array MUST have at least one element. + * Each element of this array MUST be a valid JSON Schema. + * + * see http://json-schema.org/latest/json-schema-validation.html#anchor82 + * + * @name Schema.validationKeywords.allOf + * @method + * @param {*} value Value to be validated. + * @param {object} schema Schema containing the `allOf` keyword. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. */ allOf: function allOf(value, schema, opts) { var allErrors = []; @@ -6269,21 +5727,21 @@ return allErrors.length ? allErrors : undefined; }, - /** - * Validates the provided value against all schemas defined in the Schemas `anyOf` keyword. - * The instance is valid against this keyword if and only if it is valid against - * at least one of the schemas in this keyword's value. - * - * The value of this keyword MUST be an array. This array MUST have at least one element. - * Each element of this array MUST be an object, and each object MUST be a valid JSON Schema. - * see http://json-schema.org/latest/json-schema-validation.html#anchor85 - * - * @name Schema.validationKeywords.anyOf - * @method - * @param {*} value Value to be validated. - * @param {object} schema Schema containing the `anyOf` keyword. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. + /** + * Validates the provided value against all schemas defined in the Schemas `anyOf` keyword. + * The instance is valid against this keyword if and only if it is valid against + * at least one of the schemas in this keyword's value. + * + * The value of this keyword MUST be an array. This array MUST have at least one element. + * Each element of this array MUST be an object, and each object MUST be a valid JSON Schema. + * see http://json-schema.org/latest/json-schema-validation.html#anchor85 + * + * @name Schema.validationKeywords.anyOf + * @method + * @param {*} value Value to be validated. + * @param {object} schema Schema containing the `anyOf` keyword. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. */ anyOf: function anyOf(value, schema, opts) { var validated = false; @@ -6300,32 +5758,32 @@ return validated ? undefined : allErrors; }, - /** - * http://json-schema.org/latest/json-schema-validation.html#anchor70 - * - * @name Schema.validationKeywords.dependencies - * @method - * @param {*} value TODO - * @param {object} schema TODO - * @param {object} opts TODO + /** + * http://json-schema.org/latest/json-schema-validation.html#anchor70 + * + * @name Schema.validationKeywords.dependencies + * @method + * @param {*} value TODO + * @param {object} schema TODO + * @param {object} opts TODO */ dependencies: function dependencies(value, schema, opts) {// TODO }, - /** - * Validates the provided value against an array of possible values defined by the Schema's `enum` keyword - * Validation succeeds if the value is deeply equal to one of the values in the array. - * see http://json-schema.org/latest/json-schema-validation.html#anchor76 - * - * @name Schema.validationKeywords.enum - * @method - * @param {*} value Value to validate - * @param {object} schema Schema containing the `enum` keyword. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. + /** + * Validates the provided value against an array of possible values defined by the Schema's `enum` keyword + * Validation succeeds if the value is deeply equal to one of the values in the array. + * see http://json-schema.org/latest/json-schema-validation.html#anchor76 + * + * @name Schema.validationKeywords.enum + * @method + * @param {*} value Value to validate + * @param {object} schema Schema containing the `enum` keyword. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. */ - enum: function _enum(value, schema, opts) { - var possibleValues = schema.enum; + "enum": function _enum(value, schema, opts) { + var possibleValues = schema["enum"]; if (utils.findIndex(possibleValues, function (item) { return utils.deepEqual(item, value); @@ -6334,20 +5792,21 @@ } }, - /** - * Validates each of the provided array values against a schema or an array of schemas defined by the Schema's `items` keyword - * see http://json-schema.org/latest/json-schema-validation.html#anchor37 for validation rules. - * - * @name Schema.validationKeywords.items - * @method - * @param {*} value Array to be validated. - * @param {object} schema Schema containing the items keyword. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. + /** + * Validates each of the provided array values against a schema or an array of schemas defined by the Schema's + * `items` keyword + * see http://json-schema.org/latest/json-schema-validation.html#anchor37 for validation rules. + * + * @name Schema.validationKeywords.items + * @method + * @param {*} value Array to be validated. + * @param {object} schema Schema containing the items keyword. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. */ - items: function items(value, schema, opts) { - opts || (opts = {}); // TODO: additionalItems - + items: function items(value, schema) { + var opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + // TODO: additionalItems var items = schema.items; var errors = []; var checkingTuple = utils.isArray(items); @@ -6367,17 +5826,17 @@ return errors.length ? errors : undefined; }, - /** - * Validates the provided number against a maximum value defined by the Schema's `maximum` keyword - * Validation succeeds if the value is a number, and is less than, or equal to, the value of this keyword. - * http://json-schema.org/latest/json-schema-validation.html#anchor17 - * - * @name Schema.validationKeywords.maximum - * @method - * @param {*} value Number to validate against the keyword. - * @param {object} schema Schema containing the `maximum` keyword. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. + /** + * Validates the provided number against a maximum value defined by the Schema's `maximum` keyword + * Validation succeeds if the value is a number, and is less than, or equal to, the value of this keyword. + * http://json-schema.org/latest/json-schema-validation.html#anchor17 + * + * @name Schema.validationKeywords.maximum + * @method + * @param {*} value Number to validate against the keyword. + * @param {object} schema Schema containing the `maximum` keyword. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. */ maximum: function maximum(value, schema, opts) { // Must be a number @@ -6392,17 +5851,17 @@ } }, - /** - * Validates the length of the provided array against a maximum value defined by the Schema's `maxItems` keyword. - * Validation succeeds if the length of the array is less than, or equal to the value of this keyword. - * see http://json-schema.org/latest/json-schema-validation.html#anchor42 - * - * @name Schema.validationKeywords.maxItems - * @method - * @param {*} value Array to be validated. - * @param {object} schema Schema containing the `maxItems` keyword. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. + /** + * Validates the length of the provided array against a maximum value defined by the Schema's `maxItems` keyword. + * Validation succeeds if the length of the array is less than, or equal to the value of this keyword. + * see http://json-schema.org/latest/json-schema-validation.html#anchor42 + * + * @name Schema.validationKeywords.maxItems + * @method + * @param {*} value Array to be validated. + * @param {object} schema Schema containing the `maxItems` keyword. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. */ maxItems: function maxItems(value, schema, opts) { if (utils.isArray(value)) { @@ -6410,33 +5869,34 @@ } }, - /** - * Validates the length of the provided string against a maximum value defined in the Schema's `maxLength` keyword. - * Validation succeeds if the length of the string is less than, or equal to the value of this keyword. - * see http://json-schema.org/latest/json-schema-validation.html#anchor26 - * - * @name Schema.validationKeywords.maxLength - * @method - * @param {*} value String to be validated. - * @param {object} schema Schema containing the `maxLength` keyword. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. + /** + * Validates the length of the provided string against a maximum value defined in the Schema's `maxLength` keyword. + * Validation succeeds if the length of the string is less than, or equal to the value of this keyword. + * see http://json-schema.org/latest/json-schema-validation.html#anchor26 + * + * @name Schema.validationKeywords.maxLength + * @method + * @param {*} value String to be validated. + * @param {object} schema Schema containing the `maxLength` keyword. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. */ maxLength: function maxLength(value, schema, opts) { return maxLengthCommon('maxLength', value, schema, opts); }, - /** - * Validates the count of the provided object's properties against a maximum value defined in the Schema's `maxProperties` keyword. - * Validation succeeds if the object's property count is less than, or equal to the value of this keyword. - * see http://json-schema.org/latest/json-schema-validation.html#anchor54 - * - * @name Schema.validationKeywords.maxProperties - * @method - * @param {*} value Object to be validated. - * @param {object} schema Schema containing the `maxProperties` keyword. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. + /** + * Validates the count of the provided object's properties against a maximum value defined in the Schema's + * `maxProperties` keyword. + * Validation succeeds if the object's property count is less than, or equal to the value of this keyword. + * see http://json-schema.org/latest/json-schema-validation.html#anchor54 + * + * @name Schema.validationKeywords.maxProperties + * @method + * @param {*} value Object to be validated. + * @param {object} schema Schema containing the `maxProperties` keyword. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. */ maxProperties: function maxProperties(value, schema, opts) { // validate only objects @@ -6449,17 +5909,17 @@ } }, - /** - * Validates the provided value against a minimum value defined by the Schema's `minimum` keyword - * Validation succeeds if the value is a number and is greater than, or equal to, the value of this keyword. - * http://json-schema.org/latest/json-schema-validation.html#anchor21 - * - * @name Schema.validationKeywords.minimum - * @method - * @param {*} value Number to validate against the keyword. - * @param {object} schema Schema containing the `minimum` keyword. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. + /** + * Validates the provided value against a minimum value defined by the Schema's `minimum` keyword + * Validation succeeds if the value is a number and is greater than, or equal to, the value of this keyword. + * http://json-schema.org/latest/json-schema-validation.html#anchor21 + * + * @name Schema.validationKeywords.minimum + * @method + * @param {*} value Number to validate against the keyword. + * @param {object} schema Schema containing the `minimum` keyword. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. */ minimum: function minimum(value, schema, opts) { // Must be a number @@ -6474,17 +5934,17 @@ } }, - /** - * Validates the length of the provided array against a minimum value defined by the Schema's `minItems` keyword. - * Validation succeeds if the length of the array is greater than, or equal to the value of this keyword. - * see http://json-schema.org/latest/json-schema-validation.html#anchor45 - * - * @name Schema.validationKeywords.minItems - * @method - * @param {*} value Array to be validated. - * @param {object} schema Schema containing the `minItems` keyword. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. + /** + * Validates the length of the provided array against a minimum value defined by the Schema's `minItems` keyword. + * Validation succeeds if the length of the array is greater than, or equal to the value of this keyword. + * see http://json-schema.org/latest/json-schema-validation.html#anchor45 + * + * @name Schema.validationKeywords.minItems + * @method + * @param {*} value Array to be validated. + * @param {object} schema Schema containing the `minItems` keyword. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. */ minItems: function minItems(value, schema, opts) { if (utils.isArray(value)) { @@ -6492,33 +5952,34 @@ } }, - /** - * Validates the length of the provided string against a minimum value defined in the Schema's `minLength` keyword. - * Validation succeeds if the length of the string is greater than, or equal to the value of this keyword. - * see http://json-schema.org/latest/json-schema-validation.html#anchor29 - * - * @name Schema.validationKeywords.minLength - * @method - * @param {*} value String to be validated. - * @param {object} schema Schema containing the `minLength` keyword. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. + /** + * Validates the length of the provided string against a minimum value defined in the Schema's `minLength` keyword. + * Validation succeeds if the length of the string is greater than, or equal to the value of this keyword. + * see http://json-schema.org/latest/json-schema-validation.html#anchor29 + * + * @name Schema.validationKeywords.minLength + * @method + * @param {*} value String to be validated. + * @param {object} schema Schema containing the `minLength` keyword. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. */ minLength: function minLength(value, schema, opts) { return minLengthCommon('minLength', value, schema, opts); }, - /** - * Validates the count of the provided object's properties against a minimum value defined in the Schema's `minProperties` keyword. - * Validation succeeds if the object's property count is greater than, or equal to the value of this keyword. - * see http://json-schema.org/latest/json-schema-validation.html#anchor57 - * - * @name Schema.validationKeywords.minProperties - * @method - * @param {*} value Object to be validated. - * @param {object} schema Schema containing the `minProperties` keyword. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. + /** + * Validates the count of the provided object's properties against a minimum value defined in the Schema's + * `minProperties` keyword. + * Validation succeeds if the object's property count is greater than, or equal to the value of this keyword. + * see http://json-schema.org/latest/json-schema-validation.html#anchor57 + * + * @name Schema.validationKeywords.minProperties + * @method + * @param {*} value Object to be validated. + * @param {object} schema Schema containing the `minProperties` keyword. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. */ minProperties: function minProperties(value, schema, opts) { // validate only objects @@ -6531,17 +5992,17 @@ } }, - /** - * Validates the provided number is a multiple of the number defined in the Schema's `multipleOf` keyword. - * Validation succeeds if the number can be divided equally into the value of this keyword. - * see http://json-schema.org/latest/json-schema-validation.html#anchor14 - * - * @name Schema.validationKeywords.multipleOf - * @method - * @param {*} value Number to be validated. - * @param {object} schema Schema containing the `multipleOf` keyword. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. + /** + * Validates the provided number is a multiple of the number defined in the Schema's `multipleOf` keyword. + * Validation succeeds if the number can be divided equally into the value of this keyword. + * see http://json-schema.org/latest/json-schema-validation.html#anchor14 + * + * @name Schema.validationKeywords.multipleOf + * @method + * @param {*} value Number to be validated. + * @param {object} schema Schema containing the `multipleOf` keyword. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. */ multipleOf: function multipleOf(value, schema, opts) { var multipleOf = schema.multipleOf; @@ -6553,17 +6014,18 @@ } }, - /** - * Validates the provided value is not valid with any of the schemas defined in the Schema's `not` keyword. - * An instance is valid against this keyword if and only if it is NOT valid against the schemas in this keyword's value. - * - * see http://json-schema.org/latest/json-schema-validation.html#anchor91 - * @name Schema.validationKeywords.not - * @method - * @param {*} value to be checked. - * @param {object} schema Schema containing the not keyword. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. + /** + * Validates the provided value is not valid with any of the schemas defined in the Schema's `not` keyword. + * An instance is valid against this keyword if and only if it is NOT valid against the schemas in this keyword's + * value. + * + * see http://json-schema.org/latest/json-schema-validation.html#anchor91 + * @name Schema.validationKeywords.not + * @method + * @param {*} value to be checked. + * @param {object} schema Schema containing the not keyword. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. */ not: function not(value, schema, opts) { if (!_validate(value, schema.not, opts)) { @@ -6572,17 +6034,18 @@ } }, - /** - * Validates the provided value is valid with one and only one of the schemas defined in the Schema's `oneOf` keyword. - * An instance is valid against this keyword if and only if it is valid against a single schemas in this keyword's value. - * - * see http://json-schema.org/latest/json-schema-validation.html#anchor88 - * @name Schema.validationKeywords.oneOf - * @method - * @param {*} value to be checked. - * @param {object} schema Schema containing the `oneOf` keyword. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. + /** + * Validates the provided value is valid with one and only one of the schemas defined in the Schema's `oneOf` keyword. + * An instance is valid against this keyword if and only if it is valid against a single schemas in this keyword's + * value. + * + * see http://json-schema.org/latest/json-schema-validation.html#anchor88 + * @name Schema.validationKeywords.oneOf + * @method + * @param {*} value to be checked. + * @param {object} schema Schema containing the `oneOf` keyword. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. */ oneOf: function oneOf(value, schema, opts) { var validated = false; @@ -6603,17 +6066,17 @@ return validated ? undefined : allErrors; }, - /** - * Validates the provided string matches a pattern defined in the Schema's `pattern` keyword. - * Validation succeeds if the string is a match of the regex value of this keyword. - * - * see http://json-schema.org/latest/json-schema-validation.html#anchor33 - * @name Schema.validationKeywords.pattern - * @method - * @param {*} value String to be validated. - * @param {object} schema Schema containing the `pattern` keyword. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. + /** + * Validates the provided string matches a pattern defined in the Schema's `pattern` keyword. + * Validation succeeds if the string is a match of the regex value of this keyword. + * + * see http://json-schema.org/latest/json-schema-validation.html#anchor33 + * @name Schema.validationKeywords.pattern + * @method + * @param {*} value String to be validated. + * @param {object} schema Schema containing the `pattern` keyword. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. */ pattern: function pattern(value, schema, opts) { var pattern = schema.pattern; @@ -6623,22 +6086,22 @@ } }, - /** - * Validates the provided object's properties against a map of values defined in the Schema's `properties` keyword. - * Validation succeeds if the object's property are valid with each of the schema's in the provided map. - * Validation also depends on the additionalProperties and or patternProperties. - * - * see http://json-schema.org/latest/json-schema-validation.html#anchor64 for more info. - * - * @name Schema.validationKeywords.properties - * @method - * @param {*} value Object to be validated. - * @param {object} schema Schema containing the `properties` keyword. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. + /** + * Validates the provided object's properties against a map of values defined in the Schema's `properties` keyword. + * Validation succeeds if the object's property are valid with each of the schema's in the provided map. + * Validation also depends on the additionalProperties and or patternProperties. + * + * see http://json-schema.org/latest/json-schema-validation.html#anchor64 for more info. + * + * @name Schema.validationKeywords.properties + * @method + * @param {*} value Object to be validated. + * @param {object} schema Schema containing the `properties` keyword. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. */ - properties: function properties(value, schema, opts) { - opts || (opts = {}); + properties: function properties(value, schema) { + var opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; if (utils.isArray(value)) { return; @@ -6691,20 +6154,20 @@ return errors.length ? errors : undefined; }, - /** - * Validates the provided object's has all properties listed in the Schema's `properties` keyword array. - * Validation succeeds if the object contains all properties provided in the array value of this keyword. - * see http://json-schema.org/latest/json-schema-validation.html#anchor61 - * - * @name Schema.validationKeywords.required - * @method - * @param {*} value Object to be validated. - * @param {object} schema Schema containing the `required` keyword. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. - */ - required: function required(value, schema, opts) { - opts || (opts = {}); + /** + * Validates the provided object's has all properties listed in the Schema's `properties` keyword array. + * Validation succeeds if the object contains all properties provided in the array value of this keyword. + * see http://json-schema.org/latest/json-schema-validation.html#anchor61 + * + * @name Schema.validationKeywords.required + * @method + * @param {*} value Object to be validated. + * @param {object} schema Schema containing the `required` keyword. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. + */ + required: function required(value, schema) { + var opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; var required = schema.required; var errors = []; @@ -6722,16 +6185,17 @@ return errors.length ? errors : undefined; }, - /** - * Validates the provided value's type is equal to the type, or array of types, defined in the Schema's `type` keyword. - * see http://json-schema.org/latest/json-schema-validation.html#anchor79 - * - * @name Schema.validationKeywords.type - * @method - * @param {*} value Value to be validated. - * @param {object} schema Schema containing the `type` keyword. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. + /** + * Validates the provided value's type is equal to the type, or array of types, defined in the Schema's `type` + * keyword. + * see http://json-schema.org/latest/json-schema-validation.html#anchor79 + * + * @name Schema.validationKeywords.type + * @method + * @param {*} value Value to be validated. + * @param {object} schema Schema containing the `type` keyword. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. */ type: function type(value, schema, opts) { var type = schema.type; @@ -6764,20 +6228,22 @@ } }, - /** - * Validates the provided array values are unique. - * Validation succeeds if the items in the array are unique, but only if the value of this keyword is true - * see http://json-schema.org/latest/json-schema-validation.html#anchor49 - * - * @name Schema.validationKeywords.uniqueItems - * @method - * @param {*} value Array to be validated. - * @param {object} schema Schema containing the `uniqueItems` keyword. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. + /** + * Validates the provided array values are unique. + * Validation succeeds if the items in the array are unique, but only if the value of this keyword is true + * see http://json-schema.org/latest/json-schema-validation.html#anchor49 + * + * @name Schema.validationKeywords.uniqueItems + * @method + * @param {*} value Array to be validated. + * @param {object} schema Schema containing the `uniqueItems` keyword. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. */ uniqueItems: function uniqueItems(value, schema, opts) { - if (value && value.length && schema.uniqueItems) { + var _a; + + if (((_a = value) === null || _a === void 0 ? void 0 : _a.length) && schema.uniqueItems) { var length = value.length; var item, i, j; // Check n - 1 items @@ -6794,11 +6260,11 @@ } } }; - /** - * @ignore + /** + * @ignore */ - var runOps = function runOps(ops, value, schema, opts) { + function runOps(ops, value, schema, opts) { var errors = []; ops.forEach(function (op) { if (schema[op] !== undefined) { @@ -6806,101 +6272,101 @@ } }); return errors.length ? errors : undefined; - }; - /** - * Validation keywords validated for any type: - * - * - `enum` - * - `type` - * - `allOf` - * - `anyOf` - * - `oneOf` - * - `not` - * - * @name Schema.ANY_OPS - * @type {string[]} + } + /** + * Validation keywords validated for any type: + * + * - `enum` + * - `type` + * - `allOf` + * - `anyOf` + * - `oneOf` + * - `not` + * + * @name Schema.ANY_OPS + * @type {string[]} */ var ANY_OPS = ['enum', 'type', 'allOf', 'anyOf', 'oneOf', 'not']; - /** - * Validation keywords validated for array types: - * - * - `items` - * - `maxItems` - * - `minItems` - * - `uniqueItems` - * - * @name Schema.ARRAY_OPS - * @type {string[]} + /** + * Validation keywords validated for array types: + * + * - `items` + * - `maxItems` + * - `minItems` + * - `uniqueItems` + * + * @name Schema.ARRAY_OPS + * @type {string[]} */ var ARRAY_OPS = ['items', 'maxItems', 'minItems', 'uniqueItems']; - /** - * Validation keywords validated for numeric (number and integer) types: - * - * - `multipleOf` - * - `maximum` - * - `minimum` - * - * @name Schema.NUMERIC_OPS - * @type {string[]} + /** + * Validation keywords validated for numeric (number and integer) types: + * + * - `multipleOf` + * - `maximum` + * - `minimum` + * + * @name Schema.NUMERIC_OPS + * @type {string[]} */ var NUMERIC_OPS = ['multipleOf', 'maximum', 'minimum']; - /** - * Validation keywords validated for object types: - * - * - `maxProperties` - * - `minProperties` - * - `required` - * - `properties` - * - `dependencies` - * - * @name Schema.OBJECT_OPS - * @type {string[]} + /** + * Validation keywords validated for object types: + * + * - `maxProperties` + * - `minProperties` + * - `required` + * - `properties` + * - `dependencies` + * + * @name Schema.OBJECT_OPS + * @type {string[]} */ var OBJECT_OPS = ['maxProperties', 'minProperties', 'required', 'properties', 'dependencies']; - /** - * Validation keywords validated for string types: - * - * - `maxLength` - * - `minLength` - * - `pattern` - * - * @name Schema.STRING_OPS - * @type {string[]} + /** + * Validation keywords validated for string types: + * + * - `maxLength` + * - `minLength` + * - `pattern` + * + * @name Schema.STRING_OPS + * @type {string[]} */ var STRING_OPS = ['maxLength', 'minLength', 'pattern']; - /** - * http://json-schema.org/latest/json-schema-validation.html#anchor75 - * @ignore + /** + * http://json-schema.org/latest/json-schema-validation.html#anchor75 + * @ignore */ var validateAny = function validateAny(value, schema, opts) { return runOps(ANY_OPS, value, schema, opts); }; - /** - * Validates the provided value against a given Schema according to the http://json-schema.org/ v4 specification. - * - * @name Schema.validate - * @method - * @param {*} value Value to be validated. - * @param {object} schema Valid Schema according to the http://json-schema.org/ v4 specification. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. + /** + * Validates the provided value against a given Schema according to the http://json-schema.org/ v4 specification. + * + * @name Schema.validate + * @method + * @param {*} value Value to be validated. + * @param {object} schema Valid Schema according to the http://json-schema.org/ v4 specification. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. */ - var _validate = function validate(value, schema, opts) { + var _validate = function validate(value, schema) { + var opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; var errors = []; - opts || (opts = {}); - opts.ctx || (opts.ctx = { + opts.ctx = opts.ctx || { value: value, schema: schema - }); + }; var shouldPop; var prevProp = opts.prop; @@ -6924,13 +6390,13 @@ } // Validate against parent schema - if (schema.extends) { + if (schema["extends"]) { // opts.path = path // opts.prop = prop - if (utils.isFunction(schema.extends.validate)) { - errors = errors.concat(schema.extends.validate(value, opts) || []); + if (utils.isFunction(schema["extends"].validate)) { + errors = errors.concat(schema["extends"].validate(value, opts) || []); } else { - errors = errors.concat(_validate(value, schema.extends, opts) || []); + errors = errors.concat(_validate(value, schema["extends"], opts) || []); } } @@ -6977,561 +6443,840 @@ var silentPath = 'silent'; var validationFailureMsg = 'validation failed'; - /** - * A map of validation functions grouped by type. - * - * @name Schema.typeGroupValidators - * @type {object} + /** + * A map of validation functions grouped by type. + * + * @name Schema.typeGroupValidators + * @type {object} */ var typeGroupValidators = { - /** - * Validates the provided value against the schema using all of the validation keywords specific to instances of an array. - * The validation keywords for the type `array` are: - *``` - * ['items', 'maxItems', 'minItems', 'uniqueItems'] - *``` - * see http://json-schema.org/latest/json-schema-validation.html#anchor25 - * - * @name Schema.typeGroupValidators.array - * @method - * @param {*} value Array to be validated. - * @param {object} schema Schema containing at least one array keyword. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. + /** + * Validates the provided value against the schema using all of the validation keywords specific to instances of an + * array. + * The validation keywords for the type `array` are: + * ``` + * ['items', 'maxItems', 'minItems', 'uniqueItems'] + * ``` + * see http://json-schema.org/latest/json-schema-validation.html#anchor25 + * + * @name Schema.typeGroupValidators.array + * @method + * @param {*} value Array to be validated. + * @param {object} schema Schema containing at least one array keyword. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. */ array: function array(value, schema, opts) { return runOps(ARRAY_OPS, value, schema, opts); }, - /** - * Validates the provided value against the schema using all of the validation keywords specific to instances of an integer. - * The validation keywords for the type `integer` are: - *``` - * ['multipleOf', 'maximum', 'minimum'] - *``` - * @name Schema.typeGroupValidators.integer - * @method - * @param {*} value Number to be validated. - * @param {object} schema Schema containing at least one `integer` keyword. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. + /** + * Validates the provided value against the schema using all of the validation keywords specific to instances of an + * integer. + * The validation keywords for the type `integer` are: + * ``` + * ['multipleOf', 'maximum', 'minimum'] + * ``` + * @name Schema.typeGroupValidators.integer + * @method + * @param {*} value Number to be validated. + * @param {object} schema Schema containing at least one `integer` keyword. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. */ integer: function integer(value, schema, opts) { - // Additional validations for numerics are the same - return typeGroupValidators.numeric(value, schema, opts); - }, - - /** - * Validates the provided value against the schema using all of the validation keywords specific to instances of an number. - * The validation keywords for the type `number` are: - *``` - * ['multipleOf', 'maximum', 'minimum'] - *``` - * @name Schema.typeGroupValidators.number - * @method - * @param {*} value Number to be validated. - * @param {object} schema Schema containing at least one `number` keyword. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. + return (// Additional validations for numerics are the same + typeGroupValidators.numeric(value, schema, opts) + ); + }, + + /** + * Validates the provided value against the schema using all of the validation keywords specific to instances of an + * number. + * The validation keywords for the type `number` are: + * ``` + * ['multipleOf', 'maximum', 'minimum'] + * ``` + * @name Schema.typeGroupValidators.number + * @method + * @param {*} value Number to be validated. + * @param {object} schema Schema containing at least one `number` keyword. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. */ number: function number(value, schema, opts) { - // Additional validations for numerics are the same - return typeGroupValidators.numeric(value, schema, opts); - }, - - /** - * Validates the provided value against the schema using all of the validation keywords specific to instances of a number or integer. - * The validation keywords for the type `numeric` are: - *``` - * ['multipleOf', 'maximum', 'minimum'] - *``` - * See http://json-schema.org/latest/json-schema-validation.html#anchor13. - * - * @name Schema.typeGroupValidators.numeric - * @method - * @param {*} value Number to be validated. - * @param {object} schema Schema containing at least one `numeric` keyword. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. + return (// Additional validations for numerics are the same + typeGroupValidators.numeric(value, schema, opts) + ); + }, + + /** + * Validates the provided value against the schema using all of the validation keywords specific to instances of a + * number or integer. + * The validation keywords for the type `numeric` are: + * ``` + * ['multipleOf', 'maximum', 'minimum'] + * ``` + * See http://json-schema.org/latest/json-schema-validation.html#anchor13. + * + * @name Schema.typeGroupValidators.numeric + * @method + * @param {*} value Number to be validated. + * @param {object} schema Schema containing at least one `numeric` keyword. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. */ numeric: function numeric(value, schema, opts) { return runOps(NUMERIC_OPS, value, schema, opts); }, - /** - * Validates the provided value against the schema using all of the validation keywords specific to instances of an object. - * The validation keywords for the type `object` are: - *``` - * ['maxProperties', 'minProperties', 'required', 'properties', 'dependencies'] - *``` - * See http://json-schema.org/latest/json-schema-validation.html#anchor53. - * - * @name Schema.typeGroupValidators.object - * @method - * @param {*} value Object to be validated. - * @param {object} schema Schema containing at least one `object` keyword. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. + /** + * Validates the provided value against the schema using all of the validation keywords specific to instances of an + * object. + * The validation keywords for the type `object` are: + * ``` + * ['maxProperties', 'minProperties', 'required', 'properties', 'dependencies'] + * ``` + * See http://json-schema.org/latest/json-schema-validation.html#anchor53. + * + * @name Schema.typeGroupValidators.object + * @method + * @param {*} value Object to be validated. + * @param {object} schema Schema containing at least one `object` keyword. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. */ object: function object(value, schema, opts) { return runOps(OBJECT_OPS, value, schema, opts); }, - /** - * Validates the provided value against the schema using all of the validation keywords specific to instances of an string. - * The validation keywords for the type `string` are: - *``` - * ['maxLength', 'minLength', 'pattern'] - *``` - * See http://json-schema.org/latest/json-schema-validation.html#anchor25. - * - * @name Schema.typeGroupValidators.string - * @method - * @param {*} value String to be validated. - * @param {object} schema Schema containing at least one `string` keyword. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. + /** + * Validates the provided value against the schema using all of the validation keywords specific to instances of an + * string. + * The validation keywords for the type `string` are: + * ``` + * ['maxLength', 'minLength', 'pattern'] + * ``` + * See http://json-schema.org/latest/json-schema-validation.html#anchor25. + * + * @name Schema.typeGroupValidators.string + * @method + * @param {*} value String to be validated. + * @param {object} schema Schema containing at least one `string` keyword. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. */ string: function string(value, schema, opts) { return runOps(STRING_OPS, value, schema, opts); } }; - /** - * js-data's Schema class. - * - * @example Schema#constructor - * const JSData = require('js-data'); - * const { Schema } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const PostSchema = new Schema({ - * type: 'object', - * properties: { - * title: { type: 'string' } - * } - * }); - * PostSchema.validate({ title: 1234 }); - * - * @class Schema - * @extends Component - * @param {object} definition Schema definition according to json-schema.org + /** + * js-data's Schema class. + * + * @example Schema#constructor + * const JSData = require('js-data'); + * const { Schema } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const PostSchema = new Schema({ + * type: 'object', + * properties: { + * title: { type: 'string' } + * } + * }); + * PostSchema.validate({ title: 1234 }); + * + * @example + * const JSData = require('js-data'); + * const { Schema } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * class CustomSchemaClass extends Schema { + * foo () { return 'bar'; } + * static beep () { return 'boop'; } + * } + * const customSchema = new CustomSchemaClass(); + * console.log(customSchema.foo()); + * console.log(CustomSchemaClass.beep()); + * + * @class Schema + * @extends Component + * @param {object} definition Schema definition according to json-schema.org */ - function Schema(definition) { - var _this = this; + var Schema = + /*#__PURE__*/ + function (_Component) { + _inherits(Schema, _Component); - definition || (definition = {}); // TODO: schema validation + function Schema() { + var _this; - utils.fillIn(this, definition); + var definition = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - if (this.type === 'object') { - this.properties = this.properties || {}; - utils.forOwn(this.properties, function (_definition, prop) { - if (!(_definition instanceof Schema)) { - _this.properties[prop] = new Schema(_definition); - } - }); - } else if (this.type === 'array' && this.items && !(this.items instanceof Schema)) { - this.items = new Schema(this.items); - } + _classCallCheck(this, Schema); - if (this.extends && !(this.extends instanceof Schema)) { - this.extends = new Schema(this.extends); - } + _this = _possibleConstructorReturn(this, _getPrototypeOf(Schema).call(this)); // TODO: schema validation - ['allOf', 'anyOf', 'oneOf'].forEach(function (validationKeyword) { - if (_this[validationKeyword]) { - _this[validationKeyword].forEach(function (_definition, i) { + utils.fillIn(_assertThisInitialized(_this), definition); + + if (_this.type === 'object') { + _this.properties = _this.properties || {}; + utils.forOwn(_this.properties, function (_definition, prop) { if (!(_definition instanceof Schema)) { - _this[validationKeyword][i] = new Schema(_definition); + _this.properties[prop] = new Schema(_definition); } }); + } else if (_this.type === 'array' && _this.items && !(_this.items instanceof Schema)) { + _this.items = new Schema(_this.items); } - }); - } - var Schema$1 = Component$1.extend({ - constructor: Schema, - - /** - * This adds ES5 getters/setters to the target based on the "properties" in - * this Schema, which makes possible change tracking and validation on - * property assignment. - * - * @name Schema#apply - * @method - * @param {object} target The prototype to which to apply this schema. - */ - apply: function apply(target, opts) { - var _this2 = this; - - opts || (opts = {}); - opts.getter || (opts.getter = '_get'); - opts.setter || (opts.setter = '_set'); - opts.unsetter || (opts.unsetter = '_unset'); - opts.track || (opts.track = this.track); - var properties = this.properties || {}; - utils.forOwn(properties, function (schema, prop) { - Object.defineProperty(target, prop, _this2.makeDescriptor(prop, schema, opts)); - }); - }, + if (_this["extends"] && !(_this["extends"] instanceof Schema)) { + _this["extends"] = new Schema(_this["extends"]); + } - /** - * Apply default values to the target object for missing values. - * - * @name Schema#applyDefaults - * @method - * @param {object} target The target to which to apply values for missing values. - */ - applyDefaults: function applyDefaults(target) { - if (!target) { - return; + ['allOf', 'anyOf', 'oneOf'].forEach(function (validationKeyword) { + if (_this[validationKeyword]) { + _this[validationKeyword].forEach(function (_definition, i) { + if (!(_definition instanceof Schema)) { + _this[validationKeyword][i] = new Schema(_definition); + } + }); + } + }); + return _this; + } + /** + * This adds ES5 getters/setters to the target based on the "properties" in + * this Schema, which makes possible change tracking and validation on + * property assignment. + * + * @name Schema#apply + * @method + * @param {object} target The prototype to which to apply this schema. + * @param opts + */ + + + _createClass(Schema, [{ + key: "apply", + value: function apply(target) { + var _this2 = this; + + var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + opts.getter = opts.getter || '_get'; + opts.setter = opts.setter || '_set'; + opts.unsetter = opts.unsetter || '_unset'; + opts.track = opts.track || this.track; + var properties = this.properties || {}; + utils.forOwn(properties, function (schema, prop) { + Object.defineProperty(target, prop, _this2.makeDescriptor(prop, schema, opts)); + }); } + /** + * Apply default values to the target object for missing values. + * + * @name Schema#applyDefaults + * @method + * @param {object} target The target to which to apply values for missing values. + */ - var properties = this.properties || {}; - var hasSet = utils.isFunction(target.set) || utils.isFunction(target._set); - utils.forOwn(properties, function (schema, prop) { - if (Object.hasOwnProperty.call(schema, 'default') && utils.get(target, prop) === undefined) { - if (hasSet) { - target.set(prop, utils.plainCopy(schema.default), { - silent: true - }); - } else { - utils.set(target, prop, utils.plainCopy(schema.default)); - } + }, { + key: "applyDefaults", + value: function applyDefaults(target) { + if (!target) { + return; } - if (schema.type === 'object' && schema.properties) { - if (hasSet) { - var orig = target._get('noValidate'); + var properties = this.properties || {}; + var hasSet = utils.isFunction(target.set) || utils.isFunction(target._set); + utils.forOwn(properties, function (schema, prop) { + if (schema.hasOwnProperty('default') && utils.get(target, prop) === undefined) { + if (hasSet) { + target.set(prop, utils.plainCopy(schema["default"]), { + silent: true + }); + } else { + utils.set(target, prop, utils.plainCopy(schema["default"])); + } + } - target._set('noValidate', true); + if (schema.type === 'object' && schema.properties) { + if (hasSet) { + var orig = target._get('noValidate'); - utils.set(target, prop, utils.get(target, prop) || {}, { - silent: true - }); + target._set('noValidate', true); - target._set('noValidate', orig); - } else { - utils.set(target, prop, utils.get(target, prop) || {}); + utils.set(target, prop, utils.get(target, prop) || {}, { + silent: true + }); + + target._set('noValidate', orig); + } else { + utils.set(target, prop, utils.get(target, prop) || {}); + } + + schema.applyDefaults(utils.get(target, prop)); } + }); + } + /** + * Assemble a property descriptor for tracking and validating changes to + * a property according to the given schema. This method is called when + * {@link Mapper#applySchema} is set to `true`. + * + * @name Schema#makeDescriptor + * @method + * @param {string} prop The property name. + * @param {(Schema|object)} schema The schema for the property. + * @param {object} [opts] Optional configuration. + * @param {function} [opts.getter] Custom getter function. + * @param {function} [opts.setter] Custom setter function. + * @param {function} [opts.track] Whether to track changes. + * @returns {object} A property descriptor for the given schema. + */ - schema.applyDefaults(utils.get(target, prop)); - } - }); - }, + }, { + key: "makeDescriptor", + value: function makeDescriptor(prop, schema, opts) { + var descriptor = { + // Better to allow configurability, but at the user's own risk + configurable: true, + // These properties are enumerable by default, but regardless of their + // enumerability, they won't be "own" properties of individual records + enumerable: schema.enumerable === undefined ? true : !!schema.enumerable, + get: function get() { + return this._get(keyPath); + }, + set: function set(value) { + var _this3 = this; + + // These are accessed a lot + var _get = this[getter]; + var _set = this[setter]; + var _unset = this[unsetter]; // Optionally check that the new value passes validation + + if (!_get(noValidatePath$2)) { + var errors = schema.validate(value, { + path: [prop] + }); - /** - * Assemble a property descriptor for tracking and validating changes to - * a property according to the given schema. This method is called when - * {@link Mapper#applySchema} is set to `true`. - * - * @name Schema#makeDescriptor - * @method - * @param {string} prop The property name. - * @param {(Schema|object)} schema The schema for the property. - * @param {object} [opts] Optional configuration. - * @param {function} [opts.getter] Custom getter function. - * @param {function} [opts.setter] Custom setter function. - * @param {function} [opts.track] Whether to track changes. - * @returns {object} A property descriptor for the given schema. - */ - makeDescriptor: function makeDescriptor(prop, schema, opts) { - var descriptor = { - // Better to allow configurability, but at the user's own risk - configurable: true, - // These properties are enumerable by default, but regardless of their - // enumerability, they won't be "own" properties of individual records - enumerable: schema.enumerable === undefined ? true : !!schema.enumerable - }; // Cache a few strings for optimal performance - - var keyPath = "props.".concat(prop); - var previousPath = "previous.".concat(prop); - var getter = opts.getter; - var setter = opts.setter; - var unsetter = opts.unsetter; - var track = utils.isBoolean(opts.track) ? opts.track : schema.track; - - descriptor.get = function () { - return this._get(keyPath); - }; + if (errors) { + // Immediately throw an error, preventing the record from getting into + // an invalid state + var error = new TsDataError(validationFailureMsg); + error.errors = errors; + throw error; + } + } // TODO: Make it so tracking can be turned on for all properties instead of + // only per-property - if (utils.isFunction(schema.get)) { - var originalGet = descriptor.get; - descriptor.get = function () { - return schema.get.call(this, originalGet); - }; - } + if (track && !_get(creatingPath$1)) { + // previous is versioned on database commit + // props are versioned on set() + var previous = _get(previousPath); - descriptor.set = function (value) { - var _this3 = this; + var current = _get(keyPath); - // These are accessed a lot - var _get = this[getter]; - var _set = this[setter]; - var _unset = this[unsetter]; // Optionally check that the new value passes validation + var changing = _get(changingPath); - if (!_get(noValidatePath$2)) { - var errors = schema.validate(value, { - path: [prop] - }); + var changed = _get(changedPath); - if (errors) { - // Immediately throw an error, preventing the record from getting into - // an invalid state - var error = new Error(validationFailureMsg); - error.errors = errors; - throw error; - } - } // TODO: Make it so tracking can be turned on for all properties instead of - // only per-property + if (!changing) { + // Track properties that are changing in the current event loop + changed = []; + } // Add changing properties to this array once at most - if (track && !_get(creatingPath$1)) { - // previous is versioned on database commit - // props are versioned on set() - var previous = _get(previousPath); + var index = changed.indexOf(prop); - var current = _get(keyPath); + if (current !== value && index === -1) { + changed.push(prop); + } - var changing = _get(changingPath); + if (previous === value) { + if (index >= 0) { + changed.splice(index, 1); + } + } // No changes in current event loop - var changed = _get(changedPath); - if (!changing) { - // Track properties that are changing in the current event loop - changed = []; - } // Add changing properties to this array once at most + if (!changed.length) { + changing = false; + _unset(changingPath); - var index = changed.indexOf(prop); + _unset(changedPath); // Cancel pending change event - if (current !== value && index === -1) { - changed.push(prop); - } - if (previous === value) { - if (index >= 0) { - changed.splice(index, 1); - } - } // No changes in current event loop + if (_get(eventIdPath)) { + clearTimeout(_get(eventIdPath)); + _unset(eventIdPath); + } + } // Changes detected in current event loop + + + if (!changing && changed.length) { + _set(changedPath, changed); + + _set(changingPath, true); // Saving the timeout id allows us to batch all changes in the same + // event loop into a single "change" + // TODO: Optimize + + + _set(eventIdPath, setTimeout(function () { + // Previous event loop where changes were gathered has ended, so + // notify any listeners of those changes and prepare for any new + // changes + _unset(changedPath); + + _unset(eventIdPath); + + _unset(changingPath); // TODO: Optimize - if (!changed.length) { - changing = false; - _unset(changingPath); + if (!_get(silentPath)) { + var i; - _unset(changedPath); // Cancel pending change event + for (i = 0; i < changed.length; i++) { + _this3.emit('change:' + changed[i], _this3, utils.get(_this3, changed[i])); + } + + var changes = utils.diffObjects(_defineProperty({}, prop, value), _defineProperty({}, prop, current)); + + if (_get(keepChangeHistoryPath$1)) { + var changeRecord = utils.plainCopy(changes); + changeRecord.timestamp = new Date().getTime(); + + var changeHistory = _get(changeHistoryPath); + if (!changeHistory) _set(changeHistoryPath, changeHistory = []); + changeHistory.push(changeRecord); + } - if (_get(eventIdPath)) { - clearTimeout(_get(eventIdPath)); + _this3.emit('change', _this3, changes); + } - _unset(eventIdPath); + _unset(silentPath); + }, 0)); + } } - } // Changes detected in current event loop + _set(keyPath, value); - if (!changing && changed.length) { - _set(changedPath, changed); + return value; + } + }; // Cache a few strings for optimal performance - _set(changingPath, true); // Saving the timeout id allows us to batch all changes in the same - // event loop into a single "change" - // TODO: Optimize + var keyPath = "props.".concat(prop); + var previousPath = "previous.".concat(prop); + var getter = opts.getter; + var setter = opts.setter; + var unsetter = opts.unsetter; + var track = utils.isBoolean(opts.track) ? opts.track : schema.track; + if (utils.isFunction(schema.get)) { + var originalGet = descriptor.get; - _set(eventIdPath, setTimeout(function () { - // Previous event loop where changes were gathered has ended, so - // notify any listeners of those changes and prepare for any new - // changes - _unset(changedPath); + descriptor.get = function () { + return schema.get.call(this, originalGet); + }; + } - _unset(eventIdPath); + if (utils.isFunction(schema.set)) { + var originalSet = descriptor.set; - _unset(changingPath); // TODO: Optimize + descriptor.set = function (value) { + return schema.set.call(this, value, originalSet); + }; + } + return descriptor; + } + /** + * Create a copy of the given value that contains only the properties defined + * in this schema. + * + * @name Schema#pick + * @method + * @param {*} value The value to copy. + * @returns {*} The copy. + */ - if (!_get(silentPath)) { - var i; + }, { + key: "pick", + value: function pick(value, opts) { + var _this4 = this; - for (i = 0; i < changed.length; i++) { - _this3.emit('change:' + changed[i], _this3, utils.get(_this3, changed[i])); - } + if (value === undefined) { + return; + } - var changes = utils.diffObjects(_defineProperty({}, prop, value), _defineProperty({}, prop, current)); + if (this.type === 'object') { + var copy = {}; + var properties = this.properties; - if (_get(keepChangeHistoryPath$1)) { - var changeRecord = utils.plainCopy(changes); - changeRecord.timestamp = new Date().getTime(); + if (properties) { + utils.forOwn(properties, function (_definition, prop) { + copy[prop] = _definition.pick(value[prop]); + }); + } - var changeHistory = _get(changeHistoryPath); + if (this["extends"]) { + utils.fillIn(copy, this["extends"].pick(value)); + } // Conditionally copy properties not defined in "properties" - !changeHistory && _set(changeHistoryPath, changeHistory = []); - changeHistory.push(changeRecord); - } - _this3.emit('change', _this3, changes); + if (this.additionalProperties) { + for (var key in value) { + if (!properties[key]) { + copy[key] = utils.plainCopy(value[key]); } - - _unset(silentPath); - }, 0)); + } } - } - _set(keyPath, value); + return copy; + } else if (this.type === 'array') { + return value.map(function (item) { + var _copy = _this4.items ? _this4.items.pick(item) : {}; - return value; - }; + if (_this4["extends"]) { + utils.fillIn(_copy, _this4["extends"].pick(item)); + } - if (utils.isFunction(schema.set)) { - var originalSet = descriptor.set; + return _copy; + }); + } - descriptor.set = function (value) { - return schema.set.call(this, value, originalSet); - }; + return utils.plainCopy(value); } + /** + * Validate the provided value against this schema. + * + * @name Schema#validate + * @method + * @param {*} value Value to validate. + * @param {object} [opts] Configuration options. + * @returns {(array|undefined)} Array of errors or `undefined` if valid. + */ - return descriptor; - }, + }, { + key: "validate", + value: function validate(value, opts) { + return _validate(value, this, opts); + } + }]); + + return Schema; + }(Component); + Schema.ANY_OPS = ANY_OPS; + Schema.ARRAY_OPS = ARRAY_OPS; + Schema.NUMERIC_OPS = NUMERIC_OPS; + Schema.OBJECT_OPS = OBJECT_OPS; + Schema.STRING_OPS = STRING_OPS; + Schema.typeGroupValidators = typeGroupValidators; + Schema.types = types; + Schema.validate = _validate; + Schema.validationKeywords = validationKeywords; + + var BelongsToRelation = + /*#__PURE__*/ + function (_Relation) { + _inherits(BelongsToRelation, _Relation); + + function BelongsToRelation() { + _classCallCheck(this, BelongsToRelation); + + return _possibleConstructorReturn(this, _getPrototypeOf(BelongsToRelation).apply(this, arguments)); + } - /** - * Create a copy of the given value that contains only the properties defined - * in this schema. - * - * @name Schema#pick - * @method - * @param {*} value The value to copy. - * @returns {*} The copy. - */ - pick: function pick(value) { - var _this4 = this; + _createClass(BelongsToRelation, [{ + key: "getForeignKey", + value: function getForeignKey(record) { + return utils.get(record, this.foreignKey); + } + }, { + key: "_setForeignKey", + value: function _setForeignKey(record, relatedRecord) { + utils.set(record, this.foreignKey, utils.get(relatedRecord, this.getRelation().idAttribute)); + } + }, { + key: "findExistingLinksFor", + value: function findExistingLinksFor(record) { + // console.log('\tBelongsTo#findExistingLinksFor', record) + if (!record) { + return; + } - if (value === undefined) { - return; + var relatedId = utils.get(record, this.foreignKey); + + if (relatedId !== undefined && relatedId !== null) { + return this.relatedCollection.get(relatedId); + } + } + }, { + key: "isRequiresParentId", + value: function isRequiresParentId() { + return true; + } + }, { + key: "createParentRecord", + value: function createParentRecord(props, opts) { + var _this = this; + + var relationData = this.getLocalField(props); + return this.createLinked(relationData, opts).then(function (record) { + _this.setForeignKey(props, record); + }); } + }, { + key: "createChildRecord", + value: function createChildRecord() { + throw new Error('"BelongsTo" relation does not support child creation as it cannot have children.'); + } + }]); - if (this.type === 'object') { - var copy = {}; - var properties = this.properties; + return BelongsToRelation; + }(Relation); + BelongsToRelation.TYPE_NAME = 'belongsTo'; - if (properties) { - utils.forOwn(properties, function (_definition, prop) { - copy[prop] = _definition.pick(value[prop]); - }); + var HasManyRelation = + /*#__PURE__*/ + function (_Relation) { + _inherits(HasManyRelation, _Relation); + + function HasManyRelation() { + _classCallCheck(this, HasManyRelation); + + return _possibleConstructorReturn(this, _getPrototypeOf(HasManyRelation).apply(this, arguments)); + } + + _createClass(HasManyRelation, [{ + key: "validateOptions", + value: function validateOptions(related, opts) { + _get(_getPrototypeOf(HasManyRelation.prototype), "validateOptions", this).call(this, related, opts); + + var localKeys = opts.localKeys, + foreignKeys = opts.foreignKeys, + foreignKey = opts.foreignKey; + + if (!foreignKey && !localKeys && !foreignKeys) { + throw utils.err('new Relation', 'opts.')(400, 'string', foreignKey); } + } + }, { + key: "canFindLinkFor", + value: function canFindLinkFor(record) { + var hasForeignKeys = this.foreignKey || this.foreignKeys; + return !!(hasForeignKeys || this.localKeys && utils.get(record, this.localKeys)); + } + }, { + key: "linkRecord", + value: function linkRecord(record, relatedRecords) { + var _this = this; - if (this.extends) { - utils.fillIn(copy, this.extends.pick(value)); - } // Conditionally copy properties not defined in "properties" + var relatedCollection = this.relatedCollection; + var canAutoAddLinks = this.canAutoAddLinks; + var foreignKey = this.foreignKey; + var unsaved = this.relatedCollection.unsaved(); + return relatedRecords.map(function (relatedRecord) { + var relatedId = relatedCollection.recordId(relatedRecord); + if (relatedId === undefined && unsaved.indexOf(relatedRecord) === -1 || relatedRecord !== relatedCollection.get(relatedId)) { + if (foreignKey) { + // TODO: slow, could be optimized? But user loses hook + _this.setForeignKey(record, relatedRecord); + } - if (this.additionalProperties) { - for (var key in value) { - if (!properties[key]) { - copy[key] = utils.plainCopy(value[key]); + if (canAutoAddLinks) { + relatedRecord = relatedCollection.add(relatedRecord); } } - } - return copy; - } else if (this.type === 'array') { - return value.map(function (item) { - var _copy = _this4.items ? _this4.items.pick(item) : {}; + return relatedRecord; + }); + } + }, { + key: "findExistingLinksFor", + value: function findExistingLinksFor(record) { + var _a; + + var id = utils.get(record, this.mapper.idAttribute); + var ids = this.localKeys ? utils.get(record, this.localKeys) : null; + var records; - if (_this4.extends) { - utils.fillIn(_copy, _this4.extends.pick(item)); - } + if (id !== undefined && this.foreignKey) { + records = this.findExistingLinksByForeignKey(id); + } else if (this.localKeys && ids) { + records = this.findExistingLinksByLocalKeys(ids); + } else if (id !== undefined && this.foreignKeys) { + records = this.findExistingLinksByForeignKeys(id); + } - return _copy; + if ((_a = records) === null || _a === void 0 ? void 0 : _a.length) { + return records; + } + } // e.g. user hasMany group via "foreignKeys", so find all users of a group + + }, { + key: "findExistingLinksByLocalKeys", + value: function findExistingLinksByLocalKeys(ids) { + return this.relatedCollection.filter({ + where: _defineProperty({}, this.relatedCollection.mapper.idAttribute, { + "in": ids + }) + }); + } // e.g. group hasMany user via "localKeys", so find all groups that own a user + + }, { + key: "findExistingLinksByForeignKeys", + value: function findExistingLinksByForeignKeys(id) { + return this.relatedCollection.filter({ + where: _defineProperty({}, this.foreignKeys, { + contains: id + }) + }); + } + }, { + key: "isRequiresParentId", + value: function isRequiresParentId() { + return !!this.localKeys && this.localKeys.length > 0; + } + }, { + key: "isRequiresChildId", + value: function isRequiresChildId() { + return !!this.foreignKey; + } + }, { + key: "createParentRecord", + value: function createParentRecord(props, opts) { + var _this2 = this; + + var relationData = this.getLocalField(props); + var foreignIdField = this.getRelation().idAttribute; + return this.createLinked(relationData, opts).then(function (records) { + utils.set(props, _this2.localKeys, records.map(function (record) { + return utils.get(record, foreignIdField); + })); }); } + }, { + key: "createLinked", + value: function createLinked(props, opts) { + return this.getRelation().createMany(props, opts); + } + }]); - return utils.plainCopy(value); - }, + return HasManyRelation; + }(Relation); + HasManyRelation.TYPE_NAME = 'hasMany'; + + var HasOneRelation = + /*#__PURE__*/ + function (_Relation) { + _inherits(HasOneRelation, _Relation); + + function HasOneRelation() { + _classCallCheck(this, HasOneRelation); + + return _possibleConstructorReturn(this, _getPrototypeOf(HasOneRelation).apply(this, arguments)); + } + + _createClass(HasOneRelation, [{ + key: "findExistingLinksFor", + value: function findExistingLinksFor(relatedMapper, record) { + var _a; + + var recordId = utils.get(record, relatedMapper.idAttribute); + var records = this.findExistingLinksByForeignKey(recordId); + + if ((_a = records) === null || _a === void 0 ? void 0 : _a.length) { + return records[0]; + } + } + }, { + key: "isRequiresChildId", + value: function isRequiresChildId() { + return true; + } + }]); + + return HasOneRelation; + }(Relation); + HasOneRelation.TYPE_NAME = 'hasOne'; + + [BelongsToRelation, HasManyRelation, HasOneRelation].forEach(function (RelationType) { + Relation[RelationType.TYPE_NAME] = function (related, options) { + return new RelationType(related, options); + }; + }); + + /** + * BelongsTo relation decorator. You probably won't use this directly. + * + * @method + * @param {Mapper} related The relation the target belongs to. + * @param {object} opts Configuration options. + * @param {string} opts.foreignKey The field that holds the primary key of the + * related record. + * @param {string} opts.localField The field that holds a reference to the + * related record object. + * @returns {Function} Invocation function, which accepts the target as the only + * parameter. + */ + + function belongsTo(related, opts) { + return function (mapper) { + Relation.belongsTo(related, opts).assignTo(mapper); + }; + } + /** + * HasMany relation decorator. You probably won't use this directly. + * + * @method + * @param {Mapper} related The relation of which the target has many. + * @param {object} opts Configuration options. + * @param {string} [opts.foreignKey] The field that holds the primary key of the + * related record. + * @param {string} opts.localField The field that holds a reference to the + * related record object. + * @returns {Function} Invocation function, which accepts the target as the only + * parameter. + */ - /** - * Validate the provided value against this schema. - * - * @name Schema#validate - * @method - * @param {*} value Value to validate. - * @param {object} [opts] Configuration options. - * @returns {(array|undefined)} Array of errors or `undefined` if valid. - */ - validate: function validate(value, opts) { - return _validate(value, this, opts); - } - }, { - ANY_OPS: ANY_OPS, - ARRAY_OPS: ARRAY_OPS, - NUMERIC_OPS: NUMERIC_OPS, - OBJECT_OPS: OBJECT_OPS, - STRING_OPS: STRING_OPS, - typeGroupValidators: typeGroupValidators, - types: types, - validate: _validate, - validationKeywords: validationKeywords - }); - /** - * Create a subclass of this Schema: - * @example Schema.extend - * const JSData = require('js-data'); - * const { Schema } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * // Extend the class using ES2015 class syntax. - * class CustomSchemaClass extends Schema { - * foo () { return 'bar'; } - * static beep () { return 'boop'; } - * } - * const customSchema = new CustomSchemaClass(); - * console.log(customSchema.foo()); - * console.log(CustomSchemaClass.beep()); - * - * // Extend the class using alternate method. - * const OtherSchemaClass = Schema.extend({ - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }); - * const otherSchema = new OtherSchemaClass(); - * console.log(otherSchema.foo()); - * console.log(OtherSchemaClass.beep()); - * - * // Extend the class, providing a custom constructor. - * function AnotherSchemaClass () { - * Schema.call(this); - * this.created_at = new Date().getTime(); - * } - * Schema.extend({ - * constructor: AnotherSchemaClass, - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }); - * const anotherSchema = new AnotherSchemaClass(); - * console.log(anotherSchema.created_at); - * console.log(anotherSchema.foo()); - * console.log(AnotherSchemaClass.beep()); - * - * @method Schema.extend - * @param {object} [props={}] Properties to add to the prototype of the - * subclass. - * @param {object} [props.constructor] Provide a custom constructor function - * to be used as the subclass itself. - * @param {object} [classProps={}] Static properties to add to the subclass. - * @returns {Constructor} Subclass of this Schema class. - * @since 3.0.0 + function hasMany(related, opts) { + return function (mapper) { + Relation.hasMany(related, opts).assignTo(mapper); + }; + } + /** + * HasOne relation decorator. You probably won't use this directly. + * + * @method + * @param {Mapper} related The relation of which the target has one. + * @param {object} opts Configuration options. + * @param {string} [opts.foreignKey] The field that holds the primary key of the + * related record. + * @param {string} opts.localField The field that holds a reference to the + * related record object. + * @returns {Function} Invocation function, which accepts the target as the only + * parameter. */ + function hasOne(related, opts) { + return function (mapper) { + Relation.hasOne(related, opts).assignTo(mapper); + }; + } + var DOMAIN$6 = 'Mapper'; var applyDefaultsHooks = ['beforeCreate', 'beforeCreateMany']; var validatingHooks = ['beforeCreate', 'beforeCreateMany', 'beforeUpdate', 'beforeUpdateAll', 'beforeUpdateMany']; - var makeNotify = function makeNotify(num) { + function makeNotify(num) { return function () { var _this = this; @@ -7539,6 +7284,8 @@ args[_key] = arguments[_key]; } + var _a; + var opts = args[args.length - num]; var op = opts.op; this.dbg.apply(this, [op].concat(args)); @@ -7546,7 +7293,7 @@ if (applyDefaultsHooks.indexOf(op) !== -1 && opts.applyDefaults !== false) { var schema = this.getSchema(); - if (schema && schema.applyDefaults) { + if ((_a = schema) === null || _a === void 0 ? void 0 : _a.applyDefaults) { var toProcess = args[0]; if (!utils.isArray(toProcess)) { @@ -7573,7 +7320,7 @@ opts.existingOnly = originalExistingOnly; // Abort lifecycle due to validation errors if (errors) { - var err = new Error('validation failed'); + var err = new TsDataError('validation failed'); err.errors = errors; return utils.reject(err); } @@ -7586,7 +7333,7 @@ }); } }; - }; // These are the default implementations of all of the lifecycle hooks + } // These are the default implementations of all of the lifecycle hooks var notify = makeNotify(1); @@ -7650,4157 +7397,3783 @@ } }; var MAPPER_DEFAULTS = { - /** - * Hash of registered adapters. Don't modify directly. Use - * {@link Mapper#registerAdapter} instead. - * - * @default {} - * @name Mapper#_adapters - * @since 3.0.0 - * @tutorial ["http://www.js-data.io/v3.0/docs/connecting-to-a-data-source","Connecting to a data source"] - */ _adapters: {}, - - /** - * Whether {@link Mapper#beforeCreate} and {@link Mapper#beforeCreateMany} - * should automatically receive default values according to the Mapper's schema. - * - * @default true - * @name Mapper#applyDefaults - * @since 3.0.0 - * @type {boolean} - */ applyDefaults: true, - - /** - * Whether to augment {@link Mapper#recordClass} with ES5 getters and setters - * according to the properties defined in {@link Mapper#schema}. This makes - * possible validation and change tracking on individual properties - * when using the dot (e.g. `user.name = "Bob"`) operator to modify a - * property, and is `true` by default. - * - * @default true - * @name Mapper#applySchema - * @since 3.0.0 - * @type {boolean} - */ applySchema: true, - - /** - * The name of the registered adapter that this Mapper should used by default. - * - * @default "http" - * @name Mapper#defaultAdapter - * @since 3.0.0 - * @tutorial ["http://www.js-data.io/v3.0/docs/connecting-to-a-data-source","Connecting to a data source"] - * @type {string} - */ defaultAdapter: 'http', - - /** - * The field used as the unique identifier on records handled by this Mapper. - * - * @default id - * @name Mapper#idAttribute - * @since 3.0.0 - * @type {string} - */ idAttribute: 'id', - - /** - * Whether records created from this mapper keep changeHistory on property changes. - * - * @default true - * @name Mapper#keepChangeHistory - * @since 3.0.0 - * @type {boolean} - */ keepChangeHistory: true, - - /** - * Whether this Mapper should emit operational events. - * - * @default true - * @name Mapper#notify - * @since 3.0.0 - * @type {boolean} - */ notify: true, - - /** - * Whether to skip validation when the Record instances are created. - * - * @default false - * @name Mapper#noValidate - * @since 3.0.0 - * @type {boolean} - */ noValidate: false, - - /** - * Whether {@link Mapper#create}, {@link Mapper#createMany}, - * {@link Mapper#update}, {@link Mapper#updateAll}, {@link Mapper#updateMany}, - * {@link Mapper#find}, {@link Mapper#findAll}, {@link Mapper#destroy}, - * {@link Mapper#destroyAll}, {@link Mapper#count}, and {@link Mapper#sum} - * should return a raw result object that contains both the instance data - * returned by the adapter _and_ metadata about the operation. - * - * The default is to NOT return the result object, and instead return just the - * instance data. - * - * @default false - * @name Mapper#raw - * @since 3.0.0 - * @type {boolean} - */ raw: false, - - /** - * Whether records created from this mapper automatically validate their properties - * when their properties are modified. - * - * @default true - * @name Mapper#validateOnSet - * @since 3.0.0 - * @type {boolean} - */ validateOnSet: true }; - /** - * The core of JSData's [ORM/ODM][orm] implementation. Given a minimum amout of - * meta information about a resource, a Mapper can perform generic CRUD - * operations against that resource. Apart from its configuration, a Mapper is - * stateless. The particulars of various persistence layers have been abstracted - * into adapters, which a Mapper uses to perform its operations. - * - * The term "Mapper" comes from the [Data Mapper Pattern][pattern] described in - * Martin Fowler's [Patterns of Enterprise Application Architecture][book]. A - * Data Mapper moves data between [in-memory object instances][record] and a - * relational or document-based database. JSData's Mapper can work with any - * persistence layer you can write an adapter for. - * - * _("Model" is a heavily overloaded term and is avoided in this documentation - * to prevent confusion.)_ - * - * [orm]: https://en.wikipedia.org/wiki/Object-relational_mapping - * - * @example - * [pattern]: https://en.wikipedia.org/wiki/Data_mapper_pattern - * [book]: http://martinfowler.com/books/eaa.html - * [record]: Record.html - * // Import and instantiate - * import { Mapper } from 'js-data'; - * const UserMapper = new Mapper({ name: 'user' }); - * - * @example - * // Define a Mapper using the Container component - * import { Container } from 'js-data'; - * const store = new Container(); - * store.defineMapper('user'); - * - * @class Mapper - * @extends Component - * @param {object} opts Configuration options. - * @param {boolean} [opts.applySchema=true] See {@link Mapper#applySchema}. - * @param {boolean} [opts.debug=false] See {@link Component#debug}. - * @param {string} [opts.defaultAdapter=http] See {@link Mapper#defaultAdapter}. - * @param {string} [opts.idAttribute=id] See {@link Mapper#idAttribute}. - * @param {object} [opts.methods] See {@link Mapper#methods}. - * @param {string} opts.name See {@link Mapper#name}. - * @param {boolean} [opts.notify] See {@link Mapper#notify}. - * @param {boolean} [opts.raw=false] See {@link Mapper#raw}. - * @param {Function|boolean} [opts.recordClass] See {@link Mapper#recordClass}. - * @param {Object|Schema} [opts.schema] See {@link Mapper#schema}. - * @returns {Mapper} A new {@link Mapper} instance. - * @see http://www.js-data.io/v3.0/docs/components-of-jsdata#mapper - * @since 3.0.0 - * @tutorial ["http://www.js-data.io/v3.0/docs/components-of-jsdata#mapper","Components of JSData: Mapper"] - * @tutorial ["http://www.js-data.io/v3.0/docs/modeling-your-data","Modeling your data"] + /** + * The core of JSData's [ORM/ODM][orm] implementation. Given a minimum amount of + * meta information about a resource, a Mapper can perform generic CRUD + * operations against that resource. Apart from its configuration, a Mapper is + * stateless. The particulars of various persistence layers have been abstracted + * into adapters, which a Mapper uses to perform its operations. + * + * The term "Mapper" comes from the [Data Mapper Pattern][pattern] described in + * Martin Fowler's [Patterns of Enterprise Application Architecture][book]. A + * Data Mapper moves data between [in-memory object instances][record] and a + * relational or document-based database. JSData's Mapper can work with any + * persistence layer you can write an adapter for. + * + * _("Model" is a heavily overloaded term and is avoided in this documentation + * to prevent confusion.)_ + * + * [orm]: https://en.wikipedia.org/wiki/Object-relational_mapping + * + * @example + * [pattern]: https://en.wikipedia.org/wiki/Data_mapper_pattern + * [book]: http://martinfowler.com/books/eaa.html + * [record]: Record.html + * // Import and instantiate + * import { Mapper } from 'js-data'; + * const UserMapper = new Mapper({ name: 'user' }); + * + * @example + * // Define a Mapper using the Container component + * import { Container } from 'js-data'; + * const store = new Container(); + * store.defineMapper('user'); + * + * @class Mapper + * @extends Component + * @param {object} opts Configuration options. + * @param {boolean} [opts.applySchema=true] See {@link Mapper#applySchema}. + * @param {boolean} [opts.debug=false] See {@link Component#debug}. + * @param {string} [opts.defaultAdapter=http] See {@link Mapper#defaultAdapter}. + * @param {string} [opts.idAttribute=id] See {@link Mapper#idAttribute}. + * @param {object} [opts.methods] See {@link Mapper#methods}. + * @param {string} opts.name See {@link Mapper#name}. + * @param {boolean} [opts.notify] See {@link Mapper#notify}. + * @param {boolean} [opts.raw=false] See {@link Mapper#raw}. + * @param {Function|boolean} [opts.recordClass] See {@link Mapper#recordClass}. + * @param {Object|Schema} [opts.schema] See {@link Mapper#schema}. + * @returns {Mapper} A new {@link Mapper} instance. + * @see http://www.js-data.io/v3.0/docs/components-of-jsdata#mapper + * @since 3.0.0 + * @tutorial ["http://www.js-data.io/v3.0/docs/components-of-jsdata#mapper","Components of JSData: Mapper"] + * @tutorial ["http://www.js-data.io/v3.0/docs/modeling-your-data","Modeling your data"] */ - function Mapper(opts) { - utils.classCallCheck(this, Mapper); - Component$1.call(this); - opts || (opts = {}); // Prepare certain properties to be non-enumerable + var Mapper = + /*#__PURE__*/ + function (_Component) { + _inherits(Mapper, _Component); - Object.defineProperties(this, { - _adapters: { - value: undefined, - writable: true - }, + function Mapper() { + var _this2; - /** - * The {@link Container} that holds this Mapper. __Do not modify.__ - * - * @name Mapper#lifecycleMethods - * @since 3.0.0 - * @type {Object} + var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + + _classCallCheck(this, Mapper); + + _this2 = _possibleConstructorReturn(this, _getPrototypeOf(Mapper).call(this)); + /** + * The meta information describing this Mapper's available lifecycle + * methods. __Do not modify.__ + * + * @name Mapper#lifecycleMethods + * @since 3.0.0 + * @type {Object} */ - datastore: { - value: undefined, - writable: true - }, - /** - * The meta information describing this Mapper's available lifecycle - * methods. __Do not modify.__ - * - * @name Mapper#lifecycleMethods - * @since 3.0.0 - * @type {Object} + _this2.lifecycleMethods = LIFECYCLE_METHODS; + /** + * Mapper lifecycle hook called by {@link Mapper#count}. If this method + * returns a promise then {@link Mapper#count} will wait for the promise + * to resolve before continuing. + * + * @method Mapper#afterCount + * @param {object} query The `query` argument passed to {@link Mapper#count}. + * @param {object} opts The `opts` argument passed to {@link Mapper#count}. + * @param {*} result The result, if any. + * @since 3.0.0 */ - lifecycleMethods: { - value: LIFECYCLE_METHODS - }, - /** - * Set to `false` to force the Mapper to work with POJO objects only. - * - * @example - * // Use POJOs only. - * import { Mapper, Record } from 'js-data'; - * const UserMapper = new Mapper({ recordClass: false }); - * UserMapper.recordClass // false; - * const user = UserMapper.createRecord(); - * user instanceof Record; // false - * - * @example - * // Set to a custom class to have records wrapped in your custom class. - * import { Mapper, Record } from 'js-data'; - * // Custom class - * class User { - * constructor (props = {}) { - * for (var key in props) { - * if (props.hasOwnProperty(key)) { - * this[key] = props[key]; - * } - * } - * } - * } - * const UserMapper = new Mapper({ recordClass: User }); - * UserMapper.recordClass; // function User() {} - * const user = UserMapper.createRecord(); - * user instanceof Record; // false - * user instanceof User; // true - * - * - * @example - * // Extend the {@link Record} class. - * import { Mapper, Record } from 'js-data'; - * // Custom class - * class User extends Record { - * constructor () { - * super(props); - * } - * } - * const UserMapper = new Mapper({ recordClass: User }); - * UserMapper.recordClass; // function User() {} - * const user = UserMapper.createRecord(); - * user instanceof Record; // true - * user instanceof User; // true - * - * @name Mapper#recordClass - * @default {@link Record} - * @see Record - * @since 3.0.0 - */ - recordClass: { - value: undefined, - writable: true - }, + _this2.afterCount = notify2; + /** + * Mapper lifecycle hook called by {@link Mapper#create}. If this method + * returns a promise then {@link Mapper#create} will wait for the promise + * to resolve before continuing. + * + * @method Mapper#afterCreate + * @param {object} props The `props` argument passed to {@link Mapper#create}. + * @param {object} opts The `opts` argument passed to {@link Mapper#create}. + * @param {*} result The result, if any. + * @since 3.0.0 + */ - /** - * This Mapper's {@link Schema}. - * - * @example Mapper#schema - * const JSData = require('js-data'); - * const { Mapper } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const UserMapper = new Mapper({ - * name: 'user', - * schema: { - * properties: { - * id: { type: 'number' }, - * first: { type: 'string', track: true }, - * last: { type: 'string', track: true }, - * role: { type: 'string', track: true, required: true }, - * age: { type: 'integer', track: true }, - * is_active: { type: 'number' } - * } - * } - * }); - * const user = UserMapper.createRecord({ - * id: 1, - * name: 'John', - * role: 'admin' - * }); - * user.on('change', function (user, changes) { - * console.log(changes); - * }); - * user.on('change:role', function (user, value) { - * console.log('change:role - ' + value); - * }); - * user.role = 'owner'; - * - * @name Mapper#schema - * @see Schema - * @since 3.0.0 - * @type {Schema} - */ - schema: { - value: undefined, - writable: true - } - }); // Apply user-provided configuration + _this2.afterCreate = notify2; + /** + * Mapper lifecycle hook called by {@link Mapper#createMany}. If this method + * returns a promise then {@link Mapper#createMany} will wait for the promise + * to resolve before continuing. + * + * @method Mapper#afterCreateMany + * @param {array} records The `records` argument passed to {@link Mapper#createMany}. + * @param {object} opts The `opts` argument passed to {@link Mapper#createMany}. + * @param {*} result The result, if any. + * @since 3.0.0 + */ - utils.fillIn(this, opts); // Fill in any missing options with the defaults + _this2.afterCreateMany = notify2; + /** + * Mapper lifecycle hook called by {@link Mapper#destroy}. If this method + * returns a promise then {@link Mapper#destroy} will wait for the promise + * to resolve before continuing. + * + * @method Mapper#afterDestroy + * @param {(string|number)} id The `id` argument passed to {@link Mapper#destroy}. + * @param {object} opts The `opts` argument passed to {@link Mapper#destroy}. + * @param {*} result The result, if any. + * @since 3.0.0 + */ - utils.fillIn(this, utils.copy(MAPPER_DEFAULTS)); - /** - * The name for this Mapper. This is the minimum amount of meta information - * required for a Mapper to be able to execute CRUD operations for a - * Resource. - * - * @name Mapper#name - * @since 3.0.0 - * @type {string} - */ + _this2.afterDestroy = notify2; + /** + * Mapper lifecycle hook called by {@link Mapper#destroyAll}. If this method + * returns a promise then {@link Mapper#destroyAll} will wait for the promise + * to resolve before continuing. + * + * @method Mapper#afterDestroyAll + * @param {*} data The `data` returned by the adapter. + * @param {query} query The `query` argument passed to {@link Mapper#destroyAll}. + * @param {object} opts The `opts` argument passed to {@link Mapper#destroyAll}. + * @param {*} result The result, if any. + * @since 3.0.0 + */ - if (!this.name) { - throw utils.err("new ".concat(DOMAIN$6), 'opts.name')(400, 'string', this.name); - } // Setup schema, with an empty default schema if necessary + _this2.afterDestroyAll = notify2; + /** + * Mapper lifecycle hook called by {@link Mapper#find}. If this method + * returns a promise then {@link Mapper#find} will wait for the promise + * to resolve before continuing. + * + * @method Mapper#afterFind + * @param {(string|number)} id The `id` argument passed to {@link Mapper#find}. + * @param {object} opts The `opts` argument passed to {@link Mapper#find}. + * @param {*} result The result, if any. + * @since 3.0.0 + */ + _this2.afterFind = notify2; + /** + * Mapper lifecycle hook called by {@link Mapper#findAll}. If this method + * returns a promise then {@link Mapper#findAll} will wait for the promise + * to resolve before continuing. + * + * @method Mapper#afterFindAll + * @param {object} query The `query` argument passed to {@link Mapper#findAll}. + * @param {object} opts The `opts` argument passed to {@link Mapper#findAll}. + * @param {*} result The result, if any. + * @since 3.0.0 + */ - if (this.schema) { - this.schema.type || (this.schema.type = 'object'); + _this2.afterFindAll = notify2; + /** + * Mapper lifecycle hook called by {@link Mapper#sum}. If this method + * returns a promise then {@link Mapper#sum} will wait for the promise + * to resolve before continuing. + * + * @method Mapper#afterSum + * @param {object} query The `query` argument passed to {@link Mapper#sum}. + * @param {object} opts The `opts` argument passed to {@link Mapper#sum}. + * @param {*} result The result, if any. + * @since 3.0.0 + */ - if (!(this.schema instanceof Schema$1)) { - this.schema = new Schema$1(this.schema || { - type: 'object' - }); - } - } // Create a subclass of Record that's tied to this Mapper + _this2.afterSum = notify2; + /** + * Mapper lifecycle hook called by {@link Mapper#update}. If this method + * returns a promise then {@link Mapper#update} will wait for the promise + * to resolve before continuing. + * + * @method Mapper#afterUpdate + * @param {(string|number)} id The `id` argument passed to {@link Mapper#update}. + * @param {props} props The `props` argument passed to {@link Mapper#update}. + * @param {object} opts The `opts` argument passed to {@link Mapper#update}. + * @param {*} result The result, if any. + * @since 3.0.0 + */ + _this2.afterUpdate = notify2; + /** + * Mapper lifecycle hook called by {@link Mapper#updateAll}. If this method + * returns a promise then {@link Mapper#updateAll} will wait for the promise + * to resolve before continuing. + * + * @method Mapper#afterUpdateAll + * @param {object} props The `props` argument passed to {@link Mapper#updateAll}. + * @param {object} query The `query` argument passed to {@link Mapper#updateAll}. + * @param {object} opts The `opts` argument passed to {@link Mapper#updateAll}. + * @param {*} result The result, if any. + * @since 3.0.0 + */ - if (this.recordClass === undefined) { - var superClass = Record$1; - this.recordClass = superClass.extend({ - constructor: function Record() { - var subClass = function Record(props, opts) { - utils.classCallCheck(this, subClass); - superClass.call(this, props, opts); - }; + _this2.afterUpdateAll = notify2; + /** + * Mapper lifecycle hook called by {@link Mapper#updateMany}. If this method + * returns a promise then {@link Mapper#updateMany} will wait for the promise + * to resolve before continuing. + * + * @method Mapper#afterUpdateMany + * @param {array} records The `records` argument passed to {@link Mapper#updateMany}. + * @param {object} opts The `opts` argument passed to {@link Mapper#updateMany}. + * @param {*} result The result, if any. + * @since 3.0.0 + */ - return subClass; - }() - }); - } + _this2.afterUpdateMany = notify2; + /** + * Mapper lifecycle hook called by {@link Mapper#create}. If this method + * returns a promise then {@link Mapper#create} will wait for the promise + * to resolve before continuing. + * + * @method Mapper#beforeCreate + * @param {object} props The `props` argument passed to {@link Mapper#create}. + * @param {object} opts The `opts` argument passed to {@link Mapper#create}. + * @since 3.0.0 + */ - if (this.recordClass) { - this.recordClass.mapper = this; - /** - * Functions that should be added to the prototype of {@link Mapper#recordClass}. - * - * @name Mapper#methods - * @since 3.0.0 - * @type {Object} + _this2.beforeCreate = notify; + /** + * Mapper lifecycle hook called by {@link Mapper#createMany}. If this method + * returns a promise then {@link Mapper#createMany} will wait for the promise + * to resolve before continuing. + * + * @method Mapper#beforeCreateMany + * @param {array} records The `records` argument passed to {@link Mapper#createMany}. + * @param {object} opts The `opts` argument passed to {@link Mapper#createMany}. + * @since 3.0.0 */ - if (utils.isObject(this.methods)) { - utils.addHiddenPropsToTarget(this.recordClass.prototype, this.methods); - } // We can only apply the schema to the prototype of this.recordClass if the - // class extends Record + _this2.beforeCreateMany = notify; + /** + * Mapper lifecycle hook called by {@link Mapper#count}. If this method + * returns a promise then {@link Mapper#count} will wait for the promise + * to resolve before continuing. + * + * @method Mapper#beforeCount + * @param {object} query The `query` argument passed to {@link Mapper#count}. + * @param {object} opts The `opts` argument passed to {@link Mapper#count}. + * @since 3.0.0 + */ + _this2.beforeCount = notify; + /** + * Mapper lifecycle hook called by {@link Mapper#destroy}. If this method + * returns a promise then {@link Mapper#destroy} will wait for the promise + * to resolve before continuing. + * + * @method Mapper#beforeDestroy + * @param {(string|number)} id The `id` argument passed to {@link Mapper#destroy}. + * @param {object} opts The `opts` argument passed to {@link Mapper#destroy}. + * @since 3.0.0 + */ - if (Object.isPrototypeOf.call(Record$1, this.recordClass) && this.schema && this.schema.apply && this.applySchema) { - this.schema.apply(this.recordClass.prototype); - } - } - } + _this2.beforeDestroy = notify; + /** + * Mapper lifecycle hook called by {@link Mapper#destroyAll}. If this method + * returns a promise then {@link Mapper#destroyAll} will wait for the promise + * to resolve before continuing. + * + * @method Mapper#beforeDestroyAll + * @param {query} query The `query` argument passed to {@link Mapper#destroyAll}. + * @param {object} opts The `opts` argument passed to {@link Mapper#destroyAll}. + * @since 3.0.0 + */ - var Mapper$1 = Component$1.extend({ - constructor: Mapper, - - /** - * Mapper lifecycle hook called by {@link Mapper#count}. If this method - * returns a promise then {@link Mapper#count} will wait for the promise - * to resolve before continuing. - * - * @method Mapper#afterCount - * @param {object} query The `query` argument passed to {@link Mapper#count}. - * @param {object} opts The `opts` argument passed to {@link Mapper#count}. - * @param {*} result The result, if any. - * @since 3.0.0 - */ - afterCount: notify2, - - /** - * Mapper lifecycle hook called by {@link Mapper#create}. If this method - * returns a promise then {@link Mapper#create} will wait for the promise - * to resolve before continuing. - * - * @method Mapper#afterCreate - * @param {object} props The `props` argument passed to {@link Mapper#create}. - * @param {object} opts The `opts` argument passed to {@link Mapper#create}. - * @param {*} result The result, if any. - * @since 3.0.0 - */ - afterCreate: notify2, - - /** - * Mapper lifecycle hook called by {@link Mapper#createMany}. If this method - * returns a promise then {@link Mapper#createMany} will wait for the promise - * to resolve before continuing. - * - * @method Mapper#afterCreateMany - * @param {array} records The `records` argument passed to {@link Mapper#createMany}. - * @param {object} opts The `opts` argument passed to {@link Mapper#createMany}. - * @param {*} result The result, if any. - * @since 3.0.0 - */ - afterCreateMany: notify2, - - /** - * Mapper lifecycle hook called by {@link Mapper#destroy}. If this method - * returns a promise then {@link Mapper#destroy} will wait for the promise - * to resolve before continuing. - * - * @method Mapper#afterDestroy - * @param {(string|number)} id The `id` argument passed to {@link Mapper#destroy}. - * @param {object} opts The `opts` argument passed to {@link Mapper#destroy}. - * @param {*} result The result, if any. - * @since 3.0.0 - */ - afterDestroy: notify2, - - /** - * Mapper lifecycle hook called by {@link Mapper#destroyAll}. If this method - * returns a promise then {@link Mapper#destroyAll} will wait for the promise - * to resolve before continuing. - * - * @method Mapper#afterDestroyAll - * @param {*} data The `data` returned by the adapter. - * @param {query} query The `query` argument passed to {@link Mapper#destroyAll}. - * @param {object} opts The `opts` argument passed to {@link Mapper#destroyAll}. - * @param {*} result The result, if any. - * @since 3.0.0 - */ - afterDestroyAll: notify2, - - /** - * Mapper lifecycle hook called by {@link Mapper#find}. If this method - * returns a promise then {@link Mapper#find} will wait for the promise - * to resolve before continuing. - * - * @method Mapper#afterFind - * @param {(string|number)} id The `id` argument passed to {@link Mapper#find}. - * @param {object} opts The `opts` argument passed to {@link Mapper#find}. - * @param {*} result The result, if any. - * @since 3.0.0 - */ - afterFind: notify2, - - /** - * Mapper lifecycle hook called by {@link Mapper#findAll}. If this method - * returns a promise then {@link Mapper#findAll} will wait for the promise - * to resolve before continuing. - * - * @method Mapper#afterFindAll - * @param {object} query The `query` argument passed to {@link Mapper#findAll}. - * @param {object} opts The `opts` argument passed to {@link Mapper#findAll}. - * @param {*} result The result, if any. - * @since 3.0.0 - */ - afterFindAll: notify2, - - /** - * Mapper lifecycle hook called by {@link Mapper#sum}. If this method - * returns a promise then {@link Mapper#sum} will wait for the promise - * to resolve before continuing. - * - * @method Mapper#afterSum - * @param {object} query The `query` argument passed to {@link Mapper#sum}. - * @param {object} opts The `opts` argument passed to {@link Mapper#sum}. - * @param {*} result The result, if any. - * @since 3.0.0 - */ - afterSum: notify2, - - /** - * Mapper lifecycle hook called by {@link Mapper#update}. If this method - * returns a promise then {@link Mapper#update} will wait for the promise - * to resolve before continuing. - * - * @method Mapper#afterUpdate - * @param {(string|number)} id The `id` argument passed to {@link Mapper#update}. - * @param {props} props The `props` argument passed to {@link Mapper#update}. - * @param {object} opts The `opts` argument passed to {@link Mapper#update}. - * @param {*} result The result, if any. - * @since 3.0.0 - */ - afterUpdate: notify2, - - /** - * Mapper lifecycle hook called by {@link Mapper#updateAll}. If this method - * returns a promise then {@link Mapper#updateAll} will wait for the promise - * to resolve before continuing. - * - * @method Mapper#afterUpdateAll - * @param {object} props The `props` argument passed to {@link Mapper#updateAll}. - * @param {object} query The `query` argument passed to {@link Mapper#updateAll}. - * @param {object} opts The `opts` argument passed to {@link Mapper#updateAll}. - * @param {*} result The result, if any. - * @since 3.0.0 - */ - afterUpdateAll: notify2, - - /** - * Mapper lifecycle hook called by {@link Mapper#updateMany}. If this method - * returns a promise then {@link Mapper#updateMany} will wait for the promise - * to resolve before continuing. - * - * @method Mapper#afterUpdateMany - * @param {array} records The `records` argument passed to {@link Mapper#updateMany}. - * @param {object} opts The `opts` argument passed to {@link Mapper#updateMany}. - * @param {*} result The result, if any. - * @since 3.0.0 - */ - afterUpdateMany: notify2, - - /** - * Mapper lifecycle hook called by {@link Mapper#create}. If this method - * returns a promise then {@link Mapper#create} will wait for the promise - * to resolve before continuing. - * - * @method Mapper#beforeCreate - * @param {object} props The `props` argument passed to {@link Mapper#create}. - * @param {object} opts The `opts` argument passed to {@link Mapper#create}. - * @since 3.0.0 - */ - beforeCreate: notify, - - /** - * Mapper lifecycle hook called by {@link Mapper#createMany}. If this method - * returns a promise then {@link Mapper#createMany} will wait for the promise - * to resolve before continuing. - * - * @method Mapper#beforeCreateMany - * @param {array} records The `records` argument passed to {@link Mapper#createMany}. - * @param {object} opts The `opts` argument passed to {@link Mapper#createMany}. - * @since 3.0.0 - */ - beforeCreateMany: notify, - - /** - * Mapper lifecycle hook called by {@link Mapper#count}. If this method - * returns a promise then {@link Mapper#count} will wait for the promise - * to resolve before continuing. - * - * @method Mapper#beforeCount - * @param {object} query The `query` argument passed to {@link Mapper#count}. - * @param {object} opts The `opts` argument passed to {@link Mapper#count}. - * @since 3.0.0 - */ - beforeCount: notify, - - /** - * Mapper lifecycle hook called by {@link Mapper#destroy}. If this method - * returns a promise then {@link Mapper#destroy} will wait for the promise - * to resolve before continuing. - * - * @method Mapper#beforeDestroy - * @param {(string|number)} id The `id` argument passed to {@link Mapper#destroy}. - * @param {object} opts The `opts` argument passed to {@link Mapper#destroy}. - * @since 3.0.0 - */ - beforeDestroy: notify, - - /** - * Mapper lifecycle hook called by {@link Mapper#destroyAll}. If this method - * returns a promise then {@link Mapper#destroyAll} will wait for the promise - * to resolve before continuing. - * - * @method Mapper#beforeDestroyAll - * @param {query} query The `query` argument passed to {@link Mapper#destroyAll}. - * @param {object} opts The `opts` argument passed to {@link Mapper#destroyAll}. - * @since 3.0.0 - */ - beforeDestroyAll: notify, - - /** - * Mappers lifecycle hook called by {@link Mapper#find}. If this method - * returns a promise then {@link Mapper#find} will wait for the promise - * to resolve before continuing. - * - * @method Mapper#beforeFind - * @param {(string|number)} id The `id` argument passed to {@link Mapper#find}. - * @param {object} opts The `opts` argument passed to {@link Mapper#find}. - * @since 3.0.0 - */ - beforeFind: notify, - - /** - * Mapper lifecycle hook called by {@link Mapper#findAll}. If this method - * returns a promise then {@link Mapper#findAll} will wait for the promise - * to resolve before continuing. - * - * @method Mapper#beforeFindAll - * @param {object} query The `query` argument passed to {@link Mapper#findAll}. - * @param {object} opts The `opts` argument passed to {@link Mapper#findAll}. - * @since 3.0.0 - */ - beforeFindAll: notify, - - /** - * Mapper lifecycle hook called by {@link Mapper#sum}. If this method - * returns a promise then {@link Mapper#sum} will wait for the promise - * to resolve before continuing. - * - * @method Mapper#beforeSum - * @param {string} field The `field` argument passed to {@link Mapper#sum}. - * @param {object} query The `query` argument passed to {@link Mapper#sum}. - * @param {object} opts The `opts` argument passed to {@link Mapper#sum}. - * @since 3.0.0 - */ - beforeSum: notify, - - /** - * Mapper lifecycle hook called by {@link Mapper#update}. If this method - * returns a promise then {@link Mapper#update} will wait for the promise - * to resolve before continuing. - * - * @method Mapper#beforeUpdate - * @param {(string|number)} id The `id` argument passed to {@link Mapper#update}. - * @param {props} props The `props` argument passed to {@link Mapper#update}. - * @param {object} opts The `opts` argument passed to {@link Mapper#update}. - * @since 3.0.0 - */ - beforeUpdate: notify, - - /** - * Mapper lifecycle hook called by {@link Mapper#updateAll}. If this method - * returns a promise then {@link Mapper#updateAll} will wait for the promise - * to resolve before continuing. - * - * @method Mapper#beforeUpdateAll - * @param {object} props The `props` argument passed to {@link Mapper#updateAll}. - * @param {object} query The `query` argument passed to {@link Mapper#updateAll}. - * @param {object} opts The `opts` argument passed to {@link Mapper#updateAll}. - * @since 3.0.0 - */ - beforeUpdateAll: notify, - - /** - * Mapper lifecycle hook called by {@link Mapper#updateMany}. If this method - * returns a promise then {@link Mapper#updateMany} will wait for the promise - * to resolve before continuing. - * - * @method Mapper#beforeUpdateMany - * @param {array} records The `records` argument passed to {@link Mapper#updateMany}. - * @param {object} opts The `opts` argument passed to {@link Mapper#updateMany}. - * @since 3.0.0 - */ - beforeUpdateMany: notify, - - /** - * This method is called at the end of most lifecycle methods. It does the - * following: - * - * 1. If `opts.raw` is `true`, add this Mapper's configuration to the `opts` - * argument as metadata for the operation. - * 2. Wrap the result data appropriately using {@link Mapper#wrap}, which - * calls {@link Mapper#createRecord}. - * - * @method Mapper#_end - * @private - * @since 3.0.0 - */ - _end: function _end(result, opts, skip) { - if (opts.raw) { - utils._(result, opts); - } + _this2.beforeDestroyAll = notify; + /** + * Mappers lifecycle hook called by {@link Mapper#find}. If this method + * returns a promise then {@link Mapper#find} will wait for the promise + * to resolve before continuing. + * + * @method Mapper#beforeFind + * @param {(string|number)} id The `id` argument passed to {@link Mapper#find}. + * @param {object} opts The `opts` argument passed to {@link Mapper#find}. + * @since 3.0.0 + */ - if (skip) { - return result; + _this2.beforeFind = notify; + /** + * Mapper lifecycle hook called by {@link Mapper#findAll}. If this method + * returns a promise then {@link Mapper#findAll} will wait for the promise + * to resolve before continuing. + * + * @method Mapper#beforeFindAll + * @param {object} query The `query` argument passed to {@link Mapper#findAll}. + * @param {object} opts The `opts` argument passed to {@link Mapper#findAll}. + * @since 3.0.0 + */ + + _this2.beforeFindAll = notify; + /** + * Mapper lifecycle hook called by {@link Mapper#sum}. If this method + * returns a promise then {@link Mapper#sum} will wait for the promise + * to resolve before continuing. + * + * @method Mapper#beforeSum + * @param {string} field The `field` argument passed to {@link Mapper#sum}. + * @param {object} query The `query` argument passed to {@link Mapper#sum}. + * @param {object} opts The `opts` argument passed to {@link Mapper#sum}. + * @since 3.0.0 + */ + + _this2.beforeSum = notify; + /** + * Mapper lifecycle hook called by {@link Mapper#update}. If this method + * returns a promise then {@link Mapper#update} will wait for the promise + * to resolve before continuing. + * + * @method Mapper#beforeUpdate + * @param {(string|number)} id The `id` argument passed to {@link Mapper#update}. + * @param {props} props The `props` argument passed to {@link Mapper#update}. + * @param {object} opts The `opts` argument passed to {@link Mapper#update}. + * @since 3.0.0 + */ + + _this2.beforeUpdate = notify; + /** + * Mapper lifecycle hook called by {@link Mapper#updateAll}. If this method + * returns a promise then {@link Mapper#updateAll} will wait for the promise + * to resolve before continuing. + * + * @method Mapper#beforeUpdateAll + * @param {object} props The `props` argument passed to {@link Mapper#updateAll}. + * @param {object} query The `query` argument passed to {@link Mapper#updateAll}. + * @param {object} opts The `opts` argument passed to {@link Mapper#updateAll}. + * @since 3.0.0 + */ + + _this2.beforeUpdateAll = notify; + /** + * Mapper lifecycle hook called by {@link Mapper#updateMany}. If this method + * returns a promise then {@link Mapper#updateMany} will wait for the promise + * to resolve before continuing. + * + * @method Mapper#beforeUpdateMany + * @param {array} records The `records` argument passed to {@link Mapper#updateMany}. + * @param {object} opts The `opts` argument passed to {@link Mapper#updateMany}. + * @since 3.0.0 + */ + + _this2.beforeUpdateMany = notify; // Apply user-provided configuration + + utils.fillIn(_assertThisInitialized(_this2), opts); // Fill in any missing options with the defaults + + utils.fillIn(_assertThisInitialized(_this2), utils.copy(MAPPER_DEFAULTS)); + /** + * The name for this Mapper. This is the minimum amount of meta information + * required for a Mapper to be able to execute CRUD operations for a + * Resource. + * + * @name Mapper#name + * @since 3.0.0 + * @type {string} + */ + + if (!_this2.name) { + throw utils.err("new ".concat(DOMAIN$6), 'opts.name')(400, 'string', _this2.name); + } // Setup schema, with an empty default schema if necessary + + + if (_this2.schema) { + _this2.schema.type = _this2.schema.type || 'object'; + + if (!(_this2.schema instanceof Schema)) { + _this2.schema = new Schema(_this2.schema || { + type: 'object' + }); + } + } // Create a subclass of Record that's tied to this Mapper + + + if (_this2.recordClass === undefined) { + // tslint:disable-next-line:max-classes-per-file + _this2.recordClass = + /*#__PURE__*/ + function (_Record) { + _inherits(TiedRecord, _Record); + + function TiedRecord() { + _classCallCheck(this, TiedRecord); + + return _possibleConstructorReturn(this, _getPrototypeOf(TiedRecord).apply(this, arguments)); + } + + return TiedRecord; + }(Record); } - var _data = opts.raw ? result.data : result; + if (_this2.recordClass) { + _this2.recordClass.mapper = _assertThisInitialized(_this2); + /** + * Functions that should be added to the prototype of {@link Mapper#recordClass}. + * + * @name Mapper#methods + * @since 3.0.0 + * @type {Object} + */ + + if (utils.isObject(_this2.methods)) { + utils.addHiddenPropsToTarget(_this2.recordClass.prototype, _this2.methods); + } // We can only apply the schema to the prototype of this.recordClass if the + // class extends Record + + + if (Record.prototype.isPrototypeOf(Object.create(_this2.recordClass.prototype)) && _this2.schema && _this2.schema.apply && _this2.applySchema) { + _this2.schema.apply(_this2.recordClass.prototype); + } + } - if (_data && utils.isFunction(this.wrap)) { - _data = this.wrap(_data, opts); + return _this2; + } + /** + * This method is called at the end of most lifecycle methods. It does the + * following: + * + * 1. If `opts.raw` is `true`, add this Mapper's configuration to the `opts` + * argument as metadata for the operation. + * 2. Wrap the result data appropriately using {@link Mapper#wrap}, which + * calls {@link Mapper#createRecord}. + * + * @method Mapper#_end + * @private + * @since 3.0.0 + */ + + + _createClass(Mapper, [{ + key: "_end", + value: function _end(result, opts) { + var skip = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; if (opts.raw) { - result.data = _data; - } else { - result = _data; + utils._(result, opts); + } + + if (skip) { + return result; + } + + var _data = opts.raw ? result.data : result; + + if (_data && utils.isFunction(this.wrap)) { + _data = this.wrap(_data, opts); + + if (opts.raw) { + result.data = _data; + } else { + result = _data; + } } + + return result; } + /** + * Define a belongsTo relationship. Only useful if you're managing your + * Mappers manually and not using a Container or DataStore component. + * + * @example + * PostMapper.belongsTo(UserMapper, { + * // post.user_id points to user.id + * foreignKey: 'user_id' + * // user records will be attached to post records at "post.user" + * localField: 'user' + * }); + * + * CommentMapper.belongsTo(UserMapper, { + * // comment.user_id points to user.id + * foreignKey: 'user_id' + * // user records will be attached to comment records at "comment.user" + * localField: 'user' + * }); + * CommentMapper.belongsTo(PostMapper, { + * // comment.post_id points to post.id + * foreignKey: 'post_id' + * // post records will be attached to comment records at "comment.post" + * localField: 'post' + * }); + * + * @method Mapper#belongsTo + * @see http://www.js-data.io/v3.0/docs/relations + * @since 3.0.0 + */ - return result; - }, + }, { + key: "belongsTo", + value: function belongsTo$1(relatedMapper, opts) { + return belongsTo(relatedMapper, opts)(this); + } + /** + * Select records according to the `query` argument and return the count. + * + * {@link Mapper#beforeCount} will be called before calling the adapter. + * {@link Mapper#afterCount} will be called after calling the adapter. + * + * @example + * // Get the number of published blog posts + * PostMapper.count({ status: 'published' }).then((numPublished) => { + * console.log(numPublished); // e.g. 45 + * }); + * + * @method Mapper#count + * @param {object} [query={}] Selection query. See {@link query}. + * @param {object} [query.where] See {@link query.where}. + * @param {number} [query.offset] See {@link query.offset}. + * @param {number} [query.limit] See {@link query.limit}. + * @param {string|Array[]} [query.orderBy] See {@link query.orderBy}. + * @param {object} [opts] Configuration options. Refer to the `count` method + * of whatever adapter you're using for more configuration options. + * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the + * adapter to use. + * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}. + * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}. + * @returns {Promise} Resolves with the count of the selected records. + * @since 3.0.0 + */ - /** - * Define a belongsTo relationship. Only useful if you're managing your - * Mappers manually and not using a Container or DataStore component. - * - * @example - * PostMapper.belongsTo(UserMapper, { - * // post.user_id points to user.id - * foreignKey: 'user_id' - * // user records will be attached to post records at "post.user" - * localField: 'user' - * }); - * - * CommentMapper.belongsTo(UserMapper, { - * // comment.user_id points to user.id - * foreignKey: 'user_id' - * // user records will be attached to comment records at "comment.user" - * localField: 'user' - * }); - * CommentMapper.belongsTo(PostMapper, { - * // comment.post_id points to post.id - * foreignKey: 'post_id' - * // post records will be attached to comment records at "comment.post" - * localField: 'post' - * }); - * - * @method Mapper#belongsTo - * @see http://www.js-data.io/v3.0/docs/relations - * @since 3.0.0 - */ - belongsTo: function belongsTo$1(relatedMapper, opts) { - return belongsTo(relatedMapper, opts)(this); - }, + }, { + key: "count", + value: function count(query, opts) { + return this.crud('count', query, opts); + } + /** + * Fired during {@link Mapper#create}. See + * {@link Mapper~beforeCreateListener} for how to listen for this event. + * + * @event Mapper#beforeCreate + * @see Mapper~beforeCreateListener + * @see Mapper#create + */ - /** - * Select records according to the `query` argument and return the count. - * - * {@link Mapper#beforeCount} will be called before calling the adapter. - * {@link Mapper#afterCount} will be called after calling the adapter. - * - * @example - * // Get the number of published blog posts - * PostMapper.count({ status: 'published' }).then((numPublished) => { - * console.log(numPublished); // e.g. 45 - * }); - * - * @method Mapper#count - * @param {object} [query={}] Selection query. See {@link query}. - * @param {object} [query.where] See {@link query.where}. - * @param {number} [query.offset] See {@link query.offset}. - * @param {number} [query.limit] See {@link query.limit}. - * @param {string|Array[]} [query.orderBy] See {@link query.orderBy}. - * @param {object} [opts] Configuration options. Refer to the `count` method - * of whatever adapter you're using for more configuration options. - * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the - * adapter to use. - * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}. - * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}. - * @returns {Promise} Resolves with the count of the selected records. - * @since 3.0.0 - */ - count: function count(query, opts) { - return this.crud('count', query, opts); - }, + /** + * Callback signature for the {@link Mapper#event:beforeCreate} event. + * + * @example + * function onBeforeCreate (props, opts) { + * // do something + * } + * store.on('beforeCreate', onBeforeCreate); + * + * @callback Mapper~beforeCreateListener + * @param {object} props The `props` argument passed to {@link Mapper#beforeCreate}. + * @param {object} opts The `opts` argument passed to {@link Mapper#beforeCreate}. + * @see Mapper#event:beforeCreate + * @see Mapper#create + * @since 3.0.0 + */ - /** - * Fired during {@link Mapper#create}. See - * {@link Mapper~beforeCreateListener} for how to listen for this event. - * - * @event Mapper#beforeCreate - * @see Mapper~beforeCreateListener - * @see Mapper#create - */ + /** + * Fired during {@link Mapper#create}. See + * {@link Mapper~afterCreateListener} for how to listen for this event. + * + * @event Mapper#afterCreate + * @see Mapper~afterCreateListener + * @see Mapper#create + */ - /** - * Callback signature for the {@link Mapper#event:beforeCreate} event. - * - * @example - * function onBeforeCreate (props, opts) { - * // do something - * } - * store.on('beforeCreate', onBeforeCreate); - * - * @callback Mapper~beforeCreateListener - * @param {object} props The `props` argument passed to {@link Mapper#beforeCreate}. - * @param {object} opts The `opts` argument passed to {@link Mapper#beforeCreate}. - * @see Mapper#event:beforeCreate - * @see Mapper#create - * @since 3.0.0 - */ + /** + * Callback signature for the {@link Mapper#event:afterCreate} event. + * + * @example + * function onAfterCreate (props, opts, result) { + * // do something + * } + * store.on('afterCreate', onAfterCreate); + * + * @callback Mapper~afterCreateListener + * @param {object} props The `props` argument passed to {@link Mapper#afterCreate}. + * @param {object} opts The `opts` argument passed to {@link Mapper#afterCreate}. + * @param {object} result The `result` argument passed to {@link Mapper#afterCreate}. + * @see Mapper#event:afterCreate + * @see Mapper#create + * @since 3.0.0 + */ - /** - * Fired during {@link Mapper#create}. See - * {@link Mapper~afterCreateListener} for how to listen for this event. - * - * @event Mapper#afterCreate - * @see Mapper~afterCreateListener - * @see Mapper#create - */ + /** + * Create and save a new the record using the provided `props`. + * + * {@link Mapper#beforeCreate} will be called before calling the adapter. + * {@link Mapper#afterCreate} will be called after calling the adapter. + * + * @example + * // Create and save a new blog post + * PostMapper.create({ + * title: 'Modeling your data', + * status: 'draft' + * }).then((post) => { + * console.log(post); // { id: 1234, status: 'draft', ... } + * }); + * + * @fires Mapper#beforeCreate + * @fires Mapper#afterCreate + * @method Mapper#create + * @param {object} props The properties for the new record. + * @param {object} [opts] Configuration options. Refer to the `create` method + * of whatever adapter you're using for more configuration options. + * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the + * adapter to use. + * @param {boolean} [opts.noValidate={@link Mapper#noValidate}] See {@link Mapper#noValidate}. + * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}. + * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}. + * @param {string[]} [opts.with=[]] Relations to create in a cascading + * create if `props` contains nested relations. NOT performed in a + * transaction. Each nested create will result in another {@link Mapper#create} + * or {@link Mapper#createMany} call. + * @param {string[]} [opts.pass=[]] Relations to send to the adapter as part + * of the payload. Normally relations are not sent. + * @returns {Promise} Resolves with the created record. + * @since 3.0.0 + */ - /** - * Callback signature for the {@link Mapper#event:afterCreate} event. - * - * @example - * function onAfterCreate (props, opts, result) { - * // do something - * } - * store.on('afterCreate', onAfterCreate); - * - * @callback Mapper~afterCreateListener - * @param {object} props The `props` argument passed to {@link Mapper#afterCreate}. - * @param {object} opts The `opts` argument passed to {@link Mapper#afterCreate}. - * @param {object} result The `result` argument passed to {@link Mapper#afterCreate}. - * @see Mapper#event:afterCreate - * @see Mapper#create - * @since 3.0.0 - */ + }, { + key: "create", + value: function create() { + var _this3 = this; - /** - * Create and save a new the record using the provided `props`. - * - * {@link Mapper#beforeCreate} will be called before calling the adapter. - * {@link Mapper#afterCreate} will be called after calling the adapter. - * - * @example - * // Create and save a new blog post - * PostMapper.create({ - * title: 'Modeling your data', - * status: 'draft' - * }).then((post) => { - * console.log(post); // { id: 1234, status: 'draft', ... } - * }); - * - * @fires Mapper#beforeCreate - * @fires Mapper#afterCreate - * @method Mapper#create - * @param {object} props The properties for the new record. - * @param {object} [opts] Configuration options. Refer to the `create` method - * of whatever adapter you're using for more configuration options. - * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the - * adapter to use. - * @param {boolean} [opts.noValidate={@link Mapper#noValidate}] See {@link Mapper#noValidate}. - * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}. - * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}. - * @param {string[]} [opts.with=[]] Relations to create in a cascading - * create if `props` contains nested relations. NOT performed in a - * transaction. Each nested create will result in another {@link Mapper#create} - * or {@link Mapper#createMany} call. - * @param {string[]} [opts.pass=[]] Relations to send to the adapter as part - * of the payload. Normally relations are not sent. - * @returns {Promise} Resolves with the created record. - * @since 3.0.0 - */ - create: function create(props, opts) { - var _this2 = this; - - // Default values for arguments - props || (props = {}); - opts || (opts = {}); - var originalRecord = props; - var parentRelationMap = {}; - var adapterResponse = {}; // Fill in "opts" with the Mapper's configuration - - utils._(opts, this); - - opts.adapter = this.getAdapterName(opts); - opts.op = 'beforeCreate'; - return this._runHook(opts.op, props, opts).then(function (props) { - opts.with || (opts.with = []); - return _this2._createParentRecordIfRequired(props, opts); - }).then(function (relationMap) { - parentRelationMap = relationMap; - }).then(function () { - opts.op = 'create'; - return _this2._invokeAdapterMethod(opts.op, props, opts); - }).then(function (result) { - adapterResponse = result; - }).then(function () { - var createdProps = opts.raw ? adapterResponse.data : adapterResponse; - return _this2._createOrAssignChildRecordIfRequired(createdProps, { - opts: opts, - parentRelationMap: parentRelationMap, - originalProps: props + var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var originalRecord = props; + var parentRelationMap = {}; + var adapterResponse = {}; // Fill in "opts" with the Mapper's configuration + + utils._(opts, this); + + opts.adapter = this.getAdapterName(opts); + opts.op = 'beforeCreate'; + return this._runHook(opts.op, props, opts).then(function (props) { + opts["with"] = opts["with"] || []; + return _this3._createParentRecordIfRequired(props, opts); + }).then(function (relationMap) { + parentRelationMap = relationMap; + }).then(function () { + opts.op = 'create'; + return _this3._invokeAdapterMethod(opts.op, props, opts); + }).then(function (result) { + adapterResponse = result; + }).then(function () { + var createdProps = opts.raw ? adapterResponse.data : adapterResponse; + return _this3._createOrAssignChildRecordIfRequired(createdProps, { + opts: opts, + parentRelationMap: parentRelationMap, + originalProps: props + }); + }).then(function (createdProps) { + return _this3._commitChanges(originalRecord, createdProps); + }).then(function (record) { + if (opts.raw) { + adapterResponse.data = record; + } else { + adapterResponse = record; + } + + var result = _this3._end(adapterResponse, opts); + + opts.op = 'afterCreate'; + return _this3._runHook(opts.op, props, opts, result); }); - }).then(function (createdProps) { - return _this2._commitChanges(originalRecord, createdProps); - }).then(function (record) { - if (opts.raw) { - adapterResponse.data = record; - } else { - adapterResponse = record; + } + }, { + key: "_commitChanges", + value: function _commitChanges(recordOrRecords, newValues) { + var _this4 = this; + + if (utils.isArray(recordOrRecords)) { + return recordOrRecords.map(function (record, i) { + return _this4._commitChanges(record, newValues[i]); + }); + } + + utils.set(recordOrRecords, newValues, { + silent: true + }); + + if (utils.isFunction(recordOrRecords.commit)) { + recordOrRecords.commit(); } - var result = _this2._end(adapterResponse, opts); + return recordOrRecords; + } + /** + * Use {@link Mapper#createRecord} instead. + * @deprecated + * @method Mapper#createInstance + * @param {Object|Array} props See {@link Mapper#createRecord}. + * @param {object} [opts] See {@link Mapper#createRecord}. + * @returns {Object|Array} See {@link Mapper#createRecord}. + * @see Mapper#createRecord + * @since 3.0.0 + */ + + }, { + key: "createInstance", + value: function createInstance(props, opts) { + return this.createRecord(props, opts); + } + /** + * Creates parent record for relation types like BelongsTo or HasMany with localKeys + * in order to satisfy foreignKey dependency (so called child records). + * @param {object} props See {@link Mapper#create}. + * @param {object} opts See {@link Mapper#create}. + * @returns {Object} cached parent records map + * @see Mapper#create + * @since 3.0.0 + */ - opts.op = 'afterCreate'; - return _this2._runHook(opts.op, props, opts, result); - }); - }, - _commitChanges: function _commitChanges(recordOrRecords, newValues) { - var _this3 = this; + }, { + key: "_createParentRecordIfRequired", + value: function _createParentRecordIfRequired(props, opts) { + var tasks = []; + var relations = []; + utils.forEachRelation(this, opts, function (def, optsCopy) { + if (!def.isRequiresParentId() || !def.getLocalField(props)) { + return; + } - if (utils.isArray(recordOrRecords)) { - return recordOrRecords.map(function (record, i) { - return _this3._commitChanges(record, newValues[i]); + optsCopy.raw = false; + relations.push(def); + tasks.push(def.createParentRecord(props, optsCopy)); + }); + return Promise.all(tasks).then(function (records) { + return relations.reduce(function (map, relation, index) { + relation.setLocalField(map, records[index]); + return map; + }, {}); }); } + /** + * Creates child record for relation types like HasOne or HasMany with foreignKey + * in order to satisfy foreignKey dependency (so called parent records). + * @param {object} props See {@link Mapper#create}. + * @param {object} context contains collected information. + * @param {object} context.opts See {@link Mapper#create}. + * @param {object} context.parentRelationMap contains parent records map + * @param {object} context.originalProps contains data passed into {@link Mapper#create} method + * @return {Promise} updated props + * @see Mapper#create + * @since 3.0.0 + */ - utils.set(recordOrRecords, newValues, { - silent: true - }); + }, { + key: "_createOrAssignChildRecordIfRequired", + value: function _createOrAssignChildRecordIfRequired(props, context) { + var tasks = []; + utils.forEachRelation(this, context.opts, function (def, optsCopy) { + var relationData = def.getLocalField(context.originalProps); + + if (!relationData) { + return; + } - if (utils.isFunction(recordOrRecords.commit)) { - recordOrRecords.commit(); + optsCopy.raw = false; // Create hasMany and hasOne after the main create because we needed + // a generated id to attach to these items + + if (def.isRequiresChildId()) { + tasks.push(def.createChildRecord(props, relationData, optsCopy)); + } else if (def.isRequiresParentId()) { + var parent = def.getLocalField(context.parentRelationMap); + + if (parent) { + def.setLocalField(props, parent); + } + } + }); + return Promise.all(tasks).then(function () { + return props; + }); } + /** + * Fired during {@link Mapper#createMany}. See + * {@link Mapper~beforeCreateManyListener} for how to listen for this event. + * + * @event Mapper#beforeCreateMany + * @see Mapper~beforeCreateManyListener + * @see Mapper#createMany + */ - return recordOrRecords; - }, + /** + * Callback signature for the {@link Mapper#event:beforeCreateMany} event. + * + * @example + * function onBeforeCreateMany (records, opts) { + * // do something + * } + * store.on('beforeCreateMany', onBeforeCreateMany); + * + * @callback Mapper~beforeCreateManyListener + * @param {object} records The `records` argument received by {@link Mapper#beforeCreateMany}. + * @param {object} opts The `opts` argument received by {@link Mapper#beforeCreateMany}. + * @see Mapper#event:beforeCreateMany + * @see Mapper#createMany + * @since 3.0.0 + */ - /** - * Use {@link Mapper#createRecord} instead. - * @deprecated - * @method Mapper#createInstance - * @param {Object|Array} props See {@link Mapper#createRecord}. - * @param {object} [opts] See {@link Mapper#createRecord}. - * @returns {Object|Array} See {@link Mapper#createRecord}. - * @see Mapper#createRecord - * @since 3.0.0 - */ - createInstance: function createInstance(props, opts) { - return this.createRecord(props, opts); - }, + /** + * Fired during {@link Mapper#createMany}. See + * {@link Mapper~afterCreateManyListener} for how to listen for this event. + * + * @event Mapper#afterCreateMany + * @see Mapper~afterCreateManyListener + * @see Mapper#createMany + */ - /** - * Creates parent record for relation types like BelongsTo or HasMany with localKeys - * in order to satisfy foreignKey dependency (so called child records). - * @param {object} props See {@link Mapper#create}. - * @param {object} opts See {@link Mapper#create}. - * @returns {Object} cached parent records map - * @see Mapper#create - * @since 3.0.0 - */ - _createParentRecordIfRequired: function _createParentRecordIfRequired(props, opts) { - var tasks = []; - var relations = []; - utils.forEachRelation(this, opts, function (def, optsCopy) { - if (!def.isRequiresParentId() || !def.getLocalField(props)) { - return; - } + /** + * Callback signature for the {@link Mapper#event:afterCreateMany} event. + * + * @example + * function onAfterCreateMany (records, opts, result) { + * // do something + * } + * store.on('afterCreateMany', onAfterCreateMany); + * + * @callback Mapper~afterCreateManyListener + * @param {object} records The `records` argument received by {@link Mapper#afterCreateMany}. + * @param {object} opts The `opts` argument received by {@link Mapper#afterCreateMany}. + * @param {object} result The `result` argument received by {@link Mapper#afterCreateMany}. + * @see Mapper#event:afterCreateMany + * @see Mapper#createMany + * @since 3.0.0 + */ - optsCopy.raw = false; - relations.push(def); - tasks.push(def.createParentRecord(props, optsCopy)); - }); - return utils.Promise.all(tasks).then(function (records) { - return relations.reduce(function (map, relation, index) { - relation.setLocalField(map, records[index]); - return map; - }, {}); - }); - }, + /** + * Given an array of records, batch create them via an adapter. + * + * {@link Mapper#beforeCreateMany} will be called before calling the adapter. + * {@link Mapper#afterCreateMany} will be called after calling the adapter. + * + * @example + * // Create and save several new blog posts + * PostMapper.createMany([{ + * title: 'Modeling your data', + * status: 'draft' + * }, { + * title: 'Reading data', + * status: 'draft' + * }]).then((posts) => { + * console.log(posts[0]); // { id: 1234, status: 'draft', ... } + * console.log(posts[1]); // { id: 1235, status: 'draft', ... } + * }); + * + * @fires Mapper#beforeCreate + * @fires Mapper#afterCreate + * @method Mapper#createMany + * @param {Record[]} records Array of records to be created in one batch. + * @param {object} [opts] Configuration options. Refer to the `createMany` + * method of whatever adapter you're using for more configuration options. + * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the + * adapter to use. + * @param {boolean} [opts.noValidate={@link Mapper#noValidate}] See {@link Mapper#noValidate}. + * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}. + * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}. + * @param {string[]} [opts.with=[]] Relations to create in a cascading + * create if `records` contains nested relations. NOT performed in a + * transaction. Each nested create will result in another {@link Mapper#createMany} + * call. + * @param {string[]} [opts.pass=[]] Relations to send to the adapter as part + * of the payload. Normally relations are not sent. + * @returns {Promise} Resolves with the created records. + * @since 3.0.0 + * @tutorial ["http://www.js-data.io/v3.0/docs/saving-data","Saving data"] + */ + + }, { + key: "createMany", + value: function createMany() { + var _this5 = this; + + var records = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + // Default values for arguments + var originalRecords = records; + var adapterResponse; // Fill in "opts" with the Mapper's configuration + + utils._(opts, this); + + opts.adapter = this.getAdapterName(opts); // beforeCreateMany lifecycle hook + + opts.op = 'beforeCreateMany'; + return this._runHook(opts.op, records, opts).then(function (records) { + // Deep pre-create belongsTo relations + var belongsToRelationData = {}; + opts["with"] = opts["with"] || []; + var tasks = []; + utils.forEachRelation(_this5, opts, function (def, optsCopy) { + var relationData = records.map(function (record) { + return def.getLocalField(record); + }).filter(Boolean); + + if (def.type === belongsToType && relationData.length === records.length) { + // Create belongsTo relation first because we need a generated id to + // attach to the child + optsCopy.raw = false; + tasks.push(def.createLinked(relationData, optsCopy).then(function (relatedRecords) { + records.forEach(function (record, i) { + return def.setForeignKey(record, relatedRecords[i]); + }); + }).then(function (relatedRecords) { + def.setLocalField(belongsToRelationData, relatedRecords); + })); + } + }); + return Promise.all(tasks).then(function () { + opts.op = 'createMany'; + return _this5._invokeAdapterMethod(opts.op, records, opts); + }).then(function (result) { + adapterResponse = result; + }).then(function () { + var createdRecordsData = opts.raw ? adapterResponse.data : adapterResponse; // Deep post-create hasOne relations + + tasks = []; + utils.forEachRelation(_this5, opts, function (def, optsCopy) { + var relationData = records.map(function (record) { + return def.getLocalField(record); + }).filter(Boolean); + + if (relationData.length !== records.length) { + return; + } + + optsCopy.raw = false; + var belongsToData = def.getLocalField(belongsToRelationData); + var task; // Create hasMany and hasOne after the main create because we needed + // a generated id to attach to these items + + if (def.type === hasManyType) { + // Not supported + _this5.log('warn', 'deep createMany of hasMany type not supported!'); + } else if (def.type === hasOneType) { + createdRecordsData.forEach(function (createdRecordData, i) { + def.setForeignKey(createdRecordData, relationData[i]); + }); + task = def.getRelation().createMany(relationData, optsCopy).then(function (relatedData) { + createdRecordsData.forEach(function (createdRecordData, i) { + def.setLocalField(createdRecordData, relatedData[i]); + }); + }); + } else if (def.type === belongsToType && belongsToData && belongsToData.length === createdRecordsData.length) { + createdRecordsData.forEach(function (createdRecordData, i) { + def.setLocalField(createdRecordData, belongsToData[i]); + }); + } + + if (task) { + tasks.push(task); + } + }); + return Promise.all(tasks).then(function () { + return _this5._commitChanges(originalRecords, createdRecordsData); + }); + }); + }).then(function (records) { + if (opts.raw) { + adapterResponse.data = records; + } else { + adapterResponse = records; + } + + var result = _this5._end(adapterResponse, opts); + + opts.op = 'afterCreateMany'; + return _this5._runHook(opts.op, records, opts, result); + }); + } + /** + * Create an unsaved, uncached instance of this Mapper's + * {@link Mapper#recordClass}. + * + * Returns `props` if `props` is already an instance of + * {@link Mapper#recordClass}. + * + * __Note:__ This method does __not__ interact with any adapter, and does + * __not__ save any data. It only creates new objects in memory. + * + * @example + * // Create empty unsaved record instance + * const post = PostMapper.createRecord(); + * + * @example + * // Create an unsaved record instance with inital properties + * const post = PostMapper.createRecord({ + * title: 'Modeling your data', + * status: 'draft' + * }); + * + * @example + * // Create a record instance that corresponds to a saved record + * const post = PostMapper.createRecord({ + * // JSData thinks this record has been saved if it has a primary key + * id: 1234, + * title: 'Modeling your data', + * status: 'draft' + * }); + * + * @example + * // Create record instances from an array + * const posts = PostMapper.createRecord([{ + * title: 'Modeling your data', + * status: 'draft' + * }, { + * title: 'Reading data', + * status: 'draft' + * }]); + * + * @example + * // Records are validated by default + * import { Mapper } from 'js-data'; + * const PostMapper = new Mapper({ + * name: 'post', + * schema: { properties: { title: { type: 'string' } } } + * }); + * try { + * const post = PostMapper.createRecord({ + * title: 1234, + * }); + * } catch (err) { + * console.log(err.errors); // [{ expected: 'one of (string)', actual: 'number', path: 'title' }] + * } + * + * @example + * // Skip validation + * import { Mapper } from 'js-data'; + * const PostMapper = new Mapper({ + * name: 'post', + * schema: { properties: { title: { type: 'string' } } } + * }); + * const post = PostMapper.createRecord({ + * title: 1234, + * }, { noValidate: true }); + * console.log(post.isValid()); // false + * + * @method Mapper#createRecord + * @param {Object|Object[]} props The properties for the Record instance or an + * array of property objects for the Record instances. + * @param {object} [opts] Configuration options. + * @param {boolean} [opts.noValidate={@link Mapper#noValidate}] See {@link Mapper#noValidate}. + * @returns {Record|Record[]} The Record instance or Record instances. + * @since 3.0.0 + */ + + }, { + key: "createRecord", + value: function createRecord() { + var _this6 = this; + + var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + var opts = arguments.length > 1 ? arguments[1] : undefined; + + if (utils.isArray(props)) { + return props.map(function (_props) { + return _this6.createRecord(_props, opts); + }); + } - /** - * Creates child record for relation types like HasOne or HasMany with foreignKey - * in order to satisfy foreignKey dependency (so called parent records). - * @param {object} props See {@link Mapper#create}. - * @param {object} context contains collected information. - * @param {object} context.opts See {@link Mapper#create}. - * @param {object} context.parentRelationMap contains parent records map - * @param {object} context.originalProps contains data passed into {@link Mapper#create} method - * @return {Promise} updated props - * @see Mapper#create - * @since 3.0.0 - */ - _createOrAssignChildRecordIfRequired: function _createOrAssignChildRecordIfRequired(props, context) { - var tasks = []; - utils.forEachRelation(this, context.opts, function (def, optsCopy) { - var relationData = def.getLocalField(context.originalProps); + if (!utils.isObject(props)) { + throw utils.err("".concat(DOMAIN$6, "#createRecord"), 'props')(400, 'array or object', props); + } - if (!relationData) { - return; + if (this.relationList) { + this.relationList.forEach(function (def) { + def.ensureLinkedDataHasProperType(props, opts); + }); } - optsCopy.raw = false; // Create hasMany and hasOne after the main create because we needed - // a generated id to attach to these items + var RecordCtor = this.recordClass; + var result = !RecordCtor || props instanceof RecordCtor ? props : new RecordCtor(props, opts); + return result; // Record.mapper = this; + // return new Record(props); + } + /** + * Lifecycle invocation method. You probably won't call this method directly. + * + * @method Mapper#crud + * @param {string} method Name of the lifecycle method to invoke. + * @param {...*} args Arguments to pass to the lifecycle method. + * @returns {Promise} + * @since 3.0.0 + */ - if (def.isRequiresChildId()) { - tasks.push(def.createChildRecord(props, relationData, optsCopy)); - } else if (def.isRequiresParentId()) { - var parent = def.getLocalField(context.parentRelationMap); + }, { + key: "crud", + value: function crud(method) { + var _this7 = this; - if (parent) { - def.setLocalField(props, parent); - } + for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { + args[_key2 - 1] = arguments[_key2]; } - }); - return utils.Promise.all(tasks).then(function () { - return props; - }); - }, - /** - * Fired during {@link Mapper#createMany}. See - * {@link Mapper~beforeCreateManyListener} for how to listen for this event. - * - * @event Mapper#beforeCreateMany - * @see Mapper~beforeCreateManyListener - * @see Mapper#createMany - */ + var config = this.lifecycleMethods[method]; - /** - * Callback signature for the {@link Mapper#event:beforeCreateMany} event. - * - * @example - * function onBeforeCreateMany (records, opts) { - * // do something - * } - * store.on('beforeCreateMany', onBeforeCreateMany); - * - * @callback Mapper~beforeCreateManyListener - * @param {object} records The `records` argument received by {@link Mapper#beforeCreateMany}. - * @param {object} opts The `opts` argument received by {@link Mapper#beforeCreateMany}. - * @see Mapper#event:beforeCreateMany - * @see Mapper#createMany - * @since 3.0.0 - */ + if (!config) { + throw utils.err("".concat(DOMAIN$6, "#crud"), method)(404, 'method'); + } - /** - * Fired during {@link Mapper#createMany}. See - * {@link Mapper~afterCreateManyListener} for how to listen for this event. - * - * @event Mapper#afterCreateMany - * @see Mapper~afterCreateManyListener - * @see Mapper#createMany - */ + var upper = "".concat(method.charAt(0).toUpperCase()).concat(method.substr(1)); + var before = "before".concat(upper); + var after = "after".concat(upper); + var op; // Default values for arguments - /** - * Callback signature for the {@link Mapper#event:afterCreateMany} event. - * - * @example - * function onAfterCreateMany (records, opts, result) { - * // do something - * } - * store.on('afterCreateMany', onAfterCreateMany); - * - * @callback Mapper~afterCreateManyListener - * @param {object} records The `records` argument received by {@link Mapper#afterCreateMany}. - * @param {object} opts The `opts` argument received by {@link Mapper#afterCreateMany}. - * @param {object} result The `result` argument received by {@link Mapper#afterCreateMany}. - * @see Mapper#event:afterCreateMany - * @see Mapper#createMany - * @since 3.0.0 - */ + config.defaults.forEach(function (value, i) { + if (args[i] === undefined) { + args[i] = utils.copy(value); + } + }); + var opts = args[args.length - 1]; // Fill in "opts" with the Mapper's configuration - /** - * Given an array of records, batch create them via an adapter. - * - * {@link Mapper#beforeCreateMany} will be called before calling the adapter. - * {@link Mapper#afterCreateMany} will be called after calling the adapter. - * - * @example - * // Create and save several new blog posts - * PostMapper.createMany([{ - * title: 'Modeling your data', - * status: 'draft' - * }, { - * title: 'Reading data', - * status: 'draft' - * }]).then((posts) => { - * console.log(posts[0]); // { id: 1234, status: 'draft', ... } - * console.log(posts[1]); // { id: 1235, status: 'draft', ... } - * }); - * - * @fires Mapper#beforeCreate - * @fires Mapper#afterCreate - * @method Mapper#createMany - * @param {Record[]} records Array of records to be created in one batch. - * @param {object} [opts] Configuration options. Refer to the `createMany` - * method of whatever adapter you're using for more configuration options. - * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the - * adapter to use. - * @param {boolean} [opts.noValidate={@link Mapper#noValidate}] See {@link Mapper#noValidate}. - * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}. - * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}. - * @param {string[]} [opts.with=[]] Relations to create in a cascading - * create if `records` contains nested relations. NOT performed in a - * transaction. Each nested create will result in another {@link Mapper#createMany} - * call. - * @param {string[]} [opts.pass=[]] Relations to send to the adapter as part - * of the payload. Normally relations are not sent. - * @returns {Promise} Resolves with the created records. - * @since 3.0.0 - * @tutorial ["http://www.js-data.io/v3.0/docs/saving-data","Saving data"] - */ - createMany: function createMany(records, opts) { - var _this4 = this; + utils._(opts, this); - // Default values for arguments - records || (records = []); - opts || (opts = {}); - var originalRecords = records; - var adapterResponse; // Fill in "opts" with the Mapper's configuration + var adapter = opts.adapter = this.getAdapterName(opts); // before lifecycle hook - utils._(opts, this); + op = opts.op = before; + return utils.resolve(this[op].apply(this, _toConsumableArray(args))).then(function (_value) { + var _this7$getAdapter; - opts.adapter = this.getAdapterName(opts); // beforeCreateMany lifecycle hook + if (args[config.beforeAssign] !== undefined) { + // Allow for re-assignment from lifecycle hook + args[config.beforeAssign] = _value === undefined ? args[config.beforeAssign] : _value; + } // Now delegate to the adapter - opts.op = 'beforeCreateMany'; - return this._runHook(opts.op, records, opts).then(function (records) { - // Deep pre-create belongsTo relations - var belongsToRelationData = {}; - opts.with || (opts.with = []); - var tasks = []; - utils.forEachRelation(_this4, opts, function (def, optsCopy) { - var relationData = records.map(function (record) { - return def.getLocalField(record); - }).filter(Boolean); - - if (def.type === belongsToType && relationData.length === records.length) { - // Create belongsTo relation first because we need a generated id to - // attach to the child - optsCopy.raw = false; - tasks.push(def.createLinked(relationData, optsCopy).then(function (relatedRecords) { - records.forEach(function (record, i) { - return def.setForeignKey(record, relatedRecords[i]); - }); - }).then(function (relatedRecords) { - def.setLocalField(belongsToRelationData, relatedRecords); - })); - } - }); - return utils.Promise.all(tasks).then(function () { - opts.op = 'createMany'; - return _this4._invokeAdapterMethod(opts.op, records, opts); - }).then(function (result) { - adapterResponse = result; - }).then(function () { - var createdRecordsData = opts.raw ? adapterResponse.data : adapterResponse; // Deep post-create hasOne relations - tasks = []; - utils.forEachRelation(_this4, opts, function (def, optsCopy) { - var relationData = records.map(function (record) { - return def.getLocalField(record); - }).filter(Boolean); + op = opts.op = method; + args = config.adapterArgs ? config.adapterArgs.apply(config, [_this7].concat(_toConsumableArray(args))) : args; - if (relationData.length !== records.length) { - return; - } + _this7.dbg.apply(_this7, [op].concat(_toConsumableArray(args))); - optsCopy.raw = false; - var belongsToData = def.getLocalField(belongsToRelationData); - var task; // Create hasMany and hasOne after the main create because we needed - // a generated id to attach to these items - - if (def.type === hasManyType) { - // Not supported - _this4.log('warn', 'deep createMany of hasMany type not supported!'); - } else if (def.type === hasOneType) { - createdRecordsData.forEach(function (createdRecordData, i) { - def.setForeignKey(createdRecordData, relationData[i]); - }); - task = def.getRelation().createMany(relationData, optsCopy).then(function (relatedData) { - createdRecordsData.forEach(function (createdRecordData, i) { - def.setLocalField(createdRecordData, relatedData[i]); - }); - }); - } else if (def.type === belongsToType && belongsToData && belongsToData.length === createdRecordsData.length) { - createdRecordsData.forEach(function (createdRecordData, i) { - def.setLocalField(createdRecordData, belongsToData[i]); - }); - } + return utils.resolve((_this7$getAdapter = _this7.getAdapter(adapter))[op].apply(_this7$getAdapter, [_this7].concat(_toConsumableArray(args)))); + }).then(function (result) { + // force noValidate on find/findAll + var noValidate = /find/.test(op) || opts.noValidate; - if (task) { - tasks.push(task); - } + var _opts = Object.assign({}, opts, { + noValidate: noValidate }); - return utils.Promise.all(tasks).then(function () { - return _this4._commitChanges(originalRecords, createdRecordsData); + + result = _this7._end(result, _opts, !!config.skip); + args.push(result); // after lifecycle hook + + op = opts.op = after; + return utils.resolve(_this7[op].apply(_this7, _toConsumableArray(args))).then(function (_result) { + // Allow for re-assignment from lifecycle hook + return _result === undefined ? result : _result; }); }); - }).then(function (records) { - if (opts.raw) { - adapterResponse.data = records; - } else { - adapterResponse = records; - } - - var result = _this4._end(adapterResponse, opts); + } + /** + * Fired during {@link Mapper#destroy}. See + * {@link Mapper~beforeDestroyListener} for how to listen for this event. + * + * @event Mapper#beforeDestroy + * @see Mapper~beforeDestroyListener + * @see Mapper#destroy + */ - opts.op = 'afterCreateMany'; - return _this4._runHook(opts.op, records, opts, result); - }); - }, + /** + * Callback signature for the {@link Mapper#event:beforeDestroy} event. + * + * @example + * function onBeforeDestroy (id, opts) { + * // do something + * } + * store.on('beforeDestroy', onBeforeDestroy); + * + * @callback Mapper~beforeDestroyListener + * @param {string|number} id The `id` argument passed to {@link Mapper#beforeDestroy}. + * @param {object} opts The `opts` argument passed to {@link Mapper#beforeDestroy}. + * @see Mapper#event:beforeDestroy + * @see Mapper#destroy + * @since 3.0.0 + */ - /** - * Create an unsaved, uncached instance of this Mapper's - * {@link Mapper#recordClass}. - * - * Returns `props` if `props` is already an instance of - * {@link Mapper#recordClass}. - * - * __Note:__ This method does __not__ interact with any adapter, and does - * __not__ save any data. It only creates new objects in memory. - * - * @example - * // Create empty unsaved record instance - * const post = PostMapper.createRecord(); - * - * @example - * // Create an unsaved record instance with inital properties - * const post = PostMapper.createRecord({ - * title: 'Modeling your data', - * status: 'draft' - * }); - * - * @example - * // Create a record instance that corresponds to a saved record - * const post = PostMapper.createRecord({ - * // JSData thinks this record has been saved if it has a primary key - * id: 1234, - * title: 'Modeling your data', - * status: 'draft' - * }); - * - * @example - * // Create record instances from an array - * const posts = PostMapper.createRecord([{ - * title: 'Modeling your data', - * status: 'draft' - * }, { - * title: 'Reading data', - * status: 'draft' - * }]); - * - * @example - * // Records are validated by default - * import { Mapper } from 'js-data'; - * const PostMapper = new Mapper({ - * name: 'post', - * schema: { properties: { title: { type: 'string' } } } - * }); - * try { - * const post = PostMapper.createRecord({ - * title: 1234, - * }); - * } catch (err) { - * console.log(err.errors); // [{ expected: 'one of (string)', actual: 'number', path: 'title' }] - * } - * - * @example - * // Skip validation - * import { Mapper } from 'js-data'; - * const PostMapper = new Mapper({ - * name: 'post', - * schema: { properties: { title: { type: 'string' } } } - * }); - * const post = PostMapper.createRecord({ - * title: 1234, - * }, { noValidate: true }); - * console.log(post.isValid()); // false - * - * @method Mapper#createRecord - * @param {Object|Object[]} props The properties for the Record instance or an - * array of property objects for the Record instances. - * @param {object} [opts] Configuration options. - * @param {boolean} [opts.noValidate={@link Mapper#noValidate}] See {@link Mapper#noValidate}. - * @returns {Record|Record[]} The Record instance or Record instances. - * @since 3.0.0 - */ - createRecord: function createRecord(props, opts) { - var _this5 = this; + /** + * Fired during {@link Mapper#destroy}. See + * {@link Mapper~afterDestroyListener} for how to listen for this event. + * + * @event Mapper#afterDestroy + * @see Mapper~afterDestroyListener + * @see Mapper#destroy + */ - props || (props = {}); + /** + * Callback signature for the {@link Mapper#event:afterDestroy} event. + * + * @example + * function onAfterDestroy (id, opts, result) { + * // do something + * } + * store.on('afterDestroy', onAfterDestroy); + * + * @callback Mapper~afterDestroyListener + * @param {string|number} id The `id` argument passed to {@link Mapper#afterDestroy}. + * @param {object} opts The `opts` argument passed to {@link Mapper#afterDestroy}. + * @param {object} result The `result` argument passed to {@link Mapper#afterDestroy}. + * @see Mapper#event:afterDestroy + * @see Mapper#destroy + * @since 3.0.0 + */ - if (utils.isArray(props)) { - return props.map(function (_props) { - return _this5.createRecord(_props, opts); - }); - } + /** + * Using an adapter, destroy the record with the given primary key. + * + * {@link Mapper#beforeDestroy} will be called before destroying the record. + * {@link Mapper#afterDestroy} will be called after destroying the record. + * + * @example + * // Destroy a specific blog post + * PostMapper.destroy(1234).then(() => { + * // Blog post #1234 has been destroyed + * }); + * + * @example + * // Get full response + * PostMapper.destroy(1234, { raw: true }).then((result) => { + * console.log(result.deleted); e.g. 1 + * console.log(...); // etc., more metadata can be found on the result + * }); + * + * @fires Mapper#beforeDestroy + * @fires Mapper#afterDestroy + * @method Mapper#destroy + * @param {(string|number)} id The primary key of the record to destroy. + * @param {object} [opts] Configuration options. Refer to the `destroy` method + * of whatever adapter you're using for more configuration options. + * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the + * adapter to use. + * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}. + * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}. + * @returns {Promise} Resolves when the record has been destroyed. Resolves + * even if no record was found to be destroyed. + * @since 3.0.0 + * @tutorial ["http://www.js-data.io/v3.0/docs/saving-data","Saving data"] + */ - if (!utils.isObject(props)) { - throw utils.err("".concat(DOMAIN$6, "#createRecord"), 'props')(400, 'array or object', props); - } + }, { + key: "destroy", + value: function destroy(id, opts) { + return this.crud('destroy', id, opts); + } + /** + * Fired during {@link Mapper#destroyAll}. See + * {@link Mapper~beforeDestroyAllListener} for how to listen for this event. + * + * @event Mapper#beforeDestroyAll + * @see Mapper~beforeDestroyAllListener + * @see Mapper#destroyAll + */ - if (this.relationList) { - this.relationList.forEach(function (def) { - def.ensureLinkedDataHasProperType(props, opts); - }); - } + /** + * Callback signature for the {@link Mapper#event:beforeDestroyAll} event. + * + * @example + * function onBeforeDestroyAll (query, opts) { + * // do something + * } + * store.on('beforeDestroyAll', onBeforeDestroyAll); + * + * @callback Mapper~beforeDestroyAllListener + * @param {object} query The `query` argument passed to {@link Mapper#beforeDestroyAll}. + * @param {object} opts The `opts` argument passed to {@link Mapper#beforeDestroyAll}. + * @see Mapper#event:beforeDestroyAll + * @see Mapper#destroyAll + * @since 3.0.0 + */ - var RecordCtor = this.recordClass; - return !RecordCtor || props instanceof RecordCtor ? props : new RecordCtor(props, opts); - }, + /** + * Fired during {@link Mapper#destroyAll}. See + * {@link Mapper~afterDestroyAllListener} for how to listen for this event. + * + * @event Mapper#afterDestroyAll + * @see Mapper~afterDestroyAllListener + * @see Mapper#destroyAll + */ - /** - * Lifecycle invocation method. You probably won't call this method directly. - * - * @method Mapper#crud - * @param {string} method Name of the lifecycle method to invoke. - * @param {...*} args Arguments to pass to the lifecycle method. - * @returns {Promise} - * @since 3.0.0 - */ - crud: function crud(method) { - var _this6 = this; + /** + * Callback signature for the {@link Mapper#event:afterDestroyAll} event. + * + * @example + * function onAfterDestroyAll (query, opts, result) { + * // do something + * } + * store.on('afterDestroyAll', onAfterDestroyAll); + * + * @callback Mapper~afterDestroyAllListener + * @param {object} query The `query` argument passed to {@link Mapper#afterDestroyAll}. + * @param {object} opts The `opts` argument passed to {@link Mapper#afterDestroyAll}. + * @param {object} result The `result` argument passed to {@link Mapper#afterDestroyAll}. + * @see Mapper#event:afterDestroyAll + * @see Mapper#destroyAll + * @since 3.0.0 + */ - for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { - args[_key2 - 1] = arguments[_key2]; - } + /** + * Destroy the records selected by `query` via an adapter. If no `query` is + * provided then all records will be destroyed. + * + * {@link Mapper#beforeDestroyAll} will be called before destroying the records. + * {@link Mapper#afterDestroyAll} will be called after destroying the records. + * + * @example + * // Destroy all blog posts + * PostMapper.destroyAll().then(() => { + * // All blog posts have been destroyed + * }); + * + * @example + * // Destroy all "draft" blog posts + * PostMapper.destroyAll({ status: 'draft' }).then(() => { + * // All "draft" blog posts have been destroyed + * }); + * + * @example + * // Get full response + * const query = null; + * const options = { raw: true }; + * PostMapper.destroyAll(query, options).then((result) => { + * console.log(result.deleted); e.g. 14 + * console.log(...); // etc., more metadata can be found on the result + * }); + * + * @fires Mapper#beforeDestroyAll + * @fires Mapper#afterDestroyAll + * @method Mapper#destroyAll + * @param {object} [query={}] Selection query. See {@link query}. + * @param {object} [query.where] See {@link query.where}. + * @param {number} [query.offset] See {@link query.offset}. + * @param {number} [query.limit] See {@link query.limit}. + * @param {string|Array[]} [query.orderBy] See {@link query.orderBy}. + * @param {object} [opts] Configuration options. Refer to the `destroyAll` + * method of whatever adapter you're using for more configuration options. + * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the + * adapter to use. + * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}. + * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}. + * @returns {Promise} Resolves when the records have been destroyed. Resolves + * even if no records were found to be destroyed. + * @see query + * @since 3.0.0 + * @tutorial ["http://www.js-data.io/v3.0/docs/saving-data","Saving data"] + */ - var config = this.lifecycleMethods[method]; + }, { + key: "destroyAll", + value: function destroyAll(query, opts) { + return this.crud('destroyAll', query, opts); + } + /** + * Fired during {@link Mapper#find}. See + * {@link Mapper~beforeFindListener} for how to listen for this event. + * + * @event Mapper#beforeFind + * @see Mapper~beforeFindListener + * @see Mapper#find + */ - if (!config) { - throw utils.err("".concat(DOMAIN$6, "#crud"), method)(404, 'method'); - } + /** + * Callback signature for the {@link Mapper#event:beforeFind} event. + * + * @example + * function onBeforeFind (id, opts) { + * // do something + * } + * store.on('beforeFind', onBeforeFind); + * + * @callback Mapper~beforeFindListener + * @param {string|number} id The `id` argument passed to {@link Mapper#beforeFind}. + * @param {object} opts The `opts` argument passed to {@link Mapper#beforeFind}. + * @see Mapper#event:beforeFind + * @see Mapper#find + * @since 3.0.0 + */ - var upper = "".concat(method.charAt(0).toUpperCase()).concat(method.substr(1)); - var before = "before".concat(upper); - var after = "after".concat(upper); - var op; // Default values for arguments + /** + * Fired during {@link Mapper#find}. See + * {@link Mapper~afterFindListener} for how to listen for this event. + * + * @event Mapper#afterFind + * @see Mapper~afterFindListener + * @see Mapper#find + */ - config.defaults.forEach(function (value, i) { - if (args[i] === undefined) { - args[i] = utils.copy(value); - } - }); - var opts = args[args.length - 1]; // Fill in "opts" with the Mapper's configuration + /** + * Callback signature for the {@link Mapper#event:afterFind} event. + * + * @example + * function onAfterFind (id, opts, result) { + * // do something + * } + * store.on('afterFind', onAfterFind); + * + * @callback Mapper~afterFindListener + * @param {string|number} id The `id` argument passed to {@link Mapper#afterFind}. + * @param {object} opts The `opts` argument passed to {@link Mapper#afterFind}. + * @param {object} result The `result` argument passed to {@link Mapper#afterFind}. + * @see Mapper#event:afterFind + * @see Mapper#find + * @since 3.0.0 + */ - utils._(opts, this); + /** + * Retrieve via an adapter the record with the given primary key. + * + * {@link Mapper#beforeFind} will be called before calling the adapter. + * {@link Mapper#afterFind} will be called after calling the adapter. + * + * @example + * PostMapper.find(1).then((post) => { + * console.log(post); // { id: 1, ...} + * }); + * + * @example + * // Get full response + * PostMapper.find(1, { raw: true }).then((result) => { + * console.log(result.data); // { id: 1, ...} + * console.log(result.found); // 1 + * console.log(...); // etc., more metadata can be found on the result + * }); + * + * @fires Mapper#beforeFind + * @fires Mapper#afterFind + * @method Mapper#find + * @param {(string|number)} id The primary key of the record to retrieve. + * @param {object} [opts] Configuration options. Refer to the `find` method + * of whatever adapter you're using for more configuration options. + * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the + * adapter to use. + * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}. + * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}. + * @param {string[]} [opts.with=[]] Relations to eager load in the request. + * @returns {Promise} Resolves with the found record. Resolves with + * `undefined` if no record was found. + * @see http://www.js-data.io/v3.0/docs/reading-data + * @since 3.0.0 + * @tutorial ["http://www.js-data.io/v3.0/docs/reading-data","Reading data"] + */ - var adapter = opts.adapter = this.getAdapterName(opts); // before lifecycle hook + }, { + key: "find", + value: function find(id, opts) { + return this.crud('find', id, opts); + } + /** + * Fired during {@link Mapper#findAll}. See + * {@link Mapper~beforeFindAllListener} for how to listen for this event. + * + * @event Mapper#beforeFindAll + * @see Mapper~beforeFindAllListener + * @see Mapper#findAll + */ - op = opts.op = before; - return utils.resolve(this[op].apply(this, _toConsumableArray(args))).then(function (_value) { - var _this6$getAdapter; + /** + * Callback signature for the {@link Mapper#event:beforeFindAll} event. + * + * @example + * function onBeforeFindAll (query, opts) { + * // do something + * } + * store.on('beforeFindAll', onBeforeFindAll); + * + * @callback Mapper~beforeFindAllListener + * @param {object} query The `query` argument passed to {@link Mapper#beforeFindAll}. + * @param {object} opts The `opts` argument passed to {@link Mapper#beforeFindAll}. + * @see Mapper#event:beforeFindAll + * @see Mapper#findAll + * @since 3.0.0 + */ - if (args[config.beforeAssign] !== undefined) { - // Allow for re-assignment from lifecycle hook - args[config.beforeAssign] = _value === undefined ? args[config.beforeAssign] : _value; - } // Now delegate to the adapter + /** + * Fired during {@link Mapper#findAll}. See + * {@link Mapper~afterFindAllListener} for how to listen for this event. + * + * @event Mapper#afterFindAll + * @see Mapper~afterFindAllListener + * @see Mapper#findAll + */ + /** + * Callback signature for the {@link Mapper#event:afterFindAll} event. + * + * @example + * function onAfterFindAll (query, opts, result) { + * // do something + * } + * store.on('afterFindAll', onAfterFindAll); + * + * @callback Mapper~afterFindAllListener + * @param {object} query The `query` argument passed to {@link Mapper#afterFindAll}. + * @param {object} opts The `opts` argument passed to {@link Mapper#afterFindAll}. + * @param {object} result The `result` argument passed to {@link Mapper#afterFindAll}. + * @see Mapper#event:afterFindAll + * @see Mapper#findAll + * @since 3.0.0 + */ - op = opts.op = method; - args = config.adapterArgs ? config.adapterArgs.apply(config, [_this6].concat(_toConsumableArray(args))) : args; + /** + * Using the `query` argument, select records to retrieve via an adapter. + * + * {@link Mapper#beforeFindAll} will be called before calling the adapter. + * {@link Mapper#afterFindAll} will be called after calling the adapter. + * + * @example + * // Find all "published" blog posts + * PostMapper.findAll({ status: 'published' }).then((posts) => { + * console.log(posts); // [{ id: 1, status: 'published', ...}, ...] + * }); + * + * @example + * // Get full response + * PostMapper.findAll({ status: 'published' }, { raw: true }).then((result) => { + * console.log(result.data); // [{ id: 1, status: 'published', ...}, ...] + * console.log(result.found); // e.g. 13 + * console.log(...); // etc., more metadata can be found on the result + * }); + * + * @fires Mapper#beforeFindAll + * @fires Mapper#afterFindAll + * @method Mapper#findAll + * @param {object} [query={}] Selection query. See {@link query}. + * @param {object} [query.where] See {@link query.where}. + * @param {number} [query.offset] See {@link query.offset}. + * @param {number} [query.limit] See {@link query.limit}. + * @param {string|Array[]} [query.orderBy] See {@link query.orderBy}. + * @param {object} [opts] Configuration options. Refer to the `findAll` method + * of whatever adapter you're using for more configuration options. + * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the + * adapter to use. + * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}. + * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}. + * @param {string[]} [opts.with=[]] Relations to eager load in the request. + * @returns {Promise} Resolves with the found records, if any. + * @see query + * @since 3.0.0 + * @tutorial ["http://www.js-data.io/v3.0/docs/reading-data","Reading data"] + */ - _this6.dbg.apply(_this6, [op].concat(_toConsumableArray(args))); + }, { + key: "findAll", + value: function findAll(query, opts) { + return this.crud('findAll', query, opts); + } + /** + * Return the registered adapter with the given name or the default adapter if + * no name is provided. + * + * @method Mapper#getAdapter + * @param {string} [name] The name of the adapter to retrieve. + * @returns {Adapter} The adapter. + * @since 3.0.0 + * @tutorial ["http://www.js-data.io/v3.0/docs/connecting-to-a-data-source","Connecting to a data source"] + */ - return utils.resolve((_this6$getAdapter = _this6.getAdapter(adapter))[op].apply(_this6$getAdapter, [_this6].concat(_toConsumableArray(args)))); - }).then(function (result) { - // force noValidate on find/findAll - var noValidate = /find/.test(op) || opts.noValidate; + }, { + key: "getAdapter", + value: function getAdapter(name) { + this.dbg('getAdapter', 'name:', name); + var adapter = this.getAdapterName(name); - var _opts = Object.assign({}, opts, { - noValidate: noValidate - }); + if (!adapter) { + throw utils.err("".concat(DOMAIN$6, "#getAdapter"), 'name')(400, 'string', name); + } - result = _this6._end(result, _opts, !!config.skip); - args.push(result); // after lifecycle hook + return this.getAdapters()[adapter]; + } + /** + * Return the name of a registered adapter based on the given name or options, + * or the name of the default adapter if no name provided. + * + * @method Mapper#getAdapterName + * @param {(Object|string)} [opts] The name of an adapter or options, if any. + * @returns {string} The name of the adapter. + * @since 3.0.0 + * @tutorial ["http://www.js-data.io/v3.0/docs/connecting-to-a-data-source","Connecting to a data source"] + */ - op = opts.op = after; - return utils.resolve(_this6[op].apply(_this6, _toConsumableArray(args))).then(function (_result) { - // Allow for re-assignment from lifecycle hook - return _result === undefined ? result : _result; - }); - }); - }, + }, { + key: "getAdapterName", + value: function getAdapterName() { + var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - /** - * Fired during {@link Mapper#destroy}. See - * {@link Mapper~beforeDestroyListener} for how to listen for this event. - * - * @event Mapper#beforeDestroy - * @see Mapper~beforeDestroyListener - * @see Mapper#destroy - */ + if (utils.isString(opts)) { + opts = { + adapter: opts + }; + } - /** - * Callback signature for the {@link Mapper#event:beforeDestroy} event. - * - * @example - * function onBeforeDestroy (id, opts) { - * // do something - * } - * store.on('beforeDestroy', onBeforeDestroy); - * - * @callback Mapper~beforeDestroyListener - * @param {string|number} id The `id` argument passed to {@link Mapper#beforeDestroy}. - * @param {object} opts The `opts` argument passed to {@link Mapper#beforeDestroy}. - * @see Mapper#event:beforeDestroy - * @see Mapper#destroy - * @since 3.0.0 - */ + return opts.adapter || opts.defaultAdapter; + } + /** + * Get the object of registered adapters for this Mapper. + * + * @method Mapper#getAdapters + * @returns {Object} {@link Mapper#_adapters} + * @since 3.0.0 + * @tutorial ["http://www.js-data.io/v3.0/docs/connecting-to-a-data-source","Connecting to a data source"] + */ - /** - * Fired during {@link Mapper#destroy}. See - * {@link Mapper~afterDestroyListener} for how to listen for this event. - * - * @event Mapper#afterDestroy - * @see Mapper~afterDestroyListener - * @see Mapper#destroy - */ + }, { + key: "getAdapters", + value: function getAdapters() { + return this._adapters; + } + /** + * Returns this Mapper's {@link Schema}. + * + * @method Mapper#getSchema + * @returns {Schema} This Mapper's {@link Schema}. + * @see Mapper#schema + * @since 3.0.0 + */ - /** - * Callback signature for the {@link Mapper#event:afterDestroy} event. - * - * @example - * function onAfterDestroy (id, opts, result) { - * // do something - * } - * store.on('afterDestroy', onAfterDestroy); - * - * @callback Mapper~afterDestroyListener - * @param {string|number} id The `id` argument passed to {@link Mapper#afterDestroy}. - * @param {object} opts The `opts` argument passed to {@link Mapper#afterDestroy}. - * @param {object} result The `result` argument passed to {@link Mapper#afterDestroy}. - * @see Mapper#event:afterDestroy - * @see Mapper#destroy - * @since 3.0.0 - */ + }, { + key: "getSchema", + value: function getSchema() { + return this.schema; + } + /** + * Defines a hasMany relationship. Only useful if you're managing your + * Mappers manually and not using a Container or DataStore component. + * + * @example + * UserMapper.hasMany(PostMapper, { + * // post.user_id points to user.id + * foreignKey: 'user_id' + * // post records will be attached to user records at "user.posts" + * localField: 'posts' + * }); + * + * @method Mapper#hasMany + * @see http://www.js-data.io/v3.0/docs/relations + * @since 3.0.0 + */ - /** - * Using an adapter, destroy the record with the given primary key. - * - * {@link Mapper#beforeDestroy} will be called before destroying the record. - * {@link Mapper#afterDestroy} will be called after destroying the record. - * - * @example - * // Destroy a specific blog post - * PostMapper.destroy(1234).then(() => { - * // Blog post #1234 has been destroyed - * }); - * - * @example - * // Get full response - * PostMapper.destroy(1234, { raw: true }).then((result) => { - * console.log(result.deleted); e.g. 1 - * console.log(...); // etc., more metadata can be found on the result - * }); - * - * @fires Mapper#beforeDestroy - * @fires Mapper#afterDestroy - * @method Mapper#destroy - * @param {(string|number)} id The primary key of the record to destroy. - * @param {object} [opts] Configuration options. Refer to the `destroy` method - * of whatever adapter you're using for more configuration options. - * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the - * adapter to use. - * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}. - * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}. - * @returns {Promise} Resolves when the record has been destroyed. Resolves - * even if no record was found to be destroyed. - * @since 3.0.0 - * @tutorial ["http://www.js-data.io/v3.0/docs/saving-data","Saving data"] - */ - destroy: function destroy(id, opts) { - return this.crud('destroy', id, opts); - }, + }, { + key: "hasMany", + value: function hasMany$1(relatedMapper, opts) { + return hasMany(relatedMapper, opts)(this); + } + /** + * Defines a hasOne relationship. Only useful if you're managing your Mappers + * manually and not using a {@link Container} or {@link DataStore} component. + * + * @example + * UserMapper.hasOne(ProfileMapper, { + * // profile.user_id points to user.id + * foreignKey: 'user_id' + * // profile records will be attached to user records at "user.profile" + * localField: 'profile' + * }); + * + * @method Mapper#hasOne + * @see http://www.js-data.io/v3.0/docs/relations + * @since 3.0.0 + */ - /** - * Fired during {@link Mapper#destroyAll}. See - * {@link Mapper~beforeDestroyAllListener} for how to listen for this event. - * - * @event Mapper#beforeDestroyAll - * @see Mapper~beforeDestroyAllListener - * @see Mapper#destroyAll - */ + }, { + key: "hasOne", + value: function hasOne$1(relatedMapper, opts) { + return hasOne(relatedMapper, opts)(this); + } + /** + * Return whether `record` is an instance of this Mapper's recordClass. + * + * @example + * const post = PostMapper.createRecord(); + * + * console.log(PostMapper.is(post)); // true + * // Equivalent to what's above + * console.log(post instanceof PostMapper.recordClass); // true + * + * @method Mapper#is + * @param {Object|Record} record The record to check. + * @returns {boolean} Whether `record` is an instance of this Mapper's + * {@link Mapper#recordClass}. + * @since 3.0.0 + */ - /** - * Callback signature for the {@link Mapper#event:beforeDestroyAll} event. - * - * @example - * function onBeforeDestroyAll (query, opts) { - * // do something - * } - * store.on('beforeDestroyAll', onBeforeDestroyAll); - * - * @callback Mapper~beforeDestroyAllListener - * @param {object} query The `query` argument passed to {@link Mapper#beforeDestroyAll}. - * @param {object} opts The `opts` argument passed to {@link Mapper#beforeDestroyAll}. - * @see Mapper#event:beforeDestroyAll - * @see Mapper#destroyAll - * @since 3.0.0 - */ + }, { + key: "is", + value: function is(record) { + var recordClass = this.recordClass; + return recordClass ? record instanceof recordClass : false; + } + /** + * Register an adapter on this Mapper under the given name. + * + * @method Mapper#registerAdapter + * @param {string} name The name of the adapter to register. + * @param {Adapter} adapter The adapter to register. + * @param {object} [opts] Configuration options. + * @param {boolean} [opts.default=false] Whether to make the adapter the + * default adapter for this Mapper. + * @since 3.0.0 + * @tutorial ["http://www.js-data.io/v3.0/docs/connecting-to-a-data-source","Connecting to a data source"] + */ - /** - * Fired during {@link Mapper#destroyAll}. See - * {@link Mapper~afterDestroyAllListener} for how to listen for this event. - * - * @event Mapper#afterDestroyAll - * @see Mapper~afterDestroyAllListener - * @see Mapper#destroyAll - */ + }, { + key: "registerAdapter", + value: function registerAdapter(name, adapter) { + var opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + this.getAdapters()[name] = adapter; // Optionally make it the default adapter for the target. - /** - * Callback signature for the {@link Mapper#event:afterDestroyAll} event. - * - * @example - * function onAfterDestroyAll (query, opts, result) { - * // do something - * } - * store.on('afterDestroyAll', onAfterDestroyAll); - * - * @callback Mapper~afterDestroyAllListener - * @param {object} query The `query` argument passed to {@link Mapper#afterDestroyAll}. - * @param {object} opts The `opts` argument passed to {@link Mapper#afterDestroyAll}. - * @param {object} result The `result` argument passed to {@link Mapper#afterDestroyAll}. - * @see Mapper#event:afterDestroyAll - * @see Mapper#destroyAll - * @since 3.0.0 - */ + if (opts === true || opts["default"]) { + this.defaultAdapter = name; + } + } + }, { + key: "_runHook", + value: function _runHook(hookName) { + for (var _len3 = arguments.length, hookArgs = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) { + hookArgs[_key3 - 1] = arguments[_key3]; + } - /** - * Destroy the records selected by `query` via an adapter. If no `query` is - * provided then all records will be destroyed. - * - * {@link Mapper#beforeDestroyAll} will be called before destroying the records. - * {@link Mapper#afterDestroyAll} will be called after destroying the records. - * - * @example - * // Destroy all blog posts - * PostMapper.destroyAll().then(() => { - * // All blog posts have been destroyed - * }); - * - * @example - * // Destroy all "draft" blog posts - * PostMapper.destroyAll({ status: 'draft' }).then(() => { - * // All "draft" blog posts have been destroyed - * }); - * - * @example - * // Get full response - * const query = null; - * const options = { raw: true }; - * PostMapper.destroyAll(query, options).then((result) => { - * console.log(result.deleted); e.g. 14 - * console.log(...); // etc., more metadata can be found on the result - * }); - * - * @fires Mapper#beforeDestroyAll - * @fires Mapper#afterDestroyAll - * @method Mapper#destroyAll - * @param {object} [query={}] Selection query. See {@link query}. - * @param {object} [query.where] See {@link query.where}. - * @param {number} [query.offset] See {@link query.offset}. - * @param {number} [query.limit] See {@link query.limit}. - * @param {string|Array[]} [query.orderBy] See {@link query.orderBy}. - * @param {object} [opts] Configuration options. Refer to the `destroyAll` - * method of whatever adapter you're using for more configuration options. - * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the - * adapter to use. - * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}. - * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}. - * @returns {Promise} Resolves when the records have been destroyed. Resolves - * even if no records were found to be destroyed. - * @see query - * @since 3.0.0 - * @tutorial ["http://www.js-data.io/v3.0/docs/saving-data","Saving data"] - */ - destroyAll: function destroyAll(query, opts) { - return this.crud('destroyAll', query, opts); - }, + var defaultValueIndex = hookName.indexOf('after') === 0 ? hookArgs.length - 1 : 0; + return utils.resolve(this[hookName].apply(this, hookArgs)).then(function (overridenResult) { + return overridenResult === undefined ? hookArgs[defaultValueIndex] : overridenResult; + }); + } + }, { + key: "_invokeAdapterMethod", + value: function _invokeAdapterMethod(method, propsOrRecords, opts) { + var _this8 = this; - /** - * Fired during {@link Mapper#find}. See - * {@link Mapper~beforeFindListener} for how to listen for this event. - * - * @event Mapper#beforeFind - * @see Mapper~beforeFindListener - * @see Mapper#find - */ + var conversionOptions = { + "with": opts.pass || [] + }; + var object; + this.dbg(opts.op, propsOrRecords, opts); - /** - * Callback signature for the {@link Mapper#event:beforeFind} event. - * - * @example - * function onBeforeFind (id, opts) { - * // do something - * } - * store.on('beforeFind', onBeforeFind); - * - * @callback Mapper~beforeFindListener - * @param {string|number} id The `id` argument passed to {@link Mapper#beforeFind}. - * @param {object} opts The `opts` argument passed to {@link Mapper#beforeFind}. - * @see Mapper#event:beforeFind - * @see Mapper#find - * @since 3.0.0 - */ + if (utils.isArray(propsOrRecords)) { + object = propsOrRecords.map(function (record) { + return _this8.toJSON(record, conversionOptions); + }); + } else { + object = this.toJSON(propsOrRecords, conversionOptions); + } - /** - * Fired during {@link Mapper#find}. See - * {@link Mapper~afterFindListener} for how to listen for this event. - * - * @event Mapper#afterFind - * @see Mapper~afterFindListener - * @see Mapper#find - */ + return this.getAdapter(opts.adapter)[method](this, object, opts); + } + /** + * Select records according to the `query` argument, and aggregate the sum + * value of the property specified by `field`. + * + * {@link Mapper#beforeSum} will be called before calling the adapter. + * {@link Mapper#afterSum} will be called after calling the adapter. + * + * @example + * PurchaseOrderMapper.sum('amount', { status: 'paid' }).then((amountPaid) => { + * console.log(amountPaid); // e.g. 451125.34 + * }); + * + * @method Mapper#sum + * @param {string} field The field to sum. + * @param {object} [query={}] Selection query. See {@link query}. + * @param {object} [query.where] See {@link query.where}. + * @param {number} [query.offset] See {@link query.offset}. + * @param {number} [query.limit] See {@link query.limit}. + * @param {string|Array[]} [query.orderBy] See {@link query.orderBy}. + * @param {object} [opts] Configuration options. Refer to the `sum` method + * of whatever adapter you're using for more configuration options. + * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the + * adapter to use. + * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}. + * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}. + * @returns {Promise} Resolves with the aggregated sum. + * @since 3.0.0 + */ - /** - * Callback signature for the {@link Mapper#event:afterFind} event. - * - * @example - * function onAfterFind (id, opts, result) { - * // do something - * } - * store.on('afterFind', onAfterFind); - * - * @callback Mapper~afterFindListener - * @param {string|number} id The `id` argument passed to {@link Mapper#afterFind}. - * @param {object} opts The `opts` argument passed to {@link Mapper#afterFind}. - * @param {object} result The `result` argument passed to {@link Mapper#afterFind}. - * @see Mapper#event:afterFind - * @see Mapper#find - * @since 3.0.0 - */ + }, { + key: "sum", + value: function sum(field, query, opts) { + return this.crud('sum', field, query, opts); + } + /** + * Return a plain object representation of the given record. Relations can + * be optionally be included. Non-schema properties can be excluded. + * + * @example + * import { Mapper, Schema } from 'js-data'; + * const PersonMapper = new Mapper({ + * name: 'person', + * schema: { + * properties: { + * name: { type: 'string' }, + * id: { type: 'string' } + * } + * } + * }); + * const person = PersonMapper.createRecord({ id: 1, name: 'John', foo: 'bar' }); + * // "foo" is stripped by toJSON() + * console.log(PersonMapper.toJSON(person)); // {"id":1,"name":"John"} + * + * const PersonRelaxedMapper = new Mapper({ + * name: 'personRelaxed', + * schema: { + * properties: { + * name: { type: 'string' }, + * id: { type: 'string' } + * }, + * additionalProperties: true + * } + * }); + * const person2 = PersonRelaxedMapper.createRecord({ id: 1, name: 'John', foo: 'bar' }); + * // "foo" is not stripped by toJSON + * console.log(PersonRelaxedMapper.toJSON(person2)); // {"id":1,"name":"John","foo":"bar"} + * + * @method Mapper#toJSON + * @param {Record|Record[]} records Record or records from which to create a + * POJO representation. + * @param {object} [opts] Configuration options. + * @param {string[]} [opts.with] Array of relation names or relation fields + * to include in the POJO representation. + * @param {boolean} [opts.withAll] Whether to simply include all relations in + * the representation. Overrides `opts.with`. + * @returns {Object|Object[]} POJO representation of the record or records. + * @since 3.0.0 + */ - /** - * Retrieve via an adapter the record with the given primary key. - * - * {@link Mapper#beforeFind} will be called before calling the adapter. - * {@link Mapper#afterFind} will be called after calling the adapter. - * - * @example - * PostMapper.find(1).then((post) => { - * console.log(post); // { id: 1, ...} - * }); - * - * @example - * // Get full response - * PostMapper.find(1, { raw: true }).then((result) => { - * console.log(result.data); // { id: 1, ...} - * console.log(result.found); // 1 - * console.log(...); // etc., more metadata can be found on the result - * }); - * - * @fires Mapper#beforeFind - * @fires Mapper#afterFind - * @method Mapper#find - * @param {(string|number)} id The primary key of the record to retrieve. - * @param {object} [opts] Configuration options. Refer to the `find` method - * of whatever adapter you're using for more configuration options. - * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the - * adapter to use. - * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}. - * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}. - * @param {string[]} [opts.with=[]] Relations to eager load in the request. - * @returns {Promise} Resolves with the found record. Resolves with - * `undefined` if no record was found. - * @see http://www.js-data.io/v3.0/docs/reading-data - * @since 3.0.0 - * @tutorial ["http://www.js-data.io/v3.0/docs/reading-data","Reading data"] - */ - find: function find(id, opts) { - return this.crud('find', id, opts); - }, + }, { + key: "toJSON", + value: function toJSON(records) { + var _this9 = this; - /** - * Fired during {@link Mapper#findAll}. See - * {@link Mapper~beforeFindAllListener} for how to listen for this event. - * - * @event Mapper#beforeFindAll - * @see Mapper~beforeFindAllListener - * @see Mapper#findAll - */ + var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var record; - /** - * Callback signature for the {@link Mapper#event:beforeFindAll} event. - * - * @example - * function onBeforeFindAll (query, opts) { - * // do something - * } - * store.on('beforeFindAll', onBeforeFindAll); - * - * @callback Mapper~beforeFindAllListener - * @param {object} query The `query` argument passed to {@link Mapper#beforeFindAll}. - * @param {object} opts The `opts` argument passed to {@link Mapper#beforeFindAll}. - * @see Mapper#event:beforeFindAll - * @see Mapper#findAll - * @since 3.0.0 - */ + if (utils.isArray(records)) { + return records.map(function (record) { + return _this9.toJSON(record, opts); + }); + } else { + record = records; + } - /** - * Fired during {@link Mapper#findAll}. See - * {@link Mapper~afterFindAllListener} for how to listen for this event. - * - * @event Mapper#afterFindAll - * @see Mapper~afterFindAllListener - * @see Mapper#findAll - */ + var relationFields = (this ? this.relationFields : []) || []; + var json = {}; // Copy properties defined in the schema - /** - * Callback signature for the {@link Mapper#event:afterFindAll} event. - * - * @example - * function onAfterFindAll (query, opts, result) { - * // do something - * } - * store.on('afterFindAll', onAfterFindAll); - * - * @callback Mapper~afterFindAllListener - * @param {object} query The `query` argument passed to {@link Mapper#afterFindAll}. - * @param {object} opts The `opts` argument passed to {@link Mapper#afterFindAll}. - * @param {object} result The `result` argument passed to {@link Mapper#afterFindAll}. - * @see Mapper#event:afterFindAll - * @see Mapper#findAll - * @since 3.0.0 - */ + if (this && this.schema) { + json = this.schema.pick(record); + } else { + for (var key in record) { + if (relationFields.indexOf(key) === -1) { + json[key] = utils.plainCopy(record[key]); + } + } + } // The user wants to include relations in the resulting plain object representation - /** - * Using the `query` argument, select records to retrieve via an adapter. - * - * {@link Mapper#beforeFindAll} will be called before calling the adapter. - * {@link Mapper#afterFindAll} will be called after calling the adapter. - * - * @example - * // Find all "published" blog posts - * PostMapper.findAll({ status: 'published' }).then((posts) => { - * console.log(posts); // [{ id: 1, status: 'published', ...}, ...] - * }); - * - * @example - * // Get full response - * PostMapper.findAll({ status: 'published' }, { raw: true }).then((result) => { - * console.log(result.data); // [{ id: 1, status: 'published', ...}, ...] - * console.log(result.found); // e.g. 13 - * console.log(...); // etc., more metadata can be found on the result - * }); - * - * @fires Mapper#beforeFindAll - * @fires Mapper#afterFindAll - * @method Mapper#findAll - * @param {object} [query={}] Selection query. See {@link query}. - * @param {object} [query.where] See {@link query.where}. - * @param {number} [query.offset] See {@link query.offset}. - * @param {number} [query.limit] See {@link query.limit}. - * @param {string|Array[]} [query.orderBy] See {@link query.orderBy}. - * @param {object} [opts] Configuration options. Refer to the `findAll` method - * of whatever adapter you're using for more configuration options. - * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the - * adapter to use. - * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}. - * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}. - * @param {string[]} [opts.with=[]] Relations to eager load in the request. - * @returns {Promise} Resolves with the found records, if any. - * @see query - * @since 3.0.0 - * @tutorial ["http://www.js-data.io/v3.0/docs/reading-data","Reading data"] - */ - findAll: function findAll(query, opts) { - return this.crud('findAll', query, opts); - }, - /** - * Return the registered adapter with the given name or the default adapter if - * no name is provided. - * - * @method Mapper#getAdapter - * @param {string} [name] The name of the adapter to retrieve. - * @returns {Adapter} The adapter. - * @since 3.0.0 - * @tutorial ["http://www.js-data.io/v3.0/docs/connecting-to-a-data-source","Connecting to a data source"] - */ - getAdapter: function getAdapter(name) { - this.dbg('getAdapter', 'name:', name); - var adapter = this.getAdapterName(name); + if (this && opts.withAll) { + opts["with"] = relationFields.slice(); + } - if (!adapter) { - throw utils.err("".concat(DOMAIN$6, "#getAdapter"), 'name')(400, 'string', name); - } + if (this && opts["with"]) { + if (utils.isString(opts["with"])) { + opts["with"] = [opts["with"]]; + } - return this.getAdapters()[adapter]; - }, + utils.forEachRelation(this, opts, function (def, optsCopy) { + var relationData = def.getLocalField(record); - /** - * Return the name of a registered adapter based on the given name or options, - * or the name of the default adapter if no name provided. - * - * @method Mapper#getAdapterName - * @param {(Object|string)} [opts] The name of an adapter or options, if any. - * @returns {string} The name of the adapter. - * @since 3.0.0 - * @tutorial ["http://www.js-data.io/v3.0/docs/connecting-to-a-data-source","Connecting to a data source"] - */ - getAdapterName: function getAdapterName(opts) { - opts || (opts = {}); + if (relationData) { + // The actual recursion + if (utils.isArray(relationData)) { + def.setLocalField(json, relationData.map(function (item) { + return def.getRelation().toJSON(item, optsCopy); + })); + } else { + def.setLocalField(json, def.getRelation().toJSON(relationData, optsCopy)); + } + } + }); + } - if (utils.isString(opts)) { - opts = { - adapter: opts - }; + return json; } + /** + * Fired during {@link Mapper#update}. See + * {@link Mapper~beforeUpdateListener} for how to listen for this event. + * + * @event Mapper#beforeUpdate + * @see Mapper~beforeUpdateListener + * @see Mapper#update + */ - return opts.adapter || opts.defaultAdapter; - }, - - /** - * Get the object of registered adapters for this Mapper. - * - * @method Mapper#getAdapters - * @returns {Object} {@link Mapper#_adapters} - * @since 3.0.0 - * @tutorial ["http://www.js-data.io/v3.0/docs/connecting-to-a-data-source","Connecting to a data source"] - */ - getAdapters: function getAdapters() { - return this._adapters; - }, + /** + * Callback signature for the {@link Mapper#event:beforeUpdate} event. + * + * @example + * function onBeforeUpdate (id, props, opts) { + * // do something + * } + * store.on('beforeUpdate', onBeforeUpdate); + * + * @callback Mapper~beforeUpdateListener + * @param {string|number} id The `id` argument passed to {@link Mapper#beforeUpdate}. + * @param {object} props The `props` argument passed to {@link Mapper#beforeUpdate}. + * @param {object} opts The `opts` argument passed to {@link Mapper#beforeUpdate}. + * @see Mapper#event:beforeUpdate + * @see Mapper#update + * @since 3.0.0 + */ - /** - * Returns this Mapper's {@link Schema}. - * - * @method Mapper#getSchema - * @returns {Schema} This Mapper's {@link Schema}. - * @see Mapper#schema - * @since 3.0.0 - */ - getSchema: function getSchema() { - return this.schema; - }, + /** + * Fired during {@link Mapper#update}. See + * {@link Mapper~afterUpdateListener} for how to listen for this event. + * + * @event Mapper#afterUpdate + * @see Mapper~afterUpdateListener + * @see Mapper#update + */ - /** - * Defines a hasMany relationship. Only useful if you're managing your - * Mappers manually and not using a Container or DataStore component. - * - * @example - * UserMapper.hasMany(PostMapper, { - * // post.user_id points to user.id - * foreignKey: 'user_id' - * // post records will be attached to user records at "user.posts" - * localField: 'posts' - * }); - * - * @method Mapper#hasMany - * @see http://www.js-data.io/v3.0/docs/relations - * @since 3.0.0 - */ - hasMany: function hasMany$1(relatedMapper, opts) { - return hasMany(relatedMapper, opts)(this); - }, + /** + * Callback signature for the {@link Mapper#event:afterUpdate} event. + * + * @example + * function onAfterUpdate (id, props, opts, result) { + * // do something + * } + * store.on('afterUpdate', onAfterUpdate); + * + * @callback Mapper~afterUpdateListener + * @param {string|number} id The `id` argument passed to {@link Mapper#afterUpdate}. + * @param {object} props The `props` argument passed to {@link Mapper#afterUpdate}. + * @param {object} opts The `opts` argument passed to {@link Mapper#afterUpdate}. + * @param {object} result The `result` argument passed to {@link Mapper#afterUpdate}. + * @see Mapper#event:afterUpdate + * @see Mapper#update + * @since 3.0.0 + */ - /** - * Defines a hasOne relationship. Only useful if you're managing your Mappers - * manually and not using a {@link Container} or {@link DataStore} component. - * - * @example - * UserMapper.hasOne(ProfileMapper, { - * // profile.user_id points to user.id - * foreignKey: 'user_id' - * // profile records will be attached to user records at "user.profile" - * localField: 'profile' - * }); - * - * @method Mapper#hasOne - * @see http://www.js-data.io/v3.0/docs/relations - * @since 3.0.0 - */ - hasOne: function hasOne$1(relatedMapper, opts) { - return hasOne(relatedMapper, opts)(this); - }, + /** + * Using an adapter, update the record with the primary key specified by the + * `id` argument. + * + * {@link Mapper#beforeUpdate} will be called before updating the record. + * {@link Mapper#afterUpdate} will be called after updating the record. + * + * @example + * // Update a specific post + * PostMapper.update(1234, { + * status: 'published', + * published_at: new Date() + * }).then((post) => { + * console.log(post); // { id: 1234, status: 'published', ... } + * }); + * + * @fires Mapper#beforeUpdate + * @fires Mapper#afterUpdate + * @method Mapper#update + * @param {(string|number)} id The primary key of the record to update. + * @param {object} props The update to apply to the record. + * @param {object} [opts] Configuration options. Refer to the `update` method + * of whatever adapter you're using for more configuration options. + * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the + * adapter to use. + * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}. + * @param {boolean} [opts.noValidate={@link Mapper#noValidate}] See {@link Mapper#noValidate}. + * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}. + * transaction. + * @returns {Promise} Resolves with the updated record. Rejects if the record + * could not be found. + * @since 3.0.0 + * @tutorial ["http://www.js-data.io/v3.0/docs/saving-data","Saving data"] + */ - /** - * Return whether `record` is an instance of this Mapper's recordClass. - * - * @example - * const post = PostMapper.createRecord(); - * - * console.log(PostMapper.is(post)); // true - * // Equivalent to what's above - * console.log(post instanceof PostMapper.recordClass); // true - * - * @method Mapper#is - * @param {Object|Record} record The record to check. - * @returns {boolean} Whether `record` is an instance of this Mapper's - * {@link Mapper#recordClass}. - * @since 3.0.0 - */ - is: function is(record) { - var recordClass = this.recordClass; - return recordClass ? record instanceof recordClass : false; - }, + }, { + key: "update", + value: function update(id, props, opts) { + return this.crud('update', id, props, opts); + } + /** + * Fired during {@link Mapper#updateAll}. See + * {@link Mapper~beforeUpdateAllListener} for how to listen for this event. + * + * @event Mapper#beforeUpdateAll + * @see Mapper~beforeUpdateAllListener + * @see Mapper#updateAll + */ - /** - * Register an adapter on this Mapper under the given name. - * - * @method Mapper#registerAdapter - * @param {string} name The name of the adapter to register. - * @param {Adapter} adapter The adapter to register. - * @param {object} [opts] Configuration options. - * @param {boolean} [opts.default=false] Whether to make the adapter the - * default adapter for this Mapper. - * @since 3.0.0 - * @tutorial ["http://www.js-data.io/v3.0/docs/connecting-to-a-data-source","Connecting to a data source"] - */ - registerAdapter: function registerAdapter(name, adapter, opts) { - opts || (opts = {}); - this.getAdapters()[name] = adapter; // Optionally make it the default adapter for the target. + /** + * Callback signature for the {@link Mapper#event:beforeUpdateAll} event. + * + * @example + * function onBeforeUpdateAll (props, query, opts) { + * // do something + * } + * store.on('beforeUpdateAll', onBeforeUpdateAll); + * + * @callback Mapper~beforeUpdateAllListener + * @param {object} props The `props` argument received by {@link Mapper#beforeUpdateAll}. + * @param {object} query The `query` argument received by {@link Mapper#beforeUpdateAll}. + * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdateAll}. + * @see Mapper#event:beforeUpdateAll + * @see Mapper#updateAll + * @since 3.0.0 + */ - if (opts === true || opts.default) { - this.defaultAdapter = name; - } - }, - _runHook: function _runHook(hookName) { - for (var _len3 = arguments.length, hookArgs = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) { - hookArgs[_key3 - 1] = arguments[_key3]; - } + /** + * Fired during {@link Mapper#updateAll}. See + * {@link Mapper~afterUpdateAllListener} for how to listen for this event. + * + * @event Mapper#afterUpdateAll + * @see Mapper~afterUpdateAllListener + * @see Mapper#updateAll + */ - var defaultValueIndex = hookName.indexOf('after') === 0 ? hookArgs.length - 1 : 0; - return utils.resolve(this[hookName].apply(this, hookArgs)).then(function (overridenResult) { - return overridenResult === undefined ? hookArgs[defaultValueIndex] : overridenResult; - }); - }, - _invokeAdapterMethod: function _invokeAdapterMethod(method, propsOrRecords, opts) { - var _this7 = this; + /** + * Callback signature for the {@link Mapper#event:afterUpdateAll} event. + * + * @example + * function onAfterUpdateAll (props, query, opts, result) { + * // do something + * } + * store.on('afterUpdateAll', onAfterUpdateAll); + * + * @callback Mapper~afterUpdateAllListener + * @param {object} props The `props` argument received by {@link Mapper#afterUpdateAll}. + * @param {object} query The `query` argument received by {@link Mapper#afterUpdateAll}. + * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdateAll}. + * @param {object} result The `result` argument received by {@link Mapper#afterUpdateAll}. + * @see Mapper#event:afterUpdateAll + * @see Mapper#updateAll + * @since 3.0.0 + */ - var conversionOptions = { - with: opts.pass || [] - }; - var object; - this.dbg(opts.op, propsOrRecords, opts); + /** + * Using the `query` argument, perform the a single updated to the selected + * records. + * + * {@link Mapper#beforeUpdateAll} will be called before making the update. + * {@link Mapper#afterUpdateAll} will be called after making the update. + * + * @example + * // Turn all of John's blog posts into drafts. + * const update = { status: draft: published_at: null }; + * const query = { userId: 1234 }; + * PostMapper.updateAll(update, query).then((posts) => { + * console.log(posts); // [...] + * }); + * + * @fires Mapper#beforeUpdateAll + * @fires Mapper#afterUpdateAll + * @method Mapper#updateAll + * @param {object} props Update to apply to selected records. + * @param {object} [query={}] Selection query. See {@link query}. + * @param {object} [query.where] See {@link query.where}. + * @param {number} [query.offset] See {@link query.offset}. + * @param {number} [query.limit] See {@link query.limit}. + * @param {string|Array[]} [query.orderBy] See {@link query.orderBy}. + * @param {object} [opts] Configuration options. Refer to the `updateAll` + * method of whatever adapter you're using for more configuration options. + * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the + * adapter to use. + * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}. + * @param {boolean} [opts.noValidate={@link Mapper#noValidate}] See {@link Mapper#noValidate}. + * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}. + * @returns {Promise} Resolves with the update records, if any. + * @see query + * @since 3.0.0 + * @tutorial ["http://www.js-data.io/v3.0/docs/saving-data","Saving data"] + */ - if (utils.isArray(propsOrRecords)) { - object = propsOrRecords.map(function (record) { - return _this7.toJSON(record, conversionOptions); - }); - } else { - object = this.toJSON(propsOrRecords, conversionOptions); - } + }, { + key: "updateAll", + value: function updateAll(props, query, opts) { + return this.crud('updateAll', props, query, opts); + } + /** + * Fired during {@link Mapper#updateMany}. See + * {@link Mapper~beforeUpdateManyListener} for how to listen for this event. + * + * @event Mapper#beforeUpdateMany + * @see Mapper~beforeUpdateManyListener + * @see Mapper#updateMany + */ - return this.getAdapter(opts.adapter)[method](this, object, opts); - }, + /** + * Callback signature for the {@link Mapper#event:beforeUpdateMany} event. + * + * @example + * function onBeforeUpdateMany (records, opts) { + * // do something + * } + * store.on('beforeUpdateMany', onBeforeUpdateMany); + * + * @callback Mapper~beforeUpdateManyListener + * @param {object} records The `records` argument received by {@link Mapper#beforeUpdateMany}. + * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdateMany}. + * @see Mapper#event:beforeUpdateMany + * @see Mapper#updateMany + * @since 3.0.0 + */ - /** - * Select records according to the `query` argument, and aggregate the sum - * value of the property specified by `field`. - * - * {@link Mapper#beforeSum} will be called before calling the adapter. - * {@link Mapper#afterSum} will be called after calling the adapter. - * - * @example - * PurchaseOrderMapper.sum('amount', { status: 'paid' }).then((amountPaid) => { - * console.log(amountPaid); // e.g. 451125.34 - * }); - * - * @method Mapper#sum - * @param {string} field The field to sum. - * @param {object} [query={}] Selection query. See {@link query}. - * @param {object} [query.where] See {@link query.where}. - * @param {number} [query.offset] See {@link query.offset}. - * @param {number} [query.limit] See {@link query.limit}. - * @param {string|Array[]} [query.orderBy] See {@link query.orderBy}. - * @param {object} [opts] Configuration options. Refer to the `sum` method - * of whatever adapter you're using for more configuration options. - * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the - * adapter to use. - * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}. - * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}. - * @returns {Promise} Resolves with the aggregated sum. - * @since 3.0.0 - */ - sum: function sum(field, query, opts) { - return this.crud('sum', field, query, opts); - }, + /** + * Fired during {@link Mapper#updateMany}. See + * {@link Mapper~afterUpdateManyListener} for how to listen for this event. + * + * @event Mapper#afterUpdateMany + * @see Mapper~afterUpdateManyListener + * @see Mapper#updateMany + */ - /** - * Return a plain object representation of the given record. Relations can - * be optionally be included. Non-schema properties can be excluded. - * - * @example - * import { Mapper, Schema } from 'js-data'; - * const PersonMapper = new Mapper({ - * name: 'person', - * schema: { - * properties: { - * name: { type: 'string' }, - * id: { type: 'string' } - * } - * } - * }); - * const person = PersonMapper.createRecord({ id: 1, name: 'John', foo: 'bar' }); - * // "foo" is stripped by toJSON() - * console.log(PersonMapper.toJSON(person)); // {"id":1,"name":"John"} - * - * const PersonRelaxedMapper = new Mapper({ - * name: 'personRelaxed', - * schema: { - * properties: { - * name: { type: 'string' }, - * id: { type: 'string' } - * }, - * additionalProperties: true - * } - * }); - * const person2 = PersonRelaxedMapper.createRecord({ id: 1, name: 'John', foo: 'bar' }); - * // "foo" is not stripped by toJSON - * console.log(PersonRelaxedMapper.toJSON(person2)); // {"id":1,"name":"John","foo":"bar"} - * - * @method Mapper#toJSON - * @param {Record|Record[]} records Record or records from which to create a - * POJO representation. - * @param {object} [opts] Configuration options. - * @param {string[]} [opts.with] Array of relation names or relation fields - * to include in the POJO representation. - * @param {boolean} [opts.withAll] Whether to simply include all relations in - * the representation. Overrides `opts.with`. - * @returns {Object|Object[]} POJO representation of the record or records. - * @since 3.0.0 - */ - toJSON: function toJSON(records, opts) { - var _this8 = this; + /** + * Callback signature for the {@link Mapper#event:afterUpdateMany} event. + * + * @example + * function onAfterUpdateMany (records, opts, result) { + * // do something + * } + * store.on('afterUpdateMany', onAfterUpdateMany); + * + * @callback Mapper~afterUpdateManyListener + * @param {object} records The `records` argument received by {@link Mapper#afterUpdateMany}. + * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdateMany}. + * @param {object} result The `result` argument received by {@link Mapper#afterUpdateMany}. + * @see Mapper#event:afterUpdateMany + * @see Mapper#updateMany + * @since 3.0.0 + */ - var record; - opts || (opts = {}); + /** + * Given an array of updates, perform each of the updates via an adapter. Each + * "update" is a hash of properties with which to update an record. Each + * update must contain the primary key of the record to be updated. + * + * {@link Mapper#beforeUpdateMany} will be called before making the update. + * {@link Mapper#afterUpdateMany} will be called after making the update. + * + * @example + * PostMapper.updateMany([ + * { id: 1234, status: 'draft' }, + * { id: 2468, status: 'published', published_at: new Date() } + * ]).then((posts) => { + * console.log(posts); // [...] + * }); + * + * @fires Mapper#beforeUpdateMany + * @fires Mapper#afterUpdateMany + * @method Mapper#updateMany + * @param {Record[]} records Array up record updates. + * @param {object} [opts] Configuration options. Refer to the `updateMany` + * method of whatever adapter you're using for more configuration options. + * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the + * adapter to use. + * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}. + * @param {boolean} [opts.noValidate={@link Mapper#noValidate}] See {@link Mapper#noValidate}. + * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}. + * @returns {Promise} Resolves with the updated records. Rejects if any of the + * records could be found. + * @since 3.0.0 + * @tutorial ["http://www.js-data.io/v3.0/docs/saving-data","Saving data"] + */ - if (utils.isArray(records)) { - return records.map(function (record) { - return _this8.toJSON(record, opts); - }); - } else { - record = records; - } + }, { + key: "updateMany", + value: function updateMany(records, opts) { + return this.crud('updateMany', records, opts); + } + /** + * Validate the given record or records according to this Mapper's + * {@link Schema}. If there are no validation errors then the return value + * will be `undefined`. + * + * @example + * import {Mapper, Schema} from 'js-data' + * const PersonSchema = new Schema({ + * properties: { + * name: { type: 'string' }, + * id: { type: 'string' } + * } + * }); + * const PersonMapper = new Mapper({ + * name: 'person', + * schema: PersonSchema + * }); + * let errors = PersonMapper.validate({ name: 'John' }); + * console.log(errors); // undefined + * errors = PersonMapper.validate({ name: 123 }); + * console.log(errors); // [{ expected: 'one of (string)', actual: 'number', path: 'name' }] + * + * @method Mapper#validate + * @param {Object|Object[]} record The record or records to validate. + * @param {object} [opts] Configuration options. Passed to + * {@link Schema#validate}. + * @returns {Object[]} Array of errors or `undefined` if no errors. + * @since 3.0.0 + */ - var relationFields = (this ? this.relationFields : []) || []; - var json = {}; // Copy properties defined in the schema + }, { + key: "validate", + value: function validate(record) { + var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var schema = this.getSchema(); - if (this && this.schema) { - json = this.schema.pick(record); - } else { - for (var key in record) { - if (relationFields.indexOf(key) === -1) { - json[key] = utils.plainCopy(record[key]); - } + if (!schema) { + return; } - } // The user wants to include relations in the resulting plain object representation - - if (this && opts.withAll) { - opts.with = relationFields.slice(); - } + var _opts = utils.pick(opts, ['existingOnly']); - if (this && opts.with) { - if (utils.isString(opts.with)) { - opts.with = [opts.with]; + if (utils.isArray(record)) { + var errors = record.map(function (_record) { + return schema.validate(_record, utils.pick(_opts, ['existingOnly'])); + }); + return errors.some(Boolean) ? errors : undefined; } - utils.forEachRelation(this, opts, function (def, optsCopy) { - var relationData = def.getLocalField(record); + return schema.validate(record, _opts); + } + /** + * Method used to wrap data returned by an adapter with this Mapper's + * {@link Mapper#recordClass}. This method is used by all of a Mapper's CRUD + * methods. The provided implementation of this method assumes that the `data` + * passed to it is a record or records that need to be wrapped with + * {@link Mapper#createRecord}. Override with care. + * + * Provided implementation of {@link Mapper#wrap}: + * + * ``` + * function (data, opts) { + * return this.createRecord(data, opts); + * } + * ``` + * + * @example + * const PostMapper = new Mapper({ + * name: 'post', + * // Override to customize behavior + * wrap (data, opts) { + * const originalWrap = this.constructor.prototype.wrap; + * // Let's say "GET /post" doesn't return JSON quite like JSData expects, + * // but the actual post records are nested under a "posts" field. So, + * // we override Mapper#wrap to handle this special case. + * if (opts.op === 'findAll') { + * return originalWrap.call(this, data.posts, opts); + * } + * // Otherwise perform original behavior + * return originalWrap.call(this, data, opts); + * } + * }); + * + * @method Mapper#wrap + * @param {Object|Object[]} data The record or records to be wrapped. + * @param {object} [opts] Configuration options. Passed to {@link Mapper#createRecord}. + * @returns {Record|Record[]} The wrapped record or records. + * @since 3.0.0 + */ - if (relationData) { - // The actual recursion - if (utils.isArray(relationData)) { - def.setLocalField(json, relationData.map(function (item) { - return def.getRelation().toJSON(item, optsCopy); - })); - } else { - def.setLocalField(json, def.getRelation().toJSON(relationData, optsCopy)); - } - } - }); + }, { + key: "wrap", + value: function wrap(data, opts) { + return this.createRecord(data, opts); } + /** + * @ignore + */ - return json; - }, - - /** - * Fired during {@link Mapper#update}. See - * {@link Mapper~beforeUpdateListener} for how to listen for this event. - * - * @event Mapper#beforeUpdate - * @see Mapper~beforeUpdateListener - * @see Mapper#update - */ + }, { + key: "defineRelations", + value: function defineRelations() { + var _this10 = this; + + // Setup the mapper's relations, including generating Mapper#relationList + // and Mapper#relationFields + utils.forOwn(this.relations, function (group, type) { + utils.forOwn(group, function (relations, _name) { + if (utils.isObject(relations)) { + relations = [relations]; + } - /** - * Callback signature for the {@link Mapper#event:beforeUpdate} event. - * - * @example - * function onBeforeUpdate (id, props, opts) { - * // do something - * } - * store.on('beforeUpdate', onBeforeUpdate); - * - * @callback Mapper~beforeUpdateListener - * @param {string|number} id The `id` argument passed to {@link Mapper#beforeUpdate}. - * @param {object} props The `props` argument passed to {@link Mapper#beforeUpdate}. - * @param {object} opts The `opts` argument passed to {@link Mapper#beforeUpdate}. - * @see Mapper#event:beforeUpdate - * @see Mapper#update - * @since 3.0.0 - */ + relations.forEach(function (def) { + var relatedMapper = _this10.datastore.getMapperByName(_name) || _name; - /** - * Fired during {@link Mapper#update}. See - * {@link Mapper~afterUpdateListener} for how to listen for this event. - * - * @event Mapper#afterUpdate - * @see Mapper~afterUpdateListener - * @see Mapper#update - */ + def.getRelation = function () { + return _this10.datastore.getMapper(_name); + }; - /** - * Callback signature for the {@link Mapper#event:afterUpdate} event. - * - * @example - * function onAfterUpdate (id, props, opts, result) { - * // do something - * } - * store.on('afterUpdate', onAfterUpdate); - * - * @callback Mapper~afterUpdateListener - * @param {string|number} id The `id` argument passed to {@link Mapper#afterUpdate}. - * @param {object} props The `props` argument passed to {@link Mapper#afterUpdate}. - * @param {object} opts The `opts` argument passed to {@link Mapper#afterUpdate}. - * @param {object} result The `result` argument passed to {@link Mapper#afterUpdate}. - * @see Mapper#event:afterUpdate - * @see Mapper#update - * @since 3.0.0 - */ + if (typeof Relation[type] !== 'function') { + throw utils.err(DOMAIN$6, 'defineRelations')(400, 'relation type (hasOne, hasMany, etc)', type, true); + } - /** - * Using an adapter, update the record with the primary key specified by the - * `id` argument. - * - * {@link Mapper#beforeUpdate} will be called before updating the record. - * {@link Mapper#afterUpdate} will be called after updating the record. - * - * @example - * // Update a specific post - * PostMapper.update(1234, { - * status: 'published', - * published_at: new Date() - * }).then((post) => { - * console.log(post); // { id: 1234, status: 'published', ... } - * }); - * - * @fires Mapper#beforeUpdate - * @fires Mapper#afterUpdate - * @method Mapper#update - * @param {(string|number)} id The primary key of the record to update. - * @param {object} props The update to apply to the record. - * @param {object} [opts] Configuration options. Refer to the `update` method - * of whatever adapter you're using for more configuration options. - * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the - * adapter to use. - * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}. - * @param {boolean} [opts.noValidate={@link Mapper#noValidate}] See {@link Mapper#noValidate}. - * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}. - * transaction. - * @returns {Promise} Resolves with the updated record. Rejects if the record - * could not be found. - * @since 3.0.0 - * @tutorial ["http://www.js-data.io/v3.0/docs/saving-data","Saving data"] - */ - update: function update(id, props, opts) { - return this.crud('update', id, props, opts); - }, + _this10[type](relatedMapper, def); + }); + }); + }); + } + }]); - /** - * Fired during {@link Mapper#updateAll}. See - * {@link Mapper~beforeUpdateAllListener} for how to listen for this event. - * - * @event Mapper#beforeUpdateAll - * @see Mapper~beforeUpdateAllListener - * @see Mapper#updateAll - */ + return Mapper; + }(Component); - /** - * Callback signature for the {@link Mapper#event:beforeUpdateAll} event. - * - * @example - * function onBeforeUpdateAll (props, query, opts) { - * // do something - * } - * store.on('beforeUpdateAll', onBeforeUpdateAll); - * - * @callback Mapper~beforeUpdateAllListener - * @param {object} props The `props` argument received by {@link Mapper#beforeUpdateAll}. - * @param {object} query The `query` argument received by {@link Mapper#beforeUpdateAll}. - * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdateAll}. - * @see Mapper#event:beforeUpdateAll - * @see Mapper#updateAll - * @since 3.0.0 - */ + var DOMAIN$7 = 'Container'; + var proxiedMapperMethods = ['count', 'create', 'createMany', 'createRecord', 'destroy', 'destroyAll', 'find', 'findAll', 'getSchema', 'is', 'sum', 'toJSON', 'update', 'updateAll', 'updateMany', 'validate']; + /** + * The `Container` class is a place to define and store {@link Mapper} instances. + * + * `Container` makes it easy to manage your Mappers. Without a container, you + * need to manage Mappers yourself, including resolving circular dependencies + * among relations. All Mappers in a container share the same adapters, so you + * don't have to register adapters for every single Mapper. + * + * @example Container#constructor + * // import { Container } from 'js-data'; + * const JSData = require('js-data'); + * const {Container} = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new Container(); + * + * @class Container + * @extends Component + * @param {object} [opts] Configuration options. + * @param {boolean} [opts.debug=false] See {@link Component#debug}. + * @param {Constructor} [opts.mapperClass] See {@link Container#mapperClass}. + * @param {object} [opts.mapperDefaults] See {@link Container#mapperDefaults}. + * @since 3.0.0 + */ - /** - * Fired during {@link Mapper#updateAll}. See - * {@link Mapper~afterUpdateAllListener} for how to listen for this event. - * - * @event Mapper#afterUpdateAll - * @see Mapper~afterUpdateAllListener - * @see Mapper#updateAll - */ + var Container = + /*#__PURE__*/ + function (_Component) { + _inherits(Container, _Component); - /** - * Callback signature for the {@link Mapper#event:afterUpdateAll} event. - * - * @example - * function onAfterUpdateAll (props, query, opts, result) { - * // do something - * } - * store.on('afterUpdateAll', onAfterUpdateAll); - * - * @callback Mapper~afterUpdateAllListener - * @param {object} props The `props` argument received by {@link Mapper#afterUpdateAll}. - * @param {object} query The `query` argument received by {@link Mapper#afterUpdateAll}. - * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdateAll}. - * @param {object} result The `result` argument received by {@link Mapper#afterUpdateAll}. - * @see Mapper#event:afterUpdateAll - * @see Mapper#updateAll - * @since 3.0.0 - */ + function Container() { + var _this; - /** - * Using the `query` argument, perform the a single updated to the selected - * records. - * - * {@link Mapper#beforeUpdateAll} will be called before making the update. - * {@link Mapper#afterUpdateAll} will be called after making the update. - * - * @example - * // Turn all of John's blog posts into drafts. - * const update = { status: draft: published_at: null }; - * const query = { userId: 1234 }; - * PostMapper.updateAll(update, query).then((posts) => { - * console.log(posts); // [...] - * }); - * - * @fires Mapper#beforeUpdateAll - * @fires Mapper#afterUpdateAll - * @method Mapper#updateAll - * @param {object} props Update to apply to selected records. - * @param {object} [query={}] Selection query. See {@link query}. - * @param {object} [query.where] See {@link query.where}. - * @param {number} [query.offset] See {@link query.offset}. - * @param {number} [query.limit] See {@link query.limit}. - * @param {string|Array[]} [query.orderBy] See {@link query.orderBy}. - * @param {object} [opts] Configuration options. Refer to the `updateAll` - * method of whatever adapter you're using for more configuration options. - * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the - * adapter to use. - * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}. - * @param {boolean} [opts.noValidate={@link Mapper#noValidate}] See {@link Mapper#noValidate}. - * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}. - * @returns {Promise} Resolves with the update records, if any. - * @see query - * @since 3.0.0 - * @tutorial ["http://www.js-data.io/v3.0/docs/saving-data","Saving data"] - */ - updateAll: function updateAll(props, query, opts) { - return this.crud('updateAll', props, query, opts); - }, + var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - /** - * Fired during {@link Mapper#updateMany}. See - * {@link Mapper~beforeUpdateManyListener} for how to listen for this event. - * - * @event Mapper#beforeUpdateMany - * @see Mapper~beforeUpdateManyListener - * @see Mapper#updateMany - */ + _classCallCheck(this, Container); - /** - * Callback signature for the {@link Mapper#event:beforeUpdateMany} event. - * - * @example - * function onBeforeUpdateMany (records, opts) { - * // do something - * } - * store.on('beforeUpdateMany', onBeforeUpdateMany); - * - * @callback Mapper~beforeUpdateManyListener - * @param {object} records The `records` argument received by {@link Mapper#beforeUpdateMany}. - * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdateMany}. - * @see Mapper#event:beforeUpdateMany - * @see Mapper#updateMany - * @since 3.0.0 - */ + _this = _possibleConstructorReturn(this, _getPrototypeOf(Container).call(this)); + Object.defineProperties(_assertThisInitialized(_this), { + /** + * The adapters registered with this Container, which are also shared by all + * Mappers in this Container. + * + * @name Container#_adapters + * @see Container#registerAdapter + * @since 3.0.0 + * @type {Object} + */ + _adapters: { + value: {} + }, - /** - * Fired during {@link Mapper#updateMany}. See - * {@link Mapper~afterUpdateManyListener} for how to listen for this event. - * - * @event Mapper#afterUpdateMany - * @see Mapper~afterUpdateManyListener - * @see Mapper#updateMany - */ + /** + * The the mappers in this container + * + * @name Container#_mappers + * @see Mapper + * @since 3.0.0 + * @type {Object} + */ + _mappers: { + value: {} + }, - /** - * Callback signature for the {@link Mapper#event:afterUpdateMany} event. - * - * @example - * function onAfterUpdateMany (records, opts, result) { - * // do something - * } - * store.on('afterUpdateMany', onAfterUpdateMany); - * - * @callback Mapper~afterUpdateManyListener - * @param {object} records The `records` argument received by {@link Mapper#afterUpdateMany}. - * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdateMany}. - * @param {object} result The `result` argument received by {@link Mapper#afterUpdateMany}. - * @see Mapper#event:afterUpdateMany - * @see Mapper#updateMany - * @since 3.0.0 - */ + /** + * Constructor function to use in {@link Container#defineMapper} to create new + * {@link Mapper} instances. {@link Container#mapperClass} should extend + * {@link Mapper}. By default {@link Mapper} is used to instantiate Mappers. + * + * @example Container#mapperClass + * // import { Container, Mapper } from 'js-data'; + * const JSData = require('js-data'); + * const { Container, Mapper } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * class MyMapperClass extends Mapper { + * foo () { return 'bar' } + * } + * const store = new Container({ + * mapperClass: MyMapperClass + * }); + * store.defineMapper('user'); + * console.log(store.getMapper('user').foo()); + * + * @name Container#mapperClass + * @see Mapper + * @since 3.0.0 + * @type {Constructor} + */ + mapperClass: { + value: undefined, + writable: true + } + }); // Apply options provided by the user + + utils.fillIn(_assertThisInitialized(_this), opts); + /** + * Defaults options to pass to {@link Container#mapperClass} when creating a + * new {@link Mapper}. + * + * @example Container#mapperDefaults + * // import { Container } from 'js-data'; + * const JSData = require('js-data'); + * const { Container } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new Container({ + * mapperDefaults: { + * idAttribute: '_id' + * } + * }); + * store.defineMapper('user'); + * console.log(store.getMapper('user').idAttribute); + * + * @default {} + * @name Container#mapperDefaults + * @since 3.0.0 + * @type {Object} + */ - /** - * Given an array of updates, perform each of the updates via an adapter. Each - * "update" is a hash of properties with which to update an record. Each - * update must contain the primary key of the record to be updated. - * - * {@link Mapper#beforeUpdateMany} will be called before making the update. - * {@link Mapper#afterUpdateMany} will be called after making the update. - * - * @example - * PostMapper.updateMany([ - * { id: 1234, status: 'draft' }, - * { id: 2468, status: 'published', published_at: new Date() } - * ]).then((posts) => { - * console.log(posts); // [...] - * }); - * - * @fires Mapper#beforeUpdateMany - * @fires Mapper#afterUpdateMany - * @method Mapper#updateMany - * @param {Record[]} records Array up record updates. - * @param {object} [opts] Configuration options. Refer to the `updateMany` - * method of whatever adapter you're using for more configuration options. - * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the - * adapter to use. - * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}. - * @param {boolean} [opts.noValidate={@link Mapper#noValidate}] See {@link Mapper#noValidate}. - * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}. - * @returns {Promise} Resolves with the updated records. Rejects if any of the - * records could be found. - * @since 3.0.0 - * @tutorial ["http://www.js-data.io/v3.0/docs/saving-data","Saving data"] - */ - updateMany: function updateMany(records, opts) { - return this.crud('updateMany', records, opts); - }, + _this.mapperDefaults = _this.mapperDefaults || {}; // Use the Mapper class if the user didn't provide a mapperClass - /** - * Validate the given record or records according to this Mapper's - * {@link Schema}. If there are no validation errors then the return value - * will be `undefined`. - * - * @example - * import {Mapper, Schema} from 'js-data' - * const PersonSchema = new Schema({ - * properties: { - * name: { type: 'string' }, - * id: { type: 'string' } - * } - * }); - * const PersonMapper = new Mapper({ - * name: 'person', - * schema: PersonSchema - * }); - * let errors = PersonMapper.validate({ name: 'John' }); - * console.log(errors); // undefined - * errors = PersonMapper.validate({ name: 123 }); - * console.log(errors); // [{ expected: 'one of (string)', actual: 'number', path: 'name' }] - * - * @method Mapper#validate - * @param {Object|Object[]} record The record or records to validate. - * @param {object} [opts] Configuration options. Passed to - * {@link Schema#validate}. - * @returns {Object[]} Array of errors or `undefined` if no errors. - * @since 3.0.0 - */ - validate: function validate(record, opts) { - opts || (opts = {}); - var schema = this.getSchema(); + _this.mapperClass = _this.mapperClass || Mapper; + return _this; + } + /** + * Register a new event listener on this Container. + * + * Proxy for {@link Component#on}. If an event was emitted by a {@link Mapper} + * in the Container, then the name of the {@link Mapper} will be prepended to + * the arugments passed to the listener. + * + * @example Container#on + * // import { Container } from 'js-data'; + * const JSData = require('js-data'); + * const { Container } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new Container(); + * store.on('foo', function (...args) { console.log(args.join(':')) }); + * store.defineMapper('user'); + * store.emit('foo', 'arg1', 'arg2'); + * store.getMapper('user').emit('foo', 'arg1', 'arg2'); + * + * @method Container#on + * @param {string} event Name of event to subsribe to. + * @param {Function} listener Listener function to handle the event. + * @param {*} [ctx] Optional content in which to invoke the listener. + * @since 3.0.0 + */ + + /** + * Used to bind to events emitted by mappers in this container. + * + * @method Container#_onMapperEvent + * @param {string} name Name of the mapper that emitted the event. + * @param {...*} [args] Args See {@link Mapper#emit}. + * @private + * @since 3.0.0 + */ + + + _createClass(Container, [{ + key: "_onMapperEvent", + value: function _onMapperEvent(name) { + for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + args[_key - 1] = arguments[_key]; + } - if (!schema) { - return; - } + var type = args.shift(); + this.emit.apply(this, [type, name].concat(args)); + } + /** + * Return a container scoped to a particular mapper. + * + * @example Container#as + * // import { Container } from 'js-data'; + * const JSData = require('js-data'); + * const { Container } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new Container(); + * const UserMapper = store.defineMapper('user'); + * const UserStore = store.as('user'); + * + * const user1 = store.createRecord('user', { name: 'John' }); + * const user2 = UserStore.createRecord({ name: 'John' }); + * const user3 = UserMapper.createRecord({ name: 'John' }); + * console.log(user1 === user2); + * console.log(user2 === user3); + * console.log(user1 === user3); + * + * @method Container#as + * @param {string} name Name of the {@link Mapper}. + * @returns {Object} A container scoped to a particular mapper. + * @since 3.0.0 + */ - var _opts = utils.pick(opts, ['existingOnly']); + }, { + key: "as", + value: function as(name) { + var props = {}; + var original = this; + proxiedMapperMethods.forEach(function (method) { + props[method] = { + writable: true, + value: function value() { + for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { + args[_key2] = arguments[_key2]; + } - if (utils.isArray(record)) { - var errors = record.map(function (_record) { - return schema.validate(_record, utils.pick(_opts, ['existingOnly'])); + return original[method].apply(original, [name].concat(args)); + } + }; }); - return errors.some(Boolean) ? errors : undefined; - } - - return schema.validate(record, _opts); - }, + props.getMapper = { + writable: true, + value: function value() { + return original.getMapper(name); + } + }; + return Object.create(this, props); + } + /** + * Create a new mapper and register it in this container. + * + * @example Container#defineMapper + * // import { Container } from 'js-data'; + * const JSData = require('js-data'); + * const { Container } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new Container({ + * mapperDefaults: { foo: 'bar' } + * }); + * // Container#defineMapper returns a direct reference to the newly created + * // Mapper. + * const UserMapper = store.defineMapper('user'); + * console.log(UserMapper === store.getMapper('user')); + * console.log(UserMapper === store.as('user').getMapper()); + * console.log(UserMapper.foo); + * + * @method Container#defineMapper + * @param {string} name Name under which to register the new {@link Mapper}. + * {@link Mapper#name} will be set to this value. + * @param {object} [opts] Configuration options. Passed to + * {@link Container#mapperClass} when creating the new {@link Mapper}. + * @returns {Mapper} The newly created instance of {@link Mapper}. + * @see Container#as + * @since 3.0.0 + */ - /** - * Method used to wrap data returned by an adapter with this Mapper's - * {@link Mapper#recordClass}. This method is used by all of a Mapper's CRUD - * methods. The provided implementation of this method assumes that the `data` - * passed to it is a record or records that need to be wrapped with - * {@link Mapper#createRecord}. Override with care. - * - * Provided implementation of {@link Mapper#wrap}: - * - * ``` - * function (data, opts) { - * return this.createRecord(data, opts); - * } - * ``` - * - * @example - * const PostMapper = new Mapper({ - * name: 'post', - * // Override to customize behavior - * wrap (data, opts) { - * const originalWrap = this.constructor.prototype.wrap; - * // Let's say "GET /post" doesn't return JSON quite like JSData expects, - * // but the actual post records are nested under a "posts" field. So, - * // we override Mapper#wrap to handle this special case. - * if (opts.op === 'findAll') { - * return originalWrap.call(this, data.posts, opts); - * } - * // Otherwise perform original behavior - * return originalWrap.call(this, data, opts); - * } - * }); - * - * @method Mapper#wrap - * @param {Object|Object[]} data The record or records to be wrapped. - * @param {object} [opts] Configuration options. Passed to {@link Mapper#createRecord}. - * @returns {Record|Record[]} The wrapped record or records. - * @since 3.0.0 - */ - wrap: function wrap(data, opts) { - return this.createRecord(data, opts); - }, + }, { + key: "defineMapper", + value: function defineMapper(name, opts) { + var _this2 = this; - /** - * @ignore - */ - defineRelations: function defineRelations() { - var _this9 = this; - - // Setup the mapper's relations, including generating Mapper#relationList - // and Mapper#relationFields - utils.forOwn(this.relations, function (group, type) { - utils.forOwn(group, function (relations, _name) { - if (utils.isObject(relations)) { - relations = [relations]; - } + // For backwards compatibility with defineResource + if (utils.isObject(name)) { + opts = name; + name = opts.name; + } - relations.forEach(function (def) { - var relatedMapper = _this9.datastore.getMapperByName(_name) || _name; + if (!utils.isString(name)) { + throw utils.err("".concat(DOMAIN$7, "#defineMapper"), 'name')(400, 'string', name); + } // Default values for arguments - def.getRelation = function () { - return _this9.datastore.getMapper(_name); - }; - if (typeof Relation[type] !== 'function') { - throw utils.err(DOMAIN$6, 'defineRelations')(400, 'relation type (hasOne, hasMany, etc)', type, true); - } + opts = opts || {}; // Set Mapper#name - _this9[type](relatedMapper, def); - }); - }); - }); - } - }); - /** - * Create a subclass of this Mapper: - * - * @example Mapper.extend - * const JSData = require('js-data'); - * const { Mapper } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * // Extend the class using ES2015 class syntax. - * class CustomMapperClass extends Mapper { - * foo () { return 'bar'; } - * static beep () { return 'boop'; } - * }; - * const customMapper = new CustomMapperClass(); - * console.log(customMapper.foo()); - * console.log(CustomMapperClass.beep()); - * - * // Extend the class using alternate method. - * const OtherMapperClass = Mapper.extend({ - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }); - * const otherMapper = new OtherMapperClass(); - * console.log(otherMapper.foo()); - * console.log(OtherMapperClass.beep()); - * - * // Extend the class, providing a custom constructor. - * function AnotherMapperClass () { - * Mapper.call(this); - * this.created_at = new Date().getTime(); - * } - * Mapper.extend({ - * constructor: AnotherMapperClass, - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }) - * const anotherMapper = new AnotherMapperClass(); - * console.log(anotherMapper.created_at); - * console.log(anotherMapper.foo()); - * console.log(AnotherMapperClass.beep()); - * - * @method Mapper.extend - * @param {object} [props={}] Properties to add to the prototype of the - * subclass. - * @param {object} [props.constructor] Provide a custom constructor function - * to be used as the subclass itself. - * @param {object} [classProps={}] Static properties to add to the subclass. - * @returns {Constructor} Subclass of this Mapper class. - * @since 3.0.0 - */ + opts.name = name; + opts.relations = opts.relations || {}; // Check if the user is overriding the datastore's default mapperClass - var DOMAIN$7 = 'Container'; - var proxiedMapperMethods = [ - /** - * Wrapper for {@link Mapper#count}. - * - * @example - * // Get the number of published blog posts - * import { Container } from 'js-data'; - * import RethinkDBAdapter from 'js-data-rethinkdb'; - * const store = new Container(); - * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); - * store.defineMapper('post'); - * - * store.count('post', { status: 'published' }).then((numPublished) => { - * console.log(numPublished); // e.g. 45 - * }); - * - * @method Container#count - * @param {string} name Name of the {@link Mapper} to target. - * @param {object} [query] See {@link Mapper#count}. - * @param {object} [opts] See {@link Mapper#count}. - * @returns {Promise} See {@link Mapper#count}. - * @see Mapper#count - * @since 3.0.0 - */ - 'count', - /** - * Fired during {@link Container#create}. See - * {@link Container~beforeCreateListener} for how to listen for this event. - * - * @event Container#beforeCreate - * @see Container~beforeCreateListener - * @see Container#create - */ + var mapperClass = opts.mapperClass || this.mapperClass; + delete opts.mapperClass; // Apply the datastore's defaults to the options going into the mapper - /** - * Callback signature for the {@link Container#event:beforeCreate} event. - * - * @example - * function onBeforeCreate (mapperName, props, opts) { - * // do something - * } - * store.on('beforeCreate', onBeforeCreate); - * - * @callback Container~beforeCreateListener - * @param {string} name The `name` argument received by {@link Mapper#beforeCreate}. - * @param {object} props The `props` argument received by {@link Mapper#beforeCreate}. - * @param {object} opts The `opts` argument received by {@link Mapper#beforeCreate}. - * @see Container#event:beforeCreate - * @see Container#create - * @since 3.0.0 - */ + utils.fillIn(opts, this.mapperDefaults); // Instantiate a mapper - /** - * Fired during {@link Container#create}. See - * {@link Container~afterCreateListener} for how to listen for this event. - * - * @event Container#afterCreate - * @see Container~afterCreateListener - * @see Container#create - */ + var mapper = this._mappers[name] = new mapperClass(opts); // eslint-disable-line - /** - * Callback signature for the {@link Container#event:afterCreate} event. - * - * @example - * function onAfterCreate (mapperName, props, opts, result) { - * // do something - * } - * store.on('afterCreate', onAfterCreate); - * - * @callback Container~afterCreateListener - * @param {string} name The `name` argument received by {@link Mapper#afterCreate}. - * @param {object} props The `props` argument received by {@link Mapper#afterCreate}. - * @param {object} opts The `opts` argument received by {@link Mapper#afterCreate}. - * @param {object} result The `result` argument received by {@link Mapper#afterCreate}. - * @see Container#event:afterCreate - * @see Container#create - * @since 3.0.0 - */ + mapper.relations = mapper.relations || {}; // Make sure the mapper's name is set - /** - * Wrapper for {@link Mapper#create}. - * - * @example - * // Create and save a new blog post - * import { Container } from 'js-data'; - * import RethinkDBAdapter from 'js-data-rethinkdb'; - * const store = new Container(); - * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); - * store.defineMapper('post'); - * - * store.create('post', { - * title: 'Modeling your data', - * status: 'draft' - * }).then((post) => { - * console.log(post); // { id: 1234, status: 'draft', ... } - * }); - * - * @fires Container#beforeCreate - * @fires Container#afterCreate - * @method Container#create - * @param {string} name Name of the {@link Mapper} to target. - * @param {object} props See {@link Mapper#create}. - * @param {object} [opts] See {@link Mapper#create}. - * @returns {Promise} See {@link Mapper#create}. - * @see Mapper#create - * @since 3.0.0 - */ - 'create', - /** - * Fired during {@link Container#createMany}. See - * {@link Container~beforeCreateManyListener} for how to listen for this event. - * - * @event Container#beforeCreateMany - * @see Container~beforeCreateManyListener - * @see Container#createMany - */ + mapper.name = name; // All mappers in this datastore will share adapters - /** - * Callback signature for the {@link Container#event:beforeCreateMany} event. - * - * @example - * function onBeforeCreateMany (mapperName, records, opts) { - * // do something - * } - * store.on('beforeCreateMany', onBeforeCreateMany); - * - * @callback Container~beforeCreateManyListener - * @param {string} name The `name` argument received by {@link Mapper#beforeCreateMany}. - * @param {object} records The `records` argument received by {@link Mapper#beforeCreateMany}. - * @param {object} opts The `opts` argument received by {@link Mapper#beforeCreateMany}. - * @see Container#event:beforeCreateMany - * @see Container#createMany - * @since 3.0.0 - */ + mapper._adapters = this.getAdapters(); + mapper.datastore = this; + mapper.on('all', function () { + for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { + args[_key3] = arguments[_key3]; + } - /** - * Fired during {@link Container#createMany}. See - * {@link Container~afterCreateManyListener} for how to listen for this event. - * - * @event Container#afterCreateMany - * @see Container~afterCreateManyListener - * @see Container#createMany - */ + return _this2._onMapperEvent.apply(_this2, [name].concat(args)); + }); + mapper.defineRelations(); + return mapper; + } + }, { + key: "defineResource", + value: function defineResource(name, opts) { + console.warn('DEPRECATED: defineResource is deprecated, use defineMapper instead'); + return this.defineMapper(name, opts); + } + /** + * Return the registered adapter with the given name or the default adapter if + * no name is provided. + * + * @method Container#getAdapter + * @param {string} [name] The name of the adapter to retrieve. + * @returns {Adapter} The adapter. + * @since 3.0.0 + */ - /** - * Callback signature for the {@link Container#event:afterCreateMany} event. - * - * @example - * function onAfterCreateMany (mapperName, records, opts, result) { - * // do something - * } - * store.on('afterCreateMany', onAfterCreateMany); - * - * @callback Container~afterCreateManyListener - * @param {string} name The `name` argument received by {@link Mapper#afterCreateMany}. - * @param {object} records The `records` argument received by {@link Mapper#afterCreateMany}. - * @param {object} opts The `opts` argument received by {@link Mapper#afterCreateMany}. - * @param {object} result The `result` argument received by {@link Mapper#afterCreateMany}. - * @see Container#event:afterCreateMany - * @see Container#createMany - * @since 3.0.0 - */ + }, { + key: "getAdapter", + value: function getAdapter(name) { + var adapter = this.getAdapterName(name); - /** - * Wrapper for {@link Mapper#createMany}. - * - * @example - * // Create and save several new blog posts - * import { Container } from 'js-data'; - * import RethinkDBAdapter from 'js-data-rethinkdb'; - * const store = new Container(); - * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); - * store.defineMapper('post'); - * - * store.createMany('post', [{ - * title: 'Modeling your data', - * status: 'draft' - * }, { - * title: 'Reading data', - * status: 'draft' - * }]).then((posts) => { - * console.log(posts[0]); // { id: 1234, status: 'draft', ... } - * console.log(posts[1]); // { id: 1235, status: 'draft', ... } - * }); - * - * @fires Container#beforeCreateMany - * @fires Container#afterCreateMany - * @method Container#createMany - * @param {string} name Name of the {@link Mapper} to target. - * @param {Record[]} records See {@link Mapper#createMany}. - * @param {object} [opts] See {@link Mapper#createMany}. - * @returns {Promise} See {@link Mapper#createMany}. - * @see Mapper#createMany - * @since 3.0.0 - */ - 'createMany', - /** - * Wrapper for {@link Mapper#createRecord}. - * - * __Note:__ This method does __not__ interact with any adapter, and does - * __not__ save any data. It only creates new objects in memory. - * - * @example - * // Create empty unsaved record instance - * import { Container } from 'js-data'; - * const store = new Container(); - * store.defineMapper('post'); - * const post = PostMapper.createRecord(); - * - * @method Container#createRecord - * @param {string} name Name of the {@link Mapper} to target. - * @param {Object|Object[]} props See {@link Mapper#createRecord}. - * @param {object} [opts] See {@link Mapper#createRecord}. - * @returns {Promise} See {@link Mapper#createRecord}. - * @see Mapper#createRecord - * @since 3.0.0 - */ - 'createRecord', - /** - * Fired during {@link Container#destroy}. See - * {@link Container~beforeDestroyListener} for how to listen for this event. - * - * @event Container#beforeDestroy - * @see Container~beforeDestroyListener - * @see Container#destroy - */ + if (!adapter) { + throw utils.err("".concat(DOMAIN$7, "#getAdapter"), 'name')(400, 'string', name); + } - /** - * Callback signature for the {@link Container#event:beforeDestroy} event. - * - * @example - * function onBeforeDestroy (mapperName, id, opts) { - * // do something - * } - * store.on('beforeDestroy', onBeforeDestroy); - * - * @callback Container~beforeDestroyListener - * @param {string} name The `name` argument received by {@link Mapper#beforeDestroy}. - * @param {string|number} id The `id` argument received by {@link Mapper#beforeDestroy}. - * @param {object} opts The `opts` argument received by {@link Mapper#beforeDestroy}. - * @see Container#event:beforeDestroy - * @see Container#destroy - * @since 3.0.0 - */ + return this.getAdapters()[adapter]; + } + /** + * Return the name of a registered adapter based on the given name or options, + * or the name of the default adapter if no name provided. + * + * @method Container#getAdapterName + * @param {(Object|string)} [opts] The name of an adapter or options, if any. + * @returns {string} The name of the adapter. + * @since 3.0.0 + */ - /** - * Fired during {@link Container#destroy}. See - * {@link Container~afterDestroyListener} for how to listen for this event. - * - * @event Container#afterDestroy - * @see Container~afterDestroyListener - * @see Container#destroy - */ + }, { + key: "getAdapterName", + value: function getAdapterName() { + var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - /** - * Callback signature for the {@link Container#event:afterDestroy} event. - * - * @example - * function onAfterDestroy (mapperName, id, opts, result) { - * // do something - * } - * store.on('afterDestroy', onAfterDestroy); - * - * @callback Container~afterDestroyListener - * @param {string} name The `name` argument received by {@link Mapper#afterDestroy}. - * @param {string|number} id The `id` argument received by {@link Mapper#afterDestroy}. - * @param {object} opts The `opts` argument received by {@link Mapper#afterDestroy}. - * @param {object} result The `result` argument received by {@link Mapper#afterDestroy}. - * @see Container#event:afterDestroy - * @see Container#destroy - * @since 3.0.0 - */ + if (utils.isString(opts)) { + opts = { + adapter: opts + }; + } - /** - * Wrapper for {@link Mapper#destroy}. - * - * @example - * // Destroy a specific blog post - * import { Container } from 'js-data'; - * import RethinkDBAdapter from 'js-data-rethinkdb'; - * const store = new Container(); - * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); - * store.defineMapper('post'); - * - * store.destroy('post', 1234).then(() => { - * // Blog post #1234 has been destroyed - * }); - * - * @fires Container#beforeDestroy - * @fires Container#afterDestroy - * @method Container#destroy - * @param {string} name Name of the {@link Mapper} to target. - * @param {(string|number)} id See {@link Mapper#destroy}. - * @param {object} [opts] See {@link Mapper#destroy}. - * @returns {Promise} See {@link Mapper#destroy}. - * @see Mapper#destroy - * @since 3.0.0 - */ - 'destroy', - /** - * Fired during {@link Container#destroyAll}. See - * {@link Container~beforeDestroyAllListener} for how to listen for this event. - * - * @event Container#beforeDestroyAll - * @see Container~beforeDestroyAllListener - * @see Container#destroyAll - */ + return opts.adapter || this.mapperDefaults.defaultAdapter; + } + /** + * Return the registered adapters of this container. + * + * @method Container#getAdapters + * @returns {Adapter} + * @since 3.0.0 + */ - /** - * Callback signature for the {@link Container#event:beforeDestroyAll} event. - * - * @example - * function onBeforeDestroyAll (mapperName, query, opts) { - * // do something - * } - * store.on('beforeDestroyAll', onBeforeDestroyAll); - * - * @callback Container~beforeDestroyAllListener - * @param {string} name The `name` argument received by {@link Mapper#beforeDestroyAll}. - * @param {object} query The `query` argument received by {@link Mapper#beforeDestroyAll}. - * @param {object} opts The `opts` argument received by {@link Mapper#beforeDestroyAll}. - * @see Container#event:beforeDestroyAll - * @see Container#destroyAll - * @since 3.0.0 - */ + }, { + key: "getAdapters", + value: function getAdapters() { + return this._adapters; + } + /** + * Return the mapper registered under the specified name. + * + * @example Container#getMapper + * // import { Container } from 'js-data'; + * const JSData = require('js-data'); + * const { Container } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new Container(); + * // Container#defineMapper returns a direct reference to the newly created + * // Mapper. + * const UserMapper = store.defineMapper('user'); + * console.log(UserMapper === store.getMapper('user')); + * console.log(UserMapper === store.as('user').getMapper()); + * store.getMapper('profile'); // throws Error, there is no mapper with name "profile" + * + * @method Container#getMapper + * @param {string} name {@link Mapper#name}. + * @returns {Mapper} + * @since 3.0.0 + */ - /** - * Fired during {@link Container#destroyAll}. See - * {@link Container~afterDestroyAllListener} for how to listen for this event. - * - * @event Container#afterDestroyAll - * @see Container~afterDestroyAllListener - * @see Container#destroyAll - */ + }, { + key: "getMapper", + value: function getMapper(name) { + var mapper = this.getMapperByName(name); - /** - * Callback signature for the {@link Container#event:afterDestroyAll} event. - * - * @example - * function onAfterDestroyAll (mapperName, query, opts, result) { - * // do something - * } - * store.on('afterDestroyAll', onAfterDestroyAll); - * - * @callback Container~afterDestroyAllListener - * @param {string} name The `name` argument received by {@link Mapper#afterDestroyAll}. - * @param {object} query The `query` argument received by {@link Mapper#afterDestroyAll}. - * @param {object} opts The `opts` argument received by {@link Mapper#afterDestroyAll}. - * @param {object} result The `result` argument received by {@link Mapper#afterDestroyAll}. - * @see Container#event:afterDestroyAll - * @see Container#destroyAll - * @since 3.0.0 - */ + if (!mapper) { + throw utils.err("".concat(DOMAIN$7, "#getMapper"), name)(404, 'mapper'); + } - /** - * Wrapper for {@link Mapper#destroyAll}. - * - * @example - * // Destroy all "draft" blog posts - * import { Container } from 'js-data'; - * import RethinkDBAdapter from 'js-data-rethinkdb'; - * const store = new Container(); - * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); - * store.defineMapper('post'); - * - * store.destroyAll('post', { status: 'draft' }).then(() => { - * // All "draft" blog posts have been destroyed - * }); - * - * @fires Container#beforeDestroyAll - * @fires Container#afterDestroyAll - * @method Container#destroyAll - * @param {string} name Name of the {@link Mapper} to target. - * @param {object} [query] See {@link Mapper#destroyAll}. - * @param {object} [opts] See {@link Mapper#destroyAll}. - * @returns {Promise} See {@link Mapper#destroyAll}. - * @see Mapper#destroyAll - * @since 3.0.0 - */ - 'destroyAll', - /** - * Fired during {@link Container#find}. See - * {@link Container~beforeFindListener} for how to listen for this event. - * - * @event Container#beforeFind - * @see Container~beforeFindListener - * @see Container#find - */ + return mapper; + } + /** + * Return the mapper registered under the specified name. + * Doesn't throw error if mapper doesn't exist. + * + * @example Container#getMapperByName + * // import { Container } from 'js-data'; + * const JSData = require('js-data'); + * const { Container } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new Container(); + * // Container#defineMapper returns a direct reference to the newly created + * // Mapper. + * const UserMapper = store.defineMapper('user'); + * console.log(UserMapper === store.getMapper('user')); + * console.log(UserMapper === store.as('user').getMapper()); + * console.log(store.getMapper('profile')); // Does NOT throw an error + * + * @method Container#getMapperByName + * @param {string} name {@link Mapper#name}. + * @returns {Mapper} + * @since 3.0.0 + */ - /** - * Callback signature for the {@link Container#event:beforeFind} event. - * - * @example - * function onBeforeFind (mapperName, id, opts) { - * // do something - * } - * store.on('beforeFind', onBeforeFind); - * - * @callback Container~beforeFindListener - * @param {string} name The `name` argument received by {@link Mapper#beforeFind}. - * @param {string|number} id The `id` argument received by {@link Mapper#beforeFind}. - * @param {object} opts The `opts` argument received by {@link Mapper#beforeFind}. - * @see Container#event:beforeFind - * @see Container#find - * @since 3.0.0 - */ + }, { + key: "getMapperByName", + value: function getMapperByName(name) { + return this._mappers[name]; + } + /** + * Register an adapter on this container under the given name. Adapters + * registered on a container are shared by all mappers in the container. + * + * @example + * import { Container } from 'js-data'; + * import { RethinkDBAdapter } from 'js-data-rethinkdb'; + * const store = new Container(); + * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); + * + * @method Container#registerAdapter + * @param {string} name The name of the adapter to register. + * @param {Adapter} adapter The adapter to register. + * @param {object} [opts] Configuration options. + * @param {boolean} [opts.default=false] Whether to make the adapter the + * default adapter for all Mappers in this container. + * @since 3.0.0 + * @tutorial ["http://www.js-data.io/v3.0/docs/connecting-to-a-data-source","Connecting to a data source"] + */ - /** - * Fired during {@link Container#find}. See - * {@link Container~afterFindListener} for how to listen for this event. - * - * @event Container#afterFind - * @see Container~afterFindListener - * @see Container#find - */ + }, { + key: "registerAdapter", + value: function registerAdapter(name, adapter) { + var opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + this.getAdapters()[name] = adapter; // Optionally make it the default adapter for the target. - /** - * Callback signature for the {@link Container#event:afterFind} event. - * - * @example - * function onAfterFind (mapperName, id, opts, result) { - * // do something - * } - * store.on('afterFind', onAfterFind); - * - * @callback Container~afterFindListener - * @param {string} name The `name` argument received by {@link Mapper#afterFind}. - * @param {string|number} id The `id` argument received by {@link Mapper#afterFind}. - * @param {object} opts The `opts` argument received by {@link Mapper#afterFind}. - * @param {object} result The `result` argument received by {@link Mapper#afterFind}. - * @see Container#event:afterFind - * @see Container#find - * @since 3.0.0 - */ + if (opts === true || opts["default"]) { + this.mapperDefaults.defaultAdapter = name; + utils.forOwn(this._mappers, function (mapper) { + mapper.defaultAdapter = name; + }); + } + } + /** + * Wrapper for {@link Mapper#count}. + * + * @example + * // Get the number of published blog posts + * import { Container } from 'js-data'; + * import RethinkDBAdapter from 'js-data-rethinkdb'; + * const store = new Container(); + * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); + * store.defineMapper('post'); + * + * store.count('post', { status: 'published' }).then((numPublished) => { + * console.log(numPublished); // e.g. 45 + * }); + * + * @method Container#count + * @param {string} name Name of the {@link Mapper} to target. + * @param {object} [query] See {@link Mapper#count}. + * @param {object} [opts] See {@link Mapper#count}. + * @returns {Promise} See {@link Mapper#count}. + * @see Mapper#count + * @since 3.0.0 + */ - /** - * Wrapper for {@link Mapper#find}. - * - * @example - * import { Container } from 'js-data'; - * import RethinkDBAdapter from 'js-data-rethinkdb'; - * const store = new Container(); - * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); - * store.defineMapper('post'); - * - * store.find('post', 1).then((post) => { - * console.log(post) // { id: 1, ...} - * }); - * - * @fires Container#beforeFind - * @fires Container#afterFind - * @method Container#find - * @param {string} name Name of the {@link Mapper} to target. - * @param {(string|number)} id See {@link Mapper#find}. - * @param {object} [opts] See {@link Mapper#find}. - * @returns {Promise} See {@link Mapper#find}. - * @see Mapper#find - * @since 3.0.0 - */ - 'find', - /** - * Fired during {@link Container#findAll}. See - * {@link Container~beforeFindAllListener} for how to listen for this event. - * - * @event Container#beforeFindAll - * @see Container~beforeFindAllListener - * @see Container#findAll - */ + }, { + key: "count", + value: function count(name, query, opts) { + return this.getMapper(name).count(query, opts); + } + /** + * Fired during {@link Container#create}. See + * {@link Container~beforeCreateListener} for how to listen for this event. + * + * @event Container#beforeCreate + * @see Container~beforeCreateListener + * @see Container#create + */ - /** - * Callback signature for the {@link Container#event:beforeFindAll} event. - * - * @example - * function onBeforeFindAll (mapperName, query, opts) { - * // do something - * } - * store.on('beforeFindAll', onBeforeFindAll); - * - * @callback Container~beforeFindAllListener - * @param {string} name The `name` argument received by {@link Mapper#beforeFindAll}. - * @param {object} query The `query` argument received by {@link Mapper#beforeFindAll}. - * @param {object} opts The `opts` argument received by {@link Mapper#beforeFindAll}. - * @see Container#event:beforeFindAll - * @see Container#findAll - * @since 3.0.0 - */ + /** + * Callback signature for the {@link Container#event:beforeCreate} event. + * + * @example + * function onBeforeCreate (mapperName, props, opts) { + * // do something + * } + * store.on('beforeCreate', onBeforeCreate); + * + * @callback Container~beforeCreateListener + * @param {string} name The `name` argument received by {@link Mapper#beforeCreate}. + * @param {object} props The `props` argument received by {@link Mapper#beforeCreate}. + * @param {object} opts The `opts` argument received by {@link Mapper#beforeCreate}. + * @see Container#event:beforeCreate + * @see Container#create + * @since 3.0.0 + */ - /** - * Fired during {@link Container#findAll}. See - * {@link Container~afterFindAllListener} for how to listen for this event. - * - * @event Container#afterFindAll - * @see Container~afterFindAllListener - * @see Container#findAll - */ + /** + * Fired during {@link Container#create}. See + * {@link Container~afterCreateListener} for how to listen for this event. + * + * @event Container#afterCreate + * @see Container~afterCreateListener + * @see Container#create + */ - /** - * Callback signature for the {@link Container#event:afterFindAll} event. - * - * @example - * function onAfterFindAll (mapperName, query, opts, result) { - * // do something - * } - * store.on('afterFindAll', onAfterFindAll); - * - * @callback Container~afterFindAllListener - * @param {string} name The `name` argument received by {@link Mapper#afterFindAll}. - * @param {object} query The `query` argument received by {@link Mapper#afterFindAll}. - * @param {object} opts The `opts` argument received by {@link Mapper#afterFindAll}. - * @param {object} result The `result` argument received by {@link Mapper#afterFindAll}. - * @see Container#event:afterFindAll - * @see Container#findAll - * @since 3.0.0 - */ + /** + * Callback signature for the {@link Container#event:afterCreate} event. + * + * @example + * function onAfterCreate (mapperName, props, opts, result) { + * // do something + * } + * store.on('afterCreate', onAfterCreate); + * + * @callback Container~afterCreateListener + * @param {string} name The `name` argument received by {@link Mapper#afterCreate}. + * @param {object} props The `props` argument received by {@link Mapper#afterCreate}. + * @param {object} opts The `opts` argument received by {@link Mapper#afterCreate}. + * @param {object} result The `result` argument received by {@link Mapper#afterCreate}. + * @see Container#event:afterCreate + * @see Container#create + * @since 3.0.0 + */ - /** - * Wrapper for {@link Mapper#createRecord}. - * - * @example - * // Find all "published" blog posts - * import { Container } from 'js-data'; - * import RethinkDBAdapter from 'js-data-rethinkdb'; - * const store = new Container(); - * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); - * store.defineMapper('post'); - * - * store.findAll('post', { status: 'published' }).then((posts) => { - * console.log(posts); // [{ id: 1, ...}, ...] - * }); - * - * @fires Container#beforeFindAll - * @fires Container#afterFindAll - * @method Container#findAll - * @param {string} name Name of the {@link Mapper} to target. - * @param {object} [query] See {@link Mapper#findAll}. - * @param {object} [opts] See {@link Mapper#findAll}. - * @returns {Promise} See {@link Mapper#findAll}. - * @see Mapper#findAll - * @since 3.0.0 - */ - 'findAll', - /** - * Wrapper for {@link Mapper#getSchema}. - * - * @method Container#getSchema - * @param {string} name Name of the {@link Mapper} to target. - * @returns {Schema} See {@link Mapper#getSchema}. - * @see Mapper#getSchema - * @since 3.0.0 - */ - 'getSchema', - /** - * Wrapper for {@link Mapper#is}. - * - * @example - * import { Container } from 'js-data'; - * const store = new Container(); - * store.defineMapper('post'); - * const post = store.createRecord(); - * - * console.log(store.is('post', post)); // true - * // Equivalent to what's above - * console.log(post instanceof store.getMapper('post').recordClass); // true - * - * @method Container#is - * @param {string} name Name of the {@link Mapper} to target. - * @param {Object|Record} record See {@link Mapper#is}. - * @returns {boolean} See {@link Mapper#is}. - * @see Mapper#is - * @since 3.0.0 - */ - 'is', - /** - * Wrapper for {@link Mapper#sum}. - * - * @example - * import { Container } from 'js-data'; - * import RethinkDBAdapter from 'js-data-rethinkdb'; - * const store = new Container(); - * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); - * store.defineMapper('purchase_order'); - * - * store.sum('purchase_order', 'amount', { status: 'paid' }).then((amountPaid) => { - * console.log(amountPaid); // e.g. 451125.34 - * }); - * - * @method Container#sum - * @param {string} name Name of the {@link Mapper} to target. - * @param {string} field See {@link Mapper#sum}. - * @param {object} [query] See {@link Mapper#sum}. - * @param {object} [opts] See {@link Mapper#sum}. - * @returns {Promise} See {@link Mapper#sum}. - * @see Mapper#sum - * @since 3.0.0 - */ - 'sum', - /** - * Wrapper for {@link Mapper#toJSON}. - * - * @example - * import { Container } from 'js-data'; - * import RethinkDBAdapter from 'js-data-rethinkdb'; - * const store = new Container(); - * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); - * store.defineMapper('person', { - * schema: { - * properties: { - * name: { type: 'string' }, - * id: { type: 'string' } - * } - * } - * }); - * const person = store.createRecord('person', { id: 1, name: 'John', foo: 'bar' }); - * // "foo" is stripped by toJSON() - * console.log(store.toJSON('person', person)); // {"id":1,"name":"John"} - * - * store.defineMapper('personRelaxed', { - * schema: { - * properties: { - * name: { type: 'string' }, - * id: { type: 'string' } - * }, - * additionalProperties: true - * } - * }); - * const person2 = store.createRecord('personRelaxed', { id: 1, name: 'John', foo: 'bar' }); - * // "foo" is not stripped by toJSON - * console.log(store.toJSON('personRelaxed', person2)); // {"id":1,"name":"John","foo":"bar"} - * - * @method Container#toJSON - * @param {string} name Name of the {@link Mapper} to target. - * @param {Record|Record[]} records See {@link Mapper#toJSON}. - * @param {object} [opts] See {@link Mapper#toJSON}. - * @returns {Object|Object[]} See {@link Mapper#toJSON}. - * @see Mapper#toJSON - * @since 3.0.0 - */ - 'toJSON', - /** - * Fired during {@link Container#update}. See - * {@link Container~beforeUpdateListener} for how to listen for this event. - * - * @event Container#beforeUpdate - * @see Container~beforeUpdateListener - * @see Container#update - */ + /** + * Wrapper for {@link Mapper#create}. + * + * @example + * // Create and save a new blog post + * import { Container } from 'js-data'; + * import RethinkDBAdapter from 'js-data-rethinkdb'; + * const store = new Container(); + * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); + * store.defineMapper('post'); + * + * store.create('post', { + * title: 'Modeling your data', + * status: 'draft' + * }).then((post) => { + * console.log(post); // { id: 1234, status: 'draft', ... } + * }); + * + * @fires Container#beforeCreate + * @fires Container#afterCreate + * @method Container#create + * @param {string} name Name of the {@link Mapper} to target. + * @param {object} props See {@link Mapper#create}. + * @param {object} [opts] See {@link Mapper#create}. + * @returns {Promise} See {@link Mapper#create}. + * @see Mapper#create + * @since 3.0.0 + */ - /** - * Callback signature for the {@link Container#event:beforeUpdate} event. - * - * @example - * function onBeforeUpdate (mapperName, id, props, opts) { - * // do something - * } - * store.on('beforeUpdate', onBeforeUpdate); - * - * @callback Container~beforeUpdateListener - * @param {string} name The `name` argument received by {@link Mapper#beforeUpdate}. - * @param {string|number} id The `id` argument received by {@link Mapper#beforeUpdate}. - * @param {object} props The `props` argument received by {@link Mapper#beforeUpdate}. - * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdate}. - * @see Container#event:beforeUpdate - * @see Container#update - * @since 3.0.0 - */ + }, { + key: "create", + value: function create(name, props, opts) { + return this.getMapper(name).create(props, opts); + } + /** + * Fired during {@link Container#createMany}. See + * {@link Container~beforeCreateManyListener} for how to listen for this event. + * + * @event Container#beforeCreateMany + * @see Container~beforeCreateManyListener + * @see Container#createMany + */ - /** - * Fired during {@link Container#update}. See - * {@link Container~afterUpdateListener} for how to listen for this event. - * - * @event Container#afterUpdate - * @see Container~afterUpdateListener - * @see Container#update - */ + /** + * Callback signature for the {@link Container#event:beforeCreateMany} event. + * + * @example + * function onBeforeCreateMany (mapperName, records, opts) { + * // do something + * } + * store.on('beforeCreateMany', onBeforeCreateMany); + * + * @callback Container~beforeCreateManyListener + * @param {string} name The `name` argument received by {@link Mapper#beforeCreateMany}. + * @param {object} records The `records` argument received by {@link Mapper#beforeCreateMany}. + * @param {object} opts The `opts` argument received by {@link Mapper#beforeCreateMany}. + * @see Container#event:beforeCreateMany + * @see Container#createMany + * @since 3.0.0 + */ - /** - * Callback signature for the {@link Container#event:afterUpdate} event. - * - * @example - * function onAfterUpdate (mapperName, id, props, opts, result) { - * // do something - * } - * store.on('afterUpdate', onAfterUpdate); - * - * @callback Container~afterUpdateListener - * @param {string} name The `name` argument received by {@link Mapper#afterUpdate}. - * @param {string|number} id The `id` argument received by {@link Mapper#afterUpdate}. - * @param {object} props The `props` argument received by {@link Mapper#afterUpdate}. - * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdate}. - * @param {object} result The `result` argument received by {@link Mapper#afterUpdate}. - * @see Container#event:afterUpdate - * @see Container#update - * @since 3.0.0 - */ + /** + * Fired during {@link Container#createMany}. See + * {@link Container~afterCreateManyListener} for how to listen for this event. + * + * @event Container#afterCreateMany + * @see Container~afterCreateManyListener + * @see Container#createMany + */ - /** - * Wrapper for {@link Mapper#update}. - * - * @example - * import { Container } from 'js-data'; - * import RethinkDBAdapter from 'js-data-rethinkdb'; - * const store = new Container(); - * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); - * store.defineMapper('post'); - * - * store.update('post', 1234, { - * status: 'published', - * published_at: new Date() - * }).then((post) => { - * console.log(post); // { id: 1234, status: 'published', ... } - * }); - * - * @fires Container#beforeUpdate - * @fires Container#afterUpdate - * @method Container#update - * @param {string} name Name of the {@link Mapper} to target. - * @param {(string|number)} id See {@link Mapper#update}. - * @param {object} record See {@link Mapper#update}. - * @param {object} [opts] See {@link Mapper#update}. - * @returns {Promise} See {@link Mapper#update}. - * @see Mapper#update - * @since 3.0.0 - * @tutorial ["http://www.js-data.io/v3.0/docs/saving-data","Saving data"] - */ - 'update', - /** - * Fired during {@link Container#updateAll}. See - * {@link Container~beforeUpdateAllListener} for how to listen for this event. - * - * @event Container#beforeUpdateAll - * @see Container~beforeUpdateAllListener - * @see Container#updateAll - */ + /** + * Callback signature for the {@link Container#event:afterCreateMany} event. + * + * @example + * function onAfterCreateMany (mapperName, records, opts, result) { + * // do something + * } + * store.on('afterCreateMany', onAfterCreateMany); + * + * @callback Container~afterCreateManyListener + * @param {string} name The `name` argument received by {@link Mapper#afterCreateMany}. + * @param {object} records The `records` argument received by {@link Mapper#afterCreateMany}. + * @param {object} opts The `opts` argument received by {@link Mapper#afterCreateMany}. + * @param {object} result The `result` argument received by {@link Mapper#afterCreateMany}. + * @see Container#event:afterCreateMany + * @see Container#createMany + * @since 3.0.0 + */ - /** - * Callback signature for the {@link Container#event:beforeUpdateAll} event. - * - * @example - * function onBeforeUpdateAll (mapperName, props, query, opts) { - * // do something - * } - * store.on('beforeUpdateAll', onBeforeUpdateAll); - * - * @callback Container~beforeUpdateAllListener - * @param {string} name The `name` argument received by {@link Mapper#beforeUpdateAll}. - * @param {object} props The `props` argument received by {@link Mapper#beforeUpdateAll}. - * @param {object} query The `query` argument received by {@link Mapper#beforeUpdateAll}. - * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdateAll}. - * @see Container#event:beforeUpdateAll - * @see Container#updateAll - * @since 3.0.0 - */ + /** + * Wrapper for {@link Mapper#createMany}. + * + * @example + * // Create and save several new blog posts + * import { Container } from 'js-data'; + * import RethinkDBAdapter from 'js-data-rethinkdb'; + * const store = new Container(); + * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); + * store.defineMapper('post'); + * + * store.createMany('post', [{ + * title: 'Modeling your data', + * status: 'draft' + * }, { + * title: 'Reading data', + * status: 'draft' + * }]).then((posts) => { + * console.log(posts[0]); // { id: 1234, status: 'draft', ... } + * console.log(posts[1]); // { id: 1235, status: 'draft', ... } + * }); + * + * @fires Container#beforeCreateMany + * @fires Container#afterCreateMany + * @method Container#createMany + * @param {string} name Name of the {@link Mapper} to target. + * @param {Record[]} records See {@link Mapper#createMany}. + * @param {object} [opts] See {@link Mapper#createMany}. + * @returns {Promise} See {@link Mapper#createMany}. + * @see Mapper#createMany + * @since 3.0.0 + */ - /** - * Fired during {@link Container#updateAll}. See - * {@link Container~afterUpdateAllListener} for how to listen for this event. - * - * @event Container#afterUpdateAll - * @see Container~afterUpdateAllListener - * @see Container#updateAll - */ + }, { + key: "createMany", + value: function createMany(name, records, opts) { + return this.getMapper(name).createMany(records, opts); + } + /** + * Wrapper for {@link Mapper#createRecord}. + * + * __Note:__ This method does __not__ interact with any adapter, and does + * __not__ save any data. It only creates new objects in memory. + * + * @example + * // Create empty unsaved record instance + * import { Container } from 'js-data'; + * const store = new Container(); + * store.defineMapper('post'); + * const post = PostMapper.createRecord(); + * + * @method Container#createRecord + * @param {string} name Name of the {@link Mapper} to target. + * @param {Object|Object[]} props See {@link Mapper#createRecord}. + * @param {object} [opts] See {@link Mapper#createRecord}. + * @returns {Promise} See {@link Mapper#createRecord}. + * @see Mapper#createRecord + * @since 3.0.0 + */ - /** - * Callback signature for the {@link Container#event:afterUpdateAll} event. - * - * @example - * function onAfterUpdateAll (mapperName, props, query, opts, result) { - * // do something - * } - * store.on('afterUpdateAll', onAfterUpdateAll); - * - * @callback Container~afterUpdateAllListener - * @param {string} name The `name` argument received by {@link Mapper#afterUpdateAll}. - * @param {object} props The `props` argument received by {@link Mapper#afterUpdateAll}. - * @param {object} query The `query` argument received by {@link Mapper#afterUpdateAll}. - * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdateAll}. - * @param {object} result The `result` argument received by {@link Mapper#afterUpdateAll}. - * @see Container#event:afterUpdateAll - * @see Container#updateAll - * @since 3.0.0 - */ + }, { + key: "createRecord", + value: function createRecord(name, props, opts) { + return this.getMapper(name).createRecord(props, opts); + } + /** + * Fired during {@link Container#destroy}. See + * {@link Container~beforeDestroyListener} for how to listen for this event. + * + * @event Container#beforeDestroy + * @see Container~beforeDestroyListener + * @see Container#destroy + */ - /** - * Wrapper for {@link Mapper#updateAll}. - * - * @example - * // Turn all of John's blog posts into drafts. - * import { Container } from 'js-data'; - * import RethinkDBAdapter from 'js-data-rethinkdb'; - * const store = new Container(); - * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); - * store.defineMapper('post'); - * - * const update = { status: draft: published_at: null }; - * const query = { userId: 1234 }; - * store.updateAll('post', update, query).then((posts) => { - * console.log(posts); // [...] - * }); - * - * @fires Container#beforeUpdateAll - * @fires Container#afterUpdateAll - * @method Container#updateAll - * @param {string} name Name of the {@link Mapper} to target. - * @param {object} update See {@link Mapper#updateAll}. - * @param {object} [query] See {@link Mapper#updateAll}. - * @param {object} [opts] See {@link Mapper#updateAll}. - * @returns {Promise} See {@link Mapper#updateAll}. - * @see Mapper#updateAll - * @since 3.0.0 - */ - 'updateAll', - /** - * Fired during {@link Container#updateMany}. See - * {@link Container~beforeUpdateManyListener} for how to listen for this event. - * - * @event Container#beforeUpdateMany - * @see Container~beforeUpdateManyListener - * @see Container#updateMany - */ + /** + * Callback signature for the {@link Container#event:beforeDestroy} event. + * + * @example + * function onBeforeDestroy (mapperName, id, opts) { + * // do something + * } + * store.on('beforeDestroy', onBeforeDestroy); + * + * @callback Container~beforeDestroyListener + * @param {string} name The `name` argument received by {@link Mapper#beforeDestroy}. + * @param {string|number} id The `id` argument received by {@link Mapper#beforeDestroy}. + * @param {object} opts The `opts` argument received by {@link Mapper#beforeDestroy}. + * @see Container#event:beforeDestroy + * @see Container#destroy + * @since 3.0.0 + */ - /** - * Callback signature for the {@link Container#event:beforeUpdateMany} event. - * - * @example - * function onBeforeUpdateMany (mapperName, records, opts) { - * // do something - * } - * store.on('beforeUpdateMany', onBeforeUpdateMany); - * - * @callback Container~beforeUpdateManyListener - * @param {string} name The `name` argument received by {@link Mapper#beforeUpdateMany}. - * @param {object} records The `records` argument received by {@link Mapper#beforeUpdateMany}. - * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdateMany}. - * @see Container#event:beforeUpdateMany - * @see Container#updateMany - * @since 3.0.0 - */ + /** + * Fired during {@link Container#destroy}. See + * {@link Container~afterDestroyListener} for how to listen for this event. + * + * @event Container#afterDestroy + * @see Container~afterDestroyListener + * @see Container#destroy + */ - /** - * Fired during {@link Container#updateMany}. See - * {@link Container~afterUpdateManyListener} for how to listen for this event. - * - * @event Container#afterUpdateMany - * @see Container~afterUpdateManyListener - * @see Container#updateMany - */ + /** + * Callback signature for the {@link Container#event:afterDestroy} event. + * + * @example + * function onAfterDestroy (mapperName, id, opts, result) { + * // do something + * } + * store.on('afterDestroy', onAfterDestroy); + * + * @callback Container~afterDestroyListener + * @param {string} name The `name` argument received by {@link Mapper#afterDestroy}. + * @param {string|number} id The `id` argument received by {@link Mapper#afterDestroy}. + * @param {object} opts The `opts` argument received by {@link Mapper#afterDestroy}. + * @param {object} result The `result` argument received by {@link Mapper#afterDestroy}. + * @see Container#event:afterDestroy + * @see Container#destroy + * @since 3.0.0 + */ - /** - * Callback signature for the {@link Container#event:afterUpdateMany} event. - * - * @example - * function onAfterUpdateMany (mapperName, records, opts, result) { - * // do something - * } - * store.on('afterUpdateMany', onAfterUpdateMany); - * - * @callback Container~afterUpdateManyListener - * @param {string} name The `name` argument received by {@link Mapper#afterUpdateMany}. - * @param {object} records The `records` argument received by {@link Mapper#afterUpdateMany}. - * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdateMany}. - * @param {object} result The `result` argument received by {@link Mapper#afterUpdateMany}. - * @see Container#event:afterUpdateMany - * @see Container#updateMany - * @since 3.0.0 - */ + /** + * Wrapper for {@link Mapper#destroy}. + * + * @example + * // Destroy a specific blog post + * import { Container } from 'js-data'; + * import RethinkDBAdapter from 'js-data-rethinkdb'; + * const store = new Container(); + * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); + * store.defineMapper('post'); + * + * store.destroy('post', 1234).then(() => { + * // Blog post #1234 has been destroyed + * }); + * + * @fires Container#beforeDestroy + * @fires Container#afterDestroy + * @method Container#destroy + * @param {string} name Name of the {@link Mapper} to target. + * @param {(string|number)} id See {@link Mapper#destroy}. + * @param {object} [opts] See {@link Mapper#destroy}. + * @returns {Promise} See {@link Mapper#destroy}. + * @see Mapper#destroy + * @since 3.0.0 + */ - /** - * Wrapper for {@link Mapper#updateMany}. - * - * @example - * import { Container } from 'js-data'; - * import RethinkDBAdapter from 'js-data-rethinkdb'; - * const store = new Container(); - * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); - * store.defineMapper('post'); - * - * store.updateMany('post', [ - * { id: 1234, status: 'draft' }, - * { id: 2468, status: 'published', published_at: new Date() } - * ]).then((posts) => { - * console.log(posts); // [...] - * }); - * - * @fires Container#beforeUpdateMany - * @fires Container#afterUpdateMany - * @method Container#updateMany - * @param {string} name Name of the {@link Mapper} to target. - * @param {(Object[]|Record[])} records See {@link Mapper#updateMany}. - * @param {object} [opts] See {@link Mapper#updateMany}. - * @returns {Promise} See {@link Mapper#updateMany}. - * @see Mapper#updateMany - * @since 3.0.0 - */ - 'updateMany', - /** - * Wrapper for {@link Mapper#validate}. - * - * @example - * import { Container } from 'js-data'; - * const store = new Container(); - * store.defineMapper('post', { - * schema: { - * properties: { - * name: { type: 'string' }, - * id: { type: 'string' } - * } - * } - * }); - * let errors = store.validate('post', { name: 'John' }); - * console.log(errors); // undefined - * errors = store.validate('post', { name: 123 }); - * console.log(errors); // [{ expected: 'one of (string)', actual: 'number', path: 'name' }] - * - * @method Container#validate - * @param {string} name Name of the {@link Mapper} to target. - * @param {(Object[]|Record[])} records See {@link Mapper#validate}. - * @param {object} [opts] See {@link Mapper#validate}. - * @returns {Promise} See {@link Mapper#validate}. - * @see Mapper#validate - * @since 3.0.0 - */ - 'validate']; - /** - * The `Container` class is a place to define and store {@link Mapper} instances. - * - * `Container` makes it easy to manage your Mappers. Without a container, you - * need to manage Mappers yourself, including resolving circular dependencies - * among relations. All Mappers in a container share the same adapters, so you - * don't have to register adapters for every single Mapper. - * - * @example Container#constructor - * // import { Container } from 'js-data'; - * const JSData = require('js-data'); - * const {Container} = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new Container(); - * - * @class Container - * @extends Component - * @param {object} [opts] Configuration options. - * @param {boolean} [opts.debug=false] See {@link Component#debug}. - * @param {Constructor} [opts.mapperClass] See {@link Container#mapperClass}. - * @param {object} [opts.mapperDefaults] See {@link Container#mapperDefaults}. - * @since 3.0.0 - */ + }, { + key: "destroy", + value: function destroy(name, id, opts) { + return this.getMapper(name).destroy(id, opts); + } + /** + * Fired during {@link Container#destroyAll}. See + * {@link Container~beforeDestroyAllListener} for how to listen for this event. + * + * @event Container#beforeDestroyAll + * @see Container~beforeDestroyAllListener + * @see Container#destroyAll + */ - function Container(opts) { - utils.classCallCheck(this, Container); - Component$1.call(this); - opts || (opts = {}); - Object.defineProperties(this, { - /** - * The adapters registered with this Container, which are also shared by all - * Mappers in this Container. - * - * @name Container#_adapters - * @see Container#registerAdapter - * @since 3.0.0 - * @type {Object} - */ - _adapters: { - value: {} - }, + /** + * Callback signature for the {@link Container#event:beforeDestroyAll} event. + * + * @example + * function onBeforeDestroyAll (mapperName, query, opts) { + * // do something + * } + * store.on('beforeDestroyAll', onBeforeDestroyAll); + * + * @callback Container~beforeDestroyAllListener + * @param {string} name The `name` argument received by {@link Mapper#beforeDestroyAll}. + * @param {object} query The `query` argument received by {@link Mapper#beforeDestroyAll}. + * @param {object} opts The `opts` argument received by {@link Mapper#beforeDestroyAll}. + * @see Container#event:beforeDestroyAll + * @see Container#destroyAll + * @since 3.0.0 + */ - /** - * The the mappers in this container - * - * @name Container#_mappers - * @see Mapper - * @since 3.0.0 - * @type {Object} + /** + * Fired during {@link Container#destroyAll}. See + * {@link Container~afterDestroyAllListener} for how to listen for this event. + * + * @event Container#afterDestroyAll + * @see Container~afterDestroyAllListener + * @see Container#destroyAll */ - _mappers: { - value: {} - }, - /** - * Constructor function to use in {@link Container#defineMapper} to create new - * {@link Mapper} instances. {@link Container#mapperClass} should extend - * {@link Mapper}. By default {@link Mapper} is used to instantiate Mappers. - * - * @example Container#mapperClass - * // import { Container, Mapper } from 'js-data'; - * const JSData = require('js-data'); - * const { Container, Mapper } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * class MyMapperClass extends Mapper { - * foo () { return 'bar' } - * } - * const store = new Container({ - * mapperClass: MyMapperClass - * }); - * store.defineMapper('user'); - * console.log(store.getMapper('user').foo()); - * - * @name Container#mapperClass - * @see Mapper - * @since 3.0.0 - * @type {Constructor} - */ - mapperClass: { - value: undefined, - writable: true - } - }); // Apply options provided by the user - - utils.fillIn(this, opts); - /** - * Defaults options to pass to {@link Container#mapperClass} when creating a - * new {@link Mapper}. - * - * @example Container#mapperDefaults - * // import { Container } from 'js-data'; - * const JSData = require('js-data'); - * const { Container } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new Container({ - * mapperDefaults: { - * idAttribute: '_id' - * } - * }); - * store.defineMapper('user'); - * console.log(store.getMapper('user').idAttribute); - * - * @default {} - * @name Container#mapperDefaults - * @since 3.0.0 - * @type {Object} - */ + /** + * Callback signature for the {@link Container#event:afterDestroyAll} event. + * + * @example + * function onAfterDestroyAll (mapperName, query, opts, result) { + * // do something + * } + * store.on('afterDestroyAll', onAfterDestroyAll); + * + * @callback Container~afterDestroyAllListener + * @param {string} name The `name` argument received by {@link Mapper#afterDestroyAll}. + * @param {object} query The `query` argument received by {@link Mapper#afterDestroyAll}. + * @param {object} opts The `opts` argument received by {@link Mapper#afterDestroyAll}. + * @param {object} result The `result` argument received by {@link Mapper#afterDestroyAll}. + * @see Container#event:afterDestroyAll + * @see Container#destroyAll + * @since 3.0.0 + */ - this.mapperDefaults = this.mapperDefaults || {}; // Use the Mapper class if the user didn't provide a mapperClass + /** + * Wrapper for {@link Mapper#destroyAll}. + * + * @example + * // Destroy all "draft" blog posts + * import { Container } from 'js-data'; + * import RethinkDBAdapter from 'js-data-rethinkdb'; + * const store = new Container(); + * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); + * store.defineMapper('post'); + * + * store.destroyAll('post', { status: 'draft' }).then(() => { + * // All "draft" blog posts have been destroyed + * }); + * + * @fires Container#beforeDestroyAll + * @fires Container#afterDestroyAll + * @method Container#destroyAll + * @param {string} name Name of the {@link Mapper} to target. + * @param {object} [query] See {@link Mapper#destroyAll}. + * @param {object} [opts] See {@link Mapper#destroyAll}. + * @returns {Promise} See {@link Mapper#destroyAll}. + * @see Mapper#destroyAll + * @since 3.0.0 + */ - this.mapperClass || (this.mapperClass = Mapper$1); - } - var props = { - constructor: Container, - - /** - * Register a new event listener on this Container. - * - * Proxy for {@link Component#on}. If an event was emitted by a {@link Mapper} - * in the Container, then the name of the {@link Mapper} will be prepended to - * the arugments passed to the listener. - * - * @example Container#on - * // import { Container } from 'js-data'; - * const JSData = require('js-data'); - * const { Container } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new Container(); - * store.on('foo', function (...args) { console.log(args.join(':')) }); - * store.defineMapper('user'); - * store.emit('foo', 'arg1', 'arg2'); - * store.getMapper('user').emit('foo', 'arg1', 'arg2'); - * - * @method Container#on - * @param {string} event Name of event to subsribe to. - * @param {Function} listener Listener function to handle the event. - * @param {*} [ctx] Optional content in which to invoke the listener. - * @since 3.0.0 - */ + }, { + key: "destroyAll", + value: function destroyAll(name, query, opts) { + return this.getMapper(name).destroyAll(query, opts); + } + /** + * Fired during {@link Container#find}. See + * {@link Container~beforeFindListener} for how to listen for this event. + * + * @event Container#beforeFind + * @see Container~beforeFindListener + * @see Container#find + */ - /** - * Used to bind to events emitted by mappers in this container. - * - * @method Container#_onMapperEvent - * @param {string} name Name of the mapper that emitted the event. - * @param {...*} [args] Args See {@link Mapper#emit}. - * @private - * @since 3.0.0 - */ - _onMapperEvent: function _onMapperEvent(name) { - for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { - args[_key - 1] = arguments[_key]; - } + /** + * Callback signature for the {@link Container#event:beforeFind} event. + * + * @example + * function onBeforeFind (mapperName, id, opts) { + * // do something + * } + * store.on('beforeFind', onBeforeFind); + * + * @callback Container~beforeFindListener + * @param {string} name The `name` argument received by {@link Mapper#beforeFind}. + * @param {string|number} id The `id` argument received by {@link Mapper#beforeFind}. + * @param {object} opts The `opts` argument received by {@link Mapper#beforeFind}. + * @see Container#event:beforeFind + * @see Container#find + * @since 3.0.0 + */ - var type = args.shift(); - this.emit.apply(this, [type, name].concat(args)); - }, + /** + * Fired during {@link Container#find}. See + * {@link Container~afterFindListener} for how to listen for this event. + * + * @event Container#afterFind + * @see Container~afterFindListener + * @see Container#find + */ - /** - * Return a container scoped to a particular mapper. - * - * @example Container#as - * // import { Container } from 'js-data'; - * const JSData = require('js-data'); - * const { Container } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new Container(); - * const UserMapper = store.defineMapper('user'); - * const UserStore = store.as('user'); - * - * const user1 = store.createRecord('user', { name: 'John' }); - * const user2 = UserStore.createRecord({ name: 'John' }); - * const user3 = UserMapper.createRecord({ name: 'John' }); - * console.log(user1 === user2); - * console.log(user2 === user3); - * console.log(user1 === user3); - * - * @method Container#as - * @param {string} name Name of the {@link Mapper}. - * @returns {Object} A container scoped to a particular mapper. - * @since 3.0.0 - */ - as: function as(name) { - var props = {}; - var original = this; - proxiedMapperMethods.forEach(function (method) { - props[method] = { - writable: true, - value: function value() { - for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { - args[_key2] = arguments[_key2]; - } + /** + * Callback signature for the {@link Container#event:afterFind} event. + * + * @example + * function onAfterFind (mapperName, id, opts, result) { + * // do something + * } + * store.on('afterFind', onAfterFind); + * + * @callback Container~afterFindListener + * @param {string} name The `name` argument received by {@link Mapper#afterFind}. + * @param {string|number} id The `id` argument received by {@link Mapper#afterFind}. + * @param {object} opts The `opts` argument received by {@link Mapper#afterFind}. + * @param {object} result The `result` argument received by {@link Mapper#afterFind}. + * @see Container#event:afterFind + * @see Container#find + * @since 3.0.0 + */ - return original[method].apply(original, [name].concat(args)); - } - }; - }); - props.getMapper = { - writable: true, - value: function value() { - return original.getMapper(name); - } - }; - return Object.create(this, props); - }, + /** + * Wrapper for {@link Mapper#find}. + * + * @example + * import { Container } from 'js-data'; + * import RethinkDBAdapter from 'js-data-rethinkdb'; + * const store = new Container(); + * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); + * store.defineMapper('post'); + * + * store.find('post', 1).then((post) => { + * console.log(post) // { id: 1, ...} + * }); + * + * @fires Container#beforeFind + * @fires Container#afterFind + * @method Container#find + * @param {string} name Name of the {@link Mapper} to target. + * @param {(string|number)} id See {@link Mapper#find}. + * @param {object} [opts] See {@link Mapper#find}. + * @returns {Promise} See {@link Mapper#find}. + * @see Mapper#find + * @since 3.0.0 + */ - /** - * Create a new mapper and register it in this container. - * - * @example Container#defineMapper - * // import { Container } from 'js-data'; - * const JSData = require('js-data'); - * const { Container } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new Container({ - * mapperDefaults: { foo: 'bar' } - * }); - * // Container#defineMapper returns a direct reference to the newly created - * // Mapper. - * const UserMapper = store.defineMapper('user'); - * console.log(UserMapper === store.getMapper('user')); - * console.log(UserMapper === store.as('user').getMapper()); - * console.log(UserMapper.foo); - * - * @method Container#defineMapper - * @param {string} name Name under which to register the new {@link Mapper}. - * {@link Mapper#name} will be set to this value. - * @param {object} [opts] Configuration options. Passed to - * {@link Container#mapperClass} when creating the new {@link Mapper}. - * @returns {Mapper} The newly created instance of {@link Mapper}. - * @see Container#as - * @since 3.0.0 - */ - defineMapper: function defineMapper(name, opts) { - var _this = this; + }, { + key: "find", + value: function find(name, id, opts) { + return this.getMapper(name).find(id, opts); + } + /** + * Fired during {@link Container#findAll}. See + * {@link Container~beforeFindAllListener} for how to listen for this event. + * + * @event Container#beforeFindAll + * @see Container~beforeFindAllListener + * @see Container#findAll + */ - // For backwards compatibility with defineResource - if (utils.isObject(name)) { - opts = name; - name = opts.name; - } + /** + * Callback signature for the {@link Container#event:beforeFindAll} event. + * + * @example + * function onBeforeFindAll (mapperName, query, opts) { + * // do something + * } + * store.on('beforeFindAll', onBeforeFindAll); + * + * @callback Container~beforeFindAllListener + * @param {string} name The `name` argument received by {@link Mapper#beforeFindAll}. + * @param {object} query The `query` argument received by {@link Mapper#beforeFindAll}. + * @param {object} opts The `opts` argument received by {@link Mapper#beforeFindAll}. + * @see Container#event:beforeFindAll + * @see Container#findAll + * @since 3.0.0 + */ - if (!utils.isString(name)) { - throw utils.err("".concat(DOMAIN$7, "#defineMapper"), 'name')(400, 'string', name); - } // Default values for arguments + /** + * Fired during {@link Container#findAll}. See + * {@link Container~afterFindAllListener} for how to listen for this event. + * + * @event Container#afterFindAll + * @see Container~afterFindAllListener + * @see Container#findAll + */ + /** + * Callback signature for the {@link Container#event:afterFindAll} event. + * + * @example + * function onAfterFindAll (mapperName, query, opts, result) { + * // do something + * } + * store.on('afterFindAll', onAfterFindAll); + * + * @callback Container~afterFindAllListener + * @param {string} name The `name` argument received by {@link Mapper#afterFindAll}. + * @param {object} query The `query` argument received by {@link Mapper#afterFindAll}. + * @param {object} opts The `opts` argument received by {@link Mapper#afterFindAll}. + * @param {object} result The `result` argument received by {@link Mapper#afterFindAll}. + * @see Container#event:afterFindAll + * @see Container#findAll + * @since 3.0.0 + */ - opts || (opts = {}); // Set Mapper#name + /** + * Wrapper for {@link Mapper#createRecord}. + * + * @example + * // Find all "published" blog posts + * import { Container } from 'js-data'; + * import RethinkDBAdapter from 'js-data-rethinkdb'; + * const store = new Container(); + * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); + * store.defineMapper('post'); + * + * store.findAll('post', { status: 'published' }).then((posts) => { + * console.log(posts); // [{ id: 1, ...}, ...] + * }); + * + * @fires Container#beforeFindAll + * @fires Container#afterFindAll + * @method Container#findAll + * @param {string} name Name of the {@link Mapper} to target. + * @param {object} [query] See {@link Mapper#findAll}. + * @param {object} [opts] See {@link Mapper#findAll}. + * @returns {Promise} See {@link Mapper#findAll}. + * @see Mapper#findAll + * @since 3.0.0 + */ - opts.name = name; - opts.relations || (opts.relations = {}); // Check if the user is overriding the datastore's default mapperClass + }, { + key: "findAll", + value: function findAll(name, query, opts) { + return this.getMapper(name).findAll(query, opts); + } + /** + * Wrapper for {@link Mapper#getSchema}. + * + * @method Container#getSchema + * @param {string} name Name of the {@link Mapper} to target. + * @returns {Schema} See {@link Mapper#getSchema}. + * @see Mapper#getSchema + * @since 3.0.0 + */ - var mapperClass = opts.mapperClass || this.mapperClass; - delete opts.mapperClass; // Apply the datastore's defaults to the options going into the mapper + }, { + key: "getSchema", + value: function getSchema(name) { + return this.getMapper(name).getSchema(); + } + /** + * Wrapper for {@link Mapper#is}. + * + * @example + * import { Container } from 'js-data'; + * const store = new Container(); + * store.defineMapper('post'); + * const post = store.createRecord(); + * + * console.log(store.is('post', post)); // true + * // Equivalent to what's above + * console.log(post instanceof store.getMapper('post').recordClass); // true + * + * @method Container#is + * @param {string} name Name of the {@link Mapper} to target. + * @param {Object|Record} record See {@link Mapper#is}. + * @returns {boolean} See {@link Mapper#is}. + * @see Mapper#is + * @since 3.0.0 + */ - utils.fillIn(opts, this.mapperDefaults); // Instantiate a mapper + }, { + key: "is", + value: function is(name, record) { + return this.getMapper(name).is(record); + } + /** + * Wrapper for {@link Mapper#sum}. + * + * @example + * import { Container } from 'js-data'; + * import RethinkDBAdapter from 'js-data-rethinkdb'; + * const store = new Container(); + * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); + * store.defineMapper('purchase_order'); + * + * store.sum('purchase_order', 'amount', { status: 'paid' }).then((amountPaid) => { + * console.log(amountPaid); // e.g. 451125.34 + * }); + * + * @method Container#sum + * @param {string} name Name of the {@link Mapper} to target. + * @param {string} field See {@link Mapper#sum}. + * @param {object} [query] See {@link Mapper#sum}. + * @param {object} [opts] See {@link Mapper#sum}. + * @returns {Promise} See {@link Mapper#sum}. + * @see Mapper#sum + * @since 3.0.0 + */ - var mapper = this._mappers[name] = new mapperClass(opts); // eslint-disable-line + }, { + key: "sum", + value: function sum(name, field, query, opts) { + return this.getMapper(name).sum(field, query, opts); + } + /** + * Wrapper for {@link Mapper#toJSON}. + * + * @example + * import { Container } from 'js-data'; + * import RethinkDBAdapter from 'js-data-rethinkdb'; + * const store = new Container(); + * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); + * store.defineMapper('person', { + * schema: { + * properties: { + * name: { type: 'string' }, + * id: { type: 'string' } + * } + * } + * }); + * const person = store.createRecord('person', { id: 1, name: 'John', foo: 'bar' }); + * // "foo" is stripped by toJSON() + * console.log(store.toJSON('person', person)); // {"id":1,"name":"John"} + * + * store.defineMapper('personRelaxed', { + * schema: { + * properties: { + * name: { type: 'string' }, + * id: { type: 'string' } + * }, + * additionalProperties: true + * } + * }); + * const person2 = store.createRecord('personRelaxed', { id: 1, name: 'John', foo: 'bar' }); + * // "foo" is not stripped by toJSON + * console.log(store.toJSON('personRelaxed', person2)); // {"id":1,"name":"John","foo":"bar"} + * + * @method Container#toJSON + * @param {string} name Name of the {@link Mapper} to target. + * @param {Record|Record[]} records See {@link Mapper#toJSON}. + * @param {object} [opts] See {@link Mapper#toJSON}. + * @returns {Object|Object[]} See {@link Mapper#toJSON}. + * @see Mapper#toJSON + * @since 3.0.0 + */ - mapper.relations || (mapper.relations = {}); // Make sure the mapper's name is set + }, { + key: "toJSON", + value: function toJSON(name, records, opts) { + return this.getMapper(name).toJSON(records, opts); + } + /** + * Fired during {@link Container#update}. See + * {@link Container~beforeUpdateListener} for how to listen for this event. + * + * @event Container#beforeUpdate + * @see Container~beforeUpdateListener + * @see Container#update + */ - mapper.name = name; // All mappers in this datastore will share adapters + /** + * Callback signature for the {@link Container#event:beforeUpdate} event. + * + * @example + * function onBeforeUpdate (mapperName, id, props, opts) { + * // do something + * } + * store.on('beforeUpdate', onBeforeUpdate); + * + * @callback Container~beforeUpdateListener + * @param {string} name The `name` argument received by {@link Mapper#beforeUpdate}. + * @param {string|number} id The `id` argument received by {@link Mapper#beforeUpdate}. + * @param {object} props The `props` argument received by {@link Mapper#beforeUpdate}. + * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdate}. + * @see Container#event:beforeUpdate + * @see Container#update + * @since 3.0.0 + */ - mapper._adapters = this.getAdapters(); - mapper.datastore = this; - mapper.on('all', function () { - for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { - args[_key3] = arguments[_key3]; - } + /** + * Fired during {@link Container#update}. See + * {@link Container~afterUpdateListener} for how to listen for this event. + * + * @event Container#afterUpdate + * @see Container~afterUpdateListener + * @see Container#update + */ - return _this._onMapperEvent.apply(_this, [name].concat(args)); - }); - mapper.defineRelations(); - return mapper; - }, - defineResource: function defineResource(name, opts) { - console.warn('DEPRECATED: defineResource is deprecated, use defineMapper instead'); - return this.defineMapper(name, opts); - }, + /** + * Callback signature for the {@link Container#event:afterUpdate} event. + * + * @example + * function onAfterUpdate (mapperName, id, props, opts, result) { + * // do something + * } + * store.on('afterUpdate', onAfterUpdate); + * + * @callback Container~afterUpdateListener + * @param {string} name The `name` argument received by {@link Mapper#afterUpdate}. + * @param {string|number} id The `id` argument received by {@link Mapper#afterUpdate}. + * @param {object} props The `props` argument received by {@link Mapper#afterUpdate}. + * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdate}. + * @param {object} result The `result` argument received by {@link Mapper#afterUpdate}. + * @see Container#event:afterUpdate + * @see Container#update + * @since 3.0.0 + */ - /** - * Return the registered adapter with the given name or the default adapter if - * no name is provided. - * - * @method Container#getAdapter - * @param {string} [name] The name of the adapter to retrieve. - * @returns {Adapter} The adapter. - * @since 3.0.0 - */ - getAdapter: function getAdapter(name) { - var adapter = this.getAdapterName(name); + /** + * Wrapper for {@link Mapper#update}. + * + * @example + * import { Container } from 'js-data'; + * import RethinkDBAdapter from 'js-data-rethinkdb'; + * const store = new Container(); + * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); + * store.defineMapper('post'); + * + * store.update('post', 1234, { + * status: 'published', + * published_at: new Date() + * }).then((post) => { + * console.log(post); // { id: 1234, status: 'published', ... } + * }); + * + * @fires Container#beforeUpdate + * @fires Container#afterUpdate + * @method Container#update + * @param {string} name Name of the {@link Mapper} to target. + * @param {(string|number)} id See {@link Mapper#update}. + * @param {object} props See {@link Mapper#update}. + * @param {object} [opts] See {@link Mapper#update}. + * @returns {Promise} See {@link Mapper#update}. + * @see Mapper#update + * @since 3.0.0 + * @tutorial ["http://www.js-data.io/v3.0/docs/saving-data","Saving data"] + */ - if (!adapter) { - throw utils.err("".concat(DOMAIN$7, "#getAdapter"), 'name')(400, 'string', name); - } + }, { + key: "update", + value: function update(name, id, props, opts) { + return this.getMapper(name).update(id, props, opts); + } + /** + * Fired during {@link Container#updateAll}. See + * {@link Container~beforeUpdateAllListener} for how to listen for this event. + * + * @event Container#beforeUpdateAll + * @see Container~beforeUpdateAllListener + * @see Container#updateAll + */ - return this.getAdapters()[adapter]; - }, + /** + * Callback signature for the {@link Container#event:beforeUpdateAll} event. + * + * @example + * function onBeforeUpdateAll (mapperName, props, query, opts) { + * // do something + * } + * store.on('beforeUpdateAll', onBeforeUpdateAll); + * + * @callback Container~beforeUpdateAllListener + * @param {string} name The `name` argument received by {@link Mapper#beforeUpdateAll}. + * @param {object} props The `props` argument received by {@link Mapper#beforeUpdateAll}. + * @param {object} query The `query` argument received by {@link Mapper#beforeUpdateAll}. + * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdateAll}. + * @see Container#event:beforeUpdateAll + * @see Container#updateAll + * @since 3.0.0 + */ - /** - * Return the name of a registered adapter based on the given name or options, - * or the name of the default adapter if no name provided. - * - * @method Container#getAdapterName - * @param {(Object|string)} [opts] The name of an adapter or options, if any. - * @returns {string} The name of the adapter. - * @since 3.0.0 - */ - getAdapterName: function getAdapterName(opts) { - opts || (opts = {}); + /** + * Fired during {@link Container#updateAll}. See + * {@link Container~afterUpdateAllListener} for how to listen for this event. + * + * @event Container#afterUpdateAll + * @see Container~afterUpdateAllListener + * @see Container#updateAll + */ - if (utils.isString(opts)) { - opts = { - adapter: opts - }; - } + /** + * Callback signature for the {@link Container#event:afterUpdateAll} event. + * + * @example + * function onAfterUpdateAll (mapperName, props, query, opts, result) { + * // do something + * } + * store.on('afterUpdateAll', onAfterUpdateAll); + * + * @callback Container~afterUpdateAllListener + * @param {string} name The `name` argument received by {@link Mapper#afterUpdateAll}. + * @param {object} props The `props` argument received by {@link Mapper#afterUpdateAll}. + * @param {object} query The `query` argument received by {@link Mapper#afterUpdateAll}. + * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdateAll}. + * @param {object} result The `result` argument received by {@link Mapper#afterUpdateAll}. + * @see Container#event:afterUpdateAll + * @see Container#updateAll + * @since 3.0.0 + */ - return opts.adapter || this.mapperDefaults.defaultAdapter; - }, + /** + * Wrapper for {@link Mapper#updateAll}. + * + * @example + * // Turn all of John's blog posts into drafts. + * import { Container } from 'js-data'; + * import RethinkDBAdapter from 'js-data-rethinkdb'; + * const store = new Container(); + * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); + * store.defineMapper('post'); + * + * const update = { status: draft: published_at: null }; + * const query = { userId: 1234 }; + * store.updateAll('post', update, query).then((posts) => { + * console.log(posts); // [...] + * }); + * + * @fires Container#beforeUpdateAll + * @fires Container#afterUpdateAll + * @method Container#updateAll + * @param {string} name Name of the {@link Mapper} to target. + * @param {object} props See {@link Mapper#updateAll}. + * @param {object} [query] See {@link Mapper#updateAll}. + * @param {object} [opts] See {@link Mapper#updateAll}. + * @returns {Promise} See {@link Mapper#updateAll}. + * @see Mapper#updateAll + * @since 3.0.0 + */ - /** - * Return the registered adapters of this container. - * - * @method Container#getAdapters - * @returns {Adapter} - * @since 3.0.0 - */ - getAdapters: function getAdapters() { - return this._adapters; - }, + }, { + key: "updateAll", + value: function updateAll(name, props, query, opts) { + return this.getMapper(name).updateAll(props, query, opts); + } + /** + * Fired during {@link Container#updateMany}. See + * {@link Container~beforeUpdateManyListener} for how to listen for this event. + * + * @event Container#beforeUpdateMany + * @see Container~beforeUpdateManyListener + * @see Container#updateMany + */ - /** - * Return the mapper registered under the specified name. - * - * @example Container#getMapper - * // import { Container } from 'js-data'; - * const JSData = require('js-data'); - * const { Container } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new Container(); - * // Container#defineMapper returns a direct reference to the newly created - * // Mapper. - * const UserMapper = store.defineMapper('user'); - * console.log(UserMapper === store.getMapper('user')); - * console.log(UserMapper === store.as('user').getMapper()); - * store.getMapper('profile'); // throws Error, there is no mapper with name "profile" - * - * @method Container#getMapper - * @param {string} name {@link Mapper#name}. - * @returns {Mapper} - * @since 3.0.0 - */ - getMapper: function getMapper(name) { - var mapper = this.getMapperByName(name); + /** + * Callback signature for the {@link Container#event:beforeUpdateMany} event. + * + * @example + * function onBeforeUpdateMany (mapperName, records, opts) { + * // do something + * } + * store.on('beforeUpdateMany', onBeforeUpdateMany); + * + * @callback Container~beforeUpdateManyListener + * @param {string} name The `name` argument received by {@link Mapper#beforeUpdateMany}. + * @param {object} records The `records` argument received by {@link Mapper#beforeUpdateMany}. + * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdateMany}. + * @see Container#event:beforeUpdateMany + * @see Container#updateMany + * @since 3.0.0 + */ - if (!mapper) { - throw utils.err("".concat(DOMAIN$7, "#getMapper"), name)(404, 'mapper'); - } + /** + * Fired during {@link Container#updateMany}. See + * {@link Container~afterUpdateManyListener} for how to listen for this event. + * + * @event Container#afterUpdateMany + * @see Container~afterUpdateManyListener + * @see Container#updateMany + */ - return mapper; - }, + /** + * Callback signature for the {@link Container#event:afterUpdateMany} event. + * + * @example + * function onAfterUpdateMany (mapperName, records, opts, result) { + * // do something + * } + * store.on('afterUpdateMany', onAfterUpdateMany); + * + * @callback Container~afterUpdateManyListener + * @param {string} name The `name` argument received by {@link Mapper#afterUpdateMany}. + * @param {object} records The `records` argument received by {@link Mapper#afterUpdateMany}. + * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdateMany}. + * @param {object} result The `result` argument received by {@link Mapper#afterUpdateMany}. + * @see Container#event:afterUpdateMany + * @see Container#updateMany + * @since 3.0.0 + */ - /** - * Return the mapper registered under the specified name. - * Doesn't throw error if mapper doesn't exist. - * - * @example Container#getMapperByName - * // import { Container } from 'js-data'; - * const JSData = require('js-data'); - * const { Container } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new Container(); - * // Container#defineMapper returns a direct reference to the newly created - * // Mapper. - * const UserMapper = store.defineMapper('user'); - * console.log(UserMapper === store.getMapper('user')); - * console.log(UserMapper === store.as('user').getMapper()); - * console.log(store.getMapper('profile')); // Does NOT throw an error - * - * @method Container#getMapperByName - * @param {string} name {@link Mapper#name}. - * @returns {Mapper} - * @since 3.0.0 - */ - getMapperByName: function getMapperByName(name) { - return this._mappers[name]; - }, + /** + * Wrapper for {@link Mapper#updateMany}. + * + * @example + * import { Container } from 'js-data'; + * import RethinkDBAdapter from 'js-data-rethinkdb'; + * const store = new Container(); + * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); + * store.defineMapper('post'); + * + * store.updateMany('post', [ + * { id: 1234, status: 'draft' }, + * { id: 2468, status: 'published', published_at: new Date() } + * ]).then((posts) => { + * console.log(posts); // [...] + * }); + * + * @fires Container#beforeUpdateMany + * @fires Container#afterUpdateMany + * @method Container#updateMany + * @param {string} name Name of the {@link Mapper} to target. + * @param {(Object[]|Record[])} records See {@link Mapper#updateMany}. + * @param {object} [opts] See {@link Mapper#updateMany}. + * @returns {Promise} See {@link Mapper#updateMany}. + * @see Mapper#updateMany + * @since 3.0.0 + */ - /** - * Register an adapter on this container under the given name. Adapters - * registered on a container are shared by all mappers in the container. - * - * @example - * import { Container } from 'js-data'; - * import { RethinkDBAdapter } from 'js-data-rethinkdb'; - * const store = new Container(); - * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); - * - * @method Container#registerAdapter - * @param {string} name The name of the adapter to register. - * @param {Adapter} adapter The adapter to register. - * @param {object} [opts] Configuration options. - * @param {boolean} [opts.default=false] Whether to make the adapter the - * default adapter for all Mappers in this container. - * @since 3.0.0 - * @tutorial ["http://www.js-data.io/v3.0/docs/connecting-to-a-data-source","Connecting to a data source"] - */ - registerAdapter: function registerAdapter(name, adapter, opts) { - opts || (opts = {}); - this.getAdapters()[name] = adapter; // Optionally make it the default adapter for the target. - - if (opts === true || opts.default) { - this.mapperDefaults.defaultAdapter = name; - utils.forOwn(this._mappers, function (mapper) { - mapper.defaultAdapter = name; - }); - } - } - }; - proxiedMapperMethods.forEach(function (method) { - props[method] = function (name) { - var _this$getMapper; + }, { + key: "updateMany", + value: function updateMany(name, record, opts) { + return this.getMapper(name).updateMany(record, opts); + } + /** + * Wrapper for {@link Mapper#validate}. + * + * @example + * import { Container } from 'js-data'; + * const store = new Container(); + * store.defineMapper('post', { + * schema: { + * properties: { + * name: { type: 'string' }, + * id: { type: 'string' } + * } + * } + * }); + * let errors = store.validate('post', { name: 'John' }); + * console.log(errors); // undefined + * errors = store.validate('post', { name: 123 }); + * console.log(errors); // [{ expected: 'one of (string)', actual: 'number', path: 'name' }] + * + * @method Container#validate + * @param {string} name Name of the {@link Mapper} to target. + * @param {(Object[]|Record[])} records See {@link Mapper#validate}. + * @param {object} [opts] See {@link Mapper#validate}. + * @returns {Promise} See {@link Mapper#validate}. + * @see Mapper#validate + * @since 3.0.0 + */ - for (var _len4 = arguments.length, args = new Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) { - args[_key4 - 1] = arguments[_key4]; + }, { + key: "validate", + value: function validate(name, record, opts) { + return this.getMapper(name).validate(record, opts); } + }]); - return (_this$getMapper = this.getMapper(name))[method].apply(_this$getMapper, args); - }; - }); - Component$1.extend(props); - /** - * Create a subclass of this Container: - * @example Container.extend - * const JSData = require('js-data'); - * const { Container } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * // Extend the class using ES2015 class syntax. - * class CustomContainerClass extends Container { - * foo () { return 'bar' } - * static beep () { return 'boop' } - * } - * const customContainer = new CustomContainerClass(); - * console.log(customContainer.foo()); - * console.log(CustomContainerClass.beep()); - * - * // Extend the class using alternate method. - * const OtherContainerClass = Container.extend({ - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }); - * const otherContainer = new OtherContainerClass(); - * console.log(otherContainer.foo()); - * console.log(OtherContainerClass.beep()); - * - * // Extend the class, providing a custom constructor. - * function AnotherContainerClass () { - * Container.call(this); - * this.created_at = new Date().getTime(); - * } - * Container.extend({ - * constructor: AnotherContainerClass, - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }) - * const anotherContainer = new AnotherContainerClass(); - * console.log(anotherContainer.created_at); - * console.log(anotherContainer.foo()); - * console.log(AnotherContainerClass.beep()); - * - * @method Container.extend - * @param {object} [props={}] Properties to add to the prototype of the - * subclass. - * @param {object} [props.constructor] Provide a custom constructor function - * to be used as the subclass itself. - * @param {object} [classProps={}] Static properties to add to the subclass. - * @returns {Constructor} Subclass of this Container class. - * @since 3.0.0 - */ + return Container; + }(Component); var DOMAIN$8 = 'SimpleStore'; - var proxiedCollectionMethods = [ - /** - * Wrapper for {@link Collection#add}. - * - * @example SimpleStore#add - * const JSData = require('js-data'); - * const { SimpleStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new SimpleStore(); - * store.defineMapper('book'); - * - * // Add one book to the in-memory store: - * store.add('book', { id: 1, title: 'Respect your Data' }); - * // Add multiple books to the in-memory store: - * store.add('book', [ - * { id: 2, title: 'Easy data recipes' }, - * { id: 3, title: 'Active Record 101' } - * ]); - * - * @fires SimpleStore#add - * @method SimpleStore#add - * @param {(string|number)} name Name of the {@link Mapper} to target. - * @param {(Object|Object[]|Record|Record[])} data See {@link Collection#add}. - * @param {object} [opts] Configuration options. See {@link Collection#add}. - * @returns {(Object|Object[]|Record|Record[])} See {@link Collection#add}. - * @see Collection#add - * @see Collection#add - * @since 3.0.0 - */ - 'add', - /** - * Wrapper for {@link Collection#between}. - * - * @example - * // Get all users ages 18 to 30 - * const users = store.between('user', 18, 30, { index: 'age' }); - * - * @example - * // Same as above - * const users = store.between('user', [18], [30], { index: 'age' }); - * - * @method SimpleStore#between - * @param {(string|number)} name Name of the {@link Mapper} to target. - * @param {array} leftKeys See {@link Collection#between}. - * @param {array} rightKeys See {@link Collection#between}. - * @param {object} [opts] Configuration options. See {@link Collection#between}. - * @returns {Object[]|Record[]} See {@link Collection#between}. - * @see Collection#between - * @see Collection#between - * @since 3.0.0 - */ - 'between', - /** - * Wrapper for {@link Collection#createIndex}. - * - * @example - * // Index users by age - * store.createIndex('user', 'age'); - * - * @example - * // Index users by status and role - * store.createIndex('user', 'statusAndRole', ['status', 'role']); - * - * @method SimpleStore#createIndex - * @param {(string|number)} name Name of the {@link Mapper} to target. - * @param {string} name See {@link Collection#createIndex}. - * @param {string[]} [fieldList] See {@link Collection#createIndex}. - * @see Collection#createIndex - * @see Collection#createIndex - * @since 3.0.0 - */ - 'createIndex', - /** - * Wrapper for {@link Collection#filter}. - * - * @example SimpleStore#filter - * const JSData = require('js-data'); - * const { SimpleStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new SimpleStore(); - * store.defineMapper('post'); - * store.add('post', [ - * { id: 1, status: 'draft', created_at_timestamp: new Date().getTime() } - * ]); - * - * // Get the draft posts created less than three months ago - * let posts = store.filter('post', { - * where: { - * status: { - * '==': 'draft' - * }, - * created_at_timestamp: { - * '>=': (new Date().getTime() - (1000 \* 60 \* 60 \* 24 \* 30 \* 3)) // 3 months ago - * } - * } - * }); - * console.log(posts); - * - * // Use a custom filter function - * posts = store.filter('post', function (post) { return post.id % 2 === 0 }); - * - * @method SimpleStore#filter - * @param {(string|number)} name Name of the {@link Mapper} to target. - * @param {(Object|Function)} [queryOrFn={}] See {@link Collection#filter}. - * @param {object} [thisArg] See {@link Collection#filter}. - * @returns {Array} See {@link Collection#filter}. - * @see Collection#filter - * @see Collection#filter - * @since 3.0.0 - */ - 'filter', - /** - * Wrapper for {@link Collection#get}. - * - * @example SimpleStore#get - * const JSData = require('js-data'); - * const { SimpleStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new SimpleStore(); - * store.defineMapper('post'); - * store.add('post', [ - * { id: 1, status: 'draft', created_at_timestamp: new Date().getTime() } - * ]); - * - * console.log(store.get('post', 1)); // {...} - * console.log(store.get('post', 2)); // undefined - * - * @method SimpleStore#get - * @param {(string|number)} name Name of the {@link Mapper} to target. - * @param {(string|number)} id See {@link Collection#get}. - * @returns {(Object|Record)} See {@link Collection#get}. - * @see Collection#get - * @see Collection#get - * @since 3.0.0 - */ - 'get', - /** - * Wrapper for {@link Collection#getAll}. - * - * @example - * // Get the posts where "status" is "draft" or "inReview" - * const posts = store.getAll('post', 'draft', 'inReview', { index: 'status' }); - * - * @example - * // Same as above - * const posts = store.getAll('post', ['draft'], ['inReview'], { index: 'status' }); - * - * @method SimpleStore#getAll - * @param {(string|number)} name Name of the {@link Mapper} to target. - * @param {...Array} [keyList] See {@link Collection#getAll}. - * @param {object} [opts] See {@link Collection#getAll}. - * @returns {Array} See {@link Collection#getAll}. - * @see Collection#getAll - * @see Collection#getAll - * @since 3.0.0 - */ - 'getAll', - /** - * Wrapper for {@link Collection#prune}. - * - * @method SimpleStore#prune - * @param {object} [opts] See {@link Collection#prune}. - * @returns {Array} See {@link Collection#prune}. - * @see Collection#prune - * @see Collection#prune - * @since 3.0.0 - */ - 'prune', - /** - * Wrapper for {@link Collection#query}. - * - * @example - * // Grab page 2 of users between ages 18 and 30 - * store.query('user') - * .between(18, 30, { index: 'age' }) // between ages 18 and 30 - * .skip(10) // second page - * .limit(10) // page size - * .run(); - * - * @method SimpleStore#query - * @param {(string|number)} name Name of the {@link Mapper} to target. - * @returns {Query} See {@link Collection#query}. - * @see Collection#query - * @see Collection#query - * @since 3.0.0 - */ - 'query', - /** - * Wrapper for {@link Collection#toJSON}. - * - * @example - * store.defineMapper('post', { - * schema: { - * properties: { - * id: { type: 'number' }, - * title: { type: 'string' } - * } - * } - * }); - * store.add('post', [ - * { id: 1, status: 'published', title: 'Respect your Data' }, - * { id: 2, status: 'draft', title: 'Connecting to a data source' } - * ]); - * console.log(store.toJSON('post')); - * const draftsJSON = store.query('post') - * .filter({ status: 'draft' }) - * .mapCall('toJSON') - * .run(); - * - * @method SimpleStore#toJSON - * @param {(string|number)} name Name of the {@link Mapper} to target. - * @param {object} [opts] See {@link Collection#toJSON}. - * @returns {Array} See {@link Collection#toJSON}. - * @see Collection#toJSON - * @see Collection#toJSON - * @since 3.0.0 - */ - 'toJSON', - /** - * Wrapper for {@link Collection#unsaved}. - * - * @method SimpleStore#unsaved - * @returns {Array} See {@link Collection#unsaved}. - * @see Collection#unsaved - * @see Collection#unsaved - * @since 3.0.0 - */ - 'unsaved']; + var proxiedCollectionMethods = ['add', 'between', 'createIndex', 'filter', 'get', 'getAll', 'prune', 'query', 'toJSON', 'unsaved']; var ownMethodsForScoping = ['addToCache', 'cachedFind', 'cachedFindAll', 'cacheFind', 'cacheFindAll', 'hashQuery']; var cachedFn = function cachedFn(name, hashOrId, opts) { @@ -11814,2730 +11187,2845 @@ }; var SIMPLESTORE_DEFAULTS = { - /** - * Whether to use the pending query if a `find` request for the specified - * record is currently underway. Can be set to `true`, `false`, or to a - * function that returns `true` or `false`. - * - * @default true - * @name SimpleStore#usePendingFind - * @since 3.0.0 - * @type {boolean|Function} + /** + * Whether to use the pending query if a `find` request for the specified + * record is currently underway. Can be set to `true`, `false`, or to a + * function that returns `true` or `false`. + * + * @default true + * @name SimpleStore#usePendingFind + * @since 3.0.0 + * @type {boolean|Function} */ usePendingFind: true, - /** - * Whether to use the pending query if a `findAll` request for the given query - * is currently underway. Can be set to `true`, `false`, or to a function that - * returns `true` or `false`. - * - * @default true - * @name SimpleStore#usePendingFindAll - * @since 3.0.0 - * @type {boolean|Function} + /** + * Whether to use the pending query if a `findAll` request for the given query + * is currently underway. Can be set to `true`, `false`, or to a function that + * returns `true` or `false`. + * + * @default true + * @name SimpleStore#usePendingFindAll + * @since 3.0.0 + * @type {boolean|Function} */ usePendingFindAll: true }; - /** - * The `SimpleStore` class is an extension of {@link Container}. Not only does - * `SimpleStore` manage mappers, but also collections. `SimpleStore` implements the - * asynchronous {@link Mapper} methods, such as {@link Mapper#find} and - * {@link Mapper#create}. If you use the asynchronous `SimpleStore` methods - * instead of calling them directly on the mappers, then the results of the - * method calls will be inserted into the store's collections. You can think of - * a `SimpleStore` as an [Identity Map](https://en.wikipedia.org/wiki/Identity_map_pattern) - * for the [ORM](https://en.wikipedia.org/wiki/Object-relational_mapping) - * (the Mappers). - * - * ```javascript - * import { SimpleStore } from 'js-data'; - * ``` - * - * @example - * import { SimpleStore } from 'js-data'; - * import { HttpAdapter } from 'js-data-http'; - * const store = new SimpleStore(); - * - * // SimpleStore#defineMapper returns a direct reference to the newly created - * // Mapper. - * const UserMapper = store.defineMapper('user'); - * - * // SimpleStore#as returns the store scoped to a particular Mapper. - * const UserStore = store.as('user'); - * - * // Call "find" on "UserMapper" (Stateless ORM) - * UserMapper.find(1).then((user) => { - * // retrieved a "user" record via the http adapter, but that's it - * - * // Call "find" on "store" targeting "user" (Stateful SimpleStore) - * return store.find('user', 1); // same as "UserStore.find(1)" - * }).then((user) => { - * // not only was a "user" record retrieved, but it was added to the - * // store's "user" collection - * const cachedUser = store.getCollection('user').get(1); - * console.log(user === cachedUser); // true - * }); - * - * @class SimpleStore - * @extends Container - * @param {object} [opts] Configuration options. See {@link Container}. - * @param {boolean} [opts.collectionClass={@link Collection}] See {@link SimpleStore#collectionClass}. - * @param {boolean} [opts.debug=false] See {@link Component#debug}. - * @param {boolean|Function} [opts.usePendingFind=true] See {@link SimpleStore#usePendingFind}. - * @param {boolean|Function} [opts.usePendingFindAll=true] See {@link SimpleStore#usePendingFindAll}. - * @returns {SimpleStore} - * @see Container - * @since 3.0.0 - * @tutorial ["http://www.js-data.io/v3.0/docs/components-of-jsdata#SimpleStore","Components of JSData: SimpleStore"] - * @tutorial ["http://www.js-data.io/v3.0/docs/working-with-the-SimpleStore","Working with the SimpleStore"] - * @tutorial ["http://www.js-data.io/v3.0/docs/jsdata-and-the-browser","Notes on using JSData in the Browser"] + /** + * The `SimpleStore` class is an extension of {@link Container}. Not only does + * `SimpleStore` manage mappers, but also collections. `SimpleStore` implements the + * asynchronous {@link Mapper} methods, such as {@link Mapper#find} and + * {@link Mapper#create}. If you use the asynchronous `SimpleStore` methods + * instead of calling them directly on the mappers, then the results of the + * method calls will be inserted into the store's collections. You can think of + * a `SimpleStore` as an [Identity Map](https://en.wikipedia.org/wiki/Identity_map_pattern) + * for the [ORM](https://en.wikipedia.org/wiki/Object-relational_mapping) + * (the Mappers). + * + * ```javascript + * import { SimpleStore } from 'js-data'; + * ``` + * + * @example + * import { SimpleStore } from 'js-data'; + * import { HttpAdapter } from 'js-data-http'; + * const store = new SimpleStore(); + * + * // SimpleStore#defineMapper returns a direct reference to the newly created + * // Mapper. + * const UserMapper = store.defineMapper('user'); + * + * // SimpleStore#as returns the store scoped to a particular Mapper. + * const UserStore = store.as('user'); + * + * // Call "find" on "UserMapper" (Stateless ORM) + * UserMapper.find(1).then((user) => { + * // retrieved a "user" record via the http adapter, but that's it + * + * // Call "find" on "store" targeting "user" (Stateful SimpleStore) + * return store.find('user', 1); // same as "UserStore.find(1)" + * }).then((user) => { + * // not only was a "user" record retrieved, but it was added to the + * // store's "user" collection + * const cachedUser = store.getCollection('user').get(1); + * console.log(user === cachedUser); // true + * }); + * + * @class SimpleStore + * @extends Container + * @param {object} [opts] Configuration options. See {@link Container}. + * @param {boolean} [opts.collectionClass={@link Collection}] See {@link SimpleStore#collectionClass}. + * @param {boolean} [opts.debug=false] See {@link Component#debug}. + * @param {boolean|Function} [opts.usePendingFind=true] See {@link SimpleStore#usePendingFind}. + * @param {boolean|Function} [opts.usePendingFindAll=true] See {@link SimpleStore#usePendingFindAll}. + * @returns {SimpleStore} + * @see Container + * @since 3.0.0 + * @tutorial ["http://www.js-data.io/v3.0/docs/components-of-jsdata#SimpleStore","Components of JSData: SimpleStore"] + * @tutorial ["http://www.js-data.io/v3.0/docs/working-with-the-SimpleStore","Working with the SimpleStore"] + * @tutorial ["http://www.js-data.io/v3.0/docs/jsdata-and-the-browser","Notes on using JSData in the Browser"] */ - function SimpleStore(opts) { - utils.classCallCheck(this, SimpleStore); - opts || (opts = {}); // Fill in any missing options with the defaults + var SimpleStore = + /*#__PURE__*/ + function (_Container) { + _inherits(SimpleStore, _Container); + + function SimpleStore() { + var _this; + + var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + + _classCallCheck(this, SimpleStore); + + _this = _possibleConstructorReturn(this, _getPrototypeOf(SimpleStore).call(this, Object.assign(Object.assign({}, SIMPLESTORE_DEFAULTS), opts))); + _this._collections = {}; + _this._completedQueries = {}; + _this._pendingQueries = {}; + /** + * Retrieve a cached `find` result, if any. This method is called during + * {@link SimpleStore#find} to determine if {@link Mapper#find} needs to be + * called. If this method returns `undefined` then {@link Mapper#find} will + * be called. Otherwise {@link SimpleStore#find} will immediately resolve with + * the return value of this method. + * + * When using {@link SimpleStore} in the browser, you can override this method + * to implement your own cache-busting strategy. + * + * @example + * const store = new SimpleStore({ + * cachedFind (mapperName, id, opts) { + * // Let's say for a particular Resource, we always want to pull fresh from the server + * if (mapperName === 'schedule') { + * // Return undefined to trigger a Mapper#find call + * return; + * } + * // Otherwise perform default behavior + * return SimpleStore.prototype.cachedFind.call(this, mapperName, id, opts); + * } + * }); + * + * @example + * // Extend using ES2015 class syntax. + * class MyStore extends SimpleStore { + * cachedFind (mapperName, id, opts) { + * // Let's say for a particular Resource, we always want to pull fresh from the server + * if (mapperName === 'schedule') { + * // Return undefined to trigger a Mapper#find call + * return; + * } + * // Otherwise perform default behavior + * return super.cachedFind(mapperName, id, opts); + * } + * } + * const store = new MyStore(); + * + * @method SimpleStore#cachedFind + * @param {string} name The `name` argument passed to {@link SimpleStore#find}. + * @param {(string|number)} id The `id` argument passed to {@link SimpleStore#find}. + * @param {object} opts The `opts` argument passed to {@link SimpleStore#find}. + * @since 3.0.0 + */ - utils.fillIn(opts, SIMPLESTORE_DEFAULTS); - Container.call(this, opts); - this.collectionClass = this.collectionClass || Collection$1; - this._collections = {}; - this._pendingQueries = {}; - this._completedQueries = {}; - } + _this.cachedFind = cachedFn; + /** + * Retrieve a cached `findAll` result, if any. This method is called during + * {@link SimpleStore#findAll} to determine if {@link Mapper#findAll} needs to be + * called. If this method returns `undefined` then {@link Mapper#findAll} will + * be called. Otherwise {@link SimpleStore#findAll} will immediately resolve with + * the return value of this method. + * + * When using {@link SimpleStore} in the browser, you can override this method + * to implement your own cache-busting strategy. + * + * @example + * const store = new SimpleStore({ + * cachedFindAll (mapperName, hash, opts) { + * // Let's say for a particular Resource, we always want to pull fresh from the server + * if (mapperName === 'schedule') { + * // Return undefined to trigger a Mapper#findAll call + * return undefined; + * } + * // Otherwise perform default behavior + * return SimpleStore.prototype.cachedFindAll.call(this, mapperName, hash, opts); + * } + * }); + * + * @example + * // Extend using ES2015 class syntax. + * class MyStore extends SimpleStore { + * cachedFindAll (mapperName, hash, opts) { + * // Let's say for a particular Resource, we always want to pull fresh from the server + * if (mapperName === 'schedule') { + * // Return undefined to trigger a Mapper#findAll call + * return undefined; + * } + * // Otherwise perform default behavior + * return super.cachedFindAll(mapperName, hash, opts); + * } + * } + * const store = new MyStore(); + * + * @method SimpleStore#cachedFindAll + * @param {string} name The `name` argument passed to {@link SimpleStore#findAll}. + * @param {string} hash The result of calling {@link SimpleStore#hashQuery} on + * the `query` argument passed to {@link SimpleStore#findAll}. + * @param {object} opts The `opts` argument passed to {@link SimpleStore#findAll}. + * @since 3.0.0 + */ - var props$1 = { - constructor: SimpleStore, - - /** - * Internal method used to handle Mapper responses. - * - * @method SimpleStore#_end - * @private - * @param {string} name Name of the {@link Collection} to which to - * add the data. - * @param {object} result The result from a Mapper. - * @param {object} [opts] Configuration options. - * @returns {(Object|Array)} Result. + _this.cachedFindAll = cachedFn; + _this.collectionClass = _this.collectionClass || Collection; + return _this; + } + /** + * Internal method used to handle Mapper responses. + * + * @method SimpleStore#_end + * @private + * @param {string} name Name of the {@link Collection} to which to + * add the data. + * @param {object} result The result from a Mapper. + * @param {object} [opts] Configuration options. + * @returns {(Object|Array)} Result. */ - _end: function _end(name, result, opts) { - var data = opts.raw ? result.data : result; - if (data && utils.isFunction(this.addToCache)) { - data = this.addToCache(name, data, opts); - if (opts.raw) { - result.data = data; - } else { - result = data; + _createClass(SimpleStore, [{ + key: "_end", + value: function _end(name, result, opts) { + var data = opts.raw ? result.data : result; + + if (data && utils.isFunction(this.addToCache)) { + data = this.addToCache(name, data, opts); + + if (opts.raw) { + result.data = data; + } else { + result = data; + } } + + return result; } + /** + * Register a new event listener on this SimpleStore. + * + * Proxy for {@link Container#on}. If an event was emitted by a Mapper or + * Collection in the SimpleStore, then the name of the Mapper or Collection will + * be prepended to the arugments passed to the provided event handler. + * + * @example + * // Listen for all "afterCreate" events in a SimpleStore + * store.on('afterCreate', (mapperName, props, opts, result) => { + * console.log(mapperName); // "post" + * console.log(props.id); // undefined + * console.log(result.id); // 1234 + * }); + * store.create('post', { title: 'Modeling your data' }).then((post) => { + * console.log(post.id); // 1234 + * }); + * + * @example + * // Listen for the "add" event on a collection + * store.on('add', (mapperName, records) => { + * console.log(records); // [...] + * }); + * + * @example + * // Listen for "change" events on a record + * store.on('change', (mapperName, record, changes) => { + * console.log(changes); // { changed: { title: 'Modeling your data' } } + * }); + * post.title = 'Modeling your data'; + * + * @method SimpleStore#on + * @param {string} event Name of event to subsribe to. + * @param {Function} listener Listener function to handle the event. + * @param {*} [ctx] Optional content in which to invoke the listener. + */ - return result; - }, + /** + * Used to bind to events emitted by collections in this store. + * + * @method SimpleStore#_onCollectionEvent + * @private + * @param {string} name Name of the collection that emitted the event. + * @param {...*} [args] Args passed to {@link Collection#emit}. + */ - /** - * Register a new event listener on this SimpleStore. - * - * Proxy for {@link Container#on}. If an event was emitted by a Mapper or - * Collection in the SimpleStore, then the name of the Mapper or Collection will - * be prepended to the arugments passed to the provided event handler. - * - * @example - * // Listen for all "afterCreate" events in a SimpleStore - * store.on('afterCreate', (mapperName, props, opts, result) => { - * console.log(mapperName); // "post" - * console.log(props.id); // undefined - * console.log(result.id); // 1234 - * }); - * store.create('post', { title: 'Modeling your data' }).then((post) => { - * console.log(post.id); // 1234 - * }); - * - * @example - * // Listen for the "add" event on a collection - * store.on('add', (mapperName, records) => { - * console.log(records); // [...] - * }); - * - * @example - * // Listen for "change" events on a record - * store.on('change', (mapperName, record, changes) => { - * console.log(changes); // { changed: { title: 'Modeling your data' } } - * }); - * post.title = 'Modeling your data'; - * - * @method SimpleStore#on - * @param {string} event Name of event to subsribe to. - * @param {Function} listener Listener function to handle the event. - * @param {*} [ctx] Optional content in which to invoke the listener. - */ + }, { + key: "_onCollectionEvent", + value: function _onCollectionEvent(name) { + for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + args[_key - 1] = arguments[_key]; + } - /** - * Used to bind to events emitted by collections in this store. - * - * @method SimpleStore#_onCollectionEvent - * @private - * @param {string} name Name of the collection that emitted the event. - * @param {...*} [args] Args passed to {@link Collection#emit}. - */ - _onCollectionEvent: function _onCollectionEvent(name) { - for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { - args[_key - 1] = arguments[_key]; + var type = args.shift(); + this.emit.apply(this, [type, name].concat(args)); + } + /** + * This method takes the data received from {@link SimpleStore#find}, + * {@link SimpleStore#findAll}, {@link SimpleStore#update}, etc., and adds the + * data to the store. _You don't need to call this method directly._ + * + * If you're using the http adapter and your response data is in an unexpected + * format, you may need to override this method so the right data gets added + * to the store. + * + * @example + * const store = new SimpleStore({ + * addToCache (mapperName, data, opts) { + * // Let's say for a particular Resource, response data is in a weird format + * if (name === 'comment') { + * // Re-assign the variable to add the correct records into the stores + * data = data.items; + * } + * // Now perform default behavior + * return SimpleStore.prototype.addToCache.call(this, mapperName, data, opts); + * } + * }); + * + * @example + * // Extend using ES2015 class syntax. + * class MyStore extends SimpleStore { + * addToCache (mapperName, data, opts) { + * // Let's say for a particular Resource, response data is in a weird format + * if (name === 'comment') { + * // Re-assign the variable to add the correct records into the stores + * data = data.items; + * } + * // Now perform default behavior + * return super.addToCache(mapperName, data, opts); + * } + * } + * const store = new MyStore(); + * + * @method SimpleStore#addToCache + * @param {string} name Name of the {@link Mapper} to target. + * @param {*} data Data from which data should be selected for add. + * @param {object} [opts] Configuration options. + */ + + }, { + key: "addToCache", + value: function addToCache(name, data, opts) { + return this.getCollection(name).add(data, opts); + } + /** + * Return the store scoped to a particular mapper/collection pair. + * + * @example SimpleStore.as + * const JSData = require('js-data'); + * const { SimpleStore } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new SimpleStore(); + * const UserMapper = store.defineMapper('user'); + * const UserStore = store.as('user'); + * + * const user1 = store.createRecord('user', { name: 'John' }); + * const user2 = UserStore.createRecord({ name: 'John' }); + * const user3 = UserMapper.createRecord({ name: 'John' }); + * console.log(user1 === user2); + * console.log(user2 === user3); + * console.log(user1 === user3); + * + * @method SimpleStore#as + * @param {string} name Name of the {@link Mapper}. + * @returns {Object} The store, scoped to a particular Mapper/Collection pair. + * @since 3.0.0 + */ + + }, { + key: "as", + value: function as(name) { + var props = {}; + var original = this; + var methods = ownMethodsForScoping.concat(proxiedMapperMethods).concat(proxiedCollectionMethods); + methods.forEach(function (method) { + props[method] = { + writable: true, + value: function value() { + for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { + args[_key2] = arguments[_key2]; + } + + return original[method].apply(original, [name].concat(args)); + } + }; + }); + props.getMapper = { + writable: true, + value: function value() { + return original.getMapper(name); + } + }; + props.getCollection = { + writable: true, + value: function value() { + return original.getCollection(name); + } + }; + return Object.create(this, props); + } + /** + * Mark a {@link Mapper#find} result as cached by adding an entry to + * {@link SimpleStore#_completedQueries}. By default, once a `find` entry is + * added it means subsequent calls to the same Resource with the same `id` + * argument will immediately resolve with the result of calling + * {@link SimpleStore#get} instead of delegating to {@link Mapper#find}. + * + * As part of implementing your own caching strategy, you may choose to + * override this method. + * + * @example + * const store = new SimpleStore({ + * cacheFind (mapperName, data, id, opts) { + * // Let's say for a particular Resource, we always want to pull fresh from the server + * if (mapperName === 'schedule') { + * // Return without saving an entry to SimpleStore#_completedQueries + * return; + * } + * // Otherwise perform default behavior + * return SimpleStore.prototype.cacheFind.call(this, mapperName, data, id, opts); + * } + * }); + * + * @example + * // Extend using ES2015 class syntax. + * class MyStore extends SimpleStore { + * cacheFind (mapperName, data, id, opts) { + * // Let's say for a particular Resource, we always want to pull fresh from the server + * if (mapperName === 'schedule') { + * // Return without saving an entry to SimpleStore#_completedQueries + * return; + * } + * // Otherwise perform default behavior + * return super.cacheFind(mapperName, data, id, opts); + * } + * } + * const store = new MyStore(); + * + * @method SimpleStore#cacheFind + * @param {string} name The `name` argument passed to {@link SimpleStore#find}. + * @param {*} data The result to cache. + * @param {(string|number)} id The `id` argument passed to {@link SimpleStore#find}. + * @param {object} opts The `opts` argument passed to {@link SimpleStore#find}. + * @since 3.0.0 + */ + + }, { + key: "cacheFind", + value: function cacheFind(name, data, id, opts) { + var _this2 = this; + + this._completedQueries[name][id] = function (name, id, opts) { + return _this2.get(name, id); + }; } + /** + * Mark a {@link Mapper#findAll} result as cached by adding an entry to + * {@link SimpleStore#_completedQueries}. By default, once a `findAll` entry is + * added it means subsequent calls to the same Resource with the same `query` + * argument will immediately resolve with the result of calling + * {@link SimpleStore#filter} instead of delegating to {@link Mapper#findAll}. + * + * As part of implementing your own caching strategy, you may choose to + * override this method. + * + * @example + * const store = new SimpleStore({ + * cachedFindAll (mapperName, data, hash, opts) { + * // Let's say for a particular Resource, we always want to pull fresh from the server + * if (mapperName === 'schedule') { + * // Return without saving an entry to SimpleStore#_completedQueries + * return; + * } + * // Otherwise perform default behavior. + * return SimpleStore.prototype.cachedFindAll.call(this, mapperName, data, hash, opts); + * } + * }); + * + * @example + * // Extend using ES2015 class syntax. + * class MyStore extends SimpleStore { + * cachedFindAll (mapperName, data, hash, opts) { + * // Let's say for a particular Resource, we always want to pull fresh from the server + * if (mapperName === 'schedule') { + * // Return without saving an entry to SimpleStore#_completedQueries + * return; + * } + * // Otherwise perform default behavior. + * return super.cachedFindAll(mapperName, data, hash, opts); + * } + * } + * const store = new MyStore(); + * + * @method SimpleStore#cacheFindAll + * @param {string} name The `name` argument passed to {@link SimpleStore#findAll}. + * @param {*} data The result to cache. + * @param {string} hash The result of calling {@link SimpleStore#hashQuery} on + * the `query` argument passed to {@link SimpleStore#findAll}. + * @param {object} opts The `opts` argument passed to {@link SimpleStore#findAll}. + * @since 3.0.0 + */ - var type = args.shift(); - this.emit.apply(this, [type, name].concat(args)); - }, + }, { + key: "cacheFindAll", + value: function cacheFindAll(name, data, hash, opts) { + var _this3 = this; + + this._completedQueries[name][hash] = function (name, hash, opts) { + return _this3.filter(name, utils.fromJson(hash)); + }; + } + /** + * Remove __all__ records from the in-memory store and reset + * {@link SimpleStore#_completedQueries}. + * + * @method SimpleStore#clear + * @returns {Object} Object containing all records that were in the store. + * @see SimpleStore#remove + * @see SimpleStore#removeAll + * @since 3.0.0 + */ - /** - * This method takes the data received from {@link SimpleStore#find}, - * {@link SimpleStore#findAll}, {@link SimpleStore#update}, etc., and adds the - * data to the store. _You don't need to call this method directly._ - * - * If you're using the http adapter and your response data is in an unexpected - * format, you may need to override this method so the right data gets added - * to the store. - * - * @example - * const store = new SimpleStore({ - * addToCache (mapperName, data, opts) { - * // Let's say for a particular Resource, response data is in a weird format - * if (name === 'comment') { - * // Re-assign the variable to add the correct records into the stores - * data = data.items; - * } - * // Now perform default behavior - * return SimpleStore.prototype.addToCache.call(this, mapperName, data, opts); - * } - * }); - * - * @example - * // Extend using ES2015 class syntax. - * class MyStore extends SimpleStore { - * addToCache (mapperName, data, opts) { - * // Let's say for a particular Resource, response data is in a weird format - * if (name === 'comment') { - * // Re-assign the variable to add the correct records into the stores - * data = data.items; - * } - * // Now perform default behavior - * return super.addToCache(mapperName, data, opts); - * } - * } - * const store = new MyStore(); - * - * @method SimpleStore#addToCache - * @param {string} name Name of the {@link Mapper} to target. - * @param {*} data Data from which data should be selected for add. - * @param {object} [opts] Configuration options. - */ - addToCache: function addToCache(name, data, opts) { - return this.getCollection(name).add(data, opts); - }, + }, { + key: "clear", + value: function clear() { + var _this4 = this; - /** - * Return the store scoped to a particular mapper/collection pair. - * - * @example SimpleStore.as - * const JSData = require('js-data'); - * const { SimpleStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new SimpleStore(); - * const UserMapper = store.defineMapper('user'); - * const UserStore = store.as('user'); - * - * const user1 = store.createRecord('user', { name: 'John' }); - * const user2 = UserStore.createRecord({ name: 'John' }); - * const user3 = UserMapper.createRecord({ name: 'John' }); - * console.log(user1 === user2); - * console.log(user2 === user3); - * console.log(user1 === user3); - * - * @method SimpleStore#as - * @param {string} name Name of the {@link Mapper}. - * @returns {Object} The store, scoped to a particular Mapper/Collection pair. - * @since 3.0.0 - */ - as: function as(name) { - var props = {}; - var original = this; - var methods = ownMethodsForScoping.concat(proxiedMapperMethods).concat(proxiedCollectionMethods); - methods.forEach(function (method) { - props[method] = { - writable: true, - value: function value() { - for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { - args[_key2] = arguments[_key2]; - } + var removed = {}; + utils.forOwn(this._collections, function (collection, name) { + removed[name] = collection.removeAll(); + _this4._completedQueries[name] = {}; + }); + return removed; + } + /** + * Fired during {@link SimpleStore#create}. See + * {@link SimpleStore~beforeCreateListener} for how to listen for this event. + * + * @event SimpleStore#beforeCreate + * @see SimpleStore~beforeCreateListener + * @see SimpleStore#create + */ - return original[method].apply(original, [name].concat(args)); - } - }; - }); - props.getMapper = { - writable: true, - value: function value() { - return original.getMapper(name); - } - }; - props.getCollection = { - writable: true, - value: function value() { - return original.getCollection(name); - } - }; - return Object.create(this, props); - }, + /** + * Callback signature for the {@link SimpleStore#event:beforeCreate} event. + * + * @example + * function onBeforeCreate (mapperName, props, opts) { + * // do something + * } + * store.on('beforeCreate', onBeforeCreate); + * + * @callback SimpleStore~beforeCreateListener + * @param {string} name The `name` argument received by {@link Mapper#beforeCreate}. + * @param {object} props The `props` argument received by {@link Mapper#beforeCreate}. + * @param {object} opts The `opts` argument received by {@link Mapper#beforeCreate}. + * @see SimpleStore#event:beforeCreate + * @see SimpleStore#create + * @since 3.0.0 + */ - /** - * Retrieve a cached `find` result, if any. This method is called during - * {@link SimpleStore#find} to determine if {@link Mapper#find} needs to be - * called. If this method returns `undefined` then {@link Mapper#find} will - * be called. Otherwise {@link SimpleStore#find} will immediately resolve with - * the return value of this method. - * - * When using {@link SimpleStore} in the browser, you can override this method - * to implement your own cache-busting strategy. - * - * @example - * const store = new SimpleStore({ - * cachedFind (mapperName, id, opts) { - * // Let's say for a particular Resource, we always want to pull fresh from the server - * if (mapperName === 'schedule') { - * // Return undefined to trigger a Mapper#find call - * return; - * } - * // Otherwise perform default behavior - * return SimpleStore.prototype.cachedFind.call(this, mapperName, id, opts); - * } - * }); - * - * @example - * // Extend using ES2015 class syntax. - * class MyStore extends SimpleStore { - * cachedFind (mapperName, id, opts) { - * // Let's say for a particular Resource, we always want to pull fresh from the server - * if (mapperName === 'schedule') { - * // Return undefined to trigger a Mapper#find call - * return; - * } - * // Otherwise perform default behavior - * return super.cachedFind(mapperName, id, opts); - * } - * } - * const store = new MyStore(); - * - * @method SimpleStore#cachedFind - * @param {string} name The `name` argument passed to {@link SimpleStore#find}. - * @param {(string|number)} id The `id` argument passed to {@link SimpleStore#find}. - * @param {object} opts The `opts` argument passed to {@link SimpleStore#find}. - * @since 3.0.0 - */ - cachedFind: cachedFn, - - /** - * Retrieve a cached `findAll` result, if any. This method is called during - * {@link SimpleStore#findAll} to determine if {@link Mapper#findAll} needs to be - * called. If this method returns `undefined` then {@link Mapper#findAll} will - * be called. Otherwise {@link SimpleStore#findAll} will immediately resolve with - * the return value of this method. - * - * When using {@link SimpleStore} in the browser, you can override this method - * to implement your own cache-busting strategy. - * - * @example - * const store = new SimpleStore({ - * cachedFindAll (mapperName, hash, opts) { - * // Let's say for a particular Resource, we always want to pull fresh from the server - * if (mapperName === 'schedule') { - * // Return undefined to trigger a Mapper#findAll call - * return undefined; - * } - * // Otherwise perform default behavior - * return SimpleStore.prototype.cachedFindAll.call(this, mapperName, hash, opts); - * } - * }); - * - * @example - * // Extend using ES2015 class syntax. - * class MyStore extends SimpleStore { - * cachedFindAll (mapperName, hash, opts) { - * // Let's say for a particular Resource, we always want to pull fresh from the server - * if (mapperName === 'schedule') { - * // Return undefined to trigger a Mapper#findAll call - * return undefined; - * } - * // Otherwise perform default behavior - * return super.cachedFindAll(mapperName, hash, opts); - * } - * } - * const store = new MyStore(); - * - * @method SimpleStore#cachedFindAll - * @param {string} name The `name` argument passed to {@link SimpleStore#findAll}. - * @param {string} hash The result of calling {@link SimpleStore#hashQuery} on - * the `query` argument passed to {@link SimpleStore#findAll}. - * @param {object} opts The `opts` argument passed to {@link SimpleStore#findAll}. - * @since 3.0.0 - */ - cachedFindAll: cachedFn, - - /** - * Mark a {@link Mapper#find} result as cached by adding an entry to - * {@link SimpleStore#_completedQueries}. By default, once a `find` entry is - * added it means subsequent calls to the same Resource with the same `id` - * argument will immediately resolve with the result of calling - * {@link SimpleStore#get} instead of delegating to {@link Mapper#find}. - * - * As part of implementing your own caching strategy, you may choose to - * override this method. - * - * @example - * const store = new SimpleStore({ - * cacheFind (mapperName, data, id, opts) { - * // Let's say for a particular Resource, we always want to pull fresh from the server - * if (mapperName === 'schedule') { - * // Return without saving an entry to SimpleStore#_completedQueries - * return; - * } - * // Otherwise perform default behavior - * return SimpleStore.prototype.cacheFind.call(this, mapperName, data, id, opts); - * } - * }); - * - * @example - * // Extend using ES2015 class syntax. - * class MyStore extends SimpleStore { - * cacheFind (mapperName, data, id, opts) { - * // Let's say for a particular Resource, we always want to pull fresh from the server - * if (mapperName === 'schedule') { - * // Return without saving an entry to SimpleStore#_completedQueries - * return; - * } - * // Otherwise perform default behavior - * return super.cacheFind(mapperName, data, id, opts); - * } - * } - * const store = new MyStore(); - * - * @method SimpleStore#cacheFind - * @param {string} name The `name` argument passed to {@link SimpleStore#find}. - * @param {*} data The result to cache. - * @param {(string|number)} id The `id` argument passed to {@link SimpleStore#find}. - * @param {object} opts The `opts` argument passed to {@link SimpleStore#find}. - * @since 3.0.0 - */ - cacheFind: function cacheFind(name, data, id, opts) { - var _this = this; + /** + * Fired during {@link SimpleStore#create}. See + * {@link SimpleStore~afterCreateListener} for how to listen for this event. + * + * @event SimpleStore#afterCreate + * @see SimpleStore~afterCreateListener + * @see SimpleStore#create + */ - this._completedQueries[name][id] = function (name, id, opts) { - return _this.get(name, id); - }; - }, + /** + * Callback signature for the {@link SimpleStore#event:afterCreate} event. + * + * @example + * function onAfterCreate (mapperName, props, opts, result) { + * // do something + * } + * store.on('afterCreate', onAfterCreate); + * + * @callback SimpleStore~afterCreateListener + * @param {string} name The `name` argument received by {@link Mapper#afterCreate}. + * @param {object} props The `props` argument received by {@link Mapper#afterCreate}. + * @param {object} opts The `opts` argument received by {@link Mapper#afterCreate}. + * @param {object} result The `result` argument received by {@link Mapper#afterCreate}. + * @see SimpleStore#event:afterCreate + * @see SimpleStore#create + * @since 3.0.0 + */ - /** - * Mark a {@link Mapper#findAll} result as cached by adding an entry to - * {@link SimpleStore#_completedQueries}. By default, once a `findAll` entry is - * added it means subsequent calls to the same Resource with the same `query` - * argument will immediately resolve with the result of calling - * {@link SimpleStore#filter} instead of delegating to {@link Mapper#findAll}. - * - * As part of implementing your own caching strategy, you may choose to - * override this method. - * - * @example - * const store = new SimpleStore({ - * cachedFindAll (mapperName, data, hash, opts) { - * // Let's say for a particular Resource, we always want to pull fresh from the server - * if (mapperName === 'schedule') { - * // Return without saving an entry to SimpleStore#_completedQueries - * return; - * } - * // Otherwise perform default behavior. - * return SimpleStore.prototype.cachedFindAll.call(this, mapperName, data, hash, opts); - * } - * }); - * - * @example - * // Extend using ES2015 class syntax. - * class MyStore extends SimpleStore { - * cachedFindAll (mapperName, data, hash, opts) { - * // Let's say for a particular Resource, we always want to pull fresh from the server - * if (mapperName === 'schedule') { - * // Return without saving an entry to SimpleStore#_completedQueries - * return; - * } - * // Otherwise perform default behavior. - * return super.cachedFindAll(mapperName, data, hash, opts); - * } - * } - * const store = new MyStore(); - * - * @method SimpleStore#cacheFindAll - * @param {string} name The `name` argument passed to {@link SimpleStore#findAll}. - * @param {*} data The result to cache. - * @param {string} hash The result of calling {@link SimpleStore#hashQuery} on - * the `query` argument passed to {@link SimpleStore#findAll}. - * @param {object} opts The `opts` argument passed to {@link SimpleStore#findAll}. - * @since 3.0.0 - */ - cacheFindAll: function cacheFindAll(name, data, hash, opts) { - var _this2 = this; + /** + * Wrapper for {@link Mapper#create}. Adds the created record to the store. + * + * @example + * import { SimpleStore } from 'js-data'; + * import { HttpAdapter } from 'js-data-http'; + * + * const store = new SimpleStore(); + * store.registerAdapter('http', new HttpAdapter(), { default: true }); + * + * store.defineMapper('book'); + * + * // Since this example uses the http adapter, we'll get something like: + * // + * // POST /book {"author_id":1234,...} + * store.create('book', { + * author_id: 1234, + * edition: 'First Edition', + * title: 'Respect your Data' + * }).then((book) => { + * console.log(book.id); // 120392 + * console.log(book.title); // "Respect your Data" + * }); + * + * @fires SimpleStore#beforeCreate + * @fires SimpleStore#afterCreate + * @fires SimpleStore#add + * @method SimpleStore#create + * @param {string} name Name of the {@link Mapper} to target. + * @param {object} record Passed to {@link Mapper#create}. + * @param {object} [opts] Passed to {@link Mapper#create}. See + * {@link Mapper#create} for more configuration options. + * @returns {Promise} Resolves with the result of the create. + * @since 3.0.0 + */ - this._completedQueries[name][hash] = function (name, hash, opts) { - return _this2.filter(name, utils.fromJson(hash)); - }; - }, + }, { + key: "create", + value: function create(name, record) { + var _this5 = this; - /** - * Remove __all__ records from the in-memory store and reset - * {@link SimpleStore#_completedQueries}. - * - * @method SimpleStore#clear - * @returns {Object} Object containing all records that were in the store. - * @see SimpleStore#remove - * @see SimpleStore#removeAll - * @since 3.0.0 - */ - clear: function clear() { - var _this3 = this; + var opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + return _get(_getPrototypeOf(SimpleStore.prototype), "create", this).call(this, name, record, opts).then(function (result) { + return _this5._end(name, result, opts); + }); + } + /** + * Fired during {@link SimpleStore#createMany}. See + * {@link SimpleStore~beforeCreateManyListener} for how to listen for this event. + * + * @event SimpleStore#beforeCreateMany + * @see SimpleStore~beforeCreateManyListener + * @see SimpleStore#createMany + */ - var removed = {}; - utils.forOwn(this._collections, function (collection, name) { - removed[name] = collection.removeAll(); - _this3._completedQueries[name] = {}; - }); - return removed; - }, + /** + * Callback signature for the {@link SimpleStore#event:beforeCreateMany} event. + * + * @example + * function onBeforeCreateMany (mapperName, records, opts) { + * // do something + * } + * store.on('beforeCreateMany', onBeforeCreateMany); + * + * @callback SimpleStore~beforeCreateManyListener + * @param {string} name The `name` argument received by {@link Mapper#beforeCreateMany}. + * @param {object} records The `records` argument received by {@link Mapper#beforeCreateMany}. + * @param {object} opts The `opts` argument received by {@link Mapper#beforeCreateMany}. + * @see SimpleStore#event:beforeCreateMany + * @see SimpleStore#createMany + * @since 3.0.0 + */ - /** - * Fired during {@link SimpleStore#create}. See - * {@link SimpleStore~beforeCreateListener} for how to listen for this event. - * - * @event SimpleStore#beforeCreate - * @see SimpleStore~beforeCreateListener - * @see SimpleStore#create - */ + /** + * Fired during {@link SimpleStore#createMany}. See + * {@link SimpleStore~afterCreateManyListener} for how to listen for this event. + * + * @event SimpleStore#afterCreateMany + * @see SimpleStore~afterCreateManyListener + * @see SimpleStore#createMany + */ - /** - * Callback signature for the {@link SimpleStore#event:beforeCreate} event. - * - * @example - * function onBeforeCreate (mapperName, props, opts) { - * // do something - * } - * store.on('beforeCreate', onBeforeCreate); - * - * @callback SimpleStore~beforeCreateListener - * @param {string} name The `name` argument received by {@link Mapper#beforeCreate}. - * @param {object} props The `props` argument received by {@link Mapper#beforeCreate}. - * @param {object} opts The `opts` argument received by {@link Mapper#beforeCreate}. - * @see SimpleStore#event:beforeCreate - * @see SimpleStore#create - * @since 3.0.0 - */ + /** + * Callback signature for the {@link SimpleStore#event:afterCreateMany} event. + * + * @example + * function onAfterCreateMany (mapperName, records, opts, result) { + * // do something + * } + * store.on('afterCreateMany', onAfterCreateMany); + * + * @callback SimpleStore~afterCreateManyListener + * @param {string} name The `name` argument received by {@link Mapper#afterCreateMany}. + * @param {object} records The `records` argument received by {@link Mapper#afterCreateMany}. + * @param {object} opts The `opts` argument received by {@link Mapper#afterCreateMany}. + * @param {object} result The `result` argument received by {@link Mapper#afterCreateMany}. + * @see SimpleStore#event:afterCreateMany + * @see SimpleStore#createMany + * @since 3.0.0 + */ - /** - * Fired during {@link SimpleStore#create}. See - * {@link SimpleStore~afterCreateListener} for how to listen for this event. - * - * @event SimpleStore#afterCreate - * @see SimpleStore~afterCreateListener - * @see SimpleStore#create - */ + /** + * Wrapper for {@link Mapper#createMany}. Adds the created records to the + * store. + * + * @example + * import { SimpleStore } from 'js-data'; + * import { HttpAdapter } from 'js-data-http'; + * + * const store = new SimpleStore(); + * store.registerAdapter('http', new HttpAdapter(), { default: true }); + * + * store.defineMapper('book'); + * + * // Since this example uses the http adapter, we'll get something like: + * // + * // POST /book [{"author_id":1234,...},{...}] + * store.createMany('book', [{ + * author_id: 1234, + * edition: 'First Edition', + * title: 'Respect your Data' + * }, { + * author_id: 1234, + * edition: 'Second Edition', + * title: 'Respect your Data' + * }]).then((books) => { + * console.log(books[0].id); // 142394 + * console.log(books[0].title); // "Respect your Data" + * }); + * + * @fires SimpleStore#beforeCreateMany + * @fires SimpleStore#afterCreateMany + * @fires SimpleStore#add + * @method SimpleStore#createMany + * @param {string} name Name of the {@link Mapper} to target. + * @param {array} records Passed to {@link Mapper#createMany}. + * @param {object} [opts] Passed to {@link Mapper#createMany}. See + * {@link Mapper#createMany} for more configuration options. + * @returns {Promise} Resolves with the result of the create. + * @since 3.0.0 + */ - /** - * Callback signature for the {@link SimpleStore#event:afterCreate} event. - * - * @example - * function onAfterCreate (mapperName, props, opts, result) { - * // do something - * } - * store.on('afterCreate', onAfterCreate); - * - * @callback SimpleStore~afterCreateListener - * @param {string} name The `name` argument received by {@link Mapper#afterCreate}. - * @param {object} props The `props` argument received by {@link Mapper#afterCreate}. - * @param {object} opts The `opts` argument received by {@link Mapper#afterCreate}. - * @param {object} result The `result` argument received by {@link Mapper#afterCreate}. - * @see SimpleStore#event:afterCreate - * @see SimpleStore#create - * @since 3.0.0 - */ + }, { + key: "createMany", + value: function createMany(name, records) { + var _this6 = this; - /** - * Wrapper for {@link Mapper#create}. Adds the created record to the store. - * - * @example - * import { SimpleStore } from 'js-data'; - * import { HttpAdapter } from 'js-data-http'; - * - * const store = new SimpleStore(); - * store.registerAdapter('http', new HttpAdapter(), { default: true }); - * - * store.defineMapper('book'); - * - * // Since this example uses the http adapter, we'll get something like: - * // - * // POST /book {"author_id":1234,...} - * store.create('book', { - * author_id: 1234, - * edition: 'First Edition', - * title: 'Respect your Data' - * }).then((book) => { - * console.log(book.id); // 120392 - * console.log(book.title); // "Respect your Data" - * }); - * - * @fires SimpleStore#beforeCreate - * @fires SimpleStore#afterCreate - * @fires SimpleStore#add - * @method SimpleStore#create - * @param {string} name Name of the {@link Mapper} to target. - * @param {object} record Passed to {@link Mapper#create}. - * @param {object} [opts] Passed to {@link Mapper#create}. See - * {@link Mapper#create} for more configuration options. - * @returns {Promise} Resolves with the result of the create. - * @since 3.0.0 - */ - create: function create(name, record, opts) { - var _this4 = this; + var opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + return _get(_getPrototypeOf(SimpleStore.prototype), "createMany", this).call(this, name, records, opts).then(function (result) { + return _this6._end(name, result, opts); + }); + } + }, { + key: "defineMapper", + value: function defineMapper(name) { + var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var self = this; - opts || (opts = {}); - return Container.prototype.create.call(this, name, record, opts).then(function (result) { - return _this4._end(name, result, opts); - }); - }, + var mapper = _get(_getPrototypeOf(SimpleStore.prototype), "defineMapper", this).call(this, name, opts); - /** - * Fired during {@link SimpleStore#createMany}. See - * {@link SimpleStore~beforeCreateManyListener} for how to listen for this event. - * - * @event SimpleStore#beforeCreateMany - * @see SimpleStore~beforeCreateManyListener - * @see SimpleStore#createMany - */ + self._pendingQueries[name] = {}; + self._completedQueries[name] = {}; + if (!mapper.relationList) Object.defineProperty(mapper, 'relationList', { + value: [] + }); + var collectionOpts = { + // Make sure the collection has somewhere to store "added" timestamps + _added: {}, + // Give the collection a reference to this SimpleStore + datastore: this, + // The mapper tied to the collection + mapper: mapper + }; - /** - * Callback signature for the {@link SimpleStore#event:beforeCreateMany} event. - * - * @example - * function onBeforeCreateMany (mapperName, records, opts) { - * // do something - * } - * store.on('beforeCreateMany', onBeforeCreateMany); - * - * @callback SimpleStore~beforeCreateManyListener - * @param {string} name The `name` argument received by {@link Mapper#beforeCreateMany}. - * @param {object} records The `records` argument received by {@link Mapper#beforeCreateMany}. - * @param {object} opts The `opts` argument received by {@link Mapper#beforeCreateMany}. - * @see SimpleStore#event:beforeCreateMany - * @see SimpleStore#createMany - * @since 3.0.0 - */ + if (opts && 'onConflict' in opts) { + collectionOpts.onConflict = opts.onConflict; + } // The SimpleStore uses a subclass of Collection that is "SimpleStore-aware" - /** - * Fired during {@link SimpleStore#createMany}. See - * {@link SimpleStore~afterCreateManyListener} for how to listen for this event. - * - * @event SimpleStore#afterCreateMany - * @see SimpleStore~afterCreateManyListener - * @see SimpleStore#createMany - */ - /** - * Callback signature for the {@link SimpleStore#event:afterCreateMany} event. - * - * @example - * function onAfterCreateMany (mapperName, records, opts, result) { - * // do something - * } - * store.on('afterCreateMany', onAfterCreateMany); - * - * @callback SimpleStore~afterCreateManyListener - * @param {string} name The `name` argument received by {@link Mapper#afterCreateMany}. - * @param {object} records The `records` argument received by {@link Mapper#afterCreateMany}. - * @param {object} opts The `opts` argument received by {@link Mapper#afterCreateMany}. - * @param {object} result The `result` argument received by {@link Mapper#afterCreateMany}. - * @see SimpleStore#event:afterCreateMany - * @see SimpleStore#createMany - * @since 3.0.0 - */ + var collection = self._collections[name] = new self.collectionClass(null, collectionOpts); + var schema = mapper.schema || {}; + var properties = schema.properties || {}; // TODO: Make it possible index nested properties? - /** - * Wrapper for {@link Mapper#createMany}. Adds the created records to the - * store. - * - * @example - * import { SimpleStore } from 'js-data'; - * import { HttpAdapter } from 'js-data-http'; - * - * const store = new SimpleStore(); - * store.registerAdapter('http', new HttpAdapter(), { default: true }); - * - * store.defineMapper('book'); - * - * // Since this example uses the http adapter, we'll get something like: - * // - * // POST /book [{"author_id":1234,...},{...}] - * store.createMany('book', [{ - * author_id: 1234, - * edition: 'First Edition', - * title: 'Respect your Data' - * }, { - * author_id: 1234, - * edition: 'Second Edition', - * title: 'Respect your Data' - * }]).then((books) => { - * console.log(books[0].id); // 142394 - * console.log(books[0].title); // "Respect your Data" - * }); - * - * @fires SimpleStore#beforeCreateMany - * @fires SimpleStore#afterCreateMany - * @fires SimpleStore#add - * @method SimpleStore#createMany - * @param {string} name Name of the {@link Mapper} to target. - * @param {array} records Passed to {@link Mapper#createMany}. - * @param {object} [opts] Passed to {@link Mapper#createMany}. See - * {@link Mapper#createMany} for more configuration options. - * @returns {Promise} Resolves with the result of the create. - * @since 3.0.0 - */ - createMany: function createMany(name, records, opts) { - var _this5 = this; + utils.forOwn(properties, function (opts, prop) { + if (opts.indexed) { + collection.createIndex(prop); + } + }); // Create a secondary index on the "added" timestamps of records in the + // collection - opts || (opts = {}); - return Container.prototype.createMany.call(this, name, records, opts).then(function (result) { - return _this5._end(name, result, opts); - }); - }, - defineMapper: function defineMapper(name, opts) { - var self = this; - var mapper = Container.prototype.defineMapper.call(self, name, opts); - self._pendingQueries[name] = {}; - self._completedQueries[name] = {}; - mapper.relationList || Object.defineProperty(mapper, 'relationList', { - value: [] - }); - var collectionOpts = { - // Make sure the collection has somewhere to store "added" timestamps - _added: {}, - // Give the collection a reference to this SimpleStore - datastore: self, - // The mapper tied to the collection - mapper: mapper - }; + collection.createIndex('addedTimestamps', ['$'], { + fieldGetter: function fieldGetter(obj) { + return collection._added[collection.recordId(obj)]; + } + }); + collection.on('all', function () { + for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { + args[_key3] = arguments[_key3]; + } - if (opts && 'onConflict' in opts) { - collectionOpts.onConflict = opts.onConflict; - } // The SimpleStore uses a subclass of Collection that is "SimpleStore-aware" + self._onCollectionEvent.apply(self, [name].concat(args)); + }); + return mapper; + } + /** + * Fired during {@link SimpleStore#destroy}. See + * {@link SimpleStore~beforeDestroyListener} for how to listen for this event. + * + * @event SimpleStore#beforeDestroy + * @see SimpleStore~beforeDestroyListener + * @see SimpleStore#destroy + */ + /** + * Callback signature for the {@link SimpleStore#event:beforeDestroy} event. + * + * @example + * function onBeforeDestroy (mapperName, id, opts) { + * // do something + * } + * store.on('beforeDestroy', onBeforeDestroy); + * + * @callback SimpleStore~beforeDestroyListener + * @param {string} name The `name` argument received by {@link Mapper#beforeDestroy}. + * @param {string|number} id The `id` argument received by {@link Mapper#beforeDestroy}. + * @param {object} opts The `opts` argument received by {@link Mapper#beforeDestroy}. + * @see SimpleStore#event:beforeDestroy + * @see SimpleStore#destroy + * @since 3.0.0 + */ - var collection = self._collections[name] = new self.collectionClass(null, collectionOpts); // eslint-disable-line + /** + * Fired during {@link SimpleStore#destroy}. See + * {@link SimpleStore~afterDestroyListener} for how to listen for this event. + * + * @event SimpleStore#afterDestroy + * @see SimpleStore~afterDestroyListener + * @see SimpleStore#destroy + */ - var schema = mapper.schema || {}; - var properties = schema.properties || {}; // TODO: Make it possible index nested properties? + /** + * Callback signature for the {@link SimpleStore#event:afterDestroy} event. + * + * @example + * function onAfterDestroy (mapperName, id, opts, result) { + * // do something + * } + * store.on('afterDestroy', onAfterDestroy); + * + * @callback SimpleStore~afterDestroyListener + * @param {string} name The `name` argument received by {@link Mapper#afterDestroy}. + * @param {string|number} id The `id` argument received by {@link Mapper#afterDestroy}. + * @param {object} opts The `opts` argument received by {@link Mapper#afterDestroy}. + * @param {object} result The `result` argument received by {@link Mapper#afterDestroy}. + * @see SimpleStore#event:afterDestroy + * @see SimpleStore#destroy + * @since 3.0.0 + */ - utils.forOwn(properties, function (opts, prop) { - if (opts.indexed) { - collection.createIndex(prop); - } - }); // Create a secondary index on the "added" timestamps of records in the - // collection + /** + * Wrapper for {@link Mapper#destroy}. Removes any destroyed record from the + * in-memory store. Clears out any {@link SimpleStore#_completedQueries} entries + * associated with the provided `id`. + * + * @example + * import { SimpleStore } from 'js-data'; + * import { HttpAdapter } from 'js-data-http'; + * + * const store = new SimpleStore(); + * store.registerAdapter('http', new HttpAdapter(), { default: true }); + * + * store.defineMapper('book'); + * + * store.add('book', { id: 1234, title: 'Data Management is Hard' }); + * + * // Since this example uses the http adapter, we'll get something like: + * // + * // DELETE /book/1234 + * store.destroy('book', 1234).then(() => { + * // The book record is no longer in the in-memory store + * console.log(store.get('book', 1234)); // undefined + * + * return store.find('book', 1234); + * }).then((book) { + * // The book was deleted from the database too + * console.log(book); // undefined + * }); + * + * @fires SimpleStore#beforeDestroy + * @fires SimpleStore#afterDestroy + * @fires SimpleStore#remove + * @method SimpleStore#destroy + * @param {string} name Name of the {@link Mapper} to target. + * @param {(string|number)} id Passed to {@link Mapper#destroy}. + * @param {object} [opts] Passed to {@link Mapper#destroy}. See + * {@link Mapper#destroy} for more configuration options. + * @returns {Promise} Resolves when the destroy operation completes. + * @since 3.0.0 + */ - collection.createIndex('addedTimestamps', ['$'], { - fieldGetter: function fieldGetter(obj) { - return collection._added[collection.recordId(obj)]; - } - }); - collection.on('all', function () { - for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { - args[_key3] = arguments[_key3]; - } + }, { + key: "destroy", + value: function destroy(name, id) { + var _this7 = this; - self._onCollectionEvent.apply(self, [name].concat(args)); - }); - return mapper; - }, + var opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + return _get(_getPrototypeOf(SimpleStore.prototype), "destroy", this).call(this, name, id, opts).then(function (result) { + var record = _this7.getCollection(name).remove(id, opts); - /** - * Fired during {@link SimpleStore#destroy}. See - * {@link SimpleStore~beforeDestroyListener} for how to listen for this event. - * - * @event SimpleStore#beforeDestroy - * @see SimpleStore~beforeDestroyListener - * @see SimpleStore#destroy - */ + if (opts.raw) { + result.data = record; + } else { + result = record; + } - /** - * Callback signature for the {@link SimpleStore#event:beforeDestroy} event. - * - * @example - * function onBeforeDestroy (mapperName, id, opts) { - * // do something - * } - * store.on('beforeDestroy', onBeforeDestroy); - * - * @callback SimpleStore~beforeDestroyListener - * @param {string} name The `name` argument received by {@link Mapper#beforeDestroy}. - * @param {string|number} id The `id` argument received by {@link Mapper#beforeDestroy}. - * @param {object} opts The `opts` argument received by {@link Mapper#beforeDestroy}. - * @see SimpleStore#event:beforeDestroy - * @see SimpleStore#destroy - * @since 3.0.0 - */ + delete _this7._pendingQueries[name][id]; + delete _this7._completedQueries[name][id]; + return result; + }); + } + /** + * Fired during {@link SimpleStore#destroyAll}. See + * {@link SimpleStore~beforeDestroyAllListener} for how to listen for this event. + * + * @event SimpleStore#beforeDestroyAll + * @see SimpleStore~beforeDestroyAllListener + * @see SimpleStore#destroyAll + */ - /** - * Fired during {@link SimpleStore#destroy}. See - * {@link SimpleStore~afterDestroyListener} for how to listen for this event. - * - * @event SimpleStore#afterDestroy - * @see SimpleStore~afterDestroyListener - * @see SimpleStore#destroy - */ + /** + * Callback signature for the {@link SimpleStore#event:beforeDestroyAll} event. + * + * @example + * function onBeforeDestroyAll (mapperName, query, opts) { + * // do something + * } + * store.on('beforeDestroyAll', onBeforeDestroyAll); + * + * @callback SimpleStore~beforeDestroyAllListener + * @param {string} name The `name` argument received by {@link Mapper#beforeDestroyAll}. + * @param {object} query The `query` argument received by {@link Mapper#beforeDestroyAll}. + * @param {object} opts The `opts` argument received by {@link Mapper#beforeDestroyAll}. + * @see SimpleStore#event:beforeDestroyAll + * @see SimpleStore#destroyAll + * @since 3.0.0 + */ - /** - * Callback signature for the {@link SimpleStore#event:afterDestroy} event. - * - * @example - * function onAfterDestroy (mapperName, id, opts, result) { - * // do something - * } - * store.on('afterDestroy', onAfterDestroy); - * - * @callback SimpleStore~afterDestroyListener - * @param {string} name The `name` argument received by {@link Mapper#afterDestroy}. - * @param {string|number} id The `id` argument received by {@link Mapper#afterDestroy}. - * @param {object} opts The `opts` argument received by {@link Mapper#afterDestroy}. - * @param {object} result The `result` argument received by {@link Mapper#afterDestroy}. - * @see SimpleStore#event:afterDestroy - * @see SimpleStore#destroy - * @since 3.0.0 - */ + /** + * Fired during {@link SimpleStore#destroyAll}. See + * {@link SimpleStore~afterDestroyAllListener} for how to listen for this event. + * + * @event SimpleStore#afterDestroyAll + * @see SimpleStore~afterDestroyAllListener + * @see SimpleStore#destroyAll + */ - /** - * Wrapper for {@link Mapper#destroy}. Removes any destroyed record from the - * in-memory store. Clears out any {@link SimpleStore#_completedQueries} entries - * associated with the provided `id`. - * - * @example - * import { SimpleStore } from 'js-data'; - * import { HttpAdapter } from 'js-data-http'; - * - * const store = new SimpleStore(); - * store.registerAdapter('http', new HttpAdapter(), { default: true }); - * - * store.defineMapper('book'); - * - * store.add('book', { id: 1234, title: 'Data Management is Hard' }); - * - * // Since this example uses the http adapter, we'll get something like: - * // - * // DELETE /book/1234 - * store.destroy('book', 1234).then(() => { - * // The book record is no longer in the in-memory store - * console.log(store.get('book', 1234)); // undefined - * - * return store.find('book', 1234); - * }).then((book) { - * // The book was deleted from the database too - * console.log(book); // undefined - * }); - * - * @fires SimpleStore#beforeDestroy - * @fires SimpleStore#afterDestroy - * @fires SimpleStore#remove - * @method SimpleStore#destroy - * @param {string} name Name of the {@link Mapper} to target. - * @param {(string|number)} id Passed to {@link Mapper#destroy}. - * @param {object} [opts] Passed to {@link Mapper#destroy}. See - * {@link Mapper#destroy} for more configuration options. - * @returns {Promise} Resolves when the destroy operation completes. - * @since 3.0.0 - */ - destroy: function destroy(name, id, opts) { - var _this6 = this; + /** + * Callback signature for the {@link SimpleStore#event:afterDestroyAll} event. + * + * @example + * function onAfterDestroyAll (mapperName, query, opts, result) { + * // do something + * } + * store.on('afterDestroyAll', onAfterDestroyAll); + * + * @callback SimpleStore~afterDestroyAllListener + * @param {string} name The `name` argument received by {@link Mapper#afterDestroyAll}. + * @param {object} query The `query` argument received by {@link Mapper#afterDestroyAll}. + * @param {object} opts The `opts` argument received by {@link Mapper#afterDestroyAll}. + * @param {object} result The `result` argument received by {@link Mapper#afterDestroyAll}. + * @see SimpleStore#event:afterDestroyAll + * @see SimpleStore#destroyAll + * @since 3.0.0 + */ - opts || (opts = {}); - return Container.prototype.destroy.call(this, name, id, opts).then(function (result) { - var record = _this6.getCollection(name).remove(id, opts); + /** + * Wrapper for {@link Mapper#destroyAll}. Removes any destroyed records from + * the in-memory store. + * + * @example + * import { SimpleStore } from 'js-data'; + * import { HttpAdapter } from 'js-data-http'; + * + * const store = new SimpleStore(); + * store.registerAdapter('http', new HttpAdapter(), { default: true }); + * + * store.defineMapper('book'); + * + * store.add('book', { id: 1234, title: 'Data Management is Hard' }); + * + * // Since this example uses the http adapter, we'll get something like: + * // + * // DELETE /book/1234 + * store.destroy('book', 1234).then(() => { + * // The book record is gone from the in-memory store + * console.log(store.get('book', 1234)); // undefined + * return store.find('book', 1234); + * }).then((book) { + * // The book was deleted from the database too + * console.log(book); // undefined + * }); + * + * @fires SimpleStore#beforeDestroyAll + * @fires SimpleStore#afterDestroyAll + * @fires SimpleStore#remove + * @method SimpleStore#destroyAll + * @param {string} name Name of the {@link Mapper} to target. + * @param {object} [query] Passed to {@link Mapper#destroyAll}. + * @param {object} [opts] Passed to {@link Mapper#destroyAll}. See + * {@link Mapper#destroyAll} for more configuration options. + * @returns {Promise} Resolves when the delete completes. + * @since 3.0.0 + */ - if (opts.raw) { - result.data = record; - } else { - result = record; - } + }, { + key: "destroyAll", + value: function destroyAll(name, query) { + var _this8 = this; - delete _this6._pendingQueries[name][id]; - delete _this6._completedQueries[name][id]; - return result; - }); - }, + var opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + return _get(_getPrototypeOf(SimpleStore.prototype), "destroyAll", this).call(this, name, query, opts).then(function (result) { + var records = _this8.getCollection(name).removeAll(query, opts); - /** - * Fired during {@link SimpleStore#destroyAll}. See - * {@link SimpleStore~beforeDestroyAllListener} for how to listen for this event. - * - * @event SimpleStore#beforeDestroyAll - * @see SimpleStore~beforeDestroyAllListener - * @see SimpleStore#destroyAll - */ + if (opts.raw) { + result.data = records; + } else { + result = records; + } - /** - * Callback signature for the {@link SimpleStore#event:beforeDestroyAll} event. - * - * @example - * function onBeforeDestroyAll (mapperName, query, opts) { - * // do something - * } - * store.on('beforeDestroyAll', onBeforeDestroyAll); - * - * @callback SimpleStore~beforeDestroyAllListener - * @param {string} name The `name` argument received by {@link Mapper#beforeDestroyAll}. - * @param {object} query The `query` argument received by {@link Mapper#beforeDestroyAll}. - * @param {object} opts The `opts` argument received by {@link Mapper#beforeDestroyAll}. - * @see SimpleStore#event:beforeDestroyAll - * @see SimpleStore#destroyAll - * @since 3.0.0 - */ + var hash = _this8.hashQuery(name, query, opts); - /** - * Fired during {@link SimpleStore#destroyAll}. See - * {@link SimpleStore~afterDestroyAllListener} for how to listen for this event. - * - * @event SimpleStore#afterDestroyAll - * @see SimpleStore~afterDestroyAllListener - * @see SimpleStore#destroyAll - */ + delete _this8._pendingQueries[name][hash]; + delete _this8._completedQueries[name][hash]; + return result; + }); + } + }, { + key: "eject", + value: function eject(name, id, opts) { + console.warn('DEPRECATED: "eject" is deprecated, use "remove" instead'); + return this.remove(name, id, opts); + } + }, { + key: "ejectAll", + value: function ejectAll(name, query, opts) { + console.warn('DEPRECATED: "ejectAll" is deprecated, use "removeAll" instead'); + return this.removeAll(name, query, opts); + } + /** + * Fired during {@link SimpleStore#find}. See + * {@link SimpleStore~beforeFindListener} for how to listen for this event. + * + * @event SimpleStore#beforeFind + * @see SimpleStore~beforeFindListener + * @see SimpleStore#find + */ - /** - * Callback signature for the {@link SimpleStore#event:afterDestroyAll} event. - * - * @example - * function onAfterDestroyAll (mapperName, query, opts, result) { - * // do something - * } - * store.on('afterDestroyAll', onAfterDestroyAll); - * - * @callback SimpleStore~afterDestroyAllListener - * @param {string} name The `name` argument received by {@link Mapper#afterDestroyAll}. - * @param {object} query The `query` argument received by {@link Mapper#afterDestroyAll}. - * @param {object} opts The `opts` argument received by {@link Mapper#afterDestroyAll}. - * @param {object} result The `result` argument received by {@link Mapper#afterDestroyAll}. - * @see SimpleStore#event:afterDestroyAll - * @see SimpleStore#destroyAll - * @since 3.0.0 - */ + /** + * Callback signature for the {@link SimpleStore#event:beforeFind} event. + * + * @example + * function onBeforeFind (mapperName, id, opts) { + * // do something + * } + * store.on('beforeFind', onBeforeFind); + * + * @callback SimpleStore~beforeFindListener + * @param {string} name The `name` argument received by {@link Mapper#beforeFind}. + * @param {string|number} id The `id` argument received by {@link Mapper#beforeFind}. + * @param {object} opts The `opts` argument received by {@link Mapper#beforeFind}. + * @see SimpleStore#event:beforeFind + * @see SimpleStore#find + * @since 3.0.0 + */ - /** - * Wrapper for {@link Mapper#destroyAll}. Removes any destroyed records from - * the in-memory store. - * - * @example - * import { SimpleStore } from 'js-data'; - * import { HttpAdapter } from 'js-data-http'; - * - * const store = new SimpleStore(); - * store.registerAdapter('http', new HttpAdapter(), { default: true }); - * - * store.defineMapper('book'); - * - * store.add('book', { id: 1234, title: 'Data Management is Hard' }); - * - * // Since this example uses the http adapter, we'll get something like: - * // - * // DELETE /book/1234 - * store.destroy('book', 1234).then(() => { - * // The book record is gone from the in-memory store - * console.log(store.get('book', 1234)); // undefined - * return store.find('book', 1234); - * }).then((book) { - * // The book was deleted from the database too - * console.log(book); // undefined - * }); - * - * @fires SimpleStore#beforeDestroyAll - * @fires SimpleStore#afterDestroyAll - * @fires SimpleStore#remove - * @method SimpleStore#destroyAll - * @param {string} name Name of the {@link Mapper} to target. - * @param {object} [query] Passed to {@link Mapper#destroyAll}. - * @param {object} [opts] Passed to {@link Mapper#destroyAll}. See - * {@link Mapper#destroyAll} for more configuration options. - * @returns {Promise} Resolves when the delete completes. - * @since 3.0.0 - */ - destroyAll: function destroyAll(name, query, opts) { - var _this7 = this; + /** + * Fired during {@link SimpleStore#find}. See + * {@link SimpleStore~afterFindListener} for how to listen for this event. + * + * @event SimpleStore#afterFind + * @see SimpleStore~afterFindListener + * @see SimpleStore#find + */ - opts || (opts = {}); - return Container.prototype.destroyAll.call(this, name, query, opts).then(function (result) { - var records = _this7.getCollection(name).removeAll(query, opts); + /** + * Callback signature for the {@link SimpleStore#event:afterFind} event. + * + * @example + * function onAfterFind (mapperName, id, opts, result) { + * // do something + * } + * store.on('afterFind', onAfterFind); + * + * @callback SimpleStore~afterFindListener + * @param {string} name The `name` argument received by {@link Mapper#afterFind}. + * @param {string|number} id The `id` argument received by {@link Mapper#afterFind}. + * @param {object} opts The `opts` argument received by {@link Mapper#afterFind}. + * @param {object} result The `result` argument received by {@link Mapper#afterFind}. + * @see SimpleStore#event:afterFind + * @see SimpleStore#find + * @since 3.0.0 + */ - if (opts.raw) { - result.data = records; - } else { - result = records; - } + /** + * Wrapper for {@link Mapper#find}. Adds any found record to the store. + * + * @example + * import { SimpleStore } from 'js-data'; + * import { HttpAdapter } from 'js-data-http'; + * + * const store = new SimpleStore(); + * store.registerAdapter('http', new HttpAdapter(), { default: true }); + * + * store.defineMapper('book'); + * + * // Since this example uses the http adapter, we'll get something like: + * // + * // GET /book/1234 + * store.find('book', 1234).then((book) => { + * // The book record is now in the in-memory store + * console.log(store.get('book', 1234) === book); // true + * }); + * + * @fires SimpleStore#beforeFind + * @fires SimpleStore#afterFind + * @fires SimpleStore#add + * @method SimpleStore#find + * @param {string} name Name of the {@link Mapper} to target. + * @param {(string|number)} id Passed to {@link Mapper#find}. + * @param {object} [opts] Passed to {@link Mapper#find}. + * @param {boolean} [opts.force] Bypass cacheFind + * @param {boolean|Function} [opts.usePendingFind] See {@link SimpleStore#usePendingFind} + * @returns {Promise} Resolves with the result, if any. + * @since 3.0.0 + */ - var hash = _this7.hashQuery(name, query, opts); + }, { + key: "find", + value: function find(name, id) { + var _this9 = this; - delete _this7._pendingQueries[name][hash]; - delete _this7._completedQueries[name][hash]; - return result; - }); - }, - eject: function eject(name, id, opts) { - console.warn('DEPRECATED: "eject" is deprecated, use "remove" instead'); - return this.remove(name, id, opts); - }, - ejectAll: function ejectAll(name, query, opts) { - console.warn('DEPRECATED: "ejectAll" is deprecated, use "removeAll" instead'); - return this.removeAll(name, query, opts); - }, + var opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + var mapper = this.getMapper(name); + var pendingQuery = this._pendingQueries[name][id]; + var usePendingFind = opts.usePendingFind === undefined ? this.usePendingFind : opts.usePendingFind; - /** - * Fired during {@link SimpleStore#find}. See - * {@link SimpleStore~beforeFindListener} for how to listen for this event. - * - * @event SimpleStore#beforeFind - * @see SimpleStore~beforeFindListener - * @see SimpleStore#find - */ + utils._(opts, mapper); - /** - * Callback signature for the {@link SimpleStore#event:beforeFind} event. - * - * @example - * function onBeforeFind (mapperName, id, opts) { - * // do something - * } - * store.on('beforeFind', onBeforeFind); - * - * @callback SimpleStore~beforeFindListener - * @param {string} name The `name` argument received by {@link Mapper#beforeFind}. - * @param {string|number} id The `id` argument received by {@link Mapper#beforeFind}. - * @param {object} opts The `opts` argument received by {@link Mapper#beforeFind}. - * @see SimpleStore#event:beforeFind - * @see SimpleStore#find - * @since 3.0.0 - */ + if (pendingQuery && (utils.isFunction(usePendingFind) ? usePendingFind.call(this, name, id, opts) : usePendingFind)) { + return pendingQuery; + } - /** - * Fired during {@link SimpleStore#find}. See - * {@link SimpleStore~afterFindListener} for how to listen for this event. - * - * @event SimpleStore#afterFind - * @see SimpleStore~afterFindListener - * @see SimpleStore#find - */ + var item = this.cachedFind(name, id, opts); - /** - * Callback signature for the {@link SimpleStore#event:afterFind} event. - * - * @example - * function onAfterFind (mapperName, id, opts, result) { - * // do something - * } - * store.on('afterFind', onAfterFind); - * - * @callback SimpleStore~afterFindListener - * @param {string} name The `name` argument received by {@link Mapper#afterFind}. - * @param {string|number} id The `id` argument received by {@link Mapper#afterFind}. - * @param {object} opts The `opts` argument received by {@link Mapper#afterFind}. - * @param {object} result The `result` argument received by {@link Mapper#afterFind}. - * @see SimpleStore#event:afterFind - * @see SimpleStore#find - * @since 3.0.0 - */ + if (opts.force || !item) { + var promise = this._pendingQueries[name][id] = _get(_getPrototypeOf(SimpleStore.prototype), "find", this).call(this, name, id, opts); - /** - * Wrapper for {@link Mapper#find}. Adds any found record to the store. - * - * @example - * import { SimpleStore } from 'js-data'; - * import { HttpAdapter } from 'js-data-http'; - * - * const store = new SimpleStore(); - * store.registerAdapter('http', new HttpAdapter(), { default: true }); - * - * store.defineMapper('book'); - * - * // Since this example uses the http adapter, we'll get something like: - * // - * // GET /book/1234 - * store.find('book', 1234).then((book) => { - * // The book record is now in the in-memory store - * console.log(store.get('book', 1234) === book); // true - * }); - * - * @fires SimpleStore#beforeFind - * @fires SimpleStore#afterFind - * @fires SimpleStore#add - * @method SimpleStore#find - * @param {string} name Name of the {@link Mapper} to target. - * @param {(string|number)} id Passed to {@link Mapper#find}. - * @param {object} [opts] Passed to {@link Mapper#find}. - * @param {boolean} [opts.force] Bypass cacheFind - * @param {boolean|Function} [opts.usePendingFind] See {@link SimpleStore#usePendingFind} - * @returns {Promise} Resolves with the result, if any. - * @since 3.0.0 - */ - find: function find(name, id, opts) { - var _this8 = this; + return promise.then(function (result) { + delete _this9._pendingQueries[name][id]; + result = _this9._end(name, result, opts); - opts || (opts = {}); - var mapper = this.getMapper(name); - var pendingQuery = this._pendingQueries[name][id]; - var usePendingFind = opts.usePendingFind === undefined ? this.usePendingFind : opts.usePendingFind; + _this9.cacheFind(name, result, id, opts); - utils._(opts, mapper); + return result; + }, function (err) { + delete _this9._pendingQueries[name][id]; + return utils.reject(err); + }); + } - if (pendingQuery && (utils.isFunction(usePendingFind) ? usePendingFind.call(this, name, id, opts) : usePendingFind)) { - return pendingQuery; + return utils.resolve(item); } + /** + * Fired during {@link SimpleStore#findAll}. See + * {@link SimpleStore~beforeFindAllListener} for how to listen for this event. + * + * @event SimpleStore#beforeFindAll + * @see SimpleStore~beforeFindAllListener + * @see SimpleStore#findAll + */ - var item = this.cachedFind(name, id, opts); + /** + * Callback signature for the {@link SimpleStore#event:beforeFindAll} event. + * + * @example + * function onBeforeFindAll (mapperName, query, opts) { + * // do something + * } + * store.on('beforeFindAll', onBeforeFindAll); + * + * @callback SimpleStore~beforeFindAllListener + * @param {string} name The `name` argument received by {@link Mapper#beforeFindAll}. + * @param {object} query The `query` argument received by {@link Mapper#beforeFindAll}. + * @param {object} opts The `opts` argument received by {@link Mapper#beforeFindAll}. + * @see SimpleStore#event:beforeFindAll + * @see SimpleStore#findAll + * @since 3.0.0 + */ - if (opts.force || !item) { - var promise = this._pendingQueries[name][id] = Container.prototype.find.call(this, name, id, opts); - return promise.then(function (result) { - delete _this8._pendingQueries[name][id]; - result = _this8._end(name, result, opts); + /** + * Fired during {@link SimpleStore#findAll}. See + * {@link SimpleStore~afterFindAllListener} for how to listen for this event. + * + * @event SimpleStore#afterFindAll + * @see SimpleStore~afterFindAllListener + * @see SimpleStore#findAll + */ - _this8.cacheFind(name, result, id, opts); + /** + * Callback signature for the {@link SimpleStore#event:afterFindAll} event. + * + * @example + * function onAfterFindAll (mapperName, query, opts, result) { + * // do something + * } + * store.on('afterFindAll', onAfterFindAll); + * + * @callback SimpleStore~afterFindAllListener + * @param {string} name The `name` argument received by {@link Mapper#afterFindAll}. + * @param {object} query The `query` argument received by {@link Mapper#afterFindAll}. + * @param {object} opts The `opts` argument received by {@link Mapper#afterFindAll}. + * @param {object} result The `result` argument received by {@link Mapper#afterFindAll}. + * @see SimpleStore#event:afterFindAll + * @see SimpleStore#findAll + * @since 3.0.0 + */ - return result; - }, function (err) { - delete _this8._pendingQueries[name][id]; - return utils.reject(err); - }); - } + /** + * Wrapper for {@link Mapper#findAll}. Adds any found records to the store. + * + * @example + * import { SimpleStore } from 'js-data'; + * import { HttpAdapter } from 'js-data-http'; + * + * const store = new SimpleStore(); + * store.registerAdapter('http', new HttpAdapter(), { default: true }); + * + * store.defineMapper('movie'); + * + * // Since this example uses the http adapter, we'll get something like: + * // + * // GET /movie?rating=PG + * store.find('movie', { rating: 'PG' }).then((movies) => { + * // The movie records are now in the in-memory store + * console.log(store.filter('movie')); + * }); + * + * @fires SimpleStore#beforeFindAll + * @fires SimpleStore#afterFindAll + * @fires SimpleStore#add + * @method SimpleStore#findAll + * @param {string} name Name of the {@link Mapper} to target. + * @param {object} [query] Passed to {@link Mapper.findAll}. + * @param {object} [opts] Passed to {@link Mapper.findAll}. + * @param {boolean} [opts.force] Bypass cacheFindAll + * @param {boolean|Function} [opts.usePendingFindAll] See {@link SimpleStore#usePendingFindAll} + * @returns {Promise} Resolves with the result, if any. + * @since 3.0.0 + */ - return utils.resolve(item); - }, + }, { + key: "findAll", + value: function findAll(name, query) { + var _this10 = this; - /** - * Fired during {@link SimpleStore#findAll}. See - * {@link SimpleStore~beforeFindAllListener} for how to listen for this event. - * - * @event SimpleStore#beforeFindAll - * @see SimpleStore~beforeFindAllListener - * @see SimpleStore#findAll - */ + var opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + var mapper = this.getMapper(name); + var hash = this.hashQuery(name, query, opts); + var pendingQuery = this._pendingQueries[name][hash]; + var usePendingFindAll = opts.usePendingFindAll === undefined ? this.usePendingFindAll : opts.usePendingFindAll; - /** - * Callback signature for the {@link SimpleStore#event:beforeFindAll} event. - * - * @example - * function onBeforeFindAll (mapperName, query, opts) { - * // do something - * } - * store.on('beforeFindAll', onBeforeFindAll); - * - * @callback SimpleStore~beforeFindAllListener - * @param {string} name The `name` argument received by {@link Mapper#beforeFindAll}. - * @param {object} query The `query` argument received by {@link Mapper#beforeFindAll}. - * @param {object} opts The `opts` argument received by {@link Mapper#beforeFindAll}. - * @see SimpleStore#event:beforeFindAll - * @see SimpleStore#findAll - * @since 3.0.0 - */ + utils._(opts, mapper); - /** - * Fired during {@link SimpleStore#findAll}. See - * {@link SimpleStore~afterFindAllListener} for how to listen for this event. - * - * @event SimpleStore#afterFindAll - * @see SimpleStore~afterFindAllListener - * @see SimpleStore#findAll - */ + if (pendingQuery && (utils.isFunction(usePendingFindAll) ? usePendingFindAll.call(this, name, query, opts) : usePendingFindAll)) { + return pendingQuery; + } - /** - * Callback signature for the {@link SimpleStore#event:afterFindAll} event. - * - * @example - * function onAfterFindAll (mapperName, query, opts, result) { - * // do something - * } - * store.on('afterFindAll', onAfterFindAll); - * - * @callback SimpleStore~afterFindAllListener - * @param {string} name The `name` argument received by {@link Mapper#afterFindAll}. - * @param {object} query The `query` argument received by {@link Mapper#afterFindAll}. - * @param {object} opts The `opts` argument received by {@link Mapper#afterFindAll}. - * @param {object} result The `result` argument received by {@link Mapper#afterFindAll}. - * @see SimpleStore#event:afterFindAll - * @see SimpleStore#findAll - * @since 3.0.0 - */ + var items = this.cachedFindAll(name, hash, opts); - /** - * Wrapper for {@link Mapper#findAll}. Adds any found records to the store. - * - * @example - * import { SimpleStore } from 'js-data'; - * import { HttpAdapter } from 'js-data-http'; - * - * const store = new SimpleStore(); - * store.registerAdapter('http', new HttpAdapter(), { default: true }); - * - * store.defineMapper('movie'); - * - * // Since this example uses the http adapter, we'll get something like: - * // - * // GET /movie?rating=PG - * store.find('movie', { rating: 'PG' }).then((movies) => { - * // The movie records are now in the in-memory store - * console.log(store.filter('movie')); - * }); - * - * @fires SimpleStore#beforeFindAll - * @fires SimpleStore#afterFindAll - * @fires SimpleStore#add - * @method SimpleStore#findAll - * @param {string} name Name of the {@link Mapper} to target. - * @param {object} [query] Passed to {@link Mapper.findAll}. - * @param {object} [opts] Passed to {@link Mapper.findAll}. - * @param {boolean} [opts.force] Bypass cacheFindAll - * @param {boolean|Function} [opts.usePendingFindAll] See {@link SimpleStore#usePendingFindAll} - * @returns {Promise} Resolves with the result, if any. - * @since 3.0.0 - */ - findAll: function findAll(name, query, opts) { - var _this9 = this; + if (opts.force || !items) { + var promise = this._pendingQueries[name][hash] = _get(_getPrototypeOf(SimpleStore.prototype), "findAll", this).call(this, name, query, opts); + + return promise.then(function (result) { + delete _this10._pendingQueries[name][hash]; + result = _this10._end(name, result, opts); - opts || (opts = {}); - var mapper = this.getMapper(name); - var hash = this.hashQuery(name, query, opts); - var pendingQuery = this._pendingQueries[name][hash]; - var usePendingFindAll = opts.usePendingFindAll === undefined ? this.usePendingFindAll : opts.usePendingFindAll; + _this10.cacheFindAll(name, result, hash, opts); - utils._(opts, mapper); + return result; + }, function (err) { + delete _this10._pendingQueries[name][hash]; + return utils.reject(err); + }); + } - if (pendingQuery && (utils.isFunction(usePendingFindAll) ? usePendingFindAll.call(this, name, query, opts) : usePendingFindAll)) { - return pendingQuery; + return utils.resolve(items); } + /** + * Return the {@link Collection} with the given name, if for some + * reason you need a direct reference to the collection. + * + * @param {string} name Name of the {@link Collection} to retrieve. + * @since 3.0.0 + * @throws {Error} Thrown if the specified {@link Collection} does not + * exist. + */ - var items = this.cachedFindAll(name, hash, opts); + }, { + key: "getCollection", + value: function getCollection(name) { + var collection = this._collections[name]; - if (opts.force || !items) { - var promise = this._pendingQueries[name][hash] = Container.prototype.findAll.call(this, name, query, opts); - return promise.then(function (result) { - delete _this9._pendingQueries[name][hash]; - result = _this9._end(name, result, opts); + if (!collection) { + throw utils.err("".concat(DOMAIN$8, "#getCollection"), name)(404, 'collection'); + } - _this9.cacheFindAll(name, result, hash, opts); + return collection; + } + /** + * Hashing function used to cache {@link SimpleStore#find} and + * {@link SimpleStore#findAll} requests. This method simply JSONifies the + * `query` argument passed to {@link SimpleStore#find} or + * {@link SimpleStore#findAll}. + * + * Override this method for custom hashing behavior. + * @method SimpleStore#hashQuery + * @param {string} name The `name` argument passed to {@link SimpleStore#find} + * or {@link SimpleStore#findAll}. + * @param {object} query The `query` argument passed to {@link SimpleStore#find} + * or {@link SimpleStore#findAll}. + * @returns {string} The JSONified `query`. + * @since 3.0.0 + */ - return result; - }, function (err) { - delete _this9._pendingQueries[name][hash]; - return utils.reject(err); - }); - } + }, { + key: "hashQuery", + value: function hashQuery(name, query, opts) { + return utils.toJson(query || {}); + } + }, { + key: "inject", + value: function inject(name, records, opts) { + console.warn('DEPRECATED: "inject" is deprecated, use "add" instead'); + return this.add(name, records, opts); + } + /** + * Wrapper for {@link Collection#remove}. Removes the specified + * {@link Record} from the store. + * + * @example SimpleStore#remove + * const JSData = require('js-data'); + * const { SimpleStore } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new SimpleStore(); + * store.defineMapper('book'); + * console.log(store.getAll('book').length); + * store.add('book', { id: 1234 }); + * console.log(store.getAll('book').length); + * store.remove('book', 1234); + * console.log(store.getAll('book').length); + * + * @fires SimpleStore#remove + * @method SimpleStore#remove + * @param {string} name The name of the {@link Collection} to target. + * @param {string|number} id The primary key of the {@link Record} to remove. + * @param {object} [opts] Configuration options. + * @param {string[]} [opts.with] Relations of the {@link Record} to also + * remove from the store. + * @returns {Record} The removed {@link Record}, if any. + * @see Collection#add + * @see Collection#add + * @since 3.0.0 + */ - return utils.resolve(items); - }, + }, { + key: "remove", + value: function remove(name, id, opts) { + var record = this.getCollection(name).remove(id, opts); - /** - * Return the {@link Collection} with the given name, if for some - * reason you need a direct reference to the collection. - * - * @method SimpleStore#getCollection - * @param {string} name Name of the {@link Collection} to retrieve. - * @returns {Collection} - * @since 3.0.0 - * @throws {Error} Thrown if the specified {@link Collection} does not - * exist. - */ - getCollection: function getCollection(name) { - var collection = this._collections[name]; + if (record) { + this.removeRelated(name, [record], opts); + } - if (!collection) { - throw utils.err("".concat(DOMAIN$8, "#getCollection"), name)(404, 'collection'); + return record; } + /** + * Wrapper for {@link Collection#removeAll}. Removes the selected + * {@link Record}s from the store. + * + * @example SimpleStore#removeAll + * const JSData = require('js-data'); + * const { SimpleStore } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new SimpleStore(); + * store.defineMapper('movie'); + * console.log(store.getAll('movie').length); + * store.add('movie', [{ id: 3, rating: 'R' }, { id: 4, rating: 'PG-13' }); + * console.log(store.getAll('movie').length); + * store.removeAll('movie', { rating: 'R' }); + * console.log(store.getAll('movie').length); + * + * @fires SimpleStore#remove + * @method SimpleStore#removeAll + * @param {string} name The name of the {@link Collection} to target. + * @param {object} [query={}] Selection query. See {@link query}. + * @param {object} [query.where] See {@link query.where}. + * @param {number} [query.offset] See {@link query.offset}. + * @param {number} [query.limit] See {@link query.limit}. + * @param {string|Array[]} [query.orderBy] See {@link query.orderBy}. + * @param {object} [opts] Configuration options. + * @param {string[]} [opts.with] Relations of the {@link Record} to also + * remove from the store. + * @returns {Record} The removed {@link Record}s, if any. + * @see Collection#add + * @see Collection#add + * @since 3.0.0 + */ - return collection; - }, + }, { + key: "removeAll", + value: function removeAll(name, query, opts) { + if (!query || !Object.keys(query).length) { + this._completedQueries[name] = {}; + } else { + this._completedQueries[name][this.hashQuery(name, query, opts)] = undefined; + } - /** - * Hashing function used to cache {@link SimpleStore#find} and - * {@link SimpleStore#findAll} requests. This method simply JSONifies the - * `query` argument passed to {@link SimpleStore#find} or - * {@link SimpleStore#findAll}. - * - * Override this method for custom hashing behavior. - * @method SimpleStore#hashQuery - * @param {string} name The `name` argument passed to {@link SimpleStore#find} - * or {@link SimpleStore#findAll}. - * @param {object} query The `query` argument passed to {@link SimpleStore#find} - * or {@link SimpleStore#findAll}. - * @returns {string} The JSONified `query`. - * @since 3.0.0 - */ - hashQuery: function hashQuery(name, query, opts) { - return utils.toJson(query || {}); - }, - inject: function inject(name, records, opts) { - console.warn('DEPRECATED: "inject" is deprecated, use "add" instead'); - return this.add(name, records, opts); - }, + var records = this.getCollection(name).removeAll(query, opts); - /** - * Wrapper for {@link Collection#remove}. Removes the specified - * {@link Record} from the store. - * - * @example SimpleStore#remove - * const JSData = require('js-data'); - * const { SimpleStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new SimpleStore(); - * store.defineMapper('book'); - * console.log(store.getAll('book').length); - * store.add('book', { id: 1234 }); - * console.log(store.getAll('book').length); - * store.remove('book', 1234); - * console.log(store.getAll('book').length); - * - * @fires SimpleStore#remove - * @method SimpleStore#remove - * @param {string} name The name of the {@link Collection} to target. - * @param {string|number} id The primary key of the {@link Record} to remove. - * @param {object} [opts] Configuration options. - * @param {string[]} [opts.with] Relations of the {@link Record} to also - * remove from the store. - * @returns {Record} The removed {@link Record}, if any. - * @see Collection#add - * @see Collection#add - * @since 3.0.0 - */ - remove: function remove(name, id, opts) { - var record = this.getCollection(name).remove(id, opts); + if (records.length) { + this.removeRelated(name, records, opts); + } - if (record) { - this.removeRelated(name, [record], opts); + return records; } + /** + * Remove from the store {@link Record}s that are related to the provided + * {@link Record}(s). + * + * @fires SimpleStore#remove + * @method SimpleStore#removeRelated + * @param {string} name The name of the {@link Collection} to target. + * @param {Record|Record[]} records {@link Record}s whose relations are to be + * removed. + * @param {object} [opts] Configuration options. + * @param {string[]} [opts.with] Relations of the {@link Record}(s) to remove + * from the store. + * @since 3.0.0 + */ - return record; - }, + }, { + key: "removeRelated", + value: function removeRelated(name, records, opts) { + var _this11 = this; - /** - * Wrapper for {@link Collection#removeAll}. Removes the selected - * {@link Record}s from the store. - * - * @example SimpleStore#removeAll - * const JSData = require('js-data'); - * const { SimpleStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new SimpleStore(); - * store.defineMapper('movie'); - * console.log(store.getAll('movie').length); - * store.add('movie', [{ id: 3, rating: 'R' }, { id: 4, rating: 'PG-13' }); - * console.log(store.getAll('movie').length); - * store.removeAll('movie', { rating: 'R' }); - * console.log(store.getAll('movie').length); - * - * @fires SimpleStore#remove - * @method SimpleStore#removeAll - * @param {string} name The name of the {@link Collection} to target. - * @param {object} [query={}] Selection query. See {@link query}. - * @param {object} [query.where] See {@link query.where}. - * @param {number} [query.offset] See {@link query.offset}. - * @param {number} [query.limit] See {@link query.limit}. - * @param {string|Array[]} [query.orderBy] See {@link query.orderBy}. - * @param {object} [opts] Configuration options. - * @param {string[]} [opts.with] Relations of the {@link Record} to also - * remove from the store. - * @returns {Record} The removed {@link Record}s, if any. - * @see Collection#add - * @see Collection#add - * @since 3.0.0 - */ - removeAll: function removeAll(name, query, opts) { - if (!query || !Object.keys(query).length) { - this._completedQueries[name] = {}; - } else { - this._completedQueries[name][this.hashQuery(name, query, opts)] = undefined; - } + if (!utils.isArray(records)) { + records = [records]; + } - var records = this.getCollection(name).removeAll(query, opts); + utils.forEachRelation(this.getMapper(name), opts, function (def, optsCopy) { + records.forEach(function (record) { + var relatedData; + var query; + + if (def.foreignKey && (def.type === hasOneType || def.type === hasManyType)) { + query = _defineProperty({}, def.foreignKey, def.getForeignKey(record)); + } else if (def.type === hasManyType && def.localKeys) { + query = { + where: _defineProperty({}, def.getRelation().idAttribute, { + "in": utils.get(record, def.localKeys) + }) + }; + } else if (def.type === hasManyType && def.foreignKeys) { + query = { + where: _defineProperty({}, def.foreignKeys, { + contains: def.getForeignKey(record) + }) + }; + } else if (def.type === belongsToType) { + relatedData = _this11.remove(def.relation, def.getForeignKey(record), optsCopy); + } - if (records.length) { - this.removeRelated(name, records, opts); - } + if (query) { + relatedData = _this11.removeAll(def.relation, query, optsCopy); + } - return records; - }, + if (relatedData) { + if (utils.isArray(relatedData) && !relatedData.length) { + return; + } - /** - * Remove from the store {@link Record}s that are related to the provided - * {@link Record}(s). - * - * @fires SimpleStore#remove - * @method SimpleStore#removeRelated - * @param {string} name The name of the {@link Collection} to target. - * @param {Record|Record[]} records {@link Record}s whose relations are to be - * removed. - * @param {object} [opts] Configuration options. - * @param {string[]} [opts.with] Relations of the {@link Record}(s) to remove - * from the store. - * @since 3.0.0 - */ - removeRelated: function removeRelated(name, records, opts) { - var _this10 = this; + if (def.type === hasOneType) { + relatedData = relatedData[0]; + } - if (!utils.isArray(records)) { - records = [records]; + def.setLocalField(record, relatedData); + } + }); + }); } + /** + * Fired during {@link SimpleStore#update}. See + * {@link SimpleStore~beforeUpdateListener} for how to listen for this event. + * + * @event SimpleStore#beforeUpdate + * @see SimpleStore~beforeUpdateListener + * @see SimpleStore#update + */ - utils.forEachRelation(this.getMapper(name), opts, function (def, optsCopy) { - records.forEach(function (record) { - var relatedData; - var query; - - if (def.foreignKey && (def.type === hasOneType || def.type === hasManyType)) { - query = _defineProperty({}, def.foreignKey, def.getForeignKey(record)); - } else if (def.type === hasManyType && def.localKeys) { - query = { - where: _defineProperty({}, def.getRelation().idAttribute, { - in: utils.get(record, def.localKeys) - }) - }; - } else if (def.type === hasManyType && def.foreignKeys) { - query = { - where: _defineProperty({}, def.foreignKeys, { - contains: def.getForeignKey(record) - }) - }; - } else if (def.type === belongsToType) { - relatedData = _this10.remove(def.relation, def.getForeignKey(record), optsCopy); - } + /** + * Callback signature for the {@link SimpleStore#event:beforeUpdate} event. + * + * @example + * function onBeforeUpdate (mapperName, id, props, opts) { + * // do something + * } + * store.on('beforeUpdate', onBeforeUpdate); + * + * @callback SimpleStore~beforeUpdateListener + * @param {string} name The `name` argument received by {@link Mapper#beforeUpdate}. + * @param {string|number} id The `id` argument received by {@link Mapper#beforeUpdate}. + * @param {object} props The `props` argument received by {@link Mapper#beforeUpdate}. + * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdate}. + * @see SimpleStore#event:beforeUpdate + * @see SimpleStore#update + * @since 3.0.0 + */ - if (query) { - relatedData = _this10.removeAll(def.relation, query, optsCopy); - } + /** + * Fired during {@link SimpleStore#update}. See + * {@link SimpleStore~afterUpdateListener} for how to listen for this event. + * + * @event SimpleStore#afterUpdate + * @see SimpleStore~afterUpdateListener + * @see SimpleStore#update + */ - if (relatedData) { - if (utils.isArray(relatedData) && !relatedData.length) { - return; - } + /** + * Callback signature for the {@link SimpleStore#event:afterUpdate} event. + * + * @example + * function onAfterUpdate (mapperName, id, props, opts, result) { + * // do something + * } + * store.on('afterUpdate', onAfterUpdate); + * + * @callback SimpleStore~afterUpdateListener + * @param {string} name The `name` argument received by {@link Mapper#afterUpdate}. + * @param {string|number} id The `id` argument received by {@link Mapper#afterUpdate}. + * @param {object} props The `props` argument received by {@link Mapper#afterUpdate}. + * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdate}. + * @param {object} result The `result` argument received by {@link Mapper#afterUpdate}. + * @see SimpleStore#event:afterUpdate + * @see SimpleStore#update + * @since 3.0.0 + */ - if (def.type === hasOneType) { - relatedData = relatedData[0]; - } + /** + * Wrapper for {@link Mapper#update}. Adds the updated {@link Record} to the + * store. + * + * @example + * import { SimpleStore } from 'js-data'; + * import { HttpAdapter } from 'js-data-http'; + * + * const store = new SimpleStore(); + * store.registerAdapter('http', new HttpAdapter(), { default: true }); + * + * store.defineMapper('post'); + * + * // Since this example uses the http adapter, we'll get something like: + * // + * // PUT /post/1234 {"status":"published"} + * store.update('post', 1, { status: 'published' }).then((post) => { + * // The post record has also been updated in the in-memory store + * console.log(store.get('post', 1234)); + * }); + * + * @fires SimpleStore#beforeUpdate + * @fires SimpleStore#afterUpdate + * @fires SimpleStore#add + * @method SimpleStore#update + * @param {string} name Name of the {@link Mapper} to target. + * @param {(string|number)} id Passed to {@link Mapper#update}. + * @param {object} record Passed to {@link Mapper#update}. + * @param {object} [opts] Passed to {@link Mapper#update}. See + * {@link Mapper#update} for more configuration options. + * @returns {Promise} Resolves with the result of the update. + * @since 3.0.0 + */ - def.setLocalField(record, relatedData); - } - }); - }); - }, + }, { + key: "update", + value: function update(name, id, record) { + var _this12 = this; - /** - * Fired during {@link SimpleStore#update}. See - * {@link SimpleStore~beforeUpdateListener} for how to listen for this event. - * - * @event SimpleStore#beforeUpdate - * @see SimpleStore~beforeUpdateListener - * @see SimpleStore#update - */ + var opts = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; + return _get(_getPrototypeOf(SimpleStore.prototype), "update", this).call(this, name, id, record, opts).then(function (result) { + return _this12._end(name, result, opts); + }); + } + /** + * Fired during {@link SimpleStore#updateAll}. See + * {@link SimpleStore~beforeUpdateAllListener} for how to listen for this event. + * + * @event SimpleStore#beforeUpdateAll + * @see SimpleStore~beforeUpdateAllListener + * @see SimpleStore#updateAll + */ - /** - * Callback signature for the {@link SimpleStore#event:beforeUpdate} event. - * - * @example - * function onBeforeUpdate (mapperName, id, props, opts) { - * // do something - * } - * store.on('beforeUpdate', onBeforeUpdate); - * - * @callback SimpleStore~beforeUpdateListener - * @param {string} name The `name` argument received by {@link Mapper#beforeUpdate}. - * @param {string|number} id The `id` argument received by {@link Mapper#beforeUpdate}. - * @param {object} props The `props` argument received by {@link Mapper#beforeUpdate}. - * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdate}. - * @see SimpleStore#event:beforeUpdate - * @see SimpleStore#update - * @since 3.0.0 - */ + /** + * Callback signature for the {@link SimpleStore#event:beforeUpdateAll} event. + * + * @example + * function onBeforeUpdateAll (mapperName, props, query, opts) { + * // do something + * } + * store.on('beforeUpdateAll', onBeforeUpdateAll); + * + * @callback SimpleStore~beforeUpdateAllListener + * @param {string} name The `name` argument received by {@link Mapper#beforeUpdateAll}. + * @param {object} props The `props` argument received by {@link Mapper#beforeUpdateAll}. + * @param {object} query The `query` argument received by {@link Mapper#beforeUpdateAll}. + * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdateAll}. + * @see SimpleStore#event:beforeUpdateAll + * @see SimpleStore#updateAll + * @since 3.0.0 + */ - /** - * Fired during {@link SimpleStore#update}. See - * {@link SimpleStore~afterUpdateListener} for how to listen for this event. - * - * @event SimpleStore#afterUpdate - * @see SimpleStore~afterUpdateListener - * @see SimpleStore#update - */ + /** + * Fired during {@link SimpleStore#updateAll}. See + * {@link SimpleStore~afterUpdateAllListener} for how to listen for this event. + * + * @event SimpleStore#afterUpdateAll + * @see SimpleStore~afterUpdateAllListener + * @see SimpleStore#updateAll + */ - /** - * Callback signature for the {@link SimpleStore#event:afterUpdate} event. - * - * @example - * function onAfterUpdate (mapperName, id, props, opts, result) { - * // do something - * } - * store.on('afterUpdate', onAfterUpdate); - * - * @callback SimpleStore~afterUpdateListener - * @param {string} name The `name` argument received by {@link Mapper#afterUpdate}. - * @param {string|number} id The `id` argument received by {@link Mapper#afterUpdate}. - * @param {object} props The `props` argument received by {@link Mapper#afterUpdate}. - * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdate}. - * @param {object} result The `result` argument received by {@link Mapper#afterUpdate}. - * @see SimpleStore#event:afterUpdate - * @see SimpleStore#update - * @since 3.0.0 - */ + /** + * Callback signature for the {@link SimpleStore#event:afterUpdateAll} event. + * + * @example + * function onAfterUpdateAll (mapperName, props, query, opts, result) { + * // do something + * } + * store.on('afterUpdateAll', onAfterUpdateAll); + * + * @callback SimpleStore~afterUpdateAllListener + * @param {string} name The `name` argument received by {@link Mapper#afterUpdateAll}. + * @param {object} props The `props` argument received by {@link Mapper#afterUpdateAll}. + * @param {object} query The `query` argument received by {@link Mapper#afterUpdateAll}. + * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdateAll}. + * @param {object} result The `result` argument received by {@link Mapper#afterUpdateAll}. + * @see SimpleStore#event:afterUpdateAll + * @see SimpleStore#updateAll + * @since 3.0.0 + */ - /** - * Wrapper for {@link Mapper#update}. Adds the updated {@link Record} to the - * store. - * - * @example - * import { SimpleStore } from 'js-data'; - * import { HttpAdapter } from 'js-data-http'; - * - * const store = new SimpleStore(); - * store.registerAdapter('http', new HttpAdapter(), { default: true }); - * - * store.defineMapper('post'); - * - * // Since this example uses the http adapter, we'll get something like: - * // - * // PUT /post/1234 {"status":"published"} - * store.update('post', 1, { status: 'published' }).then((post) => { - * // The post record has also been updated in the in-memory store - * console.log(store.get('post', 1234)); - * }); - * - * @fires SimpleStore#beforeUpdate - * @fires SimpleStore#afterUpdate - * @fires SimpleStore#add - * @method SimpleStore#update - * @param {string} name Name of the {@link Mapper} to target. - * @param {(string|number)} id Passed to {@link Mapper#update}. - * @param {object} record Passed to {@link Mapper#update}. - * @param {object} [opts] Passed to {@link Mapper#update}. See - * {@link Mapper#update} for more configuration options. - * @returns {Promise} Resolves with the result of the update. - * @since 3.0.0 - */ - update: function update(name, id, record, opts) { - var _this11 = this; + /** + * Wrapper for {@link Mapper#updateAll}. Adds the updated {@link Record}s to + * the store. + * + * @example + * import { SimpleStore } from 'js-data'; + * import { HttpAdapter } from 'js-data-http'; + * + * const store = new SimpleStore(); + * store.registerAdapter('http', new HttpAdapter(), { default: true }); + * + * store.defineMapper('post'); + * + * // Since this example uses the http adapter, we'll get something like: + * // + * // PUT /post?author_id=1234 {"status":"published"} + * store.updateAll('post', { author_id: 1234 }, { status: 'published' }).then((posts) => { + * // The post records have also been updated in the in-memory store + * console.log(store.filter('posts', { author_id: 1234 })); + * }); + * + * @fires SimpleStore#beforeUpdateAll + * @fires SimpleStore#afterUpdateAll + * @fires SimpleStore#add + * @method SimpleStore#updateAll + * @param {string} name Name of the {@link Mapper} to target. + * @param {object} props Passed to {@link Mapper#updateAll}. + * @param {object} [query] Passed to {@link Mapper#updateAll}. + * @param {object} [opts] Passed to {@link Mapper#updateAll}. See + * {@link Mapper#updateAll} for more configuration options. + * @returns {Promise} Resolves with the result of the update. + * @since 3.0.0 + */ - opts || (opts = {}); - return Container.prototype.update.call(this, name, id, record, opts).then(function (result) { - return _this11._end(name, result, opts); - }); - }, + }, { + key: "updateAll", + value: function updateAll(name, props, query) { + var _this13 = this; - /** - * Fired during {@link SimpleStore#updateAll}. See - * {@link SimpleStore~beforeUpdateAllListener} for how to listen for this event. - * - * @event SimpleStore#beforeUpdateAll - * @see SimpleStore~beforeUpdateAllListener - * @see SimpleStore#updateAll - */ + var opts = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; + return _get(_getPrototypeOf(SimpleStore.prototype), "updateAll", this).call(this, name, props, query, opts).then(function (result) { + return _this13._end(name, result, opts); + }); + } + /** + * Fired during {@link SimpleStore#updateMany}. See + * {@link SimpleStore~beforeUpdateManyListener} for how to listen for this event. + * + * @event SimpleStore#beforeUpdateMany + * @see SimpleStore~beforeUpdateManyListener + * @see SimpleStore#updateMany + */ - /** - * Callback signature for the {@link SimpleStore#event:beforeUpdateAll} event. - * - * @example - * function onBeforeUpdateAll (mapperName, props, query, opts) { - * // do something - * } - * store.on('beforeUpdateAll', onBeforeUpdateAll); - * - * @callback SimpleStore~beforeUpdateAllListener - * @param {string} name The `name` argument received by {@link Mapper#beforeUpdateAll}. - * @param {object} props The `props` argument received by {@link Mapper#beforeUpdateAll}. - * @param {object} query The `query` argument received by {@link Mapper#beforeUpdateAll}. - * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdateAll}. - * @see SimpleStore#event:beforeUpdateAll - * @see SimpleStore#updateAll - * @since 3.0.0 - */ + /** + * Callback signature for the {@link SimpleStore#event:beforeUpdateMany} event. + * + * @example + * function onBeforeUpdateMany (mapperName, records, opts) { + * // do something + * } + * store.on('beforeUpdateMany', onBeforeUpdateMany); + * + * @callback SimpleStore~beforeUpdateManyListener + * @param {string} name The `name` argument received by {@link Mapper#beforeUpdateMany}. + * @param {object} records The `records` argument received by {@link Mapper#beforeUpdateMany}. + * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdateMany}. + * @see SimpleStore#event:beforeUpdateMany + * @see SimpleStore#updateMany + * @since 3.0.0 + */ - /** - * Fired during {@link SimpleStore#updateAll}. See - * {@link SimpleStore~afterUpdateAllListener} for how to listen for this event. - * - * @event SimpleStore#afterUpdateAll - * @see SimpleStore~afterUpdateAllListener - * @see SimpleStore#updateAll - */ + /** + * Fired during {@link SimpleStore#updateMany}. See + * {@link SimpleStore~afterUpdateManyListener} for how to listen for this event. + * + * @event SimpleStore#afterUpdateMany + * @see SimpleStore~afterUpdateManyListener + * @see SimpleStore#updateMany + */ - /** - * Callback signature for the {@link SimpleStore#event:afterUpdateAll} event. - * - * @example - * function onAfterUpdateAll (mapperName, props, query, opts, result) { - * // do something - * } - * store.on('afterUpdateAll', onAfterUpdateAll); - * - * @callback SimpleStore~afterUpdateAllListener - * @param {string} name The `name` argument received by {@link Mapper#afterUpdateAll}. - * @param {object} props The `props` argument received by {@link Mapper#afterUpdateAll}. - * @param {object} query The `query` argument received by {@link Mapper#afterUpdateAll}. - * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdateAll}. - * @param {object} result The `result` argument received by {@link Mapper#afterUpdateAll}. - * @see SimpleStore#event:afterUpdateAll - * @see SimpleStore#updateAll - * @since 3.0.0 - */ + /** + * Callback signature for the {@link SimpleStore#event:afterUpdateMany} event. + * + * @example + * function onAfterUpdateMany (mapperName, records, opts, result) { + * // do something + * } + * store.on('afterUpdateMany', onAfterUpdateMany); + * + * @callback SimpleStore~afterUpdateManyListener + * @param {string} name The `name` argument received by {@link Mapper#afterUpdateMany}. + * @param {object} records The `records` argument received by {@link Mapper#afterUpdateMany}. + * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdateMany}. + * @param {object} result The `result` argument received by {@link Mapper#afterUpdateMany}. + * @see SimpleStore#event:afterUpdateMany + * @see SimpleStore#updateMany + * @since 3.0.0 + */ - /** - * Wrapper for {@link Mapper#updateAll}. Adds the updated {@link Record}s to - * the store. - * - * @example - * import { SimpleStore } from 'js-data'; - * import { HttpAdapter } from 'js-data-http'; - * - * const store = new SimpleStore(); - * store.registerAdapter('http', new HttpAdapter(), { default: true }); - * - * store.defineMapper('post'); - * - * // Since this example uses the http adapter, we'll get something like: - * // - * // PUT /post?author_id=1234 {"status":"published"} - * store.updateAll('post', { author_id: 1234 }, { status: 'published' }).then((posts) => { - * // The post records have also been updated in the in-memory store - * console.log(store.filter('posts', { author_id: 1234 })); - * }); - * - * @fires SimpleStore#beforeUpdateAll - * @fires SimpleStore#afterUpdateAll - * @fires SimpleStore#add - * @method SimpleStore#updateAll - * @param {string} name Name of the {@link Mapper} to target. - * @param {object} props Passed to {@link Mapper#updateAll}. - * @param {object} [query] Passed to {@link Mapper#updateAll}. - * @param {object} [opts] Passed to {@link Mapper#updateAll}. See - * {@link Mapper#updateAll} for more configuration options. - * @returns {Promise} Resolves with the result of the update. - * @since 3.0.0 - */ - updateAll: function updateAll(name, props, query, opts) { - var _this12 = this; + /** + * Wrapper for {@link Mapper#updateMany}. Adds the updated {@link Record}s to + * the store. + * + * @example + * import { SimpleStore } from 'js-data'; + * import { HttpAdapter } from 'js-data-http'; + * + * const store = new SimpleStore(); + * store.registerAdapter('http', new HttpAdapter(), { default: true }); + * + * store.defineMapper('post'); + * + * // Since this example uses the http adapter, we'll get something like: + * // + * // PUT /post [{"id":3,status":"published"},{"id":4,status":"published"}] + * store.updateMany('post', [ + * { id: 3, status: 'published' }, + * { id: 4, status: 'published' } + * ]).then((posts) => { + * // The post records have also been updated in the in-memory store + * console.log(store.getAll('post', 3, 4)); + * }); + * + * @fires SimpleStore#beforeUpdateMany + * @fires SimpleStore#afterUpdateMany + * @fires SimpleStore#add + * @method SimpleStore#updateMany + * @param {string} name Name of the {@link Mapper} to target. + * @param {(Object[]|Record[])} records Passed to {@link Mapper#updateMany}. + * @param {object} [opts] Passed to {@link Mapper#updateMany}. See + * {@link Mapper#updateMany} for more configuration options. + * @returns {Promise} Resolves with the result of the update. + * @since 3.0.0 + */ - opts || (opts = {}); - return Container.prototype.updateAll.call(this, name, props, query, opts).then(function (result) { - return _this12._end(name, result, opts); - }); - }, + }, { + key: "updateMany", + value: function updateMany(name, records) { + var _this14 = this; - /** - * Fired during {@link SimpleStore#updateMany}. See - * {@link SimpleStore~beforeUpdateManyListener} for how to listen for this event. - * - * @event SimpleStore#beforeUpdateMany - * @see SimpleStore~beforeUpdateManyListener - * @see SimpleStore#updateMany - */ + var opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + return _get(_getPrototypeOf(SimpleStore.prototype), "updateMany", this).call(this, name, records, opts).then(function (result) { + return _this14._end(name, result, opts); + }); + } + /** + * Wrapper for {@link Collection#add}. + * + * @example SimpleStore#add + * const JSData = require('js-data'); + * const { SimpleStore } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new SimpleStore(); + * store.defineMapper('book'); + * + * // Add one book to the in-memory store: + * store.add('book', { id: 1, title: 'Respect your Data' }); + * // Add multiple books to the in-memory store: + * store.add('book', [ + * { id: 2, title: 'Easy data recipes' }, + * { id: 3, title: 'Active Record 101' } + * ]); + * + * @fires SimpleStore#add + * @method SimpleStore#add + * @param {(string|number)} name Name of the {@link Mapper} to target. + * @param {(Object|Object[]|Record|Record[])} records See {@link Collection#add}. + * @param {object} [opts] Configuration options. See {@link Collection#add}. + * @returns {(Object|Object[]|Record|Record[])} See {@link Collection#add}. + * @see Collection#add + * @see Collection#add + * @since 3.0.0 + */ - /** - * Callback signature for the {@link SimpleStore#event:beforeUpdateMany} event. - * - * @example - * function onBeforeUpdateMany (mapperName, records, opts) { - * // do something - * } - * store.on('beforeUpdateMany', onBeforeUpdateMany); - * - * @callback SimpleStore~beforeUpdateManyListener - * @param {string} name The `name` argument received by {@link Mapper#beforeUpdateMany}. - * @param {object} records The `records` argument received by {@link Mapper#beforeUpdateMany}. - * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdateMany}. - * @see SimpleStore#event:beforeUpdateMany - * @see SimpleStore#updateMany - * @since 3.0.0 - */ + }, { + key: "add", + value: function add(name, records, opts) { + return this.getCollection(name).add(records, opts); + } + /** + * Wrapper for {@link Collection#between}. + * + * @example + * // Get all users ages 18 to 30 + * const users = store.between('user', 18, 30, { index: 'age' }); + * + * @example + * // Same as above + * const users = store.between('user', [18], [30], { index: 'age' }); + * + * @method SimpleStore#between + * @param {(string|number)} name Name of the {@link Mapper} to target. + * @param {array} leftKeys See {@link Collection#between}. + * @param {array} rightKeys See {@link Collection#between}. + * @param {object} [opts] Configuration options. See {@link Collection#between}. + * @returns {Object[]|Record[]} See {@link Collection#between}. + * @see Collection#between + * @see Collection#between + * @since 3.0.0 + */ - /** - * Fired during {@link SimpleStore#updateMany}. See - * {@link SimpleStore~afterUpdateManyListener} for how to listen for this event. - * - * @event SimpleStore#afterUpdateMany - * @see SimpleStore~afterUpdateManyListener - * @see SimpleStore#updateMany - */ + }, { + key: "between", + value: function between(name, leftKeys, rightKeys, opts) { + return this.getCollection(name).between(leftKeys, rightKeys, opts); + } + /** + * Wrapper for {@link Collection#createIndex}. + * + * @example + * // Index users by age + * store.createIndex('user', 'age'); + * + * @example + * // Index users by status and role + * store.createIndex('user', 'statusAndRole', ['status', 'role']); + * + * @method SimpleStore#createIndex + * @param {(string|number)} name Name of the {@link Mapper} to target. + * @param {string} indexName See {@link Collection#createIndex}. + * @param {string[]} [fieldList] See {@link Collection#createIndex}. + * @param {object} [opts] Configuration options. See {@link Collection#between}. + * @see Collection#createIndex + * @see Collection#createIndex + * @since 3.0.0 + */ - /** - * Callback signature for the {@link SimpleStore#event:afterUpdateMany} event. - * - * @example - * function onAfterUpdateMany (mapperName, records, opts, result) { - * // do something - * } - * store.on('afterUpdateMany', onAfterUpdateMany); - * - * @callback SimpleStore~afterUpdateManyListener - * @param {string} name The `name` argument received by {@link Mapper#afterUpdateMany}. - * @param {object} records The `records` argument received by {@link Mapper#afterUpdateMany}. - * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdateMany}. - * @param {object} result The `result` argument received by {@link Mapper#afterUpdateMany}. - * @see SimpleStore#event:afterUpdateMany - * @see SimpleStore#updateMany - * @since 3.0.0 - */ + }, { + key: "createIndex", + value: function createIndex(name, indexName, fieldList, opts) { + return this.getCollection(name).createIndex(indexName, fieldList, opts); + } + /** + * Wrapper for {@link Collection#filter}. + * + * @example SimpleStore#filter + * const JSData = require('js-data'); + * const { SimpleStore } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new SimpleStore(); + * store.defineMapper('post'); + * store.add('post', [ + * { id: 1, status: 'draft', created_at_timestamp: new Date().getTime() } + * ]); + * + * // Get the draft posts created less than three months ago + * let posts = store.filter('post', { + * where: { + * status: { + * '==': 'draft' + * }, + * created_at_timestamp: { + * '>=': (new Date().getTime() - (1000 \* 60 \* 60 \* 24 \* 30 \* 3)) // 3 months ago + * } + * } + * }); + * console.log(posts); + * + * // Use a custom filter function + * posts = store.filter('post', function (post) { return post.id % 2 === 0 }); + * + * @method SimpleStore#filter + * @param {(string|number)} name Name of the {@link Mapper} to target. + * @param {(Object|Function)} [queryOrFn={}] See {@link Collection#filter}. + * @param {object} [thisArg] See {@link Collection#filter}. + * @returns {Array} See {@link Collection#filter}. + * @see Collection#filter + * @see Collection#filter + * @since 3.0.0 + */ - /** - * Wrapper for {@link Mapper#updateMany}. Adds the updated {@link Record}s to - * the store. - * - * @example - * import { SimpleStore } from 'js-data'; - * import { HttpAdapter } from 'js-data-http'; - * - * const store = new SimpleStore(); - * store.registerAdapter('http', new HttpAdapter(), { default: true }); - * - * store.defineMapper('post'); - * - * // Since this example uses the http adapter, we'll get something like: - * // - * // PUT /post [{"id":3,status":"published"},{"id":4,status":"published"}] - * store.updateMany('post', [ - * { id: 3, status: 'published' }, - * { id: 4, status: 'published' } - * ]).then((posts) => { - * // The post records have also been updated in the in-memory store - * console.log(store.getAll('post', 3, 4)); - * }); - * - * @fires SimpleStore#beforeUpdateMany - * @fires SimpleStore#afterUpdateMany - * @fires SimpleStore#add - * @method SimpleStore#updateMany - * @param {string} name Name of the {@link Mapper} to target. - * @param {(Object[]|Record[])} records Passed to {@link Mapper#updateMany}. - * @param {object} [opts] Passed to {@link Mapper#updateMany}. See - * {@link Mapper#updateMany} for more configuration options. - * @returns {Promise} Resolves with the result of the update. - * @since 3.0.0 - */ - updateMany: function updateMany(name, records, opts) { - var _this13 = this; + }, { + key: "filter", + value: function filter(name, queryOrFn, thisArg) { + return this.getCollection(name).filter(queryOrFn, thisArg); + } + /** + * Wrapper for {@link Collection#get}. + * + * @example SimpleStore#get + * const JSData = require('js-data'); + * const { SimpleStore } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new SimpleStore(); + * store.defineMapper('post'); + * store.add('post', [ + * { id: 1, status: 'draft', created_at_timestamp: new Date().getTime() } + * ]); + * + * console.log(store.get('post', 1)); // {...} + * console.log(store.get('post', 2)); // undefined + * + * @method SimpleStore#get + * @param {(string|number)} name Name of the {@link Mapper} to target. + * @param {(string|number)} id See {@link Collection#get}. + * @returns {(Object|Record)} See {@link Collection#get}. + * @see Collection#get + * @see Collection#get + * @since 3.0.0 + */ - opts || (opts = {}); - return Container.prototype.updateMany.call(this, name, records, opts).then(function (result) { - return _this13._end(name, result, opts); - }); - } - }; - proxiedCollectionMethods.forEach(function (method) { - props$1[method] = function (name) { - var _this$getCollection; + }, { + key: "get", + value: function get(name, id) { + return this.getCollection(name).get(id); + } + /** + * Wrapper for {@link Collection#getAll}. + * + * @example + * // Get the posts where "status" is "draft" or "inReview" + * const posts = store.getAll('post', 'draft', 'inReview', { index: 'status' }); + * + * @example + * // Same as above + * const posts = store.getAll('post', ['draft'], ['inReview'], { index: 'status' }); + * + * @method SimpleStore#getAll + * @param {(string|number)} name Name of the {@link Mapper} to target. + * @param {...Array} [keyList] See {@link Collection#getAll}. + * @param {object} [opts] See {@link Collection#getAll}. + * @returns {Array} See {@link Collection#getAll}. + * @see Collection#getAll + * @see Collection#getAll + * @since 3.0.0 + */ - for (var _len4 = arguments.length, args = new Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) { - args[_key4 - 1] = arguments[_key4]; - } + }, { + key: "getAll", + value: function getAll(name) { + var _this$getCollection; - return (_this$getCollection = this.getCollection(name))[method].apply(_this$getCollection, args); - }; - }); - var SimpleStore$1 = Container.extend(props$1); - /** - * Fired when a record changes. Only works for records that have tracked fields. - * See {@link SimpleStore~changeListener} on how to listen for this event. - * - * @event SimpleStore#change - * @see SimpleStore~changeListener - */ + for (var _len4 = arguments.length, args = new Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) { + args[_key4 - 1] = arguments[_key4]; + } - /** - * Callback signature for the {@link SimpleStore#event:change} event. - * - * @example - * function onChange (mapperName, record, changes) { - * // do something - * } - * store.on('change', onChange); - * - * @callback SimpleStore~changeListener - * @param {string} name The name of the associated {@link Mapper}. - * @param {Record} record The Record that changed. - * @param {object} changes The changes. - * @see SimpleStore#event:change - * @since 3.0.0 - */ + return (_this$getCollection = this.getCollection(name)).getAll.apply(_this$getCollection, args); + } + /** + * Wrapper for {@link Collection#prune}. + * + * @method SimpleStore#prune + * @param name + * @param {object} [opts] See {@link Collection#prune}. + * @returns {Array} See {@link Collection#prune}. + * @see Collection#prune + * @see Collection#prune + * @since 3.0.0 + */ - /** - * Fired when one or more records are added to the in-memory store. See - * {@link SimpleStore~addListener} on how to listen for this event. - * - * @event SimpleStore#add - * @see SimpleStore~addListener - * @see SimpleStore#event:add - * @see SimpleStore#add - * @see SimpleStore#create - * @see SimpleStore#createMany - * @see SimpleStore#find - * @see SimpleStore#findAll - * @see SimpleStore#update - * @see SimpleStore#updateAll - * @see SimpleStore#updateMany - */ + }, { + key: "prune", + value: function prune(name, opts) { + return this.getCollection(name).prune(opts); + } + /** + * Wrapper for {@link Collection#query}. + * + * @example + * // Grab page 2 of users between ages 18 and 30 + * store.query('user') + * .between(18, 30, { index: 'age' }) // between ages 18 and 30 + * .skip(10) // second page + * .limit(10) // page size + * .run(); + * + * @method SimpleStore#query + * @param {(string|number)} name Name of the {@link Mapper} to target. + * @returns {Query} See {@link Collection#query}. + * @see Collection#query + * @see Collection#query + * @since 3.0.0 + */ - /** - * Callback signature for the {@link SimpleStore#event:add} event. - * - * @example - * function onAdd (mapperName, recordOrRecords) { - * // do something - * } - * store.on('add', onAdd); - * - * @callback SimpleStore~addListener - * @param {string} name The name of the associated {@link Mapper}. - * @param {Record|Record[]} The Record or Records that were added. - * @see SimpleStore#event:add - * @see SimpleStore#add - * @see SimpleStore#create - * @see SimpleStore#createMany - * @see SimpleStore#find - * @see SimpleStore#findAll - * @see SimpleStore#update - * @see SimpleStore#updateAll - * @see SimpleStore#updateMany - * @since 3.0.0 - */ + }, { + key: "query", + value: function query(name) { + return this.getCollection(name).query(); + } + /** + * Wrapper for {@link Collection#toJSON}. + * + * @example + * store.defineMapper('post', { + * schema: { + * properties: { + * id: { type: 'number' }, + * title: { type: 'string' } + * } + * } + * }); + * store.add('post', [ + * { id: 1, status: 'published', title: 'Respect your Data' }, + * { id: 2, status: 'draft', title: 'Connecting to a data source' } + * ]); + * console.log(store.toJSON('post')); + * const draftsJSON = store.query('post') + * .filter({ status: 'draft' }) + * .mapCall('toJSON') + * .run(); + * + * @method SimpleStore#toJSON + * @param {(string|number)} name Name of the {@link Mapper} to target. + * @param {object} [opts] See {@link Collection#toJSON}. + * @returns {Array} See {@link Collection#toJSON}. + * @see Collection#toJSON + * @see Collection#toJSON + * @since 3.0.0 + */ - /** - * Fired when one or more records are removed from the in-memory store. See - * {@link SimpleStore~removeListener} for how to listen for this event. - * - * @event SimpleStore#remove - * @see SimpleStore~removeListener - * @see SimpleStore#event:remove - * @see SimpleStore#clear - * @see SimpleStore#destroy - * @see SimpleStore#destroyAll - * @see SimpleStore#remove - * @see SimpleStore#removeAll - */ + }, { + key: "toJSON", + value: function toJSON(name, opts) { + return this.getCollection(name).toJSON(opts); + } + /** + * Wrapper for {@link Collection#unsaved}. + * + * @method SimpleStore#unsaved + * @returns {Array} See {@link Collection#unsaved}. + * @see Collection#unsaved + * @see Collection#unsaved + * @since 3.0.0 + */ - /** - * Callback signature for the {@link SimpleStore#event:remove} event. - * - * @example - * function onRemove (mapperName, recordsOrRecords) { - * // do something - * } - * store.on('remove', onRemove); - * - * @callback SimpleStore~removeListener - * @param {string} name The name of the associated {@link Mapper}. - * @param {Record|Record[]} Record or Records that were removed. - * @see SimpleStore#event:remove - * @see SimpleStore#clear - * @see SimpleStore#destroy - * @see SimpleStore#destroyAll - * @see SimpleStore#remove - * @see SimpleStore#removeAll - * @since 3.0.0 - */ + }, { + key: "unsaved", + value: function unsaved(name, opts) { + return this.getCollection(name).unsaved(opts); + } + }]); - /** - * Create a subclass of this SimpleStore: - * @example SimpleStore.extend - * const JSData = require('js-data'); - * const { SimpleStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * // Extend the class using ES2015 class syntax. - * class CustomSimpleStoreClass extends SimpleStore { - * foo () { return 'bar'; } - * static beep () { return 'boop'; } - * } - * const customSimpleStore = new CustomSimpleStoreClass(); - * console.log(customSimpleStore.foo()); - * console.log(CustomSimpleStoreClass.beep()); - * - * // Extend the class using alternate method. - * const OtherSimpleStoreClass = SimpleStore.extend({ - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }) - * const otherSimpleStore = new OtherSimpleStoreClass(); - * console.log(otherSimpleStore.foo()); - * console.log(OtherSimpleStoreClass.beep()); - * - * // Extend the class, providing a custom constructor. - * function AnotherSimpleStoreClass () { - * SimpleStore.call(this) - * this.created_at = new Date().getTime() - * } - * SimpleStore.extend({ - * constructor: AnotherSimpleStoreClass, - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }) - * const anotherSimpleStore = new AnotherSimpleStoreClass(); - * console.log(anotherSimpleStore.created_at); - * console.log(anotherSimpleStore.foo()); - * console.log(AnotherSimpleStoreClass.beep()); - * - * @method SimpleStore.extend - * @param {object} [props={}] Properties to add to the prototype of the - * subclass. - * @param {object} [props.constructor] Provide a custom constructor function - * to be used as the subclass itself. - * @param {object} [classProps={}] Static properties to add to the subclass. - * @returns {Constructor} Subclass of this SimpleStore class. - * @since 3.0.0 - */ + return SimpleStore; + }(Container); var DOMAIN$9 = 'LinkedCollection'; - /** - * Extends {@link Collection}. Used by a {@link DataStore} to implement an - * Identity Map. - * - * ```javascript - * import {LinkedCollection} from 'js-data' - * ``` - * - * @class LinkedCollection - * @extends Collection - * @param {array} [records] Initial set of records to insert into the - * collection. See {@link Collection}. - * @param {object} [opts] Configuration options. See {@link Collection}. - * @returns {Mapper} + /** + * Extends {@link Collection}. Used by a {@link DataStore} to implement an + * Identity Map. + * + * @example + * import {LinkedCollection} from 'js-data'; + * + * // Extend the class using ES2015 class syntax. + * class CustomLinkedCollectionClass extends LinkedCollection { + * foo () { return 'bar'; } + * static beep () { return 'boop'; } + * } + * const customLinkedCollection = new CustomLinkedCollectionClass(); + * console.log(customLinkedCollection.foo()); + * console.log(CustomLinkedCollectionClass.beep()); + * + * @class LinkedCollection + * @extends Collection + * @param {array} [records] Initial set of records to insert into the + * collection. See {@link Collection}. + * @param {object} [opts] Configuration options. See {@link Collection}. + * @returns {Mapper} */ - function LinkedCollection(records, opts) { - utils.classCallCheck(this, LinkedCollection); // Make sure this collection has somewhere to store "added" timestamps + var LinkedCollection = + /*#__PURE__*/ + function (_Collection) { + _inherits(LinkedCollection, _Collection); - Object.defineProperties(this, { - _added: { - value: {} - }, - datastore: { - writable: true, - value: undefined + function LinkedCollection(records, opts) { + var _this; + + _classCallCheck(this, LinkedCollection); + + _this = _possibleConstructorReturn(this, _getPrototypeOf(LinkedCollection).call(this, records, opts)); // Make sure this collection has a reference to a datastore + + if (!_this.datastore) { + throw utils.err("new ".concat(DOMAIN$9), 'opts.datastore')(400, 'DataStore', _this.datastore); } - }); - Collection$1.call(this, records, opts); // Make sure this collection has a reference to a datastore - if (!this.datastore) { - throw utils.err("new ".concat(DOMAIN$9), 'opts.datastore')(400, 'DataStore', this.datastore); + return _this; } - } - var LinkedCollection$1 = Collection$1.extend({ - constructor: LinkedCollection, - _addMeta: function _addMeta(record, timestamp) { - // Track when this record was added - this._added[this.recordId(record)] = timestamp; + _createClass(LinkedCollection, [{ + key: "_addMeta", + value: function _addMeta(record, timestamp) { + // Track when this record was added + this._added[this.recordId(record)] = timestamp; - if (utils.isFunction(record._set)) { - record._set('$', timestamp); + if (utils.isFunction(record._set)) { + record._set('$', timestamp); + } } - }, - _clearMeta: function _clearMeta(record) { - delete this._added[this.recordId(record)]; + }, { + key: "_clearMeta", + value: function _clearMeta(record) { + delete this._added[this.recordId(record)]; - if (utils.isFunction(record._set)) { - record._set('$'); // unset + if (utils.isFunction(record._set)) { + record._set('$'); // unset + } } - }, - _onRecordEvent: function _onRecordEvent() { - for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { - args[_key] = arguments[_key]; - } + }, { + key: "_onRecordEvent", + value: function _onRecordEvent() { + for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } - Collection$1.prototype._onRecordEvent.apply(this, args); + Collection.prototype._onRecordEvent.apply(this, args); - var event = args[0]; // This is a very brute force method - // Lots of room for optimization + var event = args[0]; // This is a very brute force method + // Lots of room for optimization - if (utils.isString(event) && event.indexOf('change') === 0) { - this.updateIndexes(args[1]); + if (utils.isString(event) && event.indexOf('change') === 0) { + this.updateIndexes(args[1]); + } } - }, - add: function add(records, opts) { - var _this = this; + }, { + key: "add", + value: function add(records, opts) { + var _this2 = this; - var mapper = this.mapper; - var timestamp = new Date().getTime(); - var singular = utils.isObject(records) && !utils.isArray(records); + var mapper = this.mapper; + var timestamp = new Date().getTime(); + var singular = utils.isObject(records) && !utils.isArray(records); - if (singular) { - records = [records]; - } + if (singular) { + records = [records]; + } - records = Collection$1.prototype.add.call(this, records, opts); + records = _get(_getPrototypeOf(LinkedCollection.prototype), "add", this).call(this, records, opts); - if (mapper.relationList.length && records.length) { - // Check the currently visited record for relations that need to be - // inserted into their respective collections. - mapper.relationList.forEach(function (def) { - def.addLinkedRecords(records); + if (mapper.relationList.length && records.length) { + // Check the currently visited record for relations that need to be + // inserted into their respective collections. + mapper.relationList.forEach(function (def) { + def.addLinkedRecords(records); + }); + } + + records.forEach(function (record) { + return _this2._addMeta(record, timestamp); }); + return singular ? records[0] : records; } + }, { + key: "remove", + value: function remove(idOrRecord, opts) { + var mapper = this.mapper; - records.forEach(function (record) { - return _this._addMeta(record, timestamp); - }); - return singular ? records[0] : records; - }, - remove: function remove(idOrRecord, opts) { - var mapper = this.mapper; - var record = Collection$1.prototype.remove.call(this, idOrRecord, opts); + var record = _get(_getPrototypeOf(LinkedCollection.prototype), "remove", this).call(this, idOrRecord, opts); - if (record) { - this._clearMeta(record); - } + if (record) { + this._clearMeta(record); + } - if (mapper.relationList.length && record) { - mapper.relationList.forEach(function (def) { - def.removeLinkedRecords(mapper, [record]); - }); + if (mapper.relationList.length && record) { + mapper.relationList.forEach(function (def) { + def.removeLinkedRecords(mapper, [record]); + }); + } + + return record; } + }, { + key: "removeAll", + value: function removeAll(query, opts) { + var mapper = this.mapper; - return record; - }, - removeAll: function removeAll(query, opts) { - var mapper = this.mapper; - var records = Collection$1.prototype.removeAll.call(this, query, opts); - records.forEach(this._clearMeta, this); + var records = _get(_getPrototypeOf(LinkedCollection.prototype), "removeAll", this).call(this, query, opts); - if (mapper.relationList.length && records.length) { - mapper.relationList.forEach(function (def) { - def.removeLinkedRecords(mapper, records); - }); + records.forEach(this._clearMeta, this); + + if (mapper.relationList.length && records.length) { + mapper.relationList.forEach(function (def) { + def.removeLinkedRecords(mapper, records); + }); + } + + return records; } + }]); - return records; - } - }); - /** - * Create a subclass of this LinkedCollection: - * - * @example LinkedCollection.extend - * const JSData = require('js-data'); - * const { LinkedCollection } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * // Extend the class using ES2015 class syntax. - * class CustomLinkedCollectionClass extends LinkedCollection { - * foo () { return 'bar'; } - * static beep () { return 'boop'; } - * } - * const customLinkedCollection = new CustomLinkedCollectionClass(); - * console.log(customLinkedCollection.foo()); - * console.log(CustomLinkedCollectionClass.beep()); - * - * // Extend the class using alternate method. - * const OtherLinkedCollectionClass = LinkedCollection.extend({ - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }); - * const otherLinkedCollection = new OtherLinkedCollectionClass(); - * console.log(otherLinkedCollection.foo()); - * console.log(OtherLinkedCollectionClass.beep()); - * - * // Extend the class, providing a custom constructor. - * function AnotherLinkedCollectionClass () { - * LinkedCollection.call(this); - * this.created_at = new Date().getTime(); - * } - * LinkedCollection.extend({ - * constructor: AnotherLinkedCollectionClass, - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }); - * const anotherLinkedCollection = new AnotherLinkedCollectionClass(); - * console.log(anotherLinkedCollection.created_at); - * console.log(anotherLinkedCollection.foo()); - * console.log(AnotherLinkedCollectionClass.beep()); - * - * @method LinkedCollection.extend - * @param {object} [props={}] Properties to add to the prototype of the - * subclass. - * @param {object} [props.constructor] Provide a custom constructor function - * to be used as the subclass itself. - * @param {object} [classProps={}] Static properties to add to the subclass. - * @returns {Constructor} Subclass of this LinkedCollection class. - * @since 3.0.0 - */ + return LinkedCollection; + }(Collection); var DATASTORE_DEFAULTS = { - /** - * Whether in-memory relations should be unlinked from records after they are - * destroyed. - * - * @default true - * @name DataStore#unlinkOnDestroy - * @since 3.0.0 - * @type {boolean} - */ - unlinkOnDestroy: true + /** + * Whether in-memory relations should be unlinked from records after they are + * destroyed. + * + * @default true + * @name DataStore#unlinkOnDestroy + * @since 3.0.0 + * @type {boolean} + */ + unlinkOnDestroy: true, + collectionClass: LinkedCollection }; - /** - * The `DataStore` class is an extension of {@link SimpleStore}. Not only does - * `DataStore` manage mappers and store data in collections, it uses the - * {@link LinkedCollection} class to link related records together in memory. - * - * ```javascript - * import { DataStore } from 'js-data'; - * ``` - * - * @example - * import { DataStore } from 'js-data'; - * import HttpAdapter from 'js-data-http'; - * const store = new DataStore(); - * - * // DataStore#defineMapper returns a direct reference to the newly created - * // Mapper. - * const UserMapper = store.defineMapper('user'); - * - * // DataStore#as returns the store scoped to a particular Mapper. - * const UserStore = store.as('user'); - * - * // Call "find" on "UserMapper" (Stateless ORM) - * UserMapper.find(1).then((user) => { - * // retrieved a "user" record via the http adapter, but that's it - * - * // Call "find" on "store" targeting "user" (Stateful DataStore) - * return store.find('user', 1); // same as "UserStore.find(1)" - * }).then((user) => { - * // not only was a "user" record retrieved, but it was added to the - * // store's "user" collection - * const cachedUser = store.getCollection('user').get(1); - * console.log(user === cachedUser); // true - * }); - * - * @class DataStore - * @extends SimpleStore - * @param {object} [opts] Configuration options. See {@link SimpleStore}. - * @param {boolean} [opts.collectionClass={@link LinkedCollection}] See {@link DataStore#collectionClass}. - * @param {boolean} [opts.debug=false] See {@link Component#debug}. - * @param {boolean} [opts.unlinkOnDestroy=true] See {@link DataStore#unlinkOnDestroy}. - * @param {boolean|Function} [opts.usePendingFind=true] See {@link DataStore#usePendingFind}. - * @param {boolean|Function} [opts.usePendingFindAll=true] See {@link DataStore#usePendingFindAll}. - * @returns {DataStore} - * @see SimpleStore - * @since 3.0.0 - * @tutorial ["http://www.js-data.io/v3.0/docs/components-of-jsdata#datastore","Components of JSData: DataStore"] - * @tutorial ["http://www.js-data.io/v3.0/docs/working-with-the-datastore","Working with the DataStore"] - * @tutorial ["http://www.js-data.io/v3.0/docs/jsdata-and-the-browser","Notes on using JSData in the Browser"] + /** + * The `DataStore` class is an extension of {@link SimpleStore}. Not only does + * `DataStore` manage mappers and store data in collections, it uses the + * {@link LinkedCollection} class to link related records together in memory. + * + * ```javascript + * import { DataStore } from 'js-data'; + * ``` + * + * @example + * import { DataStore } from 'js-data'; + * import HttpAdapter from 'js-data-http'; + * const store = new DataStore(); + * + * // DataStore#defineMapper returns a direct reference to the newly created + * // Mapper. + * const UserMapper = store.defineMapper('user'); + * + * // DataStore#as returns the store scoped to a particular Mapper. + * const UserStore = store.as('user'); + * + * // Call "find" on "UserMapper" (Stateless ORM) + * UserMapper.find(1).then((user) => { + * // retrieved a "user" record via the http adapter, but that's it + * + * // Call "find" on "store" targeting "user" (Stateful DataStore) + * return store.find('user', 1); // same as "UserStore.find(1)" + * }).then((user) => { + * // not only was a "user" record retrieved, but it was added to the + * // store's "user" collection + * const cachedUser = store.getCollection('user').get(1); + * console.log(user === cachedUser); // true + * }); + * + * @class DataStore + * @extends SimpleStore + * @param {object} [opts] Configuration options. See {@link SimpleStore}. + * @param {boolean} [opts.collectionClass={@link LinkedCollection}] See {@link DataStore#collectionClass}. + * @param {boolean} [opts.debug=false] See {@link Component#debug}. + * @param {boolean} [opts.unlinkOnDestroy=true] See {@link DataStore#unlinkOnDestroy}. + * @param {boolean|Function} [opts.usePendingFind=true] See {@link DataStore#usePendingFind}. + * @param {boolean|Function} [opts.usePendingFindAll=true] See {@link DataStore#usePendingFindAll}. + * @returns {DataStore} + * @see SimpleStore + * @since 3.0.0 + * @tutorial ["http://www.js-data.io/v3.0/docs/components-of-jsdata#datastore","Components of JSData: DataStore"] + * @tutorial ["http://www.js-data.io/v3.0/docs/working-with-the-datastore","Working with the DataStore"] + * @tutorial ["http://www.js-data.io/v3.0/docs/jsdata-and-the-browser","Notes on using JSData in the Browser"] */ - function DataStore(opts) { - utils.classCallCheck(this, DataStore); - opts || (opts = {}); // Fill in any missing options with the defaults + var DataStore = + /*#__PURE__*/ + function (_SimpleStore) { + _inherits(DataStore, _SimpleStore); - utils.fillIn(opts, DATASTORE_DEFAULTS); - opts.collectionClass || (opts.collectionClass = LinkedCollection$1); - SimpleStore$1.call(this, opts); - } + function DataStore() { + var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - var props$2 = { - constructor: DataStore, - defineMapper: function defineMapper(name, opts) { - // Complexity of this method is beyond simply using => functions to bind context - var self = this; - var mapper = SimpleStore$1.prototype.defineMapper.call(self, name, opts); - var idAttribute = mapper.idAttribute; - var collection = this.getCollection(name); - mapper.relationList.forEach(function (def) { - var relation = def.relation; - var localField = def.localField; - var path = "links.".concat(localField); - var foreignKey = def.foreignKey; - var type = def.type; - var updateOpts = { - index: foreignKey - }; - var descriptor; + _classCallCheck(this, DataStore); - var getter = function getter() { - return this._get(path); - }; + // Fill in any missing options with the defaults + return _possibleConstructorReturn(this, _getPrototypeOf(DataStore).call(this, Object.assign(Object.assign({}, DATASTORE_DEFAULTS), opts))); + } + /** + * Creates a new [Mapper] with [name] from the [opts] + * @param {string} name + * @param {object} opts + * @returns {*} + */ - if (type === belongsToType) { - if (!collection.indexes[foreignKey]) { - collection.createIndex(foreignKey); - } - descriptor = { - get: getter, - // e.g. profile.user = someUser - // or comment.post = somePost - set: function set(record) { - // e.g. const otherUser = profile.user - var currentParent = this._get(path); // e.g. profile.user === someUser + _createClass(DataStore, [{ + key: "defineMapper", + value: function defineMapper(name, opts) { + // Complexity of this method is beyond simply using => functions to bind context + var self = this; + var mapper = _get(_getPrototypeOf(DataStore.prototype), "defineMapper", this).call(this, name, opts); - if (record === currentParent) { - return currentParent; - } + var idAttribute = mapper.idAttribute; + var collection = this.getCollection(name); + mapper.relationList.forEach(function (def) { + var relation = def.relation; + var localField = def.localField; + var path = "links.".concat(localField); + var foreignKey = def.foreignKey; + var type = def.type; + var updateOpts = { + index: foreignKey + }; + var descriptor; - var id = utils.get(this, idAttribute); - var inverseDef = def.getInverse(mapper); // e.g. profile.user !== someUser - // or comment.post !== somePost + var getter = function getter() { + return this._get(path); + }; - if (currentParent && inverseDef) { - this.removeInverseRelation(currentParent, id, inverseDef, idAttribute); - } + if (type === belongsToType) { + if (!collection.indexes[foreignKey]) { + collection.createIndex(foreignKey); + } - if (record) { - // e.g. profile.user = someUser - var relatedIdAttribute = def.getRelation().idAttribute; - var relatedId = utils.get(record, relatedIdAttribute); // Prefer store record + descriptor = { + get: getter, + // e.g. profile.user = someUser + // or comment.post = somePost + set: function set(record) { + // e.g. const otherUser = profile.user + var currentParent = this._get(path); // e.g. profile.user === someUser - if (relatedId !== undefined && this._get('$')) { - record = self.get(relation, relatedId) || record; - } // Set locals - // e.g. profile.user = someUser - // or comment.post = somePost + if (record === currentParent) { + return currentParent; + } - safeSetLink(this, localField, record); - safeSetProp(this, foreignKey, relatedId); - collection.updateIndex(this, updateOpts); + var id = utils.get(this, idAttribute); + var inverseDef = def.getInverse(mapper); // e.g. profile.user !== someUser + // or comment.post !== somePost - if (inverseDef) { - this.setupInverseRelation(record, id, inverseDef, idAttribute); + if (currentParent && inverseDef) { + this.removeInverseRelation(currentParent, id, inverseDef, idAttribute); } - } else { - // Unset in-memory link only - // e.g. profile.user = undefined - // or comment.post = undefined - safeSetLink(this, localField, undefined); - } - return record; - } - }; - var foreignKeyDescriptor = Object.getOwnPropertyDescriptor(mapper.recordClass.prototype, foreignKey); + if (record) { + // e.g. profile.user = someUser + var relatedIdAttribute = def.getRelation().idAttribute; + var relatedId = utils.get(record, relatedIdAttribute); // Prefer store record - if (!foreignKeyDescriptor) { - foreignKeyDescriptor = { - enumerable: true - }; - } + if (relatedId !== undefined && this._get('$')) { + record = self.get(relation, relatedId) || record; + } // Set locals + // e.g. profile.user = someUser + // or comment.post = somePost + + + safeSetLink(this, localField, record); + safeSetProp(this, foreignKey, relatedId); + collection.updateIndex(this, updateOpts); + + if (inverseDef) { + this.setupInverseRelation(record, id, inverseDef, idAttribute); + } + } else { + // Unset in-memory link only + // e.g. profile.user = undefined + // or comment.post = undefined + safeSetLink(this, localField, undefined); + } - var originalGet = foreignKeyDescriptor.get; + return record; + } + }; + var foreignKeyDescriptor = Object.getOwnPropertyDescriptor(mapper.recordClass.prototype, foreignKey); - foreignKeyDescriptor.get = function () { - if (originalGet) { - return originalGet.call(this); + if (!foreignKeyDescriptor) { + foreignKeyDescriptor = { + enumerable: true + }; } - return this._get("props.".concat(foreignKey)); - }; + var originalGet = foreignKeyDescriptor.get; - var originalSet = foreignKeyDescriptor.set; + foreignKeyDescriptor.get = function () { + if (originalGet) { + return originalGet.call(this); + } - foreignKeyDescriptor.set = function (value) { - var _this = this; + return this._get("props.".concat(foreignKey)); + }; - if (originalSet) { - originalSet.call(this, value); - } + var originalSet = foreignKeyDescriptor.set; - var currentParent = utils.get(this, localField); - var id = utils.get(this, idAttribute); - var inverseDef = def.getInverse(mapper); - var currentParentId = currentParent ? utils.get(currentParent, def.getRelation().idAttribute) : undefined; + foreignKeyDescriptor.set = function (value) { + var _this = this; - if (inverseDef && currentParent && currentParentId !== undefined && currentParentId !== value) { - if (inverseDef.type === hasOneType) { - safeSetLink(currentParent, inverseDef.localField, undefined); - } else if (inverseDef.type === hasManyType) { - var children = utils.get(currentParent, inverseDef.localField); + if (originalSet) { + originalSet.call(this, value); + } - if (id === undefined) { - utils.remove(children, function (child) { - return child === _this; - }); - } else { - utils.remove(children, function (child) { - return child === _this || id === utils.get(child, idAttribute); - }); + var currentParent = utils.get(this, localField); + var id = utils.get(this, idAttribute); + var inverseDef = def.getInverse(mapper); + var currentParentId = currentParent ? utils.get(currentParent, def.getRelation().idAttribute) : undefined; + + if (inverseDef && currentParent && currentParentId !== undefined && currentParentId !== value) { + if (inverseDef.type === hasOneType) { + safeSetLink(currentParent, inverseDef.localField, undefined); + } else if (inverseDef.type === hasManyType) { + var children = utils.get(currentParent, inverseDef.localField); + + if (id === undefined) { + utils.remove(children, function (child) { + return child === _this; + }); + } else { + utils.remove(children, function (child) { + return child === _this || id === utils.get(child, idAttribute); + }); + } } } - } - safeSetProp(this, foreignKey, value); - collection.updateIndex(this, updateOpts); + safeSetProp(this, foreignKey, value); + collection.updateIndex(this, updateOpts); - if (value === undefined || value === null) { - if (currentParentId !== undefined) { - // Unset locals - utils.set(this, localField, undefined); - } - } else if (this._get('$')) { - var storeRecord = self.get(relation, value); + if (value === undefined || value === null) { + if (currentParentId !== undefined) { + // Unset locals + utils.set(this, localField, undefined); + } + } else if (this._get('$')) { + var storeRecord = self.get(relation, value); - if (storeRecord) { - utils.set(this, localField, storeRecord); + if (storeRecord) { + utils.set(this, localField, storeRecord); + } } - } - }; + }; - Object.defineProperty(mapper.recordClass.prototype, foreignKey, foreignKeyDescriptor); - } else if (type === hasManyType) { - var localKeys = def.localKeys; - var foreignKeys = def.foreignKeys; // TODO: Handle case when belongsTo relation isn't ever defined + Object.defineProperty(mapper.recordClass.prototype, foreignKey, foreignKeyDescriptor); + } else if (type === hasManyType) { + var localKeys = def.localKeys; + var foreignKeys = def.foreignKeys; // TODO: Handle case when belongsTo relation isn't ever defined - if (self._collections[relation] && foreignKey && !self.getCollection(relation).indexes[foreignKey]) { - self.getCollection(relation).createIndex(foreignKey); - } + if (self._collections[relation] && foreignKey && !self.getCollection(relation).indexes[foreignKey]) { + self.getCollection(relation).createIndex(foreignKey); + } - descriptor = { - get: function get() { - var current = getter.call(this); + descriptor = { + get: function get() { + var current = getter.call(this); - if (!current) { - this._set(path, []); - } + if (!current) { + this._set(path, []); + } - return getter.call(this); - }, - // e.g. post.comments = someComments - // or user.groups = someGroups - // or group.users = someUsers - set: function set(records) { - var _this2 = this; + return getter.call(this); + }, + // e.g. post.comments = someComments + // or user.groups = someGroups + // or group.users = someUsers + set: function set(records) { + var _this2 = this; - if (records && !utils.isArray(records)) { - records = [records]; - } + if (records && !utils.isArray(records)) { + records = [records]; + } - var id = utils.get(this, idAttribute); - var relatedIdAttribute = def.getRelation().idAttribute; - var inverseDef = def.getInverse(mapper); - var inverseLocalField = inverseDef.localField; - var current = this._get(path) || []; - var toLink = []; - var toLinkIds = {}; - - if (records) { - records.forEach(function (record) { - // e.g. comment.id - var relatedId = utils.get(record, relatedIdAttribute); - var currentParent = utils.get(record, inverseLocalField); - - if (currentParent && currentParent !== _this2) { - var currentChildrenOfParent = utils.get(currentParent, localField); // e.g. somePost.comments.remove(comment) - - if (relatedId === undefined) { - utils.remove(currentChildrenOfParent, function (child) { - return child === record; - }); - } else { - utils.remove(currentChildrenOfParent, function (child) { - return child === record || relatedId === utils.get(child, relatedIdAttribute); - }); + var id = utils.get(this, idAttribute); + var relatedIdAttribute = def.getRelation().idAttribute; + var inverseDef = def.getInverse(mapper); + var inverseLocalField = inverseDef.localField; + var current = this._get(path) || []; + var toLink = []; + var toLinkIds = {}; + + if (records) { + records.forEach(function (record) { + // e.g. comment.id + var relatedId = utils.get(record, relatedIdAttribute); + var currentParent = utils.get(record, inverseLocalField); + + if (currentParent && currentParent !== _this2) { + var currentChildrenOfParent = utils.get(currentParent, localField); // e.g. somePost.comments.remove(comment) + + if (relatedId === undefined) { + utils.remove(currentChildrenOfParent, function (child) { + return child === record; + }); + } else { + utils.remove(currentChildrenOfParent, function (child) { + return child === record || relatedId === utils.get(child, relatedIdAttribute); + }); + } } - } - if (relatedId !== undefined) { - if (_this2._get('$')) { - // Prefer store record - record = self.get(relation, relatedId) || record; - } // e.g. toLinkIds[comment.id] = comment + if (relatedId !== undefined) { + if (_this2._get('$')) { + // Prefer store record + record = self.get(relation, relatedId) || record; + } // e.g. toLinkIds[comment.id] = comment - toLinkIds[relatedId] = record; - } + toLinkIds[relatedId] = record; + } - toLink.push(record); - }); - } // e.g. post.comments = someComments + toLink.push(record); + }); + } // e.g. post.comments = someComments - if (foreignKey) { - current.forEach(function (record) { - // e.g. comment.id - var relatedId = utils.get(record, relatedIdAttribute); + if (foreignKey) { + current.forEach(function (record) { + // e.g. comment.id + var relatedId = utils.get(record, relatedIdAttribute); - if (relatedId === undefined && toLink.indexOf(record) === -1 || relatedId !== undefined && !(relatedId in toLinkIds)) { - // Update (unset) inverse relation - if (records) { - // e.g. comment.post_id = undefined - safeSetProp(record, foreignKey, undefined); // e.g. CommentCollection.updateIndex(comment, { index: 'post_id' }) + if (relatedId === undefined && toLink.indexOf(record) === -1 || relatedId !== undefined && !(relatedId in toLinkIds)) { + // Update (unset) inverse relation + if (records) { + // e.g. comment.post_id = undefined + safeSetProp(record, foreignKey, undefined); // e.g. CommentCollection.updateIndex(comment, { index: 'post_id' }) - self.getCollection(relation).updateIndex(record, updateOpts); - } // e.g. comment.post = undefined + self.getCollection(relation).updateIndex(record, updateOpts); + } // e.g. comment.post = undefined - safeSetLink(record, inverseLocalField, undefined); - } - }); - toLink.forEach(function (record) { - // Update (set) inverse relation - // e.g. comment.post_id = post.id - safeSetProp(record, foreignKey, id); // e.g. CommentCollection.updateIndex(comment, { index: 'post_id' }) + safeSetLink(record, inverseLocalField, undefined); + } + }); + toLink.forEach(function (record) { + // Update (set) inverse relation + // e.g. comment.post_id = post.id + safeSetProp(record, foreignKey, id); // e.g. CommentCollection.updateIndex(comment, { index: 'post_id' }) - self.getCollection(relation).updateIndex(record, updateOpts); // e.g. comment.post = post + self.getCollection(relation).updateIndex(record, updateOpts); // e.g. comment.post = post - safeSetLink(record, inverseLocalField, _this2); - }); - } else if (localKeys) { - // Update locals - // e.g. group.users = someUsers - // Update (set) inverse relation - var ids = toLink.map(function (child) { - return utils.get(child, relatedIdAttribute); - }).filter(function (id) { - return id !== undefined; - }); // e.g. group.user_ids = [1,2,3,...] - - utils.set(this, localKeys, ids); // Update (unset) inverse relation - - if (inverseDef.foreignKeys) { - current.forEach(function (child) { - var relatedId = utils.get(child, relatedIdAttribute); - - if (relatedId === undefined && toLink.indexOf(child) === -1 || relatedId !== undefined && !(relatedId in toLinkIds)) { - // Update inverse relation - // safeSetLink(child, inverseLocalField, undefined) - var parents = utils.get(child, inverseLocalField) || []; // e.g. someUser.groups.remove(group) + safeSetLink(record, inverseLocalField, _this2); + }); + } else if (localKeys) { + // Update locals + // e.g. group.users = someUsers + // Update (set) inverse relation + var ids = toLink.map(function (child) { + return utils.get(child, relatedIdAttribute); + }).filter(function (id) { + return id !== undefined; + }); // e.g. group.user_ids = [1,2,3,...] + + utils.set(this, localKeys, ids); // Update (unset) inverse relation + + if (inverseDef.foreignKeys) { + current.forEach(function (child) { + var relatedId = utils.get(child, relatedIdAttribute); + + if (relatedId === undefined && toLink.indexOf(child) === -1 || relatedId !== undefined && !(relatedId in toLinkIds)) { + // Update inverse relation + // safeSetLink(child, inverseLocalField, undefined) + var parents = utils.get(child, inverseLocalField) || []; // e.g. someUser.groups.remove(group) + + if (id === undefined) { + utils.remove(parents, function (parent) { + return parent === _this2; + }); + } else { + utils.remove(parents, function (parent) { + return parent === _this2 || id === utils.get(parent, idAttribute); + }); + } + } + }); + toLink.forEach(function (child) { + // Update (set) inverse relation + var parents = utils.get(child, inverseLocalField); // e.g. someUser.groups.push(group) if (id === undefined) { - utils.remove(parents, function (parent) { + utils.noDupeAdd(parents, _this2, function (parent) { return parent === _this2; }); } else { - utils.remove(parents, function (parent) { + utils.noDupeAdd(parents, _this2, function (parent) { return parent === _this2 || id === utils.get(parent, idAttribute); }); } - } - }); - toLink.forEach(function (child) { - // Update (set) inverse relation - var parents = utils.get(child, inverseLocalField); // e.g. someUser.groups.push(group) + }); + } + } else if (foreignKeys) { + // e.g. user.groups = someGroups + // Update (unset) inverse relation + current.forEach(function (parent) { + var ids = utils.get(parent, foreignKeys) || []; // e.g. someGroup.user_ids.remove(user.id) + + utils.remove(ids, function (_key) { + return id === _key; + }); + var children = utils.get(parent, inverseLocalField); // e.g. someGroup.users.remove(user) if (id === undefined) { - utils.noDupeAdd(parents, _this2, function (parent) { - return parent === _this2; + utils.remove(children, function (child) { + return child === _this2; }); } else { - utils.noDupeAdd(parents, _this2, function (parent) { - return parent === _this2 || id === utils.get(parent, idAttribute); + utils.remove(children, function (child) { + return child === _this2 || id === utils.get(child, idAttribute); }); } - }); - } - } else if (foreignKeys) { - // e.g. user.groups = someGroups - // Update (unset) inverse relation - current.forEach(function (parent) { - var ids = utils.get(parent, foreignKeys) || []; // e.g. someGroup.user_ids.remove(user.id) - - utils.remove(ids, function (_key) { - return id === _key; - }); - var children = utils.get(parent, inverseLocalField); // e.g. someGroup.users.remove(user) + }); // Update (set) inverse relation - if (id === undefined) { - utils.remove(children, function (child) { - return child === _this2; - }); - } else { - utils.remove(children, function (child) { - return child === _this2 || id === utils.get(child, idAttribute); + toLink.forEach(function (parent) { + var ids = utils.get(parent, foreignKeys) || []; + utils.noDupeAdd(ids, id, function (_key) { + return id === _key; }); - } - }); // Update (set) inverse relation + var children = utils.get(parent, inverseLocalField); - toLink.forEach(function (parent) { - var ids = utils.get(parent, foreignKeys) || []; - utils.noDupeAdd(ids, id, function (_key) { - return id === _key; + if (id === undefined) { + utils.noDupeAdd(children, _this2, function (child) { + return child === _this2; + }); + } else { + utils.noDupeAdd(children, _this2, function (child) { + return child === _this2 || id === utils.get(child, idAttribute); + }); + } }); - var children = utils.get(parent, inverseLocalField); - - if (id === undefined) { - utils.noDupeAdd(children, _this2, function (child) { - return child === _this2; - }); - } else { - utils.noDupeAdd(children, _this2, function (child) { - return child === _this2 || id === utils.get(child, idAttribute); - }); - } - }); - } + } - this._set(path, toLink); + this._set(path, toLink); - return toLink; + return toLink; + } + }; + } else if (type === hasOneType) { + // TODO: Handle case when belongsTo relation isn't ever defined + if (self._collections[relation] && foreignKey && !self.getCollection(relation).indexes[foreignKey]) { + self.getCollection(relation).createIndex(foreignKey); } - }; - } else if (type === hasOneType) { - // TODO: Handle case when belongsTo relation isn't ever defined - if (self._collections[relation] && foreignKey && !self.getCollection(relation).indexes[foreignKey]) { - self.getCollection(relation).createIndex(foreignKey); - } - descriptor = { - get: getter, - // e.g. user.profile = someProfile - set: function set(record) { - var current = this._get(path); + descriptor = { + get: getter, + // e.g. user.profile = someProfile + set: function set(record) { + var current = this._get(path); - if (record === current) { - return current; - } + if (record === current) { + return current; + } - var inverseLocalField = def.getInverse(mapper).localField; // Update (unset) inverse relation + var inverseLocalField = def.getInverse(mapper).localField; // Update (unset) inverse relation - if (current) { - safeSetProp(current, foreignKey, undefined); - self.getCollection(relation).updateIndex(current, updateOpts); - safeSetLink(current, inverseLocalField, undefined); - } + if (current) { + safeSetProp(current, foreignKey, undefined); + self.getCollection(relation).updateIndex(current, updateOpts); + safeSetLink(current, inverseLocalField, undefined); + } - if (record) { - var relatedId = utils.get(record, def.getRelation().idAttribute); // Prefer store record + if (record) { + var relatedId = utils.get(record, def.getRelation().idAttribute); // Prefer store record - if (relatedId !== undefined) { - record = self.get(relation, relatedId) || record; - } // Set locals + if (relatedId !== undefined) { + record = self.get(relation, relatedId) || record; + } // Set locals - safeSetLink(this, localField, record); // Update (set) inverse relation + safeSetLink(this, localField, record); // Update (set) inverse relation - safeSetProp(record, foreignKey, utils.get(this, idAttribute)); - self.getCollection(relation).updateIndex(record, updateOpts); - safeSetLink(record, inverseLocalField, this); - } else { - // Unset locals - safeSetLink(this, localField, undefined); + safeSetProp(record, foreignKey, utils.get(this, idAttribute)); + self.getCollection(relation).updateIndex(record, updateOpts); + safeSetLink(record, inverseLocalField, this); + } else { + // Unset locals + safeSetLink(this, localField, undefined); + } + + return record; } + }; + } - return record; - } - }; - } + if (descriptor) { + descriptor.enumerable = def.enumerable === undefined ? false : def.enumerable; - if (descriptor) { - descriptor.enumerable = def.enumerable === undefined ? false : def.enumerable; + if (def.get) { + var origGet = descriptor.get; - if (def.get) { - var origGet = descriptor.get; + descriptor.get = function () { + var _this3 = this; - descriptor.get = function () { - var _this3 = this; + return def.get(def, this, function () { + for (var _len = arguments.length, args = new Array(_len), _key2 = 0; _key2 < _len; _key2++) { + args[_key2] = arguments[_key2]; + } - return def.get(def, this, function () { - for (var _len = arguments.length, args = new Array(_len), _key2 = 0; _key2 < _len; _key2++) { - args[_key2] = arguments[_key2]; - } + return origGet.apply(_this3, args); + }); + }; + } - return origGet.apply(_this3, args); - }); - }; - } + if (def.set) { + var origSet = descriptor.set; - if (def.set) { - var origSet = descriptor.set; + descriptor.set = function (related) { + var _this4 = this; - descriptor.set = function (related) { - var _this4 = this; + return def.set(def, this, related, function (value) { + return origSet.call(_this4, value === undefined ? related : value); + }); + }; + } - return def.set(def, this, related, function (value) { - return origSet.call(_this4, value === undefined ? related : value); - }); - }; + Object.defineProperty(mapper.recordClass.prototype, localField, descriptor); } + }); + return mapper; + } + }, { + key: "destroy", + value: function destroy(name, id) { + var _this5 = this; - Object.defineProperty(mapper.recordClass.prototype, localField, descriptor); - } - }); - return mapper; - }, - destroy: function destroy(name, id, opts) { - var _this5 = this; + var opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + return _get(_getPrototypeOf(DataStore.prototype), "destroy", this).call(this, name, id, opts).then(function (result) { + var record; - opts || (opts = {}); - return SimpleStore$1.prototype.destroy.call(this, name, id, opts).then(function (result) { - var record; + if (opts.raw) { + record = result.data; + } else { + record = result; + } - if (opts.raw) { - record = result.data; - } else { - record = result; - } + if (record && _this5.unlinkOnDestroy) { + var _opts = utils.plainCopy(opts); - if (record && _this5.unlinkOnDestroy) { - var _opts = utils.plainCopy(opts); + _opts.withAll = true; + utils.forEachRelation(_this5.getMapper(name), _opts, function (def) { + utils.set(record, def.localField, undefined); + }); + } - _opts.withAll = true; - utils.forEachRelation(_this5.getMapper(name), _opts, function (def) { - utils.set(record, def.localField, undefined); - }); - } + return result; + }); + } + }, { + key: "destroyAll", + value: function destroyAll(name, query) { + var _this6 = this; - return result; - }); - }, - destroyAll: function destroyAll(name, query, opts) { - var _this6 = this; + var opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + return _get(_getPrototypeOf(DataStore.prototype), "destroyAll", this).call(this, name, query, opts).then(function (result) { + var _a; - opts || (opts = {}); - return SimpleStore$1.prototype.destroyAll.call(this, name, query, opts).then(function (result) { - var records; + var records; - if (opts.raw) { - records = result.data; - } else { - records = result; - } + if (opts.raw) { + records = result.data; + } else { + records = result; + } - if (records && records.length && _this6.unlinkOnDestroy) { - var _opts = utils.plainCopy(opts); + if (((_a = records) === null || _a === void 0 ? void 0 : _a.length) && _this6.unlinkOnDestroy) { + var _opts = utils.plainCopy(opts); - _opts.withAll = true; - utils.forEachRelation(_this6.getMapper(name), _opts, function (def) { - records.forEach(function (record) { - utils.set(record, def.localField, undefined); + _opts.withAll = true; + utils.forEachRelation(_this6.getMapper(name), _opts, function (def) { + records.forEach(function (record) { + utils.set(record, def.localField, undefined); + }); }); - }); - } - - return result; - }); - } - }; - var DataStore$1 = SimpleStore$1.extend(props$2); - /** - * Create a subclass of this DataStore: - * @example DataStore.extend - * const JSData = require('js-data'); - * const { DataStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * // Extend the class using ES2015 class syntax. - * class CustomDataStoreClass extends DataStore { - * foo () { return 'bar'; } - * static beep () { return 'boop'; } - * } - * const customDataStore = new CustomDataStoreClass(); - * console.log(customDataStore.foo()); - * console.log(CustomDataStoreClass.beep()); - * - * // Extend the class using alternate method. - * const OtherDataStoreClass = DataStore.extend({ - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }); - * const otherDataStore = new OtherDataStoreClass(); - * console.log(otherDataStore.foo()); - * console.log(OtherDataStoreClass.beep()); - * - * // Extend the class, providing a custom constructor. - * function AnotherDataStoreClass () { - * DataStore.call(this); - * this.created_at = new Date().getTime(); - * } - * DataStore.extend({ - * constructor: AnotherDataStoreClass, - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }); - * const anotherDataStore = new AnotherDataStoreClass(); - * console.log(anotherDataStore.created_at); - * console.log(anotherDataStore.foo()); - * console.log(AnotherDataStoreClass.beep()); - * - * @method DataStore.extend - * @param {object} [props={}] Properties to add to the prototype of the - * subclass. - * @param {object} [props.constructor] Provide a custom constructor function - * to be used as the subclass itself. - * @param {object} [classProps={}] Static properties to add to the subclass. - * @returns {Constructor} Subclass of this DataStore class. - * @since 3.0.0 - */ + } - /** - * Registered as `js-data` in NPM and Bower. - * - * Also available from CDN.JS and JSDelivr. - * - * @module js-data - * - * @example Install from NPM - * npm i --save js-data@beta - * @example Install from Bower - * bower i --save js-data@3.0.0-beta.1 - * @example Install from CDN.JS - * - * @example Install from JSDelivr - * - * @example Load into your app via script tag - * - * - * @example Load into your app via CommonJS - * var JSData = require('js-data'); - * @example Load into your app via ES2015 Modules - * import * as JSData from 'js-data'; - * @example Load into your app via AMD - * define('myApp', ['js-data'], function (JSData) { ... }); + return result; + }); + } + }]); + + return DataStore; + }(SimpleStore); + + /** + * Registered as `js-data` in NPM. + * + * @example Install from NPM + * npm i --save js-data + * @example Install from NPM + * yarn add js-data + * @example Load into your app via CommonJS + * var JSData = require('js-data'); + * @example Load into your app via ES2015 Modules + * import * as JSData from 'js-data'; */ - /** - * Describes the version of this `JSData` object. - * - * @example - * console.log(JSData.version.full); // "3.0.0-beta.1" - * - * @name version - * @memberof module:js-data - * @property {string} full The full semver value. - * @property {number} major The major version number. - * @property {number} minor The minor version number. - * @property {number} patch The patch version number. - * @property {(string|boolean)} alpha The alpha version value, otherwise `false` - * if the current version is not alpha. - * @property {(string|boolean)} beta The beta version value, otherwise `false` - * if the current version is not beta. - * @since 2.0.0 - * @type {Object} + /** + * Describes the version of this `JSData` object. + * + * @example + * console.log(JSData.version.full); // "3.0.0-beta.1" + * + * @name version + * @memberof module:js-data + * @property {string} full The full semver value. + * @property {number} major The major version number. + * @property {number} minor The minor version number. + * @property {number} patch The patch version number. + * @property {(string|boolean)} alpha The alpha version value, otherwise `false` + * if the current version is not alpha. + * @property {(string|boolean)} beta The beta version value, otherwise `false` + * if the current version is not beta. + * @since 2.0.0 + * @type {Object} */ var version = { - full: '3.0.6', - major: 3, + beta: 4, + full: '4.0.0-beta.4', + major: 4, minor: 0, - patch: 6 + patch: 0 }; - exports.Collection = Collection$1; - exports.Component = Component$1; + exports.Collection = Collection; + exports.Component = Component; exports.Container = Container; - exports.DataStore = DataStore$1; + exports.DataStore = DataStore; exports.Index = Index; - exports.LinkedCollection = LinkedCollection$1; - exports.Mapper = Mapper$1; - exports.Query = Query$1; - exports.Record = Record$1; - exports.Schema = Schema$1; + exports.LinkedCollection = LinkedCollection; + exports.Mapper = Mapper; + exports.Query = Query; + exports.Record = Record; + exports.Schema = Schema; exports.Settable = Settable; - exports.SimpleStore = SimpleStore$1; + exports.SimpleStore = SimpleStore; exports.belongsTo = belongsTo; exports.belongsToType = belongsToType; exports.hasMany = hasMany; diff --git a/dist/js-data.js.map b/dist/js-data.js.map index 2f4670fd..85fe3045 100644 --- a/dist/js-data.js.map +++ b/dist/js-data.js.map @@ -1 +1 @@ -{"version":3,"file":"js-data.js","sources":["../src/utils.js","../src/Settable.js","../src/Component.js","../src/Query.js","../src/Relation.js","../src/Relation/BelongsTo.js","../src/Relation/HasMany.js","../src/Relation/HasOne.js","../src/relations.js","../src/decorators.js","../src/Record.js","../lib/mindex/_utils.js","../lib/mindex/index.js","../src/Collection.js","../src/Schema.js","../src/Mapper.js","../src/Container.js","../src/SimpleStore.js","../src/LinkedCollection.js","../src/DataStore.js","../src/index.js"],"sourcesContent":["/**\n * Utility methods used by JSData.\n *\n * @example\n * import { utils } from 'js-data';\n * console.log(utils.isString('foo')); // true\n *\n * @namespace utils\n * @type {Object}\n */\n\nconst DOMAIN = 'utils'\n\nconst INFINITY = 1 / 0\nconst MAX_INTEGER = 1.7976931348623157e308\nconst BOOL_TAG = '[object Boolean]'\nconst DATE_TAG = '[object Date]'\nconst FUNC_TAG = '[object Function]'\nconst NUMBER_TAG = '[object Number]'\nconst OBJECT_TAG = '[object Object]'\nconst REGEXP_TAG = '[object RegExp]'\nconst STRING_TAG = '[object String]'\nconst objToString = Object.prototype.toString\nconst PATH = /^(.+)\\.(.+)$/\n\nconst ERRORS = {\n '400' () {\n return `expected: ${arguments[0]}, found: ${\n arguments[2] ? arguments[1] : typeof arguments[1]\n }`\n },\n '404' () {\n return `${arguments[0]} not found`\n }\n}\n\nconst toInteger = function (value) {\n if (!value) {\n return 0\n }\n // Coerce to number\n value = +value\n if (value === INFINITY || value === -INFINITY) {\n const sign = value < 0 ? -1 : 1\n return sign * MAX_INTEGER\n }\n const remainder = value % 1\n return value === value ? (remainder ? value - remainder : value) : 0 // eslint-disable-line\n}\n\nconst toStr = function (value) {\n return objToString.call(value)\n}\n\nconst isPlainObject = function (value) {\n return !!value && typeof value === 'object' && value.constructor === Object\n}\n\nconst mkdirP = function (object, path) {\n if (!path) {\n return object\n }\n const parts = path.split('.')\n parts.forEach(function (key) {\n if (!object[key]) {\n object[key] = {}\n }\n object = object[key]\n })\n return object\n}\n\nconst utils = {\n /**\n * Reference to the Promise constructor used by JSData. Defaults to\n * `window.Promise` or `global.Promise`.\n *\n * @example Make JSData use a different `Promise` constructor\n * import Promise from 'bluebird';\n * import { utils } from 'js-data';\n * utils.Promise = Promise;\n *\n * @name utils.Promise\n * @since 3.0.0\n * @type {Function}\n */\n Promise: Promise,\n\n /**\n * Shallow copy properties that meet the following criteria from `src` to\n * `dest`:\n *\n * - own enumerable\n * - not a function\n * - does not start with \"_\"\n *\n * @method utils._\n * @param {object} dest Destination object.\n * @param {object} src Source object.\n * @private\n * @since 3.0.0\n */\n _ (dest, src) {\n utils.forOwn(src, function (value, key) {\n if (\n key &&\n dest[key] === undefined &&\n !utils.isFunction(value) &&\n key.indexOf('_') !== 0\n ) {\n dest[key] = value\n }\n })\n },\n\n /**\n * Recursively iterates over relations found in `opts.with`.\n *\n * @method utils._forRelation\n * @param {object} opts Configuration options.\n * @param {Relation} def Relation definition.\n * @param {Function} fn Callback function.\n * @param {*} [thisArg] Execution context for the callback function.\n * @private\n * @since 3.0.0\n */\n _forRelation (opts, def, fn, thisArg) {\n const relationName = def.relation\n let containedName = null\n let index\n opts || (opts = {})\n opts.with || (opts.with = [])\n\n if ((index = utils._getIndex(opts.with, relationName)) >= 0) {\n containedName = relationName\n } else if ((index = utils._getIndex(opts.with, def.localField)) >= 0) {\n containedName = def.localField\n }\n\n if (opts.withAll) {\n fn.call(thisArg, def, {})\n return\n } else if (!containedName) {\n return\n }\n const optsCopy = {}\n utils.fillIn(optsCopy, def.getRelation())\n utils.fillIn(optsCopy, opts)\n optsCopy.with = opts.with.slice()\n optsCopy._activeWith = optsCopy.with.splice(index, 1)[0]\n optsCopy.with.forEach(function (relation, i) {\n if (\n relation &&\n relation.indexOf(containedName) === 0 &&\n relation.length >= containedName.length &&\n relation[containedName.length] === '.'\n ) {\n optsCopy.with[i] = relation.substr(containedName.length + 1)\n } else {\n optsCopy.with[i] = ''\n }\n })\n fn.call(thisArg, def, optsCopy)\n },\n\n /**\n * Find the index of a relation in the given list\n *\n * @method utils._getIndex\n * @param {string[]} list List to search.\n * @param {string} relation Relation to find.\n * @private\n * @returns {number}\n */\n _getIndex (list, relation) {\n let index = -1\n list.forEach(function (_relation, i) {\n if (_relation === relation) {\n index = i\n return false\n } else if (utils.isObject(_relation)) {\n if (_relation.relation === relation) {\n index = i\n return false\n }\n }\n })\n return index\n },\n\n /**\n * Define hidden (non-enumerable), writable properties on `target` from the\n * provided `props`.\n *\n * @example\n * import { utils } from 'js-data';\n * function Cat () {}\n * utils.addHiddenPropsToTarget(Cat.prototype, {\n * say () {\n * console.log('meow');\n * }\n * });\n * const cat = new Cat();\n * cat.say(); // \"meow\"\n *\n * @method utils.addHiddenPropsToTarget\n * @param {object} target That to which `props` should be added.\n * @param {object} props Properties to be added to `target`.\n * @since 3.0.0\n */\n addHiddenPropsToTarget (target, props) {\n const map = {}\n Object.keys(props).forEach(function (propName) {\n const descriptor = Object.getOwnPropertyDescriptor(props, propName)\n\n descriptor.enumerable = false\n map[propName] = descriptor\n })\n Object.defineProperties(target, map)\n },\n\n /**\n * Return whether the two objects are deeply different.\n *\n * @example\n * import { utils } from 'js-data';\n * utils.areDifferent({}, {}); // false\n * utils.areDifferent({ a: 1 }, { a: 1 }); // false\n * utils.areDifferent({ foo: 'bar' }, {}); // true\n *\n * @method utils.areDifferent\n * @param {object} a Base object.\n * @param {object} b Comparison object.\n * @param {object} [opts] Configuration options.\n * @param {Function} [opts.equalsFn={@link utils.deepEqual}] Equality function.\n * @param {array} [opts.ignore=[]] Array of strings or RegExp of fields to ignore.\n * @returns {boolean} Whether the two objects are deeply different.\n * @see utils.diffObjects\n * @since 3.0.0\n */\n areDifferent (newObject, oldObject, opts) {\n opts || (opts = {})\n const diff = utils.diffObjects(newObject, oldObject, opts)\n const diffCount =\n Object.keys(diff.added).length +\n Object.keys(diff.removed).length +\n Object.keys(diff.changed).length\n return diffCount > 0\n },\n\n /**\n * Verified that the given constructor is being invoked via `new`, as opposed\n * to just being called like a normal function.\n *\n * @example\n * import { utils } from 'js-data';\n * function Cat () {\n * utils.classCallCheck(this, Cat);\n * }\n * const cat = new Cat(); // this is ok\n * Cat(); // this throws an error\n *\n * @method utils.classCallCheck\n * @param {*} instance Instance that is being constructed.\n * @param {Constructor} ctor Constructor function used to construct the\n * instance.\n * @since 3.0.0\n * @throws {Error} Throws an error if the constructor is being improperly\n * invoked.\n */\n classCallCheck (instance, ctor) {\n if (!(instance instanceof ctor)) {\n throw utils.err(`${ctor.name}`)(500, 'Cannot call a class as a function')\n }\n },\n\n /**\n * Deep copy a value.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = { foo: { bar: 'baz' } };\n * const b = utils.copy(a);\n * a === b; // false\n * utils.areDifferent(a, b); // false\n *\n * @param {*} from Value to deep copy.\n * @param {*} [to] Destination object for the copy operation.\n * @param {*} [stackFrom] For internal use.\n * @param {*} [stackTo] For internal use.\n * @param {string[]|RegExp[]} [blacklist] List of strings or RegExp of\n * properties to skip.\n * @param {boolean} [plain] Whether to make a plain copy (don't try to use\n * original prototype).\n * @returns {*} Deep copy of `from`.\n * @since 3.0.0\n */\n copy (from, to, stackFrom, stackTo, blacklist, plain) {\n if (!to) {\n to = from\n if (from) {\n if (utils.isArray(from)) {\n to = utils.copy(from, [], stackFrom, stackTo, blacklist, plain)\n } else if (utils.isDate(from)) {\n to = new Date(from.getTime())\n } else if (utils.isRegExp(from)) {\n to = new RegExp(from.source, from.toString().match(/[^/]*$/)[0])\n to.lastIndex = from.lastIndex\n } else if (utils.isObject(from)) {\n if (plain) {\n to = utils.copy(from, {}, stackFrom, stackTo, blacklist, plain)\n } else {\n to = utils.copy(\n from,\n Object.create(Object.getPrototypeOf(from)),\n stackFrom,\n stackTo,\n blacklist,\n plain\n )\n }\n }\n }\n } else {\n if (from === to) {\n throw utils.err(`${DOMAIN}.copy`)(\n 500,\n 'Cannot copy! Source and destination are identical.'\n )\n }\n\n stackFrom = stackFrom || []\n stackTo = stackTo || []\n\n if (utils.isObject(from)) {\n const index = stackFrom.indexOf(from)\n if (index !== -1) {\n return stackTo[index]\n }\n\n stackFrom.push(from)\n stackTo.push(to)\n }\n\n let result\n if (utils.isArray(from)) {\n let i\n to.length = 0\n for (i = 0; i < from.length; i++) {\n result = utils.copy(\n from[i],\n null,\n stackFrom,\n stackTo,\n blacklist,\n plain\n )\n if (utils.isObject(from[i])) {\n stackFrom.push(from[i])\n stackTo.push(result)\n }\n to.push(result)\n }\n } else {\n if (utils.isArray(to)) {\n to.length = 0\n } else {\n utils.forOwn(to, function (value, key) {\n delete to[key]\n })\n }\n for (var key in from) {\n if (Object.hasOwnProperty.call(from, key)) {\n if (utils.isBlacklisted(key, blacklist)) {\n continue\n }\n result = utils.copy(\n from[key],\n null,\n stackFrom,\n stackTo,\n blacklist,\n plain\n )\n if (utils.isObject(from[key])) {\n stackFrom.push(from[key])\n stackTo.push(result)\n }\n to[key] = result\n }\n }\n }\n }\n return to\n },\n\n /**\n * Recursively shallow fill in own enumerable properties from `source` to\n * `dest`.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = { foo: { bar: 'baz' }, beep: 'boop' };\n * const b = { beep: 'bip' };\n * utils.deepFillIn(b, a);\n * console.log(b); // {\"foo\":{\"bar\":\"baz\"},\"beep\":\"bip\"}\n *\n * @method utils.deepFillIn\n * @param {object} dest The destination object.\n * @param {object} source The source object.\n * @see utils.fillIn\n * @see utils.deepMixIn\n * @since 3.0.0\n */\n deepFillIn (dest, source) {\n if (source) {\n utils.forOwn(source, function (value, key) {\n const existing = dest[key]\n if (isPlainObject(value) && isPlainObject(existing)) {\n utils.deepFillIn(existing, value)\n } else if (!Object.hasOwnProperty.call(dest, key) || dest[key] === undefined) {\n dest[key] = value\n }\n })\n }\n return dest\n },\n\n /**\n * Recursively shallow copy enumerable properties from `source` to `dest`.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = { foo: { bar: 'baz' }, beep: 'boop' };\n * const b = { beep: 'bip' };\n * utils.deepFillIn(b, a);\n * console.log(b); // {\"foo\":{\"bar\":\"baz\"},\"beep\":\"boop\"}\n *\n * @method utils.deepMixIn\n * @param {object} dest The destination object.\n * @param {object} source The source object.\n * @see utils.fillIn\n * @see utils.deepFillIn\n * @since 3.0.0\n */\n deepMixIn (dest, source) {\n if (source) {\n for (var key in source) {\n const value = source[key]\n const existing = dest[key]\n if (isPlainObject(value) && isPlainObject(existing)) {\n utils.deepMixIn(existing, value)\n } else {\n dest[key] = value\n }\n }\n }\n return dest\n },\n\n /**\n * Return a diff of the base object to the comparison object.\n *\n * @example\n * import { utils } from 'js-data';\n * const oldObject = { foo: 'bar', a: 1234 };\n * const newObject = { beep: 'boop', a: 5678 };\n * const diff = utils.diffObjects(oldObject, newObject);\n * console.log(diff.added); // {\"beep\":\"boop\"}\n * console.log(diff.changed); // {\"a\":5678}\n * console.log(diff.removed); // {\"foo\":undefined}\n *\n * @method utils.diffObjects\n * @param {object} newObject Comparison object.\n * @param {object} oldObject Base object.\n * @param {object} [opts] Configuration options.\n * @param {Function} [opts.equalsFn={@link utils.deepEqual}] Equality function.\n * @param {array} [opts.ignore=[]] Array of strings or RegExp of fields to ignore.\n * @returns {Object} The diff from the base object to the comparison object.\n * @see utils.areDifferent\n * @since 3.0.0\n */\n diffObjects (newObject, oldObject, opts) {\n opts || (opts = {})\n let equalsFn = opts.equalsFn\n const blacklist = opts.ignore\n const diff = {\n added: {},\n changed: {},\n removed: {}\n }\n if (!utils.isFunction(equalsFn)) {\n equalsFn = utils.deepEqual\n }\n\n const newKeys = Object.keys(newObject).filter(function (key) {\n return !utils.isBlacklisted(key, blacklist)\n })\n const oldKeys = Object.keys(oldObject).filter(function (key) {\n return !utils.isBlacklisted(key, blacklist)\n })\n\n // Check for properties that were added or changed\n newKeys.forEach(function (key) {\n const oldValue = oldObject[key]\n const newValue = newObject[key]\n if (equalsFn(oldValue, newValue)) {\n return\n }\n if (oldValue === undefined) {\n diff.added[key] = newValue\n } else {\n diff.changed[key] = newValue\n }\n })\n\n // Check for properties that were removed\n oldKeys.forEach(function (key) {\n const oldValue = oldObject[key]\n const newValue = newObject[key]\n if (newValue === undefined && oldValue !== undefined) {\n diff.removed[key] = undefined\n }\n })\n\n return diff\n },\n\n /**\n * Return whether the two values are equal according to the `==` operator.\n *\n * @example\n * import { utils } from 'js-data';\n * console.log(utils.equal(1,1)); // true\n * console.log(utils.equal(1,'1')); // true\n * console.log(utils.equal(93, 66)); // false\n *\n * @method utils.equal\n * @param {*} a First value in the comparison.\n * @param {*} b Second value in the comparison.\n * @returns {boolean} Whether the two values are equal according to `==`.\n * @since 3.0.0\n */\n equal (a, b) {\n return a == b // eslint-disable-line\n },\n\n /**\n * Produce a factory function for making Error objects with the provided\n * metadata. Used throughout the various js-data components.\n *\n * @example\n * import { utils } from 'js-data';\n * const errorFactory = utils.err('domain', 'target');\n * const error400 = errorFactory(400, 'expected type', 'actual type');\n * console.log(error400); // [Error: [domain:target] expected: expected type, found: string\nhttp://www.js-data.io/v3.0/docs/errors#400]\n * @method utils.err\n * @param {string} domain Namespace.\n * @param {string} target Target.\n * @returns {Function} Factory function.\n * @since 3.0.0\n */\n err (domain, target) {\n return function (code) {\n const prefix = `[${domain}:${target}] `\n let message = ERRORS[code].apply(\n null,\n Array.prototype.slice.call(arguments, 1)\n )\n message = `${prefix}${message}\nhttp://www.js-data.io/v3.0/docs/errors#${code}`\n return new Error(message)\n }\n },\n\n /**\n * Add eventing capabilities into the target object.\n *\n * @example\n * import { utils } from 'js-data';\n * const user = { name: 'John' };\n * utils.eventify(user);\n * user.on('foo', () => console.log(arguments));\n * user.emit('foo', 1, 'bar'); // should log to console values (1, \"bar\")\n *\n * @method utils.eventify\n * @param {object} target Target object.\n * @param {Function} [getter] Custom getter for retrieving the object's event\n * listeners.\n * @param {Function} [setter] Custom setter for setting the object's event\n * listeners.\n * @since 3.0.0\n */\n eventify (target, getter, setter) {\n target = target || this\n let _events = {}\n if (!getter && !setter) {\n getter = function () {\n return _events\n }\n setter = function (value) {\n _events = value\n }\n }\n Object.defineProperties(target, {\n emit: {\n value (...args) {\n const events = getter.call(this) || {}\n const type = args.shift()\n let listeners = events[type] || []\n let i\n for (i = 0; i < listeners.length; i++) {\n listeners[i].f.apply(listeners[i].c, args)\n }\n listeners = events.all || []\n args.unshift(type)\n for (i = 0; i < listeners.length; i++) {\n listeners[i].f.apply(listeners[i].c, args)\n }\n }\n },\n off: {\n value (type, func) {\n const events = getter.call(this)\n const listeners = events[type]\n if (!listeners) {\n setter.call(this, {})\n } else if (func) {\n for (let i = 0; i < listeners.length; i++) {\n if (listeners[i].f === func) {\n listeners.splice(i, 1)\n break\n }\n }\n } else {\n listeners.splice(0, listeners.length)\n }\n }\n },\n on: {\n value (type, func, thisArg) {\n if (!getter.call(this)) {\n setter.call(this, {})\n }\n const events = getter.call(this)\n events[type] = events[type] || []\n events[type].push({\n c: thisArg,\n f: func\n })\n }\n }\n })\n },\n\n /**\n * Used for sublcassing. Invoke this method in the context of a superclass to\n * to produce a subclass based on `props` and `classProps`.\n *\n * @example\n * import { utils } from 'js-data';\n * function Animal () {}\n * Animal.extend = utils.extend;\n * const Cat = Animal.extend({\n * say () {\n * console.log('meow');\n * }\n * });\n * const cat = new Cat();\n * cat instanceof Animal; // true\n * cat instanceof Cat; // true\n * cat.say(); // \"meow\"\n *\n * @method utils.extend\n * @param {object} props Instance properties for the subclass.\n * @param {object} [props.constructor] Provide a custom constructor function\n * to use as the subclass.\n * @param {object} props Static properties for the subclass.\n * @returns {Constructor} A new subclass.\n * @since 3.0.0\n */\n extend (props, classProps) {\n const superClass = this\n let subClass\n\n props || (props = {})\n classProps || (classProps = {})\n\n if (Object.hasOwnProperty.call(props, 'constructor')) {\n subClass = props.constructor\n delete props.constructor\n } else {\n subClass = function (...args) {\n utils.classCallCheck(this, subClass)\n superClass.apply(this, args)\n }\n }\n\n // Setup inheritance of instance members\n subClass.prototype = Object.create(superClass && superClass.prototype, {\n constructor: {\n configurable: true,\n enumerable: false,\n value: subClass,\n writable: true\n }\n })\n\n const obj = Object\n // Setup inheritance of static members\n if (obj.setPrototypeOf) {\n obj.setPrototypeOf(subClass, superClass)\n } else if (classProps.strictEs6Class) {\n subClass.__proto__ = superClass // eslint-disable-line\n } else {\n utils.forOwn(superClass, function (value, key) {\n subClass[key] = value\n })\n }\n if (!Object.hasOwnProperty.call(subClass, '__super__')) {\n Object.defineProperty(subClass, '__super__', {\n configurable: true,\n value: superClass\n })\n }\n\n utils.addHiddenPropsToTarget(subClass.prototype, props)\n utils.fillIn(subClass, classProps)\n\n return subClass\n },\n\n /**\n * Shallow copy own enumerable properties from `src` to `dest` that are on\n * `src` but are missing from `dest.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = { foo: 'bar', beep: 'boop' };\n * const b = { beep: 'bip' };\n * utils.fillIn(b, a);\n * console.log(b); // {\"foo\":\"bar\",\"beep\":\"bip\"}\n *\n * @method utils.fillIn\n * @param {object} dest The destination object.\n * @param {object} source The source object.\n * @see utils.deepFillIn\n * @see utils.deepMixIn\n * @since 3.0.0\n */\n fillIn (dest, src) {\n utils.forOwn(src, function (value, key) {\n if (!Object.hasOwnProperty.call(dest, key) || dest[key] === undefined) {\n dest[key] = value\n }\n })\n },\n\n /**\n * Find the last index of an item in an array according to the given checker function.\n *\n * @example\n * import { utils } from 'js-data';\n *\n * const john = { name: 'John', age: 20 };\n * const sara = { name: 'Sara', age: 25 };\n * const dan = { name: 'Dan', age: 20 };\n * const users = [john, sara, dan];\n *\n * console.log(utils.findIndex(users, (user) => user.age === 25)); // 1\n * console.log(utils.findIndex(users, (user) => user.age > 19)); // 2\n * console.log(utils.findIndex(users, (user) => user.name === 'John')); // 0\n * console.log(utils.findIndex(users, (user) => user.name === 'Jimmy')); // -1\n *\n * @method utils.findIndex\n * @param {array} array The array to search.\n * @param {Function} fn Checker function.\n * @returns {number} Index if found or -1 if not found.\n * @since 3.0.0\n */\n findIndex (array, fn) {\n let index = -1\n if (!array) {\n return index\n }\n array.forEach(function (record, i) {\n if (fn(record)) {\n index = i\n return false\n }\n })\n return index\n },\n\n /**\n * Recursively iterate over a {@link Mapper}'s relations according to\n * `opts.with`.\n *\n * @method utils.forEachRelation\n * @param {Mapper} mapper Mapper.\n * @param {object} opts Configuration options.\n * @param {Function} fn Callback function.\n * @param {*} thisArg Execution context for the callback function.\n * @since 3.0.0\n */\n forEachRelation (mapper, opts, fn, thisArg) {\n const relationList = mapper.relationList || []\n if (!relationList.length) {\n return\n }\n relationList.forEach(function (def) {\n utils._forRelation(opts, def, fn, thisArg)\n })\n },\n\n /**\n * Iterate over an object's own enumerable properties.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = { b: 1, c: 4 };\n * let sum = 0;\n * utils.forOwn(a, function (value, key) {\n * sum += value;\n * });\n * console.log(sum); // 5\n *\n * @method utils.forOwn\n * @param {object} object The object whose properties are to be enumerated.\n * @param {Function} fn Iteration function.\n * @param {object} [thisArg] Content to which to bind `fn`.\n * @since 3.0.0\n */\n forOwn (obj, fn, thisArg) {\n const keys = Object.keys(obj)\n const len = keys.length\n let i\n for (i = 0; i < len; i++) {\n if (fn.call(thisArg, obj[keys[i]], keys[i], obj) === false) {\n break\n }\n }\n },\n\n /**\n * Proxy for `JSON.parse`.\n *\n * @example\n * import { utils } from 'js-data';\n *\n * const a = utils.fromJson('{\"name\" : \"John\"}');\n * console.log(a); // { name: 'John' }\n *\n * @method utils.fromJson\n * @param {string} json JSON to parse.\n * @returns {Object} Parsed object.\n * @see utils.toJson\n * @since 3.0.0\n */\n fromJson (json) {\n return utils.isString(json) ? JSON.parse(json) : json\n },\n\n /**\n * Retrieve the specified property from the given object. Supports retrieving\n * nested properties.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = { foo: { bar: 'baz' }, beep: 'boop' };\n * console.log(utils.get(a, 'beep')); // \"boop\"\n * console.log(utils.get(a, 'foo.bar')); // \"baz\"\n *\n * @method utils.get\n * @param {object} object Object from which to retrieve a property's value.\n * @param {string} prop Property to retrieve.\n * @returns {*} Value of the specified property.\n * @see utils.set\n * @since 3.0.0\n */\n get: function (object, prop) {\n if (!prop) {\n return\n }\n const parts = prop.split('.')\n const last = parts.pop()\n\n while ((prop = parts.shift())) {\n // eslint-disable-line\n object = object[prop]\n if (object == null) {\n // eslint-disable-line\n return\n }\n }\n\n return object[last]\n },\n\n /**\n * Return the superclass for the given instance or subclass. If an instance is\n * provided, then finds the parent class of the instance's constructor.\n *\n * @example\n * import { utils } from 'js-data';\n * // using ES2015 classes\n * class Foo {}\n * class Bar extends Foo {}\n * const barInstance = new Bar();\n * let baseType = utils.getSuper(barInstance);\n * console.log(Foo === baseType); // true\n *\n * // using Function constructor with utils.extend\n * function Foo () {}\n * Foo.extend = utils.extend;\n * const Bar = Foo.extend();\n * const barInstance = new Bar();\n * let baseType = utils.getSuper(barInstance);\n * console.log(Foo === baseType); // true\n *\n * @method utils.getSuper\n * @param {Object|Function} instance Instance or constructor.\n * @param {boolean} [isCtor=false] Whether `instance` is a constructor.\n * @returns {Constructor} The superclass (grandparent constructor).\n * @since 3.0.0\n */\n getSuper (instance, isCtor) {\n const ctor = isCtor ? instance : instance.constructor\n if (Object.hasOwnProperty.call(ctor, '__super__')) {\n return ctor.__super__\n }\n return Object.getPrototypeOf(ctor) || ctor.__proto__ // eslint-disable-line\n },\n\n /**\n * Return the intersection of two arrays.\n *\n * @example\n * import { utils } from 'js-data';\n * const arrA = ['green', 'red', 'blue', 'red'];\n * const arrB = ['green', 'yellow', 'red'];\n * const intersected = utils.intersection(arrA, arrB);\n *\n * console.log(intersected); // ['green', 'red'])\n *\n * @method utils.intersection\n * @param {array} array1 First array.\n * @param {array} array2 Second array.\n * @returns {Array} Array of elements common to both arrays.\n * @since 3.0.0\n */\n intersection (array1, array2) {\n if (!array1 || !array2) {\n return []\n }\n array1 = Array.isArray(array1) ? array1 : [array1]\n array2 = Array.isArray(array2) ? array2 : [array2]\n const result = []\n let item\n let i\n const len = array1.length\n for (i = 0; i < len; i++) {\n item = array1[i]\n if (result.indexOf(item) !== -1) {\n continue\n }\n if (array2.indexOf(item) !== -1) {\n result.push(item)\n }\n }\n return result\n },\n\n /**\n * Proxy for `Array.isArray`.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = [1,2,3,4,5];\n * const b = { foo: \"bar\" };\n * console.log(utils.isArray(a)); // true\n * console.log(utils.isArray(b)); // false\n *\n * @method utils.isArray\n * @param {*} value The value to test.\n * @returns {boolean} Whether the provided value is an array.\n * @since 3.0.0\n */\n isArray: Array.isArray,\n\n /**\n * Return whether `prop` is matched by any string or regular expression in\n * `blacklist`.\n *\n * @example\n * import { utils } from 'js-data';\n * const blacklist = [/^\\$hashKey/g, /^_/g, 'id'];\n * console.log(utils.isBlacklisted(\"$hashKey\", blacklist)); // true\n * console.log(utils.isBlacklisted(\"id\", blacklist)); // true\n * console.log(utils.isBlacklisted(\"_myProp\", blacklist)); // true\n * console.log(utils.isBlacklisted(\"my_id\", blacklist)); // false\n *\n * @method utils.isBlacklisted\n * @param {string} prop The name of a property to check.\n * @param {array} blacklist Array of strings and regular expressions.\n * @returns {boolean} Whether `prop` was matched.\n * @since 3.0.0\n */\n isBlacklisted (prop, blacklist) {\n if (!blacklist || !blacklist.length) {\n return false\n }\n let matches\n for (var i = 0; i < blacklist.length; i++) {\n if (\n (toStr(blacklist[i]) === REGEXP_TAG && blacklist[i].test(prop)) ||\n blacklist[i] === prop\n ) {\n matches = prop\n return !!matches\n }\n }\n return !!matches\n },\n\n /**\n * Return whether the provided value is a boolean.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = true;\n * const b = { foo: \"bar\" };\n * console.log(utils.isBoolean(a)); // true\n * console.log(utils.isBoolean(b)); // false\n *\n * @method utils.isBoolean\n * @param {*} value The value to test.\n * @returns {boolean} Whether the provided value is a boolean.\n * @since 3.0.0\n */\n isBoolean (value) {\n return toStr(value) === BOOL_TAG\n },\n\n /**\n * Return whether the provided value is a date.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = new Date();\n * const b = { foo: \"bar\" };\n * console.log(utils.isDate(a)); // true\n * console.log(utils.isDate(b)); // false\n *\n * @method utils.isDate\n * @param {*} value The value to test.\n * @returns {Date} Whether the provided value is a date.\n * @since 3.0.0\n */\n isDate (value) {\n return value && typeof value === 'object' && toStr(value) === DATE_TAG\n },\n\n /**\n * Return whether the provided value is a function.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = function () { console.log('foo bar'); };\n * const b = { foo: \"bar\" };\n * console.log(utils.isFunction(a)); // true\n * console.log(utils.isFunction(b)); // false\n *\n * @method utils.isFunction\n * @param {*} value The value to test.\n * @returns {boolean} Whether the provided value is a function.\n * @since 3.0.0\n */\n isFunction (value) {\n return typeof value === 'function' || (value && toStr(value) === FUNC_TAG)\n },\n\n /**\n * Return whether the provided value is an integer.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = 1;\n * const b = 1.25;\n * const c = '1';\n * console.log(utils.isInteger(a)); // true\n * console.log(utils.isInteger(b)); // false\n * console.log(utils.isInteger(c)); // false\n *\n * @method utils.isInteger\n * @param {*} value The value to test.\n * @returns {boolean} Whether the provided value is an integer.\n * @since 3.0.0\n */\n isInteger (value) {\n return toStr(value) === NUMBER_TAG && value == toInteger(value) // eslint-disable-line\n },\n\n /**\n * Return whether the provided value is `null`.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = null;\n * const b = { foo: \"bar\" };\n * console.log(utils.isNull(a)); // true\n * console.log(utils.isNull(b)); // false\n *\n * @method utils.isNull\n * @param {*} value The value to test.\n * @returns {boolean} Whether the provided value is `null`.\n * @since 3.0.0\n */\n isNull (value) {\n return value === null\n },\n\n /**\n * Return whether the provided value is a number.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = 1;\n * const b = -1.25;\n * const c = '1';\n * console.log(utils.isNumber(a)); // true\n * console.log(utils.isNumber(b)); // true\n * console.log(utils.isNumber(c)); // false\n *\n * @method utils.isNumber\n * @param {*} value The value to test.\n * @returns {boolean} Whether the provided value is a number.\n * @since 3.0.0\n */\n isNumber (value) {\n const type = typeof value\n return (\n type === 'number' ||\n (value && type === 'object' && toStr(value) === NUMBER_TAG)\n )\n },\n\n /**\n * Return whether the provided value is an object.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = { foo: \"bar\" };\n * const b = 'foo bar';\n * console.log(utils.isObject(a)); // true\n * console.log(utils.isObject(b)); // false\n *\n * @method utils.isObject\n * @param {*} value The value to test.\n * @returns {boolean} Whether the provided value is an object.\n * @since 3.0.0\n */\n isObject (value) {\n return toStr(value) === OBJECT_TAG\n },\n\n /**\n * Return whether the provided value is a regular expression.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = /^\\$.+$/ig;\n * const b = new RegExp('^\\$.+$', 'ig');\n * const c = { foo: \"bar\" };\n * console.log(utils.isRegExp(a)); // true\n * console.log(utils.isRegExp(b)); // true\n * console.log(utils.isRegExp(c)); // false\n *\n * @method utils.isRegExp\n * @param {*} value The value to test.\n * @returns {boolean} Whether the provided value is a regular expression.\n * @since 3.0.0\n */\n isRegExp (value) {\n return toStr(value) === REGEXP_TAG\n },\n\n /**\n * Return whether the provided value is a string or a number.\n *\n * @example\n * import { utils } from 'js-data';\n * console.log(utils.isSorN('')); // true\n * console.log(utils.isSorN(-1.65)); // true\n * console.log(utils.isSorN('my string')); // true\n * console.log(utils.isSorN({})); // false\n * console.log(utils.isSorN([1,2,4])); // false\n *\n * @method utils.isSorN\n * @param {*} value The value to test.\n * @returns {boolean} Whether the provided value is a string or a number.\n * @since 3.0.0\n */\n isSorN (value) {\n return utils.isString(value) || utils.isNumber(value)\n },\n\n /**\n * Return whether the provided value is a string.\n *\n * @example\n * import { utils } from 'js-data';\n * console.log(utils.isString('')); // true\n * console.log(utils.isString('my string')); // true\n * console.log(utils.isString(100)); // false\n * console.log(utils.isString([1,2,4])); // false\n *\n * @method utils.isString\n * @param {*} value The value to test.\n * @returns {boolean} Whether the provided value is a string.\n * @since 3.0.0\n */\n isString (value) {\n return (\n typeof value === 'string' ||\n (value && typeof value === 'object' && toStr(value) === STRING_TAG)\n )\n },\n\n /**\n * Return whether the provided value is a `undefined`.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = undefined;\n * const b = { foo: \"bar\"};\n * console.log(utils.isUndefined(a)); // true\n * console.log(utils.isUndefined(b.baz)); // true\n * console.log(utils.isUndefined(b)); // false\n * console.log(utils.isUndefined(b.foo)); // false\n *\n * @method utils.isUndefined\n * @param {*} value The value to test.\n * @returns {boolean} Whether the provided value is a `undefined`.\n * @since 3.0.0\n */\n isUndefined (value) {\n return value === undefined\n },\n\n /**\n * Mix in logging capabilities to the target.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = { foo: \"bar\"};\n *\n * // Add standard logging to an object\n * utils.logify(a);\n * a.log('info', 'test log info'); // output 'test log info' to console.\n *\n * // Toggle debug output of an object\n * a.dbg('test debug output'); // does not output because debug is off.\n * a.debug = true;\n * a.dbg('test debug output'); // output 'test debug output' to console.\n *\n * @method utils.logify\n * @param {*} target The target.\n * @since 3.0.0\n */\n logify (target) {\n utils.addHiddenPropsToTarget(target, {\n dbg (...args) {\n if (utils.isFunction(this.log)) {\n this.log('debug', ...args)\n }\n },\n log (level, ...args) {\n if (level && !args.length) {\n args.push(level)\n level = 'debug'\n }\n if (level === 'debug' && !this.debug) {\n return\n }\n const prefix = `${level.toUpperCase()}: (${this.name ||\n this.constructor.name})`\n if (utils.isFunction(console[level])) {\n console[level](prefix, ...args)\n } else {\n console.log(prefix, ...args)\n }\n }\n })\n },\n\n /**\n * Adds the given record to the provided array only if it's not already in the\n * array.\n *\n * @example\n * import { utils } from 'js-data';\n * const colors = ['red', 'green', 'yellow'];\n *\n * console.log(colors.length); // 3\n * utils.noDupeAdd(colors, 'red');\n * console.log(colors.length); // 3, red already exists\n *\n * utils.noDupeAdd(colors, 'blue');\n * console.log(colors.length); // 4, blue was added\n *\n * @method utils.noDupeAdd\n * @param {array} array The array.\n * @param {*} record The value to add.\n * @param {Function} fn Callback function passed to {@link utils.findIndex}.\n * @since 3.0.0\n */\n noDupeAdd (array, record, fn) {\n if (!array) {\n return\n }\n const index = this.findIndex(array, fn)\n if (index < 0) {\n array.push(record)\n }\n },\n\n /**\n * Return a shallow copy of the provided object, minus the properties\n * specified in `keys`.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = { name: 'John', $hashKey: 1214910 };\n *\n * let b = utils.omit(a, ['$hashKey']);\n * console.log(b); // { name: 'John' }\n *\n * @method utils.omit\n * @param {object} props The object to copy.\n * @param {string[]} keys Array of strings, representing properties to skip.\n * @returns {Object} Shallow copy of `props`, minus `keys`.\n * @since 3.0.0\n */\n omit (props, keys) {\n const _props = {}\n utils.forOwn(props, function (value, key) {\n if (keys.indexOf(key) === -1) {\n _props[key] = value\n }\n })\n return _props\n },\n\n /**\n * Return a shallow copy of the provided object, but only include the\n * properties specified in `keys`.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = { name: 'John', $hashKey: 1214910 };\n *\n * let b = utils.pick(a, ['$hashKey']);\n * console.log(b); // { $hashKey: 1214910 }\n *\n * @method utils.pick\n * @param {object} props The object to copy.\n * @param {string[]} keys Array of strings, representing properties to keep.\n * @returns {Object} Shallow copy of `props`, but only including `keys`.\n * @since 3.0.0\n */\n pick (props, keys) {\n return keys.reduce((map, key) => {\n map[key] = props[key]\n return map\n }, {})\n },\n\n /**\n * Return a plain copy of the given value.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = { name: 'John' };\n * let b = utils.plainCopy(a);\n * console.log(a === b); // false\n *\n * @method utils.plainCopy\n * @param {*} value The value to copy.\n * @returns {*} Plain copy of `value`.\n * @see utils.copy\n * @since 3.0.0\n */\n plainCopy (value) {\n return utils.copy(value, undefined, undefined, undefined, undefined, true)\n },\n\n /**\n * Shortcut for `utils.Promise.reject(value)`.\n *\n * @example\n * import { utils } from 'js-data';\n *\n * utils.reject(\"Testing static reject\").then(function (data) {\n * // not called\n * }).catch(function (reason) {\n * console.log(reason); // \"Testing static reject\"\n * });\n *\n * @method utils.reject\n * @param {*} [value] Value with which to reject the Promise.\n * @returns {Promise} Promise reject with `value`.\n * @see utils.Promise\n * @since 3.0.0\n */\n reject (value) {\n return utils.Promise.reject(value)\n },\n\n /**\n * Remove the last item found in array according to the given checker function.\n *\n * @example\n * import { utils } from 'js-data';\n *\n * const colors = ['red', 'green', 'yellow', 'red'];\n * utils.remove(colors, (color) => color === 'red');\n * console.log(colors); // ['red', 'green', 'yellow']\n *\n * @method utils.remove\n * @param {array} array The array to search.\n * @param {Function} fn Checker function.\n */\n remove (array, fn) {\n if (!array || !array.length) {\n return\n }\n const index = this.findIndex(array, fn)\n if (index >= 0) {\n array.splice(index, 1) // todo should this be recursive?\n }\n },\n\n /**\n * Shortcut for `utils.Promise.resolve(value)`.\n *\n * @example\n * import { utils } from 'js-data';\n *\n * utils.resolve(\"Testing static resolve\").then(function (data) {\n * console.log(data); // \"Testing static resolve\"\n * }).catch(function (reason) {\n * // not called\n * });\n *\n * @param {*} [value] Value with which to resolve the Promise.\n * @returns {Promise} Promise resolved with `value`.\n * @see utils.Promise\n * @since 3.0.0\n */\n resolve (value) {\n return utils.Promise.resolve(value)\n },\n\n /**\n * Set the value at the provided key or path.\n *\n * @example\n * import { utils } from 'js-data';\n *\n * const john = {\n * name: 'John',\n * age: 25,\n * parent: {\n * name: 'John's Mom',\n * age: 50\n * }\n * };\n * // set value by key\n * utils.set(john, 'id', 98);\n * console.log(john.id); // 98\n *\n * // set value by path\n * utils.set(john, 'parent.id', 20);\n * console.log(john.parent.id); // 20\n *\n * // set value by path/value map\n * utils.set(john, {\n * 'id': 1098,\n * 'parent': { id: 1020 },\n * 'parent.age': '55'\n * });\n * console.log(john.id); // 1098\n * console.log(john.parent.id); // 1020\n * console.log(john.parent.age); // 55\n *\n * @method utils.set\n * @param {object} object The object on which to set a property.\n * @param {(string|Object)} path The key or path to the property. Can also\n * pass in an object of path/value pairs, which will all be set on the target\n * object.\n * @param {*} [value] The value to set.\n */\n set: function (object, path, value) {\n if (utils.isObject(path)) {\n utils.forOwn(path, function (value, _path) {\n utils.set(object, _path, value)\n })\n } else {\n const parts = PATH.exec(path)\n if (parts) {\n mkdirP(object, parts[1])[parts[2]] = value\n } else {\n object[path] = value\n }\n }\n },\n\n /**\n * Check whether the two provided objects are deeply equal.\n *\n * @example\n * import { utils } from 'js-data';\n *\n * const objA = {\n * name: 'John',\n * id: 27,\n * nested: {\n * item: 'item 1',\n * colors: ['red', 'green', 'blue']\n * }\n * };\n *\n * const objB = {\n * name: 'John',\n * id: 27,\n * nested: {\n * item: 'item 1',\n * colors: ['red', 'green', 'blue']\n * }\n * };\n *\n * console.log(utils.deepEqual(a,b)); // true\n * objB.nested.colors.add('yellow'); // make a change to a nested object's array\n * console.log(utils.deepEqual(a,b)); // false\n *\n * @method utils.deepEqual\n * @param {object} a First object in the comparison.\n * @param {object} b Second object in the comparison.\n * @returns {boolean} Whether the two provided objects are deeply equal.\n * @see utils.equal\n * @since 3.0.0\n */\n deepEqual (a, b) {\n if (a === b) {\n return true\n }\n let _equal = true\n if (utils.isArray(a) && utils.isArray(b)) {\n if (a.length !== b.length) {\n return false\n }\n for (let i = a.length; i--;) {\n if (!utils.deepEqual(a[i], b[i])) {\n // Exit loop early\n return false\n }\n }\n } else if (utils.isObject(a) && utils.isObject(b)) {\n utils.forOwn(a, function (value, key) {\n if (!(_equal = utils.deepEqual(value, b[key]))) {\n // Exit loop early\n return false\n }\n })\n if (_equal) {\n utils.forOwn(b, function (value, key) {\n if (!(_equal = utils.deepEqual(value, a[key]))) {\n // Exit loop early\n return false\n }\n })\n }\n } else {\n return false\n }\n return _equal\n },\n\n /**\n * Proxy for `JSON.stringify`.\n *\n * @example\n * import { utils } from 'js-data';\n *\n * const a = { name: 'John' };\n * let jsonVal = utils.toJson(a);\n * console.log(jsonVal); // '{\"name\" : \"John\"}'\n *\n * @method utils.toJson\n * @param {*} value Value to serialize to JSON.\n * @returns {string} JSON string.\n * @see utils.fromJson\n * @since 3.0.0\n */\n toJson: JSON.stringify,\n\n /**\n * Unset the value at the provided key or path.\n *\n * @example\n * import { utils } from 'js-data';\n *\n * const john = {\n * name: 'John',\n * age: 25,\n * parent: {\n * name: 'John's Mom',\n * age: 50\n * }\n * };\n *\n * utils.unset(john, age);\n * utils.unset(john, parent.age);\n *\n * console.log(john.age); // null\n * console.log(john.parent.age); // null\n *\n * @method utils.unset\n * @param {object} object The object from which to delete the property.\n * @param {string} path The key or path to the property.\n * @see utils.set\n * @since 3.0.0\n */\n unset (object, path) {\n const parts = path.split('.')\n const last = parts.pop()\n\n while ((path = parts.shift())) {\n // eslint-disable-line\n object = object[path]\n if (object == null) {\n // eslint-disable-line\n return\n }\n }\n\n object[last] = undefined\n }\n}\n\nexport const safeSetProp = function (record, field, value) {\n if (record && record._set) {\n record._set(`props.${field}`, value)\n } else {\n utils.set(record, field, value)\n }\n}\n\nexport const safeSetLink = function (record, field, value) {\n if (record && record._set) {\n record._set(`links.${field}`, value)\n } else {\n utils.set(record, field, value)\n }\n}\n\nexport default utils\n","import utils from './utils'\n\n/**\n * A base class which gives instances private properties.\n *\n * Typically you won't instantiate this class directly, but you may find it\n * useful as an abstract class for your own components.\n *\n * See {@link Settable.extend} for an example of using {@link Settable} as a\n * base class.\n *\n *```javascript\n * import {Settable} from 'js-data'\n * ```\n *\n * @class Settable\n * @returns {Settable} A new {@link Settable} instance.\n * @since 3.0.0\n */\nexport default function Settable () {\n const _props = {}\n Object.defineProperties(this, {\n /**\n * Get a private property of this instance.\n *\n * __Don't use the method unless you know what you're doing.__\n *\n * @method Settable#_get\n * @param {string} key The property to retrieve.\n * @returns {*} The value of the property.\n * @since 3.0.0\n */\n _get: { value (key) { return utils.get(_props, key) } },\n\n /**\n * Set a private property of this instance.\n *\n * __Don't use the method unless you know what you're doing.__\n *\n * @method __Don't use the method unless you know what you're doing.__#_set\n * @param {(string|Object)} key The key or path to the property. Can also\n * pass in an object of key/value pairs, which will all be set on the instance.\n * @param {*} [value] The value to set.\n * @since 3.0.0\n */\n _set: { value (key, value) { return utils.set(_props, key, value) } },\n\n /**\n * Unset a private property of this instance.\n *\n * __Don't use the method unless you know what you're doing.__\n *\n * @method __Don't use the method unless you know what you're doing.__#_unset\n * @param {string} key The property to unset.\n * @since 3.0.0\n */\n _unset: { value (key) { return utils.unset(_props, key) } }\n })\n}\n\n/**\n * Create a subclass of this Settable:\n *\n * @example Settable.extend\n * const JSData = require('js-data');\n * const { Settable } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * // Extend the class using ES2015 class syntax.\n * class CustomSettableClass extends Settable {\n * foo () { return 'bar'; }\n * static beep () { return 'boop'; }\n * }\n * const customSettable = new CustomSettableClass();\n * console.log(customSettable.foo());\n * console.log(CustomSettableClass.beep());\n *\n * // Extend the class using alternate method.\n * const OtherSettableClass = Settable.extend({\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * });\n * const otherSettable = new OtherSettableClass();\n * console.log(otherSettable.foo());\n * console.log(OtherSettableClass.beep());\n *\n * // Extend the class, providing a custom constructor.\n * function AnotherSettableClass () {\n * Settable.call(this);\n * this.created_at = new Date().getTime();\n * }\n * Settable.extend({\n * constructor: AnotherSettableClass,\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * })\n * const anotherSettable = new AnotherSettableClass();\n * console.log(anotherSettable.created_at);\n * console.log(anotherSettable.foo());\n * console.log(AnotherSettableClass.beep());\n *\n * @method Settable.extend\n * @param {object} [props={}] Properties to add to the prototype of the\n * subclass.\n * @param {object} [props.constructor] Provide a custom constructor function\n * to be used as the subclass itself.\n * @param {object} [classProps={}] Static properties to add to the subclass.\n * @returns {Constructor} Subclass of this Settable class.\n * @since 3.0.0\n */\nSettable.extend = utils.extend\n","import utils from './utils'\nimport Settable from './Settable'\n\n/**\n * The base class from which all JSData components inherit some basic\n * functionality.\n *\n * Typically you won't instantiate this class directly, but you may find it\n * useful as an abstract class for your own components.\n *\n * See {@link Component.extend} for an example of using {@link Component} as a\n * base class.\n *\n *```javascript\n * import {Component} from 'js-data'\n * ```\n *\n * @class Component\n * @param {object} [opts] Configuration options.\n * @param {boolean} [opts.debug=false] See {@link Component#debug}.\n * @returns {Component} A new {@link Component} instance.\n * @since 3.0.0\n */\nfunction Component (opts) {\n Settable.call(this)\n opts || (opts = {})\n\n /**\n * Whether to enable debug-level logs for this component. Anything that\n * extends `Component` inherits this option and the corresponding logging\n * functionality.\n *\n * @example Component#debug\n * const JSData = require('js-data');\n * const { Component } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const component = new Component();\n * component.log('debug', 'some message'); // nothing gets logged\n * // Display debug logs:\n * component.debug = true;\n * component.log('debug', 'other message'); // this DOES get logged\n *\n * @default false\n * @name Component#debug\n * @since 3.0.0\n * @type {boolean}\n */\n this.debug = Object.hasOwnProperty.call(opts, 'debug') ? !!opts.debug : false\n\n /**\n * Event listeners attached to this Component. __Do not modify.__ Use\n * {@link Component#on} and {@link Component#off} instead.\n *\n * @name Component#_listeners\n * @private\n * @instance\n * @since 3.0.0\n * @type {Object}\n */\n Object.defineProperty(this, '_listeners', { value: {}, writable: true })\n}\n\nexport default Settable.extend({\n constructor: Component\n})\n\n/**\n * Create a subclass of this Component:\n *\n * @example Component.extend\n * const JSData = require('js-data');\n * const { Component } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * // Extend the class using ES2015 class syntax.\n * class CustomComponentClass extends Component {\n * foo () { return 'bar'; }\n * static beep () { return 'boop'; }\n * }\n * const customComponent = new CustomComponentClass();\n * console.log(customComponent.foo());\n * console.log(CustomComponentClass.beep());\n *\n * // Extend the class using alternate method.\n * const OtherComponentClass = Component.extend({\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * });\n * const otherComponent = new OtherComponentClass();\n * console.log(otherComponent.foo());\n * console.log(OtherComponentClass.beep());\n *\n * // Extend the class, providing a custom constructor.\n * function AnotherComponentClass () {\n * Component.call(this);\n * this.created_at = new Date().getTime();\n * }\n * Component.extend({\n * constructor: AnotherComponentClass,\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * })\n * const anotherComponent = new AnotherComponentClass();\n * console.log(anotherComponent.created_at);\n * console.log(anotherComponent.foo());\n * console.log(AnotherComponentClass.beep());\n *\n * @method Component.extend\n * @param {object} [props={}] Properties to add to the prototype of the\n * subclass.\n * @param {object} [props.constructor] Provide a custom constructor function\n * to be used as the subclass itself.\n * @param {object} [classProps={}] Static properties to add to the subclass.\n * @returns {Constructor} Subclass of this Component class.\n * @since 3.0.0\n */\nComponent.extend = utils.extend\n\n/**\n * Log the provided values at the \"debug\" level. Debug-level logs are only\n * logged if {@link Component#debug} is `true`.\n *\n * `.dbg(...)` is shorthand for `.log('debug', ...)`.\n *\n * @method Component#dbg\n * @param {...*} [args] Values to log.\n * @since 3.0.0\n */\n/**\n * Log the provided values. By default sends values to `console[level]`.\n * Debug-level logs are only logged if {@link Component#debug} is `true`.\n *\n * Will attempt to use appropriate `console` methods if they are available.\n *\n * @method Component#log\n * @param {string} level Log level.\n * @param {...*} [args] Values to log.\n * @since 3.0.0\n */\nutils.logify(Component.prototype)\n\n/**\n * Register a new event listener on this Component.\n *\n * @example\n * // Listen for all \"afterCreate\" events in a DataStore\n * store.on('afterCreate', (mapperName, props, opts, result) => {\n * console.log(mapperName); // \"post\"\n * console.log(props.id); // undefined\n * console.log(result.id); // 1234\n * });\n * store.create('post', { title: 'Modeling your data' }).then((post) => {\n * console.log(post.id); // 1234\n * });\n *\n * @example\n * // Listen for the \"add\" event on a collection\n * collection.on('add', (records) => {\n * console.log(records); // [...]\n * });\n *\n * @example\n * // Listen for \"change\" events on a record\n * post.on('change', (record, changes) => {\n * console.log(changes); // { changed: { title: 'Modeling your data' } }\n * });\n * post.title = 'Modeling your data';\n *\n * @method Component#on\n * @param {string} event Name of event to subsribe to.\n * @param {Function} listener Listener function to handle the event.\n * @param {*} [ctx] Optional content in which to invoke the listener.\n * @since 3.0.0\n */\n/**\n * Remove an event listener from this Component. If no listener is provided,\n * then all listeners for the specified event will be removed. If no event is\n * specified then all listeners for all events will be removed.\n *\n * @example\n * // Remove a particular listener for a particular event\n * collection.off('add', handler);\n *\n * @example\n * // Remove all listeners for a particular event\n * record.off('change');\n *\n * @example\n * // Remove all listeners to all events\n * store.off();\n *\n * @method Component#off\n * @param {string} [event] Name of event to unsubsribe to.\n * @param {Function} [listener] Listener to remove.\n * @since 3.0.0\n */\n/**\n * Trigger an event on this Component.\n *\n * @example Component#emit\n * // import { Collection, DataStore } from 'js-data';\n * const JSData = require('js-data');\n * const { Collection, DataStore } = JSData;\n *\n * const collection = new Collection();\n * collection.on('foo', function (msg) {\n * console.log(msg);\n * });\n * collection.emit('foo', 'bar');\n *\n * const store = new DataStore();\n * store.on('beep', function (msg) {\n * console.log(msg);\n * });\n * store.emit('beep', 'boop');\n *\n * @method Component#emit\n * @param {string} event Name of event to emit.\n * @param {...*} [args] Arguments to pass to any listeners.\n * @since 3.0.0\n */\nutils.eventify(\n Component.prototype,\n function () {\n return this._listeners\n },\n function (value) {\n this._listeners = value\n }\n)\n","import utils from './utils'\nimport Component from './Component'\n\nconst DOMAIN = 'Query'\nconst INDEX_ERR = 'Index inaccessible after first operation'\n\n// Reserved words used by JSData's Query Syntax\nconst reserved = {\n limit: '',\n offset: '',\n orderBy: '',\n skip: '',\n sort: '',\n where: ''\n}\n\n// Used by our JavaScript implementation of the LIKE operator\nconst escapeRegExp = /([.*+?^=!:${}()|[\\]/\\\\])/g\nconst percentRegExp = /%/g\nconst underscoreRegExp = /_/g\nconst escape = function (pattern) {\n return pattern.replace(escapeRegExp, '\\\\$1')\n}\n\n/**\n * A class used by the {@link Collection} class to build queries to be executed\n * against the collection's data. An instance of `Query` is returned by\n * {@link Collection#query}. Query instances are typically short-lived, and you\n * shouldn't have to create them yourself. Just use {@link Collection#query}.\n *\n * ```javascript\n * import { Query } from 'js-data';\n * ```\n *\n * @example Query intro\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post');\n * const posts = [\n * { author: 'John', age: 30, status: 'published', id: 1 },\n * { author: 'Sally', age: 31, status: 'draft', id: 2 },\n * { author: 'Mike', age: 32, status: 'draft', id: 3 },\n * { author: 'Adam', age: 33, status: 'deleted', id: 4 },\n * { author: 'Adam', age: 33, status: 'draft', id: 5 }\n * ]\n * store.add('post', posts);\n * const drafts = store.query('post').filter({ status: 'draft' }).limit(2).run();\n * console.log(drafts);\n *\n * @class Query\n * @extends Component\n * @param {Collection} collection The collection on which this query operates.\n * @since 3.0.0\n */\nfunction Query (collection) {\n utils.classCallCheck(this, Query)\n\n /**\n * The {@link Collection} on which this query operates.\n *\n * @name Query#collection\n * @since 3.0.0\n * @type {Collection}\n */\n this.collection = collection\n\n /**\n * The current data result of this query.\n *\n * @name Query#data\n * @since 3.0.0\n * @type {Array}\n */\n this.data = null\n}\n\nexport default Component.extend({\n constructor: Query,\n\n _applyWhereFromObject (where) {\n const fields = []\n const ops = []\n const predicates = []\n utils.forOwn(where, (clause, field) => {\n if (!utils.isObject(clause)) {\n clause = {\n '==': clause\n }\n }\n utils.forOwn(clause, (expr, op) => {\n fields.push(field)\n ops.push(op)\n predicates.push(expr)\n })\n })\n return {\n fields,\n ops,\n predicates\n }\n },\n\n _applyWhereFromArray (where) {\n const groups = []\n where.forEach((_where, i) => {\n if (utils.isString(_where)) {\n return\n }\n const prev = where[i - 1]\n const parser = utils.isArray(_where) ? this._applyWhereFromArray : this._applyWhereFromObject\n const group = parser.call(this, _where)\n if (prev === 'or') {\n group.isOr = true\n }\n groups.push(group)\n })\n groups.isArray = true\n return groups\n },\n\n _testObjectGroup (keep, first, group, item) {\n let i\n const fields = group.fields\n const ops = group.ops\n const predicates = group.predicates\n const len = ops.length\n for (i = 0; i < len; i++) {\n let op = ops[i]\n const isOr = op.charAt(0) === '|'\n op = isOr ? op.substr(1) : op\n const expr = this.evaluate(utils.get(item, fields[i]), op, predicates[i])\n if (expr !== undefined) {\n keep = first ? expr : (isOr ? keep || expr : keep && expr)\n }\n first = false\n }\n return { keep, first }\n },\n\n _testArrayGroup (keep, first, groups, item) {\n let i\n const len = groups.length\n for (i = 0; i < len; i++) {\n const group = groups[i]\n const parser = group.isArray ? this._testArrayGroup : this._testObjectGroup\n const result = parser.call(this, true, true, group, item)\n if (groups[i - 1]) {\n if (group.isOr) {\n keep = keep || result.keep\n } else {\n keep = keep && result.keep\n }\n } else {\n keep = result.keep\n }\n first = result.first\n }\n return { keep, first }\n },\n\n /**\n * Find all entities between two boundaries.\n *\n * @example Get the users ages 18 to 30.\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('user');\n * const users = [\n * { name: 'Peter', age: 25, id: 1 },\n * { name: 'Jim', age: 19, id: 2 },\n * { name: 'Mike', age: 17, id: 3 },\n * { name: 'Alan', age: 29, id: 4 },\n * { name: 'Katie', age: 33, id: 5 }\n * ];\n * store.add('user', users)\n * const filteredUsers = store\n * .query('user')\n * .between(18, 30, { index: 'age' })\n * .run();\n * console.log(filteredUsers);\n *\n * @example Same as above.\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('user');\n * const users = [\n * { name: 'Peter', age: 25, id: 1 },\n * { name: 'Jim', age: 19, id: 2 },\n * { name: 'Mike', age: 17, id: 3 },\n * { name: 'Alan', age: 29, id: 4 },\n * { name: 'Katie', age: 33, id: 5 }\n * ];\n * store.add('user', users)\n * const filteredUsers = store\n * .query('user')\n * .between([18], [30], { index: 'age' })\n * .run();\n * console.log(filteredUsers);\n *\n * @method Query#between\n * @param {array} leftKeys Keys defining the left boundary.\n * @param {array} rightKeys Keys defining the right boundary.\n * @param {object} [opts] Configuration options.\n * @param {string} [opts.index] Name of the secondary index to use in the\n * query. If no index is specified, the main index is used.\n * @param {boolean} [opts.leftInclusive=true] Whether to include entities\n * on the left boundary.\n * @param {boolean} [opts.rightInclusive=false] Whether to include entities\n * on the left boundary.\n * @param {boolean} [opts.limit] Limit the result to a certain number.\n * @param {boolean} [opts.offset] The number of resulting entities to skip.\n * @returns {Query} A reference to itself for chaining.\n * @since 3.0.0\n */\n between (leftKeys, rightKeys, opts) {\n opts || (opts = {})\n if (this.data) {\n throw utils.err(`${DOMAIN}#between`)(500, 'Cannot access index')\n }\n this.data = this.collection.getIndex(opts.index).between(leftKeys, rightKeys, opts)\n return this\n },\n\n /**\n * The comparison function used by the {@link Query} class.\n *\n * @method Query#compare\n * @param {array} orderBy An orderBy clause used for sorting and sub-sorting.\n * @param {number} index The index of the current orderBy clause being used.\n * @param {*} a The first item in the comparison.\n * @param {*} b The second item in the comparison.\n * @returns {number} -1 if `b` should preceed `a`. 0 if `a` and `b` are equal.\n * 1 if `a` should preceed `b`.\n * @since 3.0.0\n */\n compare (orderBy, index, a, b) {\n const def = orderBy[index]\n let cA = utils.get(a, def[0])\n let cB = utils.get(b, def[0])\n if (cA && utils.isString(cA)) {\n cA = cA.toUpperCase()\n }\n if (cB && utils.isString(cB)) {\n cB = cB.toUpperCase()\n }\n if (a === undefined) {\n a = null\n }\n if (b === undefined) {\n b = null\n }\n if (def[1].toUpperCase() === 'DESC') {\n const temp = cB\n cB = cA\n cA = temp\n }\n if (cA < cB) {\n return -1\n } else if (cA > cB) {\n return 1\n } else {\n if (index < orderBy.length - 1) {\n return this.compare(orderBy, index + 1, a, b)\n } else {\n return 0\n }\n }\n },\n\n /**\n * Predicate evaluation function used by the {@link Query} class.\n *\n * @method Query#evaluate\n * @param {*} value The value to evaluate.\n * @param {string} op The operator to use in this evaluation.\n * @param {*} predicate The predicate to use in this evaluation.\n * @returns {boolean} Whether the value passed the evaluation or not.\n * @since 3.0.0\n */\n evaluate (value, op, predicate) {\n const ops = this.constructor.ops\n if (ops[op]) {\n return ops[op](value, predicate)\n }\n if (op.indexOf('like') === 0) {\n return this.like(predicate, op.substr(4)).exec(value) !== null\n } else if (op.indexOf('notLike') === 0) {\n return this.like(predicate, op.substr(7)).exec(value) === null\n }\n },\n\n /**\n * Find the record or records that match the provided query or are accepted by\n * the provided filter function.\n *\n * @example Get the draft posts by authors younger than 30\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post')\n * const posts = [\n * { author: 'John', age: 30, status: 'published', id: 1 },\n * { author: 'Sally', age: 31, status: 'published', id: 2 },\n * { author: 'Mike', age: 32, status: 'draft', id: 3 },\n * { author: 'Adam', age: 33, status: 'deleted', id: 4 },\n * { author: 'Adam', age: 33, status: 'published', id: 5 }\n * { author: 'Peter', age: 25, status: 'deleted', id: 6 },\n * { author: 'Sally', age: 21, status: 'draft', id: 7 },\n * { author: 'Jim', age: 27, status: 'draft', id: 8 },\n * { author: 'Jim', age: 27, status: 'published', id: 9 },\n * { author: 'Jason', age: 55, status: 'published', id: 10 }\n * ];\n * store.add('post', posts);\n * const results = store\n * .query('post')\n * .filter({\n * where: {\n * status: {\n * '==': 'draft'\n * },\n * age: {\n * '<': 30\n * }\n * }\n * })\n * .run();\n * console.log(results);\n *\n * @example Use a custom filter function\n * const posts = query\n * .filter(function (post) {\n * return post.isReady();\n * })\n * .run();\n *\n * @method Query#filter\n * @param {(Object|Function)} [queryOrFn={}] Selection query or filter\n * function.\n * @param {Function} [thisArg] Context to which to bind `queryOrFn` if\n * `queryOrFn` is a function.\n * @returns {Query} A reference to itself for chaining.\n * @since 3.0.0\n */\n filter (query, thisArg) {\n /**\n * Selection query as defined by JSData's [Query Syntax][querysyntax].\n *\n * [querysyntax]: http://www.js-data.io/v3.0/docs/query-syntax\n *\n * @example Empty \"findAll\" query\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post')\n * store.findAll('post').then((posts) => {\n * console.log(posts); // [...]\n * });\n *\n * @example Empty \"filter\" query\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post');\n * const posts = store.filter('post');\n * console.log(posts); // [...]\n *\n * @example Complex \"filter\" query\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * const PAGE_SIZE = 2;\n * let currentPage = 3;\n *\n * store.defineMapper('post');\n * const posts = [\n * { author: 'John', age: 30, status: 'published', id: 1 },\n * { author: 'Sally', age: 31, status: 'published', id: 2 },\n * { author: 'Mike', age: 32, status: 'draft', id: 3 },\n * { author: 'Adam', age: 33, status: 'deleted', id: 4 },\n * { author: 'Adam', age: 33, status: 'published', id: 5 }\n * { author: 'Peter', age: 25, status: 'deleted', id: 6 },\n * { author: 'Sally', age: 21, status: 'draft', id: 7 },\n * { author: 'Jim', age: 27, status: 'draft', id: 8 },\n * { author: 'Jim', age: 27, status: 'published', id: 9 },\n * { author: 'Jason', age: 55, status: 'published', id: 10 }\n * ];\n * store.add('post', posts);\n * // Retrieve a filtered page of blog posts\n * // Would typically replace filter with findAll\n * const results = store.filter('post', {\n * where: {\n * status: {\n * // WHERE status = 'published'\n * '==': 'published'\n * },\n * author: {\n * // AND author IN ('bob', 'alice')\n * 'in': ['bob', 'alice'],\n * // OR author IN ('karen')\n * '|in': ['karen']\n * }\n * },\n * orderBy: [\n * // ORDER BY date_published DESC,\n * ['date_published', 'DESC'],\n * // ORDER BY title ASC\n * ['title', 'ASC']\n * ],\n * // LIMIT 2\n * limit: PAGE_SIZE,\n * // SKIP 4\n * offset: PAGE_SIZE * (currentPage - 1)\n * });\n * console.log(results);\n *\n * @namespace query\n * @property {number} [limit] See {@link query.limit}.\n * @property {number} [offset] See {@link query.offset}.\n * @property {string|Array[]} [orderBy] See {@link query.orderBy}.\n * @property {number} [skip] Alias for {@link query.offset}.\n * @property {string|Array[]} [sort] Alias for {@link query.orderBy}.\n * @property {Object} [where] See {@link query.where}.\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/query-syntax\",\"JSData's Query Syntax\"]\n */\n query || (query = {})\n this.getData()\n if (utils.isObject(query)) {\n let where = {}\n\n /**\n * Filtering criteria. Records that do not meet this criteria will be exluded\n * from the result.\n *\n * @example Return posts where author is at least 32 years old\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post')\n * const posts = [\n * { author: 'John', age: 30, id: 5 },\n * { author: 'Sally', age: 31, id: 6 },\n * { author: 'Mike', age: 32, id: 7 },\n * { author: 'Adam', age: 33, id: 8 },\n * { author: 'Adam', age: 33, id: 9 }\n * ];\n * store.add('post', posts);\n * const results = store.filter('post', {\n * where: {\n * age: {\n * '>=': 30\n * }\n * }\n * });\n * console.log(results);\n *\n * @name query.where\n * @type {Object}\n * @see http://www.js-data.io/v3.0/docs/query-syntax\n * @since 3.0.0\n */\n if (utils.isObject(query.where) || utils.isArray(query.where)) {\n where = query.where\n }\n utils.forOwn(query, function (value, key) {\n if (!(key in reserved) && !(key in where)) {\n where[key] = {\n '==': value\n }\n }\n })\n let groups\n\n // Apply filter for each field\n if (utils.isObject(where) && Object.keys(where).length !== 0) {\n groups = this._applyWhereFromArray([where])\n } else if (utils.isArray(where)) {\n groups = this._applyWhereFromArray(where)\n }\n\n if (groups) {\n this.data = this.data.filter((item, i) => this._testArrayGroup(true, true, groups, item).keep)\n }\n\n // Sort\n let orderBy = query.orderBy || query.sort\n\n if (utils.isString(orderBy)) {\n orderBy = [\n [orderBy, 'ASC']\n ]\n }\n if (!utils.isArray(orderBy)) {\n orderBy = null\n }\n\n /**\n * Determines how records should be ordered in the result.\n *\n * @example Order posts by `author` then by `id` descending \n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post')\n * const posts = [\n * { author: 'John', age: 30, id: 5 },\n * { author: 'Sally', age: 31, id: 6 },\n * { author: 'Mike', age: 32, id: 7 },\n * { author: 'Adam', age: 33, id: 8 },\n * { author: 'Adam', age: 33, id: 9 }\n * ];\n * store.add('post', posts);\n * const results = store.filter('post', {\n * orderBy:[['author','ASC'],['id','DESC']]\n * });\n * console.log(results);\n *\n * @name query.orderBy\n * @type {string|Array[]}\n * @see http://www.js-data.io/v3.0/docs/query-syntax\n * @since 3.0.0\n */\n if (orderBy) {\n const index = 0\n orderBy.forEach(function (def, i) {\n if (utils.isString(def)) {\n orderBy[i] = [def, 'ASC']\n }\n })\n this.data.sort((a, b) => this.compare(orderBy, index, a, b))\n }\n\n /**\n * Number of records to skip.\n *\n * @example Retrieve the first \"page\" of blog posts using findAll\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post');\n * const PAGE_SIZE = 10;\n * let currentPage = 1;\n * store.findAll('post', {\n * offset: PAGE_SIZE * (currentPage 1)\n * limit: PAGE_SIZE\n * });\n *\n * @example Retrieve the last \"page\" of blog posts using filter\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n *\n * const PAGE_SIZE = 5;\n * let currentPage = 2;\n * store.defineMapper('post');\n * const posts = [\n * { author: 'John', age: 30, id: 1 },\n * { author: 'Sally', age: 31, id: 2 },\n * { author: 'Mike', age: 32, id: 3 },\n * { author: 'Adam', age: 33, id: 4 },\n * { author: 'Adam', age: 33, id: 5 },\n * { author: 'Peter', age: 25, id: 6 },\n * { author: 'Sally', age: 21, id: 7 },\n * { author: 'Jim', age: 27, id: 8 },\n * { author: 'Jim', age: 27, id: 9 },\n * { author: 'Jason', age: 55, id: 10 }\n * ];\n * store.add('post', posts);\n * const results = store.filter('post', {\n * offset: PAGE_SIZE * (currentPage 1)\n * limit: PAGE_SIZE\n * });\n * console.log(results)\n *\n * @name query.offset\n * @type {number}\n * @see http://www.js-data.io/v3.0/docs/query-syntax\n * @since 3.0.0\n */\n if (utils.isNumber(query.skip)) {\n this.skip(query.skip)\n } else if (utils.isNumber(query.offset)) {\n this.skip(query.offset)\n }\n\n /**\n * Maximum number of records to retrieve.\n *\n * @example Retrieve the first \"page\" of blog posts using findAll\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post');\n *\n * const PAGE_SIZE = 10\n * let currentPage = 1\n * store.findAll('post', {\n * offset: PAGE_SIZE * (currentPage 1)\n * limit: PAGE_SIZE\n * });\n *\n * @example Retrieve the last \"page\" of blog posts using filter\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n *\n * const PAGE_SIZE = 5\n * let currentPage = 2\n * store.defineMapper('post')\n * const posts = [\n * { author: 'John', age: 30, id: 1 },\n * { author: 'Sally', age: 31, id: 2 },\n * { author: 'Mike', age: 32, id: 3 },\n * { author: 'Adam', age: 33, id: 4 },\n * { author: 'Adam', age: 33, id: 5 },\n * { author: 'Peter', age: 25, id: 6 },\n * { author: 'Sally', age: 21, id: 7 },\n * { author: 'Jim', age: 27, id: 8 },\n * { author: 'Jim', age: 27, id: 9 },\n * { author: 'Jason', age: 55, id: 10 }\n * ];\n * store.add('post', posts);\n * const results = store.filter('post', {\n * offset: PAGE_SIZE * (currentPage 1)\n * limit: PAGE_SIZE\n * });\n * console.log(results)\n *\n * @name query.limit\n * @type {number}\n * @see http://www.js-data.io/v3.0/docs/query-syntax\n * @since 3.0.0\n */\n if (utils.isNumber(query.limit)) {\n this.limit(query.limit)\n }\n } else if (utils.isFunction(query)) {\n this.data = this.data.filter(query, thisArg)\n }\n return this\n },\n\n /**\n * Iterate over all entities.\n *\n * @method Query#forEach\n * @param {Function} forEachFn Iteration function.\n * @param {*} [thisArg] Context to which to bind `forEachFn`.\n * @returns {Query} A reference to itself for chaining.\n * @since 3.0.0\n */\n forEach (forEachFn, thisArg) {\n this.getData().forEach(forEachFn, thisArg)\n return this\n },\n\n /**\n * Find the entity or entities that match the provided key.\n *\n * @example Get the entity whose primary key is 25.\n * const entities = query.get(25).run();\n *\n * @example Same as above.\n * const entities = query.get([25]).run();\n *\n * @example Get all users who are active and have the \"admin\" role.\n * const activeAdmins = query.get(['active', 'admin'], {\n * index: 'activityAndRoles'\n * }).run();\n *\n * @example Get all entities that match a certain weather condition.\n * const niceDays = query.get(['sunny', 'humid', 'calm'], {\n * index: 'weatherConditions'\n * }).run();\n *\n * @method Query#get\n * @param {array} keyList Key(s) defining the entity to retrieve. If\n * `keyList` is not an array (i.e. for a single-value key), it will be\n * wrapped in an array.\n * @param {object} [opts] Configuration options.\n * @param {string} [opts.string] Name of the secondary index to use in the\n * query. If no index is specified, the main index is used.\n * @returns {Query} A reference to itself for chaining.\n * @since 3.0.0\n */\n get (keyList, opts) {\n keyList || (keyList = [])\n opts || (opts = {})\n if (this.data) {\n throw utils.err(`${DOMAIN}#get`)(500, INDEX_ERR)\n }\n if (keyList && !utils.isArray(keyList)) {\n keyList = [keyList]\n }\n if (!keyList.length) {\n this.getData()\n return this\n }\n this.data = this.collection.getIndex(opts.index).get(keyList)\n return this\n },\n\n /**\n * Find the entity or entities that match the provided keyLists.\n *\n * @example Get the posts where \"status\" is \"draft\" or \"inReview\".\n * const posts = query.getAll('draft', 'inReview', { index: 'status' }).run();\n *\n * @example Same as above.\n * const posts = query.getAll(['draft'], ['inReview'], { index: 'status' }).run();\n *\n * @method Query#getAll\n * @param {...Array} [keyList] Provide one or more keyLists, and all\n * entities matching each keyList will be retrieved. If no keyLists are\n * provided, all entities will be returned.\n * @param {object} [opts] Configuration options.\n * @param {string} [opts.index] Name of the secondary index to use in the\n * query. If no index is specified, the main index is used.\n * @returns {Query} A reference to itself for chaining.\n * @since 3.0.0\n */\n getAll (...args) {\n let opts = {}\n if (this.data) {\n throw utils.err(`${DOMAIN}#getAll`)(500, INDEX_ERR)\n }\n if (!args.length || (args.length === 1 && utils.isObject(args[0]))) {\n this.getData()\n return this\n } else if (args.length && utils.isObject(args[args.length - 1])) {\n opts = args[args.length - 1]\n args.pop()\n }\n const collection = this.collection\n const index = collection.getIndex(opts.index)\n this.data = []\n args.forEach((keyList) => {\n this.data = this.data.concat(index.get(keyList))\n })\n return this\n },\n\n /**\n * Return the current data result of this query.\n *\n * @method Query#getData\n * @returns {Array} The data in this query.\n * @since 3.0.0\n */\n getData () {\n if (!this.data) {\n this.data = this.collection.index.getAll()\n }\n return this.data\n },\n\n /**\n * Implementation used by the `like` operator. Takes a pattern and flags and\n * returns a `RegExp` instance that can test strings.\n *\n * @method Query#like\n * @param {string} pattern Testing pattern.\n * @param {string} flags Flags for the regular expression.\n * @returns {RegExp} Regular expression for testing strings.\n * @since 3.0.0\n */\n like (pattern, flags) {\n return new RegExp(`^${(escape(pattern).replace(percentRegExp, '.*').replace(underscoreRegExp, '.'))}$`, flags)\n },\n\n /**\n * Limit the result.\n *\n * @example Get only the first 2 posts.\n * const store = new JSData.DataStore();\n * store.defineMapper('post');\n * const posts = [\n * { author: 'John', age: 30, status: 'published', id: 1 },\n * { author: 'Sally', age: 31, status: 'draft', id: 2 },\n * { author: 'Mike', age: 32, status: 'draft', id: 3 },\n * { author: 'Adam', age: 33, status: 'deleted', id: 4 },\n * { author: 'Adam', age: 33, status: 'draft', id: 5 }\n * ];\n * store.add('post', posts);\n * const results = store.query('post').limit(2).run();\n * console.log(results);\n *\n * @method Query#limit\n * @param {number} num The maximum number of entities to keep in the result.\n * @returns {Query} A reference to itself for chaining.\n * @since 3.0.0\n */\n limit (num) {\n if (!utils.isNumber(num)) {\n throw utils.err(`${DOMAIN}#limit`, 'num')(400, 'number', num)\n }\n const data = this.getData()\n this.data = data.slice(0, Math.min(data.length, num))\n return this\n },\n\n /**\n * Apply a mapping function to the result data.\n *\n * @example\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('user');\n * const users = [\n * { name: 'Peter', age: 25, id: 1 },\n * { name: 'Jim', age: 19, id: 2 },\n * { name: 'Mike', age: 17, id: 3 },\n * { name: 'Alan', age: 29, id: 4 },\n * { name: 'Katie', age: 33, id: 5 }\n * ];\n * store.add('user', users);\n * const ages = store\n * .query('user')\n * .map(function (user) {\n * return user.age;\n * })\n * .run();\n * console.log(ages);\n *\n * @method Query#map\n * @param {Function} mapFn Mapping function.\n * @param {*} [thisArg] Context to which to bind `mapFn`.\n * @returns {Query} A reference to itself for chaining.\n * @since 3.0.0\n */\n map (mapFn, thisArg) {\n this.data = this.getData().map(mapFn, thisArg)\n return this\n },\n\n /**\n * Return the result of calling the specified function on each item in this\n * collection's main index.\n *\n * @example\n * const stringAges = UserCollection.query().mapCall('toString').run();\n *\n * @method Query#mapCall\n * @param {string} funcName Name of function to call\n * @parama {...*} [args] Remaining arguments to be passed to the function.\n * @returns {Query} A reference to itself for chaining.\n * @since 3.0.0\n */\n mapCall (funcName, ...args) {\n this.data = this.getData().map(function (item) {\n return item[funcName](...args)\n })\n return this\n },\n\n /**\n * Complete the execution of the query and return the resulting data.\n *\n * @method Query#run\n * @returns {Array} The result of executing this query.\n * @since 3.0.0\n */\n run () {\n const data = this.data\n this.data = null\n return data\n },\n\n /**\n * Skip a number of results.\n *\n * @example Get all but the first 2 posts.\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post');\n * const posts = [\n * { author: 'John', age: 30, status: 'published', id: 1 },\n * { author: 'Sally', age: 31, status: 'draft', id: 2 },\n * { author: 'Mike', age: 32, status: 'draft', id: 3 },\n * { author: 'Adam', age: 33, status: 'deleted', id: 4 },\n * { author: 'Adam', age: 33, status: 'draft', id: 5 }\n * ];\n * store.add('post', posts);\n * const results = store.query('post').skip(2).run();\n * console.log(results);\n *\n * @method Query#skip\n * @param {number} num The number of entities to skip.\n * @returns {Query} A reference to itself for chaining.\n * @since 3.0.0\n */\n skip (num) {\n if (!utils.isNumber(num)) {\n throw utils.err(`${DOMAIN}#skip`, 'num')(400, 'number', num)\n }\n const data = this.getData()\n if (num < data.length) {\n this.data = data.slice(num)\n } else {\n this.data = []\n }\n return this\n }\n}, {\n /**\n * The filtering operators supported by {@link Query#filter}, and which are\n * implemented by adapters (for the most part).\n *\n * @example Variant 1\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post');\n * const posts = [\n * { author: 'John', age: 30, status: 'published', id: 1 },\n * { author: 'Sally', age: 31, status: 'published', id: 2 },\n * { author: 'Mike', age: 32, status: 'published', id: 3 },\n * { author: 'Adam', age: 33, status: 'deleted', id: 4 },\n * { author: 'Adam', age: 33, status: 'published', id: 5 }\n * ];\n * store.add('post', posts);\n * const publishedPosts = store.filter('post', {\n * status: 'published',\n * limit: 2\n * });\n * console.log(publishedPosts);\n *\n *\n * @example Variant 2\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post')\n * const posts = [\n * { author: 'John', age: 30, status: 'published', id: 1 },\n * { author: 'Sally', age: 31, status: 'published', id: 2 },\n * { author: 'Mike', age: 32, status: 'published', id: 3 },\n * { author: 'Adam', age: 33, status: 'deleted', id: 4 },\n * { author: 'Adam', age: 33, status: 'published', id: 5 }\n * ];\n * store.add('post', posts);\n * const publishedPosts = store.filter('post', {\n * where: {\n * status: {\n * '==': 'published'\n * }\n * },\n * limit: 2\n * });\n * console.log(publishedPosts);\n *\n * @example Variant 3\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post');\n * const posts = [\n * { author: 'John', age: 30, status: 'published', id: 1 },\n * { author: 'Sally', age: 31, status: 'published', id: 2 },\n * { author: 'Mike', age: 32, status: 'published', id: 3 },\n * { author: 'Adam', age: 33, status: 'deleted', id: 4 },\n * { author: 'Adam', age: 33, status: 'published', id: 5 }\n * ];\n * store.add('post', posts);\n * const publishedPosts = store\n * .query('post')\n * .filter({ status: 'published' })\n * .limit(2)\n * .run();\n * console.log(publishedPosts);\n *\n * @example Variant 4\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post');\n * const posts = [\n * { author: 'John', age: 30, status: 'published', id: 1 },\n * { author: 'Sally', age: 31, status: 'published', id: 2 },\n * { author: 'Mike', age: 32, status: 'published', id: 3 },\n * { author: 'Adam', age: 33, status: 'deleted', id: 4 },\n * { author: 'Adam', age: 33, status: 'published', id: 5 }\n * ];\n * store.add('post', posts);\n * const publishedPosts = store\n * .query('post')\n * .filter({\n * where: {\n * status: {\n * '==': 'published'\n * }\n * }\n * })\n * .limit(2)\n * .run();\n * console.log(publishedPosts);\n *\n * @example Multiple operators\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post');\n * const posts = [\n * { author: 'John', age: 30, status: 'published', id: 1 },\n * { author: 'Sally', age: 31, status: 'published', id: 2 },\n * { author: 'Mike', age: 32, status: 'published', id: 3 },\n * { author: 'Adam', age: 33, status: 'deleted', id: 4 },\n * { author: 'Adam', age: 33, status: 'published', id: 5 }\n * ];\n * store.add('post', posts);\n *\n * const myPublishedPosts = store.filter('post', {\n * where: {\n * status: {\n * '==': 'published'\n * },\n * user_id: {\n * '==': currentUser.id\n * }\n * }\n * });\n *\n * console.log(myPublishedPosts);\n *\n * @name Query.ops\n * @property {Function} == Equality operator.\n * @property {Function} != Inequality operator.\n * @property {Function} > Greater than operator.\n * @property {Function} >= Greater than (inclusive) operator.\n * @property {Function} < Less than operator.\n * @property {Function} <= Less than (inclusive) operator.\n * @property {Function} isectEmpty Operator that asserts that the intersection\n * between two arrays is empty.\n * @property {Function} isectNotEmpty Operator that asserts that the\n * intersection between two arrays is __not__ empty.\n * @property {Function} in Operator that asserts whether a value is in an\n * array.\n * @property {Function} notIn Operator that asserts whether a value is __not__\n * in an array.\n * @property {Function} contains Operator that asserts whether an array\n * contains a value.\n * @property {Function} notContains Operator that asserts whether an array\n * does __not__ contain a value.\n * @since 3.0.0\n * @type {Object}\n */\n ops: {\n '=': function (value, predicate) {\n return value == predicate // eslint-disable-line\n },\n '==': function (value, predicate) {\n return value == predicate // eslint-disable-line\n },\n '===': function (value, predicate) {\n return value === predicate\n },\n '!=': function (value, predicate) {\n return value != predicate // eslint-disable-line\n },\n '!==': function (value, predicate) {\n return value !== predicate\n },\n '>': function (value, predicate) {\n return value > predicate\n },\n '>=': function (value, predicate) {\n return value >= predicate\n },\n '<': function (value, predicate) {\n return value < predicate\n },\n '<=': function (value, predicate) {\n return value <= predicate\n },\n isectEmpty: function (value, predicate) {\n return !utils.intersection((value || []), (predicate || [])).length\n },\n isectNotEmpty: function (value, predicate) {\n return utils.intersection((value || []), (predicate || [])).length\n },\n in: function (value, predicate) {\n return predicate.indexOf(value) !== -1\n },\n notIn: function (value, predicate) {\n return predicate.indexOf(value) === -1\n },\n contains: function (value, predicate) {\n return (value || []).indexOf(predicate) !== -1\n },\n notContains: function (value, predicate) {\n return (value || []).indexOf(predicate) === -1\n }\n }\n})\n\n/**\n * Create a subclass of this Query:\n * @example Query.extend\n * const JSData = require('js-data');\n * const { Query } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * // Extend the class using ES2015 class syntax.\n * class CustomQueryClass extends Query {\n * foo () { return 'bar'; }\n * static beep () { return 'boop'; }\n * }\n * const customQuery = new CustomQueryClass();\n * console.log(customQuery.foo());\n * console.log(CustomQueryClass.beep());\n *\n * // Extend the class using alternate method.\n * const OtherQueryClass = Query.extend({\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * });\n * const otherQuery = new OtherQueryClass();\n * console.log(otherQuery.foo());\n * console.log(OtherQueryClass.beep());\n *\n * // Extend the class, providing a custom constructor.\n * function AnotherQueryClass (collection) {\n * Query.call(this, collection);\n * this.created_at = new Date().getTime();\n * }\n * Query.extend({\n * constructor: AnotherQueryClass,\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * });\n * const anotherQuery = new AnotherQueryClass();\n * console.log(anotherQuery.created_at);\n * console.log(anotherQuery.foo());\n * console.log(AnotherQueryClass.beep());\n *\n * @method Query.extend\n * @param {object} [props={}] Properties to add to the prototype of the\n * subclass.\n * @param {object} [props.constructor] Provide a custom constructor function\n * to be used as the subclass itself.\n * @param {object} [classProps={}] Static properties to add to the subclass.\n * @returns {Constructor} Subclass of this Query class.\n * @since 3.0.0\n */\n","import utils from './utils'\n\n// TODO: remove this when the rest of the project is cleaned\nexport const belongsToType = 'belongsTo'\nexport const hasManyType = 'hasMany'\nexport const hasOneType = 'hasOne'\n\nconst DOMAIN = 'Relation'\n\nexport function Relation (relatedMapper, options = {}) {\n utils.classCallCheck(this, Relation)\n\n options.type = this.constructor.TYPE_NAME\n this.validateOptions(relatedMapper, options)\n\n if (typeof relatedMapper === 'object') {\n Object.defineProperty(this, 'relatedMapper', { value: relatedMapper })\n }\n\n Object.defineProperty(this, 'inverse', { writable: true })\n utils.fillIn(this, options)\n}\n\nRelation.extend = utils.extend\n\nutils.addHiddenPropsToTarget(Relation.prototype, {\n get canAutoAddLinks () {\n return this.add === undefined || !!this.add\n },\n\n get relatedCollection () {\n return this.mapper.datastore.getCollection(this.relation)\n },\n\n validateOptions (related, opts) {\n const DOMAIN_ERR = `new ${DOMAIN}`\n\n const localField = opts.localField\n if (!localField) {\n throw utils.err(DOMAIN_ERR, 'opts.localField')(400, 'string', localField)\n }\n\n const foreignKey = opts.foreignKey = opts.foreignKey || opts.localKey\n if (!foreignKey && (opts.type === belongsToType || opts.type === hasOneType)) {\n throw utils.err(DOMAIN_ERR, 'opts.foreignKey')(400, 'string', foreignKey)\n }\n\n if (utils.isString(related)) {\n opts.relation = related\n if (!utils.isFunction(opts.getRelation)) {\n throw utils.err(DOMAIN_ERR, 'opts.getRelation')(400, 'function', opts.getRelation)\n }\n } else if (related) {\n opts.relation = related.name\n } else {\n throw utils.err(DOMAIN_ERR, 'related')(400, 'Mapper or string', related)\n }\n },\n\n assignTo (mapper) {\n this.name = mapper.name\n Object.defineProperty(this, 'mapper', { value: mapper })\n\n mapper.relationList || Object.defineProperty(mapper, 'relationList', { value: [] })\n mapper.relationFields || Object.defineProperty(mapper, 'relationFields', { value: [] })\n mapper.relationList.push(this)\n mapper.relationFields.push(this.localField)\n },\n\n canFindLinkFor () {\n return !!(this.foreignKey || this.localKey)\n },\n\n getRelation () {\n return this.relatedMapper\n },\n\n getForeignKey (record) {\n return utils.get(record, this.mapper.idAttribute)\n },\n\n setForeignKey (record, relatedRecord) {\n if (!record || !relatedRecord) {\n return\n }\n\n this._setForeignKey(record, relatedRecord)\n },\n\n _setForeignKey (record, relatedRecords) {\n const idAttribute = this.mapper.idAttribute\n\n if (!utils.isArray(relatedRecords)) {\n relatedRecords = [relatedRecords]\n }\n\n relatedRecords.forEach((relatedRecord) => {\n utils.set(relatedRecord, this.foreignKey, utils.get(record, idAttribute))\n })\n },\n\n getLocalField (record) {\n return utils.get(record, this.localField)\n },\n\n setLocalField (record, relatedData) {\n return utils.set(record, this.localField, relatedData)\n },\n\n getInverse (mapper) {\n if (!this.inverse) {\n this.findInverseRelation(mapper)\n }\n\n return this.inverse\n },\n\n findInverseRelation (mapper) {\n this.getRelation().relationList.forEach((def) => {\n if (def.getRelation() === mapper && this.isInversedTo(def) && this !== def) {\n this.inverse = def\n return true\n }\n })\n },\n\n isInversedTo (def) {\n return !def.foreignKey || def.foreignKey === this.foreignKey\n },\n\n addLinkedRecords (records) {\n const datastore = this.mapper.datastore\n\n records.forEach((record) => {\n let relatedData = this.getLocalField(record)\n\n if (utils.isFunction(this.add)) {\n relatedData = this.add(datastore, this, record)\n } else if (relatedData) {\n relatedData = this.linkRecord(record, relatedData)\n }\n\n const isEmptyLinks = !relatedData || (utils.isArray(relatedData) && !relatedData.length)\n\n if (isEmptyLinks && this.canFindLinkFor(record)) {\n relatedData = this.findExistingLinksFor(record)\n }\n\n if (relatedData) {\n this.setLocalField(record, relatedData)\n }\n })\n },\n\n removeLinkedRecords (relatedMapper, records) {\n const localField = this.localField\n records.forEach((record) => {\n utils.set(record, localField, undefined)\n })\n },\n\n linkRecord (record, relatedRecord) {\n const relatedId = utils.get(relatedRecord, this.mapper.idAttribute)\n\n if (relatedId === undefined) {\n const unsaved = this.relatedCollection.unsaved()\n if (unsaved.indexOf(relatedRecord) === -1) {\n if (this.canAutoAddLinks) {\n relatedRecord = this.relatedCollection.add(relatedRecord)\n }\n }\n } else {\n if (relatedRecord !== this.relatedCollection.get(relatedId)) {\n this.setForeignKey(record, relatedRecord)\n\n if (this.canAutoAddLinks) {\n relatedRecord = this.relatedCollection.add(relatedRecord)\n }\n }\n }\n\n return relatedRecord\n },\n\n // e.g. user hasMany post via \"foreignKey\", so find all posts of user\n findExistingLinksByForeignKey (id) {\n if (id === undefined || id === null) {\n return\n }\n return this.relatedCollection.filter({\n [this.foreignKey]: id\n })\n },\n\n ensureLinkedDataHasProperType (props, opts) {\n const relatedMapper = this.getRelation()\n const relationData = this.getLocalField(props)\n\n if (utils.isArray(relationData) && (!relationData.length || relatedMapper.is(relationData[0]))) {\n return\n }\n\n if (relationData && !relatedMapper.is(relationData)) {\n utils.set(props, this.localField, relatedMapper.createRecord(relationData, opts))\n }\n },\n\n isRequiresParentId () {\n return false\n },\n\n isRequiresChildId () {\n return false\n },\n\n createChildRecord (props, relationData, opts) {\n this.setForeignKey(props, relationData)\n\n return this.createLinked(relationData, opts).then((result) => {\n this.setLocalField(props, result)\n })\n },\n\n createLinked (props, opts) {\n const create = utils.isArray(props) ? 'createMany' : 'create'\n\n return this.getRelation()[create](props, opts)\n }\n})\n","import utils from '../utils'\nimport { Relation } from '../Relation'\n\nexport const BelongsToRelation = Relation.extend({\n getForeignKey (record) {\n return utils.get(record, this.foreignKey)\n },\n\n _setForeignKey (record, relatedRecord) {\n utils.set(record, this.foreignKey, utils.get(relatedRecord, this.getRelation().idAttribute))\n },\n\n findExistingLinksFor (record) {\n // console.log('\\tBelongsTo#findExistingLinksFor', record)\n if (!record) {\n return\n }\n const relatedId = utils.get(record, this.foreignKey)\n if (relatedId !== undefined && relatedId !== null) {\n return this.relatedCollection.get(relatedId)\n }\n },\n\n isRequiresParentId () {\n return true\n },\n\n createParentRecord (props, opts) {\n const relationData = this.getLocalField(props)\n\n return this.createLinked(relationData, opts).then((record) => {\n this.setForeignKey(props, record)\n })\n },\n\n createChildRecord () {\n throw new Error('\"BelongsTo\" relation does not support child creation as it cannot have children.')\n }\n}, {\n TYPE_NAME: 'belongsTo'\n})\n","import utils from '../utils'\nimport { Relation } from '../Relation'\n\nexport const HasManyRelation = Relation.extend({\n validateOptions (related, opts) {\n Relation.prototype.validateOptions.call(this, related, opts)\n\n const { localKeys, foreignKeys, foreignKey } = opts\n\n if (!foreignKey && !localKeys && !foreignKeys) {\n throw utils.err('new Relation', 'opts.')(400, 'string', foreignKey)\n }\n },\n\n canFindLinkFor (record) {\n const hasForeignKeys = this.foreignKey || this.foreignKeys\n return !!(hasForeignKeys || (this.localKeys && utils.get(record, this.localKeys)))\n },\n\n linkRecord (record, relatedRecords) {\n const relatedCollection = this.relatedCollection\n const canAutoAddLinks = this.canAutoAddLinks\n const foreignKey = this.foreignKey\n const unsaved = this.relatedCollection.unsaved()\n\n return relatedRecords.map((relatedRecord) => {\n const relatedId = relatedCollection.recordId(relatedRecord)\n\n if ((relatedId === undefined && unsaved.indexOf(relatedRecord) === -1) || relatedRecord !== relatedCollection.get(relatedId)) {\n if (foreignKey) {\n // TODO: slow, could be optimized? But user loses hook\n this.setForeignKey(record, relatedRecord)\n }\n if (canAutoAddLinks) {\n relatedRecord = relatedCollection.add(relatedRecord)\n }\n }\n\n return relatedRecord\n })\n },\n\n findExistingLinksFor (record) {\n const id = utils.get(record, this.mapper.idAttribute)\n const ids = this.localKeys ? utils.get(record, this.localKeys) : null\n let records\n\n if (id !== undefined && this.foreignKey) {\n records = this.findExistingLinksByForeignKey(id)\n } else if (this.localKeys && ids) {\n records = this.findExistingLinksByLocalKeys(ids)\n } else if (id !== undefined && this.foreignKeys) {\n records = this.findExistingLinksByForeignKeys(id)\n }\n\n if (records && records.length) {\n return records\n }\n },\n\n // e.g. user hasMany group via \"foreignKeys\", so find all users of a group\n findExistingLinksByLocalKeys (ids) {\n return this.relatedCollection.filter({\n where: {\n [this.relatedCollection.mapper.idAttribute]: {\n in: ids\n }\n }\n })\n },\n\n // e.g. group hasMany user via \"localKeys\", so find all groups that own a user\n findExistingLinksByForeignKeys (id) {\n return this.relatedCollection.filter({\n where: {\n [this.foreignKeys]: {\n contains: id\n }\n }\n })\n },\n\n isRequiresParentId () {\n return !!this.localKeys && this.localKeys.length > 0\n },\n\n isRequiresChildId () {\n return !!this.foreignKey\n },\n\n createParentRecord (props, opts) {\n const relationData = this.getLocalField(props)\n const foreignIdField = this.getRelation().idAttribute\n\n return this.createLinked(relationData, opts).then((records) => {\n utils.set(props, this.localKeys, records.map((record) => utils.get(record, foreignIdField)))\n })\n },\n\n createLinked (props, opts) {\n return this.getRelation().createMany(props, opts)\n }\n}, {\n TYPE_NAME: 'hasMany'\n})\n","import utils from '../utils'\nimport { Relation } from '../Relation'\n\nexport const HasOneRelation = Relation.extend({\n findExistingLinksFor (relatedMapper, record) {\n const recordId = utils.get(record, relatedMapper.idAttribute)\n const records = this.findExistingLinksByForeignKey(recordId)\n\n if (records && records.length) {\n return records[0]\n }\n },\n\n isRequiresChildId () {\n return true\n }\n}, {\n TYPE_NAME: 'hasOne'\n})\n","import { Relation } from './Relation'\nimport { BelongsToRelation } from './Relation/BelongsTo'\nimport { HasManyRelation } from './Relation/HasMany'\nimport { HasOneRelation } from './Relation/HasOne'\n\n[BelongsToRelation, HasManyRelation, HasOneRelation].forEach(RelationType => {\n Relation[RelationType.TYPE_NAME] = (related, options) => new RelationType(related, options)\n})\n\nexport { belongsToType, hasManyType, hasOneType, Relation } from './Relation'\n","import { Relation } from './relations'\n\nexport { belongsToType, hasManyType, hasOneType } from './relations'\n/**\n * BelongsTo relation decorator. You probably won't use this directly.\n *\n * @name module:js-data.belongsTo\n * @method\n * @param {Mapper} related The relation the target belongs to.\n * @param {object} opts Configuration options.\n * @param {string} opts.foreignKey The field that holds the primary key of the\n * related record.\n * @param {string} opts.localField The field that holds a reference to the\n * related record object.\n * @returns {Function} Invocation function, which accepts the target as the only\n * parameter.\n */\nexport const belongsTo = function (related, opts) {\n return function (mapper) {\n Relation.belongsTo(related, opts).assignTo(mapper)\n }\n}\n\n/**\n * HasMany relation decorator. You probably won't use this directly.\n *\n * @name module:js-data.hasMany\n * @method\n * @param {Mapper} related The relation of which the target has many.\n * @param {object} opts Configuration options.\n * @param {string} [opts.foreignKey] The field that holds the primary key of the\n * related record.\n * @param {string} opts.localField The field that holds a reference to the\n * related record object.\n * @returns {Function} Invocation function, which accepts the target as the only\n * parameter.\n */\nexport const hasMany = function (related, opts) {\n return function (mapper) {\n Relation.hasMany(related, opts).assignTo(mapper)\n }\n}\n\n/**\n * HasOne relation decorator. You probably won't use this directly.\n *\n * @name module:js-data.hasOne\n * @method\n * @param {Mapper} related The relation of which the target has one.\n * @param {object} opts Configuration options.\n * @param {string} [opts.foreignKey] The field that holds the primary key of the\n * related record.\n * @param {string} opts.localField The field that holds a reference to the\n * related record object.\n * @returns {Function} Invocation function, which accepts the target as the only\n * parameter.\n */\nexport const hasOne = function (related, opts) {\n return function (mapper) {\n Relation.hasOne(related, opts).assignTo(mapper)\n }\n}\n","import utils, { safeSetLink } from './utils'\nimport Component from './Component'\nimport Settable from './Settable'\nimport {\n hasManyType,\n hasOneType\n} from './decorators'\n\nconst DOMAIN = 'Record'\n\nconst superMethod = function (mapper, name) {\n const store = mapper.datastore\n if (store && store[name]) {\n return function (...args) {\n return store[name](mapper.name, ...args)\n }\n }\n return mapper[name].bind(mapper)\n}\n\n// Cache these strings\nconst creatingPath = 'creating'\nconst noValidatePath = 'noValidate'\nconst keepChangeHistoryPath = 'keepChangeHistory'\nconst previousPath = 'previous'\n\n/**\n * js-data's Record class. An instance of `Record` corresponds to an in-memory\n * representation of a single row or document in a database, Firebase,\n * localstorage, etc. Basically, a `Record` instance represents whatever kind of\n * entity in your persistence layer that has a primary key.\n *\n * ```javascript\n * import {Record} from 'js-data'\n * ```\n *\n * @example Record#constructor\n * const JSData = require('js-data');\n * const { Record } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * // Instantiate a plain record\n * let record = new Record();\n * console.log('record: ' + JSON.stringify(record));\n *\n * // You can supply properties on instantiation\n * record = new Record({ name: 'John' });\n * console.log('record: ' + JSON.stringify(record));\n *\n * @example Record#constructor2\n * const JSData = require('js-data');\n * const { Mapper } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * // Instantiate a record that's associated with a Mapper:\n * const UserMapper = new Mapper({ name: 'user' });\n * const User = UserMapper.recordClass;\n * const user = UserMapper.createRecord({ name: 'John' });\n * const user2 = new User({ name: 'Sally' });\n * console.log('user: ' + JSON.stringify(user));\n * console.log('user2: ' + JSON.stringify(user2));\n *\n * @example Record#constructor3\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new Container();\n * store.defineMapper('user');\n *\n * // Instantiate a record that's associated with a store's Mapper\n * const user = store.createRecord('user', { name: 'John' });\n * console.log('user: ' + JSON.stringify(user));\n *\n * @example Record#constructor4\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new Container();\n * store.defineMapper('user', {\n * schema: {\n * properties: {\n * name: { type: 'string' }\n * }\n * }\n * });\n *\n * // Validate on instantiation\n * const user = store.createRecord('user', { name: 1234 });\n * console.log('user: ' + JSON.stringify(user));\n *\n * @example Record#constructor5\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new Container();\n * store.defineMapper('user', {\n * schema: {\n * properties: {\n * name: { type: 'string' }\n * }\n * }\n * });\n *\n * // Skip validation on instantiation\n * const user = store.createRecord('user', { name: 1234 }, { noValidate: true });\n * console.log('user: ' + JSON.stringify(user));\n * console.log('user.isValid(): ' + user.isValid());\n *\n * @class Record\n * @extends Component\n * @param {object} [props] The initial properties of the new Record instance.\n * @param {object} [opts] Configuration options.\n * @param {boolean} [opts.noValidate=false] Whether to skip validation on the\n * initial properties.\n * @param {boolean} [opts.validateOnSet=true] Whether to enable setter\n * validation on properties after the Record has been initialized.\n * @since 3.0.0\n */\nfunction Record (props, opts) {\n utils.classCallCheck(this, Record)\n Settable.call(this)\n props || (props = {})\n opts || (opts = {})\n const _set = this._set\n const mapper = this.constructor.mapper\n\n _set(creatingPath, true)\n _set(noValidatePath, !!opts.noValidate)\n _set(keepChangeHistoryPath, opts.keepChangeHistory === undefined ? (mapper ? mapper.keepChangeHistory : true) : opts.keepChangeHistory)\n\n // Set the idAttribute value first, if it exists.\n const id = mapper ? utils.get(props, mapper.idAttribute) : undefined\n if (id !== undefined) {\n utils.set(this, mapper.idAttribute, id)\n }\n\n utils.fillIn(this, props)\n _set(creatingPath, false)\n if (opts.validateOnSet !== undefined) {\n _set(noValidatePath, !opts.validateOnSet)\n } else if (mapper && mapper.validateOnSet !== undefined) {\n _set(noValidatePath, !mapper.validateOnSet)\n } else {\n _set(noValidatePath, false)\n }\n _set(previousPath, mapper ? mapper.toJSON(props) : utils.plainCopy(props))\n}\n\nexport default Component.extend({\n constructor: Record,\n\n /**\n * Returns the {@link Mapper} paired with this record's class, if any.\n *\n * @method Record#_mapper\n * @returns {Mapper} The {@link Mapper} paired with this record's class, if any.\n * @since 3.0.0\n */\n _mapper () {\n const mapper = this.constructor.mapper\n if (!mapper) {\n throw utils.err(`${DOMAIN}#_mapper`, '')(404, 'mapper')\n }\n return mapper\n },\n\n /**\n * Lifecycle hook.\n *\n * @method Record#afterLoadRelations\n * @param {string[]} relations The `relations` argument passed to {@link Record#loadRelations}.\n * @param {object} opts The `opts` argument passed to {@link Record#loadRelations}.\n * @since 3.0.0\n */\n afterLoadRelations () {},\n\n /**\n * Lifecycle hook.\n *\n * @method Record#beforeLoadRelations\n * @param {string[]} relations The `relations` argument passed to {@link Record#loadRelations}.\n * @param {object} opts The `opts` argument passed to {@link Record#loadRelations}.\n * @since 3.0.0\n */\n beforeLoadRelations () {},\n\n /**\n * Return the change history of this record since it was instantiated or\n * {@link Record#commit} was called.\n *\n * @method Record#changeHistory\n * @since 3.0.0\n */\n changeHistory () {\n return (this._get('history') || []).slice()\n },\n\n /**\n * Return changes to this record since it was instantiated or\n * {@link Record#commit} was called.\n *\n * @example Record#changes\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new Container();\n * store.defineMapper('user');\n * const user = store.createRecord('user');\n * console.log('user changes: ' + JSON.stringify(user.changes()));\n * user.name = 'John';\n * console.log('user changes: ' + JSON.stringify(user.changes()));\n *\n * @method Record#changes\n * @param [opts] Configuration options.\n * @param {Function} [opts.equalsFn={@link utils.deepEqual}] Equality function.\n * @param {array} [opts.ignore=[]] Array of strings or RegExp of fields to ignore.\n * @returns {Object} Object describing the changes to this record since it was\n * instantiated or its {@link Record#commit} method was last called.\n * @since 3.0.0\n */\n changes (opts) {\n opts || (opts = {})\n return utils.diffObjects(typeof this.toJSON === 'function' ? this.toJSON(opts) : this, this._get('previous'), opts)\n },\n\n /**\n * Make the record's current in-memory state it's only state, with any\n * previous property values being set to current values.\n *\n * @example Record#commit\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new Container();\n * store.defineMapper('user');\n * const user = store.createRecord('user');\n * console.log('user hasChanges: ' + user.hasChanges());\n * user.name = 'John';\n * console.log('user hasChanges: ' + user.hasChanges());\n * user.commit();\n * console.log('user hasChanges: ' + user.hasChanges());\n *\n * @method Record#commit\n * @param {object} [opts] Configuration options. Passed to {@link Record#toJSON}.\n * @since 3.0.0\n */\n commit (opts) {\n this._set('changed') // unset\n this._set('changing', false)\n this._set('history', []) // clear history\n this._set('previous', this.toJSON(opts))\n },\n\n /**\n * Call {@link Mapper#destroy} using this record's primary key.\n *\n * @example\n * import { Container } from 'js-data';\n * import { RethinkDBAdapter } from 'js-data-rethinkdb';\n *\n * const store = new Container();\n * store.registerAdapter('rethink', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('user');\n * store.find('user', 1234).then((user) => {\n * console.log(user.id); // 1234\n *\n * // Destroy this user from the database\n * return user.destroy();\n * });\n *\n * @method Record#destroy\n * @param {object} [opts] Configuration options passed to {@link Mapper#destroy}.\n * @returns {Promise} The result of calling {@link Mapper#destroy} with the\n * primary key of this record.\n * @since 3.0.0\n */\n destroy (opts) {\n opts || (opts = {})\n const mapper = this._mapper()\n return superMethod(mapper, 'destroy')(utils.get(this, mapper.idAttribute), opts)\n },\n\n /**\n * Return the value at the given path for this instance.\n *\n * @example Record#get\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n * const store = new Container();\n * store.defineMapper('user');\n *\n * const user = store.createRecord('user', { name: 'Bob' });\n * console.log('user.get(\"name\"): ' + user.get('name'));\n *\n * @method Record#get\n * @param {string} key Path of value to retrieve.\n * @returns {*} Value at path.\n * @since 3.0.0\n */\n 'get' (key) {\n return utils.get(this, key)\n },\n\n /**\n * Return whether this record has changed since it was instantiated or\n * {@link Record#commit} was called.\n *\n * @example Record#hasChanges\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n * const store = new Container();\n * store.defineMapper('user');\n * const user = store.createRecord('user');\n * console.log('user hasChanges: ' + user.hasChanges());\n * user.name = 'John';\n * console.log('user hasChanges: ' + user.hasChanges());\n * user.commit();\n * console.log('user hasChanges: ' + user.hasChanges());\n *\n * @method Record#hasChanges\n * @param [opts] Configuration options.\n * @param {Function} [opts.equalsFn={@link utils.deepEqual}] Equality function.\n * @param {array} [opts.ignore=[]] Array of strings or RegExp of fields to ignore.\n * @returns {boolean} Return whether the record has changed since it was\n * instantiated or since its {@link Record#commit} method was called.\n * @since 3.0.0\n */\n hasChanges (opts) {\n const quickHasChanges = !!(this._get('changed') || []).length\n return quickHasChanges || utils.areDifferent(typeof this.toJSON === 'function' ? this.toJSON(opts) : this, this._get('previous'), opts)\n },\n\n /**\n * Return whether the record is unsaved. Records that have primary keys are\n * considered \"saved\". Records without primary keys are considered \"unsaved\".\n *\n * @example Record#isNew\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n * const store = new Container();\n * store.defineMapper('user');\n * const user = store.createRecord('user', {\n * id: 1234\n * });\n * const user2 = store.createRecord('user');\n * console.log('user isNew: ' + user.isNew()); // false\n * console.log('user2 isNew: ' + user2.isNew()); // true\n *\n * @method Record#isNew\n * @returns {boolean} Whether the record is unsaved.\n * @since 3.0.0\n */\n isNew (opts) {\n return utils.get(this, this._mapper().idAttribute) === undefined\n },\n\n /**\n * Return whether the record in its current state passes validation.\n *\n * @example Record#isValid\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n * const store = new Container();\n * store.defineMapper('user', {\n * schema: {\n * properties: {\n * name: { type: 'string' }\n * }\n * }\n * });\n * const user = store.createRecord('user', {\n * name: 1234\n * }, {\n * noValidate: true // this allows us to put the record into an invalid state\n * });\n * console.log('user isValid: ' + user.isValid());\n * user.name = 'John';\n * console.log('user isValid: ' + user.isValid());\n *\n * @method Record#isValid\n * @param {object} [opts] Configuration options. Passed to {@link Mapper#validate}.\n * @returns {boolean} Whether the record in its current state passes\n * validation.\n * @since 3.0.0\n */\n isValid (opts) {\n return !this._mapper().validate(this, opts)\n },\n\n removeInverseRelation (currentParent, id, inverseDef, idAttribute) {\n if (inverseDef.type === hasOneType) {\n safeSetLink(currentParent, inverseDef.localField, undefined)\n } else if (inverseDef.type === hasManyType) {\n // e.g. remove comment from otherPost.comments\n const children = utils.get(currentParent, inverseDef.localField)\n if (id === undefined) {\n utils.remove(children, (child) => child === this)\n } else {\n utils.remove(children, (child) => child === this || id === utils.get(child, idAttribute))\n }\n }\n },\n\n setupInverseRelation (record, id, inverseDef, idAttribute) {\n // Update (set) inverse relation\n if (inverseDef.type === hasOneType) {\n // e.g. someUser.profile = profile\n safeSetLink(record, inverseDef.localField, this)\n } else if (inverseDef.type === hasManyType) {\n // e.g. add comment to somePost.comments\n const children = utils.get(record, inverseDef.localField)\n if (id === undefined) {\n utils.noDupeAdd(children, this, (child) => child === this)\n } else {\n utils.noDupeAdd(children, this, (child) => child === this || id === utils.get(child, idAttribute))\n }\n }\n },\n\n /**\n * Lazy load relations of this record, to be attached to the record once their\n * loaded.\n *\n * @example\n * import { Container } from 'js-data';\n * import { RethinkDBAdapter } from 'js-data-rethinkdb';\n *\n * const store = new Container();\n * store.registerAdapter('rethink', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('user', {\n * relations: {\n * hasMany: {\n * post: {\n * localField: 'posts',\n * foreignKey: 'user_id'\n * }\n * }\n * }\n * });\n * store.defineMapper('post', {\n * relations: {\n * belongsTo: {\n * user: {\n * localField: 'user',\n * foreignKey: 'user_id'\n * }\n * }\n * }\n * });\n * store.find('user', 1234).then((user) => {\n * console.log(user.id); // 1234\n *\n * // Load the user's post relations\n * return user.loadRelations(['post']);\n * }).then((user) => {\n * console.log(user.posts); // [{...}, {...}, ...]\n * });\n *\n * @method Record#loadRelations\n * @param {string[]} [relations] List of relations to load. Can use localField\n * names or Mapper names to pick relations.\n * @param {object} [opts] Configuration options.\n * @returns {Promise} Resolves with the record, with the loaded relations now\n * attached.\n * @since 3.0.0\n */\n loadRelations (relations, opts) {\n let op\n const mapper = this._mapper()\n\n // Default values for arguments\n relations || (relations = [])\n if (utils.isString(relations)) {\n relations = [relations]\n }\n opts || (opts = {})\n opts.with = relations\n\n // Fill in \"opts\" with the Model's configuration\n utils._(opts, mapper)\n opts.adapter = mapper.getAdapterName(opts)\n\n // beforeLoadRelations lifecycle hook\n op = opts.op = 'beforeLoadRelations'\n return utils.resolve(this[op](relations, opts)).then(() => {\n // Now delegate to the adapter\n op = opts.op = 'loadRelations'\n mapper.dbg(op, this, relations, opts)\n const tasks = []\n let task\n utils.forEachRelation(mapper, opts, (def, optsCopy) => {\n const relatedMapper = def.getRelation()\n optsCopy.raw = false\n if (utils.isFunction(def.load)) {\n task = def.load(mapper, def, this, opts)\n } else if (def.type === 'hasMany' || def.type === 'hasOne') {\n if (def.foreignKey) {\n task = superMethod(relatedMapper, 'findAll')({\n [def.foreignKey]: utils.get(this, mapper.idAttribute)\n }, optsCopy).then(function (relatedData) {\n if (def.type === 'hasOne') {\n return relatedData.length ? relatedData[0] : undefined\n }\n return relatedData\n })\n } else if (def.localKeys) {\n task = superMethod(relatedMapper, 'findAll')({\n where: {\n [relatedMapper.idAttribute]: {\n in: utils.get(this, def.localKeys)\n }\n }\n })\n } else if (def.foreignKeys) {\n task = superMethod(relatedMapper, 'findAll')({\n where: {\n [def.foreignKeys]: {\n contains: utils.get(this, mapper.idAttribute)\n }\n }\n }, opts)\n }\n } else if (def.type === 'belongsTo') {\n const key = utils.get(this, def.foreignKey)\n if (utils.isSorN(key)) {\n task = superMethod(relatedMapper, 'find')(key, optsCopy)\n }\n }\n if (task) {\n task = task.then((relatedData) => {\n def.setLocalField(this, relatedData)\n })\n tasks.push(task)\n }\n })\n return Promise.all(tasks)\n }).then(() => {\n // afterLoadRelations lifecycle hook\n op = opts.op = 'afterLoadRelations'\n return utils.resolve(this[op](relations, opts)).then(() => this)\n })\n },\n\n /**\n * Return the properties with which this record was instantiated.\n *\n * @example Record#previous\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n * const store = new Container();\n * store.defineMapper('user');\n * const user = store.createRecord('user', {\n * name: 'William'\n * });\n * console.log('user previous: ' + JSON.stringify(user.previous()));\n * user.name = 'Bob';\n * console.log('user previous: ' + JSON.stringify(user.previous()));\n * user.commit();\n * console.log('user previous: ' + JSON.stringify(user.previous()));\n *\n * @method Record#previous\n * @param {string} [key] If specified, return just the initial value of the\n * given key.\n * @returns {Object} The initial properties of this record.\n * @since 3.0.0\n */\n previous (key) {\n if (key) {\n return this._get(`previous.${key}`)\n }\n return this._get('previous')\n },\n\n /**\n * Revert changes to this record back to the properties it had when it was\n * instantiated.\n *\n * @example Record#revert\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n * const store = new Container();\n * store.defineMapper('user');\n * const user = store.createRecord('user', {\n * name: 'William'\n * });\n * console.log('user: ' + JSON.stringify(user));\n * user.name = 'Bob';\n * console.log('user: ' + JSON.stringify(user));\n * user.revert();\n * console.log('user: ' + JSON.stringify(user));\n *\n * @method Record#revert\n * @param {object} [opts] Configuration options.\n * @param {string[]} [opts.preserve] Array of strings or Regular Expressions\n * denoting properties that should not be reverted.\n * @since 3.0.0\n */\n revert (opts) {\n const previous = this._get('previous')\n opts || (opts = {})\n opts.preserve || (opts.preserve = [])\n utils.forOwn(this, (value, key) => {\n if (key !== this._mapper().idAttribute && !Object.hasOwnProperty.call(previous, key) && Object.hasOwnProperty.call(this, key) && opts.preserve.indexOf(key) === -1) {\n delete this[key]\n }\n })\n utils.forOwn(previous, (value, key) => {\n if (opts.preserve.indexOf(key) === -1) {\n this[key] = value\n }\n })\n this.commit()\n },\n\n /**\n * Delegates to {@link Mapper#create} or {@link Mapper#update}.\n *\n * @example\n * import { Container } from 'js-data';\n * import { RethinkDBAdapter } from 'js-data-rethinkdb';\n *\n * const store = new Container();\n * store.registerAdapter('rethink', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('session');\n * const session = store.createRecord('session', { topic: 'Node.js' });\n *\n * // Create a new record in the database\n * session.save().then(() => {\n * console.log(session.id); // 1234\n *\n * session.skill_level = 'beginner';\n *\n * // Update the record in the database\n * return session.save();\n * });\n *\n * @method Record#save\n * @param {object} [opts] Configuration options. See {@link Mapper#create} and\n * {@link Mapper#update}.\n * @param {boolean} [opts.changesOnly] Equality function. Default uses `===`.\n * @param {Function} [opts.equalsFn] Passed to {@link Record#changes} when\n * `opts.changesOnly` is `true`.\n * @param {array} [opts.ignore] Passed to {@link Record#changes} when\n * `opts.changesOnly` is `true`.\n * @returns {Promise} The result of calling {@link Mapper#create} or\n * {@link Mapper#update}.\n * @since 3.0.0\n */\n save (opts) {\n opts || (opts = {})\n const mapper = this._mapper()\n const id = utils.get(this, mapper.idAttribute)\n let props = this\n\n const postProcess = (result) => {\n const record = opts.raw ? result.data : result\n if (record) {\n utils.deepMixIn(this, record)\n this.commit()\n }\n return result\n }\n\n if (id === undefined) {\n return superMethod(mapper, 'create')(props, opts).then(postProcess)\n }\n if (opts.changesOnly) {\n const changes = this.changes(opts)\n props = {}\n utils.fillIn(props, changes.added)\n utils.fillIn(props, changes.changed)\n }\n return superMethod(mapper, 'update')(id, props, opts).then(postProcess)\n },\n\n /**\n * Set the value for a given key, or the values for the given keys if \"key\" is\n * an object. Triggers change events on those properties that have `track: true`\n * in {@link Mapper#schema}.\n *\n * @example Record#set\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n * const store = new Container();\n * store.defineMapper('user');\n *\n * const user = store.createRecord('user');\n * console.log('user: ' + JSON.stringify(user));\n *\n * user.set('name', 'Bob');\n * console.log('user: ' + JSON.stringify(user));\n *\n * user.set({ age: 30, role: 'admin' });\n * console.log('user: ' + JSON.stringify(user));\n *\n * @fires Record#change\n * @method Record#set\n * @param {(string|Object)} key Key to set or hash of key-value pairs to set.\n * @param {*} [value] Value to set for the given key.\n * @param {object} [opts] Configuration options.\n * @param {boolean} [opts.silent=false] Whether to trigger change events.\n * @since 3.0.0\n */\n 'set' (key, value, opts) {\n if (utils.isObject(key)) {\n opts = value\n }\n opts || (opts = {})\n if (opts.silent) {\n this._set('silent', true)\n }\n utils.set(this, key, value)\n if (!this._get('eventId')) {\n this._set('silent') // unset\n }\n },\n\n /**\n * Return a plain object representation of this record. If the class from\n * which this record was created has a Mapper, then {@link Mapper#toJSON} will\n * be called with this record instead.\n *\n * @example Record#toJSON\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n * const store = new Container();\n * store.defineMapper('user', {\n * schema: {\n * properties: {\n * name: { type: 'string' }\n * }\n * }\n * });\n *\n * const user = store.createRecord('user', {\n * name: 'John',\n * $$hashKey: '1234'\n * });\n * console.log('user: ' + JSON.stringify(user.toJSON()));\n *\n * @method Record#toJSON\n * @param {object} [opts] Configuration options.\n * @param {string[]} [opts.with] Array of relation names or relation fields\n * to include in the representation. Only available as an option if the class\n * from which this record was created has a Mapper and this record resides in\n * an instance of {@link DataStore}.\n * @returns {Object} Plain object representation of this record.\n * @since 3.0.0\n */\n toJSON (opts) {\n const mapper = this.constructor.mapper\n if (mapper) {\n return mapper.toJSON(this, opts)\n } else {\n const json = {}\n utils.forOwn(this, (prop, key) => {\n json[key] = utils.plainCopy(prop)\n })\n return json\n }\n },\n\n /**\n * Unset the value for a given key. Triggers change events on those properties\n * that have `track: true` in {@link Mapper#schema}.\n *\n * @example Record#unset\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n * const store = new Container();\n * store.defineMapper('user');\n *\n * const user = store.createRecord('user', {\n * name: 'John'\n * });\n * console.log('user: ' + JSON.stringify(user));\n *\n * user.unset('name');\n * console.log('user: ' + JSON.stringify(user));\n *\n * @method Record#unset\n * @param {string} key Key to unset.\n * @param {object} [opts] Configuration options.\n * @param {boolean} [opts.silent=false] Whether to trigger change events.\n * @since 3.0.0\n */\n unset (key, opts) {\n this.set(key, undefined, opts)\n },\n\n /**\n * Validate this record based on its current properties.\n *\n * @example Record#validate\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n * const store = new Container();\n * store.defineMapper('user', {\n * schema: {\n * properties: {\n * name: { type: 'string' }\n * }\n * }\n * });\n * const user = store.createRecord('user', {\n * name: 1234\n * }, {\n * noValidate: true // this allows us to put the record into an invalid state\n * });\n * console.log('user validation: ' + JSON.stringify(user.validate()));\n * user.name = 'John';\n * console.log('user validation: ' + user.validate());\n *\n * @method Record#validate\n * @param {object} [opts] Configuration options. Passed to {@link Mapper#validate}.\n * @returns {*} Array of errors or `undefined` if no errors.\n * @since 3.0.0\n */\n validate (opts) {\n return this._mapper().validate(this, opts)\n }\n}, {\n creatingPath,\n noValidatePath,\n keepChangeHistoryPath,\n previousPath\n})\n\n/**\n * Allow records to emit events.\n *\n * An record's registered listeners are stored in the record's private data.\n */\nutils.eventify(\n Record.prototype,\n function () {\n return this._get('events')\n },\n function (value) {\n this._set('events', value)\n }\n)\n\n/**\n * Fired when a record changes. Only works for records that have tracked fields.\n * See {@link Record~changeListener} on how to listen for this event.\n *\n * @event Record#change\n * @see Record~changeListener\n */\n\n/**\n * Callback signature for the {@link Record#event:change} event.\n *\n * @example\n * function onChange (record, changes) {\n * // do something\n * }\n * record.on('change', onChange);\n *\n * @callback Record~changeListener\n * @param {Record} The Record that changed.\n * @param {object} The changes.\n * @see Record#event:change\n * @since 3.0.0\n */\n\n/**\n * Create a subclass of this Record:\n * @example Record.extend\n * const JSData = require('js-data');\n * const { Record } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * // Extend the class using ES2015 class syntax.\n * class CustomRecordClass extends Record {\n * foo () { return 'bar'; }\n * static beep () { return 'boop'; }\n * }\n * const customRecord = new CustomRecordClass();\n * console.log(customRecord.foo());\n * console.log(CustomRecordClass.beep());\n *\n * // Extend the class using alternate method.\n * const OtherRecordClass = Record.extend({\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * });\n * const otherRecord = new OtherRecordClass();\n * console.log(otherRecord.foo());\n * console.log(OtherRecordClass.beep());\n *\n * // Extend the class, providing a custom constructor.\n * function AnotherRecordClass () {\n * Record.call(this);\n * this.created_at = new Date().getTime();\n * }\n * Record.extend({\n * constructor: AnotherRecordClass,\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * });\n * const anotherRecord = new AnotherRecordClass();\n * console.log(anotherRecord.created_at);\n * console.log(anotherRecord.foo());\n * console.log(AnotherRecordClass.beep());\n *\n * @method Record.extend\n * @param {object} [props={}] Properties to add to the prototype of the\n * subclass.\n * @param {object} [props.constructor] Provide a custom constructor function\n * to be used as the subclass itself.\n * @param {object} [classProps={}] Static properties to add to the subclass.\n * @returns {Constructor} Subclass of this Record class.\n * @since 3.0.0\n */\n","export function sort (a, b, hashCode) {\n // Short-circuit comparison if a and b are strictly equal\n // This is absolutely necessary for indexed objects that\n // don't have the idAttribute field\n if (a === b) {\n return 0\n }\n if (hashCode) {\n a = hashCode(a)\n b = hashCode(b)\n }\n if ((a === null && b === null) || (a === undefined && b === undefined)) {\n return -1\n }\n\n if (a === null || a === undefined) {\n return -1\n }\n\n if (b === null || b === undefined) {\n return 1\n }\n\n if (a < b) {\n return -1\n }\n\n if (a > b) {\n return 1\n }\n\n return 0\n}\n\nexport function insertAt (array, index, value) {\n array.splice(index, 0, value)\n return array\n}\n\nexport function removeAt (array, index) {\n array.splice(index, 1)\n return array\n}\n\nexport function binarySearch (array, value, field) {\n let lo = 0\n let hi = array.length\n let compared\n let mid\n\n while (lo < hi) {\n mid = ((lo + hi) / 2) | 0\n compared = sort(value, array[mid], field)\n if (compared === 0) {\n return {\n found: true,\n index: mid\n }\n } else if (compared < 0) {\n hi = mid\n } else {\n lo = mid + 1\n }\n }\n\n return {\n found: false,\n index: hi\n }\n}\n","// Copyright (c) 2015, InternalFX.\n\n// Permission to use, copy, modify, and/or distribute this software for any purpose with or\n// without fee is hereby granted, provided that the above copyright notice and this permission\n// notice appear in all copies.\n\n// THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO\n// THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT\n// SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR\n// ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION\n// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE\n// USE OR PERFORMANCE OF THIS SOFTWARE.\n\n// Modifications\n// Copyright 2015-2016 Jason Dobry\n//\n// Summary of modifications:\n// Reworked dependencies so as to re-use code already in js-data\n// Removed unused code\nimport utils from '../../src/utils'\nimport { binarySearch, insertAt, removeAt } from './_utils'\n\nexport default function Index (fieldList, opts) {\n utils.classCallCheck(this, Index)\n fieldList || (fieldList = [])\n\n if (!utils.isArray(fieldList)) {\n throw new Error('fieldList must be an array.')\n }\n\n opts || (opts = {})\n this.fieldList = fieldList\n this.fieldGetter = opts.fieldGetter\n this.hashCode = opts.hashCode\n this.isIndex = true\n this.keys = []\n this.values = []\n}\n\nutils.addHiddenPropsToTarget(Index.prototype, {\n 'set' (keyList, value) {\n if (!utils.isArray(keyList)) {\n keyList = [keyList]\n }\n\n const key = keyList.shift() || undefined\n const pos = binarySearch(this.keys, key)\n\n if (keyList.length === 0) {\n if (pos.found) {\n const dataLocation = binarySearch(this.values[pos.index], value, this.hashCode)\n if (!dataLocation.found) {\n insertAt(this.values[pos.index], dataLocation.index, value)\n }\n } else {\n insertAt(this.keys, pos.index, key)\n insertAt(this.values, pos.index, [value])\n }\n } else {\n if (pos.found) {\n this.values[pos.index].set(keyList, value)\n } else {\n insertAt(this.keys, pos.index, key)\n const newIndex = new Index([], { hashCode: this.hashCode })\n newIndex.set(keyList, value)\n insertAt(this.values, pos.index, newIndex)\n }\n }\n },\n\n 'get' (keyList) {\n if (!utils.isArray(keyList)) {\n keyList = [keyList]\n }\n\n const key = keyList.shift() || undefined\n const pos = binarySearch(this.keys, key)\n\n if (keyList.length === 0) {\n if (pos.found) {\n if (this.values[pos.index].isIndex) {\n return this.values[pos.index].getAll()\n } else {\n return this.values[pos.index].slice()\n }\n } else {\n return []\n }\n } else {\n if (pos.found) {\n return this.values[pos.index].get(keyList)\n } else {\n return []\n }\n }\n },\n\n getAll (opts) {\n opts || (opts = {})\n let results = []\n const values = this.values\n if (opts.order === 'desc') {\n for (let i = values.length - 1; i >= 0; i--) {\n const value = values[i]\n if (value.isIndex) {\n results = results.concat(value.getAll(opts))\n } else {\n results = results.concat(value)\n }\n }\n } else {\n for (let i = 0; i < values.length; i++) {\n const value = values[i]\n if (value.isIndex) {\n results = results.concat(value.getAll(opts))\n } else {\n results = results.concat(value)\n }\n }\n }\n return results\n },\n\n visitAll (cb, thisArg) {\n this.values.forEach(function (value) {\n if (value.isIndex) {\n value.visitAll(cb, thisArg)\n } else {\n value.forEach(cb, thisArg)\n }\n })\n },\n\n between (leftKeys, rightKeys, opts) {\n opts || (opts = {})\n if (!utils.isArray(leftKeys)) {\n leftKeys = [leftKeys]\n }\n if (!utils.isArray(rightKeys)) {\n rightKeys = [rightKeys]\n }\n utils.fillIn(opts, {\n leftInclusive: true,\n rightInclusive: false,\n limit: undefined,\n offset: 0\n })\n\n const results = this._between(leftKeys, rightKeys, opts)\n\n if (opts.limit) {\n return results.slice(opts.offset, opts.limit + opts.offset)\n } else {\n return results.slice(opts.offset)\n }\n },\n\n _between (leftKeys, rightKeys, opts) {\n let results = []\n\n const leftKey = leftKeys.shift()\n const rightKey = rightKeys.shift()\n\n let pos\n\n if (leftKey !== undefined) {\n pos = binarySearch(this.keys, leftKey)\n } else {\n pos = {\n found: false,\n index: 0\n }\n }\n\n if (leftKeys.length === 0) {\n if (pos.found && opts.leftInclusive === false) {\n pos.index += 1\n }\n\n for (let i = pos.index; i < this.keys.length; i += 1) {\n if (rightKey !== undefined) {\n if (opts.rightInclusive) {\n if (this.keys[i] > rightKey) { break }\n } else {\n if (this.keys[i] >= rightKey) { break }\n }\n }\n\n if (this.values[i].isIndex) {\n results = results.concat(this.values[i].getAll())\n } else {\n results = results.concat(this.values[i])\n }\n\n if (opts.limit) {\n if (results.length >= (opts.limit + opts.offset)) {\n break\n }\n }\n }\n } else {\n for (let i = pos.index; i < this.keys.length; i += 1) {\n const currKey = this.keys[i]\n if (currKey > rightKey) { break }\n\n if (this.values[i].isIndex) {\n if (currKey === leftKey) {\n results = results.concat(this.values[i]._between(utils.copy(leftKeys), rightKeys.map(function () { return undefined }), opts))\n } else if (currKey === rightKey) {\n results = results.concat(this.values[i]._between(leftKeys.map(function () { return undefined }), utils.copy(rightKeys), opts))\n } else {\n results = results.concat(this.values[i].getAll())\n }\n } else {\n results = results.concat(this.values[i])\n }\n\n if (opts.limit) {\n if (results.length >= (opts.limit + opts.offset)) {\n break\n }\n }\n }\n }\n\n if (opts.limit) {\n return results.slice(0, opts.limit + opts.offset)\n } else {\n return results\n }\n },\n\n peek () {\n if (this.values.length) {\n if (this.values[0].isIndex) {\n return this.values[0].peek()\n } else {\n return this.values[0]\n }\n }\n return []\n },\n\n clear () {\n this.keys = []\n this.values = []\n },\n\n insertRecord (data) {\n const keyList = this.fieldList.map(function (field) {\n if (utils.isFunction(field)) {\n return field(data) || undefined\n } else {\n return data[field] || undefined\n }\n })\n this.set(keyList, data)\n },\n\n removeRecord (data) {\n let removed\n const isUnique = this.hashCode(data) !== undefined\n this.values.forEach((value, i) => {\n if (value.isIndex) {\n if (value.removeRecord(data)) {\n if (value.keys.length === 0) {\n removeAt(this.keys, i)\n removeAt(this.values, i)\n }\n removed = true\n return false\n }\n } else {\n let dataLocation = {}\n if (this.keys[i] === undefined || !isUnique) {\n for (let j = value.length - 1; j >= 0; j--) {\n if (value[j] === data) {\n dataLocation = {\n found: true,\n index: j\n }\n break\n }\n }\n } else if (isUnique) {\n dataLocation = binarySearch(value, data, this.hashCode)\n }\n if (dataLocation.found) {\n removeAt(value, dataLocation.index)\n if (value.length === 0) {\n removeAt(this.keys, i)\n removeAt(this.values, i)\n }\n removed = true\n return false\n }\n }\n })\n return removed ? data : undefined\n },\n\n updateRecord (data) {\n const removed = this.removeRecord(data)\n if (removed !== undefined) {\n this.insertRecord(data)\n }\n }\n})\n","import utils from './utils'\nimport Component from './Component'\nimport Query from './Query'\nimport Record from './Record'\nimport Index from '../lib/mindex/index'\n\nconst { noValidatePath } = Record\n\nconst DOMAIN = 'Collection'\n\nconst COLLECTION_DEFAULTS = {\n /**\n * Whether to call {@link Record#commit} on records that are added to the\n * collection and already exist in the collection.\n *\n * @name Collection#commitOnMerge\n * @type {boolean}\n * @default true\n */\n commitOnMerge: true,\n\n /**\n * Whether record events should bubble up and be emitted by the collection.\n *\n * @name Collection#emitRecordEvents\n * @type {boolean}\n * @default true\n */\n emitRecordEvents: true,\n\n /**\n * Field to be used as the unique identifier for records in this collection.\n * Defaults to `\"id\"` unless {@link Collection#mapper} is set, in which case\n * this will default to {@link Mapper#idAttribute}.\n *\n * @name Collection#idAttribute\n * @type {string}\n * @default \"id\"\n */\n idAttribute: 'id',\n\n /**\n * What to do when inserting a record into this Collection that shares a\n * primary key with a record already in this Collection.\n *\n * Possible values:\n * merge\n * replace\n * skip\n *\n * Merge:\n *\n * Recursively shallow copy properties from the new record onto the existing\n * record.\n *\n * Replace:\n *\n * Shallow copy top-level properties from the new record onto the existing\n * record. Any top-level own properties of the existing record that are _not_\n * on the new record will be removed.\n *\n * Skip:\n *\n * Ignore new record, keep existing record.\n *\n * @name Collection#onConflict\n * @type {string}\n * @default \"merge\"\n */\n onConflict: 'merge'\n}\n\n/**\n * An ordered set of {@link Record} instances.\n *\n * @example Collection#constructor\n * // import { Collection, Record } from 'js-data';\n * const JSData = require('js-data');\n * const {Collection, Record} = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const user1 = new Record({ id: 1 });\n * const user2 = new Record({ id: 2 });\n * const UserCollection = new Collection([user1, user2]);\n * console.log(UserCollection.get(1) === user1);\n *\n * @class Collection\n * @extends Component\n * @param {array} [records] Initial set of records to insert into the\n * collection.\n * @param {object} [opts] Configuration options.\n * @param {string} [opts.commitOnMerge] See {@link Collection#commitOnMerge}.\n * @param {string} [opts.idAttribute] See {@link Collection#idAttribute}.\n * @param {string} [opts.onConflict=\"merge\"] See {@link Collection#onConflict}.\n * @param {string} [opts.mapper] See {@link Collection#mapper}.\n * @since 3.0.0\n */\nfunction Collection (records, opts) {\n utils.classCallCheck(this, Collection)\n Component.call(this, opts)\n\n if (records && !utils.isArray(records)) {\n opts = records\n records = []\n }\n if (utils.isString(opts)) {\n opts = { idAttribute: opts }\n }\n\n // Default values for arguments\n records || (records = [])\n opts || (opts = {})\n\n Object.defineProperties(this, {\n /**\n * Default Mapper for this collection. Optional. If a Mapper is provided, then\n * the collection will use the {@link Mapper#idAttribute} setting, and will\n * wrap records in {@link Mapper#recordClass}.\n *\n * @example Collection#mapper\n * const JSData = require('js-data');\n * const {Collection, Mapper} = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * class MyMapperClass extends Mapper {\n * foo () { return 'bar'; }\n * }\n * const myMapper = new MyMapperClass({ name: 'myMapper' });\n * const collection = new Collection(null, { mapper: myMapper });\n *\n * @name Collection#mapper\n * @type {Mapper}\n * @default null\n * @since 3.0.0\n */\n mapper: {\n value: undefined,\n writable: true\n },\n // Query class used by this collection\n queryClass: {\n value: undefined,\n writable: true\n }\n })\n\n // Apply user-provided configuration\n utils.fillIn(this, opts)\n // Fill in any missing options with the defaults\n utils.fillIn(this, utils.copy(COLLECTION_DEFAULTS))\n\n if (!this.queryClass) {\n this.queryClass = Query\n }\n\n const idAttribute = this.recordId()\n\n Object.defineProperties(this, {\n /**\n * The main index, which uses @{link Collection#recordId} as the key.\n *\n * @name Collection#index\n * @type {Index}\n */\n index: {\n value: new Index([idAttribute], {\n hashCode (obj) {\n return utils.get(obj, idAttribute)\n }\n })\n },\n\n /**\n * Object that holds the secondary indexes of this collection.\n *\n * @name Collection#indexes\n * @type {Object.}\n */\n indexes: {\n value: {}\n }\n })\n\n // Insert initial data into the collection\n if (utils.isObject(records) || (utils.isArray(records) && records.length)) {\n this.add(records)\n }\n}\n\nexport default Component.extend({\n constructor: Collection,\n\n /**\n * Used to bind to events emitted by records in this Collection.\n *\n * @method Collection#_onRecordEvent\n * @since 3.0.0\n * @private\n * @param {...*} [arg] Args passed to {@link Collection#emit}.\n */\n _onRecordEvent (...args) {\n if (this.emitRecordEvents) {\n this.emit(...args)\n }\n },\n\n /**\n * Insert the provided record or records.\n *\n * If a record is already in the collection then the provided record will\n * either merge with or replace the existing record based on the value of the\n * `onConflict` option.\n *\n * The collection's secondary indexes will be updated as each record is\n * visited.\n *\n * @method Collection#add\n * @since 3.0.0\n * @param {(Object|Object[]|Record|Record[])} data The record or records to insert.\n * @param {object} [opts] Configuration options.\n * @param {boolean} [opts.commitOnMerge=true] See {@link Collection#commitOnMerge}.\n * @param {boolean} [opts.noValidate] See {@link Record#noValidate}.\n * @param {string} [opts.onConflict] See {@link Collection#onConflict}.\n * @returns {(Object|Object[]|Record|Record[])} The added record or records.\n */\n add (records, opts) {\n // Default values for arguments\n opts || (opts = {})\n\n // Fill in \"opts\" with the Collection's configuration\n utils._(opts, this)\n records = this.beforeAdd(records, opts) || records\n\n // Track whether just one record or an array of records is being inserted\n let singular = false\n const idAttribute = this.recordId()\n if (!utils.isArray(records)) {\n if (utils.isObject(records)) {\n records = [records]\n singular = true\n } else {\n throw utils.err(`${DOMAIN}#add`, 'records')(\n 400,\n 'object or array',\n records\n )\n }\n }\n\n // Map the provided records to existing records.\n // New records will be inserted. If any records map to existing records,\n // they will be merged into the existing records according to the onConflict\n // option.\n records = records.map(record => {\n const id = this.recordId(record)\n // Grab existing record if there is one\n const existing = id === undefined ? id : this.get(id)\n // If the currently visited record is just a reference to an existing\n // record, then there is nothing to be done. Exit early.\n if (record === existing) {\n return existing\n }\n\n if (existing) {\n // Here, the currently visited record corresponds to a record already\n // in the collection, so we need to merge them\n const onConflict = opts.onConflict || this.onConflict\n if (\n onConflict !== 'merge' &&\n onConflict !== 'replace' &&\n onConflict !== 'skip'\n ) {\n throw utils.err(`${DOMAIN}#add`, 'opts.onConflict')(\n 400,\n 'one of (merge, replace, skip)',\n onConflict,\n true\n )\n }\n const existingNoValidate = existing._get(noValidatePath)\n if (opts.noValidate) {\n // Disable validation\n existing._set(noValidatePath, true)\n }\n if (onConflict === 'merge') {\n utils.deepMixIn(existing, record)\n } else if (onConflict === 'replace') {\n utils.forOwn(existing, (value, key) => {\n if (key !== idAttribute && record[key] === undefined) {\n existing[key] = undefined\n }\n })\n existing.set(record)\n } // else if(onConflict === 'skip'){ do nothing }\n\n if (opts.noValidate) {\n // Restore previous `noValidate` value\n existing._set(noValidatePath, existingNoValidate)\n }\n record = existing\n if (opts.commitOnMerge && utils.isFunction(record.commit)) {\n record.commit()\n }\n // Update all indexes in the collection\n this.updateIndexes(record)\n } else {\n // Here, the currently visted record does not correspond to any record\n // in the collection, so (optionally) instantiate this record and insert\n // it into the collection\n record = this.mapper ? this.mapper.createRecord(record, opts) : record\n this.index.insertRecord(record)\n utils.forOwn(this.indexes, function (index, name) {\n index.insertRecord(record)\n })\n if (record && utils.isFunction(record.on)) {\n record.on('all', this._onRecordEvent, this)\n }\n }\n return record\n })\n // Finally, return the inserted data\n const result = singular ? records[0] : records\n if (!opts.silent) {\n this.emit('add', result)\n }\n return this.afterAdd(records, opts, result) || result\n },\n\n /**\n * Lifecycle hook called by {@link Collection#add}. If this method returns a\n * value then {@link Collection#add} will return that same value.\n *\n * @method Collection#method\n * @since 3.0.0\n * @param {(Object|Object[]|Record|Record[])} result The record or records\n * that were added to this Collection by {@link Collection#add}.\n * @param {object} opts The `opts` argument passed to {@link Collection#add}.\n */\n afterAdd () {},\n\n /**\n * Lifecycle hook called by {@link Collection#remove}. If this method returns\n * a value then {@link Collection#remove} will return that same value.\n *\n * @method Collection#afterRemove\n * @since 3.0.0\n * @param {(string|number)} id The `id` argument passed to {@link Collection#remove}.\n * @param {object} opts The `opts` argument passed to {@link Collection#remove}.\n * @param {object} record The result that will be returned by {@link Collection#remove}.\n */\n afterRemove () {},\n\n /**\n * Lifecycle hook called by {@link Collection#removeAll}. If this method\n * returns a value then {@link Collection#removeAll} will return that same\n * value.\n *\n * @method Collection#afterRemoveAll\n * @since 3.0.0\n * @param {object} query The `query` argument passed to {@link Collection#removeAll}.\n * @param {object} opts The `opts` argument passed to {@link Collection#removeAll}.\n * @param {object} records The result that will be returned by {@link Collection#removeAll}.\n */\n afterRemoveAll () {},\n\n /**\n * Lifecycle hook called by {@link Collection#add}. If this method returns a\n * value then the `records` argument in {@link Collection#add} will be\n * re-assigned to the returned value.\n *\n * @method Collection#beforeAdd\n * @since 3.0.0\n * @param {(Object|Object[]|Record|Record[])} records The `records` argument passed to {@link Collection#add}.\n * @param {object} opts The `opts` argument passed to {@link Collection#add}.\n */\n beforeAdd () {},\n\n /**\n * Lifecycle hook called by {@link Collection#remove}.\n *\n * @method Collection#beforeRemove\n * @since 3.0.0\n * @param {(string|number)} id The `id` argument passed to {@link Collection#remove}.\n * @param {object} opts The `opts` argument passed to {@link Collection#remove}.\n */\n beforeRemove () {},\n\n /**\n * Lifecycle hook called by {@link Collection#removeAll}.\n *\n * @method Collection#beforeRemoveAll\n * @since 3.0.0\n * @param {object} query The `query` argument passed to {@link Collection#removeAll}.\n * @param {object} opts The `opts` argument passed to {@link Collection#removeAll}.\n */\n beforeRemoveAll () {},\n\n /**\n * Find all records between two boundaries.\n *\n * Shortcut for `collection.query().between(18, 30, { index: 'age' }).run()`\n *\n * @example\n * // Get all users ages 18 to 30\n * const users = collection.between(18, 30, { index: 'age' });\n *\n * @example\n * // Same as above\n * const users = collection.between([18], [30], { index: 'age' });\n *\n * @method Collection#between\n * @since 3.0.0\n * @param {array} leftKeys Keys defining the left boundary.\n * @param {array} rightKeys Keys defining the right boundary.\n * @param {object} [opts] Configuration options.\n * @param {string} [opts.index] Name of the secondary index to use in the\n * query. If no index is specified, the main index is used.\n * @param {boolean} [opts.leftInclusive=true] Whether to include records\n * on the left boundary.\n * @param {boolean} [opts.rightInclusive=false] Whether to include records\n * on the left boundary.\n * @param {boolean} [opts.limit] Limit the result to a certain number.\n * @param {boolean} [opts.offset] The number of resulting records to skip.\n * @returns {Object[]|Record[]} The result.\n */\n between (leftKeys, rightKeys, opts) {\n return this.query()\n .between(leftKeys, rightKeys, opts)\n .run()\n },\n\n /**\n * Create a new secondary index on the contents of the collection.\n *\n * @example\n * // Index users by age\n * collection.createIndex('age');\n *\n * @example\n * // Index users by status and role\n * collection.createIndex('statusAndRole', ['status', 'role']);\n *\n * @method Collection#createIndex\n * @since 3.0.0\n * @param {string} name The name of the new secondary index.\n * @param {string[]} [fieldList] Array of field names to use as the key or\n * compound key of the new secondary index. If no fieldList is provided, then\n * the name will also be the field that is used to index the collection.\n */\n createIndex (name, fieldList, opts) {\n if (utils.isString(name) && fieldList === undefined) {\n fieldList = [name]\n }\n opts || (opts = {})\n opts.hashCode || (opts.hashCode = obj => this.recordId(obj))\n const index = (this.indexes[name] = new Index(fieldList, opts))\n this.index.visitAll(index.insertRecord, index)\n },\n\n /**\n * Find the record or records that match the provided query or pass the\n * provided filter function.\n *\n * Shortcut for `collection.query().filter(queryOrFn[, thisArg]).run()`\n *\n * @example Collection#filter\n * const JSData = require('js-data');\n * const { Collection } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const collection = new Collection([\n * { id: 1, status: 'draft', created_at_timestamp: new Date().getTime() }\n * ]);\n *\n * // Get the draft posts created less than three months ago\n * let posts = collection.filter({\n * where: {\n * status: {\n * '==': 'draft'\n * },\n * created_at_timestamp: {\n * '>=': (new Date().getTime() - (1000 \\* 60 \\* 60 \\* 24 \\* 30 \\* 3)) // 3 months ago\n * }\n * }\n * });\n * console.log(posts);\n *\n * // Use a custom filter function\n * posts = collection.filter((post) => post.id % 2 === 0);\n *\n * @method Collection#filter\n * @param {(Object|Function)} [queryOrFn={}] Selection query or filter\n * function.\n * @param {object} [thisArg] Context to which to bind `queryOrFn` if\n * `queryOrFn` is a function.\n * @returns {Array} The result.\n * @see query\n * @since 3.0.0\n */\n filter (query, thisArg) {\n return this.query()\n .filter(query, thisArg)\n .run()\n },\n\n /**\n * Iterate over all records.\n *\n * @example\n * collection.forEach(function (record) {\n * // do something\n * });\n *\n * @method Collection#forEach\n * @since 3.0.0\n * @param {Function} forEachFn Iteration function.\n * @param {*} [thisArg] Context to which to bind `forEachFn`.\n * @returns {Array} The result.\n */\n forEach (cb, thisArg) {\n this.index.visitAll(cb, thisArg)\n },\n\n /**\n * Get the record with the given id.\n *\n * @method Collection#get\n * @since 3.0.0\n * @param {(string|number)} id The primary key of the record to get.\n * @returns {(Object|Record)} The record with the given id.\n */\n get (id) {\n const instances =\n id === undefined\n ? []\n : this.query()\n .get(id)\n .run()\n return instances.length ? instances[0] : undefined\n },\n\n /**\n * Find the record or records that match the provided keyLists.\n *\n * Shortcut for `collection.query().getAll(keyList1, keyList2, ...).run()`\n *\n * @example\n * // Get the posts where \"status\" is \"draft\" or \"inReview\"\n * const posts = collection.getAll('draft', 'inReview', { index: 'status' });\n *\n * @example\n * // Same as above\n * const posts = collection.getAll(['draft'], ['inReview'], { index: 'status' });\n *\n * @method Collection#getAll\n * @since 3.0.0\n * @param {...Array} [keyList] Provide one or more keyLists, and all\n * records matching each keyList will be retrieved. If no keyLists are\n * provided, all records will be returned.\n * @param {object} [opts] Configuration options.\n * @param {string} [opts.index] Name of the secondary index to use in the\n * query. If no index is specified, the main index is used.\n * @returns {Array} The result.\n */\n getAll (...args) {\n return this.query()\n .getAll(...args)\n .run()\n },\n\n /**\n * Return the index with the given name. If no name is provided, return the\n * main index. Throws an error if the specified index does not exist.\n *\n * @method Collection#getIndex\n * @since 3.0.0\n * @param {string} [name] The name of the index to retrieve.\n */\n getIndex (name) {\n const index = name ? this.indexes[name] : this.index\n if (!index) {\n throw utils.err(`${DOMAIN}#getIndex`, name)(404, 'index')\n }\n return index\n },\n\n /**\n * Limit the result.\n *\n * Shortcut for `collection.query().limit(maximumNumber).run()`\n *\n * @example\n * const posts = collection.limit(10);\n *\n * @method Collection#limit\n * @since 3.0.0\n * @param {number} num The maximum number of records to keep in the result.\n * @returns {Array} The result.\n */\n limit (num) {\n return this.query()\n .limit(num)\n .run()\n },\n\n /**\n * Apply a mapping function to all records.\n *\n * @example\n * const names = collection.map((user) => user.name);\n *\n * @method Collection#map\n * @since 3.0.0\n * @param {Function} mapFn Mapping function.\n * @param {*} [thisArg] Context to which to bind `mapFn`.\n * @returns {Array} The result of the mapping.\n */\n map (cb, thisArg) {\n const data = []\n this.index.visitAll(function (value) {\n data.push(cb.call(thisArg, value))\n })\n return data\n },\n\n /**\n * Return the result of calling the specified function on each record in this\n * collection's main index.\n *\n * @method Collection#mapCall\n * @since 3.0.0\n * @param {string} funcName Name of function to call\n * @parama {...*} [args] Remaining arguments to be passed to the function.\n * @returns {Array} The result.\n */\n mapCall (funcName, ...args) {\n const data = []\n this.index.visitAll(function (record) {\n data.push(record[funcName](...args))\n })\n return data\n },\n\n /**\n * Return all \"unsaved\" (not uniquely identifiable) records in this colleciton.\n *\n * @method Collection#prune\n * @param {object} [opts] Configuration options, passed to {@link Collection#removeAll}.\n * @since 3.0.0\n * @returns {Array} The removed records, if any.\n */\n prune (opts) {\n return this.removeAll(this.unsaved(), opts)\n },\n\n /**\n * Create a new query to be executed against the contents of the collection.\n * The result will be all or a subset of the contents of the collection.\n *\n * @example\n * // Grab page 2 of users between ages 18 and 30\n * collection.query()\n * .between(18, 30, { index: 'age' }) // between ages 18 and 30\n * .skip(10) // second page\n * .limit(10) // page size\n * .run();\n *\n * @method Collection#query\n * @since 3.0.0\n * @returns {Query} New query object.\n */\n query () {\n const Ctor = this.queryClass\n return new Ctor(this)\n },\n\n /**\n * Return the primary key of the given, or if no record is provided, return the\n * name of the field that holds the primary key of records in this Collection.\n *\n * @method Collection#recordId\n * @since 3.0.0\n * @param {(Object|Record)} [record] The record whose primary key is to be\n * returned.\n * @returns {(string|number)} Primary key or name of field that holds primary\n * key.\n */\n recordId (record) {\n if (record) {\n return utils.get(record, this.recordId())\n }\n return this.mapper ? this.mapper.idAttribute : this.idAttribute\n },\n\n /**\n * Reduce the data in the collection to a single value and return the result.\n *\n * @example\n * const totalVotes = collection.reduce((prev, record) => {\n * return prev + record.upVotes + record.downVotes;\n * }, 0);\n *\n * @method Collection#reduce\n * @since 3.0.0\n * @param {Function} cb Reduction callback.\n * @param {*} initialValue Initial value of the reduction.\n * @returns {*} The result.\n */\n reduce (cb, initialValue) {\n const data = this.getAll()\n return data.reduce(cb, initialValue)\n },\n\n /**\n * Remove the record with the given id from this Collection.\n *\n * @method Collection#remove\n * @since 3.0.0\n * @param {(string|number|object|Record)} idOrRecord The primary key of the\n * record to be removed, or a reference to the record that is to be removed.\n * @param {object} [opts] Configuration options.\n * @returns {Object|Record} The removed record, if any.\n */\n remove (idOrRecord, opts) {\n // Default values for arguments\n opts || (opts = {})\n this.beforeRemove(idOrRecord, opts)\n let record = utils.isSorN(idOrRecord) ? this.get(idOrRecord) : idOrRecord\n\n // The record is in the collection, remove it\n if (utils.isObject(record)) {\n record = this.index.removeRecord(record)\n if (record) {\n utils.forOwn(this.indexes, function (index, name) {\n index.removeRecord(record)\n })\n if (utils.isFunction(record.off)) {\n record.off('all', this._onRecordEvent, this)\n }\n if (!opts.silent) {\n this.emit('remove', record)\n }\n }\n }\n return this.afterRemove(idOrRecord, opts, record) || record\n },\n\n /**\n * Remove from this collection the given records or the records selected by\n * the given \"query\".\n *\n * @method Collection#removeAll\n * @since 3.0.0\n * @param {Object|Object[]|Record[]} [queryOrRecords={}] Records to be removed or selection query. See {@link query}.\n * @param {object} [queryOrRecords.where] See {@link query.where}.\n * @param {number} [queryOrRecords.offset] See {@link query.offset}.\n * @param {number} [queryOrRecords.limit] See {@link query.limit}.\n * @param {string|Array[]} [queryOrRecords.orderBy] See {@link query.orderBy}.\n * @param {object} [opts] Configuration options.\n * @returns {(Object[]|Record[])} The removed records, if any.\n */\n removeAll (queryOrRecords, opts) {\n // Default values for arguments\n opts || (opts = {})\n this.beforeRemoveAll(queryOrRecords, opts)\n let records = utils.isArray(queryOrRecords)\n ? queryOrRecords.slice()\n : this.filter(queryOrRecords)\n\n // Remove each selected record from the collection\n const optsCopy = utils.plainCopy(opts)\n optsCopy.silent = true\n records = records\n .map(record => this.remove(record, optsCopy))\n .filter(record => record)\n if (!opts.silent) {\n this.emit('remove', records)\n }\n return this.afterRemoveAll(queryOrRecords, opts, records) || records\n },\n\n /**\n * Skip a number of results.\n *\n * Shortcut for `collection.query().skip(numberToSkip).run()`\n *\n * @example\n * const posts = collection.skip(10);\n *\n * @method Collection#skip\n * @since 3.0.0\n * @param {number} num The number of records to skip.\n * @returns {Array} The result.\n */\n skip (num) {\n return this.query()\n .skip(num)\n .run()\n },\n\n /**\n * Return the plain JSON representation of all items in this collection.\n * Assumes records in this collection have a toJSON method.\n *\n * @method Collection#toJSON\n * @since 3.0.0\n * @param {object} [opts] Configuration options.\n * @param {string[]} [opts.with] Array of relation names or relation fields\n * to include in the representation.\n * @returns {Array} The records.\n */\n toJSON (opts) {\n return this.mapCall('toJSON', opts)\n },\n\n /**\n * Return all \"unsaved\" (not uniquely identifiable) records in this colleciton.\n *\n * @method Collection#unsaved\n * @since 3.0.0\n * @returns {Array} The unsaved records, if any.\n */\n unsaved (opts) {\n return this.index.get()\n },\n\n /**\n * Update a record's position in a single index of this collection. See\n * {@link Collection#updateIndexes} to update a record's position in all\n * indexes at once.\n *\n * @method Collection#updateIndex\n * @since 3.0.0\n * @param {object} record The record to update.\n * @param {object} [opts] Configuration options.\n * @param {string} [opts.index] The index in which to update the record's\n * position. If you don't specify an index then the record will be updated\n * in the main index.\n */\n updateIndex (record, opts) {\n opts || (opts = {})\n this.getIndex(opts.index).updateRecord(record)\n },\n\n /**\n * Updates all indexes in this collection for the provided record. Has no\n * effect if the record is not in the collection.\n *\n * @method Collection#updateIndexes\n * @since 3.0.0\n * @param {object} record TODO\n */\n updateIndexes (record) {\n this.index.updateRecord(record)\n utils.forOwn(this.indexes, function (index, name) {\n index.updateRecord(record)\n })\n }\n})\n\n/**\n * Fired when a record changes. Only works for records that have tracked changes.\n * See {@link Collection~changeListener} on how to listen for this event.\n *\n * @event Collection#change\n * @see Collection~changeListener\n */\n\n/**\n * Callback signature for the {@link Collection#event:change} event.\n *\n * @example\n * function onChange (record, changes) {\n * // do something\n * }\n * collection.on('change', onChange);\n *\n * @callback Collection~changeListener\n * @param {Record} The Record that changed.\n * @param {object} The changes.\n * @see Collection#event:change\n * @since 3.0.0\n */\n\n/**\n * Fired when one or more records are added to the Collection. See\n * {@link Collection~addListener} on how to listen for this event.\n *\n * @event Collection#add\n * @see Collection~addListener\n * @see Collection#event:add\n * @see Collection#add\n */\n\n/**\n * Callback signature for the {@link Collection#event:add} event.\n *\n * @example\n * function onAdd (recordOrRecords) {\n * // do something\n * }\n * collection.on('add', onAdd);\n *\n * @callback Collection~addListener\n * @param {Record|Record[]} The Record or Records that were added.\n * @see Collection#event:add\n * @see Collection#add\n * @since 3.0.0\n */\n\n/**\n * Fired when one or more records are removed from the Collection. See\n * {@link Collection~removeListener} for how to listen for this event.\n *\n * @event Collection#remove\n * @see Collection~removeListener\n * @see Collection#event:remove\n * @see Collection#remove\n * @see Collection#removeAll\n */\n\n/**\n * Callback signature for the {@link Collection#event:remove} event.\n *\n * @example\n * function onRemove (recordsOrRecords) {\n * // do something\n * }\n * collection.on('remove', onRemove);\n *\n * @callback Collection~removeListener\n * @param {Record|Record[]} Record or Records that were removed.\n * @see Collection#event:remove\n * @see Collection#remove\n * @see Collection#removeAll\n * @since 3.0.0\n */\n\n/**\n * Create a subclass of this Collection:\n * @example Collection.extend\n * const JSData = require('js-data');\n * const { Collection } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * // Extend the class using ES2015 class syntax.\n * class CustomCollectionClass extends Collection {\n * foo () { return 'bar'; }\n * static beep () { return 'boop'; }\n * }\n * const customCollection = new CustomCollectionClass();\n * console.log(customCollection.foo());\n * console.log(CustomCollectionClass.beep());\n *\n * // Extend the class using alternate method.\n * const OtherCollectionClass = Collection.extend({\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * });\n * const otherCollection = new OtherCollectionClass();\n * console.log(otherCollection.foo());\n * console.log(OtherCollectionClass.beep());\n *\n * // Extend the class, providing a custom constructor.\n * function AnotherCollectionClass () {\n * Collection.call(this);\n * this.created_at = new Date().getTime();\n * }\n * Collection.extend({\n * constructor: AnotherCollectionClass,\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * });\n * const anotherCollection = new AnotherCollectionClass();\n * console.log(anotherCollection.created_at);\n * console.log(anotherCollection.foo());\n * console.log(AnotherCollectionClass.beep());\n *\n * @method Collection.extend\n * @param {object} [props={}] Properties to add to the prototype of the\n * subclass.\n * @param {object} [props.constructor] Provide a custom constructor function\n * to be used as the subclass itself.\n * @param {object} [classProps={}] Static properties to add to the subclass.\n * @returns {Constructor} Subclass of this Collection class.\n * @since 3.0.0\n */\n","import utils from './utils'\nimport Component from './Component'\n\nconst DOMAIN = 'Schema'\n\n/**\n * A function map for each of the seven primitive JSON types defined by the core specification.\n * Each function will check a given value and return true or false if the value is an instance of that type.\n * ```\n * types.integer(1) // returns true\n * types.string({}) // returns false\n * ```\n * http://json-schema.org/latest/json-schema-core.html#anchor8\n * @name Schema.types\n * @type {object}\n */\nconst types = {\n array: utils.isArray,\n boolean: utils.isBoolean,\n integer: utils.isInteger,\n null: utils.isNull,\n number: utils.isNumber,\n object: utils.isObject,\n string: utils.isString\n}\n\n/**\n * @ignore\n */\nconst segmentToString = function (segment, prev) {\n let str = ''\n if (segment) {\n if (utils.isNumber(segment)) {\n str += `[${segment}]`\n } else if (prev) {\n str += `.${segment}`\n } else {\n str += `${segment}`\n }\n }\n return str\n}\n\n/**\n * @ignore\n */\nconst makePath = function (opts) {\n opts || (opts = {})\n let path = ''\n const segments = opts.path || []\n segments.forEach(function (segment) {\n path += segmentToString(segment, path)\n })\n path += segmentToString(opts.prop, path)\n return path\n}\n\n/**\n * @ignore\n */\nconst makeError = function (actual, expected, opts) {\n return {\n expected,\n actual: '' + actual,\n path: makePath(opts)\n }\n}\n\n/**\n * @ignore\n */\nconst addError = function (actual, expected, opts, errors) {\n errors.push(makeError(actual, expected, opts))\n}\n\n/**\n * @ignore\n */\nconst maxLengthCommon = function (keyword, value, schema, opts) {\n const max = schema[keyword]\n if (value.length > max) {\n return makeError(value.length, `length no more than ${max}`, opts)\n }\n}\n\n/**\n * @ignore\n */\nconst minLengthCommon = function (keyword, value, schema, opts) {\n const min = schema[keyword]\n if (value.length < min) {\n return makeError(value.length, `length no less than ${min}`, opts)\n }\n}\n\n/**\n * A map of all object member validation functions for each keyword defined in the JSON Schema.\n * @name Schema.validationKeywords\n * @type {object}\n */\nconst validationKeywords = {\n /**\n * Validates the provided value against all schemas defined in the Schemas `allOf` keyword.\n * The instance is valid against if and only if it is valid against all the schemas declared in the Schema's value.\n *\n * The value of this keyword MUST be an array. This array MUST have at least one element.\n * Each element of this array MUST be a valid JSON Schema.\n *\n * see http://json-schema.org/latest/json-schema-validation.html#anchor82\n *\n * @name Schema.validationKeywords.allOf\n * @method\n * @param {*} value Value to be validated.\n * @param {object} schema Schema containing the `allOf` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n allOf (value, schema, opts) {\n let allErrors = []\n schema.allOf.forEach(function (_schema) {\n allErrors = allErrors.concat(validate(value, _schema, opts) || [])\n })\n return allErrors.length ? allErrors : undefined\n },\n\n /**\n * Validates the provided value against all schemas defined in the Schemas `anyOf` keyword.\n * The instance is valid against this keyword if and only if it is valid against\n * at least one of the schemas in this keyword's value.\n *\n * The value of this keyword MUST be an array. This array MUST have at least one element.\n * Each element of this array MUST be an object, and each object MUST be a valid JSON Schema.\n * see http://json-schema.org/latest/json-schema-validation.html#anchor85\n *\n * @name Schema.validationKeywords.anyOf\n * @method\n * @param {*} value Value to be validated.\n * @param {object} schema Schema containing the `anyOf` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n anyOf (value, schema, opts) {\n let validated = false\n let allErrors = []\n schema.anyOf.forEach(function (_schema) {\n const errors = validate(value, _schema, opts)\n if (errors) {\n allErrors = allErrors.concat(errors)\n } else {\n validated = true\n }\n })\n return validated ? undefined : allErrors\n },\n\n /**\n * http://json-schema.org/latest/json-schema-validation.html#anchor70\n *\n * @name Schema.validationKeywords.dependencies\n * @method\n * @param {*} value TODO\n * @param {object} schema TODO\n * @param {object} opts TODO\n */\n dependencies (value, schema, opts) {\n // TODO\n },\n\n /**\n * Validates the provided value against an array of possible values defined by the Schema's `enum` keyword\n * Validation succeeds if the value is deeply equal to one of the values in the array.\n * see http://json-schema.org/latest/json-schema-validation.html#anchor76\n *\n * @name Schema.validationKeywords.enum\n * @method\n * @param {*} value Value to validate\n * @param {object} schema Schema containing the `enum` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n enum (value, schema, opts) {\n const possibleValues = schema.enum\n if (utils.findIndex(possibleValues, (item) => utils.deepEqual(item, value)) === -1) {\n return makeError(value, `one of (${possibleValues.join(', ')})`, opts)\n }\n },\n\n /**\n * Validates each of the provided array values against a schema or an array of schemas defined by the Schema's `items` keyword\n * see http://json-schema.org/latest/json-schema-validation.html#anchor37 for validation rules.\n *\n * @name Schema.validationKeywords.items\n * @method\n * @param {*} value Array to be validated.\n * @param {object} schema Schema containing the items keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n items (value, schema, opts) {\n opts || (opts = {})\n // TODO: additionalItems\n let items = schema.items\n let errors = []\n const checkingTuple = utils.isArray(items)\n const length = value.length\n for (var prop = 0; prop < length; prop++) {\n if (checkingTuple) {\n // Validating a tuple, instead of just checking each item against the\n // same schema\n items = schema.items[prop]\n }\n opts.prop = prop\n errors = errors.concat(validate(value[prop], items, opts) || [])\n }\n return errors.length ? errors : undefined\n },\n\n /**\n * Validates the provided number against a maximum value defined by the Schema's `maximum` keyword\n * Validation succeeds if the value is a number, and is less than, or equal to, the value of this keyword.\n * http://json-schema.org/latest/json-schema-validation.html#anchor17\n *\n * @name Schema.validationKeywords.maximum\n * @method\n * @param {*} value Number to validate against the keyword.\n * @param {object} schema Schema containing the `maximum` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n maximum (value, schema, opts) {\n // Must be a number\n const maximum = schema.maximum\n // Must be a boolean\n // Depends on maximum\n // default: false\n const exclusiveMaximum = schema.exclusiveMaximum\n if (typeof value === typeof maximum && !(exclusiveMaximum ? maximum > value : maximum >= value)) {\n return exclusiveMaximum\n ? makeError(value, `no more than nor equal to ${maximum}`, opts)\n : makeError(value, `no more than ${maximum}`, opts)\n }\n },\n\n /**\n * Validates the length of the provided array against a maximum value defined by the Schema's `maxItems` keyword.\n * Validation succeeds if the length of the array is less than, or equal to the value of this keyword.\n * see http://json-schema.org/latest/json-schema-validation.html#anchor42\n *\n * @name Schema.validationKeywords.maxItems\n * @method\n * @param {*} value Array to be validated.\n * @param {object} schema Schema containing the `maxItems` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n maxItems (value, schema, opts) {\n if (utils.isArray(value)) {\n return maxLengthCommon('maxItems', value, schema, opts)\n }\n },\n\n /**\n * Validates the length of the provided string against a maximum value defined in the Schema's `maxLength` keyword.\n * Validation succeeds if the length of the string is less than, or equal to the value of this keyword.\n * see http://json-schema.org/latest/json-schema-validation.html#anchor26\n *\n * @name Schema.validationKeywords.maxLength\n * @method\n * @param {*} value String to be validated.\n * @param {object} schema Schema containing the `maxLength` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n maxLength (value, schema, opts) {\n return maxLengthCommon('maxLength', value, schema, opts)\n },\n\n /**\n * Validates the count of the provided object's properties against a maximum value defined in the Schema's `maxProperties` keyword.\n * Validation succeeds if the object's property count is less than, or equal to the value of this keyword.\n * see http://json-schema.org/latest/json-schema-validation.html#anchor54\n *\n * @name Schema.validationKeywords.maxProperties\n * @method\n * @param {*} value Object to be validated.\n * @param {object} schema Schema containing the `maxProperties` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n maxProperties (value, schema, opts) {\n // validate only objects\n if (!utils.isObject(value)) return\n const maxProperties = schema.maxProperties\n const length = Object.keys(value).length\n if (length > maxProperties) {\n return makeError(length, `no more than ${maxProperties} properties`, opts)\n }\n },\n\n /**\n * Validates the provided value against a minimum value defined by the Schema's `minimum` keyword\n * Validation succeeds if the value is a number and is greater than, or equal to, the value of this keyword.\n * http://json-schema.org/latest/json-schema-validation.html#anchor21\n *\n * @name Schema.validationKeywords.minimum\n * @method\n * @param {*} value Number to validate against the keyword.\n * @param {object} schema Schema containing the `minimum` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n minimum (value, schema, opts) {\n // Must be a number\n const minimum = schema.minimum\n // Must be a boolean\n // Depends on minimum\n // default: false\n const exclusiveMinimum = schema.exclusiveMinimum\n if (typeof value === typeof minimum && !(exclusiveMinimum ? value > minimum : value >= minimum)) {\n return exclusiveMinimum\n ? makeError(value, `no less than nor equal to ${minimum}`, opts)\n : makeError(value, `no less than ${minimum}`, opts)\n }\n },\n\n /**\n * Validates the length of the provided array against a minimum value defined by the Schema's `minItems` keyword.\n * Validation succeeds if the length of the array is greater than, or equal to the value of this keyword.\n * see http://json-schema.org/latest/json-schema-validation.html#anchor45\n *\n * @name Schema.validationKeywords.minItems\n * @method\n * @param {*} value Array to be validated.\n * @param {object} schema Schema containing the `minItems` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n minItems (value, schema, opts) {\n if (utils.isArray(value)) {\n return minLengthCommon('minItems', value, schema, opts)\n }\n },\n\n /**\n * Validates the length of the provided string against a minimum value defined in the Schema's `minLength` keyword.\n * Validation succeeds if the length of the string is greater than, or equal to the value of this keyword.\n * see http://json-schema.org/latest/json-schema-validation.html#anchor29\n *\n * @name Schema.validationKeywords.minLength\n * @method\n * @param {*} value String to be validated.\n * @param {object} schema Schema containing the `minLength` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n minLength (value, schema, opts) {\n return minLengthCommon('minLength', value, schema, opts)\n },\n\n /**\n * Validates the count of the provided object's properties against a minimum value defined in the Schema's `minProperties` keyword.\n * Validation succeeds if the object's property count is greater than, or equal to the value of this keyword.\n * see http://json-schema.org/latest/json-schema-validation.html#anchor57\n *\n * @name Schema.validationKeywords.minProperties\n * @method\n * @param {*} value Object to be validated.\n * @param {object} schema Schema containing the `minProperties` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n minProperties (value, schema, opts) {\n // validate only objects\n if (!utils.isObject(value)) return\n const minProperties = schema.minProperties\n const length = Object.keys(value).length\n if (length < minProperties) {\n return makeError(length, `no more than ${minProperties} properties`, opts)\n }\n },\n\n /**\n * Validates the provided number is a multiple of the number defined in the Schema's `multipleOf` keyword.\n * Validation succeeds if the number can be divided equally into the value of this keyword.\n * see http://json-schema.org/latest/json-schema-validation.html#anchor14\n *\n * @name Schema.validationKeywords.multipleOf\n * @method\n * @param {*} value Number to be validated.\n * @param {object} schema Schema containing the `multipleOf` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n multipleOf (value, schema, opts) {\n const multipleOf = schema.multipleOf\n if (utils.isNumber(value)) {\n if ((value / multipleOf) % 1 !== 0) {\n return makeError(value, `multipleOf ${multipleOf}`, opts)\n }\n }\n },\n\n /**\n * Validates the provided value is not valid with any of the schemas defined in the Schema's `not` keyword.\n * An instance is valid against this keyword if and only if it is NOT valid against the schemas in this keyword's value.\n *\n * see http://json-schema.org/latest/json-schema-validation.html#anchor91\n * @name Schema.validationKeywords.not\n * @method\n * @param {*} value to be checked.\n * @param {object} schema Schema containing the not keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n not (value, schema, opts) {\n if (!validate(value, schema.not, opts)) {\n // TODO: better messaging\n return makeError('succeeded', 'should have failed', opts)\n }\n },\n\n /**\n * Validates the provided value is valid with one and only one of the schemas defined in the Schema's `oneOf` keyword.\n * An instance is valid against this keyword if and only if it is valid against a single schemas in this keyword's value.\n *\n * see http://json-schema.org/latest/json-schema-validation.html#anchor88\n * @name Schema.validationKeywords.oneOf\n * @method\n * @param {*} value to be checked.\n * @param {object} schema Schema containing the `oneOf` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n oneOf (value, schema, opts) {\n let validated = false\n let allErrors = []\n schema.oneOf.forEach(function (_schema) {\n const errors = validate(value, _schema, opts)\n if (errors) {\n allErrors = allErrors.concat(errors)\n } else if (validated) {\n allErrors = [makeError('valid against more than one', 'valid against only one', opts)]\n validated = false\n return false\n } else {\n validated = true\n }\n })\n return validated ? undefined : allErrors\n },\n\n /**\n * Validates the provided string matches a pattern defined in the Schema's `pattern` keyword.\n * Validation succeeds if the string is a match of the regex value of this keyword.\n *\n * see http://json-schema.org/latest/json-schema-validation.html#anchor33\n * @name Schema.validationKeywords.pattern\n * @method\n * @param {*} value String to be validated.\n * @param {object} schema Schema containing the `pattern` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n pattern (value, schema, opts) {\n const pattern = schema.pattern\n if (utils.isString(value) && !value.match(pattern)) {\n return makeError(value, pattern, opts)\n }\n },\n\n /**\n * Validates the provided object's properties against a map of values defined in the Schema's `properties` keyword.\n * Validation succeeds if the object's property are valid with each of the schema's in the provided map.\n * Validation also depends on the additionalProperties and or patternProperties.\n *\n * see http://json-schema.org/latest/json-schema-validation.html#anchor64 for more info.\n *\n * @name Schema.validationKeywords.properties\n * @method\n * @param {*} value Object to be validated.\n * @param {object} schema Schema containing the `properties` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n properties (value, schema, opts) {\n opts || (opts = {})\n\n if (utils.isArray(value)) {\n return\n }\n\n // Can be a boolean or an object\n // Technically the default is an \"empty schema\", but here \"true\" is\n // functionally the same\n const additionalProperties = schema.additionalProperties === undefined ? true : schema.additionalProperties\n const validated = []\n // \"p\": The property set from \"properties\".\n // Default is an object\n const properties = schema.properties || {}\n // \"pp\": The property set from \"patternProperties\".\n // Default is an object\n const patternProperties = schema.patternProperties || {}\n let errors = []\n\n utils.forOwn(properties, function (_schema, prop) {\n opts.prop = prop\n errors = errors.concat(validate(value[prop], _schema, opts) || [])\n validated.push(prop)\n })\n\n const toValidate = utils.omit(value, validated)\n utils.forOwn(patternProperties, function (_schema, pattern) {\n utils.forOwn(toValidate, function (undef, prop) {\n if (prop.match(pattern)) {\n opts.prop = prop\n errors = errors.concat(validate(value[prop], _schema, opts) || [])\n validated.push(prop)\n }\n })\n })\n const keys = Object.keys(utils.omit(value, validated))\n // If \"s\" is not empty, validation fails\n if (additionalProperties === false) {\n if (keys.length) {\n const origProp = opts.prop\n opts.prop = ''\n addError(`extra fields: ${keys.join(', ')}`, 'no extra fields', opts, errors)\n opts.prop = origProp\n }\n } else if (utils.isObject(additionalProperties)) {\n // Otherwise, validate according to provided schema\n keys.forEach(function (prop) {\n opts.prop = prop\n errors = errors.concat(validate(value[prop], additionalProperties, opts) || [])\n })\n }\n return errors.length ? errors : undefined\n },\n\n /**\n * Validates the provided object's has all properties listed in the Schema's `properties` keyword array.\n * Validation succeeds if the object contains all properties provided in the array value of this keyword.\n * see http://json-schema.org/latest/json-schema-validation.html#anchor61\n *\n * @name Schema.validationKeywords.required\n * @method\n * @param {*} value Object to be validated.\n * @param {object} schema Schema containing the `required` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n required (value, schema, opts) {\n opts || (opts = {})\n const required = schema.required\n const errors = []\n if (!opts.existingOnly) {\n required.forEach(function (prop) {\n if (utils.get(value, prop) === undefined) {\n const prevProp = opts.prop\n opts.prop = prop\n addError(undefined, 'a value', opts, errors)\n opts.prop = prevProp\n }\n })\n }\n return errors.length ? errors : undefined\n },\n\n /**\n * Validates the provided value's type is equal to the type, or array of types, defined in the Schema's `type` keyword.\n * see http://json-schema.org/latest/json-schema-validation.html#anchor79\n *\n * @name Schema.validationKeywords.type\n * @method\n * @param {*} value Value to be validated.\n * @param {object} schema Schema containing the `type` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n type (value, schema, opts) {\n let type = schema.type\n let validType\n // Can be one of several types\n if (utils.isString(type)) {\n type = [type]\n }\n // Try to match the value against an expected type\n type.forEach(function (_type) {\n // TODO: throw an error if type is not defined\n if (types[_type](value, schema, opts)) {\n // Matched a type\n validType = _type\n return false\n }\n })\n // Value did not match any expected type\n if (!validType) {\n return makeError(value !== undefined && value !== null ? typeof value : '' + value, `one of (${type.join(', ')})`, opts)\n }\n // Run keyword validators for matched type\n // http://json-schema.org/latest/json-schema-validation.html#anchor12\n const validator = typeGroupValidators[validType]\n if (validator) {\n return validator(value, schema, opts)\n }\n },\n\n /**\n * Validates the provided array values are unique.\n * Validation succeeds if the items in the array are unique, but only if the value of this keyword is true\n * see http://json-schema.org/latest/json-schema-validation.html#anchor49\n *\n * @name Schema.validationKeywords.uniqueItems\n * @method\n * @param {*} value Array to be validated.\n * @param {object} schema Schema containing the `uniqueItems` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n uniqueItems (value, schema, opts) {\n if (value && value.length && schema.uniqueItems) {\n const length = value.length\n let item, i, j\n // Check n - 1 items\n for (i = length - 1; i > 0; i--) {\n item = value[i]\n // Only compare against unchecked items\n for (j = i - 1; j >= 0; j--) {\n // Found a duplicate\n if (utils.deepEqual(item, value[j])) {\n return makeError(item, 'no duplicates', opts)\n }\n }\n }\n }\n }\n}\n\n/**\n * @ignore\n */\nconst runOps = function (ops, value, schema, opts) {\n let errors = []\n ops.forEach(function (op) {\n if (schema[op] !== undefined) {\n errors = errors.concat(validationKeywords[op](value, schema, opts) || [])\n }\n })\n return errors.length ? errors : undefined\n}\n\n/**\n * Validation keywords validated for any type:\n *\n * - `enum`\n * - `type`\n * - `allOf`\n * - `anyOf`\n * - `oneOf`\n * - `not`\n *\n * @name Schema.ANY_OPS\n * @type {string[]}\n */\nconst ANY_OPS = ['enum', 'type', 'allOf', 'anyOf', 'oneOf', 'not']\n\n/**\n * Validation keywords validated for array types:\n *\n * - `items`\n * - `maxItems`\n * - `minItems`\n * - `uniqueItems`\n *\n * @name Schema.ARRAY_OPS\n * @type {string[]}\n */\nconst ARRAY_OPS = ['items', 'maxItems', 'minItems', 'uniqueItems']\n\n/**\n * Validation keywords validated for numeric (number and integer) types:\n *\n * - `multipleOf`\n * - `maximum`\n * - `minimum`\n *\n * @name Schema.NUMERIC_OPS\n * @type {string[]}\n */\nconst NUMERIC_OPS = ['multipleOf', 'maximum', 'minimum']\n\n/**\n * Validation keywords validated for object types:\n *\n * - `maxProperties`\n * - `minProperties`\n * - `required`\n * - `properties`\n * - `dependencies`\n *\n * @name Schema.OBJECT_OPS\n * @type {string[]}\n */\nconst OBJECT_OPS = ['maxProperties', 'minProperties', 'required', 'properties', 'dependencies']\n\n/**\n * Validation keywords validated for string types:\n *\n * - `maxLength`\n * - `minLength`\n * - `pattern`\n *\n * @name Schema.STRING_OPS\n * @type {string[]}\n */\nconst STRING_OPS = ['maxLength', 'minLength', 'pattern']\n\n/**\n * http://json-schema.org/latest/json-schema-validation.html#anchor75\n * @ignore\n */\nconst validateAny = function (value, schema, opts) {\n return runOps(ANY_OPS, value, schema, opts)\n}\n\n/**\n * Validates the provided value against a given Schema according to the http://json-schema.org/ v4 specification.\n *\n * @name Schema.validate\n * @method\n * @param {*} value Value to be validated.\n * @param {object} schema Valid Schema according to the http://json-schema.org/ v4 specification.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\nconst validate = function (value, schema, opts) {\n let errors = []\n opts || (opts = {})\n opts.ctx || (opts.ctx = { value, schema })\n let shouldPop\n const prevProp = opts.prop\n if (schema === undefined) {\n return\n }\n if (!utils.isObject(schema)) {\n throw utils.err(`${DOMAIN}#validate`)(500, `Invalid schema at path: \"${opts.path}\"`)\n }\n if (opts.path === undefined) {\n opts.path = []\n }\n // Track our location as we recurse\n if (opts.prop !== undefined) {\n shouldPop = true\n opts.path.push(opts.prop)\n opts.prop = undefined\n }\n // Validate against parent schema\n if (schema.extends) {\n // opts.path = path\n // opts.prop = prop\n if (utils.isFunction(schema.extends.validate)) {\n errors = errors.concat(schema.extends.validate(value, opts) || [])\n } else {\n errors = errors.concat(validate(value, schema.extends, opts) || [])\n }\n }\n if (value === undefined) {\n // Check if property is required\n if (schema.required === true && !opts.existingOnly) {\n addError(value, 'a value', opts, errors)\n }\n if (shouldPop) {\n opts.path.pop()\n opts.prop = prevProp\n }\n return errors.length ? errors : undefined\n }\n\n errors = errors.concat(validateAny(value, schema, opts) || [])\n if (shouldPop) {\n opts.path.pop()\n opts.prop = prevProp\n }\n return errors.length ? errors : undefined\n}\n\n// These strings are cached for optimal performance of the change detection\n// boolean - Whether a Record is changing in the current execution frame\nconst changingPath = 'changing'\n// string[] - Properties that have changed in the current execution frame\nconst changedPath = 'changed'\n// Object[] - History of change records\nconst changeHistoryPath = 'history'\n// boolean - Whether a Record is currently being instantiated\nconst creatingPath = 'creating'\n// number - The setTimeout change event id of a Record, if any\nconst eventIdPath = 'eventId'\n// boolean - Whether to skip validation for a Record's currently changing property\nconst noValidatePath = 'noValidate'\n// boolean - Whether to preserve Change History for a Record\nconst keepChangeHistoryPath = 'keepChangeHistory'\n// boolean - Whether to skip change notification for a Record's currently\n// changing property\nconst silentPath = 'silent'\nconst validationFailureMsg = 'validation failed'\n\n/**\n * A map of validation functions grouped by type.\n *\n * @name Schema.typeGroupValidators\n * @type {object}\n */\nconst typeGroupValidators = {\n /**\n * Validates the provided value against the schema using all of the validation keywords specific to instances of an array.\n * The validation keywords for the type `array` are:\n *```\n * ['items', 'maxItems', 'minItems', 'uniqueItems']\n *```\n * see http://json-schema.org/latest/json-schema-validation.html#anchor25\n *\n * @name Schema.typeGroupValidators.array\n * @method\n * @param {*} value Array to be validated.\n * @param {object} schema Schema containing at least one array keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n array: function (value, schema, opts) {\n return runOps(ARRAY_OPS, value, schema, opts)\n },\n\n /**\n * Validates the provided value against the schema using all of the validation keywords specific to instances of an integer.\n * The validation keywords for the type `integer` are:\n *```\n * ['multipleOf', 'maximum', 'minimum']\n *```\n * @name Schema.typeGroupValidators.integer\n * @method\n * @param {*} value Number to be validated.\n * @param {object} schema Schema containing at least one `integer` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n integer: function (value, schema, opts) {\n // Additional validations for numerics are the same\n return typeGroupValidators.numeric(value, schema, opts)\n },\n\n /**\n * Validates the provided value against the schema using all of the validation keywords specific to instances of an number.\n * The validation keywords for the type `number` are:\n *```\n * ['multipleOf', 'maximum', 'minimum']\n *```\n * @name Schema.typeGroupValidators.number\n * @method\n * @param {*} value Number to be validated.\n * @param {object} schema Schema containing at least one `number` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n number: function (value, schema, opts) {\n // Additional validations for numerics are the same\n return typeGroupValidators.numeric(value, schema, opts)\n },\n\n /**\n * Validates the provided value against the schema using all of the validation keywords specific to instances of a number or integer.\n * The validation keywords for the type `numeric` are:\n *```\n * ['multipleOf', 'maximum', 'minimum']\n *```\n * See http://json-schema.org/latest/json-schema-validation.html#anchor13.\n *\n * @name Schema.typeGroupValidators.numeric\n * @method\n * @param {*} value Number to be validated.\n * @param {object} schema Schema containing at least one `numeric` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n numeric: function (value, schema, opts) {\n return runOps(NUMERIC_OPS, value, schema, opts)\n },\n\n /**\n * Validates the provided value against the schema using all of the validation keywords specific to instances of an object.\n * The validation keywords for the type `object` are:\n *```\n * ['maxProperties', 'minProperties', 'required', 'properties', 'dependencies']\n *```\n * See http://json-schema.org/latest/json-schema-validation.html#anchor53.\n *\n * @name Schema.typeGroupValidators.object\n * @method\n * @param {*} value Object to be validated.\n * @param {object} schema Schema containing at least one `object` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n object: function (value, schema, opts) {\n return runOps(OBJECT_OPS, value, schema, opts)\n },\n\n /**\n * Validates the provided value against the schema using all of the validation keywords specific to instances of an string.\n * The validation keywords for the type `string` are:\n *```\n * ['maxLength', 'minLength', 'pattern']\n *```\n * See http://json-schema.org/latest/json-schema-validation.html#anchor25.\n *\n * @name Schema.typeGroupValidators.string\n * @method\n * @param {*} value String to be validated.\n * @param {object} schema Schema containing at least one `string` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n string: function (value, schema, opts) {\n return runOps(STRING_OPS, value, schema, opts)\n }\n}\n\n/**\n * js-data's Schema class.\n *\n * @example Schema#constructor\n * const JSData = require('js-data');\n * const { Schema } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const PostSchema = new Schema({\n * type: 'object',\n * properties: {\n * title: { type: 'string' }\n * }\n * });\n * PostSchema.validate({ title: 1234 });\n *\n * @class Schema\n * @extends Component\n * @param {object} definition Schema definition according to json-schema.org\n */\nfunction Schema (definition) {\n definition || (definition = {})\n // TODO: schema validation\n utils.fillIn(this, definition)\n\n if (this.type === 'object') {\n this.properties = this.properties || {}\n utils.forOwn(this.properties, (_definition, prop) => {\n if (!(_definition instanceof Schema)) {\n this.properties[prop] = new Schema(_definition)\n }\n })\n } else if (this.type === 'array' && this.items && !(this.items instanceof Schema)) {\n this.items = new Schema(this.items)\n }\n if (this.extends && !(this.extends instanceof Schema)) {\n this.extends = new Schema(this.extends)\n }\n ['allOf', 'anyOf', 'oneOf'].forEach((validationKeyword) => {\n if (this[validationKeyword]) {\n this[validationKeyword].forEach((_definition, i) => {\n if (!(_definition instanceof Schema)) {\n this[validationKeyword][i] = new Schema(_definition)\n }\n })\n }\n })\n}\n\nexport default Component.extend({\n constructor: Schema,\n\n /**\n * This adds ES5 getters/setters to the target based on the \"properties\" in\n * this Schema, which makes possible change tracking and validation on\n * property assignment.\n *\n * @name Schema#apply\n * @method\n * @param {object} target The prototype to which to apply this schema.\n */\n apply (target, opts) {\n opts || (opts = {})\n opts.getter || (opts.getter = '_get')\n opts.setter || (opts.setter = '_set')\n opts.unsetter || (opts.unsetter = '_unset')\n opts.track || (opts.track = this.track)\n const properties = this.properties || {}\n utils.forOwn(properties, (schema, prop) => {\n Object.defineProperty(\n target,\n prop,\n this.makeDescriptor(prop, schema, opts)\n )\n })\n },\n\n /**\n * Apply default values to the target object for missing values.\n *\n * @name Schema#applyDefaults\n * @method\n * @param {object} target The target to which to apply values for missing values.\n */\n applyDefaults (target) {\n if (!target) {\n return\n }\n const properties = this.properties || {}\n const hasSet = utils.isFunction(target.set) || utils.isFunction(target._set)\n utils.forOwn(properties, function (schema, prop) {\n if (Object.hasOwnProperty.call(schema, 'default') && utils.get(target, prop) === undefined) {\n if (hasSet) {\n target.set(prop, utils.plainCopy(schema.default), { silent: true })\n } else {\n utils.set(target, prop, utils.plainCopy(schema.default))\n }\n }\n if (schema.type === 'object' && schema.properties) {\n if (hasSet) {\n const orig = target._get('noValidate')\n target._set('noValidate', true)\n utils.set(target, prop, utils.get(target, prop) || {}, { silent: true })\n target._set('noValidate', orig)\n } else {\n utils.set(target, prop, utils.get(target, prop) || {})\n }\n schema.applyDefaults(utils.get(target, prop))\n }\n })\n },\n\n /**\n * Assemble a property descriptor for tracking and validating changes to\n * a property according to the given schema. This method is called when\n * {@link Mapper#applySchema} is set to `true`.\n *\n * @name Schema#makeDescriptor\n * @method\n * @param {string} prop The property name.\n * @param {(Schema|object)} schema The schema for the property.\n * @param {object} [opts] Optional configuration.\n * @param {function} [opts.getter] Custom getter function.\n * @param {function} [opts.setter] Custom setter function.\n * @param {function} [opts.track] Whether to track changes.\n * @returns {object} A property descriptor for the given schema.\n */\n makeDescriptor (prop, schema, opts) {\n const descriptor = {\n // Better to allow configurability, but at the user's own risk\n configurable: true,\n // These properties are enumerable by default, but regardless of their\n // enumerability, they won't be \"own\" properties of individual records\n enumerable: schema.enumerable === undefined ? true : !!schema.enumerable\n }\n // Cache a few strings for optimal performance\n const keyPath = `props.${prop}`\n const previousPath = `previous.${prop}`\n const getter = opts.getter\n const setter = opts.setter\n const unsetter = opts.unsetter\n const track = utils.isBoolean(opts.track) ? opts.track : schema.track\n\n descriptor.get = function () {\n return this._get(keyPath)\n }\n\n if (utils.isFunction(schema.get)) {\n const originalGet = descriptor.get\n descriptor.get = function () {\n return schema.get.call(this, originalGet)\n }\n }\n\n descriptor.set = function (value) {\n // These are accessed a lot\n const _get = this[getter]\n const _set = this[setter]\n const _unset = this[unsetter]\n // Optionally check that the new value passes validation\n if (!_get(noValidatePath)) {\n const errors = schema.validate(value, { path: [prop] })\n if (errors) {\n // Immediately throw an error, preventing the record from getting into\n // an invalid state\n const error = new Error(validationFailureMsg)\n error.errors = errors\n throw error\n }\n }\n // TODO: Make it so tracking can be turned on for all properties instead of\n // only per-property\n if (track && !_get(creatingPath)) {\n // previous is versioned on database commit\n // props are versioned on set()\n const previous = _get(previousPath)\n const current = _get(keyPath)\n let changing = _get(changingPath)\n let changed = _get(changedPath)\n\n if (!changing) {\n // Track properties that are changing in the current event loop\n changed = []\n }\n\n // Add changing properties to this array once at most\n const index = changed.indexOf(prop)\n if (current !== value && index === -1) {\n changed.push(prop)\n }\n if (previous === value) {\n if (index >= 0) {\n changed.splice(index, 1)\n }\n }\n // No changes in current event loop\n if (!changed.length) {\n changing = false\n _unset(changingPath)\n _unset(changedPath)\n // Cancel pending change event\n if (_get(eventIdPath)) {\n clearTimeout(_get(eventIdPath))\n _unset(eventIdPath)\n }\n }\n // Changes detected in current event loop\n if (!changing && changed.length) {\n _set(changedPath, changed)\n _set(changingPath, true)\n // Saving the timeout id allows us to batch all changes in the same\n // event loop into a single \"change\"\n // TODO: Optimize\n _set(eventIdPath, setTimeout(() => {\n // Previous event loop where changes were gathered has ended, so\n // notify any listeners of those changes and prepare for any new\n // changes\n _unset(changedPath)\n _unset(eventIdPath)\n _unset(changingPath)\n // TODO: Optimize\n if (!_get(silentPath)) {\n let i\n for (i = 0; i < changed.length; i++) {\n this.emit('change:' + changed[i], this, utils.get(this, changed[i]))\n }\n\n const changes = utils.diffObjects({ [prop]: value }, { [prop]: current })\n\n if (_get(keepChangeHistoryPath)) {\n const changeRecord = utils.plainCopy(changes)\n changeRecord.timestamp = new Date().getTime()\n let changeHistory = _get(changeHistoryPath)\n !changeHistory && _set(changeHistoryPath, (changeHistory = []))\n changeHistory.push(changeRecord)\n }\n this.emit('change', this, changes)\n }\n _unset(silentPath)\n }, 0))\n }\n }\n _set(keyPath, value)\n return value\n }\n\n if (utils.isFunction(schema.set)) {\n const originalSet = descriptor.set\n descriptor.set = function (value) {\n return schema.set.call(this, value, originalSet)\n }\n }\n\n return descriptor\n },\n\n /**\n * Create a copy of the given value that contains only the properties defined\n * in this schema.\n *\n * @name Schema#pick\n * @method\n * @param {*} value The value to copy.\n * @returns {*} The copy.\n */\n pick (value) {\n if (value === undefined) {\n return\n }\n if (this.type === 'object') {\n const copy = {}\n const properties = this.properties\n if (properties) {\n utils.forOwn(properties, (_definition, prop) => {\n copy[prop] = _definition.pick(value[prop])\n })\n }\n if (this.extends) {\n utils.fillIn(copy, this.extends.pick(value))\n }\n // Conditionally copy properties not defined in \"properties\"\n if (this.additionalProperties) {\n for (var key in value) {\n if (!properties[key]) {\n copy[key] = utils.plainCopy(value[key])\n }\n }\n }\n return copy\n } else if (this.type === 'array') {\n return value.map((item) => {\n const _copy = this.items ? this.items.pick(item) : {}\n if (this.extends) {\n utils.fillIn(_copy, this.extends.pick(item))\n }\n return _copy\n })\n }\n return utils.plainCopy(value)\n },\n\n /**\n * Validate the provided value against this schema.\n *\n * @name Schema#validate\n * @method\n * @param {*} value Value to validate.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n validate (value, opts) {\n return validate(value, this, opts)\n }\n}, {\n ANY_OPS,\n ARRAY_OPS,\n NUMERIC_OPS,\n OBJECT_OPS,\n STRING_OPS,\n typeGroupValidators,\n types,\n validate,\n validationKeywords\n})\n\n/**\n * Create a subclass of this Schema:\n * @example Schema.extend\n * const JSData = require('js-data');\n * const { Schema } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * // Extend the class using ES2015 class syntax.\n * class CustomSchemaClass extends Schema {\n * foo () { return 'bar'; }\n * static beep () { return 'boop'; }\n * }\n * const customSchema = new CustomSchemaClass();\n * console.log(customSchema.foo());\n * console.log(CustomSchemaClass.beep());\n *\n * // Extend the class using alternate method.\n * const OtherSchemaClass = Schema.extend({\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * });\n * const otherSchema = new OtherSchemaClass();\n * console.log(otherSchema.foo());\n * console.log(OtherSchemaClass.beep());\n *\n * // Extend the class, providing a custom constructor.\n * function AnotherSchemaClass () {\n * Schema.call(this);\n * this.created_at = new Date().getTime();\n * }\n * Schema.extend({\n * constructor: AnotherSchemaClass,\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * });\n * const anotherSchema = new AnotherSchemaClass();\n * console.log(anotherSchema.created_at);\n * console.log(anotherSchema.foo());\n * console.log(AnotherSchemaClass.beep());\n *\n * @method Schema.extend\n * @param {object} [props={}] Properties to add to the prototype of the\n * subclass.\n * @param {object} [props.constructor] Provide a custom constructor function\n * to be used as the subclass itself.\n * @param {object} [classProps={}] Static properties to add to the subclass.\n * @returns {Constructor} Subclass of this Schema class.\n * @since 3.0.0\n */\n","import utils from './utils'\nimport Component from './Component'\nimport Record from './Record'\nimport Schema from './Schema'\nimport { Relation } from './relations'\nimport {\n belongsTo,\n belongsToType,\n hasMany,\n hasManyType,\n hasOne,\n hasOneType\n} from './decorators'\n\nconst DOMAIN = 'Mapper'\nconst applyDefaultsHooks = [\n 'beforeCreate',\n 'beforeCreateMany'\n]\nconst validatingHooks = [\n 'beforeCreate',\n 'beforeCreateMany',\n 'beforeUpdate',\n 'beforeUpdateAll',\n 'beforeUpdateMany'\n]\nconst makeNotify = function (num) {\n return function (...args) {\n const opts = args[args.length - num]\n const op = opts.op\n this.dbg(op, ...args)\n\n if (applyDefaultsHooks.indexOf(op) !== -1 && opts.applyDefaults !== false) {\n const schema = this.getSchema()\n if (schema && schema.applyDefaults) {\n let toProcess = args[0]\n if (!utils.isArray(toProcess)) {\n toProcess = [toProcess]\n }\n toProcess.forEach((record) => {\n schema.applyDefaults(record)\n })\n }\n }\n\n // Automatic validation\n if (validatingHooks.indexOf(op) !== -1 && !opts.noValidate) {\n // Save current value of option\n const originalExistingOnly = opts.existingOnly\n\n // For updates, ignore required fields if they aren't present\n if (op.indexOf('beforeUpdate') === 0 && opts.existingOnly === undefined) {\n opts.existingOnly = true\n }\n const errors = this.validate(args[op === 'beforeUpdate' ? 1 : 0], utils.pick(opts, ['existingOnly']))\n\n // Restore option\n opts.existingOnly = originalExistingOnly\n\n // Abort lifecycle due to validation errors\n if (errors) {\n const err = new Error('validation failed')\n err.errors = errors\n return utils.reject(err)\n }\n }\n\n // Emit lifecycle event\n if (opts.notify || (opts.notify === undefined && this.notify)) {\n setTimeout(() => {\n this.emit(op, ...args)\n })\n }\n }\n}\n\n// These are the default implementations of all of the lifecycle hooks\nconst notify = makeNotify(1)\nconst notify2 = makeNotify(2)\n\n// This object provides meta information used by Mapper#crud to actually\n// execute each lifecycle method\nconst LIFECYCLE_METHODS = {\n count: {\n defaults: [{}, {}],\n skip: true,\n types: []\n },\n destroy: {\n defaults: [{}, {}],\n skip: true,\n types: []\n },\n destroyAll: {\n defaults: [{}, {}],\n skip: true,\n types: []\n },\n find: {\n defaults: [undefined, {}],\n types: []\n },\n findAll: {\n defaults: [{}, {}],\n types: []\n },\n sum: {\n defaults: [undefined, {}, {}],\n skip: true,\n types: []\n },\n update: {\n adapterArgs (mapper, id, props, opts) {\n return [id, mapper.toJSON(props, opts), opts]\n },\n beforeAssign: 1,\n defaults: [undefined, {}, {}],\n types: []\n },\n updateAll: {\n adapterArgs (mapper, props, query, opts) {\n return [mapper.toJSON(props, opts), query, opts]\n },\n beforeAssign: 0,\n defaults: [{}, {}, {}],\n types: []\n },\n updateMany: {\n adapterArgs (mapper, records, opts) {\n return [records.map((record) => mapper.toJSON(record, opts)), opts]\n },\n beforeAssign: 0,\n defaults: [[], {}],\n types: []\n }\n}\n\nconst MAPPER_DEFAULTS = {\n /**\n * Hash of registered adapters. Don't modify directly. Use\n * {@link Mapper#registerAdapter} instead.\n *\n * @default {}\n * @name Mapper#_adapters\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/connecting-to-a-data-source\",\"Connecting to a data source\"]\n */\n _adapters: {},\n\n /**\n * Whether {@link Mapper#beforeCreate} and {@link Mapper#beforeCreateMany}\n * should automatically receive default values according to the Mapper's schema.\n *\n * @default true\n * @name Mapper#applyDefaults\n * @since 3.0.0\n * @type {boolean}\n */\n applyDefaults: true,\n\n /**\n * Whether to augment {@link Mapper#recordClass} with ES5 getters and setters\n * according to the properties defined in {@link Mapper#schema}. This makes\n * possible validation and change tracking on individual properties\n * when using the dot (e.g. `user.name = \"Bob\"`) operator to modify a\n * property, and is `true` by default.\n *\n * @default true\n * @name Mapper#applySchema\n * @since 3.0.0\n * @type {boolean}\n */\n applySchema: true,\n\n /**\n * The name of the registered adapter that this Mapper should used by default.\n *\n * @default \"http\"\n * @name Mapper#defaultAdapter\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/connecting-to-a-data-source\",\"Connecting to a data source\"]\n * @type {string}\n */\n defaultAdapter: 'http',\n\n /**\n * The field used as the unique identifier on records handled by this Mapper.\n *\n * @default id\n * @name Mapper#idAttribute\n * @since 3.0.0\n * @type {string}\n */\n idAttribute: 'id',\n\n /**\n * Whether records created from this mapper keep changeHistory on property changes.\n *\n * @default true\n * @name Mapper#keepChangeHistory\n * @since 3.0.0\n * @type {boolean}\n */\n keepChangeHistory: true,\n\n /**\n * Whether this Mapper should emit operational events.\n *\n * @default true\n * @name Mapper#notify\n * @since 3.0.0\n * @type {boolean}\n */\n notify: true,\n\n /**\n * Whether to skip validation when the Record instances are created.\n *\n * @default false\n * @name Mapper#noValidate\n * @since 3.0.0\n * @type {boolean}\n */\n noValidate: false,\n\n /**\n * Whether {@link Mapper#create}, {@link Mapper#createMany},\n * {@link Mapper#update}, {@link Mapper#updateAll}, {@link Mapper#updateMany},\n * {@link Mapper#find}, {@link Mapper#findAll}, {@link Mapper#destroy},\n * {@link Mapper#destroyAll}, {@link Mapper#count}, and {@link Mapper#sum}\n * should return a raw result object that contains both the instance data\n * returned by the adapter _and_ metadata about the operation.\n *\n * The default is to NOT return the result object, and instead return just the\n * instance data.\n *\n * @default false\n * @name Mapper#raw\n * @since 3.0.0\n * @type {boolean}\n */\n raw: false,\n\n /**\n * Whether records created from this mapper automatically validate their properties\n * when their properties are modified.\n *\n * @default true\n * @name Mapper#validateOnSet\n * @since 3.0.0\n * @type {boolean}\n */\n validateOnSet: true\n}\n\n/**\n * The core of JSData's [ORM/ODM][orm] implementation. Given a minimum amout of\n * meta information about a resource, a Mapper can perform generic CRUD\n * operations against that resource. Apart from its configuration, a Mapper is\n * stateless. The particulars of various persistence layers have been abstracted\n * into adapters, which a Mapper uses to perform its operations.\n *\n * The term \"Mapper\" comes from the [Data Mapper Pattern][pattern] described in\n * Martin Fowler's [Patterns of Enterprise Application Architecture][book]. A\n * Data Mapper moves data between [in-memory object instances][record] and a\n * relational or document-based database. JSData's Mapper can work with any\n * persistence layer you can write an adapter for.\n *\n * _(\"Model\" is a heavily overloaded term and is avoided in this documentation\n * to prevent confusion.)_\n *\n * [orm]: https://en.wikipedia.org/wiki/Object-relational_mapping\n *\n * @example\n * [pattern]: https://en.wikipedia.org/wiki/Data_mapper_pattern\n * [book]: http://martinfowler.com/books/eaa.html\n * [record]: Record.html\n * // Import and instantiate\n * import { Mapper } from 'js-data';\n * const UserMapper = new Mapper({ name: 'user' });\n *\n * @example\n * // Define a Mapper using the Container component\n * import { Container } from 'js-data';\n * const store = new Container();\n * store.defineMapper('user');\n *\n * @class Mapper\n * @extends Component\n * @param {object} opts Configuration options.\n * @param {boolean} [opts.applySchema=true] See {@link Mapper#applySchema}.\n * @param {boolean} [opts.debug=false] See {@link Component#debug}.\n * @param {string} [opts.defaultAdapter=http] See {@link Mapper#defaultAdapter}.\n * @param {string} [opts.idAttribute=id] See {@link Mapper#idAttribute}.\n * @param {object} [opts.methods] See {@link Mapper#methods}.\n * @param {string} opts.name See {@link Mapper#name}.\n * @param {boolean} [opts.notify] See {@link Mapper#notify}.\n * @param {boolean} [opts.raw=false] See {@link Mapper#raw}.\n * @param {Function|boolean} [opts.recordClass] See {@link Mapper#recordClass}.\n * @param {Object|Schema} [opts.schema] See {@link Mapper#schema}.\n * @returns {Mapper} A new {@link Mapper} instance.\n * @see http://www.js-data.io/v3.0/docs/components-of-jsdata#mapper\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/components-of-jsdata#mapper\",\"Components of JSData: Mapper\"]\n * @tutorial [\"http://www.js-data.io/v3.0/docs/modeling-your-data\",\"Modeling your data\"]\n */\nfunction Mapper (opts) {\n utils.classCallCheck(this, Mapper)\n Component.call(this)\n opts || (opts = {})\n\n // Prepare certain properties to be non-enumerable\n Object.defineProperties(this, {\n _adapters: {\n value: undefined,\n writable: true\n },\n\n /**\n * The {@link Container} that holds this Mapper. __Do not modify.__\n *\n * @name Mapper#lifecycleMethods\n * @since 3.0.0\n * @type {Object}\n */\n datastore: {\n value: undefined,\n writable: true\n },\n\n /**\n * The meta information describing this Mapper's available lifecycle\n * methods. __Do not modify.__\n *\n * @name Mapper#lifecycleMethods\n * @since 3.0.0\n * @type {Object}\n */\n lifecycleMethods: {\n value: LIFECYCLE_METHODS\n },\n\n /**\n * Set to `false` to force the Mapper to work with POJO objects only.\n *\n * @example\n * // Use POJOs only.\n * import { Mapper, Record } from 'js-data';\n * const UserMapper = new Mapper({ recordClass: false });\n * UserMapper.recordClass // false;\n * const user = UserMapper.createRecord();\n * user instanceof Record; // false\n *\n * @example\n * // Set to a custom class to have records wrapped in your custom class.\n * import { Mapper, Record } from 'js-data';\n * // Custom class\n * class User {\n * constructor (props = {}) {\n * for (var key in props) {\n * if (props.hasOwnProperty(key)) {\n * this[key] = props[key];\n * }\n * }\n * }\n * }\n * const UserMapper = new Mapper({ recordClass: User });\n * UserMapper.recordClass; // function User() {}\n * const user = UserMapper.createRecord();\n * user instanceof Record; // false\n * user instanceof User; // true\n *\n *\n * @example\n * // Extend the {@link Record} class.\n * import { Mapper, Record } from 'js-data';\n * // Custom class\n * class User extends Record {\n * constructor () {\n * super(props);\n * }\n * }\n * const UserMapper = new Mapper({ recordClass: User });\n * UserMapper.recordClass; // function User() {}\n * const user = UserMapper.createRecord();\n * user instanceof Record; // true\n * user instanceof User; // true\n *\n * @name Mapper#recordClass\n * @default {@link Record}\n * @see Record\n * @since 3.0.0\n */\n recordClass: {\n value: undefined,\n writable: true\n },\n\n /**\n * This Mapper's {@link Schema}.\n *\n * @example Mapper#schema\n * const JSData = require('js-data');\n * const { Mapper } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const UserMapper = new Mapper({\n * name: 'user',\n * schema: {\n * properties: {\n * id: { type: 'number' },\n * first: { type: 'string', track: true },\n * last: { type: 'string', track: true },\n * role: { type: 'string', track: true, required: true },\n * age: { type: 'integer', track: true },\n * is_active: { type: 'number' }\n * }\n * }\n * });\n * const user = UserMapper.createRecord({\n * id: 1,\n * name: 'John',\n * role: 'admin'\n * });\n * user.on('change', function (user, changes) {\n * console.log(changes);\n * });\n * user.on('change:role', function (user, value) {\n * console.log('change:role - ' + value);\n * });\n * user.role = 'owner';\n *\n * @name Mapper#schema\n * @see Schema\n * @since 3.0.0\n * @type {Schema}\n */\n schema: {\n value: undefined,\n writable: true\n }\n })\n\n // Apply user-provided configuration\n utils.fillIn(this, opts)\n // Fill in any missing options with the defaults\n utils.fillIn(this, utils.copy(MAPPER_DEFAULTS))\n\n /**\n * The name for this Mapper. This is the minimum amount of meta information\n * required for a Mapper to be able to execute CRUD operations for a\n * Resource.\n *\n * @name Mapper#name\n * @since 3.0.0\n * @type {string}\n */\n if (!this.name) {\n throw utils.err(`new ${DOMAIN}`, 'opts.name')(400, 'string', this.name)\n }\n\n // Setup schema, with an empty default schema if necessary\n if (this.schema) {\n this.schema.type || (this.schema.type = 'object')\n if (!(this.schema instanceof Schema)) {\n this.schema = new Schema(this.schema || { type: 'object' })\n }\n }\n\n // Create a subclass of Record that's tied to this Mapper\n if (this.recordClass === undefined) {\n const superClass = Record\n this.recordClass = superClass.extend({\n constructor: (function Record () {\n var subClass = function Record (props, opts) {\n utils.classCallCheck(this, subClass)\n superClass.call(this, props, opts)\n }\n return subClass\n })()\n })\n }\n\n if (this.recordClass) {\n this.recordClass.mapper = this\n\n /**\n * Functions that should be added to the prototype of {@link Mapper#recordClass}.\n *\n * @name Mapper#methods\n * @since 3.0.0\n * @type {Object}\n */\n if (utils.isObject(this.methods)) {\n utils.addHiddenPropsToTarget(this.recordClass.prototype, this.methods)\n }\n\n // We can only apply the schema to the prototype of this.recordClass if the\n // class extends Record\n if (Object.isPrototypeOf.call(Record, this.recordClass) && this.schema && this.schema.apply && this.applySchema) {\n this.schema.apply(this.recordClass.prototype)\n }\n }\n}\n\nexport default Component.extend({\n constructor: Mapper,\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#count}. If this method\n * returns a promise then {@link Mapper#count} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#afterCount\n * @param {object} query The `query` argument passed to {@link Mapper#count}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#count}.\n * @param {*} result The result, if any.\n * @since 3.0.0\n */\n afterCount: notify2,\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#create}. If this method\n * returns a promise then {@link Mapper#create} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#afterCreate\n * @param {object} props The `props` argument passed to {@link Mapper#create}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#create}.\n * @param {*} result The result, if any.\n * @since 3.0.0\n */\n afterCreate: notify2,\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#createMany}. If this method\n * returns a promise then {@link Mapper#createMany} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#afterCreateMany\n * @param {array} records The `records` argument passed to {@link Mapper#createMany}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#createMany}.\n * @param {*} result The result, if any.\n * @since 3.0.0\n */\n afterCreateMany: notify2,\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#destroy}. If this method\n * returns a promise then {@link Mapper#destroy} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#afterDestroy\n * @param {(string|number)} id The `id` argument passed to {@link Mapper#destroy}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#destroy}.\n * @param {*} result The result, if any.\n * @since 3.0.0\n */\n afterDestroy: notify2,\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#destroyAll}. If this method\n * returns a promise then {@link Mapper#destroyAll} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#afterDestroyAll\n * @param {*} data The `data` returned by the adapter.\n * @param {query} query The `query` argument passed to {@link Mapper#destroyAll}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#destroyAll}.\n * @param {*} result The result, if any.\n * @since 3.0.0\n */\n afterDestroyAll: notify2,\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#find}. If this method\n * returns a promise then {@link Mapper#find} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#afterFind\n * @param {(string|number)} id The `id` argument passed to {@link Mapper#find}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#find}.\n * @param {*} result The result, if any.\n * @since 3.0.0\n */\n afterFind: notify2,\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#findAll}. If this method\n * returns a promise then {@link Mapper#findAll} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#afterFindAll\n * @param {object} query The `query` argument passed to {@link Mapper#findAll}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#findAll}.\n * @param {*} result The result, if any.\n * @since 3.0.0\n */\n afterFindAll: notify2,\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#sum}. If this method\n * returns a promise then {@link Mapper#sum} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#afterSum\n * @param {object} query The `query` argument passed to {@link Mapper#sum}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#sum}.\n * @param {*} result The result, if any.\n * @since 3.0.0\n */\n afterSum: notify2,\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#update}. If this method\n * returns a promise then {@link Mapper#update} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#afterUpdate\n * @param {(string|number)} id The `id` argument passed to {@link Mapper#update}.\n * @param {props} props The `props` argument passed to {@link Mapper#update}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#update}.\n * @param {*} result The result, if any.\n * @since 3.0.0\n */\n afterUpdate: notify2,\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#updateAll}. If this method\n * returns a promise then {@link Mapper#updateAll} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#afterUpdateAll\n * @param {object} props The `props` argument passed to {@link Mapper#updateAll}.\n * @param {object} query The `query` argument passed to {@link Mapper#updateAll}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#updateAll}.\n * @param {*} result The result, if any.\n * @since 3.0.0\n */\n afterUpdateAll: notify2,\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#updateMany}. If this method\n * returns a promise then {@link Mapper#updateMany} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#afterUpdateMany\n * @param {array} records The `records` argument passed to {@link Mapper#updateMany}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#updateMany}.\n * @param {*} result The result, if any.\n * @since 3.0.0\n */\n afterUpdateMany: notify2,\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#create}. If this method\n * returns a promise then {@link Mapper#create} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#beforeCreate\n * @param {object} props The `props` argument passed to {@link Mapper#create}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#create}.\n * @since 3.0.0\n */\n beforeCreate: notify,\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#createMany}. If this method\n * returns a promise then {@link Mapper#createMany} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#beforeCreateMany\n * @param {array} records The `records` argument passed to {@link Mapper#createMany}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#createMany}.\n * @since 3.0.0\n */\n beforeCreateMany: notify,\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#count}. If this method\n * returns a promise then {@link Mapper#count} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#beforeCount\n * @param {object} query The `query` argument passed to {@link Mapper#count}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#count}.\n * @since 3.0.0\n */\n beforeCount: notify,\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#destroy}. If this method\n * returns a promise then {@link Mapper#destroy} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#beforeDestroy\n * @param {(string|number)} id The `id` argument passed to {@link Mapper#destroy}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#destroy}.\n * @since 3.0.0\n */\n beforeDestroy: notify,\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#destroyAll}. If this method\n * returns a promise then {@link Mapper#destroyAll} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#beforeDestroyAll\n * @param {query} query The `query` argument passed to {@link Mapper#destroyAll}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#destroyAll}.\n * @since 3.0.0\n */\n beforeDestroyAll: notify,\n\n /**\n * Mappers lifecycle hook called by {@link Mapper#find}. If this method\n * returns a promise then {@link Mapper#find} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#beforeFind\n * @param {(string|number)} id The `id` argument passed to {@link Mapper#find}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#find}.\n * @since 3.0.0\n */\n beforeFind: notify,\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#findAll}. If this method\n * returns a promise then {@link Mapper#findAll} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#beforeFindAll\n * @param {object} query The `query` argument passed to {@link Mapper#findAll}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#findAll}.\n * @since 3.0.0\n */\n beforeFindAll: notify,\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#sum}. If this method\n * returns a promise then {@link Mapper#sum} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#beforeSum\n * @param {string} field The `field` argument passed to {@link Mapper#sum}.\n * @param {object} query The `query` argument passed to {@link Mapper#sum}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#sum}.\n * @since 3.0.0\n */\n beforeSum: notify,\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#update}. If this method\n * returns a promise then {@link Mapper#update} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#beforeUpdate\n * @param {(string|number)} id The `id` argument passed to {@link Mapper#update}.\n * @param {props} props The `props` argument passed to {@link Mapper#update}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#update}.\n * @since 3.0.0\n */\n beforeUpdate: notify,\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#updateAll}. If this method\n * returns a promise then {@link Mapper#updateAll} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#beforeUpdateAll\n * @param {object} props The `props` argument passed to {@link Mapper#updateAll}.\n * @param {object} query The `query` argument passed to {@link Mapper#updateAll}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#updateAll}.\n * @since 3.0.0\n */\n beforeUpdateAll: notify,\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#updateMany}. If this method\n * returns a promise then {@link Mapper#updateMany} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#beforeUpdateMany\n * @param {array} records The `records` argument passed to {@link Mapper#updateMany}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#updateMany}.\n * @since 3.0.0\n */\n beforeUpdateMany: notify,\n\n /**\n * This method is called at the end of most lifecycle methods. It does the\n * following:\n *\n * 1. If `opts.raw` is `true`, add this Mapper's configuration to the `opts`\n * argument as metadata for the operation.\n * 2. Wrap the result data appropriately using {@link Mapper#wrap}, which\n * calls {@link Mapper#createRecord}.\n *\n * @method Mapper#_end\n * @private\n * @since 3.0.0\n */\n _end (result, opts, skip) {\n if (opts.raw) {\n utils._(result, opts)\n }\n if (skip) {\n return result\n }\n let _data = opts.raw ? result.data : result\n if (_data && utils.isFunction(this.wrap)) {\n _data = this.wrap(_data, opts)\n if (opts.raw) {\n result.data = _data\n } else {\n result = _data\n }\n }\n return result\n },\n\n /**\n * Define a belongsTo relationship. Only useful if you're managing your\n * Mappers manually and not using a Container or DataStore component.\n *\n * @example\n * PostMapper.belongsTo(UserMapper, {\n * // post.user_id points to user.id\n * foreignKey: 'user_id'\n * // user records will be attached to post records at \"post.user\"\n * localField: 'user'\n * });\n *\n * CommentMapper.belongsTo(UserMapper, {\n * // comment.user_id points to user.id\n * foreignKey: 'user_id'\n * // user records will be attached to comment records at \"comment.user\"\n * localField: 'user'\n * });\n * CommentMapper.belongsTo(PostMapper, {\n * // comment.post_id points to post.id\n * foreignKey: 'post_id'\n * // post records will be attached to comment records at \"comment.post\"\n * localField: 'post'\n * });\n *\n * @method Mapper#belongsTo\n * @see http://www.js-data.io/v3.0/docs/relations\n * @since 3.0.0\n */\n belongsTo (relatedMapper, opts) {\n return belongsTo(relatedMapper, opts)(this)\n },\n\n /**\n * Select records according to the `query` argument and return the count.\n *\n * {@link Mapper#beforeCount} will be called before calling the adapter.\n * {@link Mapper#afterCount} will be called after calling the adapter.\n *\n * @example\n * // Get the number of published blog posts\n * PostMapper.count({ status: 'published' }).then((numPublished) => {\n * console.log(numPublished); // e.g. 45\n * });\n *\n * @method Mapper#count\n * @param {object} [query={}] Selection query. See {@link query}.\n * @param {object} [query.where] See {@link query.where}.\n * @param {number} [query.offset] See {@link query.offset}.\n * @param {number} [query.limit] See {@link query.limit}.\n * @param {string|Array[]} [query.orderBy] See {@link query.orderBy}.\n * @param {object} [opts] Configuration options. Refer to the `count` method\n * of whatever adapter you're using for more configuration options.\n * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the\n * adapter to use.\n * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}.\n * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}.\n * @returns {Promise} Resolves with the count of the selected records.\n * @since 3.0.0\n */\n count (query, opts) {\n return this.crud('count', query, opts)\n },\n\n /**\n * Fired during {@link Mapper#create}. See\n * {@link Mapper~beforeCreateListener} for how to listen for this event.\n *\n * @event Mapper#beforeCreate\n * @see Mapper~beforeCreateListener\n * @see Mapper#create\n */\n /**\n * Callback signature for the {@link Mapper#event:beforeCreate} event.\n *\n * @example\n * function onBeforeCreate (props, opts) {\n * // do something\n * }\n * store.on('beforeCreate', onBeforeCreate);\n *\n * @callback Mapper~beforeCreateListener\n * @param {object} props The `props` argument passed to {@link Mapper#beforeCreate}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#beforeCreate}.\n * @see Mapper#event:beforeCreate\n * @see Mapper#create\n * @since 3.0.0\n */\n /**\n * Fired during {@link Mapper#create}. See\n * {@link Mapper~afterCreateListener} for how to listen for this event.\n *\n * @event Mapper#afterCreate\n * @see Mapper~afterCreateListener\n * @see Mapper#create\n */\n /**\n * Callback signature for the {@link Mapper#event:afterCreate} event.\n *\n * @example\n * function onAfterCreate (props, opts, result) {\n * // do something\n * }\n * store.on('afterCreate', onAfterCreate);\n *\n * @callback Mapper~afterCreateListener\n * @param {object} props The `props` argument passed to {@link Mapper#afterCreate}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#afterCreate}.\n * @param {object} result The `result` argument passed to {@link Mapper#afterCreate}.\n * @see Mapper#event:afterCreate\n * @see Mapper#create\n * @since 3.0.0\n */\n /**\n * Create and save a new the record using the provided `props`.\n *\n * {@link Mapper#beforeCreate} will be called before calling the adapter.\n * {@link Mapper#afterCreate} will be called after calling the adapter.\n *\n * @example\n * // Create and save a new blog post\n * PostMapper.create({\n * title: 'Modeling your data',\n * status: 'draft'\n * }).then((post) => {\n * console.log(post); // { id: 1234, status: 'draft', ... }\n * });\n *\n * @fires Mapper#beforeCreate\n * @fires Mapper#afterCreate\n * @method Mapper#create\n * @param {object} props The properties for the new record.\n * @param {object} [opts] Configuration options. Refer to the `create` method\n * of whatever adapter you're using for more configuration options.\n * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the\n * adapter to use.\n * @param {boolean} [opts.noValidate={@link Mapper#noValidate}] See {@link Mapper#noValidate}.\n * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}.\n * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}.\n * @param {string[]} [opts.with=[]] Relations to create in a cascading\n * create if `props` contains nested relations. NOT performed in a\n * transaction. Each nested create will result in another {@link Mapper#create}\n * or {@link Mapper#createMany} call.\n * @param {string[]} [opts.pass=[]] Relations to send to the adapter as part\n * of the payload. Normally relations are not sent.\n * @returns {Promise} Resolves with the created record.\n * @since 3.0.0\n */\n create (props, opts) {\n // Default values for arguments\n props || (props = {})\n opts || (opts = {})\n const originalRecord = props\n let parentRelationMap = {}\n let adapterResponse = {}\n\n // Fill in \"opts\" with the Mapper's configuration\n utils._(opts, this)\n opts.adapter = this.getAdapterName(opts)\n\n opts.op = 'beforeCreate'\n return this._runHook(opts.op, props, opts).then((props) => {\n opts.with || (opts.with = [])\n return this._createParentRecordIfRequired(props, opts)\n }).then((relationMap) => {\n parentRelationMap = relationMap\n }).then(() => {\n opts.op = 'create'\n return this._invokeAdapterMethod(opts.op, props, opts)\n }).then((result) => {\n adapterResponse = result\n }).then(() => {\n const createdProps = opts.raw ? adapterResponse.data : adapterResponse\n\n return this._createOrAssignChildRecordIfRequired(createdProps, {\n opts,\n parentRelationMap,\n originalProps: props\n })\n }).then((createdProps) => {\n return this._commitChanges(originalRecord, createdProps)\n }).then((record) => {\n if (opts.raw) {\n adapterResponse.data = record\n } else {\n adapterResponse = record\n }\n const result = this._end(adapterResponse, opts)\n opts.op = 'afterCreate'\n return this._runHook(opts.op, props, opts, result)\n })\n },\n\n _commitChanges (recordOrRecords, newValues) {\n if (utils.isArray(recordOrRecords)) {\n return recordOrRecords.map((record, i) => this._commitChanges(record, newValues[i]))\n }\n\n utils.set(recordOrRecords, newValues, { silent: true })\n\n if (utils.isFunction(recordOrRecords.commit)) {\n recordOrRecords.commit()\n }\n\n return recordOrRecords\n },\n\n /**\n * Use {@link Mapper#createRecord} instead.\n * @deprecated\n * @method Mapper#createInstance\n * @param {Object|Array} props See {@link Mapper#createRecord}.\n * @param {object} [opts] See {@link Mapper#createRecord}.\n * @returns {Object|Array} See {@link Mapper#createRecord}.\n * @see Mapper#createRecord\n * @since 3.0.0\n */\n createInstance (props, opts) {\n return this.createRecord(props, opts)\n },\n\n /**\n * Creates parent record for relation types like BelongsTo or HasMany with localKeys\n * in order to satisfy foreignKey dependency (so called child records).\n * @param {object} props See {@link Mapper#create}.\n * @param {object} opts See {@link Mapper#create}.\n * @returns {Object} cached parent records map\n * @see Mapper#create\n * @since 3.0.0\n */\n _createParentRecordIfRequired (props, opts) {\n const tasks = []\n const relations = []\n\n utils.forEachRelation(this, opts, (def, optsCopy) => {\n if (!def.isRequiresParentId() || !def.getLocalField(props)) {\n return\n }\n\n optsCopy.raw = false\n relations.push(def)\n tasks.push(def.createParentRecord(props, optsCopy))\n })\n\n return utils.Promise.all(tasks).then(records => {\n return relations.reduce((map, relation, index) => {\n relation.setLocalField(map, records[index])\n return map\n }, {})\n })\n },\n\n /**\n * Creates child record for relation types like HasOne or HasMany with foreignKey\n * in order to satisfy foreignKey dependency (so called parent records).\n * @param {object} props See {@link Mapper#create}.\n * @param {object} context contains collected information.\n * @param {object} context.opts See {@link Mapper#create}.\n * @param {object} context.parentRelationMap contains parent records map\n * @param {object} context.originalProps contains data passed into {@link Mapper#create} method\n * @return {Promise} updated props\n * @see Mapper#create\n * @since 3.0.0\n */\n _createOrAssignChildRecordIfRequired (props, context) {\n const tasks = []\n\n utils.forEachRelation(this, context.opts, (def, optsCopy) => {\n const relationData = def.getLocalField(context.originalProps)\n\n if (!relationData) {\n return\n }\n\n optsCopy.raw = false\n // Create hasMany and hasOne after the main create because we needed\n // a generated id to attach to these items\n if (def.isRequiresChildId()) {\n tasks.push(def.createChildRecord(props, relationData, optsCopy))\n } else if (def.isRequiresParentId()) {\n const parent = def.getLocalField(context.parentRelationMap)\n\n if (parent) {\n def.setLocalField(props, parent)\n }\n }\n })\n\n return utils.Promise.all(tasks)\n .then(() => props)\n },\n\n /**\n * Fired during {@link Mapper#createMany}. See\n * {@link Mapper~beforeCreateManyListener} for how to listen for this event.\n *\n * @event Mapper#beforeCreateMany\n * @see Mapper~beforeCreateManyListener\n * @see Mapper#createMany\n */\n /**\n * Callback signature for the {@link Mapper#event:beforeCreateMany} event.\n *\n * @example\n * function onBeforeCreateMany (records, opts) {\n * // do something\n * }\n * store.on('beforeCreateMany', onBeforeCreateMany);\n *\n * @callback Mapper~beforeCreateManyListener\n * @param {object} records The `records` argument received by {@link Mapper#beforeCreateMany}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeCreateMany}.\n * @see Mapper#event:beforeCreateMany\n * @see Mapper#createMany\n * @since 3.0.0\n */\n /**\n * Fired during {@link Mapper#createMany}. See\n * {@link Mapper~afterCreateManyListener} for how to listen for this event.\n *\n * @event Mapper#afterCreateMany\n * @see Mapper~afterCreateManyListener\n * @see Mapper#createMany\n */\n /**\n * Callback signature for the {@link Mapper#event:afterCreateMany} event.\n *\n * @example\n * function onAfterCreateMany (records, opts, result) {\n * // do something\n * }\n * store.on('afterCreateMany', onAfterCreateMany);\n *\n * @callback Mapper~afterCreateManyListener\n * @param {object} records The `records` argument received by {@link Mapper#afterCreateMany}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterCreateMany}.\n * @param {object} result The `result` argument received by {@link Mapper#afterCreateMany}.\n * @see Mapper#event:afterCreateMany\n * @see Mapper#createMany\n * @since 3.0.0\n */\n /**\n * Given an array of records, batch create them via an adapter.\n *\n * {@link Mapper#beforeCreateMany} will be called before calling the adapter.\n * {@link Mapper#afterCreateMany} will be called after calling the adapter.\n *\n * @example\n * // Create and save several new blog posts\n * PostMapper.createMany([{\n * title: 'Modeling your data',\n * status: 'draft'\n * }, {\n * title: 'Reading data',\n * status: 'draft'\n * }]).then((posts) => {\n * console.log(posts[0]); // { id: 1234, status: 'draft', ... }\n * console.log(posts[1]); // { id: 1235, status: 'draft', ... }\n * });\n *\n * @fires Mapper#beforeCreate\n * @fires Mapper#afterCreate\n * @method Mapper#createMany\n * @param {Record[]} records Array of records to be created in one batch.\n * @param {object} [opts] Configuration options. Refer to the `createMany`\n * method of whatever adapter you're using for more configuration options.\n * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the\n * adapter to use.\n * @param {boolean} [opts.noValidate={@link Mapper#noValidate}] See {@link Mapper#noValidate}.\n * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}.\n * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}.\n * @param {string[]} [opts.with=[]] Relations to create in a cascading\n * create if `records` contains nested relations. NOT performed in a\n * transaction. Each nested create will result in another {@link Mapper#createMany}\n * call.\n * @param {string[]} [opts.pass=[]] Relations to send to the adapter as part\n * of the payload. Normally relations are not sent.\n * @returns {Promise} Resolves with the created records.\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/saving-data\",\"Saving data\"]\n */\n createMany (records, opts) {\n // Default values for arguments\n records || (records = [])\n opts || (opts = {})\n const originalRecords = records\n let adapterResponse\n\n // Fill in \"opts\" with the Mapper's configuration\n utils._(opts, this)\n opts.adapter = this.getAdapterName(opts)\n\n // beforeCreateMany lifecycle hook\n opts.op = 'beforeCreateMany'\n return this._runHook(opts.op, records, opts).then((records) => {\n // Deep pre-create belongsTo relations\n const belongsToRelationData = {}\n opts.with || (opts.with = [])\n let tasks = []\n utils.forEachRelation(this, opts, (def, optsCopy) => {\n const relationData = records\n .map((record) => def.getLocalField(record))\n .filter(Boolean)\n if (def.type === belongsToType && relationData.length === records.length) {\n // Create belongsTo relation first because we need a generated id to\n // attach to the child\n optsCopy.raw = false\n tasks.push(def.createLinked(relationData, optsCopy).then((relatedRecords) => {\n records.forEach((record, i) => def.setForeignKey(record, relatedRecords[i]))\n }).then((relatedRecords) => {\n def.setLocalField(belongsToRelationData, relatedRecords)\n }))\n }\n })\n return utils.Promise.all(tasks).then(() => {\n opts.op = 'createMany'\n return this._invokeAdapterMethod(opts.op, records, opts)\n }).then((result) => {\n adapterResponse = result\n }).then(() => {\n const createdRecordsData = opts.raw ? adapterResponse.data : adapterResponse\n\n // Deep post-create hasOne relations\n tasks = []\n utils.forEachRelation(this, opts, (def, optsCopy) => {\n const relationData = records\n .map((record) => def.getLocalField(record))\n .filter(Boolean)\n if (relationData.length !== records.length) {\n return\n }\n\n optsCopy.raw = false\n const belongsToData = def.getLocalField(belongsToRelationData)\n let task\n // Create hasMany and hasOne after the main create because we needed\n // a generated id to attach to these items\n if (def.type === hasManyType) {\n // Not supported\n this.log('warn', 'deep createMany of hasMany type not supported!')\n } else if (def.type === hasOneType) {\n createdRecordsData.forEach((createdRecordData, i) => {\n def.setForeignKey(createdRecordData, relationData[i])\n })\n task = def.getRelation().createMany(relationData, optsCopy).then((relatedData) => {\n createdRecordsData.forEach((createdRecordData, i) => {\n def.setLocalField(createdRecordData, relatedData[i])\n })\n })\n } else if (def.type === belongsToType && belongsToData && belongsToData.length === createdRecordsData.length) {\n createdRecordsData.forEach((createdRecordData, i) => {\n def.setLocalField(createdRecordData, belongsToData[i])\n })\n }\n if (task) {\n tasks.push(task)\n }\n })\n return utils.Promise.all(tasks).then(() => {\n return this._commitChanges(originalRecords, createdRecordsData)\n })\n })\n }).then((records) => {\n if (opts.raw) {\n adapterResponse.data = records\n } else {\n adapterResponse = records\n }\n const result = this._end(adapterResponse, opts)\n opts.op = 'afterCreateMany'\n return this._runHook(opts.op, records, opts, result)\n })\n },\n\n /**\n * Create an unsaved, uncached instance of this Mapper's\n * {@link Mapper#recordClass}.\n *\n * Returns `props` if `props` is already an instance of\n * {@link Mapper#recordClass}.\n *\n * __Note:__ This method does __not__ interact with any adapter, and does\n * __not__ save any data. It only creates new objects in memory.\n *\n * @example\n * // Create empty unsaved record instance\n * const post = PostMapper.createRecord();\n *\n * @example\n * // Create an unsaved record instance with inital properties\n * const post = PostMapper.createRecord({\n * title: 'Modeling your data',\n * status: 'draft'\n * });\n *\n * @example\n * // Create a record instance that corresponds to a saved record\n * const post = PostMapper.createRecord({\n * // JSData thinks this record has been saved if it has a primary key\n * id: 1234,\n * title: 'Modeling your data',\n * status: 'draft'\n * });\n *\n * @example\n * // Create record instances from an array\n * const posts = PostMapper.createRecord([{\n * title: 'Modeling your data',\n * status: 'draft'\n * }, {\n * title: 'Reading data',\n * status: 'draft'\n * }]);\n *\n * @example\n * // Records are validated by default\n * import { Mapper } from 'js-data';\n * const PostMapper = new Mapper({\n * name: 'post',\n * schema: { properties: { title: { type: 'string' } } }\n * });\n * try {\n * const post = PostMapper.createRecord({\n * title: 1234,\n * });\n * } catch (err) {\n * console.log(err.errors); // [{ expected: 'one of (string)', actual: 'number', path: 'title' }]\n * }\n *\n * @example\n * // Skip validation\n * import { Mapper } from 'js-data';\n * const PostMapper = new Mapper({\n * name: 'post',\n * schema: { properties: { title: { type: 'string' } } }\n * });\n * const post = PostMapper.createRecord({\n * title: 1234,\n * }, { noValidate: true });\n * console.log(post.isValid()); // false\n *\n * @method Mapper#createRecord\n * @param {Object|Object[]} props The properties for the Record instance or an\n * array of property objects for the Record instances.\n * @param {object} [opts] Configuration options.\n * @param {boolean} [opts.noValidate={@link Mapper#noValidate}] See {@link Mapper#noValidate}.\n * @returns {Record|Record[]} The Record instance or Record instances.\n * @since 3.0.0\n */\n createRecord (props, opts) {\n props || (props = {})\n if (utils.isArray(props)) {\n return props.map((_props) => this.createRecord(_props, opts))\n }\n if (!utils.isObject(props)) {\n throw utils.err(`${DOMAIN}#createRecord`, 'props')(400, 'array or object', props)\n }\n\n if (this.relationList) {\n this.relationList.forEach(function (def) {\n def.ensureLinkedDataHasProperType(props, opts)\n })\n }\n const RecordCtor = this.recordClass\n\n return (!RecordCtor || props instanceof RecordCtor) ? props : new RecordCtor(props, opts)\n },\n\n /**\n * Lifecycle invocation method. You probably won't call this method directly.\n *\n * @method Mapper#crud\n * @param {string} method Name of the lifecycle method to invoke.\n * @param {...*} args Arguments to pass to the lifecycle method.\n * @returns {Promise}\n * @since 3.0.0\n */\n crud (method, ...args) {\n const config = this.lifecycleMethods[method]\n if (!config) {\n throw utils.err(`${DOMAIN}#crud`, method)(404, 'method')\n }\n\n const upper = `${method.charAt(0).toUpperCase()}${method.substr(1)}`\n const before = `before${upper}`\n const after = `after${upper}`\n\n let op\n\n // Default values for arguments\n config.defaults.forEach((value, i) => {\n if (args[i] === undefined) {\n args[i] = utils.copy(value)\n }\n })\n\n const opts = args[args.length - 1]\n\n // Fill in \"opts\" with the Mapper's configuration\n utils._(opts, this)\n const adapter = opts.adapter = this.getAdapterName(opts)\n\n // before lifecycle hook\n op = opts.op = before\n return utils.resolve(this[op](...args)).then((_value) => {\n if (args[config.beforeAssign] !== undefined) {\n // Allow for re-assignment from lifecycle hook\n args[config.beforeAssign] = _value === undefined ? args[config.beforeAssign] : _value\n }\n // Now delegate to the adapter\n op = opts.op = method\n args = config.adapterArgs ? config.adapterArgs(this, ...args) : args\n this.dbg(op, ...args)\n return utils.resolve(this.getAdapter(adapter)[op](this, ...args))\n }).then((result) => {\n // force noValidate on find/findAll\n const noValidate = /find/.test(op) || opts.noValidate\n const _opts = Object.assign({}, opts, { noValidate })\n\n result = this._end(result, _opts, !!config.skip)\n args.push(result)\n // after lifecycle hook\n op = opts.op = after\n return utils.resolve(this[op](...args)).then((_result) => {\n // Allow for re-assignment from lifecycle hook\n return _result === undefined ? result : _result\n })\n })\n },\n\n /**\n * Fired during {@link Mapper#destroy}. See\n * {@link Mapper~beforeDestroyListener} for how to listen for this event.\n *\n * @event Mapper#beforeDestroy\n * @see Mapper~beforeDestroyListener\n * @see Mapper#destroy\n */\n /**\n * Callback signature for the {@link Mapper#event:beforeDestroy} event.\n *\n * @example\n * function onBeforeDestroy (id, opts) {\n * // do something\n * }\n * store.on('beforeDestroy', onBeforeDestroy);\n *\n * @callback Mapper~beforeDestroyListener\n * @param {string|number} id The `id` argument passed to {@link Mapper#beforeDestroy}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#beforeDestroy}.\n * @see Mapper#event:beforeDestroy\n * @see Mapper#destroy\n * @since 3.0.0\n */\n /**\n * Fired during {@link Mapper#destroy}. See\n * {@link Mapper~afterDestroyListener} for how to listen for this event.\n *\n * @event Mapper#afterDestroy\n * @see Mapper~afterDestroyListener\n * @see Mapper#destroy\n */\n /**\n * Callback signature for the {@link Mapper#event:afterDestroy} event.\n *\n * @example\n * function onAfterDestroy (id, opts, result) {\n * // do something\n * }\n * store.on('afterDestroy', onAfterDestroy);\n *\n * @callback Mapper~afterDestroyListener\n * @param {string|number} id The `id` argument passed to {@link Mapper#afterDestroy}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#afterDestroy}.\n * @param {object} result The `result` argument passed to {@link Mapper#afterDestroy}.\n * @see Mapper#event:afterDestroy\n * @see Mapper#destroy\n * @since 3.0.0\n */\n /**\n * Using an adapter, destroy the record with the given primary key.\n *\n * {@link Mapper#beforeDestroy} will be called before destroying the record.\n * {@link Mapper#afterDestroy} will be called after destroying the record.\n *\n * @example\n * // Destroy a specific blog post\n * PostMapper.destroy(1234).then(() => {\n * // Blog post #1234 has been destroyed\n * });\n *\n * @example\n * // Get full response\n * PostMapper.destroy(1234, { raw: true }).then((result) => {\n * console.log(result.deleted); e.g. 1\n * console.log(...); // etc., more metadata can be found on the result\n * });\n *\n * @fires Mapper#beforeDestroy\n * @fires Mapper#afterDestroy\n * @method Mapper#destroy\n * @param {(string|number)} id The primary key of the record to destroy.\n * @param {object} [opts] Configuration options. Refer to the `destroy` method\n * of whatever adapter you're using for more configuration options.\n * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the\n * adapter to use.\n * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}.\n * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}.\n * @returns {Promise} Resolves when the record has been destroyed. Resolves\n * even if no record was found to be destroyed.\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/saving-data\",\"Saving data\"]\n */\n destroy (id, opts) {\n return this.crud('destroy', id, opts)\n },\n\n /**\n * Fired during {@link Mapper#destroyAll}. See\n * {@link Mapper~beforeDestroyAllListener} for how to listen for this event.\n *\n * @event Mapper#beforeDestroyAll\n * @see Mapper~beforeDestroyAllListener\n * @see Mapper#destroyAll\n */\n /**\n * Callback signature for the {@link Mapper#event:beforeDestroyAll} event.\n *\n * @example\n * function onBeforeDestroyAll (query, opts) {\n * // do something\n * }\n * store.on('beforeDestroyAll', onBeforeDestroyAll);\n *\n * @callback Mapper~beforeDestroyAllListener\n * @param {object} query The `query` argument passed to {@link Mapper#beforeDestroyAll}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#beforeDestroyAll}.\n * @see Mapper#event:beforeDestroyAll\n * @see Mapper#destroyAll\n * @since 3.0.0\n */\n /**\n * Fired during {@link Mapper#destroyAll}. See\n * {@link Mapper~afterDestroyAllListener} for how to listen for this event.\n *\n * @event Mapper#afterDestroyAll\n * @see Mapper~afterDestroyAllListener\n * @see Mapper#destroyAll\n */\n /**\n * Callback signature for the {@link Mapper#event:afterDestroyAll} event.\n *\n * @example\n * function onAfterDestroyAll (query, opts, result) {\n * // do something\n * }\n * store.on('afterDestroyAll', onAfterDestroyAll);\n *\n * @callback Mapper~afterDestroyAllListener\n * @param {object} query The `query` argument passed to {@link Mapper#afterDestroyAll}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#afterDestroyAll}.\n * @param {object} result The `result` argument passed to {@link Mapper#afterDestroyAll}.\n * @see Mapper#event:afterDestroyAll\n * @see Mapper#destroyAll\n * @since 3.0.0\n */\n /**\n * Destroy the records selected by `query` via an adapter. If no `query` is\n * provided then all records will be destroyed.\n *\n * {@link Mapper#beforeDestroyAll} will be called before destroying the records.\n * {@link Mapper#afterDestroyAll} will be called after destroying the records.\n *\n * @example\n * // Destroy all blog posts\n * PostMapper.destroyAll().then(() => {\n * // All blog posts have been destroyed\n * });\n *\n * @example\n * // Destroy all \"draft\" blog posts\n * PostMapper.destroyAll({ status: 'draft' }).then(() => {\n * // All \"draft\" blog posts have been destroyed\n * });\n *\n * @example\n * // Get full response\n * const query = null;\n * const options = { raw: true };\n * PostMapper.destroyAll(query, options).then((result) => {\n * console.log(result.deleted); e.g. 14\n * console.log(...); // etc., more metadata can be found on the result\n * });\n *\n * @fires Mapper#beforeDestroyAll\n * @fires Mapper#afterDestroyAll\n * @method Mapper#destroyAll\n * @param {object} [query={}] Selection query. See {@link query}.\n * @param {object} [query.where] See {@link query.where}.\n * @param {number} [query.offset] See {@link query.offset}.\n * @param {number} [query.limit] See {@link query.limit}.\n * @param {string|Array[]} [query.orderBy] See {@link query.orderBy}.\n * @param {object} [opts] Configuration options. Refer to the `destroyAll`\n * method of whatever adapter you're using for more configuration options.\n * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the\n * adapter to use.\n * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}.\n * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}.\n * @returns {Promise} Resolves when the records have been destroyed. Resolves\n * even if no records were found to be destroyed.\n * @see query\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/saving-data\",\"Saving data\"]\n */\n destroyAll (query, opts) {\n return this.crud('destroyAll', query, opts)\n },\n\n /**\n * Fired during {@link Mapper#find}. See\n * {@link Mapper~beforeFindListener} for how to listen for this event.\n *\n * @event Mapper#beforeFind\n * @see Mapper~beforeFindListener\n * @see Mapper#find\n */\n /**\n * Callback signature for the {@link Mapper#event:beforeFind} event.\n *\n * @example\n * function onBeforeFind (id, opts) {\n * // do something\n * }\n * store.on('beforeFind', onBeforeFind);\n *\n * @callback Mapper~beforeFindListener\n * @param {string|number} id The `id` argument passed to {@link Mapper#beforeFind}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#beforeFind}.\n * @see Mapper#event:beforeFind\n * @see Mapper#find\n * @since 3.0.0\n */\n /**\n * Fired during {@link Mapper#find}. See\n * {@link Mapper~afterFindListener} for how to listen for this event.\n *\n * @event Mapper#afterFind\n * @see Mapper~afterFindListener\n * @see Mapper#find\n */\n /**\n * Callback signature for the {@link Mapper#event:afterFind} event.\n *\n * @example\n * function onAfterFind (id, opts, result) {\n * // do something\n * }\n * store.on('afterFind', onAfterFind);\n *\n * @callback Mapper~afterFindListener\n * @param {string|number} id The `id` argument passed to {@link Mapper#afterFind}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#afterFind}.\n * @param {object} result The `result` argument passed to {@link Mapper#afterFind}.\n * @see Mapper#event:afterFind\n * @see Mapper#find\n * @since 3.0.0\n */\n /**\n * Retrieve via an adapter the record with the given primary key.\n *\n * {@link Mapper#beforeFind} will be called before calling the adapter.\n * {@link Mapper#afterFind} will be called after calling the adapter.\n *\n * @example\n * PostMapper.find(1).then((post) => {\n * console.log(post); // { id: 1, ...}\n * });\n *\n * @example\n * // Get full response\n * PostMapper.find(1, { raw: true }).then((result) => {\n * console.log(result.data); // { id: 1, ...}\n * console.log(result.found); // 1\n * console.log(...); // etc., more metadata can be found on the result\n * });\n *\n * @fires Mapper#beforeFind\n * @fires Mapper#afterFind\n * @method Mapper#find\n * @param {(string|number)} id The primary key of the record to retrieve.\n * @param {object} [opts] Configuration options. Refer to the `find` method\n * of whatever adapter you're using for more configuration options.\n * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the\n * adapter to use.\n * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}.\n * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}.\n * @param {string[]} [opts.with=[]] Relations to eager load in the request.\n * @returns {Promise} Resolves with the found record. Resolves with\n * `undefined` if no record was found.\n * @see http://www.js-data.io/v3.0/docs/reading-data\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/reading-data\",\"Reading data\"]\n */\n find (id, opts) {\n return this.crud('find', id, opts)\n },\n\n /**\n * Fired during {@link Mapper#findAll}. See\n * {@link Mapper~beforeFindAllListener} for how to listen for this event.\n *\n * @event Mapper#beforeFindAll\n * @see Mapper~beforeFindAllListener\n * @see Mapper#findAll\n */\n /**\n * Callback signature for the {@link Mapper#event:beforeFindAll} event.\n *\n * @example\n * function onBeforeFindAll (query, opts) {\n * // do something\n * }\n * store.on('beforeFindAll', onBeforeFindAll);\n *\n * @callback Mapper~beforeFindAllListener\n * @param {object} query The `query` argument passed to {@link Mapper#beforeFindAll}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#beforeFindAll}.\n * @see Mapper#event:beforeFindAll\n * @see Mapper#findAll\n * @since 3.0.0\n */\n /**\n * Fired during {@link Mapper#findAll}. See\n * {@link Mapper~afterFindAllListener} for how to listen for this event.\n *\n * @event Mapper#afterFindAll\n * @see Mapper~afterFindAllListener\n * @see Mapper#findAll\n */\n /**\n * Callback signature for the {@link Mapper#event:afterFindAll} event.\n *\n * @example\n * function onAfterFindAll (query, opts, result) {\n * // do something\n * }\n * store.on('afterFindAll', onAfterFindAll);\n *\n * @callback Mapper~afterFindAllListener\n * @param {object} query The `query` argument passed to {@link Mapper#afterFindAll}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#afterFindAll}.\n * @param {object} result The `result` argument passed to {@link Mapper#afterFindAll}.\n * @see Mapper#event:afterFindAll\n * @see Mapper#findAll\n * @since 3.0.0\n */\n /**\n * Using the `query` argument, select records to retrieve via an adapter.\n *\n * {@link Mapper#beforeFindAll} will be called before calling the adapter.\n * {@link Mapper#afterFindAll} will be called after calling the adapter.\n *\n * @example\n * // Find all \"published\" blog posts\n * PostMapper.findAll({ status: 'published' }).then((posts) => {\n * console.log(posts); // [{ id: 1, status: 'published', ...}, ...]\n * });\n *\n * @example\n * // Get full response\n * PostMapper.findAll({ status: 'published' }, { raw: true }).then((result) => {\n * console.log(result.data); // [{ id: 1, status: 'published', ...}, ...]\n * console.log(result.found); // e.g. 13\n * console.log(...); // etc., more metadata can be found on the result\n * });\n *\n * @fires Mapper#beforeFindAll\n * @fires Mapper#afterFindAll\n * @method Mapper#findAll\n * @param {object} [query={}] Selection query. See {@link query}.\n * @param {object} [query.where] See {@link query.where}.\n * @param {number} [query.offset] See {@link query.offset}.\n * @param {number} [query.limit] See {@link query.limit}.\n * @param {string|Array[]} [query.orderBy] See {@link query.orderBy}.\n * @param {object} [opts] Configuration options. Refer to the `findAll` method\n * of whatever adapter you're using for more configuration options.\n * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the\n * adapter to use.\n * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}.\n * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}.\n * @param {string[]} [opts.with=[]] Relations to eager load in the request.\n * @returns {Promise} Resolves with the found records, if any.\n * @see query\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/reading-data\",\"Reading data\"]\n */\n findAll (query, opts) {\n return this.crud('findAll', query, opts)\n },\n\n /**\n * Return the registered adapter with the given name or the default adapter if\n * no name is provided.\n *\n * @method Mapper#getAdapter\n * @param {string} [name] The name of the adapter to retrieve.\n * @returns {Adapter} The adapter.\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/connecting-to-a-data-source\",\"Connecting to a data source\"]\n */\n getAdapter (name) {\n this.dbg('getAdapter', 'name:', name)\n const adapter = this.getAdapterName(name)\n if (!adapter) {\n throw utils.err(`${DOMAIN}#getAdapter`, 'name')(400, 'string', name)\n }\n return this.getAdapters()[adapter]\n },\n\n /**\n * Return the name of a registered adapter based on the given name or options,\n * or the name of the default adapter if no name provided.\n *\n * @method Mapper#getAdapterName\n * @param {(Object|string)} [opts] The name of an adapter or options, if any.\n * @returns {string} The name of the adapter.\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/connecting-to-a-data-source\",\"Connecting to a data source\"]\n */\n getAdapterName (opts) {\n opts || (opts = {})\n if (utils.isString(opts)) {\n opts = { adapter: opts }\n }\n return opts.adapter || opts.defaultAdapter\n },\n\n /**\n * Get the object of registered adapters for this Mapper.\n *\n * @method Mapper#getAdapters\n * @returns {Object} {@link Mapper#_adapters}\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/connecting-to-a-data-source\",\"Connecting to a data source\"]\n */\n getAdapters () {\n return this._adapters\n },\n\n /**\n * Returns this Mapper's {@link Schema}.\n *\n * @method Mapper#getSchema\n * @returns {Schema} This Mapper's {@link Schema}.\n * @see Mapper#schema\n * @since 3.0.0\n */\n getSchema () {\n return this.schema\n },\n\n /**\n * Defines a hasMany relationship. Only useful if you're managing your\n * Mappers manually and not using a Container or DataStore component.\n *\n * @example\n * UserMapper.hasMany(PostMapper, {\n * // post.user_id points to user.id\n * foreignKey: 'user_id'\n * // post records will be attached to user records at \"user.posts\"\n * localField: 'posts'\n * });\n *\n * @method Mapper#hasMany\n * @see http://www.js-data.io/v3.0/docs/relations\n * @since 3.0.0\n */\n hasMany (relatedMapper, opts) {\n return hasMany(relatedMapper, opts)(this)\n },\n\n /**\n * Defines a hasOne relationship. Only useful if you're managing your Mappers\n * manually and not using a {@link Container} or {@link DataStore} component.\n *\n * @example\n * UserMapper.hasOne(ProfileMapper, {\n * // profile.user_id points to user.id\n * foreignKey: 'user_id'\n * // profile records will be attached to user records at \"user.profile\"\n * localField: 'profile'\n * });\n *\n * @method Mapper#hasOne\n * @see http://www.js-data.io/v3.0/docs/relations\n * @since 3.0.0\n */\n hasOne (relatedMapper, opts) {\n return hasOne(relatedMapper, opts)(this)\n },\n\n /**\n * Return whether `record` is an instance of this Mapper's recordClass.\n *\n * @example\n * const post = PostMapper.createRecord();\n *\n * console.log(PostMapper.is(post)); // true\n * // Equivalent to what's above\n * console.log(post instanceof PostMapper.recordClass); // true\n *\n * @method Mapper#is\n * @param {Object|Record} record The record to check.\n * @returns {boolean} Whether `record` is an instance of this Mapper's\n * {@link Mapper#recordClass}.\n * @since 3.0.0\n */\n is (record) {\n const recordClass = this.recordClass\n return recordClass ? record instanceof recordClass : false\n },\n\n /**\n * Register an adapter on this Mapper under the given name.\n *\n * @method Mapper#registerAdapter\n * @param {string} name The name of the adapter to register.\n * @param {Adapter} adapter The adapter to register.\n * @param {object} [opts] Configuration options.\n * @param {boolean} [opts.default=false] Whether to make the adapter the\n * default adapter for this Mapper.\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/connecting-to-a-data-source\",\"Connecting to a data source\"]\n */\n registerAdapter (name, adapter, opts) {\n opts || (opts = {})\n this.getAdapters()[name] = adapter\n // Optionally make it the default adapter for the target.\n if (opts === true || opts.default) {\n this.defaultAdapter = name\n }\n },\n\n _runHook (hookName, ...hookArgs) {\n const defaultValueIndex = hookName.indexOf('after') === 0 ? hookArgs.length - 1 : 0\n\n return utils.resolve(this[hookName](...hookArgs))\n .then((overridenResult) => overridenResult === undefined ? hookArgs[defaultValueIndex] : overridenResult)\n },\n\n _invokeAdapterMethod (method, propsOrRecords, opts) {\n const conversionOptions = { with: opts.pass || [] }\n let object\n\n this.dbg(opts.op, propsOrRecords, opts)\n\n if (utils.isArray(propsOrRecords)) {\n object = propsOrRecords.map(record => this.toJSON(record, conversionOptions))\n } else {\n object = this.toJSON(propsOrRecords, conversionOptions)\n }\n\n return this.getAdapter(opts.adapter)[method](this, object, opts)\n },\n\n /**\n * Select records according to the `query` argument, and aggregate the sum\n * value of the property specified by `field`.\n *\n * {@link Mapper#beforeSum} will be called before calling the adapter.\n * {@link Mapper#afterSum} will be called after calling the adapter.\n *\n * @example\n * PurchaseOrderMapper.sum('amount', { status: 'paid' }).then((amountPaid) => {\n * console.log(amountPaid); // e.g. 451125.34\n * });\n *\n * @method Mapper#sum\n * @param {string} field The field to sum.\n * @param {object} [query={}] Selection query. See {@link query}.\n * @param {object} [query.where] See {@link query.where}.\n * @param {number} [query.offset] See {@link query.offset}.\n * @param {number} [query.limit] See {@link query.limit}.\n * @param {string|Array[]} [query.orderBy] See {@link query.orderBy}.\n * @param {object} [opts] Configuration options. Refer to the `sum` method\n * of whatever adapter you're using for more configuration options.\n * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the\n * adapter to use.\n * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}.\n * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}.\n * @returns {Promise} Resolves with the aggregated sum.\n * @since 3.0.0\n */\n sum (field, query, opts) {\n return this.crud('sum', field, query, opts)\n },\n\n /**\n * Return a plain object representation of the given record. Relations can\n * be optionally be included. Non-schema properties can be excluded.\n *\n * @example\n * import { Mapper, Schema } from 'js-data';\n * const PersonMapper = new Mapper({\n * name: 'person',\n * schema: {\n * properties: {\n * name: { type: 'string' },\n * id: { type: 'string' }\n * }\n * }\n * });\n * const person = PersonMapper.createRecord({ id: 1, name: 'John', foo: 'bar' });\n * // \"foo\" is stripped by toJSON()\n * console.log(PersonMapper.toJSON(person)); // {\"id\":1,\"name\":\"John\"}\n *\n * const PersonRelaxedMapper = new Mapper({\n * name: 'personRelaxed',\n * schema: {\n * properties: {\n * name: { type: 'string' },\n * id: { type: 'string' }\n * },\n * additionalProperties: true\n * }\n * });\n * const person2 = PersonRelaxedMapper.createRecord({ id: 1, name: 'John', foo: 'bar' });\n * // \"foo\" is not stripped by toJSON\n * console.log(PersonRelaxedMapper.toJSON(person2)); // {\"id\":1,\"name\":\"John\",\"foo\":\"bar\"}\n *\n * @method Mapper#toJSON\n * @param {Record|Record[]} records Record or records from which to create a\n * POJO representation.\n * @param {object} [opts] Configuration options.\n * @param {string[]} [opts.with] Array of relation names or relation fields\n * to include in the POJO representation.\n * @param {boolean} [opts.withAll] Whether to simply include all relations in\n * the representation. Overrides `opts.with`.\n * @returns {Object|Object[]} POJO representation of the record or records.\n * @since 3.0.0\n */\n toJSON (records, opts) {\n let record\n opts || (opts = {})\n if (utils.isArray(records)) {\n return records.map((record) => this.toJSON(record, opts))\n } else {\n record = records\n }\n const relationFields = (this ? this.relationFields : []) || []\n let json = {}\n\n // Copy properties defined in the schema\n if (this && this.schema) {\n json = this.schema.pick(record)\n } else {\n for (var key in record) {\n if (relationFields.indexOf(key) === -1) {\n json[key] = utils.plainCopy(record[key])\n }\n }\n }\n\n // The user wants to include relations in the resulting plain object representation\n if (this && opts.withAll) {\n opts.with = relationFields.slice()\n }\n if (this && opts.with) {\n if (utils.isString(opts.with)) {\n opts.with = [opts.with]\n }\n utils.forEachRelation(this, opts, (def, optsCopy) => {\n const relationData = def.getLocalField(record)\n if (relationData) {\n // The actual recursion\n if (utils.isArray(relationData)) {\n def.setLocalField(json, relationData.map((item) => {\n return def.getRelation().toJSON(item, optsCopy)\n }))\n } else {\n def.setLocalField(json, def.getRelation().toJSON(relationData, optsCopy))\n }\n }\n })\n }\n return json\n },\n\n /**\n * Fired during {@link Mapper#update}. See\n * {@link Mapper~beforeUpdateListener} for how to listen for this event.\n *\n * @event Mapper#beforeUpdate\n * @see Mapper~beforeUpdateListener\n * @see Mapper#update\n */\n /**\n * Callback signature for the {@link Mapper#event:beforeUpdate} event.\n *\n * @example\n * function onBeforeUpdate (id, props, opts) {\n * // do something\n * }\n * store.on('beforeUpdate', onBeforeUpdate);\n *\n * @callback Mapper~beforeUpdateListener\n * @param {string|number} id The `id` argument passed to {@link Mapper#beforeUpdate}.\n * @param {object} props The `props` argument passed to {@link Mapper#beforeUpdate}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#beforeUpdate}.\n * @see Mapper#event:beforeUpdate\n * @see Mapper#update\n * @since 3.0.0\n */\n /**\n * Fired during {@link Mapper#update}. See\n * {@link Mapper~afterUpdateListener} for how to listen for this event.\n *\n * @event Mapper#afterUpdate\n * @see Mapper~afterUpdateListener\n * @see Mapper#update\n */\n /**\n * Callback signature for the {@link Mapper#event:afterUpdate} event.\n *\n * @example\n * function onAfterUpdate (id, props, opts, result) {\n * // do something\n * }\n * store.on('afterUpdate', onAfterUpdate);\n *\n * @callback Mapper~afterUpdateListener\n * @param {string|number} id The `id` argument passed to {@link Mapper#afterUpdate}.\n * @param {object} props The `props` argument passed to {@link Mapper#afterUpdate}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#afterUpdate}.\n * @param {object} result The `result` argument passed to {@link Mapper#afterUpdate}.\n * @see Mapper#event:afterUpdate\n * @see Mapper#update\n * @since 3.0.0\n */\n /**\n * Using an adapter, update the record with the primary key specified by the\n * `id` argument.\n *\n * {@link Mapper#beforeUpdate} will be called before updating the record.\n * {@link Mapper#afterUpdate} will be called after updating the record.\n *\n * @example\n * // Update a specific post\n * PostMapper.update(1234, {\n * status: 'published',\n * published_at: new Date()\n * }).then((post) => {\n * console.log(post); // { id: 1234, status: 'published', ... }\n * });\n *\n * @fires Mapper#beforeUpdate\n * @fires Mapper#afterUpdate\n * @method Mapper#update\n * @param {(string|number)} id The primary key of the record to update.\n * @param {object} props The update to apply to the record.\n * @param {object} [opts] Configuration options. Refer to the `update` method\n * of whatever adapter you're using for more configuration options.\n * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the\n * adapter to use.\n * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}.\n * @param {boolean} [opts.noValidate={@link Mapper#noValidate}] See {@link Mapper#noValidate}.\n * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}.\n * transaction.\n * @returns {Promise} Resolves with the updated record. Rejects if the record\n * could not be found.\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/saving-data\",\"Saving data\"]\n */\n update (id, props, opts) {\n return this.crud('update', id, props, opts)\n },\n\n /**\n * Fired during {@link Mapper#updateAll}. See\n * {@link Mapper~beforeUpdateAllListener} for how to listen for this event.\n *\n * @event Mapper#beforeUpdateAll\n * @see Mapper~beforeUpdateAllListener\n * @see Mapper#updateAll\n */\n /**\n * Callback signature for the {@link Mapper#event:beforeUpdateAll} event.\n *\n * @example\n * function onBeforeUpdateAll (props, query, opts) {\n * // do something\n * }\n * store.on('beforeUpdateAll', onBeforeUpdateAll);\n *\n * @callback Mapper~beforeUpdateAllListener\n * @param {object} props The `props` argument received by {@link Mapper#beforeUpdateAll}.\n * @param {object} query The `query` argument received by {@link Mapper#beforeUpdateAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdateAll}.\n * @see Mapper#event:beforeUpdateAll\n * @see Mapper#updateAll\n * @since 3.0.0\n */\n /**\n * Fired during {@link Mapper#updateAll}. See\n * {@link Mapper~afterUpdateAllListener} for how to listen for this event.\n *\n * @event Mapper#afterUpdateAll\n * @see Mapper~afterUpdateAllListener\n * @see Mapper#updateAll\n */\n /**\n * Callback signature for the {@link Mapper#event:afterUpdateAll} event.\n *\n * @example\n * function onAfterUpdateAll (props, query, opts, result) {\n * // do something\n * }\n * store.on('afterUpdateAll', onAfterUpdateAll);\n *\n * @callback Mapper~afterUpdateAllListener\n * @param {object} props The `props` argument received by {@link Mapper#afterUpdateAll}.\n * @param {object} query The `query` argument received by {@link Mapper#afterUpdateAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdateAll}.\n * @param {object} result The `result` argument received by {@link Mapper#afterUpdateAll}.\n * @see Mapper#event:afterUpdateAll\n * @see Mapper#updateAll\n * @since 3.0.0\n */\n /**\n * Using the `query` argument, perform the a single updated to the selected\n * records.\n *\n * {@link Mapper#beforeUpdateAll} will be called before making the update.\n * {@link Mapper#afterUpdateAll} will be called after making the update.\n *\n * @example\n * // Turn all of John's blog posts into drafts.\n * const update = { status: draft: published_at: null };\n * const query = { userId: 1234 };\n * PostMapper.updateAll(update, query).then((posts) => {\n * console.log(posts); // [...]\n * });\n *\n * @fires Mapper#beforeUpdateAll\n * @fires Mapper#afterUpdateAll\n * @method Mapper#updateAll\n * @param {object} props Update to apply to selected records.\n * @param {object} [query={}] Selection query. See {@link query}.\n * @param {object} [query.where] See {@link query.where}.\n * @param {number} [query.offset] See {@link query.offset}.\n * @param {number} [query.limit] See {@link query.limit}.\n * @param {string|Array[]} [query.orderBy] See {@link query.orderBy}.\n * @param {object} [opts] Configuration options. Refer to the `updateAll`\n * method of whatever adapter you're using for more configuration options.\n * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the\n * adapter to use.\n * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}.\n * @param {boolean} [opts.noValidate={@link Mapper#noValidate}] See {@link Mapper#noValidate}.\n * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}.\n * @returns {Promise} Resolves with the update records, if any.\n * @see query\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/saving-data\",\"Saving data\"]\n */\n updateAll (props, query, opts) {\n return this.crud('updateAll', props, query, opts)\n },\n\n /**\n * Fired during {@link Mapper#updateMany}. See\n * {@link Mapper~beforeUpdateManyListener} for how to listen for this event.\n *\n * @event Mapper#beforeUpdateMany\n * @see Mapper~beforeUpdateManyListener\n * @see Mapper#updateMany\n */\n /**\n * Callback signature for the {@link Mapper#event:beforeUpdateMany} event.\n *\n * @example\n * function onBeforeUpdateMany (records, opts) {\n * // do something\n * }\n * store.on('beforeUpdateMany', onBeforeUpdateMany);\n *\n * @callback Mapper~beforeUpdateManyListener\n * @param {object} records The `records` argument received by {@link Mapper#beforeUpdateMany}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdateMany}.\n * @see Mapper#event:beforeUpdateMany\n * @see Mapper#updateMany\n * @since 3.0.0\n */\n /**\n * Fired during {@link Mapper#updateMany}. See\n * {@link Mapper~afterUpdateManyListener} for how to listen for this event.\n *\n * @event Mapper#afterUpdateMany\n * @see Mapper~afterUpdateManyListener\n * @see Mapper#updateMany\n */\n /**\n * Callback signature for the {@link Mapper#event:afterUpdateMany} event.\n *\n * @example\n * function onAfterUpdateMany (records, opts, result) {\n * // do something\n * }\n * store.on('afterUpdateMany', onAfterUpdateMany);\n *\n * @callback Mapper~afterUpdateManyListener\n * @param {object} records The `records` argument received by {@link Mapper#afterUpdateMany}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdateMany}.\n * @param {object} result The `result` argument received by {@link Mapper#afterUpdateMany}.\n * @see Mapper#event:afterUpdateMany\n * @see Mapper#updateMany\n * @since 3.0.0\n */\n /**\n * Given an array of updates, perform each of the updates via an adapter. Each\n * \"update\" is a hash of properties with which to update an record. Each\n * update must contain the primary key of the record to be updated.\n *\n * {@link Mapper#beforeUpdateMany} will be called before making the update.\n * {@link Mapper#afterUpdateMany} will be called after making the update.\n *\n * @example\n * PostMapper.updateMany([\n * { id: 1234, status: 'draft' },\n * { id: 2468, status: 'published', published_at: new Date() }\n * ]).then((posts) => {\n * console.log(posts); // [...]\n * });\n *\n * @fires Mapper#beforeUpdateMany\n * @fires Mapper#afterUpdateMany\n * @method Mapper#updateMany\n * @param {Record[]} records Array up record updates.\n * @param {object} [opts] Configuration options. Refer to the `updateMany`\n * method of whatever adapter you're using for more configuration options.\n * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the\n * adapter to use.\n * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}.\n * @param {boolean} [opts.noValidate={@link Mapper#noValidate}] See {@link Mapper#noValidate}.\n * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}.\n * @returns {Promise} Resolves with the updated records. Rejects if any of the\n * records could be found.\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/saving-data\",\"Saving data\"]\n */\n updateMany (records, opts) {\n return this.crud('updateMany', records, opts)\n },\n\n /**\n * Validate the given record or records according to this Mapper's\n * {@link Schema}. If there are no validation errors then the return value\n * will be `undefined`.\n *\n * @example\n * import {Mapper, Schema} from 'js-data'\n * const PersonSchema = new Schema({\n * properties: {\n * name: { type: 'string' },\n * id: { type: 'string' }\n * }\n * });\n * const PersonMapper = new Mapper({\n * name: 'person',\n * schema: PersonSchema\n * });\n * let errors = PersonMapper.validate({ name: 'John' });\n * console.log(errors); // undefined\n * errors = PersonMapper.validate({ name: 123 });\n * console.log(errors); // [{ expected: 'one of (string)', actual: 'number', path: 'name' }]\n *\n * @method Mapper#validate\n * @param {Object|Object[]} record The record or records to validate.\n * @param {object} [opts] Configuration options. Passed to\n * {@link Schema#validate}.\n * @returns {Object[]} Array of errors or `undefined` if no errors.\n * @since 3.0.0\n */\n validate (record, opts) {\n opts || (opts = {})\n const schema = this.getSchema()\n if (!schema) {\n return\n }\n const _opts = utils.pick(opts, ['existingOnly'])\n if (utils.isArray(record)) {\n const errors = record.map((_record) => schema.validate(_record, utils.pick(_opts, ['existingOnly'])))\n\n return errors.some(Boolean) ? errors : undefined\n }\n return schema.validate(record, _opts)\n },\n\n /**\n * Method used to wrap data returned by an adapter with this Mapper's\n * {@link Mapper#recordClass}. This method is used by all of a Mapper's CRUD\n * methods. The provided implementation of this method assumes that the `data`\n * passed to it is a record or records that need to be wrapped with\n * {@link Mapper#createRecord}. Override with care.\n *\n * Provided implementation of {@link Mapper#wrap}:\n *\n * ```\n * function (data, opts) {\n * return this.createRecord(data, opts);\n * }\n * ```\n *\n * @example\n * const PostMapper = new Mapper({\n * name: 'post',\n * // Override to customize behavior\n * wrap (data, opts) {\n * const originalWrap = this.constructor.prototype.wrap;\n * // Let's say \"GET /post\" doesn't return JSON quite like JSData expects,\n * // but the actual post records are nested under a \"posts\" field. So,\n * // we override Mapper#wrap to handle this special case.\n * if (opts.op === 'findAll') {\n * return originalWrap.call(this, data.posts, opts);\n * }\n * // Otherwise perform original behavior\n * return originalWrap.call(this, data, opts);\n * }\n * });\n *\n * @method Mapper#wrap\n * @param {Object|Object[]} data The record or records to be wrapped.\n * @param {object} [opts] Configuration options. Passed to {@link Mapper#createRecord}.\n * @returns {Record|Record[]} The wrapped record or records.\n * @since 3.0.0\n */\n wrap (data, opts) {\n return this.createRecord(data, opts)\n },\n\n /**\n * @ignore\n */\n defineRelations () {\n // Setup the mapper's relations, including generating Mapper#relationList\n // and Mapper#relationFields\n utils.forOwn(this.relations, (group, type) => {\n utils.forOwn(group, (relations, _name) => {\n if (utils.isObject(relations)) {\n relations = [relations]\n }\n relations.forEach((def) => {\n const relatedMapper = this.datastore.getMapperByName(_name) || _name\n def.getRelation = () => this.datastore.getMapper(_name)\n\n if (typeof Relation[type] !== 'function') {\n throw utils.err(DOMAIN, 'defineRelations')(400, 'relation type (hasOne, hasMany, etc)', type, true)\n }\n\n this[type](relatedMapper, def)\n })\n })\n })\n }\n})\n\n/**\n * Create a subclass of this Mapper:\n *\n * @example Mapper.extend\n * const JSData = require('js-data');\n * const { Mapper } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * // Extend the class using ES2015 class syntax.\n * class CustomMapperClass extends Mapper {\n * foo () { return 'bar'; }\n * static beep () { return 'boop'; }\n * };\n * const customMapper = new CustomMapperClass();\n * console.log(customMapper.foo());\n * console.log(CustomMapperClass.beep());\n *\n * // Extend the class using alternate method.\n * const OtherMapperClass = Mapper.extend({\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * });\n * const otherMapper = new OtherMapperClass();\n * console.log(otherMapper.foo());\n * console.log(OtherMapperClass.beep());\n *\n * // Extend the class, providing a custom constructor.\n * function AnotherMapperClass () {\n * Mapper.call(this);\n * this.created_at = new Date().getTime();\n * }\n * Mapper.extend({\n * constructor: AnotherMapperClass,\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * })\n * const anotherMapper = new AnotherMapperClass();\n * console.log(anotherMapper.created_at);\n * console.log(anotherMapper.foo());\n * console.log(AnotherMapperClass.beep());\n *\n * @method Mapper.extend\n * @param {object} [props={}] Properties to add to the prototype of the\n * subclass.\n * @param {object} [props.constructor] Provide a custom constructor function\n * to be used as the subclass itself.\n * @param {object} [classProps={}] Static properties to add to the subclass.\n * @returns {Constructor} Subclass of this Mapper class.\n * @since 3.0.0\n */\n","import utils from './utils'\nimport Component from './Component'\nimport Mapper from './Mapper'\n\nconst DOMAIN = 'Container'\n\nexport const proxiedMapperMethods = [\n /**\n * Wrapper for {@link Mapper#count}.\n *\n * @example\n * // Get the number of published blog posts\n * import { Container } from 'js-data';\n * import RethinkDBAdapter from 'js-data-rethinkdb';\n * const store = new Container();\n * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('post');\n *\n * store.count('post', { status: 'published' }).then((numPublished) => {\n * console.log(numPublished); // e.g. 45\n * });\n *\n * @method Container#count\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {object} [query] See {@link Mapper#count}.\n * @param {object} [opts] See {@link Mapper#count}.\n * @returns {Promise} See {@link Mapper#count}.\n * @see Mapper#count\n * @since 3.0.0\n */\n 'count',\n\n /**\n * Fired during {@link Container#create}. See\n * {@link Container~beforeCreateListener} for how to listen for this event.\n *\n * @event Container#beforeCreate\n * @see Container~beforeCreateListener\n * @see Container#create\n */\n /**\n * Callback signature for the {@link Container#event:beforeCreate} event.\n *\n * @example\n * function onBeforeCreate (mapperName, props, opts) {\n * // do something\n * }\n * store.on('beforeCreate', onBeforeCreate);\n *\n * @callback Container~beforeCreateListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeCreate}.\n * @param {object} props The `props` argument received by {@link Mapper#beforeCreate}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeCreate}.\n * @see Container#event:beforeCreate\n * @see Container#create\n * @since 3.0.0\n */\n /**\n * Fired during {@link Container#create}. See\n * {@link Container~afterCreateListener} for how to listen for this event.\n *\n * @event Container#afterCreate\n * @see Container~afterCreateListener\n * @see Container#create\n */\n /**\n * Callback signature for the {@link Container#event:afterCreate} event.\n *\n * @example\n * function onAfterCreate (mapperName, props, opts, result) {\n * // do something\n * }\n * store.on('afterCreate', onAfterCreate);\n *\n * @callback Container~afterCreateListener\n * @param {string} name The `name` argument received by {@link Mapper#afterCreate}.\n * @param {object} props The `props` argument received by {@link Mapper#afterCreate}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterCreate}.\n * @param {object} result The `result` argument received by {@link Mapper#afterCreate}.\n * @see Container#event:afterCreate\n * @see Container#create\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#create}.\n *\n * @example\n * // Create and save a new blog post\n * import { Container } from 'js-data';\n * import RethinkDBAdapter from 'js-data-rethinkdb';\n * const store = new Container();\n * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('post');\n *\n * store.create('post', {\n * title: 'Modeling your data',\n * status: 'draft'\n * }).then((post) => {\n * console.log(post); // { id: 1234, status: 'draft', ... }\n * });\n *\n * @fires Container#beforeCreate\n * @fires Container#afterCreate\n * @method Container#create\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {object} props See {@link Mapper#create}.\n * @param {object} [opts] See {@link Mapper#create}.\n * @returns {Promise} See {@link Mapper#create}.\n * @see Mapper#create\n * @since 3.0.0\n */\n 'create',\n\n /**\n * Fired during {@link Container#createMany}. See\n * {@link Container~beforeCreateManyListener} for how to listen for this event.\n *\n * @event Container#beforeCreateMany\n * @see Container~beforeCreateManyListener\n * @see Container#createMany\n */\n /**\n * Callback signature for the {@link Container#event:beforeCreateMany} event.\n *\n * @example\n * function onBeforeCreateMany (mapperName, records, opts) {\n * // do something\n * }\n * store.on('beforeCreateMany', onBeforeCreateMany);\n *\n * @callback Container~beforeCreateManyListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeCreateMany}.\n * @param {object} records The `records` argument received by {@link Mapper#beforeCreateMany}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeCreateMany}.\n * @see Container#event:beforeCreateMany\n * @see Container#createMany\n * @since 3.0.0\n */\n /**\n * Fired during {@link Container#createMany}. See\n * {@link Container~afterCreateManyListener} for how to listen for this event.\n *\n * @event Container#afterCreateMany\n * @see Container~afterCreateManyListener\n * @see Container#createMany\n */\n /**\n * Callback signature for the {@link Container#event:afterCreateMany} event.\n *\n * @example\n * function onAfterCreateMany (mapperName, records, opts, result) {\n * // do something\n * }\n * store.on('afterCreateMany', onAfterCreateMany);\n *\n * @callback Container~afterCreateManyListener\n * @param {string} name The `name` argument received by {@link Mapper#afterCreateMany}.\n * @param {object} records The `records` argument received by {@link Mapper#afterCreateMany}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterCreateMany}.\n * @param {object} result The `result` argument received by {@link Mapper#afterCreateMany}.\n * @see Container#event:afterCreateMany\n * @see Container#createMany\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#createMany}.\n *\n * @example\n * // Create and save several new blog posts\n * import { Container } from 'js-data';\n * import RethinkDBAdapter from 'js-data-rethinkdb';\n * const store = new Container();\n * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('post');\n *\n * store.createMany('post', [{\n * title: 'Modeling your data',\n * status: 'draft'\n * }, {\n * title: 'Reading data',\n * status: 'draft'\n * }]).then((posts) => {\n * console.log(posts[0]); // { id: 1234, status: 'draft', ... }\n * console.log(posts[1]); // { id: 1235, status: 'draft', ... }\n * });\n *\n * @fires Container#beforeCreateMany\n * @fires Container#afterCreateMany\n * @method Container#createMany\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {Record[]} records See {@link Mapper#createMany}.\n * @param {object} [opts] See {@link Mapper#createMany}.\n * @returns {Promise} See {@link Mapper#createMany}.\n * @see Mapper#createMany\n * @since 3.0.0\n */\n 'createMany',\n\n /**\n * Wrapper for {@link Mapper#createRecord}.\n *\n * __Note:__ This method does __not__ interact with any adapter, and does\n * __not__ save any data. It only creates new objects in memory.\n *\n * @example\n * // Create empty unsaved record instance\n * import { Container } from 'js-data';\n * const store = new Container();\n * store.defineMapper('post');\n * const post = PostMapper.createRecord();\n *\n * @method Container#createRecord\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {Object|Object[]} props See {@link Mapper#createRecord}.\n * @param {object} [opts] See {@link Mapper#createRecord}.\n * @returns {Promise} See {@link Mapper#createRecord}.\n * @see Mapper#createRecord\n * @since 3.0.0\n */\n 'createRecord',\n\n /**\n * Fired during {@link Container#destroy}. See\n * {@link Container~beforeDestroyListener} for how to listen for this event.\n *\n * @event Container#beforeDestroy\n * @see Container~beforeDestroyListener\n * @see Container#destroy\n */\n /**\n * Callback signature for the {@link Container#event:beforeDestroy} event.\n *\n * @example\n * function onBeforeDestroy (mapperName, id, opts) {\n * // do something\n * }\n * store.on('beforeDestroy', onBeforeDestroy);\n *\n * @callback Container~beforeDestroyListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeDestroy}.\n * @param {string|number} id The `id` argument received by {@link Mapper#beforeDestroy}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeDestroy}.\n * @see Container#event:beforeDestroy\n * @see Container#destroy\n * @since 3.0.0\n */\n /**\n * Fired during {@link Container#destroy}. See\n * {@link Container~afterDestroyListener} for how to listen for this event.\n *\n * @event Container#afterDestroy\n * @see Container~afterDestroyListener\n * @see Container#destroy\n */\n /**\n * Callback signature for the {@link Container#event:afterDestroy} event.\n *\n * @example\n * function onAfterDestroy (mapperName, id, opts, result) {\n * // do something\n * }\n * store.on('afterDestroy', onAfterDestroy);\n *\n * @callback Container~afterDestroyListener\n * @param {string} name The `name` argument received by {@link Mapper#afterDestroy}.\n * @param {string|number} id The `id` argument received by {@link Mapper#afterDestroy}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterDestroy}.\n * @param {object} result The `result` argument received by {@link Mapper#afterDestroy}.\n * @see Container#event:afterDestroy\n * @see Container#destroy\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#destroy}.\n *\n * @example\n * // Destroy a specific blog post\n * import { Container } from 'js-data';\n * import RethinkDBAdapter from 'js-data-rethinkdb';\n * const store = new Container();\n * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('post');\n *\n * store.destroy('post', 1234).then(() => {\n * // Blog post #1234 has been destroyed\n * });\n *\n * @fires Container#beforeDestroy\n * @fires Container#afterDestroy\n * @method Container#destroy\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {(string|number)} id See {@link Mapper#destroy}.\n * @param {object} [opts] See {@link Mapper#destroy}.\n * @returns {Promise} See {@link Mapper#destroy}.\n * @see Mapper#destroy\n * @since 3.0.0\n */\n 'destroy',\n\n /**\n * Fired during {@link Container#destroyAll}. See\n * {@link Container~beforeDestroyAllListener} for how to listen for this event.\n *\n * @event Container#beforeDestroyAll\n * @see Container~beforeDestroyAllListener\n * @see Container#destroyAll\n */\n /**\n * Callback signature for the {@link Container#event:beforeDestroyAll} event.\n *\n * @example\n * function onBeforeDestroyAll (mapperName, query, opts) {\n * // do something\n * }\n * store.on('beforeDestroyAll', onBeforeDestroyAll);\n *\n * @callback Container~beforeDestroyAllListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeDestroyAll}.\n * @param {object} query The `query` argument received by {@link Mapper#beforeDestroyAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeDestroyAll}.\n * @see Container#event:beforeDestroyAll\n * @see Container#destroyAll\n * @since 3.0.0\n */\n /**\n * Fired during {@link Container#destroyAll}. See\n * {@link Container~afterDestroyAllListener} for how to listen for this event.\n *\n * @event Container#afterDestroyAll\n * @see Container~afterDestroyAllListener\n * @see Container#destroyAll\n */\n /**\n * Callback signature for the {@link Container#event:afterDestroyAll} event.\n *\n * @example\n * function onAfterDestroyAll (mapperName, query, opts, result) {\n * // do something\n * }\n * store.on('afterDestroyAll', onAfterDestroyAll);\n *\n * @callback Container~afterDestroyAllListener\n * @param {string} name The `name` argument received by {@link Mapper#afterDestroyAll}.\n * @param {object} query The `query` argument received by {@link Mapper#afterDestroyAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterDestroyAll}.\n * @param {object} result The `result` argument received by {@link Mapper#afterDestroyAll}.\n * @see Container#event:afterDestroyAll\n * @see Container#destroyAll\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#destroyAll}.\n *\n * @example\n * // Destroy all \"draft\" blog posts\n * import { Container } from 'js-data';\n * import RethinkDBAdapter from 'js-data-rethinkdb';\n * const store = new Container();\n * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('post');\n *\n * store.destroyAll('post', { status: 'draft' }).then(() => {\n * // All \"draft\" blog posts have been destroyed\n * });\n *\n * @fires Container#beforeDestroyAll\n * @fires Container#afterDestroyAll\n * @method Container#destroyAll\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {object} [query] See {@link Mapper#destroyAll}.\n * @param {object} [opts] See {@link Mapper#destroyAll}.\n * @returns {Promise} See {@link Mapper#destroyAll}.\n * @see Mapper#destroyAll\n * @since 3.0.0\n */\n 'destroyAll',\n\n /**\n * Fired during {@link Container#find}. See\n * {@link Container~beforeFindListener} for how to listen for this event.\n *\n * @event Container#beforeFind\n * @see Container~beforeFindListener\n * @see Container#find\n */\n /**\n * Callback signature for the {@link Container#event:beforeFind} event.\n *\n * @example\n * function onBeforeFind (mapperName, id, opts) {\n * // do something\n * }\n * store.on('beforeFind', onBeforeFind);\n *\n * @callback Container~beforeFindListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeFind}.\n * @param {string|number} id The `id` argument received by {@link Mapper#beforeFind}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeFind}.\n * @see Container#event:beforeFind\n * @see Container#find\n * @since 3.0.0\n */\n /**\n * Fired during {@link Container#find}. See\n * {@link Container~afterFindListener} for how to listen for this event.\n *\n * @event Container#afterFind\n * @see Container~afterFindListener\n * @see Container#find\n */\n /**\n * Callback signature for the {@link Container#event:afterFind} event.\n *\n * @example\n * function onAfterFind (mapperName, id, opts, result) {\n * // do something\n * }\n * store.on('afterFind', onAfterFind);\n *\n * @callback Container~afterFindListener\n * @param {string} name The `name` argument received by {@link Mapper#afterFind}.\n * @param {string|number} id The `id` argument received by {@link Mapper#afterFind}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterFind}.\n * @param {object} result The `result` argument received by {@link Mapper#afterFind}.\n * @see Container#event:afterFind\n * @see Container#find\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#find}.\n *\n * @example\n * import { Container } from 'js-data';\n * import RethinkDBAdapter from 'js-data-rethinkdb';\n * const store = new Container();\n * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('post');\n *\n * store.find('post', 1).then((post) => {\n * console.log(post) // { id: 1, ...}\n * });\n *\n * @fires Container#beforeFind\n * @fires Container#afterFind\n * @method Container#find\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {(string|number)} id See {@link Mapper#find}.\n * @param {object} [opts] See {@link Mapper#find}.\n * @returns {Promise} See {@link Mapper#find}.\n * @see Mapper#find\n * @since 3.0.0\n */\n 'find',\n\n /**\n * Fired during {@link Container#findAll}. See\n * {@link Container~beforeFindAllListener} for how to listen for this event.\n *\n * @event Container#beforeFindAll\n * @see Container~beforeFindAllListener\n * @see Container#findAll\n */\n /**\n * Callback signature for the {@link Container#event:beforeFindAll} event.\n *\n * @example\n * function onBeforeFindAll (mapperName, query, opts) {\n * // do something\n * }\n * store.on('beforeFindAll', onBeforeFindAll);\n *\n * @callback Container~beforeFindAllListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeFindAll}.\n * @param {object} query The `query` argument received by {@link Mapper#beforeFindAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeFindAll}.\n * @see Container#event:beforeFindAll\n * @see Container#findAll\n * @since 3.0.0\n */\n /**\n * Fired during {@link Container#findAll}. See\n * {@link Container~afterFindAllListener} for how to listen for this event.\n *\n * @event Container#afterFindAll\n * @see Container~afterFindAllListener\n * @see Container#findAll\n */\n /**\n * Callback signature for the {@link Container#event:afterFindAll} event.\n *\n * @example\n * function onAfterFindAll (mapperName, query, opts, result) {\n * // do something\n * }\n * store.on('afterFindAll', onAfterFindAll);\n *\n * @callback Container~afterFindAllListener\n * @param {string} name The `name` argument received by {@link Mapper#afterFindAll}.\n * @param {object} query The `query` argument received by {@link Mapper#afterFindAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterFindAll}.\n * @param {object} result The `result` argument received by {@link Mapper#afterFindAll}.\n * @see Container#event:afterFindAll\n * @see Container#findAll\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#createRecord}.\n *\n * @example\n * // Find all \"published\" blog posts\n * import { Container } from 'js-data';\n * import RethinkDBAdapter from 'js-data-rethinkdb';\n * const store = new Container();\n * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('post');\n *\n * store.findAll('post', { status: 'published' }).then((posts) => {\n * console.log(posts); // [{ id: 1, ...}, ...]\n * });\n *\n * @fires Container#beforeFindAll\n * @fires Container#afterFindAll\n * @method Container#findAll\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {object} [query] See {@link Mapper#findAll}.\n * @param {object} [opts] See {@link Mapper#findAll}.\n * @returns {Promise} See {@link Mapper#findAll}.\n * @see Mapper#findAll\n * @since 3.0.0\n */\n 'findAll',\n\n /**\n * Wrapper for {@link Mapper#getSchema}.\n *\n * @method Container#getSchema\n * @param {string} name Name of the {@link Mapper} to target.\n * @returns {Schema} See {@link Mapper#getSchema}.\n * @see Mapper#getSchema\n * @since 3.0.0\n */\n 'getSchema',\n\n /**\n * Wrapper for {@link Mapper#is}.\n *\n * @example\n * import { Container } from 'js-data';\n * const store = new Container();\n * store.defineMapper('post');\n * const post = store.createRecord();\n *\n * console.log(store.is('post', post)); // true\n * // Equivalent to what's above\n * console.log(post instanceof store.getMapper('post').recordClass); // true\n *\n * @method Container#is\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {Object|Record} record See {@link Mapper#is}.\n * @returns {boolean} See {@link Mapper#is}.\n * @see Mapper#is\n * @since 3.0.0\n */\n 'is',\n\n /**\n * Wrapper for {@link Mapper#sum}.\n *\n * @example\n * import { Container } from 'js-data';\n * import RethinkDBAdapter from 'js-data-rethinkdb';\n * const store = new Container();\n * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('purchase_order');\n *\n * store.sum('purchase_order', 'amount', { status: 'paid' }).then((amountPaid) => {\n * console.log(amountPaid); // e.g. 451125.34\n * });\n *\n * @method Container#sum\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {string} field See {@link Mapper#sum}.\n * @param {object} [query] See {@link Mapper#sum}.\n * @param {object} [opts] See {@link Mapper#sum}.\n * @returns {Promise} See {@link Mapper#sum}.\n * @see Mapper#sum\n * @since 3.0.0\n */\n 'sum',\n\n /**\n * Wrapper for {@link Mapper#toJSON}.\n *\n * @example\n * import { Container } from 'js-data';\n * import RethinkDBAdapter from 'js-data-rethinkdb';\n * const store = new Container();\n * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('person', {\n * schema: {\n * properties: {\n * name: { type: 'string' },\n * id: { type: 'string' }\n * }\n * }\n * });\n * const person = store.createRecord('person', { id: 1, name: 'John', foo: 'bar' });\n * // \"foo\" is stripped by toJSON()\n * console.log(store.toJSON('person', person)); // {\"id\":1,\"name\":\"John\"}\n *\n * store.defineMapper('personRelaxed', {\n * schema: {\n * properties: {\n * name: { type: 'string' },\n * id: { type: 'string' }\n * },\n * additionalProperties: true\n * }\n * });\n * const person2 = store.createRecord('personRelaxed', { id: 1, name: 'John', foo: 'bar' });\n * // \"foo\" is not stripped by toJSON\n * console.log(store.toJSON('personRelaxed', person2)); // {\"id\":1,\"name\":\"John\",\"foo\":\"bar\"}\n *\n * @method Container#toJSON\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {Record|Record[]} records See {@link Mapper#toJSON}.\n * @param {object} [opts] See {@link Mapper#toJSON}.\n * @returns {Object|Object[]} See {@link Mapper#toJSON}.\n * @see Mapper#toJSON\n * @since 3.0.0\n */\n 'toJSON',\n\n /**\n * Fired during {@link Container#update}. See\n * {@link Container~beforeUpdateListener} for how to listen for this event.\n *\n * @event Container#beforeUpdate\n * @see Container~beforeUpdateListener\n * @see Container#update\n */\n /**\n * Callback signature for the {@link Container#event:beforeUpdate} event.\n *\n * @example\n * function onBeforeUpdate (mapperName, id, props, opts) {\n * // do something\n * }\n * store.on('beforeUpdate', onBeforeUpdate);\n *\n * @callback Container~beforeUpdateListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeUpdate}.\n * @param {string|number} id The `id` argument received by {@link Mapper#beforeUpdate}.\n * @param {object} props The `props` argument received by {@link Mapper#beforeUpdate}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdate}.\n * @see Container#event:beforeUpdate\n * @see Container#update\n * @since 3.0.0\n */\n /**\n * Fired during {@link Container#update}. See\n * {@link Container~afterUpdateListener} for how to listen for this event.\n *\n * @event Container#afterUpdate\n * @see Container~afterUpdateListener\n * @see Container#update\n */\n /**\n * Callback signature for the {@link Container#event:afterUpdate} event.\n *\n * @example\n * function onAfterUpdate (mapperName, id, props, opts, result) {\n * // do something\n * }\n * store.on('afterUpdate', onAfterUpdate);\n *\n * @callback Container~afterUpdateListener\n * @param {string} name The `name` argument received by {@link Mapper#afterUpdate}.\n * @param {string|number} id The `id` argument received by {@link Mapper#afterUpdate}.\n * @param {object} props The `props` argument received by {@link Mapper#afterUpdate}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdate}.\n * @param {object} result The `result` argument received by {@link Mapper#afterUpdate}.\n * @see Container#event:afterUpdate\n * @see Container#update\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#update}.\n *\n * @example\n * import { Container } from 'js-data';\n * import RethinkDBAdapter from 'js-data-rethinkdb';\n * const store = new Container();\n * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('post');\n *\n * store.update('post', 1234, {\n * status: 'published',\n * published_at: new Date()\n * }).then((post) => {\n * console.log(post); // { id: 1234, status: 'published', ... }\n * });\n *\n * @fires Container#beforeUpdate\n * @fires Container#afterUpdate\n * @method Container#update\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {(string|number)} id See {@link Mapper#update}.\n * @param {object} record See {@link Mapper#update}.\n * @param {object} [opts] See {@link Mapper#update}.\n * @returns {Promise} See {@link Mapper#update}.\n * @see Mapper#update\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/saving-data\",\"Saving data\"]\n */\n 'update',\n\n /**\n * Fired during {@link Container#updateAll}. See\n * {@link Container~beforeUpdateAllListener} for how to listen for this event.\n *\n * @event Container#beforeUpdateAll\n * @see Container~beforeUpdateAllListener\n * @see Container#updateAll\n */\n /**\n * Callback signature for the {@link Container#event:beforeUpdateAll} event.\n *\n * @example\n * function onBeforeUpdateAll (mapperName, props, query, opts) {\n * // do something\n * }\n * store.on('beforeUpdateAll', onBeforeUpdateAll);\n *\n * @callback Container~beforeUpdateAllListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeUpdateAll}.\n * @param {object} props The `props` argument received by {@link Mapper#beforeUpdateAll}.\n * @param {object} query The `query` argument received by {@link Mapper#beforeUpdateAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdateAll}.\n * @see Container#event:beforeUpdateAll\n * @see Container#updateAll\n * @since 3.0.0\n */\n /**\n * Fired during {@link Container#updateAll}. See\n * {@link Container~afterUpdateAllListener} for how to listen for this event.\n *\n * @event Container#afterUpdateAll\n * @see Container~afterUpdateAllListener\n * @see Container#updateAll\n */\n /**\n * Callback signature for the {@link Container#event:afterUpdateAll} event.\n *\n * @example\n * function onAfterUpdateAll (mapperName, props, query, opts, result) {\n * // do something\n * }\n * store.on('afterUpdateAll', onAfterUpdateAll);\n *\n * @callback Container~afterUpdateAllListener\n * @param {string} name The `name` argument received by {@link Mapper#afterUpdateAll}.\n * @param {object} props The `props` argument received by {@link Mapper#afterUpdateAll}.\n * @param {object} query The `query` argument received by {@link Mapper#afterUpdateAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdateAll}.\n * @param {object} result The `result` argument received by {@link Mapper#afterUpdateAll}.\n * @see Container#event:afterUpdateAll\n * @see Container#updateAll\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#updateAll}.\n *\n * @example\n * // Turn all of John's blog posts into drafts.\n * import { Container } from 'js-data';\n * import RethinkDBAdapter from 'js-data-rethinkdb';\n * const store = new Container();\n * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('post');\n *\n * const update = { status: draft: published_at: null };\n * const query = { userId: 1234 };\n * store.updateAll('post', update, query).then((posts) => {\n * console.log(posts); // [...]\n * });\n *\n * @fires Container#beforeUpdateAll\n * @fires Container#afterUpdateAll\n * @method Container#updateAll\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {object} update See {@link Mapper#updateAll}.\n * @param {object} [query] See {@link Mapper#updateAll}.\n * @param {object} [opts] See {@link Mapper#updateAll}.\n * @returns {Promise} See {@link Mapper#updateAll}.\n * @see Mapper#updateAll\n * @since 3.0.0\n */\n 'updateAll',\n\n /**\n * Fired during {@link Container#updateMany}. See\n * {@link Container~beforeUpdateManyListener} for how to listen for this event.\n *\n * @event Container#beforeUpdateMany\n * @see Container~beforeUpdateManyListener\n * @see Container#updateMany\n */\n /**\n * Callback signature for the {@link Container#event:beforeUpdateMany} event.\n *\n * @example\n * function onBeforeUpdateMany (mapperName, records, opts) {\n * // do something\n * }\n * store.on('beforeUpdateMany', onBeforeUpdateMany);\n *\n * @callback Container~beforeUpdateManyListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeUpdateMany}.\n * @param {object} records The `records` argument received by {@link Mapper#beforeUpdateMany}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdateMany}.\n * @see Container#event:beforeUpdateMany\n * @see Container#updateMany\n * @since 3.0.0\n */\n /**\n * Fired during {@link Container#updateMany}. See\n * {@link Container~afterUpdateManyListener} for how to listen for this event.\n *\n * @event Container#afterUpdateMany\n * @see Container~afterUpdateManyListener\n * @see Container#updateMany\n */\n /**\n * Callback signature for the {@link Container#event:afterUpdateMany} event.\n *\n * @example\n * function onAfterUpdateMany (mapperName, records, opts, result) {\n * // do something\n * }\n * store.on('afterUpdateMany', onAfterUpdateMany);\n *\n * @callback Container~afterUpdateManyListener\n * @param {string} name The `name` argument received by {@link Mapper#afterUpdateMany}.\n * @param {object} records The `records` argument received by {@link Mapper#afterUpdateMany}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdateMany}.\n * @param {object} result The `result` argument received by {@link Mapper#afterUpdateMany}.\n * @see Container#event:afterUpdateMany\n * @see Container#updateMany\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#updateMany}.\n *\n * @example\n * import { Container } from 'js-data';\n * import RethinkDBAdapter from 'js-data-rethinkdb';\n * const store = new Container();\n * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('post');\n *\n * store.updateMany('post', [\n * { id: 1234, status: 'draft' },\n * { id: 2468, status: 'published', published_at: new Date() }\n * ]).then((posts) => {\n * console.log(posts); // [...]\n * });\n *\n * @fires Container#beforeUpdateMany\n * @fires Container#afterUpdateMany\n * @method Container#updateMany\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {(Object[]|Record[])} records See {@link Mapper#updateMany}.\n * @param {object} [opts] See {@link Mapper#updateMany}.\n * @returns {Promise} See {@link Mapper#updateMany}.\n * @see Mapper#updateMany\n * @since 3.0.0\n */\n 'updateMany',\n\n /**\n * Wrapper for {@link Mapper#validate}.\n *\n * @example\n * import { Container } from 'js-data';\n * const store = new Container();\n * store.defineMapper('post', {\n * schema: {\n * properties: {\n * name: { type: 'string' },\n * id: { type: 'string' }\n * }\n * }\n * });\n * let errors = store.validate('post', { name: 'John' });\n * console.log(errors); // undefined\n * errors = store.validate('post', { name: 123 });\n * console.log(errors); // [{ expected: 'one of (string)', actual: 'number', path: 'name' }]\n *\n * @method Container#validate\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {(Object[]|Record[])} records See {@link Mapper#validate}.\n * @param {object} [opts] See {@link Mapper#validate}.\n * @returns {Promise} See {@link Mapper#validate}.\n * @see Mapper#validate\n * @since 3.0.0\n */\n 'validate'\n]\n\n/**\n * The `Container` class is a place to define and store {@link Mapper} instances.\n *\n * `Container` makes it easy to manage your Mappers. Without a container, you\n * need to manage Mappers yourself, including resolving circular dependencies\n * among relations. All Mappers in a container share the same adapters, so you\n * don't have to register adapters for every single Mapper.\n *\n * @example Container#constructor\n * // import { Container } from 'js-data';\n * const JSData = require('js-data');\n * const {Container} = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new Container();\n *\n * @class Container\n * @extends Component\n * @param {object} [opts] Configuration options.\n * @param {boolean} [opts.debug=false] See {@link Component#debug}.\n * @param {Constructor} [opts.mapperClass] See {@link Container#mapperClass}.\n * @param {object} [opts.mapperDefaults] See {@link Container#mapperDefaults}.\n * @since 3.0.0\n */\nexport function Container (opts) {\n utils.classCallCheck(this, Container)\n Component.call(this)\n opts || (opts = {})\n\n Object.defineProperties(this, {\n /**\n * The adapters registered with this Container, which are also shared by all\n * Mappers in this Container.\n *\n * @name Container#_adapters\n * @see Container#registerAdapter\n * @since 3.0.0\n * @type {Object}\n */\n _adapters: {\n value: {}\n },\n\n /**\n * The the mappers in this container\n *\n * @name Container#_mappers\n * @see Mapper\n * @since 3.0.0\n * @type {Object}\n */\n _mappers: {\n value: {}\n },\n\n /**\n * Constructor function to use in {@link Container#defineMapper} to create new\n * {@link Mapper} instances. {@link Container#mapperClass} should extend\n * {@link Mapper}. By default {@link Mapper} is used to instantiate Mappers.\n *\n * @example Container#mapperClass\n * // import { Container, Mapper } from 'js-data';\n * const JSData = require('js-data');\n * const { Container, Mapper } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * class MyMapperClass extends Mapper {\n * foo () { return 'bar' }\n * }\n * const store = new Container({\n * mapperClass: MyMapperClass\n * });\n * store.defineMapper('user');\n * console.log(store.getMapper('user').foo());\n *\n * @name Container#mapperClass\n * @see Mapper\n * @since 3.0.0\n * @type {Constructor}\n */\n mapperClass: {\n value: undefined,\n writable: true\n }\n })\n\n // Apply options provided by the user\n utils.fillIn(this, opts)\n\n /**\n * Defaults options to pass to {@link Container#mapperClass} when creating a\n * new {@link Mapper}.\n *\n * @example Container#mapperDefaults\n * // import { Container } from 'js-data';\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new Container({\n * mapperDefaults: {\n * idAttribute: '_id'\n * }\n * });\n * store.defineMapper('user');\n * console.log(store.getMapper('user').idAttribute);\n *\n * @default {}\n * @name Container#mapperDefaults\n * @since 3.0.0\n * @type {Object}\n */\n this.mapperDefaults = this.mapperDefaults || {}\n\n // Use the Mapper class if the user didn't provide a mapperClass\n this.mapperClass || (this.mapperClass = Mapper)\n}\n\nconst props = {\n constructor: Container,\n\n /**\n * Register a new event listener on this Container.\n *\n * Proxy for {@link Component#on}. If an event was emitted by a {@link Mapper}\n * in the Container, then the name of the {@link Mapper} will be prepended to\n * the arugments passed to the listener.\n *\n * @example Container#on\n * // import { Container } from 'js-data';\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new Container();\n * store.on('foo', function (...args) { console.log(args.join(':')) });\n * store.defineMapper('user');\n * store.emit('foo', 'arg1', 'arg2');\n * store.getMapper('user').emit('foo', 'arg1', 'arg2');\n *\n * @method Container#on\n * @param {string} event Name of event to subsribe to.\n * @param {Function} listener Listener function to handle the event.\n * @param {*} [ctx] Optional content in which to invoke the listener.\n * @since 3.0.0\n */\n\n /**\n * Used to bind to events emitted by mappers in this container.\n *\n * @method Container#_onMapperEvent\n * @param {string} name Name of the mapper that emitted the event.\n * @param {...*} [args] Args See {@link Mapper#emit}.\n * @private\n * @since 3.0.0\n */\n _onMapperEvent (name, ...args) {\n const type = args.shift()\n this.emit(type, name, ...args)\n },\n\n /**\n * Return a container scoped to a particular mapper.\n *\n * @example Container#as\n * // import { Container } from 'js-data';\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new Container();\n * const UserMapper = store.defineMapper('user');\n * const UserStore = store.as('user');\n *\n * const user1 = store.createRecord('user', { name: 'John' });\n * const user2 = UserStore.createRecord({ name: 'John' });\n * const user3 = UserMapper.createRecord({ name: 'John' });\n * console.log(user1 === user2);\n * console.log(user2 === user3);\n * console.log(user1 === user3);\n *\n * @method Container#as\n * @param {string} name Name of the {@link Mapper}.\n * @returns {Object} A container scoped to a particular mapper.\n * @since 3.0.0\n */\n as (name) {\n const props = {}\n const original = this\n proxiedMapperMethods.forEach(function (method) {\n props[method] = {\n writable: true,\n value (...args) {\n return original[method](name, ...args)\n }\n }\n })\n props.getMapper = {\n writable: true,\n value () {\n return original.getMapper(name)\n }\n }\n return Object.create(this, props)\n },\n\n /**\n * Create a new mapper and register it in this container.\n *\n * @example Container#defineMapper\n * // import { Container } from 'js-data';\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new Container({\n * mapperDefaults: { foo: 'bar' }\n * });\n * // Container#defineMapper returns a direct reference to the newly created\n * // Mapper.\n * const UserMapper = store.defineMapper('user');\n * console.log(UserMapper === store.getMapper('user'));\n * console.log(UserMapper === store.as('user').getMapper());\n * console.log(UserMapper.foo);\n *\n * @method Container#defineMapper\n * @param {string} name Name under which to register the new {@link Mapper}.\n * {@link Mapper#name} will be set to this value.\n * @param {object} [opts] Configuration options. Passed to\n * {@link Container#mapperClass} when creating the new {@link Mapper}.\n * @returns {Mapper} The newly created instance of {@link Mapper}.\n * @see Container#as\n * @since 3.0.0\n */\n defineMapper (name, opts) {\n // For backwards compatibility with defineResource\n if (utils.isObject(name)) {\n opts = name\n name = opts.name\n }\n if (!utils.isString(name)) {\n throw utils.err(`${DOMAIN}#defineMapper`, 'name')(400, 'string', name)\n }\n\n // Default values for arguments\n opts || (opts = {})\n // Set Mapper#name\n opts.name = name\n opts.relations || (opts.relations = {})\n\n // Check if the user is overriding the datastore's default mapperClass\n const mapperClass = opts.mapperClass || this.mapperClass\n delete opts.mapperClass\n\n // Apply the datastore's defaults to the options going into the mapper\n utils.fillIn(opts, this.mapperDefaults)\n\n // Instantiate a mapper\n const mapper = this._mappers[name] = new mapperClass(opts) // eslint-disable-line\n mapper.relations || (mapper.relations = {})\n // Make sure the mapper's name is set\n mapper.name = name\n // All mappers in this datastore will share adapters\n mapper._adapters = this.getAdapters()\n\n mapper.datastore = this\n\n mapper.on('all', (...args) => this._onMapperEvent(name, ...args))\n mapper.defineRelations()\n\n return mapper\n },\n\n defineResource (name, opts) {\n console.warn('DEPRECATED: defineResource is deprecated, use defineMapper instead')\n return this.defineMapper(name, opts)\n },\n\n /**\n * Return the registered adapter with the given name or the default adapter if\n * no name is provided.\n *\n * @method Container#getAdapter\n * @param {string} [name] The name of the adapter to retrieve.\n * @returns {Adapter} The adapter.\n * @since 3.0.0\n */\n getAdapter (name) {\n const adapter = this.getAdapterName(name)\n if (!adapter) {\n throw utils.err(`${DOMAIN}#getAdapter`, 'name')(400, 'string', name)\n }\n return this.getAdapters()[adapter]\n },\n\n /**\n * Return the name of a registered adapter based on the given name or options,\n * or the name of the default adapter if no name provided.\n *\n * @method Container#getAdapterName\n * @param {(Object|string)} [opts] The name of an adapter or options, if any.\n * @returns {string} The name of the adapter.\n * @since 3.0.0\n */\n getAdapterName (opts) {\n opts || (opts = {})\n if (utils.isString(opts)) {\n opts = { adapter: opts }\n }\n return opts.adapter || this.mapperDefaults.defaultAdapter\n },\n\n /**\n * Return the registered adapters of this container.\n *\n * @method Container#getAdapters\n * @returns {Adapter}\n * @since 3.0.0\n */\n getAdapters () {\n return this._adapters\n },\n\n /**\n * Return the mapper registered under the specified name.\n *\n * @example Container#getMapper\n * // import { Container } from 'js-data';\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new Container();\n * // Container#defineMapper returns a direct reference to the newly created\n * // Mapper.\n * const UserMapper = store.defineMapper('user');\n * console.log(UserMapper === store.getMapper('user'));\n * console.log(UserMapper === store.as('user').getMapper());\n * store.getMapper('profile'); // throws Error, there is no mapper with name \"profile\"\n *\n * @method Container#getMapper\n * @param {string} name {@link Mapper#name}.\n * @returns {Mapper}\n * @since 3.0.0\n */\n getMapper (name) {\n const mapper = this.getMapperByName(name)\n if (!mapper) {\n throw utils.err(`${DOMAIN}#getMapper`, name)(404, 'mapper')\n }\n return mapper\n },\n\n /**\n * Return the mapper registered under the specified name.\n * Doesn't throw error if mapper doesn't exist.\n *\n * @example Container#getMapperByName\n * // import { Container } from 'js-data';\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new Container();\n * // Container#defineMapper returns a direct reference to the newly created\n * // Mapper.\n * const UserMapper = store.defineMapper('user');\n * console.log(UserMapper === store.getMapper('user'));\n * console.log(UserMapper === store.as('user').getMapper());\n * console.log(store.getMapper('profile')); // Does NOT throw an error\n *\n * @method Container#getMapperByName\n * @param {string} name {@link Mapper#name}.\n * @returns {Mapper}\n * @since 3.0.0\n */\n getMapperByName (name) {\n return this._mappers[name]\n },\n\n /**\n * Register an adapter on this container under the given name. Adapters\n * registered on a container are shared by all mappers in the container.\n *\n * @example\n * import { Container } from 'js-data';\n * import { RethinkDBAdapter } from 'js-data-rethinkdb';\n * const store = new Container();\n * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true });\n *\n * @method Container#registerAdapter\n * @param {string} name The name of the adapter to register.\n * @param {Adapter} adapter The adapter to register.\n * @param {object} [opts] Configuration options.\n * @param {boolean} [opts.default=false] Whether to make the adapter the\n * default adapter for all Mappers in this container.\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/connecting-to-a-data-source\",\"Connecting to a data source\"]\n */\n registerAdapter (name, adapter, opts) {\n opts || (opts = {})\n this.getAdapters()[name] = adapter\n // Optionally make it the default adapter for the target.\n if (opts === true || opts.default) {\n this.mapperDefaults.defaultAdapter = name\n utils.forOwn(this._mappers, function (mapper) {\n mapper.defaultAdapter = name\n })\n }\n }\n}\n\nproxiedMapperMethods.forEach(function (method) {\n props[method] = function (name, ...args) {\n return this.getMapper(name)[method](...args)\n }\n})\n\nComponent.extend(props)\n\n/**\n * Create a subclass of this Container:\n * @example Container.extend\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * // Extend the class using ES2015 class syntax.\n * class CustomContainerClass extends Container {\n * foo () { return 'bar' }\n * static beep () { return 'boop' }\n * }\n * const customContainer = new CustomContainerClass();\n * console.log(customContainer.foo());\n * console.log(CustomContainerClass.beep());\n *\n * // Extend the class using alternate method.\n * const OtherContainerClass = Container.extend({\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * });\n * const otherContainer = new OtherContainerClass();\n * console.log(otherContainer.foo());\n * console.log(OtherContainerClass.beep());\n *\n * // Extend the class, providing a custom constructor.\n * function AnotherContainerClass () {\n * Container.call(this);\n * this.created_at = new Date().getTime();\n * }\n * Container.extend({\n * constructor: AnotherContainerClass,\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * })\n * const anotherContainer = new AnotherContainerClass();\n * console.log(anotherContainer.created_at);\n * console.log(anotherContainer.foo());\n * console.log(AnotherContainerClass.beep());\n *\n * @method Container.extend\n * @param {object} [props={}] Properties to add to the prototype of the\n * subclass.\n * @param {object} [props.constructor] Provide a custom constructor function\n * to be used as the subclass itself.\n * @param {object} [classProps={}] Static properties to add to the subclass.\n * @returns {Constructor} Subclass of this Container class.\n * @since 3.0.0\n */\n","import utils from './utils'\n\nimport {\n belongsToType,\n hasManyType,\n hasOneType\n} from './decorators'\nimport { proxiedMapperMethods, Container } from './Container'\nimport Collection from './Collection'\n\nconst DOMAIN = 'SimpleStore'\nconst proxiedCollectionMethods = [\n /**\n * Wrapper for {@link Collection#add}.\n *\n * @example SimpleStore#add\n * const JSData = require('js-data');\n * const { SimpleStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new SimpleStore();\n * store.defineMapper('book');\n *\n * // Add one book to the in-memory store:\n * store.add('book', { id: 1, title: 'Respect your Data' });\n * // Add multiple books to the in-memory store:\n * store.add('book', [\n * { id: 2, title: 'Easy data recipes' },\n * { id: 3, title: 'Active Record 101' }\n * ]);\n *\n * @fires SimpleStore#add\n * @method SimpleStore#add\n * @param {(string|number)} name Name of the {@link Mapper} to target.\n * @param {(Object|Object[]|Record|Record[])} data See {@link Collection#add}.\n * @param {object} [opts] Configuration options. See {@link Collection#add}.\n * @returns {(Object|Object[]|Record|Record[])} See {@link Collection#add}.\n * @see Collection#add\n * @see Collection#add\n * @since 3.0.0\n */\n 'add',\n\n /**\n * Wrapper for {@link Collection#between}.\n *\n * @example\n * // Get all users ages 18 to 30\n * const users = store.between('user', 18, 30, { index: 'age' });\n *\n * @example\n * // Same as above\n * const users = store.between('user', [18], [30], { index: 'age' });\n *\n * @method SimpleStore#between\n * @param {(string|number)} name Name of the {@link Mapper} to target.\n * @param {array} leftKeys See {@link Collection#between}.\n * @param {array} rightKeys See {@link Collection#between}.\n * @param {object} [opts] Configuration options. See {@link Collection#between}.\n * @returns {Object[]|Record[]} See {@link Collection#between}.\n * @see Collection#between\n * @see Collection#between\n * @since 3.0.0\n */\n 'between',\n\n /**\n * Wrapper for {@link Collection#createIndex}.\n *\n * @example\n * // Index users by age\n * store.createIndex('user', 'age');\n *\n * @example\n * // Index users by status and role\n * store.createIndex('user', 'statusAndRole', ['status', 'role']);\n *\n * @method SimpleStore#createIndex\n * @param {(string|number)} name Name of the {@link Mapper} to target.\n * @param {string} name See {@link Collection#createIndex}.\n * @param {string[]} [fieldList] See {@link Collection#createIndex}.\n * @see Collection#createIndex\n * @see Collection#createIndex\n * @since 3.0.0\n */\n 'createIndex',\n\n /**\n * Wrapper for {@link Collection#filter}.\n *\n * @example SimpleStore#filter\n * const JSData = require('js-data');\n * const { SimpleStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new SimpleStore();\n * store.defineMapper('post');\n * store.add('post', [\n * { id: 1, status: 'draft', created_at_timestamp: new Date().getTime() }\n * ]);\n *\n * // Get the draft posts created less than three months ago\n * let posts = store.filter('post', {\n * where: {\n * status: {\n * '==': 'draft'\n * },\n * created_at_timestamp: {\n * '>=': (new Date().getTime() - (1000 \\* 60 \\* 60 \\* 24 \\* 30 \\* 3)) // 3 months ago\n * }\n * }\n * });\n * console.log(posts);\n *\n * // Use a custom filter function\n * posts = store.filter('post', function (post) { return post.id % 2 === 0 });\n *\n * @method SimpleStore#filter\n * @param {(string|number)} name Name of the {@link Mapper} to target.\n * @param {(Object|Function)} [queryOrFn={}] See {@link Collection#filter}.\n * @param {object} [thisArg] See {@link Collection#filter}.\n * @returns {Array} See {@link Collection#filter}.\n * @see Collection#filter\n * @see Collection#filter\n * @since 3.0.0\n */\n 'filter',\n\n /**\n * Wrapper for {@link Collection#get}.\n *\n * @example SimpleStore#get\n * const JSData = require('js-data');\n * const { SimpleStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new SimpleStore();\n * store.defineMapper('post');\n * store.add('post', [\n * { id: 1, status: 'draft', created_at_timestamp: new Date().getTime() }\n * ]);\n *\n * console.log(store.get('post', 1)); // {...}\n * console.log(store.get('post', 2)); // undefined\n *\n * @method SimpleStore#get\n * @param {(string|number)} name Name of the {@link Mapper} to target.\n * @param {(string|number)} id See {@link Collection#get}.\n * @returns {(Object|Record)} See {@link Collection#get}.\n * @see Collection#get\n * @see Collection#get\n * @since 3.0.0\n */\n 'get',\n\n /**\n * Wrapper for {@link Collection#getAll}.\n *\n * @example\n * // Get the posts where \"status\" is \"draft\" or \"inReview\"\n * const posts = store.getAll('post', 'draft', 'inReview', { index: 'status' });\n *\n * @example\n * // Same as above\n * const posts = store.getAll('post', ['draft'], ['inReview'], { index: 'status' });\n *\n * @method SimpleStore#getAll\n * @param {(string|number)} name Name of the {@link Mapper} to target.\n * @param {...Array} [keyList] See {@link Collection#getAll}.\n * @param {object} [opts] See {@link Collection#getAll}.\n * @returns {Array} See {@link Collection#getAll}.\n * @see Collection#getAll\n * @see Collection#getAll\n * @since 3.0.0\n */\n 'getAll',\n\n /**\n * Wrapper for {@link Collection#prune}.\n *\n * @method SimpleStore#prune\n * @param {object} [opts] See {@link Collection#prune}.\n * @returns {Array} See {@link Collection#prune}.\n * @see Collection#prune\n * @see Collection#prune\n * @since 3.0.0\n */\n 'prune',\n\n /**\n * Wrapper for {@link Collection#query}.\n *\n * @example\n * // Grab page 2 of users between ages 18 and 30\n * store.query('user')\n * .between(18, 30, { index: 'age' }) // between ages 18 and 30\n * .skip(10) // second page\n * .limit(10) // page size\n * .run();\n *\n * @method SimpleStore#query\n * @param {(string|number)} name Name of the {@link Mapper} to target.\n * @returns {Query} See {@link Collection#query}.\n * @see Collection#query\n * @see Collection#query\n * @since 3.0.0\n */\n 'query',\n\n /**\n * Wrapper for {@link Collection#toJSON}.\n *\n * @example\n * store.defineMapper('post', {\n * schema: {\n * properties: {\n * id: { type: 'number' },\n * title: { type: 'string' }\n * }\n * }\n * });\n * store.add('post', [\n * { id: 1, status: 'published', title: 'Respect your Data' },\n * { id: 2, status: 'draft', title: 'Connecting to a data source' }\n * ]);\n * console.log(store.toJSON('post'));\n * const draftsJSON = store.query('post')\n * .filter({ status: 'draft' })\n * .mapCall('toJSON')\n * .run();\n *\n * @method SimpleStore#toJSON\n * @param {(string|number)} name Name of the {@link Mapper} to target.\n * @param {object} [opts] See {@link Collection#toJSON}.\n * @returns {Array} See {@link Collection#toJSON}.\n * @see Collection#toJSON\n * @see Collection#toJSON\n * @since 3.0.0\n */\n 'toJSON',\n\n /**\n * Wrapper for {@link Collection#unsaved}.\n *\n * @method SimpleStore#unsaved\n * @returns {Array} See {@link Collection#unsaved}.\n * @see Collection#unsaved\n * @see Collection#unsaved\n * @since 3.0.0\n */\n 'unsaved'\n]\nconst ownMethodsForScoping = [\n 'addToCache',\n 'cachedFind',\n 'cachedFindAll',\n 'cacheFind',\n 'cacheFindAll',\n 'hashQuery'\n]\n\nconst cachedFn = function (name, hashOrId, opts) {\n const cached = this._completedQueries[name][hashOrId]\n if (utils.isFunction(cached)) {\n return cached(name, hashOrId, opts)\n }\n return cached\n}\n\nconst SIMPLESTORE_DEFAULTS = {\n /**\n * Whether to use the pending query if a `find` request for the specified\n * record is currently underway. Can be set to `true`, `false`, or to a\n * function that returns `true` or `false`.\n *\n * @default true\n * @name SimpleStore#usePendingFind\n * @since 3.0.0\n * @type {boolean|Function}\n */\n usePendingFind: true,\n\n /**\n * Whether to use the pending query if a `findAll` request for the given query\n * is currently underway. Can be set to `true`, `false`, or to a function that\n * returns `true` or `false`.\n *\n * @default true\n * @name SimpleStore#usePendingFindAll\n * @since 3.0.0\n * @type {boolean|Function}\n */\n usePendingFindAll: true\n}\n\n/**\n * The `SimpleStore` class is an extension of {@link Container}. Not only does\n * `SimpleStore` manage mappers, but also collections. `SimpleStore` implements the\n * asynchronous {@link Mapper} methods, such as {@link Mapper#find} and\n * {@link Mapper#create}. If you use the asynchronous `SimpleStore` methods\n * instead of calling them directly on the mappers, then the results of the\n * method calls will be inserted into the store's collections. You can think of\n * a `SimpleStore` as an [Identity Map](https://en.wikipedia.org/wiki/Identity_map_pattern)\n * for the [ORM](https://en.wikipedia.org/wiki/Object-relational_mapping)\n * (the Mappers).\n *\n * ```javascript\n * import { SimpleStore } from 'js-data';\n * ```\n *\n * @example\n * import { SimpleStore } from 'js-data';\n * import { HttpAdapter } from 'js-data-http';\n * const store = new SimpleStore();\n *\n * // SimpleStore#defineMapper returns a direct reference to the newly created\n * // Mapper.\n * const UserMapper = store.defineMapper('user');\n *\n * // SimpleStore#as returns the store scoped to a particular Mapper.\n * const UserStore = store.as('user');\n *\n * // Call \"find\" on \"UserMapper\" (Stateless ORM)\n * UserMapper.find(1).then((user) => {\n * // retrieved a \"user\" record via the http adapter, but that's it\n *\n * // Call \"find\" on \"store\" targeting \"user\" (Stateful SimpleStore)\n * return store.find('user', 1); // same as \"UserStore.find(1)\"\n * }).then((user) => {\n * // not only was a \"user\" record retrieved, but it was added to the\n * // store's \"user\" collection\n * const cachedUser = store.getCollection('user').get(1);\n * console.log(user === cachedUser); // true\n * });\n *\n * @class SimpleStore\n * @extends Container\n * @param {object} [opts] Configuration options. See {@link Container}.\n * @param {boolean} [opts.collectionClass={@link Collection}] See {@link SimpleStore#collectionClass}.\n * @param {boolean} [opts.debug=false] See {@link Component#debug}.\n * @param {boolean|Function} [opts.usePendingFind=true] See {@link SimpleStore#usePendingFind}.\n * @param {boolean|Function} [opts.usePendingFindAll=true] See {@link SimpleStore#usePendingFindAll}.\n * @returns {SimpleStore}\n * @see Container\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/components-of-jsdata#SimpleStore\",\"Components of JSData: SimpleStore\"]\n * @tutorial [\"http://www.js-data.io/v3.0/docs/working-with-the-SimpleStore\",\"Working with the SimpleStore\"]\n * @tutorial [\"http://www.js-data.io/v3.0/docs/jsdata-and-the-browser\",\"Notes on using JSData in the Browser\"]\n */\nfunction SimpleStore (opts) {\n utils.classCallCheck(this, SimpleStore)\n\n opts || (opts = {})\n // Fill in any missing options with the defaults\n utils.fillIn(opts, SIMPLESTORE_DEFAULTS)\n Container.call(this, opts)\n\n this.collectionClass = this.collectionClass || Collection\n this._collections = {}\n this._pendingQueries = {}\n this._completedQueries = {}\n}\n\nconst props = {\n constructor: SimpleStore,\n\n /**\n * Internal method used to handle Mapper responses.\n *\n * @method SimpleStore#_end\n * @private\n * @param {string} name Name of the {@link Collection} to which to\n * add the data.\n * @param {object} result The result from a Mapper.\n * @param {object} [opts] Configuration options.\n * @returns {(Object|Array)} Result.\n */\n _end (name, result, opts) {\n let data = opts.raw ? result.data : result\n if (data && utils.isFunction(this.addToCache)) {\n data = this.addToCache(name, data, opts)\n if (opts.raw) {\n result.data = data\n } else {\n result = data\n }\n }\n return result\n },\n\n /**\n * Register a new event listener on this SimpleStore.\n *\n * Proxy for {@link Container#on}. If an event was emitted by a Mapper or\n * Collection in the SimpleStore, then the name of the Mapper or Collection will\n * be prepended to the arugments passed to the provided event handler.\n *\n * @example\n * // Listen for all \"afterCreate\" events in a SimpleStore\n * store.on('afterCreate', (mapperName, props, opts, result) => {\n * console.log(mapperName); // \"post\"\n * console.log(props.id); // undefined\n * console.log(result.id); // 1234\n * });\n * store.create('post', { title: 'Modeling your data' }).then((post) => {\n * console.log(post.id); // 1234\n * });\n *\n * @example\n * // Listen for the \"add\" event on a collection\n * store.on('add', (mapperName, records) => {\n * console.log(records); // [...]\n * });\n *\n * @example\n * // Listen for \"change\" events on a record\n * store.on('change', (mapperName, record, changes) => {\n * console.log(changes); // { changed: { title: 'Modeling your data' } }\n * });\n * post.title = 'Modeling your data';\n *\n * @method SimpleStore#on\n * @param {string} event Name of event to subsribe to.\n * @param {Function} listener Listener function to handle the event.\n * @param {*} [ctx] Optional content in which to invoke the listener.\n */\n\n /**\n * Used to bind to events emitted by collections in this store.\n *\n * @method SimpleStore#_onCollectionEvent\n * @private\n * @param {string} name Name of the collection that emitted the event.\n * @param {...*} [args] Args passed to {@link Collection#emit}.\n */\n _onCollectionEvent (name, ...args) {\n const type = args.shift()\n this.emit(type, name, ...args)\n },\n\n /**\n * This method takes the data received from {@link SimpleStore#find},\n * {@link SimpleStore#findAll}, {@link SimpleStore#update}, etc., and adds the\n * data to the store. _You don't need to call this method directly._\n *\n * If you're using the http adapter and your response data is in an unexpected\n * format, you may need to override this method so the right data gets added\n * to the store.\n *\n * @example\n * const store = new SimpleStore({\n * addToCache (mapperName, data, opts) {\n * // Let's say for a particular Resource, response data is in a weird format\n * if (name === 'comment') {\n * // Re-assign the variable to add the correct records into the stores\n * data = data.items;\n * }\n * // Now perform default behavior\n * return SimpleStore.prototype.addToCache.call(this, mapperName, data, opts);\n * }\n * });\n *\n * @example\n * // Extend using ES2015 class syntax.\n * class MyStore extends SimpleStore {\n * addToCache (mapperName, data, opts) {\n * // Let's say for a particular Resource, response data is in a weird format\n * if (name === 'comment') {\n * // Re-assign the variable to add the correct records into the stores\n * data = data.items;\n * }\n * // Now perform default behavior\n * return super.addToCache(mapperName, data, opts);\n * }\n * }\n * const store = new MyStore();\n *\n * @method SimpleStore#addToCache\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {*} data Data from which data should be selected for add.\n * @param {object} [opts] Configuration options.\n */\n addToCache (name, data, opts) {\n return this.getCollection(name).add(data, opts)\n },\n\n /**\n * Return the store scoped to a particular mapper/collection pair.\n *\n * @example SimpleStore.as\n * const JSData = require('js-data');\n * const { SimpleStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new SimpleStore();\n * const UserMapper = store.defineMapper('user');\n * const UserStore = store.as('user');\n *\n * const user1 = store.createRecord('user', { name: 'John' });\n * const user2 = UserStore.createRecord({ name: 'John' });\n * const user3 = UserMapper.createRecord({ name: 'John' });\n * console.log(user1 === user2);\n * console.log(user2 === user3);\n * console.log(user1 === user3);\n *\n * @method SimpleStore#as\n * @param {string} name Name of the {@link Mapper}.\n * @returns {Object} The store, scoped to a particular Mapper/Collection pair.\n * @since 3.0.0\n */\n as (name) {\n const props = {}\n const original = this\n const methods = ownMethodsForScoping\n .concat(proxiedMapperMethods)\n .concat(proxiedCollectionMethods)\n\n methods.forEach(function (method) {\n props[method] = {\n writable: true,\n value (...args) {\n return original[method](name, ...args)\n }\n }\n })\n props.getMapper = {\n writable: true,\n value () {\n return original.getMapper(name)\n }\n }\n props.getCollection = {\n writable: true,\n value () {\n return original.getCollection(name)\n }\n }\n return Object.create(this, props)\n },\n\n /**\n * Retrieve a cached `find` result, if any. This method is called during\n * {@link SimpleStore#find} to determine if {@link Mapper#find} needs to be\n * called. If this method returns `undefined` then {@link Mapper#find} will\n * be called. Otherwise {@link SimpleStore#find} will immediately resolve with\n * the return value of this method.\n *\n * When using {@link SimpleStore} in the browser, you can override this method\n * to implement your own cache-busting strategy.\n *\n * @example\n * const store = new SimpleStore({\n * cachedFind (mapperName, id, opts) {\n * // Let's say for a particular Resource, we always want to pull fresh from the server\n * if (mapperName === 'schedule') {\n * // Return undefined to trigger a Mapper#find call\n * return;\n * }\n * // Otherwise perform default behavior\n * return SimpleStore.prototype.cachedFind.call(this, mapperName, id, opts);\n * }\n * });\n *\n * @example\n * // Extend using ES2015 class syntax.\n * class MyStore extends SimpleStore {\n * cachedFind (mapperName, id, opts) {\n * // Let's say for a particular Resource, we always want to pull fresh from the server\n * if (mapperName === 'schedule') {\n * // Return undefined to trigger a Mapper#find call\n * return;\n * }\n * // Otherwise perform default behavior\n * return super.cachedFind(mapperName, id, opts);\n * }\n * }\n * const store = new MyStore();\n *\n * @method SimpleStore#cachedFind\n * @param {string} name The `name` argument passed to {@link SimpleStore#find}.\n * @param {(string|number)} id The `id` argument passed to {@link SimpleStore#find}.\n * @param {object} opts The `opts` argument passed to {@link SimpleStore#find}.\n * @since 3.0.0\n */\n cachedFind: cachedFn,\n\n /**\n * Retrieve a cached `findAll` result, if any. This method is called during\n * {@link SimpleStore#findAll} to determine if {@link Mapper#findAll} needs to be\n * called. If this method returns `undefined` then {@link Mapper#findAll} will\n * be called. Otherwise {@link SimpleStore#findAll} will immediately resolve with\n * the return value of this method.\n *\n * When using {@link SimpleStore} in the browser, you can override this method\n * to implement your own cache-busting strategy.\n *\n * @example\n * const store = new SimpleStore({\n * cachedFindAll (mapperName, hash, opts) {\n * // Let's say for a particular Resource, we always want to pull fresh from the server\n * if (mapperName === 'schedule') {\n * // Return undefined to trigger a Mapper#findAll call\n * return undefined;\n * }\n * // Otherwise perform default behavior\n * return SimpleStore.prototype.cachedFindAll.call(this, mapperName, hash, opts);\n * }\n * });\n *\n * @example\n * // Extend using ES2015 class syntax.\n * class MyStore extends SimpleStore {\n * cachedFindAll (mapperName, hash, opts) {\n * // Let's say for a particular Resource, we always want to pull fresh from the server\n * if (mapperName === 'schedule') {\n * // Return undefined to trigger a Mapper#findAll call\n * return undefined;\n * }\n * // Otherwise perform default behavior\n * return super.cachedFindAll(mapperName, hash, opts);\n * }\n * }\n * const store = new MyStore();\n *\n * @method SimpleStore#cachedFindAll\n * @param {string} name The `name` argument passed to {@link SimpleStore#findAll}.\n * @param {string} hash The result of calling {@link SimpleStore#hashQuery} on\n * the `query` argument passed to {@link SimpleStore#findAll}.\n * @param {object} opts The `opts` argument passed to {@link SimpleStore#findAll}.\n * @since 3.0.0\n */\n cachedFindAll: cachedFn,\n\n /**\n * Mark a {@link Mapper#find} result as cached by adding an entry to\n * {@link SimpleStore#_completedQueries}. By default, once a `find` entry is\n * added it means subsequent calls to the same Resource with the same `id`\n * argument will immediately resolve with the result of calling\n * {@link SimpleStore#get} instead of delegating to {@link Mapper#find}.\n *\n * As part of implementing your own caching strategy, you may choose to\n * override this method.\n *\n * @example\n * const store = new SimpleStore({\n * cacheFind (mapperName, data, id, opts) {\n * // Let's say for a particular Resource, we always want to pull fresh from the server\n * if (mapperName === 'schedule') {\n * // Return without saving an entry to SimpleStore#_completedQueries\n * return;\n * }\n * // Otherwise perform default behavior\n * return SimpleStore.prototype.cacheFind.call(this, mapperName, data, id, opts);\n * }\n * });\n *\n * @example\n * // Extend using ES2015 class syntax.\n * class MyStore extends SimpleStore {\n * cacheFind (mapperName, data, id, opts) {\n * // Let's say for a particular Resource, we always want to pull fresh from the server\n * if (mapperName === 'schedule') {\n * // Return without saving an entry to SimpleStore#_completedQueries\n * return;\n * }\n * // Otherwise perform default behavior\n * return super.cacheFind(mapperName, data, id, opts);\n * }\n * }\n * const store = new MyStore();\n *\n * @method SimpleStore#cacheFind\n * @param {string} name The `name` argument passed to {@link SimpleStore#find}.\n * @param {*} data The result to cache.\n * @param {(string|number)} id The `id` argument passed to {@link SimpleStore#find}.\n * @param {object} opts The `opts` argument passed to {@link SimpleStore#find}.\n * @since 3.0.0\n */\n cacheFind (name, data, id, opts) {\n this._completedQueries[name][id] = (name, id, opts) => this.get(name, id)\n },\n\n /**\n * Mark a {@link Mapper#findAll} result as cached by adding an entry to\n * {@link SimpleStore#_completedQueries}. By default, once a `findAll` entry is\n * added it means subsequent calls to the same Resource with the same `query`\n * argument will immediately resolve with the result of calling\n * {@link SimpleStore#filter} instead of delegating to {@link Mapper#findAll}.\n *\n * As part of implementing your own caching strategy, you may choose to\n * override this method.\n *\n * @example\n * const store = new SimpleStore({\n * cachedFindAll (mapperName, data, hash, opts) {\n * // Let's say for a particular Resource, we always want to pull fresh from the server\n * if (mapperName === 'schedule') {\n * // Return without saving an entry to SimpleStore#_completedQueries\n * return;\n * }\n * // Otherwise perform default behavior.\n * return SimpleStore.prototype.cachedFindAll.call(this, mapperName, data, hash, opts);\n * }\n * });\n *\n * @example\n * // Extend using ES2015 class syntax.\n * class MyStore extends SimpleStore {\n * cachedFindAll (mapperName, data, hash, opts) {\n * // Let's say for a particular Resource, we always want to pull fresh from the server\n * if (mapperName === 'schedule') {\n * // Return without saving an entry to SimpleStore#_completedQueries\n * return;\n * }\n * // Otherwise perform default behavior.\n * return super.cachedFindAll(mapperName, data, hash, opts);\n * }\n * }\n * const store = new MyStore();\n *\n * @method SimpleStore#cacheFindAll\n * @param {string} name The `name` argument passed to {@link SimpleStore#findAll}.\n * @param {*} data The result to cache.\n * @param {string} hash The result of calling {@link SimpleStore#hashQuery} on\n * the `query` argument passed to {@link SimpleStore#findAll}.\n * @param {object} opts The `opts` argument passed to {@link SimpleStore#findAll}.\n * @since 3.0.0\n */\n cacheFindAll (name, data, hash, opts) {\n this._completedQueries[name][hash] = (name, hash, opts) => this.filter(name, utils.fromJson(hash))\n },\n\n /**\n * Remove __all__ records from the in-memory store and reset\n * {@link SimpleStore#_completedQueries}.\n *\n * @method SimpleStore#clear\n * @returns {Object} Object containing all records that were in the store.\n * @see SimpleStore#remove\n * @see SimpleStore#removeAll\n * @since 3.0.0\n */\n clear () {\n const removed = {}\n utils.forOwn(this._collections, (collection, name) => {\n removed[name] = collection.removeAll()\n this._completedQueries[name] = {}\n })\n return removed\n },\n\n /**\n * Fired during {@link SimpleStore#create}. See\n * {@link SimpleStore~beforeCreateListener} for how to listen for this event.\n *\n * @event SimpleStore#beforeCreate\n * @see SimpleStore~beforeCreateListener\n * @see SimpleStore#create\n */\n /**\n * Callback signature for the {@link SimpleStore#event:beforeCreate} event.\n *\n * @example\n * function onBeforeCreate (mapperName, props, opts) {\n * // do something\n * }\n * store.on('beforeCreate', onBeforeCreate);\n *\n * @callback SimpleStore~beforeCreateListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeCreate}.\n * @param {object} props The `props` argument received by {@link Mapper#beforeCreate}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeCreate}.\n * @see SimpleStore#event:beforeCreate\n * @see SimpleStore#create\n * @since 3.0.0\n */\n /**\n * Fired during {@link SimpleStore#create}. See\n * {@link SimpleStore~afterCreateListener} for how to listen for this event.\n *\n * @event SimpleStore#afterCreate\n * @see SimpleStore~afterCreateListener\n * @see SimpleStore#create\n */\n /**\n * Callback signature for the {@link SimpleStore#event:afterCreate} event.\n *\n * @example\n * function onAfterCreate (mapperName, props, opts, result) {\n * // do something\n * }\n * store.on('afterCreate', onAfterCreate);\n *\n * @callback SimpleStore~afterCreateListener\n * @param {string} name The `name` argument received by {@link Mapper#afterCreate}.\n * @param {object} props The `props` argument received by {@link Mapper#afterCreate}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterCreate}.\n * @param {object} result The `result` argument received by {@link Mapper#afterCreate}.\n * @see SimpleStore#event:afterCreate\n * @see SimpleStore#create\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#create}. Adds the created record to the store.\n *\n * @example\n * import { SimpleStore } from 'js-data';\n * import { HttpAdapter } from 'js-data-http';\n *\n * const store = new SimpleStore();\n * store.registerAdapter('http', new HttpAdapter(), { default: true });\n *\n * store.defineMapper('book');\n *\n * // Since this example uses the http adapter, we'll get something like:\n * //\n * // POST /book {\"author_id\":1234,...}\n * store.create('book', {\n * author_id: 1234,\n * edition: 'First Edition',\n * title: 'Respect your Data'\n * }).then((book) => {\n * console.log(book.id); // 120392\n * console.log(book.title); // \"Respect your Data\"\n * });\n *\n * @fires SimpleStore#beforeCreate\n * @fires SimpleStore#afterCreate\n * @fires SimpleStore#add\n * @method SimpleStore#create\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {object} record Passed to {@link Mapper#create}.\n * @param {object} [opts] Passed to {@link Mapper#create}. See\n * {@link Mapper#create} for more configuration options.\n * @returns {Promise} Resolves with the result of the create.\n * @since 3.0.0\n */\n create (name, record, opts) {\n opts || (opts = {})\n return Container.prototype.create.call(this, name, record, opts)\n .then((result) => this._end(name, result, opts))\n },\n\n /**\n * Fired during {@link SimpleStore#createMany}. See\n * {@link SimpleStore~beforeCreateManyListener} for how to listen for this event.\n *\n * @event SimpleStore#beforeCreateMany\n * @see SimpleStore~beforeCreateManyListener\n * @see SimpleStore#createMany\n */\n /**\n * Callback signature for the {@link SimpleStore#event:beforeCreateMany} event.\n *\n * @example\n * function onBeforeCreateMany (mapperName, records, opts) {\n * // do something\n * }\n * store.on('beforeCreateMany', onBeforeCreateMany);\n *\n * @callback SimpleStore~beforeCreateManyListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeCreateMany}.\n * @param {object} records The `records` argument received by {@link Mapper#beforeCreateMany}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeCreateMany}.\n * @see SimpleStore#event:beforeCreateMany\n * @see SimpleStore#createMany\n * @since 3.0.0\n */\n /**\n * Fired during {@link SimpleStore#createMany}. See\n * {@link SimpleStore~afterCreateManyListener} for how to listen for this event.\n *\n * @event SimpleStore#afterCreateMany\n * @see SimpleStore~afterCreateManyListener\n * @see SimpleStore#createMany\n */\n /**\n * Callback signature for the {@link SimpleStore#event:afterCreateMany} event.\n *\n * @example\n * function onAfterCreateMany (mapperName, records, opts, result) {\n * // do something\n * }\n * store.on('afterCreateMany', onAfterCreateMany);\n *\n * @callback SimpleStore~afterCreateManyListener\n * @param {string} name The `name` argument received by {@link Mapper#afterCreateMany}.\n * @param {object} records The `records` argument received by {@link Mapper#afterCreateMany}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterCreateMany}.\n * @param {object} result The `result` argument received by {@link Mapper#afterCreateMany}.\n * @see SimpleStore#event:afterCreateMany\n * @see SimpleStore#createMany\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#createMany}. Adds the created records to the\n * store.\n *\n * @example\n * import { SimpleStore } from 'js-data';\n * import { HttpAdapter } from 'js-data-http';\n *\n * const store = new SimpleStore();\n * store.registerAdapter('http', new HttpAdapter(), { default: true });\n *\n * store.defineMapper('book');\n *\n * // Since this example uses the http adapter, we'll get something like:\n * //\n * // POST /book [{\"author_id\":1234,...},{...}]\n * store.createMany('book', [{\n * author_id: 1234,\n * edition: 'First Edition',\n * title: 'Respect your Data'\n * }, {\n * author_id: 1234,\n * edition: 'Second Edition',\n * title: 'Respect your Data'\n * }]).then((books) => {\n * console.log(books[0].id); // 142394\n * console.log(books[0].title); // \"Respect your Data\"\n * });\n *\n * @fires SimpleStore#beforeCreateMany\n * @fires SimpleStore#afterCreateMany\n * @fires SimpleStore#add\n * @method SimpleStore#createMany\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {array} records Passed to {@link Mapper#createMany}.\n * @param {object} [opts] Passed to {@link Mapper#createMany}. See\n * {@link Mapper#createMany} for more configuration options.\n * @returns {Promise} Resolves with the result of the create.\n * @since 3.0.0\n */\n createMany (name, records, opts) {\n opts || (opts = {})\n return Container.prototype.createMany.call(this, name, records, opts)\n .then((result) => this._end(name, result, opts))\n },\n\n defineMapper (name, opts) {\n const self = this\n const mapper = Container.prototype.defineMapper.call(self, name, opts)\n self._pendingQueries[name] = {}\n self._completedQueries[name] = {}\n mapper.relationList || Object.defineProperty(mapper, 'relationList', { value: [] })\n\n const collectionOpts = {\n // Make sure the collection has somewhere to store \"added\" timestamps\n _added: {},\n // Give the collection a reference to this SimpleStore\n datastore: self,\n // The mapper tied to the collection\n mapper\n }\n\n if (opts && ('onConflict' in opts)) {\n collectionOpts.onConflict = opts.onConflict\n }\n\n // The SimpleStore uses a subclass of Collection that is \"SimpleStore-aware\"\n const collection = self._collections[name] = new self.collectionClass(null, collectionOpts) // eslint-disable-line\n\n const schema = mapper.schema || {}\n const properties = schema.properties || {}\n // TODO: Make it possible index nested properties?\n utils.forOwn(properties, function (opts, prop) {\n if (opts.indexed) {\n collection.createIndex(prop)\n }\n })\n\n // Create a secondary index on the \"added\" timestamps of records in the\n // collection\n collection.createIndex('addedTimestamps', ['$'], {\n fieldGetter (obj) {\n return collection._added[collection.recordId(obj)]\n }\n })\n\n collection.on('all', function (...args) {\n self._onCollectionEvent(name, ...args)\n })\n\n return mapper\n },\n\n /**\n * Fired during {@link SimpleStore#destroy}. See\n * {@link SimpleStore~beforeDestroyListener} for how to listen for this event.\n *\n * @event SimpleStore#beforeDestroy\n * @see SimpleStore~beforeDestroyListener\n * @see SimpleStore#destroy\n */\n /**\n * Callback signature for the {@link SimpleStore#event:beforeDestroy} event.\n *\n * @example\n * function onBeforeDestroy (mapperName, id, opts) {\n * // do something\n * }\n * store.on('beforeDestroy', onBeforeDestroy);\n *\n * @callback SimpleStore~beforeDestroyListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeDestroy}.\n * @param {string|number} id The `id` argument received by {@link Mapper#beforeDestroy}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeDestroy}.\n * @see SimpleStore#event:beforeDestroy\n * @see SimpleStore#destroy\n * @since 3.0.0\n */\n /**\n * Fired during {@link SimpleStore#destroy}. See\n * {@link SimpleStore~afterDestroyListener} for how to listen for this event.\n *\n * @event SimpleStore#afterDestroy\n * @see SimpleStore~afterDestroyListener\n * @see SimpleStore#destroy\n */\n /**\n * Callback signature for the {@link SimpleStore#event:afterDestroy} event.\n *\n * @example\n * function onAfterDestroy (mapperName, id, opts, result) {\n * // do something\n * }\n * store.on('afterDestroy', onAfterDestroy);\n *\n * @callback SimpleStore~afterDestroyListener\n * @param {string} name The `name` argument received by {@link Mapper#afterDestroy}.\n * @param {string|number} id The `id` argument received by {@link Mapper#afterDestroy}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterDestroy}.\n * @param {object} result The `result` argument received by {@link Mapper#afterDestroy}.\n * @see SimpleStore#event:afterDestroy\n * @see SimpleStore#destroy\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#destroy}. Removes any destroyed record from the\n * in-memory store. Clears out any {@link SimpleStore#_completedQueries} entries\n * associated with the provided `id`.\n *\n * @example\n * import { SimpleStore } from 'js-data';\n * import { HttpAdapter } from 'js-data-http';\n *\n * const store = new SimpleStore();\n * store.registerAdapter('http', new HttpAdapter(), { default: true });\n *\n * store.defineMapper('book');\n *\n * store.add('book', { id: 1234, title: 'Data Management is Hard' });\n *\n * // Since this example uses the http adapter, we'll get something like:\n * //\n * // DELETE /book/1234\n * store.destroy('book', 1234).then(() => {\n * // The book record is no longer in the in-memory store\n * console.log(store.get('book', 1234)); // undefined\n *\n * return store.find('book', 1234);\n * }).then((book) {\n * // The book was deleted from the database too\n * console.log(book); // undefined\n * });\n *\n * @fires SimpleStore#beforeDestroy\n * @fires SimpleStore#afterDestroy\n * @fires SimpleStore#remove\n * @method SimpleStore#destroy\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {(string|number)} id Passed to {@link Mapper#destroy}.\n * @param {object} [opts] Passed to {@link Mapper#destroy}. See\n * {@link Mapper#destroy} for more configuration options.\n * @returns {Promise} Resolves when the destroy operation completes.\n * @since 3.0.0\n */\n destroy (name, id, opts) {\n opts || (opts = {})\n return Container.prototype.destroy.call(this, name, id, opts).then((result) => {\n const record = this.getCollection(name).remove(id, opts)\n\n if (opts.raw) {\n result.data = record\n } else {\n result = record\n }\n delete this._pendingQueries[name][id]\n delete this._completedQueries[name][id]\n return result\n })\n },\n\n /**\n * Fired during {@link SimpleStore#destroyAll}. See\n * {@link SimpleStore~beforeDestroyAllListener} for how to listen for this event.\n *\n * @event SimpleStore#beforeDestroyAll\n * @see SimpleStore~beforeDestroyAllListener\n * @see SimpleStore#destroyAll\n */\n /**\n * Callback signature for the {@link SimpleStore#event:beforeDestroyAll} event.\n *\n * @example\n * function onBeforeDestroyAll (mapperName, query, opts) {\n * // do something\n * }\n * store.on('beforeDestroyAll', onBeforeDestroyAll);\n *\n * @callback SimpleStore~beforeDestroyAllListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeDestroyAll}.\n * @param {object} query The `query` argument received by {@link Mapper#beforeDestroyAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeDestroyAll}.\n * @see SimpleStore#event:beforeDestroyAll\n * @see SimpleStore#destroyAll\n * @since 3.0.0\n */\n /**\n * Fired during {@link SimpleStore#destroyAll}. See\n * {@link SimpleStore~afterDestroyAllListener} for how to listen for this event.\n *\n * @event SimpleStore#afterDestroyAll\n * @see SimpleStore~afterDestroyAllListener\n * @see SimpleStore#destroyAll\n */\n /**\n * Callback signature for the {@link SimpleStore#event:afterDestroyAll} event.\n *\n * @example\n * function onAfterDestroyAll (mapperName, query, opts, result) {\n * // do something\n * }\n * store.on('afterDestroyAll', onAfterDestroyAll);\n *\n * @callback SimpleStore~afterDestroyAllListener\n * @param {string} name The `name` argument received by {@link Mapper#afterDestroyAll}.\n * @param {object} query The `query` argument received by {@link Mapper#afterDestroyAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterDestroyAll}.\n * @param {object} result The `result` argument received by {@link Mapper#afterDestroyAll}.\n * @see SimpleStore#event:afterDestroyAll\n * @see SimpleStore#destroyAll\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#destroyAll}. Removes any destroyed records from\n * the in-memory store.\n *\n * @example\n * import { SimpleStore } from 'js-data';\n * import { HttpAdapter } from 'js-data-http';\n *\n * const store = new SimpleStore();\n * store.registerAdapter('http', new HttpAdapter(), { default: true });\n *\n * store.defineMapper('book');\n *\n * store.add('book', { id: 1234, title: 'Data Management is Hard' });\n *\n * // Since this example uses the http adapter, we'll get something like:\n * //\n * // DELETE /book/1234\n * store.destroy('book', 1234).then(() => {\n * // The book record is gone from the in-memory store\n * console.log(store.get('book', 1234)); // undefined\n * return store.find('book', 1234);\n * }).then((book) {\n * // The book was deleted from the database too\n * console.log(book); // undefined\n * });\n *\n * @fires SimpleStore#beforeDestroyAll\n * @fires SimpleStore#afterDestroyAll\n * @fires SimpleStore#remove\n * @method SimpleStore#destroyAll\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {object} [query] Passed to {@link Mapper#destroyAll}.\n * @param {object} [opts] Passed to {@link Mapper#destroyAll}. See\n * {@link Mapper#destroyAll} for more configuration options.\n * @returns {Promise} Resolves when the delete completes.\n * @since 3.0.0\n */\n destroyAll (name, query, opts) {\n opts || (opts = {})\n return Container.prototype.destroyAll.call(this, name, query, opts).then((result) => {\n const records = this.getCollection(name).removeAll(query, opts)\n\n if (opts.raw) {\n result.data = records\n } else {\n result = records\n }\n const hash = this.hashQuery(name, query, opts)\n delete this._pendingQueries[name][hash]\n delete this._completedQueries[name][hash]\n return result\n })\n },\n\n eject (name, id, opts) {\n console.warn('DEPRECATED: \"eject\" is deprecated, use \"remove\" instead')\n return this.remove(name, id, opts)\n },\n\n ejectAll (name, query, opts) {\n console.warn('DEPRECATED: \"ejectAll\" is deprecated, use \"removeAll\" instead')\n return this.removeAll(name, query, opts)\n },\n\n /**\n * Fired during {@link SimpleStore#find}. See\n * {@link SimpleStore~beforeFindListener} for how to listen for this event.\n *\n * @event SimpleStore#beforeFind\n * @see SimpleStore~beforeFindListener\n * @see SimpleStore#find\n */\n /**\n * Callback signature for the {@link SimpleStore#event:beforeFind} event.\n *\n * @example\n * function onBeforeFind (mapperName, id, opts) {\n * // do something\n * }\n * store.on('beforeFind', onBeforeFind);\n *\n * @callback SimpleStore~beforeFindListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeFind}.\n * @param {string|number} id The `id` argument received by {@link Mapper#beforeFind}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeFind}.\n * @see SimpleStore#event:beforeFind\n * @see SimpleStore#find\n * @since 3.0.0\n */\n /**\n * Fired during {@link SimpleStore#find}. See\n * {@link SimpleStore~afterFindListener} for how to listen for this event.\n *\n * @event SimpleStore#afterFind\n * @see SimpleStore~afterFindListener\n * @see SimpleStore#find\n */\n /**\n * Callback signature for the {@link SimpleStore#event:afterFind} event.\n *\n * @example\n * function onAfterFind (mapperName, id, opts, result) {\n * // do something\n * }\n * store.on('afterFind', onAfterFind);\n *\n * @callback SimpleStore~afterFindListener\n * @param {string} name The `name` argument received by {@link Mapper#afterFind}.\n * @param {string|number} id The `id` argument received by {@link Mapper#afterFind}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterFind}.\n * @param {object} result The `result` argument received by {@link Mapper#afterFind}.\n * @see SimpleStore#event:afterFind\n * @see SimpleStore#find\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#find}. Adds any found record to the store.\n *\n * @example\n * import { SimpleStore } from 'js-data';\n * import { HttpAdapter } from 'js-data-http';\n *\n * const store = new SimpleStore();\n * store.registerAdapter('http', new HttpAdapter(), { default: true });\n *\n * store.defineMapper('book');\n *\n * // Since this example uses the http adapter, we'll get something like:\n * //\n * // GET /book/1234\n * store.find('book', 1234).then((book) => {\n * // The book record is now in the in-memory store\n * console.log(store.get('book', 1234) === book); // true\n * });\n *\n * @fires SimpleStore#beforeFind\n * @fires SimpleStore#afterFind\n * @fires SimpleStore#add\n * @method SimpleStore#find\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {(string|number)} id Passed to {@link Mapper#find}.\n * @param {object} [opts] Passed to {@link Mapper#find}.\n * @param {boolean} [opts.force] Bypass cacheFind\n * @param {boolean|Function} [opts.usePendingFind] See {@link SimpleStore#usePendingFind}\n * @returns {Promise} Resolves with the result, if any.\n * @since 3.0.0\n */\n find (name, id, opts) {\n opts || (opts = {})\n const mapper = this.getMapper(name)\n const pendingQuery = this._pendingQueries[name][id]\n const usePendingFind = opts.usePendingFind === undefined ? this.usePendingFind : opts.usePendingFind\n utils._(opts, mapper)\n\n if (pendingQuery && (utils.isFunction(usePendingFind) ? usePendingFind.call(this, name, id, opts) : usePendingFind)) {\n return pendingQuery\n }\n const item = this.cachedFind(name, id, opts)\n\n if (opts.force || !item) {\n const promise = this._pendingQueries[name][id] = Container.prototype.find.call(this, name, id, opts)\n return promise\n .then((result) => {\n delete this._pendingQueries[name][id]\n result = this._end(name, result, opts)\n this.cacheFind(name, result, id, opts)\n return result\n }, (err) => {\n delete this._pendingQueries[name][id]\n return utils.reject(err)\n })\n }\n\n return utils.resolve(item)\n },\n\n /**\n * Fired during {@link SimpleStore#findAll}. See\n * {@link SimpleStore~beforeFindAllListener} for how to listen for this event.\n *\n * @event SimpleStore#beforeFindAll\n * @see SimpleStore~beforeFindAllListener\n * @see SimpleStore#findAll\n */\n /**\n * Callback signature for the {@link SimpleStore#event:beforeFindAll} event.\n *\n * @example\n * function onBeforeFindAll (mapperName, query, opts) {\n * // do something\n * }\n * store.on('beforeFindAll', onBeforeFindAll);\n *\n * @callback SimpleStore~beforeFindAllListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeFindAll}.\n * @param {object} query The `query` argument received by {@link Mapper#beforeFindAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeFindAll}.\n * @see SimpleStore#event:beforeFindAll\n * @see SimpleStore#findAll\n * @since 3.0.0\n */\n /**\n * Fired during {@link SimpleStore#findAll}. See\n * {@link SimpleStore~afterFindAllListener} for how to listen for this event.\n *\n * @event SimpleStore#afterFindAll\n * @see SimpleStore~afterFindAllListener\n * @see SimpleStore#findAll\n */\n /**\n * Callback signature for the {@link SimpleStore#event:afterFindAll} event.\n *\n * @example\n * function onAfterFindAll (mapperName, query, opts, result) {\n * // do something\n * }\n * store.on('afterFindAll', onAfterFindAll);\n *\n * @callback SimpleStore~afterFindAllListener\n * @param {string} name The `name` argument received by {@link Mapper#afterFindAll}.\n * @param {object} query The `query` argument received by {@link Mapper#afterFindAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterFindAll}.\n * @param {object} result The `result` argument received by {@link Mapper#afterFindAll}.\n * @see SimpleStore#event:afterFindAll\n * @see SimpleStore#findAll\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#findAll}. Adds any found records to the store.\n *\n * @example\n * import { SimpleStore } from 'js-data';\n * import { HttpAdapter } from 'js-data-http';\n *\n * const store = new SimpleStore();\n * store.registerAdapter('http', new HttpAdapter(), { default: true });\n *\n * store.defineMapper('movie');\n *\n * // Since this example uses the http adapter, we'll get something like:\n * //\n * // GET /movie?rating=PG\n * store.find('movie', { rating: 'PG' }).then((movies) => {\n * // The movie records are now in the in-memory store\n * console.log(store.filter('movie'));\n * });\n *\n * @fires SimpleStore#beforeFindAll\n * @fires SimpleStore#afterFindAll\n * @fires SimpleStore#add\n * @method SimpleStore#findAll\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {object} [query] Passed to {@link Mapper.findAll}.\n * @param {object} [opts] Passed to {@link Mapper.findAll}.\n * @param {boolean} [opts.force] Bypass cacheFindAll\n * @param {boolean|Function} [opts.usePendingFindAll] See {@link SimpleStore#usePendingFindAll}\n * @returns {Promise} Resolves with the result, if any.\n * @since 3.0.0\n */\n findAll (name, query, opts) {\n opts || (opts = {})\n const mapper = this.getMapper(name)\n const hash = this.hashQuery(name, query, opts)\n const pendingQuery = this._pendingQueries[name][hash]\n const usePendingFindAll = opts.usePendingFindAll === undefined ? this.usePendingFindAll : opts.usePendingFindAll\n utils._(opts, mapper)\n\n if (pendingQuery && (utils.isFunction(usePendingFindAll) ? usePendingFindAll.call(this, name, query, opts) : usePendingFindAll)) {\n return pendingQuery\n }\n\n const items = this.cachedFindAll(name, hash, opts)\n\n if (opts.force || !items) {\n const promise = this._pendingQueries[name][hash] = Container.prototype.findAll.call(this, name, query, opts)\n return promise\n .then((result) => {\n delete this._pendingQueries[name][hash]\n result = this._end(name, result, opts)\n this.cacheFindAll(name, result, hash, opts)\n return result\n }, (err) => {\n delete this._pendingQueries[name][hash]\n return utils.reject(err)\n })\n }\n\n return utils.resolve(items)\n },\n\n /**\n * Return the {@link Collection} with the given name, if for some\n * reason you need a direct reference to the collection.\n *\n * @method SimpleStore#getCollection\n * @param {string} name Name of the {@link Collection} to retrieve.\n * @returns {Collection}\n * @since 3.0.0\n * @throws {Error} Thrown if the specified {@link Collection} does not\n * exist.\n */\n getCollection (name) {\n const collection = this._collections[name]\n if (!collection) {\n throw utils.err(`${DOMAIN}#getCollection`, name)(404, 'collection')\n }\n return collection\n },\n\n /**\n * Hashing function used to cache {@link SimpleStore#find} and\n * {@link SimpleStore#findAll} requests. This method simply JSONifies the\n * `query` argument passed to {@link SimpleStore#find} or\n * {@link SimpleStore#findAll}.\n *\n * Override this method for custom hashing behavior.\n * @method SimpleStore#hashQuery\n * @param {string} name The `name` argument passed to {@link SimpleStore#find}\n * or {@link SimpleStore#findAll}.\n * @param {object} query The `query` argument passed to {@link SimpleStore#find}\n * or {@link SimpleStore#findAll}.\n * @returns {string} The JSONified `query`.\n * @since 3.0.0\n */\n hashQuery (name, query, opts) {\n return utils.toJson(query || {})\n },\n\n inject (name, records, opts) {\n console.warn('DEPRECATED: \"inject\" is deprecated, use \"add\" instead')\n return this.add(name, records, opts)\n },\n\n /**\n * Wrapper for {@link Collection#remove}. Removes the specified\n * {@link Record} from the store.\n *\n * @example SimpleStore#remove\n * const JSData = require('js-data');\n * const { SimpleStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new SimpleStore();\n * store.defineMapper('book');\n * console.log(store.getAll('book').length);\n * store.add('book', { id: 1234 });\n * console.log(store.getAll('book').length);\n * store.remove('book', 1234);\n * console.log(store.getAll('book').length);\n *\n * @fires SimpleStore#remove\n * @method SimpleStore#remove\n * @param {string} name The name of the {@link Collection} to target.\n * @param {string|number} id The primary key of the {@link Record} to remove.\n * @param {object} [opts] Configuration options.\n * @param {string[]} [opts.with] Relations of the {@link Record} to also\n * remove from the store.\n * @returns {Record} The removed {@link Record}, if any.\n * @see Collection#add\n * @see Collection#add\n * @since 3.0.0\n */\n remove (name, id, opts) {\n const record = this.getCollection(name).remove(id, opts)\n if (record) {\n this.removeRelated(name, [record], opts)\n }\n return record\n },\n\n /**\n * Wrapper for {@link Collection#removeAll}. Removes the selected\n * {@link Record}s from the store.\n *\n * @example SimpleStore#removeAll\n * const JSData = require('js-data');\n * const { SimpleStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new SimpleStore();\n * store.defineMapper('movie');\n * console.log(store.getAll('movie').length);\n * store.add('movie', [{ id: 3, rating: 'R' }, { id: 4, rating: 'PG-13' });\n * console.log(store.getAll('movie').length);\n * store.removeAll('movie', { rating: 'R' });\n * console.log(store.getAll('movie').length);\n *\n * @fires SimpleStore#remove\n * @method SimpleStore#removeAll\n * @param {string} name The name of the {@link Collection} to target.\n * @param {object} [query={}] Selection query. See {@link query}.\n * @param {object} [query.where] See {@link query.where}.\n * @param {number} [query.offset] See {@link query.offset}.\n * @param {number} [query.limit] See {@link query.limit}.\n * @param {string|Array[]} [query.orderBy] See {@link query.orderBy}.\n * @param {object} [opts] Configuration options.\n * @param {string[]} [opts.with] Relations of the {@link Record} to also\n * remove from the store.\n * @returns {Record} The removed {@link Record}s, if any.\n * @see Collection#add\n * @see Collection#add\n * @since 3.0.0\n */\n removeAll (name, query, opts) {\n if (!query || !Object.keys(query).length) {\n this._completedQueries[name] = {}\n } else {\n this._completedQueries[name][this.hashQuery(name, query, opts)] = undefined\n }\n const records = this.getCollection(name).removeAll(query, opts)\n if (records.length) {\n this.removeRelated(name, records, opts)\n }\n return records\n },\n\n /**\n * Remove from the store {@link Record}s that are related to the provided\n * {@link Record}(s).\n *\n * @fires SimpleStore#remove\n * @method SimpleStore#removeRelated\n * @param {string} name The name of the {@link Collection} to target.\n * @param {Record|Record[]} records {@link Record}s whose relations are to be\n * removed.\n * @param {object} [opts] Configuration options.\n * @param {string[]} [opts.with] Relations of the {@link Record}(s) to remove\n * from the store.\n * @since 3.0.0\n */\n removeRelated (name, records, opts) {\n if (!utils.isArray(records)) {\n records = [records]\n }\n utils.forEachRelation(this.getMapper(name), opts, (def, optsCopy) => {\n records.forEach((record) => {\n let relatedData\n let query\n if (def.foreignKey && (def.type === hasOneType || def.type === hasManyType)) {\n query = { [def.foreignKey]: def.getForeignKey(record) }\n } else if (def.type === hasManyType && def.localKeys) {\n query = {\n where: {\n [def.getRelation().idAttribute]: {\n in: utils.get(record, def.localKeys)\n }\n }\n }\n } else if (def.type === hasManyType && def.foreignKeys) {\n query = {\n where: {\n [def.foreignKeys]: {\n contains: def.getForeignKey(record)\n }\n }\n }\n } else if (def.type === belongsToType) {\n relatedData = this.remove(def.relation, def.getForeignKey(record), optsCopy)\n }\n if (query) {\n relatedData = this.removeAll(def.relation, query, optsCopy)\n }\n if (relatedData) {\n if (utils.isArray(relatedData) && !relatedData.length) {\n return\n }\n if (def.type === hasOneType) {\n relatedData = relatedData[0]\n }\n def.setLocalField(record, relatedData)\n }\n })\n })\n },\n\n /**\n * Fired during {@link SimpleStore#update}. See\n * {@link SimpleStore~beforeUpdateListener} for how to listen for this event.\n *\n * @event SimpleStore#beforeUpdate\n * @see SimpleStore~beforeUpdateListener\n * @see SimpleStore#update\n */\n /**\n * Callback signature for the {@link SimpleStore#event:beforeUpdate} event.\n *\n * @example\n * function onBeforeUpdate (mapperName, id, props, opts) {\n * // do something\n * }\n * store.on('beforeUpdate', onBeforeUpdate);\n *\n * @callback SimpleStore~beforeUpdateListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeUpdate}.\n * @param {string|number} id The `id` argument received by {@link Mapper#beforeUpdate}.\n * @param {object} props The `props` argument received by {@link Mapper#beforeUpdate}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdate}.\n * @see SimpleStore#event:beforeUpdate\n * @see SimpleStore#update\n * @since 3.0.0\n */\n /**\n * Fired during {@link SimpleStore#update}. See\n * {@link SimpleStore~afterUpdateListener} for how to listen for this event.\n *\n * @event SimpleStore#afterUpdate\n * @see SimpleStore~afterUpdateListener\n * @see SimpleStore#update\n */\n /**\n * Callback signature for the {@link SimpleStore#event:afterUpdate} event.\n *\n * @example\n * function onAfterUpdate (mapperName, id, props, opts, result) {\n * // do something\n * }\n * store.on('afterUpdate', onAfterUpdate);\n *\n * @callback SimpleStore~afterUpdateListener\n * @param {string} name The `name` argument received by {@link Mapper#afterUpdate}.\n * @param {string|number} id The `id` argument received by {@link Mapper#afterUpdate}.\n * @param {object} props The `props` argument received by {@link Mapper#afterUpdate}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdate}.\n * @param {object} result The `result` argument received by {@link Mapper#afterUpdate}.\n * @see SimpleStore#event:afterUpdate\n * @see SimpleStore#update\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#update}. Adds the updated {@link Record} to the\n * store.\n *\n * @example\n * import { SimpleStore } from 'js-data';\n * import { HttpAdapter } from 'js-data-http';\n *\n * const store = new SimpleStore();\n * store.registerAdapter('http', new HttpAdapter(), { default: true });\n *\n * store.defineMapper('post');\n *\n * // Since this example uses the http adapter, we'll get something like:\n * //\n * // PUT /post/1234 {\"status\":\"published\"}\n * store.update('post', 1, { status: 'published' }).then((post) => {\n * // The post record has also been updated in the in-memory store\n * console.log(store.get('post', 1234));\n * });\n *\n * @fires SimpleStore#beforeUpdate\n * @fires SimpleStore#afterUpdate\n * @fires SimpleStore#add\n * @method SimpleStore#update\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {(string|number)} id Passed to {@link Mapper#update}.\n * @param {object} record Passed to {@link Mapper#update}.\n * @param {object} [opts] Passed to {@link Mapper#update}. See\n * {@link Mapper#update} for more configuration options.\n * @returns {Promise} Resolves with the result of the update.\n * @since 3.0.0\n */\n update (name, id, record, opts) {\n opts || (opts = {})\n return Container.prototype.update.call(this, name, id, record, opts)\n .then((result) => this._end(name, result, opts))\n },\n\n /**\n * Fired during {@link SimpleStore#updateAll}. See\n * {@link SimpleStore~beforeUpdateAllListener} for how to listen for this event.\n *\n * @event SimpleStore#beforeUpdateAll\n * @see SimpleStore~beforeUpdateAllListener\n * @see SimpleStore#updateAll\n */\n /**\n * Callback signature for the {@link SimpleStore#event:beforeUpdateAll} event.\n *\n * @example\n * function onBeforeUpdateAll (mapperName, props, query, opts) {\n * // do something\n * }\n * store.on('beforeUpdateAll', onBeforeUpdateAll);\n *\n * @callback SimpleStore~beforeUpdateAllListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeUpdateAll}.\n * @param {object} props The `props` argument received by {@link Mapper#beforeUpdateAll}.\n * @param {object} query The `query` argument received by {@link Mapper#beforeUpdateAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdateAll}.\n * @see SimpleStore#event:beforeUpdateAll\n * @see SimpleStore#updateAll\n * @since 3.0.0\n */\n /**\n * Fired during {@link SimpleStore#updateAll}. See\n * {@link SimpleStore~afterUpdateAllListener} for how to listen for this event.\n *\n * @event SimpleStore#afterUpdateAll\n * @see SimpleStore~afterUpdateAllListener\n * @see SimpleStore#updateAll\n */\n /**\n * Callback signature for the {@link SimpleStore#event:afterUpdateAll} event.\n *\n * @example\n * function onAfterUpdateAll (mapperName, props, query, opts, result) {\n * // do something\n * }\n * store.on('afterUpdateAll', onAfterUpdateAll);\n *\n * @callback SimpleStore~afterUpdateAllListener\n * @param {string} name The `name` argument received by {@link Mapper#afterUpdateAll}.\n * @param {object} props The `props` argument received by {@link Mapper#afterUpdateAll}.\n * @param {object} query The `query` argument received by {@link Mapper#afterUpdateAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdateAll}.\n * @param {object} result The `result` argument received by {@link Mapper#afterUpdateAll}.\n * @see SimpleStore#event:afterUpdateAll\n * @see SimpleStore#updateAll\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#updateAll}. Adds the updated {@link Record}s to\n * the store.\n *\n * @example\n * import { SimpleStore } from 'js-data';\n * import { HttpAdapter } from 'js-data-http';\n *\n * const store = new SimpleStore();\n * store.registerAdapter('http', new HttpAdapter(), { default: true });\n *\n * store.defineMapper('post');\n *\n * // Since this example uses the http adapter, we'll get something like:\n * //\n * // PUT /post?author_id=1234 {\"status\":\"published\"}\n * store.updateAll('post', { author_id: 1234 }, { status: 'published' }).then((posts) => {\n * // The post records have also been updated in the in-memory store\n * console.log(store.filter('posts', { author_id: 1234 }));\n * });\n *\n * @fires SimpleStore#beforeUpdateAll\n * @fires SimpleStore#afterUpdateAll\n * @fires SimpleStore#add\n * @method SimpleStore#updateAll\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {object} props Passed to {@link Mapper#updateAll}.\n * @param {object} [query] Passed to {@link Mapper#updateAll}.\n * @param {object} [opts] Passed to {@link Mapper#updateAll}. See\n * {@link Mapper#updateAll} for more configuration options.\n * @returns {Promise} Resolves with the result of the update.\n * @since 3.0.0\n */\n updateAll (name, props, query, opts) {\n opts || (opts = {})\n return Container.prototype.updateAll.call(this, name, props, query, opts)\n .then((result) => this._end(name, result, opts))\n },\n\n /**\n * Fired during {@link SimpleStore#updateMany}. See\n * {@link SimpleStore~beforeUpdateManyListener} for how to listen for this event.\n *\n * @event SimpleStore#beforeUpdateMany\n * @see SimpleStore~beforeUpdateManyListener\n * @see SimpleStore#updateMany\n */\n /**\n * Callback signature for the {@link SimpleStore#event:beforeUpdateMany} event.\n *\n * @example\n * function onBeforeUpdateMany (mapperName, records, opts) {\n * // do something\n * }\n * store.on('beforeUpdateMany', onBeforeUpdateMany);\n *\n * @callback SimpleStore~beforeUpdateManyListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeUpdateMany}.\n * @param {object} records The `records` argument received by {@link Mapper#beforeUpdateMany}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdateMany}.\n * @see SimpleStore#event:beforeUpdateMany\n * @see SimpleStore#updateMany\n * @since 3.0.0\n */\n /**\n * Fired during {@link SimpleStore#updateMany}. See\n * {@link SimpleStore~afterUpdateManyListener} for how to listen for this event.\n *\n * @event SimpleStore#afterUpdateMany\n * @see SimpleStore~afterUpdateManyListener\n * @see SimpleStore#updateMany\n */\n /**\n * Callback signature for the {@link SimpleStore#event:afterUpdateMany} event.\n *\n * @example\n * function onAfterUpdateMany (mapperName, records, opts, result) {\n * // do something\n * }\n * store.on('afterUpdateMany', onAfterUpdateMany);\n *\n * @callback SimpleStore~afterUpdateManyListener\n * @param {string} name The `name` argument received by {@link Mapper#afterUpdateMany}.\n * @param {object} records The `records` argument received by {@link Mapper#afterUpdateMany}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdateMany}.\n * @param {object} result The `result` argument received by {@link Mapper#afterUpdateMany}.\n * @see SimpleStore#event:afterUpdateMany\n * @see SimpleStore#updateMany\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#updateMany}. Adds the updated {@link Record}s to\n * the store.\n *\n * @example\n * import { SimpleStore } from 'js-data';\n * import { HttpAdapter } from 'js-data-http';\n *\n * const store = new SimpleStore();\n * store.registerAdapter('http', new HttpAdapter(), { default: true });\n *\n * store.defineMapper('post');\n *\n * // Since this example uses the http adapter, we'll get something like:\n * //\n * // PUT /post [{\"id\":3,status\":\"published\"},{\"id\":4,status\":\"published\"}]\n * store.updateMany('post', [\n * { id: 3, status: 'published' },\n * { id: 4, status: 'published' }\n * ]).then((posts) => {\n * // The post records have also been updated in the in-memory store\n * console.log(store.getAll('post', 3, 4));\n * });\n *\n * @fires SimpleStore#beforeUpdateMany\n * @fires SimpleStore#afterUpdateMany\n * @fires SimpleStore#add\n * @method SimpleStore#updateMany\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {(Object[]|Record[])} records Passed to {@link Mapper#updateMany}.\n * @param {object} [opts] Passed to {@link Mapper#updateMany}. See\n * {@link Mapper#updateMany} for more configuration options.\n * @returns {Promise} Resolves with the result of the update.\n * @since 3.0.0\n */\n updateMany (name, records, opts) {\n opts || (opts = {})\n return Container.prototype.updateMany.call(this, name, records, opts)\n .then((result) => this._end(name, result, opts))\n }\n}\n\nproxiedCollectionMethods.forEach(function (method) {\n props[method] = function (name, ...args) {\n return this.getCollection(name)[method](...args)\n }\n})\n\nexport default Container.extend(props)\n\n/**\n * Fired when a record changes. Only works for records that have tracked fields.\n * See {@link SimpleStore~changeListener} on how to listen for this event.\n *\n * @event SimpleStore#change\n * @see SimpleStore~changeListener\n */\n\n/**\n * Callback signature for the {@link SimpleStore#event:change} event.\n *\n * @example\n * function onChange (mapperName, record, changes) {\n * // do something\n * }\n * store.on('change', onChange);\n *\n * @callback SimpleStore~changeListener\n * @param {string} name The name of the associated {@link Mapper}.\n * @param {Record} record The Record that changed.\n * @param {object} changes The changes.\n * @see SimpleStore#event:change\n * @since 3.0.0\n */\n\n/**\n * Fired when one or more records are added to the in-memory store. See\n * {@link SimpleStore~addListener} on how to listen for this event.\n *\n * @event SimpleStore#add\n * @see SimpleStore~addListener\n * @see SimpleStore#event:add\n * @see SimpleStore#add\n * @see SimpleStore#create\n * @see SimpleStore#createMany\n * @see SimpleStore#find\n * @see SimpleStore#findAll\n * @see SimpleStore#update\n * @see SimpleStore#updateAll\n * @see SimpleStore#updateMany\n */\n\n/**\n * Callback signature for the {@link SimpleStore#event:add} event.\n *\n * @example\n * function onAdd (mapperName, recordOrRecords) {\n * // do something\n * }\n * store.on('add', onAdd);\n *\n * @callback SimpleStore~addListener\n * @param {string} name The name of the associated {@link Mapper}.\n * @param {Record|Record[]} The Record or Records that were added.\n * @see SimpleStore#event:add\n * @see SimpleStore#add\n * @see SimpleStore#create\n * @see SimpleStore#createMany\n * @see SimpleStore#find\n * @see SimpleStore#findAll\n * @see SimpleStore#update\n * @see SimpleStore#updateAll\n * @see SimpleStore#updateMany\n * @since 3.0.0\n */\n\n/**\n * Fired when one or more records are removed from the in-memory store. See\n * {@link SimpleStore~removeListener} for how to listen for this event.\n *\n * @event SimpleStore#remove\n * @see SimpleStore~removeListener\n * @see SimpleStore#event:remove\n * @see SimpleStore#clear\n * @see SimpleStore#destroy\n * @see SimpleStore#destroyAll\n * @see SimpleStore#remove\n * @see SimpleStore#removeAll\n */\n\n/**\n * Callback signature for the {@link SimpleStore#event:remove} event.\n *\n * @example\n * function onRemove (mapperName, recordsOrRecords) {\n * // do something\n * }\n * store.on('remove', onRemove);\n *\n * @callback SimpleStore~removeListener\n * @param {string} name The name of the associated {@link Mapper}.\n * @param {Record|Record[]} Record or Records that were removed.\n * @see SimpleStore#event:remove\n * @see SimpleStore#clear\n * @see SimpleStore#destroy\n * @see SimpleStore#destroyAll\n * @see SimpleStore#remove\n * @see SimpleStore#removeAll\n * @since 3.0.0\n */\n\n/**\n * Create a subclass of this SimpleStore:\n * @example SimpleStore.extend\n * const JSData = require('js-data');\n * const { SimpleStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * // Extend the class using ES2015 class syntax.\n * class CustomSimpleStoreClass extends SimpleStore {\n * foo () { return 'bar'; }\n * static beep () { return 'boop'; }\n * }\n * const customSimpleStore = new CustomSimpleStoreClass();\n * console.log(customSimpleStore.foo());\n * console.log(CustomSimpleStoreClass.beep());\n *\n * // Extend the class using alternate method.\n * const OtherSimpleStoreClass = SimpleStore.extend({\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * })\n * const otherSimpleStore = new OtherSimpleStoreClass();\n * console.log(otherSimpleStore.foo());\n * console.log(OtherSimpleStoreClass.beep());\n *\n * // Extend the class, providing a custom constructor.\n * function AnotherSimpleStoreClass () {\n * SimpleStore.call(this)\n * this.created_at = new Date().getTime()\n * }\n * SimpleStore.extend({\n * constructor: AnotherSimpleStoreClass,\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * })\n * const anotherSimpleStore = new AnotherSimpleStoreClass();\n * console.log(anotherSimpleStore.created_at);\n * console.log(anotherSimpleStore.foo());\n * console.log(AnotherSimpleStoreClass.beep());\n *\n * @method SimpleStore.extend\n * @param {object} [props={}] Properties to add to the prototype of the\n * subclass.\n * @param {object} [props.constructor] Provide a custom constructor function\n * to be used as the subclass itself.\n * @param {object} [classProps={}] Static properties to add to the subclass.\n * @returns {Constructor} Subclass of this SimpleStore class.\n * @since 3.0.0\n */\n","import utils from './utils'\nimport './decorators'\nimport Collection from './Collection'\n\nconst DOMAIN = 'LinkedCollection'\n\n/**\n * Extends {@link Collection}. Used by a {@link DataStore} to implement an\n * Identity Map.\n *\n * ```javascript\n * import {LinkedCollection} from 'js-data'\n * ```\n *\n * @class LinkedCollection\n * @extends Collection\n * @param {array} [records] Initial set of records to insert into the\n * collection. See {@link Collection}.\n * @param {object} [opts] Configuration options. See {@link Collection}.\n * @returns {Mapper}\n */\nfunction LinkedCollection (records, opts) {\n utils.classCallCheck(this, LinkedCollection)\n // Make sure this collection has somewhere to store \"added\" timestamps\n Object.defineProperties(this, {\n _added: {\n value: {}\n },\n datastore: {\n writable: true,\n value: undefined\n }\n })\n\n Collection.call(this, records, opts)\n\n // Make sure this collection has a reference to a datastore\n if (!this.datastore) {\n throw utils.err(`new ${DOMAIN}`, 'opts.datastore')(400, 'DataStore', this.datastore)\n }\n}\n\nexport default Collection.extend({\n constructor: LinkedCollection,\n\n _addMeta (record, timestamp) {\n // Track when this record was added\n this._added[this.recordId(record)] = timestamp\n\n if (utils.isFunction(record._set)) {\n record._set('$', timestamp)\n }\n },\n\n _clearMeta (record) {\n delete this._added[this.recordId(record)]\n if (utils.isFunction(record._set)) {\n record._set('$') // unset\n }\n },\n\n _onRecordEvent (...args) {\n Collection.prototype._onRecordEvent.apply(this, args)\n const event = args[0]\n // This is a very brute force method\n // Lots of room for optimization\n if (utils.isString(event) && event.indexOf('change') === 0) {\n this.updateIndexes(args[1])\n }\n },\n\n add (records, opts) {\n const mapper = this.mapper\n const timestamp = new Date().getTime()\n const singular = utils.isObject(records) && !utils.isArray(records)\n\n if (singular) {\n records = [records]\n }\n records = Collection.prototype.add.call(this, records, opts)\n\n if (mapper.relationList.length && records.length) {\n // Check the currently visited record for relations that need to be\n // inserted into their respective collections.\n mapper.relationList.forEach(function (def) {\n def.addLinkedRecords(records)\n })\n }\n\n records.forEach((record) => this._addMeta(record, timestamp))\n\n return singular ? records[0] : records\n },\n\n remove (idOrRecord, opts) {\n const mapper = this.mapper\n const record = Collection.prototype.remove.call(this, idOrRecord, opts)\n if (record) {\n this._clearMeta(record)\n }\n\n if (mapper.relationList.length && record) {\n mapper.relationList.forEach(function (def) {\n def.removeLinkedRecords(mapper, [record])\n })\n }\n\n return record\n },\n\n removeAll (query, opts) {\n const mapper = this.mapper\n const records = Collection.prototype.removeAll.call(this, query, opts)\n records.forEach(this._clearMeta, this)\n\n if (mapper.relationList.length && records.length) {\n mapper.relationList.forEach(function (def) {\n def.removeLinkedRecords(mapper, records)\n })\n }\n\n return records\n }\n})\n\n/**\n * Create a subclass of this LinkedCollection:\n *\n * @example LinkedCollection.extend\n * const JSData = require('js-data');\n * const { LinkedCollection } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * // Extend the class using ES2015 class syntax.\n * class CustomLinkedCollectionClass extends LinkedCollection {\n * foo () { return 'bar'; }\n * static beep () { return 'boop'; }\n * }\n * const customLinkedCollection = new CustomLinkedCollectionClass();\n * console.log(customLinkedCollection.foo());\n * console.log(CustomLinkedCollectionClass.beep());\n *\n * // Extend the class using alternate method.\n * const OtherLinkedCollectionClass = LinkedCollection.extend({\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * });\n * const otherLinkedCollection = new OtherLinkedCollectionClass();\n * console.log(otherLinkedCollection.foo());\n * console.log(OtherLinkedCollectionClass.beep());\n *\n * // Extend the class, providing a custom constructor.\n * function AnotherLinkedCollectionClass () {\n * LinkedCollection.call(this);\n * this.created_at = new Date().getTime();\n * }\n * LinkedCollection.extend({\n * constructor: AnotherLinkedCollectionClass,\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * });\n * const anotherLinkedCollection = new AnotherLinkedCollectionClass();\n * console.log(anotherLinkedCollection.created_at);\n * console.log(anotherLinkedCollection.foo());\n * console.log(AnotherLinkedCollectionClass.beep());\n *\n * @method LinkedCollection.extend\n * @param {object} [props={}] Properties to add to the prototype of the\n * subclass.\n * @param {object} [props.constructor] Provide a custom constructor function\n * to be used as the subclass itself.\n * @param {object} [classProps={}] Static properties to add to the subclass.\n * @returns {Constructor} Subclass of this LinkedCollection class.\n * @since 3.0.0\n */\n","import utils, { safeSetLink, safeSetProp } from './utils'\n\nimport {\n belongsToType,\n hasManyType,\n hasOneType\n} from './decorators'\nimport SimpleStore from './SimpleStore'\nimport LinkedCollection from './LinkedCollection'\n\nconst DATASTORE_DEFAULTS = {\n /**\n * Whether in-memory relations should be unlinked from records after they are\n * destroyed.\n *\n * @default true\n * @name DataStore#unlinkOnDestroy\n * @since 3.0.0\n * @type {boolean}\n */\n unlinkOnDestroy: true\n}\n\n/**\n * The `DataStore` class is an extension of {@link SimpleStore}. Not only does\n * `DataStore` manage mappers and store data in collections, it uses the\n * {@link LinkedCollection} class to link related records together in memory.\n *\n * ```javascript\n * import { DataStore } from 'js-data';\n * ```\n *\n * @example\n * import { DataStore } from 'js-data';\n * import HttpAdapter from 'js-data-http';\n * const store = new DataStore();\n *\n * // DataStore#defineMapper returns a direct reference to the newly created\n * // Mapper.\n * const UserMapper = store.defineMapper('user');\n *\n * // DataStore#as returns the store scoped to a particular Mapper.\n * const UserStore = store.as('user');\n *\n * // Call \"find\" on \"UserMapper\" (Stateless ORM)\n * UserMapper.find(1).then((user) => {\n * // retrieved a \"user\" record via the http adapter, but that's it\n *\n * // Call \"find\" on \"store\" targeting \"user\" (Stateful DataStore)\n * return store.find('user', 1); // same as \"UserStore.find(1)\"\n * }).then((user) => {\n * // not only was a \"user\" record retrieved, but it was added to the\n * // store's \"user\" collection\n * const cachedUser = store.getCollection('user').get(1);\n * console.log(user === cachedUser); // true\n * });\n *\n * @class DataStore\n * @extends SimpleStore\n * @param {object} [opts] Configuration options. See {@link SimpleStore}.\n * @param {boolean} [opts.collectionClass={@link LinkedCollection}] See {@link DataStore#collectionClass}.\n * @param {boolean} [opts.debug=false] See {@link Component#debug}.\n * @param {boolean} [opts.unlinkOnDestroy=true] See {@link DataStore#unlinkOnDestroy}.\n * @param {boolean|Function} [opts.usePendingFind=true] See {@link DataStore#usePendingFind}.\n * @param {boolean|Function} [opts.usePendingFindAll=true] See {@link DataStore#usePendingFindAll}.\n * @returns {DataStore}\n * @see SimpleStore\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/components-of-jsdata#datastore\",\"Components of JSData: DataStore\"]\n * @tutorial [\"http://www.js-data.io/v3.0/docs/working-with-the-datastore\",\"Working with the DataStore\"]\n * @tutorial [\"http://www.js-data.io/v3.0/docs/jsdata-and-the-browser\",\"Notes on using JSData in the Browser\"]\n */\nfunction DataStore (opts) {\n utils.classCallCheck(this, DataStore)\n\n opts || (opts = {})\n // Fill in any missing options with the defaults\n utils.fillIn(opts, DATASTORE_DEFAULTS)\n opts.collectionClass || (opts.collectionClass = LinkedCollection)\n SimpleStore.call(this, opts)\n}\n\nconst props = {\n constructor: DataStore,\n\n defineMapper (name, opts) {\n // Complexity of this method is beyond simply using => functions to bind context\n const self = this\n const mapper = SimpleStore.prototype.defineMapper.call(self, name, opts)\n const idAttribute = mapper.idAttribute\n const collection = this.getCollection(name)\n\n mapper.relationList.forEach(function (def) {\n const relation = def.relation\n const localField = def.localField\n const path = `links.${localField}`\n const foreignKey = def.foreignKey\n const type = def.type\n const updateOpts = { index: foreignKey }\n let descriptor\n\n const getter = function () { return this._get(path) }\n\n if (type === belongsToType) {\n if (!collection.indexes[foreignKey]) {\n collection.createIndex(foreignKey)\n }\n\n descriptor = {\n get: getter,\n // e.g. profile.user = someUser\n // or comment.post = somePost\n set (record) {\n // e.g. const otherUser = profile.user\n const currentParent = this._get(path)\n // e.g. profile.user === someUser\n if (record === currentParent) {\n return currentParent\n }\n const id = utils.get(this, idAttribute)\n const inverseDef = def.getInverse(mapper)\n\n // e.g. profile.user !== someUser\n // or comment.post !== somePost\n if (currentParent && inverseDef) {\n this.removeInverseRelation(currentParent, id, inverseDef, idAttribute)\n }\n if (record) {\n // e.g. profile.user = someUser\n const relatedIdAttribute = def.getRelation().idAttribute\n const relatedId = utils.get(record, relatedIdAttribute)\n\n // Prefer store record\n if (relatedId !== undefined && this._get('$')) {\n record = self.get(relation, relatedId) || record\n }\n\n // Set locals\n // e.g. profile.user = someUser\n // or comment.post = somePost\n safeSetLink(this, localField, record)\n safeSetProp(this, foreignKey, relatedId)\n collection.updateIndex(this, updateOpts)\n\n if (inverseDef) {\n this.setupInverseRelation(record, id, inverseDef, idAttribute)\n }\n } else {\n // Unset in-memory link only\n // e.g. profile.user = undefined\n // or comment.post = undefined\n safeSetLink(this, localField, undefined)\n }\n return record\n }\n }\n\n let foreignKeyDescriptor = Object.getOwnPropertyDescriptor(mapper.recordClass.prototype, foreignKey)\n if (!foreignKeyDescriptor) {\n foreignKeyDescriptor = {\n enumerable: true\n }\n }\n const originalGet = foreignKeyDescriptor.get\n foreignKeyDescriptor.get = function () {\n if (originalGet) {\n return originalGet.call(this)\n }\n return this._get(`props.${foreignKey}`)\n }\n const originalSet = foreignKeyDescriptor.set\n foreignKeyDescriptor.set = function (value) {\n if (originalSet) {\n originalSet.call(this, value)\n }\n const currentParent = utils.get(this, localField)\n const id = utils.get(this, idAttribute)\n const inverseDef = def.getInverse(mapper)\n const currentParentId = currentParent ? utils.get(currentParent, def.getRelation().idAttribute) : undefined\n\n if (inverseDef && currentParent && currentParentId !== undefined && currentParentId !== value) {\n if (inverseDef.type === hasOneType) {\n safeSetLink(currentParent, inverseDef.localField, undefined)\n } else if (inverseDef.type === hasManyType) {\n const children = utils.get(currentParent, inverseDef.localField)\n if (id === undefined) {\n utils.remove(children, (child) => child === this)\n } else {\n utils.remove(children, (child) => child === this || id === utils.get(child, idAttribute))\n }\n }\n }\n\n safeSetProp(this, foreignKey, value)\n collection.updateIndex(this, updateOpts)\n\n if ((value === undefined || value === null)) {\n if (currentParentId !== undefined) {\n // Unset locals\n utils.set(this, localField, undefined)\n }\n } else if (this._get('$')) {\n const storeRecord = self.get(relation, value)\n if (storeRecord) {\n utils.set(this, localField, storeRecord)\n }\n }\n }\n Object.defineProperty(mapper.recordClass.prototype, foreignKey, foreignKeyDescriptor)\n } else if (type === hasManyType) {\n const localKeys = def.localKeys\n const foreignKeys = def.foreignKeys\n\n // TODO: Handle case when belongsTo relation isn't ever defined\n if (self._collections[relation] && foreignKey && !self.getCollection(relation).indexes[foreignKey]) {\n self.getCollection(relation).createIndex(foreignKey)\n }\n\n descriptor = {\n get () {\n const current = getter.call(this)\n if (!current) {\n this._set(path, [])\n }\n return getter.call(this)\n },\n // e.g. post.comments = someComments\n // or user.groups = someGroups\n // or group.users = someUsers\n set (records) {\n if (records && !utils.isArray(records)) {\n records = [records]\n }\n const id = utils.get(this, idAttribute)\n const relatedIdAttribute = def.getRelation().idAttribute\n const inverseDef = def.getInverse(mapper)\n const inverseLocalField = inverseDef.localField\n const current = this._get(path) || []\n const toLink = []\n const toLinkIds = {}\n\n if (records) {\n records.forEach((record) => {\n // e.g. comment.id\n const relatedId = utils.get(record, relatedIdAttribute)\n const currentParent = utils.get(record, inverseLocalField)\n if (currentParent && currentParent !== this) {\n const currentChildrenOfParent = utils.get(currentParent, localField)\n // e.g. somePost.comments.remove(comment)\n if (relatedId === undefined) {\n utils.remove(currentChildrenOfParent, (child) => child === record)\n } else {\n utils.remove(currentChildrenOfParent, (child) => child === record || relatedId === utils.get(child, relatedIdAttribute))\n }\n }\n if (relatedId !== undefined) {\n if (this._get('$')) {\n // Prefer store record\n record = self.get(relation, relatedId) || record\n }\n // e.g. toLinkIds[comment.id] = comment\n toLinkIds[relatedId] = record\n }\n toLink.push(record)\n })\n }\n\n // e.g. post.comments = someComments\n if (foreignKey) {\n current.forEach((record) => {\n // e.g. comment.id\n const relatedId = utils.get(record, relatedIdAttribute)\n if ((relatedId === undefined && toLink.indexOf(record) === -1) || (relatedId !== undefined && !(relatedId in toLinkIds))) {\n // Update (unset) inverse relation\n if (records) {\n // e.g. comment.post_id = undefined\n safeSetProp(record, foreignKey, undefined)\n // e.g. CommentCollection.updateIndex(comment, { index: 'post_id' })\n self.getCollection(relation).updateIndex(record, updateOpts)\n }\n // e.g. comment.post = undefined\n safeSetLink(record, inverseLocalField, undefined)\n }\n })\n toLink.forEach((record) => {\n // Update (set) inverse relation\n // e.g. comment.post_id = post.id\n safeSetProp(record, foreignKey, id)\n // e.g. CommentCollection.updateIndex(comment, { index: 'post_id' })\n self.getCollection(relation).updateIndex(record, updateOpts)\n // e.g. comment.post = post\n safeSetLink(record, inverseLocalField, this)\n })\n } else if (localKeys) {\n // Update locals\n // e.g. group.users = someUsers\n // Update (set) inverse relation\n const ids = toLink.map((child) => utils.get(child, relatedIdAttribute)).filter((id) => id !== undefined)\n // e.g. group.user_ids = [1,2,3,...]\n utils.set(this, localKeys, ids)\n // Update (unset) inverse relation\n if (inverseDef.foreignKeys) {\n current.forEach((child) => {\n const relatedId = utils.get(child, relatedIdAttribute)\n if ((relatedId === undefined && toLink.indexOf(child) === -1) || (relatedId !== undefined && !(relatedId in toLinkIds))) {\n // Update inverse relation\n // safeSetLink(child, inverseLocalField, undefined)\n const parents = utils.get(child, inverseLocalField) || []\n // e.g. someUser.groups.remove(group)\n if (id === undefined) {\n utils.remove(parents, (parent) => parent === this)\n } else {\n utils.remove(parents, (parent) => parent === this || id === utils.get(parent, idAttribute))\n }\n }\n })\n toLink.forEach((child) => {\n // Update (set) inverse relation\n const parents = utils.get(child, inverseLocalField)\n // e.g. someUser.groups.push(group)\n if (id === undefined) {\n utils.noDupeAdd(parents, this, (parent) => parent === this)\n } else {\n utils.noDupeAdd(parents, this, (parent) => parent === this || id === utils.get(parent, idAttribute))\n }\n })\n }\n } else if (foreignKeys) {\n // e.g. user.groups = someGroups\n // Update (unset) inverse relation\n current.forEach((parent) => {\n const ids = utils.get(parent, foreignKeys) || []\n // e.g. someGroup.user_ids.remove(user.id)\n utils.remove(ids, (_key) => id === _key)\n const children = utils.get(parent, inverseLocalField)\n // e.g. someGroup.users.remove(user)\n if (id === undefined) {\n utils.remove(children, (child) => child === this)\n } else {\n utils.remove(children, (child) => child === this || id === utils.get(child, idAttribute))\n }\n })\n // Update (set) inverse relation\n toLink.forEach((parent) => {\n const ids = utils.get(parent, foreignKeys) || []\n utils.noDupeAdd(ids, id, (_key) => id === _key)\n const children = utils.get(parent, inverseLocalField)\n if (id === undefined) {\n utils.noDupeAdd(children, this, (child) => child === this)\n } else {\n utils.noDupeAdd(children, this, (child) => child === this || id === utils.get(child, idAttribute))\n }\n })\n }\n\n this._set(path, toLink)\n return toLink\n }\n }\n } else if (type === hasOneType) {\n // TODO: Handle case when belongsTo relation isn't ever defined\n if (self._collections[relation] && foreignKey && !self.getCollection(relation).indexes[foreignKey]) {\n self.getCollection(relation).createIndex(foreignKey)\n }\n descriptor = {\n get: getter,\n // e.g. user.profile = someProfile\n set (record) {\n const current = this._get(path)\n if (record === current) {\n return current\n }\n const inverseLocalField = def.getInverse(mapper).localField\n // Update (unset) inverse relation\n if (current) {\n safeSetProp(current, foreignKey, undefined)\n self.getCollection(relation).updateIndex(current, updateOpts)\n safeSetLink(current, inverseLocalField, undefined)\n }\n if (record) {\n const relatedId = utils.get(record, def.getRelation().idAttribute)\n // Prefer store record\n if (relatedId !== undefined) {\n record = self.get(relation, relatedId) || record\n }\n\n // Set locals\n safeSetLink(this, localField, record)\n\n // Update (set) inverse relation\n safeSetProp(record, foreignKey, utils.get(this, idAttribute))\n self.getCollection(relation).updateIndex(record, updateOpts)\n safeSetLink(record, inverseLocalField, this)\n } else {\n // Unset locals\n safeSetLink(this, localField, undefined)\n }\n return record\n }\n }\n }\n\n if (descriptor) {\n descriptor.enumerable = def.enumerable === undefined ? false : def.enumerable\n if (def.get) {\n const origGet = descriptor.get\n descriptor.get = function () {\n return def.get(def, this, (...args) => origGet.apply(this, args))\n }\n }\n if (def.set) {\n const origSet = descriptor.set\n descriptor.set = function (related) {\n return def.set(def, this, related, (value) => origSet.call(this, value === undefined ? related : value))\n }\n }\n Object.defineProperty(mapper.recordClass.prototype, localField, descriptor)\n }\n })\n\n return mapper\n },\n\n destroy (name, id, opts) {\n opts || (opts = {})\n return SimpleStore.prototype.destroy.call(this, name, id, opts).then((result) => {\n let record\n if (opts.raw) {\n record = result.data\n } else {\n record = result\n }\n\n if (record && this.unlinkOnDestroy) {\n const _opts = utils.plainCopy(opts)\n _opts.withAll = true\n utils.forEachRelation(this.getMapper(name), _opts, (def) => {\n utils.set(record, def.localField, undefined)\n })\n }\n return result\n })\n },\n\n destroyAll (name, query, opts) {\n opts || (opts = {})\n return SimpleStore.prototype.destroyAll.call(this, name, query, opts).then((result) => {\n let records\n if (opts.raw) {\n records = result.data\n } else {\n records = result\n }\n\n if (records && records.length && this.unlinkOnDestroy) {\n const _opts = utils.plainCopy(opts)\n _opts.withAll = true\n utils.forEachRelation(this.getMapper(name), _opts, (def) => {\n records.forEach((record) => {\n utils.set(record, def.localField, undefined)\n })\n })\n }\n return result\n })\n }\n}\n\nexport default SimpleStore.extend(props)\n\n/**\n * Create a subclass of this DataStore:\n * @example DataStore.extend\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * // Extend the class using ES2015 class syntax.\n * class CustomDataStoreClass extends DataStore {\n * foo () { return 'bar'; }\n * static beep () { return 'boop'; }\n * }\n * const customDataStore = new CustomDataStoreClass();\n * console.log(customDataStore.foo());\n * console.log(CustomDataStoreClass.beep());\n *\n * // Extend the class using alternate method.\n * const OtherDataStoreClass = DataStore.extend({\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * });\n * const otherDataStore = new OtherDataStoreClass();\n * console.log(otherDataStore.foo());\n * console.log(OtherDataStoreClass.beep());\n *\n * // Extend the class, providing a custom constructor.\n * function AnotherDataStoreClass () {\n * DataStore.call(this);\n * this.created_at = new Date().getTime();\n * }\n * DataStore.extend({\n * constructor: AnotherDataStoreClass,\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * });\n * const anotherDataStore = new AnotherDataStoreClass();\n * console.log(anotherDataStore.created_at);\n * console.log(anotherDataStore.foo());\n * console.log(AnotherDataStoreClass.beep());\n *\n * @method DataStore.extend\n * @param {object} [props={}] Properties to add to the prototype of the\n * subclass.\n * @param {object} [props.constructor] Provide a custom constructor function\n * to be used as the subclass itself.\n * @param {object} [classProps={}] Static properties to add to the subclass.\n * @returns {Constructor} Subclass of this DataStore class.\n * @since 3.0.0\n */\n","/**\n * Registered as `js-data` in NPM and Bower.\n *\n * Also available from CDN.JS and JSDelivr.\n *\n * @module js-data\n *\n * @example Install from NPM\n * npm i --save js-data@beta\n * @example Install from Bower\n * bower i --save js-data@3.0.0-beta.1\n * @example Install from CDN.JS\n * \n * @example Install from JSDelivr\n * \n * @example Load into your app via script tag\n * \n * \n * @example Load into your app via CommonJS\n * var JSData = require('js-data');\n * @example Load into your app via ES2015 Modules\n * import * as JSData from 'js-data';\n * @example Load into your app via AMD\n * define('myApp', ['js-data'], function (JSData) { ... });\n */\n\n/**\n * JSData's utility methods.\n *\n * @example\n * import { utils } from 'js-data';\n * console.log(utils.isString('foo')); // true\n *\n * @name module:js-data.utils\n * @property {Function} Promise See {@link utils.Promise}.\n * @see utils\n * @since 3.0.0\n * @type {Object}\n */\nimport utils from './utils'\n\n/**\n * JSData's {@link Collection} class.\n *\n * @example\n * import { Collection } from 'js-data';\n * const collection = new Collection();\n *\n * @name module:js-data.Collection\n * @see Collection\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/components-of-jsdata#collection\",\"Components of JSData: Collection\"]\n * @type {Constructor}\n */\nimport Collection from './Collection'\n\n/**\n * JSData's {@link Component} class. Most components in JSData extend this\n * class.\n *\n * @example\n * import { Component } from 'js-data';\n * // Make a custom component.\n * const MyComponent = Component.extend({\n * myMethod (someArg) { ... }\n * });\n *\n * @name module:js-data.Component\n * @see Component\n * @since 3.0.0\n * @type {Constructor}\n */\nimport Component from './Component'\n\n/**\n * JSData's {@link Container} class. Defines and manages {@link Mapper}s. Used\n * in Node.js and in the browser, though in the browser you may want to use\n * {@link DataStore} instead.\n *\n * @example\n * import { Container } from 'js-data';\n * const store = new Container();\n *\n * @name module:js-data.Container\n * @see Container\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/components-of-jsdata#container\",\"Components of JSData: Container\"]\n * @type {Constructor}\n */\nimport { Container } from './Container'\n\n/**\n * JSData's {@link DataStore} class. Primarily for use in the browser. In\n * Node.js you probably want to use {@link Container} instead.\n *\n * @example\n * import { DataStore } from 'js-data';\n * const store = new DataStore();\n *\n * @name module:js-data.DataStore\n * @see DataStore\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/components-of-jsdata#datastore\",\"Components of JSData: DataStore\"]\n * @type {Constructor}\n */\nimport DataStore from './DataStore'\n\n/**\n * JSData's {@link Index} class, based on [mindex]{@link https://github.com/internalfx/mindex}.\n *\n * @name module:js-data.Index\n * @see Index\n * @since 3.0.0\n * @type {Constructor}\n */\nimport Index from '../lib/mindex/index'\n\n/**\n * JSData's {@link LinkedCollection} class. Used by the {@link DataStore}\n * component. If you need to create a collection manually, you should probably\n * use the {@link Collection} class.\n *\n * @name module:js-data.LinkedCollection\n * @see DataStore\n * @see LinkedCollection\n * @since 3.0.0\n * @type {Constructor}\n */\nimport LinkedCollection from './LinkedCollection'\n\n/**\n * JSData's {@link Mapper} class. The core of the ORM.\n *\n * @example Recommended use\n * import { Container } from 'js-data';\n * const store = new Container();\n * store.defineMapper('user');\n *\n * @example Create Mapper manually\n * import { Mapper } from 'js-data';\n * const UserMapper = new Mapper({ name: 'user' });\n *\n * @name module:js-data.Mapper\n * @see Container\n * @see Mapper\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/modeling-your-data\",\"Modeling your data\"]\n * @tutorial [\"http://www.js-data.io/v3.0/docs/components-of-jsdata#mapper\",\"Components of JSData: Mapper\"]\n * @type {Constructor}\n */\nimport Mapper from './Mapper'\n\n/**\n * JSData's {@link Query} class. Used by the {@link Collection} component.\n *\n * @name module:js-data.Query\n * @see Query\n * @since 3.0.0\n * @type {Constructor}\n */\nimport Query from './Query'\n\n/**\n * JSData's {@link Record} class.\n *\n * @example\n * import { Container } from 'js-data';\n * const store = new Container();\n * store.defineMapper('user');\n * const user = store.createRecord('user');\n *\n * @name module:js-data.Record\n * @see Record\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/components-of-jsdata#record\",\"Components of JSData: Record\"]\n * @type {Constructor}\n */\nimport Record from './Record'\n\n/**\n * JSData's {@link Schema} class. Implements http://json-schema.org/draft-04.\n *\n * @example\n * import { Container, Schema } from 'js-data';\n * const userSchema = new Schema({\n * properties: {\n * id: { type: 'string' },\n * name: { type: 'string' }\n * }\n * });\n * const store = new Container();\n * store.defineMapper('user', {\n * schema: userSchema\n * });\n *\n * @name module:js-data.Schema\n * @see Schema\n * @see http://json-schema.org/\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/components-of-jsdata#schema\",\"Components of JSData: schema\"]\n * @tutorial [\"http://www.js-data.io/v3.0/docs/schemas\",\"JSData's Schema Syntax\"]\n * @type {Constructor}\n */\nimport Schema from './Schema'\n\n/**\n * JSData's {@link Settable} class.\n *\n * @example\n * import { Settable } from 'js-data';\n * const obj = new Settable();\n * obj.set('secret', 'value');\n * console.log(JSON.stringify(obj)); // {}\n *\n * @name module:js-data.Settable\n * @see Settable\n * @since 3.0.0\n * @type {Constructor}\n */\nimport Settable from './Settable'\n\n/**\n * JSData's {@link SimpleStore} class. Primarily for use in the browser. In\n * Node.js you probably want to use {@link Container} instead.\n *\n * @example\n * import { SimpleStore } from 'js-data';\n * const store = new SimpleStore();\n *\n * @name module:js-data.SimpleStore\n * @see SimpleStore\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/components-of-jsdata#SimpleStore\",\"Components of JSData: SimpleStore\"]\n * @type {Constructor}\n */\nimport SimpleStore from './SimpleStore'\n\n/**\n * Describes the version of this `JSData` object.\n *\n * @example\n * console.log(JSData.version.full); // \"3.0.0-beta.1\"\n *\n * @name version\n * @memberof module:js-data\n * @property {string} full The full semver value.\n * @property {number} major The major version number.\n * @property {number} minor The minor version number.\n * @property {number} patch The patch version number.\n * @property {(string|boolean)} alpha The alpha version value, otherwise `false`\n * if the current version is not alpha.\n * @property {(string|boolean)} beta The beta version value, otherwise `false`\n * if the current version is not beta.\n * @since 2.0.0\n * @type {Object}\n */\nexport const version = '<%= version %>'\n\nexport * from './decorators'\n\nexport {\n Collection,\n Component,\n Container,\n DataStore,\n Index,\n LinkedCollection,\n Mapper,\n Query,\n Record,\n Schema,\n Settable,\n SimpleStore,\n utils\n}\n"],"names":["DOMAIN","INFINITY","MAX_INTEGER","BOOL_TAG","DATE_TAG","FUNC_TAG","NUMBER_TAG","OBJECT_TAG","REGEXP_TAG","STRING_TAG","objToString","Object","prototype","toString","PATH","ERRORS","arguments","toInteger","value","sign","remainder","toStr","call","isPlainObject","constructor","mkdirP","object","path","parts","split","forEach","key","utils","Promise","_","dest","src","forOwn","undefined","isFunction","indexOf","_forRelation","opts","def","fn","thisArg","relationName","relation","containedName","index","with","_getIndex","localField","withAll","optsCopy","fillIn","getRelation","slice","_activeWith","splice","i","length","substr","list","_relation","isObject","addHiddenPropsToTarget","target","props","map","keys","propName","descriptor","getOwnPropertyDescriptor","enumerable","defineProperties","areDifferent","newObject","oldObject","diff","diffObjects","diffCount","added","removed","changed","classCallCheck","instance","ctor","err","name","copy","from","to","stackFrom","stackTo","blacklist","plain","isArray","isDate","Date","getTime","isRegExp","RegExp","source","match","lastIndex","create","getPrototypeOf","push","result","hasOwnProperty","isBlacklisted","deepFillIn","existing","deepMixIn","equalsFn","ignore","deepEqual","newKeys","filter","oldKeys","oldValue","newValue","equal","a","b","domain","code","prefix","message","apply","Array","Error","eventify","getter","setter","_events","emit","events","args","type","shift","listeners","f","c","all","unshift","off","func","on","extend","classProps","superClass","subClass","configurable","writable","obj","setPrototypeOf","strictEs6Class","__proto__","defineProperty","findIndex","array","record","forEachRelation","mapper","relationList","len","fromJson","json","isString","JSON","parse","get","prop","last","pop","getSuper","isCtor","__super__","intersection","array1","array2","item","matches","test","isBoolean","isInteger","isNull","isNumber","isSorN","isUndefined","logify","dbg","log","level","debug","toUpperCase","console","noDupeAdd","omit","_props","pick","reduce","plainCopy","reject","remove","resolve","set","_path","exec","_equal","toJson","stringify","unset","safeSetProp","field","_set","safeSetLink","Settable","_get","_unset","Component","_listeners","INDEX_ERR","reserved","limit","offset","orderBy","skip","sort","where","escapeRegExp","percentRegExp","underscoreRegExp","escape","pattern","replace","Query","collection","data","_applyWhereFromObject","fields","ops","predicates","clause","expr","op","_applyWhereFromArray","groups","_where","prev","parser","group","isOr","_testObjectGroup","keep","first","charAt","evaluate","_testArrayGroup","between","leftKeys","rightKeys","getIndex","compare","cA","cB","temp","predicate","like","query","getData","forEachFn","keyList","getAll","concat","flags","num","Math","min","mapFn","mapCall","funcName","run","isectEmpty","isectNotEmpty","in","notIn","contains","notContains","belongsToType","hasManyType","hasOneType","Relation","relatedMapper","options","TYPE_NAME","validateOptions","canAutoAddLinks","add","relatedCollection","datastore","getCollection","related","DOMAIN_ERR","foreignKey","localKey","assignTo","relationFields","canFindLinkFor","getForeignKey","idAttribute","setForeignKey","relatedRecord","_setForeignKey","relatedRecords","getLocalField","setLocalField","relatedData","getInverse","inverse","findInverseRelation","isInversedTo","addLinkedRecords","records","linkRecord","isEmptyLinks","findExistingLinksFor","removeLinkedRecords","relatedId","unsaved","findExistingLinksByForeignKey","id","ensureLinkedDataHasProperType","relationData","is","createRecord","isRequiresParentId","isRequiresChildId","createChildRecord","createLinked","then","BelongsToRelation","createParentRecord","HasManyRelation","localKeys","foreignKeys","hasForeignKeys","recordId","ids","findExistingLinksByLocalKeys","findExistingLinksByForeignKeys","foreignIdField","createMany","HasOneRelation","RelationType","belongsTo","hasMany","hasOne","superMethod","store","bind","creatingPath","noValidatePath","keepChangeHistoryPath","previousPath","Record","noValidate","keepChangeHistory","validateOnSet","toJSON","_mapper","afterLoadRelations","beforeLoadRelations","changeHistory","changes","commit","destroy","hasChanges","quickHasChanges","isNew","isValid","validate","removeInverseRelation","currentParent","inverseDef","children","child","setupInverseRelation","loadRelations","relations","adapter","getAdapterName","tasks","task","raw","load","previous","revert","preserve","save","postProcess","changesOnly","silent","hashCode","insertAt","removeAt","binarySearch","lo","hi","compared","mid","found","Index","fieldList","fieldGetter","isIndex","values","pos","dataLocation","newIndex","results","order","visitAll","cb","leftInclusive","rightInclusive","_between","leftKey","rightKey","currKey","peek","clear","insertRecord","removeRecord","isUnique","j","updateRecord","COLLECTION_DEFAULTS","commitOnMerge","emitRecordEvents","onConflict","Collection","queryClass","indexes","_onRecordEvent","beforeAdd","singular","existingNoValidate","updateIndexes","afterAdd","afterRemove","afterRemoveAll","beforeRemove","beforeRemoveAll","createIndex","instances","prune","removeAll","Ctor","initialValue","idOrRecord","queryOrRecords","updateIndex","types","boolean","integer","null","number","string","segmentToString","segment","str","makePath","segments","makeError","actual","expected","addError","errors","maxLengthCommon","keyword","schema","max","minLengthCommon","validationKeywords","allOf","allErrors","_schema","anyOf","validated","dependencies","enum","possibleValues","join","items","checkingTuple","maximum","exclusiveMaximum","maxItems","maxLength","maxProperties","minimum","exclusiveMinimum","minItems","minLength","minProperties","multipleOf","not","oneOf","properties","additionalProperties","patternProperties","toValidate","undef","origProp","required","existingOnly","prevProp","validType","_type","validator","typeGroupValidators","uniqueItems","runOps","ANY_OPS","ARRAY_OPS","NUMERIC_OPS","OBJECT_OPS","STRING_OPS","validateAny","ctx","shouldPop","extends","changingPath","changedPath","changeHistoryPath","eventIdPath","silentPath","validationFailureMsg","numeric","Schema","definition","_definition","validationKeyword","unsetter","track","makeDescriptor","applyDefaults","hasSet","default","orig","keyPath","originalGet","error","current","changing","clearTimeout","setTimeout","changeRecord","timestamp","originalSet","_copy","applyDefaultsHooks","validatingHooks","makeNotify","getSchema","toProcess","originalExistingOnly","notify","notify2","LIFECYCLE_METHODS","count","defaults","destroyAll","find","findAll","sum","update","adapterArgs","beforeAssign","updateAll","updateMany","MAPPER_DEFAULTS","_adapters","applySchema","defaultAdapter","Mapper","lifecycleMethods","recordClass","methods","isPrototypeOf","afterCount","afterCreate","afterCreateMany","afterDestroy","afterDestroyAll","afterFind","afterFindAll","afterSum","afterUpdate","afterUpdateAll","afterUpdateMany","beforeCreate","beforeCreateMany","beforeCount","beforeDestroy","beforeDestroyAll","beforeFind","beforeFindAll","beforeSum","beforeUpdate","beforeUpdateAll","beforeUpdateMany","_end","_data","wrap","crud","originalRecord","parentRelationMap","adapterResponse","_runHook","_createParentRecordIfRequired","relationMap","_invokeAdapterMethod","createdProps","_createOrAssignChildRecordIfRequired","originalProps","_commitChanges","recordOrRecords","newValues","createInstance","context","parent","originalRecords","belongsToRelationData","Boolean","createdRecordsData","belongsToData","createdRecordData","RecordCtor","method","config","upper","before","after","_value","getAdapter","_opts","assign","_result","getAdapters","registerAdapter","hookName","hookArgs","defaultValueIndex","overridenResult","propsOrRecords","conversionOptions","pass","_record","some","defineRelations","_name","getMapperByName","getMapper","proxiedMapperMethods","Container","_mappers","mapperClass","mapperDefaults","_onMapperEvent","as","original","defineMapper","defineResource","warn","proxiedCollectionMethods","ownMethodsForScoping","cachedFn","hashOrId","cached","_completedQueries","SIMPLESTORE_DEFAULTS","usePendingFind","usePendingFindAll","SimpleStore","collectionClass","_collections","_pendingQueries","addToCache","_onCollectionEvent","cachedFind","cachedFindAll","cacheFind","cacheFindAll","hash","self","collectionOpts","_added","indexed","hashQuery","eject","ejectAll","pendingQuery","force","promise","inject","removeRelated","LinkedCollection","_addMeta","_clearMeta","event","DATASTORE_DEFAULTS","unlinkOnDestroy","DataStore","updateOpts","relatedIdAttribute","foreignKeyDescriptor","currentParentId","storeRecord","inverseLocalField","toLink","toLinkIds","currentChildrenOfParent","parents","_key","origGet","origSet","version"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"js-data.js","sources":["../src/utils.ts","../src/Settable.ts","../src/Component.ts","../src/Query.ts","../src/Relation.ts","../src/Record.ts","../src/mindex/_utils.ts","../src/mindex/index.ts","../src/Collection.ts","../src/TsDataError.ts","../src/Schema.ts","../src/Relation/BelongsTo.ts","../src/Relation/HasMany.ts","../src/Relation/HasOne.ts","../src/relations.ts","../src/decorators.ts","../src/Mapper.ts","../src/Container.ts","../src/SimpleStore.ts","../src/LinkedCollection.ts","../src/DataStore.ts","../src/index.ts"],"sourcesContent":["/**\n * Utility methods used by JSData.\n *\n * @example\n * import { utils } from 'js-data';\n * console.log(utils.isString('foo')); // true\n *\n * @namespace utils\n * @type {Object}\n */\n\nconst DOMAIN = 'utils'\n\nconst INFINITY = 1 / 0\nconst MAX_INTEGER = 1.7976931348623157e308\nconst BOOL_TAG = '[object Boolean]'\nconst DATE_TAG = '[object Date]'\nconst FUNC_TAG = '[object Function]'\nconst NUMBER_TAG = '[object Number]'\nconst OBJECT_TAG = '[object Object]'\nconst REGEXP_TAG = '[object RegExp]'\nconst STRING_TAG = '[object String]'\nconst objToString = Object.prototype.toString\nconst PATH = /^(.+)\\.(.+)$/\n\nconst ERRORS = {\n '400' (...args) {\n return `expected: ${args[0]}, found: ${args[2] ? args[1] : typeof args[1]}`\n },\n '404' (...args) {\n return `${args[0]} not found`\n }\n}\n\nconst toInteger = value => {\n if (!value) {\n return 0\n }\n // Coerce to number\n value = +value\n if (value === INFINITY || value === -INFINITY) {\n const sign = value < 0 ? -1 : 1\n return sign * MAX_INTEGER\n }\n const remainder = value % 1\n return value === value ? (remainder ? value - remainder : value) : 0; // eslint-disable-line\n}\n\nconst toStr = value => objToString.call(value)\n\nconst isPlainObject = value => !!value && typeof value === 'object' && value.constructor === Object\n\nconst mkdirP = (object, path) => {\n if (!path) {\n return object\n }\n const parts = path.split('.')\n parts.forEach(key => {\n if (!object[key]) {\n object[key] = {}\n }\n object = object[key]\n })\n return object\n}\n\nconst utils = {\n /**\n * Shallow copy properties that meet the following criteria from `src` to\n * `dest`:\n *\n * - own enumerable\n * - not a function\n * - does not start with \"_\"\n *\n * @method utils._\n * @param {object} dest Destination object.\n * @param {object} src Source object.\n * @private\n * @since 3.0.0\n */\n _ (dest, src) {\n utils.forOwn(src, (value, key) => {\n if (key && dest[key] === undefined && !utils.isFunction(value) && key.indexOf('_') !== 0) {\n dest[key] = value\n }\n })\n },\n\n /**\n * Recursively iterates over relations found in `opts.with`.\n *\n * @method utils._forRelation\n * @param {object} opts Configuration options.\n * @param {Relation} def Relation definition.\n * @param {Function} fn Callback function.\n * @param {*} [thisArg] Execution context for the callback function.\n * @private\n * @since 3.0.0\n */\n _forRelation (opts: any = {}, def, fn, thisArg) {\n const relationName = def.relation\n let containedName = null\n let index\n opts.with = opts.with || []\n\n if ((index = utils._getIndex(opts.with, relationName)) >= 0) {\n containedName = relationName\n } else if ((index = utils._getIndex(opts.with, def.localField)) >= 0) {\n containedName = def.localField\n }\n\n if (opts.withAll) {\n fn.call(thisArg, def, {})\n return\n } else if (!containedName) {\n return\n }\n const optsCopy: any = {}\n utils.fillIn(optsCopy, def.getRelation())\n utils.fillIn(optsCopy, opts)\n optsCopy.with = opts.with.slice()\n optsCopy._activeWith = optsCopy.with.splice(index, 1)[0]\n optsCopy.with.forEach((relation, i) => {\n if (\n relation &&\n relation.indexOf(containedName) === 0 &&\n relation.length >= containedName.length &&\n relation[containedName.length] === '.'\n ) {\n optsCopy.with[i] = relation.substr(containedName.length + 1)\n } else {\n optsCopy.with[i] = ''\n }\n })\n fn.call(thisArg, def, optsCopy)\n },\n\n /**\n * Find the index of a relation in the given list\n *\n * @method utils._getIndex\n * @param {string[]} list List to search.\n * @param {string} relation Relation to find.\n * @private\n * @returns {number}\n */\n _getIndex (list, relation) {\n let index = -1\n list.forEach((_relation, i) => {\n if (_relation === relation) {\n index = i\n return false\n } else if (utils.isObject(_relation)) {\n if (_relation.relation === relation) {\n index = i\n return false\n }\n }\n })\n return index\n },\n\n /**\n * Define hidden (non-enumerable), writable properties on `target` from the\n * provided `props`.\n *\n * @example\n * import { utils } from 'js-data';\n * function Cat () {}\n * utils.addHiddenPropsToTarget(Cat.prototype, {\n * say () {\n * console.log('meow');\n * }\n * });\n * const cat = new Cat();\n * cat.say(); // \"meow\"\n *\n * @method utils.addHiddenPropsToTarget\n * @param {object} target That to which `props` should be added.\n * @param {object} props Properties to be added to `target`.\n * @since 3.0.0\n */\n addHiddenPropsToTarget (target, props) {\n const map = {}\n Object.keys(props).forEach(propName => {\n const descriptor = Object.getOwnPropertyDescriptor(props, propName)\n\n descriptor.enumerable = false\n map[propName] = descriptor\n })\n Object.defineProperties(target, map)\n },\n\n /**\n * Return whether the two objects are deeply different.\n *\n * @example\n * import { utils } from 'js-data';\n * utils.areDifferent({}, {}); // false\n * utils.areDifferent({ a: 1 }, { a: 1 }); // false\n * utils.areDifferent({ foo: 'bar' }, {}); // true\n *\n * @method utils.areDifferent\n * @param newObject\n * @param oldObject\n * @param {object} [opts] Configuration options.\n * @param {Function} [opts.equalsFn={@link utils.deepEqual}] Equality function.\n * @param {array} [opts.ignore=[]] Array of strings or RegExp of fields to ignore.\n * @returns {boolean} Whether the two objects are deeply different.\n * @see utils.diffObjects\n * @since 3.0.0\n */\n areDifferent (newObject, oldObject, opts: any = {}) {\n const diff = utils.diffObjects(newObject, oldObject, opts)\n const diffCount =\n Object.keys(diff.added).length + Object.keys(diff.removed).length + Object.keys(diff.changed).length\n return diffCount > 0\n },\n\n /**\n * Deep copy a value.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = { foo: { bar: 'baz' } };\n * const b = utils.copy(a);\n * a === b; // false\n * utils.areDifferent(a, b); // false\n *\n * @param {*} from Value to deep copy.\n * @param {*} [to] Destination object for the copy operation.\n * @param {*} [stackFrom] For internal use.\n * @param {*} [stackTo] For internal use.\n * @param {string[]|RegExp[]} [blacklist] List of strings or RegExp of\n * properties to skip.\n * @param {boolean} [plain] Whether to make a plain copy (don't try to use\n * original prototype).\n * @returns {*} Deep copy of `from`.\n * @since 3.0.0\n */\n copy (from, to?, stackFrom?, stackTo?, blacklist?, plain?) {\n if (!to) {\n to = from\n if (from) {\n if (utils.isArray(from)) {\n to = utils.copy(from, [], stackFrom, stackTo, blacklist, plain)\n } else if (utils.isDate(from)) {\n to = new Date(from.getTime())\n } else if (utils.isRegExp(from)) {\n to = new RegExp(from.source, from.toString().match(/[^/]*$/)[0])\n to.lastIndex = from.lastIndex\n } else if (utils.isObject(from)) {\n if (plain) {\n to = utils.copy(from, {}, stackFrom, stackTo, blacklist, plain)\n } else {\n to = utils.copy(from, Object.create(Object.getPrototypeOf(from)), stackFrom, stackTo, blacklist, plain)\n }\n }\n }\n } else {\n if (from === to) {\n throw utils.err(`${DOMAIN}.copy`)(500, 'Cannot copy! Source and destination are identical.')\n }\n\n stackFrom = stackFrom || []\n stackTo = stackTo || []\n\n if (utils.isObject(from)) {\n const index = stackFrom.indexOf(from)\n if (index !== -1) {\n return stackTo[index]\n }\n\n stackFrom.push(from)\n stackTo.push(to)\n }\n\n let result\n if (utils.isArray(from)) {\n let i\n to.length = 0\n for (i = 0; i < from.length; i++) {\n result = utils.copy(from[i], null, stackFrom, stackTo, blacklist, plain)\n if (utils.isObject(from[i])) {\n stackFrom.push(from[i])\n stackTo.push(result)\n }\n to.push(result)\n }\n } else {\n if (utils.isArray(to)) {\n to.length = 0\n } else {\n utils.forOwn(to, (value, key) => {\n delete to[key]\n })\n }\n for (const key in from) {\n if (from.hasOwnProperty(key)) {\n if (utils.isBlacklisted(key, blacklist)) {\n continue\n }\n result = utils.copy(from[key], null, stackFrom, stackTo, blacklist, plain)\n if (utils.isObject(from[key])) {\n stackFrom.push(from[key])\n stackTo.push(result)\n }\n to[key] = result\n }\n }\n }\n }\n return to\n },\n\n /**\n * Recursively shallow fill in own enumerable properties from `source` to\n * `dest`.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = { foo: { bar: 'baz' }, beep: 'boop' };\n * const b = { beep: 'bip' };\n * utils.deepFillIn(b, a);\n * console.log(b); // {\"foo\":{\"bar\":\"baz\"},\"beep\":\"bip\"}\n *\n * @method utils.deepFillIn\n * @param {object} dest The destination object.\n * @param {object} source The source object.\n * @see utils.fillIn\n * @see utils.deepMixIn\n * @since 3.0.0\n */\n deepFillIn (dest, source?) {\n if (source) {\n utils.forOwn(source, (value, key) => {\n const existing = dest[key]\n if (isPlainObject(value) && isPlainObject(existing)) {\n utils.deepFillIn(existing, value)\n } else if (!dest.hasOwnProperty(key) || dest[key] === undefined) {\n dest[key] = value\n }\n })\n }\n return dest\n },\n\n /**\n * Recursively shallow copy enumerable properties from `source` to `dest`.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = { foo: { bar: 'baz' }, beep: 'boop' };\n * const b = { beep: 'bip' };\n * utils.deepFillIn(b, a);\n * console.log(b); // {\"foo\":{\"bar\":\"baz\"},\"beep\":\"boop\"}\n *\n * @method utils.deepMixIn\n * @param {object} dest The destination object.\n * @param {object} source The source object.\n * @see utils.fillIn\n * @see utils.deepFillIn\n * @since 3.0.0\n */\n deepMixIn (dest, source?) {\n if (source) {\n // tslint:disable-next-line:forin\n for (const key in source) {\n const value = source[key]\n const existing = dest[key]\n if (isPlainObject(value) && isPlainObject(existing)) {\n utils.deepMixIn(existing, value)\n } else {\n dest[key] = value\n }\n }\n }\n return dest\n },\n\n /**\n * Return a diff of the base object to the comparison object.\n *\n * @example\n * import { utils } from 'js-data';\n * const oldObject = { foo: 'bar', a: 1234 };\n * const newObject = { beep: 'boop', a: 5678 };\n * const diff = utils.diffObjects(oldObject, newObject);\n * console.log(diff.added); // {\"beep\":\"boop\"}\n * console.log(diff.changed); // {\"a\":5678}\n * console.log(diff.removed); // {\"foo\":undefined}\n *\n * @method utils.diffObjects\n * @param {object} newObject Comparison object.\n * @param {object} oldObject Base object.\n * @param {object} [opts] Configuration options.\n * @param {Function} [opts.equalsFn={@link utils.deepEqual}] Equality function.\n * @param {array} [opts.ignore=[]] Array of strings or RegExp of fields to ignore.\n * @returns {Object} The diff from the base object to the comparison object.\n * @see utils.areDifferent\n * @since 3.0.0\n */\n diffObjects (newObject, oldObject, opts: any = {}) {\n let equalsFn = opts.equalsFn\n const blacklist = opts.ignore\n const diff = {\n added: {},\n changed: {},\n removed: {}\n }\n if (!utils.isFunction(equalsFn)) {\n equalsFn = utils.deepEqual\n }\n\n const newKeys = Object.keys(newObject).filter(key => !utils.isBlacklisted(key, blacklist))\n const oldKeys = Object.keys(oldObject).filter(key => !utils.isBlacklisted(key, blacklist))\n\n // Check for properties that were added or changed\n newKeys.forEach(key => {\n const oldValue = oldObject[key]\n const newValue = newObject[key]\n if (equalsFn(oldValue, newValue)) {\n return\n }\n if (oldValue === undefined) {\n diff.added[key] = newValue\n } else {\n diff.changed[key] = newValue\n }\n })\n\n // Check for properties that were removed\n oldKeys.forEach(key => {\n const oldValue = oldObject[key]\n const newValue = newObject[key]\n if (newValue === undefined && oldValue !== undefined) {\n diff.removed[key] = undefined\n }\n })\n\n return diff\n },\n\n /**\n * Return whether the two values are equal according to the `==` operator.\n *\n * @example\n * import { utils } from 'js-data';\n * console.log(utils.equal(1,1)); // true\n * console.log(utils.equal(1,'1')); // true\n * console.log(utils.equal(93, 66)); // false\n *\n * @method utils.equal\n * @param {*} a First value in the comparison.\n * @param {*} b Second value in the comparison.\n * @returns {boolean} Whether the two values are equal according to `==`.\n * @since 3.0.0\n */\n equal (a, b) {\n // tslint:disable-next-line:triple-equals\n return a == b; // eslint-disable-line\n },\n\n /**\n * Produce a factory function for making Error objects with the provided\n * metadata. Used throughout the various js-data components.\n *\n * @example\n * import { utils } from 'js-data';\n * const errorFactory = utils.err('domain', 'target');\n * const error400 = errorFactory(400, 'expected type', 'actual type');\n * console.log(error400); // [Error: [domain:target] expected: expected type, found: string\n * http://www.js-data.io/v3.0/docs/errors#400]\n * @method utils.err\n * @param {string} domain Namespace.\n * @param {string} target Target.\n * @returns {Function} Factory function.\n * @since 3.0.0\n */\n err (domain, target?) {\n return (code, ...args) => {\n const prefix = `[${domain}:${target}] `\n let message = ERRORS[code].apply(null, args)\n message = `${prefix}${message}\nhttp://www.js-data.io/v3.0/docs/errors#${code}`\n return new Error(message)\n }\n },\n\n /**\n * Add eventing capabilities into the target object.\n *\n * @example\n * import { utils } from 'js-data';\n * const user = { name: 'John' };\n * utils.eventify(user);\n * user.on('foo', () => console.log(arguments));\n * user.emit('foo', 1, 'bar'); // should log to console values (1, \"bar\")\n *\n * @method utils.eventify\n * @param {object} target Target object.\n * @param {Function} [getter] Custom getter for retrieving the object's event\n * listeners.\n * @param {Function} [setter] Custom setter for setting the object's event\n * listeners.\n * @since 3.0.0\n */\n eventify (target, getter?, setter?) {\n target = target || this\n let _events = {}\n if (!getter && !setter) {\n getter = () => _events\n setter = value => (_events = value)\n }\n Object.defineProperties(target, {\n emit: {\n value (...args) {\n const events = getter.call(this) || {}\n const type = args.shift()\n let listeners = events[type] || []\n let i\n for (i = 0; i < listeners.length; i++) {\n listeners[i].f.apply(listeners[i].c, args)\n }\n listeners = events.all || []\n args.unshift(type)\n for (i = 0; i < listeners.length; i++) {\n listeners[i].f.apply(listeners[i].c, args)\n }\n }\n },\n off: {\n value (type, func) {\n const events = getter.call(this)\n const listeners = events[type]\n if (!listeners) {\n setter.call(this, {})\n } else if (func) {\n for (let i = 0; i < listeners.length; i++) {\n if (listeners[i].f === func) {\n listeners.splice(i, 1)\n break\n }\n }\n } else {\n listeners.splice(0, listeners.length)\n }\n }\n },\n on: {\n value (type, func, thisArg) {\n if (!getter.call(this)) {\n setter.call(this, {})\n }\n const events = getter.call(this)\n events[type] = events[type] || []\n events[type].push({\n c: thisArg,\n f: func\n })\n }\n }\n })\n },\n\n /**\n * Shallow copy own enumerable properties from `src` to `dest` that are on\n * `src` but are missing from `dest.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = { foo: 'bar', beep: 'boop' };\n * const b = { beep: 'bip' };\n * utils.fillIn(b, a);\n * console.log(b); // {\"foo\":\"bar\",\"beep\":\"bip\"}\n *\n * @method utils.fillIn\n * @param {object} dest The destination object.\n * @param src\n * @see utils.deepFillIn\n * @see utils.deepMixIn\n * @since 3.0.0\n */\n fillIn (dest, src) {\n utils.forOwn(src, (value, key) => {\n if (!dest.hasOwnProperty(key) || dest[key] === undefined) {\n dest[key] = value\n }\n })\n },\n\n /**\n * Find the last index of an item in an array according to the given checker function.\n *\n * @example\n * import { utils } from 'js-data';\n *\n * const john = { name: 'John', age: 20 };\n * const sara = { name: 'Sara', age: 25 };\n * const dan = { name: 'Dan', age: 20 };\n * const users = [john, sara, dan];\n *\n * console.log(utils.findIndex(users, (user) => user.age === 25)); // 1\n * console.log(utils.findIndex(users, (user) => user.age > 19)); // 2\n * console.log(utils.findIndex(users, (user) => user.name === 'John')); // 0\n * console.log(utils.findIndex(users, (user) => user.name === 'Jimmy')); // -1\n *\n * @method utils.findIndex\n * @param {array} array The array to search.\n * @param {Function} fn Checker function.\n * @returns {number} Index if found or -1 if not found.\n * @since 3.0.0\n */\n findIndex (array, fn) {\n let index = -1\n if (!array) {\n return index\n }\n array.forEach((record, i) => {\n if (fn(record)) {\n index = i\n return false\n }\n })\n return index\n },\n\n /**\n * Recursively iterate over a {@link Mapper}'s relations according to\n * `opts.with`.\n *\n * @method utils.forEachRelation\n * @param {Mapper} mapper Mapper.\n * @param {object} opts Configuration options.\n * @param {Function} fn Callback function.\n * @param {*} thisArg Execution context for the callback function.\n * @since 3.0.0\n */\n forEachRelation (mapper, opts, fn, thisArg?) {\n const relationList = mapper.relationList || []\n if (!relationList.length) {\n return\n }\n relationList.forEach(def => {\n utils._forRelation(opts, def, fn, thisArg)\n })\n },\n\n /**\n * Iterate over an object's own enumerable properties.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = { b: 1, c: 4 };\n * let sum = 0;\n * utils.forOwn(a, function (value, key) {\n * sum += value;\n * });\n * console.log(sum); // 5\n *\n * @method utils.forOwn\n * @param obj\n * @param {Function} fn Iteration function.\n * @param {object} [thisArg] Content to which to bind `fn`.\n * @since 3.0.0\n */\n forOwn (obj, fn, thisArg?) {\n const keys = Object.keys(obj)\n const len = keys.length\n let i\n for (i = 0; i < len; i++) {\n if (fn.call(thisArg, obj[keys[i]], keys[i], obj) === false) {\n break\n }\n }\n },\n\n /**\n * Proxy for `JSON.parse`.\n *\n * @example\n * import { utils } from 'js-data';\n *\n * const a = utils.fromJson('{\"name\" : \"John\"}');\n * console.log(a); // { name: 'John' }\n *\n * @method utils.fromJson\n * @param {string} json JSON to parse.\n * @returns {Object} Parsed object.\n * @see utils.toJson\n * @since 3.0.0\n */\n fromJson (json) {\n return utils.isString(json) ? JSON.parse(json) : json\n },\n\n /**\n * Retrieve the specified property from the given object. Supports retrieving\n * nested properties.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = { foo: { bar: 'baz' }, beep: 'boop' };\n * console.log(utils.get(a, 'beep')); // \"boop\"\n * console.log(utils.get(a, 'foo.bar')); // \"baz\"\n *\n * @method utils.get\n * @param {object} object Object from which to retrieve a property's value.\n * @param {string} prop Property to retrieve.\n * @returns {*} Value of the specified property.\n * @see utils.set\n * @since 3.0.0\n */\n get (object, prop) {\n if (!prop) {\n return\n }\n /* if prop is function, get the property by calling a function, passing an object as a parameter */\n if (utils.isFunction(prop)) {\n return prop(object)\n }\n const parts = prop.split('.')\n const last = parts.pop()\n\n while ((prop = parts.shift())) {\n // eslint-disable-line\n object = object[prop]\n if (object == null) {\n // eslint-disable-line\n return\n }\n }\n\n return object[last]\n },\n\n /**\n * Return the superclass for the given instance or subclass. If an instance is\n * provided, then finds the parent class of the instance's constructor.\n *\n * @example\n * import { utils } from 'js-data';\n * // using ES2015 classes\n * class Foo {}\n * class Bar extends Foo {}\n * const barInstance = new Bar();\n * let baseType = utils.getSuper(barInstance);\n * console.log(Foo === baseType); // true\n *\n * // using Function constructor with utils.extend\n * function Foo () {}\n * Foo.extend = utils.extend;\n * const Bar = Foo.extend();\n * const barInstance = new Bar();\n * let baseType = utils.getSuper(barInstance);\n * console.log(Foo === baseType); // true\n *\n * @method utils.getSuper\n * @param {Object|Function} instance Instance or constructor.\n * @param {boolean} [isCtor=false] Whether `instance` is a constructor.\n * @returns {Constructor} The superclass (grandparent constructor).\n * @since 3.0.0\n */\n getSuper (instance, isCtor?) {\n const ctor = isCtor ? instance : instance.constructor\n if (ctor.hasOwnProperty('__super__')) {\n return ctor.__super__\n }\n return Object.getPrototypeOf(ctor) || ctor.__proto__; // eslint-disable-line\n },\n\n /**\n * Return the intersection of two arrays.\n *\n * @example\n * import { utils } from 'js-data';\n * const arrA = ['green', 'red', 'blue', 'red'];\n * const arrB = ['green', 'yellow', 'red'];\n * const intersected = utils.intersection(arrA, arrB);\n *\n * console.log(intersected); // ['green', 'red'])\n *\n * @method utils.intersection\n * @param {array} array1 First array.\n * @param {array} array2 Second array.\n * @returns {Array} Array of elements common to both arrays.\n * @since 3.0.0\n */\n intersection (array1, array2) {\n if (!array1 || !array2) {\n return []\n }\n array1 = Array.isArray(array1) ? array1 : [array1]\n array2 = Array.isArray(array2) ? array2 : [array2]\n const result = []\n let item\n let i\n const len = array1.length\n for (i = 0; i < len; i++) {\n item = array1[i]\n if (result.indexOf(item) !== -1) {\n continue\n }\n if (array2.indexOf(item) !== -1) {\n result.push(item)\n }\n }\n return result\n },\n\n /**\n * Proxy for `Array.isArray`.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = [1,2,3,4,5];\n * const b = { foo: \"bar\" };\n * console.log(utils.isArray(a)); // true\n * console.log(utils.isArray(b)); // false\n *\n * @method utils.isArray\n * @param {*} value The value to test.\n * @returns {boolean} Whether the provided value is an array.\n * @since 3.0.0\n */\n isArray: Array.isArray,\n\n /**\n * Return whether `prop` is matched by any string or regular expression in\n * `blacklist`.\n *\n * @example\n * import { utils } from 'js-data';\n * const blacklist = [/^\\$hashKey/g, /^_/g, 'id'];\n * console.log(utils.isBlacklisted(\"$hashKey\", blacklist)); // true\n * console.log(utils.isBlacklisted(\"id\", blacklist)); // true\n * console.log(utils.isBlacklisted(\"_myProp\", blacklist)); // true\n * console.log(utils.isBlacklisted(\"my_id\", blacklist)); // false\n *\n * @method utils.isBlacklisted\n * @param {string} prop The name of a property to check.\n * @param {array} blacklist Array of strings and regular expressions.\n * @returns {boolean} Whether `prop` was matched.\n * @since 3.0.0\n */\n isBlacklisted (prop, blacklist) {\n if (!blacklist || !blacklist.length) {\n return false\n }\n let matches\n for (const item of blacklist) {\n if ((toStr(item) === REGEXP_TAG && item.test(prop)) || item === prop) {\n matches = prop\n return !!matches\n }\n }\n return !!matches\n },\n\n /**\n * Return whether the provided value is a boolean.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = true;\n * const b = { foo: \"bar\" };\n * console.log(utils.isBoolean(a)); // true\n * console.log(utils.isBoolean(b)); // false\n *\n * @method utils.isBoolean\n * @param {*} value The value to test.\n * @returns {boolean} Whether the provided value is a boolean.\n * @since 3.0.0\n */\n isBoolean (value) {\n return toStr(value) === BOOL_TAG\n },\n\n /**\n * Return whether the provided value is a date.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = new Date();\n * const b = { foo: \"bar\" };\n * console.log(utils.isDate(a)); // true\n * console.log(utils.isDate(b)); // false\n *\n * @method utils.isDate\n * @param {*} value The value to test.\n * @returns {Date} Whether the provided value is a date.\n * @since 3.0.0\n */\n isDate (value) {\n return value && typeof value === 'object' && toStr(value) === DATE_TAG\n },\n\n /**\n * Return whether the provided value is a function.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = function () { console.log('foo bar'); };\n * const b = { foo: \"bar\" };\n * console.log(utils.isFunction(a)); // true\n * console.log(utils.isFunction(b)); // false\n *\n * @method utils.isFunction\n * @param {*} value The value to test.\n * @returns {boolean} Whether the provided value is a function.\n * @since 3.0.0\n */\n isFunction (value) {\n return typeof value === 'function' || (value && toStr(value) === FUNC_TAG)\n },\n\n /**\n * Return whether the provided value is an integer.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = 1;\n * const b = 1.25;\n * const c = '1';\n * console.log(utils.isInteger(a)); // true\n * console.log(utils.isInteger(b)); // false\n * console.log(utils.isInteger(c)); // false\n *\n * @method utils.isInteger\n * @param {*} value The value to test.\n * @returns {boolean} Whether the provided value is an integer.\n * @since 3.0.0\n */\n isInteger (value) {\n // tslint:disable-next-line:triple-equals\n return toStr(value) === NUMBER_TAG && value == toInteger(value); // eslint-disable-line\n },\n\n /**\n * Return whether the provided value is `null`.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = null;\n * const b = { foo: \"bar\" };\n * console.log(utils.isNull(a)); // true\n * console.log(utils.isNull(b)); // false\n *\n * @method utils.isNull\n * @param {*} value The value to test.\n * @returns {boolean} Whether the provided value is `null`.\n * @since 3.0.0\n */\n isNull (value) {\n return value === null\n },\n\n /**\n * Return whether the provided value is a number.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = 1;\n * const b = -1.25;\n * const c = '1';\n * console.log(utils.isNumber(a)); // true\n * console.log(utils.isNumber(b)); // true\n * console.log(utils.isNumber(c)); // false\n *\n * @method utils.isNumber\n * @param {*} value The value to test.\n * @returns {boolean} Whether the provided value is a number.\n * @since 3.0.0\n */\n isNumber (value) {\n const type = typeof value\n return type === 'number' || (value && type === 'object' && toStr(value) === NUMBER_TAG)\n },\n\n /**\n * Return whether the provided value is an object.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = { foo: \"bar\" };\n * const b = 'foo bar';\n * console.log(utils.isObject(a)); // true\n * console.log(utils.isObject(b)); // false\n *\n * @method utils.isObject\n * @param {*} value The value to test.\n * @returns {boolean} Whether the provided value is an object.\n * @since 3.0.0\n */\n isObject (value) {\n return toStr(value) === OBJECT_TAG\n },\n\n /**\n * Return whether the provided value is a regular expression.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = /^\\$.+$/ig;\n * const b = new RegExp('^\\$.+$', 'ig');\n * const c = { foo: \"bar\" };\n * console.log(utils.isRegExp(a)); // true\n * console.log(utils.isRegExp(b)); // true\n * console.log(utils.isRegExp(c)); // false\n *\n * @method utils.isRegExp\n * @param {*} value The value to test.\n * @returns {boolean} Whether the provided value is a regular expression.\n * @since 3.0.0\n */\n isRegExp (value) {\n return toStr(value) === REGEXP_TAG\n },\n\n /**\n * Return whether the provided value is a string or a number.\n *\n * @example\n * import { utils } from 'js-data';\n * console.log(utils.isSorN('')); // true\n * console.log(utils.isSorN(-1.65)); // true\n * console.log(utils.isSorN('my string')); // true\n * console.log(utils.isSorN({})); // false\n * console.log(utils.isSorN([1,2,4])); // false\n *\n * @method utils.isSorN\n * @param {*} value The value to test.\n * @returns {boolean} Whether the provided value is a string or a number.\n * @since 3.0.0\n */\n isSorN (value) {\n return utils.isString(value) || utils.isNumber(value)\n },\n\n /**\n * Return whether the provided value is a string.\n *\n * @example\n * import { utils } from 'js-data';\n * console.log(utils.isString('')); // true\n * console.log(utils.isString('my string')); // true\n * console.log(utils.isString(100)); // false\n * console.log(utils.isString([1,2,4])); // false\n *\n * @method utils.isString\n * @param {*} value The value to test.\n * @returns {boolean} Whether the provided value is a string.\n * @since 3.0.0\n */\n isString (value) {\n return typeof value === 'string' || (value && typeof value === 'object' && toStr(value) === STRING_TAG)\n },\n\n /**\n * Return whether the provided value is a `undefined`.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = undefined;\n * const b = { foo: \"bar\"};\n * console.log(utils.isUndefined(a)); // true\n * console.log(utils.isUndefined(b.baz)); // true\n * console.log(utils.isUndefined(b)); // false\n * console.log(utils.isUndefined(b.foo)); // false\n *\n * @method utils.isUndefined\n * @param {*} value The value to test.\n * @returns {boolean} Whether the provided value is a `undefined`.\n * @since 3.0.0\n */\n isUndefined (value) {\n return value === undefined\n },\n\n /**\n * Mix in logging capabilities to the target.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = { foo: \"bar\"};\n *\n * // Add standard logging to an object\n * utils.logify(a);\n * a.log('info', 'test log info'); // output 'test log info' to console.\n *\n * // Toggle debug output of an object\n * a.dbg('test debug output'); // does not output because debug is off.\n * a.debug = true;\n * a.dbg('test debug output'); // output 'test debug output' to console.\n *\n * @method utils.logify\n * @param {*} target The target.\n * @since 3.0.0\n */\n logify (target) {\n utils.addHiddenPropsToTarget(target, {\n dbg (...args) {\n if (utils.isFunction(this.log)) {\n this.log('debug', ...args)\n }\n },\n log (level, ...args) {\n if (level && !args.length) {\n args.push(level)\n level = 'debug'\n }\n if (level === 'debug' && !this.debug) {\n return\n }\n const prefix = `${level.toUpperCase()}: (${this.name || this.constructor.name})`\n if (utils.isFunction(console[level])) {\n console[level](prefix, ...args)\n } else {\n console.log(prefix, ...args)\n }\n }\n })\n },\n\n /**\n * Adds the given record to the provided array only if it's not already in the\n * array.\n *\n * @example\n * import { utils } from 'js-data';\n * const colors = ['red', 'green', 'yellow'];\n *\n * console.log(colors.length); // 3\n * utils.noDupeAdd(colors, 'red');\n * console.log(colors.length); // 3, red already exists\n *\n * utils.noDupeAdd(colors, 'blue');\n * console.log(colors.length); // 4, blue was added\n *\n * @method utils.noDupeAdd\n * @param {array} array The array.\n * @param {*} record The value to add.\n * @param {Function} fn Callback function passed to {@link utils.findIndex}.\n * @since 3.0.0\n */\n noDupeAdd (array, record?, fn?) {\n if (!array) {\n return\n }\n const index = this.findIndex(array, fn)\n if (index < 0) {\n array.push(record)\n }\n },\n\n /**\n * Return a shallow copy of the provided object, minus the properties\n * specified in `keys`.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = { name: 'John', $hashKey: 1214910 };\n *\n * let b = utils.omit(a, ['$hashKey']);\n * console.log(b); // { name: 'John' }\n *\n * @method utils.omit\n * @param {object} props The object to copy.\n * @param {string[]} keys Array of strings, representing properties to skip.\n * @returns {Object} Shallow copy of `props`, minus `keys`.\n * @since 3.0.0\n */\n omit (props, keys) {\n const _props = {}\n utils.forOwn(props, (value, key) => {\n if (keys.indexOf(key) === -1) {\n _props[key] = value\n }\n })\n return _props\n },\n\n /**\n * Return a shallow copy of the provided object, but only include the\n * properties specified in `keys`.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = { name: 'John', $hashKey: 1214910 };\n *\n * let b = utils.pick(a, ['$hashKey']);\n * console.log(b); // { $hashKey: 1214910 }\n *\n * @method utils.pick\n * @param {object} props The object to copy.\n * @param {string[]} keys Array of strings, representing properties to keep.\n * @returns {Object} Shallow copy of `props`, but only including `keys`.\n * @since 3.0.0\n */\n pick (props, keys) {\n return keys.reduce((map, key) => {\n map[key] = props[key]\n return map\n }, {})\n },\n\n /**\n * Return a plain copy of the given value.\n *\n * @example\n * import { utils } from 'js-data';\n * const a = { name: 'John' };\n * let b = utils.plainCopy(a);\n * console.log(a === b); // false\n *\n * @method utils.plainCopy\n * @param {*} value The value to copy.\n * @returns {*} Plain copy of `value`.\n * @see utils.copy\n * @since 3.0.0\n */\n plainCopy (value) {\n return utils.copy(value, undefined, undefined, undefined, undefined, true)\n },\n\n /**\n * Shortcut for `utils.Promise.reject(value)`.\n *\n * @example\n * import { utils } from 'js-data';\n *\n * utils.reject(\"Testing static reject\").then(function (data) {\n * // not called\n * }).catch(function (reason) {\n * console.log(reason); // \"Testing static reject\"\n * });\n *\n * @method utils.reject\n * @param {*} [value] Value with which to reject the Promise.\n * @returns {Promise} Promise reject with `value`.\n */\n reject (value) {\n return Promise.reject(value)\n },\n\n /**\n * Remove the last item found in array according to the given checker function.\n *\n * @example\n * import { utils } from 'js-data';\n *\n * const colors = ['red', 'green', 'yellow', 'red'];\n * utils.remove(colors, (color) => color === 'red');\n * console.log(colors); // ['red', 'green', 'yellow']\n *\n * @method utils.remove\n * @param {array} array The array to search.\n * @param {Function} fn Checker function.\n */\n remove (array, fn?) {\n if (!array || !array.length) {\n return\n }\n const index = this.findIndex(array, fn)\n if (index >= 0) {\n array.splice(index, 1) // todo should this be recursive?\n }\n },\n\n /**\n * Shortcut for `utils.Promise.resolve(value)`.\n *\n * @example\n * import { utils } from 'js-data';\n *\n * utils.resolve(\"Testing static resolve\").then(function (data) {\n * console.log(data); // \"Testing static resolve\"\n * }).catch(function (reason) {\n * // not called\n * });\n *\n * @param {*} [value] Value with which to resolve the Promise.\n * @returns {Promise} Promise resolved with `value`.\n */\n resolve (value?) {\n return Promise.resolve(value)\n },\n\n /**\n * Set the value at the provided key or path.\n *\n * @example\n * import { utils } from 'js-data';\n *\n * const john = {\n * name: 'John',\n * age: 25,\n * parent: {\n * name: 'John's Mom',\n * age: 50\n * }\n * };\n * // set value by key\n * utils.set(john, 'id', 98);\n * console.log(john.id); // 98\n *\n * // set value by path\n * utils.set(john, 'parent.id', 20);\n * console.log(john.parent.id); // 20\n *\n * // set value by path/value map\n * utils.set(john, {\n * 'id': 1098,\n * 'parent': { id: 1020 },\n * 'parent.age': '55'\n * });\n * console.log(john.id); // 1098\n * console.log(john.parent.id); // 1020\n * console.log(john.parent.age); // 55\n *\n * @method utils.set\n * @param {object} object The object on which to set a property.\n * @param {(string|Object)} path The key or path to the property. Can also\n * pass in an object of path/value pairs, which will all be set on the target\n * object.\n * @param {*} [value] The value to set.\n */\n set (object, path, value?, opts?) {\n if (utils.isObject(path)) {\n utils.forOwn(path, (value, _path) => {\n utils.set(object, _path, value)\n })\n } else {\n const parts = PATH.exec(path)\n if (parts) {\n mkdirP(object, parts[1])[parts[2]] = value\n } else {\n object[path] = value\n }\n }\n },\n\n /**\n * Check whether the two provided objects are deeply equal.\n *\n * @example\n * import { utils } from 'js-data';\n *\n * const objA = {\n * name: 'John',\n * id: 27,\n * nested: {\n * item: 'item 1',\n * colors: ['red', 'green', 'blue']\n * }\n * };\n *\n * const objB = {\n * name: 'John',\n * id: 27,\n * nested: {\n * item: 'item 1',\n * colors: ['red', 'green', 'blue']\n * }\n * };\n *\n * console.log(utils.deepEqual(a,b)); // true\n * objB.nested.colors.add('yellow'); // make a change to a nested object's array\n * console.log(utils.deepEqual(a,b)); // false\n *\n * @method utils.deepEqual\n * @param {object} a First object in the comparison.\n * @param {object} b Second object in the comparison.\n * @returns {boolean} Whether the two provided objects are deeply equal.\n * @see utils.equal\n * @since 3.0.0\n */\n deepEqual (a, b) {\n if (a === b) {\n return true\n }\n let _equal = true\n if (utils.isArray(a) && utils.isArray(b)) {\n if (a.length !== b.length) {\n return false\n }\n for (let i = a.length; i--;) {\n if (!utils.deepEqual(a[i], b[i])) {\n // Exit loop early\n return false\n }\n }\n } else if (utils.isObject(a) && utils.isObject(b)) {\n utils.forOwn(a, (value, key) => {\n if (!(_equal = utils.deepEqual(value, b[key]))) {\n // Exit loop early\n return false\n }\n })\n if (_equal) {\n utils.forOwn(b, (value, key) => {\n if (!(_equal = utils.deepEqual(value, a[key]))) {\n // Exit loop early\n return false\n }\n })\n }\n } else {\n return false\n }\n return _equal\n },\n\n /**\n * Proxy for `JSON.stringify`.\n *\n * @example\n * import { utils } from 'js-data';\n *\n * const a = { name: 'John' };\n * let jsonVal = utils.toJson(a);\n * console.log(jsonVal); // '{\"name\" : \"John\"}'\n *\n * @method utils.toJson\n * @param {*} value Value to serialize to JSON.\n * @returns {string} JSON string.\n * @see utils.fromJson\n * @since 3.0.0\n */\n toJson: JSON.stringify,\n\n /**\n * Unset the value at the provided key or path.\n *\n * @example\n * import { utils } from 'js-data';\n *\n * const john = {\n * name: 'John',\n * age: 25,\n * parent: {\n * name: 'John's Mom',\n * age: 50\n * }\n * };\n *\n * utils.unset(john, age);\n * utils.unset(john, parent.age);\n *\n * console.log(john.age); // null\n * console.log(john.parent.age); // null\n *\n * @method utils.unset\n * @param {object} object The object from which to delete the property.\n * @param {string} path The key or path to the property.\n * @see utils.set\n * @since 3.0.0\n */\n unset (object, path: string) {\n const parts = path.split('.')\n const last = parts.pop()\n\n while ((path = parts.shift())) {\n // eslint-disable-line\n object = object[path]\n if (object == null) {\n // eslint-disable-line\n return\n }\n }\n\n object[last] = undefined\n },\n /**\n * Gets default locale for the js-data context.\n *\n * @example\n * import { utils } from 'js-data';\n *\n *\n * utils.getDefaultLocale();\n *\n * @method utils.getDefaultLocale\n * @since 4.0.0\n */\n getDefaultLocale () {\n return 'en'\n }\n}\n\nexport const safeSetProp = (record, field, value) => {\n if (record?._set) {\n record._set(`props.${field}`, value)\n } else {\n utils.set(record, field, value)\n }\n}\n\nexport const safeSetLink = (record, field, value) => {\n if (record?._set) {\n record._set(`links.${field}`, value)\n } else {\n utils.set(record, field, value)\n }\n}\n\nexport default utils\n","import utils from './utils'\n\n/**\n * A base class which gives instances private properties.\n *\n * Typically you won't instantiate this class directly, but you may find it\n * useful as an abstract class for your own components.\n *\n * @example\n * import {Settable} from 'js-data';\n *\n * class CustomSettableClass extends Settable {\n * foo () { return 'bar'; }\n * static beep () { return 'boop'; }\n * }\n *\n * const customSettable = new CustomSettableClass();\n * console.log(customSettable.foo());\n * console.log(CustomSettableClass.beep());\n *\n * @since 3.0.0\n */\nexport default class Settable {\n [customAttr: string]: any;\n\n /**\n * Get a private property of this instance.\n *\n * __Don't use the method unless you know what you're doing.__\n *\n * @method Settable#_get\n * @param {string} key The property to retrieve.\n * @returns {*} The value of the property.\n * @since 3.0.0\n */\n protected _get: (key: string) => any;\n\n /**\n * Set a private property of this instance.\n *\n * __Don't use the method unless you know what you're doing.__\n *\n * @method __Don't use the method unless you know what you're doing.__#_set\n * @param {(string|Object)} key The key or path to the property. Can also\n * pass in an object of key/value pairs, which will all be set on the instance.\n * @param {*} [value] The value to set.\n * @since 3.0.0\n */\n protected _set: (key, value?) => any;\n\n /**\n * Unset a private property of this instance.\n *\n * __Don't use the method unless you know what you're doing.__\n *\n * @method __Don't use the method unless you know what you're doing.__#_unset\n * @param {string} key The property to unset.\n * @since 3.0.0\n */\n protected _unset: (key) => any;\n\n constructor () {\n const _props = {}\n\n Object.defineProperties(this, {\n _get: {\n value (key) {\n return utils.get(_props, key)\n }\n },\n _set: {\n value (key, value) {\n return utils.set(_props, key, value)\n }\n },\n _unset: {\n value (key) {\n return utils.unset(_props, key)\n }\n }\n })\n }\n}\n","import utils from './utils'\nimport Settable from './Settable'\n\nexport interface ComponentOpts {\n debug?: boolean\n}\n\n/**\n * The base class from which all JSData components inherit some basic\n * functionality.\n *\n * Typically you won't instantiate this class directly, but you may find it\n * useful as an abstract class for your own components.\n *\n * @example\n * import {Component} from 'js-data'\n *\n * class CustomComponentClass extends Component {\n * foo () { return 'bar'; }\n * static beep () { return 'boop'; }\n * }\n * const customComponent = new CustomComponentClass();\n * console.log(customComponent.foo());\n * console.log(CustomComponentClass.beep());\n * ```\n *\n * @param {object} [opts] Configuration options.\n * @param {boolean} [opts.debug=false] See {@link Component#debug}.\n * @returns {Component} A new {@link Component} instance.\n * @since 3.0.0\n */\nexport default class Component extends Settable {\n /**\n * Whether to enable debug-level logs for this component. Anything that\n * extends `Component` inherits this option and the corresponding logging\n * functionality.\n *\n * @example Component#debug\n * const JSData = require('js-data');\n * const { Component } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const component = new Component();\n * component.log('debug', 'some message'); // nothing gets logged\n * // Display debug logs:\n * component.debug = true;\n * component.log('debug', 'other message'); // this DOES get logged\n *\n * @default false\n * @name Component#debug\n * @since 3.0.0\n * @type {boolean}\n */\n protected debug: boolean;\n\n /**\n * Event listeners attached to this Component. __Do not modify.__ Use\n * {@link Component#on} and {@link Component#off} instead.\n *\n * @name Component#_listeners\n * @private\n * @instance\n * @since 3.0.0\n * @type {Object}\n */\n _listeners = {};\n\n /**\n * Log the provided values at the \"debug\" level. Debug-level logs are only\n * logged if {@link Component#debug} is `true`.\n *\n * `.dbg(...)` is shorthand for `.log('debug', ...)`.\n *\n * @method Component#dbg\n * @param {...*} [args] Values to log.\n * @since 3.0.0\n */\n dbg: (...args) => void;\n\n /**\n * Log the provided values. By default sends values to `console[level]`.\n * Debug-level logs are only logged if {@link Component#debug} is `true`.\n *\n * Will attempt to use appropriate `console` methods if they are available.\n *\n * @method Component#log\n * @param {string} level Log level.\n * @param {...*} [args] Values to log.\n * @since 3.0.0\n */\n log: (...args) => void;\n\n /**\n * Register a new event listener on this Component.\n *\n * @example\n * // Listen for all \"afterCreate\" events in a DataStore\n * store.on('afterCreate', (mapperName, props, opts, result) => {\n * console.log(mapperName); // \"post\"\n * console.log(props.id); // undefined\n * console.log(result.id); // 1234\n * });\n * store.create('post', { title: 'Modeling your data' }).then((post) => {\n * console.log(post.id); // 1234\n * });\n *\n * @example\n * // Listen for the \"add\" event on a collection\n * collection.on('add', (records) => {\n * console.log(records); // [...]\n * });\n *\n * @example\n * // Listen for \"change\" events on a record\n * post.on('change', (record, changes) => {\n * console.log(changes); // { changed: { title: 'Modeling your data' } }\n * });\n * post.title = 'Modeling your data';\n *\n * @method Component#on\n * @param {string} event Name of event to subscribe to.\n * @param {Function} listener Listener function to handle the event.\n * @param {*} [ctx] Optional content in which to invoke the listener.\n * @since 3.0.0\n */\n on: (name: string, listener: Function, ctx?) => void;\n\n /**\n * Remove an event listener from this Component. If no listener is provided,\n * then all listeners for the specified event will be removed. If no event is\n * specified then all listeners for all events will be removed.\n *\n * @example\n * // Remove a particular listener for a particular event\n * collection.off('add', handler);\n *\n * @example\n * // Remove all listeners for a particular event\n * record.off('change');\n *\n * @example\n * // Remove all listeners to all events\n * store.off();\n *\n * @method Component#off\n * @param {string} [event] Name of event to unsubscribe to.\n * @param {Function} [listener] Listener to remove.\n * @since 3.0.0\n */\n off: (event: string, listener?: Function, thisArg?) => void;\n\n /**\n * Trigger an event on this Component.\n *\n * @example Component#emit\n * // import { Collection, DataStore } from 'js-data';\n * const JSData = require('js-data');\n * const { Collection, DataStore } = JSData;\n *\n * const collection = new Collection();\n * collection.on('foo', function (msg) {\n * console.log(msg);\n * });\n * collection.emit('foo', 'bar');\n *\n * const store = new DataStore();\n * store.on('beep', function (msg) {\n * console.log(msg);\n * });\n * store.emit('beep', 'boop');\n *\n * @method Component#emit\n * @param {string} event Name of event to emit.\n * @param {...*} [args] Arguments to pass to any listeners.\n * @since 3.0.0\n */\n emit: (event: string, ...args) => void;\n\n constructor (opts: ComponentOpts | any = {}) {\n super()\n this.debug = opts.debug ?? false\n }\n}\n\nutils.logify(Component.prototype)\n\nutils.eventify(\n Component.prototype,\n function () {\n return this._listeners\n },\n function (value) {\n this._listeners = value\n }\n)\n","import utils from './utils'\nimport Component from './Component'\n\nconst DOMAIN = 'Query'\nconst INDEX_ERR = 'Index inaccessible after first operation'\n\n// Reserved words used by JSData's Query Syntax\nconst reserved = {\n limit: '',\n offset: '',\n orderBy: '',\n skip: '',\n sort: '',\n where: '',\n locale: ''\n}\n\n// Used by our JavaScript implementation of the LIKE operator\nconst escapeRegExp = /([.*+?^=!:${}()|[\\]/\\\\])/g\nconst percentRegExp = /%/g\nconst underscoreRegExp = /_/g\n\nfunction escape (pattern) {\n return pattern.replace(escapeRegExp, '\\\\$1')\n}\n\nexport interface QueryDefinition {\n [attr: string]: any\n where?: any\n orderBy?: any\n sort?: any\n skip?: number\n limit?: number\n offset?: number\n}\n\n/**\n * A class used by the {@link Collection} class to build queries to be executed\n * against the collection's data. An instance of `Query` is returned by\n * {@link Collection#query}. Query instances are typically short-lived, and you\n * shouldn't have to create them yourself. Just use {@link Collection#query}.\n *\n * ```javascript\n * import { Query } from 'js-data';\n * ```\n *\n * @example Query intro\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post');\n * const posts = [\n * { author: 'John', age: 30, status: 'published', id: 1 },\n * { author: 'Sally', age: 31, status: 'draft', id: 2 },\n * { author: 'Mike', age: 32, status: 'draft', id: 3 },\n * { author: 'Adam', age: 33, status: 'deleted', id: 4 },\n * { author: 'Adam', age: 33, status: 'draft', id: 5 }\n * ]\n * store.add('post', posts);\n * const drafts = store.query('post').filter({ status: 'draft' }).limit(2).run();\n * console.log(drafts);\n *\n * @class Query\n * @extends Component\n * @param {Collection} collection The collection on which this query operates.\n * @since 3.0.0\n */\nexport default class Query extends Component {\n /**\n * The current data result of this query.\n *\n * @name Query#data\n * @since 3.0.0\n * @type {Array}\n */\n private data = null;\n\n constructor (public collection?) {\n super()\n }\n\n _applyWhereFromObject (where) {\n const fields = []\n const ops = []\n const predicates = []\n utils.forOwn(where, (clause, field) => {\n if (!utils.isObject(clause)) {\n clause = {\n '==': clause\n }\n }\n utils.forOwn(clause, (expr, op) => {\n fields.push(field)\n ops.push(op)\n predicates.push(expr)\n })\n })\n return {\n fields,\n ops,\n predicates\n }\n }\n\n _applyWhereFromArray (where) {\n const groups: any = []\n where.forEach((_where, i) => {\n if (utils.isString(_where)) {\n return\n }\n const prev = where[i - 1]\n const parser = utils.isArray(_where) ? this._applyWhereFromArray : this._applyWhereFromObject\n const group = parser.call(this, _where)\n if (prev === 'or') {\n group.isOr = true\n }\n groups.push(group)\n })\n groups.isArray = true\n return groups\n }\n\n _testObjectGroup (keep, first, group, item) {\n let i\n const fields = group.fields\n const ops = group.ops\n const predicates = group.predicates\n const len = ops.length\n for (i = 0; i < len; i++) {\n let op = ops[i]\n const isOr = op.charAt(0) === '|'\n op = isOr ? op.substr(1) : op\n const expr = this.evaluate(utils.get(item, fields[i]), op, predicates[i])\n if (expr !== undefined) {\n keep = first ? expr : isOr ? keep || expr : keep && expr\n }\n first = false\n }\n return { keep, first }\n }\n\n _testArrayGroup (keep, first, groups, item) {\n let i\n const len = groups.length\n for (i = 0; i < len; i++) {\n const group = groups[i]\n const parser = group.isArray ? this._testArrayGroup : this._testObjectGroup\n const result = parser.call(this, true, true, group, item)\n if (groups[i - 1]) {\n if (group.isOr) {\n keep = keep || result.keep\n } else {\n keep = keep && result.keep\n }\n } else {\n keep = result.keep\n }\n first = result.first\n }\n return { keep, first }\n }\n\n /**\n * Find all entities between two boundaries.\n *\n * @example Get the users ages 18 to 30.\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('user');\n * const users = [\n * { name: 'Peter', age: 25, id: 1 },\n * { name: 'Jim', age: 19, id: 2 },\n * { name: 'Mike', age: 17, id: 3 },\n * { name: 'Alan', age: 29, id: 4 },\n * { name: 'Katie', age: 33, id: 5 }\n * ];\n * store.add('user', users)\n * const filteredUsers = store\n * .query('user')\n * .between(18, 30, { index: 'age' })\n * .run();\n * console.log(filteredUsers);\n *\n * @example Same as above.\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('user');\n * const users = [\n * { name: 'Peter', age: 25, id: 1 },\n * { name: 'Jim', age: 19, id: 2 },\n * { name: 'Mike', age: 17, id: 3 },\n * { name: 'Alan', age: 29, id: 4 },\n * { name: 'Katie', age: 33, id: 5 }\n * ];\n * store.add('user', users)\n * const filteredUsers = store\n * .query('user')\n * .between([18], [30], { index: 'age' })\n * .run();\n * console.log(filteredUsers);\n *\n * @method Query#between\n * @param {array} leftKeys Keys defining the left boundary.\n * @param {array} rightKeys Keys defining the right boundary.\n * @param {object} [opts] Configuration options.\n * @param {string} [opts.index] Name of the secondary index to use in the\n * query. If no index is specified, the main index is used.\n * @param {boolean} [opts.leftInclusive=true] Whether to include entities\n * on the left boundary.\n * @param {boolean} [opts.rightInclusive=false] Whether to include entities\n * on the left boundary.\n * @param {boolean} [opts.limit] Limit the result to a certain number.\n * @param {boolean} [opts.offset] The number of resulting entities to skip.\n * @returns {Query} A reference to itself for chaining.\n * @since 3.0.0\n */\n between (leftKeys?, rightKeys?, opts: any = {}) {\n if (this.data) {\n throw utils.err(`${DOMAIN}#between`)(500, 'Cannot access index')\n }\n this.data = this.collection.getIndex(opts.index).between(leftKeys, rightKeys, opts)\n return this\n }\n\n /**\n * The comparison function used by the {@link Query} class.\n *\n * @method Query#compare\n * @param {array} orderBy An orderBy clause used for sorting and sub-sorting.\n * @param {number} index The index of the current orderBy clause being used.\n * @param {*} a The first item in the comparison.\n * @param {*} b The second item in the comparison.\n * @returns {number} -1 if `b` should preceed `a`. 0 if `a` and `b` are equal.\n * 1 if `a` should preceed `b`.\n * @since 3.0.0\n */\n compare (orderBy, index, a, b, compare) {\n const def = orderBy[index]\n let cA = utils.get(a, def[0])\n let cB = utils.get(b, def[0])\n if (cA && utils.isString(cA)) {\n cA = cA.toUpperCase()\n }\n if (cB && utils.isString(cB)) {\n cB = cB.toUpperCase()\n }\n if (a === undefined) {\n a = null\n }\n if (b === undefined) {\n b = null\n }\n if (def[1].toUpperCase() === 'DESC') {\n const temp = cB\n cB = cA\n cA = temp\n }\n /* Fix: compare by using collator */\n // let isNumeric = false\n // if (utils.isNumber(cA) || utils.isNumber(cB)) {\n // isNumeric = true\n // }\n const n = compare(cA, cB)\n if (n === -1 || n === 1) {\n return n\n } else {\n if (index < orderBy.length - 1) {\n return this.compare(orderBy, index + 1, a, b, compare)\n } else {\n return 0\n }\n }\n }\n\n /**\n * Predicate evaluation function used by the {@link Query} class.\n *\n * @method Query#evaluate\n * @param {*} value The value to evaluate.\n * @param {string} op The operator to use in this evaluation.\n * @param {*} predicate The predicate to use in this evaluation.\n * @returns {boolean} Whether the value passed the evaluation or not.\n * @since 3.0.0\n */\n evaluate (value, op, predicate) {\n const ops = Query.ops\n if (ops[op]) {\n return ops[op](value, predicate)\n }\n if (op.indexOf('like') === 0) {\n return this.like(predicate, op.substr(4)).exec(value) !== null\n } else if (op.indexOf('notLike') === 0) {\n return this.like(predicate, op.substr(7)).exec(value) === null\n }\n }\n\n /**\n * Find the record or records that match the provided query or are accepted by\n * the provided filter function.\n *\n * @example Get the draft posts by authors younger than 30\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post')\n * const posts = [\n * { author: 'John', age: 30, status: 'published', id: 1 },\n * { author: 'Sally', age: 31, status: 'published', id: 2 },\n * { author: 'Mike', age: 32, status: 'draft', id: 3 },\n * { author: 'Adam', age: 33, status: 'deleted', id: 4 },\n * { author: 'Adam', age: 33, status: 'published', id: 5 }\n * { author: 'Peter', age: 25, status: 'deleted', id: 6 },\n * { author: 'Sally', age: 21, status: 'draft', id: 7 },\n * { author: 'Jim', age: 27, status: 'draft', id: 8 },\n * { author: 'Jim', age: 27, status: 'published', id: 9 },\n * { author: 'Jason', age: 55, status: 'published', id: 10 }\n * ];\n * store.add('post', posts);\n * const results = store\n * .query('post')\n * .filter({\n * where: {\n * status: {\n * '==': 'draft'\n * },\n * age: {\n * '<': 30\n * }\n * }\n * })\n * .run();\n * console.log(results);\n *\n * @example Use a custom filter function\n * const posts = query\n * .filter(function (post) {\n * return post.isReady();\n * })\n * .run();\n *\n * @method Query#filter\n * @param {(Object|Function)} [query={}] Selection query or filter\n * function.\n * @param {Function} [thisArg] Context to which to bind `queryOrFn` if\n * `queryOrFn` is a function.\n * @returns {Query} A reference to itself for chaining.\n * @since 3.0.0\n */\n filter (query: QueryDefinition = {}, thisArg?: Function): Query {\n /**\n * Selection query as defined by JSData's [Query Syntax][querysyntax].\n *\n * [querysyntax]: http://www.js-data.io/v3.0/docs/query-syntax\n *\n * @example Empty \"findAll\" query\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post')\n * store.findAll('post').then((posts) => {\n * console.log(posts); // [...]\n * });\n *\n * @example Empty \"filter\" query\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post');\n * const posts = store.filter('post');\n * console.log(posts); // [...]\n *\n * @example Complex \"filter\" query\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * const PAGE_SIZE = 2;\n * let currentPage = 3;\n *\n * store.defineMapper('post');\n * const posts = [\n * { author: 'John', age: 30, status: 'published', id: 1 },\n * { author: 'Sally', age: 31, status: 'published', id: 2 },\n * { author: 'Mike', age: 32, status: 'draft', id: 3 },\n * { author: 'Adam', age: 33, status: 'deleted', id: 4 },\n * { author: 'Adam', age: 33, status: 'published', id: 5 }\n * { author: 'Peter', age: 25, status: 'deleted', id: 6 },\n * { author: 'Sally', age: 21, status: 'draft', id: 7 },\n * { author: 'Jim', age: 27, status: 'draft', id: 8 },\n * { author: 'Jim', age: 27, status: 'published', id: 9 },\n * { author: 'Jason', age: 55, status: 'published', id: 10 }\n * ];\n * store.add('post', posts);\n * // Retrieve a filtered page of blog posts\n * // Would typically replace filter with findAll\n * const results = store.filter('post', {\n * where: {\n * status: {\n * // WHERE status = 'published'\n * '==': 'published'\n * },\n * author: {\n * // AND author IN ('bob', 'alice')\n * 'in': ['bob', 'alice'],\n * // OR author IN ('karen')\n * '|in': ['karen']\n * }\n * },\n * orderBy: [\n * // ORDER BY date_published DESC,\n * ['date_published', 'DESC'],\n * // ORDER BY title ASC\n * ['title', 'ASC']\n * ],\n * // LIMIT 2\n * limit: PAGE_SIZE,\n * // SKIP 4\n * offset: PAGE_SIZE * (currentPage - 1)\n * });\n * console.log(results);\n *\n * @namespace query\n * @property {number} [limit] See {@link query.limit}.\n * @property {number} [offset] See {@link query.offset}.\n * @property {string|Array[]} [orderBy] See {@link query.orderBy}.\n * @property {number} [skip] Alias for {@link query.offset}.\n * @property {string|Array[]} [sort] Alias for {@link query.orderBy}.\n * @property {Object} [where] See {@link query.where}.\n * @property {String} [locale] See {@link query.locale}.\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/query-syntax\",\"JSData's Query Syntax\"]\n */\n this.getData()\n if (utils.isObject(query)) {\n let where = {}\n\n /**\n * Filtering criteria. Records that do not meet this criteria will be exluded\n * from the result.\n *\n * @example Return posts where author is at least 32 years old\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post')\n * const posts = [\n * { author: 'John', age: 30, id: 5 },\n * { author: 'Sally', age: 31, id: 6 },\n * { author: 'Mike', age: 32, id: 7 },\n * { author: 'Adam', age: 33, id: 8 },\n * { author: 'Adam', age: 33, id: 9 }\n * ];\n * store.add('post', posts);\n * const results = store.filter('post', {\n * where: {\n * age: {\n * '>=': 30\n * }\n * }\n * });\n * console.log(results);\n *\n * @name query.where\n * @type {Object}\n * @see http://www.js-data.io/v3.0/docs/query-syntax\n * @since 3.0.0\n */\n if (utils.isObject(query.where) || utils.isArray(query.where)) {\n where = query.where\n }\n utils.forOwn(query, (value, key) => {\n if (!(key in reserved) && !(key in where)) {\n where[key] = {\n '==': value\n }\n }\n })\n let groups\n\n // Apply filter for each field\n if (utils.isObject(where) && Object.keys(where).length !== 0) {\n groups = this._applyWhereFromArray([where])\n } else if (utils.isArray(where)) {\n groups = this._applyWhereFromArray(where)\n }\n\n if (groups) {\n this.data = this.data.filter(item => this._testArrayGroup(true, true, groups, item).keep)\n }\n\n // Sort\n let orderBy = query.orderBy || query.sort\n\n if (utils.isString(orderBy)) {\n orderBy = [[orderBy, 'ASC']]\n }\n if (!utils.isArray(orderBy)) {\n orderBy = null\n }\n\n /**\n * Determines how records should be ordered in the result.\n *\n * @example Order posts by `author` then by `id` descending \n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post')\n * const posts = [\n * { author: 'John', age: 30, id: 5 },\n * { author: 'Sally', age: 31, id: 6 },\n * { author: 'Mike', age: 32, id: 7 },\n * { author: 'Adam', age: 33, id: 8 },\n * { author: 'Adam', age: 33, id: 9 }\n * ];\n * store.add('post', posts);\n * const results = store.filter('post', {\n * orderBy:[['author','ASC'],['id','DESC']]\n * });\n * console.log(results);\n *\n * @name query.orderBy\n * @type {string|Array[]}\n * @see http://www.js-data.io/v3.0/docs/query-syntax\n * @since 3.0.0\n */\n if (orderBy) {\n const index = 0\n orderBy.forEach((def, i) => {\n if (utils.isString(def)) {\n orderBy[i] = [def, 'ASC']\n }\n })\n let locale: string = utils.getDefaultLocale()\n if (utils.isString(query.locale)) {\n locale = query.locale\n }\n /** The locale params has to be explicitly set for the collator.compare to work.\n *\n * @example Order posts with specific locale, defaults to 'en'\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post')\n * const posts = [\n * { author: 'คลอน', age: 30, id: 5 },\n * { author: 'กลอน', age: 31, id: 6 },\n * { author: 'สาระ', age: 32, id: 7 },\n * { author: 'ศาลา', age: 33, id: 8 },\n * { author: 'จักรพรรณ', age: 33, id: 9 }\n * ];\n * store.add('post', posts);\n * const results = store.filter('post', {\n * orderBy:[['author','ASC'],['id','DESC']],\n * locale: 'th'\n * });\n * console.log(results);\n *\n * @name query.locale\n * @type {string}\n * @see http://www.js-data.io/v4.0/docs/query-syntax\n * @since 4.0.0\n */\n const collator = new Intl.Collator(locale, {\n numeric: true\n })\n\n this.data.sort((a, b) => this.compare(orderBy, index, a, b, collator.compare))\n }\n\n /**\n * Number of records to skip.\n *\n * @example Retrieve the first \"page\" of blog posts using findAll\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post');\n * const PAGE_SIZE = 10;\n * let currentPage = 1;\n * store.findAll('post', {\n * offset: PAGE_SIZE * (currentPage 1)\n * limit: PAGE_SIZE\n * });\n *\n * @example Retrieve the last \"page\" of blog posts using filter\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n *\n * const PAGE_SIZE = 5;\n * let currentPage = 2;\n * store.defineMapper('post');\n * const posts = [\n * { author: 'John', age: 30, id: 1 },\n * { author: 'Sally', age: 31, id: 2 },\n * { author: 'Mike', age: 32, id: 3 },\n * { author: 'Adam', age: 33, id: 4 },\n * { author: 'Adam', age: 33, id: 5 },\n * { author: 'Peter', age: 25, id: 6 },\n * { author: 'Sally', age: 21, id: 7 },\n * { author: 'Jim', age: 27, id: 8 },\n * { author: 'Jim', age: 27, id: 9 },\n * { author: 'Jason', age: 55, id: 10 }\n * ];\n * store.add('post', posts);\n * const results = store.filter('post', {\n * offset: PAGE_SIZE * (currentPage 1)\n * limit: PAGE_SIZE\n * });\n * console.log(results)\n *\n * @name query.offset\n * @type {number}\n * @see http://www.js-data.io/v3.0/docs/query-syntax\n * @since 3.0.0\n */\n if (utils.isNumber(query.skip)) {\n this.skip(query.skip)\n } else if (utils.isNumber(query.offset)) {\n this.skip(query.offset)\n }\n\n /**\n * Maximum number of records to retrieve.\n *\n * @example Retrieve the first \"page\" of blog posts using findAll\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post');\n *\n * const PAGE_SIZE = 10\n * let currentPage = 1\n * store.findAll('post', {\n * offset: PAGE_SIZE * (currentPage 1)\n * limit: PAGE_SIZE\n * });\n *\n * @example Retrieve the last \"page\" of blog posts using filter\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n *\n * const PAGE_SIZE = 5\n * let currentPage = 2\n * store.defineMapper('post')\n * const posts = [\n * { author: 'John', age: 30, id: 1 },\n * { author: 'Sally', age: 31, id: 2 },\n * { author: 'Mike', age: 32, id: 3 },\n * { author: 'Adam', age: 33, id: 4 },\n * { author: 'Adam', age: 33, id: 5 },\n * { author: 'Peter', age: 25, id: 6 },\n * { author: 'Sally', age: 21, id: 7 },\n * { author: 'Jim', age: 27, id: 8 },\n * { author: 'Jim', age: 27, id: 9 },\n * { author: 'Jason', age: 55, id: 10 }\n * ];\n * store.add('post', posts);\n * const results = store.filter('post', {\n * offset: PAGE_SIZE * (currentPage 1)\n * limit: PAGE_SIZE\n * });\n * console.log(results)\n *\n * @name query.limit\n * @type {number}\n * @see http://www.js-data.io/v3.0/docs/query-syntax\n * @since 3.0.0\n */\n if (utils.isNumber(query.limit)) {\n this.limit(query.limit)\n }\n } else if (utils.isFunction(query)) {\n this.data = this.data.filter(query, thisArg)\n }\n return this\n }\n\n /**\n * Iterate over all entities.\n *\n * @method Query#forEach\n * @param {Function} forEachFn Iteration function.\n * @param {*} [thisArg] Context to which to bind `forEachFn`.\n * @returns {Query} A reference to itself for chaining.\n * @since 3.0.0\n */\n forEach (forEachFn: Function, thisArg?) {\n this.getData().forEach(forEachFn, thisArg)\n return this\n }\n\n /**\n * Find the entity or entities that match the provided key.\n *\n * @example Get the entity whose primary key is 25.\n * const entities = query.get(25).run();\n *\n * @example Same as above.\n * const entities = query.get([25]).run();\n *\n * @example Get all users who are active and have the \"admin\" role.\n * const activeAdmins = query.get(['active', 'admin'], {\n * index: 'activityAndRoles'\n * }).run();\n *\n * @example Get all entities that match a certain weather condition.\n * const niceDays = query.get(['sunny', 'humid', 'calm'], {\n * index: 'weatherConditions'\n * }).run();\n *\n * @method Query#get\n * @param {array} keyList Key(s) defining the entity to retrieve. If\n * `keyList` is not an array (i.e. for a single-value key), it will be\n * wrapped in an array.\n * @param {object} [opts] Configuration options.\n * @param {string} [opts.string] Name of the secondary index to use in the\n * query. If no index is specified, the main index is used.\n * @returns {Query} A reference to itself for chaining.\n * @since 3.0.0\n */\n get (keyList = [], opts: any = {}) {\n if (this.data) {\n throw utils.err(`${DOMAIN}#get`)(500, INDEX_ERR)\n }\n if (keyList && !utils.isArray(keyList)) {\n keyList = [keyList]\n }\n if (!keyList.length) {\n this.getData()\n return this\n }\n this.data = this.collection.getIndex(opts.index).get(keyList)\n return this\n }\n\n /**\n * Find the entity or entities that match the provided keyLists.\n *\n * @example Get the posts where \"status\" is \"draft\" or \"inReview\".\n * const posts = query.getAll('draft', 'inReview', { index: 'status' }).run();\n *\n * @example Same as above.\n * const posts = query.getAll(['draft'], ['inReview'], { index: 'status' }).run();\n *\n * @method Query#getAll\n * @param {...Array} [keyList] Provide one or more keyLists, and all\n * entities matching each keyList will be retrieved. If no keyLists are\n * provided, all entities will be returned.\n * @param {object} [opts] Configuration options.\n * @param {string} [opts.index] Name of the secondary index to use in the\n * query. If no index is specified, the main index is used.\n * @returns {Query} A reference to itself for chaining.\n * @since 3.0.0\n */\n getAll(keyList?: [], opts?);\n getAll (...args) {\n let opts: any = {}\n if (this.data) {\n throw utils.err(`${DOMAIN}#getAll`)(500, INDEX_ERR)\n }\n if (!args.length || (args.length === 1 && utils.isObject(args[0]))) {\n this.getData()\n return this\n } else if (args.length && utils.isObject(args[args.length - 1])) {\n opts = args[args.length - 1]\n args.pop()\n }\n const index = this.collection.getIndex(opts.index)\n this.data = []\n args.forEach(keyList => {\n this.data = this.data.concat(index.get(keyList))\n })\n return this\n }\n\n /**\n * Return the current data result of this query.\n *\n * @method Query#getData\n * @returns {Array} The data in this query.\n * @since 3.0.0\n */\n getData () {\n if (!this.data) {\n this.data = this.collection.index.getAll()\n }\n return this.data\n }\n\n /**\n * Implementation used by the `like` operator. Takes a pattern and flags and\n * returns a `RegExp` instance that can test strings.\n *\n * @method Query#like\n * @param {string} pattern Testing pattern.\n * @param {string} flags Flags for the regular expression.\n * @returns {RegExp} Regular expression for testing strings.\n * @since 3.0.0\n */\n like (pattern, flags) {\n return new RegExp(\n `^${escape(pattern)\n .replace(percentRegExp, '.*')\n .replace(underscoreRegExp, '.')}$`,\n flags\n )\n }\n\n /**\n * Limit the result.\n *\n * @example Get only the first 2 posts.\n * const store = new JSData.DataStore();\n * store.defineMapper('post');\n * const posts = [\n * { author: 'John', age: 30, status: 'published', id: 1 },\n * { author: 'Sally', age: 31, status: 'draft', id: 2 },\n * { author: 'Mike', age: 32, status: 'draft', id: 3 },\n * { author: 'Adam', age: 33, status: 'deleted', id: 4 },\n * { author: 'Adam', age: 33, status: 'draft', id: 5 }\n * ];\n * store.add('post', posts);\n * const results = store.query('post').limit(2).run();\n * console.log(results);\n *\n * @method Query#limit\n * @param {number} num The maximum number of entities to keep in the result.\n * @returns {Query} A reference to itself for chaining.\n * @since 3.0.0\n */\n limit (num) {\n if (!utils.isNumber(num)) {\n throw utils.err(`${DOMAIN}#limit`, 'num')(400, 'number', num)\n }\n const data = this.getData()\n this.data = data.slice(0, Math.min(data.length, num))\n return this\n }\n\n /**\n * Apply a mapping function to the result data.\n *\n * @example\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('user');\n * const users = [\n * { name: 'Peter', age: 25, id: 1 },\n * { name: 'Jim', age: 19, id: 2 },\n * { name: 'Mike', age: 17, id: 3 },\n * { name: 'Alan', age: 29, id: 4 },\n * { name: 'Katie', age: 33, id: 5 }\n * ];\n * store.add('user', users);\n * const ages = store\n * .query('user')\n * .map(function (user) {\n * return user.age;\n * })\n * .run();\n * console.log(ages);\n *\n * @method Query#map\n * @param {Function} mapFn Mapping function.\n * @param {*} [thisArg] Context to which to bind `mapFn`.\n * @returns {Query} A reference to itself for chaining.\n * @since 3.0.0\n */\n map (mapFn, thisArg?) {\n this.data = this.getData().map(mapFn, thisArg)\n return this\n }\n\n /**\n * Return the result of calling the specified function on each item in this\n * collection's main index.\n *\n * @example\n * const stringAges = UserCollection.query().mapCall('toString').run();\n *\n * @method Query#mapCall\n * @param {string} funcName Name of function to call\n * @param args Remaining arguments to be passed to the function.\n * @returns {Query} A reference to itself for chaining.\n * @since 3.0.0\n */\n mapCall (funcName, ...args) {\n this.data = this.getData().map(item => item[funcName](...args))\n return this\n }\n\n /**\n * Complete the execution of the query and return the resulting data.\n *\n * @method Query#run\n * @returns {Array} The result of executing this query.\n * @since 3.0.0\n */\n run () {\n const data = this.data\n this.data = null\n return data\n }\n\n /**\n * Skip a number of results.\n *\n * @example Get all but the first 2 posts.\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post');\n * const posts = [\n * { author: 'John', age: 30, status: 'published', id: 1 },\n * { author: 'Sally', age: 31, status: 'draft', id: 2 },\n * { author: 'Mike', age: 32, status: 'draft', id: 3 },\n * { author: 'Adam', age: 33, status: 'deleted', id: 4 },\n * { author: 'Adam', age: 33, status: 'draft', id: 5 }\n * ];\n * store.add('post', posts);\n * const results = store.query('post').skip(2).run();\n * console.log(results);\n *\n * @method Query#skip\n * @param {number} num The number of entities to skip.\n * @returns {Query} A reference to itself for chaining.\n * @since 3.0.0\n */\n skip (num) {\n if (!utils.isNumber(num)) {\n throw utils.err(`${DOMAIN}#skip`, 'num')(400, 'number', num)\n }\n const data = this.getData()\n if (num < data.length) {\n this.data = data.slice(num)\n } else {\n this.data = []\n }\n return this\n }\n\n /**\n * The filtering operators supported by {@link Query#filter}, and which are\n * implemented by adapters (for the most part).\n *\n * @example Variant 1\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post');\n * const posts = [\n * { author: 'John', age: 30, status: 'published', id: 1 },\n * { author: 'Sally', age: 31, status: 'published', id: 2 },\n * { author: 'Mike', age: 32, status: 'published', id: 3 },\n * { author: 'Adam', age: 33, status: 'deleted', id: 4 },\n * { author: 'Adam', age: 33, status: 'published', id: 5 }\n * ];\n * store.add('post', posts);\n * const publishedPosts = store.filter('post', {\n * status: 'published',\n * limit: 2\n * });\n * console.log(publishedPosts);\n *\n *\n * @example Variant 2\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post')\n * const posts = [\n * { author: 'John', age: 30, status: 'published', id: 1 },\n * { author: 'Sally', age: 31, status: 'published', id: 2 },\n * { author: 'Mike', age: 32, status: 'published', id: 3 },\n * { author: 'Adam', age: 33, status: 'deleted', id: 4 },\n * { author: 'Adam', age: 33, status: 'published', id: 5 }\n * ];\n * store.add('post', posts);\n * const publishedPosts = store.filter('post', {\n * where: {\n * status: {\n * '==': 'published'\n * }\n * },\n * limit: 2\n * });\n * console.log(publishedPosts);\n *\n * @example Variant 3\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post');\n * const posts = [\n * { author: 'John', age: 30, status: 'published', id: 1 },\n * { author: 'Sally', age: 31, status: 'published', id: 2 },\n * { author: 'Mike', age: 32, status: 'published', id: 3 },\n * { author: 'Adam', age: 33, status: 'deleted', id: 4 },\n * { author: 'Adam', age: 33, status: 'published', id: 5 }\n * ];\n * store.add('post', posts);\n * const publishedPosts = store\n * .query('post')\n * .filter({ status: 'published' })\n * .limit(2)\n * .run();\n * console.log(publishedPosts);\n *\n * @example Variant 4\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post');\n * const posts = [\n * { author: 'John', age: 30, status: 'published', id: 1 },\n * { author: 'Sally', age: 31, status: 'published', id: 2 },\n * { author: 'Mike', age: 32, status: 'published', id: 3 },\n * { author: 'Adam', age: 33, status: 'deleted', id: 4 },\n * { author: 'Adam', age: 33, status: 'published', id: 5 }\n * ];\n * store.add('post', posts);\n * const publishedPosts = store\n * .query('post')\n * .filter({\n * where: {\n * status: {\n * '==': 'published'\n * }\n * }\n * })\n * .limit(2)\n * .run();\n * console.log(publishedPosts);\n *\n * @example Multiple operators\n * const JSData = require('js-data');\n * const { DataStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new DataStore();\n * store.defineMapper('post');\n * const posts = [\n * { author: 'John', age: 30, status: 'published', id: 1 },\n * { author: 'Sally', age: 31, status: 'published', id: 2 },\n * { author: 'Mike', age: 32, status: 'published', id: 3 },\n * { author: 'Adam', age: 33, status: 'deleted', id: 4 },\n * { author: 'Adam', age: 33, status: 'published', id: 5 }\n * ];\n * store.add('post', posts);\n *\n * const myPublishedPosts = store.filter('post', {\n * where: {\n * status: {\n * '==': 'published'\n * },\n * user_id: {\n * '==': currentUser.id\n * }\n * }\n * });\n *\n * console.log(myPublishedPosts);\n *\n * @name Query.ops\n * @property {Function} == Equality operator.\n * @property {Function} != Inequality operator.\n * @property {Function} > Greater than operator.\n * @property {Function} >= Greater than (inclusive) operator.\n * @property {Function} < Less than operator.\n * @property {Function} <= Less than (inclusive) operator.\n * @property {Function} isectEmpty Operator that asserts that the intersection\n * between two arrays is empty.\n * @property {Function} isectNotEmpty Operator that asserts that the\n * intersection between two arrays is __not__ empty.\n * @property {Function} in Operator that asserts whether a value is in an\n * array.\n * @property {Function} notIn Operator that asserts whether a value is __not__\n * in an array.\n * @property {Function} contains Operator that asserts whether an array\n * contains a value.\n * @property {Function} notContains Operator that asserts whether an array\n * does __not__ contain a value.\n * @since 3.0.0\n * @type {Object}\n */\n static ops = {\n '=' (value, predicate) {\n // tslint:disable-next-line:triple-equals\n return value == predicate; // eslint-disable-line\n },\n '==' (value, predicate) {\n // tslint:disable-next-line:triple-equals\n return value == predicate; // eslint-disable-line\n },\n '===' (value, predicate) {\n return value === predicate\n },\n '!=' (value, predicate) {\n // tslint:disable-next-line:triple-equals\n return value != predicate; // eslint-disable-line\n },\n '!==' (value, predicate) {\n return value !== predicate\n },\n '>' (value, predicate) {\n return value > predicate\n },\n '>=' (value, predicate) {\n return value >= predicate\n },\n '<' (value, predicate) {\n return value < predicate\n },\n '<=' (value, predicate) {\n return value <= predicate\n },\n isectEmpty (value, predicate) {\n return !utils.intersection(value || [], predicate || []).length\n },\n isectNotEmpty (value, predicate) {\n return utils.intersection(value || [], predicate || []).length\n },\n in (value, predicate) {\n return predicate.indexOf(value) !== -1\n },\n notIn (value, predicate) {\n return predicate.indexOf(value) === -1\n },\n contains (value, predicate) {\n return (value || []).indexOf(predicate) !== -1\n },\n notContains (value, predicate) {\n return (value || []).indexOf(predicate) === -1\n }\n };\n}\n","import utils from './utils'\n\n// TODO: remove this when the rest of the project is cleaned\nexport const belongsToType = 'belongsTo'\nexport const hasManyType = 'hasMany'\nexport const hasOneType = 'hasOne'\n\nconst DOMAIN = 'Relation'\n\nexport interface RelationOpts {\n type?: string\n}\n\nexport abstract class Relation {\n protected TYPE_NAME = DOMAIN;\n protected add;\n protected mapper;\n protected relation;\n name: string;\n private readonly localField;\n private readonly localKey;\n protected foreignKey;\n protected relatedMapper;\n protected inverse;\n\n constructor (relatedMapper, options: RelationOpts = {}) {\n options.type = (this.constructor as any).TYPE_NAME\n this.validateOptions(relatedMapper, options)\n\n if (typeof relatedMapper === 'object') {\n this.relatedMapper = relatedMapper\n }\n\n utils.fillIn(this, options)\n }\n\n get canAutoAddLinks () {\n return this.add === undefined || !!this.add\n }\n\n get relatedCollection () {\n return this.mapper.datastore.getCollection(this.relation)\n }\n\n validateOptions (related, opts) {\n const DOMAIN_ERR = `new ${DOMAIN}`\n\n const localField = opts.localField\n if (!localField) {\n throw utils.err(DOMAIN_ERR, 'opts.localField')(400, 'string', localField)\n }\n\n const foreignKey = (opts.foreignKey = opts.foreignKey || opts.localKey)\n if (!foreignKey && (opts.type === belongsToType || opts.type === hasOneType)) {\n throw utils.err(DOMAIN_ERR, 'opts.foreignKey')(400, 'string', foreignKey)\n }\n\n if (utils.isString(related)) {\n opts.relation = related\n if (!utils.isFunction(opts.getRelation)) {\n throw utils.err(DOMAIN_ERR, 'opts.getRelation')(400, 'function', opts.getRelation)\n }\n } else if (related) {\n opts.relation = related.name\n } else {\n throw utils.err(DOMAIN_ERR, 'related')(400, 'Mapper or string', related)\n }\n }\n\n assignTo (mapper) {\n this.name = mapper.name\n Object.defineProperty(this, 'mapper', { value: mapper })\n\n if (!mapper.relationList) Object.defineProperty(mapper, 'relationList', { value: [] })\n if (!mapper.relationFields) Object.defineProperty(mapper, 'relationFields', { value: [] })\n mapper.relationList.push(this)\n mapper.relationFields.push(this.localField)\n }\n\n canFindLinkFor (record?) {\n return !!(this.foreignKey || this.localKey)\n }\n\n getRelation () {\n return this.relatedMapper\n }\n\n getForeignKey (record) {\n return utils.get(record, this.mapper.idAttribute)\n }\n\n setForeignKey (record, relatedRecord) {\n if (!record || !relatedRecord) {\n return\n }\n\n this._setForeignKey(record, relatedRecord)\n }\n\n _setForeignKey (record, relatedRecords) {\n const idAttribute = this.mapper.idAttribute\n\n if (!utils.isArray(relatedRecords)) {\n relatedRecords = [relatedRecords]\n }\n\n relatedRecords.forEach(relatedRecord => {\n utils.set(relatedRecord, this.foreignKey, utils.get(record, idAttribute))\n })\n }\n\n getLocalField (record) {\n return utils.get(record, this.localField)\n }\n\n setLocalField (record, relatedData) {\n return utils.set(record, this.localField, relatedData)\n }\n\n getInverse (mapper) {\n if (!this.inverse) {\n this.findInverseRelation(mapper)\n }\n\n return this.inverse\n }\n\n findInverseRelation (mapper) {\n this.getRelation().relationList.forEach(def => {\n if (def.getRelation() === mapper && this.isInversedTo(def) && this !== def) {\n this.inverse = def\n return true\n }\n })\n }\n\n isInversedTo (def) {\n return !def.foreignKey || def.foreignKey === this.foreignKey\n }\n\n addLinkedRecords (records) {\n const datastore = this.mapper.datastore\n\n records.forEach(record => {\n let relatedData = this.getLocalField(record)\n\n if (utils.isFunction(this.add)) {\n relatedData = this.add(datastore, this, record)\n } else if (relatedData) {\n relatedData = this.linkRecord(record, relatedData)\n }\n\n const isEmptyLinks = !relatedData || (utils.isArray(relatedData) && !relatedData.length)\n\n if (isEmptyLinks && this.canFindLinkFor(record)) {\n relatedData = this.findExistingLinksFor(record)\n }\n\n if (relatedData) {\n this.setLocalField(record, relatedData)\n }\n })\n }\n\n removeLinkedRecords (relatedMapper, records) {\n const localField = this.localField\n records.forEach(record => {\n utils.set(record, localField, undefined)\n })\n }\n\n linkRecord (record, relatedRecord) {\n const relatedId = utils.get(relatedRecord, this.mapper.idAttribute)\n\n if (relatedId === undefined) {\n const unsaved = this.relatedCollection.unsaved()\n if (unsaved.indexOf(relatedRecord) === -1) {\n if (this.canAutoAddLinks) {\n relatedRecord = this.relatedCollection.add(relatedRecord)\n }\n }\n } else {\n if (relatedRecord !== this.relatedCollection.get(relatedId)) {\n this.setForeignKey(record, relatedRecord)\n\n if (this.canAutoAddLinks) {\n relatedRecord = this.relatedCollection.add(relatedRecord)\n }\n }\n }\n\n return relatedRecord\n }\n\n // e.g. user hasMany post via \"foreignKey\", so find all posts of user\n findExistingLinksByForeignKey (id) {\n if (id === undefined || id === null) {\n return\n }\n return this.relatedCollection.filter({\n [this.foreignKey]: id\n })\n }\n\n ensureLinkedDataHasProperType (props, opts) {\n const relatedMapper = this.getRelation()\n const relationData = this.getLocalField(props)\n\n if (utils.isArray(relationData) && (!relationData.length || relatedMapper.is(relationData[0]))) {\n return\n }\n\n if (relationData && !relatedMapper.is(relationData)) {\n utils.set(props, this.localField, relatedMapper.createRecord(relationData, opts))\n }\n }\n\n isRequiresParentId () {\n return false\n }\n\n isRequiresChildId () {\n return false\n }\n\n createChildRecord (props, relationData, opts) {\n this.setForeignKey(props, relationData)\n\n return this.createLinked(relationData, opts).then(result => {\n this.setLocalField(props, result)\n })\n }\n\n createLinked (props, opts) {\n const create = utils.isArray(props) ? 'createMany' : 'create'\n\n return this.getRelation()[create](props, opts)\n }\n\n abstract findExistingLinksFor(relatedMapper, record);\n abstract findExistingLinksFor(...record);\n\n static belongsTo;\n static hasMany;\n static hasOne;\n}\n","import utils, { safeSetLink } from './utils'\nimport Settable from './Settable'\nimport { hasManyType, hasOneType } from './Relation'\nimport Mapper from './Mapper'\n\nconst DOMAIN = 'Record'\n\nfunction superMethod (mapper, name) {\n const store = mapper.datastore\n if (store?.[name]) {\n return (...args) => store[name](mapper.name, ...args)\n }\n return mapper[name].bind(mapper)\n}\n\n// Cache these strings\nconst creatingPath = 'creating'\nconst noValidatePath = 'noValidate'\nconst keepChangeHistoryPath = 'keepChangeHistory'\nconst previousPath = 'previous'\n\n/**\n * js-data's Record class. An instance of `Record` corresponds to an in-memory\n * representation of a single row or document in a database, Firebase,\n * localstorage, etc. Basically, a `Record` instance represents whatever kind of\n * entity in your persistence layer that has a primary key.\n *\n * ```javascript\n * import {Record} from 'js-data'\n * ```\n *\n * @example Record#constructor\n * const JSData = require('js-data');\n * const { Record } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * // Instantiate a plain record\n * let record = new Record();\n * console.log('record: ' + JSON.stringify(record));\n *\n * // You can supply properties on instantiation\n * record = new Record({ name: 'John' });\n * console.log('record: ' + JSON.stringify(record));\n *\n * @example Record#constructor2\n * const JSData = require('js-data');\n * const { Mapper } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * // Instantiate a record that's associated with a Mapper:\n * const UserMapper = new Mapper({ name: 'user' });\n * const User = UserMapper.recordClass;\n * const user = UserMapper.createRecord({ name: 'John' });\n * const user2 = new User({ name: 'Sally' });\n * console.log('user: ' + JSON.stringify(user));\n * console.log('user2: ' + JSON.stringify(user2));\n *\n * @example Record#constructor3\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new Container();\n * store.defineMapper('user');\n *\n * // Instantiate a record that's associated with a store's Mapper\n * const user = store.createRecord('user', { name: 'John' });\n * console.log('user: ' + JSON.stringify(user));\n *\n * @example Record#constructor4\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new Container();\n * store.defineMapper('user', {\n * schema: {\n * properties: {\n * name: { type: 'string' }\n * }\n * }\n * });\n *\n * // Validate on instantiation\n * const user = store.createRecord('user', { name: 1234 });\n * console.log('user: ' + JSON.stringify(user));\n *\n * @example Record#constructor5\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new Container();\n * store.defineMapper('user', {\n * schema: {\n * properties: {\n * name: { type: 'string' }\n * }\n * }\n * });\n *\n * // Skip validation on instantiation\n * const user = store.createRecord('user', { name: 1234 }, { noValidate: true });\n * console.log('user: ' + JSON.stringify(user));\n * console.log('user.isValid(): ' + user.isValid());\n *\n * @class Record\n * @extends Settable\n * @param {object} [props] The initial properties of the new Record instance.\n * @param {object} [opts] Configuration options.\n * @param {boolean} [opts.noValidate=false] Whether to skip validation on the\n * initial properties.\n * @param {boolean} [opts.validateOnSet=true] Whether to enable setter\n * validation on properties after the Record has been initialized.\n * @since 3.0.0\n */\nexport default class Record extends Settable {\n static mapper: Mapper;\n\n constructor (props: any = {}, opts: any = {}) {\n super()\n const _set = this._set\n const mapper = (this.constructor as any).mapper\n\n _set(creatingPath, true)\n _set(noValidatePath, !!opts.noValidate)\n _set(\n keepChangeHistoryPath,\n opts.keepChangeHistory === undefined ? (mapper ? mapper.keepChangeHistory : true) : opts.keepChangeHistory\n )\n\n // Set the idAttribute value first, if it exists.\n const id = mapper ? utils.get(props, mapper.idAttribute) : undefined\n if (id !== undefined) {\n utils.set(this, mapper.idAttribute, id)\n }\n\n utils.fillIn(this, props)\n _set(creatingPath, false)\n if (opts.validateOnSet !== undefined) {\n _set(noValidatePath, !opts.validateOnSet)\n } else if (mapper?.validateOnSet !== undefined) {\n _set(noValidatePath, !mapper.validateOnSet)\n } else {\n _set(noValidatePath, false)\n }\n _set(previousPath, mapper ? mapper.toJSON(props) : utils.plainCopy(props))\n }\n\n /**\n * Returns the {@link Mapper} paired with this record's class, if any.\n *\n * @method Record#_mapper\n * @returns {Mapper} The {@link Mapper} paired with this record's class, if any.\n * @since 3.0.0\n */\n _mapper () {\n const mapper = (this.constructor as any).mapper\n if (!mapper) {\n throw utils.err(`${DOMAIN}#_mapper`, '')(404, 'mapper')\n }\n return mapper\n }\n\n /**\n * Lifecycle hook.\n *\n * @method Record#afterLoadRelations\n * @param {string[]} relations The `relations` argument passed to {@link Record#loadRelations}.\n * @param {object} opts The `opts` argument passed to {@link Record#loadRelations}.\n * @since 3.0.0\n */\n afterLoadRelations (relations: string[], opts?) {}\n\n /**\n * Lifecycle hook.\n *\n * @method Record#beforeLoadRelations\n * @param {string[]} relations The `relations` argument passed to {@link Record#loadRelations}.\n * @param {object} opts The `opts` argument passed to {@link Record#loadRelations}.\n * @since 3.0.0\n */\n beforeLoadRelations (relations: string[], opts?) {}\n\n /**\n * Return the change history of this record since it was instantiated or\n * {@link Record#commit} was called.\n *\n * @method Record#changeHistory\n * @since 3.0.0\n */\n changeHistory () {\n return (this._get('history') || []).slice()\n }\n\n /**\n * Return changes to this record since it was instantiated or\n * {@link Record#commit} was called.\n *\n * @example Record#changes\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new Container();\n * store.defineMapper('user');\n * const user = store.createRecord('user');\n * console.log('user changes: ' + JSON.stringify(user.changes()));\n * user.name = 'John';\n * console.log('user changes: ' + JSON.stringify(user.changes()));\n *\n * @method Record#changes\n * @param [opts] Configuration options.\n * @param {Function} [opts.equalsFn={@link utils.deepEqual}] Equality function.\n * @param {array} [opts.ignore=[]] Array of strings or RegExp of fields to ignore.\n * @returns {Object} Object describing the changes to this record since it was\n * instantiated or its {@link Record#commit} method was last called.\n * @since 3.0.0\n */\n changes (opts: any = {}) {\n return utils.diffObjects(typeof this.toJSON === 'function' ? this.toJSON(opts) : this, this._get('previous'), opts)\n }\n\n /**\n * Make the record's current in-memory state it's only state, with any\n * previous property values being set to current values.\n *\n * @example Record#commit\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new Container();\n * store.defineMapper('user');\n * const user = store.createRecord('user');\n * console.log('user hasChanges: ' + user.hasChanges());\n * user.name = 'John';\n * console.log('user hasChanges: ' + user.hasChanges());\n * user.commit();\n * console.log('user hasChanges: ' + user.hasChanges());\n *\n * @method Record#commit\n * @param {object} [opts] Configuration options. Passed to {@link Record#toJSON}.\n * @since 3.0.0\n */\n commit (opts?) {\n this._set('changed') // unset\n this._set('changing', false)\n this._set('history', []) // clear history\n this._set('previous', this.toJSON(opts))\n }\n\n /**\n * Call {@link Mapper#destroy} using this record's primary key.\n *\n * @example\n * import { Container } from 'js-data';\n * import { RethinkDBAdapter } from 'js-data-rethinkdb';\n *\n * const store = new Container();\n * store.registerAdapter('rethink', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('user');\n * store.find('user', 1234).then((user) => {\n * console.log(user.id); // 1234\n *\n * // Destroy this user from the database\n * return user.destroy();\n * });\n *\n * @method Record#destroy\n * @param {object} [opts] Configuration options passed to {@link Mapper#destroy}.\n * @returns {Promise} The result of calling {@link Mapper#destroy} with the\n * primary key of this record.\n * @since 3.0.0\n */\n destroy (opts: any = {}) {\n const mapper = this._mapper()\n return superMethod(mapper, 'destroy')(utils.get(this, mapper.idAttribute), opts)\n }\n\n /**\n * Return the value at the given path for this instance.\n *\n * @example Record#get\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n * const store = new Container();\n * store.defineMapper('user');\n *\n * const user = store.createRecord('user', { name: 'Bob' });\n * console.log('user.get(\"name\"): ' + user.get('name'));\n *\n * @method Record#get\n * @param {string} key Path of value to retrieve.\n * @returns {*} Value at path.\n * @since 3.0.0\n */\n get (key) {\n return utils.get(this, key)\n }\n\n /**\n * Return whether this record has changed since it was instantiated or\n * {@link Record#commit} was called.\n *\n * @example Record#hasChanges\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n * const store = new Container();\n * store.defineMapper('user');\n * const user = store.createRecord('user');\n * console.log('user hasChanges: ' + user.hasChanges());\n * user.name = 'John';\n * console.log('user hasChanges: ' + user.hasChanges());\n * user.commit();\n * console.log('user hasChanges: ' + user.hasChanges());\n *\n * @method Record#hasChanges\n * @param [opts] Configuration options.\n * @param {Function} [opts.equalsFn={@link utils.deepEqual}] Equality function.\n * @param {array} [opts.ignore=[]] Array of strings or RegExp of fields to ignore.\n * @returns {boolean} Return whether the record has changed since it was\n * instantiated or since its {@link Record#commit} method was called.\n * @since 3.0.0\n */\n hasChanges (opts?) {\n const quickHasChanges = !!(this._get('changed') || []).length\n return (\n quickHasChanges ||\n utils.areDifferent(typeof this.toJSON === 'function' ? this.toJSON(opts) : this, this._get('previous'), opts)\n )\n }\n\n /**\n * Return whether the record is unsaved. Records that have primary keys are\n * considered \"saved\". Records without primary keys are considered \"unsaved\".\n *\n * @example Record#isNew\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n * const store = new Container();\n * store.defineMapper('user');\n * const user = store.createRecord('user', {\n * id: 1234\n * });\n * const user2 = store.createRecord('user');\n * console.log('user isNew: ' + user.isNew()); // false\n * console.log('user2 isNew: ' + user2.isNew()); // true\n *\n * @method Record#isNew\n * @returns {boolean} Whether the record is unsaved.\n * @since 3.0.0\n */\n isNew (opts?) {\n return utils.get(this, this._mapper().idAttribute) === undefined\n }\n\n /**\n * Return whether the record in its current state passes validation.\n *\n * @example Record#isValid\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n * const store = new Container();\n * store.defineMapper('user', {\n * schema: {\n * properties: {\n * name: { type: 'string' }\n * }\n * }\n * });\n * const user = store.createRecord('user', {\n * name: 1234\n * }, {\n * noValidate: true // this allows us to put the record into an invalid state\n * });\n * console.log('user isValid: ' + user.isValid());\n * user.name = 'John';\n * console.log('user isValid: ' + user.isValid());\n *\n * @method Record#isValid\n * @param {object} [opts] Configuration options. Passed to {@link Mapper#validate}.\n * @returns {boolean} Whether the record in its current state passes\n * validation.\n * @since 3.0.0\n */\n isValid (opts) {\n return !this._mapper().validate(this, opts)\n }\n\n removeInverseRelation (currentParent, id, inverseDef, idAttribute) {\n if (inverseDef.type === hasOneType) {\n safeSetLink(currentParent, inverseDef.localField, undefined)\n } else if (inverseDef.type === hasManyType) {\n // e.g. remove comment from otherPost.comments\n const children = utils.get(currentParent, inverseDef.localField)\n if (id === undefined) {\n utils.remove(children, child => child === this)\n } else {\n utils.remove(children, child => child === this || id === utils.get(child, idAttribute))\n }\n }\n }\n\n setupInverseRelation (record, id, inverseDef, idAttribute) {\n // Update (set) inverse relation\n if (inverseDef.type === hasOneType) {\n // e.g. someUser.profile = profile\n safeSetLink(record, inverseDef.localField, this)\n } else if (inverseDef.type === hasManyType) {\n // e.g. add comment to somePost.comments\n const children = utils.get(record, inverseDef.localField)\n if (id === undefined) {\n utils.noDupeAdd(children, this, child => child === this)\n } else {\n utils.noDupeAdd(children, this, child => child === this || id === utils.get(child, idAttribute))\n }\n }\n }\n\n /**\n * Lazy load relations of this record, to be attached to the record once their\n * loaded.\n *\n * @example\n * import { Container } from 'js-data';\n * import { RethinkDBAdapter } from 'js-data-rethinkdb';\n *\n * const store = new Container();\n * store.registerAdapter('rethink', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('user', {\n * relations: {\n * hasMany: {\n * post: {\n * localField: 'posts',\n * foreignKey: 'user_id'\n * }\n * }\n * }\n * });\n * store.defineMapper('post', {\n * relations: {\n * belongsTo: {\n * user: {\n * localField: 'user',\n * foreignKey: 'user_id'\n * }\n * }\n * }\n * });\n * store.find('user', 1234).then((user) => {\n * console.log(user.id); // 1234\n *\n * // Load the user's post relations\n * return user.loadRelations(['post']);\n * }).then((user) => {\n * console.log(user.posts); // [{...}, {...}, ...]\n * });\n *\n * @method Record#loadRelations\n * @param {string[]} [relations] List of relations to load. Can use localField\n * names or Mapper names to pick relations.\n * @param {object} [opts] Configuration options.\n * @returns {Promise} Resolves with the record, with the loaded relations now\n * attached.\n * @since 3.0.0\n */\n loadRelations (relations: string[] | string | any = [], opts: any = {}) {\n let op\n const mapper = this._mapper()\n\n if (utils.isString(relations)) {\n relations = [relations]\n }\n opts.with = relations\n\n // Fill in \"opts\" with the Model's configuration\n utils._(opts, mapper)\n opts.adapter = mapper.getAdapterName(opts)\n\n // beforeLoadRelations lifecycle hook\n op = opts.op = 'beforeLoadRelations'\n return utils\n .resolve(this[op](relations, opts))\n .then(() => {\n // Now delegate to the adapter\n op = opts.op = 'loadRelations'\n mapper.dbg(op, this, relations, opts)\n const tasks = []\n let task\n utils.forEachRelation(mapper, opts, (def, optsCopy) => {\n const relatedMapper = def.getRelation()\n optsCopy.raw = false\n if (utils.isFunction(def.load)) {\n task = def.load(mapper, def, this, opts)\n } else if (def.type === 'hasMany' || def.type === 'hasOne') {\n if (def.foreignKey) {\n task = superMethod(relatedMapper, 'findAll')(\n {\n [def.foreignKey]: utils.get(this, mapper.idAttribute)\n },\n optsCopy\n ).then(relatedData =>\n def.type === 'hasOne' ? (relatedData.length ? relatedData[0] : undefined) : relatedData\n )\n } else if (def.localKeys) {\n task = superMethod(\n relatedMapper,\n 'findAll'\n )({\n where: {\n [relatedMapper.idAttribute]: {\n in: utils.get(this, def.localKeys)\n }\n }\n })\n } else if (def.foreignKeys) {\n task = superMethod(relatedMapper, 'findAll')(\n {\n where: {\n [def.foreignKeys]: {\n contains: utils.get(this, mapper.idAttribute)\n }\n }\n },\n opts\n )\n }\n } else if (def.type === 'belongsTo') {\n const key = utils.get(this, def.foreignKey)\n if (utils.isSorN(key)) {\n task = superMethod(relatedMapper, 'find')(key, optsCopy)\n }\n }\n if (task) {\n task = task.then(relatedData => {\n def.setLocalField(this, relatedData)\n })\n tasks.push(task)\n }\n })\n return Promise.all(tasks)\n })\n .then(() => {\n // afterLoadRelations lifecycle hook\n op = opts.op = 'afterLoadRelations'\n return utils.resolve(this[op](relations, opts)).then(() => this)\n })\n }\n\n /**\n * Return the properties with which this record was instantiated.\n *\n * @example Record#previous\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n * const store = new Container();\n * store.defineMapper('user');\n * const user = store.createRecord('user', {\n * name: 'William'\n * });\n * console.log('user previous: ' + JSON.stringify(user.previous()));\n * user.name = 'Bob';\n * console.log('user previous: ' + JSON.stringify(user.previous()));\n * user.commit();\n * console.log('user previous: ' + JSON.stringify(user.previous()));\n *\n * @method Record#previous\n * @param {string} [key] If specified, return just the initial value of the\n * given key.\n * @returns {Object} The initial properties of this record.\n * @since 3.0.0\n */\n previous (key) {\n if (key) {\n return this._get(`previous.${key}`)\n }\n return this._get('previous')\n }\n\n /**\n * Revert changes to this record back to the properties it had when it was\n * instantiated.\n *\n * @example Record#revert\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n * const store = new Container();\n * store.defineMapper('user');\n * const user = store.createRecord('user', {\n * name: 'William'\n * });\n * console.log('user: ' + JSON.stringify(user));\n * user.name = 'Bob';\n * console.log('user: ' + JSON.stringify(user));\n * user.revert();\n * console.log('user: ' + JSON.stringify(user));\n *\n * @method Record#revert\n * @param {object} [opts] Configuration options.\n * @param {string[]} [opts.preserve] Array of strings or Regular Expressions\n * denoting properties that should not be reverted.\n * @since 3.0.0\n */\n revert (opts: any = {}) {\n const previous = this._get('previous')\n opts.preserve = opts.preserve || []\n utils.forOwn(this, (value, key) => {\n if (\n key !== this._mapper().idAttribute &&\n !previous.hasOwnProperty(key) &&\n this.hasOwnProperty(key) &&\n opts.preserve.indexOf(key) === -1\n ) {\n delete this[key]\n }\n })\n utils.forOwn(previous, (value, key) => {\n if (opts.preserve.indexOf(key) === -1) {\n this[key] = value\n }\n })\n this.commit()\n }\n\n /**\n * Delegates to {@link Mapper#create} or {@link Mapper#update}.\n *\n * @example\n * import { Container } from 'js-data';\n * import { RethinkDBAdapter } from 'js-data-rethinkdb';\n *\n * const store = new Container();\n * store.registerAdapter('rethink', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('session');\n * const session = store.createRecord('session', { topic: 'Node.js' });\n *\n * // Create a new record in the database\n * session.save().then(() => {\n * console.log(session.id); // 1234\n *\n * session.skill_level = 'beginner';\n *\n * // Update the record in the database\n * return session.save();\n * });\n *\n * @method Record#save\n * @param {object} [opts] Configuration options. See {@link Mapper#create} and\n * {@link Mapper#update}.\n * @param {boolean} [opts.changesOnly] Equality function. Default uses `===`.\n * @param {Function} [opts.equalsFn] Passed to {@link Record#changes} when\n * `opts.changesOnly` is `true`.\n * @param {array} [opts.ignore] Passed to {@link Record#changes} when\n * `opts.changesOnly` is `true`.\n * @returns {Promise} The result of calling {@link Mapper#create} or\n * {@link Mapper#update}.\n * @since 3.0.0\n */\n save (opts: any = {}) {\n const mapper = this._mapper()\n const id = utils.get(this, mapper.idAttribute)\n let props: any = this\n\n const postProcess = result => {\n const record = opts.raw ? result.data : result\n if (record) {\n utils.deepMixIn(this, record)\n this.commit()\n }\n return result\n }\n\n if (id === undefined) {\n return superMethod(mapper, 'create')(props, opts).then(postProcess)\n }\n if (opts.changesOnly) {\n const changes = this.changes(opts)\n props = {}\n utils.fillIn(props, changes.added)\n utils.fillIn(props, changes.changed)\n }\n return superMethod(mapper, 'update')(id, props, opts).then(postProcess)\n }\n\n /**\n * Set the value for a given key, or the values for the given keys if \"key\" is\n * an object. Triggers change events on those properties that have `track: true`\n * in {@link Mapper#schema}.\n *\n * @example Record#set\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n * const store = new Container();\n * store.defineMapper('user');\n *\n * const user = store.createRecord('user');\n * console.log('user: ' + JSON.stringify(user));\n *\n * user.set('name', 'Bob');\n * console.log('user: ' + JSON.stringify(user));\n *\n * user.set({ age: 30, role: 'admin' });\n * console.log('user: ' + JSON.stringify(user));\n *\n * @fires Record#change\n * @method Record#set\n * @param {(string|Object)} key Key to set or hash of key-value pairs to set.\n * @param {*} [value] Value to set for the given key.\n * @param {object} [opts] Configuration options.\n * @param {boolean} [opts.silent=false] Whether to trigger change events.\n * @since 3.0.0\n */\n set (key: string | any, value?, opts?) {\n if (utils.isObject(key)) {\n opts = value\n }\n opts = opts || {}\n if (opts.silent) {\n this._set('silent', true)\n }\n utils.set(this, key, value)\n if (!this._get('eventId')) {\n this._set('silent') // unset\n }\n }\n\n /**\n * Return a plain object representation of this record. If the class from\n * which this record was created has a Mapper, then {@link Mapper#toJSON} will\n * be called with this record instead.\n *\n * @example Record#toJSON\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n * const store = new Container();\n * store.defineMapper('user', {\n * schema: {\n * properties: {\n * name: { type: 'string' }\n * }\n * }\n * });\n *\n * const user = store.createRecord('user', {\n * name: 'John',\n * $$hashKey: '1234'\n * });\n * console.log('user: ' + JSON.stringify(user.toJSON()));\n *\n * @method Record#toJSON\n * @param {object} [opts] Configuration options.\n * @param {string[]} [opts.with] Array of relation names or relation fields\n * to include in the representation. Only available as an option if the class\n * from which this record was created has a Mapper and this record resides in\n * an instance of {@link DataStore}.\n * @returns {Object} Plain object representation of this record.\n * @since 3.0.0\n */\n toJSON (opts?) {\n const mapper = (this.constructor as typeof Record).mapper\n if (mapper) {\n return mapper.toJSON(this, opts)\n } else {\n const json = {}\n utils.forOwn(this, (prop, key) => {\n json[key] = utils.plainCopy(prop)\n })\n return json\n }\n }\n\n /**\n * Unset the value for a given key. Triggers change events on those properties\n * that have `track: true` in {@link Mapper#schema}.\n *\n * @example Record#unset\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n * const store = new Container();\n * store.defineMapper('user');\n *\n * const user = store.createRecord('user', {\n * name: 'John'\n * });\n * console.log('user: ' + JSON.stringify(user));\n *\n * user.unset('name');\n * console.log('user: ' + JSON.stringify(user));\n *\n * @method Record#unset\n * @param {string} key Key to unset.\n * @param {object} [opts] Configuration options.\n * @param {boolean} [opts.silent=false] Whether to trigger change events.\n * @since 3.0.0\n */\n unset (key: string, opts?) {\n this.set(key, undefined, opts)\n }\n\n /**\n * Validate this record based on its current properties.\n *\n * @example Record#validate\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n * const store = new Container();\n * store.defineMapper('user', {\n * schema: {\n * properties: {\n * name: { type: 'string' }\n * }\n * }\n * });\n * const user = store.createRecord('user', {\n * name: 1234\n * }, {\n * noValidate: true // this allows us to put the record into an invalid state\n * });\n * console.log('user validation: ' + JSON.stringify(user.validate()));\n * user.name = 'John';\n * console.log('user validation: ' + user.validate());\n *\n * @method Record#validate\n * @param {object} [opts] Configuration options. Passed to {@link Mapper#validate}.\n * @returns {*} Array of errors or `undefined` if no errors.\n * @since 3.0.0\n */\n validate (opts) {\n return this._mapper().validate(this, opts)\n }\n\n static creatingPath = creatingPath;\n static noValidatePath = noValidatePath;\n static keepChangeHistoryPath = keepChangeHistoryPath;\n static previousPath = previousPath;\n}\n\n/**\n * Allow records to emit events.\n *\n * An record's registered listeners are stored in the record's private data.\n */\nutils.eventify(\n Record.prototype,\n function () {\n return this._get('events')\n },\n function (value) {\n this._set('events', value)\n }\n)\n\n/**\n * Fired when a record changes. Only works for records that have tracked fields.\n * See {@link Record~changeListener} on how to listen for this event.\n *\n * @event Record#change\n * @see Record~changeListener\n */\n\n/**\n * Callback signature for the {@link Record#event:change} event.\n *\n * @example\n * function onChange (record, changes) {\n * // do something\n * }\n * record.on('change', onChange);\n *\n * @callback Record~changeListener\n * @param {Record} The Record that changed.\n * @param {object} The changes.\n * @see Record#event:change\n * @since 3.0.0\n */\n\n/**\n * Create a subclass of this Record:\n * @example Record.extend\n * const JSData = require('js-data');\n * const { Record } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * // Extend the class using ES2015 class syntax.\n * class CustomRecordClass extends Record {\n * foo () { return 'bar'; }\n * static beep () { return 'boop'; }\n * }\n * const customRecord = new CustomRecordClass();\n * console.log(customRecord.foo());\n * console.log(CustomRecordClass.beep());\n *\n * // Extend the class using alternate method.\n * const OtherRecordClass = Record.extend({\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * });\n * const otherRecord = new OtherRecordClass();\n * console.log(otherRecord.foo());\n * console.log(OtherRecordClass.beep());\n *\n * // Extend the class, providing a custom constructor.\n * function AnotherRecordClass () {\n * Record.call(this);\n * this.created_at = new Date().getTime();\n * }\n * Record.extend({\n * constructor: AnotherRecordClass,\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * });\n * const anotherRecord = new AnotherRecordClass();\n * console.log(anotherRecord.created_at);\n * console.log(anotherRecord.foo());\n * console.log(AnotherRecordClass.beep());\n *\n * @method Record.extend\n * @param {object} [props={}] Properties to add to the prototype of the\n * subclass.\n * @param {object} [props.constructor] Provide a custom constructor function\n * to be used as the subclass itself.\n * @param {object} [classProps={}] Static properties to add to the subclass.\n * @returns {Constructor} Subclass of this Record class.\n * @since 3.0.0\n */\n","export function sort (a, b, hashCode) {\n // Short-circuit comparison if a and b are strictly equal\n // This is absolutely necessary for indexed objects that\n // don't have the idAttribute field\n if (a === b) {\n return 0\n } else if (hashCode) {\n a = hashCode(a)\n b = hashCode(b)\n }\n return (a === null && b === null) || (a === undefined && b === undefined)\n ? -1\n : a === null || a === undefined\n ? -1\n : b === null || b === undefined\n ? 1\n : a < b\n ? -1\n : a > b\n ? 1\n : 0\n}\n\nexport function insertAt (array, index, value) {\n array.splice(index, 0, value)\n return array\n}\n\nexport function removeAt (array, index) {\n array.splice(index, 1)\n return array\n}\n\nexport function binarySearch (array, value, field?) {\n let lo = 0\n let hi = array.length\n let compared\n let mid\n\n while (lo < hi) {\n // tslint:disable-next-line:no-bitwise\n mid = ((lo + hi) / 2) | 0\n compared = sort(value, array[mid], field)\n if (compared === 0) {\n return {\n found: true,\n index: mid\n }\n } else if (compared < 0) {\n hi = mid\n } else {\n lo = mid + 1\n }\n }\n\n return {\n found: false,\n index: hi\n }\n}\n","// Copyright (c) 2015, InternalFX.\n\n// Permission to use, copy, modify, and/or distribute this software for any purpose with or\n// without fee is hereby granted, provided that the above copyright notice and this permission\n// notice appear in all copies.\n\n// THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO\n// THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT\n// SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR\n// ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION\n// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE\n// USE OR PERFORMANCE OF THIS SOFTWARE.\n\n// Modifications\n// Copyright 2015-2016 Jason Dobry\n//\n// Summary of modifications:\n// Reworked dependencies so as to re-use code already in js-data\n// Removed unused code\nimport utils from '../../src/utils'\nimport { binarySearch, insertAt, removeAt } from './_utils'\n\nexport interface IndexOpts {\n fieldGetter?\n hashCode?\n}\n\nexport default class Index {\n fieldList: any[];\n fieldGetter: any;\n hashCode: any;\n isIndex: boolean;\n keys: any[];\n values: any[];\n\n constructor (fieldList = [], opts: IndexOpts = {}) {\n if (!utils.isArray(fieldList)) {\n throw new Error('fieldList must be an array.')\n }\n\n this.fieldList = fieldList\n this.fieldGetter = opts.fieldGetter\n this.hashCode = opts.hashCode\n this.isIndex = true\n this.keys = []\n this.values = []\n }\n\n set (keyList, value) {\n if (!utils.isArray(keyList)) {\n keyList = [keyList]\n }\n\n const key = keyList.shift() || undefined\n const pos = binarySearch(this.keys, key)\n\n if (keyList.length === 0) {\n if (pos.found) {\n const dataLocation = binarySearch(this.values[pos.index], value, this.hashCode)\n if (!dataLocation.found) {\n insertAt(this.values[pos.index], dataLocation.index, value)\n }\n } else {\n insertAt(this.keys, pos.index, key)\n insertAt(this.values, pos.index, [value])\n }\n } else {\n if (pos.found) {\n this.values[pos.index].set(keyList, value)\n } else {\n insertAt(this.keys, pos.index, key)\n const newIndex = new Index([], { hashCode: this.hashCode })\n newIndex.set(keyList, value)\n insertAt(this.values, pos.index, newIndex)\n }\n }\n }\n\n get (keyList?) {\n if (!utils.isArray(keyList)) {\n keyList = [keyList]\n }\n\n const key = keyList.shift() || undefined\n const pos = binarySearch(this.keys, key)\n\n if (keyList.length === 0) {\n if (pos.found) {\n if (this.values[pos.index].isIndex) {\n return this.values[pos.index].getAll()\n } else {\n return this.values[pos.index].slice()\n }\n } else {\n return []\n }\n } else {\n if (pos.found) {\n return this.values[pos.index].get(keyList)\n } else {\n return []\n }\n }\n }\n\n getAll (opts: any = {}) {\n let results = []\n const values = this.values\n if (opts.order === 'desc') {\n for (let i = values.length - 1; i >= 0; i--) {\n const value = values[i]\n if (value.isIndex) {\n results = results.concat(value.getAll(opts))\n } else {\n results = results.concat(value)\n }\n }\n } else {\n for (const value of values) {\n if (value.isIndex) {\n results = results.concat(value.getAll(opts))\n } else {\n results = results.concat(value)\n }\n }\n }\n return results\n }\n\n visitAll (cb, thisArg?) {\n this.values.forEach(value => {\n if (value.isIndex) {\n value.visitAll(cb, thisArg)\n } else {\n value.forEach(cb, thisArg)\n }\n })\n }\n\n between (leftKeys, rightKeys, opts: any = {}) {\n if (!utils.isArray(leftKeys)) {\n leftKeys = [leftKeys]\n }\n if (!utils.isArray(rightKeys)) {\n rightKeys = [rightKeys]\n }\n utils.fillIn(opts, {\n leftInclusive: true,\n rightInclusive: false,\n limit: undefined,\n offset: 0\n })\n\n const results = this._between(leftKeys, rightKeys, opts)\n\n if (opts.limit) {\n return results.slice(opts.offset, opts.limit + opts.offset)\n } else {\n return results.slice(opts.offset)\n }\n }\n\n _between (leftKeys, rightKeys, opts) {\n let results = []\n\n const leftKey = leftKeys.shift()\n const rightKey = rightKeys.shift()\n\n let pos\n\n if (leftKey !== undefined) {\n pos = binarySearch(this.keys, leftKey)\n } else {\n pos = {\n found: false,\n index: 0\n }\n }\n\n if (leftKeys.length === 0) {\n if (pos.found && opts.leftInclusive === false) {\n pos.index += 1\n }\n\n for (let i = pos.index; i < this.keys.length; i += 1) {\n if (rightKey !== undefined) {\n if (opts.rightInclusive) {\n if (this.keys[i] > rightKey) {\n break\n }\n } else {\n if (this.keys[i] >= rightKey) {\n break\n }\n }\n }\n\n if (this.values[i].isIndex) {\n results = results.concat(this.values[i].getAll())\n } else {\n results = results.concat(this.values[i])\n }\n\n if (opts.limit) {\n if (results.length >= opts.limit + opts.offset) {\n break\n }\n }\n }\n } else {\n for (let i = pos.index; i < this.keys.length; i += 1) {\n const currKey = this.keys[i]\n if (currKey > rightKey) {\n break\n }\n\n if (this.values[i].isIndex) {\n if (currKey === leftKey) {\n results = results.concat(\n this.values[i]._between(\n utils.copy(leftKeys),\n rightKeys.map(() => undefined),\n opts\n )\n )\n } else if (currKey === rightKey) {\n results = results.concat(\n this.values[i]._between(\n leftKeys.map(() => undefined),\n utils.copy(rightKeys),\n opts\n )\n )\n } else {\n results = results.concat(this.values[i].getAll())\n }\n } else {\n results = results.concat(this.values[i])\n }\n\n if (opts.limit) {\n if (results.length >= opts.limit + opts.offset) {\n break\n }\n }\n }\n }\n\n if (opts.limit) {\n return results.slice(0, opts.limit + opts.offset)\n } else {\n return results\n }\n }\n\n peek () {\n return this.values.length ? (this.values[0].isIndex ? this.values[0].peek() : this.values[0]) : []\n }\n\n clear () {\n this.keys = []\n this.values = []\n }\n\n insertRecord (data) {\n const keyList = this.fieldList.map(field =>\n utils.isFunction(field) ? field(data) || undefined : data[field] || undefined\n )\n this.set(keyList, data)\n }\n\n removeRecord (data) {\n let removed\n const isUnique = this.hashCode(data) !== undefined\n this.values.forEach((value, i) => {\n if (value.isIndex) {\n if (value.removeRecord(data)) {\n if (value.keys.length === 0) {\n removeAt(this.keys, i)\n removeAt(this.values, i)\n }\n removed = true\n return false\n }\n } else {\n let dataLocation: any = {}\n if (this.keys[i] === undefined || !isUnique) {\n for (let j = value.length - 1; j >= 0; j--) {\n if (value[j] === data) {\n dataLocation = {\n found: true,\n index: j\n }\n break\n }\n }\n } else if (isUnique) {\n dataLocation = binarySearch(value, data, this.hashCode)\n }\n if (dataLocation.found) {\n removeAt(value, dataLocation.index)\n if (value.length === 0) {\n removeAt(this.keys, i)\n removeAt(this.values, i)\n }\n removed = true\n return false\n }\n }\n })\n return removed ? data : undefined\n }\n\n updateRecord (data) {\n const removed = this.removeRecord(data)\n if (removed !== undefined) {\n this.insertRecord(data)\n }\n }\n}\n","import utils from './utils'\nimport Component, { ComponentOpts } from './Component'\nimport Query from './Query'\nimport Record from './Record'\nimport Index from './mindex'\n\nconst { noValidatePath } = Record\n\nconst DOMAIN = 'Collection'\n\nexport interface CollectionOpts extends ComponentOpts {\n /**\n * Whether to call {@link Record#commit} on records that are added to the\n * collection and already exist in the collection.\n *\n * @name Collection#commitOnMerge\n * @type {boolean}\n * @default true\n */\n commitOnMerge?: boolean\n\n /**\n * Whether record events should bubble up and be emitted by the collection.\n *\n * @name Collection#emitRecordEvents\n * @type {boolean}\n * @default true\n */\n emitRecordEvents?: boolean\n\n /**\n * Field to be used as the unique identifier for records in this collection.\n * Defaults to `\"id\"` unless {@link Collection#mapper} is set, in which case\n * this will default to {@link Mapper#idAttribute}.\n *\n * @name Collection#idAttribute\n * @type {string}\n * @default \"id\"\n */\n idAttribute?: string\n\n /**\n * What to do when inserting a record into this Collection that shares a\n * primary key with a record already in this Collection.\n *\n * Possible values:\n * merge\n * replace\n * skip\n *\n * Merge:\n *\n * Recursively shallow copy properties from the new record onto the existing\n * record.\n *\n * Replace:\n *\n * Shallow copy top-level properties from the new record onto the existing\n * record. Any top-level own properties of the existing record that are _not_\n * on the new record will be removed.\n *\n * Skip:\n *\n * Ignore new record, keep existing record.\n *\n * @default \"merge\"\n */\n onConflict?: 'merge' | 'replace' | 'skip'\n}\n\nconst COLLECTION_DEFAULTS: CollectionOpts = {\n commitOnMerge: true,\n emitRecordEvents: true,\n idAttribute: 'id',\n onConflict: 'merge'\n}\n\n/**\n * An ordered set of {@link Record} instances.\n *\n * @example Collection#constructor\n * // import { Collection, Record } from 'js-data';\n * const JSData = require('js-data');\n * const {Collection, Record} = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const user1 = new Record({ id: 1 });\n * const user2 = new Record({ id: 2 });\n * const UserCollection = new Collection([user1, user2]);\n * console.log(UserCollection.get(1) === user1);\n *\n * @class Collection\n * @extends Component\n * @param {array} [records] Initial set of records to insert into the\n * collection.\n * @param {object} [opts] Configuration options.\n * @param {string} [opts.commitOnMerge] See {@link Collection#commitOnMerge}.\n * @param {string} [opts.idAttribute] See {@link Collection#idAttribute}.\n * @param {string} [opts.onConflict=\"merge\"] See {@link Collection#onConflict}.\n * @param {string} [opts.mapper] See {@link Collection#mapper}.\n * @since 3.0.0\n */\nexport default class Collection extends Component {\n queryClass\n emitRecordEvents: any\n onConflict: string\n /**\n * Default Mapper for this collection. Optional. If a Mapper is provided, then\n * the collection will use the {@link Mapper#idAttribute} setting, and will\n * wrap records in {@link Mapper#recordClass}.\n *\n * @example Collection#mapper\n * const JSData = require('js-data');\n * const {Collection, Mapper} = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * class MyMapperClass extends Mapper {\n * foo () { return 'bar'; }\n * }\n * const myMapper = new MyMapperClass({ name: 'myMapper' });\n * const collection = new Collection(null, { mapper: myMapper });\n *\n * @name Collection#mapper\n * @type {Mapper}\n * @default null\n * @since 3.0.0\n */\n mapper: any\n /**\n * The main index, which uses @{link Collection#recordId} as the key.\n *\n * @name Collection#index\n * @type {Index}\n */\n index: Index\n /**\n * Object that holds the secondary indexes of this collection.\n *\n * @name Collection#indexes\n * @type {Object.}\n */\n indexes: { [key: string]: Index } = {}\n idAttribute: any\n _added = {}\n emit: any\n\n constructor (records: any = {}, opts: CollectionOpts | string | any = {}) {\n super(opts)\n\n if (records && !utils.isArray(records)) {\n opts = records\n records = []\n }\n if (utils.isString(opts)) {\n opts = { idAttribute: opts }\n }\n\n // Apply user-provided configuration\n utils.fillIn(this, opts)\n // Fill in any missing options with the defaults\n utils.fillIn(this, utils.copy(COLLECTION_DEFAULTS))\n\n if (!this.queryClass) {\n this.queryClass = Query\n }\n\n const idAttribute = this.recordId()\n\n this.index = new Index([idAttribute], {\n hashCode (obj) {\n return utils.get(obj, idAttribute)\n }\n })\n\n // Insert initial data into the collection\n if (utils.isObject(records) || (utils.isArray(records) && records.length)) {\n this.add(records)\n }\n }\n\n /**\n * Used to bind to events emitted by records in this Collection.\n *\n * @method Collection#_onRecordEvent\n * @since 3.0.0\n * @private\n * @param {...*} [args] Args passed to {@link Collection#emit}.\n */\n _onRecordEvent (...args) {\n if (this.emitRecordEvents) {\n this.emit(...args)\n }\n }\n\n /**\n * Insert the provided record or records.\n *\n * If a record is already in the collection then the provided record will\n * either merge with or replace the existing record based on the value of the\n * `onConflict` option.\n *\n * The collection's secondary indexes will be updated as each record is\n * visited.\n *\n * @method Collection#add\n * @since 3.0.0\n * @param {(Object|Object[]|Record|Record[])} records The record or records to insert.\n * @param {object} [opts] Configuration options.\n * @param {boolean} [opts.commitOnMerge=true] See {@link Collection#commitOnMerge}.\n * @param {boolean} [opts.noValidate] See {@link Record#noValidate}.\n * @param {string} [opts.onConflict] See {@link Collection#onConflict}.\n * @returns {(Object|Object[]|Record|Record[])} The added record or records.\n */\n add (records, opts: any = {}) {\n // Fill in \"opts\" with the Collection's configuration\n utils._(opts, this)\n records = this.beforeAdd(records, opts) || records\n\n // Track whether just one record or an array of records is being inserted\n let singular = false\n const idAttribute = this.recordId()\n if (!utils.isArray(records)) {\n if (utils.isObject(records)) {\n records = [records]\n singular = true\n } else {\n throw utils.err(`${DOMAIN}#add`, 'records')(\n 400,\n 'object or array',\n records\n )\n }\n }\n\n // Map the provided records to existing records.\n // New records will be inserted. If any records map to existing records,\n // they will be merged into the existing records according to the onConflict\n // option.\n records = records.map(record => {\n const id = this.recordId(record)\n // Grab existing record if there is one\n const existing = id === undefined ? id : this.get(id)\n // If the currently visited record is just a reference to an existing\n // record, then there is nothing to be done. Exit early.\n if (record === existing) {\n return existing\n }\n\n if (existing) {\n // Here, the currently visited record corresponds to a record already\n // in the collection, so we need to merge them\n const onConflict = opts.onConflict || this.onConflict\n if (\n onConflict !== 'merge' &&\n onConflict !== 'replace' &&\n onConflict !== 'skip'\n ) {\n throw utils.err(`${DOMAIN}#add`, 'opts.onConflict')(\n 400,\n 'one of (merge, replace, skip)',\n onConflict,\n true\n )\n }\n const existingNoValidate = existing._get(noValidatePath)\n if (opts.noValidate) {\n // Disable validation\n existing._set(noValidatePath, true)\n }\n if (onConflict === 'merge') {\n utils.deepMixIn(existing, record)\n } else if (onConflict === 'replace') {\n utils.forOwn(existing, (value, key) => {\n if (key !== idAttribute && record[key] === undefined) {\n existing[key] = undefined\n }\n })\n existing.set(record)\n } // else if(onConflict === 'skip'){ do nothing }\n\n if (opts.noValidate) {\n // Restore previous `noValidate` value\n existing._set(noValidatePath, existingNoValidate)\n }\n record = existing\n if (opts.commitOnMerge && utils.isFunction(record.commit)) {\n record.commit()\n }\n // Update all indexes in the collection\n this.updateIndexes(record)\n } else {\n // Here, the currently visited record does not correspond to any record\n // in the collection, so (optionally) instantiate this record and insert\n // it into the collection\n record = this.mapper ? this.mapper.createRecord(record, opts) : record\n this.index.insertRecord(record)\n utils.forOwn(this.indexes, (index, name) => {\n index.insertRecord(record)\n })\n if (record && utils.isFunction(record.on)) {\n record.on('all', this._onRecordEvent, this)\n }\n }\n return record\n })\n // Finally, return the inserted data\n const result = singular ? records[0] : records\n if (!opts.silent) {\n this.emit('add', result)\n }\n return this.afterAdd(records, opts, result) || result\n }\n\n /**\n * Lifecycle hook called by {@link Collection#add}. If this method returns a\n * value then {@link Collection#add} will return that same value.\n *\n * @method Collection#method\n * @since 3.0.0\n * @param {(Object|Object[]|Record|Record[])} record The record or records\n * that were added to this Collection by {@link Collection#add}.\n * @param {object} opts The `opts` argument passed to {@link Collection#add}.\n * @param result\n */\n afterAdd (record, opts, result) {\n return null\n }\n\n /**\n * Lifecycle hook called by {@link Collection#remove}. If this method returns\n * a value then {@link Collection#remove} will return that same value.\n *\n * @method Collection#afterRemove\n * @since 3.0.0\n * @param {(string|number)} id The `id` argument passed to {@link Collection#remove}.\n * @param {object} opts The `opts` argument passed to {@link Collection#remove}.\n * @param {object} record The result that will be returned by {@link Collection#remove}.\n */\n afterRemove (id, opts, record) {\n return null\n }\n\n /**\n * Lifecycle hook called by {@link Collection#removeAll}. If this method\n * returns a value then {@link Collection#removeAll} will return that same\n * value.\n *\n * @method Collection#afterRemoveAll\n * @since 3.0.0\n * @param {object} query The `query` argument passed to {@link Collection#removeAll}.\n * @param {object} opts The `opts` argument passed to {@link Collection#removeAll}.\n * @param {object} records The result that will be returned by {@link Collection#removeAll}.\n */\n afterRemoveAll (query, opts, records) {\n return null\n }\n\n /**\n * Lifecycle hook called by {@link Collection#add}. If this method returns a\n * value then the `records` argument in {@link Collection#add} will be\n * re-assigned to the returned value.\n *\n * @method Collection#beforeAdd\n * @since 3.0.0\n * @param {(Object|Object[]|Record|Record[])} records The `records` argument passed to {@link Collection#add}.\n * @param {object} opts The `opts` argument passed to {@link Collection#add}.\n */\n beforeAdd (records, opts) {\n return null\n }\n\n /**\n * Lifecycle hook called by {@link Collection#remove}.\n *\n * @method Collection#beforeRemove\n * @since 3.0.0\n * @param {(string|number)} id The `id` argument passed to {@link Collection#remove}.\n * @param {object} opts The `opts` argument passed to {@link Collection#remove}.\n */\n beforeRemove (id, opts) {\n return null\n }\n\n /**\n * Lifecycle hook called by {@link Collection#removeAll}.\n *\n * @method Collection#beforeRemoveAll\n * @since 3.0.0\n * @param {object} query The `query` argument passed to {@link Collection#removeAll}.\n * @param {object} opts The `opts` argument passed to {@link Collection#removeAll}.\n */\n beforeRemoveAll (query, opts) {\n return null\n }\n\n /**\n * Find all records between two boundaries.\n *\n * Shortcut for `collection.query().between(18, 30, { index: 'age' }).run()`\n *\n * @example\n * // Get all users ages 18 to 30\n * const users = collection.between(18, 30, { index: 'age' });\n *\n * @example\n * // Same as above\n * const users = collection.between([18], [30], { index: 'age' });\n *\n * @method Collection#between\n * @since 3.0.0\n * @param {array} leftKeys Keys defining the left boundary.\n * @param {array} rightKeys Keys defining the right boundary.\n * @param {object} [opts] Configuration options.\n * @param {string} [opts.index] Name of the secondary index to use in the\n * query. If no index is specified, the main index is used.\n * @param {boolean} [opts.leftInclusive=true] Whether to include records\n * on the left boundary.\n * @param {boolean} [opts.rightInclusive=false] Whether to include records\n * on the left boundary.\n * @param {boolean} [opts.limit] Limit the result to a certain number.\n * @param {boolean} [opts.offset] The number of resulting records to skip.\n * @returns {Object[]|Record[]} The result.\n */\n between (leftKeys, rightKeys, opts) {\n return this.query()\n .between(leftKeys, rightKeys, opts)\n .run()\n }\n\n /**\n * Create a new secondary index on the contents of the collection.\n *\n * @example\n * // Index users by age\n * collection.createIndex('age');\n *\n * @example\n * // Index users by status and role\n * collection.createIndex('statusAndRole', ['status', 'role']);\n *\n * @method Collection#createIndex\n * @since 3.0.0\n * @param {string} name The name of the new secondary index.\n * @param {string[]} [fieldList] Array of field names to use as the key or\n * compound key of the new secondary index. If no fieldList is provided, then\n * the name will also be the field that is used to index the collection.\n * @param opts\n */\n createIndex (name, fieldList?, opts: any = {}) {\n if (utils.isString(name) && fieldList === undefined) {\n fieldList = [name]\n }\n opts.hashCode = opts.hashCode || (obj => this.recordId(obj))\n const index = (this.indexes[name] = new Index(fieldList, opts))\n this.index.visitAll(index.insertRecord, index)\n }\n\n /**\n * Find the record or records that match the provided query or pass the\n * provided filter function.\n *\n * Shortcut for `collection.query().filter(queryOrFn[, thisArg]).run()`\n *\n * @example Collection#filter\n * const JSData = require('js-data');\n * const { Collection } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const collection = new Collection([\n * { id: 1, status: 'draft', created_at_timestamp: new Date().getTime() }\n * ]);\n *\n * // Get the draft posts created less than three months ago\n * let posts = collection.filter({\n * where: {\n * status: {\n * '==': 'draft'\n * },\n * created_at_timestamp: {\n * '>=': (new Date().getTime() - (1000 \\* 60 \\* 60 \\* 24 \\* 30 \\* 3)) // 3 months ago\n * }\n * }\n * });\n * console.log(posts);\n *\n * // Use a custom filter function\n * posts = collection.filter((post) => post.id % 2 === 0);\n *\n * @method Collection#filter\n * @param {(Object|Function)} [queryOrFn={}] Selection query or filter\n * function.\n * @param {object} [thisArg] Context to which to bind `queryOrFn` if\n * `queryOrFn` is a function.\n * @returns {Array} The result.\n * @see query\n * @since 3.0.0\n */\n filter (queryOrFn, thisArg?) {\n return this.query()\n .filter(queryOrFn, thisArg)\n .run()\n }\n\n /**\n * Iterate over all records.\n *\n * @example\n * collection.forEach(function (record) {\n * // do something\n * });\n *\n * @method Collection#forEach\n * @since 3.0.0\n * @param {Function} forEachFn Iteration function.\n * @param {*} [thisArg] Context to which to bind `forEachFn`.\n * @returns {Array} The result.\n */\n forEach (forEachFn, thisArg?) {\n this.index.visitAll(forEachFn, thisArg)\n }\n\n /**\n * Get the record with the given id.\n *\n * @method Collection#get\n * @since 3.0.0\n * @param {(string|number)} id The primary key of the record to get.\n * @returns {(Object|Record)} The record with the given id.\n */\n get (id) {\n const instances =\n id === undefined\n ? []\n : this.query()\n .get(id)\n .run()\n return instances.length ? instances[0] : undefined\n }\n\n /**\n * Find the record or records that match the provided keyLists.\n *\n * Shortcut for `collection.query().getAll(keyList1, keyList2, ...).run()`\n *\n * @example\n * // Get the posts where \"status\" is \"draft\" or \"inReview\"\n * const posts = collection.getAll('draft', 'inReview', { index: 'status' });\n *\n * @example\n * // Same as above\n * const posts = collection.getAll(['draft'], ['inReview'], { index: 'status' });\n *\n * @method Collection#getAll\n * @since 3.0.0\n * @param {...Array} [keyList] Provide one or more keyLists, and all\n * records matching each keyList will be retrieved. If no keyLists are\n * provided, all records will be returned.\n * @param {object} [opts] Configuration options.\n * @param {string} [opts.index] Name of the secondary index to use in the\n * query. If no index is specified, the main index is used.\n * @returns {Array} The result.\n */\n getAll(keyList?: Array | string | number, opts?)\n getAll(keyList?: Array | string | number, ...args)\n getAll (...args) {\n return this.query()\n .getAll(...args)\n .run()\n }\n\n /**\n * Return the index with the given name. If no name is provided, return the\n * main index. Throws an error if the specified index does not exist.\n *\n * @method Collection#getIndex\n * @since 3.0.0\n * @param {string} [name] The name of the index to retrieve.\n */\n getIndex (name): Index {\n const index = name ? this.indexes[name] : this.index\n if (!index) {\n throw utils.err(`${DOMAIN}#getIndex`, name)(404, 'index')\n }\n return index\n }\n\n /**\n * Limit the result.\n *\n * Shortcut for `collection.query().limit(maximumNumber).run()`\n *\n * @example\n * const posts = collection.limit(10);\n *\n * @method Collection#limit\n * @since 3.0.0\n * @param {number} num The maximum number of records to keep in the result.\n * @returns {Array} The result.\n */\n limit (num) {\n return this.query()\n .limit(num)\n .run()\n }\n\n /**\n * Apply a mapping function to all records.\n *\n * @example\n * const names = collection.map((user) => user.name);\n *\n * @method Collection#map\n * @since 3.0.0\n * @param {Function} mapFn Mapping function.\n * @param {*} [thisArg] Context to which to bind `mapFn`.\n * @returns {Array} The result of the mapping.\n */\n map (cb, thisArg) {\n const data = []\n this.index.visitAll(value => {\n data.push(cb.call(thisArg, value))\n })\n return data\n }\n\n /**\n * Return the result of calling the specified function on each record in this\n * collection's main index.\n *\n * @method Collection#mapCall\n * @since 3.0.0\n * @param {string} funcName Name of function to call\n * @param {...*} [args] Remaining arguments to be passed to the function.\n * @returns {Array} The result.\n */\n mapCall (funcName, ...args) {\n const data = []\n this.index.visitAll(record => {\n data.push(record[funcName](...args))\n })\n return data\n }\n\n /**\n * Return all \"unsaved\" (not uniquely identifiable) records in this colleciton.\n *\n * @method Collection#prune\n * @param {object} [opts] Configuration options, passed to {@link Collection#removeAll}.\n * @since 3.0.0\n * @returns {Array} The removed records, if any.\n */\n prune (opts) {\n return this.removeAll(this.unsaved(), opts)\n }\n\n /**\n * Create a new query to be executed against the contents of the collection.\n * The result will be all or a subset of the contents of the collection.\n *\n * @example\n * // Grab page 2 of users between ages 18 and 30\n * collection.query()\n * .between(18, 30, { index: 'age' }) // between ages 18 and 30\n * .skip(10) // second page\n * .limit(10) // page size\n * .run();\n *\n * @method Collection#query\n * @since 3.0.0\n * @returns {Query} New query object.\n */\n query (): Query {\n const Ctor = this.queryClass\n return new Ctor(this)\n }\n\n /**\n * Return the primary key of the given, or if no record is provided, return the\n * name of the field that holds the primary key of records in this Collection.\n *\n * @method Collection#recordId\n * @since 3.0.0\n * @param {(Object|Record)} [record] The record whose primary key is to be\n * returned.\n * @returns {(string|number)} Primary key or name of field that holds primary\n * key.\n */\n recordId (record?) {\n if (record) {\n return utils.get(record, this.recordId())\n }\n return this.mapper ? this.mapper.idAttribute : this.idAttribute\n }\n\n /**\n * Reduce the data in the collection to a single value and return the result.\n *\n * @example\n * const totalVotes = collection.reduce((prev, record) => {\n * return prev + record.upVotes + record.downVotes;\n * }, 0);\n *\n * @method Collection#reduce\n * @since 3.0.0\n * @param {Function} cb Reduction callback.\n * @param {*} initialValue Initial value of the reduction.\n * @returns {*} The result.\n */\n reduce (cb, initialValue) {\n const data = this.getAll()\n return data.reduce(cb, initialValue)\n }\n\n /**\n * Remove the record with the given id from this Collection.\n *\n * @method Collection#remove\n * @since 3.0.0\n * @param {(string|number|object|Record)} idOrRecord The primary key of the\n * record to be removed, or a reference to the record that is to be removed.\n * @param {object} [opts] Configuration options.\n * @returns {Object|Record} The removed record, if any.\n */\n remove (idOrRecord, opts: any = {}) {\n this.beforeRemove(idOrRecord, opts)\n let record = utils.isSorN(idOrRecord) ? this.get(idOrRecord) : idOrRecord\n\n // The record is in the collection, remove it\n if (utils.isObject(record)) {\n record = this.index.removeRecord(record)\n if (record) {\n utils.forOwn(this.indexes, (index, name) => {\n index.removeRecord(record)\n })\n if (utils.isFunction(record.off)) {\n record.off('all', this._onRecordEvent, this)\n }\n if (!opts.silent) {\n this.emit('remove', record)\n }\n }\n }\n return this.afterRemove(idOrRecord, opts, record) || record\n }\n\n /**\n * Remove from this collection the given records or the records selected by\n * the given \"query\".\n *\n * @method Collection#removeAll\n * @since 3.0.0\n * @param {Object|Object[]|Record[]} [queryOrRecords={}] Records to be removed or selection query. See {@link query}.\n * @param {object} [queryOrRecords.where] See {@link query.where}.\n * @param {number} [queryOrRecords.offset] See {@link query.offset}.\n * @param {number} [queryOrRecords.limit] See {@link query.limit}.\n * @param {string|Array[]} [queryOrRecords.orderBy] See {@link query.orderBy}.\n * @param {object} [opts] Configuration options.\n * @returns {(Object[]|Record[])} The removed records, if any.\n */\n removeAll (queryOrRecords, opts: any = {}) {\n this.beforeRemoveAll(queryOrRecords, opts)\n let records = utils.isArray(queryOrRecords)\n ? queryOrRecords.slice()\n : this.filter(queryOrRecords)\n\n // Remove each selected record from the collection\n const optsCopy = utils.plainCopy(opts)\n optsCopy.silent = true\n records = records\n .map(record => this.remove(record, optsCopy))\n .filter(record => record)\n if (!opts.silent) {\n this.emit('remove', records)\n }\n return this.afterRemoveAll(queryOrRecords, opts, records) || records\n }\n\n /**\n * Skip a number of results.\n *\n * Shortcut for `collection.query().skip(numberToSkip).run()`\n *\n * @example\n * const posts = collection.skip(10);\n *\n * @method Collection#skip\n * @since 3.0.0\n * @param {number} num The number of records to skip.\n * @returns {Array} The result.\n */\n skip (num) {\n return this.query()\n .skip(num)\n .run()\n }\n\n /**\n * Return the plain JSON representation of all items in this collection.\n * Assumes records in this collection have a toJSON method.\n *\n * @method Collection#toJSON\n * @since 3.0.0\n * @param {object} [opts] Configuration options.\n * @param {string[]} [opts.with] Array of relation names or relation fields\n * to include in the representation.\n * @returns {Array} The records.\n */\n toJSON (opts?) {\n return this.mapCall('toJSON', opts)\n }\n\n /**\n * Return all \"unsaved\" (not uniquely identifiable) records in this colleciton.\n *\n * @method Collection#unsaved\n * @since 3.0.0\n * @returns {Array} The unsaved records, if any.\n */\n unsaved (opts?) {\n return this.index.get()\n }\n\n /**\n * Update a record's position in a single index of this collection. See\n * {@link Collection#updateIndexes} to update a record's position in all\n * indexes at once.\n *\n * @method Collection#updateIndex\n * @since 3.0.0\n * @param {object} record The record to update.\n * @param {object} [opts] Configuration options.\n * @param {string} [opts.index] The index in which to update the record's\n * position. If you don't specify an index then the record will be updated\n * in the main index.\n */\n updateIndex (record, opts: { index?: string } = {}) {\n this.getIndex(opts.index).updateRecord(record)\n }\n\n /**\n * Updates all indexes in this collection for the provided record. Has no\n * effect if the record is not in the collection.\n *\n * @method Collection#updateIndexes\n * @since 3.0.0\n * @param {object} record TODO\n */\n updateIndexes (record) {\n this.index.updateRecord(record)\n utils.forOwn(this.indexes, index => index.updateRecord(record))\n }\n}\n\n/**\n * Fired when a record changes. Only works for records that have tracked changes.\n * See {@link Collection~changeListener} on how to listen for this event.\n *\n * @event Collection#change\n * @see Collection~changeListener\n */\n\n/**\n * Callback signature for the {@link Collection#event:change} event.\n *\n * @example\n * function onChange (record, changes) {\n * // do something\n * }\n * collection.on('change', onChange);\n *\n * @callback Collection~changeListener\n * @param {Record} The Record that changed.\n * @param {object} The changes.\n * @see Collection#event:change\n * @since 3.0.0\n */\n\n/**\n * Fired when one or more records are added to the Collection. See\n * {@link Collection~addListener} on how to listen for this event.\n *\n * @event Collection#add\n * @see Collection~addListener\n * @see Collection#event:add\n * @see Collection#add\n */\n\n/**\n * Callback signature for the {@link Collection#event:add} event.\n *\n * @example\n * function onAdd (recordOrRecords) {\n * // do something\n * }\n * collection.on('add', onAdd);\n *\n * @callback Collection~addListener\n * @param {Record|Record[]} The Record or Records that were added.\n * @see Collection#event:add\n * @see Collection#add\n * @since 3.0.0\n */\n\n/**\n * Fired when one or more records are removed from the Collection. See\n * {@link Collection~removeListener} for how to listen for this event.\n *\n * @event Collection#remove\n * @see Collection~removeListener\n * @see Collection#event:remove\n * @see Collection#remove\n * @see Collection#removeAll\n */\n\n/**\n * Callback signature for the {@link Collection#event:remove} event.\n *\n * @example\n * function onRemove (recordsOrRecords) {\n * // do something\n * }\n * collection.on('remove', onRemove);\n *\n * @callback Collection~removeListener\n * @param {Record|Record[]} Record or Records that were removed.\n * @see Collection#event:remove\n * @see Collection#remove\n * @see Collection#removeAll\n * @since 3.0.0\n */\n\n/**\n * Create a subclass of this Collection:\n * @example Collection.extend\n * const JSData = require('js-data');\n * const { Collection } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * // Extend the class using ES2015 class syntax.\n * class CustomCollectionClass extends Collection {\n * foo () { return 'bar'; }\n * static beep () { return 'boop'; }\n * }\n * const customCollection = new CustomCollectionClass();\n * console.log(customCollection.foo());\n * console.log(CustomCollectionClass.beep());\n *\n * // Extend the class using alternate method.\n * const OtherCollectionClass = Collection.extend({\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * });\n * const otherCollection = new OtherCollectionClass();\n * console.log(otherCollection.foo());\n * console.log(OtherCollectionClass.beep());\n *\n * // Extend the class, providing a custom constructor.\n * function AnotherCollectionClass () {\n * Collection.call(this);\n * this.created_at = new Date().getTime();\n * }\n * Collection.extend({\n * constructor: AnotherCollectionClass,\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * });\n * const anotherCollection = new AnotherCollectionClass();\n * console.log(anotherCollection.created_at);\n * console.log(anotherCollection.foo());\n * console.log(AnotherCollectionClass.beep());\n *\n * @method Collection.extend\n * @param {object} [props={}] Properties to add to the prototype of the\n * subclass.\n * @param {object} [props.constructor] Provide a custom constructor function\n * to be used as the subclass itself.\n * @param {object} [classProps={}] Static properties to add to the subclass.\n * @returns {Constructor} Subclass of this Collection class.\n * @since 3.0.0\n */\n","export class TsDataError extends Error {\n errors: any;\n}\n","import utils from './utils'\nimport Component from './Component'\nimport { TsDataError } from './TsDataError'\n\nconst DOMAIN = 'Schema'\n\n/**\n * A function map for each of the seven primitive JSON types defined by the core specification.\n * Each function will check a given value and return true or false if the value is an instance of that type.\n * ```\n * types.integer(1) // returns true\n * types.string({}) // returns false\n * ```\n * http://json-schema.org/latest/json-schema-core.html#anchor8\n * @name Schema.types\n * @type {object}\n */\nconst types = {\n array: utils.isArray,\n boolean: utils.isBoolean,\n integer: utils.isInteger,\n null: utils.isNull,\n number: utils.isNumber,\n object: utils.isObject,\n string: utils.isString\n}\n\n/**\n * @ignore\n */\nfunction segmentToString (segment, prev) {\n let str = ''\n if (segment) {\n if (utils.isNumber(segment)) {\n str += `[${segment}]`\n } else if (prev) {\n str += `.${segment}`\n } else {\n str += `${segment}`\n }\n }\n return str\n}\n\n/**\n * @ignore\n */\nfunction makePath (opts: any = {}) {\n let path = ''\n const segments = opts.path || []\n segments.forEach(segment => {\n path += segmentToString(segment, path)\n })\n path += segmentToString(opts.prop, path)\n return path\n}\n\n/**\n * @ignore\n */\nfunction makeError (actual, expected, opts) {\n return {\n expected,\n actual: '' + actual,\n path: makePath(opts)\n }\n}\n\n/**\n * @ignore\n */\nfunction addError (actual, expected, opts, errors) {\n errors.push(makeError(actual, expected, opts))\n}\n\n/**\n * @ignore\n */\nfunction maxLengthCommon (keyword, value, schema, opts) {\n const max = schema[keyword]\n if (value.length > max) {\n return makeError(value.length, `length no more than ${max}`, opts)\n }\n}\n\n/**\n * @ignore\n */\nfunction minLengthCommon (keyword, value, schema, opts) {\n const min = schema[keyword]\n if (value.length < min) {\n return makeError(value.length, `length no less than ${min}`, opts)\n }\n}\n\n/**\n * A map of all object member validation functions for each keyword defined in the JSON Schema.\n * @name Schema.validationKeywords\n * @type {object}\n */\nconst validationKeywords = {\n /**\n * Validates the provided value against all schemas defined in the Schemas `allOf` keyword.\n * The instance is valid against if and only if it is valid against all the schemas declared in the Schema's value.\n *\n * The value of this keyword MUST be an array. This array MUST have at least one element.\n * Each element of this array MUST be a valid JSON Schema.\n *\n * see http://json-schema.org/latest/json-schema-validation.html#anchor82\n *\n * @name Schema.validationKeywords.allOf\n * @method\n * @param {*} value Value to be validated.\n * @param {object} schema Schema containing the `allOf` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n allOf (value, schema, opts) {\n let allErrors = []\n schema.allOf.forEach(_schema => {\n allErrors = allErrors.concat(validate(value, _schema, opts) || [])\n })\n return allErrors.length ? allErrors : undefined\n },\n\n /**\n * Validates the provided value against all schemas defined in the Schemas `anyOf` keyword.\n * The instance is valid against this keyword if and only if it is valid against\n * at least one of the schemas in this keyword's value.\n *\n * The value of this keyword MUST be an array. This array MUST have at least one element.\n * Each element of this array MUST be an object, and each object MUST be a valid JSON Schema.\n * see http://json-schema.org/latest/json-schema-validation.html#anchor85\n *\n * @name Schema.validationKeywords.anyOf\n * @method\n * @param {*} value Value to be validated.\n * @param {object} schema Schema containing the `anyOf` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n anyOf (value, schema, opts) {\n let validated = false\n let allErrors = []\n schema.anyOf.forEach(_schema => {\n const errors = validate(value, _schema, opts)\n if (errors) {\n allErrors = allErrors.concat(errors)\n } else {\n validated = true\n }\n })\n return validated ? undefined : allErrors\n },\n\n /**\n * http://json-schema.org/latest/json-schema-validation.html#anchor70\n *\n * @name Schema.validationKeywords.dependencies\n * @method\n * @param {*} value TODO\n * @param {object} schema TODO\n * @param {object} opts TODO\n */\n dependencies (value, schema, opts) {\n // TODO\n },\n\n /**\n * Validates the provided value against an array of possible values defined by the Schema's `enum` keyword\n * Validation succeeds if the value is deeply equal to one of the values in the array.\n * see http://json-schema.org/latest/json-schema-validation.html#anchor76\n *\n * @name Schema.validationKeywords.enum\n * @method\n * @param {*} value Value to validate\n * @param {object} schema Schema containing the `enum` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n enum (value, schema, opts) {\n const possibleValues = schema.enum\n if (utils.findIndex(possibleValues, item => utils.deepEqual(item, value)) === -1) {\n return makeError(value, `one of (${possibleValues.join(', ')})`, opts)\n }\n },\n\n /**\n * Validates each of the provided array values against a schema or an array of schemas defined by the Schema's\n * `items` keyword\n * see http://json-schema.org/latest/json-schema-validation.html#anchor37 for validation rules.\n *\n * @name Schema.validationKeywords.items\n * @method\n * @param {*} value Array to be validated.\n * @param {object} schema Schema containing the items keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n items (value, schema, opts: any = {}) {\n // TODO: additionalItems\n let items = schema.items\n let errors = []\n const checkingTuple = utils.isArray(items)\n const length = value.length\n for (let prop = 0; prop < length; prop++) {\n if (checkingTuple) {\n // Validating a tuple, instead of just checking each item against the\n // same schema\n items = schema.items[prop]\n }\n opts.prop = prop\n errors = errors.concat(validate(value[prop], items, opts) || [])\n }\n return errors.length ? errors : undefined\n },\n\n /**\n * Validates the provided number against a maximum value defined by the Schema's `maximum` keyword\n * Validation succeeds if the value is a number, and is less than, or equal to, the value of this keyword.\n * http://json-schema.org/latest/json-schema-validation.html#anchor17\n *\n * @name Schema.validationKeywords.maximum\n * @method\n * @param {*} value Number to validate against the keyword.\n * @param {object} schema Schema containing the `maximum` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n maximum (value, schema, opts) {\n // Must be a number\n const maximum = schema.maximum\n // Must be a boolean\n // Depends on maximum\n // default: false\n const exclusiveMaximum = schema.exclusiveMaximum\n if (typeof value === typeof maximum && !(exclusiveMaximum ? maximum > value : maximum >= value)) {\n return exclusiveMaximum\n ? makeError(value, `no more than nor equal to ${maximum}`, opts)\n : makeError(value, `no more than ${maximum}`, opts)\n }\n },\n\n /**\n * Validates the length of the provided array against a maximum value defined by the Schema's `maxItems` keyword.\n * Validation succeeds if the length of the array is less than, or equal to the value of this keyword.\n * see http://json-schema.org/latest/json-schema-validation.html#anchor42\n *\n * @name Schema.validationKeywords.maxItems\n * @method\n * @param {*} value Array to be validated.\n * @param {object} schema Schema containing the `maxItems` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n maxItems (value, schema, opts) {\n if (utils.isArray(value)) {\n return maxLengthCommon('maxItems', value, schema, opts)\n }\n },\n\n /**\n * Validates the length of the provided string against a maximum value defined in the Schema's `maxLength` keyword.\n * Validation succeeds if the length of the string is less than, or equal to the value of this keyword.\n * see http://json-schema.org/latest/json-schema-validation.html#anchor26\n *\n * @name Schema.validationKeywords.maxLength\n * @method\n * @param {*} value String to be validated.\n * @param {object} schema Schema containing the `maxLength` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n maxLength (value, schema, opts) {\n return maxLengthCommon('maxLength', value, schema, opts)\n },\n\n /**\n * Validates the count of the provided object's properties against a maximum value defined in the Schema's\n * `maxProperties` keyword.\n * Validation succeeds if the object's property count is less than, or equal to the value of this keyword.\n * see http://json-schema.org/latest/json-schema-validation.html#anchor54\n *\n * @name Schema.validationKeywords.maxProperties\n * @method\n * @param {*} value Object to be validated.\n * @param {object} schema Schema containing the `maxProperties` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n maxProperties (value, schema, opts) {\n // validate only objects\n if (!utils.isObject(value)) return\n const maxProperties = schema.maxProperties\n const length = Object.keys(value).length\n if (length > maxProperties) {\n return makeError(length, `no more than ${maxProperties} properties`, opts)\n }\n },\n\n /**\n * Validates the provided value against a minimum value defined by the Schema's `minimum` keyword\n * Validation succeeds if the value is a number and is greater than, or equal to, the value of this keyword.\n * http://json-schema.org/latest/json-schema-validation.html#anchor21\n *\n * @name Schema.validationKeywords.minimum\n * @method\n * @param {*} value Number to validate against the keyword.\n * @param {object} schema Schema containing the `minimum` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n minimum (value, schema, opts) {\n // Must be a number\n const minimum = schema.minimum\n // Must be a boolean\n // Depends on minimum\n // default: false\n const exclusiveMinimum = schema.exclusiveMinimum\n if (typeof value === typeof minimum && !(exclusiveMinimum ? value > minimum : value >= minimum)) {\n return exclusiveMinimum\n ? makeError(value, `no less than nor equal to ${minimum}`, opts)\n : makeError(value, `no less than ${minimum}`, opts)\n }\n },\n\n /**\n * Validates the length of the provided array against a minimum value defined by the Schema's `minItems` keyword.\n * Validation succeeds if the length of the array is greater than, or equal to the value of this keyword.\n * see http://json-schema.org/latest/json-schema-validation.html#anchor45\n *\n * @name Schema.validationKeywords.minItems\n * @method\n * @param {*} value Array to be validated.\n * @param {object} schema Schema containing the `minItems` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n minItems (value, schema, opts) {\n if (utils.isArray(value)) {\n return minLengthCommon('minItems', value, schema, opts)\n }\n },\n\n /**\n * Validates the length of the provided string against a minimum value defined in the Schema's `minLength` keyword.\n * Validation succeeds if the length of the string is greater than, or equal to the value of this keyword.\n * see http://json-schema.org/latest/json-schema-validation.html#anchor29\n *\n * @name Schema.validationKeywords.minLength\n * @method\n * @param {*} value String to be validated.\n * @param {object} schema Schema containing the `minLength` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n minLength (value, schema, opts) {\n return minLengthCommon('minLength', value, schema, opts)\n },\n\n /**\n * Validates the count of the provided object's properties against a minimum value defined in the Schema's\n * `minProperties` keyword.\n * Validation succeeds if the object's property count is greater than, or equal to the value of this keyword.\n * see http://json-schema.org/latest/json-schema-validation.html#anchor57\n *\n * @name Schema.validationKeywords.minProperties\n * @method\n * @param {*} value Object to be validated.\n * @param {object} schema Schema containing the `minProperties` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n minProperties (value, schema, opts) {\n // validate only objects\n if (!utils.isObject(value)) return\n const minProperties = schema.minProperties\n const length = Object.keys(value).length\n if (length < minProperties) {\n return makeError(length, `no more than ${minProperties} properties`, opts)\n }\n },\n\n /**\n * Validates the provided number is a multiple of the number defined in the Schema's `multipleOf` keyword.\n * Validation succeeds if the number can be divided equally into the value of this keyword.\n * see http://json-schema.org/latest/json-schema-validation.html#anchor14\n *\n * @name Schema.validationKeywords.multipleOf\n * @method\n * @param {*} value Number to be validated.\n * @param {object} schema Schema containing the `multipleOf` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n multipleOf (value, schema, opts) {\n const multipleOf = schema.multipleOf\n if (utils.isNumber(value)) {\n if ((value / multipleOf) % 1 !== 0) {\n return makeError(value, `multipleOf ${multipleOf}`, opts)\n }\n }\n },\n\n /**\n * Validates the provided value is not valid with any of the schemas defined in the Schema's `not` keyword.\n * An instance is valid against this keyword if and only if it is NOT valid against the schemas in this keyword's\n * value.\n *\n * see http://json-schema.org/latest/json-schema-validation.html#anchor91\n * @name Schema.validationKeywords.not\n * @method\n * @param {*} value to be checked.\n * @param {object} schema Schema containing the not keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n not (value, schema, opts) {\n if (!validate(value, schema.not, opts)) {\n // TODO: better messaging\n return makeError('succeeded', 'should have failed', opts)\n }\n },\n\n /**\n * Validates the provided value is valid with one and only one of the schemas defined in the Schema's `oneOf` keyword.\n * An instance is valid against this keyword if and only if it is valid against a single schemas in this keyword's\n * value.\n *\n * see http://json-schema.org/latest/json-schema-validation.html#anchor88\n * @name Schema.validationKeywords.oneOf\n * @method\n * @param {*} value to be checked.\n * @param {object} schema Schema containing the `oneOf` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n oneOf (value, schema, opts) {\n let validated = false\n let allErrors = []\n schema.oneOf.forEach(_schema => {\n const errors = validate(value, _schema, opts)\n if (errors) {\n allErrors = allErrors.concat(errors)\n } else if (validated) {\n allErrors = [makeError('valid against more than one', 'valid against only one', opts)]\n validated = false\n return false\n } else {\n validated = true\n }\n })\n return validated ? undefined : allErrors\n },\n\n /**\n * Validates the provided string matches a pattern defined in the Schema's `pattern` keyword.\n * Validation succeeds if the string is a match of the regex value of this keyword.\n *\n * see http://json-schema.org/latest/json-schema-validation.html#anchor33\n * @name Schema.validationKeywords.pattern\n * @method\n * @param {*} value String to be validated.\n * @param {object} schema Schema containing the `pattern` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n pattern (value, schema, opts) {\n const pattern = schema.pattern\n if (utils.isString(value) && !value.match(pattern)) {\n return makeError(value, pattern, opts)\n }\n },\n\n /**\n * Validates the provided object's properties against a map of values defined in the Schema's `properties` keyword.\n * Validation succeeds if the object's property are valid with each of the schema's in the provided map.\n * Validation also depends on the additionalProperties and or patternProperties.\n *\n * see http://json-schema.org/latest/json-schema-validation.html#anchor64 for more info.\n *\n * @name Schema.validationKeywords.properties\n * @method\n * @param {*} value Object to be validated.\n * @param {object} schema Schema containing the `properties` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n properties (value, schema, opts: any = {}) {\n if (utils.isArray(value)) {\n return\n }\n\n // Can be a boolean or an object\n // Technically the default is an \"empty schema\", but here \"true\" is\n // functionally the same\n const additionalProperties = schema.additionalProperties === undefined ? true : schema.additionalProperties\n const validated = []\n // \"p\": The property set from \"properties\".\n // Default is an object\n const properties = schema.properties || {}\n // \"pp\": The property set from \"patternProperties\".\n // Default is an object\n const patternProperties = schema.patternProperties || {}\n let errors = []\n\n utils.forOwn(properties, (_schema, prop) => {\n opts.prop = prop\n errors = errors.concat(validate(value[prop], _schema, opts) || [])\n validated.push(prop)\n })\n\n const toValidate = utils.omit(value, validated)\n utils.forOwn(patternProperties, (_schema, pattern) => {\n utils.forOwn(toValidate, (undef, prop) => {\n if (prop.match(pattern)) {\n opts.prop = prop\n errors = errors.concat(validate(value[prop], _schema, opts) || [])\n validated.push(prop)\n }\n })\n })\n const keys = Object.keys(utils.omit(value, validated))\n // If \"s\" is not empty, validation fails\n if (additionalProperties === false) {\n if (keys.length) {\n const origProp = opts.prop\n opts.prop = ''\n addError(`extra fields: ${keys.join(', ')}`, 'no extra fields', opts, errors)\n opts.prop = origProp\n }\n } else if (utils.isObject(additionalProperties)) {\n // Otherwise, validate according to provided schema\n keys.forEach(prop => {\n opts.prop = prop\n errors = errors.concat(validate(value[prop], additionalProperties, opts) || [])\n })\n }\n return errors.length ? errors : undefined\n },\n\n /**\n * Validates the provided object's has all properties listed in the Schema's `properties` keyword array.\n * Validation succeeds if the object contains all properties provided in the array value of this keyword.\n * see http://json-schema.org/latest/json-schema-validation.html#anchor61\n *\n * @name Schema.validationKeywords.required\n * @method\n * @param {*} value Object to be validated.\n * @param {object} schema Schema containing the `required` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n required (value, schema, opts: any = {}) {\n const required = schema.required\n const errors = []\n if (!opts.existingOnly) {\n required.forEach(prop => {\n if (utils.get(value, prop) === undefined) {\n const prevProp = opts.prop\n opts.prop = prop\n addError(undefined, 'a value', opts, errors)\n opts.prop = prevProp\n }\n })\n }\n return errors.length ? errors : undefined\n },\n\n /**\n * Validates the provided value's type is equal to the type, or array of types, defined in the Schema's `type`\n * keyword.\n * see http://json-schema.org/latest/json-schema-validation.html#anchor79\n *\n * @name Schema.validationKeywords.type\n * @method\n * @param {*} value Value to be validated.\n * @param {object} schema Schema containing the `type` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n type (value, schema, opts) {\n let type = schema.type\n let validType\n // Can be one of several types\n if (utils.isString(type)) {\n type = [type]\n }\n // Try to match the value against an expected type\n type.forEach(_type => {\n // TODO: throw an error if type is not defined\n if (types[_type](value, schema, opts)) {\n // Matched a type\n validType = _type\n return false\n }\n })\n // Value did not match any expected type\n if (!validType) {\n return makeError(\n value !== undefined && value !== null ? typeof value : '' + value,\n `one of (${type.join(', ')})`,\n opts\n )\n }\n // Run keyword validators for matched type\n // http://json-schema.org/latest/json-schema-validation.html#anchor12\n const validator = typeGroupValidators[validType]\n if (validator) {\n return validator(value, schema, opts)\n }\n },\n\n /**\n * Validates the provided array values are unique.\n * Validation succeeds if the items in the array are unique, but only if the value of this keyword is true\n * see http://json-schema.org/latest/json-schema-validation.html#anchor49\n *\n * @name Schema.validationKeywords.uniqueItems\n * @method\n * @param {*} value Array to be validated.\n * @param {object} schema Schema containing the `uniqueItems` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n uniqueItems (value, schema, opts) {\n if (value?.length && schema.uniqueItems) {\n const length = value.length\n let item, i, j\n // Check n - 1 items\n for (i = length - 1; i > 0; i--) {\n item = value[i]\n // Only compare against unchecked items\n for (j = i - 1; j >= 0; j--) {\n // Found a duplicate\n if (utils.deepEqual(item, value[j])) {\n return makeError(item, 'no duplicates', opts)\n }\n }\n }\n }\n }\n}\n\n/**\n * @ignore\n */\nfunction runOps (ops, value, schema, opts) {\n let errors = []\n ops.forEach(op => {\n if (schema[op] !== undefined) {\n errors = errors.concat(validationKeywords[op](value, schema, opts) || [])\n }\n })\n return errors.length ? errors : undefined\n}\n\n/**\n * Validation keywords validated for any type:\n *\n * - `enum`\n * - `type`\n * - `allOf`\n * - `anyOf`\n * - `oneOf`\n * - `not`\n *\n * @name Schema.ANY_OPS\n * @type {string[]}\n */\nconst ANY_OPS = ['enum', 'type', 'allOf', 'anyOf', 'oneOf', 'not']\n\n/**\n * Validation keywords validated for array types:\n *\n * - `items`\n * - `maxItems`\n * - `minItems`\n * - `uniqueItems`\n *\n * @name Schema.ARRAY_OPS\n * @type {string[]}\n */\nconst ARRAY_OPS = ['items', 'maxItems', 'minItems', 'uniqueItems']\n\n/**\n * Validation keywords validated for numeric (number and integer) types:\n *\n * - `multipleOf`\n * - `maximum`\n * - `minimum`\n *\n * @name Schema.NUMERIC_OPS\n * @type {string[]}\n */\nconst NUMERIC_OPS = ['multipleOf', 'maximum', 'minimum']\n\n/**\n * Validation keywords validated for object types:\n *\n * - `maxProperties`\n * - `minProperties`\n * - `required`\n * - `properties`\n * - `dependencies`\n *\n * @name Schema.OBJECT_OPS\n * @type {string[]}\n */\nconst OBJECT_OPS = ['maxProperties', 'minProperties', 'required', 'properties', 'dependencies']\n\n/**\n * Validation keywords validated for string types:\n *\n * - `maxLength`\n * - `minLength`\n * - `pattern`\n *\n * @name Schema.STRING_OPS\n * @type {string[]}\n */\nconst STRING_OPS = ['maxLength', 'minLength', 'pattern']\n\n/**\n * http://json-schema.org/latest/json-schema-validation.html#anchor75\n * @ignore\n */\nconst validateAny = (value, schema, opts) => runOps(ANY_OPS, value, schema, opts)\n\n/**\n * Validates the provided value against a given Schema according to the http://json-schema.org/ v4 specification.\n *\n * @name Schema.validate\n * @method\n * @param {*} value Value to be validated.\n * @param {object} schema Valid Schema according to the http://json-schema.org/ v4 specification.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\nconst validate = (value, schema, opts: any = {}) => {\n let errors = []\n opts.ctx = opts.ctx || { value, schema }\n let shouldPop\n const prevProp = opts.prop\n if (schema === undefined) {\n return\n }\n if (!utils.isObject(schema)) {\n throw utils.err(`${DOMAIN}#validate`)(500, `Invalid schema at path: \"${opts.path}\"`)\n }\n if (opts.path === undefined) {\n opts.path = []\n }\n // Track our location as we recurse\n if (opts.prop !== undefined) {\n shouldPop = true\n opts.path.push(opts.prop)\n opts.prop = undefined\n }\n // Validate against parent schema\n if (schema.extends) {\n // opts.path = path\n // opts.prop = prop\n if (utils.isFunction(schema.extends.validate)) {\n errors = errors.concat(schema.extends.validate(value, opts) || [])\n } else {\n errors = errors.concat(validate(value, schema.extends, opts) || [])\n }\n }\n if (value === undefined) {\n // Check if property is required\n if (schema.required === true && !opts.existingOnly) {\n addError(value, 'a value', opts, errors)\n }\n if (shouldPop) {\n opts.path.pop()\n opts.prop = prevProp\n }\n return errors.length ? errors : undefined\n }\n\n errors = errors.concat(validateAny(value, schema, opts) || [])\n if (shouldPop) {\n opts.path.pop()\n opts.prop = prevProp\n }\n return errors.length ? errors : undefined\n}\n\n// These strings are cached for optimal performance of the change detection\n// boolean - Whether a Record is changing in the current execution frame\nconst changingPath = 'changing'\n// string[] - Properties that have changed in the current execution frame\nconst changedPath = 'changed'\n// Object[] - History of change records\nconst changeHistoryPath = 'history'\n// boolean - Whether a Record is currently being instantiated\nconst creatingPath = 'creating'\n// number - The setTimeout change event id of a Record, if any\nconst eventIdPath = 'eventId'\n// boolean - Whether to skip validation for a Record's currently changing property\nconst noValidatePath = 'noValidate'\n// boolean - Whether to preserve Change History for a Record\nconst keepChangeHistoryPath = 'keepChangeHistory'\n// boolean - Whether to skip change notification for a Record's currently\n// changing property\nconst silentPath = 'silent'\nconst validationFailureMsg = 'validation failed'\n\n/**\n * A map of validation functions grouped by type.\n *\n * @name Schema.typeGroupValidators\n * @type {object}\n */\nconst typeGroupValidators = {\n /**\n * Validates the provided value against the schema using all of the validation keywords specific to instances of an\n * array.\n * The validation keywords for the type `array` are:\n * ```\n * ['items', 'maxItems', 'minItems', 'uniqueItems']\n * ```\n * see http://json-schema.org/latest/json-schema-validation.html#anchor25\n *\n * @name Schema.typeGroupValidators.array\n * @method\n * @param {*} value Array to be validated.\n * @param {object} schema Schema containing at least one array keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n array: (value, schema, opts?) => runOps(ARRAY_OPS, value, schema, opts),\n\n /**\n * Validates the provided value against the schema using all of the validation keywords specific to instances of an\n * integer.\n * The validation keywords for the type `integer` are:\n * ```\n * ['multipleOf', 'maximum', 'minimum']\n * ```\n * @name Schema.typeGroupValidators.integer\n * @method\n * @param {*} value Number to be validated.\n * @param {object} schema Schema containing at least one `integer` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n integer: (value, schema, opts) =>\n // Additional validations for numerics are the same\n typeGroupValidators.numeric(value, schema, opts),\n\n /**\n * Validates the provided value against the schema using all of the validation keywords specific to instances of an\n * number.\n * The validation keywords for the type `number` are:\n * ```\n * ['multipleOf', 'maximum', 'minimum']\n * ```\n * @name Schema.typeGroupValidators.number\n * @method\n * @param {*} value Number to be validated.\n * @param {object} schema Schema containing at least one `number` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n number: (value, schema, opts) =>\n // Additional validations for numerics are the same\n typeGroupValidators.numeric(value, schema, opts),\n\n /**\n * Validates the provided value against the schema using all of the validation keywords specific to instances of a\n * number or integer.\n * The validation keywords for the type `numeric` are:\n * ```\n * ['multipleOf', 'maximum', 'minimum']\n * ```\n * See http://json-schema.org/latest/json-schema-validation.html#anchor13.\n *\n * @name Schema.typeGroupValidators.numeric\n * @method\n * @param {*} value Number to be validated.\n * @param {object} schema Schema containing at least one `numeric` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n numeric: (value, schema, opts) => runOps(NUMERIC_OPS, value, schema, opts),\n\n /**\n * Validates the provided value against the schema using all of the validation keywords specific to instances of an\n * object.\n * The validation keywords for the type `object` are:\n * ```\n * ['maxProperties', 'minProperties', 'required', 'properties', 'dependencies']\n * ```\n * See http://json-schema.org/latest/json-schema-validation.html#anchor53.\n *\n * @name Schema.typeGroupValidators.object\n * @method\n * @param {*} value Object to be validated.\n * @param {object} schema Schema containing at least one `object` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n object: (value, schema, opts) => runOps(OBJECT_OPS, value, schema, opts),\n\n /**\n * Validates the provided value against the schema using all of the validation keywords specific to instances of an\n * string.\n * The validation keywords for the type `string` are:\n * ```\n * ['maxLength', 'minLength', 'pattern']\n * ```\n * See http://json-schema.org/latest/json-schema-validation.html#anchor25.\n *\n * @name Schema.typeGroupValidators.string\n * @method\n * @param {*} value String to be validated.\n * @param {object} schema Schema containing at least one `string` keyword.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n string: (value, schema, opts?) => runOps(STRING_OPS, value, schema, opts)\n}\n\nexport interface PropertyDefinition {\n type: string | string[]\n track?: boolean\n description?: string\n indexed?: boolean\n items?: PropertyDefinition\n minItems?: number\n uniqueItems?: boolean\n extends?: Schema\n get?: Function\n properties?: { [name: string]: PropertyDefinition }\n required?: string[] | boolean\n maximum?: number\n exclusiveMaximum?: boolean\n minimum?: number\n exclusiveMinimum?: boolean\n additionalProperties?: boolean\n}\n\nexport interface SchemaDefinition {\n type?: string\n description?: string\n $schema?: string\n title?: string\n properties?: { [name: string]: PropertyDefinition | any }\n extends?: SchemaDefinition | Schema\n items?: SchemaDefinition | Schema\n track?: boolean\n additionalProperties?\n required?: string[]\n}\n\n/**\n * js-data's Schema class.\n *\n * @example Schema#constructor\n * const JSData = require('js-data');\n * const { Schema } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const PostSchema = new Schema({\n * type: 'object',\n * properties: {\n * title: { type: 'string' }\n * }\n * });\n * PostSchema.validate({ title: 1234 });\n *\n * @example\n * const JSData = require('js-data');\n * const { Schema } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * class CustomSchemaClass extends Schema {\n * foo () { return 'bar'; }\n * static beep () { return 'boop'; }\n * }\n * const customSchema = new CustomSchemaClass();\n * console.log(customSchema.foo());\n * console.log(CustomSchemaClass.beep());\n *\n * @class Schema\n * @extends Component\n * @param {object} definition Schema definition according to json-schema.org\n */\nexport default class Schema extends Component {\n type: string;\n properties: any;\n private readonly extends: Schema;\n private readonly items: Schema;\n private readonly track: any;\n private readonly additionalProperties: any;\n\n constructor (definition: SchemaDefinition = {}) {\n super()\n // TODO: schema validation\n utils.fillIn(this, definition)\n\n if (this.type === 'object') {\n this.properties = this.properties || {}\n utils.forOwn(this.properties, (_definition, prop) => {\n if (!(_definition instanceof Schema)) {\n this.properties[prop] = new Schema(_definition)\n }\n })\n } else if (this.type === 'array' && this.items && !(this.items instanceof Schema)) {\n this.items = new Schema(this.items)\n }\n if (this.extends && !(this.extends instanceof Schema)) {\n this.extends = new Schema(this.extends)\n }\n ['allOf', 'anyOf', 'oneOf'].forEach(validationKeyword => {\n if (this[validationKeyword]) {\n this[validationKeyword].forEach((_definition, i) => {\n if (!(_definition instanceof Schema)) {\n this[validationKeyword][i] = new Schema(_definition)\n }\n })\n }\n })\n }\n\n /**\n * This adds ES5 getters/setters to the target based on the \"properties\" in\n * this Schema, which makes possible change tracking and validation on\n * property assignment.\n *\n * @name Schema#apply\n * @method\n * @param {object} target The prototype to which to apply this schema.\n * @param opts\n */\n apply (target, opts: any = {}) {\n opts.getter = opts.getter || '_get'\n opts.setter = opts.setter || '_set'\n opts.unsetter = opts.unsetter || '_unset'\n opts.track = opts.track || this.track\n const properties = this.properties || {}\n utils.forOwn(properties, (schema, prop) => {\n Object.defineProperty(target, prop, this.makeDescriptor(prop, schema, opts))\n })\n }\n\n /**\n * Apply default values to the target object for missing values.\n *\n * @name Schema#applyDefaults\n * @method\n * @param {object} target The target to which to apply values for missing values.\n */\n applyDefaults (target) {\n if (!target) {\n return\n }\n const properties = this.properties || {}\n const hasSet = utils.isFunction(target.set) || utils.isFunction(target._set)\n utils.forOwn(properties, (schema, prop) => {\n if (schema.hasOwnProperty('default') && utils.get(target, prop) === undefined) {\n if (hasSet) {\n target.set(prop, utils.plainCopy(schema.default), { silent: true })\n } else {\n utils.set(target, prop, utils.plainCopy(schema.default))\n }\n }\n if (schema.type === 'object' && schema.properties) {\n if (hasSet) {\n const orig = target._get('noValidate')\n target._set('noValidate', true)\n utils.set(target, prop, utils.get(target, prop) || {}, { silent: true })\n target._set('noValidate', orig)\n } else {\n utils.set(target, prop, utils.get(target, prop) || {})\n }\n schema.applyDefaults(utils.get(target, prop))\n }\n })\n }\n\n /**\n * Assemble a property descriptor for tracking and validating changes to\n * a property according to the given schema. This method is called when\n * {@link Mapper#applySchema} is set to `true`.\n *\n * @name Schema#makeDescriptor\n * @method\n * @param {string} prop The property name.\n * @param {(Schema|object)} schema The schema for the property.\n * @param {object} [opts] Optional configuration.\n * @param {function} [opts.getter] Custom getter function.\n * @param {function} [opts.setter] Custom setter function.\n * @param {function} [opts.track] Whether to track changes.\n * @returns {object} A property descriptor for the given schema.\n */\n makeDescriptor (prop, schema, opts) {\n const descriptor: any = {\n // Better to allow configurability, but at the user's own risk\n configurable: true,\n // These properties are enumerable by default, but regardless of their\n // enumerability, they won't be \"own\" properties of individual records\n enumerable: schema.enumerable === undefined ? true : !!schema.enumerable,\n get () {\n return this._get(keyPath)\n },\n set (value) {\n // These are accessed a lot\n const _get = this[getter]\n const _set = this[setter]\n const _unset = this[unsetter]\n // Optionally check that the new value passes validation\n if (!_get(noValidatePath)) {\n const errors = schema.validate(value, { path: [prop] })\n if (errors) {\n // Immediately throw an error, preventing the record from getting into\n // an invalid state\n const error = new TsDataError(validationFailureMsg)\n error.errors = errors\n throw error\n }\n }\n // TODO: Make it so tracking can be turned on for all properties instead of\n // only per-property\n if (track && !_get(creatingPath)) {\n // previous is versioned on database commit\n // props are versioned on set()\n const previous = _get(previousPath)\n const current = _get(keyPath)\n let changing = _get(changingPath)\n let changed = _get(changedPath)\n\n if (!changing) {\n // Track properties that are changing in the current event loop\n changed = []\n }\n\n // Add changing properties to this array once at most\n const index = changed.indexOf(prop)\n if (current !== value && index === -1) {\n changed.push(prop)\n }\n if (previous === value) {\n if (index >= 0) {\n changed.splice(index, 1)\n }\n }\n // No changes in current event loop\n if (!changed.length) {\n changing = false\n _unset(changingPath)\n _unset(changedPath)\n // Cancel pending change event\n if (_get(eventIdPath)) {\n clearTimeout(_get(eventIdPath))\n _unset(eventIdPath)\n }\n }\n // Changes detected in current event loop\n if (!changing && changed.length) {\n _set(changedPath, changed)\n _set(changingPath, true)\n // Saving the timeout id allows us to batch all changes in the same\n // event loop into a single \"change\"\n // TODO: Optimize\n _set(\n eventIdPath,\n setTimeout(() => {\n // Previous event loop where changes were gathered has ended, so\n // notify any listeners of those changes and prepare for any new\n // changes\n _unset(changedPath)\n _unset(eventIdPath)\n _unset(changingPath)\n // TODO: Optimize\n if (!_get(silentPath)) {\n let i\n for (i = 0; i < changed.length; i++) {\n this.emit('change:' + changed[i], this, utils.get(this, changed[i]))\n }\n\n const changes = utils.diffObjects({ [prop]: value }, { [prop]: current })\n\n if (_get(keepChangeHistoryPath)) {\n const changeRecord = utils.plainCopy(changes)\n changeRecord.timestamp = new Date().getTime()\n let changeHistory = _get(changeHistoryPath)\n if (!changeHistory) _set(changeHistoryPath, (changeHistory = []))\n changeHistory.push(changeRecord)\n }\n this.emit('change', this, changes)\n }\n _unset(silentPath)\n }, 0)\n )\n }\n }\n _set(keyPath, value)\n return value\n }\n }\n // Cache a few strings for optimal performance\n const keyPath = `props.${prop}`\n const previousPath = `previous.${prop}`\n const getter = opts.getter\n const setter = opts.setter\n const unsetter = opts.unsetter\n const track = utils.isBoolean(opts.track) ? opts.track : schema.track\n\n if (utils.isFunction(schema.get)) {\n const originalGet = descriptor.get\n descriptor.get = function () {\n return schema.get.call(this, originalGet)\n }\n }\n\n if (utils.isFunction(schema.set)) {\n const originalSet = descriptor.set\n descriptor.set = function (value) {\n return schema.set.call(this, value, originalSet)\n }\n }\n\n return descriptor\n }\n\n /**\n * Create a copy of the given value that contains only the properties defined\n * in this schema.\n *\n * @name Schema#pick\n * @method\n * @param {*} value The value to copy.\n * @returns {*} The copy.\n */\n pick (value, opts?) {\n if (value === undefined) {\n return\n }\n if (this.type === 'object') {\n const copy = {}\n const properties = this.properties\n if (properties) {\n utils.forOwn(properties, (_definition, prop) => {\n copy[prop] = _definition.pick(value[prop])\n })\n }\n if (this.extends) {\n utils.fillIn(copy, this.extends.pick(value))\n }\n // Conditionally copy properties not defined in \"properties\"\n if (this.additionalProperties) {\n for (const key in value) {\n if (!properties[key]) {\n copy[key] = utils.plainCopy(value[key])\n }\n }\n }\n return copy\n } else if (this.type === 'array') {\n return value.map(item => {\n const _copy = this.items ? this.items.pick(item) : {}\n if (this.extends) {\n utils.fillIn(_copy, this.extends.pick(item))\n }\n return _copy\n })\n }\n return utils.plainCopy(value)\n }\n\n /**\n * Validate the provided value against this schema.\n *\n * @name Schema#validate\n * @method\n * @param {*} value Value to validate.\n * @param {object} [opts] Configuration options.\n * @returns {(array|undefined)} Array of errors or `undefined` if valid.\n */\n validate (value, opts?) {\n return validate(value, this, opts)\n }\n\n static ANY_OPS = ANY_OPS;\n static ARRAY_OPS = ARRAY_OPS;\n static NUMERIC_OPS = NUMERIC_OPS;\n static OBJECT_OPS = OBJECT_OPS;\n static STRING_OPS = STRING_OPS;\n static typeGroupValidators = typeGroupValidators;\n static types = types;\n static validate = validate;\n static validationKeywords: any = validationKeywords;\n}\n","import utils from '../utils'\nimport { Relation } from '../Relation'\n\nexport class BelongsToRelation extends Relation {\n getForeignKey (record) {\n return utils.get(record, this.foreignKey)\n }\n\n _setForeignKey (record, relatedRecord) {\n utils.set(record, this.foreignKey, utils.get(relatedRecord, this.getRelation().idAttribute))\n }\n\n findExistingLinksFor (record) {\n // console.log('\\tBelongsTo#findExistingLinksFor', record)\n if (!record) {\n return\n }\n const relatedId = utils.get(record, this.foreignKey)\n if (relatedId !== undefined && relatedId !== null) {\n return this.relatedCollection.get(relatedId)\n }\n }\n\n isRequiresParentId () {\n return true\n }\n\n createParentRecord (props, opts) {\n const relationData = this.getLocalField(props)\n\n return this.createLinked(relationData, opts).then(record => {\n this.setForeignKey(props, record)\n })\n }\n\n createChildRecord () {\n throw new Error('\"BelongsTo\" relation does not support child creation as it cannot have children.')\n }\n\n static TYPE_NAME = 'belongsTo';\n}\n","import utils from '../utils'\nimport { Relation } from '../Relation'\n\nexport class HasManyRelation extends Relation {\n foreignKeys: any;\n localKeys: any;\n validateOptions (related, opts) {\n super.validateOptions(related, opts)\n\n const { localKeys, foreignKeys, foreignKey } = opts\n\n if (!foreignKey && !localKeys && !foreignKeys) {\n throw utils.err('new Relation', 'opts.')(400, 'string', foreignKey)\n }\n }\n\n canFindLinkFor (record) {\n const hasForeignKeys = this.foreignKey || this.foreignKeys\n return !!(hasForeignKeys || (this.localKeys && utils.get(record, this.localKeys)))\n }\n\n linkRecord (record, relatedRecords) {\n const relatedCollection = this.relatedCollection\n const canAutoAddLinks = this.canAutoAddLinks\n const foreignKey = this.foreignKey\n const unsaved = this.relatedCollection.unsaved()\n\n return relatedRecords.map(relatedRecord => {\n const relatedId = relatedCollection.recordId(relatedRecord)\n\n if (\n (relatedId === undefined && unsaved.indexOf(relatedRecord) === -1) ||\n relatedRecord !== relatedCollection.get(relatedId)\n ) {\n if (foreignKey) {\n // TODO: slow, could be optimized? But user loses hook\n this.setForeignKey(record, relatedRecord)\n }\n if (canAutoAddLinks) {\n relatedRecord = relatedCollection.add(relatedRecord)\n }\n }\n\n return relatedRecord\n })\n }\n\n findExistingLinksFor (record) {\n const id = utils.get(record, this.mapper.idAttribute)\n const ids = this.localKeys ? utils.get(record, this.localKeys) : null\n let records\n\n if (id !== undefined && this.foreignKey) {\n records = this.findExistingLinksByForeignKey(id)\n } else if (this.localKeys && ids) {\n records = this.findExistingLinksByLocalKeys(ids)\n } else if (id !== undefined && this.foreignKeys) {\n records = this.findExistingLinksByForeignKeys(id)\n }\n\n if (records?.length) {\n return records\n }\n }\n\n // e.g. user hasMany group via \"foreignKeys\", so find all users of a group\n findExistingLinksByLocalKeys (ids) {\n return this.relatedCollection.filter({\n where: {\n [this.relatedCollection.mapper.idAttribute]: {\n in: ids\n }\n }\n })\n }\n\n // e.g. group hasMany user via \"localKeys\", so find all groups that own a user\n findExistingLinksByForeignKeys (id) {\n return this.relatedCollection.filter({\n where: {\n [this.foreignKeys]: {\n contains: id\n }\n }\n })\n }\n\n isRequiresParentId () {\n return !!this.localKeys && this.localKeys.length > 0\n }\n\n isRequiresChildId () {\n return !!this.foreignKey\n }\n\n createParentRecord (props, opts) {\n const relationData = this.getLocalField(props)\n const foreignIdField = this.getRelation().idAttribute\n\n return this.createLinked(relationData, opts).then(records => {\n utils.set(\n props,\n this.localKeys,\n records.map(record => utils.get(record, foreignIdField))\n )\n })\n }\n\n createLinked (props, opts) {\n return this.getRelation().createMany(props, opts)\n }\n\n static TYPE_NAME = 'hasMany';\n}\n","import utils from '../utils'\nimport { Relation } from '../Relation'\n\nexport class HasOneRelation extends Relation {\n findExistingLinksFor (relatedMapper, record) {\n const recordId = utils.get(record, relatedMapper.idAttribute)\n const records = this.findExistingLinksByForeignKey(recordId)\n\n if (records?.length) {\n return records[0]\n }\n }\n\n isRequiresChildId () {\n return true\n }\n\n static TYPE_NAME = 'hasOne';\n}\n","import { Relation } from './Relation'\nimport { BelongsToRelation } from './Relation/BelongsTo'\nimport { HasManyRelation } from './Relation/HasMany'\nimport { HasOneRelation } from './Relation/HasOne';\n\n[BelongsToRelation, HasManyRelation, HasOneRelation].forEach(RelationType => {\n Relation[RelationType.TYPE_NAME] = (related, options) => new RelationType(related, options)\n})\n\nexport { belongsToType, hasManyType, hasOneType, Relation } from './Relation'\n","import { Relation } from './relations'\n\nexport { belongsToType, hasManyType, hasOneType } from './relations'\n\n/**\n * BelongsTo relation decorator. You probably won't use this directly.\n *\n * @method\n * @param {Mapper} related The relation the target belongs to.\n * @param {object} opts Configuration options.\n * @param {string} opts.foreignKey The field that holds the primary key of the\n * related record.\n * @param {string} opts.localField The field that holds a reference to the\n * related record object.\n * @returns {Function} Invocation function, which accepts the target as the only\n * parameter.\n */\nexport function belongsTo (related, opts) {\n return mapper => {\n Relation.belongsTo(related, opts).assignTo(mapper)\n }\n}\n\n/**\n * HasMany relation decorator. You probably won't use this directly.\n *\n * @method\n * @param {Mapper} related The relation of which the target has many.\n * @param {object} opts Configuration options.\n * @param {string} [opts.foreignKey] The field that holds the primary key of the\n * related record.\n * @param {string} opts.localField The field that holds a reference to the\n * related record object.\n * @returns {Function} Invocation function, which accepts the target as the only\n * parameter.\n */\nexport function hasMany (related, opts) {\n return mapper => {\n Relation.hasMany(related, opts).assignTo(mapper)\n }\n}\n\n/**\n * HasOne relation decorator. You probably won't use this directly.\n *\n * @method\n * @param {Mapper} related The relation of which the target has one.\n * @param {object} opts Configuration options.\n * @param {string} [opts.foreignKey] The field that holds the primary key of the\n * related record.\n * @param {string} opts.localField The field that holds a reference to the\n * related record object.\n * @returns {Function} Invocation function, which accepts the target as the only\n * parameter.\n */\nexport function hasOne (related, opts) {\n return mapper => {\n Relation.hasOne(related, opts).assignTo(mapper)\n }\n}\n","import utils from './utils'\nimport Component from './Component'\nimport Record from './Record'\nimport Schema, { PropertyDefinition, SchemaDefinition } from './Schema'\nimport { Relation } from './Relation'\nimport { belongsTo, belongsToType, hasMany, hasManyType, hasOne, hasOneType } from './decorators'\nimport { TsDataError } from './TsDataError'\nimport { QueryDefinition } from './Query'\n\nconst DOMAIN = 'Mapper'\nconst applyDefaultsHooks = ['beforeCreate', 'beforeCreateMany']\nconst validatingHooks = ['beforeCreate', 'beforeCreateMany', 'beforeUpdate', 'beforeUpdateAll', 'beforeUpdateMany']\n\nfunction makeNotify (num) {\n return function (...args) {\n const opts = args[args.length - num]\n const op = opts.op\n this.dbg(op, ...args)\n\n if (applyDefaultsHooks.indexOf(op) !== -1 && opts.applyDefaults !== false) {\n const schema = this.getSchema()\n if (schema?.applyDefaults) {\n let toProcess = args[0]\n if (!utils.isArray(toProcess)) {\n toProcess = [toProcess]\n }\n toProcess.forEach(record => {\n schema.applyDefaults(record)\n })\n }\n }\n\n // Automatic validation\n if (validatingHooks.indexOf(op) !== -1 && !opts.noValidate) {\n // Save current value of option\n const originalExistingOnly = opts.existingOnly\n\n // For updates, ignore required fields if they aren't present\n if (op.indexOf('beforeUpdate') === 0 && opts.existingOnly === undefined) {\n opts.existingOnly = true\n }\n const errors = this.validate(args[op === 'beforeUpdate' ? 1 : 0], utils.pick(opts, ['existingOnly']))\n\n // Restore option\n opts.existingOnly = originalExistingOnly\n\n // Abort lifecycle due to validation errors\n if (errors) {\n const err = new TsDataError('validation failed')\n err.errors = errors\n return utils.reject(err)\n }\n }\n\n // Emit lifecycle event\n if (opts.notify || (opts.notify === undefined && this.notify)) {\n setTimeout(() => {\n this.emit(op, ...args)\n })\n }\n }\n}\n\n// These are the default implementations of all of the lifecycle hooks\nconst notify = makeNotify(1)\nconst notify2 = makeNotify(2)\n\n// This object provides meta information used by Mapper#crud to actually\n// execute each lifecycle method\nconst LIFECYCLE_METHODS = {\n count: {\n defaults: [{}, {}],\n skip: true,\n types: []\n },\n destroy: {\n defaults: [{}, {}],\n skip: true,\n types: []\n },\n destroyAll: {\n defaults: [{}, {}],\n skip: true,\n types: []\n },\n find: {\n defaults: [undefined, {}],\n types: []\n },\n findAll: {\n defaults: [{}, {}],\n types: []\n },\n sum: {\n defaults: [undefined, {}, {}],\n skip: true,\n types: []\n },\n update: {\n adapterArgs (mapper, id, props, opts) {\n return [id, mapper.toJSON(props, opts), opts]\n },\n beforeAssign: 1,\n defaults: [undefined, {}, {}],\n types: []\n },\n updateAll: {\n adapterArgs (mapper, props, query, opts) {\n return [mapper.toJSON(props, opts), query, opts]\n },\n beforeAssign: 0,\n defaults: [{}, {}, {}],\n types: []\n },\n updateMany: {\n adapterArgs (mapper, records, opts) {\n return [records.map(record => mapper.toJSON(record, opts)), opts]\n },\n beforeAssign: 0,\n defaults: [[], {}],\n types: []\n }\n}\n\nexport interface MapperOpts {\n name?: string\n\n [customAttr: string]: any\n\n endpoint?: string\n\n onConflict?: 'skip'\n\n relations?: any\n\n type?: string\n\n schema?: SchemaDefinition | Schema\n\n recordClass?: typeof Record | boolean\n\n wrap?: boolean\n\n methods?: { [name: string]: Function }\n\n scopes?: any\n\n mapperClass?: typeof Mapper\n\n /**\n * Hash of registered adapters. Don't modify directly. Use\n * {@link Mapper#registerAdapter} instead.\n *\n * @default {}\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/connecting-to-a-data-source\",\"Connecting to a data source\"]\n */\n _adapters?: {}\n\n /**\n * Whether {@link Mapper#beforeCreate} and {@link Mapper#beforeCreateMany}\n * should automatically receive default values according to the Mapper's schema.\n *\n * @default true\n * @since 3.0.0\n */\n applyDefaults?: boolean\n\n /**\n * Whether to augment {@link Mapper#recordClass} with ES5 getters and setters\n * according to the properties defined in {@link Mapper#schema}. This makes\n * possible validation and change tracking on individual properties\n * when using the dot (e.g. `user.name = \"Bob\"`) operator to modify a\n * property, and is `true` by default.\n *\n * @default true\n * @since 3.0.0\n */\n applySchema?: boolean\n\n /**\n * The name of the registered adapter that this Mapper should used by default.\n *\n * @default \"http\"\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/connecting-to-a-data-source\",\"Connecting to a data source\"]\n */\n defaultAdapter?: string\n\n /**\n * The field used as the unique identifier on records handled by this Mapper.\n *\n * @default id\n * @since 3.0.0\n */\n idAttribute?: string\n\n properties?: { [name: string]: PropertyDefinition }\n\n /**\n * Whether records created from this mapper keep changeHistory on property changes.\n *\n * @default true\n * @since 3.0.0\n */\n keepChangeHistory?: boolean\n\n /**\n * Whether this Mapper should emit operational events.\n *\n * @default true\n * @since 3.0.0\n */\n notify?: boolean\n\n /**\n * Whether to skip validation when the Record instances are created.\n *\n * @default false\n * @since 3.0.0\n */\n noValidate?: boolean\n\n /**\n * Whether {@link Mapper#create}, {@link Mapper#createMany},\n * {@link Mapper#update}, {@link Mapper#updateAll}, {@link Mapper#updateMany},\n * {@link Mapper#find}, {@link Mapper#findAll}, {@link Mapper#destroy},\n * {@link Mapper#destroyAll}, {@link Mapper#count}, and {@link Mapper#sum}\n * should return a raw result object that contains both the instance data\n * returned by the adapter _and_ metadata about the operation.\n *\n * The default is to NOT return the result object, and instead return just the\n * instance data.\n *\n * @default false\n * @since 3.0.0\n */\n raw?: boolean\n\n /**\n * Whether records created from this mapper automatically validate their properties\n * when their properties are modified.\n *\n * @default true\n * @since 3.0.0\n */\n validateOnSet?: boolean\n}\n\nconst MAPPER_DEFAULTS: MapperOpts = {\n _adapters: {},\n applyDefaults: true,\n applySchema: true,\n defaultAdapter: 'http',\n idAttribute: 'id',\n keepChangeHistory: true,\n notify: true,\n noValidate: false,\n raw: false,\n validateOnSet: true\n}\n\n/**\n * The core of JSData's [ORM/ODM][orm] implementation. Given a minimum amount of\n * meta information about a resource, a Mapper can perform generic CRUD\n * operations against that resource. Apart from its configuration, a Mapper is\n * stateless. The particulars of various persistence layers have been abstracted\n * into adapters, which a Mapper uses to perform its operations.\n *\n * The term \"Mapper\" comes from the [Data Mapper Pattern][pattern] described in\n * Martin Fowler's [Patterns of Enterprise Application Architecture][book]. A\n * Data Mapper moves data between [in-memory object instances][record] and a\n * relational or document-based database. JSData's Mapper can work with any\n * persistence layer you can write an adapter for.\n *\n * _(\"Model\" is a heavily overloaded term and is avoided in this documentation\n * to prevent confusion.)_\n *\n * [orm]: https://en.wikipedia.org/wiki/Object-relational_mapping\n *\n * @example\n * [pattern]: https://en.wikipedia.org/wiki/Data_mapper_pattern\n * [book]: http://martinfowler.com/books/eaa.html\n * [record]: Record.html\n * // Import and instantiate\n * import { Mapper } from 'js-data';\n * const UserMapper = new Mapper({ name: 'user' });\n *\n * @example\n * // Define a Mapper using the Container component\n * import { Container } from 'js-data';\n * const store = new Container();\n * store.defineMapper('user');\n *\n * @class Mapper\n * @extends Component\n * @param {object} opts Configuration options.\n * @param {boolean} [opts.applySchema=true] See {@link Mapper#applySchema}.\n * @param {boolean} [opts.debug=false] See {@link Component#debug}.\n * @param {string} [opts.defaultAdapter=http] See {@link Mapper#defaultAdapter}.\n * @param {string} [opts.idAttribute=id] See {@link Mapper#idAttribute}.\n * @param {object} [opts.methods] See {@link Mapper#methods}.\n * @param {string} opts.name See {@link Mapper#name}.\n * @param {boolean} [opts.notify] See {@link Mapper#notify}.\n * @param {boolean} [opts.raw=false] See {@link Mapper#raw}.\n * @param {Function|boolean} [opts.recordClass] See {@link Mapper#recordClass}.\n * @param {Object|Schema} [opts.schema] See {@link Mapper#schema}.\n * @returns {Mapper} A new {@link Mapper} instance.\n * @see http://www.js-data.io/v3.0/docs/components-of-jsdata#mapper\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/components-of-jsdata#mapper\",\"Components of JSData: Mapper\"]\n * @tutorial [\"http://www.js-data.io/v3.0/docs/modeling-your-data\",\"Modeling your data\"]\n */\nexport default class Mapper extends Component {\n idAttribute: string;\n\n name: string;\n /**\n * This Mapper's {@link Schema}.\n *\n * @example Mapper#schema\n * const JSData = require('js-data');\n * const { Mapper } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const UserMapper = new Mapper({\n * name: 'user',\n * schema: {\n * properties: {\n * id: { type: 'number' },\n * first: { type: 'string', track: true },\n * last: { type: 'string', track: true },\n * role: { type: 'string', track: true, required: true },\n * age: { type: 'integer', track: true },\n * is_active: { type: 'number' }\n * }\n * }\n * });\n * const user = UserMapper.createRecord({\n * id: 1,\n * name: 'John',\n * role: 'admin'\n * });\n * user.on('change', function (user, changes) {\n * console.log(changes);\n * });\n * user.on('change:role', function (user, value) {\n * console.log('change:role - ' + value);\n * });\n * user.role = 'owner';\n *\n * @name Mapper#schema\n * @see Schema\n * @since 3.0.0\n * @type {Schema}\n */\n schema: Schema;\n /**\n * Set to `false` to force the Mapper to work with POJO objects only.\n *\n * @example\n * // Use POJOs only.\n * import { Mapper, Record } from 'js-data';\n * const UserMapper = new Mapper({ recordClass: false });\n * UserMapper.recordClass // false;\n * const user = UserMapper.createRecord();\n * user instanceof Record; // false\n *\n * @example\n * // Set to a custom class to have records wrapped in your custom class.\n * import { Mapper, Record } from 'js-data';\n * // Custom class\n * class User {\n * constructor (props = {}) {\n * for (var key in props) {\n * if (props.hasOwnProperty(key)) {\n * this[key] = props[key];\n * }\n * }\n * }\n * }\n * const UserMapper = new Mapper({ recordClass: User });\n * UserMapper.recordClass; // function User() {}\n * const user = UserMapper.createRecord();\n * user instanceof Record; // false\n * user instanceof User; // true\n *\n *\n * @example\n * // Extend the {@link Record} class.\n * import { Mapper, Record } from 'js-data';\n * // Custom class\n * class User extends Record {\n * constructor () {\n * super(props);\n * }\n * }\n * const UserMapper = new Mapper({ recordClass: User });\n * UserMapper.recordClass; // function User() {}\n * const user = UserMapper.createRecord();\n * user instanceof Record; // true\n * user instanceof User; // true\n *\n * @name Mapper#recordClass\n * @default {@link Record}\n * @see Record\n * @since 3.0.0\n */\n recordClass: typeof Record | Function | false | any;\n methods: any;\n applySchema: any;\n relationList: any;\n defaultAdapter: any;\n relationFields: any;\n _adapters: any;\n relations: any;\n /**\n * The meta information describing this Mapper's available lifecycle\n * methods. __Do not modify.__\n *\n * @name Mapper#lifecycleMethods\n * @since 3.0.0\n * @type {Object}\n */\n lifecycleMethods = LIFECYCLE_METHODS;\n\n /**\n * The {@link Container} that holds this Mapper. __Do not modify.__\n *\n * @name Mapper#lifecycleMethods\n * @since 3.0.0\n * @type {Object}\n */\n datastore: any;\n validateOnSet: any;\n keepChangeHistory: any;\n\n constructor (opts: MapperOpts = {}) {\n super()\n\n // Apply user-provided configuration\n utils.fillIn(this, opts)\n // Fill in any missing options with the defaults\n utils.fillIn(this, utils.copy(MAPPER_DEFAULTS))\n\n /**\n * The name for this Mapper. This is the minimum amount of meta information\n * required for a Mapper to be able to execute CRUD operations for a\n * Resource.\n *\n * @name Mapper#name\n * @since 3.0.0\n * @type {string}\n */\n if (!this.name) {\n throw utils.err(`new ${DOMAIN}`, 'opts.name')(400, 'string', this.name)\n }\n\n // Setup schema, with an empty default schema if necessary\n if (this.schema) {\n this.schema.type = this.schema.type || 'object'\n if (!(this.schema instanceof Schema)) {\n this.schema = new Schema(this.schema || { type: 'object' })\n }\n }\n\n // Create a subclass of Record that's tied to this Mapper\n if (this.recordClass === undefined) {\n // tslint:disable-next-line:max-classes-per-file\n this.recordClass = class TiedRecord extends Record {}\n }\n\n if (this.recordClass) {\n this.recordClass.mapper = this\n\n /**\n * Functions that should be added to the prototype of {@link Mapper#recordClass}.\n *\n * @name Mapper#methods\n * @since 3.0.0\n * @type {Object}\n */\n if (utils.isObject(this.methods)) {\n utils.addHiddenPropsToTarget(this.recordClass.prototype, this.methods)\n }\n\n // We can only apply the schema to the prototype of this.recordClass if the\n // class extends Record\n if (\n Record.prototype.isPrototypeOf(Object.create(this.recordClass.prototype)) &&\n this.schema &&\n this.schema.apply &&\n this.applySchema\n ) {\n this.schema.apply(this.recordClass.prototype)\n }\n }\n }\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#count}. If this method\n * returns a promise then {@link Mapper#count} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#afterCount\n * @param {object} query The `query` argument passed to {@link Mapper#count}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#count}.\n * @param {*} result The result, if any.\n * @since 3.0.0\n */\n afterCount = notify2;\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#create}. If this method\n * returns a promise then {@link Mapper#create} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#afterCreate\n * @param {object} props The `props` argument passed to {@link Mapper#create}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#create}.\n * @param {*} result The result, if any.\n * @since 3.0.0\n */\n afterCreate = notify2;\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#createMany}. If this method\n * returns a promise then {@link Mapper#createMany} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#afterCreateMany\n * @param {array} records The `records` argument passed to {@link Mapper#createMany}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#createMany}.\n * @param {*} result The result, if any.\n * @since 3.0.0\n */\n afterCreateMany = notify2;\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#destroy}. If this method\n * returns a promise then {@link Mapper#destroy} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#afterDestroy\n * @param {(string|number)} id The `id` argument passed to {@link Mapper#destroy}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#destroy}.\n * @param {*} result The result, if any.\n * @since 3.0.0\n */\n afterDestroy = notify2;\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#destroyAll}. If this method\n * returns a promise then {@link Mapper#destroyAll} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#afterDestroyAll\n * @param {*} data The `data` returned by the adapter.\n * @param {query} query The `query` argument passed to {@link Mapper#destroyAll}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#destroyAll}.\n * @param {*} result The result, if any.\n * @since 3.0.0\n */\n afterDestroyAll = notify2;\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#find}. If this method\n * returns a promise then {@link Mapper#find} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#afterFind\n * @param {(string|number)} id The `id` argument passed to {@link Mapper#find}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#find}.\n * @param {*} result The result, if any.\n * @since 3.0.0\n */\n afterFind = notify2;\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#findAll}. If this method\n * returns a promise then {@link Mapper#findAll} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#afterFindAll\n * @param {object} query The `query` argument passed to {@link Mapper#findAll}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#findAll}.\n * @param {*} result The result, if any.\n * @since 3.0.0\n */\n afterFindAll = notify2;\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#sum}. If this method\n * returns a promise then {@link Mapper#sum} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#afterSum\n * @param {object} query The `query` argument passed to {@link Mapper#sum}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#sum}.\n * @param {*} result The result, if any.\n * @since 3.0.0\n */\n afterSum = notify2;\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#update}. If this method\n * returns a promise then {@link Mapper#update} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#afterUpdate\n * @param {(string|number)} id The `id` argument passed to {@link Mapper#update}.\n * @param {props} props The `props` argument passed to {@link Mapper#update}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#update}.\n * @param {*} result The result, if any.\n * @since 3.0.0\n */\n afterUpdate = notify2;\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#updateAll}. If this method\n * returns a promise then {@link Mapper#updateAll} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#afterUpdateAll\n * @param {object} props The `props` argument passed to {@link Mapper#updateAll}.\n * @param {object} query The `query` argument passed to {@link Mapper#updateAll}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#updateAll}.\n * @param {*} result The result, if any.\n * @since 3.0.0\n */\n afterUpdateAll = notify2;\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#updateMany}. If this method\n * returns a promise then {@link Mapper#updateMany} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#afterUpdateMany\n * @param {array} records The `records` argument passed to {@link Mapper#updateMany}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#updateMany}.\n * @param {*} result The result, if any.\n * @since 3.0.0\n */\n afterUpdateMany = notify2;\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#create}. If this method\n * returns a promise then {@link Mapper#create} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#beforeCreate\n * @param {object} props The `props` argument passed to {@link Mapper#create}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#create}.\n * @since 3.0.0\n */\n beforeCreate = notify;\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#createMany}. If this method\n * returns a promise then {@link Mapper#createMany} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#beforeCreateMany\n * @param {array} records The `records` argument passed to {@link Mapper#createMany}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#createMany}.\n * @since 3.0.0\n */\n beforeCreateMany = notify;\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#count}. If this method\n * returns a promise then {@link Mapper#count} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#beforeCount\n * @param {object} query The `query` argument passed to {@link Mapper#count}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#count}.\n * @since 3.0.0\n */\n beforeCount = notify;\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#destroy}. If this method\n * returns a promise then {@link Mapper#destroy} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#beforeDestroy\n * @param {(string|number)} id The `id` argument passed to {@link Mapper#destroy}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#destroy}.\n * @since 3.0.0\n */\n beforeDestroy = notify;\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#destroyAll}. If this method\n * returns a promise then {@link Mapper#destroyAll} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#beforeDestroyAll\n * @param {query} query The `query` argument passed to {@link Mapper#destroyAll}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#destroyAll}.\n * @since 3.0.0\n */\n beforeDestroyAll = notify;\n\n /**\n * Mappers lifecycle hook called by {@link Mapper#find}. If this method\n * returns a promise then {@link Mapper#find} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#beforeFind\n * @param {(string|number)} id The `id` argument passed to {@link Mapper#find}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#find}.\n * @since 3.0.0\n */\n beforeFind = notify;\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#findAll}. If this method\n * returns a promise then {@link Mapper#findAll} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#beforeFindAll\n * @param {object} query The `query` argument passed to {@link Mapper#findAll}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#findAll}.\n * @since 3.0.0\n */\n beforeFindAll = notify;\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#sum}. If this method\n * returns a promise then {@link Mapper#sum} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#beforeSum\n * @param {string} field The `field` argument passed to {@link Mapper#sum}.\n * @param {object} query The `query` argument passed to {@link Mapper#sum}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#sum}.\n * @since 3.0.0\n */\n beforeSum = notify;\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#update}. If this method\n * returns a promise then {@link Mapper#update} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#beforeUpdate\n * @param {(string|number)} id The `id` argument passed to {@link Mapper#update}.\n * @param {props} props The `props` argument passed to {@link Mapper#update}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#update}.\n * @since 3.0.0\n */\n beforeUpdate = notify;\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#updateAll}. If this method\n * returns a promise then {@link Mapper#updateAll} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#beforeUpdateAll\n * @param {object} props The `props` argument passed to {@link Mapper#updateAll}.\n * @param {object} query The `query` argument passed to {@link Mapper#updateAll}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#updateAll}.\n * @since 3.0.0\n */\n beforeUpdateAll = notify;\n\n /**\n * Mapper lifecycle hook called by {@link Mapper#updateMany}. If this method\n * returns a promise then {@link Mapper#updateMany} will wait for the promise\n * to resolve before continuing.\n *\n * @method Mapper#beforeUpdateMany\n * @param {array} records The `records` argument passed to {@link Mapper#updateMany}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#updateMany}.\n * @since 3.0.0\n */\n beforeUpdateMany = notify;\n\n /**\n * This method is called at the end of most lifecycle methods. It does the\n * following:\n *\n * 1. If `opts.raw` is `true`, add this Mapper's configuration to the `opts`\n * argument as metadata for the operation.\n * 2. Wrap the result data appropriately using {@link Mapper#wrap}, which\n * calls {@link Mapper#createRecord}.\n *\n * @method Mapper#_end\n * @private\n * @since 3.0.0\n */\n _end (result, opts, skip = false) {\n if (opts.raw) {\n utils._(result, opts)\n }\n if (skip) {\n return result\n }\n let _data = opts.raw ? result.data : result\n if (_data && utils.isFunction(this.wrap)) {\n _data = this.wrap(_data, opts)\n if (opts.raw) {\n result.data = _data\n } else {\n result = _data\n }\n }\n return result\n }\n\n /**\n * Define a belongsTo relationship. Only useful if you're managing your\n * Mappers manually and not using a Container or DataStore component.\n *\n * @example\n * PostMapper.belongsTo(UserMapper, {\n * // post.user_id points to user.id\n * foreignKey: 'user_id'\n * // user records will be attached to post records at \"post.user\"\n * localField: 'user'\n * });\n *\n * CommentMapper.belongsTo(UserMapper, {\n * // comment.user_id points to user.id\n * foreignKey: 'user_id'\n * // user records will be attached to comment records at \"comment.user\"\n * localField: 'user'\n * });\n * CommentMapper.belongsTo(PostMapper, {\n * // comment.post_id points to post.id\n * foreignKey: 'post_id'\n * // post records will be attached to comment records at \"comment.post\"\n * localField: 'post'\n * });\n *\n * @method Mapper#belongsTo\n * @see http://www.js-data.io/v3.0/docs/relations\n * @since 3.0.0\n */\n belongsTo (relatedMapper, opts) {\n return belongsTo(relatedMapper, opts)(this)\n }\n\n /**\n * Select records according to the `query` argument and return the count.\n *\n * {@link Mapper#beforeCount} will be called before calling the adapter.\n * {@link Mapper#afterCount} will be called after calling the adapter.\n *\n * @example\n * // Get the number of published blog posts\n * PostMapper.count({ status: 'published' }).then((numPublished) => {\n * console.log(numPublished); // e.g. 45\n * });\n *\n * @method Mapper#count\n * @param {object} [query={}] Selection query. See {@link query}.\n * @param {object} [query.where] See {@link query.where}.\n * @param {number} [query.offset] See {@link query.offset}.\n * @param {number} [query.limit] See {@link query.limit}.\n * @param {string|Array[]} [query.orderBy] See {@link query.orderBy}.\n * @param {object} [opts] Configuration options. Refer to the `count` method\n * of whatever adapter you're using for more configuration options.\n * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the\n * adapter to use.\n * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}.\n * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}.\n * @returns {Promise} Resolves with the count of the selected records.\n * @since 3.0.0\n */\n count (query, opts?) {\n return this.crud('count', query, opts)\n }\n\n /**\n * Fired during {@link Mapper#create}. See\n * {@link Mapper~beforeCreateListener} for how to listen for this event.\n *\n * @event Mapper#beforeCreate\n * @see Mapper~beforeCreateListener\n * @see Mapper#create\n */\n /**\n * Callback signature for the {@link Mapper#event:beforeCreate} event.\n *\n * @example\n * function onBeforeCreate (props, opts) {\n * // do something\n * }\n * store.on('beforeCreate', onBeforeCreate);\n *\n * @callback Mapper~beforeCreateListener\n * @param {object} props The `props` argument passed to {@link Mapper#beforeCreate}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#beforeCreate}.\n * @see Mapper#event:beforeCreate\n * @see Mapper#create\n * @since 3.0.0\n */\n /**\n * Fired during {@link Mapper#create}. See\n * {@link Mapper~afterCreateListener} for how to listen for this event.\n *\n * @event Mapper#afterCreate\n * @see Mapper~afterCreateListener\n * @see Mapper#create\n */\n\n /**\n * Callback signature for the {@link Mapper#event:afterCreate} event.\n *\n * @example\n * function onAfterCreate (props, opts, result) {\n * // do something\n * }\n * store.on('afterCreate', onAfterCreate);\n *\n * @callback Mapper~afterCreateListener\n * @param {object} props The `props` argument passed to {@link Mapper#afterCreate}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#afterCreate}.\n * @param {object} result The `result` argument passed to {@link Mapper#afterCreate}.\n * @see Mapper#event:afterCreate\n * @see Mapper#create\n * @since 3.0.0\n */\n /**\n * Create and save a new the record using the provided `props`.\n *\n * {@link Mapper#beforeCreate} will be called before calling the adapter.\n * {@link Mapper#afterCreate} will be called after calling the adapter.\n *\n * @example\n * // Create and save a new blog post\n * PostMapper.create({\n * title: 'Modeling your data',\n * status: 'draft'\n * }).then((post) => {\n * console.log(post); // { id: 1234, status: 'draft', ... }\n * });\n *\n * @fires Mapper#beforeCreate\n * @fires Mapper#afterCreate\n * @method Mapper#create\n * @param {object} props The properties for the new record.\n * @param {object} [opts] Configuration options. Refer to the `create` method\n * of whatever adapter you're using for more configuration options.\n * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the\n * adapter to use.\n * @param {boolean} [opts.noValidate={@link Mapper#noValidate}] See {@link Mapper#noValidate}.\n * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}.\n * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}.\n * @param {string[]} [opts.with=[]] Relations to create in a cascading\n * create if `props` contains nested relations. NOT performed in a\n * transaction. Each nested create will result in another {@link Mapper#create}\n * or {@link Mapper#createMany} call.\n * @param {string[]} [opts.pass=[]] Relations to send to the adapter as part\n * of the payload. Normally relations are not sent.\n * @returns {Promise} Resolves with the created record.\n * @since 3.0.0\n */\n create (props: any = {}, opts: any = {}) {\n const originalRecord = props\n let parentRelationMap = {}\n let adapterResponse: any = {}\n\n // Fill in \"opts\" with the Mapper's configuration\n utils._(opts, this)\n opts.adapter = this.getAdapterName(opts)\n\n opts.op = 'beforeCreate'\n return this._runHook(opts.op, props, opts)\n .then(props => {\n opts.with = opts.with || []\n return this._createParentRecordIfRequired(props, opts)\n })\n .then(relationMap => {\n parentRelationMap = relationMap\n })\n .then(() => {\n opts.op = 'create'\n return this._invokeAdapterMethod(opts.op, props, opts)\n })\n .then(result => {\n adapterResponse = result\n })\n .then(() => {\n const createdProps = opts.raw ? adapterResponse.data : adapterResponse\n\n return this._createOrAssignChildRecordIfRequired(createdProps, {\n opts,\n parentRelationMap,\n originalProps: props\n })\n })\n .then(createdProps => {\n return this._commitChanges(originalRecord, createdProps)\n })\n .then(record => {\n if (opts.raw) {\n adapterResponse.data = record\n } else {\n adapterResponse = record\n }\n const result = this._end(adapterResponse, opts)\n opts.op = 'afterCreate'\n return this._runHook(opts.op, props, opts, result)\n })\n }\n\n _commitChanges (recordOrRecords, newValues) {\n if (utils.isArray(recordOrRecords)) {\n return recordOrRecords.map((record, i) => this._commitChanges(record, newValues[i]))\n }\n\n utils.set(recordOrRecords, newValues, { silent: true })\n\n if (utils.isFunction(recordOrRecords.commit)) {\n recordOrRecords.commit()\n }\n\n return recordOrRecords\n }\n\n /**\n * Use {@link Mapper#createRecord} instead.\n * @deprecated\n * @method Mapper#createInstance\n * @param {Object|Array} props See {@link Mapper#createRecord}.\n * @param {object} [opts] See {@link Mapper#createRecord}.\n * @returns {Object|Array} See {@link Mapper#createRecord}.\n * @see Mapper#createRecord\n * @since 3.0.0\n */\n createInstance (props, opts?) {\n return this.createRecord(props, opts)\n }\n\n /**\n * Creates parent record for relation types like BelongsTo or HasMany with localKeys\n * in order to satisfy foreignKey dependency (so called child records).\n * @param {object} props See {@link Mapper#create}.\n * @param {object} opts See {@link Mapper#create}.\n * @returns {Object} cached parent records map\n * @see Mapper#create\n * @since 3.0.0\n */\n _createParentRecordIfRequired (props, opts) {\n const tasks = []\n const relations = []\n\n utils.forEachRelation(this, opts, (def, optsCopy) => {\n if (!def.isRequiresParentId() || !def.getLocalField(props)) {\n return\n }\n\n optsCopy.raw = false\n relations.push(def)\n tasks.push(def.createParentRecord(props, optsCopy))\n })\n\n return Promise.all(tasks).then(records => {\n return relations.reduce((map, relation, index) => {\n relation.setLocalField(map, records[index])\n return map\n }, {})\n })\n }\n\n /**\n * Creates child record for relation types like HasOne or HasMany with foreignKey\n * in order to satisfy foreignKey dependency (so called parent records).\n * @param {object} props See {@link Mapper#create}.\n * @param {object} context contains collected information.\n * @param {object} context.opts See {@link Mapper#create}.\n * @param {object} context.parentRelationMap contains parent records map\n * @param {object} context.originalProps contains data passed into {@link Mapper#create} method\n * @return {Promise} updated props\n * @see Mapper#create\n * @since 3.0.0\n */\n _createOrAssignChildRecordIfRequired (props, context) {\n const tasks = []\n\n utils.forEachRelation(this, context.opts, (def, optsCopy) => {\n const relationData = def.getLocalField(context.originalProps)\n\n if (!relationData) {\n return\n }\n\n optsCopy.raw = false\n // Create hasMany and hasOne after the main create because we needed\n // a generated id to attach to these items\n if (def.isRequiresChildId()) {\n tasks.push(def.createChildRecord(props, relationData, optsCopy))\n } else if (def.isRequiresParentId()) {\n const parent = def.getLocalField(context.parentRelationMap)\n\n if (parent) {\n def.setLocalField(props, parent)\n }\n }\n })\n\n return Promise.all(tasks).then(() => props)\n }\n\n /**\n * Fired during {@link Mapper#createMany}. See\n * {@link Mapper~beforeCreateManyListener} for how to listen for this event.\n *\n * @event Mapper#beforeCreateMany\n * @see Mapper~beforeCreateManyListener\n * @see Mapper#createMany\n */\n /**\n * Callback signature for the {@link Mapper#event:beforeCreateMany} event.\n *\n * @example\n * function onBeforeCreateMany (records, opts) {\n * // do something\n * }\n * store.on('beforeCreateMany', onBeforeCreateMany);\n *\n * @callback Mapper~beforeCreateManyListener\n * @param {object} records The `records` argument received by {@link Mapper#beforeCreateMany}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeCreateMany}.\n * @see Mapper#event:beforeCreateMany\n * @see Mapper#createMany\n * @since 3.0.0\n */\n /**\n * Fired during {@link Mapper#createMany}. See\n * {@link Mapper~afterCreateManyListener} for how to listen for this event.\n *\n * @event Mapper#afterCreateMany\n * @see Mapper~afterCreateManyListener\n * @see Mapper#createMany\n */\n\n /**\n * Callback signature for the {@link Mapper#event:afterCreateMany} event.\n *\n * @example\n * function onAfterCreateMany (records, opts, result) {\n * // do something\n * }\n * store.on('afterCreateMany', onAfterCreateMany);\n *\n * @callback Mapper~afterCreateManyListener\n * @param {object} records The `records` argument received by {@link Mapper#afterCreateMany}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterCreateMany}.\n * @param {object} result The `result` argument received by {@link Mapper#afterCreateMany}.\n * @see Mapper#event:afterCreateMany\n * @see Mapper#createMany\n * @since 3.0.0\n */\n /**\n * Given an array of records, batch create them via an adapter.\n *\n * {@link Mapper#beforeCreateMany} will be called before calling the adapter.\n * {@link Mapper#afterCreateMany} will be called after calling the adapter.\n *\n * @example\n * // Create and save several new blog posts\n * PostMapper.createMany([{\n * title: 'Modeling your data',\n * status: 'draft'\n * }, {\n * title: 'Reading data',\n * status: 'draft'\n * }]).then((posts) => {\n * console.log(posts[0]); // { id: 1234, status: 'draft', ... }\n * console.log(posts[1]); // { id: 1235, status: 'draft', ... }\n * });\n *\n * @fires Mapper#beforeCreate\n * @fires Mapper#afterCreate\n * @method Mapper#createMany\n * @param {Record[]} records Array of records to be created in one batch.\n * @param {object} [opts] Configuration options. Refer to the `createMany`\n * method of whatever adapter you're using for more configuration options.\n * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the\n * adapter to use.\n * @param {boolean} [opts.noValidate={@link Mapper#noValidate}] See {@link Mapper#noValidate}.\n * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}.\n * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}.\n * @param {string[]} [opts.with=[]] Relations to create in a cascading\n * create if `records` contains nested relations. NOT performed in a\n * transaction. Each nested create will result in another {@link Mapper#createMany}\n * call.\n * @param {string[]} [opts.pass=[]] Relations to send to the adapter as part\n * of the payload. Normally relations are not sent.\n * @returns {Promise} Resolves with the created records.\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/saving-data\",\"Saving data\"]\n */\n createMany (records = [], opts: any = {}) {\n // Default values for arguments\n const originalRecords = records\n let adapterResponse\n\n // Fill in \"opts\" with the Mapper's configuration\n utils._(opts, this)\n opts.adapter = this.getAdapterName(opts)\n\n // beforeCreateMany lifecycle hook\n opts.op = 'beforeCreateMany'\n return this._runHook(opts.op, records, opts)\n .then(records => {\n // Deep pre-create belongsTo relations\n const belongsToRelationData = {}\n opts.with = opts.with || []\n let tasks = []\n utils.forEachRelation(this, opts, (def, optsCopy) => {\n const relationData = records.map(record => def.getLocalField(record)).filter(Boolean)\n if (def.type === belongsToType && relationData.length === records.length) {\n // Create belongsTo relation first because we need a generated id to\n // attach to the child\n optsCopy.raw = false\n tasks.push(\n def\n .createLinked(relationData, optsCopy)\n .then(relatedRecords => {\n records.forEach((record, i) => def.setForeignKey(record, relatedRecords[i]))\n })\n .then(relatedRecords => {\n def.setLocalField(belongsToRelationData, relatedRecords)\n })\n )\n }\n })\n return Promise.all(tasks)\n .then(() => {\n opts.op = 'createMany'\n return this._invokeAdapterMethod(opts.op, records, opts)\n })\n .then(result => {\n adapterResponse = result\n })\n .then(() => {\n const createdRecordsData = opts.raw ? adapterResponse.data : adapterResponse\n\n // Deep post-create hasOne relations\n tasks = []\n utils.forEachRelation(this, opts, (def, optsCopy) => {\n const relationData = records.map(record => def.getLocalField(record)).filter(Boolean)\n if (relationData.length !== records.length) {\n return\n }\n\n optsCopy.raw = false\n const belongsToData = def.getLocalField(belongsToRelationData)\n let task\n // Create hasMany and hasOne after the main create because we needed\n // a generated id to attach to these items\n if (def.type === hasManyType) {\n // Not supported\n this.log('warn', 'deep createMany of hasMany type not supported!')\n } else if (def.type === hasOneType) {\n createdRecordsData.forEach((createdRecordData, i) => {\n def.setForeignKey(createdRecordData, relationData[i])\n })\n task = def\n .getRelation()\n .createMany(relationData, optsCopy)\n .then(relatedData => {\n createdRecordsData.forEach((createdRecordData, i) => {\n def.setLocalField(createdRecordData, relatedData[i])\n })\n })\n } else if (\n def.type === belongsToType &&\n belongsToData &&\n belongsToData.length === createdRecordsData.length\n ) {\n createdRecordsData.forEach((createdRecordData, i) => {\n def.setLocalField(createdRecordData, belongsToData[i])\n })\n }\n if (task) {\n tasks.push(task)\n }\n })\n return Promise.all(tasks).then(() => {\n return this._commitChanges(originalRecords, createdRecordsData)\n })\n })\n })\n .then(records => {\n if (opts.raw) {\n adapterResponse.data = records\n } else {\n adapterResponse = records\n }\n const result = this._end(adapterResponse, opts)\n opts.op = 'afterCreateMany'\n return this._runHook(opts.op, records, opts, result)\n })\n }\n\n /**\n * Create an unsaved, uncached instance of this Mapper's\n * {@link Mapper#recordClass}.\n *\n * Returns `props` if `props` is already an instance of\n * {@link Mapper#recordClass}.\n *\n * __Note:__ This method does __not__ interact with any adapter, and does\n * __not__ save any data. It only creates new objects in memory.\n *\n * @example\n * // Create empty unsaved record instance\n * const post = PostMapper.createRecord();\n *\n * @example\n * // Create an unsaved record instance with inital properties\n * const post = PostMapper.createRecord({\n * title: 'Modeling your data',\n * status: 'draft'\n * });\n *\n * @example\n * // Create a record instance that corresponds to a saved record\n * const post = PostMapper.createRecord({\n * // JSData thinks this record has been saved if it has a primary key\n * id: 1234,\n * title: 'Modeling your data',\n * status: 'draft'\n * });\n *\n * @example\n * // Create record instances from an array\n * const posts = PostMapper.createRecord([{\n * title: 'Modeling your data',\n * status: 'draft'\n * }, {\n * title: 'Reading data',\n * status: 'draft'\n * }]);\n *\n * @example\n * // Records are validated by default\n * import { Mapper } from 'js-data';\n * const PostMapper = new Mapper({\n * name: 'post',\n * schema: { properties: { title: { type: 'string' } } }\n * });\n * try {\n * const post = PostMapper.createRecord({\n * title: 1234,\n * });\n * } catch (err) {\n * console.log(err.errors); // [{ expected: 'one of (string)', actual: 'number', path: 'title' }]\n * }\n *\n * @example\n * // Skip validation\n * import { Mapper } from 'js-data';\n * const PostMapper = new Mapper({\n * name: 'post',\n * schema: { properties: { title: { type: 'string' } } }\n * });\n * const post = PostMapper.createRecord({\n * title: 1234,\n * }, { noValidate: true });\n * console.log(post.isValid()); // false\n *\n * @method Mapper#createRecord\n * @param {Object|Object[]} props The properties for the Record instance or an\n * array of property objects for the Record instances.\n * @param {object} [opts] Configuration options.\n * @param {boolean} [opts.noValidate={@link Mapper#noValidate}] See {@link Mapper#noValidate}.\n * @returns {Record|Record[]} The Record instance or Record instances.\n * @since 3.0.0\n */\n createRecord (props: any = {}, opts?): Record | Record[] | any {\n if (utils.isArray(props)) {\n return props.map(_props => this.createRecord(_props, opts))\n }\n if (!utils.isObject(props)) {\n throw utils.err(`${DOMAIN}#createRecord`, 'props')(400, 'array or object', props)\n }\n\n if (this.relationList) {\n this.relationList.forEach(def => {\n def.ensureLinkedDataHasProperType(props, opts)\n })\n }\n const RecordCtor = this.recordClass\n\n const result = !RecordCtor || props instanceof RecordCtor ? props : new RecordCtor(props, opts)\n return result\n // Record.mapper = this;\n // return new Record(props);\n }\n\n /**\n * Lifecycle invocation method. You probably won't call this method directly.\n *\n * @method Mapper#crud\n * @param {string} method Name of the lifecycle method to invoke.\n * @param {...*} args Arguments to pass to the lifecycle method.\n * @returns {Promise}\n * @since 3.0.0\n */\n crud (method, ...args) {\n const config = this.lifecycleMethods[method]\n if (!config) {\n throw utils.err(`${DOMAIN}#crud`, method)(404, 'method')\n }\n\n const upper = `${method.charAt(0).toUpperCase()}${method.substr(1)}`\n const before = `before${upper}`\n const after = `after${upper}`\n\n let op\n\n // Default values for arguments\n config.defaults.forEach((value, i) => {\n if (args[i] === undefined) {\n args[i] = utils.copy(value)\n }\n })\n\n const opts = args[args.length - 1]\n\n // Fill in \"opts\" with the Mapper's configuration\n utils._(opts, this)\n const adapter = opts.adapter = this.getAdapterName(opts)\n\n // before lifecycle hook\n op = opts.op = before\n return utils\n .resolve(this[op](...args))\n .then(_value => {\n if (args[config.beforeAssign] !== undefined) {\n // Allow for re-assignment from lifecycle hook\n args[config.beforeAssign] = _value === undefined ? args[config.beforeAssign] : _value\n }\n // Now delegate to the adapter\n op = opts.op = method\n args = config.adapterArgs ? config.adapterArgs(this, ...args) : args\n this.dbg(op, ...args)\n return utils.resolve(this.getAdapter(adapter)[op](this, ...args))\n })\n .then(result => {\n // force noValidate on find/findAll\n const noValidate = /find/.test(op) || opts.noValidate\n const _opts = Object.assign({}, opts, { noValidate })\n\n result = this._end(result, _opts, !!config.skip)\n args.push(result)\n // after lifecycle hook\n op = opts.op = after\n return utils.resolve(this[op](...args)).then(_result => {\n // Allow for re-assignment from lifecycle hook\n return _result === undefined ? result : _result\n })\n })\n }\n\n /**\n * Fired during {@link Mapper#destroy}. See\n * {@link Mapper~beforeDestroyListener} for how to listen for this event.\n *\n * @event Mapper#beforeDestroy\n * @see Mapper~beforeDestroyListener\n * @see Mapper#destroy\n */\n /**\n * Callback signature for the {@link Mapper#event:beforeDestroy} event.\n *\n * @example\n * function onBeforeDestroy (id, opts) {\n * // do something\n * }\n * store.on('beforeDestroy', onBeforeDestroy);\n *\n * @callback Mapper~beforeDestroyListener\n * @param {string|number} id The `id` argument passed to {@link Mapper#beforeDestroy}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#beforeDestroy}.\n * @see Mapper#event:beforeDestroy\n * @see Mapper#destroy\n * @since 3.0.0\n */\n /**\n * Fired during {@link Mapper#destroy}. See\n * {@link Mapper~afterDestroyListener} for how to listen for this event.\n *\n * @event Mapper#afterDestroy\n * @see Mapper~afterDestroyListener\n * @see Mapper#destroy\n */\n\n /**\n * Callback signature for the {@link Mapper#event:afterDestroy} event.\n *\n * @example\n * function onAfterDestroy (id, opts, result) {\n * // do something\n * }\n * store.on('afterDestroy', onAfterDestroy);\n *\n * @callback Mapper~afterDestroyListener\n * @param {string|number} id The `id` argument passed to {@link Mapper#afterDestroy}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#afterDestroy}.\n * @param {object} result The `result` argument passed to {@link Mapper#afterDestroy}.\n * @see Mapper#event:afterDestroy\n * @see Mapper#destroy\n * @since 3.0.0\n */\n /**\n * Using an adapter, destroy the record with the given primary key.\n *\n * {@link Mapper#beforeDestroy} will be called before destroying the record.\n * {@link Mapper#afterDestroy} will be called after destroying the record.\n *\n * @example\n * // Destroy a specific blog post\n * PostMapper.destroy(1234).then(() => {\n * // Blog post #1234 has been destroyed\n * });\n *\n * @example\n * // Get full response\n * PostMapper.destroy(1234, { raw: true }).then((result) => {\n * console.log(result.deleted); e.g. 1\n * console.log(...); // etc., more metadata can be found on the result\n * });\n *\n * @fires Mapper#beforeDestroy\n * @fires Mapper#afterDestroy\n * @method Mapper#destroy\n * @param {(string|number)} id The primary key of the record to destroy.\n * @param {object} [opts] Configuration options. Refer to the `destroy` method\n * of whatever adapter you're using for more configuration options.\n * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the\n * adapter to use.\n * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}.\n * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}.\n * @returns {Promise} Resolves when the record has been destroyed. Resolves\n * even if no record was found to be destroyed.\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/saving-data\",\"Saving data\"]\n */\n destroy (id: string | number, opts?) {\n return this.crud('destroy', id, opts)\n }\n\n /**\n * Fired during {@link Mapper#destroyAll}. See\n * {@link Mapper~beforeDestroyAllListener} for how to listen for this event.\n *\n * @event Mapper#beforeDestroyAll\n * @see Mapper~beforeDestroyAllListener\n * @see Mapper#destroyAll\n */\n /**\n * Callback signature for the {@link Mapper#event:beforeDestroyAll} event.\n *\n * @example\n * function onBeforeDestroyAll (query, opts) {\n * // do something\n * }\n * store.on('beforeDestroyAll', onBeforeDestroyAll);\n *\n * @callback Mapper~beforeDestroyAllListener\n * @param {object} query The `query` argument passed to {@link Mapper#beforeDestroyAll}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#beforeDestroyAll}.\n * @see Mapper#event:beforeDestroyAll\n * @see Mapper#destroyAll\n * @since 3.0.0\n */\n /**\n * Fired during {@link Mapper#destroyAll}. See\n * {@link Mapper~afterDestroyAllListener} for how to listen for this event.\n *\n * @event Mapper#afterDestroyAll\n * @see Mapper~afterDestroyAllListener\n * @see Mapper#destroyAll\n */\n\n /**\n * Callback signature for the {@link Mapper#event:afterDestroyAll} event.\n *\n * @example\n * function onAfterDestroyAll (query, opts, result) {\n * // do something\n * }\n * store.on('afterDestroyAll', onAfterDestroyAll);\n *\n * @callback Mapper~afterDestroyAllListener\n * @param {object} query The `query` argument passed to {@link Mapper#afterDestroyAll}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#afterDestroyAll}.\n * @param {object} result The `result` argument passed to {@link Mapper#afterDestroyAll}.\n * @see Mapper#event:afterDestroyAll\n * @see Mapper#destroyAll\n * @since 3.0.0\n */\n /**\n * Destroy the records selected by `query` via an adapter. If no `query` is\n * provided then all records will be destroyed.\n *\n * {@link Mapper#beforeDestroyAll} will be called before destroying the records.\n * {@link Mapper#afterDestroyAll} will be called after destroying the records.\n *\n * @example\n * // Destroy all blog posts\n * PostMapper.destroyAll().then(() => {\n * // All blog posts have been destroyed\n * });\n *\n * @example\n * // Destroy all \"draft\" blog posts\n * PostMapper.destroyAll({ status: 'draft' }).then(() => {\n * // All \"draft\" blog posts have been destroyed\n * });\n *\n * @example\n * // Get full response\n * const query = null;\n * const options = { raw: true };\n * PostMapper.destroyAll(query, options).then((result) => {\n * console.log(result.deleted); e.g. 14\n * console.log(...); // etc., more metadata can be found on the result\n * });\n *\n * @fires Mapper#beforeDestroyAll\n * @fires Mapper#afterDestroyAll\n * @method Mapper#destroyAll\n * @param {object} [query={}] Selection query. See {@link query}.\n * @param {object} [query.where] See {@link query.where}.\n * @param {number} [query.offset] See {@link query.offset}.\n * @param {number} [query.limit] See {@link query.limit}.\n * @param {string|Array[]} [query.orderBy] See {@link query.orderBy}.\n * @param {object} [opts] Configuration options. Refer to the `destroyAll`\n * method of whatever adapter you're using for more configuration options.\n * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the\n * adapter to use.\n * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}.\n * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}.\n * @returns {Promise} Resolves when the records have been destroyed. Resolves\n * even if no records were found to be destroyed.\n * @see query\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/saving-data\",\"Saving data\"]\n */\n destroyAll (query?, opts?) {\n return this.crud('destroyAll', query, opts)\n }\n\n /**\n * Fired during {@link Mapper#find}. See\n * {@link Mapper~beforeFindListener} for how to listen for this event.\n *\n * @event Mapper#beforeFind\n * @see Mapper~beforeFindListener\n * @see Mapper#find\n */\n /**\n * Callback signature for the {@link Mapper#event:beforeFind} event.\n *\n * @example\n * function onBeforeFind (id, opts) {\n * // do something\n * }\n * store.on('beforeFind', onBeforeFind);\n *\n * @callback Mapper~beforeFindListener\n * @param {string|number} id The `id` argument passed to {@link Mapper#beforeFind}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#beforeFind}.\n * @see Mapper#event:beforeFind\n * @see Mapper#find\n * @since 3.0.0\n */\n /**\n * Fired during {@link Mapper#find}. See\n * {@link Mapper~afterFindListener} for how to listen for this event.\n *\n * @event Mapper#afterFind\n * @see Mapper~afterFindListener\n * @see Mapper#find\n */\n\n /**\n * Callback signature for the {@link Mapper#event:afterFind} event.\n *\n * @example\n * function onAfterFind (id, opts, result) {\n * // do something\n * }\n * store.on('afterFind', onAfterFind);\n *\n * @callback Mapper~afterFindListener\n * @param {string|number} id The `id` argument passed to {@link Mapper#afterFind}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#afterFind}.\n * @param {object} result The `result` argument passed to {@link Mapper#afterFind}.\n * @see Mapper#event:afterFind\n * @see Mapper#find\n * @since 3.0.0\n */\n /**\n * Retrieve via an adapter the record with the given primary key.\n *\n * {@link Mapper#beforeFind} will be called before calling the adapter.\n * {@link Mapper#afterFind} will be called after calling the adapter.\n *\n * @example\n * PostMapper.find(1).then((post) => {\n * console.log(post); // { id: 1, ...}\n * });\n *\n * @example\n * // Get full response\n * PostMapper.find(1, { raw: true }).then((result) => {\n * console.log(result.data); // { id: 1, ...}\n * console.log(result.found); // 1\n * console.log(...); // etc., more metadata can be found on the result\n * });\n *\n * @fires Mapper#beforeFind\n * @fires Mapper#afterFind\n * @method Mapper#find\n * @param {(string|number)} id The primary key of the record to retrieve.\n * @param {object} [opts] Configuration options. Refer to the `find` method\n * of whatever adapter you're using for more configuration options.\n * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the\n * adapter to use.\n * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}.\n * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}.\n * @param {string[]} [opts.with=[]] Relations to eager load in the request.\n * @returns {Promise} Resolves with the found record. Resolves with\n * `undefined` if no record was found.\n * @see http://www.js-data.io/v3.0/docs/reading-data\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/reading-data\",\"Reading data\"]\n */\n find (id: string | number, opts?) {\n return this.crud('find', id, opts)\n }\n\n /**\n * Fired during {@link Mapper#findAll}. See\n * {@link Mapper~beforeFindAllListener} for how to listen for this event.\n *\n * @event Mapper#beforeFindAll\n * @see Mapper~beforeFindAllListener\n * @see Mapper#findAll\n */\n /**\n * Callback signature for the {@link Mapper#event:beforeFindAll} event.\n *\n * @example\n * function onBeforeFindAll (query, opts) {\n * // do something\n * }\n * store.on('beforeFindAll', onBeforeFindAll);\n *\n * @callback Mapper~beforeFindAllListener\n * @param {object} query The `query` argument passed to {@link Mapper#beforeFindAll}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#beforeFindAll}.\n * @see Mapper#event:beforeFindAll\n * @see Mapper#findAll\n * @since 3.0.0\n */\n /**\n * Fired during {@link Mapper#findAll}. See\n * {@link Mapper~afterFindAllListener} for how to listen for this event.\n *\n * @event Mapper#afterFindAll\n * @see Mapper~afterFindAllListener\n * @see Mapper#findAll\n */\n\n /**\n * Callback signature for the {@link Mapper#event:afterFindAll} event.\n *\n * @example\n * function onAfterFindAll (query, opts, result) {\n * // do something\n * }\n * store.on('afterFindAll', onAfterFindAll);\n *\n * @callback Mapper~afterFindAllListener\n * @param {object} query The `query` argument passed to {@link Mapper#afterFindAll}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#afterFindAll}.\n * @param {object} result The `result` argument passed to {@link Mapper#afterFindAll}.\n * @see Mapper#event:afterFindAll\n * @see Mapper#findAll\n * @since 3.0.0\n */\n /**\n * Using the `query` argument, select records to retrieve via an adapter.\n *\n * {@link Mapper#beforeFindAll} will be called before calling the adapter.\n * {@link Mapper#afterFindAll} will be called after calling the adapter.\n *\n * @example\n * // Find all \"published\" blog posts\n * PostMapper.findAll({ status: 'published' }).then((posts) => {\n * console.log(posts); // [{ id: 1, status: 'published', ...}, ...]\n * });\n *\n * @example\n * // Get full response\n * PostMapper.findAll({ status: 'published' }, { raw: true }).then((result) => {\n * console.log(result.data); // [{ id: 1, status: 'published', ...}, ...]\n * console.log(result.found); // e.g. 13\n * console.log(...); // etc., more metadata can be found on the result\n * });\n *\n * @fires Mapper#beforeFindAll\n * @fires Mapper#afterFindAll\n * @method Mapper#findAll\n * @param {object} [query={}] Selection query. See {@link query}.\n * @param {object} [query.where] See {@link query.where}.\n * @param {number} [query.offset] See {@link query.offset}.\n * @param {number} [query.limit] See {@link query.limit}.\n * @param {string|Array[]} [query.orderBy] See {@link query.orderBy}.\n * @param {object} [opts] Configuration options. Refer to the `findAll` method\n * of whatever adapter you're using for more configuration options.\n * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the\n * adapter to use.\n * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}.\n * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}.\n * @param {string[]} [opts.with=[]] Relations to eager load in the request.\n * @returns {Promise} Resolves with the found records, if any.\n * @see query\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/reading-data\",\"Reading data\"]\n */\n findAll (query, opts?) {\n return this.crud('findAll', query, opts)\n }\n\n /**\n * Return the registered adapter with the given name or the default adapter if\n * no name is provided.\n *\n * @method Mapper#getAdapter\n * @param {string} [name] The name of the adapter to retrieve.\n * @returns {Adapter} The adapter.\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/connecting-to-a-data-source\",\"Connecting to a data source\"]\n */\n getAdapter (name?: string) {\n this.dbg('getAdapter', 'name:', name)\n const adapter = this.getAdapterName(name)\n if (!adapter) {\n throw utils.err(`${DOMAIN}#getAdapter`, 'name')(400, 'string', name)\n }\n return this.getAdapters()[adapter]\n }\n\n /**\n * Return the name of a registered adapter based on the given name or options,\n * or the name of the default adapter if no name provided.\n *\n * @method Mapper#getAdapterName\n * @param {(Object|string)} [opts] The name of an adapter or options, if any.\n * @returns {string} The name of the adapter.\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/connecting-to-a-data-source\",\"Connecting to a data source\"]\n */\n getAdapterName (opts: any = {}) {\n if (utils.isString(opts)) {\n opts = { adapter: opts }\n }\n return opts.adapter || opts.defaultAdapter\n }\n\n /**\n * Get the object of registered adapters for this Mapper.\n *\n * @method Mapper#getAdapters\n * @returns {Object} {@link Mapper#_adapters}\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/connecting-to-a-data-source\",\"Connecting to a data source\"]\n */\n getAdapters () {\n return this._adapters\n }\n\n /**\n * Returns this Mapper's {@link Schema}.\n *\n * @method Mapper#getSchema\n * @returns {Schema} This Mapper's {@link Schema}.\n * @see Mapper#schema\n * @since 3.0.0\n */\n getSchema () {\n return this.schema\n }\n\n /**\n * Defines a hasMany relationship. Only useful if you're managing your\n * Mappers manually and not using a Container or DataStore component.\n *\n * @example\n * UserMapper.hasMany(PostMapper, {\n * // post.user_id points to user.id\n * foreignKey: 'user_id'\n * // post records will be attached to user records at \"user.posts\"\n * localField: 'posts'\n * });\n *\n * @method Mapper#hasMany\n * @see http://www.js-data.io/v3.0/docs/relations\n * @since 3.0.0\n */\n hasMany (relatedMapper, opts) {\n return hasMany(relatedMapper, opts)(this)\n }\n\n /**\n * Defines a hasOne relationship. Only useful if you're managing your Mappers\n * manually and not using a {@link Container} or {@link DataStore} component.\n *\n * @example\n * UserMapper.hasOne(ProfileMapper, {\n * // profile.user_id points to user.id\n * foreignKey: 'user_id'\n * // profile records will be attached to user records at \"user.profile\"\n * localField: 'profile'\n * });\n *\n * @method Mapper#hasOne\n * @see http://www.js-data.io/v3.0/docs/relations\n * @since 3.0.0\n */\n hasOne (relatedMapper, opts) {\n return hasOne(relatedMapper, opts)(this)\n }\n\n /**\n * Return whether `record` is an instance of this Mapper's recordClass.\n *\n * @example\n * const post = PostMapper.createRecord();\n *\n * console.log(PostMapper.is(post)); // true\n * // Equivalent to what's above\n * console.log(post instanceof PostMapper.recordClass); // true\n *\n * @method Mapper#is\n * @param {Object|Record} record The record to check.\n * @returns {boolean} Whether `record` is an instance of this Mapper's\n * {@link Mapper#recordClass}.\n * @since 3.0.0\n */\n is (record) {\n const recordClass = this.recordClass\n return recordClass ? record instanceof recordClass : false\n }\n\n /**\n * Register an adapter on this Mapper under the given name.\n *\n * @method Mapper#registerAdapter\n * @param {string} name The name of the adapter to register.\n * @param {Adapter} adapter The adapter to register.\n * @param {object} [opts] Configuration options.\n * @param {boolean} [opts.default=false] Whether to make the adapter the\n * default adapter for this Mapper.\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/connecting-to-a-data-source\",\"Connecting to a data source\"]\n */\n registerAdapter (name, adapter, opts: any = {}) {\n this.getAdapters()[name] = adapter\n // Optionally make it the default adapter for the target.\n if (opts === true || opts.default) {\n this.defaultAdapter = name\n }\n }\n\n _runHook (hookName, ...hookArgs) {\n const defaultValueIndex = hookName.indexOf('after') === 0 ? hookArgs.length - 1 : 0\n\n return utils\n .resolve(this[hookName](...hookArgs))\n .then(overridenResult => (overridenResult === undefined ? hookArgs[defaultValueIndex] : overridenResult))\n }\n\n _invokeAdapterMethod (method, propsOrRecords, opts) {\n const conversionOptions = { with: opts.pass || [] }\n let object\n\n this.dbg(opts.op, propsOrRecords, opts)\n\n if (utils.isArray(propsOrRecords)) {\n object = propsOrRecords.map(record => this.toJSON(record, conversionOptions))\n } else {\n object = this.toJSON(propsOrRecords, conversionOptions)\n }\n\n return this.getAdapter(opts.adapter)[method](this, object, opts)\n }\n\n /**\n * Select records according to the `query` argument, and aggregate the sum\n * value of the property specified by `field`.\n *\n * {@link Mapper#beforeSum} will be called before calling the adapter.\n * {@link Mapper#afterSum} will be called after calling the adapter.\n *\n * @example\n * PurchaseOrderMapper.sum('amount', { status: 'paid' }).then((amountPaid) => {\n * console.log(amountPaid); // e.g. 451125.34\n * });\n *\n * @method Mapper#sum\n * @param {string} field The field to sum.\n * @param {object} [query={}] Selection query. See {@link query}.\n * @param {object} [query.where] See {@link query.where}.\n * @param {number} [query.offset] See {@link query.offset}.\n * @param {number} [query.limit] See {@link query.limit}.\n * @param {string|Array[]} [query.orderBy] See {@link query.orderBy}.\n * @param {object} [opts] Configuration options. Refer to the `sum` method\n * of whatever adapter you're using for more configuration options.\n * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the\n * adapter to use.\n * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}.\n * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}.\n * @returns {Promise} Resolves with the aggregated sum.\n * @since 3.0.0\n */\n sum (field, query: QueryDefinition, opts?) {\n return this.crud('sum', field, query, opts)\n }\n\n /**\n * Return a plain object representation of the given record. Relations can\n * be optionally be included. Non-schema properties can be excluded.\n *\n * @example\n * import { Mapper, Schema } from 'js-data';\n * const PersonMapper = new Mapper({\n * name: 'person',\n * schema: {\n * properties: {\n * name: { type: 'string' },\n * id: { type: 'string' }\n * }\n * }\n * });\n * const person = PersonMapper.createRecord({ id: 1, name: 'John', foo: 'bar' });\n * // \"foo\" is stripped by toJSON()\n * console.log(PersonMapper.toJSON(person)); // {\"id\":1,\"name\":\"John\"}\n *\n * const PersonRelaxedMapper = new Mapper({\n * name: 'personRelaxed',\n * schema: {\n * properties: {\n * name: { type: 'string' },\n * id: { type: 'string' }\n * },\n * additionalProperties: true\n * }\n * });\n * const person2 = PersonRelaxedMapper.createRecord({ id: 1, name: 'John', foo: 'bar' });\n * // \"foo\" is not stripped by toJSON\n * console.log(PersonRelaxedMapper.toJSON(person2)); // {\"id\":1,\"name\":\"John\",\"foo\":\"bar\"}\n *\n * @method Mapper#toJSON\n * @param {Record|Record[]} records Record or records from which to create a\n * POJO representation.\n * @param {object} [opts] Configuration options.\n * @param {string[]} [opts.with] Array of relation names or relation fields\n * to include in the POJO representation.\n * @param {boolean} [opts.withAll] Whether to simply include all relations in\n * the representation. Overrides `opts.with`.\n * @returns {Object|Object[]} POJO representation of the record or records.\n * @since 3.0.0\n */\n toJSON (records, opts: any = {}) {\n let record\n if (utils.isArray(records)) {\n return records.map(record => this.toJSON(record, opts))\n } else {\n record = records\n }\n const relationFields = (this ? this.relationFields : []) || []\n let json = {}\n\n // Copy properties defined in the schema\n if (this && this.schema) {\n json = this.schema.pick(record)\n } else {\n for (const key in record) {\n if (relationFields.indexOf(key) === -1) {\n json[key] = utils.plainCopy(record[key])\n }\n }\n }\n\n // The user wants to include relations in the resulting plain object representation\n if (this && opts.withAll) {\n opts.with = relationFields.slice()\n }\n if (this && opts.with) {\n if (utils.isString(opts.with)) {\n opts.with = [opts.with]\n }\n utils.forEachRelation(this, opts, (def, optsCopy) => {\n const relationData = def.getLocalField(record)\n if (relationData) {\n // The actual recursion\n if (utils.isArray(relationData)) {\n def.setLocalField(\n json,\n relationData.map(item => {\n return def.getRelation().toJSON(item, optsCopy)\n })\n )\n } else {\n def.setLocalField(json, def.getRelation().toJSON(relationData, optsCopy))\n }\n }\n })\n }\n return json\n }\n\n /**\n * Fired during {@link Mapper#update}. See\n * {@link Mapper~beforeUpdateListener} for how to listen for this event.\n *\n * @event Mapper#beforeUpdate\n * @see Mapper~beforeUpdateListener\n * @see Mapper#update\n */\n /**\n * Callback signature for the {@link Mapper#event:beforeUpdate} event.\n *\n * @example\n * function onBeforeUpdate (id, props, opts) {\n * // do something\n * }\n * store.on('beforeUpdate', onBeforeUpdate);\n *\n * @callback Mapper~beforeUpdateListener\n * @param {string|number} id The `id` argument passed to {@link Mapper#beforeUpdate}.\n * @param {object} props The `props` argument passed to {@link Mapper#beforeUpdate}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#beforeUpdate}.\n * @see Mapper#event:beforeUpdate\n * @see Mapper#update\n * @since 3.0.0\n */\n /**\n * Fired during {@link Mapper#update}. See\n * {@link Mapper~afterUpdateListener} for how to listen for this event.\n *\n * @event Mapper#afterUpdate\n * @see Mapper~afterUpdateListener\n * @see Mapper#update\n */\n\n /**\n * Callback signature for the {@link Mapper#event:afterUpdate} event.\n *\n * @example\n * function onAfterUpdate (id, props, opts, result) {\n * // do something\n * }\n * store.on('afterUpdate', onAfterUpdate);\n *\n * @callback Mapper~afterUpdateListener\n * @param {string|number} id The `id` argument passed to {@link Mapper#afterUpdate}.\n * @param {object} props The `props` argument passed to {@link Mapper#afterUpdate}.\n * @param {object} opts The `opts` argument passed to {@link Mapper#afterUpdate}.\n * @param {object} result The `result` argument passed to {@link Mapper#afterUpdate}.\n * @see Mapper#event:afterUpdate\n * @see Mapper#update\n * @since 3.0.0\n */\n /**\n * Using an adapter, update the record with the primary key specified by the\n * `id` argument.\n *\n * {@link Mapper#beforeUpdate} will be called before updating the record.\n * {@link Mapper#afterUpdate} will be called after updating the record.\n *\n * @example\n * // Update a specific post\n * PostMapper.update(1234, {\n * status: 'published',\n * published_at: new Date()\n * }).then((post) => {\n * console.log(post); // { id: 1234, status: 'published', ... }\n * });\n *\n * @fires Mapper#beforeUpdate\n * @fires Mapper#afterUpdate\n * @method Mapper#update\n * @param {(string|number)} id The primary key of the record to update.\n * @param {object} props The update to apply to the record.\n * @param {object} [opts] Configuration options. Refer to the `update` method\n * of whatever adapter you're using for more configuration options.\n * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the\n * adapter to use.\n * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}.\n * @param {boolean} [opts.noValidate={@link Mapper#noValidate}] See {@link Mapper#noValidate}.\n * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}.\n * transaction.\n * @returns {Promise} Resolves with the updated record. Rejects if the record\n * could not be found.\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/saving-data\",\"Saving data\"]\n */\n update (id, props, opts?) {\n return this.crud('update', id, props, opts)\n }\n\n /**\n * Fired during {@link Mapper#updateAll}. See\n * {@link Mapper~beforeUpdateAllListener} for how to listen for this event.\n *\n * @event Mapper#beforeUpdateAll\n * @see Mapper~beforeUpdateAllListener\n * @see Mapper#updateAll\n */\n /**\n * Callback signature for the {@link Mapper#event:beforeUpdateAll} event.\n *\n * @example\n * function onBeforeUpdateAll (props, query, opts) {\n * // do something\n * }\n * store.on('beforeUpdateAll', onBeforeUpdateAll);\n *\n * @callback Mapper~beforeUpdateAllListener\n * @param {object} props The `props` argument received by {@link Mapper#beforeUpdateAll}.\n * @param {object} query The `query` argument received by {@link Mapper#beforeUpdateAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdateAll}.\n * @see Mapper#event:beforeUpdateAll\n * @see Mapper#updateAll\n * @since 3.0.0\n */\n /**\n * Fired during {@link Mapper#updateAll}. See\n * {@link Mapper~afterUpdateAllListener} for how to listen for this event.\n *\n * @event Mapper#afterUpdateAll\n * @see Mapper~afterUpdateAllListener\n * @see Mapper#updateAll\n */\n\n /**\n * Callback signature for the {@link Mapper#event:afterUpdateAll} event.\n *\n * @example\n * function onAfterUpdateAll (props, query, opts, result) {\n * // do something\n * }\n * store.on('afterUpdateAll', onAfterUpdateAll);\n *\n * @callback Mapper~afterUpdateAllListener\n * @param {object} props The `props` argument received by {@link Mapper#afterUpdateAll}.\n * @param {object} query The `query` argument received by {@link Mapper#afterUpdateAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdateAll}.\n * @param {object} result The `result` argument received by {@link Mapper#afterUpdateAll}.\n * @see Mapper#event:afterUpdateAll\n * @see Mapper#updateAll\n * @since 3.0.0\n */\n /**\n * Using the `query` argument, perform the a single updated to the selected\n * records.\n *\n * {@link Mapper#beforeUpdateAll} will be called before making the update.\n * {@link Mapper#afterUpdateAll} will be called after making the update.\n *\n * @example\n * // Turn all of John's blog posts into drafts.\n * const update = { status: draft: published_at: null };\n * const query = { userId: 1234 };\n * PostMapper.updateAll(update, query).then((posts) => {\n * console.log(posts); // [...]\n * });\n *\n * @fires Mapper#beforeUpdateAll\n * @fires Mapper#afterUpdateAll\n * @method Mapper#updateAll\n * @param {object} props Update to apply to selected records.\n * @param {object} [query={}] Selection query. See {@link query}.\n * @param {object} [query.where] See {@link query.where}.\n * @param {number} [query.offset] See {@link query.offset}.\n * @param {number} [query.limit] See {@link query.limit}.\n * @param {string|Array[]} [query.orderBy] See {@link query.orderBy}.\n * @param {object} [opts] Configuration options. Refer to the `updateAll`\n * method of whatever adapter you're using for more configuration options.\n * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the\n * adapter to use.\n * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}.\n * @param {boolean} [opts.noValidate={@link Mapper#noValidate}] See {@link Mapper#noValidate}.\n * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}.\n * @returns {Promise} Resolves with the update records, if any.\n * @see query\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/saving-data\",\"Saving data\"]\n */\n updateAll (props, query?: QueryDefinition, opts?) {\n return this.crud('updateAll', props, query, opts)\n }\n\n /**\n * Fired during {@link Mapper#updateMany}. See\n * {@link Mapper~beforeUpdateManyListener} for how to listen for this event.\n *\n * @event Mapper#beforeUpdateMany\n * @see Mapper~beforeUpdateManyListener\n * @see Mapper#updateMany\n */\n /**\n * Callback signature for the {@link Mapper#event:beforeUpdateMany} event.\n *\n * @example\n * function onBeforeUpdateMany (records, opts) {\n * // do something\n * }\n * store.on('beforeUpdateMany', onBeforeUpdateMany);\n *\n * @callback Mapper~beforeUpdateManyListener\n * @param {object} records The `records` argument received by {@link Mapper#beforeUpdateMany}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdateMany}.\n * @see Mapper#event:beforeUpdateMany\n * @see Mapper#updateMany\n * @since 3.0.0\n */\n /**\n * Fired during {@link Mapper#updateMany}. See\n * {@link Mapper~afterUpdateManyListener} for how to listen for this event.\n *\n * @event Mapper#afterUpdateMany\n * @see Mapper~afterUpdateManyListener\n * @see Mapper#updateMany\n */\n\n /**\n * Callback signature for the {@link Mapper#event:afterUpdateMany} event.\n *\n * @example\n * function onAfterUpdateMany (records, opts, result) {\n * // do something\n * }\n * store.on('afterUpdateMany', onAfterUpdateMany);\n *\n * @callback Mapper~afterUpdateManyListener\n * @param {object} records The `records` argument received by {@link Mapper#afterUpdateMany}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdateMany}.\n * @param {object} result The `result` argument received by {@link Mapper#afterUpdateMany}.\n * @see Mapper#event:afterUpdateMany\n * @see Mapper#updateMany\n * @since 3.0.0\n */\n /**\n * Given an array of updates, perform each of the updates via an adapter. Each\n * \"update\" is a hash of properties with which to update an record. Each\n * update must contain the primary key of the record to be updated.\n *\n * {@link Mapper#beforeUpdateMany} will be called before making the update.\n * {@link Mapper#afterUpdateMany} will be called after making the update.\n *\n * @example\n * PostMapper.updateMany([\n * { id: 1234, status: 'draft' },\n * { id: 2468, status: 'published', published_at: new Date() }\n * ]).then((posts) => {\n * console.log(posts); // [...]\n * });\n *\n * @fires Mapper#beforeUpdateMany\n * @fires Mapper#afterUpdateMany\n * @method Mapper#updateMany\n * @param {Record[]} records Array up record updates.\n * @param {object} [opts] Configuration options. Refer to the `updateMany`\n * method of whatever adapter you're using for more configuration options.\n * @param {boolean} [opts.adapter={@link Mapper#defaultAdapter}] Name of the\n * adapter to use.\n * @param {boolean} [opts.notify={@link Mapper#notify}] See {@link Mapper#notify}.\n * @param {boolean} [opts.noValidate={@link Mapper#noValidate}] See {@link Mapper#noValidate}.\n * @param {boolean} [opts.raw={@link Mapper#raw}] See {@link Mapper#raw}.\n * @returns {Promise} Resolves with the updated records. Rejects if any of the\n * records could be found.\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/saving-data\",\"Saving data\"]\n */\n updateMany (records, opts?) {\n return this.crud('updateMany', records, opts)\n }\n\n /**\n * Validate the given record or records according to this Mapper's\n * {@link Schema}. If there are no validation errors then the return value\n * will be `undefined`.\n *\n * @example\n * import {Mapper, Schema} from 'js-data'\n * const PersonSchema = new Schema({\n * properties: {\n * name: { type: 'string' },\n * id: { type: 'string' }\n * }\n * });\n * const PersonMapper = new Mapper({\n * name: 'person',\n * schema: PersonSchema\n * });\n * let errors = PersonMapper.validate({ name: 'John' });\n * console.log(errors); // undefined\n * errors = PersonMapper.validate({ name: 123 });\n * console.log(errors); // [{ expected: 'one of (string)', actual: 'number', path: 'name' }]\n *\n * @method Mapper#validate\n * @param {Object|Object[]} record The record or records to validate.\n * @param {object} [opts] Configuration options. Passed to\n * {@link Schema#validate}.\n * @returns {Object[]} Array of errors or `undefined` if no errors.\n * @since 3.0.0\n */\n validate (record, opts: any = {}) {\n const schema = this.getSchema()\n if (!schema) {\n return\n }\n const _opts = utils.pick(opts, ['existingOnly'])\n if (utils.isArray(record)) {\n const errors = record.map(_record => schema.validate(_record, utils.pick(_opts, ['existingOnly'])))\n\n return errors.some(Boolean) ? errors : undefined\n }\n return schema.validate(record, _opts)\n }\n\n /**\n * Method used to wrap data returned by an adapter with this Mapper's\n * {@link Mapper#recordClass}. This method is used by all of a Mapper's CRUD\n * methods. The provided implementation of this method assumes that the `data`\n * passed to it is a record or records that need to be wrapped with\n * {@link Mapper#createRecord}. Override with care.\n *\n * Provided implementation of {@link Mapper#wrap}:\n *\n * ```\n * function (data, opts) {\n * return this.createRecord(data, opts);\n * }\n * ```\n *\n * @example\n * const PostMapper = new Mapper({\n * name: 'post',\n * // Override to customize behavior\n * wrap (data, opts) {\n * const originalWrap = this.constructor.prototype.wrap;\n * // Let's say \"GET /post\" doesn't return JSON quite like JSData expects,\n * // but the actual post records are nested under a \"posts\" field. So,\n * // we override Mapper#wrap to handle this special case.\n * if (opts.op === 'findAll') {\n * return originalWrap.call(this, data.posts, opts);\n * }\n * // Otherwise perform original behavior\n * return originalWrap.call(this, data, opts);\n * }\n * });\n *\n * @method Mapper#wrap\n * @param {Object|Object[]} data The record or records to be wrapped.\n * @param {object} [opts] Configuration options. Passed to {@link Mapper#createRecord}.\n * @returns {Record|Record[]} The wrapped record or records.\n * @since 3.0.0\n */\n wrap (data, opts) {\n return this.createRecord(data, opts)\n }\n\n /**\n * @ignore\n */\n defineRelations () {\n // Setup the mapper's relations, including generating Mapper#relationList\n // and Mapper#relationFields\n utils.forOwn(this.relations, (group, type) => {\n utils.forOwn(group, (relations, _name) => {\n if (utils.isObject(relations)) {\n relations = [relations]\n }\n relations.forEach(def => {\n const relatedMapper = this.datastore.getMapperByName(_name) || _name\n def.getRelation = () => this.datastore.getMapper(_name)\n\n if (typeof Relation[type] !== 'function') {\n throw utils.err(DOMAIN, 'defineRelations')(400, 'relation type (hasOne, hasMany, etc)', type, true)\n }\n\n this[type](relatedMapper, def)\n })\n })\n })\n }\n}\n\n/**\n * Create a subclass of this Mapper:\n *\n * @example Mapper.extend\n * const JSData = require('js-data');\n * const { Mapper } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * // Extend the class using ES2015 class syntax.\n * class CustomMapperClass extends Mapper {\n * foo () { return 'bar'; }\n * static beep () { return 'boop'; }\n * };\n * const customMapper = new CustomMapperClass();\n * console.log(customMapper.foo());\n * console.log(CustomMapperClass.beep());\n *\n * // Extend the class using alternate method.\n * const OtherMapperClass = Mapper.extend({\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * });\n * const otherMapper = new OtherMapperClass();\n * console.log(otherMapper.foo());\n * console.log(OtherMapperClass.beep());\n *\n * // Extend the class, providing a custom constructor.\n * function AnotherMapperClass () {\n * Mapper.call(this);\n * this.created_at = new Date().getTime();\n * }\n * Mapper.extend({\n * constructor: AnotherMapperClass,\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * })\n * const anotherMapper = new AnotherMapperClass();\n * console.log(anotherMapper.created_at);\n * console.log(anotherMapper.foo());\n * console.log(AnotherMapperClass.beep());\n *\n * @method Mapper.extend\n * @param {object} [props={}] Properties to add to the prototype of the\n * subclass.\n * @param {object} [props.constructor] Provide a custom constructor function\n * to be used as the subclass itself.\n * @param {object} [classProps={}] Static properties to add to the subclass.\n * @returns {Constructor} Subclass of this Mapper class.\n * @since 3.0.0\n */\n","import utils from './utils'\nimport Component from './Component'\nimport Mapper, { MapperOpts } from './Mapper'\nimport Record from './Record'\n\nconst DOMAIN = 'Container'\n\nexport const proxiedMapperMethods = [\n 'count',\n 'create',\n 'createMany',\n 'createRecord',\n 'destroy',\n 'destroyAll',\n 'find',\n 'findAll',\n 'getSchema',\n 'is',\n 'sum',\n 'toJSON',\n 'update',\n 'updateAll',\n 'updateMany',\n 'validate'\n]\n\n/**\n * The `Container` class is a place to define and store {@link Mapper} instances.\n *\n * `Container` makes it easy to manage your Mappers. Without a container, you\n * need to manage Mappers yourself, including resolving circular dependencies\n * among relations. All Mappers in a container share the same adapters, so you\n * don't have to register adapters for every single Mapper.\n *\n * @example Container#constructor\n * // import { Container } from 'js-data';\n * const JSData = require('js-data');\n * const {Container} = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new Container();\n *\n * @class Container\n * @extends Component\n * @param {object} [opts] Configuration options.\n * @param {boolean} [opts.debug=false] See {@link Component#debug}.\n * @param {Constructor} [opts.mapperClass] See {@link Container#mapperClass}.\n * @param {object} [opts.mapperDefaults] See {@link Container#mapperDefaults}.\n * @since 3.0.0\n */\nexport class Container extends Component {\n mapperDefaults: any;\n mapperClass: typeof Mapper;\n _adapters: any;\n _mappers: { [name: string]: Mapper };\n\n constructor (opts = {}) {\n super()\n\n Object.defineProperties(this, {\n /**\n * The adapters registered with this Container, which are also shared by all\n * Mappers in this Container.\n *\n * @name Container#_adapters\n * @see Container#registerAdapter\n * @since 3.0.0\n * @type {Object}\n */\n _adapters: {\n value: {}\n },\n\n /**\n * The the mappers in this container\n *\n * @name Container#_mappers\n * @see Mapper\n * @since 3.0.0\n * @type {Object}\n */\n _mappers: {\n value: {}\n },\n\n /**\n * Constructor function to use in {@link Container#defineMapper} to create new\n * {@link Mapper} instances. {@link Container#mapperClass} should extend\n * {@link Mapper}. By default {@link Mapper} is used to instantiate Mappers.\n *\n * @example Container#mapperClass\n * // import { Container, Mapper } from 'js-data';\n * const JSData = require('js-data');\n * const { Container, Mapper } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * class MyMapperClass extends Mapper {\n * foo () { return 'bar' }\n * }\n * const store = new Container({\n * mapperClass: MyMapperClass\n * });\n * store.defineMapper('user');\n * console.log(store.getMapper('user').foo());\n *\n * @name Container#mapperClass\n * @see Mapper\n * @since 3.0.0\n * @type {Constructor}\n */\n mapperClass: {\n value: undefined,\n writable: true\n }\n })\n\n // Apply options provided by the user\n utils.fillIn(this, opts)\n\n /**\n * Defaults options to pass to {@link Container#mapperClass} when creating a\n * new {@link Mapper}.\n *\n * @example Container#mapperDefaults\n * // import { Container } from 'js-data';\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new Container({\n * mapperDefaults: {\n * idAttribute: '_id'\n * }\n * });\n * store.defineMapper('user');\n * console.log(store.getMapper('user').idAttribute);\n *\n * @default {}\n * @name Container#mapperDefaults\n * @since 3.0.0\n * @type {Object}\n */\n this.mapperDefaults = this.mapperDefaults || {}\n\n // Use the Mapper class if the user didn't provide a mapperClass\n this.mapperClass = this.mapperClass || Mapper\n }\n\n /**\n * Register a new event listener on this Container.\n *\n * Proxy for {@link Component#on}. If an event was emitted by a {@link Mapper}\n * in the Container, then the name of the {@link Mapper} will be prepended to\n * the arugments passed to the listener.\n *\n * @example Container#on\n * // import { Container } from 'js-data';\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new Container();\n * store.on('foo', function (...args) { console.log(args.join(':')) });\n * store.defineMapper('user');\n * store.emit('foo', 'arg1', 'arg2');\n * store.getMapper('user').emit('foo', 'arg1', 'arg2');\n *\n * @method Container#on\n * @param {string} event Name of event to subsribe to.\n * @param {Function} listener Listener function to handle the event.\n * @param {*} [ctx] Optional content in which to invoke the listener.\n * @since 3.0.0\n */\n\n /**\n * Used to bind to events emitted by mappers in this container.\n *\n * @method Container#_onMapperEvent\n * @param {string} name Name of the mapper that emitted the event.\n * @param {...*} [args] Args See {@link Mapper#emit}.\n * @private\n * @since 3.0.0\n */\n _onMapperEvent (name, ...args) {\n const type = args.shift()\n this.emit(type, name, ...args)\n }\n\n /**\n * Return a container scoped to a particular mapper.\n *\n * @example Container#as\n * // import { Container } from 'js-data';\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new Container();\n * const UserMapper = store.defineMapper('user');\n * const UserStore = store.as('user');\n *\n * const user1 = store.createRecord('user', { name: 'John' });\n * const user2 = UserStore.createRecord({ name: 'John' });\n * const user3 = UserMapper.createRecord({ name: 'John' });\n * console.log(user1 === user2);\n * console.log(user2 === user3);\n * console.log(user1 === user3);\n *\n * @method Container#as\n * @param {string} name Name of the {@link Mapper}.\n * @returns {Object} A container scoped to a particular mapper.\n * @since 3.0.0\n */\n as (name) {\n const props: any = {}\n const original = this\n proxiedMapperMethods.forEach(method => {\n props[method] = {\n writable: true,\n value (...args) {\n return original[method](name, ...args)\n }\n }\n })\n props.getMapper = {\n writable: true,\n value () {\n return original.getMapper(name)\n }\n }\n return Object.create(this, props)\n }\n\n /**\n * Create a new mapper and register it in this container.\n *\n * @example Container#defineMapper\n * // import { Container } from 'js-data';\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new Container({\n * mapperDefaults: { foo: 'bar' }\n * });\n * // Container#defineMapper returns a direct reference to the newly created\n * // Mapper.\n * const UserMapper = store.defineMapper('user');\n * console.log(UserMapper === store.getMapper('user'));\n * console.log(UserMapper === store.as('user').getMapper());\n * console.log(UserMapper.foo);\n *\n * @method Container#defineMapper\n * @param {string} name Name under which to register the new {@link Mapper}.\n * {@link Mapper#name} will be set to this value.\n * @param {object} [opts] Configuration options. Passed to\n * {@link Container#mapperClass} when creating the new {@link Mapper}.\n * @returns {Mapper} The newly created instance of {@link Mapper}.\n * @see Container#as\n * @since 3.0.0\n */\n defineMapper (name?: string | MapperOpts | any, opts?: MapperOpts) {\n // For backwards compatibility with defineResource\n if (utils.isObject(name)) {\n opts = name\n name = opts.name\n }\n if (!utils.isString(name)) {\n throw utils.err(`${DOMAIN}#defineMapper`, 'name')(400, 'string', name)\n }\n\n // Default values for arguments\n opts = opts || {}\n // Set Mapper#name\n opts.name = name\n opts.relations = opts.relations || {}\n\n // Check if the user is overriding the datastore's default mapperClass\n const mapperClass = opts.mapperClass || this.mapperClass\n delete opts.mapperClass\n\n // Apply the datastore's defaults to the options going into the mapper\n utils.fillIn(opts, this.mapperDefaults)\n\n // Instantiate a mapper\n const mapper = (this._mappers[name] = new mapperClass(opts)); // eslint-disable-line\n mapper.relations = mapper.relations || {}\n // Make sure the mapper's name is set\n mapper.name = name\n // All mappers in this datastore will share adapters\n mapper._adapters = this.getAdapters()\n\n mapper.datastore = this\n\n mapper.on('all', (...args) => this._onMapperEvent(name, ...args))\n mapper.defineRelations()\n\n return mapper\n }\n\n defineResource (name, opts) {\n console.warn('DEPRECATED: defineResource is deprecated, use defineMapper instead')\n return this.defineMapper(name, opts)\n }\n\n /**\n * Return the registered adapter with the given name or the default adapter if\n * no name is provided.\n *\n * @method Container#getAdapter\n * @param {string} [name] The name of the adapter to retrieve.\n * @returns {Adapter} The adapter.\n * @since 3.0.0\n */\n getAdapter (name?) {\n const adapter = this.getAdapterName(name)\n if (!adapter) {\n throw utils.err(`${DOMAIN}#getAdapter`, 'name')(400, 'string', name)\n }\n return this.getAdapters()[adapter]\n }\n\n /**\n * Return the name of a registered adapter based on the given name or options,\n * or the name of the default adapter if no name provided.\n *\n * @method Container#getAdapterName\n * @param {(Object|string)} [opts] The name of an adapter or options, if any.\n * @returns {string} The name of the adapter.\n * @since 3.0.0\n */\n getAdapterName (opts: any = {}) {\n if (utils.isString(opts)) {\n opts = { adapter: opts }\n }\n return opts.adapter || this.mapperDefaults.defaultAdapter\n }\n\n /**\n * Return the registered adapters of this container.\n *\n * @method Container#getAdapters\n * @returns {Adapter}\n * @since 3.0.0\n */\n getAdapters () {\n return this._adapters\n }\n\n /**\n * Return the mapper registered under the specified name.\n *\n * @example Container#getMapper\n * // import { Container } from 'js-data';\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new Container();\n * // Container#defineMapper returns a direct reference to the newly created\n * // Mapper.\n * const UserMapper = store.defineMapper('user');\n * console.log(UserMapper === store.getMapper('user'));\n * console.log(UserMapper === store.as('user').getMapper());\n * store.getMapper('profile'); // throws Error, there is no mapper with name \"profile\"\n *\n * @method Container#getMapper\n * @param {string} name {@link Mapper#name}.\n * @returns {Mapper}\n * @since 3.0.0\n */\n getMapper (name: string): Mapper {\n const mapper = this.getMapperByName(name)\n if (!mapper) {\n throw utils.err(`${DOMAIN}#getMapper`, name)(404, 'mapper')\n }\n return mapper\n }\n\n /**\n * Return the mapper registered under the specified name.\n * Doesn't throw error if mapper doesn't exist.\n *\n * @example Container#getMapperByName\n * // import { Container } from 'js-data';\n * const JSData = require('js-data');\n * const { Container } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new Container();\n * // Container#defineMapper returns a direct reference to the newly created\n * // Mapper.\n * const UserMapper = store.defineMapper('user');\n * console.log(UserMapper === store.getMapper('user'));\n * console.log(UserMapper === store.as('user').getMapper());\n * console.log(store.getMapper('profile')); // Does NOT throw an error\n *\n * @method Container#getMapperByName\n * @param {string} name {@link Mapper#name}.\n * @returns {Mapper}\n * @since 3.0.0\n */\n getMapperByName (name) {\n return this._mappers[name]\n }\n\n /**\n * Register an adapter on this container under the given name. Adapters\n * registered on a container are shared by all mappers in the container.\n *\n * @example\n * import { Container } from 'js-data';\n * import { RethinkDBAdapter } from 'js-data-rethinkdb';\n * const store = new Container();\n * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true });\n *\n * @method Container#registerAdapter\n * @param {string} name The name of the adapter to register.\n * @param {Adapter} adapter The adapter to register.\n * @param {object} [opts] Configuration options.\n * @param {boolean} [opts.default=false] Whether to make the adapter the\n * default adapter for all Mappers in this container.\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/connecting-to-a-data-source\",\"Connecting to a data source\"]\n */\n registerAdapter (name, adapter, opts: any = {}) {\n this.getAdapters()[name] = adapter\n // Optionally make it the default adapter for the target.\n if (opts === true || opts.default) {\n this.mapperDefaults.defaultAdapter = name\n utils.forOwn(this._mappers, mapper => {\n mapper.defaultAdapter = name\n })\n }\n }\n\n /**\n * Wrapper for {@link Mapper#count}.\n *\n * @example\n * // Get the number of published blog posts\n * import { Container } from 'js-data';\n * import RethinkDBAdapter from 'js-data-rethinkdb';\n * const store = new Container();\n * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('post');\n *\n * store.count('post', { status: 'published' }).then((numPublished) => {\n * console.log(numPublished); // e.g. 45\n * });\n *\n * @method Container#count\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {object} [query] See {@link Mapper#count}.\n * @param {object} [opts] See {@link Mapper#count}.\n * @returns {Promise} See {@link Mapper#count}.\n * @see Mapper#count\n * @since 3.0.0\n */\n count (name, query, opts?) {\n return this.getMapper(name).count(query, opts)\n }\n\n /**\n * Fired during {@link Container#create}. See\n * {@link Container~beforeCreateListener} for how to listen for this event.\n *\n * @event Container#beforeCreate\n * @see Container~beforeCreateListener\n * @see Container#create\n */\n /**\n * Callback signature for the {@link Container#event:beforeCreate} event.\n *\n * @example\n * function onBeforeCreate (mapperName, props, opts) {\n * // do something\n * }\n * store.on('beforeCreate', onBeforeCreate);\n *\n * @callback Container~beforeCreateListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeCreate}.\n * @param {object} props The `props` argument received by {@link Mapper#beforeCreate}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeCreate}.\n * @see Container#event:beforeCreate\n * @see Container#create\n * @since 3.0.0\n */\n /**\n * Fired during {@link Container#create}. See\n * {@link Container~afterCreateListener} for how to listen for this event.\n *\n * @event Container#afterCreate\n * @see Container~afterCreateListener\n * @see Container#create\n */\n\n /**\n * Callback signature for the {@link Container#event:afterCreate} event.\n *\n * @example\n * function onAfterCreate (mapperName, props, opts, result) {\n * // do something\n * }\n * store.on('afterCreate', onAfterCreate);\n *\n * @callback Container~afterCreateListener\n * @param {string} name The `name` argument received by {@link Mapper#afterCreate}.\n * @param {object} props The `props` argument received by {@link Mapper#afterCreate}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterCreate}.\n * @param {object} result The `result` argument received by {@link Mapper#afterCreate}.\n * @see Container#event:afterCreate\n * @see Container#create\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#create}.\n *\n * @example\n * // Create and save a new blog post\n * import { Container } from 'js-data';\n * import RethinkDBAdapter from 'js-data-rethinkdb';\n * const store = new Container();\n * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('post');\n *\n * store.create('post', {\n * title: 'Modeling your data',\n * status: 'draft'\n * }).then((post) => {\n * console.log(post); // { id: 1234, status: 'draft', ... }\n * });\n *\n * @fires Container#beforeCreate\n * @fires Container#afterCreate\n * @method Container#create\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {object} props See {@link Mapper#create}.\n * @param {object} [opts] See {@link Mapper#create}.\n * @returns {Promise} See {@link Mapper#create}.\n * @see Mapper#create\n * @since 3.0.0\n */\n create (name, props, opts) {\n return this.getMapper(name).create(props, opts)\n }\n\n /**\n * Fired during {@link Container#createMany}. See\n * {@link Container~beforeCreateManyListener} for how to listen for this event.\n *\n * @event Container#beforeCreateMany\n * @see Container~beforeCreateManyListener\n * @see Container#createMany\n */\n /**\n * Callback signature for the {@link Container#event:beforeCreateMany} event.\n *\n * @example\n * function onBeforeCreateMany (mapperName, records, opts) {\n * // do something\n * }\n * store.on('beforeCreateMany', onBeforeCreateMany);\n *\n * @callback Container~beforeCreateManyListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeCreateMany}.\n * @param {object} records The `records` argument received by {@link Mapper#beforeCreateMany}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeCreateMany}.\n * @see Container#event:beforeCreateMany\n * @see Container#createMany\n * @since 3.0.0\n */\n /**\n * Fired during {@link Container#createMany}. See\n * {@link Container~afterCreateManyListener} for how to listen for this event.\n *\n * @event Container#afterCreateMany\n * @see Container~afterCreateManyListener\n * @see Container#createMany\n */\n\n /**\n * Callback signature for the {@link Container#event:afterCreateMany} event.\n *\n * @example\n * function onAfterCreateMany (mapperName, records, opts, result) {\n * // do something\n * }\n * store.on('afterCreateMany', onAfterCreateMany);\n *\n * @callback Container~afterCreateManyListener\n * @param {string} name The `name` argument received by {@link Mapper#afterCreateMany}.\n * @param {object} records The `records` argument received by {@link Mapper#afterCreateMany}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterCreateMany}.\n * @param {object} result The `result` argument received by {@link Mapper#afterCreateMany}.\n * @see Container#event:afterCreateMany\n * @see Container#createMany\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#createMany}.\n *\n * @example\n * // Create and save several new blog posts\n * import { Container } from 'js-data';\n * import RethinkDBAdapter from 'js-data-rethinkdb';\n * const store = new Container();\n * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('post');\n *\n * store.createMany('post', [{\n * title: 'Modeling your data',\n * status: 'draft'\n * }, {\n * title: 'Reading data',\n * status: 'draft'\n * }]).then((posts) => {\n * console.log(posts[0]); // { id: 1234, status: 'draft', ... }\n * console.log(posts[1]); // { id: 1235, status: 'draft', ... }\n * });\n *\n * @fires Container#beforeCreateMany\n * @fires Container#afterCreateMany\n * @method Container#createMany\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {Record[]} records See {@link Mapper#createMany}.\n * @param {object} [opts] See {@link Mapper#createMany}.\n * @returns {Promise} See {@link Mapper#createMany}.\n * @see Mapper#createMany\n * @since 3.0.0\n */\n createMany (name, records, opts) {\n return this.getMapper(name).createMany(records, opts)\n }\n\n /**\n * Wrapper for {@link Mapper#createRecord}.\n *\n * __Note:__ This method does __not__ interact with any adapter, and does\n * __not__ save any data. It only creates new objects in memory.\n *\n * @example\n * // Create empty unsaved record instance\n * import { Container } from 'js-data';\n * const store = new Container();\n * store.defineMapper('post');\n * const post = PostMapper.createRecord();\n *\n * @method Container#createRecord\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {Object|Object[]} props See {@link Mapper#createRecord}.\n * @param {object} [opts] See {@link Mapper#createRecord}.\n * @returns {Promise} See {@link Mapper#createRecord}.\n * @see Mapper#createRecord\n * @since 3.0.0\n */\n createRecord (name, props?, opts?) {\n return this.getMapper(name).createRecord(props, opts)\n }\n\n /**\n * Fired during {@link Container#destroy}. See\n * {@link Container~beforeDestroyListener} for how to listen for this event.\n *\n * @event Container#beforeDestroy\n * @see Container~beforeDestroyListener\n * @see Container#destroy\n */\n /**\n * Callback signature for the {@link Container#event:beforeDestroy} event.\n *\n * @example\n * function onBeforeDestroy (mapperName, id, opts) {\n * // do something\n * }\n * store.on('beforeDestroy', onBeforeDestroy);\n *\n * @callback Container~beforeDestroyListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeDestroy}.\n * @param {string|number} id The `id` argument received by {@link Mapper#beforeDestroy}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeDestroy}.\n * @see Container#event:beforeDestroy\n * @see Container#destroy\n * @since 3.0.0\n */\n /**\n * Fired during {@link Container#destroy}. See\n * {@link Container~afterDestroyListener} for how to listen for this event.\n *\n * @event Container#afterDestroy\n * @see Container~afterDestroyListener\n * @see Container#destroy\n */\n\n /**\n * Callback signature for the {@link Container#event:afterDestroy} event.\n *\n * @example\n * function onAfterDestroy (mapperName, id, opts, result) {\n * // do something\n * }\n * store.on('afterDestroy', onAfterDestroy);\n *\n * @callback Container~afterDestroyListener\n * @param {string} name The `name` argument received by {@link Mapper#afterDestroy}.\n * @param {string|number} id The `id` argument received by {@link Mapper#afterDestroy}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterDestroy}.\n * @param {object} result The `result` argument received by {@link Mapper#afterDestroy}.\n * @see Container#event:afterDestroy\n * @see Container#destroy\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#destroy}.\n *\n * @example\n * // Destroy a specific blog post\n * import { Container } from 'js-data';\n * import RethinkDBAdapter from 'js-data-rethinkdb';\n * const store = new Container();\n * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('post');\n *\n * store.destroy('post', 1234).then(() => {\n * // Blog post #1234 has been destroyed\n * });\n *\n * @fires Container#beforeDestroy\n * @fires Container#afterDestroy\n * @method Container#destroy\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {(string|number)} id See {@link Mapper#destroy}.\n * @param {object} [opts] See {@link Mapper#destroy}.\n * @returns {Promise} See {@link Mapper#destroy}.\n * @see Mapper#destroy\n * @since 3.0.0\n */\n destroy (name, id, opts) {\n return this.getMapper(name).destroy(id, opts)\n }\n\n /**\n * Fired during {@link Container#destroyAll}. See\n * {@link Container~beforeDestroyAllListener} for how to listen for this event.\n *\n * @event Container#beforeDestroyAll\n * @see Container~beforeDestroyAllListener\n * @see Container#destroyAll\n */\n /**\n * Callback signature for the {@link Container#event:beforeDestroyAll} event.\n *\n * @example\n * function onBeforeDestroyAll (mapperName, query, opts) {\n * // do something\n * }\n * store.on('beforeDestroyAll', onBeforeDestroyAll);\n *\n * @callback Container~beforeDestroyAllListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeDestroyAll}.\n * @param {object} query The `query` argument received by {@link Mapper#beforeDestroyAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeDestroyAll}.\n * @see Container#event:beforeDestroyAll\n * @see Container#destroyAll\n * @since 3.0.0\n */\n /**\n * Fired during {@link Container#destroyAll}. See\n * {@link Container~afterDestroyAllListener} for how to listen for this event.\n *\n * @event Container#afterDestroyAll\n * @see Container~afterDestroyAllListener\n * @see Container#destroyAll\n */\n\n /**\n * Callback signature for the {@link Container#event:afterDestroyAll} event.\n *\n * @example\n * function onAfterDestroyAll (mapperName, query, opts, result) {\n * // do something\n * }\n * store.on('afterDestroyAll', onAfterDestroyAll);\n *\n * @callback Container~afterDestroyAllListener\n * @param {string} name The `name` argument received by {@link Mapper#afterDestroyAll}.\n * @param {object} query The `query` argument received by {@link Mapper#afterDestroyAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterDestroyAll}.\n * @param {object} result The `result` argument received by {@link Mapper#afterDestroyAll}.\n * @see Container#event:afterDestroyAll\n * @see Container#destroyAll\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#destroyAll}.\n *\n * @example\n * // Destroy all \"draft\" blog posts\n * import { Container } from 'js-data';\n * import RethinkDBAdapter from 'js-data-rethinkdb';\n * const store = new Container();\n * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('post');\n *\n * store.destroyAll('post', { status: 'draft' }).then(() => {\n * // All \"draft\" blog posts have been destroyed\n * });\n *\n * @fires Container#beforeDestroyAll\n * @fires Container#afterDestroyAll\n * @method Container#destroyAll\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {object} [query] See {@link Mapper#destroyAll}.\n * @param {object} [opts] See {@link Mapper#destroyAll}.\n * @returns {Promise} See {@link Mapper#destroyAll}.\n * @see Mapper#destroyAll\n * @since 3.0.0\n */\n destroyAll (name, query, opts) {\n return this.getMapper(name).destroyAll(query, opts)\n }\n\n /**\n * Fired during {@link Container#find}. See\n * {@link Container~beforeFindListener} for how to listen for this event.\n *\n * @event Container#beforeFind\n * @see Container~beforeFindListener\n * @see Container#find\n */\n /**\n * Callback signature for the {@link Container#event:beforeFind} event.\n *\n * @example\n * function onBeforeFind (mapperName, id, opts) {\n * // do something\n * }\n * store.on('beforeFind', onBeforeFind);\n *\n * @callback Container~beforeFindListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeFind}.\n * @param {string|number} id The `id` argument received by {@link Mapper#beforeFind}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeFind}.\n * @see Container#event:beforeFind\n * @see Container#find\n * @since 3.0.0\n */\n /**\n * Fired during {@link Container#find}. See\n * {@link Container~afterFindListener} for how to listen for this event.\n *\n * @event Container#afterFind\n * @see Container~afterFindListener\n * @see Container#find\n */\n\n /**\n * Callback signature for the {@link Container#event:afterFind} event.\n *\n * @example\n * function onAfterFind (mapperName, id, opts, result) {\n * // do something\n * }\n * store.on('afterFind', onAfterFind);\n *\n * @callback Container~afterFindListener\n * @param {string} name The `name` argument received by {@link Mapper#afterFind}.\n * @param {string|number} id The `id` argument received by {@link Mapper#afterFind}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterFind}.\n * @param {object} result The `result` argument received by {@link Mapper#afterFind}.\n * @see Container#event:afterFind\n * @see Container#find\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#find}.\n *\n * @example\n * import { Container } from 'js-data';\n * import RethinkDBAdapter from 'js-data-rethinkdb';\n * const store = new Container();\n * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('post');\n *\n * store.find('post', 1).then((post) => {\n * console.log(post) // { id: 1, ...}\n * });\n *\n * @fires Container#beforeFind\n * @fires Container#afterFind\n * @method Container#find\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {(string|number)} id See {@link Mapper#find}.\n * @param {object} [opts] See {@link Mapper#find}.\n * @returns {Promise} See {@link Mapper#find}.\n * @see Mapper#find\n * @since 3.0.0\n */\n find (name, id, opts) {\n return this.getMapper(name).find(id, opts)\n }\n\n /**\n * Fired during {@link Container#findAll}. See\n * {@link Container~beforeFindAllListener} for how to listen for this event.\n *\n * @event Container#beforeFindAll\n * @see Container~beforeFindAllListener\n * @see Container#findAll\n */\n /**\n * Callback signature for the {@link Container#event:beforeFindAll} event.\n *\n * @example\n * function onBeforeFindAll (mapperName, query, opts) {\n * // do something\n * }\n * store.on('beforeFindAll', onBeforeFindAll);\n *\n * @callback Container~beforeFindAllListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeFindAll}.\n * @param {object} query The `query` argument received by {@link Mapper#beforeFindAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeFindAll}.\n * @see Container#event:beforeFindAll\n * @see Container#findAll\n * @since 3.0.0\n */\n /**\n * Fired during {@link Container#findAll}. See\n * {@link Container~afterFindAllListener} for how to listen for this event.\n *\n * @event Container#afterFindAll\n * @see Container~afterFindAllListener\n * @see Container#findAll\n */\n\n /**\n * Callback signature for the {@link Container#event:afterFindAll} event.\n *\n * @example\n * function onAfterFindAll (mapperName, query, opts, result) {\n * // do something\n * }\n * store.on('afterFindAll', onAfterFindAll);\n *\n * @callback Container~afterFindAllListener\n * @param {string} name The `name` argument received by {@link Mapper#afterFindAll}.\n * @param {object} query The `query` argument received by {@link Mapper#afterFindAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterFindAll}.\n * @param {object} result The `result` argument received by {@link Mapper#afterFindAll}.\n * @see Container#event:afterFindAll\n * @see Container#findAll\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#createRecord}.\n *\n * @example\n * // Find all \"published\" blog posts\n * import { Container } from 'js-data';\n * import RethinkDBAdapter from 'js-data-rethinkdb';\n * const store = new Container();\n * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('post');\n *\n * store.findAll('post', { status: 'published' }).then((posts) => {\n * console.log(posts); // [{ id: 1, ...}, ...]\n * });\n *\n * @fires Container#beforeFindAll\n * @fires Container#afterFindAll\n * @method Container#findAll\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {object} [query] See {@link Mapper#findAll}.\n * @param {object} [opts] See {@link Mapper#findAll}.\n * @returns {Promise} See {@link Mapper#findAll}.\n * @see Mapper#findAll\n * @since 3.0.0\n */\n findAll (name, query, opts) {\n return this.getMapper(name).findAll(query, opts)\n }\n\n /**\n * Wrapper for {@link Mapper#getSchema}.\n *\n * @method Container#getSchema\n * @param {string} name Name of the {@link Mapper} to target.\n * @returns {Schema} See {@link Mapper#getSchema}.\n * @see Mapper#getSchema\n * @since 3.0.0\n */\n getSchema (name) {\n return this.getMapper(name).getSchema()\n }\n\n /**\n * Wrapper for {@link Mapper#is}.\n *\n * @example\n * import { Container } from 'js-data';\n * const store = new Container();\n * store.defineMapper('post');\n * const post = store.createRecord();\n *\n * console.log(store.is('post', post)); // true\n * // Equivalent to what's above\n * console.log(post instanceof store.getMapper('post').recordClass); // true\n *\n * @method Container#is\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {Object|Record} record See {@link Mapper#is}.\n * @returns {boolean} See {@link Mapper#is}.\n * @see Mapper#is\n * @since 3.0.0\n */\n is (name, record) {\n return this.getMapper(name).is(record)\n }\n\n /**\n * Wrapper for {@link Mapper#sum}.\n *\n * @example\n * import { Container } from 'js-data';\n * import RethinkDBAdapter from 'js-data-rethinkdb';\n * const store = new Container();\n * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('purchase_order');\n *\n * store.sum('purchase_order', 'amount', { status: 'paid' }).then((amountPaid) => {\n * console.log(amountPaid); // e.g. 451125.34\n * });\n *\n * @method Container#sum\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {string} field See {@link Mapper#sum}.\n * @param {object} [query] See {@link Mapper#sum}.\n * @param {object} [opts] See {@link Mapper#sum}.\n * @returns {Promise} See {@link Mapper#sum}.\n * @see Mapper#sum\n * @since 3.0.0\n */\n sum (name, field, query, opts) {\n return this.getMapper(name).sum(field, query, opts)\n }\n\n /**\n * Wrapper for {@link Mapper#toJSON}.\n *\n * @example\n * import { Container } from 'js-data';\n * import RethinkDBAdapter from 'js-data-rethinkdb';\n * const store = new Container();\n * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('person', {\n * schema: {\n * properties: {\n * name: { type: 'string' },\n * id: { type: 'string' }\n * }\n * }\n * });\n * const person = store.createRecord('person', { id: 1, name: 'John', foo: 'bar' });\n * // \"foo\" is stripped by toJSON()\n * console.log(store.toJSON('person', person)); // {\"id\":1,\"name\":\"John\"}\n *\n * store.defineMapper('personRelaxed', {\n * schema: {\n * properties: {\n * name: { type: 'string' },\n * id: { type: 'string' }\n * },\n * additionalProperties: true\n * }\n * });\n * const person2 = store.createRecord('personRelaxed', { id: 1, name: 'John', foo: 'bar' });\n * // \"foo\" is not stripped by toJSON\n * console.log(store.toJSON('personRelaxed', person2)); // {\"id\":1,\"name\":\"John\",\"foo\":\"bar\"}\n *\n * @method Container#toJSON\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {Record|Record[]} records See {@link Mapper#toJSON}.\n * @param {object} [opts] See {@link Mapper#toJSON}.\n * @returns {Object|Object[]} See {@link Mapper#toJSON}.\n * @see Mapper#toJSON\n * @since 3.0.0\n */\n toJSON (name, records, opts?) {\n return this.getMapper(name).toJSON(records, opts)\n }\n\n /**\n * Fired during {@link Container#update}. See\n * {@link Container~beforeUpdateListener} for how to listen for this event.\n *\n * @event Container#beforeUpdate\n * @see Container~beforeUpdateListener\n * @see Container#update\n */\n /**\n * Callback signature for the {@link Container#event:beforeUpdate} event.\n *\n * @example\n * function onBeforeUpdate (mapperName, id, props, opts) {\n * // do something\n * }\n * store.on('beforeUpdate', onBeforeUpdate);\n *\n * @callback Container~beforeUpdateListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeUpdate}.\n * @param {string|number} id The `id` argument received by {@link Mapper#beforeUpdate}.\n * @param {object} props The `props` argument received by {@link Mapper#beforeUpdate}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdate}.\n * @see Container#event:beforeUpdate\n * @see Container#update\n * @since 3.0.0\n */\n /**\n * Fired during {@link Container#update}. See\n * {@link Container~afterUpdateListener} for how to listen for this event.\n *\n * @event Container#afterUpdate\n * @see Container~afterUpdateListener\n * @see Container#update\n */\n\n /**\n * Callback signature for the {@link Container#event:afterUpdate} event.\n *\n * @example\n * function onAfterUpdate (mapperName, id, props, opts, result) {\n * // do something\n * }\n * store.on('afterUpdate', onAfterUpdate);\n *\n * @callback Container~afterUpdateListener\n * @param {string} name The `name` argument received by {@link Mapper#afterUpdate}.\n * @param {string|number} id The `id` argument received by {@link Mapper#afterUpdate}.\n * @param {object} props The `props` argument received by {@link Mapper#afterUpdate}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdate}.\n * @param {object} result The `result` argument received by {@link Mapper#afterUpdate}.\n * @see Container#event:afterUpdate\n * @see Container#update\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#update}.\n *\n * @example\n * import { Container } from 'js-data';\n * import RethinkDBAdapter from 'js-data-rethinkdb';\n * const store = new Container();\n * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('post');\n *\n * store.update('post', 1234, {\n * status: 'published',\n * published_at: new Date()\n * }).then((post) => {\n * console.log(post); // { id: 1234, status: 'published', ... }\n * });\n *\n * @fires Container#beforeUpdate\n * @fires Container#afterUpdate\n * @method Container#update\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {(string|number)} id See {@link Mapper#update}.\n * @param {object} props See {@link Mapper#update}.\n * @param {object} [opts] See {@link Mapper#update}.\n * @returns {Promise} See {@link Mapper#update}.\n * @see Mapper#update\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/saving-data\",\"Saving data\"]\n */\n update (name, id, props, opts) {\n return this.getMapper(name).update(id, props, opts)\n }\n\n /**\n * Fired during {@link Container#updateAll}. See\n * {@link Container~beforeUpdateAllListener} for how to listen for this event.\n *\n * @event Container#beforeUpdateAll\n * @see Container~beforeUpdateAllListener\n * @see Container#updateAll\n */\n /**\n * Callback signature for the {@link Container#event:beforeUpdateAll} event.\n *\n * @example\n * function onBeforeUpdateAll (mapperName, props, query, opts) {\n * // do something\n * }\n * store.on('beforeUpdateAll', onBeforeUpdateAll);\n *\n * @callback Container~beforeUpdateAllListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeUpdateAll}.\n * @param {object} props The `props` argument received by {@link Mapper#beforeUpdateAll}.\n * @param {object} query The `query` argument received by {@link Mapper#beforeUpdateAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdateAll}.\n * @see Container#event:beforeUpdateAll\n * @see Container#updateAll\n * @since 3.0.0\n */\n /**\n * Fired during {@link Container#updateAll}. See\n * {@link Container~afterUpdateAllListener} for how to listen for this event.\n *\n * @event Container#afterUpdateAll\n * @see Container~afterUpdateAllListener\n * @see Container#updateAll\n */\n\n /**\n * Callback signature for the {@link Container#event:afterUpdateAll} event.\n *\n * @example\n * function onAfterUpdateAll (mapperName, props, query, opts, result) {\n * // do something\n * }\n * store.on('afterUpdateAll', onAfterUpdateAll);\n *\n * @callback Container~afterUpdateAllListener\n * @param {string} name The `name` argument received by {@link Mapper#afterUpdateAll}.\n * @param {object} props The `props` argument received by {@link Mapper#afterUpdateAll}.\n * @param {object} query The `query` argument received by {@link Mapper#afterUpdateAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdateAll}.\n * @param {object} result The `result` argument received by {@link Mapper#afterUpdateAll}.\n * @see Container#event:afterUpdateAll\n * @see Container#updateAll\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#updateAll}.\n *\n * @example\n * // Turn all of John's blog posts into drafts.\n * import { Container } from 'js-data';\n * import RethinkDBAdapter from 'js-data-rethinkdb';\n * const store = new Container();\n * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('post');\n *\n * const update = { status: draft: published_at: null };\n * const query = { userId: 1234 };\n * store.updateAll('post', update, query).then((posts) => {\n * console.log(posts); // [...]\n * });\n *\n * @fires Container#beforeUpdateAll\n * @fires Container#afterUpdateAll\n * @method Container#updateAll\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {object} props See {@link Mapper#updateAll}.\n * @param {object} [query] See {@link Mapper#updateAll}.\n * @param {object} [opts] See {@link Mapper#updateAll}.\n * @returns {Promise} See {@link Mapper#updateAll}.\n * @see Mapper#updateAll\n * @since 3.0.0\n */\n updateAll (name, props, query, opts) {\n return this.getMapper(name).updateAll(props, query, opts)\n }\n\n /**\n * Fired during {@link Container#updateMany}. See\n * {@link Container~beforeUpdateManyListener} for how to listen for this event.\n *\n * @event Container#beforeUpdateMany\n * @see Container~beforeUpdateManyListener\n * @see Container#updateMany\n */\n /**\n * Callback signature for the {@link Container#event:beforeUpdateMany} event.\n *\n * @example\n * function onBeforeUpdateMany (mapperName, records, opts) {\n * // do something\n * }\n * store.on('beforeUpdateMany', onBeforeUpdateMany);\n *\n * @callback Container~beforeUpdateManyListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeUpdateMany}.\n * @param {object} records The `records` argument received by {@link Mapper#beforeUpdateMany}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdateMany}.\n * @see Container#event:beforeUpdateMany\n * @see Container#updateMany\n * @since 3.0.0\n */\n /**\n * Fired during {@link Container#updateMany}. See\n * {@link Container~afterUpdateManyListener} for how to listen for this event.\n *\n * @event Container#afterUpdateMany\n * @see Container~afterUpdateManyListener\n * @see Container#updateMany\n */\n\n /**\n * Callback signature for the {@link Container#event:afterUpdateMany} event.\n *\n * @example\n * function onAfterUpdateMany (mapperName, records, opts, result) {\n * // do something\n * }\n * store.on('afterUpdateMany', onAfterUpdateMany);\n *\n * @callback Container~afterUpdateManyListener\n * @param {string} name The `name` argument received by {@link Mapper#afterUpdateMany}.\n * @param {object} records The `records` argument received by {@link Mapper#afterUpdateMany}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdateMany}.\n * @param {object} result The `result` argument received by {@link Mapper#afterUpdateMany}.\n * @see Container#event:afterUpdateMany\n * @see Container#updateMany\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#updateMany}.\n *\n * @example\n * import { Container } from 'js-data';\n * import RethinkDBAdapter from 'js-data-rethinkdb';\n * const store = new Container();\n * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true });\n * store.defineMapper('post');\n *\n * store.updateMany('post', [\n * { id: 1234, status: 'draft' },\n * { id: 2468, status: 'published', published_at: new Date() }\n * ]).then((posts) => {\n * console.log(posts); // [...]\n * });\n *\n * @fires Container#beforeUpdateMany\n * @fires Container#afterUpdateMany\n * @method Container#updateMany\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {(Object[]|Record[])} records See {@link Mapper#updateMany}.\n * @param {object} [opts] See {@link Mapper#updateMany}.\n * @returns {Promise} See {@link Mapper#updateMany}.\n * @see Mapper#updateMany\n * @since 3.0.0\n */\n updateMany (name, record, opts) {\n return this.getMapper(name).updateMany(record, opts)\n }\n\n /**\n * Wrapper for {@link Mapper#validate}.\n *\n * @example\n * import { Container } from 'js-data';\n * const store = new Container();\n * store.defineMapper('post', {\n * schema: {\n * properties: {\n * name: { type: 'string' },\n * id: { type: 'string' }\n * }\n * }\n * });\n * let errors = store.validate('post', { name: 'John' });\n * console.log(errors); // undefined\n * errors = store.validate('post', { name: 123 });\n * console.log(errors); // [{ expected: 'one of (string)', actual: 'number', path: 'name' }]\n *\n * @method Container#validate\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {(Object[]|Record[])} records See {@link Mapper#validate}.\n * @param {object} [opts] See {@link Mapper#validate}.\n * @returns {Promise} See {@link Mapper#validate}.\n * @see Mapper#validate\n * @since 3.0.0\n */\n validate (name, record, opts) {\n return this.getMapper(name).validate(record, opts)\n }\n}\n","import utils from './utils'\n\nimport { belongsToType, hasManyType, hasOneType } from './decorators'\nimport { Container, proxiedMapperMethods } from './Container'\nimport Collection from './Collection'\nimport { MapperOpts } from './Mapper'\nimport Schema from './Schema'\n\nconst DOMAIN = 'SimpleStore'\nconst proxiedCollectionMethods = [\n 'add',\n 'between',\n 'createIndex',\n 'filter',\n 'get',\n 'getAll',\n 'prune',\n 'query',\n 'toJSON',\n 'unsaved'\n]\nconst ownMethodsForScoping = ['addToCache', 'cachedFind', 'cachedFindAll', 'cacheFind', 'cacheFindAll', 'hashQuery']\n\nconst cachedFn = function (name, hashOrId, opts) {\n const cached = this._completedQueries[name][hashOrId]\n if (utils.isFunction(cached)) {\n return cached(name, hashOrId, opts)\n }\n return cached\n}\n\nexport interface SimpleStoreOpts {\n /**\n * Whether to use the pending query if a `find` request for the specified\n * record is currently underway. Can be set to `true`, `false`, or to a\n * function that returns `true` or `false`.\n *\n * @default true\n * @name SimpleStore#usePendingFind\n * @since 3.0.0\n * @type {boolean|Function}\n */\n usePendingFind?: boolean | Function\n\n /**\n * Whether to use the pending query if a `findAll` request for the given query\n * is currently underway. Can be set to `true`, `false`, or to a function that\n * returns `true` or `false`.\n *\n * @default true\n * @name SimpleStore#usePendingFindAll\n * @since 3.0.0\n * @type {boolean|Function}\n */\n usePendingFindAll?: boolean | Function\n}\n\nconst SIMPLESTORE_DEFAULTS = {\n /**\n * Whether to use the pending query if a `find` request for the specified\n * record is currently underway. Can be set to `true`, `false`, or to a\n * function that returns `true` or `false`.\n *\n * @default true\n * @name SimpleStore#usePendingFind\n * @since 3.0.0\n * @type {boolean|Function}\n */\n usePendingFind: true,\n\n /**\n * Whether to use the pending query if a `findAll` request for the given query\n * is currently underway. Can be set to `true`, `false`, or to a function that\n * returns `true` or `false`.\n *\n * @default true\n * @name SimpleStore#usePendingFindAll\n * @since 3.0.0\n * @type {boolean|Function}\n */\n usePendingFindAll: true\n}\n\n/**\n * The `SimpleStore` class is an extension of {@link Container}. Not only does\n * `SimpleStore` manage mappers, but also collections. `SimpleStore` implements the\n * asynchronous {@link Mapper} methods, such as {@link Mapper#find} and\n * {@link Mapper#create}. If you use the asynchronous `SimpleStore` methods\n * instead of calling them directly on the mappers, then the results of the\n * method calls will be inserted into the store's collections. You can think of\n * a `SimpleStore` as an [Identity Map](https://en.wikipedia.org/wiki/Identity_map_pattern)\n * for the [ORM](https://en.wikipedia.org/wiki/Object-relational_mapping)\n * (the Mappers).\n *\n * ```javascript\n * import { SimpleStore } from 'js-data';\n * ```\n *\n * @example\n * import { SimpleStore } from 'js-data';\n * import { HttpAdapter } from 'js-data-http';\n * const store = new SimpleStore();\n *\n * // SimpleStore#defineMapper returns a direct reference to the newly created\n * // Mapper.\n * const UserMapper = store.defineMapper('user');\n *\n * // SimpleStore#as returns the store scoped to a particular Mapper.\n * const UserStore = store.as('user');\n *\n * // Call \"find\" on \"UserMapper\" (Stateless ORM)\n * UserMapper.find(1).then((user) => {\n * // retrieved a \"user\" record via the http adapter, but that's it\n *\n * // Call \"find\" on \"store\" targeting \"user\" (Stateful SimpleStore)\n * return store.find('user', 1); // same as \"UserStore.find(1)\"\n * }).then((user) => {\n * // not only was a \"user\" record retrieved, but it was added to the\n * // store's \"user\" collection\n * const cachedUser = store.getCollection('user').get(1);\n * console.log(user === cachedUser); // true\n * });\n *\n * @class SimpleStore\n * @extends Container\n * @param {object} [opts] Configuration options. See {@link Container}.\n * @param {boolean} [opts.collectionClass={@link Collection}] See {@link SimpleStore#collectionClass}.\n * @param {boolean} [opts.debug=false] See {@link Component#debug}.\n * @param {boolean|Function} [opts.usePendingFind=true] See {@link SimpleStore#usePendingFind}.\n * @param {boolean|Function} [opts.usePendingFindAll=true] See {@link SimpleStore#usePendingFindAll}.\n * @returns {SimpleStore}\n * @see Container\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/components-of-jsdata#SimpleStore\",\"Components of JSData: SimpleStore\"]\n * @tutorial [\"http://www.js-data.io/v3.0/docs/working-with-the-SimpleStore\",\"Working with the SimpleStore\"]\n * @tutorial [\"http://www.js-data.io/v3.0/docs/jsdata-and-the-browser\",\"Notes on using JSData in the Browser\"]\n */\nexport default class SimpleStore extends Container {\n collectionClass: typeof Collection;\n _collections: { [name: string]: Collection } = {};\n _completedQueries = {};\n _pendingQueries = {};\n usePendingFind: boolean;\n usePendingFindAll: boolean;\n\n constructor (opts: SimpleStoreOpts = {}) {\n super({ ...SIMPLESTORE_DEFAULTS, ...opts })\n this.collectionClass = this.collectionClass || Collection\n }\n\n /**\n * Internal method used to handle Mapper responses.\n *\n * @method SimpleStore#_end\n * @private\n * @param {string} name Name of the {@link Collection} to which to\n * add the data.\n * @param {object} result The result from a Mapper.\n * @param {object} [opts] Configuration options.\n * @returns {(Object|Array)} Result.\n */\n _end (name, result, opts) {\n let data = opts.raw ? result.data : result\n if (data && utils.isFunction(this.addToCache)) {\n data = this.addToCache(name, data, opts)\n if (opts.raw) {\n result.data = data\n } else {\n result = data\n }\n }\n return result\n }\n\n /**\n * Register a new event listener on this SimpleStore.\n *\n * Proxy for {@link Container#on}. If an event was emitted by a Mapper or\n * Collection in the SimpleStore, then the name of the Mapper or Collection will\n * be prepended to the arugments passed to the provided event handler.\n *\n * @example\n * // Listen for all \"afterCreate\" events in a SimpleStore\n * store.on('afterCreate', (mapperName, props, opts, result) => {\n * console.log(mapperName); // \"post\"\n * console.log(props.id); // undefined\n * console.log(result.id); // 1234\n * });\n * store.create('post', { title: 'Modeling your data' }).then((post) => {\n * console.log(post.id); // 1234\n * });\n *\n * @example\n * // Listen for the \"add\" event on a collection\n * store.on('add', (mapperName, records) => {\n * console.log(records); // [...]\n * });\n *\n * @example\n * // Listen for \"change\" events on a record\n * store.on('change', (mapperName, record, changes) => {\n * console.log(changes); // { changed: { title: 'Modeling your data' } }\n * });\n * post.title = 'Modeling your data';\n *\n * @method SimpleStore#on\n * @param {string} event Name of event to subsribe to.\n * @param {Function} listener Listener function to handle the event.\n * @param {*} [ctx] Optional content in which to invoke the listener.\n */\n\n /**\n * Used to bind to events emitted by collections in this store.\n *\n * @method SimpleStore#_onCollectionEvent\n * @private\n * @param {string} name Name of the collection that emitted the event.\n * @param {...*} [args] Args passed to {@link Collection#emit}.\n */\n _onCollectionEvent (name, ...args) {\n const type = args.shift()\n this.emit(type, name, ...args)\n }\n\n /**\n * This method takes the data received from {@link SimpleStore#find},\n * {@link SimpleStore#findAll}, {@link SimpleStore#update}, etc., and adds the\n * data to the store. _You don't need to call this method directly._\n *\n * If you're using the http adapter and your response data is in an unexpected\n * format, you may need to override this method so the right data gets added\n * to the store.\n *\n * @example\n * const store = new SimpleStore({\n * addToCache (mapperName, data, opts) {\n * // Let's say for a particular Resource, response data is in a weird format\n * if (name === 'comment') {\n * // Re-assign the variable to add the correct records into the stores\n * data = data.items;\n * }\n * // Now perform default behavior\n * return SimpleStore.prototype.addToCache.call(this, mapperName, data, opts);\n * }\n * });\n *\n * @example\n * // Extend using ES2015 class syntax.\n * class MyStore extends SimpleStore {\n * addToCache (mapperName, data, opts) {\n * // Let's say for a particular Resource, response data is in a weird format\n * if (name === 'comment') {\n * // Re-assign the variable to add the correct records into the stores\n * data = data.items;\n * }\n * // Now perform default behavior\n * return super.addToCache(mapperName, data, opts);\n * }\n * }\n * const store = new MyStore();\n *\n * @method SimpleStore#addToCache\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {*} data Data from which data should be selected for add.\n * @param {object} [opts] Configuration options.\n */\n addToCache (name, data, opts) {\n return this.getCollection(name).add(data, opts)\n }\n\n /**\n * Return the store scoped to a particular mapper/collection pair.\n *\n * @example SimpleStore.as\n * const JSData = require('js-data');\n * const { SimpleStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new SimpleStore();\n * const UserMapper = store.defineMapper('user');\n * const UserStore = store.as('user');\n *\n * const user1 = store.createRecord('user', { name: 'John' });\n * const user2 = UserStore.createRecord({ name: 'John' });\n * const user3 = UserMapper.createRecord({ name: 'John' });\n * console.log(user1 === user2);\n * console.log(user2 === user3);\n * console.log(user1 === user3);\n *\n * @method SimpleStore#as\n * @param {string} name Name of the {@link Mapper}.\n * @returns {Object} The store, scoped to a particular Mapper/Collection pair.\n * @since 3.0.0\n */\n as (name) {\n const props: any = {}\n const original = this\n const methods = ownMethodsForScoping.concat(proxiedMapperMethods).concat(proxiedCollectionMethods)\n\n methods.forEach(method => {\n props[method] = {\n writable: true,\n value (...args) {\n return original[method](name, ...args)\n }\n }\n })\n props.getMapper = {\n writable: true,\n value () {\n return original.getMapper(name)\n }\n }\n props.getCollection = {\n writable: true,\n value () {\n return original.getCollection(name)\n }\n }\n return Object.create(this, props)\n }\n\n /**\n * Retrieve a cached `find` result, if any. This method is called during\n * {@link SimpleStore#find} to determine if {@link Mapper#find} needs to be\n * called. If this method returns `undefined` then {@link Mapper#find} will\n * be called. Otherwise {@link SimpleStore#find} will immediately resolve with\n * the return value of this method.\n *\n * When using {@link SimpleStore} in the browser, you can override this method\n * to implement your own cache-busting strategy.\n *\n * @example\n * const store = new SimpleStore({\n * cachedFind (mapperName, id, opts) {\n * // Let's say for a particular Resource, we always want to pull fresh from the server\n * if (mapperName === 'schedule') {\n * // Return undefined to trigger a Mapper#find call\n * return;\n * }\n * // Otherwise perform default behavior\n * return SimpleStore.prototype.cachedFind.call(this, mapperName, id, opts);\n * }\n * });\n *\n * @example\n * // Extend using ES2015 class syntax.\n * class MyStore extends SimpleStore {\n * cachedFind (mapperName, id, opts) {\n * // Let's say for a particular Resource, we always want to pull fresh from the server\n * if (mapperName === 'schedule') {\n * // Return undefined to trigger a Mapper#find call\n * return;\n * }\n * // Otherwise perform default behavior\n * return super.cachedFind(mapperName, id, opts);\n * }\n * }\n * const store = new MyStore();\n *\n * @method SimpleStore#cachedFind\n * @param {string} name The `name` argument passed to {@link SimpleStore#find}.\n * @param {(string|number)} id The `id` argument passed to {@link SimpleStore#find}.\n * @param {object} opts The `opts` argument passed to {@link SimpleStore#find}.\n * @since 3.0.0\n */\n cachedFind = cachedFn\n\n /**\n * Retrieve a cached `findAll` result, if any. This method is called during\n * {@link SimpleStore#findAll} to determine if {@link Mapper#findAll} needs to be\n * called. If this method returns `undefined` then {@link Mapper#findAll} will\n * be called. Otherwise {@link SimpleStore#findAll} will immediately resolve with\n * the return value of this method.\n *\n * When using {@link SimpleStore} in the browser, you can override this method\n * to implement your own cache-busting strategy.\n *\n * @example\n * const store = new SimpleStore({\n * cachedFindAll (mapperName, hash, opts) {\n * // Let's say for a particular Resource, we always want to pull fresh from the server\n * if (mapperName === 'schedule') {\n * // Return undefined to trigger a Mapper#findAll call\n * return undefined;\n * }\n * // Otherwise perform default behavior\n * return SimpleStore.prototype.cachedFindAll.call(this, mapperName, hash, opts);\n * }\n * });\n *\n * @example\n * // Extend using ES2015 class syntax.\n * class MyStore extends SimpleStore {\n * cachedFindAll (mapperName, hash, opts) {\n * // Let's say for a particular Resource, we always want to pull fresh from the server\n * if (mapperName === 'schedule') {\n * // Return undefined to trigger a Mapper#findAll call\n * return undefined;\n * }\n * // Otherwise perform default behavior\n * return super.cachedFindAll(mapperName, hash, opts);\n * }\n * }\n * const store = new MyStore();\n *\n * @method SimpleStore#cachedFindAll\n * @param {string} name The `name` argument passed to {@link SimpleStore#findAll}.\n * @param {string} hash The result of calling {@link SimpleStore#hashQuery} on\n * the `query` argument passed to {@link SimpleStore#findAll}.\n * @param {object} opts The `opts` argument passed to {@link SimpleStore#findAll}.\n * @since 3.0.0\n */\n cachedFindAll = cachedFn\n\n /**\n * Mark a {@link Mapper#find} result as cached by adding an entry to\n * {@link SimpleStore#_completedQueries}. By default, once a `find` entry is\n * added it means subsequent calls to the same Resource with the same `id`\n * argument will immediately resolve with the result of calling\n * {@link SimpleStore#get} instead of delegating to {@link Mapper#find}.\n *\n * As part of implementing your own caching strategy, you may choose to\n * override this method.\n *\n * @example\n * const store = new SimpleStore({\n * cacheFind (mapperName, data, id, opts) {\n * // Let's say for a particular Resource, we always want to pull fresh from the server\n * if (mapperName === 'schedule') {\n * // Return without saving an entry to SimpleStore#_completedQueries\n * return;\n * }\n * // Otherwise perform default behavior\n * return SimpleStore.prototype.cacheFind.call(this, mapperName, data, id, opts);\n * }\n * });\n *\n * @example\n * // Extend using ES2015 class syntax.\n * class MyStore extends SimpleStore {\n * cacheFind (mapperName, data, id, opts) {\n * // Let's say for a particular Resource, we always want to pull fresh from the server\n * if (mapperName === 'schedule') {\n * // Return without saving an entry to SimpleStore#_completedQueries\n * return;\n * }\n * // Otherwise perform default behavior\n * return super.cacheFind(mapperName, data, id, opts);\n * }\n * }\n * const store = new MyStore();\n *\n * @method SimpleStore#cacheFind\n * @param {string} name The `name` argument passed to {@link SimpleStore#find}.\n * @param {*} data The result to cache.\n * @param {(string|number)} id The `id` argument passed to {@link SimpleStore#find}.\n * @param {object} opts The `opts` argument passed to {@link SimpleStore#find}.\n * @since 3.0.0\n */\n cacheFind (name, data, id, opts) {\n this._completedQueries[name][id] = (name, id, opts) => this.get(name, id)\n }\n\n /**\n * Mark a {@link Mapper#findAll} result as cached by adding an entry to\n * {@link SimpleStore#_completedQueries}. By default, once a `findAll` entry is\n * added it means subsequent calls to the same Resource with the same `query`\n * argument will immediately resolve with the result of calling\n * {@link SimpleStore#filter} instead of delegating to {@link Mapper#findAll}.\n *\n * As part of implementing your own caching strategy, you may choose to\n * override this method.\n *\n * @example\n * const store = new SimpleStore({\n * cachedFindAll (mapperName, data, hash, opts) {\n * // Let's say for a particular Resource, we always want to pull fresh from the server\n * if (mapperName === 'schedule') {\n * // Return without saving an entry to SimpleStore#_completedQueries\n * return;\n * }\n * // Otherwise perform default behavior.\n * return SimpleStore.prototype.cachedFindAll.call(this, mapperName, data, hash, opts);\n * }\n * });\n *\n * @example\n * // Extend using ES2015 class syntax.\n * class MyStore extends SimpleStore {\n * cachedFindAll (mapperName, data, hash, opts) {\n * // Let's say for a particular Resource, we always want to pull fresh from the server\n * if (mapperName === 'schedule') {\n * // Return without saving an entry to SimpleStore#_completedQueries\n * return;\n * }\n * // Otherwise perform default behavior.\n * return super.cachedFindAll(mapperName, data, hash, opts);\n * }\n * }\n * const store = new MyStore();\n *\n * @method SimpleStore#cacheFindAll\n * @param {string} name The `name` argument passed to {@link SimpleStore#findAll}.\n * @param {*} data The result to cache.\n * @param {string} hash The result of calling {@link SimpleStore#hashQuery} on\n * the `query` argument passed to {@link SimpleStore#findAll}.\n * @param {object} opts The `opts` argument passed to {@link SimpleStore#findAll}.\n * @since 3.0.0\n */\n cacheFindAll (name, data, hash, opts) {\n this._completedQueries[name][hash] = (name, hash, opts) => this.filter(name, utils.fromJson(hash))\n }\n\n /**\n * Remove __all__ records from the in-memory store and reset\n * {@link SimpleStore#_completedQueries}.\n *\n * @method SimpleStore#clear\n * @returns {Object} Object containing all records that were in the store.\n * @see SimpleStore#remove\n * @see SimpleStore#removeAll\n * @since 3.0.0\n */\n clear () {\n const removed = {}\n utils.forOwn(this._collections, (collection, name) => {\n removed[name] = collection.removeAll()\n this._completedQueries[name] = {}\n })\n return removed\n }\n\n /**\n * Fired during {@link SimpleStore#create}. See\n * {@link SimpleStore~beforeCreateListener} for how to listen for this event.\n *\n * @event SimpleStore#beforeCreate\n * @see SimpleStore~beforeCreateListener\n * @see SimpleStore#create\n */\n /**\n * Callback signature for the {@link SimpleStore#event:beforeCreate} event.\n *\n * @example\n * function onBeforeCreate (mapperName, props, opts) {\n * // do something\n * }\n * store.on('beforeCreate', onBeforeCreate);\n *\n * @callback SimpleStore~beforeCreateListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeCreate}.\n * @param {object} props The `props` argument received by {@link Mapper#beforeCreate}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeCreate}.\n * @see SimpleStore#event:beforeCreate\n * @see SimpleStore#create\n * @since 3.0.0\n */\n /**\n * Fired during {@link SimpleStore#create}. See\n * {@link SimpleStore~afterCreateListener} for how to listen for this event.\n *\n * @event SimpleStore#afterCreate\n * @see SimpleStore~afterCreateListener\n * @see SimpleStore#create\n */\n\n /**\n * Callback signature for the {@link SimpleStore#event:afterCreate} event.\n *\n * @example\n * function onAfterCreate (mapperName, props, opts, result) {\n * // do something\n * }\n * store.on('afterCreate', onAfterCreate);\n *\n * @callback SimpleStore~afterCreateListener\n * @param {string} name The `name` argument received by {@link Mapper#afterCreate}.\n * @param {object} props The `props` argument received by {@link Mapper#afterCreate}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterCreate}.\n * @param {object} result The `result` argument received by {@link Mapper#afterCreate}.\n * @see SimpleStore#event:afterCreate\n * @see SimpleStore#create\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#create}. Adds the created record to the store.\n *\n * @example\n * import { SimpleStore } from 'js-data';\n * import { HttpAdapter } from 'js-data-http';\n *\n * const store = new SimpleStore();\n * store.registerAdapter('http', new HttpAdapter(), { default: true });\n *\n * store.defineMapper('book');\n *\n * // Since this example uses the http adapter, we'll get something like:\n * //\n * // POST /book {\"author_id\":1234,...}\n * store.create('book', {\n * author_id: 1234,\n * edition: 'First Edition',\n * title: 'Respect your Data'\n * }).then((book) => {\n * console.log(book.id); // 120392\n * console.log(book.title); // \"Respect your Data\"\n * });\n *\n * @fires SimpleStore#beforeCreate\n * @fires SimpleStore#afterCreate\n * @fires SimpleStore#add\n * @method SimpleStore#create\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {object} record Passed to {@link Mapper#create}.\n * @param {object} [opts] Passed to {@link Mapper#create}. See\n * {@link Mapper#create} for more configuration options.\n * @returns {Promise} Resolves with the result of the create.\n * @since 3.0.0\n */\n create (name, record, opts: any = {}) {\n return super.create(name, record, opts).then(result => this._end(name, result, opts))\n }\n\n /**\n * Fired during {@link SimpleStore#createMany}. See\n * {@link SimpleStore~beforeCreateManyListener} for how to listen for this event.\n *\n * @event SimpleStore#beforeCreateMany\n * @see SimpleStore~beforeCreateManyListener\n * @see SimpleStore#createMany\n */\n /**\n * Callback signature for the {@link SimpleStore#event:beforeCreateMany} event.\n *\n * @example\n * function onBeforeCreateMany (mapperName, records, opts) {\n * // do something\n * }\n * store.on('beforeCreateMany', onBeforeCreateMany);\n *\n * @callback SimpleStore~beforeCreateManyListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeCreateMany}.\n * @param {object} records The `records` argument received by {@link Mapper#beforeCreateMany}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeCreateMany}.\n * @see SimpleStore#event:beforeCreateMany\n * @see SimpleStore#createMany\n * @since 3.0.0\n */\n /**\n * Fired during {@link SimpleStore#createMany}. See\n * {@link SimpleStore~afterCreateManyListener} for how to listen for this event.\n *\n * @event SimpleStore#afterCreateMany\n * @see SimpleStore~afterCreateManyListener\n * @see SimpleStore#createMany\n */\n\n /**\n * Callback signature for the {@link SimpleStore#event:afterCreateMany} event.\n *\n * @example\n * function onAfterCreateMany (mapperName, records, opts, result) {\n * // do something\n * }\n * store.on('afterCreateMany', onAfterCreateMany);\n *\n * @callback SimpleStore~afterCreateManyListener\n * @param {string} name The `name` argument received by {@link Mapper#afterCreateMany}.\n * @param {object} records The `records` argument received by {@link Mapper#afterCreateMany}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterCreateMany}.\n * @param {object} result The `result` argument received by {@link Mapper#afterCreateMany}.\n * @see SimpleStore#event:afterCreateMany\n * @see SimpleStore#createMany\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#createMany}. Adds the created records to the\n * store.\n *\n * @example\n * import { SimpleStore } from 'js-data';\n * import { HttpAdapter } from 'js-data-http';\n *\n * const store = new SimpleStore();\n * store.registerAdapter('http', new HttpAdapter(), { default: true });\n *\n * store.defineMapper('book');\n *\n * // Since this example uses the http adapter, we'll get something like:\n * //\n * // POST /book [{\"author_id\":1234,...},{...}]\n * store.createMany('book', [{\n * author_id: 1234,\n * edition: 'First Edition',\n * title: 'Respect your Data'\n * }, {\n * author_id: 1234,\n * edition: 'Second Edition',\n * title: 'Respect your Data'\n * }]).then((books) => {\n * console.log(books[0].id); // 142394\n * console.log(books[0].title); // \"Respect your Data\"\n * });\n *\n * @fires SimpleStore#beforeCreateMany\n * @fires SimpleStore#afterCreateMany\n * @fires SimpleStore#add\n * @method SimpleStore#createMany\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {array} records Passed to {@link Mapper#createMany}.\n * @param {object} [opts] Passed to {@link Mapper#createMany}. See\n * {@link Mapper#createMany} for more configuration options.\n * @returns {Promise} Resolves with the result of the create.\n * @since 3.0.0\n */\n createMany (name, records, opts: any = {}) {\n return super.createMany(name, records, opts).then(result => this._end(name, result, opts))\n }\n\n defineMapper (name, opts: MapperOpts = {}) {\n const self = this\n const mapper = super.defineMapper(name, opts)\n self._pendingQueries[name] = {}\n self._completedQueries[name] = {}\n if (!mapper.relationList) Object.defineProperty(mapper, 'relationList', { value: [] })\n\n const collectionOpts: any = {\n // Make sure the collection has somewhere to store \"added\" timestamps\n _added: {},\n // Give the collection a reference to this SimpleStore\n datastore: this,\n // The mapper tied to the collection\n mapper\n }\n\n if (opts && 'onConflict' in opts) {\n collectionOpts.onConflict = opts.onConflict\n }\n\n // The SimpleStore uses a subclass of Collection that is \"SimpleStore-aware\"\n const collection = (self._collections[name] = new self.collectionClass(null, collectionOpts))\n\n const schema = mapper.schema || ({} as Schema)\n const properties = schema.properties || {}\n // TODO: Make it possible index nested properties?\n utils.forOwn(properties, (opts, prop) => {\n if (opts.indexed) {\n collection.createIndex(prop)\n }\n })\n\n // Create a secondary index on the \"added\" timestamps of records in the\n // collection\n collection.createIndex('addedTimestamps', ['$'], {\n fieldGetter (obj) {\n return collection._added[collection.recordId(obj)]\n }\n })\n\n collection.on('all', (...args) => {\n self._onCollectionEvent(name, ...args)\n })\n\n return mapper\n }\n\n /**\n * Fired during {@link SimpleStore#destroy}. See\n * {@link SimpleStore~beforeDestroyListener} for how to listen for this event.\n *\n * @event SimpleStore#beforeDestroy\n * @see SimpleStore~beforeDestroyListener\n * @see SimpleStore#destroy\n */\n /**\n * Callback signature for the {@link SimpleStore#event:beforeDestroy} event.\n *\n * @example\n * function onBeforeDestroy (mapperName, id, opts) {\n * // do something\n * }\n * store.on('beforeDestroy', onBeforeDestroy);\n *\n * @callback SimpleStore~beforeDestroyListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeDestroy}.\n * @param {string|number} id The `id` argument received by {@link Mapper#beforeDestroy}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeDestroy}.\n * @see SimpleStore#event:beforeDestroy\n * @see SimpleStore#destroy\n * @since 3.0.0\n */\n /**\n * Fired during {@link SimpleStore#destroy}. See\n * {@link SimpleStore~afterDestroyListener} for how to listen for this event.\n *\n * @event SimpleStore#afterDestroy\n * @see SimpleStore~afterDestroyListener\n * @see SimpleStore#destroy\n */\n\n /**\n * Callback signature for the {@link SimpleStore#event:afterDestroy} event.\n *\n * @example\n * function onAfterDestroy (mapperName, id, opts, result) {\n * // do something\n * }\n * store.on('afterDestroy', onAfterDestroy);\n *\n * @callback SimpleStore~afterDestroyListener\n * @param {string} name The `name` argument received by {@link Mapper#afterDestroy}.\n * @param {string|number} id The `id` argument received by {@link Mapper#afterDestroy}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterDestroy}.\n * @param {object} result The `result` argument received by {@link Mapper#afterDestroy}.\n * @see SimpleStore#event:afterDestroy\n * @see SimpleStore#destroy\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#destroy}. Removes any destroyed record from the\n * in-memory store. Clears out any {@link SimpleStore#_completedQueries} entries\n * associated with the provided `id`.\n *\n * @example\n * import { SimpleStore } from 'js-data';\n * import { HttpAdapter } from 'js-data-http';\n *\n * const store = new SimpleStore();\n * store.registerAdapter('http', new HttpAdapter(), { default: true });\n *\n * store.defineMapper('book');\n *\n * store.add('book', { id: 1234, title: 'Data Management is Hard' });\n *\n * // Since this example uses the http adapter, we'll get something like:\n * //\n * // DELETE /book/1234\n * store.destroy('book', 1234).then(() => {\n * // The book record is no longer in the in-memory store\n * console.log(store.get('book', 1234)); // undefined\n *\n * return store.find('book', 1234);\n * }).then((book) {\n * // The book was deleted from the database too\n * console.log(book); // undefined\n * });\n *\n * @fires SimpleStore#beforeDestroy\n * @fires SimpleStore#afterDestroy\n * @fires SimpleStore#remove\n * @method SimpleStore#destroy\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {(string|number)} id Passed to {@link Mapper#destroy}.\n * @param {object} [opts] Passed to {@link Mapper#destroy}. See\n * {@link Mapper#destroy} for more configuration options.\n * @returns {Promise} Resolves when the destroy operation completes.\n * @since 3.0.0\n */\n destroy (name, id, opts: any = {}) {\n return super.destroy(name, id, opts).then(result => {\n const record = this.getCollection(name).remove(id, opts)\n\n if (opts.raw) {\n result.data = record\n } else {\n result = record\n }\n delete this._pendingQueries[name][id]\n delete this._completedQueries[name][id]\n return result\n })\n }\n\n /**\n * Fired during {@link SimpleStore#destroyAll}. See\n * {@link SimpleStore~beforeDestroyAllListener} for how to listen for this event.\n *\n * @event SimpleStore#beforeDestroyAll\n * @see SimpleStore~beforeDestroyAllListener\n * @see SimpleStore#destroyAll\n */\n /**\n * Callback signature for the {@link SimpleStore#event:beforeDestroyAll} event.\n *\n * @example\n * function onBeforeDestroyAll (mapperName, query, opts) {\n * // do something\n * }\n * store.on('beforeDestroyAll', onBeforeDestroyAll);\n *\n * @callback SimpleStore~beforeDestroyAllListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeDestroyAll}.\n * @param {object} query The `query` argument received by {@link Mapper#beforeDestroyAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeDestroyAll}.\n * @see SimpleStore#event:beforeDestroyAll\n * @see SimpleStore#destroyAll\n * @since 3.0.0\n */\n /**\n * Fired during {@link SimpleStore#destroyAll}. See\n * {@link SimpleStore~afterDestroyAllListener} for how to listen for this event.\n *\n * @event SimpleStore#afterDestroyAll\n * @see SimpleStore~afterDestroyAllListener\n * @see SimpleStore#destroyAll\n */\n\n /**\n * Callback signature for the {@link SimpleStore#event:afterDestroyAll} event.\n *\n * @example\n * function onAfterDestroyAll (mapperName, query, opts, result) {\n * // do something\n * }\n * store.on('afterDestroyAll', onAfterDestroyAll);\n *\n * @callback SimpleStore~afterDestroyAllListener\n * @param {string} name The `name` argument received by {@link Mapper#afterDestroyAll}.\n * @param {object} query The `query` argument received by {@link Mapper#afterDestroyAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterDestroyAll}.\n * @param {object} result The `result` argument received by {@link Mapper#afterDestroyAll}.\n * @see SimpleStore#event:afterDestroyAll\n * @see SimpleStore#destroyAll\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#destroyAll}. Removes any destroyed records from\n * the in-memory store.\n *\n * @example\n * import { SimpleStore } from 'js-data';\n * import { HttpAdapter } from 'js-data-http';\n *\n * const store = new SimpleStore();\n * store.registerAdapter('http', new HttpAdapter(), { default: true });\n *\n * store.defineMapper('book');\n *\n * store.add('book', { id: 1234, title: 'Data Management is Hard' });\n *\n * // Since this example uses the http adapter, we'll get something like:\n * //\n * // DELETE /book/1234\n * store.destroy('book', 1234).then(() => {\n * // The book record is gone from the in-memory store\n * console.log(store.get('book', 1234)); // undefined\n * return store.find('book', 1234);\n * }).then((book) {\n * // The book was deleted from the database too\n * console.log(book); // undefined\n * });\n *\n * @fires SimpleStore#beforeDestroyAll\n * @fires SimpleStore#afterDestroyAll\n * @fires SimpleStore#remove\n * @method SimpleStore#destroyAll\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {object} [query] Passed to {@link Mapper#destroyAll}.\n * @param {object} [opts] Passed to {@link Mapper#destroyAll}. See\n * {@link Mapper#destroyAll} for more configuration options.\n * @returns {Promise} Resolves when the delete completes.\n * @since 3.0.0\n */\n destroyAll (name, query, opts: any = {}) {\n return super.destroyAll(name, query, opts).then(result => {\n const records = this.getCollection(name).removeAll(query, opts)\n\n if (opts.raw) {\n result.data = records\n } else {\n result = records\n }\n const hash = this.hashQuery(name, query, opts)\n delete this._pendingQueries[name][hash]\n delete this._completedQueries[name][hash]\n return result\n })\n }\n\n eject (name, id, opts) {\n console.warn('DEPRECATED: \"eject\" is deprecated, use \"remove\" instead')\n return this.remove(name, id, opts)\n }\n\n ejectAll (name, query, opts) {\n console.warn('DEPRECATED: \"ejectAll\" is deprecated, use \"removeAll\" instead')\n return this.removeAll(name, query, opts)\n }\n\n /**\n * Fired during {@link SimpleStore#find}. See\n * {@link SimpleStore~beforeFindListener} for how to listen for this event.\n *\n * @event SimpleStore#beforeFind\n * @see SimpleStore~beforeFindListener\n * @see SimpleStore#find\n */\n /**\n * Callback signature for the {@link SimpleStore#event:beforeFind} event.\n *\n * @example\n * function onBeforeFind (mapperName, id, opts) {\n * // do something\n * }\n * store.on('beforeFind', onBeforeFind);\n *\n * @callback SimpleStore~beforeFindListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeFind}.\n * @param {string|number} id The `id` argument received by {@link Mapper#beforeFind}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeFind}.\n * @see SimpleStore#event:beforeFind\n * @see SimpleStore#find\n * @since 3.0.0\n */\n /**\n * Fired during {@link SimpleStore#find}. See\n * {@link SimpleStore~afterFindListener} for how to listen for this event.\n *\n * @event SimpleStore#afterFind\n * @see SimpleStore~afterFindListener\n * @see SimpleStore#find\n */\n\n /**\n * Callback signature for the {@link SimpleStore#event:afterFind} event.\n *\n * @example\n * function onAfterFind (mapperName, id, opts, result) {\n * // do something\n * }\n * store.on('afterFind', onAfterFind);\n *\n * @callback SimpleStore~afterFindListener\n * @param {string} name The `name` argument received by {@link Mapper#afterFind}.\n * @param {string|number} id The `id` argument received by {@link Mapper#afterFind}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterFind}.\n * @param {object} result The `result` argument received by {@link Mapper#afterFind}.\n * @see SimpleStore#event:afterFind\n * @see SimpleStore#find\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#find}. Adds any found record to the store.\n *\n * @example\n * import { SimpleStore } from 'js-data';\n * import { HttpAdapter } from 'js-data-http';\n *\n * const store = new SimpleStore();\n * store.registerAdapter('http', new HttpAdapter(), { default: true });\n *\n * store.defineMapper('book');\n *\n * // Since this example uses the http adapter, we'll get something like:\n * //\n * // GET /book/1234\n * store.find('book', 1234).then((book) => {\n * // The book record is now in the in-memory store\n * console.log(store.get('book', 1234) === book); // true\n * });\n *\n * @fires SimpleStore#beforeFind\n * @fires SimpleStore#afterFind\n * @fires SimpleStore#add\n * @method SimpleStore#find\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {(string|number)} id Passed to {@link Mapper#find}.\n * @param {object} [opts] Passed to {@link Mapper#find}.\n * @param {boolean} [opts.force] Bypass cacheFind\n * @param {boolean|Function} [opts.usePendingFind] See {@link SimpleStore#usePendingFind}\n * @returns {Promise} Resolves with the result, if any.\n * @since 3.0.0\n */\n find (name, id, opts: any = {}) {\n const mapper = this.getMapper(name)\n const pendingQuery = this._pendingQueries[name][id]\n const usePendingFind = opts.usePendingFind === undefined ? this.usePendingFind : opts.usePendingFind\n utils._(opts, mapper)\n\n if (\n pendingQuery &&\n (utils.isFunction(usePendingFind) ? usePendingFind.call(this, name, id, opts) : usePendingFind)\n ) {\n return pendingQuery\n }\n const item = this.cachedFind(name, id, opts)\n\n if (opts.force || !item) {\n const promise = (this._pendingQueries[name][id] = super.find(name, id, opts))\n return promise.then(\n result => {\n delete this._pendingQueries[name][id]\n result = this._end(name, result, opts)\n this.cacheFind(name, result, id, opts)\n return result\n },\n err => {\n delete this._pendingQueries[name][id]\n return utils.reject(err)\n }\n )\n }\n\n return utils.resolve(item)\n }\n\n /**\n * Fired during {@link SimpleStore#findAll}. See\n * {@link SimpleStore~beforeFindAllListener} for how to listen for this event.\n *\n * @event SimpleStore#beforeFindAll\n * @see SimpleStore~beforeFindAllListener\n * @see SimpleStore#findAll\n */\n /**\n * Callback signature for the {@link SimpleStore#event:beforeFindAll} event.\n *\n * @example\n * function onBeforeFindAll (mapperName, query, opts) {\n * // do something\n * }\n * store.on('beforeFindAll', onBeforeFindAll);\n *\n * @callback SimpleStore~beforeFindAllListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeFindAll}.\n * @param {object} query The `query` argument received by {@link Mapper#beforeFindAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeFindAll}.\n * @see SimpleStore#event:beforeFindAll\n * @see SimpleStore#findAll\n * @since 3.0.0\n */\n /**\n * Fired during {@link SimpleStore#findAll}. See\n * {@link SimpleStore~afterFindAllListener} for how to listen for this event.\n *\n * @event SimpleStore#afterFindAll\n * @see SimpleStore~afterFindAllListener\n * @see SimpleStore#findAll\n */\n\n /**\n * Callback signature for the {@link SimpleStore#event:afterFindAll} event.\n *\n * @example\n * function onAfterFindAll (mapperName, query, opts, result) {\n * // do something\n * }\n * store.on('afterFindAll', onAfterFindAll);\n *\n * @callback SimpleStore~afterFindAllListener\n * @param {string} name The `name` argument received by {@link Mapper#afterFindAll}.\n * @param {object} query The `query` argument received by {@link Mapper#afterFindAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterFindAll}.\n * @param {object} result The `result` argument received by {@link Mapper#afterFindAll}.\n * @see SimpleStore#event:afterFindAll\n * @see SimpleStore#findAll\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#findAll}. Adds any found records to the store.\n *\n * @example\n * import { SimpleStore } from 'js-data';\n * import { HttpAdapter } from 'js-data-http';\n *\n * const store = new SimpleStore();\n * store.registerAdapter('http', new HttpAdapter(), { default: true });\n *\n * store.defineMapper('movie');\n *\n * // Since this example uses the http adapter, we'll get something like:\n * //\n * // GET /movie?rating=PG\n * store.find('movie', { rating: 'PG' }).then((movies) => {\n * // The movie records are now in the in-memory store\n * console.log(store.filter('movie'));\n * });\n *\n * @fires SimpleStore#beforeFindAll\n * @fires SimpleStore#afterFindAll\n * @fires SimpleStore#add\n * @method SimpleStore#findAll\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {object} [query] Passed to {@link Mapper.findAll}.\n * @param {object} [opts] Passed to {@link Mapper.findAll}.\n * @param {boolean} [opts.force] Bypass cacheFindAll\n * @param {boolean|Function} [opts.usePendingFindAll] See {@link SimpleStore#usePendingFindAll}\n * @returns {Promise} Resolves with the result, if any.\n * @since 3.0.0\n */\n findAll (name, query, opts: any = {}) {\n const mapper = this.getMapper(name)\n const hash = this.hashQuery(name, query, opts)\n const pendingQuery = this._pendingQueries[name][hash]\n const usePendingFindAll = opts.usePendingFindAll === undefined ? this.usePendingFindAll : opts.usePendingFindAll\n utils._(opts, mapper)\n\n if (\n pendingQuery &&\n (utils.isFunction(usePendingFindAll) ? usePendingFindAll.call(this, name, query, opts) : usePendingFindAll)\n ) {\n return pendingQuery\n }\n\n const items = this.cachedFindAll(name, hash, opts)\n\n if (opts.force || !items) {\n const promise = (this._pendingQueries[name][hash] = super.findAll(name, query, opts))\n return promise.then(\n result => {\n delete this._pendingQueries[name][hash]\n result = this._end(name, result, opts)\n this.cacheFindAll(name, result, hash, opts)\n return result\n },\n err => {\n delete this._pendingQueries[name][hash]\n return utils.reject(err)\n }\n )\n }\n\n return utils.resolve(items)\n }\n\n /**\n * Return the {@link Collection} with the given name, if for some\n * reason you need a direct reference to the collection.\n *\n * @param {string} name Name of the {@link Collection} to retrieve.\n * @since 3.0.0\n * @throws {Error} Thrown if the specified {@link Collection} does not\n * exist.\n */\n getCollection (name): Collection {\n const collection = this._collections[name]\n if (!collection) {\n throw utils.err(`${DOMAIN}#getCollection`, name)(404, 'collection')\n }\n return collection\n }\n\n /**\n * Hashing function used to cache {@link SimpleStore#find} and\n * {@link SimpleStore#findAll} requests. This method simply JSONifies the\n * `query` argument passed to {@link SimpleStore#find} or\n * {@link SimpleStore#findAll}.\n *\n * Override this method for custom hashing behavior.\n * @method SimpleStore#hashQuery\n * @param {string} name The `name` argument passed to {@link SimpleStore#find}\n * or {@link SimpleStore#findAll}.\n * @param {object} query The `query` argument passed to {@link SimpleStore#find}\n * or {@link SimpleStore#findAll}.\n * @returns {string} The JSONified `query`.\n * @since 3.0.0\n */\n hashQuery (name, query, opts) {\n return utils.toJson(query || {})\n }\n\n inject (name, records, opts) {\n console.warn('DEPRECATED: \"inject\" is deprecated, use \"add\" instead')\n return this.add(name, records, opts)\n }\n\n /**\n * Wrapper for {@link Collection#remove}. Removes the specified\n * {@link Record} from the store.\n *\n * @example SimpleStore#remove\n * const JSData = require('js-data');\n * const { SimpleStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new SimpleStore();\n * store.defineMapper('book');\n * console.log(store.getAll('book').length);\n * store.add('book', { id: 1234 });\n * console.log(store.getAll('book').length);\n * store.remove('book', 1234);\n * console.log(store.getAll('book').length);\n *\n * @fires SimpleStore#remove\n * @method SimpleStore#remove\n * @param {string} name The name of the {@link Collection} to target.\n * @param {string|number} id The primary key of the {@link Record} to remove.\n * @param {object} [opts] Configuration options.\n * @param {string[]} [opts.with] Relations of the {@link Record} to also\n * remove from the store.\n * @returns {Record} The removed {@link Record}, if any.\n * @see Collection#add\n * @see Collection#add\n * @since 3.0.0\n */\n remove (name, id, opts?) {\n const record = this.getCollection(name).remove(id, opts)\n if (record) {\n this.removeRelated(name, [record], opts)\n }\n return record\n }\n\n /**\n * Wrapper for {@link Collection#removeAll}. Removes the selected\n * {@link Record}s from the store.\n *\n * @example SimpleStore#removeAll\n * const JSData = require('js-data');\n * const { SimpleStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new SimpleStore();\n * store.defineMapper('movie');\n * console.log(store.getAll('movie').length);\n * store.add('movie', [{ id: 3, rating: 'R' }, { id: 4, rating: 'PG-13' });\n * console.log(store.getAll('movie').length);\n * store.removeAll('movie', { rating: 'R' });\n * console.log(store.getAll('movie').length);\n *\n * @fires SimpleStore#remove\n * @method SimpleStore#removeAll\n * @param {string} name The name of the {@link Collection} to target.\n * @param {object} [query={}] Selection query. See {@link query}.\n * @param {object} [query.where] See {@link query.where}.\n * @param {number} [query.offset] See {@link query.offset}.\n * @param {number} [query.limit] See {@link query.limit}.\n * @param {string|Array[]} [query.orderBy] See {@link query.orderBy}.\n * @param {object} [opts] Configuration options.\n * @param {string[]} [opts.with] Relations of the {@link Record} to also\n * remove from the store.\n * @returns {Record} The removed {@link Record}s, if any.\n * @see Collection#add\n * @see Collection#add\n * @since 3.0.0\n */\n removeAll (name, query, opts) {\n if (!query || !Object.keys(query).length) {\n this._completedQueries[name] = {}\n } else {\n this._completedQueries[name][this.hashQuery(name, query, opts)] = undefined\n }\n const records = this.getCollection(name).removeAll(query, opts)\n if (records.length) {\n this.removeRelated(name, records, opts)\n }\n return records\n }\n\n /**\n * Remove from the store {@link Record}s that are related to the provided\n * {@link Record}(s).\n *\n * @fires SimpleStore#remove\n * @method SimpleStore#removeRelated\n * @param {string} name The name of the {@link Collection} to target.\n * @param {Record|Record[]} records {@link Record}s whose relations are to be\n * removed.\n * @param {object} [opts] Configuration options.\n * @param {string[]} [opts.with] Relations of the {@link Record}(s) to remove\n * from the store.\n * @since 3.0.0\n */\n removeRelated (name, records, opts) {\n if (!utils.isArray(records)) {\n records = [records]\n }\n utils.forEachRelation(this.getMapper(name), opts, (def, optsCopy) => {\n records.forEach(record => {\n let relatedData\n let query\n if (def.foreignKey && (def.type === hasOneType || def.type === hasManyType)) {\n query = { [def.foreignKey]: def.getForeignKey(record) }\n } else if (def.type === hasManyType && def.localKeys) {\n query = {\n where: {\n [def.getRelation().idAttribute]: {\n in: utils.get(record, def.localKeys)\n }\n }\n }\n } else if (def.type === hasManyType && def.foreignKeys) {\n query = {\n where: {\n [def.foreignKeys]: {\n contains: def.getForeignKey(record)\n }\n }\n }\n } else if (def.type === belongsToType) {\n relatedData = this.remove(def.relation, def.getForeignKey(record), optsCopy)\n }\n if (query) {\n relatedData = this.removeAll(def.relation, query, optsCopy)\n }\n if (relatedData) {\n if (utils.isArray(relatedData) && !relatedData.length) {\n return\n }\n if (def.type === hasOneType) {\n relatedData = relatedData[0]\n }\n def.setLocalField(record, relatedData)\n }\n })\n })\n }\n\n /**\n * Fired during {@link SimpleStore#update}. See\n * {@link SimpleStore~beforeUpdateListener} for how to listen for this event.\n *\n * @event SimpleStore#beforeUpdate\n * @see SimpleStore~beforeUpdateListener\n * @see SimpleStore#update\n */\n /**\n * Callback signature for the {@link SimpleStore#event:beforeUpdate} event.\n *\n * @example\n * function onBeforeUpdate (mapperName, id, props, opts) {\n * // do something\n * }\n * store.on('beforeUpdate', onBeforeUpdate);\n *\n * @callback SimpleStore~beforeUpdateListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeUpdate}.\n * @param {string|number} id The `id` argument received by {@link Mapper#beforeUpdate}.\n * @param {object} props The `props` argument received by {@link Mapper#beforeUpdate}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdate}.\n * @see SimpleStore#event:beforeUpdate\n * @see SimpleStore#update\n * @since 3.0.0\n */\n /**\n * Fired during {@link SimpleStore#update}. See\n * {@link SimpleStore~afterUpdateListener} for how to listen for this event.\n *\n * @event SimpleStore#afterUpdate\n * @see SimpleStore~afterUpdateListener\n * @see SimpleStore#update\n */\n\n /**\n * Callback signature for the {@link SimpleStore#event:afterUpdate} event.\n *\n * @example\n * function onAfterUpdate (mapperName, id, props, opts, result) {\n * // do something\n * }\n * store.on('afterUpdate', onAfterUpdate);\n *\n * @callback SimpleStore~afterUpdateListener\n * @param {string} name The `name` argument received by {@link Mapper#afterUpdate}.\n * @param {string|number} id The `id` argument received by {@link Mapper#afterUpdate}.\n * @param {object} props The `props` argument received by {@link Mapper#afterUpdate}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdate}.\n * @param {object} result The `result` argument received by {@link Mapper#afterUpdate}.\n * @see SimpleStore#event:afterUpdate\n * @see SimpleStore#update\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#update}. Adds the updated {@link Record} to the\n * store.\n *\n * @example\n * import { SimpleStore } from 'js-data';\n * import { HttpAdapter } from 'js-data-http';\n *\n * const store = new SimpleStore();\n * store.registerAdapter('http', new HttpAdapter(), { default: true });\n *\n * store.defineMapper('post');\n *\n * // Since this example uses the http adapter, we'll get something like:\n * //\n * // PUT /post/1234 {\"status\":\"published\"}\n * store.update('post', 1, { status: 'published' }).then((post) => {\n * // The post record has also been updated in the in-memory store\n * console.log(store.get('post', 1234));\n * });\n *\n * @fires SimpleStore#beforeUpdate\n * @fires SimpleStore#afterUpdate\n * @fires SimpleStore#add\n * @method SimpleStore#update\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {(string|number)} id Passed to {@link Mapper#update}.\n * @param {object} record Passed to {@link Mapper#update}.\n * @param {object} [opts] Passed to {@link Mapper#update}. See\n * {@link Mapper#update} for more configuration options.\n * @returns {Promise} Resolves with the result of the update.\n * @since 3.0.0\n */\n update (name, id, record, opts: any = {}) {\n return super.update(name, id, record, opts).then(result => this._end(name, result, opts))\n }\n\n /**\n * Fired during {@link SimpleStore#updateAll}. See\n * {@link SimpleStore~beforeUpdateAllListener} for how to listen for this event.\n *\n * @event SimpleStore#beforeUpdateAll\n * @see SimpleStore~beforeUpdateAllListener\n * @see SimpleStore#updateAll\n */\n /**\n * Callback signature for the {@link SimpleStore#event:beforeUpdateAll} event.\n *\n * @example\n * function onBeforeUpdateAll (mapperName, props, query, opts) {\n * // do something\n * }\n * store.on('beforeUpdateAll', onBeforeUpdateAll);\n *\n * @callback SimpleStore~beforeUpdateAllListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeUpdateAll}.\n * @param {object} props The `props` argument received by {@link Mapper#beforeUpdateAll}.\n * @param {object} query The `query` argument received by {@link Mapper#beforeUpdateAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdateAll}.\n * @see SimpleStore#event:beforeUpdateAll\n * @see SimpleStore#updateAll\n * @since 3.0.0\n */\n /**\n * Fired during {@link SimpleStore#updateAll}. See\n * {@link SimpleStore~afterUpdateAllListener} for how to listen for this event.\n *\n * @event SimpleStore#afterUpdateAll\n * @see SimpleStore~afterUpdateAllListener\n * @see SimpleStore#updateAll\n */\n\n /**\n * Callback signature for the {@link SimpleStore#event:afterUpdateAll} event.\n *\n * @example\n * function onAfterUpdateAll (mapperName, props, query, opts, result) {\n * // do something\n * }\n * store.on('afterUpdateAll', onAfterUpdateAll);\n *\n * @callback SimpleStore~afterUpdateAllListener\n * @param {string} name The `name` argument received by {@link Mapper#afterUpdateAll}.\n * @param {object} props The `props` argument received by {@link Mapper#afterUpdateAll}.\n * @param {object} query The `query` argument received by {@link Mapper#afterUpdateAll}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdateAll}.\n * @param {object} result The `result` argument received by {@link Mapper#afterUpdateAll}.\n * @see SimpleStore#event:afterUpdateAll\n * @see SimpleStore#updateAll\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#updateAll}. Adds the updated {@link Record}s to\n * the store.\n *\n * @example\n * import { SimpleStore } from 'js-data';\n * import { HttpAdapter } from 'js-data-http';\n *\n * const store = new SimpleStore();\n * store.registerAdapter('http', new HttpAdapter(), { default: true });\n *\n * store.defineMapper('post');\n *\n * // Since this example uses the http adapter, we'll get something like:\n * //\n * // PUT /post?author_id=1234 {\"status\":\"published\"}\n * store.updateAll('post', { author_id: 1234 }, { status: 'published' }).then((posts) => {\n * // The post records have also been updated in the in-memory store\n * console.log(store.filter('posts', { author_id: 1234 }));\n * });\n *\n * @fires SimpleStore#beforeUpdateAll\n * @fires SimpleStore#afterUpdateAll\n * @fires SimpleStore#add\n * @method SimpleStore#updateAll\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {object} props Passed to {@link Mapper#updateAll}.\n * @param {object} [query] Passed to {@link Mapper#updateAll}.\n * @param {object} [opts] Passed to {@link Mapper#updateAll}. See\n * {@link Mapper#updateAll} for more configuration options.\n * @returns {Promise} Resolves with the result of the update.\n * @since 3.0.0\n */\n updateAll (name, props, query, opts: any = {}) {\n return super.updateAll(name, props, query, opts).then(result => this._end(name, result, opts))\n }\n\n /**\n * Fired during {@link SimpleStore#updateMany}. See\n * {@link SimpleStore~beforeUpdateManyListener} for how to listen for this event.\n *\n * @event SimpleStore#beforeUpdateMany\n * @see SimpleStore~beforeUpdateManyListener\n * @see SimpleStore#updateMany\n */\n /**\n * Callback signature for the {@link SimpleStore#event:beforeUpdateMany} event.\n *\n * @example\n * function onBeforeUpdateMany (mapperName, records, opts) {\n * // do something\n * }\n * store.on('beforeUpdateMany', onBeforeUpdateMany);\n *\n * @callback SimpleStore~beforeUpdateManyListener\n * @param {string} name The `name` argument received by {@link Mapper#beforeUpdateMany}.\n * @param {object} records The `records` argument received by {@link Mapper#beforeUpdateMany}.\n * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdateMany}.\n * @see SimpleStore#event:beforeUpdateMany\n * @see SimpleStore#updateMany\n * @since 3.0.0\n */\n /**\n * Fired during {@link SimpleStore#updateMany}. See\n * {@link SimpleStore~afterUpdateManyListener} for how to listen for this event.\n *\n * @event SimpleStore#afterUpdateMany\n * @see SimpleStore~afterUpdateManyListener\n * @see SimpleStore#updateMany\n */\n\n /**\n * Callback signature for the {@link SimpleStore#event:afterUpdateMany} event.\n *\n * @example\n * function onAfterUpdateMany (mapperName, records, opts, result) {\n * // do something\n * }\n * store.on('afterUpdateMany', onAfterUpdateMany);\n *\n * @callback SimpleStore~afterUpdateManyListener\n * @param {string} name The `name` argument received by {@link Mapper#afterUpdateMany}.\n * @param {object} records The `records` argument received by {@link Mapper#afterUpdateMany}.\n * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdateMany}.\n * @param {object} result The `result` argument received by {@link Mapper#afterUpdateMany}.\n * @see SimpleStore#event:afterUpdateMany\n * @see SimpleStore#updateMany\n * @since 3.0.0\n */\n /**\n * Wrapper for {@link Mapper#updateMany}. Adds the updated {@link Record}s to\n * the store.\n *\n * @example\n * import { SimpleStore } from 'js-data';\n * import { HttpAdapter } from 'js-data-http';\n *\n * const store = new SimpleStore();\n * store.registerAdapter('http', new HttpAdapter(), { default: true });\n *\n * store.defineMapper('post');\n *\n * // Since this example uses the http adapter, we'll get something like:\n * //\n * // PUT /post [{\"id\":3,status\":\"published\"},{\"id\":4,status\":\"published\"}]\n * store.updateMany('post', [\n * { id: 3, status: 'published' },\n * { id: 4, status: 'published' }\n * ]).then((posts) => {\n * // The post records have also been updated in the in-memory store\n * console.log(store.getAll('post', 3, 4));\n * });\n *\n * @fires SimpleStore#beforeUpdateMany\n * @fires SimpleStore#afterUpdateMany\n * @fires SimpleStore#add\n * @method SimpleStore#updateMany\n * @param {string} name Name of the {@link Mapper} to target.\n * @param {(Object[]|Record[])} records Passed to {@link Mapper#updateMany}.\n * @param {object} [opts] Passed to {@link Mapper#updateMany}. See\n * {@link Mapper#updateMany} for more configuration options.\n * @returns {Promise} Resolves with the result of the update.\n * @since 3.0.0\n */\n updateMany (name, records, opts: any = {}) {\n return super.updateMany(name, records, opts).then(result => this._end(name, result, opts))\n }\n\n /**\n * Wrapper for {@link Collection#add}.\n *\n * @example SimpleStore#add\n * const JSData = require('js-data');\n * const { SimpleStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new SimpleStore();\n * store.defineMapper('book');\n *\n * // Add one book to the in-memory store:\n * store.add('book', { id: 1, title: 'Respect your Data' });\n * // Add multiple books to the in-memory store:\n * store.add('book', [\n * { id: 2, title: 'Easy data recipes' },\n * { id: 3, title: 'Active Record 101' }\n * ]);\n *\n * @fires SimpleStore#add\n * @method SimpleStore#add\n * @param {(string|number)} name Name of the {@link Mapper} to target.\n * @param {(Object|Object[]|Record|Record[])} records See {@link Collection#add}.\n * @param {object} [opts] Configuration options. See {@link Collection#add}.\n * @returns {(Object|Object[]|Record|Record[])} See {@link Collection#add}.\n * @see Collection#add\n * @see Collection#add\n * @since 3.0.0\n */\n add (name, records, opts?) {\n return this.getCollection(name).add(records, opts)\n }\n\n /**\n * Wrapper for {@link Collection#between}.\n *\n * @example\n * // Get all users ages 18 to 30\n * const users = store.between('user', 18, 30, { index: 'age' });\n *\n * @example\n * // Same as above\n * const users = store.between('user', [18], [30], { index: 'age' });\n *\n * @method SimpleStore#between\n * @param {(string|number)} name Name of the {@link Mapper} to target.\n * @param {array} leftKeys See {@link Collection#between}.\n * @param {array} rightKeys See {@link Collection#between}.\n * @param {object} [opts] Configuration options. See {@link Collection#between}.\n * @returns {Object[]|Record[]} See {@link Collection#between}.\n * @see Collection#between\n * @see Collection#between\n * @since 3.0.0\n */\n between (name, leftKeys, rightKeys, opts) {\n return this.getCollection(name).between(leftKeys, rightKeys, opts)\n }\n\n /**\n * Wrapper for {@link Collection#createIndex}.\n *\n * @example\n * // Index users by age\n * store.createIndex('user', 'age');\n *\n * @example\n * // Index users by status and role\n * store.createIndex('user', 'statusAndRole', ['status', 'role']);\n *\n * @method SimpleStore#createIndex\n * @param {(string|number)} name Name of the {@link Mapper} to target.\n * @param {string} indexName See {@link Collection#createIndex}.\n * @param {string[]} [fieldList] See {@link Collection#createIndex}.\n * @param {object} [opts] Configuration options. See {@link Collection#between}.\n * @see Collection#createIndex\n * @see Collection#createIndex\n * @since 3.0.0\n */\n createIndex (name: string | number, indexName: string, fieldList?: string[], opts?) {\n return this.getCollection(name).createIndex(indexName, fieldList, opts)\n }\n\n /**\n * Wrapper for {@link Collection#filter}.\n *\n * @example SimpleStore#filter\n * const JSData = require('js-data');\n * const { SimpleStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new SimpleStore();\n * store.defineMapper('post');\n * store.add('post', [\n * { id: 1, status: 'draft', created_at_timestamp: new Date().getTime() }\n * ]);\n *\n * // Get the draft posts created less than three months ago\n * let posts = store.filter('post', {\n * where: {\n * status: {\n * '==': 'draft'\n * },\n * created_at_timestamp: {\n * '>=': (new Date().getTime() - (1000 \\* 60 \\* 60 \\* 24 \\* 30 \\* 3)) // 3 months ago\n * }\n * }\n * });\n * console.log(posts);\n *\n * // Use a custom filter function\n * posts = store.filter('post', function (post) { return post.id % 2 === 0 });\n *\n * @method SimpleStore#filter\n * @param {(string|number)} name Name of the {@link Mapper} to target.\n * @param {(Object|Function)} [queryOrFn={}] See {@link Collection#filter}.\n * @param {object} [thisArg] See {@link Collection#filter}.\n * @returns {Array} See {@link Collection#filter}.\n * @see Collection#filter\n * @see Collection#filter\n * @since 3.0.0\n */\n filter (name, queryOrFn?, thisArg?) {\n return this.getCollection(name).filter(queryOrFn, thisArg)\n }\n\n /**\n * Wrapper for {@link Collection#get}.\n *\n * @example SimpleStore#get\n * const JSData = require('js-data');\n * const { SimpleStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * const store = new SimpleStore();\n * store.defineMapper('post');\n * store.add('post', [\n * { id: 1, status: 'draft', created_at_timestamp: new Date().getTime() }\n * ]);\n *\n * console.log(store.get('post', 1)); // {...}\n * console.log(store.get('post', 2)); // undefined\n *\n * @method SimpleStore#get\n * @param {(string|number)} name Name of the {@link Mapper} to target.\n * @param {(string|number)} id See {@link Collection#get}.\n * @returns {(Object|Record)} See {@link Collection#get}.\n * @see Collection#get\n * @see Collection#get\n * @since 3.0.0\n */\n get (name, id) {\n return this.getCollection(name).get(id)\n }\n\n /**\n * Wrapper for {@link Collection#getAll}.\n *\n * @example\n * // Get the posts where \"status\" is \"draft\" or \"inReview\"\n * const posts = store.getAll('post', 'draft', 'inReview', { index: 'status' });\n *\n * @example\n * // Same as above\n * const posts = store.getAll('post', ['draft'], ['inReview'], { index: 'status' });\n *\n * @method SimpleStore#getAll\n * @param {(string|number)} name Name of the {@link Mapper} to target.\n * @param {...Array} [keyList] See {@link Collection#getAll}.\n * @param {object} [opts] See {@link Collection#getAll}.\n * @returns {Array} See {@link Collection#getAll}.\n * @see Collection#getAll\n * @see Collection#getAll\n * @since 3.0.0\n */\n getAll (name, ...args) {\n return this.getCollection(name).getAll(...args)\n }\n\n /**\n * Wrapper for {@link Collection#prune}.\n *\n * @method SimpleStore#prune\n * @param name\n * @param {object} [opts] See {@link Collection#prune}.\n * @returns {Array} See {@link Collection#prune}.\n * @see Collection#prune\n * @see Collection#prune\n * @since 3.0.0\n */\n prune (name: string, opts?) {\n return this.getCollection(name).prune(opts)\n }\n\n /**\n * Wrapper for {@link Collection#query}.\n *\n * @example\n * // Grab page 2 of users between ages 18 and 30\n * store.query('user')\n * .between(18, 30, { index: 'age' }) // between ages 18 and 30\n * .skip(10) // second page\n * .limit(10) // page size\n * .run();\n *\n * @method SimpleStore#query\n * @param {(string|number)} name Name of the {@link Mapper} to target.\n * @returns {Query} See {@link Collection#query}.\n * @see Collection#query\n * @see Collection#query\n * @since 3.0.0\n */\n query (name) {\n return this.getCollection(name).query()\n }\n\n /**\n * Wrapper for {@link Collection#toJSON}.\n *\n * @example\n * store.defineMapper('post', {\n * schema: {\n * properties: {\n * id: { type: 'number' },\n * title: { type: 'string' }\n * }\n * }\n * });\n * store.add('post', [\n * { id: 1, status: 'published', title: 'Respect your Data' },\n * { id: 2, status: 'draft', title: 'Connecting to a data source' }\n * ]);\n * console.log(store.toJSON('post'));\n * const draftsJSON = store.query('post')\n * .filter({ status: 'draft' })\n * .mapCall('toJSON')\n * .run();\n *\n * @method SimpleStore#toJSON\n * @param {(string|number)} name Name of the {@link Mapper} to target.\n * @param {object} [opts] See {@link Collection#toJSON}.\n * @returns {Array} See {@link Collection#toJSON}.\n * @see Collection#toJSON\n * @see Collection#toJSON\n * @since 3.0.0\n */\n toJSON (name, opts) {\n return this.getCollection(name).toJSON(opts)\n }\n\n /**\n * Wrapper for {@link Collection#unsaved}.\n *\n * @method SimpleStore#unsaved\n * @returns {Array} See {@link Collection#unsaved}.\n * @see Collection#unsaved\n * @see Collection#unsaved\n * @since 3.0.0\n */\n unsaved (name, opts?) {\n return this.getCollection(name).unsaved(opts)\n }\n}\n\n/**\n * Fired when a record changes. Only works for records that have tracked fields.\n * See {@link SimpleStore~changeListener} on how to listen for this event.\n *\n * @event SimpleStore#change\n * @see SimpleStore~changeListener\n */\n\n/**\n * Callback signature for the {@link SimpleStore#event:change} event.\n *\n * @example\n * function onChange (mapperName, record, changes) {\n * // do something\n * }\n * store.on('change', onChange);\n *\n * @callback SimpleStore~changeListener\n * @param {string} name The name of the associated {@link Mapper}.\n * @param {Record} record The Record that changed.\n * @param {object} changes The changes.\n * @see SimpleStore#event:change\n * @since 3.0.0\n */\n\n/**\n * Fired when one or more records are added to the in-memory store. See\n * {@link SimpleStore~addListener} on how to listen for this event.\n *\n * @event SimpleStore#add\n * @see SimpleStore~addListener\n * @see SimpleStore#event:add\n * @see SimpleStore#add\n * @see SimpleStore#create\n * @see SimpleStore#createMany\n * @see SimpleStore#find\n * @see SimpleStore#findAll\n * @see SimpleStore#update\n * @see SimpleStore#updateAll\n * @see SimpleStore#updateMany\n */\n\n/**\n * Callback signature for the {@link SimpleStore#event:add} event.\n *\n * @example\n * function onAdd (mapperName, recordOrRecords) {\n * // do something\n * }\n * store.on('add', onAdd);\n *\n * @callback SimpleStore~addListener\n * @param {string} name The name of the associated {@link Mapper}.\n * @param {Record|Record[]} The Record or Records that were added.\n * @see SimpleStore#event:add\n * @see SimpleStore#add\n * @see SimpleStore#create\n * @see SimpleStore#createMany\n * @see SimpleStore#find\n * @see SimpleStore#findAll\n * @see SimpleStore#update\n * @see SimpleStore#updateAll\n * @see SimpleStore#updateMany\n * @since 3.0.0\n */\n\n/**\n * Fired when one or more records are removed from the in-memory store. See\n * {@link SimpleStore~removeListener} for how to listen for this event.\n *\n * @event SimpleStore#remove\n * @see SimpleStore~removeListener\n * @see SimpleStore#event:remove\n * @see SimpleStore#clear\n * @see SimpleStore#destroy\n * @see SimpleStore#destroyAll\n * @see SimpleStore#remove\n * @see SimpleStore#removeAll\n */\n\n/**\n * Callback signature for the {@link SimpleStore#event:remove} event.\n *\n * @example\n * function onRemove (mapperName, recordsOrRecords) {\n * // do something\n * }\n * store.on('remove', onRemove);\n *\n * @callback SimpleStore~removeListener\n * @param {string} name The name of the associated {@link Mapper}.\n * @param {Record|Record[]} Record or Records that were removed.\n * @see SimpleStore#event:remove\n * @see SimpleStore#clear\n * @see SimpleStore#destroy\n * @see SimpleStore#destroyAll\n * @see SimpleStore#remove\n * @see SimpleStore#removeAll\n * @since 3.0.0\n */\n\n/**\n * Create a subclass of this SimpleStore:\n * @example SimpleStore.extend\n * const JSData = require('js-data');\n * const { SimpleStore } = JSData;\n * console.log('Using JSData v' + JSData.version.full);\n *\n * // Extend the class using ES2015 class syntax.\n * class CustomSimpleStoreClass extends SimpleStore {\n * foo () { return 'bar'; }\n * static beep () { return 'boop'; }\n * }\n * const customSimpleStore = new CustomSimpleStoreClass();\n * console.log(customSimpleStore.foo());\n * console.log(CustomSimpleStoreClass.beep());\n *\n * // Extend the class using alternate method.\n * const OtherSimpleStoreClass = SimpleStore.extend({\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * })\n * const otherSimpleStore = new OtherSimpleStoreClass();\n * console.log(otherSimpleStore.foo());\n * console.log(OtherSimpleStoreClass.beep());\n *\n * // Extend the class, providing a custom constructor.\n * function AnotherSimpleStoreClass () {\n * SimpleStore.call(this)\n * this.created_at = new Date().getTime()\n * }\n * SimpleStore.extend({\n * constructor: AnotherSimpleStoreClass,\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * })\n * const anotherSimpleStore = new AnotherSimpleStoreClass();\n * console.log(anotherSimpleStore.created_at);\n * console.log(anotherSimpleStore.foo());\n * console.log(AnotherSimpleStoreClass.beep());\n *\n * @method SimpleStore.extend\n * @param {object} [props={}] Properties to add to the prototype of the\n * subclass.\n * @param {object} [props.constructor] Provide a custom constructor function\n * to be used as the subclass itself.\n * @param {object} [classProps={}] Static properties to add to the subclass.\n * @returns {Constructor} Subclass of this SimpleStore class.\n * @since 3.0.0\n */\n","import utils from './utils'\nimport './decorators'\nimport Collection from './Collection'\n\nconst DOMAIN = 'LinkedCollection'\n\n/**\n * Extends {@link Collection}. Used by a {@link DataStore} to implement an\n * Identity Map.\n *\n * @example\n * import {LinkedCollection} from 'js-data';\n *\n * // Extend the class using ES2015 class syntax.\n * class CustomLinkedCollectionClass extends LinkedCollection {\n * foo () { return 'bar'; }\n * static beep () { return 'boop'; }\n * }\n * const customLinkedCollection = new CustomLinkedCollectionClass();\n * console.log(customLinkedCollection.foo());\n * console.log(CustomLinkedCollectionClass.beep());\n *\n * @class LinkedCollection\n * @extends Collection\n * @param {array} [records] Initial set of records to insert into the\n * collection. See {@link Collection}.\n * @param {object} [opts] Configuration options. See {@link Collection}.\n * @returns {Mapper}\n */\nexport default class LinkedCollection extends Collection {\n datastore: any;\n\n constructor (records, opts) {\n super(records, opts)\n\n // Make sure this collection has a reference to a datastore\n if (!this.datastore) {\n throw utils.err(`new ${DOMAIN}`, 'opts.datastore')(400, 'DataStore', this.datastore)\n }\n }\n\n _addMeta (record, timestamp) {\n // Track when this record was added\n this._added[this.recordId(record)] = timestamp\n\n if (utils.isFunction(record._set)) {\n record._set('$', timestamp)\n }\n }\n\n _clearMeta (record) {\n delete this._added[this.recordId(record)]\n if (utils.isFunction(record._set)) {\n record._set('$') // unset\n }\n }\n\n _onRecordEvent (...args) {\n Collection.prototype._onRecordEvent.apply(this, args)\n const event = args[0]\n // This is a very brute force method\n // Lots of room for optimization\n if (utils.isString(event) && event.indexOf('change') === 0) {\n this.updateIndexes(args[1])\n }\n }\n\n add (records, opts) {\n const mapper = this.mapper\n const timestamp = new Date().getTime()\n const singular = utils.isObject(records) && !utils.isArray(records)\n\n if (singular) {\n records = [records]\n }\n records = super.add(records, opts)\n\n if (mapper.relationList.length && records.length) {\n // Check the currently visited record for relations that need to be\n // inserted into their respective collections.\n mapper.relationList.forEach(def => {\n def.addLinkedRecords(records)\n })\n }\n\n records.forEach(record => this._addMeta(record, timestamp))\n\n return singular ? records[0] : records\n }\n\n remove (idOrRecord, opts) {\n const mapper = this.mapper\n const record = super.remove(idOrRecord, opts)\n if (record) {\n this._clearMeta(record)\n }\n\n if (mapper.relationList.length && record) {\n mapper.relationList.forEach(def => {\n def.removeLinkedRecords(mapper, [record])\n })\n }\n\n return record\n }\n\n removeAll (query, opts) {\n const mapper = this.mapper\n const records = super.removeAll(query, opts)\n records.forEach(this._clearMeta, this)\n\n if (mapper.relationList.length && records.length) {\n mapper.relationList.forEach(def => {\n def.removeLinkedRecords(mapper, records)\n })\n }\n\n return records\n }\n}\n\n/**\n * Create a subclass of this LinkedCollection:\n *\n * // Extend the class using alternate method.\n * const OtherLinkedCollectionClass = LinkedCollection.extend({\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * });\n * const otherLinkedCollection = new OtherLinkedCollectionClass();\n * console.log(otherLinkedCollection.foo());\n * console.log(OtherLinkedCollectionClass.beep());\n *\n * // Extend the class, providing a custom constructor.\n * function AnotherLinkedCollectionClass () {\n * LinkedCollection.call(this);\n * this.created_at = new Date().getTime();\n * }\n * LinkedCollection.extend({\n * constructor: AnotherLinkedCollectionClass,\n * foo () { return 'bar'; }\n * }, {\n * beep () { return 'boop'; }\n * });\n * const anotherLinkedCollection = new AnotherLinkedCollectionClass();\n * console.log(anotherLinkedCollection.created_at);\n * console.log(anotherLinkedCollection.foo());\n * console.log(AnotherLinkedCollectionClass.beep());\n *\n * @method LinkedCollection.extend\n * @param {object} [props={}] Properties to add to the prototype of the\n * subclass.\n * @param {object} [props.constructor] Provide a custom constructor function\n * to be used as the subclass itself.\n * @param {object} [classProps={}] Static properties to add to the subclass.\n * @returns {Constructor} Subclass of this LinkedCollection class.\n * @since 3.0.0\n */\n","import utils, { safeSetLink, safeSetProp } from './utils'\n\nimport { belongsToType, hasManyType, hasOneType } from './decorators'\nimport SimpleStore, { SimpleStoreOpts } from './SimpleStore'\nimport LinkedCollection from './LinkedCollection'\nimport { MapperOpts } from './Mapper'\n\nexport interface DataStoreOpts extends SimpleStoreOpts {\n [customAttr: string]: any\n\n linkRelations?: boolean\n unlinkOnDestroy?: boolean\n collectionClass /*: typeof Collection */?\n mapperClass?\n scopes?: any\n}\n\nconst DATASTORE_DEFAULTS: DataStoreOpts = {\n /**\n * Whether in-memory relations should be unlinked from records after they are\n * destroyed.\n *\n * @default true\n * @name DataStore#unlinkOnDestroy\n * @since 3.0.0\n * @type {boolean}\n */\n unlinkOnDestroy: true,\n\n collectionClass: LinkedCollection\n}\n\n/**\n * The `DataStore` class is an extension of {@link SimpleStore}. Not only does\n * `DataStore` manage mappers and store data in collections, it uses the\n * {@link LinkedCollection} class to link related records together in memory.\n *\n * ```javascript\n * import { DataStore } from 'js-data';\n * ```\n *\n * @example\n * import { DataStore } from 'js-data';\n * import HttpAdapter from 'js-data-http';\n * const store = new DataStore();\n *\n * // DataStore#defineMapper returns a direct reference to the newly created\n * // Mapper.\n * const UserMapper = store.defineMapper('user');\n *\n * // DataStore#as returns the store scoped to a particular Mapper.\n * const UserStore = store.as('user');\n *\n * // Call \"find\" on \"UserMapper\" (Stateless ORM)\n * UserMapper.find(1).then((user) => {\n * // retrieved a \"user\" record via the http adapter, but that's it\n *\n * // Call \"find\" on \"store\" targeting \"user\" (Stateful DataStore)\n * return store.find('user', 1); // same as \"UserStore.find(1)\"\n * }).then((user) => {\n * // not only was a \"user\" record retrieved, but it was added to the\n * // store's \"user\" collection\n * const cachedUser = store.getCollection('user').get(1);\n * console.log(user === cachedUser); // true\n * });\n *\n * @class DataStore\n * @extends SimpleStore\n * @param {object} [opts] Configuration options. See {@link SimpleStore}.\n * @param {boolean} [opts.collectionClass={@link LinkedCollection}] See {@link DataStore#collectionClass}.\n * @param {boolean} [opts.debug=false] See {@link Component#debug}.\n * @param {boolean} [opts.unlinkOnDestroy=true] See {@link DataStore#unlinkOnDestroy}.\n * @param {boolean|Function} [opts.usePendingFind=true] See {@link DataStore#usePendingFind}.\n * @param {boolean|Function} [opts.usePendingFindAll=true] See {@link DataStore#usePendingFindAll}.\n * @returns {DataStore}\n * @see SimpleStore\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/components-of-jsdata#datastore\",\"Components of JSData: DataStore\"]\n * @tutorial [\"http://www.js-data.io/v3.0/docs/working-with-the-datastore\",\"Working with the DataStore\"]\n * @tutorial [\"http://www.js-data.io/v3.0/docs/jsdata-and-the-browser\",\"Notes on using JSData in the Browser\"]\n */\nexport default class DataStore extends SimpleStore {\n unlinkOnDestroy: any;\n\n constructor (opts: DataStoreOpts = {}) {\n // Fill in any missing options with the defaults\n super({ ...DATASTORE_DEFAULTS, ...opts })\n }\n\n /**\n * Creates a new [Mapper] with [name] from the [opts]\n * @param {string} name\n * @param {object} opts\n * @returns {*}\n */\n defineMapper (name, opts?: MapperOpts) {\n // Complexity of this method is beyond simply using => functions to bind context\n const self = this\n const mapper = super.defineMapper(name, opts)\n const idAttribute = mapper.idAttribute\n const collection = this.getCollection(name)\n\n mapper.relationList.forEach(def => {\n const relation = def.relation\n const localField = def.localField\n const path = `links.${localField}`\n const foreignKey = def.foreignKey\n const type = def.type\n const updateOpts = { index: foreignKey }\n let descriptor\n\n const getter = function () {\n return this._get(path)\n }\n\n if (type === belongsToType) {\n if (!collection.indexes[foreignKey]) {\n collection.createIndex(foreignKey)\n }\n\n descriptor = {\n get: getter,\n // e.g. profile.user = someUser\n // or comment.post = somePost\n set (record) {\n // e.g. const otherUser = profile.user\n const currentParent = this._get(path)\n // e.g. profile.user === someUser\n if (record === currentParent) {\n return currentParent\n }\n const id = utils.get(this, idAttribute)\n const inverseDef = def.getInverse(mapper)\n\n // e.g. profile.user !== someUser\n // or comment.post !== somePost\n if (currentParent && inverseDef) {\n this.removeInverseRelation(currentParent, id, inverseDef, idAttribute)\n }\n if (record) {\n // e.g. profile.user = someUser\n const relatedIdAttribute = def.getRelation().idAttribute\n const relatedId = utils.get(record, relatedIdAttribute)\n\n // Prefer store record\n if (relatedId !== undefined && this._get('$')) {\n record = self.get(relation, relatedId) || record\n }\n\n // Set locals\n // e.g. profile.user = someUser\n // or comment.post = somePost\n safeSetLink(this, localField, record)\n safeSetProp(this, foreignKey, relatedId)\n collection.updateIndex(this, updateOpts)\n\n if (inverseDef) {\n this.setupInverseRelation(record, id, inverseDef, idAttribute)\n }\n } else {\n // Unset in-memory link only\n // e.g. profile.user = undefined\n // or comment.post = undefined\n safeSetLink(this, localField, undefined)\n }\n return record\n }\n }\n\n let foreignKeyDescriptor = Object.getOwnPropertyDescriptor(mapper.recordClass.prototype, foreignKey)\n if (!foreignKeyDescriptor) {\n foreignKeyDescriptor = {\n enumerable: true\n }\n }\n const originalGet = foreignKeyDescriptor.get\n foreignKeyDescriptor.get = function () {\n if (originalGet) {\n return originalGet.call(this)\n }\n return this._get(`props.${foreignKey}`)\n }\n const originalSet = foreignKeyDescriptor.set\n foreignKeyDescriptor.set = function (value) {\n if (originalSet) {\n originalSet.call(this, value)\n }\n const currentParent = utils.get(this, localField)\n const id = utils.get(this, idAttribute)\n const inverseDef = def.getInverse(mapper)\n const currentParentId = currentParent ? utils.get(currentParent, def.getRelation().idAttribute) : undefined\n\n if (inverseDef && currentParent && currentParentId !== undefined && currentParentId !== value) {\n if (inverseDef.type === hasOneType) {\n safeSetLink(currentParent, inverseDef.localField, undefined)\n } else if (inverseDef.type === hasManyType) {\n const children = utils.get(currentParent, inverseDef.localField)\n if (id === undefined) {\n utils.remove(children, child => child === this)\n } else {\n utils.remove(children, child => child === this || id === utils.get(child, idAttribute))\n }\n }\n }\n\n safeSetProp(this, foreignKey, value)\n collection.updateIndex(this, updateOpts)\n\n if (value === undefined || value === null) {\n if (currentParentId !== undefined) {\n // Unset locals\n utils.set(this, localField, undefined)\n }\n } else if (this._get('$')) {\n const storeRecord = self.get(relation, value)\n if (storeRecord) {\n utils.set(this, localField, storeRecord)\n }\n }\n }\n Object.defineProperty(mapper.recordClass.prototype, foreignKey, foreignKeyDescriptor)\n } else if (type === hasManyType) {\n const localKeys = def.localKeys\n const foreignKeys = def.foreignKeys\n\n // TODO: Handle case when belongsTo relation isn't ever defined\n if (self._collections[relation] && foreignKey && !self.getCollection(relation).indexes[foreignKey]) {\n self.getCollection(relation).createIndex(foreignKey)\n }\n\n descriptor = {\n get () {\n const current = getter.call(this)\n if (!current) {\n this._set(path, [])\n }\n return getter.call(this)\n },\n // e.g. post.comments = someComments\n // or user.groups = someGroups\n // or group.users = someUsers\n set (records) {\n if (records && !utils.isArray(records)) {\n records = [records]\n }\n const id = utils.get(this, idAttribute)\n const relatedIdAttribute = def.getRelation().idAttribute\n const inverseDef = def.getInverse(mapper)\n const inverseLocalField = inverseDef.localField\n const current = this._get(path) || []\n const toLink = []\n const toLinkIds = {}\n\n if (records) {\n records.forEach(record => {\n // e.g. comment.id\n const relatedId = utils.get(record, relatedIdAttribute)\n const currentParent = utils.get(record, inverseLocalField)\n if (currentParent && currentParent !== this) {\n const currentChildrenOfParent = utils.get(currentParent, localField)\n // e.g. somePost.comments.remove(comment)\n if (relatedId === undefined) {\n utils.remove(currentChildrenOfParent, child => child === record)\n } else {\n utils.remove(\n currentChildrenOfParent,\n child => child === record || relatedId === utils.get(child, relatedIdAttribute)\n )\n }\n }\n if (relatedId !== undefined) {\n if (this._get('$')) {\n // Prefer store record\n record = self.get(relation, relatedId) || record\n }\n // e.g. toLinkIds[comment.id] = comment\n toLinkIds[relatedId] = record\n }\n toLink.push(record)\n })\n }\n\n // e.g. post.comments = someComments\n if (foreignKey) {\n current.forEach(record => {\n // e.g. comment.id\n const relatedId = utils.get(record, relatedIdAttribute)\n if (\n (relatedId === undefined && toLink.indexOf(record) === -1) ||\n (relatedId !== undefined && !(relatedId in toLinkIds))\n ) {\n // Update (unset) inverse relation\n if (records) {\n // e.g. comment.post_id = undefined\n safeSetProp(record, foreignKey, undefined)\n // e.g. CommentCollection.updateIndex(comment, { index: 'post_id' })\n self.getCollection(relation).updateIndex(record, updateOpts)\n }\n // e.g. comment.post = undefined\n safeSetLink(record, inverseLocalField, undefined)\n }\n })\n toLink.forEach(record => {\n // Update (set) inverse relation\n // e.g. comment.post_id = post.id\n safeSetProp(record, foreignKey, id)\n // e.g. CommentCollection.updateIndex(comment, { index: 'post_id' })\n self.getCollection(relation).updateIndex(record, updateOpts)\n // e.g. comment.post = post\n safeSetLink(record, inverseLocalField, this)\n })\n } else if (localKeys) {\n // Update locals\n // e.g. group.users = someUsers\n // Update (set) inverse relation\n const ids = toLink.map(child => utils.get(child, relatedIdAttribute)).filter(id => id !== undefined)\n // e.g. group.user_ids = [1,2,3,...]\n utils.set(this, localKeys, ids)\n // Update (unset) inverse relation\n if (inverseDef.foreignKeys) {\n current.forEach(child => {\n const relatedId = utils.get(child, relatedIdAttribute)\n if (\n (relatedId === undefined && toLink.indexOf(child) === -1) ||\n (relatedId !== undefined && !(relatedId in toLinkIds))\n ) {\n // Update inverse relation\n // safeSetLink(child, inverseLocalField, undefined)\n const parents = utils.get(child, inverseLocalField) || []\n // e.g. someUser.groups.remove(group)\n if (id === undefined) {\n utils.remove(parents, parent => parent === this)\n } else {\n utils.remove(parents, parent => parent === this || id === utils.get(parent, idAttribute))\n }\n }\n })\n toLink.forEach(child => {\n // Update (set) inverse relation\n const parents = utils.get(child, inverseLocalField)\n // e.g. someUser.groups.push(group)\n if (id === undefined) {\n utils.noDupeAdd(parents, this, parent => parent === this)\n } else {\n utils.noDupeAdd(parents, this, parent => parent === this || id === utils.get(parent, idAttribute))\n }\n })\n }\n } else if (foreignKeys) {\n // e.g. user.groups = someGroups\n // Update (unset) inverse relation\n current.forEach(parent => {\n const ids = utils.get(parent, foreignKeys) || []\n // e.g. someGroup.user_ids.remove(user.id)\n utils.remove(ids, _key => id === _key)\n const children = utils.get(parent, inverseLocalField)\n // e.g. someGroup.users.remove(user)\n if (id === undefined) {\n utils.remove(children, child => child === this)\n } else {\n utils.remove(children, child => child === this || id === utils.get(child, idAttribute))\n }\n })\n // Update (set) inverse relation\n toLink.forEach(parent => {\n const ids = utils.get(parent, foreignKeys) || []\n utils.noDupeAdd(ids, id, _key => id === _key)\n const children = utils.get(parent, inverseLocalField)\n if (id === undefined) {\n utils.noDupeAdd(children, this, child => child === this)\n } else {\n utils.noDupeAdd(children, this, child => child === this || id === utils.get(child, idAttribute))\n }\n })\n }\n\n this._set(path, toLink)\n return toLink\n }\n }\n } else if (type === hasOneType) {\n // TODO: Handle case when belongsTo relation isn't ever defined\n if (self._collections[relation] && foreignKey && !self.getCollection(relation).indexes[foreignKey]) {\n self.getCollection(relation).createIndex(foreignKey)\n }\n descriptor = {\n get: getter,\n // e.g. user.profile = someProfile\n set (record) {\n const current = this._get(path)\n if (record === current) {\n return current\n }\n const inverseLocalField = def.getInverse(mapper).localField\n // Update (unset) inverse relation\n if (current) {\n safeSetProp(current, foreignKey, undefined)\n self.getCollection(relation).updateIndex(current, updateOpts)\n safeSetLink(current, inverseLocalField, undefined)\n }\n if (record) {\n const relatedId = utils.get(record, def.getRelation().idAttribute)\n // Prefer store record\n if (relatedId !== undefined) {\n record = self.get(relation, relatedId) || record\n }\n\n // Set locals\n safeSetLink(this, localField, record)\n\n // Update (set) inverse relation\n safeSetProp(record, foreignKey, utils.get(this, idAttribute))\n self.getCollection(relation).updateIndex(record, updateOpts)\n safeSetLink(record, inverseLocalField, this)\n } else {\n // Unset locals\n safeSetLink(this, localField, undefined)\n }\n return record\n }\n }\n }\n\n if (descriptor) {\n descriptor.enumerable = def.enumerable === undefined ? false : def.enumerable\n if (def.get) {\n const origGet = descriptor.get\n descriptor.get = function () {\n return def.get(def, this, (...args) => origGet.apply(this, args))\n }\n }\n if (def.set) {\n const origSet = descriptor.set\n descriptor.set = function (related) {\n return def.set(def, this, related, value => origSet.call(this, value === undefined ? related : value))\n }\n }\n Object.defineProperty(mapper.recordClass.prototype, localField, descriptor)\n }\n })\n\n return mapper\n }\n\n destroy (name, id, opts: any = {}) {\n return super.destroy(name, id, opts).then(result => {\n let record\n if (opts.raw) {\n record = result.data\n } else {\n record = result\n }\n\n if (record && this.unlinkOnDestroy) {\n const _opts = utils.plainCopy(opts)\n _opts.withAll = true\n utils.forEachRelation(this.getMapper(name), _opts, def => {\n utils.set(record, def.localField, undefined)\n })\n }\n return result\n })\n }\n\n destroyAll (name, query, opts: any = {}) {\n return super.destroyAll(name, query, opts).then(result => {\n let records\n if (opts.raw) {\n records = result.data\n } else {\n records = result\n }\n\n if (records?.length && this.unlinkOnDestroy) {\n const _opts = utils.plainCopy(opts)\n _opts.withAll = true\n utils.forEachRelation(this.getMapper(name), _opts, def => {\n records.forEach(record => {\n utils.set(record, def.localField, undefined)\n })\n })\n }\n return result\n })\n }\n}\n","/**\n * Registered as `js-data` in NPM.\n *\n * @example Install from NPM\n * npm i --save js-data\n * @example Install from NPM\n * yarn add js-data\n * @example Load into your app via CommonJS\n * var JSData = require('js-data');\n * @example Load into your app via ES2015 Modules\n * import * as JSData from 'js-data';\n */\n\n/**\n * JSData's utility methods.\n *\n * @example\n * import { utils } from 'js-data';\n * console.log(utils.isString('foo')); // true\n *\n * @name module:js-data.utils\n * @property {Function} Promise See {@link utils.Promise}.\n * @see utils\n * @since 3.0.0\n * @type {Object}\n */\nimport utils from './utils'\n\n/**\n * JSData's {@link Collection} class.\n *\n * @example\n * import { Collection } from 'js-data';\n * const collection = new Collection();\n *\n * @name module:js-data.Collection\n * @see Collection\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/components-of-jsdata#collection\",\"Components of JSData: Collection\"]\n * @type {Constructor}\n */\nimport Collection from './Collection'\n\n/**\n * JSData's {@link Component} class. Most components in JSData extend this\n * class.\n *\n * @example\n * import { Component } from 'js-data';\n * // Make a custom component.\n * const MyComponent = Component.extend({\n * myMethod (someArg) { ... }\n * });\n *\n * @name module:js-data.Component\n * @see Component\n * @since 3.0.0\n * @type {Constructor}\n */\nimport Component from './Component'\n\n/**\n * JSData's {@link Container} class. Defines and manages {@link Mapper}s. Used\n * in Node.js and in the browser, though in the browser you may want to use\n * {@link DataStore} instead.\n *\n * @example\n * import { Container } from 'js-data';\n * const store = new Container();\n *\n * @name module:js-data.Container\n * @see Container\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/components-of-jsdata#container\",\"Components of JSData: Container\"]\n * @type {Constructor}\n */\nimport { Container } from './Container'\n\n/**\n * JSData's {@link DataStore} class. Primarily for use in the browser. In\n * Node.js you probably want to use {@link Container} instead.\n *\n * @example\n * import { DataStore } from 'js-data';\n * const store = new DataStore();\n *\n * @name module:js-data.DataStore\n * @see DataStore\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/components-of-jsdata#datastore\",\"Components of JSData: DataStore\"]\n * @type {Constructor}\n */\nimport DataStore from './DataStore'\n\n/**\n * JSData's {@link Index} class, based on [mindex]{@link https://github.com/internalfx/mindex}.\n *\n * @name module:js-data.Index\n * @see Index\n * @since 3.0.0\n * @type {Constructor}\n */\nimport Index from './mindex'\n\n/**\n * JSData's {@link LinkedCollection} class. Used by the {@link DataStore}\n * component. If you need to create a collection manually, you should probably\n * use the {@link Collection} class.\n *\n * @name module:js-data.LinkedCollection\n * @see DataStore\n * @see LinkedCollection\n * @since 3.0.0\n * @type {Constructor}\n */\nimport LinkedCollection from './LinkedCollection'\n\n/**\n * JSData's {@link Mapper} class. The core of the ORM.\n *\n * @example Recommended use\n * import { Container } from 'js-data';\n * const store = new Container();\n * store.defineMapper('user');\n *\n * @example Create Mapper manually\n * import { Mapper } from 'js-data';\n * const UserMapper = new Mapper({ name: 'user' });\n *\n * @name module:js-data.Mapper\n * @see Container\n * @see Mapper\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/modeling-your-data\",\"Modeling your data\"]\n * @tutorial [\"http://www.js-data.io/v3.0/docs/components-of-jsdata#mapper\",\"Components of JSData: Mapper\"]\n * @type {Constructor}\n */\nimport Mapper from './Mapper'\n\n/**\n * JSData's {@link Query} class. Used by the {@link Collection} component.\n *\n * @name module:js-data.Query\n * @see Query\n * @since 3.0.0\n * @type {Constructor}\n */\nimport Query from './Query'\n\n/**\n * JSData's {@link Record} class.\n *\n * @example\n * import { Container } from 'js-data';\n * const store = new Container();\n * store.defineMapper('user');\n * const user = store.createRecord('user');\n *\n * @name module:js-data.Record\n * @see Record\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/components-of-jsdata#record\",\"Components of JSData: Record\"]\n * @type {Constructor}\n */\nimport Record from './Record'\n\n/**\n * JSData's {@link Schema} class. Implements http://json-schema.org/draft-04.\n *\n * @example\n * import { Container, Schema } from 'js-data';\n * const userSchema = new Schema({\n * properties: {\n * id: { type: 'string' },\n * name: { type: 'string' }\n * }\n * });\n * const store = new Container();\n * store.defineMapper('user', {\n * schema: userSchema\n * });\n *\n * @name module:js-data.Schema\n * @see Schema\n * @see http://json-schema.org/\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/components-of-jsdata#schema\",\"Components of JSData: schema\"]\n * @tutorial [\"http://www.js-data.io/v3.0/docs/schemas\",\"JSData's Schema Syntax\"]\n * @type {Constructor}\n */\nimport Schema from './Schema'\n\n/**\n * JSData's {@link Settable} class.\n *\n * @example\n * import { Settable } from 'js-data';\n * const obj = new Settable();\n * obj.set('secret', 'value');\n * console.log(JSON.stringify(obj)); // {}\n *\n * @name module:js-data.Settable\n * @see Settable\n * @since 3.0.0\n * @type {Constructor}\n */\nimport Settable from './Settable'\n\n/**\n * JSData's {@link SimpleStore} class. Primarily for use in the browser. In\n * Node.js you probably want to use {@link Container} instead.\n *\n * @example\n * import { SimpleStore } from 'js-data';\n * const store = new SimpleStore();\n *\n * @name module:js-data.SimpleStore\n * @see SimpleStore\n * @since 3.0.0\n * @tutorial [\"http://www.js-data.io/v3.0/docs/components-of-jsdata#SimpleStore\",\"Components of JSData: SimpleStore\"]\n * @type {Constructor}\n */\nimport SimpleStore from './SimpleStore'\n\n/**\n * Describes the version of this `JSData` object.\n *\n * @example\n * console.log(JSData.version.full); // \"3.0.0-beta.1\"\n *\n * @name version\n * @memberof module:js-data\n * @property {string} full The full semver value.\n * @property {number} major The major version number.\n * @property {number} minor The minor version number.\n * @property {number} patch The patch version number.\n * @property {(string|boolean)} alpha The alpha version value, otherwise `false`\n * if the current version is not alpha.\n * @property {(string|boolean)} beta The beta version value, otherwise `false`\n * if the current version is not beta.\n * @since 2.0.0\n * @type {Object}\n */\nexport const version = '<%= version %>'\n\nexport * from './decorators'\n\nexport {\n Collection,\n Component,\n Container,\n DataStore,\n Index,\n LinkedCollection,\n Mapper,\n Query,\n Record,\n Schema,\n Settable,\n SimpleStore,\n utils\n}\n"],"names":["DOMAIN","INFINITY","MAX_INTEGER","BOOL_TAG","DATE_TAG","FUNC_TAG","NUMBER_TAG","OBJECT_TAG","REGEXP_TAG","STRING_TAG","objToString","Object","prototype","toString","PATH","ERRORS","toInteger","value","sign","remainder","toStr","call","isPlainObject","constructor","mkdirP","object","path","parts","split","forEach","key","utils","_","dest","src","forOwn","undefined","isFunction","indexOf","_forRelation","opts","def","fn","thisArg","relationName","relation","containedName","index","_getIndex","localField","withAll","optsCopy","fillIn","getRelation","slice","_activeWith","splice","i","length","substr","list","_relation","isObject","addHiddenPropsToTarget","target","props","map","keys","propName","descriptor","getOwnPropertyDescriptor","enumerable","defineProperties","areDifferent","newObject","oldObject","diff","diffObjects","diffCount","added","removed","changed","copy","from","to","stackFrom","stackTo","blacklist","plain","isArray","isDate","Date","getTime","isRegExp","RegExp","source","match","lastIndex","create","getPrototypeOf","err","push","result","hasOwnProperty","isBlacklisted","deepFillIn","existing","deepMixIn","equalsFn","ignore","deepEqual","newKeys","filter","oldKeys","oldValue","newValue","equal","a","b","domain","code","prefix","args","message","apply","Error","eventify","getter","setter","_events","emit","events","type","shift","listeners","f","c","all","unshift","off","func","on","findIndex","array","record","forEachRelation","mapper","relationList","obj","len","fromJson","json","isString","JSON","parse","get","prop","last","pop","getSuper","instance","isCtor","ctor","__super__","__proto__","intersection","array1","array2","Array","item","matches","test","isBoolean","isInteger","isNull","isNumber","isSorN","isUndefined","logify","dbg","log","level","debug","toUpperCase","name","console","noDupeAdd","omit","_props","pick","reduce","plainCopy","reject","Promise","remove","resolve","set","_path","exec","_equal","toJson","stringify","unset","getDefaultLocale","safeSetProp","field","_set","safeSetLink","Settable","_get","_unset","Component","_listeners","INDEX_ERR","reserved","limit","offset","orderBy","skip","sort","where","locale","escapeRegExp","percentRegExp","underscoreRegExp","escape","pattern","replace","Query","collection","fields","ops","predicates","clause","expr","op","groups","_where","prev","parser","_applyWhereFromArray","_applyWhereFromObject","group","isOr","keep","first","charAt","evaluate","_testArrayGroup","_testObjectGroup","leftKeys","rightKeys","data","getIndex","between","compare","cA","cB","temp","n","predicate","like","query","getData","collator","Intl","Collator","numeric","forEachFn","keyList","concat","getAll","flags","num","Math","min","mapFn","funcName","isectEmpty","isectNotEmpty","notIn","contains","notContains","belongsToType","hasManyType","hasOneType","Relation","relatedMapper","options","TYPE_NAME","validateOptions","related","DOMAIN_ERR","foreignKey","localKey","defineProperty","relationFields","idAttribute","relatedRecord","_setForeignKey","relatedRecords","relatedData","inverse","findInverseRelation","isInversedTo","records","datastore","getLocalField","add","linkRecord","isEmptyLinks","canFindLinkFor","findExistingLinksFor","setLocalField","relatedId","unsaved","relatedCollection","canAutoAddLinks","setForeignKey","id","relationData","is","createRecord","createLinked","then","getCollection","superMethod","store","bind","creatingPath","noValidatePath","keepChangeHistoryPath","previousPath","Record","noValidate","keepChangeHistory","validateOnSet","toJSON","relations","_mapper","quickHasChanges","validate","currentParent","inverseDef","children","child","adapter","getAdapterName","tasks","task","raw","load","localKeys","foreignKeys","previous","preserve","commit","postProcess","changesOnly","changes","silent","hashCode","insertAt","removeAt","binarySearch","lo","hi","compared","mid","found","Index","fieldList","fieldGetter","isIndex","values","pos","dataLocation","newIndex","results","order","cb","visitAll","leftInclusive","rightInclusive","_between","leftKey","rightKey","currKey","peek","isUnique","removeRecord","j","insertRecord","COLLECTION_DEFAULTS","commitOnMerge","emitRecordEvents","onConflict","Collection","queryClass","recordId","beforeAdd","singular","existingNoValidate","updateIndexes","indexes","_onRecordEvent","afterAdd","run","queryOrFn","instances","removeAll","Ctor","initialValue","idOrRecord","beforeRemove","afterRemove","queryOrRecords","beforeRemoveAll","afterRemoveAll","mapCall","updateRecord","TsDataError","types","integer","number","string","segmentToString","segment","str","makePath","segments","makeError","actual","expected","addError","errors","maxLengthCommon","keyword","schema","max","minLengthCommon","validationKeywords","allOf","allErrors","_schema","anyOf","validated","dependencies","possibleValues","join","items","checkingTuple","maximum","exclusiveMaximum","maxItems","maxLength","maxProperties","minimum","exclusiveMinimum","minItems","minLength","minProperties","multipleOf","not","oneOf","properties","additionalProperties","patternProperties","toValidate","undef","origProp","required","existingOnly","prevProp","validType","_type","validator","typeGroupValidators","uniqueItems","runOps","ANY_OPS","ARRAY_OPS","NUMERIC_OPS","OBJECT_OPS","STRING_OPS","validateAny","ctx","shouldPop","changingPath","changedPath","changeHistoryPath","eventIdPath","silentPath","validationFailureMsg","Schema","definition","_definition","validationKeyword","unsetter","track","makeDescriptor","hasSet","orig","applyDefaults","configurable","keyPath","error","current","changing","clearTimeout","setTimeout","changeRecord","timestamp","changeHistory","originalGet","originalSet","_copy","BelongsToRelation","HasManyRelation","hasForeignKeys","ids","findExistingLinksByForeignKey","findExistingLinksByLocalKeys","findExistingLinksByForeignKeys","foreignIdField","createMany","HasOneRelation","RelationType","belongsTo","assignTo","hasMany","hasOne","applyDefaultsHooks","validatingHooks","makeNotify","getSchema","toProcess","originalExistingOnly","notify","notify2","LIFECYCLE_METHODS","count","defaults","destroy","destroyAll","find","findAll","sum","update","adapterArgs","beforeAssign","updateAll","updateMany","MAPPER_DEFAULTS","_adapters","applySchema","defaultAdapter","Mapper","recordClass","methods","isPrototypeOf","_data","wrap","crud","originalRecord","parentRelationMap","adapterResponse","_runHook","_createParentRecordIfRequired","relationMap","_invokeAdapterMethod","createdProps","_createOrAssignChildRecordIfRequired","originalProps","_commitChanges","_end","recordOrRecords","newValues","isRequiresParentId","createParentRecord","context","isRequiresChildId","createChildRecord","parent","originalRecords","belongsToRelationData","Boolean","createdRecordsData","belongsToData","createdRecordData","ensureLinkedDataHasProperType","RecordCtor","method","config","lifecycleMethods","upper","before","after","_value","getAdapter","_opts","assign","_result","getAdapters","hookName","hookArgs","defaultValueIndex","overridenResult","propsOrRecords","conversionOptions","pass","_record","some","_name","getMapperByName","getMapper","proxiedMapperMethods","Container","_mappers","mapperClass","writable","mapperDefaults","original","_onMapperEvent","defineRelations","warn","defineMapper","proxiedCollectionMethods","ownMethodsForScoping","cachedFn","hashOrId","cached","_completedQueries","SIMPLESTORE_DEFAULTS","usePendingFind","usePendingFindAll","SimpleStore","collectionClass","addToCache","hash","_collections","self","_pendingQueries","collectionOpts","_added","indexed","createIndex","_onCollectionEvent","hashQuery","pendingQuery","cachedFind","force","promise","cacheFind","cachedFindAll","cacheFindAll","removeRelated","getForeignKey","indexName","prune","LinkedCollection","event","addLinkedRecords","_addMeta","_clearMeta","removeLinkedRecords","DATASTORE_DEFAULTS","unlinkOnDestroy","DataStore","updateOpts","getInverse","removeInverseRelation","relatedIdAttribute","updateIndex","setupInverseRelation","foreignKeyDescriptor","currentParentId","storeRecord","inverseLocalField","toLink","toLinkIds","currentChildrenOfParent","parents","_key","origGet","origSet","version"],"mappings":"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"} \ No newline at end of file diff --git a/dist/js-data.min.js b/dist/js-data.min.js index 7713d5d8..79cce7ae 100644 --- a/dist/js-data.min.js +++ b/dist/js-data.min.js @@ -1,11 +1,11 @@ /*! * js-data -* @version 3.0.6 - Homepage +* @version 4.0.0-beta.4 - Homepage * @author js-data project authors * @copyright (c) 2014-2016 js-data project authors * @license MIT * * @overview js-data is a framework-agnostic, datastore-agnostic ORM/ODM for Node.js and the Browser. */ -!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define("js-data",["exports"],t):t((e=e||self).JSData={})}(this,function(e){"use strict";function _typeof(e){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function _defineProperty(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function _toConsumableArray(e){return function _arrayWithoutHoles(e){if(Array.isArray(e)){for(var t=0,n=new Array(e.length);t=a.length&&"."===e[a.length]?s.with[t]=e.substr(a.length+1):s.with[t]=""}),n.call(i,t,s)}},_getIndex:function _getIndex(e,n){var i=-1;return e.forEach(function(e,t){return e===n||x.isObject(e)&&e.relation===n?(i=t,!1):void 0}),i},addHiddenPropsToTarget:function addHiddenPropsToTarget(e,n){var i={};Object.keys(n).forEach(function(e){var t=Object.getOwnPropertyDescriptor(n,e);t.enumerable=!1,i[e]=t}),Object.defineProperties(e,i)},areDifferent:function areDifferent(e,t,n){n=n||{};var i=x.diffObjects(e,t,n);return 0":function _(e,t){return t=":function _(e,t){return t<=e},"<":function _(e,t){return e")(400,"string",r)},canFindLinkFor:function canFindLinkFor(e){return!!(this.foreignKey||this.foreignKeys||this.localKeys&&x.get(e,this.localKeys))},linkRecord:function linkRecord(n,e){var i=this,r=this.relatedCollection,o=this.canAutoAddLinks,a=this.foreignKey,s=this.relatedCollection.unsaved();return e.map(function(e){var t=r.recordId(e);return(void 0===t&&-1===s.indexOf(e)||e!==r.get(t))&&(a&&i.setForeignKey(n,e),o&&(e=r.add(e))),e})},findExistingLinksFor:function findExistingLinksFor(e){var t,n=x.get(e,this.mapper.idAttribute),i=this.localKeys?x.get(e,this.localKeys):null;if(void 0!==n&&this.foreignKey?t=this.findExistingLinksByForeignKey(n):this.localKeys&&i?t=this.findExistingLinksByLocalKeys(i):void 0!==n&&this.foreignKeys&&(t=this.findExistingLinksByForeignKeys(n)),t&&t.length)return t},findExistingLinksByLocalKeys:function findExistingLinksByLocalKeys(e){return this.relatedCollection.filter({where:_defineProperty({},this.relatedCollection.mapper.idAttribute,{in:e})})},findExistingLinksByForeignKeys:function findExistingLinksByForeignKeys(e){return this.relatedCollection.filter({where:_defineProperty({},this.foreignKeys,{contains:e})})},isRequiresParentId:function isRequiresParentId(){return!!this.localKeys&&0a)break}else if(this.keys[s]>=a)break;if(r=this.values[s].isIndex?r.concat(this.values[s].getAll()):r.concat(this.values[s]),n.limit&&r.length>=n.limit+n.offset)break}}else for(var c=i.index;c=n.limit+n.offset)break}return n.limit?r.slice(0,n.limit+n.offset):r},peek:function peek(){return this.values.length?this.values[0].isIndex?this.values[0].peek():this.values[0]:[]},clear:function clear(){this.keys=[],this.values=[]},insertRecord:function insertRecord(t){var e=this.fieldList.map(function(e){return x.isFunction(e)?e(t)||void 0:t[e]||void 0});this.set(e,t)},removeRecord:function removeRecord(r){var o,a=this,s=void 0!==this.hashCode(r);return this.values.forEach(function(e,t){if(e.isIndex){if(e.removeRecord(r))return 0===e.keys.length&&(removeAt(a.keys,t),removeAt(a.values,t)),!(o=!0)}else{var n={};if(void 0!==a.keys[t]&&s)s&&(n=binarySearch(e,r,a.hashCode));else for(var i=e.length-1;0<=i;i--)if(e[i]===r){n={found:!0,index:i};break}if(n.found)return removeAt(e,n.index),0===e.length&&(removeAt(a.keys,t),removeAt(a.values,t)),!(o=!0)}}),o?r:void 0},updateRecord:function updateRecord(e){void 0!==this.removeRecord(e)&&this.insertRecord(e)}});var E=F.noValidatePath,j="Collection",S={commitOnMerge:!0,emitRecordEvents:!0,idAttribute:"id",onConflict:"merge"};function ca(e,t){var n="";return e&&(x.isNumber(e)?n+="[".concat(e,"]"):n+=t?".".concat(e):"".concat(e)),n}function ea(e,t,n){return{expected:t,actual:""+e,path:function makePath(e){var t="";return((e=e||{}).path||[]).forEach(function(e){t+=ca(e,t)}),t+=ca(e.prop,t)}(n)}}function fa(e,t,n,i){i.push(ea(e,t,n))}function ga(e,t,n,i){var r=n[e];if(t.length>r)return ea(t.length,"length no more than ".concat(r),i)}function ha(e,t,n,i){var r=n[e];if(t.length=c.length&&"."===e[c.length]?f.with[t]=e.substr(c.length+1):f.with[t]=""}),s.call(l,a,f)}},_getIndex:function _getIndex(e,n){var r=-1;return e.forEach(function(e,t){return e===n||A.isObject(e)&&e.relation===n?(r=t,!1):void 0}),r},addHiddenPropsToTarget:function addHiddenPropsToTarget(e,n){var r={};Object.keys(n).forEach(function(e){var t=Object.getOwnPropertyDescriptor(n,e);t.enumerable=!1,r[e]=t}),Object.defineProperties(e,r)},areDifferent:function areDifferent(e,t,n){var r=2":function _(e,t){return t=":function _(e,t){return t<=e},"<":function _(e,t){return ea)break}else if(this.keys[s]>=a)break;if(i=this.values[s].isIndex?i.concat(this.values[s].getAll()):i.concat(this.values[s]),n.limit&&i.length>=n.limit+n.offset)break}}else for(var l=r.index;l=n.limit+n.offset)break}return n.limit?i.slice(0,n.limit+n.offset):i}},{key:"peek",value:function peek(){return this.values.length?this.values[0].isIndex?this.values[0].peek():this.values[0]:[]}},{key:"clear",value:function clear(){this.keys=[],this.values=[]}},{key:"insertRecord",value:function insertRecord(t){var e=this.fieldList.map(function(e){return A.isFunction(e)?e(t)||void 0:t[e]||void 0});this.set(e,t)}},{key:"removeRecord",value:function removeRecord(i){var o,a=this,s=void 0!==this.hashCode(i);return this.values.forEach(function(e,t){if(e.isIndex){if(e.removeRecord(i))return 0===e.keys.length&&(removeAt(a.keys,t),removeAt(a.values,t)),!(o=!0)}else{var n={};if(void 0!==a.keys[t]&&s)s&&(n=binarySearch(e,i,a.hashCode));else for(var r=e.length-1;0<=r;r--)if(e[r]===i){n={found:!0,index:r};break}if(n.found)return removeAt(e,n.index),0===e.length&&(removeAt(a.keys,t),removeAt(a.values,t)),!(o=!0)}}),o?i:void 0}},{key:"updateRecord",value:function updateRecord(e){void 0!==this.removeRecord(e)&&this.insertRecord(e)}}]),Index}(),F=I.noValidatePath,M="Collection",j={commitOnMerge:!0,emitRecordEvents:!0,idAttribute:"id",onConflict:"merge"},L=function(){function Collection(){var e,t=0i)return makeError(t.length,"length no more than ".concat(i),r)}function minLengthCommon(e,t,n,r){var i=n[e];if(t.length")(400,"string",i)}},{key:"canFindLinkFor",value:function canFindLinkFor(e){return!!(this.foreignKey||this.foreignKeys||this.localKeys&&A.get(e,this.localKeys))}},{key:"linkRecord",value:function linkRecord(n,e){var r=this,i=this.relatedCollection,o=this.canAutoAddLinks,a=this.foreignKey,s=this.relatedCollection.unsaved();return e.map(function(e){var t=i.recordId(e);return(void 0===t&&-1===s.indexOf(e)||e!==i.get(t))&&(a&&r.setForeignKey(n,e),o&&(e=i.add(e))),e})}},{key:"findExistingLinksFor",value:function findExistingLinksFor(e){var t,n=A.get(e,this.mapper.idAttribute),r=this.localKeys?A.get(e,this.localKeys):null;if(void 0!==n&&this.foreignKey?t=this.findExistingLinksByForeignKey(n):this.localKeys&&r?t=this.findExistingLinksByLocalKeys(r):void 0!==n&&this.foreignKeys&&(t=this.findExistingLinksByForeignKeys(n)),null!==t&&void 0!==t&&t.length)return t}},{key:"findExistingLinksByLocalKeys",value:function findExistingLinksByLocalKeys(e){return this.relatedCollection.filter({where:_defineProperty({},this.relatedCollection.mapper.idAttribute,{in:e})})}},{key:"findExistingLinksByForeignKeys",value:function findExistingLinksByForeignKeys(e){return this.relatedCollection.filter({where:_defineProperty({},this.foreignKeys,{contains:e})})}},{key:"isRequiresParentId",value:function isRequiresParentId(){return!!this.localKeys&&0",">=","<","<=","isectEmpty","isectNotEmpty","in","_in","notIn","contains","notContains","belongsToType","hasManyType","hasOneType","Relation","relatedMapper","options","TYPE_NAME","validateOptions","canAutoAddLinks","add","relatedCollection","datastore","getCollection","related","DOMAIN_ERR","foreignKey","localKey","assignTo","relationFields","canFindLinkFor","getForeignKey","idAttribute","setForeignKey","relatedRecord","_setForeignKey","relatedRecords","getLocalField","setLocalField","relatedData","getInverse","inverse","findInverseRelation","isInversedTo","addLinkedRecords","records","linkRecord","findExistingLinksFor","removeLinkedRecords","relatedId","unsaved","findExistingLinksByForeignKey","id","ensureLinkedDataHasProperType","relationData","is","createRecord","isRequiresParentId","isRequiresChildId","createChildRecord","_this4","createLinked","then","createParentRecord","localKeys","foreignKeys","recordId","ids","findExistingLinksByLocalKeys","findExistingLinksByForeignKeys","foreignIdField","createMany","RelationType","belongsTo","hasMany","hasOne","superMethod","store","bind","creatingPath","noValidatePath","keepChangeHistoryPath","previousPath","Record","noValidate","keepChangeHistory","validateOnSet","toJSON","Record$1","_mapper","afterLoadRelations","beforeLoadRelations","changeHistory","changes","commit","destroy","hasChanges","isNew","isValid","validate","removeInverseRelation","currentParent","inverseDef","children","child","setupInverseRelation","loadRelations","relations","adapter","getAdapterName","task","tasks","raw","load","previous","revert","preserve","save","_this5","postProcess","changesOnly","silent","insertAt","removeAt","binarySearch","compared","mid","hashCode","lo","hi","found","Index","fieldList","fieldGetter","isIndex","values","pos","dataLocation","newIndex","results","order","_i","visitAll","cb","leftInclusive","rightInclusive","_between","leftKey","rightKey","_i2","currKey","peek","clear","insertRecord","removeRecord","isUnique","j","updateRecord","noValidatePath$1","DOMAIN$4","COLLECTION_DEFAULTS","commitOnMerge","emitRecordEvents","onConflict","segmentToString","segment","str","makeError","actual","expected","makePath","addError","errors","maxLengthCommon","keyword","schema","max","minLengthCommon","runOps","validationKeywords","Collection$1","Collection","queryClass","indexes","_onRecordEvent","beforeAdd","singular","existingNoValidate","updateIndexes","afterAdd","afterRemove","afterRemoveAll","beforeRemove","beforeRemoveAll","createIndex","instances","_this$query","prune","removeAll","initialValue","idOrRecord","queryOrRecords","updateIndex","types","boolean","integer","null","number","string","allOf","allErrors","_schema","_validate","anyOf","validated","dependencies","enum","_enum","possibleValues","join","items","checkingTuple","maximum","exclusiveMaximum","maxItems","maxLength","maxProperties","minimum","exclusiveMinimum","minItems","minLength","minProperties","multipleOf","not","oneOf","properties","additionalProperties","patternProperties","toValidate","undef","origProp","required","existingOnly","prevProp","validType","_type","validator","typeGroupValidators","uniqueItems","ANY_OPS","ARRAY_OPS","NUMERIC_OPS","OBJECT_OPS","STRING_OPS","shouldPop","ctx","extends","validateAny","changingPath","changedPath","changeHistoryPath","eventIdPath","numeric","makeNotify","applyDefaultsHooks","applyDefaults","getSchema","toProcess","validatingHooks","originalExistingOnly","notify","setTimeout","Schema$1","Schema","definition","_definition","validationKeyword","unsetter","track","makeDescriptor","hasSet","default","orig","keyPath","originalGet","error","current","changing","clearTimeout","changeRecord","timestamp","originalSet","_copy","DOMAIN$6","notify2","LIFECYCLE_METHODS","count","defaults","destroyAll","find","findAll","sum","update","adapterArgs","beforeAssign","updateAll","updateMany","MAPPER_DEFAULTS","_adapters","applySchema","defaultAdapter","Mapper$1","Mapper","lifecycleMethods","recordClass","methods","isPrototypeOf","afterCount","afterCreate","afterCreateMany","afterDestroy","afterDestroyAll","afterFind","afterFindAll","afterSum","afterUpdate","afterUpdateAll","afterUpdateMany","beforeCreate","beforeCreateMany","beforeCount","beforeDestroy","beforeDestroyAll","beforeFind","beforeFindAll","beforeSum","beforeUpdate","beforeUpdateAll","beforeUpdateMany","_end","_data","wrap","belongsTo$1","crud","originalRecord","parentRelationMap","adapterResponse","_runHook","_createParentRecordIfRequired","relationMap","_invokeAdapterMethod","createdProps","_createOrAssignChildRecordIfRequired","originalProps","_commitChanges","recordOrRecords","newValues","createInstance","context","parent","originalRecords","belongsToRelationData","Boolean","createdRecordsData","belongsToData","createdRecordData","RecordCtor","method","_this6","config","upper","before","after","_this6$getAdapter","getAdapter","_opts","assign","_result","getAdapters","hasMany$1","hasOne$1","registerAdapter","hookName","hookArgs","defaultValueIndex","overridenResult","propsOrRecords","_this7","conversionOptions","pass","_this8","_record","some","defineRelations","_this9","_name","getMapperByName","getMapper","DOMAIN$7","proxiedMapperMethods","Container","_mappers","mapperClass","mapperDefaults","_onMapperEvent","as","original","defineMapper","defineResource","warn","_this$getMapper","cachedFn","hashOrId","cached","_completedQueries","proxiedCollectionMethods","ownMethodsForScoping","SIMPLESTORE_DEFAULTS","usePendingFind","usePendingFindAll","props$1","SimpleStore","collectionClass","_collections","_pendingQueries","addToCache","_onCollectionEvent","cachedFind","cachedFindAll","cacheFind","cacheFindAll","hash","collectionOpts","_added","indexed","hashQuery","eject","ejectAll","pendingQuery","force","inject","removeRelated","_this10","_this11","_this12","_this13","_this$getCollection","SimpleStore$1","DOMAIN$9","LinkedCollection$1","LinkedCollection","_addMeta","_clearMeta","event","DATASTORE_DEFAULTS","unlinkOnDestroy","props$2","DataStore","updateOpts","relatedIdAttribute","foreignKeyDescriptor","currentParentId","storeRecord","inverseLocalField","toLink","toLinkIds","currentChildrenOfParent","parents","origGet","origSet","DataStore$1","version","full","major","minor","patch"],"mappings":"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"} \ No newline at end of file +{"version":3,"sources":["dist/js-data.js"],"names":["global","factory","exports","module","define","amd","self","JSData","this","_typeof","obj","Symbol","iterator","constructor","prototype","_classCallCheck","instance","Constructor","TypeError","_defineProperties","target","props","i","length","descriptor","enumerable","configurable","writable","Object","defineProperty","key","_createClass","protoProps","staticProps","_defineProperty","value","_inherits","subClass","superClass","create","_setPrototypeOf","_getPrototypeOf","o","setPrototypeOf","getPrototypeOf","__proto__","p","_construct","Parent","args","Class","isNativeReflectConstruct","Reflect","construct","sham","Proxy","Date","toString","call","e","a","push","apply","Function","bind","arguments","_wrapNativeSuper","_cache","Map","undefined","_isNativeFunction","fn","indexOf","has","get","set","Wrapper","_assertThisInitialized","ReferenceError","_possibleConstructorReturn","_get","property","receiver","base","_superPropBase","object","hasOwnProperty","desc","getOwnPropertyDescriptor","_toConsumableArray","arr","_arrayWithoutHoles","Array","isArray","arr2","_iterableToArray","iter","from","_nonIterableSpread","toStr","objToString","isPlainObject","safeSetProp","record","field","_set","concat","utils","safeSetLink","Settable","_props","defineProperties","_value","_unset","unset","NUMBER_TAG","REGEXP_TAG","PATH","ERRORS","400","_","404","dest","src","forOwn","isFunction","_forRelation","index","opts","def","thisArg","relationName","relation","containedName","_getIndex","localField","withAll","optsCopy","fillIn","getRelation","slice","_activeWith","splice","forEach","substr","list","_relation","isObject","addHiddenPropsToTarget","map","keys","propName","areDifferent","newObject","oldObject","diff","diffObjects","added","removed","changed","copy","to","stackFrom","stackTo","blacklist","plain","err","result","isBlacklisted","isDate","getTime","isRegExp","RegExp","source","match","lastIndex","deepFillIn","existing","deepMixIn","equalsFn","ignore","deepEqual","newKeys","filter","oldKeys","oldValue","newValue","equal","b","domain","code","prefix","_len","_key","message","Error","eventify","getter","setter","_events","emit","events","_len2","_key2","type","shift","listeners","f","c","all","unshift","off","func","on","findIndex","array","forEachRelation","mapper","relationList","len","fromJson","json","isString","JSON","parse","prop","parts","split","last","pop","getSuper","isCtor","ctor","__super__","intersection","array1","array2","item","matches","_iteratorNormalCompletion","_didIteratorError","_iteratorError","_step","_iterator","next","done","test","isBoolean","isInteger","toInteger","remainder","isNull","isNumber","isSorN","isUndefined","logify","dbg","log","_len3","_key3","level","_len4","_key4","debug","_console","_console2","toUpperCase","name","console","noDupeAdd","omit","pick","reduce","plainCopy","reject","Promise","remove","resolve","path","_path","exec","mkdirP","_equal","toJson","stringify","getDefaultLocale","Component","_this","_a","_listeners","DOMAIN$1","INDEX_ERR","reserved","limit","offset","orderBy","skip","sort","where","locale","escapeRegExp","percentRegExp","underscoreRegExp","Query","collection","data","_applyWhereFromObject","fields","ops","predicates","clause","==","expr","op","_applyWhereFromArray","_this2","groups","_where","prev","group","isOr","_testObjectGroup","keep","first","charAt","evaluate","_testArrayGroup","between","leftKeys","rightKeys","getIndex","compare","_compare","cA","cB","temp","n","predicate","like","_this3","query","getData","collator","Intl","Collator","numeric","forEachFn","keyList","getAll","_this4","pattern","flags","escape","replace","num","Math","min","mapFn","mapCall","funcName","run","=","===","!=","!==",">",">=","<","<=","isectEmpty","isectNotEmpty","in","_in","notIn","contains","notContains","belongsToType","hasManyType","hasOneType","DOMAIN$2","Relation","relatedMapper","options","TYPE_NAME","validateOptions","related","DOMAIN_ERR","foreignKey","localKey","assignTo","relationFields","canFindLinkFor","getForeignKey","idAttribute","setForeignKey","relatedRecord","_setForeignKey","relatedRecords","getLocalField","setLocalField","relatedData","getInverse","inverse","findInverseRelation","isInversedTo","addLinkedRecords","records","datastore","add","linkRecord","findExistingLinksFor","removeLinkedRecords","relatedId","relatedCollection","unsaved","canAutoAddLinks","findExistingLinksByForeignKey","id","ensureLinkedDataHasProperType","relationData","is","createRecord","isRequiresParentId","isRequiresChildId","createChildRecord","createLinked","then","getCollection","superMethod","store","creatingPath","noValidatePath","keepChangeHistoryPath","previousPath","Record","noValidate","keepChangeHistory","validateOnSet","toJSON","_mapper","afterLoadRelations","beforeLoadRelations","changeHistory","changes","commit","destroy","hasChanges","isNew","isValid","validate","removeInverseRelation","currentParent","inverseDef","children","child","setupInverseRelation","loadRelations","relations","adapter","getAdapterName","task","tasks","raw","load","localKeys","foreignKeys","previous","revert","_this5","preserve","save","postProcess","_this6","changesOnly","silent","insertAt","removeAt","binarySearch","compared","mid","hashCode","lo","hi","found","Index","fieldList","fieldGetter","isIndex","values","pos","dataLocation","newIndex","results","order","visitAll","cb","leftInclusive","rightInclusive","_between","leftKey","rightKey","_i","currKey","peek","clear","insertRecord","removeRecord","isUnique","j","updateRecord","noValidatePath$1","DOMAIN$4","COLLECTION_DEFAULTS","commitOnMerge","emitRecordEvents","onConflict","Collection","indexes","_added","queryClass","recordId","_onRecordEvent","beforeAdd","singular","existingNoValidate","updateIndexes","afterAdd","afterRemove","afterRemoveAll","beforeRemove","beforeRemoveAll","createIndex","queryOrFn","instances","_this$query","prune","removeAll","initialValue","idOrRecord","queryOrRecords","updateIndex","TsDataError","types","boolean","integer","null","number","string","segmentToString","segment","str","makeError","actual","expected","makePath","addError","errors","maxLengthCommon","keyword","schema","max","minLengthCommon","validationKeywords","allOf","allErrors","_schema","_validate","anyOf","validated","dependencies","enum","_enum","possibleValues","join","items","checkingTuple","maximum","exclusiveMaximum","maxItems","maxLength","maxProperties","minimum","exclusiveMinimum","minItems","minLength","minProperties","multipleOf","not","oneOf","properties","additionalProperties","patternProperties","toValidate","undef","origProp","required","existingOnly","prevProp","validType","_type","validator","typeGroupValidators","uniqueItems","runOps","ANY_OPS","ARRAY_OPS","NUMERIC_OPS","OBJECT_OPS","STRING_OPS","shouldPop","ctx","validateAny","changingPath","changedPath","changeHistoryPath","eventIdPath","Schema","definition","_definition","validationKeyword","unsetter","track","makeDescriptor","applyDefaults","hasSet","orig","keyPath","error","current","changing","clearTimeout","setTimeout","changeRecord","timestamp","originalGet","originalSet","_copy","BelongsToRelation","createParentRecord","HasManyRelation","ids","findExistingLinksByLocalKeys","findExistingLinksByForeignKeys","foreignIdField","createMany","HasOneRelation","belongsTo","hasMany","hasOne","RelationType","DOMAIN$6","applyDefaultsHooks","validatingHooks","makeNotify","getSchema","toProcess","originalExistingOnly","notify","cachedFn","hashOrId","cached","_completedQueries","notify2","LIFECYCLE_METHODS","count","defaults","destroyAll","find","findAll","sum","update","adapterArgs","beforeAssign","updateAll","updateMany","MAPPER_DEFAULTS","_adapters","applySchema","defaultAdapter","Mapper","lifecycleMethods","afterCount","afterCreate","afterCreateMany","afterDestroy","afterDestroyAll","afterFind","afterFindAll","afterSum","afterUpdate","afterUpdateAll","afterUpdateMany","beforeCreate","beforeCreateMany","beforeCount","beforeDestroy","beforeDestroyAll","beforeFind","beforeFindAll","beforeSum","beforeUpdate","beforeUpdateAll","beforeUpdateMany","recordClass","TiedRecord","methods","isPrototypeOf","_end","_data","wrap","belongsTo$1","crud","originalRecord","parentRelationMap","adapterResponse","_runHook","_createParentRecordIfRequired","relationMap","_invokeAdapterMethod","createdProps","_createOrAssignChildRecordIfRequired","originalProps","_commitChanges","recordOrRecords","newValues","createInstance","context","parent","originalRecords","belongsToRelationData","Boolean","createdRecordsData","belongsToData","createdRecordData","RecordCtor","method","_this7","config","upper","before","after","_this7$getAdapter","getAdapter","_opts","assign","_result","getAdapters","hasMany$1","hasOne$1","registerAdapter","hookName","hookArgs","defaultValueIndex","overridenResult","propsOrRecords","_this8","conversionOptions","with","pass","_this9","_record","some","defineRelations","_this10","_name","getMapperByName","getMapper","DOMAIN$7","proxiedMapperMethods","Container","_mappers","mapperClass","mapperDefaults","_onMapperEvent","as","original","defineMapper","defineResource","warn","proxiedCollectionMethods","ownMethodsForScoping","SIMPLESTORE_DEFAULTS","usePendingFind","usePendingFindAll","SimpleStore","_collections","_pendingQueries","cachedFind","cachedFindAll","collectionClass","addToCache","_onCollectionEvent","cacheFind","cacheFindAll","hash","collectionOpts","indexed","hashQuery","eject","ejectAll","pendingQuery","force","inject","removeRelated","_this11","_this12","_this13","_this14","indexName","_this$getCollection","LinkedCollection","_addMeta","_clearMeta","event","DATASTORE_DEFAULTS","unlinkOnDestroy","DataStore","updateOpts","relatedIdAttribute","foreignKeyDescriptor","currentParentId","storeRecord","inverseLocalField","toLink","toLinkIds","currentChildrenOfParent","parents","origGet","origSet","version","beta","full","major","minor","patch"],"mappings":"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"} \ No newline at end of file diff --git a/karma.conf.js b/karma.conf.js deleted file mode 100644 index e7c3d89e..00000000 --- a/karma.conf.js +++ /dev/null @@ -1,137 +0,0 @@ -var browsers = ['ChromeHeadless'] - -var customLaunchers = { - sl_chrome: { - base: 'SauceLabs', - browserName: 'chrome', - platform: 'Windows 10', - version: 'latest' - }, - sl_firefox: { - base: 'SauceLabs', - browserName: 'firefox', - platform: 'Windows 10', - version: 'latest' - }, - sl_safari_9: { - base: 'SauceLabs', - browserName: 'safari', - platform: 'OS X 10.11', - version: '9.0' - }, - sl_edge: { - base: 'SauceLabs', - browserName: 'microsoftedge', - platform: 'Windows 10', - version: 'latest' - }, - sl_ie_11: { - base: 'SauceLabs', - browserName: 'internet explorer', - platform: 'Windows 8.1', - version: '11' - }, - sl_android_5: { - base: 'SauceLabs', - browserName: 'android', - platform: 'Linux', - version: '5.1' - } -} - -if (process.env.SAUCE_USERNAME && process.env.SAUCE_ACCESS_KEY) { - browsers = browsers.concat(Object.keys(customLaunchers)) -} - -module.exports = function (config) { - config.set({ - basePath: './', - frameworks: [ - 'chai', - 'mocha', - 'sinon' - ], - plugins: [ - 'karma-babel-preprocessor', - 'karma-chai', - 'karma-chrome-launcher', - 'karma-mocha', - 'karma-phantomjs-launcher', - 'karma-sauce-launcher', - 'karma-sinon' - ], - files: [ - 'node_modules/@babel/polyfill/dist/polyfill.js', - 'src/utils.js', - 'src/Relation.js', - 'src/Relation/*.js', - 'src/relations.js', - 'src/decorators.js', - 'src/Settable.js', - 'src/Component.js', - 'src/Schema.js', - 'src/Query.js', - 'src/Record.js', - 'src/Mapper.js', - 'lib/mindex/_utils.js', - 'lib/mindex/index.js', - 'src/Collection.js', - 'src/Container.js', - 'src/SimpleStore.js', - 'src/LinkedCollection.js', - 'src/DataStore.js', - 'src/index.js', - 'test/_setup.js', - 'test/unit/schema/_productSchema.js', - 'test/**/*.js' - ], - preprocessors: { - 'src/**/*.js': ['babel'], - 'lib/**/*.js': ['babel'], - 'test/**/*.js': ['babel'] - }, - babelPreprocessor: { - options: { - presets: [ - ['@babel/preset-env', { - 'targets': { - 'browsers': ['last 2 versions', 'safari >= 7', - '> 1%', - 'IE 11' - ] - } - }] - ], - plugins: [ - '@babel/transform-regenerator', - '@babel/transform-modules-umd' - ], - sourceMap: 'inline' - } - }, - browsers: browsers, - reporters: ['progress', 'saucelabs'], - sauceLabs: { - testName: 'JSData Tests', - public: 'public', - recordVideo: false, - recordScreenshots: false, - build: process.env.CIRCLE_BUILD_NUM ? ('circle-' + process.env.CIRCLE_BUILD_NUM) : ('local-' + new Date().getTime()) - }, - customLaunchers: customLaunchers, - port: 9876, - browserDisconnectTimeout: 10000, - browserNoActivityTimeout: 30000, - captureTimeout: 120000, - colors: true, - logLevel: config.LOG_INFO, - autoWatch: false, - singleRun: true, - // client: { - // mocha: { - // grep: 'Schema' - // } - // }, - concurrency: Infinity - }) -} diff --git a/package-lock.json b/package-lock.json index 837fdb26..fefeeaad 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "js-data", - "version": "3.0.6", + "version": "4.0.0-beta.4", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -14,9 +14,9 @@ } }, "@babel/cli": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.8.3.tgz", - "integrity": "sha512-K2UXPZCKMv7KwWy9Bl4sa6+jTNP7JyDiHKzoOiUUygaEDbC60vaargZDnO9oFMvlq8pIKOOyUUgeMYrsaN9djA==", + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.8.4.tgz", + "integrity": "sha512-XXLgAm6LBbaNxaGhMAznXXaxtCWfuv6PIDJ9Alsy9JYTOh+j2jJz+L/162kkfU1j/pTSxK1xGmlwI4pdIMkoag==", "dev": true, "requires": { "chokidar": "^2.1.8", @@ -30,5573 +30,2511 @@ "source-map": "^0.5.0" }, "dependencies": { - "commander": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.0.tgz", - "integrity": "sha512-NIQrwvv9V39FHgGFm36+U9SMQzbiHvU79k+iADraJTpmrFFfx7Ds0IvDoAdZsDrknlkRk14OYoWXb57uTh7/sw==", - "dev": true - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - }, - "slash": { + "anymatch": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", - "dev": true - } - } - }, - "@babel/code-frame": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", - "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", - "dev": true, - "requires": { - "@babel/highlight": "^7.8.3" - } - }, - "@babel/compat-data": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.8.1.tgz", - "integrity": "sha512-Z+6ZOXvyOWYxJ50BwxzdhRnRsGST8Y3jaZgxYig575lTjVSs3KtJnmESwZegg6e2Dn0td1eDhoWlp1wI4BTCPw==", - "dev": true, - "requires": { - "browserslist": "^4.8.2", - "invariant": "^2.2.4", - "semver": "^5.5.0" - }, - "dependencies": { - "browserslist": { - "version": "4.8.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.8.5.tgz", - "integrity": "sha512-4LMHuicxkabIB+n9874jZX/az1IaZ5a+EUuvD7KFOu9x/Bd5YHyO0DIz2ls/Kl8g0ItS4X/ilEgf4T1Br0lgSg==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30001022", - "electron-to-chromium": "^1.3.338", - "node-releases": "^1.1.46" - } - }, - "caniuse-lite": { - "version": "1.0.30001022", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001022.tgz", - "integrity": "sha512-FjwPPtt/I07KyLPkBQ0g7/XuZg6oUkYBVnPHNj3VHJbOjmmJ/GdSo/GUY6MwINEQvjhP6WZVbX8Tvms8xh0D5A==", - "dev": true - }, - "electron-to-chromium": { - "version": "1.3.340", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.340.tgz", - "integrity": "sha512-hRFBAglhcj5iVYH+o8QU0+XId1WGoc0VGowJB1cuJAt3exHGrivZvWeAO5BRgBZqwZtwxjm8a5MQeGoT/Su3ww==", - "dev": true - } - } - }, - "@babel/core": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.8.3.tgz", - "integrity": "sha512-4XFkf8AwyrEG7Ziu3L2L0Cv+WyY47Tcsp70JFmpftbAA1K7YL/sgE9jh9HyNj08Y/U50ItUchpN0w6HxAoX1rA==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.8.3", - "@babel/generator": "^7.8.3", - "@babel/helpers": "^7.8.3", - "@babel/parser": "^7.8.3", - "@babel/template": "^7.8.3", - "@babel/traverse": "^7.8.3", - "@babel/types": "^7.8.3", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.1", - "json5": "^2.1.0", - "lodash": "^4.17.13", - "resolve": "^1.3.2", - "semver": "^5.4.1", - "source-map": "^0.5.0" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", - "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", - "dev": true, - "requires": { - "@babel/highlight": "^7.8.3" - } - }, - "@babel/generator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.8.3.tgz", - "integrity": "sha512-WjoPk8hRpDRqqzRpvaR8/gDUPkrnOOeuT2m8cNICJtZH6mwaCo3v0OKMI7Y6SM1pBtyijnLtAL0HDi41pf41ug==", - "dev": true, - "requires": { - "@babel/types": "^7.8.3", - "jsesc": "^2.5.1", - "lodash": "^4.17.13", - "source-map": "^0.5.0" - } - }, - "@babel/helper-function-name": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz", - "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "^7.8.3", - "@babel/template": "^7.8.3", - "@babel/types": "^7.8.3" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz", - "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==", - "dev": true, - "requires": { - "@babel/types": "^7.8.3" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz", - "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==", - "dev": true, - "requires": { - "@babel/types": "^7.8.3" - } - }, - "@babel/highlight": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", - "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", - "dev": true, - "requires": { - "chalk": "^2.0.0", - "esutils": "^2.0.2", - "js-tokens": "^4.0.0" - } - }, - "@babel/parser": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.3.tgz", - "integrity": "sha512-/V72F4Yp/qmHaTALizEm9Gf2eQHV3QyTL3K0cNfijwnMnb1L+LDlAubb/ZnSdGAVzVSWakujHYs1I26x66sMeQ==", - "dev": true - }, - "@babel/template": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz", - "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.8.3", - "@babel/parser": "^7.8.3", - "@babel/types": "^7.8.3" - } - }, - "@babel/traverse": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.8.3.tgz", - "integrity": "sha512-we+a2lti+eEImHmEXp7bM9cTxGzxPmBiVJlLVD+FuuQMeeO7RaDbutbgeheDkw+Xe3mCfJHnGOWLswT74m2IPg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.8.3", - "@babel/generator": "^7.8.3", - "@babel/helper-function-name": "^7.8.3", - "@babel/helper-split-export-declaration": "^7.8.3", - "@babel/parser": "^7.8.3", - "@babel/types": "^7.8.3", - "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.13" - } - }, - "@babel/types": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", - "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.13", - "to-fast-properties": "^2.0.0" - } - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", "dev": true, + "optional": true, "requires": { - "color-convert": "^1.9.0" + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "optional": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } } }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } + "optional": true }, - "convert-source-map": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", - "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", "dev": true, + "optional": true, "requires": { - "safe-buffer": "~5.1.1" + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "optional": true, + "requires": { + "is-extendable": "^0.1.0" + } + } } }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", "dev": true, + "optional": true, "requires": { - "ms": "^2.1.1" + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" } }, - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - }, - "js-tokens": { + "fill-range": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - }, - "json5": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.1.tgz", - "integrity": "sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - }, - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", "dev": true, + "optional": true, "requires": { - "has-flag": "^3.0.0" + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "optional": true, + "requires": { + "is-extendable": "^0.1.0" + } + } } }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "@babel/generator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.8.3.tgz", - "integrity": "sha512-WjoPk8hRpDRqqzRpvaR8/gDUPkrnOOeuT2m8cNICJtZH6mwaCo3v0OKMI7Y6SM1pBtyijnLtAL0HDi41pf41ug==", - "dev": true, - "requires": { - "@babel/types": "^7.8.3", - "jsesc": "^2.5.1", - "lodash": "^4.17.13", - "source-map": "^0.5.0" - } - }, - "@babel/helper-annotate-as-pure": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.8.3.tgz", - "integrity": "sha512-6o+mJrZBxOoEX77Ezv9zwW7WV8DdluouRKNY/IR5u/YTMuKHgugHOzYWlYvYLpLA9nPsQCAAASpCIbjI9Mv+Uw==", - "dev": true, - "requires": { - "@babel/types": "^7.8.3" - }, - "dependencies": { - "@babel/types": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", - "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", + "fsevents": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.11.tgz", + "integrity": "sha512-+ux3lx6peh0BpvY0JebGyZoiR4D+oYzdPZMKJwkZ+sFkNJzpL7tXc/wehS49gUAxg3tmMHPHZkA8JU2rhhgDHw==", "dev": true, + "optional": true, "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.13", - "to-fast-properties": "^2.0.0" - } - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.8.3.tgz", - "integrity": "sha512-5eFOm2SyFPK4Rh3XMMRDjN7lBH0orh3ss0g3rTYZnBQ+r6YPj7lgDyCvPphynHvUrobJmeMignBr6Acw9mAPlw==", - "dev": true, - "requires": { - "@babel/helper-explode-assignable-expression": "^7.8.3", - "@babel/types": "^7.8.3" - }, - "dependencies": { - "@babel/types": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", - "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.13", - "to-fast-properties": "^2.0.0" - } - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "@babel/helper-call-delegate": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.8.3.tgz", - "integrity": "sha512-6Q05px0Eb+N4/GTyKPPvnkig7Lylw+QzihMpws9iiZQv7ZImf84ZsZpQH7QoWN4n4tm81SnSzPgHw2qtO0Zf3A==", - "dev": true, - "requires": { - "@babel/helper-hoist-variables": "^7.8.3", - "@babel/traverse": "^7.8.3", - "@babel/types": "^7.8.3" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", - "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", - "dev": true, - "requires": { - "@babel/highlight": "^7.8.3" - } - }, - "@babel/generator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.8.3.tgz", - "integrity": "sha512-WjoPk8hRpDRqqzRpvaR8/gDUPkrnOOeuT2m8cNICJtZH6mwaCo3v0OKMI7Y6SM1pBtyijnLtAL0HDi41pf41ug==", - "dev": true, - "requires": { - "@babel/types": "^7.8.3", - "jsesc": "^2.5.1", - "lodash": "^4.17.13", - "source-map": "^0.5.0" - } - }, - "@babel/helper-function-name": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz", - "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "^7.8.3", - "@babel/template": "^7.8.3", - "@babel/types": "^7.8.3" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz", - "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==", - "dev": true, - "requires": { - "@babel/types": "^7.8.3" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz", - "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==", - "dev": true, - "requires": { - "@babel/types": "^7.8.3" - } - }, - "@babel/highlight": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", - "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", - "dev": true, - "requires": { - "chalk": "^2.0.0", - "esutils": "^2.0.2", - "js-tokens": "^4.0.0" - } - }, - "@babel/parser": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.3.tgz", - "integrity": "sha512-/V72F4Yp/qmHaTALizEm9Gf2eQHV3QyTL3K0cNfijwnMnb1L+LDlAubb/ZnSdGAVzVSWakujHYs1I26x66sMeQ==", - "dev": true - }, - "@babel/template": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz", - "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.8.3", - "@babel/parser": "^7.8.3", - "@babel/types": "^7.8.3" - } - }, - "@babel/traverse": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.8.3.tgz", - "integrity": "sha512-we+a2lti+eEImHmEXp7bM9cTxGzxPmBiVJlLVD+FuuQMeeO7RaDbutbgeheDkw+Xe3mCfJHnGOWLswT74m2IPg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.8.3", - "@babel/generator": "^7.8.3", - "@babel/helper-function-name": "^7.8.3", - "@babel/helper-split-export-declaration": "^7.8.3", - "@babel/parser": "^7.8.3", - "@babel/types": "^7.8.3", - "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.13" - } - }, - "@babel/types": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", - "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.13", - "to-fast-properties": "^2.0.0" - } - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "@babel/helper-compilation-targets": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.8.3.tgz", - "integrity": "sha512-JLylPCsFjhLN+6uBSSh3iYdxKdeO9MNmoY96PE/99d8kyBFaXLORtAVhqN6iHa+wtPeqxKLghDOZry0+Aiw9Tw==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.8.1", - "browserslist": "^4.8.2", - "invariant": "^2.2.4", - "levenary": "^1.1.0", - "semver": "^5.5.0" - }, - "dependencies": { - "browserslist": { - "version": "4.8.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.8.5.tgz", - "integrity": "sha512-4LMHuicxkabIB+n9874jZX/az1IaZ5a+EUuvD7KFOu9x/Bd5YHyO0DIz2ls/Kl8g0ItS4X/ilEgf4T1Br0lgSg==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30001022", - "electron-to-chromium": "^1.3.338", - "node-releases": "^1.1.46" - } - }, - "caniuse-lite": { - "version": "1.0.30001022", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001022.tgz", - "integrity": "sha512-FjwPPtt/I07KyLPkBQ0g7/XuZg6oUkYBVnPHNj3VHJbOjmmJ/GdSo/GUY6MwINEQvjhP6WZVbX8Tvms8xh0D5A==", - "dev": true - }, - "electron-to-chromium": { - "version": "1.3.340", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.340.tgz", - "integrity": "sha512-hRFBAglhcj5iVYH+o8QU0+XId1WGoc0VGowJB1cuJAt3exHGrivZvWeAO5BRgBZqwZtwxjm8a5MQeGoT/Su3ww==", - "dev": true - } - } - }, - "@babel/helper-create-regexp-features-plugin": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.8.3.tgz", - "integrity": "sha512-Gcsm1OHCUr9o9TcJln57xhWHtdXbA2pgQ58S0Lxlks0WMGNXuki4+GLfX0p+L2ZkINUGZvfkz8rzoqJQSthI+Q==", - "dev": true, - "requires": { - "@babel/helper-regex": "^7.8.3", - "regexpu-core": "^4.6.0" - }, - "dependencies": { - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", - "dev": true - }, - "regexpu-core": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.6.0.tgz", - "integrity": "sha512-YlVaefl8P5BnFYOITTNzDvan1ulLOiXJzCNZxduTIosN17b87h3bvG9yHMoHaRuo88H4mQ06Aodj5VtYGGGiTg==", - "dev": true, - "requires": { - "regenerate": "^1.4.0", - "regenerate-unicode-properties": "^8.1.0", - "regjsgen": "^0.5.0", - "regjsparser": "^0.6.0", - "unicode-match-property-ecmascript": "^1.0.4", - "unicode-match-property-value-ecmascript": "^1.1.0" - } - }, - "regjsgen": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.1.tgz", - "integrity": "sha512-5qxzGZjDs9w4tzT3TPhCJqWdCc3RLYwy9J2NB0nm5Lz+S273lvWcpjaTGHsT1dc6Hhfq41uSEOw8wBmxrKOuyg==", - "dev": true - }, - "regjsparser": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.2.tgz", - "integrity": "sha512-E9ghzUtoLwDekPT0DYCp+c4h+bvuUpe6rRHCTYn6eGoqj1LgKXxT6I0Il4WbjhQkOghzi/V+y03bPKvbllL93Q==", - "dev": true, - "requires": { - "jsesc": "~0.5.0" - } - } - } - }, - "@babel/helper-define-map": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.8.3.tgz", - "integrity": "sha512-PoeBYtxoZGtct3md6xZOCWPcKuMuk3IHhgxsRRNtnNShebf4C8YonTSblsK4tvDbm+eJAw2HAPOfCr+Q/YRG/g==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.8.3", - "@babel/types": "^7.8.3", - "lodash": "^4.17.13" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", - "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", - "dev": true, - "requires": { - "@babel/highlight": "^7.8.3" - } - }, - "@babel/helper-function-name": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz", - "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "^7.8.3", - "@babel/template": "^7.8.3", - "@babel/types": "^7.8.3" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz", - "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==", - "dev": true, - "requires": { - "@babel/types": "^7.8.3" - } - }, - "@babel/highlight": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", - "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", - "dev": true, - "requires": { - "chalk": "^2.0.0", - "esutils": "^2.0.2", - "js-tokens": "^4.0.0" - } - }, - "@babel/parser": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.3.tgz", - "integrity": "sha512-/V72F4Yp/qmHaTALizEm9Gf2eQHV3QyTL3K0cNfijwnMnb1L+LDlAubb/ZnSdGAVzVSWakujHYs1I26x66sMeQ==", - "dev": true - }, - "@babel/template": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz", - "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.8.3", - "@babel/parser": "^7.8.3", - "@babel/types": "^7.8.3" - } - }, - "@babel/types": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", - "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.13", - "to-fast-properties": "^2.0.0" - } - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "@babel/helper-explode-assignable-expression": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.8.3.tgz", - "integrity": "sha512-N+8eW86/Kj147bO9G2uclsg5pwfs/fqqY5rwgIL7eTBklgXjcOJ3btzS5iM6AitJcftnY7pm2lGsrJVYLGjzIw==", - "dev": true, - "requires": { - "@babel/traverse": "^7.8.3", - "@babel/types": "^7.8.3" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", - "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", - "dev": true, - "requires": { - "@babel/highlight": "^7.8.3" - } - }, - "@babel/generator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.8.3.tgz", - "integrity": "sha512-WjoPk8hRpDRqqzRpvaR8/gDUPkrnOOeuT2m8cNICJtZH6mwaCo3v0OKMI7Y6SM1pBtyijnLtAL0HDi41pf41ug==", - "dev": true, - "requires": { - "@babel/types": "^7.8.3", - "jsesc": "^2.5.1", - "lodash": "^4.17.13", - "source-map": "^0.5.0" - } - }, - "@babel/helper-function-name": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz", - "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "^7.8.3", - "@babel/template": "^7.8.3", - "@babel/types": "^7.8.3" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz", - "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==", - "dev": true, - "requires": { - "@babel/types": "^7.8.3" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz", - "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==", - "dev": true, - "requires": { - "@babel/types": "^7.8.3" - } - }, - "@babel/highlight": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", - "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", - "dev": true, - "requires": { - "chalk": "^2.0.0", - "esutils": "^2.0.2", - "js-tokens": "^4.0.0" - } - }, - "@babel/parser": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.3.tgz", - "integrity": "sha512-/V72F4Yp/qmHaTALizEm9Gf2eQHV3QyTL3K0cNfijwnMnb1L+LDlAubb/ZnSdGAVzVSWakujHYs1I26x66sMeQ==", - "dev": true - }, - "@babel/template": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz", - "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.8.3", - "@babel/parser": "^7.8.3", - "@babel/types": "^7.8.3" - } - }, - "@babel/traverse": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.8.3.tgz", - "integrity": "sha512-we+a2lti+eEImHmEXp7bM9cTxGzxPmBiVJlLVD+FuuQMeeO7RaDbutbgeheDkw+Xe3mCfJHnGOWLswT74m2IPg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.8.3", - "@babel/generator": "^7.8.3", - "@babel/helper-function-name": "^7.8.3", - "@babel/helper-split-export-declaration": "^7.8.3", - "@babel/parser": "^7.8.3", - "@babel/types": "^7.8.3", - "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.13" - } - }, - "@babel/types": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", - "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.13", - "to-fast-properties": "^2.0.0" - } - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "@babel/helper-function-name": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz", - "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "^7.8.3", - "@babel/template": "^7.8.3", - "@babel/types": "^7.8.3" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz", - "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==", - "dev": true, - "requires": { - "@babel/types": "^7.8.3" - } - }, - "@babel/helper-hoist-variables": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.8.3.tgz", - "integrity": "sha512-ky1JLOjcDUtSc+xkt0xhYff7Z6ILTAHKmZLHPxAhOP0Nd77O+3nCsd6uSVYur6nJnCI029CrNbYlc0LoPfAPQg==", - "dev": true, - "requires": { - "@babel/types": "^7.8.3" - }, - "dependencies": { - "@babel/types": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", - "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.13", - "to-fast-properties": "^2.0.0" - } - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "@babel/helper-member-expression-to-functions": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.8.3.tgz", - "integrity": "sha512-fO4Egq88utkQFjbPrSHGmGLFqmrshs11d46WI+WZDESt7Wu7wN2G2Iu+NMMZJFDOVRHAMIkB5SNh30NtwCA7RA==", - "dev": true, - "requires": { - "@babel/types": "^7.8.3" - }, - "dependencies": { - "@babel/types": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", - "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.13", - "to-fast-properties": "^2.0.0" - } - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "@babel/helper-module-imports": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.8.3.tgz", - "integrity": "sha512-R0Bx3jippsbAEtzkpZ/6FIiuzOURPcMjHp+Z6xPe6DtApDJx+w7UYyOLanZqO8+wKR9G10s/FmHXvxaMd9s6Kg==", - "dev": true, - "requires": { - "@babel/types": "^7.8.3" - }, - "dependencies": { - "@babel/types": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", - "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.13", - "to-fast-properties": "^2.0.0" - } - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "@babel/helper-module-transforms": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.8.3.tgz", - "integrity": "sha512-C7NG6B7vfBa/pwCOshpMbOYUmrYQDfCpVL/JCRu0ek8B5p8kue1+BCXpg2vOYs7w5ACB9GTOBYQ5U6NwrMg+3Q==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.8.3", - "@babel/helper-simple-access": "^7.8.3", - "@babel/helper-split-export-declaration": "^7.8.3", - "@babel/template": "^7.8.3", - "@babel/types": "^7.8.3", - "lodash": "^4.17.13" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", - "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", - "dev": true, - "requires": { - "@babel/highlight": "^7.8.3" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz", - "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==", - "dev": true, - "requires": { - "@babel/types": "^7.8.3" - } - }, - "@babel/highlight": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", - "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", - "dev": true, - "requires": { - "chalk": "^2.0.0", - "esutils": "^2.0.2", - "js-tokens": "^4.0.0" - } - }, - "@babel/parser": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.3.tgz", - "integrity": "sha512-/V72F4Yp/qmHaTALizEm9Gf2eQHV3QyTL3K0cNfijwnMnb1L+LDlAubb/ZnSdGAVzVSWakujHYs1I26x66sMeQ==", - "dev": true - }, - "@babel/template": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz", - "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.8.3", - "@babel/parser": "^7.8.3", - "@babel/types": "^7.8.3" - } - }, - "@babel/types": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", - "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.13", - "to-fast-properties": "^2.0.0" - } - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "@babel/helper-optimise-call-expression": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.8.3.tgz", - "integrity": "sha512-Kag20n86cbO2AvHca6EJsvqAd82gc6VMGule4HwebwMlwkpXuVqrNRj6CkCV2sKxgi9MyAUnZVnZ6lJ1/vKhHQ==", - "dev": true, - "requires": { - "@babel/types": "^7.8.3" - }, - "dependencies": { - "@babel/types": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", - "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.13", - "to-fast-properties": "^2.0.0" - } - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "@babel/helper-plugin-utils": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", - "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", - "dev": true - }, - "@babel/helper-regex": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.8.3.tgz", - "integrity": "sha512-BWt0QtYv/cg/NecOAZMdcn/waj/5P26DR4mVLXfFtDokSR6fyuG0Pj+e2FqtSME+MqED1khnSMulkmGl8qWiUQ==", - "dev": true, - "requires": { - "lodash": "^4.17.13" - }, - "dependencies": { - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - } - } - }, - "@babel/helper-remap-async-to-generator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.8.3.tgz", - "integrity": "sha512-kgwDmw4fCg7AVgS4DukQR/roGp+jP+XluJE5hsRZwxCYGg+Rv9wSGErDWhlI90FODdYfd4xG4AQRiMDjjN0GzA==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.8.3", - "@babel/helper-wrap-function": "^7.8.3", - "@babel/template": "^7.8.3", - "@babel/traverse": "^7.8.3", - "@babel/types": "^7.8.3" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", - "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", - "dev": true, - "requires": { - "@babel/highlight": "^7.8.3" - } - }, - "@babel/generator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.8.3.tgz", - "integrity": "sha512-WjoPk8hRpDRqqzRpvaR8/gDUPkrnOOeuT2m8cNICJtZH6mwaCo3v0OKMI7Y6SM1pBtyijnLtAL0HDi41pf41ug==", - "dev": true, - "requires": { - "@babel/types": "^7.8.3", - "jsesc": "^2.5.1", - "lodash": "^4.17.13", - "source-map": "^0.5.0" - } - }, - "@babel/helper-function-name": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz", - "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "^7.8.3", - "@babel/template": "^7.8.3", - "@babel/types": "^7.8.3" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz", - "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==", - "dev": true, - "requires": { - "@babel/types": "^7.8.3" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz", - "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==", - "dev": true, - "requires": { - "@babel/types": "^7.8.3" - } - }, - "@babel/highlight": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", - "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", - "dev": true, - "requires": { - "chalk": "^2.0.0", - "esutils": "^2.0.2", - "js-tokens": "^4.0.0" - } - }, - "@babel/parser": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.3.tgz", - "integrity": "sha512-/V72F4Yp/qmHaTALizEm9Gf2eQHV3QyTL3K0cNfijwnMnb1L+LDlAubb/ZnSdGAVzVSWakujHYs1I26x66sMeQ==", - "dev": true - }, - "@babel/template": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz", - "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.8.3", - "@babel/parser": "^7.8.3", - "@babel/types": "^7.8.3" - } - }, - "@babel/traverse": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.8.3.tgz", - "integrity": "sha512-we+a2lti+eEImHmEXp7bM9cTxGzxPmBiVJlLVD+FuuQMeeO7RaDbutbgeheDkw+Xe3mCfJHnGOWLswT74m2IPg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.8.3", - "@babel/generator": "^7.8.3", - "@babel/helper-function-name": "^7.8.3", - "@babel/helper-split-export-declaration": "^7.8.3", - "@babel/parser": "^7.8.3", - "@babel/types": "^7.8.3", - "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.13" - } - }, - "@babel/types": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", - "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.13", - "to-fast-properties": "^2.0.0" - } - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "@babel/helper-replace-supers": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.8.3.tgz", - "integrity": "sha512-xOUssL6ho41U81etpLoT2RTdvdus4VfHamCuAm4AHxGr+0it5fnwoVdwUJ7GFEqCsQYzJUhcbsN9wB9apcYKFA==", - "dev": true, - "requires": { - "@babel/helper-member-expression-to-functions": "^7.8.3", - "@babel/helper-optimise-call-expression": "^7.8.3", - "@babel/traverse": "^7.8.3", - "@babel/types": "^7.8.3" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", - "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", - "dev": true, - "requires": { - "@babel/highlight": "^7.8.3" - } - }, - "@babel/generator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.8.3.tgz", - "integrity": "sha512-WjoPk8hRpDRqqzRpvaR8/gDUPkrnOOeuT2m8cNICJtZH6mwaCo3v0OKMI7Y6SM1pBtyijnLtAL0HDi41pf41ug==", - "dev": true, - "requires": { - "@babel/types": "^7.8.3", - "jsesc": "^2.5.1", - "lodash": "^4.17.13", - "source-map": "^0.5.0" - } - }, - "@babel/helper-function-name": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz", - "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "^7.8.3", - "@babel/template": "^7.8.3", - "@babel/types": "^7.8.3" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz", - "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==", - "dev": true, - "requires": { - "@babel/types": "^7.8.3" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz", - "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==", - "dev": true, - "requires": { - "@babel/types": "^7.8.3" - } - }, - "@babel/highlight": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", - "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", - "dev": true, - "requires": { - "chalk": "^2.0.0", - "esutils": "^2.0.2", - "js-tokens": "^4.0.0" - } - }, - "@babel/parser": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.3.tgz", - "integrity": "sha512-/V72F4Yp/qmHaTALizEm9Gf2eQHV3QyTL3K0cNfijwnMnb1L+LDlAubb/ZnSdGAVzVSWakujHYs1I26x66sMeQ==", - "dev": true - }, - "@babel/template": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz", - "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.8.3", - "@babel/parser": "^7.8.3", - "@babel/types": "^7.8.3" - } - }, - "@babel/traverse": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.8.3.tgz", - "integrity": "sha512-we+a2lti+eEImHmEXp7bM9cTxGzxPmBiVJlLVD+FuuQMeeO7RaDbutbgeheDkw+Xe3mCfJHnGOWLswT74m2IPg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.8.3", - "@babel/generator": "^7.8.3", - "@babel/helper-function-name": "^7.8.3", - "@babel/helper-split-export-declaration": "^7.8.3", - "@babel/parser": "^7.8.3", - "@babel/types": "^7.8.3", - "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.13" - } - }, - "@babel/types": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", - "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.13", - "to-fast-properties": "^2.0.0" - } - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "@babel/helper-simple-access": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.8.3.tgz", - "integrity": "sha512-VNGUDjx5cCWg4vvCTR8qQ7YJYZ+HBjxOgXEl7ounz+4Sn7+LMD3CFrCTEU6/qXKbA2nKg21CwhhBzO0RpRbdCw==", - "dev": true, - "requires": { - "@babel/template": "^7.8.3", - "@babel/types": "^7.8.3" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", - "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", - "dev": true, - "requires": { - "@babel/highlight": "^7.8.3" - } - }, - "@babel/highlight": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", - "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", - "dev": true, - "requires": { - "chalk": "^2.0.0", - "esutils": "^2.0.2", - "js-tokens": "^4.0.0" - } - }, - "@babel/parser": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.3.tgz", - "integrity": "sha512-/V72F4Yp/qmHaTALizEm9Gf2eQHV3QyTL3K0cNfijwnMnb1L+LDlAubb/ZnSdGAVzVSWakujHYs1I26x66sMeQ==", - "dev": true - }, - "@babel/template": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz", - "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.8.3", - "@babel/parser": "^7.8.3", - "@babel/types": "^7.8.3" - } - }, - "@babel/types": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", - "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.13", - "to-fast-properties": "^2.0.0" - } - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz", - "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==", - "dev": true, - "requires": { - "@babel/types": "^7.8.3" - } - }, - "@babel/helper-wrap-function": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.8.3.tgz", - "integrity": "sha512-LACJrbUET9cQDzb6kG7EeD7+7doC3JNvUgTEQOx2qaO1fKlzE/Bf05qs9w1oXQMmXlPO65lC3Tq9S6gZpTErEQ==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.8.3", - "@babel/template": "^7.8.3", - "@babel/traverse": "^7.8.3", - "@babel/types": "^7.8.3" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", - "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", - "dev": true, - "requires": { - "@babel/highlight": "^7.8.3" - } - }, - "@babel/generator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.8.3.tgz", - "integrity": "sha512-WjoPk8hRpDRqqzRpvaR8/gDUPkrnOOeuT2m8cNICJtZH6mwaCo3v0OKMI7Y6SM1pBtyijnLtAL0HDi41pf41ug==", - "dev": true, - "requires": { - "@babel/types": "^7.8.3", - "jsesc": "^2.5.1", - "lodash": "^4.17.13", - "source-map": "^0.5.0" - } - }, - "@babel/helper-function-name": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz", - "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "^7.8.3", - "@babel/template": "^7.8.3", - "@babel/types": "^7.8.3" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz", - "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==", - "dev": true, - "requires": { - "@babel/types": "^7.8.3" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz", - "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==", - "dev": true, - "requires": { - "@babel/types": "^7.8.3" - } - }, - "@babel/highlight": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", - "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", - "dev": true, - "requires": { - "chalk": "^2.0.0", - "esutils": "^2.0.2", - "js-tokens": "^4.0.0" - } - }, - "@babel/parser": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.3.tgz", - "integrity": "sha512-/V72F4Yp/qmHaTALizEm9Gf2eQHV3QyTL3K0cNfijwnMnb1L+LDlAubb/ZnSdGAVzVSWakujHYs1I26x66sMeQ==", - "dev": true - }, - "@babel/template": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz", - "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.8.3", - "@babel/parser": "^7.8.3", - "@babel/types": "^7.8.3" - } - }, - "@babel/traverse": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.8.3.tgz", - "integrity": "sha512-we+a2lti+eEImHmEXp7bM9cTxGzxPmBiVJlLVD+FuuQMeeO7RaDbutbgeheDkw+Xe3mCfJHnGOWLswT74m2IPg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.8.3", - "@babel/generator": "^7.8.3", - "@babel/helper-function-name": "^7.8.3", - "@babel/helper-split-export-declaration": "^7.8.3", - "@babel/parser": "^7.8.3", - "@babel/types": "^7.8.3", - "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.13" - } - }, - "@babel/types": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", - "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.13", - "to-fast-properties": "^2.0.0" - } - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "@babel/helpers": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.8.3.tgz", - "integrity": "sha512-LmU3q9Pah/XyZU89QvBgGt+BCsTPoQa+73RxAQh8fb8qkDyIfeQnmgs+hvzhTCKTzqOyk7JTkS3MS1S8Mq5yrQ==", - "dev": true, - "requires": { - "@babel/template": "^7.8.3", - "@babel/traverse": "^7.8.3", - "@babel/types": "^7.8.3" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", - "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", - "dev": true, - "requires": { - "@babel/highlight": "^7.8.3" - } - }, - "@babel/generator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.8.3.tgz", - "integrity": "sha512-WjoPk8hRpDRqqzRpvaR8/gDUPkrnOOeuT2m8cNICJtZH6mwaCo3v0OKMI7Y6SM1pBtyijnLtAL0HDi41pf41ug==", - "dev": true, - "requires": { - "@babel/types": "^7.8.3", - "jsesc": "^2.5.1", - "lodash": "^4.17.13", - "source-map": "^0.5.0" - } - }, - "@babel/helper-function-name": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz", - "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "^7.8.3", - "@babel/template": "^7.8.3", - "@babel/types": "^7.8.3" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz", - "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==", - "dev": true, - "requires": { - "@babel/types": "^7.8.3" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz", - "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==", - "dev": true, - "requires": { - "@babel/types": "^7.8.3" - } - }, - "@babel/highlight": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", - "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", - "dev": true, - "requires": { - "chalk": "^2.0.0", - "esutils": "^2.0.2", - "js-tokens": "^4.0.0" - } - }, - "@babel/parser": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.3.tgz", - "integrity": "sha512-/V72F4Yp/qmHaTALizEm9Gf2eQHV3QyTL3K0cNfijwnMnb1L+LDlAubb/ZnSdGAVzVSWakujHYs1I26x66sMeQ==", - "dev": true - }, - "@babel/template": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz", - "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.8.3", - "@babel/parser": "^7.8.3", - "@babel/types": "^7.8.3" - } - }, - "@babel/traverse": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.8.3.tgz", - "integrity": "sha512-we+a2lti+eEImHmEXp7bM9cTxGzxPmBiVJlLVD+FuuQMeeO7RaDbutbgeheDkw+Xe3mCfJHnGOWLswT74m2IPg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.8.3", - "@babel/generator": "^7.8.3", - "@babel/helper-function-name": "^7.8.3", - "@babel/helper-split-export-declaration": "^7.8.3", - "@babel/parser": "^7.8.3", - "@babel/types": "^7.8.3", - "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.13" - } - }, - "@babel/types": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", - "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.13", - "to-fast-properties": "^2.0.0" - } - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "@babel/highlight": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", - "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", - "dev": true, - "requires": { - "chalk": "^2.0.0", - "esutils": "^2.0.2", - "js-tokens": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "@babel/node": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/node/-/node-7.8.3.tgz", - "integrity": "sha512-GZpHg1gPnZTk1PvHRc4g/M5c50nHERkk3ojb5AuUTZFAjEKzDhBJcqvwWa7NrNT3W3Nf8t8Sj8JjA6rtXJ1z/g==", - "dev": true, - "requires": { - "@babel/register": "^7.8.3", - "commander": "^4.0.1", - "core-js": "^3.2.1", - "lodash": "^4.17.13", - "node-environment-flags": "^1.0.5", - "regenerator-runtime": "^0.13.3", - "resolve": "^1.13.1", - "v8flags": "^3.1.1" - }, - "dependencies": { - "commander": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.0.tgz", - "integrity": "sha512-NIQrwvv9V39FHgGFm36+U9SMQzbiHvU79k+iADraJTpmrFFfx7Ds0IvDoAdZsDrknlkRk14OYoWXb57uTh7/sw==", - "dev": true - }, - "core-js": { - "version": "3.6.4", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.4.tgz", - "integrity": "sha512-4paDGScNgZP2IXXilaffL9X7968RuvwlkK3xWtZRVqgd8SYNiVKRJvkFd1aqqEuPfN7E68ZHEp9hDj6lHj4Hyw==", - "dev": true - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - }, - "regenerator-runtime": { - "version": "0.13.3", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz", - "integrity": "sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw==", - "dev": true - }, - "resolve": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.0.tgz", - "integrity": "sha512-+hTmAldEGE80U2wJJDC1lebb5jWqvTYAfm3YZ1ckk1gBr0MnCqUKlwK1e+anaFljIl+F5tR5IoZcm4ZDA1zMQw==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } - } - } - }, - "@babel/parser": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.3.tgz", - "integrity": "sha512-/V72F4Yp/qmHaTALizEm9Gf2eQHV3QyTL3K0cNfijwnMnb1L+LDlAubb/ZnSdGAVzVSWakujHYs1I26x66sMeQ==", - "dev": true - }, - "@babel/plugin-external-helpers": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-external-helpers/-/plugin-external-helpers-7.8.3.tgz", - "integrity": "sha512-mx0WXDDiIl5DwzMtzWGRSPugXi9BxROS05GQrhLNbEamhBiicgn994ibwkyiBH+6png7bm/yA7AUsvHyCXi4Vw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.3" - } - }, - "@babel/plugin-proposal-async-generator-functions": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.8.3.tgz", - "integrity": "sha512-NZ9zLv848JsV3hs8ryEh7Uaz/0KsmPLqv0+PdkDJL1cJy0K4kOCFa8zc1E3mp+RHPQcpdfb/6GovEsW4VDrOMw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.3", - "@babel/helper-remap-async-to-generator": "^7.8.3", - "@babel/plugin-syntax-async-generators": "^7.8.0" - } - }, - "@babel/plugin-proposal-dynamic-import": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.8.3.tgz", - "integrity": "sha512-NyaBbyLFXFLT9FP+zk0kYlUlA8XtCUbehs67F0nnEg7KICgMc2mNkIeu9TYhKzyXMkrapZFwAhXLdnt4IYHy1w==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.3", - "@babel/plugin-syntax-dynamic-import": "^7.8.0" - } - }, - "@babel/plugin-proposal-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.8.3.tgz", - "integrity": "sha512-KGhQNZ3TVCQG/MjRbAUwuH+14y9q0tpxs1nWWs3pbSleRdDro9SAMMDyye8HhY1gqZ7/NqIc8SKhya0wRDgP1Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.3", - "@babel/plugin-syntax-json-strings": "^7.8.0" - } - }, - "@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-TS9MlfzXpXKt6YYomudb/KU7nQI6/xnapG6in1uZxoxDghuSMZsPb6D2fyUwNYSAp4l1iR7QtFOjkqcRYcUsfw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.3", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0" - } - }, - "@babel/plugin-proposal-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-8qvuPwU/xxUCt78HocNlv0mXXo0wdh9VT1R04WU8HGOfaOob26pF+9P5/lYjN/q7DHOX1bvX60hnhOvuQUJdbA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.3", - "@babel/plugin-syntax-object-rest-spread": "^7.8.0" - } - }, - "@babel/plugin-proposal-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-0gkX7J7E+AtAw9fcwlVQj8peP61qhdg/89D5swOkjYbkboA2CVckn3kiyum1DE0wskGb7KJJxBdyEBApDLLVdw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.0" - } - }, - "@babel/plugin-proposal-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.8.3.tgz", - "integrity": "sha512-QIoIR9abkVn+seDE3OjA08jWcs3eZ9+wJCKSRgo3WdEU2csFYgdScb+8qHB3+WXsGJD55u+5hWCISI7ejXS+kg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.0" - } - }, - "@babel/plugin-proposal-unicode-property-regex": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.8.3.tgz", - "integrity": "sha512-1/1/rEZv2XGweRwwSkLpY+s60za9OZ1hJs4YDqFHCw0kYWYwL5IFljVY1MYBL+weT1l9pokDO2uhSTLVxzoHkQ==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3" - } - }, - "@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-dynamic-import": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", - "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-top-level-await": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.8.3.tgz", - "integrity": "sha512-kwj1j9lL/6Wd0hROD3b/OZZ7MSrZLqqn9RAZ5+cYYsflQ9HZBIKCUkr3+uL1MEJ1NePiUbf98jjiMQSv0NMR9g==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.3" - } - }, - "@babel/plugin-transform-arrow-functions": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.8.3.tgz", - "integrity": "sha512-0MRF+KC8EqH4dbuITCWwPSzsyO3HIWWlm30v8BbbpOrS1B++isGxPnnuq/IZvOX5J2D/p7DQalQm+/2PnlKGxg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.3" - } - }, - "@babel/plugin-transform-async-to-generator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.8.3.tgz", - "integrity": "sha512-imt9tFLD9ogt56Dd5CI/6XgpukMwd/fLGSrix2httihVe7LOGVPhyhMh1BU5kDM7iHD08i8uUtmV2sWaBFlHVQ==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3", - "@babel/helper-remap-async-to-generator": "^7.8.3" - } - }, - "@babel/plugin-transform-block-scoped-functions": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.8.3.tgz", - "integrity": "sha512-vo4F2OewqjbB1+yaJ7k2EJFHlTP3jR634Z9Cj9itpqNjuLXvhlVxgnjsHsdRgASR8xYDrx6onw4vW5H6We0Jmg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.3" - } - }, - "@babel/plugin-transform-block-scoping": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.8.3.tgz", - "integrity": "sha512-pGnYfm7RNRgYRi7bids5bHluENHqJhrV4bCZRwc5GamaWIIs07N4rZECcmJL6ZClwjDz1GbdMZFtPs27hTB06w==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.3", - "lodash": "^4.17.13" - }, - "dependencies": { - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - } - } - }, - "@babel/plugin-transform-classes": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.8.3.tgz", - "integrity": "sha512-SjT0cwFJ+7Rbr1vQsvphAHwUHvSUPmMjMU/0P59G8U2HLFqSa082JO7zkbDNWs9kH/IUqpHI6xWNesGf8haF1w==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.8.3", - "@babel/helper-define-map": "^7.8.3", - "@babel/helper-function-name": "^7.8.3", - "@babel/helper-optimise-call-expression": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3", - "@babel/helper-replace-supers": "^7.8.3", - "@babel/helper-split-export-declaration": "^7.8.3", - "globals": "^11.1.0" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", - "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", - "dev": true, - "requires": { - "@babel/highlight": "^7.8.3" - } - }, - "@babel/helper-function-name": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz", - "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "^7.8.3", - "@babel/template": "^7.8.3", - "@babel/types": "^7.8.3" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz", - "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==", - "dev": true, - "requires": { - "@babel/types": "^7.8.3" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz", - "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==", - "dev": true, - "requires": { - "@babel/types": "^7.8.3" - } - }, - "@babel/highlight": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", - "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", - "dev": true, - "requires": { - "chalk": "^2.0.0", - "esutils": "^2.0.2", - "js-tokens": "^4.0.0" - } - }, - "@babel/parser": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.3.tgz", - "integrity": "sha512-/V72F4Yp/qmHaTALizEm9Gf2eQHV3QyTL3K0cNfijwnMnb1L+LDlAubb/ZnSdGAVzVSWakujHYs1I26x66sMeQ==", - "dev": true - }, - "@babel/template": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz", - "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.8.3", - "@babel/parser": "^7.8.3", - "@babel/types": "^7.8.3" - } - }, - "@babel/types": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", - "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.13", - "to-fast-properties": "^2.0.0" - } - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "@babel/plugin-transform-computed-properties": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.8.3.tgz", - "integrity": "sha512-O5hiIpSyOGdrQZRQ2ccwtTVkgUDBBiCuK//4RJ6UfePllUTCENOzKxfh6ulckXKc0DixTFLCfb2HVkNA7aDpzA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.3" - } - }, - "@babel/plugin-transform-destructuring": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.8.3.tgz", - "integrity": "sha512-H4X646nCkiEcHZUZaRkhE2XVsoz0J/1x3VVujnn96pSoGCtKPA99ZZA+va+gK+92Zycd6OBKCD8tDb/731bhgQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.3" - } - }, - "@babel/plugin-transform-dotall-regex": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.8.3.tgz", - "integrity": "sha512-kLs1j9Nn4MQoBYdRXH6AeaXMbEJFaFu/v1nQkvib6QzTj8MZI5OQzqmD83/2jEM1z0DLilra5aWO5YpyC0ALIw==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3" - } - }, - "@babel/plugin-transform-duplicate-keys": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.8.3.tgz", - "integrity": "sha512-s8dHiBUbcbSgipS4SMFuWGqCvyge5V2ZeAWzR6INTVC3Ltjig/Vw1G2Gztv0vU/hRG9X8IvKvYdoksnUfgXOEQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.3" - } - }, - "@babel/plugin-transform-exponentiation-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.8.3.tgz", - "integrity": "sha512-zwIpuIymb3ACcInbksHaNcR12S++0MDLKkiqXHl3AzpgdKlFNhog+z/K0+TGW+b0w5pgTq4H6IwV/WhxbGYSjQ==", - "dev": true, - "requires": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3" - } - }, - "@babel/plugin-transform-for-of": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.8.3.tgz", - "integrity": "sha512-ZjXznLNTxhpf4Q5q3x1NsngzGA38t9naWH8Gt+0qYZEJAcvPI9waSStSh56u19Ofjr7QmD0wUsQ8hw8s/p1VnA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.3" - } - }, - "@babel/plugin-transform-function-name": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.8.3.tgz", - "integrity": "sha512-rO/OnDS78Eifbjn5Py9v8y0aR+aSYhDhqAwVfsTl0ERuMZyr05L1aFSCJnbv2mmsLkit/4ReeQ9N2BgLnOcPCQ==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", - "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", - "dev": true, - "requires": { - "@babel/highlight": "^7.8.3" - } - }, - "@babel/helper-function-name": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz", - "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "^7.8.3", - "@babel/template": "^7.8.3", - "@babel/types": "^7.8.3" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz", - "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==", - "dev": true, - "requires": { - "@babel/types": "^7.8.3" - } - }, - "@babel/highlight": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", - "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", - "dev": true, - "requires": { - "chalk": "^2.0.0", - "esutils": "^2.0.2", - "js-tokens": "^4.0.0" - } - }, - "@babel/parser": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.3.tgz", - "integrity": "sha512-/V72F4Yp/qmHaTALizEm9Gf2eQHV3QyTL3K0cNfijwnMnb1L+LDlAubb/ZnSdGAVzVSWakujHYs1I26x66sMeQ==", - "dev": true - }, - "@babel/template": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz", - "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.8.3", - "@babel/parser": "^7.8.3", - "@babel/types": "^7.8.3" - } - }, - "@babel/types": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", - "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.13", - "to-fast-properties": "^2.0.0" - } - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "@babel/plugin-transform-literals": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.8.3.tgz", - "integrity": "sha512-3Tqf8JJ/qB7TeldGl+TT55+uQei9JfYaregDcEAyBZ7akutriFrt6C/wLYIer6OYhleVQvH/ntEhjE/xMmy10A==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.3" - } - }, - "@babel/plugin-transform-member-expression-literals": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.8.3.tgz", - "integrity": "sha512-3Wk2EXhnw+rP+IDkK6BdtPKsUE5IeZ6QOGrPYvw52NwBStw9V1ZVzxgK6fSKSxqUvH9eQPR3tm3cOq79HlsKYA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.3" - } - }, - "@babel/plugin-transform-modules-amd": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.8.3.tgz", - "integrity": "sha512-MadJiU3rLKclzT5kBH4yxdry96odTUwuqrZM+GllFI/VhxfPz+k9MshJM+MwhfkCdxxclSbSBbUGciBngR+kEQ==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3", - "babel-plugin-dynamic-import-node": "^2.3.0" - } - }, - "@babel/plugin-transform-modules-commonjs": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.8.3.tgz", - "integrity": "sha512-JpdMEfA15HZ/1gNuB9XEDlZM1h/gF/YOH7zaZzQu2xCFRfwc01NXBMHHSTT6hRjlXJJs5x/bfODM3LiCk94Sxg==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3", - "@babel/helper-simple-access": "^7.8.3", - "babel-plugin-dynamic-import-node": "^2.3.0" - } - }, - "@babel/plugin-transform-modules-systemjs": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.8.3.tgz", - "integrity": "sha512-8cESMCJjmArMYqa9AO5YuMEkE4ds28tMpZcGZB/jl3n0ZzlsxOAi3mC+SKypTfT8gjMupCnd3YiXCkMjj2jfOg==", - "dev": true, - "requires": { - "@babel/helper-hoist-variables": "^7.8.3", - "@babel/helper-module-transforms": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3", - "babel-plugin-dynamic-import-node": "^2.3.0" - } - }, - "@babel/plugin-transform-modules-umd": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.8.3.tgz", - "integrity": "sha512-evhTyWhbwbI3/U6dZAnx/ePoV7H6OUG+OjiJFHmhr9FPn0VShjwC2kdxqIuQ/+1P50TMrneGzMeyMTFOjKSnAw==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3" - } - }, - "@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.8.3.tgz", - "integrity": "sha512-f+tF/8UVPU86TrCb06JoPWIdDpTNSGGcAtaD9mLP0aYGA0OS0j7j7DHJR0GTFrUZPUU6loZhbsVZgTh0N+Qdnw==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.8.3" - } - }, - "@babel/plugin-transform-new-target": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.8.3.tgz", - "integrity": "sha512-QuSGysibQpyxexRyui2vca+Cmbljo8bcRckgzYV4kRIsHpVeyeC3JDO63pY+xFZ6bWOBn7pfKZTqV4o/ix9sFw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.3" - } - }, - "@babel/plugin-transform-object-super": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.8.3.tgz", - "integrity": "sha512-57FXk+gItG/GejofIyLIgBKTas4+pEU47IXKDBWFTxdPd7F80H8zybyAY7UoblVfBhBGs2EKM+bJUu2+iUYPDQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.3", - "@babel/helper-replace-supers": "^7.8.3" - } - }, - "@babel/plugin-transform-parameters": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.8.3.tgz", - "integrity": "sha512-/pqngtGb54JwMBZ6S/D3XYylQDFtGjWrnoCF4gXZOUpFV/ujbxnoNGNvDGu6doFWRPBveE72qTx/RRU44j5I/Q==", - "dev": true, - "requires": { - "@babel/helper-call-delegate": "^7.8.3", - "@babel/helper-get-function-arity": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3" - }, - "dependencies": { - "@babel/helper-get-function-arity": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz", - "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==", - "dev": true, - "requires": { - "@babel/types": "^7.8.3" - } - }, - "@babel/types": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", - "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.13", - "to-fast-properties": "^2.0.0" - } - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "@babel/plugin-transform-property-literals": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.8.3.tgz", - "integrity": "sha512-uGiiXAZMqEoQhRWMK17VospMZh5sXWg+dlh2soffpkAl96KAm+WZuJfa6lcELotSRmooLqg0MWdH6UUq85nmmg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.3" - } - }, - "@babel/plugin-transform-regenerator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.8.3.tgz", - "integrity": "sha512-qt/kcur/FxrQrzFR432FGZznkVAjiyFtCOANjkAKwCbt465L6ZCiUQh2oMYGU3Wo8LRFJxNDFwWn106S5wVUNA==", - "dev": true, - "requires": { - "regenerator-transform": "^0.14.0" - }, - "dependencies": { - "regenerator-transform": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.1.tgz", - "integrity": "sha512-flVuee02C3FKRISbxhXl9mGzdbWUVHubl1SMaknjxkFB1/iqpJhArQUvRxOOPEc/9tAiX0BaQ28FJH10E4isSQ==", - "dev": true, - "requires": { - "private": "^0.1.6" - } - } - } - }, - "@babel/plugin-transform-reserved-words": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.8.3.tgz", - "integrity": "sha512-mwMxcycN3omKFDjDQUl+8zyMsBfjRFr0Zn/64I41pmjv4NJuqcYlEtezwYtw9TFd9WR1vN5kiM+O0gMZzO6L0A==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.3" - } - }, - "@babel/plugin-transform-shorthand-properties": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.8.3.tgz", - "integrity": "sha512-I9DI6Odg0JJwxCHzbzW08ggMdCezoWcuQRz3ptdudgwaHxTjxw5HgdFJmZIkIMlRymL6YiZcped4TTCB0JcC8w==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.3" - } - }, - "@babel/plugin-transform-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.8.3.tgz", - "integrity": "sha512-CkuTU9mbmAoFOI1tklFWYYbzX5qCIZVXPVy0jpXgGwkplCndQAa58s2jr66fTeQnA64bDox0HL4U56CFYoyC7g==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.3" - } - }, - "@babel/plugin-transform-sticky-regex": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.8.3.tgz", - "integrity": "sha512-9Spq0vGCD5Bb4Z/ZXXSK5wbbLFMG085qd2vhL1JYu1WcQ5bXqZBAYRzU1d+p79GcHs2szYv5pVQCX13QgldaWw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.3", - "@babel/helper-regex": "^7.8.3" - } - }, - "@babel/plugin-transform-template-literals": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.8.3.tgz", - "integrity": "sha512-820QBtykIQOLFT8NZOcTRJ1UNuztIELe4p9DCgvj4NK+PwluSJ49we7s9FB1HIGNIYT7wFUJ0ar2QpCDj0escQ==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3" - } - }, - "@babel/plugin-transform-typeof-symbol": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.8.3.tgz", - "integrity": "sha512-3TrkKd4LPqm4jHs6nPtSDI/SV9Cm5PRJkHLUgTcqRQQTMAZ44ZaAdDZJtvWFSaRcvT0a1rTmJ5ZA5tDKjleF3g==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.3" - } - }, - "@babel/plugin-transform-unicode-regex": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.8.3.tgz", - "integrity": "sha512-+ufgJjYdmWfSQ+6NS9VGUR2ns8cjJjYbrbi11mZBTaWm+Fui/ncTLFF28Ei1okavY+xkojGr1eJxNsWYeA5aZw==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3" - } - }, - "@babel/polyfill": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/polyfill/-/polyfill-7.8.3.tgz", - "integrity": "sha512-0QEgn2zkCzqGIkSWWAEmvxD7e00Nm9asTtQvi7HdlYvMhjy/J38V/1Y9ode0zEJeIuxAI0uftiAzqc7nVeWUGg==", - "dev": true, - "requires": { - "core-js": "^2.6.5", - "regenerator-runtime": "^0.13.2" - }, - "dependencies": { - "core-js": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", - "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==", - "dev": true - }, - "regenerator-runtime": { - "version": "0.13.3", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz", - "integrity": "sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw==", - "dev": true - } - } - }, - "@babel/preset-env": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.8.3.tgz", - "integrity": "sha512-Rs4RPL2KjSLSE2mWAx5/iCH+GC1ikKdxPrhnRS6PfFVaiZeom22VFKN4X8ZthyN61kAaR05tfXTbCvatl9WIQg==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.8.0", - "@babel/helper-compilation-targets": "^7.8.3", - "@babel/helper-module-imports": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3", - "@babel/plugin-proposal-async-generator-functions": "^7.8.3", - "@babel/plugin-proposal-dynamic-import": "^7.8.3", - "@babel/plugin-proposal-json-strings": "^7.8.3", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-proposal-object-rest-spread": "^7.8.3", - "@babel/plugin-proposal-optional-catch-binding": "^7.8.3", - "@babel/plugin-proposal-optional-chaining": "^7.8.3", - "@babel/plugin-proposal-unicode-property-regex": "^7.8.3", - "@babel/plugin-syntax-async-generators": "^7.8.0", - "@babel/plugin-syntax-dynamic-import": "^7.8.0", - "@babel/plugin-syntax-json-strings": "^7.8.0", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0", - "@babel/plugin-syntax-object-rest-spread": "^7.8.0", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.0", - "@babel/plugin-syntax-optional-chaining": "^7.8.0", - "@babel/plugin-syntax-top-level-await": "^7.8.3", - "@babel/plugin-transform-arrow-functions": "^7.8.3", - "@babel/plugin-transform-async-to-generator": "^7.8.3", - "@babel/plugin-transform-block-scoped-functions": "^7.8.3", - "@babel/plugin-transform-block-scoping": "^7.8.3", - "@babel/plugin-transform-classes": "^7.8.3", - "@babel/plugin-transform-computed-properties": "^7.8.3", - "@babel/plugin-transform-destructuring": "^7.8.3", - "@babel/plugin-transform-dotall-regex": "^7.8.3", - "@babel/plugin-transform-duplicate-keys": "^7.8.3", - "@babel/plugin-transform-exponentiation-operator": "^7.8.3", - "@babel/plugin-transform-for-of": "^7.8.3", - "@babel/plugin-transform-function-name": "^7.8.3", - "@babel/plugin-transform-literals": "^7.8.3", - "@babel/plugin-transform-member-expression-literals": "^7.8.3", - "@babel/plugin-transform-modules-amd": "^7.8.3", - "@babel/plugin-transform-modules-commonjs": "^7.8.3", - "@babel/plugin-transform-modules-systemjs": "^7.8.3", - "@babel/plugin-transform-modules-umd": "^7.8.3", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.8.3", - "@babel/plugin-transform-new-target": "^7.8.3", - "@babel/plugin-transform-object-super": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.8.3", - "@babel/plugin-transform-property-literals": "^7.8.3", - "@babel/plugin-transform-regenerator": "^7.8.3", - "@babel/plugin-transform-reserved-words": "^7.8.3", - "@babel/plugin-transform-shorthand-properties": "^7.8.3", - "@babel/plugin-transform-spread": "^7.8.3", - "@babel/plugin-transform-sticky-regex": "^7.8.3", - "@babel/plugin-transform-template-literals": "^7.8.3", - "@babel/plugin-transform-typeof-symbol": "^7.8.3", - "@babel/plugin-transform-unicode-regex": "^7.8.3", - "@babel/types": "^7.8.3", - "browserslist": "^4.8.2", - "core-js-compat": "^3.6.2", - "invariant": "^2.2.2", - "levenary": "^1.1.0", - "semver": "^5.5.0" - }, - "dependencies": { - "@babel/types": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", - "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.13", - "to-fast-properties": "^2.0.0" - } - }, - "browserslist": { - "version": "4.8.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.8.5.tgz", - "integrity": "sha512-4LMHuicxkabIB+n9874jZX/az1IaZ5a+EUuvD7KFOu9x/Bd5YHyO0DIz2ls/Kl8g0ItS4X/ilEgf4T1Br0lgSg==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30001022", - "electron-to-chromium": "^1.3.338", - "node-releases": "^1.1.46" - } - }, - "caniuse-lite": { - "version": "1.0.30001022", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001022.tgz", - "integrity": "sha512-FjwPPtt/I07KyLPkBQ0g7/XuZg6oUkYBVnPHNj3VHJbOjmmJ/GdSo/GUY6MwINEQvjhP6WZVbX8Tvms8xh0D5A==", - "dev": true - }, - "electron-to-chromium": { - "version": "1.3.340", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.340.tgz", - "integrity": "sha512-hRFBAglhcj5iVYH+o8QU0+XId1WGoc0VGowJB1cuJAt3exHGrivZvWeAO5BRgBZqwZtwxjm8a5MQeGoT/Su3ww==", - "dev": true - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "@babel/register": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.8.3.tgz", - "integrity": "sha512-t7UqebaWwo9nXWClIPLPloa5pN33A2leVs8Hf0e9g9YwUP8/H9NeR7DJU+4CXo23QtjChQv5a3DjEtT83ih1rg==", - "dev": true, - "requires": { - "find-cache-dir": "^2.0.0", - "lodash": "^4.17.13", - "make-dir": "^2.1.0", - "pirates": "^4.0.0", - "source-map-support": "^0.5.16" - }, - "dependencies": { - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "source-map-support": { - "version": "0.5.16", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.16.tgz", - "integrity": "sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - } - } - }, - "@babel/runtime": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.8.3.tgz", - "integrity": "sha512-fVHx1rzEmwB130VTkLnxR+HmxcTjGzH12LYQcFFoBwakMd3aOMD4OsRN7tGG/UOYE2ektgFrS8uACAoRk1CY0w==", - "dev": true, - "requires": { - "regenerator-runtime": "^0.13.2" - }, - "dependencies": { - "regenerator-runtime": { - "version": "0.13.3", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz", - "integrity": "sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw==", - "dev": true - } - } - }, - "@babel/template": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz", - "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.8.3", - "@babel/parser": "^7.8.3", - "@babel/types": "^7.8.3" - } - }, - "@babel/traverse": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.8.3.tgz", - "integrity": "sha512-we+a2lti+eEImHmEXp7bM9cTxGzxPmBiVJlLVD+FuuQMeeO7RaDbutbgeheDkw+Xe3mCfJHnGOWLswT74m2IPg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.8.3", - "@babel/generator": "^7.8.3", - "@babel/helper-function-name": "^7.8.3", - "@babel/helper-split-export-declaration": "^7.8.3", - "@babel/parser": "^7.8.3", - "@babel/types": "^7.8.3", - "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.13" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, - "@babel/types": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", - "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.13", - "to-fast-properties": "^2.0.0" - }, - "dependencies": { - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "@glimmer/interfaces": { - "version": "0.41.4", - "resolved": "https://registry.npmjs.org/@glimmer/interfaces/-/interfaces-0.41.4.tgz", - "integrity": "sha512-MzXwMyod3MlwSZezHSaVBsCEIW/giYYfTDYARR46QnYsaFVatMVbydjsI7jkAuBCbnLCyNOIc1TrYIj71i/rpg==", - "dev": true - }, - "@glimmer/syntax": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@glimmer/syntax/-/syntax-0.41.0.tgz", - "integrity": "sha512-sYmgUMdK0jX+3ZNX9C2TKvL1YZGsKIcXRicwnzoTC7F56z29CbSCc7o6Zf0CI4L2Q7FSnHDxldlSe48wBAr6vQ==", - "dev": true, - "requires": { - "@glimmer/interfaces": "^0.41.0", - "@glimmer/util": "^0.41.0", - "handlebars": "^4.0.13", - "simple-html-tokenizer": "^0.5.7" - } - }, - "@glimmer/util": { - "version": "0.41.4", - "resolved": "https://registry.npmjs.org/@glimmer/util/-/util-0.41.4.tgz", - "integrity": "sha512-DwS94K+M0vtG+cymxH0rslJr09qpdjyOLdCjmpKcG/nNiZQfMA1ybAaFEmwk9UaVlUG9STENFeQwyrLevJB+7g==", - "dev": true - }, - "@iarna/toml": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.3.tgz", - "integrity": "sha512-FmuxfCuolpLl0AnQ2NHSzoUKWEJDFl63qXjzdoWBVyFCXzMGm1spBzk7LeHNoVCiWCF7mRVms9e6jEV9+MoPbg==", - "dev": true - }, - "@istanbuljs/load-nyc-config": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.0.0.tgz", - "integrity": "sha512-ZR0rq/f/E4f4XcgnDvtMWXCUJpi8eO0rssVhmztsZqLIEFA9UUP9zmpE0VxlM+kv/E1ul2I876Fwil2ayptDVg==", - "dev": true, - "requires": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, - "dependencies": { - "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true - } - } - }, - "@istanbuljs/schema": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.2.tgz", - "integrity": "sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==", - "dev": true - }, - "@js-data/repo-tools": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@js-data/repo-tools/-/repo-tools-1.0.1.tgz", - "integrity": "sha512-R9f1f+Hd8W68eOTw16yTQLfxDBiO3isSaG+/pz+cY4qPnhvl18aORM/U8+ggk+kFYUdiOce4o6pqePiuo5eXqA==", - "dev": true, - "requires": { - "babel-eslint": "^7.2.3", - "lodash": "^4.17.15", - "npm-check-updates": "^4.0.1", - "standard": "^8.6.0" - }, - "dependencies": { - "acorn-jsx": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", - "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", - "dev": true, - "requires": { - "acorn": "^3.0.4" - }, - "dependencies": { - "acorn": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", - "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", - "dev": true - } - } - }, - "ajv": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", - "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", - "dev": true, - "requires": { - "co": "^4.6.0", - "json-stable-stringify": "^1.0.1" - } - }, - "ansi-align": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz", - "integrity": "sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw==", - "dev": true, - "requires": { - "string-width": "^3.0.0" - } - }, - "ansi-escapes": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", - "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", - "dev": true - }, - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "dev": true, - "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - } - }, - "babel-eslint": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-7.2.3.tgz", - "integrity": "sha1-sv4tgBJkcPXBlELcdXJTqJdxCCc=", - "dev": true, - "requires": { - "babel-code-frame": "^6.22.0", - "babel-traverse": "^6.23.1", - "babel-types": "^6.23.0", - "babylon": "^6.17.0" - } - }, - "boxen": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-3.2.0.tgz", - "integrity": "sha512-cU4J/+NodM3IHdSL2yN8bqYqnmlBTidDR4RC7nJs61ZmtGz8VZzM3HLQX0zY5mrSmPtR3xWwsq2jOUQqFZN8+A==", - "dev": true, - "requires": { - "ansi-align": "^3.0.0", - "camelcase": "^5.3.1", - "chalk": "^2.4.2", - "cli-boxes": "^2.2.0", - "string-width": "^3.0.0", - "term-size": "^1.2.0", - "type-fest": "^0.3.0", - "widest-line": "^2.0.0" + "bindings": "^1.5.0", + "nan": "^2.12.1", + "node-pre-gyp": "*" }, "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "abbrev": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.1.3", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "debug": { + "version": "3.2.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "^2.1.1" + } + }, + "deep-extend": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.7", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.6.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "glob": { + "version": "7.1.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.24", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore-walk": { + "version": "3.0.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "bundled": true, + "dev": true, + "optional": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true, + "optional": true + }, + "minipass": { + "version": "2.9.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.3.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.9.0" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "needle": { + "version": "2.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "^3.2.6", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.14.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4.4.2" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npm-normalize-package-bin": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "npm-packlist": { + "version": "1.4.7", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, "dev": true, + "optional": true, "requires": { - "color-convert": "^1.9.0" + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" } }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "number-is-nan": { + "version": "1.0.1", + "bundled": true, "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "once": { + "version": "1.4.0", + "bundled": true, "dev": true, + "optional": true, "requires": { - "color-name": "1.1.3" + "wrappy": "1" } }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "osenv": { + "version": "0.1.5", + "bundled": true, "dev": true, + "optional": true, "requires": { - "has-flag": "^3.0.0" + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" } - } - } - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", - "dev": true - }, - "cli-boxes": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.0.tgz", - "integrity": "sha512-gpaBrMAizVEANOpfZp/EEUixTXDyGt7DFzdK5hU+UbWt/J0lB0w20ncZj59Z9a93xHb9u12zF5BS6i9RKbtg4w==", - "dev": true - }, - "cli-cursor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", - "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", - "dev": true, - "requires": { - "restore-cursor": "^1.0.1" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "commander": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.0.tgz", - "integrity": "sha512-NIQrwvv9V39FHgGFm36+U9SMQzbiHvU79k+iADraJTpmrFFfx7Ds0IvDoAdZsDrknlkRk14OYoWXb57uTh7/sw==", - "dev": true - }, - "configstore": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/configstore/-/configstore-4.0.0.tgz", - "integrity": "sha512-CmquAXFBocrzaSM8mtGPMM/HiWmyIpr4CcJl/rgY2uCObZ/S7cKU0silxslqJejl+t/T9HS8E0PUNQD81JGUEQ==", - "dev": true, - "requires": { - "dot-prop": "^4.1.0", - "graceful-fs": "^4.1.2", - "make-dir": "^1.0.0", - "unique-string": "^1.0.0", - "write-file-atomic": "^2.0.0", - "xdg-basedir": "^3.0.0" - } - }, - "doctrine": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", - "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "isarray": "^1.0.0" - } - }, - "dot-prop": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", - "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", - "dev": true, - "requires": { - "is-obj": "^1.0.0" - } - }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "eslint": { - "version": "3.10.2", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-3.10.2.tgz", - "integrity": "sha1-yaEOi/bp1lZRIEd4xQM0Hx6sPOc=", - "dev": true, - "requires": { - "babel-code-frame": "^6.16.0", - "chalk": "^1.1.3", - "concat-stream": "^1.4.6", - "debug": "^2.1.1", - "doctrine": "^1.2.2", - "escope": "^3.6.0", - "espree": "^3.3.1", - "estraverse": "^4.2.0", - "esutils": "^2.0.2", - "file-entry-cache": "^2.0.0", - "glob": "^7.0.3", - "globals": "^9.2.0", - "ignore": "^3.2.0", - "imurmurhash": "^0.1.4", - "inquirer": "^0.12.0", - "is-my-json-valid": "^2.10.0", - "is-resolvable": "^1.0.0", - "js-yaml": "^3.5.1", - "json-stable-stringify": "^1.0.0", - "levn": "^0.3.0", - "lodash": "^4.0.0", - "mkdirp": "^0.5.0", - "natural-compare": "^1.4.0", - "optionator": "^0.8.2", - "path-is-inside": "^1.0.1", - "pluralize": "^1.2.1", - "progress": "^1.1.8", - "require-uncached": "^1.0.2", - "shelljs": "^0.7.5", - "strip-bom": "^3.0.0", - "strip-json-comments": "~1.0.1", - "table": "^3.7.8", - "text-table": "~0.2.0", - "user-home": "^2.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "process-nextick-args": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.8", + "bundled": true, "dev": true, + "optional": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } } }, - "progress": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", - "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", - "dev": true + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "rimraf": { + "version": "2.7.1", + "bundled": true, "dev": true, + "optional": true, "requires": { - "ansi-regex": "^2.0.0" + "glob": "^7.1.3" } }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "eslint-config-standard": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-6.2.1.tgz", - "integrity": "sha1-06aKr8cZFjnn7kQec0hzkCY1QpI=", - "dev": true - }, - "eslint-plugin-promise": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-3.4.2.tgz", - "integrity": "sha1-G+J5Pq/i0YtbEjuBNsJp+AT+cSI=", - "dev": true - }, - "eslint-plugin-standard": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-2.0.1.tgz", - "integrity": "sha1-NYlpn/nJF/LCX3apFmh/ZBw2n/M=", - "dev": true - }, - "espree": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", - "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", - "dev": true, - "requires": { - "acorn": "^5.5.0", - "acorn-jsx": "^3.0.0" - } - }, - "figures": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", - "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5", - "object-assign": "^4.1.0" - } - }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "get-stdin": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-7.0.0.tgz", - "integrity": "sha512-zRKcywvrXlXsA0v0i9Io4KDRaAw7+a1ZpjRwl9Wox8PFlVCCHra7E9c4kqXCoCM9nR5tBkaTTZRBoCm60bFqTQ==", - "dev": true - }, - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "got": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", - "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", - "dev": true, - "requires": { - "@sindresorhus/is": "^0.14.0", - "@szmarczak/http-timer": "^1.1.2", - "cacheable-request": "^6.0.0", - "decompress-response": "^3.3.0", - "duplexer3": "^0.1.4", - "get-stream": "^4.1.0", - "lowercase-keys": "^1.0.1", - "mimic-response": "^1.0.1", - "p-cancelable": "^1.0.0", - "to-readable-stream": "^1.0.0", - "url-parse-lax": "^3.0.0" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "ignore": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", - "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", - "dev": true - }, - "inquirer": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz", - "integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=", - "dev": true, - "requires": { - "ansi-escapes": "^1.1.0", - "ansi-regex": "^2.0.0", - "chalk": "^1.0.0", - "cli-cursor": "^1.0.1", - "cli-width": "^2.0.0", - "figures": "^1.3.5", - "lodash": "^4.3.0", - "readline2": "^1.0.1", - "run-async": "^0.1.0", - "rx-lite": "^3.1.2", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.0", - "through": "^2.3.6" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true + "safe-buffer": { + "version": "5.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "dev": true, + "optional": true }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true + "semver": { + "version": "5.7.1", + "bundled": true, + "dev": true, + "optional": true }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "set-blocking": { + "version": "2.0.0", + "bundled": true, "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } + "optional": true }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "signal-exit": { + "version": "3.0.2", + "bundled": true, "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } + "optional": true }, "string-width": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", "strip-ansi": "^3.0.0" } }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, "strip-ansi": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "bundled": true, "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "4.4.13", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.8.6", + "minizlib": "^1.2.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.3" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "wide-align": { + "version": "1.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "yallist": { + "version": "3.1.1", + "bundled": true, + "dev": true, + "optional": true } } }, - "is-ci": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", - "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", - "dev": true, - "requires": { - "ci-info": "^2.0.0" - } - }, - "is-npm": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-3.0.0.tgz", - "integrity": "sha512-wsigDr1Kkschp2opC4G3yA6r9EgVA6NjRpWzIi9axXqeIaAATPRJc4uLujXe3Nd9uO8KoDyA4MD6aZSeXTADhA==", - "dev": true - }, - "latest-version": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", - "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", "dev": true, + "optional": true, "requires": { - "package-json": "^6.3.0" + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "optional": true, + "requires": { + "is-extglob": "^2.1.0" + } + } } }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", "dev": true, + "optional": true, "requires": { - "p-locate": "^4.1.0" + "binary-extensions": "^1.0.0" } }, - "make-dir": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", - "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", "dev": true, - "requires": { - "pify": "^3.0.0" - } + "optional": true }, - "npm-check-updates": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-check-updates/-/npm-check-updates-4.0.1.tgz", - "integrity": "sha512-rDrKAqhQuTYq2EkndroPMZGA9N6tpTotOVOIJoxRa3ZKnb/mOcq2TZv4A4LLSM8+9kZlP+sBwE+XAGh8wWZw/w==", + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", "dev": true, + "optional": true, "requires": { - "chalk": "^3.0.0", - "cint": "^8.2.1", - "cli-table": "^0.3.1", - "commander": "^4.0.1", - "fast-diff": "^1.2.0", - "find-up": "4.1.0", - "get-stdin": "^7.0.0", - "json-parse-helpfulerror": "^1.0.3", - "libnpmconfig": "^1.2.1", - "lodash": "^4.17.15", - "node-alias": "^1.0.4", - "pacote": "^10.2.0", - "progress": "^2.0.3", - "prompts": "^2.3.0", - "rc-config-loader": "^3.0.0", - "requireg": "^0.2.2", - "semver": "^6.3.0", - "semver-utils": "^1.1.4", - "spawn-please": "^0.3.0", - "update-notifier": "^3.0.1" + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "optional": true, + "requires": { + "is-buffer": "^1.1.5" + } + } } }, - "onetime": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", - "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", - "dev": true - }, - "p-limit": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz", - "integrity": "sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==", + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", "dev": true, "requires": { - "p-try": "^2.0.0" + "pify": "^4.0.1", + "semver": "^5.6.0" } }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", "dev": true, + "optional": true, "requires": { - "p-limit": "^2.2.0" + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" } }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", "dev": true }, - "package-json": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", - "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", "dev": true, + "optional": true, "requires": { - "got": "^9.6.0", - "registry-auth-token": "^4.0.0", - "registry-url": "^5.0.0", - "semver": "^6.2.0" + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" } }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - }, - "pluralize": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-1.2.1.tgz", - "integrity": "sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU=", + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true }, - "prepend-http": { + "slash": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", - "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", - "dev": true - }, - "progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", "dev": true }, - "registry-auth-token": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.1.1.tgz", - "integrity": "sha512-9bKS7nTl9+/A1s7tnPeGrUpRcVY+LUh7bfFgzpndALdPfXQBfQV77rQVtqgUV3ti4vc/Ik81Ex8UJDWDQ12zQA==", - "dev": true, - "requires": { - "rc": "^1.2.8" - } - }, - "registry-url": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", - "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", - "dev": true, - "requires": { - "rc": "^1.2.8" - } - }, - "restore-cursor": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", - "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", "dev": true, + "optional": true, "requires": { - "exit-hook": "^1.0.0", - "onetime": "^1.0.0" + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" } - }, - "run-async": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz", - "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=", + } + } + }, + "@babel/code-frame": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", + "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", + "dev": true, + "requires": { + "@babel/highlight": "^7.8.3" + } + }, + "@babel/compat-data": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.8.5.tgz", + "integrity": "sha512-jWYUqQX/ObOhG1UiEkbH5SANsE/8oKXiQWjj7p7xgj9Zmnt//aUvyz4dBkK0HNsS8/cbyC5NmmH87VekW+mXFg==", + "dev": true, + "requires": { + "browserslist": "^4.8.5", + "invariant": "^2.2.4", + "semver": "^5.5.0" + } + }, + "@babel/core": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.8.4.tgz", + "integrity": "sha512-0LiLrB2PwrVI+a2/IEskBopDYSd8BCb3rOvH7D5tzoWd696TBEduBvuLVm4Nx6rltrLZqvI3MCalB2K2aVzQjA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/generator": "^7.8.4", + "@babel/helpers": "^7.8.4", + "@babel/parser": "^7.8.4", + "@babel/template": "^7.8.3", + "@babel/traverse": "^7.8.4", + "@babel/types": "^7.8.3", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.0", + "lodash": "^4.17.13", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "dependencies": { + "@babel/generator": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.8.4.tgz", + "integrity": "sha512-PwhclGdRpNAf3IxZb0YVuITPZmmrXz9zf6fH8lT4XbrmfQKr6ryBzhv593P5C6poJRciFCL/eHGW2NuGrgEyxA==", "dev": true, "requires": { - "once": "^1.3.0" + "@babel/types": "^7.8.3", + "jsesc": "^2.5.1", + "lodash": "^4.17.13", + "source-map": "^0.5.0" } }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - }, - "slice-ansi": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", - "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", - "dev": true - }, - "spawn-please": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/spawn-please/-/spawn-please-0.3.0.tgz", - "integrity": "sha1-2zOOxM/2Orxp8dDgjO6euL69nRE=", + "@babel/parser": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.4.tgz", + "integrity": "sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw==", "dev": true }, - "standard": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/standard/-/standard-8.6.0.tgz", - "integrity": "sha1-Y1Eyvnv7VnwpIQBfMPnjUOR1Kq0=", + "@babel/traverse": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.8.4.tgz", + "integrity": "sha512-NGLJPZwnVEyBPLI+bl9y9aSnxMhsKz42so7ApAv9D+b4vAFPpY013FTS9LdKxcABoIYFU52HcYga1pPlx454mg==", "dev": true, "requires": { - "eslint": "~3.10.2", - "eslint-config-standard": "6.2.1", - "eslint-config-standard-jsx": "3.2.0", - "eslint-plugin-promise": "~3.4.0", - "eslint-plugin-react": "~6.7.1", - "eslint-plugin-standard": "~2.0.1", - "standard-engine": "~5.2.0" + "@babel/code-frame": "^7.8.3", + "@babel/generator": "^7.8.4", + "@babel/helper-function-name": "^7.8.3", + "@babel/helper-split-export-declaration": "^7.8.3", + "@babel/parser": "^7.8.4", + "@babel/types": "^7.8.3", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.13" } }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" + "ms": "^2.1.1" } }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "@babel/generator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.8.3.tgz", + "integrity": "sha512-WjoPk8hRpDRqqzRpvaR8/gDUPkrnOOeuT2m8cNICJtZH6mwaCo3v0OKMI7Y6SM1pBtyijnLtAL0HDi41pf41ug==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3", + "jsesc": "^2.5.1", + "lodash": "^4.17.13", + "source-map": "^0.5.0" + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.8.3.tgz", + "integrity": "sha512-6o+mJrZBxOoEX77Ezv9zwW7WV8DdluouRKNY/IR5u/YTMuKHgugHOzYWlYvYLpLA9nPsQCAAASpCIbjI9Mv+Uw==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.8.3.tgz", + "integrity": "sha512-5eFOm2SyFPK4Rh3XMMRDjN7lBH0orh3ss0g3rTYZnBQ+r6YPj7lgDyCvPphynHvUrobJmeMignBr6Acw9mAPlw==", + "dev": true, + "requires": { + "@babel/helper-explode-assignable-expression": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-call-delegate": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.8.3.tgz", + "integrity": "sha512-6Q05px0Eb+N4/GTyKPPvnkig7Lylw+QzihMpws9iiZQv7ZImf84ZsZpQH7QoWN4n4tm81SnSzPgHw2qtO0Zf3A==", + "dev": true, + "requires": { + "@babel/helper-hoist-variables": "^7.8.3", + "@babel/traverse": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-compilation-targets": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.8.4.tgz", + "integrity": "sha512-3k3BsKMvPp5bjxgMdrFyq0UaEO48HciVrOVF0+lon8pp95cyJ2ujAh0TrBHNMnJGT2rr0iKOJPFFbSqjDyf/Pg==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.8.4", + "browserslist": "^4.8.5", + "invariant": "^2.2.4", + "levenary": "^1.1.1", + "semver": "^5.5.0" + } + }, + "@babel/helper-create-class-features-plugin": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.8.3.tgz", + "integrity": "sha512-qmp4pD7zeTxsv0JNecSBsEmG1ei2MqwJq4YQcK3ZWm/0t07QstWfvuV/vm3Qt5xNMFETn2SZqpMx2MQzbtq+KA==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.8.3", + "@babel/helper-member-expression-to-functions": "^7.8.3", + "@babel/helper-optimise-call-expression": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-replace-supers": "^7.8.3", + "@babel/helper-split-export-declaration": "^7.8.3" + } + }, + "@babel/helper-create-regexp-features-plugin": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.8.3.tgz", + "integrity": "sha512-Gcsm1OHCUr9o9TcJln57xhWHtdXbA2pgQ58S0Lxlks0WMGNXuki4+GLfX0p+L2ZkINUGZvfkz8rzoqJQSthI+Q==", + "dev": true, + "requires": { + "@babel/helper-regex": "^7.8.3", + "regexpu-core": "^4.6.0" + } + }, + "@babel/helper-define-map": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.8.3.tgz", + "integrity": "sha512-PoeBYtxoZGtct3md6xZOCWPcKuMuk3IHhgxsRRNtnNShebf4C8YonTSblsK4tvDbm+eJAw2HAPOfCr+Q/YRG/g==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.8.3", + "@babel/types": "^7.8.3", + "lodash": "^4.17.13" + } + }, + "@babel/helper-explode-assignable-expression": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.8.3.tgz", + "integrity": "sha512-N+8eW86/Kj147bO9G2uclsg5pwfs/fqqY5rwgIL7eTBklgXjcOJ3btzS5iM6AitJcftnY7pm2lGsrJVYLGjzIw==", + "dev": true, + "requires": { + "@babel/traverse": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-function-name": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz", + "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.8.3", + "@babel/template": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz", + "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.8.3.tgz", + "integrity": "sha512-ky1JLOjcDUtSc+xkt0xhYff7Z6ILTAHKmZLHPxAhOP0Nd77O+3nCsd6uSVYur6nJnCI029CrNbYlc0LoPfAPQg==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.8.3.tgz", + "integrity": "sha512-fO4Egq88utkQFjbPrSHGmGLFqmrshs11d46WI+WZDESt7Wu7wN2G2Iu+NMMZJFDOVRHAMIkB5SNh30NtwCA7RA==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-module-imports": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.8.3.tgz", + "integrity": "sha512-R0Bx3jippsbAEtzkpZ/6FIiuzOURPcMjHp+Z6xPe6DtApDJx+w7UYyOLanZqO8+wKR9G10s/FmHXvxaMd9s6Kg==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-module-transforms": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.8.3.tgz", + "integrity": "sha512-C7NG6B7vfBa/pwCOshpMbOYUmrYQDfCpVL/JCRu0ek8B5p8kue1+BCXpg2vOYs7w5ACB9GTOBYQ5U6NwrMg+3Q==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.8.3", + "@babel/helper-simple-access": "^7.8.3", + "@babel/helper-split-export-declaration": "^7.8.3", + "@babel/template": "^7.8.3", + "@babel/types": "^7.8.3", + "lodash": "^4.17.13" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.8.3.tgz", + "integrity": "sha512-Kag20n86cbO2AvHca6EJsvqAd82gc6VMGule4HwebwMlwkpXuVqrNRj6CkCV2sKxgi9MyAUnZVnZ6lJ1/vKhHQ==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + }, + "@babel/helper-regex": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.8.3.tgz", + "integrity": "sha512-BWt0QtYv/cg/NecOAZMdcn/waj/5P26DR4mVLXfFtDokSR6fyuG0Pj+e2FqtSME+MqED1khnSMulkmGl8qWiUQ==", + "dev": true, + "requires": { + "lodash": "^4.17.13" + } + }, + "@babel/helper-remap-async-to-generator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.8.3.tgz", + "integrity": "sha512-kgwDmw4fCg7AVgS4DukQR/roGp+jP+XluJE5hsRZwxCYGg+Rv9wSGErDWhlI90FODdYfd4xG4AQRiMDjjN0GzA==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.8.3", + "@babel/helper-wrap-function": "^7.8.3", + "@babel/template": "^7.8.3", + "@babel/traverse": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-replace-supers": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.8.3.tgz", + "integrity": "sha512-xOUssL6ho41U81etpLoT2RTdvdus4VfHamCuAm4AHxGr+0it5fnwoVdwUJ7GFEqCsQYzJUhcbsN9wB9apcYKFA==", + "dev": true, + "requires": { + "@babel/helper-member-expression-to-functions": "^7.8.3", + "@babel/helper-optimise-call-expression": "^7.8.3", + "@babel/traverse": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-simple-access": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.8.3.tgz", + "integrity": "sha512-VNGUDjx5cCWg4vvCTR8qQ7YJYZ+HBjxOgXEl7ounz+4Sn7+LMD3CFrCTEU6/qXKbA2nKg21CwhhBzO0RpRbdCw==", + "dev": true, + "requires": { + "@babel/template": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz", + "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-wrap-function": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.8.3.tgz", + "integrity": "sha512-LACJrbUET9cQDzb6kG7EeD7+7doC3JNvUgTEQOx2qaO1fKlzE/Bf05qs9w1oXQMmXlPO65lC3Tq9S6gZpTErEQ==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.8.3", + "@babel/template": "^7.8.3", + "@babel/traverse": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/helpers": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.8.4.tgz", + "integrity": "sha512-VPbe7wcQ4chu4TDQjimHv/5tj73qz88o12EPkO2ValS2QiQS/1F2SsjyIGNnAD0vF/nZS6Cf9i+vW6HIlnaR8w==", + "dev": true, + "requires": { + "@babel/template": "^7.8.3", + "@babel/traverse": "^7.8.4", + "@babel/types": "^7.8.3" + }, + "dependencies": { + "@babel/generator": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.8.4.tgz", + "integrity": "sha512-PwhclGdRpNAf3IxZb0YVuITPZmmrXz9zf6fH8lT4XbrmfQKr6ryBzhv593P5C6poJRciFCL/eHGW2NuGrgEyxA==", "dev": true, "requires": { - "ansi-regex": "^4.1.0" + "@babel/types": "^7.8.3", + "jsesc": "^2.5.1", + "lodash": "^4.17.13", + "source-map": "^0.5.0" } }, - "strip-json-comments": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz", - "integrity": "sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E=", + "@babel/parser": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.4.tgz", + "integrity": "sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw==", "dev": true }, - "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "@babel/traverse": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.8.4.tgz", + "integrity": "sha512-NGLJPZwnVEyBPLI+bl9y9aSnxMhsKz42so7ApAv9D+b4vAFPpY013FTS9LdKxcABoIYFU52HcYga1pPlx454mg==", "dev": true, "requires": { - "has-flag": "^4.0.0" + "@babel/code-frame": "^7.8.3", + "@babel/generator": "^7.8.4", + "@babel/helper-function-name": "^7.8.3", + "@babel/helper-split-export-declaration": "^7.8.3", + "@babel/parser": "^7.8.4", + "@babel/types": "^7.8.3", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.13" } }, - "table": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/table/-/table-3.8.3.tgz", - "integrity": "sha1-K7xULw/amGGnVdOUf+/Ys/UThV8=", + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { - "ajv": "^4.7.0", - "ajv-keywords": "^1.0.0", - "chalk": "^1.1.1", - "lodash": "^4.0.0", - "slice-ansi": "0.0.4", - "string-width": "^2.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } + "ms": "^2.1.1" } }, - "type-fest": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz", - "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==", + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true }, - "update-notifier": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-3.0.1.tgz", - "integrity": "sha512-grrmrB6Zb8DUiyDIaeRTBCkgISYUgETNe7NglEbVsrLWXeESnlCSP50WfRSj/GmzMPl6Uchj24S/p80nP/ZQrQ==", - "dev": true, - "requires": { - "boxen": "^3.0.0", - "chalk": "^2.0.1", - "configstore": "^4.0.0", - "has-yarn": "^2.1.0", - "import-lazy": "^2.1.0", - "is-ci": "^2.0.0", - "is-installed-globally": "^0.1.0", - "is-npm": "^3.0.0", - "is-yarn-global": "^0.3.0", - "latest-version": "^5.0.0", - "semver-diff": "^2.0.0", - "xdg-basedir": "^3.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "url-parse-lax": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", - "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "@babel/highlight": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", + "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { - "prepend-http": "^2.0.0" + "color-convert": "^1.9.0" } }, - "widest-line": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz", - "integrity": "sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==", + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { - "string-width": "^2.1.1" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" } }, - "write-file-atomic": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", - "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "requires": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" + "has-flag": "^3.0.0" } - }, - "xdg-basedir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", - "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=", - "dev": true } } }, - "@nodelib/fs.scandir": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz", - "integrity": "sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw==", + "@babel/parser": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.3.tgz", + "integrity": "sha512-/V72F4Yp/qmHaTALizEm9Gf2eQHV3QyTL3K0cNfijwnMnb1L+LDlAubb/ZnSdGAVzVSWakujHYs1I26x66sMeQ==", + "dev": true + }, + "@babel/plugin-proposal-async-generator-functions": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.8.3.tgz", + "integrity": "sha512-NZ9zLv848JsV3hs8ryEh7Uaz/0KsmPLqv0+PdkDJL1cJy0K4kOCFa8zc1E3mp+RHPQcpdfb/6GovEsW4VDrOMw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-remap-async-to-generator": "^7.8.3", + "@babel/plugin-syntax-async-generators": "^7.8.0" + } + }, + "@babel/plugin-proposal-class-properties": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.8.3.tgz", + "integrity": "sha512-EqFhbo7IosdgPgZggHaNObkmO1kNUe3slaKu54d5OWvy+p9QIKOzK1GAEpAIsZtWVtPXUHSMcT4smvDrCfY4AA==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-proposal-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.8.3.tgz", + "integrity": "sha512-NyaBbyLFXFLT9FP+zk0kYlUlA8XtCUbehs67F0nnEg7KICgMc2mNkIeu9TYhKzyXMkrapZFwAhXLdnt4IYHy1w==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-dynamic-import": "^7.8.0" + } + }, + "@babel/plugin-proposal-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.8.3.tgz", + "integrity": "sha512-KGhQNZ3TVCQG/MjRbAUwuH+14y9q0tpxs1nWWs3pbSleRdDro9SAMMDyye8HhY1gqZ7/NqIc8SKhya0wRDgP1Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.0" + } + }, + "@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-TS9MlfzXpXKt6YYomudb/KU7nQI6/xnapG6in1uZxoxDghuSMZsPb6D2fyUwNYSAp4l1iR7QtFOjkqcRYcUsfw==", "dev": true, "requires": { - "@nodelib/fs.stat": "2.0.3", - "run-parallel": "^1.1.9" + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0" } }, - "@nodelib/fs.stat": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz", - "integrity": "sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA==", - "dev": true - }, - "@nodelib/fs.walk": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz", - "integrity": "sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ==", + "@babel/plugin-proposal-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-8qvuPwU/xxUCt78HocNlv0mXXo0wdh9VT1R04WU8HGOfaOob26pF+9P5/lYjN/q7DHOX1bvX60hnhOvuQUJdbA==", "dev": true, "requires": { - "@nodelib/fs.scandir": "2.1.3", - "fastq": "^1.6.0" + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.0" } }, - "@npmcli/ci-detect": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@npmcli/ci-detect/-/ci-detect-1.1.1.tgz", - "integrity": "sha512-h5eW3DljLypyhvfK94FkSSm4qtSUFddth/xW+7vnkVCEUJR38MYvctCSZkxqrzmXZSzpfImuAwwKvRqkEuDvCQ==", - "dev": true - }, - "@npmcli/installed-package-contents": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-1.0.5.tgz", - "integrity": "sha512-aKIwguaaqb6ViwSOFytniGvLPb9SMCUm39TgM3SfUo7n0TxUMbwoXfpwyvQ4blm10lzbAwTsvjr7QZ85LvTi4A==", + "@babel/plugin-proposal-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-0gkX7J7E+AtAw9fcwlVQj8peP61qhdg/89D5swOkjYbkboA2CVckn3kiyum1DE0wskGb7KJJxBdyEBApDLLVdw==", "dev": true, "requires": { - "npm-bundled": "^1.1.1", - "npm-normalize-package-bin": "^1.0.1", - "read-package-json-fast": "^1.1.1", - "readdir-scoped-modules": "^1.1.0" + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.0" } }, - "@samverschueren/stream-to-observable": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz", - "integrity": "sha512-MI4Xx6LHs4Webyvi6EbspgyAb4D2Q2VtnCQ1blOJcoLS6mVa8lNN2rkIy1CVxfTUpoyIbCTkXES1rLXztFD1lg==", + "@babel/plugin-proposal-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.8.3.tgz", + "integrity": "sha512-QIoIR9abkVn+seDE3OjA08jWcs3eZ9+wJCKSRgo3WdEU2csFYgdScb+8qHB3+WXsGJD55u+5hWCISI7ejXS+kg==", "dev": true, "requires": { - "any-observable": "^0.3.0" + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.0" } }, - "@sindresorhus/is": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", - "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", - "dev": true - }, - "@sinonjs/commons": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.7.0.tgz", - "integrity": "sha512-qbk9AP+cZUsKdW1GJsBpxPKFmCJ0T8swwzVje3qFd+AkQb74Q/tiuzrdfFg8AD2g5HH/XbE/I8Uc1KYHVYWfhg==", + "@babel/plugin-proposal-unicode-property-regex": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.8.3.tgz", + "integrity": "sha512-1/1/rEZv2XGweRwwSkLpY+s60za9OZ1hJs4YDqFHCw0kYWYwL5IFljVY1MYBL+weT1l9pokDO2uhSTLVxzoHkQ==", "dev": true, "requires": { - "type-detect": "4.0.8" + "@babel/helper-create-regexp-features-plugin": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" } }, - "@sinonjs/formatio": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-4.0.1.tgz", - "integrity": "sha512-asIdlLFrla/WZybhm0C8eEzaDNNrzymiTqHMeJl6zPW2881l3uuVRpm0QlRQEjqYWv6CcKMGYME3LbrLJsORBw==", + "@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", "dev": true, "requires": { - "@sinonjs/commons": "^1", - "@sinonjs/samsam": "^4.2.0" + "@babel/helper-plugin-utils": "^7.8.0" } }, - "@sinonjs/samsam": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-4.2.2.tgz", - "integrity": "sha512-z9o4LZUzSD9Hl22zV38aXNykgFeVj8acqfFabCY6FY83n/6s/XwNJyYYldz6/9lBJanpno9h+oL6HTISkviweA==", + "@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", "dev": true, "requires": { - "@sinonjs/commons": "^1.6.0", - "lodash.get": "^4.4.2", - "type-detect": "^4.0.8" + "@babel/helper-plugin-utils": "^7.8.0" } }, - "@sinonjs/text-encoding": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", - "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", - "dev": true - }, - "@szmarczak/http-timer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", - "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", "dev": true, "requires": { - "defer-to-connect": "^1.0.1" + "@babel/helper-plugin-utils": "^7.8.0" } }, - "@types/color-name": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", - "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", - "dev": true - }, - "@types/estree": { - "version": "0.0.42", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.42.tgz", - "integrity": "sha512-K1DPVvnBCPxzD+G51/cxVIoc2X8uUVl1zpJeE6iKcgHMj4+tbat5Xu4TjV7v2QSDbIeAfLi2hIk+u2+s0MlpUQ==", - "dev": true - }, - "@types/events": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", - "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==", - "dev": true - }, - "@types/glob": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz", - "integrity": "sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==", + "@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", "dev": true, "requires": { - "@types/events": "*", - "@types/minimatch": "*", - "@types/node": "*" + "@babel/helper-plugin-utils": "^7.8.0" } }, - "@types/minimatch": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", - "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", - "dev": true + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } }, - "@types/node": { - "version": "13.5.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-13.5.0.tgz", - "integrity": "sha512-Onhn+z72D2O2Pb2ql2xukJ55rglumsVo1H6Fmyi8mlU9SvKdBk/pUSUAiBY/d9bAOF7VVWajX3sths/+g6ZiAQ==", - "dev": true + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } }, - "@types/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", - "dev": true + "@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } }, - "@types/unist": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.3.tgz", - "integrity": "sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ==", - "dev": true + "@babel/plugin-syntax-top-level-await": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.8.3.tgz", + "integrity": "sha512-kwj1j9lL/6Wd0hROD3b/OZZ7MSrZLqqn9RAZ5+cYYsflQ9HZBIKCUkr3+uL1MEJ1NePiUbf98jjiMQSv0NMR9g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } }, - "@typescript-eslint/typescript-estree": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.6.1.tgz", - "integrity": "sha512-+sTnssW6bcbDZKE8Ce7VV6LdzkQz2Bxk7jzk1J8H1rovoTxnm6iXvYIyncvNsaB/kBCOM63j/LNJfm27bNdUoA==", + "@babel/plugin-syntax-typescript": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.8.3.tgz", + "integrity": "sha512-GO1MQ/SGGGoiEXY0e0bSpHimJvxqB7lktLLIq2pv8xG7WZ8IMEle74jIe1FhprHBWjwjZtXHkycDLZXIWM5Wfg==", "dev": true, "requires": { - "debug": "^4.1.1", - "glob": "^7.1.4", - "is-glob": "^4.0.1", - "lodash.unescape": "4.0.1", - "semver": "^6.3.0", - "tsutils": "^3.17.1" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-arrow-functions": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.8.3.tgz", + "integrity": "sha512-0MRF+KC8EqH4dbuITCWwPSzsyO3HIWWlm30v8BbbpOrS1B++isGxPnnuq/IZvOX5J2D/p7DQalQm+/2PnlKGxg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" } }, - "accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "@babel/plugin-transform-async-to-generator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.8.3.tgz", + "integrity": "sha512-imt9tFLD9ogt56Dd5CI/6XgpukMwd/fLGSrix2httihVe7LOGVPhyhMh1BU5kDM7iHD08i8uUtmV2sWaBFlHVQ==", "dev": true, "requires": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" - }, - "dependencies": { - "mime-db": { - "version": "1.43.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", - "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==", - "dev": true - }, - "mime-types": { - "version": "2.1.26", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", - "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", - "dev": true, - "requires": { - "mime-db": "1.43.0" - } - } + "@babel/helper-module-imports": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-remap-async-to-generator": "^7.8.3" } }, - "acorn": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.1.tgz", - "integrity": "sha512-d+nbxBUGKg7Arpsvbnlq61mc12ek3EY8EQldM3GPAhWJ1UVxC6TDGbIvUMNU6obBX3i1+ptCIzV4vq0gFPEGVQ==", - "dev": true - }, - "acorn-jsx": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.1.0.tgz", - "integrity": "sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw==", - "dev": true - }, - "adm-zip": { - "version": "0.4.13", - "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.13.tgz", - "integrity": "sha512-fERNJX8sOXfel6qCBCMPvZLzENBEhZTzKqg6vrOW5pvoEaQuJhRU4ndTAh6lHOxn1I6jnz2NHra56ZODM751uw==", - "dev": true - }, - "after": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", - "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=", - "dev": true + "@babel/plugin-transform-block-scoped-functions": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.8.3.tgz", + "integrity": "sha512-vo4F2OewqjbB1+yaJ7k2EJFHlTP3jR634Z9Cj9itpqNjuLXvhlVxgnjsHsdRgASR8xYDrx6onw4vW5H6We0Jmg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } }, - "agent-base": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", - "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", + "@babel/plugin-transform-block-scoping": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.8.3.tgz", + "integrity": "sha512-pGnYfm7RNRgYRi7bids5bHluENHqJhrV4bCZRwc5GamaWIIs07N4rZECcmJL6ZClwjDz1GbdMZFtPs27hTB06w==", "dev": true, "requires": { - "es6-promisify": "^5.0.0" + "@babel/helper-plugin-utils": "^7.8.3", + "lodash": "^4.17.13" } }, - "agentkeepalive": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.1.0.tgz", - "integrity": "sha512-CW/n1wxF8RpEuuiq6Vbn9S8m0VSYDMnZESqaJ6F2cWN9fY8rei2qaxweIaRgq+ek8TqfoFIsUjaGNKGGEHElSg==", + "@babel/plugin-transform-classes": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.8.3.tgz", + "integrity": "sha512-SjT0cwFJ+7Rbr1vQsvphAHwUHvSUPmMjMU/0P59G8U2HLFqSa082JO7zkbDNWs9kH/IUqpHI6xWNesGf8haF1w==", "dev": true, "requires": { - "debug": "^4.1.0", - "depd": "^1.1.2", - "humanize-ms": "^1.2.1" + "@babel/helper-annotate-as-pure": "^7.8.3", + "@babel/helper-define-map": "^7.8.3", + "@babel/helper-function-name": "^7.8.3", + "@babel/helper-optimise-call-expression": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-replace-supers": "^7.8.3", + "@babel/helper-split-export-declaration": "^7.8.3", + "globals": "^11.1.0" }, "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true } } }, - "aggregate-error": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.0.1.tgz", - "integrity": "sha512-quoaXsZ9/BLNae5yiNoUz+Nhkwz83GhWwtYFglcjEQB2NDHCIpApbqXxIFnm4Pq/Nvhrsq5sYJFyohrrxnTGAA==", + "@babel/plugin-transform-computed-properties": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.8.3.tgz", + "integrity": "sha512-O5hiIpSyOGdrQZRQ2ccwtTVkgUDBBiCuK//4RJ6UfePllUTCENOzKxfh6ulckXKc0DixTFLCfb2HVkNA7aDpzA==", "dev": true, "requires": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "dependencies": { - "indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true - } + "@babel/helper-plugin-utils": "^7.8.3" } }, - "ajv": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.11.0.tgz", - "integrity": "sha512-nCprB/0syFYy9fVYU1ox1l2KN8S9I+tziH8D4zdZuLT3N6RMlGSGt5FSTpAiHB/Whv8Qs1cWHma1aMKZyaHRKA==", + "@babel/plugin-transform-destructuring": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.8.3.tgz", + "integrity": "sha512-H4X646nCkiEcHZUZaRkhE2XVsoz0J/1x3VVujnn96pSoGCtKPA99ZZA+va+gK+92Zycd6OBKCD8tDb/731bhgQ==", "dev": true, "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "@babel/helper-plugin-utils": "^7.8.3" } }, - "ajv-keywords": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz", - "integrity": "sha1-MU3QpLM2j609/NxU7eYXG4htrzw=", - "dev": true + "@babel/plugin-transform-dotall-regex": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.8.3.tgz", + "integrity": "sha512-kLs1j9Nn4MQoBYdRXH6AeaXMbEJFaFu/v1nQkvib6QzTj8MZI5OQzqmD83/2jEM1z0DLilra5aWO5YpyC0ALIw==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" + } }, - "angular-estree-parser": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/angular-estree-parser/-/angular-estree-parser-1.1.5.tgz", - "integrity": "sha512-M82O7HGwgS6mBfQq9ijCwuP4uYgSgycmNWQOHomToWRAdfX/c2pAwpCYdbVG9lc6Go8mr5+A2bRQnykdCVdpuA==", + "@babel/plugin-transform-duplicate-keys": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.8.3.tgz", + "integrity": "sha512-s8dHiBUbcbSgipS4SMFuWGqCvyge5V2ZeAWzR6INTVC3Ltjig/Vw1G2Gztv0vU/hRG9X8IvKvYdoksnUfgXOEQ==", "dev": true, "requires": { - "lines-and-columns": "^1.1.6", - "tslib": "^1.9.3" + "@babel/helper-plugin-utils": "^7.8.3" } }, - "angular-html-parser": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/angular-html-parser/-/angular-html-parser-1.3.0.tgz", - "integrity": "sha512-FCLuM8ZUt30qwiV5KlW8uWL9cwlS2loOIGq8wUQFypkJ1QZqJk829yxTsvp2DvCMZ7uLwfjIaIrKV5N2+RLiSQ==", + "@babel/plugin-transform-exponentiation-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.8.3.tgz", + "integrity": "sha512-zwIpuIymb3ACcInbksHaNcR12S++0MDLKkiqXHl3AzpgdKlFNhog+z/K0+TGW+b0w5pgTq4H6IwV/WhxbGYSjQ==", "dev": true, "requires": { - "tslib": "^1.9.3" + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" } }, - "ansi-colors": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", - "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", - "dev": true + "@babel/plugin-transform-for-of": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.8.4.tgz", + "integrity": "sha512-iAXNlOWvcYUYoV8YIxwS7TxGRJcxyl8eQCfT+A5j8sKUzRFvJdcyjp97jL2IghWSRDaL2PU2O2tX8Cu9dTBq5A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } }, - "ansi-escapes": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", - "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", - "dev": true + "@babel/plugin-transform-function-name": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.8.3.tgz", + "integrity": "sha512-rO/OnDS78Eifbjn5Py9v8y0aR+aSYhDhqAwVfsTl0ERuMZyr05L1aFSCJnbv2mmsLkit/4ReeQ9N2BgLnOcPCQ==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" + } }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true + "@babel/plugin-transform-literals": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.8.3.tgz", + "integrity": "sha512-3Tqf8JJ/qB7TeldGl+TT55+uQei9JfYaregDcEAyBZ7akutriFrt6C/wLYIer6OYhleVQvH/ntEhjE/xMmy10A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true + "@babel/plugin-transform-member-expression-literals": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.8.3.tgz", + "integrity": "sha512-3Wk2EXhnw+rP+IDkK6BdtPKsUE5IeZ6QOGrPYvw52NwBStw9V1ZVzxgK6fSKSxqUvH9eQPR3tm3cOq79HlsKYA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } }, - "any-observable": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/any-observable/-/any-observable-0.3.0.tgz", - "integrity": "sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog==", - "dev": true + "@babel/plugin-transform-modules-amd": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.8.3.tgz", + "integrity": "sha512-MadJiU3rLKclzT5kBH4yxdry96odTUwuqrZM+GllFI/VhxfPz+k9MshJM+MwhfkCdxxclSbSBbUGciBngR+kEQ==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "babel-plugin-dynamic-import-node": "^2.3.0" + } }, - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "@babel/plugin-transform-modules-commonjs": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.8.3.tgz", + "integrity": "sha512-JpdMEfA15HZ/1gNuB9XEDlZM1h/gF/YOH7zaZzQu2xCFRfwc01NXBMHHSTT6hRjlXJJs5x/bfODM3LiCk94Sxg==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-simple-access": "^7.8.3", + "babel-plugin-dynamic-import-node": "^2.3.0" + } + }, + "@babel/plugin-transform-modules-systemjs": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.8.3.tgz", + "integrity": "sha512-8cESMCJjmArMYqa9AO5YuMEkE4ds28tMpZcGZB/jl3n0ZzlsxOAi3mC+SKypTfT8gjMupCnd3YiXCkMjj2jfOg==", + "dev": true, + "requires": { + "@babel/helper-hoist-variables": "^7.8.3", + "@babel/helper-module-transforms": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "babel-plugin-dynamic-import-node": "^2.3.0" + } + }, + "@babel/plugin-transform-modules-umd": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.8.3.tgz", + "integrity": "sha512-evhTyWhbwbI3/U6dZAnx/ePoV7H6OUG+OjiJFHmhr9FPn0VShjwC2kdxqIuQ/+1P50TMrneGzMeyMTFOjKSnAw==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.8.3.tgz", + "integrity": "sha512-f+tF/8UVPU86TrCb06JoPWIdDpTNSGGcAtaD9mLP0aYGA0OS0j7j7DHJR0GTFrUZPUU6loZhbsVZgTh0N+Qdnw==", "dev": true, - "optional": true, "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "optional": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } + "@babel/helper-create-regexp-features-plugin": "^7.8.3" } }, - "append-transform": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz", - "integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==", + "@babel/plugin-transform-new-target": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.8.3.tgz", + "integrity": "sha512-QuSGysibQpyxexRyui2vca+Cmbljo8bcRckgzYV4kRIsHpVeyeC3JDO63pY+xFZ6bWOBn7pfKZTqV4o/ix9sFw==", "dev": true, "requires": { - "default-require-extensions": "^3.0.0" + "@babel/helper-plugin-utils": "^7.8.3" } }, - "aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "dev": true - }, - "archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", - "dev": true - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "@babel/plugin-transform-object-super": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.8.3.tgz", + "integrity": "sha512-57FXk+gItG/GejofIyLIgBKTas4+pEU47IXKDBWFTxdPd7F80H8zybyAY7UoblVfBhBGs2EKM+bJUu2+iUYPDQ==", "dev": true, "requires": { - "sprintf-js": "~1.0.2" + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-replace-supers": "^7.8.3" } }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "@babel/plugin-transform-parameters": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.8.4.tgz", + "integrity": "sha512-IsS3oTxeTsZlE5KqzTbcC2sV0P9pXdec53SU+Yxv7o/6dvGM5AkTotQKhoSffhNgZ/dftsSiOoxy7evCYJXzVA==", "dev": true, - "optional": true + "requires": { + "@babel/helper-call-delegate": "^7.8.3", + "@babel/helper-get-function-arity": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" + } }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "@babel/plugin-transform-property-literals": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.8.3.tgz", + "integrity": "sha512-uGiiXAZMqEoQhRWMK17VospMZh5sXWg+dlh2soffpkAl96KAm+WZuJfa6lcELotSRmooLqg0MWdH6UUq85nmmg==", "dev": true, - "optional": true + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "@babel/plugin-transform-regenerator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.8.3.tgz", + "integrity": "sha512-qt/kcur/FxrQrzFR432FGZznkVAjiyFtCOANjkAKwCbt465L6ZCiUQh2oMYGU3Wo8LRFJxNDFwWn106S5wVUNA==", "dev": true, - "optional": true + "requires": { + "regenerator-transform": "^0.14.0" + } }, - "array-differ": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-2.1.0.tgz", - "integrity": "sha512-KbUpJgx909ZscOc/7CLATBFam7P1Z1QRQInvgT0UztM9Q72aGKCunKASAl7WNW0tnPmPyEMeMhdsfWhfmW037w==", - "dev": true + "@babel/plugin-transform-reserved-words": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.8.3.tgz", + "integrity": "sha512-mwMxcycN3omKFDjDQUl+8zyMsBfjRFr0Zn/64I41pmjv4NJuqcYlEtezwYtw9TFd9WR1vN5kiM+O0gMZzO6L0A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } }, - "array-includes": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz", - "integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=", + "@babel/plugin-transform-shorthand-properties": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.8.3.tgz", + "integrity": "sha512-I9DI6Odg0JJwxCHzbzW08ggMdCezoWcuQRz3ptdudgwaHxTjxw5HgdFJmZIkIMlRymL6YiZcped4TTCB0JcC8w==", "dev": true, "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.7.0" + "@babel/helper-plugin-utils": "^7.8.3" } }, - "array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "@babel/plugin-transform-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.8.3.tgz", + "integrity": "sha512-CkuTU9mbmAoFOI1tklFWYYbzX5qCIZVXPVy0jpXgGwkplCndQAa58s2jr66fTeQnA64bDox0HL4U56CFYoyC7g==", "dev": true, "requires": { - "array-uniq": "^1.0.1" + "@babel/helper-plugin-utils": "^7.8.3" } }, - "array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", - "dev": true + "@babel/plugin-transform-sticky-regex": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.8.3.tgz", + "integrity": "sha512-9Spq0vGCD5Bb4Z/ZXXSK5wbbLFMG085qd2vhL1JYu1WcQ5bXqZBAYRzU1d+p79GcHs2szYv5pVQCX13QgldaWw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-regex": "^7.8.3" + } }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "@babel/plugin-transform-template-literals": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.8.3.tgz", + "integrity": "sha512-820QBtykIQOLFT8NZOcTRJ1UNuztIELe4p9DCgvj4NK+PwluSJ49we7s9FB1HIGNIYT7wFUJ0ar2QpCDj0escQ==", "dev": true, - "optional": true + "requires": { + "@babel/helper-annotate-as-pure": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" + } }, - "array.prototype.flat": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz", - "integrity": "sha512-gBlRZV0VSmfPIeWfuuy56XZMvbVfbEUnOXUvt3F/eUUUSyzlgLxhEX4YAEpxNAogRGehPSnfXyPtYyKAhkzQhQ==", + "@babel/plugin-transform-typeof-symbol": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.8.4.tgz", + "integrity": "sha512-2QKyfjGdvuNfHsb7qnBBlKclbD4CfshH2KvDabiijLMGXPHJXGxtDzwIF7bQP+T0ysw8fYTtxPafgfs/c1Lrqg==", "dev": true, "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.4", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.4.tgz", - "integrity": "sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.1.5", - "is-regex": "^1.0.5", - "object-inspect": "^1.7.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimleft": "^2.1.1", - "string.prototype.trimright": "^2.1.1" - } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "is-callable": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", - "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", - "dev": true - }, - "is-regex": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", - "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - } + "@babel/helper-plugin-utils": "^7.8.3" } }, - "arraybuffer.slice": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", - "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==", - "dev": true + "@babel/plugin-transform-typescript": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.8.3.tgz", + "integrity": "sha512-Ebj230AxcrKGZPKIp4g4TdQLrqX95TobLUWKd/CwG7X1XHUH1ZpkpFvXuXqWbtGRWb7uuEWNlrl681wsOArAdQ==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-typescript": "^7.8.3" + } }, - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true + "@babel/plugin-transform-unicode-regex": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.8.3.tgz", + "integrity": "sha512-+ufgJjYdmWfSQ+6NS9VGUR2ns8cjJjYbrbi11mZBTaWm+Fui/ncTLFF28Ei1okavY+xkojGr1eJxNsWYeA5aZw==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" + } }, - "asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=", - "dev": true + "@babel/preset-env": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.8.4.tgz", + "integrity": "sha512-HihCgpr45AnSOHRbS5cWNTINs0TwaR8BS8xIIH+QwiW8cKL0llV91njQMpeMReEPVs+1Ao0x3RLEBLtt1hOq4w==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.8.4", + "@babel/helper-compilation-targets": "^7.8.4", + "@babel/helper-module-imports": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-proposal-async-generator-functions": "^7.8.3", + "@babel/plugin-proposal-dynamic-import": "^7.8.3", + "@babel/plugin-proposal-json-strings": "^7.8.3", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-proposal-object-rest-spread": "^7.8.3", + "@babel/plugin-proposal-optional-catch-binding": "^7.8.3", + "@babel/plugin-proposal-optional-chaining": "^7.8.3", + "@babel/plugin-proposal-unicode-property-regex": "^7.8.3", + "@babel/plugin-syntax-async-generators": "^7.8.0", + "@babel/plugin-syntax-dynamic-import": "^7.8.0", + "@babel/plugin-syntax-json-strings": "^7.8.0", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0", + "@babel/plugin-syntax-object-rest-spread": "^7.8.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.0", + "@babel/plugin-syntax-top-level-await": "^7.8.3", + "@babel/plugin-transform-arrow-functions": "^7.8.3", + "@babel/plugin-transform-async-to-generator": "^7.8.3", + "@babel/plugin-transform-block-scoped-functions": "^7.8.3", + "@babel/plugin-transform-block-scoping": "^7.8.3", + "@babel/plugin-transform-classes": "^7.8.3", + "@babel/plugin-transform-computed-properties": "^7.8.3", + "@babel/plugin-transform-destructuring": "^7.8.3", + "@babel/plugin-transform-dotall-regex": "^7.8.3", + "@babel/plugin-transform-duplicate-keys": "^7.8.3", + "@babel/plugin-transform-exponentiation-operator": "^7.8.3", + "@babel/plugin-transform-for-of": "^7.8.4", + "@babel/plugin-transform-function-name": "^7.8.3", + "@babel/plugin-transform-literals": "^7.8.3", + "@babel/plugin-transform-member-expression-literals": "^7.8.3", + "@babel/plugin-transform-modules-amd": "^7.8.3", + "@babel/plugin-transform-modules-commonjs": "^7.8.3", + "@babel/plugin-transform-modules-systemjs": "^7.8.3", + "@babel/plugin-transform-modules-umd": "^7.8.3", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.8.3", + "@babel/plugin-transform-new-target": "^7.8.3", + "@babel/plugin-transform-object-super": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.8.4", + "@babel/plugin-transform-property-literals": "^7.8.3", + "@babel/plugin-transform-regenerator": "^7.8.3", + "@babel/plugin-transform-reserved-words": "^7.8.3", + "@babel/plugin-transform-shorthand-properties": "^7.8.3", + "@babel/plugin-transform-spread": "^7.8.3", + "@babel/plugin-transform-sticky-regex": "^7.8.3", + "@babel/plugin-transform-template-literals": "^7.8.3", + "@babel/plugin-transform-typeof-symbol": "^7.8.4", + "@babel/plugin-transform-unicode-regex": "^7.8.3", + "@babel/types": "^7.8.3", + "browserslist": "^4.8.5", + "core-js-compat": "^3.6.2", + "invariant": "^2.2.2", + "levenary": "^1.1.1", + "semver": "^5.5.0" + } }, - "asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "@babel/preset-typescript": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.8.3.tgz", + "integrity": "sha512-qee5LgPGui9zQ0jR1TeU5/fP9L+ovoArklEqY12ek8P/wV5ZeM/VYSQYwICeoT6FfpJTekG9Ilay5PhwsOpMHA==", "dev": true, "requires": { - "safer-buffer": "~2.1.0" + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-transform-typescript": "^7.8.3" } }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - }, - "assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true - }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true, - "optional": true - }, - "astral-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", - "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", - "dev": true - }, - "async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "@babel/runtime": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.8.4.tgz", + "integrity": "sha512-neAp3zt80trRVBI1x0azq6c57aNBqYZH8KhMm3TaB7wEI5Q4A2SHfBHE8w9gOhI/lrqxtEbXZgQIrHP+wvSGwQ==", "dev": true, "requires": { - "lodash": "^4.17.14" + "regenerator-runtime": "^0.13.2" }, "dependencies": { - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "regenerator-runtime": { + "version": "0.13.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz", + "integrity": "sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw==", "dev": true } } }, - "async-each": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", - "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", - "dev": true, - "optional": true - }, - "async-limiter": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", - "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", - "dev": true - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true - }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true, - "optional": true - }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", - "dev": true - }, - "aws4": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", - "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", - "dev": true - }, - "babel-code-frame": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "@babel/template": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz", + "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==", "dev": true, "requires": { - "chalk": "^1.1.3", - "esutils": "^2.0.2", - "js-tokens": "^3.0.2" + "@babel/code-frame": "^7.8.3", + "@babel/parser": "^7.8.3", + "@babel/types": "^7.8.3" } }, - "babel-eslint": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.0.3.tgz", - "integrity": "sha512-z3U7eMY6r/3f3/JB9mTsLjyxrv0Yb1zb8PCWCLpguxfCzBIZUwy23R1t/XKewP+8mEN2Ck8Dtr4q20z6ce6SoA==", + "@babel/traverse": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.8.3.tgz", + "integrity": "sha512-we+a2lti+eEImHmEXp7bM9cTxGzxPmBiVJlLVD+FuuQMeeO7RaDbutbgeheDkw+Xe3mCfJHnGOWLswT74m2IPg==", "dev": true, "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.0.0", - "@babel/traverse": "^7.0.0", - "@babel/types": "^7.0.0", - "eslint-visitor-keys": "^1.0.0", - "resolve": "^1.12.0" + "@babel/code-frame": "^7.8.3", + "@babel/generator": "^7.8.3", + "@babel/helper-function-name": "^7.8.3", + "@babel/helper-split-export-declaration": "^7.8.3", + "@babel/parser": "^7.8.3", + "@babel/types": "^7.8.3", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.13" }, "dependencies": { - "resolve": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.0.tgz", - "integrity": "sha512-+hTmAldEGE80U2wJJDC1lebb5jWqvTYAfm3YZ1ckk1gBr0MnCqUKlwK1e+anaFljIl+F5tR5IoZcm4ZDA1zMQw==", + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { - "path-parse": "^1.0.6" + "ms": "^2.1.1" } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true } } }, - "babel-messages": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", - "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-dynamic-import-node": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz", - "integrity": "sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ==", - "dev": true, - "requires": { - "object.assign": "^4.1.0" - } - }, - "babel-runtime": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "@babel/types": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", + "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", "dev": true, "requires": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + }, + "dependencies": { + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + } } }, - "babel-traverse": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", - "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", - "dev": true, - "requires": { - "babel-code-frame": "^6.26.0", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "debug": "^2.6.8", - "globals": "^9.18.0", - "invariant": "^2.2.2", - "lodash": "^4.17.4" - } + "@glimmer/interfaces": { + "version": "0.41.4", + "resolved": "https://registry.npmjs.org/@glimmer/interfaces/-/interfaces-0.41.4.tgz", + "integrity": "sha512-MzXwMyod3MlwSZezHSaVBsCEIW/giYYfTDYARR46QnYsaFVatMVbydjsI7jkAuBCbnLCyNOIc1TrYIj71i/rpg==", + "dev": true }, - "babel-types": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", - "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "@glimmer/syntax": { + "version": "0.41.0", + "resolved": "https://registry.npmjs.org/@glimmer/syntax/-/syntax-0.41.0.tgz", + "integrity": "sha512-sYmgUMdK0jX+3ZNX9C2TKvL1YZGsKIcXRicwnzoTC7F56z29CbSCc7o6Zf0CI4L2Q7FSnHDxldlSe48wBAr6vQ==", "dev": true, "requires": { - "babel-runtime": "^6.26.0", - "esutils": "^2.0.2", - "lodash": "^4.17.4", - "to-fast-properties": "^1.0.3" + "@glimmer/interfaces": "^0.41.0", + "@glimmer/util": "^0.41.0", + "handlebars": "^4.0.13", + "simple-html-tokenizer": "^0.5.7" } }, - "babylon": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", - "dev": true - }, - "backo2": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", - "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=", + "@glimmer/util": { + "version": "0.41.4", + "resolved": "https://registry.npmjs.org/@glimmer/util/-/util-0.41.4.tgz", + "integrity": "sha512-DwS94K+M0vtG+cymxH0rslJr09qpdjyOLdCjmpKcG/nNiZQfMA1ybAaFEmwk9UaVlUG9STENFeQwyrLevJB+7g==", "dev": true }, - "bail": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz", - "integrity": "sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ==", + "@iarna/toml": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.3.tgz", + "integrity": "sha512-FmuxfCuolpLl0AnQ2NHSzoUKWEJDFl63qXjzdoWBVyFCXzMGm1spBzk7LeHNoVCiWCF7mRVms9e6jEV9+MoPbg==", "dev": true }, - "balanced-match": { + "@istanbuljs/load-nyc-config": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.0.0.tgz", + "integrity": "sha512-ZR0rq/f/E4f4XcgnDvtMWXCUJpi8eO0rssVhmztsZqLIEFA9UUP9zmpE0VxlM+kv/E1ul2I876Fwil2ayptDVg==", "dev": true, - "optional": true, "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "dependencies": { + "js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + } + } + }, + "@istanbuljs/schema": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.2.tgz", + "integrity": "sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==", + "dev": true + }, + "@js-data/repo-tools": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@js-data/repo-tools/-/repo-tools-1.0.1.tgz", + "integrity": "sha512-R9f1f+Hd8W68eOTw16yTQLfxDBiO3isSaG+/pz+cY4qPnhvl18aORM/U8+ggk+kFYUdiOce4o6pqePiuo5eXqA==", + "dev": true, + "requires": { + "babel-eslint": "^7.2.3", + "lodash": "^4.17.15", + "npm-check-updates": "^4.0.1", + "standard": "^8.6.0" }, "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "ajv": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", "dev": true, - "optional": true, "requires": { - "is-descriptor": "^1.0.0" + "co": "^4.6.0", + "json-stable-stringify": "^1.0.1" } }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "ansi-escapes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", + "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", + "dev": true + }, + "cli-cursor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", + "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", "dev": true, - "optional": true, "requires": { - "kind-of": "^6.0.0" + "restore-cursor": "^1.0.1" } }, - "is-data-descriptor": { + "doctrine": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "isarray": "^1.0.0" + } + }, + "eslint-config-standard": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-6.2.1.tgz", + "integrity": "sha1-06aKr8cZFjnn7kQec0hzkCY1QpI=", + "dev": true + }, + "eslint-plugin-promise": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-3.4.2.tgz", + "integrity": "sha1-G+J5Pq/i0YtbEjuBNsJp+AT+cSI=", + "dev": true + }, + "eslint-plugin-standard": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-2.0.1.tgz", + "integrity": "sha1-NYlpn/nJF/LCX3apFmh/ZBw2n/M=", + "dev": true + }, + "inquirer": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz", + "integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=", + "dev": true, + "requires": { + "ansi-escapes": "^1.1.0", + "ansi-regex": "^2.0.0", + "chalk": "^1.0.0", + "cli-cursor": "^1.0.1", + "cli-width": "^2.0.0", + "figures": "^1.3.5", + "lodash": "^4.3.0", + "readline2": "^1.0.1", + "run-async": "^0.1.0", + "rx-lite": "^3.1.2", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.0", + "through": "^2.3.6" + } + }, + "is-fullwidth-code-point": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, - "optional": true, "requires": { - "kind-of": "^6.0.0" + "number-is-nan": "^1.0.0" } }, - "is-descriptor": { + "onetime": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", + "dev": true + }, + "pluralize": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-1.2.1.tgz", + "integrity": "sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU=", + "dev": true + }, + "progress": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", + "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", + "dev": true + }, + "restore-cursor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", + "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "dev": true, + "requires": { + "exit-hook": "^1.0.0", + "onetime": "^1.0.0" + } + }, + "run-async": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz", + "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=", + "dev": true, + "requires": { + "once": "^1.3.0" + } + }, + "standard": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/standard/-/standard-8.6.0.tgz", + "integrity": "sha1-Y1Eyvnv7VnwpIQBfMPnjUOR1Kq0=", + "dev": true, + "requires": { + "eslint": "~3.10.2", + "eslint-config-standard": "6.2.1", + "eslint-config-standard-jsx": "3.2.0", + "eslint-plugin-promise": "~3.4.0", + "eslint-plugin-react": "~6.7.1", + "eslint-plugin-standard": "~2.0.1", + "standard-engine": "~5.2.0" + }, + "dependencies": { + "eslint": { + "version": "3.10.2", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-3.10.2.tgz", + "integrity": "sha1-yaEOi/bp1lZRIEd4xQM0Hx6sPOc=", + "dev": true, + "requires": { + "babel-code-frame": "^6.16.0", + "chalk": "^1.1.3", + "concat-stream": "^1.4.6", + "debug": "^2.1.1", + "doctrine": "^1.2.2", + "escope": "^3.6.0", + "espree": "^3.3.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "file-entry-cache": "^2.0.0", + "glob": "^7.0.3", + "globals": "^9.2.0", + "ignore": "^3.2.0", + "imurmurhash": "^0.1.4", + "inquirer": "^0.12.0", + "is-my-json-valid": "^2.10.0", + "is-resolvable": "^1.0.0", + "js-yaml": "^3.5.1", + "json-stable-stringify": "^1.0.0", + "levn": "^0.3.0", + "lodash": "^4.0.0", + "mkdirp": "^0.5.0", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "path-is-inside": "^1.0.1", + "pluralize": "^1.2.1", + "progress": "^1.1.8", + "require-uncached": "^1.0.2", + "shelljs": "^0.7.5", + "strip-bom": "^3.0.0", + "strip-json-comments": "~1.0.1", + "table": "^3.7.8", + "text-table": "~0.2.0", + "user-home": "^2.0.0" + } + } + } + }, + "string-width": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, - "optional": true, "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-json-comments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz", + "integrity": "sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E=", + "dev": true + }, + "table": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/table/-/table-3.8.3.tgz", + "integrity": "sha1-K7xULw/amGGnVdOUf+/Ys/UThV8=", + "dev": true, + "requires": { + "ajv": "^4.7.0", + "ajv-keywords": "^1.0.0", + "chalk": "^1.1.1", + "lodash": "^4.0.0", + "slice-ansi": "0.0.4", + "string-width": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } } } } }, - "base64-arraybuffer": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", - "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=", - "dev": true + "@nodelib/fs.scandir": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz", + "integrity": "sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.3", + "run-parallel": "^1.1.9" + } }, - "base64id": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz", - "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=", + "@nodelib/fs.stat": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz", + "integrity": "sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA==", "dev": true }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "@nodelib/fs.walk": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz", + "integrity": "sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ==", "dev": true, - "optional": true, "requires": { - "tweetnacl": "^0.14.3" + "@nodelib/fs.scandir": "2.1.3", + "fastq": "^1.6.0" } }, - "better-assert": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", - "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", + "@npmcli/ci-detect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@npmcli/ci-detect/-/ci-detect-1.1.1.tgz", + "integrity": "sha512-h5eW3DljLypyhvfK94FkSSm4qtSUFddth/xW+7vnkVCEUJR38MYvctCSZkxqrzmXZSzpfImuAwwKvRqkEuDvCQ==", + "dev": true + }, + "@npmcli/installed-package-contents": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-1.0.5.tgz", + "integrity": "sha512-aKIwguaaqb6ViwSOFytniGvLPb9SMCUm39TgM3SfUo7n0TxUMbwoXfpwyvQ4blm10lzbAwTsvjr7QZ85LvTi4A==", "dev": true, "requires": { - "callsite": "1.0.0" + "npm-bundled": "^1.1.1", + "npm-normalize-package-bin": "^1.0.1", + "read-package-json-fast": "^1.1.1", + "readdir-scoped-modules": "^1.1.0" } }, - "binary-extensions": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", - "dev": true, - "optional": true - }, - "bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "@samverschueren/stream-to-observable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz", + "integrity": "sha512-MI4Xx6LHs4Webyvi6EbspgyAb4D2Q2VtnCQ1blOJcoLS6mVa8lNN2rkIy1CVxfTUpoyIbCTkXES1rLXztFD1lg==", "dev": true, - "optional": true, "requires": { - "file-uri-to-path": "1.0.0" + "any-observable": "^0.3.0" } }, - "blob": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", - "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==", + "@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", "dev": true }, - "bluebird": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", - "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==", - "dev": true - }, - "body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", - "dev": true, - "requires": { - "bytes": "3.1.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" - }, - "dependencies": { - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", - "dev": true - } + "@sinonjs/commons": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.7.0.tgz", + "integrity": "sha512-qbk9AP+cZUsKdW1GJsBpxPKFmCJ0T8swwzVje3qFd+AkQb74Q/tiuzrdfFg8AD2g5HH/XbE/I8Uc1KYHVYWfhg==", + "dev": true, + "requires": { + "type-detect": "4.0.8" } }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "@sinonjs/formatio": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-4.0.1.tgz", + "integrity": "sha512-asIdlLFrla/WZybhm0C8eEzaDNNrzymiTqHMeJl6zPW2881l3uuVRpm0QlRQEjqYWv6CcKMGYME3LbrLJsORBw==", "dev": true, "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "@sinonjs/commons": "^1", + "@sinonjs/samsam": "^4.2.0" } }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "@sinonjs/samsam": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-4.2.2.tgz", + "integrity": "sha512-z9o4LZUzSD9Hl22zV38aXNykgFeVj8acqfFabCY6FY83n/6s/XwNJyYYldz6/9lBJanpno9h+oL6HTISkviweA==", "dev": true, - "optional": true, "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "optional": true, - "requires": { - "is-extendable": "^0.1.0" - } - } + "@sinonjs/commons": "^1.6.0", + "lodash.get": "^4.4.2", + "type-detect": "^4.0.8" } }, - "browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "@sinonjs/text-encoding": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", + "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", "dev": true }, - "buffer-alloc": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", - "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", + "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", "dev": true, "requires": { - "buffer-alloc-unsafe": "^1.1.0", - "buffer-fill": "^1.0.0" + "defer-to-connect": "^1.0.1" } }, - "buffer-alloc-unsafe": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", - "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", - "dev": true - }, - "buffer-fill": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", - "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=", + "@types/chai": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.2.8.tgz", + "integrity": "sha512-U1bQiWbln41Yo6EeHMr+34aUhvrMVyrhn9lYfPSpLTCrZlGxU4Rtn1bocX+0p2Fc/Jkd2FanCEXdw0WNfHHM0w==", "dev": true }, - "buffer-from": { + "@types/color-name": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", "dev": true }, - "builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "@types/eslint-visitor-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", + "integrity": "sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==", "dev": true }, - "builtins": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz", - "integrity": "sha1-y5T662HIaWRR2zZTThQi+U8K7og=", + "@types/estree": { + "version": "0.0.42", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.42.tgz", + "integrity": "sha512-K1DPVvnBCPxzD+G51/cxVIoc2X8uUVl1zpJeE6iKcgHMj4+tbat5Xu4TjV7v2QSDbIeAfLi2hIk+u2+s0MlpUQ==", "dev": true }, - "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "@types/events": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", + "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==", "dev": true }, - "cacache": { - "version": "13.0.1", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-13.0.1.tgz", - "integrity": "sha512-5ZvAxd05HDDU+y9BVvcqYu2LLXmPnQ0hW62h32g4xBTgL/MppR4/04NHfj/ycM2y6lmTnbw6HVi+1eN0Psba6w==", + "@types/glob": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz", + "integrity": "sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==", "dev": true, "requires": { - "chownr": "^1.1.2", - "figgy-pudding": "^3.5.1", - "fs-minipass": "^2.0.0", - "glob": "^7.1.4", - "graceful-fs": "^4.2.2", - "infer-owner": "^1.0.4", - "lru-cache": "^5.1.1", - "minipass": "^3.0.0", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.2", - "mkdirp": "^0.5.1", - "move-concurrently": "^1.0.1", - "p-map": "^3.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^2.7.1", - "ssri": "^7.0.0", - "unique-filename": "^1.1.1" - }, - "dependencies": { - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "graceful-fs": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", - "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", - "dev": true - }, - "lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "requires": { - "yallist": "^3.0.2" - } - }, - "p-map": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", - "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", - "dev": true, - "requires": { - "aggregate-error": "^3.0.0" - } - }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - } + "@types/events": "*", + "@types/minimatch": "*", + "@types/node": "*" } }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "optional": true, - "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - } + "@types/json-schema": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.4.tgz", + "integrity": "sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA==", + "dev": true }, - "cacheable-request": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", - "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", - "dev": true, - "requires": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^3.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^4.1.0", - "responselike": "^1.0.2" - }, - "dependencies": { - "get-stream": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz", - "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "dev": true - } - } + "@types/minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", + "dev": true }, - "caching-transform": { + "@types/mocha": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-7.0.1.tgz", + "integrity": "sha512-L/Nw/2e5KUaprNJoRA33oly+M8X8n0K+FwLTbYqwTcR14wdPWeRkigBLfSFpN/Asf9ENZTMZwLxjtjeYucAA4Q==", + "dev": true + }, + "@types/node": { + "version": "13.5.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-13.5.3.tgz", + "integrity": "sha512-ZPnWX9PW992w6DUsz3JIXHaSb5v7qmKCVzC3km6SxcDGxk7zmLfYaCJTbktIa5NeywJkkZDhGldKqDIvC5DRrA==", + "dev": true + }, + "@types/parse-json": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", - "integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", + "dev": true + }, + "@types/sinon": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-7.5.1.tgz", + "integrity": "sha512-EZQUP3hSZQyTQRfiLqelC9NMWd1kqLcmQE0dMiklxBkgi84T+cHOhnKpgk4NnOWpGX863yE6+IaGnOXUNFqDnQ==", + "dev": true + }, + "@types/unist": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.3.tgz", + "integrity": "sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ==", + "dev": true + }, + "@typescript-eslint/eslint-plugin": { + "version": "2.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.18.0.tgz", + "integrity": "sha512-kuO8WQjV+RCZvAXVRJfXWiJ8iYEtfHlKgcqqqXg9uUkIolEHuUaMmm8/lcO4xwCOtaw6mY0gStn2Lg4/eUXXYQ==", "dev": true, "requires": { - "hasha": "^5.0.0", - "make-dir": "^3.0.0", - "package-hash": "^4.0.0", - "write-file-atomic": "^3.0.0" + "@typescript-eslint/experimental-utils": "2.18.0", + "eslint-utils": "^1.4.3", + "functional-red-black-tree": "^1.0.1", + "regexpp": "^3.0.0", + "tsutils": "^3.17.1" }, "dependencies": { - "hasha": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.1.0.tgz", - "integrity": "sha512-OFPDWmzPN1l7atOV1TgBVmNtBxaIysToK6Ve9DK+vT6pYuklw/nPNT+HJbZi0KDcI6vWB+9tgvZ5YD7fA3CXcA==", + "@typescript-eslint/experimental-utils": { + "version": "2.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-2.18.0.tgz", + "integrity": "sha512-J6MopKPHuJYmQUkANLip7g9I82ZLe1naCbxZZW3O2sIxTiq/9YYoOELEKY7oPg0hJ0V/AQ225h2z0Yp+RRMXhw==", "dev": true, "requires": { - "is-stream": "^2.0.0", - "type-fest": "^0.8.0" + "@types/json-schema": "^7.0.3", + "@typescript-eslint/typescript-estree": "2.18.0", + "eslint-scope": "^5.0.0" } }, - "is-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", - "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", - "dev": true + "@typescript-eslint/typescript-estree": { + "version": "2.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.18.0.tgz", + "integrity": "sha512-gVHylf7FDb8VSi2ypFuEL3hOtoC4HkZZ5dOjXvVjoyKdRrvXAOPSzpNRnKMfaUUEiSLP8UF9j9X9EDLxC0lfZg==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "eslint-visitor-keys": "^1.1.0", + "glob": "^7.1.6", + "is-glob": "^4.0.1", + "lodash": "^4.17.15", + "semver": "^6.3.0", + "tsutils": "^3.17.1" + } }, - "make-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.0.0.tgz", - "integrity": "sha512-grNJDhb8b1Jm1qeqW5R/O63wUo4UXo2v2HMic6YT9i/HBlF93S8jkMgH7yugvY9ABDShH4VZMn8I+U8+fCNegw==", + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { - "semver": "^6.0.0" + "ms": "^2.1.1" + } + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", @@ -5605,292 +2543,194 @@ } } }, - "caller-callsite": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", - "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", + "@typescript-eslint/experimental-utils": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-2.17.0.tgz", + "integrity": "sha512-2bNf+mZ/3mj5/3CP56v+ldRK3vFy9jOvmCPs/Gr2DeSJh+asPZrhFniv4QmQsHWQFPJFWhFHgkGgJeRmK4m8iQ==", "dev": true, "requires": { - "callsites": "^2.0.0" - }, - "dependencies": { - "callsites": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", - "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", - "dev": true - } + "@types/json-schema": "^7.0.3", + "@typescript-eslint/typescript-estree": "2.17.0", + "eslint-scope": "^5.0.0" } }, - "caller-path": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", - "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", + "@typescript-eslint/parser": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-2.17.0.tgz", + "integrity": "sha512-k1g3gRQ4fwfJoIfgUpz78AovicSWKFANmvTfkAHP24MgJHjWfZI6ya7tsQZt1sLczvP4G9BE5G5MgADHdmJB/w==", "dev": true, "requires": { - "callsites": "^0.2.0" + "@types/eslint-visitor-keys": "^1.0.0", + "@typescript-eslint/experimental-utils": "2.17.0", + "@typescript-eslint/typescript-estree": "2.17.0", + "eslint-visitor-keys": "^1.1.0" } }, - "callsite": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", - "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=", - "dev": true - }, - "callsites": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", - "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", - "dev": true - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true - }, - "catharsis": { - "version": "0.8.11", - "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.8.11.tgz", - "integrity": "sha512-a+xUyMV7hD1BrDQA/3iPV7oc+6W26BgVJO05PGEoatMyIuPScQKsde6i3YorWX1qs+AZjnJ18NqdKoCtKiNh1g==", + "@typescript-eslint/typescript-estree": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.17.0.tgz", + "integrity": "sha512-g0eVRULGnEEUakxRfJO0s0Hr1LLQqsI6OrkiCLpdHtdJJek+wyd8mb00vedqAoWldeDcOcP8plqw8/jx9Gr3Lw==", "dev": true, "requires": { - "lodash": "^4.17.14" + "debug": "^4.1.1", + "eslint-visitor-keys": "^1.1.0", + "glob": "^7.1.6", + "is-glob": "^4.0.1", + "lodash": "^4.17.15", + "semver": "^6.3.0", + "tsutils": "^3.17.1" }, "dependencies": { - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true } } }, - "chai": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", - "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", - "dev": true, - "requires": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.2", - "deep-eql": "^3.0.1", - "get-func-name": "^2.0.0", - "pathval": "^1.1.0", - "type-detect": "^4.0.5" - } - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "character-entities": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz", - "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==", - "dev": true - }, - "character-entities-legacy": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz", - "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==", - "dev": true - }, - "character-reference-invalid": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz", - "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==", - "dev": true - }, - "chardet": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", - "dev": true - }, - "check-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", + "acorn": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.1.tgz", + "integrity": "sha512-d+nbxBUGKg7Arpsvbnlq61mc12ek3EY8EQldM3GPAhWJ1UVxC6TDGbIvUMNU6obBX3i1+ptCIzV4vq0gFPEGVQ==", "dev": true }, - "chokidar": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "acorn-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", "dev": true, - "optional": true, "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "fsevents": "^1.2.7", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - } - }, - "chownr": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.3.tgz", - "integrity": "sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw==", - "dev": true - }, - "ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", - "dev": true - }, - "cint": { - "version": "8.2.1", - "resolved": "https://registry.npmjs.org/cint/-/cint-8.2.1.tgz", - "integrity": "sha1-cDhrG0jidz0NYxZqVa/5TvRFahI=", - "dev": true - }, - "circular-json": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", - "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", - "dev": true - }, - "cjk-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/cjk-regex/-/cjk-regex-2.0.0.tgz", - "integrity": "sha512-E4gFi2f3jC0zFVHpaAcupW+gv9OejZ2aV3DP/LlSO0dDcZJAXw7W0ivn+vN17edN/PhU4HCgs1bfx7lPK7FpdA==", + "acorn": "^3.0.4" + }, + "dependencies": { + "acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", + "dev": true + } + } + }, + "agentkeepalive": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.1.0.tgz", + "integrity": "sha512-CW/n1wxF8RpEuuiq6Vbn9S8m0VSYDMnZESqaJ6F2cWN9fY8rei2qaxweIaRgq+ek8TqfoFIsUjaGNKGGEHElSg==", "dev": true, "requires": { - "regexp-util": "^1.2.1", - "unicode-regex": "^2.0.0" + "debug": "^4.1.0", + "depd": "^1.1.2", + "humanize-ms": "^1.2.1" }, "dependencies": { - "unicode-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-regex/-/unicode-regex-2.0.0.tgz", - "integrity": "sha512-5nbEG2YU7loyTvPABaKb+8B0u8L7vWCsVmCSsiaO249ZdMKlvrXlxR2ex4TUVAdzv/Cne/TdoXSSaJArGXaleQ==", + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { - "regexp-util": "^1.2.0" + "ms": "^2.1.1" } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true } } }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "aggregate-error": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.0.1.tgz", + "integrity": "sha512-quoaXsZ9/BLNae5yiNoUz+Nhkwz83GhWwtYFglcjEQB2NDHCIpApbqXxIFnm4Pq/Nvhrsq5sYJFyohrrxnTGAA==", "dev": true, - "optional": true, "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" }, "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "optional": true, - "requires": { - "is-descriptor": "^0.1.0" - } + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true } } }, - "clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true - }, - "cli-cursor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "ajv": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.11.0.tgz", + "integrity": "sha512-nCprB/0syFYy9fVYU1ox1l2KN8S9I+tziH8D4zdZuLT3N6RMlGSGt5FSTpAiHB/Whv8Qs1cWHma1aMKZyaHRKA==", "dev": true, "requires": { - "restore-cursor": "^2.0.0" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" } }, - "cli-table": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.1.tgz", - "integrity": "sha1-9TsFJmqLGguTSz0IIebi3FkUriM=", + "ajv-keywords": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz", + "integrity": "sha1-MU3QpLM2j609/NxU7eYXG4htrzw=", + "dev": true + }, + "angular-estree-parser": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/angular-estree-parser/-/angular-estree-parser-1.1.5.tgz", + "integrity": "sha512-M82O7HGwgS6mBfQq9ijCwuP4uYgSgycmNWQOHomToWRAdfX/c2pAwpCYdbVG9lc6Go8mr5+A2bRQnykdCVdpuA==", "dev": true, "requires": { - "colors": "1.0.3" + "lines-and-columns": "^1.1.6", + "tslib": "^1.9.3" } }, - "cli-truncate": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-0.2.1.tgz", - "integrity": "sha1-nxXPuwcFAFNpIWxiasfQWrkN1XQ=", + "angular-html-parser": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/angular-html-parser/-/angular-html-parser-1.3.0.tgz", + "integrity": "sha512-FCLuM8ZUt30qwiV5KlW8uWL9cwlS2loOIGq8wUQFypkJ1QZqJk829yxTsvp2DvCMZ7uLwfjIaIrKV5N2+RLiSQ==", "dev": true, "requires": { - "slice-ansi": "0.0.4", - "string-width": "^1.0.1" - }, - "dependencies": { - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - } + "tslib": "^1.9.3" } }, - "cli-width": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", - "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", - "dev": true - }, - "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "ansi-align": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz", + "integrity": "sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw==", "dev": true, "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" + "string-width": "^3.0.0" }, "dependencies": { "ansi-regex": { @@ -5927,2302 +2767,2364 @@ } } }, - "clone-response": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", - "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "ansi-colors": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", + "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", + "dev": true + }, + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "any-observable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/any-observable/-/any-observable-0.3.0.tgz", + "integrity": "sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog==", + "dev": true + }, + "anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", "dev": true, "requires": { - "mimic-response": "^1.0.0" + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" } }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "append-transform": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz", + "integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==", + "dev": true, + "requires": { + "default-require-extensions": "^3.0.0" + } + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", "dev": true }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", "dev": true }, - "collapse-white-space": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.6.tgz", - "integrity": "sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ==", + "arg": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.2.tgz", + "integrity": "sha512-+ytCkGcBtHZ3V2r2Z06AncYO8jz46UEamcspGoU8lHcEbpn6J77QK0vdWvChsclg/tM5XIJC5tnjmPp7Eq6Obg==", "dev": true }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, - "optional": true, "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" + "sprintf-js": "~1.0.2" } }, - "color-convert": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.2.tgz", - "integrity": "sha512-3NUJZdhMhcdPn8vJ9v2UQJoH0qqoGUkYTgFEPZaPjEtwmmKUfNV46zZmgB2M5M4DCEQHMaCfWHCxiBflLm04Tg==", + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true, + "optional": true + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true, + "optional": true + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true, + "optional": true + }, + "array-differ": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-2.1.0.tgz", + "integrity": "sha512-KbUpJgx909ZscOc/7CLATBFam7P1Z1QRQInvgT0UztM9Q72aGKCunKASAl7WNW0tnPmPyEMeMhdsfWhfmW037w==", + "dev": true + }, + "array-includes": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.1.tgz", + "integrity": "sha512-c2VXaCHl7zPsvpkFsw4nxvFie4fh1ur9bpcgsVkIjqn0H/Xwdg+7fv3n2r/isyS8EBj5b06M9kHyZuIr4El6WQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0", + "is-string": "^1.0.5" + } + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", "dev": true, "requires": { - "color-name": "1.1.1" + "array-uniq": "^1.0.1" } }, - "color-name": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.1.tgz", - "integrity": "sha1-SxQVMEz1ACjqgWQ2Q72C6gWANok=", - "dev": true - }, - "colors": { + "array-uniq": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", - "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", "dev": true }, - "combined-stream": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", - "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true, + "optional": true + }, + "array.prototype.flat": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz", + "integrity": "sha512-gBlRZV0VSmfPIeWfuuy56XZMvbVfbEUnOXUvt3F/eUUUSyzlgLxhEX4YAEpxNAogRGehPSnfXyPtYyKAhkzQhQ==", "dev": true, "requires": { - "delayed-stream": "~1.0.0" + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" } }, - "commander": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.0.tgz", - "integrity": "sha512-NIQrwvv9V39FHgGFm36+U9SMQzbiHvU79k+iADraJTpmrFFfx7Ds0IvDoAdZsDrknlkRk14OYoWXb57uTh7/sw==", + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", "dev": true }, - "commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=", "dev": true }, - "compare-versions": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.5.1.tgz", - "integrity": "sha512-9fGPIB7C6AyM18CJJBHt5EnCZDG3oiTJYy0NjfIAGjKpzv0tkxWko7TNQHF5ymqm7IH03tqmeuBxtvD+Izh6mg==", + "assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", "dev": true }, - "component-bind": { + "assign-symbols": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", - "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=", - "dev": true + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true, + "optional": true }, - "component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", "dev": true }, - "component-inherit": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", - "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=", - "dev": true + "async-each": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", + "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", + "dev": true, + "optional": true }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true, + "optional": true }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", "dev": true, "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" } }, - "connect": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", - "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", + "babel-eslint": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-7.2.3.tgz", + "integrity": "sha1-sv4tgBJkcPXBlELcdXJTqJdxCCc=", "dev": true, "requires": { - "debug": "2.6.9", - "finalhandler": "1.1.2", - "parseurl": "~1.3.3", - "utils-merge": "1.0.1" + "babel-code-frame": "^6.22.0", + "babel-traverse": "^6.23.1", + "babel-types": "^6.23.0", + "babylon": "^6.17.0" } }, - "contains-path": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", - "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", - "dev": true + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } }, - "content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", - "dev": true + "babel-plugin-dynamic-import-node": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz", + "integrity": "sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ==", + "dev": true, + "requires": { + "object.assign": "^4.1.0" + } }, - "convert-source-map": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", - "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=", - "dev": true + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, + "requires": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + } }, - "cookie": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", - "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", + "babel-traverse": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", + "dev": true, + "requires": { + "babel-code-frame": "^6.26.0", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "debug": "^2.6.8", + "globals": "^9.18.0", + "invariant": "^2.2.2", + "lodash": "^4.17.4" + } + }, + "babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" + } + }, + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", "dev": true }, - "copy-concurrently": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", - "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "backbone": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/backbone/-/backbone-1.4.0.tgz", + "integrity": "sha512-RLmDrRXkVdouTg38jcgHhyQ/2zjg7a8E6sz2zxfz21Hh17xDJYUHBZimVIt5fUyS8vbfpeSmTL3gUjTEvUV3qQ==", "dev": true, "requires": { - "aproba": "^1.1.1", - "fs-write-stream-atomic": "^1.0.8", - "iferr": "^0.1.5", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.0" + "underscore": ">=1.8.3" } }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "bail": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz", + "integrity": "sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ==", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", "dev": true, - "optional": true + "optional": true, + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "optional": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "optional": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "optional": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "optional": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } }, - "core-js": { - "version": "2.5.7", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz", - "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==", + "binary-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz", + "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==", "dev": true }, - "core-js-compat": { - "version": "3.6.4", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.6.4.tgz", - "integrity": "sha512-zAa3IZPvsJ0slViBQ2z+vgyyTuhd3MFn1rBQjZSKVEgB0UMYhUkCj9jJUVPgGTGqWvsBVmfnruXgTcNyTlEiSA==", + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", "dev": true, + "optional": true, "requires": { - "browserslist": "^4.8.3", - "semver": "7.0.0" + "file-uri-to-path": "1.0.0" + } + }, + "boxen": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-3.2.0.tgz", + "integrity": "sha512-cU4J/+NodM3IHdSL2yN8bqYqnmlBTidDR4RC7nJs61ZmtGz8VZzM3HLQX0zY5mrSmPtR3xWwsq2jOUQqFZN8+A==", + "dev": true, + "requires": { + "ansi-align": "^3.0.0", + "camelcase": "^5.3.1", + "chalk": "^2.4.2", + "cli-boxes": "^2.2.0", + "string-width": "^3.0.0", + "term-size": "^1.2.0", + "type-fest": "^0.3.0", + "widest-line": "^2.0.0" }, "dependencies": { - "browserslist": { - "version": "4.8.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.8.5.tgz", - "integrity": "sha512-4LMHuicxkabIB+n9874jZX/az1IaZ5a+EUuvD7KFOu9x/Bd5YHyO0DIz2ls/Kl8g0ItS4X/ilEgf4T1Br0lgSg==", + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30001022", - "electron-to-chromium": "^1.3.338", - "node-releases": "^1.1.46" + "color-convert": "^1.9.0" } }, - "caniuse-lite": { - "version": "1.0.30001022", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001022.tgz", - "integrity": "sha512-FjwPPtt/I07KyLPkBQ0g7/XuZg6oUkYBVnPHNj3VHJbOjmmJ/GdSo/GUY6MwINEQvjhP6WZVbX8Tvms8xh0D5A==", - "dev": true + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } }, - "electron-to-chromium": { - "version": "1.3.340", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.340.tgz", - "integrity": "sha512-hRFBAglhcj5iVYH+o8QU0+XId1WGoc0VGowJB1cuJAt3exHGrivZvWeAO5BRgBZqwZtwxjm8a5MQeGoT/Su3ww==", + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", "dev": true }, - "semver": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", - "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", - "dev": true - } - } - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true - }, - "cosmiconfig": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", - "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", - "dev": true, - "requires": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.1.0", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.7.2" - }, - "dependencies": { - "parse-json": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.0.0.tgz", - "integrity": "sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw==", + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", "dev": true, "requires": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1", - "lines-and-columns": "^1.1.6" + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" } }, - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "type-fest": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz", + "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==", "dev": true } } }, - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "crypto-random-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", - "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=", - "dev": true - }, - "custom-event": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", - "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=", - "dev": true - }, - "d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "requires": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dev": true, "requires": { - "assert-plus": "^1.0.0" + "fill-range": "^7.0.1" } }, - "dashify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dashify/-/dashify-2.0.0.tgz", - "integrity": "sha512-hpA5C/YrPjucXypHPPc0oJ1l9Hf6wWbiOL7Ik42cxnsUOhWiCB/fylKbKqqJalW9FgkNQCw16YO8uW9Hs0Iy1A==", - "dev": true - }, - "date-fns": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz", - "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==", - "dev": true - }, - "date-format": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-2.1.0.tgz", - "integrity": "sha512-bYQuGLeFxhkxNOF3rcMtiZxvCBAquGzZm6oWA1oZ0g2THUzivaRhv8uOhdr19LmoobSOLoIAxeUK2RdbM8IFTA==", + "browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "browserslist": { + "version": "4.8.6", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.8.6.tgz", + "integrity": "sha512-ZHao85gf0eZ0ESxLfCp73GG9O/VTytYDIkIiZDlURppLTI9wErSM/5yAKEq6rcUdxBLjMELmrYUJGg5sxGKMHg==", "dev": true, "requires": { - "ms": "2.0.0" + "caniuse-lite": "^1.0.30001023", + "electron-to-chromium": "^1.3.341", + "node-releases": "^1.1.47" } }, - "debug-log": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/debug-log/-/debug-log-1.0.1.tgz", - "integrity": "sha1-IwdjLUwEOCuN+KMvcLiVBG1SdF8=", - "dev": true - }, - "debuglog": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/debuglog/-/debuglog-1.0.1.tgz", - "integrity": "sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI=", + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", "dev": true }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "builtins": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz", + "integrity": "sha1-y5T662HIaWRR2zZTThQi+U8K7og=", "dev": true }, - "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", - "dev": true, - "optional": true - }, - "decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "cacache": { + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-13.0.1.tgz", + "integrity": "sha512-5ZvAxd05HDDU+y9BVvcqYu2LLXmPnQ0hW62h32g4xBTgL/MppR4/04NHfj/ycM2y6lmTnbw6HVi+1eN0Psba6w==", "dev": true, "requires": { - "mimic-response": "^1.0.0" + "chownr": "^1.1.2", + "figgy-pudding": "^3.5.1", + "fs-minipass": "^2.0.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.2", + "infer-owner": "^1.0.4", + "lru-cache": "^5.1.1", + "minipass": "^3.0.0", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "p-map": "^3.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^2.7.1", + "ssri": "^7.0.0", + "unique-filename": "^1.1.1" + }, + "dependencies": { + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", + "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", + "dev": true + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "p-map": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", + "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", + "dev": true, + "requires": { + "aggregate-error": "^3.0.0" + } + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } } }, - "dedent": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", - "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", - "dev": true - }, - "deep-eql": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", - "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", "dev": true, + "optional": true, "requires": { - "type-detect": "^4.0.0" + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" } }, - "deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true - }, - "deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true - }, - "default-require-extensions": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.0.tgz", - "integrity": "sha512-ek6DpXq/SCpvjhpFsLFRVtIxJCRw6fUR42lYMVZuUMK7n8eMz4Uh5clckdBjEpLhn/gEBZo7hDJnJcwdKLKQjg==", + "cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", "dev": true, "requires": { - "strip-bom": "^4.0.0" + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" }, "dependencies": { - "strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "get-stream": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz", + "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", "dev": true } } }, - "defer-to-connect": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.1.tgz", - "integrity": "sha512-J7thop4u3mRTkYRQ+Vpfwy2G5Ehoy82I14+14W4YMDLKdWloI9gSzRbV30s/NckQGVJtPkWNcW4oMAUigTdqiQ==", - "dev": true - }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, - "requires": { - "object-keys": "^1.0.12" - } - }, - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "caching-transform": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", + "integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==", "dev": true, - "optional": true, "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" + "hasha": "^5.0.0", + "make-dir": "^3.0.0", + "package-hash": "^4.0.0", + "write-file-atomic": "^3.0.0" }, "dependencies": { - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "hasha": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.1.0.tgz", + "integrity": "sha512-OFPDWmzPN1l7atOV1TgBVmNtBxaIysToK6Ve9DK+vT6pYuklw/nPNT+HJbZi0KDcI6vWB+9tgvZ5YD7fA3CXcA==", "dev": true, - "optional": true, "requires": { - "kind-of": "^6.0.0" + "is-stream": "^2.0.0", + "type-fest": "^0.8.0" } }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "optional": true, - "requires": { - "kind-of": "^6.0.0" - } + "is-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", + "dev": true }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "make-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.0.0.tgz", + "integrity": "sha512-grNJDhb8b1Jm1qeqW5R/O63wUo4UXo2v2HMic6YT9i/HBlF93S8jkMgH7yugvY9ABDShH4VZMn8I+U8+fCNegw==", "dev": true, - "optional": true, "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "semver": "^6.0.0" } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true } } }, - "deglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/deglob/-/deglob-2.1.1.tgz", - "integrity": "sha512-2kjwuGGonL7gWE1XU4Fv79+vVzpoQCl0V+boMwWtOQJV2AGDabCwez++nB1Nli/8BabAfZQ/UuHPlp6AymKdWw==", + "caller-callsite": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", + "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", "dev": true, "requires": { - "find-root": "^1.0.0", - "glob": "^7.0.5", - "ignore": "^3.0.9", - "pkg-config": "^1.1.0", - "run-parallel": "^1.1.2", - "uniq": "^1.0.1" + "callsites": "^2.0.0" }, "dependencies": { - "ignore": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", - "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", + "callsites": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", + "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", "dev": true } } }, - "del": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", - "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "caller-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", + "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", "dev": true, "requires": { - "globby": "^5.0.0", - "is-path-cwd": "^1.0.0", - "is-path-in-cwd": "^1.0.0", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "rimraf": "^2.2.8" + "callsites": "^0.2.0" + } + }, + "callsites": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "caniuse-lite": { + "version": "1.0.30001025", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001025.tgz", + "integrity": "sha512-SKyFdHYfXUZf5V85+PJgLYyit27q4wgvZuf8QTOk1osbypcROihMBlx9GRar2/pIcKH2r4OehdlBr9x6PXetAQ==", + "dev": true + }, + "chai": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", + "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", + "dev": true, + "requires": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^3.0.1", + "get-func-name": "^2.0.0", + "pathval": "^1.1.0", + "type-detect": "^4.0.5" + } + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" } }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "character-entities": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz", + "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==", + "dev": true + }, + "character-entities-legacy": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz", + "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==", + "dev": true + }, + "character-reference-invalid": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz", + "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==", "dev": true }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", "dev": true }, - "detect-newline": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", - "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=", + "check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", "dev": true }, - "dezalgo": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.3.tgz", - "integrity": "sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY=", + "chokidar": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.0.tgz", + "integrity": "sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A==", "dev": true, "requires": { - "asap": "^2.0.0", - "wrappy": "1" + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.1.1", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.2.0" } }, - "di": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", - "integrity": "sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=", + "chownr": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.3.tgz", + "integrity": "sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw==", "dev": true }, - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", "dev": true }, - "dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "cint": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/cint/-/cint-8.2.1.tgz", + "integrity": "sha1-cDhrG0jidz0NYxZqVa/5TvRFahI=", + "dev": true + }, + "circular-json": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", + "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", + "dev": true + }, + "cjk-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cjk-regex/-/cjk-regex-2.0.0.tgz", + "integrity": "sha512-E4gFi2f3jC0zFVHpaAcupW+gv9OejZ2aV3DP/LlSO0dDcZJAXw7W0ivn+vN17edN/PhU4HCgs1bfx7lPK7FpdA==", "dev": true, "requires": { - "path-type": "^4.0.0" + "regexp-util": "^1.2.1", + "unicode-regex": "^2.0.0" }, "dependencies": { - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true + "unicode-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-regex/-/unicode-regex-2.0.0.tgz", + "integrity": "sha512-5nbEG2YU7loyTvPABaKb+8B0u8L7vWCsVmCSsiaO249ZdMKlvrXlxR2ex4TUVAdzv/Cne/TdoXSSaJArGXaleQ==", + "dev": true, + "requires": { + "regexp-util": "^1.2.0" + } } } }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "dom-serialize": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", - "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=", - "dev": true, - "requires": { - "custom-event": "~1.0.0", - "ent": "~2.2.0", - "extend": "^3.0.0", - "void-elements": "^2.0.0" - } - }, - "dom-serializer": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", - "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", "dev": true, + "optional": true, "requires": { - "domelementtype": "^2.0.1", - "entities": "^2.0.0" + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" }, "dependencies": { - "domelementtype": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.1.tgz", - "integrity": "sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ==", - "dev": true - }, - "entities": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.0.tgz", - "integrity": "sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw==", - "dev": true + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "optional": true, + "requires": { + "is-descriptor": "^0.1.0" + } } } }, - "domelementtype": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", - "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", + "clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", "dev": true }, - "domhandler": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", - "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", - "dev": true, - "requires": { - "domelementtype": "1" - } + "cli-boxes": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.0.tgz", + "integrity": "sha512-gpaBrMAizVEANOpfZp/EEUixTXDyGt7DFzdK5hU+UbWt/J0lB0w20ncZj59Z9a93xHb9u12zF5BS6i9RKbtg4w==", + "dev": true }, - "domutils": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", - "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", "dev": true, "requires": { - "dom-serializer": "0", - "domelementtype": "1" + "restore-cursor": "^2.0.0" } }, - "duplexer3": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", - "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", - "dev": true - }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "cli-table": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.1.tgz", + "integrity": "sha1-9TsFJmqLGguTSz0IIebi3FkUriM=", "dev": true, - "optional": true, "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" + "colors": "1.0.3" } }, - "editorconfig": { - "version": "0.15.3", - "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.3.tgz", - "integrity": "sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g==", + "cli-truncate": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-0.2.1.tgz", + "integrity": "sha1-nxXPuwcFAFNpIWxiasfQWrkN1XQ=", "dev": true, "requires": { - "commander": "^2.19.0", - "lru-cache": "^4.1.5", - "semver": "^5.6.0", - "sigmund": "^1.0.1" + "slice-ansi": "0.0.4", + "string-width": "^1.0.1" }, "dependencies": { - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "editorconfig-to-prettier": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/editorconfig-to-prettier/-/editorconfig-to-prettier-0.1.1.tgz", - "integrity": "sha512-MMadSSVRDb4uKdxV6bCXXN4cTsxIsXYtV4XdPu6FOCSAw6zsCIDA+QEktEU+u6h+c/mTrul5NR+pwFpPxwetiQ==", - "dev": true - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", - "dev": true - }, - "elegant-spinner": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz", - "integrity": "sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", - "dev": true - }, - "encoding": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", - "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", - "dev": true, - "optional": true, - "requires": { - "iconv-lite": "~0.4.13" - } - }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "requires": { - "once": "^1.4.0" + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } } }, - "engine.io": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.1.tgz", - "integrity": "sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w==", + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", + "dev": true + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", "dev": true, "requires": { - "accepts": "~1.3.4", - "base64id": "1.0.0", - "cookie": "0.3.1", - "debug": "~3.1.0", - "engine.io-parser": "~2.1.0", - "ws": "~3.3.1" + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" }, "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { - "ms": "2.0.0" + "color-convert": "^1.9.0" } - } - } - }, - "engine.io-client": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", - "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==", - "dev": true, - "requires": { - "component-emitter": "1.2.1", - "component-inherit": "0.0.3", - "debug": "~3.1.0", - "engine.io-parser": "~2.1.1", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "parseqs": "0.0.5", - "parseuri": "0.0.5", - "ws": "~3.3.1", - "xmlhttprequest-ssl": "~1.5.4", - "yeast": "0.1.2" - }, - "dependencies": { - "debug": { + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "string-width": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "dev": true, "requires": { - "ms": "2.0.0" + "ansi-regex": "^4.1.0" + } + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" } } } }, - "engine.io-parser": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz", - "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==", + "clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", "dev": true, "requires": { - "after": "0.8.2", - "arraybuffer.slice": "~0.0.7", - "base64-arraybuffer": "0.1.5", - "blob": "0.0.5", - "has-binary2": "~1.0.2" + "mimic-response": "^1.0.0" } }, - "ent": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", - "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=", + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", "dev": true }, - "entities": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", - "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", "dev": true }, - "err-code": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/err-code/-/err-code-1.1.2.tgz", - "integrity": "sha1-BuARbTAo9q70gGhJ6w6mp0iuaWA=", + "collapse-white-space": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.6.tgz", + "integrity": "sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ==", "dev": true }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", "dev": true, + "optional": true, "requires": { - "is-arrayish": "^0.2.1" + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" } }, - "es-abstract": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz", - "integrity": "sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==", + "color-convert": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.2.tgz", + "integrity": "sha512-3NUJZdhMhcdPn8vJ9v2UQJoH0qqoGUkYTgFEPZaPjEtwmmKUfNV46zZmgB2M5M4DCEQHMaCfWHCxiBflLm04Tg==", "dev": true, "requires": { - "es-to-primitive": "^1.1.1", - "function-bind": "^1.1.1", - "has": "^1.0.1", - "is-callable": "^1.1.3", - "is-regex": "^1.0.4" + "color-name": "1.1.1" } }, - "es-to-primitive": { + "color-name": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz", - "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha1-SxQVMEz1ACjqgWQ2Q72C6gWANok=", + "dev": true + }, + "colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=", + "dev": true + }, + "commander": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.0.tgz", + "integrity": "sha512-NIQrwvv9V39FHgGFm36+U9SMQzbiHvU79k+iADraJTpmrFFfx7Ds0IvDoAdZsDrknlkRk14OYoWXb57uTh7/sw==", + "dev": true + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, + "compare-versions": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.5.1.tgz", + "integrity": "sha512-9fGPIB7C6AyM18CJJBHt5EnCZDG3oiTJYy0NjfIAGjKpzv0tkxWko7TNQHF5ymqm7IH03tqmeuBxtvD+Izh6mg==", + "dev": true + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true, + "optional": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", "dev": true, "requires": { - "is-callable": "^1.1.1", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.1" + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" } }, - "es5-ext": { - "version": "0.10.53", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", - "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", + "configstore": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-4.0.0.tgz", + "integrity": "sha512-CmquAXFBocrzaSM8mtGPMM/HiWmyIpr4CcJl/rgY2uCObZ/S7cKU0silxslqJejl+t/T9HS8E0PUNQD81JGUEQ==", "dev": true, "requires": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.3", - "next-tick": "~1.0.0" + "dot-prop": "^4.1.0", + "graceful-fs": "^4.1.2", + "make-dir": "^1.0.0", + "unique-string": "^1.0.0", + "write-file-atomic": "^2.0.0", + "xdg-basedir": "^3.0.0" + }, + "dependencies": { + "write-file-atomic": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + } } }, - "es6-error": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", - "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "contains-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", + "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", "dev": true }, - "es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", "dev": true, "requires": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" + "safe-buffer": "~5.1.1" } }, - "es6-map": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", - "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", + "copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", "dev": true, "requires": { - "d": "1", - "es5-ext": "~0.10.14", - "es6-iterator": "~2.0.1", - "es6-set": "~0.1.5", - "es6-symbol": "~3.1.1", - "event-emitter": "~0.3.5" + "aproba": "^1.1.1", + "fs-write-stream-atomic": "^1.0.8", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.0" } }, - "es6-promise": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.4.tgz", - "integrity": "sha512-/NdNZVJg+uZgtm9eS3O6lrOLYmQag2DjdEXuPaHlZ6RuVqgqaVZfgYCepEIKsLqwdQArOPtC3XzRLqGGfT8KQQ==", - "dev": true - }, - "es6-promisify": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", - "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", "dev": true, - "requires": { - "es6-promise": "^4.0.3" - } + "optional": true }, - "es6-set": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", - "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", + "core-js": { + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", + "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==", + "dev": true + }, + "core-js-compat": { + "version": "3.6.4", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.6.4.tgz", + "integrity": "sha512-zAa3IZPvsJ0slViBQ2z+vgyyTuhd3MFn1rBQjZSKVEgB0UMYhUkCj9jJUVPgGTGqWvsBVmfnruXgTcNyTlEiSA==", "dev": true, "requires": { - "d": "1", - "es5-ext": "~0.10.14", - "es6-iterator": "~2.0.1", - "es6-symbol": "3.1.1", - "event-emitter": "~0.3.5" + "browserslist": "^4.8.3", + "semver": "7.0.0" }, "dependencies": { - "es6-symbol": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", - "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "~0.10.14" - } + "semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "dev": true } } }, - "es6-symbol": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", - "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "cosmiconfig": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", + "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", "dev": true, "requires": { - "d": "^1.0.1", - "ext": "^1.1.2" + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.7.2" } }, - "es6-weak-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", - "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", "dev": true, "requires": { - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.1" + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" } }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "crypto-random-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", + "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=", "dev": true }, - "escope": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", - "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", + "d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", "dev": true, "requires": { - "es6-map": "^0.1.3", - "es6-weak-map": "^2.0.1", - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" + "es5-ext": "^0.10.50", + "type": "^1.0.1" } }, - "eslint": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.8.0.tgz", - "integrity": "sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "ajv": "^6.10.0", - "chalk": "^2.1.0", - "cross-spawn": "^6.0.5", - "debug": "^4.0.1", - "doctrine": "^3.0.0", - "eslint-scope": "^5.0.0", - "eslint-utils": "^1.4.3", - "eslint-visitor-keys": "^1.1.0", - "espree": "^6.1.2", - "esquery": "^1.0.1", - "esutils": "^2.0.2", - "file-entry-cache": "^5.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.0.0", - "globals": "^12.1.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "inquirer": "^7.0.0", - "is-glob": "^4.0.0", - "js-yaml": "^3.13.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.3.0", - "lodash": "^4.17.14", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.1", - "natural-compare": "^1.4.0", - "optionator": "^0.8.3", - "progress": "^2.0.0", - "regexpp": "^2.0.1", - "semver": "^6.1.2", - "strip-ansi": "^5.2.0", - "strip-json-comments": "^3.0.1", - "table": "^5.2.3", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", - "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", - "dev": true, - "requires": { - "@babel/highlight": "^7.8.3" - } - }, - "@babel/highlight": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", - "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", - "dev": true, - "requires": { - "chalk": "^2.0.0", - "esutils": "^2.0.2", - "js-tokens": "^4.0.0" - } - }, - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "eslint-scope": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz", - "integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==", - "dev": true, - "requires": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - } - }, - "eslint-utils": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", - "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^1.1.0" - } - }, - "eslint-visitor-keys": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", - "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", - "dev": true - }, - "file-entry-cache": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", - "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", - "dev": true, - "requires": { - "flat-cache": "^2.0.1" - } - }, - "flat-cache": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", - "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", - "dev": true, - "requires": { - "flatted": "^2.0.0", - "rimraf": "2.6.3", - "write": "1.0.3" - } - }, - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz", - "integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - }, - "dependencies": { - "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - } - } - }, - "globals": { - "version": "12.3.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-12.3.0.tgz", - "integrity": "sha512-wAfjdLgFsPZsklLJvOBUBmzYE8/CwhEqSBEMRXA3qxIiNtyqvjYurAtIfDh6chlEPUfmTY3MnZh5Hfh4q0UlIw==", - "dev": true, - "requires": { - "type-fest": "^0.8.1" - } - }, - "js-tokens": { + "dashify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dashify/-/dashify-2.0.0.tgz", + "integrity": "sha512-hpA5C/YrPjucXypHPPc0oJ1l9Hf6wWbiOL7Ik42cxnsUOhWiCB/fylKbKqqJalW9FgkNQCw16YO8uW9Hs0Iy1A==", + "dev": true + }, + "date-fns": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz", + "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "debug-log": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/debug-log/-/debug-log-1.0.1.tgz", + "integrity": "sha1-IwdjLUwEOCuN+KMvcLiVBG1SdF8=", + "dev": true + }, + "debuglog": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/debuglog/-/debuglog-1.0.1.tgz", + "integrity": "sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI=", + "dev": true + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true, + "optional": true + }, + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + } + }, + "dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", + "dev": true + }, + "deep-eql": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", + "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "dev": true, + "requires": { + "type-detect": "^4.0.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "default-require-extensions": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.0.tgz", + "integrity": "sha512-ek6DpXq/SCpvjhpFsLFRVtIxJCRw6fUR42lYMVZuUMK7n8eMz4Uh5clckdBjEpLhn/gEBZo7hDJnJcwdKLKQjg==", + "dev": true, + "requires": { + "strip-bom": "^4.0.0" + }, + "dependencies": { + "strip-bom": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", "dev": true - }, - "optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + } + } + }, + "defer-to-connect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.1.tgz", + "integrity": "sha512-J7thop4u3mRTkYRQ+Vpfwy2G5Ehoy82I14+14W4YMDLKdWloI9gSzRbV30s/NckQGVJtPkWNcW4oMAUigTdqiQ==", + "dev": true + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "optional": true, + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, + "optional": true, "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" + "kind-of": "^6.0.0" } }, - "regexpp": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", - "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", - "dev": true - }, - "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "dev": true, + "optional": true, "requires": { - "glob": "^7.1.3" + "kind-of": "^6.0.0" } }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, + "optional": true, "requires": { - "ansi-regex": "^4.1.0" + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" } - }, - "strip-json-comments": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", - "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", + } + } + }, + "deglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/deglob/-/deglob-2.1.1.tgz", + "integrity": "sha512-2kjwuGGonL7gWE1XU4Fv79+vVzpoQCl0V+boMwWtOQJV2AGDabCwez++nB1Nli/8BabAfZQ/UuHPlp6AymKdWw==", + "dev": true, + "requires": { + "find-root": "^1.0.0", + "glob": "^7.0.5", + "ignore": "^3.0.9", + "pkg-config": "^1.1.0", + "run-parallel": "^1.1.2", + "uniq": "^1.0.1" + }, + "dependencies": { + "ignore": { + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", + "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "write": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", - "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", - "dev": true, - "requires": { - "mkdirp": "^0.5.1" - } } } }, - "eslint-config-standard": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-14.1.0.tgz", - "integrity": "sha512-EF6XkrrGVbvv8hL/kYa/m6vnvmUT+K82pJJc4JJVMM6+Qgqh0pnwprSxdduDLB9p/7bIxD+YV5O0wfb8lmcPbA==", + "del": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "dev": true, + "requires": { + "globby": "^5.0.0", + "is-path-cwd": "^1.0.0", + "is-path-in-cwd": "^1.0.0", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "rimraf": "^2.2.8" + } + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true + }, + "detect-newline": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", + "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=", "dev": true }, - "eslint-config-standard-jsx": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/eslint-config-standard-jsx/-/eslint-config-standard-jsx-3.2.0.tgz", - "integrity": "sha1-wkDibtkZoRpCqk3oBZRys4Jo1iA=", + "dezalgo": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.3.tgz", + "integrity": "sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY=", + "dev": true, + "requires": { + "asap": "^2.0.0", + "wrappy": "1" + } + }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", "dev": true }, - "eslint-import-resolver-node": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz", - "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==", + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, "requires": { - "debug": "^2.6.9", - "resolve": "^1.5.0" + "path-type": "^4.0.0" } }, - "eslint-module-utils": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.5.2.tgz", - "integrity": "sha512-LGScZ/JSlqGKiT8OC+cYRxseMjyqt6QO54nl281CK93unD89ijSeRV6An8Ci/2nvWVKe8K/Tqdm75RQoIOCr+Q==", + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, "requires": { - "debug": "^2.6.9", - "pkg-dir": "^2.0.0" + "esutils": "^2.0.2" + } + }, + "dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", + "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" }, "dependencies": { - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } + "domelementtype": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.1.tgz", + "integrity": "sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ==", + "dev": true }, - "pkg-dir": { + "entities": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", - "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", - "dev": true, - "requires": { - "find-up": "^2.1.0" - } + "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.0.tgz", + "integrity": "sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw==", + "dev": true } } }, - "eslint-plugin-es": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.0.tgz", - "integrity": "sha512-6/Jb/J/ZvSebydwbBJO1R9E5ky7YeElfK56Veh7e4QGFHCXoIXGH9HhVz+ibJLM3XJ1XjP+T7rKBLUa/Y7eIng==", + "domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", + "dev": true + }, + "domhandler": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", + "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", "dev": true, "requires": { - "eslint-utils": "^2.0.0", - "regexpp": "^3.0.0" + "domelementtype": "1" } }, - "eslint-plugin-import": { - "version": "2.20.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.20.0.tgz", - "integrity": "sha512-NK42oA0mUc8Ngn4kONOPsPB1XhbUvNHqF+g307dPV28aknPoiNnKLFd9em4nkswwepdF5ouieqv5Th/63U7YJQ==", + "domutils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", + "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", "dev": true, "requires": { - "array-includes": "^3.0.3", - "array.prototype.flat": "^1.2.1", - "contains-path": "^0.1.0", - "debug": "^2.6.9", - "doctrine": "1.5.0", - "eslint-import-resolver-node": "^0.3.2", - "eslint-module-utils": "^2.4.1", - "has": "^1.0.3", - "minimatch": "^3.0.4", - "object.values": "^1.1.0", - "read-pkg-up": "^2.0.0", - "resolve": "^1.12.0" - }, - "dependencies": { - "doctrine": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", - "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "isarray": "^1.0.0" - } - }, - "eslint-module-utils": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.5.2.tgz", - "integrity": "sha512-LGScZ/JSlqGKiT8OC+cYRxseMjyqt6QO54nl281CK93unD89ijSeRV6An8Ci/2nvWVKe8K/Tqdm75RQoIOCr+Q==", - "dev": true, - "requires": { - "debug": "^2.6.9", - "pkg-dir": "^2.0.0" - } - }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "pkg-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", - "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", - "dev": true, - "requires": { - "find-up": "^2.1.0" - } - }, - "resolve": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.0.tgz", - "integrity": "sha512-+hTmAldEGE80U2wJJDC1lebb5jWqvTYAfm3YZ1ckk1gBr0MnCqUKlwK1e+anaFljIl+F5tR5IoZcm4ZDA1zMQw==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } - } + "dom-serializer": "0", + "domelementtype": "1" } }, - "eslint-plugin-node": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.0.0.tgz", - "integrity": "sha512-chUs/NVID+sknFiJzxoN9lM7uKSOEta8GC8365hw1nDfwIPIjjpRSwwPvQanWv8dt/pDe9EV4anmVSwdiSndNg==", + "dot-prop": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", + "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", "dev": true, "requires": { - "eslint-plugin-es": "^3.0.0", - "eslint-utils": "^2.0.0", - "ignore": "^5.1.1", - "minimatch": "^3.0.4", - "resolve": "^1.10.1", - "semver": "^6.1.0" + "is-obj": "^1.0.0" + } + }, + "duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", + "dev": true + }, + "editorconfig": { + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.3.tgz", + "integrity": "sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g==", + "dev": true, + "requires": { + "commander": "^2.19.0", + "lru-cache": "^4.1.5", + "semver": "^5.6.0", + "sigmund": "^1.0.1" }, "dependencies": { - "ignore": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.4.tgz", - "integrity": "sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A==", + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true }, - "resolve": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.0.tgz", - "integrity": "sha512-+hTmAldEGE80U2wJJDC1lebb5jWqvTYAfm3YZ1ckk1gBr0MnCqUKlwK1e+anaFljIl+F5tR5IoZcm4ZDA1zMQw==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } - }, "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true } } }, - "eslint-plugin-promise": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-4.2.1.tgz", - "integrity": "sha512-VoM09vT7bfA7D+upt+FjeBO5eHIJQBUWki1aPvB+vbNiHS3+oGIJGIeyBtKQTME6UPXXy3vV07OL1tHd3ANuDw==", + "editorconfig-to-prettier": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/editorconfig-to-prettier/-/editorconfig-to-prettier-0.1.1.tgz", + "integrity": "sha512-MMadSSVRDb4uKdxV6bCXXN4cTsxIsXYtV4XdPu6FOCSAw6zsCIDA+QEktEU+u6h+c/mTrul5NR+pwFpPxwetiQ==", "dev": true }, - "eslint-plugin-react": { - "version": "6.7.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-6.7.1.tgz", - "integrity": "sha1-Gvlq6lRYVoJRV9l8G1DVqPtkpac=", + "electron-to-chromium": { + "version": "1.3.345", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.345.tgz", + "integrity": "sha512-f8nx53+Z9Y+SPWGg3YdHrbYYfIJAtbUjpFfW4X1RwTZ94iUG7geg9tV8HqzAXX7XTNgyWgAFvce4yce8ZKxKmg==", + "dev": true + }, + "elegant-spinner": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz", + "integrity": "sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "encoding": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", + "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", "dev": true, + "optional": true, "requires": { - "doctrine": "^1.2.2", - "jsx-ast-utils": "^1.3.3" - }, - "dependencies": { - "doctrine": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", - "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "isarray": "^1.0.0" - } - } + "iconv-lite": "~0.4.13" } }, - "eslint-plugin-standard": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-4.0.1.tgz", - "integrity": "sha512-v/KBnfyaOMPmZc/dmc6ozOdWqekGp7bBGq4jLAecEfPGmfKiWS4sA8sC0LqiV9w5qmXAtXVn4M3p1jSyhY85SQ==", - "dev": true - }, - "eslint-scope": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz", - "integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==", + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", "dev": true, "requires": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" + "once": "^1.4.0" } }, - "eslint-utils": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.0.0.tgz", - "integrity": "sha512-0HCPuJv+7Wv1bACm8y5/ECVfYdfsAm9xmVb7saeFlxjPYALefjhbYoCkBjPdPzGH8wWyTpAez82Fh3VKYEZ8OA==", + "entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", + "dev": true + }, + "err-code": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-1.1.2.tgz", + "integrity": "sha1-BuARbTAo9q70gGhJ6w6mp0iuaWA=", + "dev": true + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "dev": true, "requires": { - "eslint-visitor-keys": "^1.1.0" + "is-arrayish": "^0.2.1" } }, - "eslint-visitor-keys": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", - "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", - "dev": true - }, - "espree": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/espree/-/espree-6.1.2.tgz", - "integrity": "sha512-2iUPuuPP+yW1PZaMSDM9eyVf8D5P0Hi8h83YtZ5bPc/zHYjII5khoixIUTMO794NOY8F/ThF1Bo8ncZILarUTA==", + "es-abstract": { + "version": "1.17.4", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.4.tgz", + "integrity": "sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ==", "dev": true, "requires": { - "acorn": "^7.1.0", - "acorn-jsx": "^5.1.0", - "eslint-visitor-keys": "^1.1.0" + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.5", + "is-regex": "^1.0.5", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.1", + "string.prototype.trimright": "^2.1.1" }, "dependencies": { - "acorn": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", - "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==", - "dev": true - }, - "eslint-visitor-keys": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", - "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "dev": true } } }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, - "esquery": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", - "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", "dev": true, "requires": { - "estraverse": "^4.0.0" + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" } }, - "esrecurse": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", - "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "es5-ext": { + "version": "0.10.53", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", + "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", "dev": true, "requires": { - "estraverse": "^4.1.0" + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.3", + "next-tick": "~1.0.0" } }, - "estraverse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", - "dev": true - }, - "estree-walker": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", - "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", + "es6-error": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", "dev": true }, - "esutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", - "dev": true + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } }, - "event-emitter": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "es6-map": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", + "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", "dev": true, "requires": { "d": "1", - "es5-ext": "~0.10.14" + "es5-ext": "~0.10.14", + "es6-iterator": "~2.0.1", + "es6-set": "~0.1.5", + "es6-symbol": "~3.1.1", + "event-emitter": "~0.3.5" } }, - "eventemitter3": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.0.tgz", - "integrity": "sha512-qerSRB0p+UDEssxTtm6EDKcE7W4OaoisfIMl4CngyEhjpYglocpNg6UEqCvemdGhosAsg4sO2dXJOdyBifPGCg==", + "es6-promise": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.4.tgz", + "integrity": "sha512-/NdNZVJg+uZgtm9eS3O6lrOLYmQag2DjdEXuPaHlZ6RuVqgqaVZfgYCepEIKsLqwdQArOPtC3XzRLqGGfT8KQQ==", "dev": true }, - "execa": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-3.4.0.tgz", - "integrity": "sha512-r9vdGQk4bmCuK1yKQu1KTwcT2zwfWdbdaXfCtAh+5nU/4fSX+JAb7vZGvI5naJrQlvONrEB20jeruESI69530g==", + "es6-promisify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", "dev": true, "requires": { - "cross-spawn": "^7.0.0", - "get-stream": "^5.0.0", - "human-signals": "^1.1.1", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.0", - "onetime": "^5.1.0", - "p-finally": "^2.0.0", - "signal-exit": "^3.0.2", - "strip-final-newline": "^2.0.0" - }, - "dependencies": { - "cross-spawn": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.1.tgz", - "integrity": "sha512-u7v4o84SwFpD32Z8IIcPZ6z1/ie24O6RU3RbtL5Y316l3KuHVPx9ItBgWQ6VlfAFnRnTtMUrsQ9MUUTuEZjogg==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "get-stream": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz", - "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "is-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", - "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", - "dev": true - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "requires": { - "path-key": "^3.0.0" - } - }, - "p-finally": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-2.0.1.tgz", - "integrity": "sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw==", - "dev": true - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } + "es6-promise": "^4.0.3" } }, - "exit-hook": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", - "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", - "dev": true - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "es6-set": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", + "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", "dev": true, - "optional": true, "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" + "d": "1", + "es5-ext": "~0.10.14", + "es6-iterator": "~2.0.1", + "es6-symbol": "3.1.1", + "event-emitter": "~0.3.5" }, "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "optional": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "es6-symbol": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", + "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", "dev": true, - "optional": true, "requires": { - "is-extendable": "^0.1.0" + "d": "1", + "es5-ext": "~0.10.14" } } } }, - "ext": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", - "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", + "es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", "dev": true, "requires": { - "type": "^2.0.0" - }, - "dependencies": { - "type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/type/-/type-2.0.0.tgz", - "integrity": "sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow==", - "dev": true - } + "d": "^1.0.1", + "ext": "^1.1.2" } }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "es6-weak-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", "dev": true, - "optional": true, "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "optional": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" } }, - "external-editor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", - "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "escope": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", + "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", "dev": true, "requires": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" - }, - "dependencies": { - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - } + "es6-map": "^0.1.3", + "es6-weak-map": "^2.0.1", + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" } }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "eslint": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.8.0.tgz", + "integrity": "sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig==", "dev": true, - "optional": true, "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" + "@babel/code-frame": "^7.0.0", + "ajv": "^6.10.0", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "eslint-scope": "^5.0.0", + "eslint-utils": "^1.4.3", + "eslint-visitor-keys": "^1.1.0", + "espree": "^6.1.2", + "esquery": "^1.0.1", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.0.0", + "globals": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "inquirer": "^7.0.0", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.14", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.3", + "progress": "^2.0.0", + "regexpp": "^2.0.1", + "semver": "^6.1.2", + "strip-ansi": "^5.2.0", + "strip-json-comments": "^3.0.1", + "table": "^5.2.3", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" }, "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "acorn": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", + "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==", + "dev": true + }, + "acorn-jsx": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.1.0.tgz", + "integrity": "sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw==", + "dev": true + }, + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, - "optional": true, "requires": { - "is-descriptor": "^1.0.0" + "color-convert": "^1.9.0" } }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, - "optional": true, "requires": { - "is-extendable": "^0.1.0" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" } }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", "dev": true, - "optional": true, "requires": { - "kind-of": "^6.0.0" + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } } }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, - "optional": true, "requires": { - "kind-of": "^6.0.0" + "ms": "^2.1.1" } }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, - "optional": true, "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "esutils": "^2.0.2" } - } - } - }, - "extract-zip": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.6.7.tgz", - "integrity": "sha1-qEC0uK9kAyZMjbV/Txp0Mz74H+k=", - "dev": true, - "requires": { - "concat-stream": "1.6.2", - "debug": "2.6.9", - "mkdirp": "0.5.1", - "yauzl": "2.4.1" - } - }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true - }, - "fast-deep-equal": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", - "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", - "dev": true - }, - "fast-diff": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", - "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", - "dev": true - }, - "fast-glob": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.1.1.tgz", - "integrity": "sha512-nTCREpBY8w8r+boyFYAx21iL6faSsQynliPHM4Uf56SbkyohCNxpVPEH9xrF5TXKy+IsjkPUHDKiUkzBVRXn9g==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.0", - "merge2": "^1.3.0", - "micromatch": "^4.0.2" - }, - "dependencies": { - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + }, + "espree": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/espree/-/espree-6.1.2.tgz", + "integrity": "sha512-2iUPuuPP+yW1PZaMSDM9eyVf8D5P0Hi8h83YtZ5bPc/zHYjII5khoixIUTMO794NOY8F/ThF1Bo8ncZILarUTA==", + "dev": true, + "requires": { + "acorn": "^7.1.0", + "acorn-jsx": "^5.1.0", + "eslint-visitor-keys": "^1.1.0" + } + }, + "file-entry-cache": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", "dev": true, "requires": { - "fill-range": "^7.0.1" + "flat-cache": "^2.0.1" } }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "flat-cache": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", "dev": true, "requires": { - "to-regex-range": "^5.0.1" + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" } }, - "glob-parent": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz", - "integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==", + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", "dev": true, "requires": { - "is-glob": "^4.0.1" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } }, - "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "globals": { + "version": "12.3.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.3.0.tgz", + "integrity": "sha512-wAfjdLgFsPZsklLJvOBUBmzYE8/CwhEqSBEMRXA3qxIiNtyqvjYurAtIfDh6chlEPUfmTY3MnZh5Hfh4q0UlIw==", "dev": true, "requires": { - "is-extglob": "^2.1.1" + "type-fest": "^0.8.1" } }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", "dev": true }, - "micromatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", - "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "regexpp": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", + "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", + "dev": true + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", "dev": true, "requires": { - "braces": "^3.0.1", - "picomatch": "^2.0.5" + "glob": "^7.1.3" } }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "strip-json-comments": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", + "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "write": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", "dev": true, "requires": { - "is-number": "^7.0.0" + "mkdirp": "^0.5.1" } } } }, - "fast-json-stable-stringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "eslint-config-standard": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-14.1.0.tgz", + "integrity": "sha512-EF6XkrrGVbvv8hL/kYa/m6vnvmUT+K82pJJc4JJVMM6+Qgqh0pnwprSxdduDLB9p/7bIxD+YV5O0wfb8lmcPbA==", "dev": true }, - "fastq": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.6.0.tgz", - "integrity": "sha512-jmxqQ3Z/nXoeyDmWAzF9kH1aGZSis6e/SbfPmJpUnyZ0ogr6iscHQaml4wsEepEWSdtmpy+eVXmCRIMpxaXqOA==", - "dev": true, - "requires": { - "reusify": "^1.0.0" - } - }, - "fd-slicer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", - "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", - "dev": true, - "requires": { - "pend": "~1.2.0" - } - }, - "figgy-pudding": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.1.tgz", - "integrity": "sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==", + "eslint-config-standard-jsx": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/eslint-config-standard-jsx/-/eslint-config-standard-jsx-3.2.0.tgz", + "integrity": "sha1-wkDibtkZoRpCqk3oBZRys4Jo1iA=", "dev": true }, - "figures": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", - "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5", - "object-assign": "^4.1.0" - } - }, - "file-entry-cache": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", - "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "eslint-config-standard-with-typescript": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/eslint-config-standard-with-typescript/-/eslint-config-standard-with-typescript-12.0.1.tgz", + "integrity": "sha512-v0DDNzsb36Oun3N04Y27Ca9DfF+S9Orrdtqa5anUUpwIu/MMqCRxYAcKdD0Uao+Gzqz9EjaFYjBKZCPFyXH5jw==", "dev": true, "requires": { - "flat-cache": "^1.2.1", - "object-assign": "^4.0.1" + "@typescript-eslint/parser": "^2.10.0", + "eslint-config-standard": "^14.1.0" + }, + "dependencies": { + "eslint-config-standard": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-14.1.0.tgz", + "integrity": "sha512-EF6XkrrGVbvv8hL/kYa/m6vnvmUT+K82pJJc4JJVMM6+Qgqh0pnwprSxdduDLB9p/7bIxD+YV5O0wfb8lmcPbA==", + "dev": true + } } }, - "file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "dev": true, - "optional": true - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "eslint-import-resolver-node": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.3.tgz", + "integrity": "sha512-b8crLDo0M5RSe5YG8Pu2DYBj71tSB6OvXkfzwbJU2w7y8P4/yo0MyF8jU26IEuEuHF2K5/gcAJE3LhQGqBBbVg==", "dev": true, - "optional": true, "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" + "debug": "^2.6.9", + "resolve": "^1.13.1" }, "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "resolve": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.0.tgz", + "integrity": "sha512-+hTmAldEGE80U2wJJDC1lebb5jWqvTYAfm3YZ1ckk1gBr0MnCqUKlwK1e+anaFljIl+F5tR5IoZcm4ZDA1zMQw==", "dev": true, - "optional": true, "requires": { - "is-extendable": "^0.1.0" + "path-parse": "^1.0.6" } } } }, - "finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", - "dev": true, - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" - } - }, - "find-cache-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", - "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "eslint-module-utils": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.5.2.tgz", + "integrity": "sha512-LGScZ/JSlqGKiT8OC+cYRxseMjyqt6QO54nl281CK93unD89ijSeRV6An8Ci/2nvWVKe8K/Tqdm75RQoIOCr+Q==", "dev": true, "requires": { - "commondir": "^1.0.1", - "make-dir": "^2.0.0", - "pkg-dir": "^3.0.0" + "debug": "^2.6.9", + "pkg-dir": "^2.0.0" }, "dependencies": { "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", "dev": true, "requires": { - "locate-path": "^3.0.0" + "locate-path": "^2.0.0" } }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", "dev": true, "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" + "find-up": "^2.1.0" } - }, - "p-limit": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz", - "integrity": "sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==", + } + } + }, + "eslint-plugin-es": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.0.tgz", + "integrity": "sha512-6/Jb/J/ZvSebydwbBJO1R9E5ky7YeElfK56Veh7e4QGFHCXoIXGH9HhVz+ibJLM3XJ1XjP+T7rKBLUa/Y7eIng==", + "dev": true, + "requires": { + "eslint-utils": "^2.0.0", + "regexpp": "^3.0.0" + }, + "dependencies": { + "eslint-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.0.0.tgz", + "integrity": "sha512-0HCPuJv+7Wv1bACm8y5/ECVfYdfsAm9xmVb7saeFlxjPYALefjhbYoCkBjPdPzGH8wWyTpAez82Fh3VKYEZ8OA==", "dev": true, "requires": { - "p-try": "^2.0.0" + "eslint-visitor-keys": "^1.1.0" } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + } + } + }, + "eslint-plugin-import": { + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.20.0.tgz", + "integrity": "sha512-NK42oA0mUc8Ngn4kONOPsPB1XhbUvNHqF+g307dPV28aknPoiNnKLFd9em4nkswwepdF5ouieqv5Th/63U7YJQ==", + "dev": true, + "requires": { + "array-includes": "^3.0.3", + "array.prototype.flat": "^1.2.1", + "contains-path": "^0.1.0", + "debug": "^2.6.9", + "doctrine": "1.5.0", + "eslint-import-resolver-node": "^0.3.2", + "eslint-module-utils": "^2.4.1", + "has": "^1.0.3", + "minimatch": "^3.0.4", + "object.values": "^1.1.0", + "read-pkg-up": "^2.0.0", + "resolve": "^1.12.0" + }, + "dependencies": { + "doctrine": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", "dev": true, "requires": { - "p-limit": "^2.0.0" + "esutils": "^2.0.2", + "isarray": "^1.0.0" } }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - }, - "pkg-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "resolve": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.0.tgz", + "integrity": "sha512-+hTmAldEGE80U2wJJDC1lebb5jWqvTYAfm3YZ1ckk1gBr0MnCqUKlwK1e+anaFljIl+F5tR5IoZcm4ZDA1zMQw==", "dev": true, "requires": { - "find-up": "^3.0.0" + "path-parse": "^1.0.6" } } } }, - "find-parent-dir": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/find-parent-dir/-/find-parent-dir-0.3.0.tgz", - "integrity": "sha1-M8RLQpqysvBkYpnF+fcY83b/jVQ=", - "dev": true - }, - "find-project-root": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/find-project-root/-/find-project-root-1.1.1.tgz", - "integrity": "sha1-0kJyei2QRyXfVxTyPf3N7doLbvg=", - "dev": true - }, - "find-root": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", - "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", - "dev": true - }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "eslint-plugin-node": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.0.0.tgz", + "integrity": "sha512-chUs/NVID+sknFiJzxoN9lM7uKSOEta8GC8365hw1nDfwIPIjjpRSwwPvQanWv8dt/pDe9EV4anmVSwdiSndNg==", "dev": true, "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "eslint-plugin-es": "^3.0.0", + "eslint-utils": "^2.0.0", + "ignore": "^5.1.1", + "minimatch": "^3.0.4", + "resolve": "^1.10.1", + "semver": "^6.1.0" }, "dependencies": { - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "eslint-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.0.0.tgz", + "integrity": "sha512-0HCPuJv+7Wv1bACm8y5/ECVfYdfsAm9xmVb7saeFlxjPYALefjhbYoCkBjPdPzGH8wWyTpAez82Fh3VKYEZ8OA==", "dev": true, "requires": { - "p-locate": "^4.1.0" + "eslint-visitor-keys": "^1.1.0" } }, - "p-limit": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz", - "integrity": "sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } + "ignore": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.4.tgz", + "integrity": "sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A==", + "dev": true }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "resolve": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.0.tgz", + "integrity": "sha512-+hTmAldEGE80U2wJJDC1lebb5jWqvTYAfm3YZ1ckk1gBr0MnCqUKlwK1e+anaFljIl+F5tR5IoZcm4ZDA1zMQw==", "dev": true, "requires": { - "p-limit": "^2.2.0" + "path-parse": "^1.0.6" } }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true } } }, - "find-versions": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-3.2.0.tgz", - "integrity": "sha512-P8WRou2S+oe222TOCHitLy8zj+SIsVJh52VP4lvXkaFVnOFFdoWv1H1Jjvel1aI6NCFOAaeAVm8qrI0odiLcww==", - "dev": true, - "requires": { - "semver-regex": "^2.0.0" - } + "eslint-plugin-promise": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-4.2.1.tgz", + "integrity": "sha512-VoM09vT7bfA7D+upt+FjeBO5eHIJQBUWki1aPvB+vbNiHS3+oGIJGIeyBtKQTME6UPXXy3vV07OL1tHd3ANuDw==", + "dev": true }, - "flat": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", - "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==", + "eslint-plugin-react": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-6.7.1.tgz", + "integrity": "sha1-Gvlq6lRYVoJRV9l8G1DVqPtkpac=", "dev": true, "requires": { - "is-buffer": "~2.0.3" + "doctrine": "^1.2.2", + "jsx-ast-utils": "^1.3.3" }, "dependencies": { - "is-buffer": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", - "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==", - "dev": true + "doctrine": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "isarray": "^1.0.0" + } } } }, - "flat-cache": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", - "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", + "eslint-plugin-standard": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-4.0.1.tgz", + "integrity": "sha512-v/KBnfyaOMPmZc/dmc6ozOdWqekGp7bBGq4jLAecEfPGmfKiWS4sA8sC0LqiV9w5qmXAtXVn4M3p1jSyhY85SQ==", + "dev": true + }, + "eslint-scope": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz", + "integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==", "dev": true, "requires": { - "circular-json": "^0.3.1", - "del": "^2.0.2", - "graceful-fs": "^4.1.2", - "write": "^0.2.1" + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" } }, - "flatted": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz", - "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==", - "dev": true + "eslint-utils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", + "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } }, - "flatten": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.3.tgz", - "integrity": "sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg==", + "eslint-visitor-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", + "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", "dev": true }, - "flow-parser": { - "version": "0.111.3", - "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.111.3.tgz", - "integrity": "sha512-iEjGZ94OBMcESxnLorXNjJmtd/JtQYXUVrQpfwvtAKkuyawRmv+2LM6nqyOsOJkISEYbyY6ziudRE0u4VyPSVA==", + "espree": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", + "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", + "dev": true, + "requires": { + "acorn": "^5.5.0", + "acorn-jsx": "^3.0.0" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true }, - "follow-redirects": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.9.0.tgz", - "integrity": "sha512-CRcPzsSIbXyVDl0QI01muNDu69S8trU4jArW9LpOt2WtC6LyUJetcIrmfHsRBx7/Jb6GHJUiuqyYxPooFfNt6A==", + "esquery": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", + "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", + "dev": true, + "requires": { + "estraverse": "^4.0.0" + } + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", "dev": true, "requires": { - "debug": "^3.0.0" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } + "estraverse": "^4.1.0" } }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", "dev": true, - "optional": true + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } }, - "foreground-child": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", - "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", + "execa": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-3.4.0.tgz", + "integrity": "sha512-r9vdGQk4bmCuK1yKQu1KTwcT2zwfWdbdaXfCtAh+5nU/4fSX+JAb7vZGvI5naJrQlvONrEB20jeruESI69530g==", "dev": true, "requires": { "cross-spawn": "^7.0.0", - "signal-exit": "^3.0.2" + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "p-finally": "^2.0.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" }, "dependencies": { "cross-spawn": { @@ -8236,6 +5138,36 @@ "which": "^2.0.1" } }, + "get-stream": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz", + "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "is-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", + "dev": true + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "requires": { + "path-key": "^3.0.0" + } + }, + "p-finally": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-2.0.1.tgz", + "integrity": "sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw==", + "dev": true + }, "path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -8268,652 +5200,551 @@ } } }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true - }, - "form-data": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", - "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "1.0.6", - "mime-types": "^2.1.12" - } - }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "optional": true, - "requires": { - "map-cache": "^0.2.2" - } - }, - "fromentries": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.2.0.tgz", - "integrity": "sha512-33X7H/wdfO99GdRLLgkjUrD4geAFdq/Uv0kl3HD4da6HDixd2GUg8Mw7dahLCV9r/EARkmtYBB6Tch4EEokFTQ==", - "dev": true - }, - "fs-extra": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-1.0.0.tgz", - "integrity": "sha1-zTzl9+fLYUWIP8rjGR6Yd/hYeVA=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^2.1.0", - "klaw": "^1.0.0" - }, - "dependencies": { - "klaw": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", - "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.9" - } - } - } - }, - "fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "fs-readdir-recursive": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", - "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", - "dev": true - }, - "fs-write-stream-atomic": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", - "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "iferr": "^0.1.5", - "imurmurhash": "^0.1.4", - "readable-stream": "1 || 2" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "exit-hook": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", + "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", "dev": true }, - "fsevents": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.11.tgz", - "integrity": "sha512-+ux3lx6peh0BpvY0JebGyZoiR4D+oYzdPZMKJwkZ+sFkNJzpL7tXc/wehS49gUAxg3tmMHPHZkA8JU2rhhgDHw==", - "dev": true, - "optional": true, - "requires": { - "bindings": "^1.5.0", - "nan": "^2.12.1", - "node-pre-gyp": "*" - }, - "dependencies": { - "abbrev": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "aproba": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "balanced-match": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "chownr": { - "version": "1.1.3", - "bundled": true, - "dev": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "debug": { - "version": "3.2.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ms": "^2.1.1" - } - }, - "deep-extend": { - "version": "0.6.0", - "bundled": true, - "dev": true, - "optional": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "detect-libc": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "fs-minipass": { - "version": "1.2.7", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.6.0" - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "glob": { - "version": "7.1.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "iconv-lite": { - "version": "0.4.24", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ignore-walk": { - "version": "3.0.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimatch": "^3.0.4" - } - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "bundled": true, - "dev": true, - "optional": true - }, - "ini": { - "version": "1.3.5", - "bundled": true, - "dev": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "bundled": true, - "dev": true, - "optional": true - }, - "minipass": { - "version": "2.9.0", - "bundled": true, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "optional": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "optional": true, "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" + "is-descriptor": "^0.1.0" } }, - "minizlib": { - "version": "1.3.3", - "bundled": true, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "optional": true, "requires": { - "minipass": "^2.9.0" + "is-extendable": "^0.1.0" } - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, + } + } + }, + "ext": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", + "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", + "dev": true, + "requires": { + "type": "^2.0.0" + }, + "dependencies": { + "type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.0.0.tgz", + "integrity": "sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow==", + "dev": true + } + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "optional": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", "dev": true, "optional": true, "requires": { - "minimist": "0.0.8" + "is-plain-object": "^2.0.4" } - }, - "ms": { - "version": "2.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "needle": { - "version": "2.4.0", - "bundled": true, + } + } + }, + "external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "dependencies": { + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dev": true, - "optional": true, "requires": { - "debug": "^3.2.6", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" + "safer-buffer": ">= 2.1.2 < 3" } - }, - "node-pre-gyp": { - "version": "0.14.0", - "bundled": true, + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "optional": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "optional": true, "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.1", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.2.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4.4.2" + "is-descriptor": "^1.0.0" } }, - "nopt": { - "version": "4.0.1", - "bundled": true, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "optional": true, "requires": { - "abbrev": "1", - "osenv": "^0.1.4" + "is-extendable": "^0.1.0" } }, - "npm-bundled": { - "version": "1.1.1", - "bundled": true, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, "optional": true, "requires": { - "npm-normalize-package-bin": "^1.0.1" + "kind-of": "^6.0.0" } }, - "npm-normalize-package-bin": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "npm-packlist": { - "version": "1.4.7", - "bundled": true, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "dev": true, "optional": true, "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" + "kind-of": "^6.0.0" } }, - "npmlog": { - "version": "4.1.2", - "bundled": true, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, "optional": true, "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "bundled": true, + } + } + }, + "fast-deep-equal": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", + "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", + "dev": true + }, + "fast-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "dev": true + }, + "fast-glob": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.1.1.tgz", + "integrity": "sha512-nTCREpBY8w8r+boyFYAx21iL6faSsQynliPHM4Uf56SbkyohCNxpVPEH9xrF5TXKy+IsjkPUHDKiUkzBVRXn9g==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.0", + "merge2": "^1.3.0", + "micromatch": "^4.0.2" + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "fastq": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.6.0.tgz", + "integrity": "sha512-jmxqQ3Z/nXoeyDmWAzF9kH1aGZSis6e/SbfPmJpUnyZ0ogr6iscHQaml4wsEepEWSdtmpy+eVXmCRIMpxaXqOA==", + "dev": true, + "requires": { + "reusify": "^1.0.0" + } + }, + "figgy-pudding": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.1.tgz", + "integrity": "sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==", + "dev": true + }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" + } + }, + "file-entry-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", + "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "dev": true, + "requires": { + "flat-cache": "^1.2.1", + "object-assign": "^4.0.1" + } + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true, + "optional": true + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "find-cache-dir": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.2.0.tgz", + "integrity": "sha512-1JKclkYYsf1q9WIJKLZa9S9muC+08RIjzAlLrK4QcYLJMS6mk9yombQ9qf+zJ7H9LS800k0s44L4sDq9VYzqyg==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^3.0.0", + "pkg-dir": "^4.1.0" + }, + "dependencies": { + "make-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.0.0.tgz", + "integrity": "sha512-grNJDhb8b1Jm1qeqW5R/O63wUo4UXo2v2HMic6YT9i/HBlF93S8jkMgH7yugvY9ABDShH4VZMn8I+U8+fCNegw==", "dev": true, - "optional": true, "requires": { - "wrappy": "1" + "semver": "^6.0.0" } }, - "os-homedir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "osenv": { - "version": "0.1.5", - "bundled": true, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "find-parent-dir": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/find-parent-dir/-/find-parent-dir-0.3.0.tgz", + "integrity": "sha1-M8RLQpqysvBkYpnF+fcY83b/jVQ=", + "dev": true + }, + "find-project-root": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/find-project-root/-/find-project-root-1.1.1.tgz", + "integrity": "sha1-0kJyei2QRyXfVxTyPf3N7doLbvg=", + "dev": true + }, + "find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", + "dev": true + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "dependencies": { + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, - "optional": true, "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" + "p-locate": "^4.1.0" } }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "process-nextick-args": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "rc": { - "version": "1.2.8", - "bundled": true, + "p-limit": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz", + "integrity": "sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==", "dev": true, - "optional": true, "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - } + "p-try": "^2.0.0" } }, - "readable-stream": { - "version": "2.3.6", - "bundled": true, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, - "optional": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "p-limit": "^2.2.0" } }, - "rimraf": { - "version": "2.7.1", - "bundled": true, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + } + } + }, + "find-versions": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-3.2.0.tgz", + "integrity": "sha512-P8WRou2S+oe222TOCHitLy8zj+SIsVJh52VP4lvXkaFVnOFFdoWv1H1Jjvel1aI6NCFOAaeAVm8qrI0odiLcww==", + "dev": true, + "requires": { + "semver-regex": "^2.0.0" + } + }, + "flat": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", + "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==", + "dev": true, + "requires": { + "is-buffer": "~2.0.3" + } + }, + "flat-cache": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", + "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", + "dev": true, + "requires": { + "circular-json": "^0.3.1", + "del": "^2.0.2", + "graceful-fs": "^4.1.2", + "write": "^0.2.1" + } + }, + "flatted": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz", + "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==", + "dev": true + }, + "flatten": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.3.tgz", + "integrity": "sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg==", + "dev": true + }, + "flow-parser": { + "version": "0.111.3", + "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.111.3.tgz", + "integrity": "sha512-iEjGZ94OBMcESxnLorXNjJmtd/JtQYXUVrQpfwvtAKkuyawRmv+2LM6nqyOsOJkISEYbyY6ziudRE0u4VyPSVA==", + "dev": true + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true, + "optional": true + }, + "foreground-child": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", + "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.0", + "signal-exit": "^3.0.2" + }, + "dependencies": { + "cross-spawn": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.1.tgz", + "integrity": "sha512-u7v4o84SwFpD32Z8IIcPZ6z1/ie24O6RU3RbtL5Y316l3KuHVPx9ItBgWQ6VlfAFnRnTtMUrsQ9MUUTuEZjogg==", "dev": true, - "optional": true, "requires": { - "glob": "^7.1.3" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" } }, - "safe-buffer": { - "version": "5.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "safer-buffer": { - "version": "2.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "sax": { - "version": "1.2.4", - "bundled": true, - "dev": true, - "optional": true - }, - "semver": { - "version": "5.7.1", - "bundled": true, - "dev": true, - "optional": true + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true }, - "set-blocking": { + "shebang-command": { "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "tar": { - "version": "4.4.13", - "bundled": true, + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, - "optional": true, "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.8.6", - "minizlib": "^1.2.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.3" + "shebang-regex": "^3.0.0" } }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true }, - "wide-align": { - "version": "1.1.3", - "bundled": true, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, - "optional": true, "requires": { - "string-width": "^1.0.2 || 2" + "isexe": "^2.0.0" } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "yallist": { - "version": "3.1.1", - "bundled": true, - "dev": true, - "optional": true } } }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "optional": true, + "requires": { + "map-cache": "^0.2.2" + } + }, + "fromentries": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.2.0.tgz", + "integrity": "sha512-33X7H/wdfO99GdRLLgkjUrD4geAFdq/Uv0kl3HD4da6HDixd2GUg8Mw7dahLCV9r/EARkmtYBB6Tch4EEokFTQ==", + "dev": true + }, + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "dependencies": { + "graceful-fs": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", + "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", + "dev": true + } + } + }, + "fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "fs-readdir-recursive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", + "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", + "dev": true + }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz", + "integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==", + "dev": true, + "optional": true + }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -8969,9 +5800,9 @@ "dev": true }, "get-stdin": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz", - "integrity": "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g=", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-7.0.0.tgz", + "integrity": "sha512-zRKcywvrXlXsA0v0i9Io4KDRaAw7+a1ZpjRwl9Wox8PFlVCCHra7E9c4kqXCoCM9nR5tBkaTTZRBoCm60bFqTQ==", "dev": true }, "get-stream": { @@ -8987,15 +5818,6 @@ "dev": true, "optional": true }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", @@ -9011,26 +5833,12 @@ } }, "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz", + "integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==", "dev": true, - "optional": true, "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "optional": true, - "requires": { - "is-extglob": "^2.1.0" - } - } + "is-glob": "^4.0.1" } }, "global-dirs": { @@ -9062,6 +5870,36 @@ "pinkie-promise": "^2.0.0" } }, + "got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "dev": true, + "requires": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + }, + "dependencies": { + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + } + } + }, "graceful-fs": { "version": "4.1.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", @@ -9103,48 +5941,6 @@ } } }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "dev": true - }, - "har-validator": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.0.tgz", - "integrity": "sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA==", - "dev": true, - "requires": { - "ajv": "^5.3.0", - "har-schema": "^2.0.0" - }, - "dependencies": { - "ajv": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", - "dev": true, - "requires": { - "co": "^4.6.0", - "fast-deep-equal": "^1.0.0", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0" - } - }, - "fast-deep-equal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", - "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", - "dev": true - }, - "json-schema-traverse": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", - "dev": true - } - } - }, "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -9163,29 +5959,6 @@ "ansi-regex": "^2.0.0" } }, - "has-binary2": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", - "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", - "dev": true, - "requires": { - "isarray": "2.0.1" - }, - "dependencies": { - "isarray": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", - "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", - "dev": true - } - } - }, - "has-cors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", - "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=", - "dev": true - }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -9221,6 +5994,35 @@ "kind-of": "^4.0.0" }, "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true, + "optional": true + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "optional": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "optional": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, "kind-of": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", @@ -9239,22 +6041,18 @@ "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", "dev": true }, - "hasha": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/hasha/-/hasha-2.2.0.tgz", - "integrity": "sha1-eNfL/B5tZjA/55g3NlmEUXsvbuE=", - "dev": true, - "requires": { - "is-stream": "^1.0.1", - "pinkie-promise": "^2.0.0" - } - }, "he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true }, + "highlight.js": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.18.0.tgz", + "integrity": "sha512-A97kI1KAUzKoAiEoaGcf2O9YPS8nbDTCRFokaaeBhnqjQTvbAuAJrQMm21zw8s8xzaMtCQBtgbyGXLGxdxQyqQ==", + "dev": true + }, "home-or-tmp": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", @@ -9265,19 +6063,10 @@ "os-tmpdir": "^1.0.1" } }, - "homedir-polyfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", - "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", - "dev": true, - "requires": { - "parse-passwd": "^1.0.0" - } - }, "hosted-git-info": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", - "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.5.tgz", + "integrity": "sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg==", "dev": true }, "html-element-attributes": { @@ -9337,30 +6126,6 @@ "integrity": "sha512-TcIMG3qeVLgDr1TEd2XvHaTnMPwYQUQMIBLy+5pLSDKYFc7UIqj39w8EGzZkaxoLv/l2K8HaI0t5AVA+YYgUew==", "dev": true }, - "http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - } - }, - "http-proxy": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.0.tgz", - "integrity": "sha512-84I2iJM/n1d4Hdgc6y2+qY5mDaz2PUVjlg9znE9byl+q0uC3DeByqBGReQu5tpLK0TAqTIXScRUV+dg7+bUPpQ==", - "dev": true, - "requires": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - } - }, "http-proxy-agent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-3.0.0.tgz", @@ -9394,44 +6159,6 @@ } } }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, - "https-proxy-agent": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-3.0.1.tgz", - "integrity": "sha512-+ML2Rbh6DAuee7d07tYGEKOEi2voWPUGan+ExdPbPW6Z3svq+JCqr0v8WmKPOkz1vOVykPCBSuobe7G8GJUtVg==", - "dev": true, - "requires": { - "agent-base": "^4.3.0", - "debug": "^3.1.0" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, "human-signals": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", @@ -9534,9 +6261,9 @@ "dev": true }, "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", + "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", "dev": true }, "ignore-walk": { @@ -9548,12 +6275,6 @@ "minimatch": "^3.0.4" } }, - "immediate": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", - "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=", - "dev": true - }, "import-fresh": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", @@ -9596,12 +6317,6 @@ "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", "dev": true }, - "indexof": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", - "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", - "dev": true - }, "infer-owner": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", @@ -9640,9 +6355,9 @@ } }, "inquirer": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.0.3.tgz", - "integrity": "sha512-+OiOVeVydu4hnCGLCSX+wedovR/Yzskv9BFqUNNKq9uU2qg7LCcCo3R86S2E7WLo0y/x2pnEZfZe1CoYnORUAw==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.0.4.tgz", + "integrity": "sha512-Bu5Td5+j11sCkqfqmUTiwv+tWisMtP0L7Q8WrqA2C/BbBhy1YTdFrvjjlrKq8oagA/tLQBski2Gcx/Sqyi2qSQ==", "dev": true, "requires": { "ansi-escapes": "^4.2.1", @@ -9695,12 +6410,6 @@ "supports-color": "^5.3.0" } }, - "chardet": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", - "dev": true - }, "cli-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", @@ -9710,17 +6419,6 @@ "restore-cursor": "^3.1.0" } }, - "external-editor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", - "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", - "dev": true, - "requires": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" - } - }, "figures": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.1.0.tgz", @@ -9730,48 +6428,12 @@ "escape-string-regexp": "^1.0.5" } }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "dev": true - }, - "onetime": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz", - "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - }, "restore-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", @@ -9782,15 +6444,6 @@ "signal-exit": "^3.0.2" } }, - "rxjs": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.4.tgz", - "integrity": "sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, "string-width": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", @@ -9872,6 +6525,13 @@ "kind-of": "^3.0.2" }, "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true, + "optional": true + }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", @@ -9907,35 +6567,24 @@ "dev": true }, "is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, - "optional": true, "requires": { - "binary-extensions": "^1.0.0" + "binary-extensions": "^2.0.0" } }, "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true, - "optional": true - }, - "is-builtin-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", - "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", - "dev": true, - "requires": { - "builtin-modules": "^1.0.0" - } + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", + "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==", + "dev": true }, "is-callable": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", - "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", + "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", "dev": true }, "is-ci": { @@ -9945,6 +6594,14 @@ "dev": true, "requires": { "ci-info": "^2.0.0" + }, + "dependencies": { + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + } } }, "is-data-descriptor": { @@ -9957,6 +6614,13 @@ "kind-of": "^3.0.2" }, "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true, + "optional": true + }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", @@ -10028,9 +6692,9 @@ "dev": true }, "is-glob": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", - "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", "dev": true, "requires": { "is-extglob": "^2.1.1" @@ -10077,27 +6741,17 @@ "xtend": "^4.0.0" } }, - "is-number": { + "is-npm": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "optional": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "optional": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-3.0.0.tgz", + "integrity": "sha512-wsigDr1Kkschp2opC4G3yA6r9EgVA6NjRpWzIi9axXqeIaAATPRJc4uLujXe3Nd9uO8KoDyA4MD6aZSeXTADhA==", + "dev": true + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true }, "is-obj": { "version": "1.0.1", @@ -10167,12 +6821,12 @@ "dev": true }, "is-regex": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", - "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", + "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", "dev": true, "requires": { - "has": "^1.0.1" + "has": "^1.0.3" } }, "is-regexp": { @@ -10193,12 +6847,21 @@ "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", "dev": true }, - "is-symbol": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz", - "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=", + "is-string": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", + "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", "dev": true }, + "is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", @@ -10235,15 +6898,6 @@ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, - "isbinaryfile": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.3.tgz", - "integrity": "sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw==", - "dev": true, - "requires": { - "buffer-alloc": "^1.2.0" - } - }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -10257,12 +6911,6 @@ "dev": true, "optional": true }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true - }, "istanbul-lib-coverage": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz", @@ -10514,6 +7162,12 @@ "integrity": "sha1-o6vicYryQaKykE+EpiWXDzia4yo=", "dev": true }, + "jquery": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.4.1.tgz", + "integrity": "sha512-36+AdBzCL+y6qjw5Tx7HgzeGCzC81MDDgaUP8ld2zhx58HdqXGoBd+tHdrBMiyjGQs0Hxs/MLZTu/eHNJJuWPw==", + "dev": true + }, "js-base64": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.5.1.tgz", @@ -10527,79 +7181,15 @@ "dev": true }, "js-yaml": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", - "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", "dev": true, "requires": { "argparse": "^1.0.7", "esprima": "^4.0.0" } }, - "js2xmlparser": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.0.tgz", - "integrity": "sha512-WuNgdZOXVmBk5kUPMcTcVUpbGRzLfNkv7+7APq7WiDihpXVKrgxo6wwRpRl9OQeEBgKCVk9mR7RbzrnNWC8oBw==", - "dev": true, - "requires": { - "xmlcreate": "^2.0.0" - } - }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true, - "optional": true - }, - "jsdoc": { - "version": "3.6.3", - "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.6.3.tgz", - "integrity": "sha512-Yf1ZKA3r9nvtMWHO1kEuMZTlHOF8uoQ0vyo5eH7SQy5YeIiHM+B0DgKnn+X6y6KDYZcF7G2SPkKF+JORCXWE/A==", - "dev": true, - "requires": { - "@babel/parser": "^7.4.4", - "bluebird": "^3.5.4", - "catharsis": "^0.8.11", - "escape-string-regexp": "^2.0.0", - "js2xmlparser": "^4.0.0", - "klaw": "^3.0.0", - "markdown-it": "^8.4.2", - "markdown-it-anchor": "^5.0.2", - "marked": "^0.7.0", - "mkdirp": "^0.5.1", - "requizzle": "^0.2.3", - "strip-json-comments": "^3.0.1", - "taffydb": "2.6.2", - "underscore": "~1.9.1" - }, - "dependencies": { - "@babel/parser": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.3.tgz", - "integrity": "sha512-/V72F4Yp/qmHaTALizEm9Gf2eQHV3QyTL3K0cNfijwnMnb1L+LDlAubb/ZnSdGAVzVSWakujHYs1I26x66sMeQ==", - "dev": true - }, - "bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true - }, - "escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true - }, - "strip-json-comments": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", - "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", - "dev": true - } - } - }, "jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -10633,12 +7223,6 @@ "jju": "^1.1.0" } }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", - "dev": true - }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -10660,282 +7244,13 @@ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true - }, "json5": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.1.tgz", - "integrity": "sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } - } - }, - "jsonfile": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", - "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", - "dev": true - }, - "jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", - "dev": true - }, - "jsonpointer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", - "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", - "dev": true - }, - "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "dev": true, - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, - "jsx-ast-utils": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-1.4.1.tgz", - "integrity": "sha1-OGchPo3Xm/Ho8jAMDPwe+xgsDfE=", - "dev": true - }, - "jszip": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.2.2.tgz", - "integrity": "sha512-NmKajvAFQpbg3taXQXr/ccS2wcucR1AZ+NtyWp2Nq7HHVsXhcJFR8p0Baf32C2yVvBylFWVeKf+WI2AnvlPhpA==", - "dev": true, - "requires": { - "lie": "~3.3.0", - "pako": "~1.0.2", - "readable-stream": "~2.3.6", - "set-immediate-shim": "~1.0.1" - } - }, - "just-extend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.0.2.tgz", - "integrity": "sha512-FrLwOgm+iXrPV+5zDU6Jqu4gCRXbWEQg2O3SKONsWE4w7AXFRkryS53bpWdaL9cNol+AmR3AEYz6kn+o0fCPnw==", - "dev": true - }, - "karma": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/karma/-/karma-4.4.1.tgz", - "integrity": "sha512-L5SIaXEYqzrh6b1wqYC42tNsFMx2PWuxky84pK9coK09MvmL7mxii3G3bZBh/0rvD27lqDd0le9jyhzvwif73A==", - "dev": true, - "requires": { - "bluebird": "^3.3.0", - "body-parser": "^1.16.1", - "braces": "^3.0.2", - "chokidar": "^3.0.0", - "colors": "^1.1.0", - "connect": "^3.6.0", - "di": "^0.0.1", - "dom-serialize": "^2.2.0", - "flatted": "^2.0.0", - "glob": "^7.1.1", - "graceful-fs": "^4.1.2", - "http-proxy": "^1.13.0", - "isbinaryfile": "^3.0.0", - "lodash": "^4.17.14", - "log4js": "^4.0.0", - "mime": "^2.3.1", - "minimatch": "^3.0.2", - "optimist": "^0.6.1", - "qjobs": "^1.1.4", - "range-parser": "^1.2.0", - "rimraf": "^2.6.0", - "safe-buffer": "^5.0.1", - "socket.io": "2.1.1", - "source-map": "^0.6.1", - "tmp": "0.0.33", - "useragent": "2.3.0" - }, - "dependencies": { - "anymatch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", - "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "binary-extensions": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz", - "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==", - "dev": true - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "chokidar": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.1.tgz", - "integrity": "sha512-4QYCEWOcK3OJrxwvyyAOxFuhpvOVCYkr33LPfFNBjAD/w3sEzWsp2BUOkI4l9bHvWioAd0rc6NlHUOEaWkTeqg==", - "dev": true, - "requires": { - "anymatch": "~3.1.1", - "braces": "~3.0.2", - "fsevents": "~2.1.2", - "glob-parent": "~5.1.0", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.3.0" - } - }, - "colors": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", - "dev": true - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "fsevents": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz", - "integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==", - "dev": true, - "optional": true - }, - "glob-parent": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz", - "integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - }, - "readdirp": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.3.0.tgz", - "integrity": "sha512-zz0pAkSPOXXm1viEwygWIPSPkcBYjW1xU5j/JBh5t9bGCJwa6f9+BJa6VaB2g+b55yVrmXzqkyLf4xaWYM0IkQ==", - "dev": true, - "requires": { - "picomatch": "^2.0.7" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - } - } - }, - "karma-babel-preprocessor": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/karma-babel-preprocessor/-/karma-babel-preprocessor-8.0.1.tgz", - "integrity": "sha512-5upyawNi3c7Gg6tPH1FWRVTmUijGf3v1GV4ScLM/2jKdDP18SlaKlUpu8eJrRI3STO8qK1bkqFcdgAA364nLYQ==", - "dev": true - }, - "karma-chai": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/karma-chai/-/karma-chai-0.1.0.tgz", - "integrity": "sha1-vuWtQEAFF4Ea40u5RfdikJEIt5o=", - "dev": true - }, - "karma-chrome-launcher": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-3.1.0.tgz", - "integrity": "sha512-3dPs/n7vgz1rxxtynpzZTvb9y/GIaW8xjAwcIGttLbycqoFtI7yo1NGnQi6oFTherRE+GIhCAHZC4vEqWGhNvg==", - "dev": true, - "requires": { - "which": "^1.2.1" - } - }, - "karma-mocha": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/karma-mocha/-/karma-mocha-1.3.0.tgz", - "integrity": "sha1-7qrH/8DiAetjxGdEDStpx883eL8=", + "integrity": "sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ==", "dev": true, "requires": { - "minimist": "1.2.0" + "minimist": "^1.2.0" }, "dependencies": { "minimist": { @@ -10946,37 +7261,43 @@ } } }, - "karma-phantomjs-launcher": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/karma-phantomjs-launcher/-/karma-phantomjs-launcher-1.0.4.tgz", - "integrity": "sha1-0jyjSAG9qYY60xjju0vUBisTrNI=", + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", "dev": true, "requires": { - "lodash": "^4.0.1", - "phantomjs-prebuilt": "^2.1.7" + "graceful-fs": "^4.1.6" } }, - "karma-sauce-launcher": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/karma-sauce-launcher/-/karma-sauce-launcher-2.0.2.tgz", - "integrity": "sha512-jLUFaJhHMcKpxFWUesyWYihzM5FvQiJsDwGcCtKeOy2lsWhkVw0V0Byqb1d+wU6myU1mribBtsIcub23HS4kWA==", - "dev": true, - "requires": { - "sauce-connect-launcher": "^1.2.4", - "saucelabs": "^1.5.0", - "selenium-webdriver": "^4.0.0-alpha.1" - } + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true }, - "karma-sinon": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/karma-sinon/-/karma-sinon-1.0.5.tgz", - "integrity": "sha1-TjRD8oMP3s/2JNN0cWPxIX2qKpo=", + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", "dev": true }, - "kew": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/kew/-/kew-0.7.0.tgz", - "integrity": "sha1-edk9LTM2PW/dKXCzNdkUGtWR15s=", + "jsonpointer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", + "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", + "dev": true + }, + "jsx-ast-utils": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-1.4.1.tgz", + "integrity": "sha1-OGchPo3Xm/Ho8jAMDPwe+xgsDfE=", + "dev": true + }, + "just-extend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.0.2.tgz", + "integrity": "sha512-FrLwOgm+iXrPV+5zDU6Jqu4gCRXbWEQg2O3SKONsWE4w7AXFRkryS53bpWdaL9cNol+AmR3AEYz6kn+o0fCPnw==", "dev": true }, "keyv": { @@ -10989,27 +7310,27 @@ } }, "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "dev": true, "optional": true }, - "klaw": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", - "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.9" - } - }, "kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", "dev": true }, + "latest-version": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", + "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", + "dev": true, + "requires": { + "package-json": "^6.3.0" + } + }, "leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", @@ -11017,20 +7338,12 @@ "dev": true }, "levenary": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/levenary/-/levenary-1.1.0.tgz", - "integrity": "sha512-VHcwhO0UTpUW7rLPN2/OiWJdgA1e9BqEDALhrgCe/F+uUJnep6CoUsTzMeP8Rh0NGr9uKquXxqe7lwLZo509nQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/levenary/-/levenary-1.1.1.tgz", + "integrity": "sha512-mkAdOIt79FD6irqjYSs4rdbnlT5vRonMEvBVPVb3XmevfS8kgRXwfes0dhPdEtzTWD/1eNE/Bm/G1iRt6DcnQQ==", "dev": true, "requires": { "leven": "^3.1.0" - }, - "dependencies": { - "leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true - } } }, "levn": { @@ -11105,15 +7418,6 @@ } } }, - "lie": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", - "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", - "dev": true, - "requires": { - "immediate": "~3.0.5" - } - }, "lines-and-columns": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", @@ -11126,19 +7430,10 @@ "integrity": "sha512-DBZPIWjrQmb/52UlSEN8MTiwwugrAh4NBX9/DyIG8IuO8rDLYDRM+KVPbuiPVKd3ResxYtZB5AiSuc8dTzOSog==", "dev": true }, - "linkify-it": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", - "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==", - "dev": true, - "requires": { - "uc.micro": "^1.0.1" - } - }, "lint-staged": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-10.0.2.tgz", - "integrity": "sha512-ZldhtIfT7bynVa7nmU/1jbK05r9hYQXbIQqZSotqdBCAcGJDEUqaUB7kG3ZCdoe9Qkj6HUM3x2yjCGJRxPUQLA==", + "version": "10.0.7", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-10.0.7.tgz", + "integrity": "sha512-Byj0F4l7GYUpYYHEqyFH69NiI6ICTg0CeCKbhRorL+ickbzILKUlZLiyCkljZV02wnoh7yH7PmFyYm9PRNwk9g==", "dev": true, "requires": { "chalk": "^3.0.0", @@ -11166,15 +7461,6 @@ "color-convert": "^2.0.1" } }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, "chalk": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", @@ -11209,98 +7495,12 @@ "ms": "^2.1.1" } }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "log-symbols": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", - "integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==", - "dev": true, - "requires": { - "chalk": "^2.4.2" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "micromatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", - "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", - "dev": true, - "requires": { - "braces": "^3.0.1", - "picomatch": "^2.0.5" - } - }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -11315,15 +7515,6 @@ "requires": { "has-flag": "^4.0.0" } - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } } } }, @@ -11439,6 +7630,17 @@ "parse-json": "^2.2.0", "pify": "^2.0.0", "strip-bom": "^3.0.0" + }, + "dependencies": { + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + } } }, "locate-path": { @@ -11520,12 +7722,12 @@ "dev": true }, "log-symbols": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", - "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", + "integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==", "dev": true, "requires": { - "chalk": "^2.0.1" + "chalk": "^2.4.2" }, "dependencies": { "ansi-styles": { @@ -11538,9 +7740,9 @@ } }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", @@ -11549,9 +7751,9 @@ } }, "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -11568,63 +7770,6 @@ "ansi-escapes": "^3.0.0", "cli-cursor": "^2.0.0", "wrap-ansi": "^3.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - }, - "wrap-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-3.0.1.tgz", - "integrity": "sha1-KIoE2H7aXChuBg3+jxNc6NAH+Lo=", - "dev": true, - "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0" - } - } - } - }, - "log4js": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-4.5.1.tgz", - "integrity": "sha512-EEEgFcE9bLgaYUKuozyFfytQM2wDHtXn4tAN41pkaxpNjAykv11GVdeI4tHtmPWW4Xrgh9R/2d7XYghDVjbKKw==", - "dev": true, - "requires": { - "date-format": "^2.0.0", - "debug": "^4.1.1", - "flatted": "^2.0.0", - "rfdc": "^1.1.4", - "streamroller": "^1.0.6" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } } }, "lolex": { @@ -11661,30 +7806,35 @@ "yallist": "^2.1.2" } }, + "lunr": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.8.tgz", + "integrity": "sha512-oxMeX/Y35PNFuZoHp+jUj5OSEmLCaIH4KTFJh7a93cHBoFmpw2IoPs22VIz7vyO2YUnx2Tn9dzIwO2P/4quIRg==", + "dev": true + }, "make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", "dev": true, "requires": { - "pify": "^4.0.1", - "semver": "^5.6.0" + "pify": "^3.0.0" }, "dependencies": { "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", "dev": true } } }, + "make-error": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.5.tgz", + "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==", + "dev": true + }, "make-fetch-happen": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-7.1.0.tgz", @@ -11788,107 +7938,37 @@ "integrity": "sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg==", "dev": true }, - "markdown-it": { - "version": "8.4.2", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-8.4.2.tgz", - "integrity": "sha512-GcRz3AWTqSUphY3vsUqQSFMbgR38a4Lh3GWlHRh/7MRwz8mcu9n2IO7HOh+bXHrR9kOPDl5RNCaEsrneb+xhHQ==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "entities": "~1.1.1", - "linkify-it": "^2.0.0", - "mdurl": "^1.0.1", - "uc.micro": "^1.0.5" - } - }, - "markdown-it-anchor": { - "version": "5.2.5", - "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-5.2.5.tgz", - "integrity": "sha512-xLIjLQmtym3QpoY9llBgApknl7pxAcN3WDRc2d3rwpl+/YvDZHPmKscGs+L6E05xf2KrCXPBvosWt7MZukwSpQ==", - "dev": true - }, - "marked": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-0.7.0.tgz", - "integrity": "sha512-c+yYdCZJQrsRjTPhUx7VKkApw9bwDkNbHUKo1ovgcfDjb2kc8rLuRbIFyXL5WOEUwzSSKo3IXpph2K6DqB/KZg==", - "dev": true - }, - "mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", - "dev": true - }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", - "dev": true - }, "mem": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/mem/-/mem-5.1.1.tgz", "integrity": "sha512-qvwipnozMohxLXG1pOqoLiZKNkC4r4qqRucSoDwXowsNGDSULiqFTRUF05vcZWnwJSG22qTsynQhxbaMtnX9gw==", "dev": true, "requires": { - "map-age-cleaner": "^0.1.3", - "mimic-fn": "^2.1.0", - "p-is-promise": "^2.1.0" - } - }, - "merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "merge2": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.3.0.tgz", - "integrity": "sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw==", - "dev": true - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "optional": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" + "map-age-cleaner": "^0.1.3", + "mimic-fn": "^2.1.0", + "p-is-promise": "^2.1.0" } }, - "mime": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz", - "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==", + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", "dev": true }, - "mime-db": { - "version": "1.35.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.35.0.tgz", - "integrity": "sha512-JWT/IcCTsB0Io3AhWUMjRqucrHSPsSf2xKLaRldJVULioggvkJvggZ3VXNNSRkCddE6D+BUI4HEIZIA2OjwIvg==", + "merge2": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.3.0.tgz", + "integrity": "sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw==", "dev": true }, - "mime-types": { - "version": "2.1.19", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.19.tgz", - "integrity": "sha512-P1tKYHVSZ6uFo26mtnve4HQFE3koh1UWVkp8YUC+ESBHe945xWSoXuHHiGarDqcEZ+whpCDnlNw5LON0kLo+sw==", + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", "dev": true, "requires": { - "mime-db": "~1.35.0" + "braces": "^3.0.1", + "picomatch": "^2.0.5" } }, "mimic-fn": { @@ -12013,9 +8093,9 @@ } }, "mixin-deep": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", - "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", "dev": true, "optional": true, "requires": { @@ -12045,9 +8125,9 @@ } }, "mocha": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-7.0.0.tgz", - "integrity": "sha512-CirsOPbO3jU86YKjjMzFLcXIb5YiGLUrjrXFHoJ3e2z9vWiaZVCZQ2+gtRGMPWF+nFhN6AWwLM/juzAQ6KRkbA==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-7.0.1.tgz", + "integrity": "sha512-9eWmWTdHLXh72rGrdZjNbG3aa1/3NRPpul1z0D979QpEnFdCG0Q5tv834N+94QEN2cysfV72YocQ3fn87s70fg==", "dev": true, "requires": { "ansi-colors": "3.2.3", @@ -12076,45 +8156,35 @@ "yargs-unparser": "1.6.0" }, "dependencies": { - "anymatch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", - "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "binary-extensions": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz", - "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==", - "dev": true - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { - "fill-range": "^7.0.1" + "color-convert": "^1.9.0" } }, - "chokidar": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.0.tgz", - "integrity": "sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A==", + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { - "anymatch": "~3.1.1", - "braces": "~3.0.2", - "fsevents": "~2.1.1", - "glob-parent": "~5.1.0", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.2.0" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "debug": { @@ -12126,15 +8196,6 @@ "ms": "^2.1.1" } }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, "find-up": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", @@ -12144,13 +8205,6 @@ "locate-path": "^3.0.0" } }, - "fsevents": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz", - "integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==", - "dev": true, - "optional": true - }, "glob": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", @@ -12165,49 +8219,6 @@ "path-is-absolute": "^1.0.0" } }, - "glob-parent": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz", - "integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, "locate-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", @@ -12218,6 +8229,15 @@ "path-exists": "^3.0.0" } }, + "log-symbols": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "dev": true, + "requires": { + "chalk": "^2.0.1" + } + }, "ms": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", @@ -12254,15 +8274,6 @@ "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", "dev": true }, - "readdirp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.2.0.tgz", - "integrity": "sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ==", - "dev": true, - "requires": { - "picomatch": "^2.0.4" - } - }, "supports-color": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", @@ -12271,15 +8282,6 @@ "requires": { "has-flag": "^3.0.0" } - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } } } }, @@ -12328,9 +8330,9 @@ } }, "mute-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", - "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", "dev": true }, "n-readlines": { @@ -12372,12 +8374,6 @@ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, - "negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", - "dev": true - }, "neo-async": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz", @@ -12444,12 +8440,6 @@ } } }, - "node-modules-regexp": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz", - "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=", - "dev": true - }, "node-preload": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", @@ -12460,9 +8450,9 @@ } }, "node-releases": { - "version": "1.1.47", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.47.tgz", - "integrity": "sha512-k4xjVPx5FpwBUj0Gw7uvFOTF4Ep8Hok1I6qjwL3pLfwe7Y0REQSAqOwwv9TWBCUtMHxcXfY4PgRLRozcChvTcA==", + "version": "1.1.48", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.48.tgz", + "integrity": "sha512-Hr8BbmUl1ujAST0K0snItzEA5zkJTQup8VNTKNfT6Zw8vTJkIiagUPNfxHmgDOyfFYNfKAul40sD0UEYTvwebw==", "dev": true, "requires": { "semver": "^6.3.0" @@ -12477,15 +8467,26 @@ } }, "normalize-package-data": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", "dev": true, "requires": { "hosted-git-info": "^2.1.4", - "is-builtin-module": "^1.0.0", + "resolve": "^1.10.0", "semver": "2 || 3 || 4 || 5", "validate-npm-package-license": "^3.0.1" + }, + "dependencies": { + "resolve": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.0.tgz", + "integrity": "sha512-+hTmAldEGE80U2wJJDC1lebb5jWqvTYAfm3YZ1ckk1gBr0MnCqUKlwK1e+anaFljIl+F5tR5IoZcm4ZDA1zMQw==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + } } }, "normalize-path": { @@ -12509,6 +8510,92 @@ "npm-normalize-package-bin": "^1.0.1" } }, + "npm-check-updates": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-check-updates/-/npm-check-updates-4.0.1.tgz", + "integrity": "sha512-rDrKAqhQuTYq2EkndroPMZGA9N6tpTotOVOIJoxRa3ZKnb/mOcq2TZv4A4LLSM8+9kZlP+sBwE+XAGh8wWZw/w==", + "dev": true, + "requires": { + "chalk": "^3.0.0", + "cint": "^8.2.1", + "cli-table": "^0.3.1", + "commander": "^4.0.1", + "fast-diff": "^1.2.0", + "find-up": "4.1.0", + "get-stdin": "^7.0.0", + "json-parse-helpfulerror": "^1.0.3", + "libnpmconfig": "^1.2.1", + "lodash": "^4.17.15", + "node-alias": "^1.0.4", + "pacote": "^10.2.0", + "progress": "^2.0.3", + "prompts": "^2.3.0", + "rc-config-loader": "^3.0.0", + "requireg": "^0.2.2", + "semver": "^6.3.0", + "semver-utils": "^1.1.4", + "spawn-please": "^0.3.0", + "update-notifier": "^3.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, "npm-normalize-package-bin": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", @@ -12898,24 +8985,12 @@ } } }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "dev": true - }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "dev": true }, - "object-component": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", - "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=", - "dev": true - }, "object-copy": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", @@ -12938,6 +9013,13 @@ "is-descriptor": "^0.1.0" } }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true, + "optional": true + }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", @@ -12975,87 +9057,25 @@ "object.assign": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - } - }, - "object.entries": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.1.tgz", - "integrity": "sha512-ilqR7BgdyZetJutmDPfXCDffGa0/Yzl2ivVNpbx/g4UeWrCdRnFDUBrKJGLhGieRHDATnyZXWBeCb29k9CJysQ==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1", - "function-bind": "^1.1.1", - "has": "^1.0.3" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.4", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.4.tgz", - "integrity": "sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.1.5", - "is-regex": "^1.0.5", - "object-inspect": "^1.7.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimleft": "^2.1.1", - "string.prototype.trimright": "^2.1.1" - } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "is-callable": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", - "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", - "dev": true - }, - "is-regex": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", - "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - } + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } + }, + "object.entries": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.1.tgz", + "integrity": "sha512-ilqR7BgdyZetJutmDPfXCDffGa0/Yzl2ivVNpbx/g4UeWrCdRnFDUBrKJGLhGieRHDATnyZXWBeCb29k9CJysQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1", + "has": "^1.0.3" } }, "object.fromentries": { @@ -13068,68 +9088,6 @@ "es-abstract": "^1.17.0-next.1", "function-bind": "^1.1.1", "has": "^1.0.3" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.4", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.4.tgz", - "integrity": "sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.1.5", - "is-regex": "^1.0.5", - "object-inspect": "^1.7.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimleft": "^2.1.1", - "string.prototype.trimright": "^2.1.1" - } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "is-callable": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", - "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", - "dev": true - }, - "is-regex": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", - "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - } } }, "object.getownpropertydescriptors": { @@ -13140,68 +9098,6 @@ "requires": { "define-properties": "^1.1.3", "es-abstract": "^1.17.0-next.1" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.4", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.4.tgz", - "integrity": "sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.1.5", - "is-regex": "^1.0.5", - "object-inspect": "^1.7.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimleft": "^2.1.1", - "string.prototype.trimright": "^2.1.1" - } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "is-callable": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", - "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", - "dev": true - }, - "is-regex": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", - "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - } } }, "object.pick": { @@ -13224,77 +9120,6 @@ "es-abstract": "^1.17.0-next.1", "function-bind": "^1.1.1", "has": "^1.0.3" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.4", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.4.tgz", - "integrity": "sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.1.5", - "is-regex": "^1.0.5", - "object-inspect": "^1.7.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimleft": "^2.1.1", - "string.prototype.trimright": "^2.1.1" - } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "is-callable": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", - "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", - "dev": true - }, - "is-regex": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", - "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - } - } - }, - "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "dev": true, - "requires": { - "ee-first": "1.1.1" } }, "once": { @@ -13340,17 +9165,17 @@ } }, "optionator": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", - "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", "dev": true, "requires": { "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.4", + "fast-levenshtein": "~2.0.6", "levn": "~0.3.0", "prelude-ls": "~1.1.2", "type-check": "~0.3.2", - "wordwrap": "~1.0.0" + "word-wrap": "~1.2.3" } }, "os-homedir": { @@ -13465,6 +9290,26 @@ } } }, + "package-json": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", + "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", + "dev": true, + "requires": { + "got": "^9.6.0", + "registry-auth-token": "^4.0.0", + "registry-url": "^5.0.0", + "semver": "^6.2.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, "pacote": { "version": "10.3.0", "resolved": "https://registry.npmjs.org/pacote/-/pacote-10.3.0.tgz", @@ -13525,12 +9370,6 @@ } } }, - "pako": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.10.tgz", - "integrity": "sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw==", - "dev": true - }, "parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -13563,49 +9402,22 @@ } }, "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.0.0.tgz", + "integrity": "sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw==", "dev": true, "requires": { - "error-ex": "^1.2.0" + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1", + "lines-and-columns": "^1.1.6" } }, - "parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", - "dev": true - }, "parse-srcset": { "version": "github:ikatyang/parse-srcset#54eb9c1cb21db5c62b4d0e275d7249516df6f0ee", "from": "github:ikatyang/parse-srcset#54eb9c1cb21db5c62b4d0e275d7249516df6f0ee", "dev": true }, - "parseqs": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", - "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", - "dev": true, - "requires": { - "better-assert": "~1.0.0" - } - }, - "parseuri": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", - "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", - "dev": true, - "requires": { - "better-assert": "~1.0.0" - } - }, - "parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "dev": true - }, "pascalcase": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", @@ -13668,13 +9480,10 @@ } }, "path-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", - "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", - "dev": true, - "requires": { - "pify": "^2.0.0" - } + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true }, "pathval": { "version": "1.1.0", @@ -13682,43 +9491,6 @@ "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", "dev": true }, - "pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", - "dev": true - }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "dev": true - }, - "phantomjs-prebuilt": { - "version": "2.1.16", - "resolved": "https://registry.npmjs.org/phantomjs-prebuilt/-/phantomjs-prebuilt-2.1.16.tgz", - "integrity": "sha1-79ISpKOWbTZHaE6ouniFSb4q7+8=", - "dev": true, - "requires": { - "es6-promise": "^4.0.3", - "extract-zip": "^1.6.5", - "fs-extra": "^1.0.0", - "hasha": "^2.2.0", - "kew": "^0.7.0", - "progress": "^1.1.8", - "request": "^2.81.0", - "request-progress": "^2.0.1", - "which": "^1.2.10" - }, - "dependencies": { - "progress": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", - "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", - "dev": true - } - } - }, "picomatch": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.1.tgz", @@ -13746,15 +9518,6 @@ "pinkie": "^2.0.0" } }, - "pirates": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.1.tgz", - "integrity": "sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA==", - "dev": true, - "requires": { - "node-modules-regexp": "^1.0.0" - } - }, "pkg-conf": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-3.1.0.tgz", @@ -14033,6 +9796,12 @@ "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", "dev": true }, + "prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", + "dev": true + }, "prettier-standard": { "version": "16.1.0", "resolved": "https://registry.npmjs.org/prettier-standard/-/prettier-standard-16.1.0.tgz", @@ -14062,15 +9831,6 @@ "color-convert": "^1.9.0" } }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, "caller-path": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", @@ -14212,21 +9972,6 @@ "strip-final-newline": "^2.0.0" } }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "get-stdin": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-7.0.0.tgz", - "integrity": "sha512-zRKcywvrXlXsA0v0i9Io4KDRaAw7+a1ZpjRwl9Wox8PFlVCCHra7E9c4kqXCoCM9nR5tBkaTTZRBoCm60bFqTQ==", - "dev": true - }, "get-stream": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz", @@ -14255,12 +10000,6 @@ "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", "dev": true }, - "ignore": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", - "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", - "dev": true - }, "import-fresh": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", @@ -14271,21 +10010,6 @@ "resolve-from": "^3.0.0" } }, - "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, "is-path-cwd": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", @@ -14304,16 +10028,6 @@ "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", "dev": true }, - "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, "lint-staged": { "version": "9.4.3", "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-9.4.3.tgz", @@ -14336,25 +10050,6 @@ "stringify-object": "^3.3.0" } }, - "log-symbols": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", - "integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==", - "dev": true, - "requires": { - "chalk": "^2.4.2" - } - }, - "micromatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", - "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", - "dev": true, - "requires": { - "braces": "^3.0.1", - "picomatch": "^2.0.5" - } - }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -14408,9 +10103,9 @@ "dev": true }, "rimraf": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.0.tgz", - "integrity": "sha512-NDGVxTsjqfunkds7CqsOiEnxln4Bo7Nddl3XhS4pXg5OzwkLqJ971ZVAAnB+DDLnF76N+VnDEiBHaVV8I06SUg==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.1.tgz", + "integrity": "sha512-IQ4ikL8SjBiEDZfk+DFVwqRK8md24RWMEJkdSlgNLkyyAImcjf8SWvU1qFMDOb4igBClbTQ/ugPqXcRwdFTxZw==", "dev": true, "requires": { "glob": "^7.1.3" @@ -14456,15 +10151,6 @@ "has-flag": "^3.0.0" } }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -14556,6 +10242,20 @@ "integrity": "sha512-bqv+iCo9i+uLVbI0ILzKkvMorqxouI+GbV13ivcARXn9NNEabi2IEz912IgNpT/60BNXac5dgcfjb94NjsF33A==", "dev": true }, + "@typescript-eslint/typescript-estree": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.6.1.tgz", + "integrity": "sha512-+sTnssW6bcbDZKE8Ce7VV6LdzkQz2Bxk7jzk1J8H1rovoTxnm6iXvYIyncvNsaB/kBCOM63j/LNJfm27bNdUoA==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "glob": "^7.1.4", + "is-glob": "^4.0.1", + "lodash.unescape": "4.0.1", + "semver": "^6.3.0", + "tsutils": "^3.17.1" + } + }, "ansi-regex": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", @@ -14605,10 +10305,19 @@ "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", "dev": true, "requires": { - "import-fresh": "^2.0.0", - "is-directory": "^0.3.1", - "js-yaml": "^3.13.1", - "parse-json": "^4.0.0" + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.1", + "parse-json": "^4.0.0" + } + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" } }, "diff": { @@ -14638,6 +10347,20 @@ "pump": "^3.0.0" } }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, "globby": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", @@ -14651,6 +10374,12 @@ "pinkie-promise": "^2.0.0" } }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, "import-fresh": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", @@ -14667,22 +10396,18 @@ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true }, - "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, "minimist": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, "parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", @@ -14767,9 +10492,9 @@ } }, "progress": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", - "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true }, "promise-inflight": { @@ -14815,12 +10540,6 @@ "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", "dev": true }, - "psl": { - "version": "1.1.29", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz", - "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==", - "dev": true - }, "pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", @@ -14837,47 +10556,6 @@ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", "dev": true }, - "qjobs": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", - "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==", - "dev": true - }, - "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", - "dev": true - }, - "range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true - }, - "raw-body": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", - "dev": true, - "requires": { - "bytes": "3.1.0", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "dependencies": { - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - } - } - }, "rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", @@ -14952,6 +10630,17 @@ "load-json-file": "^2.0.0", "normalize-package-data": "^2.3.2", "path-type": "^2.0.0" + }, + "dependencies": { + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "requires": { + "pify": "^2.0.0" + } + } } }, "read-pkg-up": { @@ -15003,15 +10692,12 @@ } }, "readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.2.0.tgz", + "integrity": "sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ==", "dev": true, - "optional": true, "requires": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" + "picomatch": "^2.0.4" } }, "readline2": { @@ -15072,6 +10758,15 @@ "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", "dev": true }, + "regenerator-transform": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.1.tgz", + "integrity": "sha512-flVuee02C3FKRISbxhXl9mGzdbWUVHubl1SMaknjxkFB1/iqpJhArQUvRxOOPEc/9tAiX0BaQ28FJH10E4isSQ==", + "dev": true, + "requires": { + "private": "^0.1.6" + } + }, "regex-not": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", @@ -15098,6 +10793,61 @@ "integrity": "sha512-Z+hNr7RAVWxznLPuA7DIh8UNX1j9CDrUQxskw9IrBE1Dxue2lyXT+shqEIeLUjrokxIP8CMy1WkjgG3rTsd5/g==", "dev": true }, + "regexpu-core": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.6.0.tgz", + "integrity": "sha512-YlVaefl8P5BnFYOITTNzDvan1ulLOiXJzCNZxduTIosN17b87h3bvG9yHMoHaRuo88H4mQ06Aodj5VtYGGGiTg==", + "dev": true, + "requires": { + "regenerate": "^1.4.0", + "regenerate-unicode-properties": "^8.1.0", + "regjsgen": "^0.5.0", + "regjsparser": "^0.6.0", + "unicode-match-property-ecmascript": "^1.0.4", + "unicode-match-property-value-ecmascript": "^1.1.0" + } + }, + "registry-auth-token": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.1.1.tgz", + "integrity": "sha512-9bKS7nTl9+/A1s7tnPeGrUpRcVY+LUh7bfFgzpndALdPfXQBfQV77rQVtqgUV3ti4vc/Ik81Ex8UJDWDQ12zQA==", + "dev": true, + "requires": { + "rc": "^1.2.8" + } + }, + "registry-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", + "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", + "dev": true, + "requires": { + "rc": "^1.2.8" + } + }, + "regjsgen": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.1.tgz", + "integrity": "sha512-5qxzGZjDs9w4tzT3TPhCJqWdCc3RLYwy9J2NB0nm5Lz+S273lvWcpjaTGHsT1dc6Hhfq41uSEOw8wBmxrKOuyg==", + "dev": true + }, + "regjsparser": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.2.tgz", + "integrity": "sha512-E9ghzUtoLwDekPT0DYCp+c4h+bvuUpe6rRHCTYn6eGoqj1LgKXxT6I0Il4WbjhQkOghzi/V+y03bPKvbllL93Q==", + "dev": true, + "requires": { + "jsesc": "~0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true + } + } + }, "release-zalgo": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", @@ -15147,9 +10897,9 @@ "optional": true }, "repeat-element": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", - "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", "dev": true, "optional": true }, @@ -15165,51 +10915,6 @@ "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", "dev": true }, - "request": { - "version": "2.88.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", - "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", - "dev": true, - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.0", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.4.3", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "dependencies": { - "uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", - "dev": true - } - } - }, - "request-progress": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-2.0.1.tgz", - "integrity": "sha1-XTa7V5YcZzqlt4jbyBQf3yO0Tgg=", - "dev": true, - "requires": { - "throttleit": "^1.0.0" - } - }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -15260,29 +10965,6 @@ } } }, - "requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", - "dev": true - }, - "requizzle": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.3.tgz", - "integrity": "sha512-YanoyJjykPxGHii0fZP0uUPEXpvqfBDxWV7s6GKAiiOsiqhX6vHNyW3Qzdmqp/iq/ExbhaGbVrjB4ruEVSM4GQ==", - "dev": true, - "requires": { - "lodash": "^4.17.14" - }, - "dependencies": { - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - } - } - }, "resolve": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", @@ -15360,12 +11042,6 @@ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true }, - "rfdc": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.4.tgz", - "integrity": "sha512-5C9HXdzK8EAqN7JDif30jqsBzavB7wLpaubisuQIGHWf2gUXSpzy6ArX/+Da8RjFpagWsCn+pIgxTMAmKw9Zug==", - "dev": true - }, "rimraf": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", @@ -15376,9 +11052,9 @@ } }, "rollup": { - "version": "1.29.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.29.1.tgz", - "integrity": "sha512-dGQ+b9d1FOX/gluiggTAVnTvzQZUEkCi/TwZcax7ujugVRHs0nkYJlV9U4hsifGEMojnO+jvEML2CJQ6qXgbHA==", + "version": "1.31.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.31.0.tgz", + "integrity": "sha512-9C6ovSyNeEwvuRuUUmsTpJcXac1AwSL1a3x+O5lpmQKZqi5mmrjauLeqIjvREC+yNRR8fPdzByojDng+af3nVw==", "dev": true, "requires": { "@types/estree": "*", @@ -15404,13 +11080,45 @@ "rollup-pluginutils": "^2.8.1" } }, + "rollup-plugin-typescript2": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/rollup-plugin-typescript2/-/rollup-plugin-typescript2-0.25.3.tgz", + "integrity": "sha512-ADkSaidKBovJmf5VBnZBZe+WzaZwofuvYdzGAKTN/J4hN7QJCFYAq7IrH9caxlru6T5qhX41PNFS1S4HqhsGQg==", + "dev": true, + "requires": { + "find-cache-dir": "^3.0.0", + "fs-extra": "8.1.0", + "resolve": "1.12.0", + "rollup-pluginutils": "2.8.1", + "tslib": "1.10.0" + }, + "dependencies": { + "resolve": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", + "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + } + } + }, "rollup-pluginutils": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", - "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.1.tgz", + "integrity": "sha512-J5oAoysWar6GuZo0s+3bZ6sVZAC0pfqKz68De7ZgDi5z63jOVZn1uJL/+z1jeKHNbGII8kAyHF5q8LnxSX5lQg==", "dev": true, "requires": { "estree-walker": "^0.6.1" + }, + "dependencies": { + "estree-walker": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", + "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", + "dev": true + } } }, "run-async": { @@ -15458,168 +11166,67 @@ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, - "safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "optional": true, - "requires": { - "ret": "~0.1.10" - } - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "sanitize-html": { - "version": "1.21.1", - "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-1.21.1.tgz", - "integrity": "sha512-W6enXSVphVaVbmVbzVngBthR5f5sMmhq3EfPfBlzBzp2WnX8Rnk7NGpP7KmHUc0Y3MVk9tv/+CbpdHchX9ai7g==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "htmlparser2": "^3.10.0", - "lodash.clonedeep": "^4.5.0", - "lodash.escaperegexp": "^4.1.2", - "lodash.isplainobject": "^4.0.6", - "lodash.isstring": "^4.0.1", - "lodash.mergewith": "^4.6.1", - "postcss": "^7.0.5", - "srcset": "^1.0.0", - "xtend": "^4.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "sauce-connect-launcher": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/sauce-connect-launcher/-/sauce-connect-launcher-1.3.1.tgz", - "integrity": "sha512-vIf9qDol3q2FlYzrKt0dr3kvec6LSjX2WS+/mVnAJIhqh1evSkPKCR2AzcJrnSmx9Xt9PtV0tLY7jYh0wsQi8A==", - "dev": true, - "requires": { - "adm-zip": "~0.4.3", - "async": "^2.1.2", - "https-proxy-agent": "^3.0.0", - "lodash": "^4.16.6", - "rimraf": "^2.5.4" - } - }, - "saucelabs": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/saucelabs/-/saucelabs-1.5.0.tgz", - "integrity": "sha512-jlX3FGdWvYf4Q3LFfFWS1QvPg3IGCGWxIc8QBFdPTbpTJnt/v17FHXYVAn7C8sHf1yUXo2c7yIM0isDryfYtHQ==", - "dev": true, - "requires": { - "https-proxy-agent": "^2.2.1" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "https-proxy-agent": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", - "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", - "dev": true, - "requires": { - "agent-base": "^4.3.0", - "debug": "^3.1.0" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "optional": true, + "requires": { + "ret": "~0.1.10" } }, - "sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true }, - "selenium-webdriver": { - "version": "4.0.0-alpha.5", - "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-4.0.0-alpha.5.tgz", - "integrity": "sha512-hktl3DSrhzM59yLhWzDGHIX9o56DvA+cVK7Dw6FcJR6qQ4CGzkaHeXQPcdrslkWMTeq0Ci9AmCxq0EMOvm2Rkg==", + "sanitize-html": { + "version": "1.21.1", + "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-1.21.1.tgz", + "integrity": "sha512-W6enXSVphVaVbmVbzVngBthR5f5sMmhq3EfPfBlzBzp2WnX8Rnk7NGpP7KmHUc0Y3MVk9tv/+CbpdHchX9ai7g==", "dev": true, "requires": { - "jszip": "^3.1.5", - "rimraf": "^2.6.3", - "tmp": "0.0.30", - "xml2js": "^0.4.19" + "chalk": "^2.4.1", + "htmlparser2": "^3.10.0", + "lodash.clonedeep": "^4.5.0", + "lodash.escaperegexp": "^4.1.2", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.mergewith": "^4.6.1", + "postcss": "^7.0.5", + "srcset": "^1.0.0", + "xtend": "^4.0.1" }, "dependencies": { - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "color-convert": "^1.9.0" } }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { - "glob": "^7.1.3" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" } }, - "tmp": { - "version": "0.0.30", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.30.tgz", - "integrity": "sha1-ckGdSovn1s51FI/YsyTlk6cRwu0=", + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "requires": { - "os-tmpdir": "~1.0.1" + "has-flag": "^3.0.0" } } } @@ -15663,16 +11270,10 @@ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, - "set-immediate-shim": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", - "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", - "dev": true - }, "set-value": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", - "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", "dev": true, "optional": true, "requires": { @@ -15694,12 +11295,6 @@ } } }, - "setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", - "dev": true - }, "shebang-command": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", @@ -15739,9 +11334,9 @@ "dev": true }, "simple-html-tokenizer": { - "version": "0.5.8", - "resolved": "https://registry.npmjs.org/simple-html-tokenizer/-/simple-html-tokenizer-0.5.8.tgz", - "integrity": "sha512-0Sq4FvLlQEQODVA6PH2MIrc7tzYO0KT2HzzwvaVLYClWgIsuvaNUOrhrAvTi1pZHrcq7GDB4WiI3ukjqBMxcGQ==", + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/simple-html-tokenizer/-/simple-html-tokenizer-0.5.9.tgz", + "integrity": "sha512-w/3FEDN94r4JQ9WoYrIr8RqDIPZdyNkdpbK9glFady1CAEyD97XWCv8HFetQO21w81e7h7Nh59iYTyG1mUJftg==", "dev": true }, "sinon": { @@ -15911,6 +11506,13 @@ "kind-of": "^3.2.0" }, "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true, + "optional": true + }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", @@ -15923,98 +11525,6 @@ } } }, - "socket.io": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.1.1.tgz", - "integrity": "sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==", - "dev": true, - "requires": { - "debug": "~3.1.0", - "engine.io": "~3.2.0", - "has-binary2": "~1.0.2", - "socket.io-adapter": "~1.1.0", - "socket.io-client": "2.1.1", - "socket.io-parser": "~3.2.0" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } - } - }, - "socket.io-adapter": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.2.tgz", - "integrity": "sha512-WzZRUj1kUjrTIrUKpZLEzFZ1OLj5FwLlAFQs9kuZJzJi5DKdU7FsWc36SNmA8iDOtwBQyT8FkrriRM8vXLYz8g==", - "dev": true - }, - "socket.io-client": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz", - "integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==", - "dev": true, - "requires": { - "backo2": "1.0.2", - "base64-arraybuffer": "0.1.5", - "component-bind": "1.0.0", - "component-emitter": "1.2.1", - "debug": "~3.1.0", - "engine.io-client": "~3.2.0", - "has-binary2": "~1.0.2", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "object-component": "0.0.3", - "parseqs": "0.0.5", - "parseuri": "0.0.5", - "socket.io-parser": "~3.2.0", - "to-array": "0.1.4" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } - } - }, - "socket.io-parser": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", - "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==", - "dev": true, - "requires": { - "component-emitter": "1.2.1", - "debug": "~3.1.0", - "isarray": "2.0.1" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "isarray": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", - "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", - "dev": true - } - } - }, "socks": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/socks/-/socks-2.3.3.tgz", @@ -16053,19 +11563,37 @@ "dev": true }, "source-map-resolve": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", - "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", "dev": true, "optional": true, "requires": { - "atob": "^2.1.1", + "atob": "^2.1.2", "decode-uri-component": "^0.2.0", "resolve-url": "^0.2.1", "source-map-url": "^0.4.0", "urix": "^0.1.0" } }, + "source-map-support": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.16.tgz", + "integrity": "sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, "source-map-url": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", @@ -16073,6 +11601,12 @@ "dev": true, "optional": true }, + "spawn-please": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/spawn-please/-/spawn-please-0.3.0.tgz", + "integrity": "sha1-2zOOxM/2Orxp8dDgjO6euL69nRE=", + "dev": true + }, "spawn-wrap": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz", @@ -16137,9 +11671,9 @@ } }, "spdx-correct": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", - "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", + "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", "dev": true, "requires": { "spdx-expression-parse": "^3.0.0", @@ -16147,9 +11681,9 @@ } }, "spdx-exceptions": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz", - "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", "dev": true }, "spdx-expression-parse": { @@ -16163,9 +11697,9 @@ } }, "spdx-license-ids": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz", - "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", + "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", "dev": true }, "split-string": { @@ -16194,23 +11728,6 @@ "number-is-nan": "^1.0.0" } }, - "sshpk": { - "version": "1.14.2", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz", - "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=", - "dev": true, - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - } - }, "ssri": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/ssri/-/ssri-7.1.0.tgz", @@ -16238,6 +11755,18 @@ "standard-engine": "^12.0.0" }, "dependencies": { + "acorn": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", + "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==", + "dev": true + }, + "acorn-jsx": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.1.0.tgz", + "integrity": "sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw==", + "dev": true + }, "ansi-regex": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", @@ -16264,6 +11793,27 @@ "supports-color": "^5.3.0" } }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, "debug": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", @@ -16460,12 +12010,14 @@ } } }, - "eslint-utils": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", - "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", + "espree": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/espree/-/espree-6.1.2.tgz", + "integrity": "sha512-2iUPuuPP+yW1PZaMSDM9eyVf8D5P0Hi8h83YtZ5bPc/zHYjII5khoixIUTMO794NOY8F/ThF1Bo8ncZILarUTA==", "dev": true, "requires": { + "acorn": "^7.1.0", + "acorn-jsx": "^5.1.0", "eslint-visitor-keys": "^1.1.0" } }, @@ -16498,12 +12050,6 @@ "write": "1.0.3" } }, - "get-stdin": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-7.0.0.tgz", - "integrity": "sha512-zRKcywvrXlXsA0v0i9Io4KDRaAw7+a1ZpjRwl9Wox8PFlVCCHra7E9c4kqXCoCM9nR5tBkaTTZRBoCm60bFqTQ==", - "dev": true - }, "glob": { "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", @@ -16518,32 +12064,18 @@ "path-is-absolute": "^1.0.0" } }, - "glob-parent": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz", - "integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - }, - "dependencies": { - "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - } - } - }, "globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, "inquirer": { "version": "6.5.2", "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", @@ -16565,16 +12097,6 @@ "through": "^2.3.6" } }, - "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, "jsx-ast-utils": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.2.3.tgz", @@ -16597,6 +12119,12 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "dev": true + }, "regexpp": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", @@ -16688,6 +12216,12 @@ "pkg-config": "^1.0.1" }, "dependencies": { + "get-stdin": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz", + "integrity": "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g=", + "dev": true + }, "minimist": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", @@ -16697,9 +12231,9 @@ } }, "state-toggle": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.2.tgz", - "integrity": "sha512-8LpelPGR0qQM4PnfLiplOQNJcIN1/r2Gy0xKB2zKnIW2YzPMt2sR4I/+gtPjhN7Svh9kw+zqEg2SFwpBO9iNiw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.3.tgz", + "integrity": "sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ==", "dev": true }, "static-extend": { @@ -16725,68 +12259,6 @@ } } }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", - "dev": true - }, - "streamroller": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-1.0.6.tgz", - "integrity": "sha512-3QC47Mhv3/aZNFpDDVO44qQb9gwB9QggMEE0sQmkTAwBVYdBRWISdsywlkfm5II1Q5y/pmrHflti/IgmIzdDBg==", - "dev": true, - "requires": { - "async": "^2.6.2", - "date-format": "^2.0.0", - "debug": "^3.2.6", - "fs-extra": "^7.0.1", - "lodash": "^4.17.14" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, "string-argv": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz", @@ -16938,12 +12410,6 @@ "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", "dev": true }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - }, "slice-ansi": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", @@ -16977,12 +12443,6 @@ } } }, - "taffydb": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz", - "integrity": "sha1-fLy2S1oUG2ou/CxdLGe04VCyomg=", - "dev": true - }, "tar": { "version": "5.0.5", "resolved": "https://registry.npmjs.org/tar/-/tar-5.0.5.tgz", @@ -17014,17 +12474,6 @@ "execa": "^0.7.0" }, "dependencies": { - "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "dev": true, - "requires": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, "execa": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", @@ -17075,12 +12524,6 @@ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, - "throttleit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz", - "integrity": "sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw=", - "dev": true - }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -17096,12 +12539,6 @@ "os-tmpdir": "~1.0.2" } }, - "to-array": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", - "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=", - "dev": true - }, "to-fast-properties": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", @@ -17118,6 +12555,13 @@ "kind-of": "^3.0.2" }, "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true, + "optional": true + }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", @@ -17150,38 +12594,12 @@ } }, "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "optional": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } - }, - "toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", - "dev": true - }, - "tough-cookie": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", - "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, "requires": { - "psl": "^1.1.24", - "punycode": "^1.4.1" - }, - "dependencies": { - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true - } + "is-number": "^7.0.0" } }, "trim": { @@ -17202,10 +12620,31 @@ "integrity": "sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==", "dev": true }, + "ts-node": { + "version": "8.6.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.6.2.tgz", + "integrity": "sha512-4mZEbofxGqLL2RImpe3zMJukvEvcO1XP8bj8ozBPySdCUXEcU5cIRwR0aM3R+VoZq7iXc8N86NC0FspGRqP4gg==", + "dev": true, + "requires": { + "arg": "^4.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "source-map-support": "^0.5.6", + "yn": "3.1.1" + }, + "dependencies": { + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true + } + } + }, "tslib": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", - "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==", "dev": true }, "tsutils": { @@ -17217,22 +12656,6 @@ "tslib": "^1.8.1" } }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true, - "optional": true - }, "type": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", @@ -17260,52 +12683,75 @@ "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", "dev": true }, - "type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dev": true, + "requires": { + "is-typedarray": "^1.0.0" + } + }, + "typedoc": { + "version": "0.16.9", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.16.9.tgz", + "integrity": "sha512-UvOGoy76yqwCXwxPgatwgXWfsQ3FczyZ6ZNLjhCPK+TsDir6LiU3YB6N9XZmPv36E+7LA860mnc8a0v6YADKFw==", "dev": true, "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" + "@types/minimatch": "3.0.3", + "fs-extra": "^8.1.0", + "handlebars": "^4.7.2", + "highlight.js": "^9.17.1", + "lodash": "^4.17.15", + "marked": "^0.8.0", + "minimatch": "^3.0.0", + "progress": "^2.0.3", + "shelljs": "^0.8.3", + "typedoc-default-themes": "^0.7.2", + "typescript": "3.7.x" }, "dependencies": { - "mime-db": { - "version": "1.43.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", - "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==", + "marked": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-0.8.0.tgz", + "integrity": "sha512-MyUe+T/Pw4TZufHkzAfDj6HarCBWia2y27/bhuYkTaiUnfDYFnCP3KUN+9oM7Wi6JA2rymtVYbQu3spE0GCmxQ==", "dev": true }, - "mime-types": { - "version": "2.1.26", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", - "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", + "shelljs": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.3.tgz", + "integrity": "sha512-fc0BKlAWiLpwZljmOvAOTE/gXawtCoNrP5oaY7KIaQbbyHeQVg01pSEuEGvGh3HEdBU4baCD7wQBwADmM/7f7A==", "dev": true, "requires": { - "mime-db": "1.43.0" + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" } } } }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "typedoc-default-themes": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/typedoc-default-themes/-/typedoc-default-themes-0.7.2.tgz", + "integrity": "sha512-fiFKlFO6VTqjcno8w6WpTsbCgXmfPHVjnLfYkmByZE7moaz+E2DSpAT+oHtDHv7E0BM5kAhPrHJELP2J2Y2T9A==", "dev": true, "requires": { - "is-typedarray": "^1.0.0" + "backbone": "^1.4.0", + "jquery": "^3.4.1", + "lunr": "^2.3.8", + "underscore": "^1.9.1" } }, - "uc.micro": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", - "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", + "typescript": { + "version": "3.7.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.5.tgz", + "integrity": "sha512-/P5lkRXkWHNAbcJIiHPfRoKqyd7bsyCma1hZNUGfn20qm64T6ZBlrzprymeu918H+mB/0rIg2gGK/BXkhhYgBw==", "dev": true }, "uglify-js": { @@ -17332,12 +12778,6 @@ } } }, - "ultron": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", - "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==", - "dev": true - }, "underscore": { "version": "1.9.2", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.2.tgz", @@ -17345,13 +12785,13 @@ "dev": true }, "unherit": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.2.tgz", - "integrity": "sha512-W3tMnpaMG7ZY6xe/moK04U9fBhi6wEiCYHUW5Mop/wQHf12+79EQGwxYejNdhEz2mkqkBlGwm7pxmgBKMVUj0w==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.3.tgz", + "integrity": "sha512-Ft16BJcnapDKp0+J/rqFC3Rrk6Y/Ng4nzsC028k2jdDII/rdZ7Wd3pPT/6+vIIxRagwRc9K0IUX0Ra4fKvw+WQ==", "dev": true, "requires": { - "inherits": "^2.0.1", - "xtend": "^4.0.1" + "inherits": "^2.0.0", + "xtend": "^4.0.0" } }, "unicode-canonical-property-names-ecmascript": { @@ -17405,41 +12845,16 @@ } }, "union-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", - "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", "dev": true, "optional": true, "requires": { "arr-union": "^3.1.0", "get-value": "^2.0.6", "is-extendable": "^0.1.1", - "set-value": "^0.4.3" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "optional": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "set-value": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", - "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", - "dev": true, - "optional": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.1", - "to-object-path": "^0.3.0" - } - } + "set-value": "^2.0.1" } }, "uniq": { @@ -17523,12 +12938,6 @@ "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", "dev": true }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", - "dev": true - }, "unset-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", @@ -17580,6 +12989,57 @@ "dev": true, "optional": true }, + "update-notifier": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-3.0.1.tgz", + "integrity": "sha512-grrmrB6Zb8DUiyDIaeRTBCkgISYUgETNe7NglEbVsrLWXeESnlCSP50WfRSj/GmzMPl6Uchj24S/p80nP/ZQrQ==", + "dev": true, + "requires": { + "boxen": "^3.0.0", + "chalk": "^2.0.1", + "configstore": "^4.0.0", + "has-yarn": "^2.1.0", + "import-lazy": "^2.1.0", + "is-ci": "^2.0.0", + "is-installed-globally": "^0.1.0", + "is-npm": "^3.0.0", + "is-yarn-global": "^0.3.0", + "latest-version": "^5.0.0", + "semver-diff": "^2.0.0", + "xdg-basedir": "^3.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, "uri-js": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", @@ -17596,6 +13056,15 @@ "dev": true, "optional": true }, + "url-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", + "dev": true, + "requires": { + "prepend-http": "^2.0.0" + } + }, "use": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", @@ -17612,28 +13081,12 @@ "os-homedir": "^1.0.0" } }, - "useragent": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz", - "integrity": "sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==", - "dev": true, - "requires": { - "lru-cache": "4.1.x", - "tmp": "0.0.x" - } - }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", - "dev": true - }, "uuid": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", @@ -17646,15 +13099,6 @@ "integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==", "dev": true }, - "v8flags": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.3.tgz", - "integrity": "sha512-amh9CCg3ZxkzQ48Mhcb8iX7xpAfYJgePHxWMQCBWECpOSqJUXgY26ncA61UTV0BkPqfhcy6mzwCIoP4ygxpW8w==", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1" - } - }, "validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", @@ -17674,17 +13118,6 @@ "builtins": "^1.0.3" } }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, "vfile": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/vfile/-/vfile-4.0.2.tgz", @@ -17696,14 +13129,6 @@ "replace-ext": "1.0.0", "unist-util-stringify-position": "^2.0.0", "vfile-message": "^2.0.0" - }, - "dependencies": { - "is-buffer": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", - "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==", - "dev": true - } } }, "vfile-location": { @@ -17770,12 +13195,6 @@ } } }, - "void-elements": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", - "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=", - "dev": true - }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", @@ -17806,68 +13225,44 @@ "string-width": "^1.0.2 || 2" } }, + "widest-line": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz", + "integrity": "sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==", + "dev": true, + "requires": { + "string-width": "^2.1.1" + } + }, "word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", "dev": true }, - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", - "dev": true - }, "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-3.0.1.tgz", + "integrity": "sha1-KIoE2H7aXChuBg3+jxNc6NAH+Lo=", "dev": true, "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0" }, "dependencies": { "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "^4.1.0" + "ansi-regex": "^3.0.0" } } } @@ -17899,43 +13294,10 @@ "typedarray-to-buffer": "^3.1.5" } }, - "ws": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", - "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", - "dev": true, - "requires": { - "async-limiter": "~1.0.0", - "safe-buffer": "~5.1.0", - "ultron": "~1.1.0" - } - }, - "xml2js": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", - "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", - "dev": true, - "requires": { - "sax": ">=0.6.0", - "xmlbuilder": "~11.0.0" - } - }, - "xmlbuilder": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", - "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", - "dev": true - }, - "xmlcreate": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.1.tgz", - "integrity": "sha512-MjGsXhKG8YjTKrDCXseFo3ClbMGvUD4en29H2Cev1dv4P/chlpw6KdYmlCWDkhosBVKRDjM836+3e3pm1cBNJA==", - "dev": true - }, - "xmlhttprequest-ssl": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", - "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=", + "xdg-basedir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", + "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=", "dev": true }, "xtend": { @@ -17974,14 +13336,6 @@ "lines-and-columns": "^1.1.6", "tslib": "^1.10.0", "yaml": "^1.7.1" - }, - "dependencies": { - "tslib": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", - "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==", - "dev": true - } } }, "yargs": { @@ -18093,14 +13447,6 @@ "requires": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" - }, - "dependencies": { - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - } } }, "yargs-unparser": { @@ -18112,29 +13458,12 @@ "flat": "^4.1.0", "lodash": "^4.17.15", "yargs": "^13.3.0" - }, - "dependencies": { - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - } - } - }, - "yauzl": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz", - "integrity": "sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=", - "dev": true, - "requires": { - "fd-slicer": "~1.0.1" } }, - "yeast": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", - "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=", + "yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", "dev": true } } diff --git a/package.json b/package.json index ebe55c63..e4cf954c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "js-data", "description": "Robust, framework-agnostic in-memory data store.", - "version": "3.0.6", + "version": "4.0.0-beta.4", "homepage": "http://www.js-data.io", "repository": { "type": "git", @@ -11,14 +11,11 @@ "license": "MIT", "main": "./dist/js-data.js", "jsnext:main": "dist/js-data.es2015.js", - "typings": "./dist/js-data.d.ts", + "types": "./dist/index.d.ts", "files": [ "dist/", - "lib/", - "src/", "AUTHORS", - "CONTRIBUTORS", - "typings.json" + "CONTRIBUTORS" ], "keywords": [ "orm", @@ -34,7 +31,7 @@ "localstorage" ], "standard": { - "parser": "babel-eslint", + "parser": "@typescript-eslint/parser", "globals": [ "beforeEach", "after", @@ -45,67 +42,58 @@ "scripts": { "banner": "node scripts/banner.js", "build": "npm run lint && npm run bundle && npm run min && npm run banner", - "bundle:es5": "rollup src/index.js -c -o dist/js-data.js -m dist/js-data.js.map -f umd", - "bundle:next": "rollup src/index.js -c -o dist/js-data.es2015.js -m dist/js-data.es2015.js.map -f es", + "bundle:es5": "rollup src/index.ts -c -o dist/js-data.js -m dist/js-data.js.map -f umd", + "bundle:next": "rollup src/index.ts -c -o dist/js-data.es2015.js -m dist/js-data.es2015.js.map -f es", "bundle": "npm run bundle:es5 && npm run bundle:next && repo-tools write-version dist/js-data.js dist/js-data.es2015.js", - "cover": "nyc --require @babel/register --require @babel/polyfill --cache mocha --recursive -R dot && nyc report --reporter=html", - "doc": "jsdoc -c conf.json src && node scripts/cleanup.js", + "cover": "nyc npm run mocha && nyc report --reporter=html", + "doc": "typedoc --out doc src", "gzip": "echo gzipped size: $(cat dist/js-data.min.js | gzip -f9 | wc -c)kb", - "lint": "eslint --fix src/**/*.js && standard --fix 'src/**/*.js' 'test/**/*.js' 'scripts/*.js' 'lib/**/*.js' '*.config.js'", + "lint": "eslint --fix 'src/**/*.ts' 'test/**/*.ts' && standard --fix 'scripts/*.js' '*.config.js'", "min": "uglifyjs -o dist/js-data.min.js --source-map url=js-data.min.map -v -m -c --keep-fnames --screw-ie8 -- dist/js-data.js", - "mocha": "mocha -b --recursive -R dot -r @babel/register -r @babel/polyfill", + "mocha": "mocha --recursive -t 20000 -R dot -r ts-node/register './**/*.test.ts'", "precommit": "lint-staged && npm run lint", "prepush": "npm test", - "release": "npm test && npm run doc && repo-tools updates && repo-tools changelog && repo-tools authors", + "release": "npm test && npm run doc && repo-tools changelog && repo-tools authors", "test": "npm run build && npm run cover" }, "lint-staged": { - "linters": { - "src/**/*.js": [ - "prettier-standard", - "git add" - ] - } + "{src,test}/**/*.ts": "eslint --fix" }, "devDependencies": { - "@babel/cli": "^7.8.3", - "@babel/core": "^7.8.3", - "@babel/node": "^7.8.3", - "@babel/plugin-external-helpers": "^7.8.3", + "@babel/cli": "^7.8.4", + "@babel/core": "^7.8.4", + "@babel/plugin-proposal-class-properties": "^7.8.3", "@babel/plugin-transform-modules-umd": "^7.8.3", - "@babel/plugin-transform-regenerator": "^7.8.3", - "@babel/polyfill": "^7.8.3", - "@babel/preset-env": "^7.8.3", + "@babel/preset-env": "^7.8.4", + "@babel/preset-typescript": "^7.8.3", "@js-data/repo-tools": "^1.0.1", - "babel-eslint": "^10.0.3", + "@types/chai": "^4.2.8", + "@types/mocha": "^7.0.1", + "@types/sinon": "^7.5.1", + "@typescript-eslint/eslint-plugin": "^2.17.0", "chai": "^4.2.0", "eslint": "^6.8.0", - "eslint-config-standard": "^14.1.0", + "eslint-config-standard-with-typescript": "^12.0.1", "eslint-plugin-import": "^2.20.0", "eslint-plugin-node": "^11.0.0", "eslint-plugin-promise": "^4.2.1", "eslint-plugin-standard": "^4.0.1", "husky": "^4.2.1", "ink-docstrap": "git+https://github.com/js-data/docstrap.git#cfbe45fa313e1628c493076d5e15d2b855dfbf2c", - "jsdoc": "^3.6.3", - "karma": "^4.4.1", - "karma-babel-preprocessor": "^8.0.1", - "karma-chai": "^0.1.0", - "karma-chrome-launcher": "^3.1.0", - "karma-mocha": "^1.3.0", - "karma-phantomjs-launcher": "^1.0.4", - "karma-sauce-launcher": "^2.0.2", - "karma-sinon": "^1.0.5", - "lint-staged": "^10.0.2", + "lint-staged": "^10.0.7", "lodash": "^4.17.15", "mocha": "^7.0.0", "nyc": "15.0.0", - "phantomjs-prebuilt": "^2.1.16", "prettier-standard": "^16.1.0", - "rollup": "^1.29.0", + "rollup": "^1.31.0", "rollup-plugin-babel": "^4.3.3", + "rollup-plugin-typescript2": "^0.25.3", "sinon": "^8.1.0", - "standard": "14.3.1", + "standard": "^14.3.1", + "ts-node": "^8.6.2", + "tslib": "^1.10.0", + "typedoc": "^0.16.9", + "typescript": "^3.7.5", "uglify-js": "^3.7.6" } } diff --git a/rollup.config.js b/rollup.config.js index e29df31b..20184626 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -1,27 +1,27 @@ +import typescript from 'rollup-plugin-typescript2' import babel from 'rollup-plugin-babel' -export default { - output: { - amd: { - id: 'js-data' +export default commandLineArgs => { + const isUmd = commandLineArgs.format === 'umd' + return { + output: { + amd: { + id: 'js-data' + }, + name: 'JSData' }, - name: 'JSData' - }, - plugins: [ - babel({ - babelrc: false, - presets: [ - [ - '@babel/preset-env', - { - modules: false, - targets: { - browsers: ['last 2 versions', 'safari >= 7', '> 1%', 'IE 11'] - } - } - ] - ], - exclude: 'node_modules/**' - }) - ] + plugins: [ + typescript({ + tsconfigOverride: { + compilerOptions: { + module: 'es2015', + declaration: isUmd + }, + include: ['src'], + exclude: ['node_modules', 'test', 'scripts', './rollup.config.js'] + } + }), + isUmd && babel({ extensions: ['.ts'] }) + ] + } } diff --git a/src/Collection.js b/src/Collection.ts similarity index 86% rename from src/Collection.js rename to src/Collection.ts index bf72dcab..96c3ca34 100644 --- a/src/Collection.js +++ b/src/Collection.ts @@ -1,14 +1,14 @@ import utils from './utils' -import Component from './Component' +import Component, { ComponentOpts } from './Component' import Query from './Query' import Record from './Record' -import Index from '../lib/mindex/index' +import Index from './mindex' const { noValidatePath } = Record const DOMAIN = 'Collection' -const COLLECTION_DEFAULTS = { +export interface CollectionOpts extends ComponentOpts { /** * Whether to call {@link Record#commit} on records that are added to the * collection and already exist in the collection. @@ -17,7 +17,7 @@ const COLLECTION_DEFAULTS = { * @type {boolean} * @default true */ - commitOnMerge: true, + commitOnMerge?: boolean /** * Whether record events should bubble up and be emitted by the collection. @@ -26,7 +26,7 @@ const COLLECTION_DEFAULTS = { * @type {boolean} * @default true */ - emitRecordEvents: true, + emitRecordEvents?: boolean /** * Field to be used as the unique identifier for records in this collection. @@ -37,7 +37,7 @@ const COLLECTION_DEFAULTS = { * @type {string} * @default "id" */ - idAttribute: 'id', + idAttribute?: string /** * What to do when inserting a record into this Collection that shares a @@ -63,10 +63,15 @@ const COLLECTION_DEFAULTS = { * * Ignore new record, keep existing record. * - * @name Collection#onConflict - * @type {string} * @default "merge" */ + onConflict?: 'merge' | 'replace' | 'skip' +} + +const COLLECTION_DEFAULTS: CollectionOpts = { + commitOnMerge: true, + emitRecordEvents: true, + idAttribute: 'id', onConflict: 'merge' } @@ -95,100 +100,83 @@ const COLLECTION_DEFAULTS = { * @param {string} [opts.mapper] See {@link Collection#mapper}. * @since 3.0.0 */ -function Collection (records, opts) { - utils.classCallCheck(this, Collection) - Component.call(this, opts) +export default class Collection extends Component { + queryClass + emitRecordEvents: any + onConflict: string + /** + * Default Mapper for this collection. Optional. If a Mapper is provided, then + * the collection will use the {@link Mapper#idAttribute} setting, and will + * wrap records in {@link Mapper#recordClass}. + * + * @example Collection#mapper + * const JSData = require('js-data'); + * const {Collection, Mapper} = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * class MyMapperClass extends Mapper { + * foo () { return 'bar'; } + * } + * const myMapper = new MyMapperClass({ name: 'myMapper' }); + * const collection = new Collection(null, { mapper: myMapper }); + * + * @name Collection#mapper + * @type {Mapper} + * @default null + * @since 3.0.0 + */ + mapper: any + /** + * The main index, which uses @{link Collection#recordId} as the key. + * + * @name Collection#index + * @type {Index} + */ + index: Index + /** + * Object that holds the secondary indexes of this collection. + * + * @name Collection#indexes + * @type {Object.} + */ + indexes: { [key: string]: Index } = {} + idAttribute: any + _added = {} + emit: any - if (records && !utils.isArray(records)) { - opts = records - records = [] - } - if (utils.isString(opts)) { - opts = { idAttribute: opts } - } + constructor (records: any = {}, opts: CollectionOpts | string | any = {}) { + super(opts) - // Default values for arguments - records || (records = []) - opts || (opts = {}) - - Object.defineProperties(this, { - /** - * Default Mapper for this collection. Optional. If a Mapper is provided, then - * the collection will use the {@link Mapper#idAttribute} setting, and will - * wrap records in {@link Mapper#recordClass}. - * - * @example Collection#mapper - * const JSData = require('js-data'); - * const {Collection, Mapper} = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * class MyMapperClass extends Mapper { - * foo () { return 'bar'; } - * } - * const myMapper = new MyMapperClass({ name: 'myMapper' }); - * const collection = new Collection(null, { mapper: myMapper }); - * - * @name Collection#mapper - * @type {Mapper} - * @default null - * @since 3.0.0 - */ - mapper: { - value: undefined, - writable: true - }, - // Query class used by this collection - queryClass: { - value: undefined, - writable: true + if (records && !utils.isArray(records)) { + opts = records + records = [] + } + if (utils.isString(opts)) { + opts = { idAttribute: opts } } - }) - - // Apply user-provided configuration - utils.fillIn(this, opts) - // Fill in any missing options with the defaults - utils.fillIn(this, utils.copy(COLLECTION_DEFAULTS)) - if (!this.queryClass) { - this.queryClass = Query - } + // Apply user-provided configuration + utils.fillIn(this, opts) + // Fill in any missing options with the defaults + utils.fillIn(this, utils.copy(COLLECTION_DEFAULTS)) - const idAttribute = this.recordId() - - Object.defineProperties(this, { - /** - * The main index, which uses @{link Collection#recordId} as the key. - * - * @name Collection#index - * @type {Index} - */ - index: { - value: new Index([idAttribute], { - hashCode (obj) { - return utils.get(obj, idAttribute) - } - }) - }, - - /** - * Object that holds the secondary indexes of this collection. - * - * @name Collection#indexes - * @type {Object.} - */ - indexes: { - value: {} + if (!this.queryClass) { + this.queryClass = Query } - }) - // Insert initial data into the collection - if (utils.isObject(records) || (utils.isArray(records) && records.length)) { - this.add(records) - } -} + const idAttribute = this.recordId() + + this.index = new Index([idAttribute], { + hashCode (obj) { + return utils.get(obj, idAttribute) + } + }) -export default Component.extend({ - constructor: Collection, + // Insert initial data into the collection + if (utils.isObject(records) || (utils.isArray(records) && records.length)) { + this.add(records) + } + } /** * Used to bind to events emitted by records in this Collection. @@ -196,13 +184,13 @@ export default Component.extend({ * @method Collection#_onRecordEvent * @since 3.0.0 * @private - * @param {...*} [arg] Args passed to {@link Collection#emit}. + * @param {...*} [args] Args passed to {@link Collection#emit}. */ _onRecordEvent (...args) { if (this.emitRecordEvents) { this.emit(...args) } - }, + } /** * Insert the provided record or records. @@ -216,17 +204,14 @@ export default Component.extend({ * * @method Collection#add * @since 3.0.0 - * @param {(Object|Object[]|Record|Record[])} data The record or records to insert. + * @param {(Object|Object[]|Record|Record[])} records The record or records to insert. * @param {object} [opts] Configuration options. * @param {boolean} [opts.commitOnMerge=true] See {@link Collection#commitOnMerge}. * @param {boolean} [opts.noValidate] See {@link Record#noValidate}. * @param {string} [opts.onConflict] See {@link Collection#onConflict}. * @returns {(Object|Object[]|Record|Record[])} The added record or records. */ - add (records, opts) { - // Default values for arguments - opts || (opts = {}) - + add (records, opts: any = {}) { // Fill in "opts" with the Collection's configuration utils._(opts, this) records = this.beforeAdd(records, opts) || records @@ -304,12 +289,12 @@ export default Component.extend({ // Update all indexes in the collection this.updateIndexes(record) } else { - // Here, the currently visted record does not correspond to any record + // Here, the currently visited record does not correspond to any record // in the collection, so (optionally) instantiate this record and insert // it into the collection record = this.mapper ? this.mapper.createRecord(record, opts) : record this.index.insertRecord(record) - utils.forOwn(this.indexes, function (index, name) { + utils.forOwn(this.indexes, (index, name) => { index.insertRecord(record) }) if (record && utils.isFunction(record.on)) { @@ -324,7 +309,7 @@ export default Component.extend({ this.emit('add', result) } return this.afterAdd(records, opts, result) || result - }, + } /** * Lifecycle hook called by {@link Collection#add}. If this method returns a @@ -332,11 +317,14 @@ export default Component.extend({ * * @method Collection#method * @since 3.0.0 - * @param {(Object|Object[]|Record|Record[])} result The record or records + * @param {(Object|Object[]|Record|Record[])} record The record or records * that were added to this Collection by {@link Collection#add}. * @param {object} opts The `opts` argument passed to {@link Collection#add}. + * @param result */ - afterAdd () {}, + afterAdd (record, opts, result) { + return null + } /** * Lifecycle hook called by {@link Collection#remove}. If this method returns @@ -348,7 +336,9 @@ export default Component.extend({ * @param {object} opts The `opts` argument passed to {@link Collection#remove}. * @param {object} record The result that will be returned by {@link Collection#remove}. */ - afterRemove () {}, + afterRemove (id, opts, record) { + return null + } /** * Lifecycle hook called by {@link Collection#removeAll}. If this method @@ -361,7 +351,9 @@ export default Component.extend({ * @param {object} opts The `opts` argument passed to {@link Collection#removeAll}. * @param {object} records The result that will be returned by {@link Collection#removeAll}. */ - afterRemoveAll () {}, + afterRemoveAll (query, opts, records) { + return null + } /** * Lifecycle hook called by {@link Collection#add}. If this method returns a @@ -373,7 +365,9 @@ export default Component.extend({ * @param {(Object|Object[]|Record|Record[])} records The `records` argument passed to {@link Collection#add}. * @param {object} opts The `opts` argument passed to {@link Collection#add}. */ - beforeAdd () {}, + beforeAdd (records, opts) { + return null + } /** * Lifecycle hook called by {@link Collection#remove}. @@ -383,7 +377,9 @@ export default Component.extend({ * @param {(string|number)} id The `id` argument passed to {@link Collection#remove}. * @param {object} opts The `opts` argument passed to {@link Collection#remove}. */ - beforeRemove () {}, + beforeRemove (id, opts) { + return null + } /** * Lifecycle hook called by {@link Collection#removeAll}. @@ -393,7 +389,9 @@ export default Component.extend({ * @param {object} query The `query` argument passed to {@link Collection#removeAll}. * @param {object} opts The `opts` argument passed to {@link Collection#removeAll}. */ - beforeRemoveAll () {}, + beforeRemoveAll (query, opts) { + return null + } /** * Find all records between two boundaries. @@ -427,7 +425,7 @@ export default Component.extend({ return this.query() .between(leftKeys, rightKeys, opts) .run() - }, + } /** * Create a new secondary index on the contents of the collection. @@ -446,16 +444,16 @@ export default Component.extend({ * @param {string[]} [fieldList] Array of field names to use as the key or * compound key of the new secondary index. If no fieldList is provided, then * the name will also be the field that is used to index the collection. + * @param opts */ - createIndex (name, fieldList, opts) { + createIndex (name, fieldList?, opts: any = {}) { if (utils.isString(name) && fieldList === undefined) { fieldList = [name] } - opts || (opts = {}) - opts.hashCode || (opts.hashCode = obj => this.recordId(obj)) + opts.hashCode = opts.hashCode || (obj => this.recordId(obj)) const index = (this.indexes[name] = new Index(fieldList, opts)) this.index.visitAll(index.insertRecord, index) - }, + } /** * Find the record or records that match the provided query or pass the @@ -497,11 +495,11 @@ export default Component.extend({ * @see query * @since 3.0.0 */ - filter (query, thisArg) { + filter (queryOrFn, thisArg?) { return this.query() - .filter(query, thisArg) + .filter(queryOrFn, thisArg) .run() - }, + } /** * Iterate over all records. @@ -517,9 +515,9 @@ export default Component.extend({ * @param {*} [thisArg] Context to which to bind `forEachFn`. * @returns {Array} The result. */ - forEach (cb, thisArg) { - this.index.visitAll(cb, thisArg) - }, + forEach (forEachFn, thisArg?) { + this.index.visitAll(forEachFn, thisArg) + } /** * Get the record with the given id. @@ -537,7 +535,7 @@ export default Component.extend({ .get(id) .run() return instances.length ? instances[0] : undefined - }, + } /** * Find the record or records that match the provided keyLists. @@ -562,11 +560,13 @@ export default Component.extend({ * query. If no index is specified, the main index is used. * @returns {Array} The result. */ + getAll(keyList?: Array | string | number, opts?) + getAll(keyList?: Array | string | number, ...args) getAll (...args) { return this.query() .getAll(...args) .run() - }, + } /** * Return the index with the given name. If no name is provided, return the @@ -576,13 +576,13 @@ export default Component.extend({ * @since 3.0.0 * @param {string} [name] The name of the index to retrieve. */ - getIndex (name) { + getIndex (name): Index { const index = name ? this.indexes[name] : this.index if (!index) { throw utils.err(`${DOMAIN}#getIndex`, name)(404, 'index') } return index - }, + } /** * Limit the result. @@ -601,7 +601,7 @@ export default Component.extend({ return this.query() .limit(num) .run() - }, + } /** * Apply a mapping function to all records. @@ -617,11 +617,11 @@ export default Component.extend({ */ map (cb, thisArg) { const data = [] - this.index.visitAll(function (value) { + this.index.visitAll(value => { data.push(cb.call(thisArg, value)) }) return data - }, + } /** * Return the result of calling the specified function on each record in this @@ -630,16 +630,16 @@ export default Component.extend({ * @method Collection#mapCall * @since 3.0.0 * @param {string} funcName Name of function to call - * @parama {...*} [args] Remaining arguments to be passed to the function. + * @param {...*} [args] Remaining arguments to be passed to the function. * @returns {Array} The result. */ mapCall (funcName, ...args) { const data = [] - this.index.visitAll(function (record) { + this.index.visitAll(record => { data.push(record[funcName](...args)) }) return data - }, + } /** * Return all "unsaved" (not uniquely identifiable) records in this colleciton. @@ -651,7 +651,7 @@ export default Component.extend({ */ prune (opts) { return this.removeAll(this.unsaved(), opts) - }, + } /** * Create a new query to be executed against the contents of the collection. @@ -669,10 +669,10 @@ export default Component.extend({ * @since 3.0.0 * @returns {Query} New query object. */ - query () { + query (): Query { const Ctor = this.queryClass return new Ctor(this) - }, + } /** * Return the primary key of the given, or if no record is provided, return the @@ -685,12 +685,12 @@ export default Component.extend({ * @returns {(string|number)} Primary key or name of field that holds primary * key. */ - recordId (record) { + recordId (record?) { if (record) { return utils.get(record, this.recordId()) } return this.mapper ? this.mapper.idAttribute : this.idAttribute - }, + } /** * Reduce the data in the collection to a single value and return the result. @@ -709,7 +709,7 @@ export default Component.extend({ reduce (cb, initialValue) { const data = this.getAll() return data.reduce(cb, initialValue) - }, + } /** * Remove the record with the given id from this Collection. @@ -721,9 +721,7 @@ export default Component.extend({ * @param {object} [opts] Configuration options. * @returns {Object|Record} The removed record, if any. */ - remove (idOrRecord, opts) { - // Default values for arguments - opts || (opts = {}) + remove (idOrRecord, opts: any = {}) { this.beforeRemove(idOrRecord, opts) let record = utils.isSorN(idOrRecord) ? this.get(idOrRecord) : idOrRecord @@ -731,7 +729,7 @@ export default Component.extend({ if (utils.isObject(record)) { record = this.index.removeRecord(record) if (record) { - utils.forOwn(this.indexes, function (index, name) { + utils.forOwn(this.indexes, (index, name) => { index.removeRecord(record) }) if (utils.isFunction(record.off)) { @@ -743,7 +741,7 @@ export default Component.extend({ } } return this.afterRemove(idOrRecord, opts, record) || record - }, + } /** * Remove from this collection the given records or the records selected by @@ -759,9 +757,7 @@ export default Component.extend({ * @param {object} [opts] Configuration options. * @returns {(Object[]|Record[])} The removed records, if any. */ - removeAll (queryOrRecords, opts) { - // Default values for arguments - opts || (opts = {}) + removeAll (queryOrRecords, opts: any = {}) { this.beforeRemoveAll(queryOrRecords, opts) let records = utils.isArray(queryOrRecords) ? queryOrRecords.slice() @@ -777,7 +773,7 @@ export default Component.extend({ this.emit('remove', records) } return this.afterRemoveAll(queryOrRecords, opts, records) || records - }, + } /** * Skip a number of results. @@ -796,7 +792,7 @@ export default Component.extend({ return this.query() .skip(num) .run() - }, + } /** * Return the plain JSON representation of all items in this collection. @@ -809,9 +805,9 @@ export default Component.extend({ * to include in the representation. * @returns {Array} The records. */ - toJSON (opts) { + toJSON (opts?) { return this.mapCall('toJSON', opts) - }, + } /** * Return all "unsaved" (not uniquely identifiable) records in this colleciton. @@ -820,9 +816,9 @@ export default Component.extend({ * @since 3.0.0 * @returns {Array} The unsaved records, if any. */ - unsaved (opts) { + unsaved (opts?) { return this.index.get() - }, + } /** * Update a record's position in a single index of this collection. See @@ -837,10 +833,9 @@ export default Component.extend({ * position. If you don't specify an index then the record will be updated * in the main index. */ - updateIndex (record, opts) { - opts || (opts = {}) + updateIndex (record, opts: { index?: string } = {}) { this.getIndex(opts.index).updateRecord(record) - }, + } /** * Updates all indexes in this collection for the provided record. Has no @@ -852,11 +847,9 @@ export default Component.extend({ */ updateIndexes (record) { this.index.updateRecord(record) - utils.forOwn(this.indexes, function (index, name) { - index.updateRecord(record) - }) + utils.forOwn(this.indexes, index => index.updateRecord(record)) } -}) +} /** * Fired when a record changes. Only works for records that have tracked changes. diff --git a/src/Component.js b/src/Component.js deleted file mode 100644 index f6f86e13..00000000 --- a/src/Component.js +++ /dev/null @@ -1,233 +0,0 @@ -import utils from './utils' -import Settable from './Settable' - -/** - * The base class from which all JSData components inherit some basic - * functionality. - * - * Typically you won't instantiate this class directly, but you may find it - * useful as an abstract class for your own components. - * - * See {@link Component.extend} for an example of using {@link Component} as a - * base class. - * - *```javascript - * import {Component} from 'js-data' - * ``` - * - * @class Component - * @param {object} [opts] Configuration options. - * @param {boolean} [opts.debug=false] See {@link Component#debug}. - * @returns {Component} A new {@link Component} instance. - * @since 3.0.0 - */ -function Component (opts) { - Settable.call(this) - opts || (opts = {}) - - /** - * Whether to enable debug-level logs for this component. Anything that - * extends `Component` inherits this option and the corresponding logging - * functionality. - * - * @example Component#debug - * const JSData = require('js-data'); - * const { Component } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const component = new Component(); - * component.log('debug', 'some message'); // nothing gets logged - * // Display debug logs: - * component.debug = true; - * component.log('debug', 'other message'); // this DOES get logged - * - * @default false - * @name Component#debug - * @since 3.0.0 - * @type {boolean} - */ - this.debug = Object.hasOwnProperty.call(opts, 'debug') ? !!opts.debug : false - - /** - * Event listeners attached to this Component. __Do not modify.__ Use - * {@link Component#on} and {@link Component#off} instead. - * - * @name Component#_listeners - * @private - * @instance - * @since 3.0.0 - * @type {Object} - */ - Object.defineProperty(this, '_listeners', { value: {}, writable: true }) -} - -export default Settable.extend({ - constructor: Component -}) - -/** - * Create a subclass of this Component: - * - * @example Component.extend - * const JSData = require('js-data'); - * const { Component } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * // Extend the class using ES2015 class syntax. - * class CustomComponentClass extends Component { - * foo () { return 'bar'; } - * static beep () { return 'boop'; } - * } - * const customComponent = new CustomComponentClass(); - * console.log(customComponent.foo()); - * console.log(CustomComponentClass.beep()); - * - * // Extend the class using alternate method. - * const OtherComponentClass = Component.extend({ - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }); - * const otherComponent = new OtherComponentClass(); - * console.log(otherComponent.foo()); - * console.log(OtherComponentClass.beep()); - * - * // Extend the class, providing a custom constructor. - * function AnotherComponentClass () { - * Component.call(this); - * this.created_at = new Date().getTime(); - * } - * Component.extend({ - * constructor: AnotherComponentClass, - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }) - * const anotherComponent = new AnotherComponentClass(); - * console.log(anotherComponent.created_at); - * console.log(anotherComponent.foo()); - * console.log(AnotherComponentClass.beep()); - * - * @method Component.extend - * @param {object} [props={}] Properties to add to the prototype of the - * subclass. - * @param {object} [props.constructor] Provide a custom constructor function - * to be used as the subclass itself. - * @param {object} [classProps={}] Static properties to add to the subclass. - * @returns {Constructor} Subclass of this Component class. - * @since 3.0.0 - */ -Component.extend = utils.extend - -/** - * Log the provided values at the "debug" level. Debug-level logs are only - * logged if {@link Component#debug} is `true`. - * - * `.dbg(...)` is shorthand for `.log('debug', ...)`. - * - * @method Component#dbg - * @param {...*} [args] Values to log. - * @since 3.0.0 - */ -/** - * Log the provided values. By default sends values to `console[level]`. - * Debug-level logs are only logged if {@link Component#debug} is `true`. - * - * Will attempt to use appropriate `console` methods if they are available. - * - * @method Component#log - * @param {string} level Log level. - * @param {...*} [args] Values to log. - * @since 3.0.0 - */ -utils.logify(Component.prototype) - -/** - * Register a new event listener on this Component. - * - * @example - * // Listen for all "afterCreate" events in a DataStore - * store.on('afterCreate', (mapperName, props, opts, result) => { - * console.log(mapperName); // "post" - * console.log(props.id); // undefined - * console.log(result.id); // 1234 - * }); - * store.create('post', { title: 'Modeling your data' }).then((post) => { - * console.log(post.id); // 1234 - * }); - * - * @example - * // Listen for the "add" event on a collection - * collection.on('add', (records) => { - * console.log(records); // [...] - * }); - * - * @example - * // Listen for "change" events on a record - * post.on('change', (record, changes) => { - * console.log(changes); // { changed: { title: 'Modeling your data' } } - * }); - * post.title = 'Modeling your data'; - * - * @method Component#on - * @param {string} event Name of event to subsribe to. - * @param {Function} listener Listener function to handle the event. - * @param {*} [ctx] Optional content in which to invoke the listener. - * @since 3.0.0 - */ -/** - * Remove an event listener from this Component. If no listener is provided, - * then all listeners for the specified event will be removed. If no event is - * specified then all listeners for all events will be removed. - * - * @example - * // Remove a particular listener for a particular event - * collection.off('add', handler); - * - * @example - * // Remove all listeners for a particular event - * record.off('change'); - * - * @example - * // Remove all listeners to all events - * store.off(); - * - * @method Component#off - * @param {string} [event] Name of event to unsubsribe to. - * @param {Function} [listener] Listener to remove. - * @since 3.0.0 - */ -/** - * Trigger an event on this Component. - * - * @example Component#emit - * // import { Collection, DataStore } from 'js-data'; - * const JSData = require('js-data'); - * const { Collection, DataStore } = JSData; - * - * const collection = new Collection(); - * collection.on('foo', function (msg) { - * console.log(msg); - * }); - * collection.emit('foo', 'bar'); - * - * const store = new DataStore(); - * store.on('beep', function (msg) { - * console.log(msg); - * }); - * store.emit('beep', 'boop'); - * - * @method Component#emit - * @param {string} event Name of event to emit. - * @param {...*} [args] Arguments to pass to any listeners. - * @since 3.0.0 - */ -utils.eventify( - Component.prototype, - function () { - return this._listeners - }, - function (value) { - this._listeners = value - } -) diff --git a/src/Component.ts b/src/Component.ts new file mode 100644 index 00000000..b9280f24 --- /dev/null +++ b/src/Component.ts @@ -0,0 +1,195 @@ +import utils from './utils' +import Settable from './Settable' + +export interface ComponentOpts { + debug?: boolean +} + +/** + * The base class from which all JSData components inherit some basic + * functionality. + * + * Typically you won't instantiate this class directly, but you may find it + * useful as an abstract class for your own components. + * + * @example + * import {Component} from 'js-data' + * + * class CustomComponentClass extends Component { + * foo () { return 'bar'; } + * static beep () { return 'boop'; } + * } + * const customComponent = new CustomComponentClass(); + * console.log(customComponent.foo()); + * console.log(CustomComponentClass.beep()); + * ``` + * + * @param {object} [opts] Configuration options. + * @param {boolean} [opts.debug=false] See {@link Component#debug}. + * @returns {Component} A new {@link Component} instance. + * @since 3.0.0 + */ +export default class Component extends Settable { + /** + * Whether to enable debug-level logs for this component. Anything that + * extends `Component` inherits this option and the corresponding logging + * functionality. + * + * @example Component#debug + * const JSData = require('js-data'); + * const { Component } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const component = new Component(); + * component.log('debug', 'some message'); // nothing gets logged + * // Display debug logs: + * component.debug = true; + * component.log('debug', 'other message'); // this DOES get logged + * + * @default false + * @name Component#debug + * @since 3.0.0 + * @type {boolean} + */ + protected debug: boolean; + + /** + * Event listeners attached to this Component. __Do not modify.__ Use + * {@link Component#on} and {@link Component#off} instead. + * + * @name Component#_listeners + * @private + * @instance + * @since 3.0.0 + * @type {Object} + */ + _listeners = {}; + + /** + * Log the provided values at the "debug" level. Debug-level logs are only + * logged if {@link Component#debug} is `true`. + * + * `.dbg(...)` is shorthand for `.log('debug', ...)`. + * + * @method Component#dbg + * @param {...*} [args] Values to log. + * @since 3.0.0 + */ + dbg: (...args) => void; + + /** + * Log the provided values. By default sends values to `console[level]`. + * Debug-level logs are only logged if {@link Component#debug} is `true`. + * + * Will attempt to use appropriate `console` methods if they are available. + * + * @method Component#log + * @param {string} level Log level. + * @param {...*} [args] Values to log. + * @since 3.0.0 + */ + log: (...args) => void; + + /** + * Register a new event listener on this Component. + * + * @example + * // Listen for all "afterCreate" events in a DataStore + * store.on('afterCreate', (mapperName, props, opts, result) => { + * console.log(mapperName); // "post" + * console.log(props.id); // undefined + * console.log(result.id); // 1234 + * }); + * store.create('post', { title: 'Modeling your data' }).then((post) => { + * console.log(post.id); // 1234 + * }); + * + * @example + * // Listen for the "add" event on a collection + * collection.on('add', (records) => { + * console.log(records); // [...] + * }); + * + * @example + * // Listen for "change" events on a record + * post.on('change', (record, changes) => { + * console.log(changes); // { changed: { title: 'Modeling your data' } } + * }); + * post.title = 'Modeling your data'; + * + * @method Component#on + * @param {string} event Name of event to subscribe to. + * @param {Function} listener Listener function to handle the event. + * @param {*} [ctx] Optional content in which to invoke the listener. + * @since 3.0.0 + */ + on: (name: string, listener: Function, ctx?) => void; + + /** + * Remove an event listener from this Component. If no listener is provided, + * then all listeners for the specified event will be removed. If no event is + * specified then all listeners for all events will be removed. + * + * @example + * // Remove a particular listener for a particular event + * collection.off('add', handler); + * + * @example + * // Remove all listeners for a particular event + * record.off('change'); + * + * @example + * // Remove all listeners to all events + * store.off(); + * + * @method Component#off + * @param {string} [event] Name of event to unsubscribe to. + * @param {Function} [listener] Listener to remove. + * @since 3.0.0 + */ + off: (event: string, listener?: Function, thisArg?) => void; + + /** + * Trigger an event on this Component. + * + * @example Component#emit + * // import { Collection, DataStore } from 'js-data'; + * const JSData = require('js-data'); + * const { Collection, DataStore } = JSData; + * + * const collection = new Collection(); + * collection.on('foo', function (msg) { + * console.log(msg); + * }); + * collection.emit('foo', 'bar'); + * + * const store = new DataStore(); + * store.on('beep', function (msg) { + * console.log(msg); + * }); + * store.emit('beep', 'boop'); + * + * @method Component#emit + * @param {string} event Name of event to emit. + * @param {...*} [args] Arguments to pass to any listeners. + * @since 3.0.0 + */ + emit: (event: string, ...args) => void; + + constructor (opts: ComponentOpts | any = {}) { + super() + this.debug = opts.debug ?? false + } +} + +utils.logify(Component.prototype) + +utils.eventify( + Component.prototype, + function () { + return this._listeners + }, + function (value) { + this._listeners = value + } +) diff --git a/src/Container.js b/src/Container.ts similarity index 89% rename from src/Container.js rename to src/Container.ts index ee427bfa..2e10c5fb 100644 --- a/src/Container.js +++ b/src/Container.ts @@ -1,10 +1,439 @@ import utils from './utils' import Component from './Component' -import Mapper from './Mapper' +import Mapper, { MapperOpts } from './Mapper' +import Record from './Record' const DOMAIN = 'Container' export const proxiedMapperMethods = [ + 'count', + 'create', + 'createMany', + 'createRecord', + 'destroy', + 'destroyAll', + 'find', + 'findAll', + 'getSchema', + 'is', + 'sum', + 'toJSON', + 'update', + 'updateAll', + 'updateMany', + 'validate' +] + +/** + * The `Container` class is a place to define and store {@link Mapper} instances. + * + * `Container` makes it easy to manage your Mappers. Without a container, you + * need to manage Mappers yourself, including resolving circular dependencies + * among relations. All Mappers in a container share the same adapters, so you + * don't have to register adapters for every single Mapper. + * + * @example Container#constructor + * // import { Container } from 'js-data'; + * const JSData = require('js-data'); + * const {Container} = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new Container(); + * + * @class Container + * @extends Component + * @param {object} [opts] Configuration options. + * @param {boolean} [opts.debug=false] See {@link Component#debug}. + * @param {Constructor} [opts.mapperClass] See {@link Container#mapperClass}. + * @param {object} [opts.mapperDefaults] See {@link Container#mapperDefaults}. + * @since 3.0.0 + */ +export class Container extends Component { + mapperDefaults: any; + mapperClass: typeof Mapper; + _adapters: any; + _mappers: { [name: string]: Mapper }; + + constructor (opts = {}) { + super() + + Object.defineProperties(this, { + /** + * The adapters registered with this Container, which are also shared by all + * Mappers in this Container. + * + * @name Container#_adapters + * @see Container#registerAdapter + * @since 3.0.0 + * @type {Object} + */ + _adapters: { + value: {} + }, + + /** + * The the mappers in this container + * + * @name Container#_mappers + * @see Mapper + * @since 3.0.0 + * @type {Object} + */ + _mappers: { + value: {} + }, + + /** + * Constructor function to use in {@link Container#defineMapper} to create new + * {@link Mapper} instances. {@link Container#mapperClass} should extend + * {@link Mapper}. By default {@link Mapper} is used to instantiate Mappers. + * + * @example Container#mapperClass + * // import { Container, Mapper } from 'js-data'; + * const JSData = require('js-data'); + * const { Container, Mapper } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * class MyMapperClass extends Mapper { + * foo () { return 'bar' } + * } + * const store = new Container({ + * mapperClass: MyMapperClass + * }); + * store.defineMapper('user'); + * console.log(store.getMapper('user').foo()); + * + * @name Container#mapperClass + * @see Mapper + * @since 3.0.0 + * @type {Constructor} + */ + mapperClass: { + value: undefined, + writable: true + } + }) + + // Apply options provided by the user + utils.fillIn(this, opts) + + /** + * Defaults options to pass to {@link Container#mapperClass} when creating a + * new {@link Mapper}. + * + * @example Container#mapperDefaults + * // import { Container } from 'js-data'; + * const JSData = require('js-data'); + * const { Container } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new Container({ + * mapperDefaults: { + * idAttribute: '_id' + * } + * }); + * store.defineMapper('user'); + * console.log(store.getMapper('user').idAttribute); + * + * @default {} + * @name Container#mapperDefaults + * @since 3.0.0 + * @type {Object} + */ + this.mapperDefaults = this.mapperDefaults || {} + + // Use the Mapper class if the user didn't provide a mapperClass + this.mapperClass = this.mapperClass || Mapper + } + + /** + * Register a new event listener on this Container. + * + * Proxy for {@link Component#on}. If an event was emitted by a {@link Mapper} + * in the Container, then the name of the {@link Mapper} will be prepended to + * the arugments passed to the listener. + * + * @example Container#on + * // import { Container } from 'js-data'; + * const JSData = require('js-data'); + * const { Container } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new Container(); + * store.on('foo', function (...args) { console.log(args.join(':')) }); + * store.defineMapper('user'); + * store.emit('foo', 'arg1', 'arg2'); + * store.getMapper('user').emit('foo', 'arg1', 'arg2'); + * + * @method Container#on + * @param {string} event Name of event to subsribe to. + * @param {Function} listener Listener function to handle the event. + * @param {*} [ctx] Optional content in which to invoke the listener. + * @since 3.0.0 + */ + + /** + * Used to bind to events emitted by mappers in this container. + * + * @method Container#_onMapperEvent + * @param {string} name Name of the mapper that emitted the event. + * @param {...*} [args] Args See {@link Mapper#emit}. + * @private + * @since 3.0.0 + */ + _onMapperEvent (name, ...args) { + const type = args.shift() + this.emit(type, name, ...args) + } + + /** + * Return a container scoped to a particular mapper. + * + * @example Container#as + * // import { Container } from 'js-data'; + * const JSData = require('js-data'); + * const { Container } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new Container(); + * const UserMapper = store.defineMapper('user'); + * const UserStore = store.as('user'); + * + * const user1 = store.createRecord('user', { name: 'John' }); + * const user2 = UserStore.createRecord({ name: 'John' }); + * const user3 = UserMapper.createRecord({ name: 'John' }); + * console.log(user1 === user2); + * console.log(user2 === user3); + * console.log(user1 === user3); + * + * @method Container#as + * @param {string} name Name of the {@link Mapper}. + * @returns {Object} A container scoped to a particular mapper. + * @since 3.0.0 + */ + as (name) { + const props: any = {} + const original = this + proxiedMapperMethods.forEach(method => { + props[method] = { + writable: true, + value (...args) { + return original[method](name, ...args) + } + } + }) + props.getMapper = { + writable: true, + value () { + return original.getMapper(name) + } + } + return Object.create(this, props) + } + + /** + * Create a new mapper and register it in this container. + * + * @example Container#defineMapper + * // import { Container } from 'js-data'; + * const JSData = require('js-data'); + * const { Container } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new Container({ + * mapperDefaults: { foo: 'bar' } + * }); + * // Container#defineMapper returns a direct reference to the newly created + * // Mapper. + * const UserMapper = store.defineMapper('user'); + * console.log(UserMapper === store.getMapper('user')); + * console.log(UserMapper === store.as('user').getMapper()); + * console.log(UserMapper.foo); + * + * @method Container#defineMapper + * @param {string} name Name under which to register the new {@link Mapper}. + * {@link Mapper#name} will be set to this value. + * @param {object} [opts] Configuration options. Passed to + * {@link Container#mapperClass} when creating the new {@link Mapper}. + * @returns {Mapper} The newly created instance of {@link Mapper}. + * @see Container#as + * @since 3.0.0 + */ + defineMapper (name?: string | MapperOpts | any, opts?: MapperOpts) { + // For backwards compatibility with defineResource + if (utils.isObject(name)) { + opts = name + name = opts.name + } + if (!utils.isString(name)) { + throw utils.err(`${DOMAIN}#defineMapper`, 'name')(400, 'string', name) + } + + // Default values for arguments + opts = opts || {} + // Set Mapper#name + opts.name = name + opts.relations = opts.relations || {} + + // Check if the user is overriding the datastore's default mapperClass + const mapperClass = opts.mapperClass || this.mapperClass + delete opts.mapperClass + + // Apply the datastore's defaults to the options going into the mapper + utils.fillIn(opts, this.mapperDefaults) + + // Instantiate a mapper + const mapper = (this._mappers[name] = new mapperClass(opts)); // eslint-disable-line + mapper.relations = mapper.relations || {} + // Make sure the mapper's name is set + mapper.name = name + // All mappers in this datastore will share adapters + mapper._adapters = this.getAdapters() + + mapper.datastore = this + + mapper.on('all', (...args) => this._onMapperEvent(name, ...args)) + mapper.defineRelations() + + return mapper + } + + defineResource (name, opts) { + console.warn('DEPRECATED: defineResource is deprecated, use defineMapper instead') + return this.defineMapper(name, opts) + } + + /** + * Return the registered adapter with the given name or the default adapter if + * no name is provided. + * + * @method Container#getAdapter + * @param {string} [name] The name of the adapter to retrieve. + * @returns {Adapter} The adapter. + * @since 3.0.0 + */ + getAdapter (name?) { + const adapter = this.getAdapterName(name) + if (!adapter) { + throw utils.err(`${DOMAIN}#getAdapter`, 'name')(400, 'string', name) + } + return this.getAdapters()[adapter] + } + + /** + * Return the name of a registered adapter based on the given name or options, + * or the name of the default adapter if no name provided. + * + * @method Container#getAdapterName + * @param {(Object|string)} [opts] The name of an adapter or options, if any. + * @returns {string} The name of the adapter. + * @since 3.0.0 + */ + getAdapterName (opts: any = {}) { + if (utils.isString(opts)) { + opts = { adapter: opts } + } + return opts.adapter || this.mapperDefaults.defaultAdapter + } + + /** + * Return the registered adapters of this container. + * + * @method Container#getAdapters + * @returns {Adapter} + * @since 3.0.0 + */ + getAdapters () { + return this._adapters + } + + /** + * Return the mapper registered under the specified name. + * + * @example Container#getMapper + * // import { Container } from 'js-data'; + * const JSData = require('js-data'); + * const { Container } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new Container(); + * // Container#defineMapper returns a direct reference to the newly created + * // Mapper. + * const UserMapper = store.defineMapper('user'); + * console.log(UserMapper === store.getMapper('user')); + * console.log(UserMapper === store.as('user').getMapper()); + * store.getMapper('profile'); // throws Error, there is no mapper with name "profile" + * + * @method Container#getMapper + * @param {string} name {@link Mapper#name}. + * @returns {Mapper} + * @since 3.0.0 + */ + getMapper (name: string): Mapper { + const mapper = this.getMapperByName(name) + if (!mapper) { + throw utils.err(`${DOMAIN}#getMapper`, name)(404, 'mapper') + } + return mapper + } + + /** + * Return the mapper registered under the specified name. + * Doesn't throw error if mapper doesn't exist. + * + * @example Container#getMapperByName + * // import { Container } from 'js-data'; + * const JSData = require('js-data'); + * const { Container } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new Container(); + * // Container#defineMapper returns a direct reference to the newly created + * // Mapper. + * const UserMapper = store.defineMapper('user'); + * console.log(UserMapper === store.getMapper('user')); + * console.log(UserMapper === store.as('user').getMapper()); + * console.log(store.getMapper('profile')); // Does NOT throw an error + * + * @method Container#getMapperByName + * @param {string} name {@link Mapper#name}. + * @returns {Mapper} + * @since 3.0.0 + */ + getMapperByName (name) { + return this._mappers[name] + } + + /** + * Register an adapter on this container under the given name. Adapters + * registered on a container are shared by all mappers in the container. + * + * @example + * import { Container } from 'js-data'; + * import { RethinkDBAdapter } from 'js-data-rethinkdb'; + * const store = new Container(); + * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); + * + * @method Container#registerAdapter + * @param {string} name The name of the adapter to register. + * @param {Adapter} adapter The adapter to register. + * @param {object} [opts] Configuration options. + * @param {boolean} [opts.default=false] Whether to make the adapter the + * default adapter for all Mappers in this container. + * @since 3.0.0 + * @tutorial ["http://www.js-data.io/v3.0/docs/connecting-to-a-data-source","Connecting to a data source"] + */ + registerAdapter (name, adapter, opts: any = {}) { + this.getAdapters()[name] = adapter + // Optionally make it the default adapter for the target. + if (opts === true || opts.default) { + this.mapperDefaults.defaultAdapter = name + utils.forOwn(this._mappers, mapper => { + mapper.defaultAdapter = name + }) + } + } + /** * Wrapper for {@link Mapper#count}. * @@ -28,7 +457,9 @@ export const proxiedMapperMethods = [ * @see Mapper#count * @since 3.0.0 */ - 'count', + count (name, query, opts?) { + return this.getMapper(name).count(query, opts) + } /** * Fired during {@link Container#create}. See @@ -63,6 +494,7 @@ export const proxiedMapperMethods = [ * @see Container~afterCreateListener * @see Container#create */ + /** * Callback signature for the {@link Container#event:afterCreate} event. * @@ -109,7 +541,9 @@ export const proxiedMapperMethods = [ * @see Mapper#create * @since 3.0.0 */ - 'create', + create (name, props, opts) { + return this.getMapper(name).create(props, opts) + } /** * Fired during {@link Container#createMany}. See @@ -144,6 +578,7 @@ export const proxiedMapperMethods = [ * @see Container~afterCreateManyListener * @see Container#createMany */ + /** * Callback signature for the {@link Container#event:afterCreateMany} event. * @@ -194,7 +629,9 @@ export const proxiedMapperMethods = [ * @see Mapper#createMany * @since 3.0.0 */ - 'createMany', + createMany (name, records, opts) { + return this.getMapper(name).createMany(records, opts) + } /** * Wrapper for {@link Mapper#createRecord}. @@ -217,7 +654,9 @@ export const proxiedMapperMethods = [ * @see Mapper#createRecord * @since 3.0.0 */ - 'createRecord', + createRecord (name, props?, opts?) { + return this.getMapper(name).createRecord(props, opts) + } /** * Fired during {@link Container#destroy}. See @@ -252,6 +691,7 @@ export const proxiedMapperMethods = [ * @see Container~afterDestroyListener * @see Container#destroy */ + /** * Callback signature for the {@link Container#event:afterDestroy} event. * @@ -295,7 +735,9 @@ export const proxiedMapperMethods = [ * @see Mapper#destroy * @since 3.0.0 */ - 'destroy', + destroy (name, id, opts) { + return this.getMapper(name).destroy(id, opts) + } /** * Fired during {@link Container#destroyAll}. See @@ -330,6 +772,7 @@ export const proxiedMapperMethods = [ * @see Container~afterDestroyAllListener * @see Container#destroyAll */ + /** * Callback signature for the {@link Container#event:afterDestroyAll} event. * @@ -373,7 +816,9 @@ export const proxiedMapperMethods = [ * @see Mapper#destroyAll * @since 3.0.0 */ - 'destroyAll', + destroyAll (name, query, opts) { + return this.getMapper(name).destroyAll(query, opts) + } /** * Fired during {@link Container#find}. See @@ -408,6 +853,7 @@ export const proxiedMapperMethods = [ * @see Container~afterFindListener * @see Container#find */ + /** * Callback signature for the {@link Container#event:afterFind} event. * @@ -450,7 +896,9 @@ export const proxiedMapperMethods = [ * @see Mapper#find * @since 3.0.0 */ - 'find', + find (name, id, opts) { + return this.getMapper(name).find(id, opts) + } /** * Fired during {@link Container#findAll}. See @@ -485,6 +933,7 @@ export const proxiedMapperMethods = [ * @see Container~afterFindAllListener * @see Container#findAll */ + /** * Callback signature for the {@link Container#event:afterFindAll} event. * @@ -528,7 +977,9 @@ export const proxiedMapperMethods = [ * @see Mapper#findAll * @since 3.0.0 */ - 'findAll', + findAll (name, query, opts) { + return this.getMapper(name).findAll(query, opts) + } /** * Wrapper for {@link Mapper#getSchema}. @@ -539,7 +990,9 @@ export const proxiedMapperMethods = [ * @see Mapper#getSchema * @since 3.0.0 */ - 'getSchema', + getSchema (name) { + return this.getMapper(name).getSchema() + } /** * Wrapper for {@link Mapper#is}. @@ -561,7 +1014,9 @@ export const proxiedMapperMethods = [ * @see Mapper#is * @since 3.0.0 */ - 'is', + is (name, record) { + return this.getMapper(name).is(record) + } /** * Wrapper for {@link Mapper#sum}. @@ -586,7 +1041,9 @@ export const proxiedMapperMethods = [ * @see Mapper#sum * @since 3.0.0 */ - 'sum', + sum (name, field, query, opts) { + return this.getMapper(name).sum(field, query, opts) + } /** * Wrapper for {@link Mapper#toJSON}. @@ -629,7 +1086,9 @@ export const proxiedMapperMethods = [ * @see Mapper#toJSON * @since 3.0.0 */ - 'toJSON', + toJSON (name, records, opts?) { + return this.getMapper(name).toJSON(records, opts) + } /** * Fired during {@link Container#update}. See @@ -659,198 +1118,34 @@ export const proxiedMapperMethods = [ */ /** * Fired during {@link Container#update}. See - * {@link Container~afterUpdateListener} for how to listen for this event. - * - * @event Container#afterUpdate - * @see Container~afterUpdateListener - * @see Container#update - */ - /** - * Callback signature for the {@link Container#event:afterUpdate} event. - * - * @example - * function onAfterUpdate (mapperName, id, props, opts, result) { - * // do something - * } - * store.on('afterUpdate', onAfterUpdate); - * - * @callback Container~afterUpdateListener - * @param {string} name The `name` argument received by {@link Mapper#afterUpdate}. - * @param {string|number} id The `id` argument received by {@link Mapper#afterUpdate}. - * @param {object} props The `props` argument received by {@link Mapper#afterUpdate}. - * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdate}. - * @param {object} result The `result` argument received by {@link Mapper#afterUpdate}. - * @see Container#event:afterUpdate - * @see Container#update - * @since 3.0.0 - */ - /** - * Wrapper for {@link Mapper#update}. - * - * @example - * import { Container } from 'js-data'; - * import RethinkDBAdapter from 'js-data-rethinkdb'; - * const store = new Container(); - * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); - * store.defineMapper('post'); - * - * store.update('post', 1234, { - * status: 'published', - * published_at: new Date() - * }).then((post) => { - * console.log(post); // { id: 1234, status: 'published', ... } - * }); - * - * @fires Container#beforeUpdate - * @fires Container#afterUpdate - * @method Container#update - * @param {string} name Name of the {@link Mapper} to target. - * @param {(string|number)} id See {@link Mapper#update}. - * @param {object} record See {@link Mapper#update}. - * @param {object} [opts] See {@link Mapper#update}. - * @returns {Promise} See {@link Mapper#update}. - * @see Mapper#update - * @since 3.0.0 - * @tutorial ["http://www.js-data.io/v3.0/docs/saving-data","Saving data"] - */ - 'update', - - /** - * Fired during {@link Container#updateAll}. See - * {@link Container~beforeUpdateAllListener} for how to listen for this event. - * - * @event Container#beforeUpdateAll - * @see Container~beforeUpdateAllListener - * @see Container#updateAll - */ - /** - * Callback signature for the {@link Container#event:beforeUpdateAll} event. - * - * @example - * function onBeforeUpdateAll (mapperName, props, query, opts) { - * // do something - * } - * store.on('beforeUpdateAll', onBeforeUpdateAll); - * - * @callback Container~beforeUpdateAllListener - * @param {string} name The `name` argument received by {@link Mapper#beforeUpdateAll}. - * @param {object} props The `props` argument received by {@link Mapper#beforeUpdateAll}. - * @param {object} query The `query` argument received by {@link Mapper#beforeUpdateAll}. - * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdateAll}. - * @see Container#event:beforeUpdateAll - * @see Container#updateAll - * @since 3.0.0 - */ - /** - * Fired during {@link Container#updateAll}. See - * {@link Container~afterUpdateAllListener} for how to listen for this event. - * - * @event Container#afterUpdateAll - * @see Container~afterUpdateAllListener - * @see Container#updateAll - */ - /** - * Callback signature for the {@link Container#event:afterUpdateAll} event. - * - * @example - * function onAfterUpdateAll (mapperName, props, query, opts, result) { - * // do something - * } - * store.on('afterUpdateAll', onAfterUpdateAll); - * - * @callback Container~afterUpdateAllListener - * @param {string} name The `name` argument received by {@link Mapper#afterUpdateAll}. - * @param {object} props The `props` argument received by {@link Mapper#afterUpdateAll}. - * @param {object} query The `query` argument received by {@link Mapper#afterUpdateAll}. - * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdateAll}. - * @param {object} result The `result` argument received by {@link Mapper#afterUpdateAll}. - * @see Container#event:afterUpdateAll - * @see Container#updateAll - * @since 3.0.0 - */ - /** - * Wrapper for {@link Mapper#updateAll}. - * - * @example - * // Turn all of John's blog posts into drafts. - * import { Container } from 'js-data'; - * import RethinkDBAdapter from 'js-data-rethinkdb'; - * const store = new Container(); - * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); - * store.defineMapper('post'); - * - * const update = { status: draft: published_at: null }; - * const query = { userId: 1234 }; - * store.updateAll('post', update, query).then((posts) => { - * console.log(posts); // [...] - * }); - * - * @fires Container#beforeUpdateAll - * @fires Container#afterUpdateAll - * @method Container#updateAll - * @param {string} name Name of the {@link Mapper} to target. - * @param {object} update See {@link Mapper#updateAll}. - * @param {object} [query] See {@link Mapper#updateAll}. - * @param {object} [opts] See {@link Mapper#updateAll}. - * @returns {Promise} See {@link Mapper#updateAll}. - * @see Mapper#updateAll - * @since 3.0.0 - */ - 'updateAll', - - /** - * Fired during {@link Container#updateMany}. See - * {@link Container~beforeUpdateManyListener} for how to listen for this event. - * - * @event Container#beforeUpdateMany - * @see Container~beforeUpdateManyListener - * @see Container#updateMany - */ - /** - * Callback signature for the {@link Container#event:beforeUpdateMany} event. - * - * @example - * function onBeforeUpdateMany (mapperName, records, opts) { - * // do something - * } - * store.on('beforeUpdateMany', onBeforeUpdateMany); - * - * @callback Container~beforeUpdateManyListener - * @param {string} name The `name` argument received by {@link Mapper#beforeUpdateMany}. - * @param {object} records The `records` argument received by {@link Mapper#beforeUpdateMany}. - * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdateMany}. - * @see Container#event:beforeUpdateMany - * @see Container#updateMany - * @since 3.0.0 - */ - /** - * Fired during {@link Container#updateMany}. See - * {@link Container~afterUpdateManyListener} for how to listen for this event. - * - * @event Container#afterUpdateMany - * @see Container~afterUpdateManyListener - * @see Container#updateMany + * {@link Container~afterUpdateListener} for how to listen for this event. + * + * @event Container#afterUpdate + * @see Container~afterUpdateListener + * @see Container#update */ + /** - * Callback signature for the {@link Container#event:afterUpdateMany} event. + * Callback signature for the {@link Container#event:afterUpdate} event. * * @example - * function onAfterUpdateMany (mapperName, records, opts, result) { + * function onAfterUpdate (mapperName, id, props, opts, result) { * // do something * } - * store.on('afterUpdateMany', onAfterUpdateMany); + * store.on('afterUpdate', onAfterUpdate); * - * @callback Container~afterUpdateManyListener - * @param {string} name The `name` argument received by {@link Mapper#afterUpdateMany}. - * @param {object} records The `records` argument received by {@link Mapper#afterUpdateMany}. - * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdateMany}. - * @param {object} result The `result` argument received by {@link Mapper#afterUpdateMany}. - * @see Container#event:afterUpdateMany - * @see Container#updateMany + * @callback Container~afterUpdateListener + * @param {string} name The `name` argument received by {@link Mapper#afterUpdate}. + * @param {string|number} id The `id` argument received by {@link Mapper#afterUpdate}. + * @param {object} props The `props` argument received by {@link Mapper#afterUpdate}. + * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdate}. + * @param {object} result The `result` argument received by {@link Mapper#afterUpdate}. + * @see Container#event:afterUpdate + * @see Container#update * @since 3.0.0 */ /** - * Wrapper for {@link Mapper#updateMany}. + * Wrapper for {@link Mapper#update}. * * @example * import { Container } from 'js-data'; @@ -859,523 +1154,226 @@ export const proxiedMapperMethods = [ * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); * store.defineMapper('post'); * - * store.updateMany('post', [ - * { id: 1234, status: 'draft' }, - * { id: 2468, status: 'published', published_at: new Date() } - * ]).then((posts) => { - * console.log(posts); // [...] - * }); - * - * @fires Container#beforeUpdateMany - * @fires Container#afterUpdateMany - * @method Container#updateMany - * @param {string} name Name of the {@link Mapper} to target. - * @param {(Object[]|Record[])} records See {@link Mapper#updateMany}. - * @param {object} [opts] See {@link Mapper#updateMany}. - * @returns {Promise} See {@link Mapper#updateMany}. - * @see Mapper#updateMany - * @since 3.0.0 - */ - 'updateMany', - - /** - * Wrapper for {@link Mapper#validate}. - * - * @example - * import { Container } from 'js-data'; - * const store = new Container(); - * store.defineMapper('post', { - * schema: { - * properties: { - * name: { type: 'string' }, - * id: { type: 'string' } - * } - * } + * store.update('post', 1234, { + * status: 'published', + * published_at: new Date() + * }).then((post) => { + * console.log(post); // { id: 1234, status: 'published', ... } * }); - * let errors = store.validate('post', { name: 'John' }); - * console.log(errors); // undefined - * errors = store.validate('post', { name: 123 }); - * console.log(errors); // [{ expected: 'one of (string)', actual: 'number', path: 'name' }] * - * @method Container#validate + * @fires Container#beforeUpdate + * @fires Container#afterUpdate + * @method Container#update * @param {string} name Name of the {@link Mapper} to target. - * @param {(Object[]|Record[])} records See {@link Mapper#validate}. - * @param {object} [opts] See {@link Mapper#validate}. - * @returns {Promise} See {@link Mapper#validate}. - * @see Mapper#validate + * @param {(string|number)} id See {@link Mapper#update}. + * @param {object} props See {@link Mapper#update}. + * @param {object} [opts] See {@link Mapper#update}. + * @returns {Promise} See {@link Mapper#update}. + * @see Mapper#update * @since 3.0.0 + * @tutorial ["http://www.js-data.io/v3.0/docs/saving-data","Saving data"] */ - 'validate' -] - -/** - * The `Container` class is a place to define and store {@link Mapper} instances. - * - * `Container` makes it easy to manage your Mappers. Without a container, you - * need to manage Mappers yourself, including resolving circular dependencies - * among relations. All Mappers in a container share the same adapters, so you - * don't have to register adapters for every single Mapper. - * - * @example Container#constructor - * // import { Container } from 'js-data'; - * const JSData = require('js-data'); - * const {Container} = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new Container(); - * - * @class Container - * @extends Component - * @param {object} [opts] Configuration options. - * @param {boolean} [opts.debug=false] See {@link Component#debug}. - * @param {Constructor} [opts.mapperClass] See {@link Container#mapperClass}. - * @param {object} [opts.mapperDefaults] See {@link Container#mapperDefaults}. - * @since 3.0.0 - */ -export function Container (opts) { - utils.classCallCheck(this, Container) - Component.call(this) - opts || (opts = {}) - - Object.defineProperties(this, { - /** - * The adapters registered with this Container, which are also shared by all - * Mappers in this Container. - * - * @name Container#_adapters - * @see Container#registerAdapter - * @since 3.0.0 - * @type {Object} - */ - _adapters: { - value: {} - }, - - /** - * The the mappers in this container - * - * @name Container#_mappers - * @see Mapper - * @since 3.0.0 - * @type {Object} - */ - _mappers: { - value: {} - }, - - /** - * Constructor function to use in {@link Container#defineMapper} to create new - * {@link Mapper} instances. {@link Container#mapperClass} should extend - * {@link Mapper}. By default {@link Mapper} is used to instantiate Mappers. - * - * @example Container#mapperClass - * // import { Container, Mapper } from 'js-data'; - * const JSData = require('js-data'); - * const { Container, Mapper } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * class MyMapperClass extends Mapper { - * foo () { return 'bar' } - * } - * const store = new Container({ - * mapperClass: MyMapperClass - * }); - * store.defineMapper('user'); - * console.log(store.getMapper('user').foo()); - * - * @name Container#mapperClass - * @see Mapper - * @since 3.0.0 - * @type {Constructor} - */ - mapperClass: { - value: undefined, - writable: true - } - }) - - // Apply options provided by the user - utils.fillIn(this, opts) + update (name, id, props, opts) { + return this.getMapper(name).update(id, props, opts) + } /** - * Defaults options to pass to {@link Container#mapperClass} when creating a - * new {@link Mapper}. - * - * @example Container#mapperDefaults - * // import { Container } from 'js-data'; - * const JSData = require('js-data'); - * const { Container } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new Container({ - * mapperDefaults: { - * idAttribute: '_id' - * } - * }); - * store.defineMapper('user'); - * console.log(store.getMapper('user').idAttribute); + * Fired during {@link Container#updateAll}. See + * {@link Container~beforeUpdateAllListener} for how to listen for this event. * - * @default {} - * @name Container#mapperDefaults - * @since 3.0.0 - * @type {Object} + * @event Container#beforeUpdateAll + * @see Container~beforeUpdateAllListener + * @see Container#updateAll */ - this.mapperDefaults = this.mapperDefaults || {} - - // Use the Mapper class if the user didn't provide a mapperClass - this.mapperClass || (this.mapperClass = Mapper) -} - -const props = { - constructor: Container, - /** - * Register a new event listener on this Container. - * - * Proxy for {@link Component#on}. If an event was emitted by a {@link Mapper} - * in the Container, then the name of the {@link Mapper} will be prepended to - * the arugments passed to the listener. - * - * @example Container#on - * // import { Container } from 'js-data'; - * const JSData = require('js-data'); - * const { Container } = JSData; - * console.log('Using JSData v' + JSData.version.full); + * Callback signature for the {@link Container#event:beforeUpdateAll} event. * - * const store = new Container(); - * store.on('foo', function (...args) { console.log(args.join(':')) }); - * store.defineMapper('user'); - * store.emit('foo', 'arg1', 'arg2'); - * store.getMapper('user').emit('foo', 'arg1', 'arg2'); + * @example + * function onBeforeUpdateAll (mapperName, props, query, opts) { + * // do something + * } + * store.on('beforeUpdateAll', onBeforeUpdateAll); * - * @method Container#on - * @param {string} event Name of event to subsribe to. - * @param {Function} listener Listener function to handle the event. - * @param {*} [ctx] Optional content in which to invoke the listener. + * @callback Container~beforeUpdateAllListener + * @param {string} name The `name` argument received by {@link Mapper#beforeUpdateAll}. + * @param {object} props The `props` argument received by {@link Mapper#beforeUpdateAll}. + * @param {object} query The `query` argument received by {@link Mapper#beforeUpdateAll}. + * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdateAll}. + * @see Container#event:beforeUpdateAll + * @see Container#updateAll * @since 3.0.0 */ - /** - * Used to bind to events emitted by mappers in this container. + * Fired during {@link Container#updateAll}. See + * {@link Container~afterUpdateAllListener} for how to listen for this event. * - * @method Container#_onMapperEvent - * @param {string} name Name of the mapper that emitted the event. - * @param {...*} [args] Args See {@link Mapper#emit}. - * @private - * @since 3.0.0 + * @event Container#afterUpdateAll + * @see Container~afterUpdateAllListener + * @see Container#updateAll */ - _onMapperEvent (name, ...args) { - const type = args.shift() - this.emit(type, name, ...args) - }, /** - * Return a container scoped to a particular mapper. - * - * @example Container#as - * // import { Container } from 'js-data'; - * const JSData = require('js-data'); - * const { Container } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new Container(); - * const UserMapper = store.defineMapper('user'); - * const UserStore = store.as('user'); + * Callback signature for the {@link Container#event:afterUpdateAll} event. * - * const user1 = store.createRecord('user', { name: 'John' }); - * const user2 = UserStore.createRecord({ name: 'John' }); - * const user3 = UserMapper.createRecord({ name: 'John' }); - * console.log(user1 === user2); - * console.log(user2 === user3); - * console.log(user1 === user3); + * @example + * function onAfterUpdateAll (mapperName, props, query, opts, result) { + * // do something + * } + * store.on('afterUpdateAll', onAfterUpdateAll); * - * @method Container#as - * @param {string} name Name of the {@link Mapper}. - * @returns {Object} A container scoped to a particular mapper. + * @callback Container~afterUpdateAllListener + * @param {string} name The `name` argument received by {@link Mapper#afterUpdateAll}. + * @param {object} props The `props` argument received by {@link Mapper#afterUpdateAll}. + * @param {object} query The `query` argument received by {@link Mapper#afterUpdateAll}. + * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdateAll}. + * @param {object} result The `result` argument received by {@link Mapper#afterUpdateAll}. + * @see Container#event:afterUpdateAll + * @see Container#updateAll * @since 3.0.0 */ - as (name) { - const props = {} - const original = this - proxiedMapperMethods.forEach(function (method) { - props[method] = { - writable: true, - value (...args) { - return original[method](name, ...args) - } - } - }) - props.getMapper = { - writable: true, - value () { - return original.getMapper(name) - } - } - return Object.create(this, props) - }, - /** - * Create a new mapper and register it in this container. + * Wrapper for {@link Mapper#updateAll}. * - * @example Container#defineMapper - * // import { Container } from 'js-data'; - * const JSData = require('js-data'); - * const { Container } = JSData; - * console.log('Using JSData v' + JSData.version.full); + * @example + * // Turn all of John's blog posts into drafts. + * import { Container } from 'js-data'; + * import RethinkDBAdapter from 'js-data-rethinkdb'; + * const store = new Container(); + * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); + * store.defineMapper('post'); * - * const store = new Container({ - * mapperDefaults: { foo: 'bar' } + * const update = { status: draft: published_at: null }; + * const query = { userId: 1234 }; + * store.updateAll('post', update, query).then((posts) => { + * console.log(posts); // [...] * }); - * // Container#defineMapper returns a direct reference to the newly created - * // Mapper. - * const UserMapper = store.defineMapper('user'); - * console.log(UserMapper === store.getMapper('user')); - * console.log(UserMapper === store.as('user').getMapper()); - * console.log(UserMapper.foo); * - * @method Container#defineMapper - * @param {string} name Name under which to register the new {@link Mapper}. - * {@link Mapper#name} will be set to this value. - * @param {object} [opts] Configuration options. Passed to - * {@link Container#mapperClass} when creating the new {@link Mapper}. - * @returns {Mapper} The newly created instance of {@link Mapper}. - * @see Container#as + * @fires Container#beforeUpdateAll + * @fires Container#afterUpdateAll + * @method Container#updateAll + * @param {string} name Name of the {@link Mapper} to target. + * @param {object} props See {@link Mapper#updateAll}. + * @param {object} [query] See {@link Mapper#updateAll}. + * @param {object} [opts] See {@link Mapper#updateAll}. + * @returns {Promise} See {@link Mapper#updateAll}. + * @see Mapper#updateAll * @since 3.0.0 */ - defineMapper (name, opts) { - // For backwards compatibility with defineResource - if (utils.isObject(name)) { - opts = name - name = opts.name - } - if (!utils.isString(name)) { - throw utils.err(`${DOMAIN}#defineMapper`, 'name')(400, 'string', name) - } - - // Default values for arguments - opts || (opts = {}) - // Set Mapper#name - opts.name = name - opts.relations || (opts.relations = {}) - - // Check if the user is overriding the datastore's default mapperClass - const mapperClass = opts.mapperClass || this.mapperClass - delete opts.mapperClass - - // Apply the datastore's defaults to the options going into the mapper - utils.fillIn(opts, this.mapperDefaults) - - // Instantiate a mapper - const mapper = this._mappers[name] = new mapperClass(opts) // eslint-disable-line - mapper.relations || (mapper.relations = {}) - // Make sure the mapper's name is set - mapper.name = name - // All mappers in this datastore will share adapters - mapper._adapters = this.getAdapters() - - mapper.datastore = this - - mapper.on('all', (...args) => this._onMapperEvent(name, ...args)) - mapper.defineRelations() - - return mapper - }, - - defineResource (name, opts) { - console.warn('DEPRECATED: defineResource is deprecated, use defineMapper instead') - return this.defineMapper(name, opts) - }, + updateAll (name, props, query, opts) { + return this.getMapper(name).updateAll(props, query, opts) + } /** - * Return the registered adapter with the given name or the default adapter if - * no name is provided. + * Fired during {@link Container#updateMany}. See + * {@link Container~beforeUpdateManyListener} for how to listen for this event. * - * @method Container#getAdapter - * @param {string} [name] The name of the adapter to retrieve. - * @returns {Adapter} The adapter. - * @since 3.0.0 + * @event Container#beforeUpdateMany + * @see Container~beforeUpdateManyListener + * @see Container#updateMany */ - getAdapter (name) { - const adapter = this.getAdapterName(name) - if (!adapter) { - throw utils.err(`${DOMAIN}#getAdapter`, 'name')(400, 'string', name) - } - return this.getAdapters()[adapter] - }, - /** - * Return the name of a registered adapter based on the given name or options, - * or the name of the default adapter if no name provided. + * Callback signature for the {@link Container#event:beforeUpdateMany} event. * - * @method Container#getAdapterName - * @param {(Object|string)} [opts] The name of an adapter or options, if any. - * @returns {string} The name of the adapter. + * @example + * function onBeforeUpdateMany (mapperName, records, opts) { + * // do something + * } + * store.on('beforeUpdateMany', onBeforeUpdateMany); + * + * @callback Container~beforeUpdateManyListener + * @param {string} name The `name` argument received by {@link Mapper#beforeUpdateMany}. + * @param {object} records The `records` argument received by {@link Mapper#beforeUpdateMany}. + * @param {object} opts The `opts` argument received by {@link Mapper#beforeUpdateMany}. + * @see Container#event:beforeUpdateMany + * @see Container#updateMany * @since 3.0.0 */ - getAdapterName (opts) { - opts || (opts = {}) - if (utils.isString(opts)) { - opts = { adapter: opts } - } - return opts.adapter || this.mapperDefaults.defaultAdapter - }, - /** - * Return the registered adapters of this container. + * Fired during {@link Container#updateMany}. See + * {@link Container~afterUpdateManyListener} for how to listen for this event. * - * @method Container#getAdapters - * @returns {Adapter} - * @since 3.0.0 + * @event Container#afterUpdateMany + * @see Container~afterUpdateManyListener + * @see Container#updateMany */ - getAdapters () { - return this._adapters - }, /** - * Return the mapper registered under the specified name. - * - * @example Container#getMapper - * // import { Container } from 'js-data'; - * const JSData = require('js-data'); - * const { Container } = JSData; - * console.log('Using JSData v' + JSData.version.full); + * Callback signature for the {@link Container#event:afterUpdateMany} event. * - * const store = new Container(); - * // Container#defineMapper returns a direct reference to the newly created - * // Mapper. - * const UserMapper = store.defineMapper('user'); - * console.log(UserMapper === store.getMapper('user')); - * console.log(UserMapper === store.as('user').getMapper()); - * store.getMapper('profile'); // throws Error, there is no mapper with name "profile" + * @example + * function onAfterUpdateMany (mapperName, records, opts, result) { + * // do something + * } + * store.on('afterUpdateMany', onAfterUpdateMany); * - * @method Container#getMapper - * @param {string} name {@link Mapper#name}. - * @returns {Mapper} + * @callback Container~afterUpdateManyListener + * @param {string} name The `name` argument received by {@link Mapper#afterUpdateMany}. + * @param {object} records The `records` argument received by {@link Mapper#afterUpdateMany}. + * @param {object} opts The `opts` argument received by {@link Mapper#afterUpdateMany}. + * @param {object} result The `result` argument received by {@link Mapper#afterUpdateMany}. + * @see Container#event:afterUpdateMany + * @see Container#updateMany * @since 3.0.0 */ - getMapper (name) { - const mapper = this.getMapperByName(name) - if (!mapper) { - throw utils.err(`${DOMAIN}#getMapper`, name)(404, 'mapper') - } - return mapper - }, - /** - * Return the mapper registered under the specified name. - * Doesn't throw error if mapper doesn't exist. - * - * @example Container#getMapperByName - * // import { Container } from 'js-data'; - * const JSData = require('js-data'); - * const { Container } = JSData; - * console.log('Using JSData v' + JSData.version.full); + * Wrapper for {@link Mapper#updateMany}. * + * @example + * import { Container } from 'js-data'; + * import RethinkDBAdapter from 'js-data-rethinkdb'; * const store = new Container(); - * // Container#defineMapper returns a direct reference to the newly created - * // Mapper. - * const UserMapper = store.defineMapper('user'); - * console.log(UserMapper === store.getMapper('user')); - * console.log(UserMapper === store.as('user').getMapper()); - * console.log(store.getMapper('profile')); // Does NOT throw an error + * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); + * store.defineMapper('post'); * - * @method Container#getMapperByName - * @param {string} name {@link Mapper#name}. - * @returns {Mapper} + * store.updateMany('post', [ + * { id: 1234, status: 'draft' }, + * { id: 2468, status: 'published', published_at: new Date() } + * ]).then((posts) => { + * console.log(posts); // [...] + * }); + * + * @fires Container#beforeUpdateMany + * @fires Container#afterUpdateMany + * @method Container#updateMany + * @param {string} name Name of the {@link Mapper} to target. + * @param {(Object[]|Record[])} records See {@link Mapper#updateMany}. + * @param {object} [opts] See {@link Mapper#updateMany}. + * @returns {Promise} See {@link Mapper#updateMany}. + * @see Mapper#updateMany * @since 3.0.0 */ - getMapperByName (name) { - return this._mappers[name] - }, + updateMany (name, record, opts) { + return this.getMapper(name).updateMany(record, opts) + } /** - * Register an adapter on this container under the given name. Adapters - * registered on a container are shared by all mappers in the container. + * Wrapper for {@link Mapper#validate}. * * @example * import { Container } from 'js-data'; - * import { RethinkDBAdapter } from 'js-data-rethinkdb'; * const store = new Container(); - * store.registerAdapter('rethinkdb', new RethinkDBAdapter(), { default: true }); + * store.defineMapper('post', { + * schema: { + * properties: { + * name: { type: 'string' }, + * id: { type: 'string' } + * } + * } + * }); + * let errors = store.validate('post', { name: 'John' }); + * console.log(errors); // undefined + * errors = store.validate('post', { name: 123 }); + * console.log(errors); // [{ expected: 'one of (string)', actual: 'number', path: 'name' }] * - * @method Container#registerAdapter - * @param {string} name The name of the adapter to register. - * @param {Adapter} adapter The adapter to register. - * @param {object} [opts] Configuration options. - * @param {boolean} [opts.default=false] Whether to make the adapter the - * default adapter for all Mappers in this container. + * @method Container#validate + * @param {string} name Name of the {@link Mapper} to target. + * @param {(Object[]|Record[])} records See {@link Mapper#validate}. + * @param {object} [opts] See {@link Mapper#validate}. + * @returns {Promise} See {@link Mapper#validate}. + * @see Mapper#validate * @since 3.0.0 - * @tutorial ["http://www.js-data.io/v3.0/docs/connecting-to-a-data-source","Connecting to a data source"] */ - registerAdapter (name, adapter, opts) { - opts || (opts = {}) - this.getAdapters()[name] = adapter - // Optionally make it the default adapter for the target. - if (opts === true || opts.default) { - this.mapperDefaults.defaultAdapter = name - utils.forOwn(this._mappers, function (mapper) { - mapper.defaultAdapter = name - }) - } + validate (name, record, opts) { + return this.getMapper(name).validate(record, opts) } } - -proxiedMapperMethods.forEach(function (method) { - props[method] = function (name, ...args) { - return this.getMapper(name)[method](...args) - } -}) - -Component.extend(props) - -/** - * Create a subclass of this Container: - * @example Container.extend - * const JSData = require('js-data'); - * const { Container } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * // Extend the class using ES2015 class syntax. - * class CustomContainerClass extends Container { - * foo () { return 'bar' } - * static beep () { return 'boop' } - * } - * const customContainer = new CustomContainerClass(); - * console.log(customContainer.foo()); - * console.log(CustomContainerClass.beep()); - * - * // Extend the class using alternate method. - * const OtherContainerClass = Container.extend({ - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }); - * const otherContainer = new OtherContainerClass(); - * console.log(otherContainer.foo()); - * console.log(OtherContainerClass.beep()); - * - * // Extend the class, providing a custom constructor. - * function AnotherContainerClass () { - * Container.call(this); - * this.created_at = new Date().getTime(); - * } - * Container.extend({ - * constructor: AnotherContainerClass, - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }) - * const anotherContainer = new AnotherContainerClass(); - * console.log(anotherContainer.created_at); - * console.log(anotherContainer.foo()); - * console.log(AnotherContainerClass.beep()); - * - * @method Container.extend - * @param {object} [props={}] Properties to add to the prototype of the - * subclass. - * @param {object} [props.constructor] Provide a custom constructor function - * to be used as the subclass itself. - * @param {object} [classProps={}] Static properties to add to the subclass. - * @returns {Constructor} Subclass of this Container class. - * @since 3.0.0 - */ diff --git a/src/DataStore.js b/src/DataStore.ts similarity index 74% rename from src/DataStore.js rename to src/DataStore.ts index 70988ce6..f67d24f2 100644 --- a/src/DataStore.js +++ b/src/DataStore.ts @@ -1,14 +1,21 @@ import utils, { safeSetLink, safeSetProp } from './utils' -import { - belongsToType, - hasManyType, - hasOneType -} from './decorators' -import SimpleStore from './SimpleStore' +import { belongsToType, hasManyType, hasOneType } from './decorators' +import SimpleStore, { SimpleStoreOpts } from './SimpleStore' import LinkedCollection from './LinkedCollection' +import { MapperOpts } from './Mapper' -const DATASTORE_DEFAULTS = { +export interface DataStoreOpts extends SimpleStoreOpts { + [customAttr: string]: any + + linkRelations?: boolean + unlinkOnDestroy?: boolean + collectionClass /*: typeof Collection */? + mapperClass? + scopes?: any +} + +const DATASTORE_DEFAULTS: DataStoreOpts = { /** * Whether in-memory relations should be unlinked from records after they are * destroyed. @@ -18,7 +25,9 @@ const DATASTORE_DEFAULTS = { * @since 3.0.0 * @type {boolean} */ - unlinkOnDestroy: true + unlinkOnDestroy: true, + + collectionClass: LinkedCollection } /** @@ -70,27 +79,28 @@ const DATASTORE_DEFAULTS = { * @tutorial ["http://www.js-data.io/v3.0/docs/working-with-the-datastore","Working with the DataStore"] * @tutorial ["http://www.js-data.io/v3.0/docs/jsdata-and-the-browser","Notes on using JSData in the Browser"] */ -function DataStore (opts) { - utils.classCallCheck(this, DataStore) - - opts || (opts = {}) - // Fill in any missing options with the defaults - utils.fillIn(opts, DATASTORE_DEFAULTS) - opts.collectionClass || (opts.collectionClass = LinkedCollection) - SimpleStore.call(this, opts) -} +export default class DataStore extends SimpleStore { + unlinkOnDestroy: any; -const props = { - constructor: DataStore, + constructor (opts: DataStoreOpts = {}) { + // Fill in any missing options with the defaults + super({ ...DATASTORE_DEFAULTS, ...opts }) + } - defineMapper (name, opts) { + /** + * Creates a new [Mapper] with [name] from the [opts] + * @param {string} name + * @param {object} opts + * @returns {*} + */ + defineMapper (name, opts?: MapperOpts) { // Complexity of this method is beyond simply using => functions to bind context const self = this - const mapper = SimpleStore.prototype.defineMapper.call(self, name, opts) + const mapper = super.defineMapper(name, opts) const idAttribute = mapper.idAttribute const collection = this.getCollection(name) - mapper.relationList.forEach(function (def) { + mapper.relationList.forEach(def => { const relation = def.relation const localField = def.localField const path = `links.${localField}` @@ -99,7 +109,9 @@ const props = { const updateOpts = { index: foreignKey } let descriptor - const getter = function () { return this._get(path) } + const getter = function () { + return this._get(path) + } if (type === belongsToType) { if (!collection.indexes[foreignKey]) { @@ -184,9 +196,9 @@ const props = { } else if (inverseDef.type === hasManyType) { const children = utils.get(currentParent, inverseDef.localField) if (id === undefined) { - utils.remove(children, (child) => child === this) + utils.remove(children, child => child === this) } else { - utils.remove(children, (child) => child === this || id === utils.get(child, idAttribute)) + utils.remove(children, child => child === this || id === utils.get(child, idAttribute)) } } } @@ -194,7 +206,7 @@ const props = { safeSetProp(this, foreignKey, value) collection.updateIndex(this, updateOpts) - if ((value === undefined || value === null)) { + if (value === undefined || value === null) { if (currentParentId !== undefined) { // Unset locals utils.set(this, localField, undefined) @@ -240,7 +252,7 @@ const props = { const toLinkIds = {} if (records) { - records.forEach((record) => { + records.forEach(record => { // e.g. comment.id const relatedId = utils.get(record, relatedIdAttribute) const currentParent = utils.get(record, inverseLocalField) @@ -248,9 +260,12 @@ const props = { const currentChildrenOfParent = utils.get(currentParent, localField) // e.g. somePost.comments.remove(comment) if (relatedId === undefined) { - utils.remove(currentChildrenOfParent, (child) => child === record) + utils.remove(currentChildrenOfParent, child => child === record) } else { - utils.remove(currentChildrenOfParent, (child) => child === record || relatedId === utils.get(child, relatedIdAttribute)) + utils.remove( + currentChildrenOfParent, + child => child === record || relatedId === utils.get(child, relatedIdAttribute) + ) } } if (relatedId !== undefined) { @@ -267,10 +282,13 @@ const props = { // e.g. post.comments = someComments if (foreignKey) { - current.forEach((record) => { + current.forEach(record => { // e.g. comment.id const relatedId = utils.get(record, relatedIdAttribute) - if ((relatedId === undefined && toLink.indexOf(record) === -1) || (relatedId !== undefined && !(relatedId in toLinkIds))) { + if ( + (relatedId === undefined && toLink.indexOf(record) === -1) || + (relatedId !== undefined && !(relatedId in toLinkIds)) + ) { // Update (unset) inverse relation if (records) { // e.g. comment.post_id = undefined @@ -282,7 +300,7 @@ const props = { safeSetLink(record, inverseLocalField, undefined) } }) - toLink.forEach((record) => { + toLink.forEach(record => { // Update (set) inverse relation // e.g. comment.post_id = post.id safeSetProp(record, foreignKey, id) @@ -295,60 +313,63 @@ const props = { // Update locals // e.g. group.users = someUsers // Update (set) inverse relation - const ids = toLink.map((child) => utils.get(child, relatedIdAttribute)).filter((id) => id !== undefined) + const ids = toLink.map(child => utils.get(child, relatedIdAttribute)).filter(id => id !== undefined) // e.g. group.user_ids = [1,2,3,...] utils.set(this, localKeys, ids) // Update (unset) inverse relation if (inverseDef.foreignKeys) { - current.forEach((child) => { + current.forEach(child => { const relatedId = utils.get(child, relatedIdAttribute) - if ((relatedId === undefined && toLink.indexOf(child) === -1) || (relatedId !== undefined && !(relatedId in toLinkIds))) { + if ( + (relatedId === undefined && toLink.indexOf(child) === -1) || + (relatedId !== undefined && !(relatedId in toLinkIds)) + ) { // Update inverse relation // safeSetLink(child, inverseLocalField, undefined) const parents = utils.get(child, inverseLocalField) || [] // e.g. someUser.groups.remove(group) if (id === undefined) { - utils.remove(parents, (parent) => parent === this) + utils.remove(parents, parent => parent === this) } else { - utils.remove(parents, (parent) => parent === this || id === utils.get(parent, idAttribute)) + utils.remove(parents, parent => parent === this || id === utils.get(parent, idAttribute)) } } }) - toLink.forEach((child) => { + toLink.forEach(child => { // Update (set) inverse relation const parents = utils.get(child, inverseLocalField) // e.g. someUser.groups.push(group) if (id === undefined) { - utils.noDupeAdd(parents, this, (parent) => parent === this) + utils.noDupeAdd(parents, this, parent => parent === this) } else { - utils.noDupeAdd(parents, this, (parent) => parent === this || id === utils.get(parent, idAttribute)) + utils.noDupeAdd(parents, this, parent => parent === this || id === utils.get(parent, idAttribute)) } }) } } else if (foreignKeys) { // e.g. user.groups = someGroups // Update (unset) inverse relation - current.forEach((parent) => { + current.forEach(parent => { const ids = utils.get(parent, foreignKeys) || [] // e.g. someGroup.user_ids.remove(user.id) - utils.remove(ids, (_key) => id === _key) + utils.remove(ids, _key => id === _key) const children = utils.get(parent, inverseLocalField) // e.g. someGroup.users.remove(user) if (id === undefined) { - utils.remove(children, (child) => child === this) + utils.remove(children, child => child === this) } else { - utils.remove(children, (child) => child === this || id === utils.get(child, idAttribute)) + utils.remove(children, child => child === this || id === utils.get(child, idAttribute)) } }) // Update (set) inverse relation - toLink.forEach((parent) => { + toLink.forEach(parent => { const ids = utils.get(parent, foreignKeys) || [] - utils.noDupeAdd(ids, id, (_key) => id === _key) + utils.noDupeAdd(ids, id, _key => id === _key) const children = utils.get(parent, inverseLocalField) if (id === undefined) { - utils.noDupeAdd(children, this, (child) => child === this) + utils.noDupeAdd(children, this, child => child === this) } else { - utils.noDupeAdd(children, this, (child) => child === this || id === utils.get(child, idAttribute)) + utils.noDupeAdd(children, this, child => child === this || id === utils.get(child, idAttribute)) } }) } @@ -411,7 +432,7 @@ const props = { if (def.set) { const origSet = descriptor.set descriptor.set = function (related) { - return def.set(def, this, related, (value) => origSet.call(this, value === undefined ? related : value)) + return def.set(def, this, related, value => origSet.call(this, value === undefined ? related : value)) } } Object.defineProperty(mapper.recordClass.prototype, localField, descriptor) @@ -419,11 +440,10 @@ const props = { }) return mapper - }, + } - destroy (name, id, opts) { - opts || (opts = {}) - return SimpleStore.prototype.destroy.call(this, name, id, opts).then((result) => { + destroy (name, id, opts: any = {}) { + return super.destroy(name, id, opts).then(result => { let record if (opts.raw) { record = result.data @@ -434,17 +454,16 @@ const props = { if (record && this.unlinkOnDestroy) { const _opts = utils.plainCopy(opts) _opts.withAll = true - utils.forEachRelation(this.getMapper(name), _opts, (def) => { + utils.forEachRelation(this.getMapper(name), _opts, def => { utils.set(record, def.localField, undefined) }) } return result }) - }, + } - destroyAll (name, query, opts) { - opts || (opts = {}) - return SimpleStore.prototype.destroyAll.call(this, name, query, opts).then((result) => { + destroyAll (name, query, opts: any = {}) { + return super.destroyAll(name, query, opts).then(result => { let records if (opts.raw) { records = result.data @@ -452,11 +471,11 @@ const props = { records = result } - if (records && records.length && this.unlinkOnDestroy) { + if (records?.length && this.unlinkOnDestroy) { const _opts = utils.plainCopy(opts) _opts.withAll = true - utils.forEachRelation(this.getMapper(name), _opts, (def) => { - records.forEach((record) => { + utils.forEachRelation(this.getMapper(name), _opts, def => { + records.forEach(record => { utils.set(record, def.localField, undefined) }) }) @@ -465,57 +484,3 @@ const props = { }) } } - -export default SimpleStore.extend(props) - -/** - * Create a subclass of this DataStore: - * @example DataStore.extend - * const JSData = require('js-data'); - * const { DataStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * // Extend the class using ES2015 class syntax. - * class CustomDataStoreClass extends DataStore { - * foo () { return 'bar'; } - * static beep () { return 'boop'; } - * } - * const customDataStore = new CustomDataStoreClass(); - * console.log(customDataStore.foo()); - * console.log(CustomDataStoreClass.beep()); - * - * // Extend the class using alternate method. - * const OtherDataStoreClass = DataStore.extend({ - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }); - * const otherDataStore = new OtherDataStoreClass(); - * console.log(otherDataStore.foo()); - * console.log(OtherDataStoreClass.beep()); - * - * // Extend the class, providing a custom constructor. - * function AnotherDataStoreClass () { - * DataStore.call(this); - * this.created_at = new Date().getTime(); - * } - * DataStore.extend({ - * constructor: AnotherDataStoreClass, - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }); - * const anotherDataStore = new AnotherDataStoreClass(); - * console.log(anotherDataStore.created_at); - * console.log(anotherDataStore.foo()); - * console.log(AnotherDataStoreClass.beep()); - * - * @method DataStore.extend - * @param {object} [props={}] Properties to add to the prototype of the - * subclass. - * @param {object} [props.constructor] Provide a custom constructor function - * to be used as the subclass itself. - * @param {object} [classProps={}] Static properties to add to the subclass. - * @returns {Constructor} Subclass of this DataStore class. - * @since 3.0.0 - */ diff --git a/src/LinkedCollection.js b/src/LinkedCollection.ts similarity index 74% rename from src/LinkedCollection.js rename to src/LinkedCollection.ts index 6b626990..999ce418 100644 --- a/src/LinkedCollection.js +++ b/src/LinkedCollection.ts @@ -8,9 +8,17 @@ const DOMAIN = 'LinkedCollection' * Extends {@link Collection}. Used by a {@link DataStore} to implement an * Identity Map. * - * ```javascript - * import {LinkedCollection} from 'js-data' - * ``` + * @example + * import {LinkedCollection} from 'js-data'; + * + * // Extend the class using ES2015 class syntax. + * class CustomLinkedCollectionClass extends LinkedCollection { + * foo () { return 'bar'; } + * static beep () { return 'boop'; } + * } + * const customLinkedCollection = new CustomLinkedCollectionClass(); + * console.log(customLinkedCollection.foo()); + * console.log(CustomLinkedCollectionClass.beep()); * * @class LinkedCollection * @extends Collection @@ -19,29 +27,17 @@ const DOMAIN = 'LinkedCollection' * @param {object} [opts] Configuration options. See {@link Collection}. * @returns {Mapper} */ -function LinkedCollection (records, opts) { - utils.classCallCheck(this, LinkedCollection) - // Make sure this collection has somewhere to store "added" timestamps - Object.defineProperties(this, { - _added: { - value: {} - }, - datastore: { - writable: true, - value: undefined - } - }) +export default class LinkedCollection extends Collection { + datastore: any; - Collection.call(this, records, opts) + constructor (records, opts) { + super(records, opts) - // Make sure this collection has a reference to a datastore - if (!this.datastore) { - throw utils.err(`new ${DOMAIN}`, 'opts.datastore')(400, 'DataStore', this.datastore) + // Make sure this collection has a reference to a datastore + if (!this.datastore) { + throw utils.err(`new ${DOMAIN}`, 'opts.datastore')(400, 'DataStore', this.datastore) + } } -} - -export default Collection.extend({ - constructor: LinkedCollection, _addMeta (record, timestamp) { // Track when this record was added @@ -50,14 +46,14 @@ export default Collection.extend({ if (utils.isFunction(record._set)) { record._set('$', timestamp) } - }, + } _clearMeta (record) { delete this._added[this.recordId(record)] if (utils.isFunction(record._set)) { record._set('$') // unset } - }, + } _onRecordEvent (...args) { Collection.prototype._onRecordEvent.apply(this, args) @@ -67,7 +63,7 @@ export default Collection.extend({ if (utils.isString(event) && event.indexOf('change') === 0) { this.updateIndexes(args[1]) } - }, + } add (records, opts) { const mapper = this.mapper @@ -77,69 +73,55 @@ export default Collection.extend({ if (singular) { records = [records] } - records = Collection.prototype.add.call(this, records, opts) + records = super.add(records, opts) if (mapper.relationList.length && records.length) { // Check the currently visited record for relations that need to be // inserted into their respective collections. - mapper.relationList.forEach(function (def) { + mapper.relationList.forEach(def => { def.addLinkedRecords(records) }) } - records.forEach((record) => this._addMeta(record, timestamp)) + records.forEach(record => this._addMeta(record, timestamp)) return singular ? records[0] : records - }, + } remove (idOrRecord, opts) { const mapper = this.mapper - const record = Collection.prototype.remove.call(this, idOrRecord, opts) + const record = super.remove(idOrRecord, opts) if (record) { this._clearMeta(record) } if (mapper.relationList.length && record) { - mapper.relationList.forEach(function (def) { + mapper.relationList.forEach(def => { def.removeLinkedRecords(mapper, [record]) }) } return record - }, + } removeAll (query, opts) { const mapper = this.mapper - const records = Collection.prototype.removeAll.call(this, query, opts) + const records = super.removeAll(query, opts) records.forEach(this._clearMeta, this) if (mapper.relationList.length && records.length) { - mapper.relationList.forEach(function (def) { + mapper.relationList.forEach(def => { def.removeLinkedRecords(mapper, records) }) } return records } -}) +} /** * Create a subclass of this LinkedCollection: * - * @example LinkedCollection.extend - * const JSData = require('js-data'); - * const { LinkedCollection } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * // Extend the class using ES2015 class syntax. - * class CustomLinkedCollectionClass extends LinkedCollection { - * foo () { return 'bar'; } - * static beep () { return 'boop'; } - * } - * const customLinkedCollection = new CustomLinkedCollectionClass(); - * console.log(customLinkedCollection.foo()); - * console.log(CustomLinkedCollectionClass.beep()); - * * // Extend the class using alternate method. * const OtherLinkedCollectionClass = LinkedCollection.extend({ * foo () { return 'bar'; } diff --git a/src/Mapper.js b/src/Mapper.ts similarity index 83% rename from src/Mapper.js rename to src/Mapper.ts index a436d0ef..1731abef 100644 --- a/src/Mapper.js +++ b/src/Mapper.ts @@ -1,30 +1,17 @@ import utils from './utils' import Component from './Component' import Record from './Record' -import Schema from './Schema' -import { Relation } from './relations' -import { - belongsTo, - belongsToType, - hasMany, - hasManyType, - hasOne, - hasOneType -} from './decorators' +import Schema, { PropertyDefinition, SchemaDefinition } from './Schema' +import { Relation } from './Relation' +import { belongsTo, belongsToType, hasMany, hasManyType, hasOne, hasOneType } from './decorators' +import { TsDataError } from './TsDataError' +import { QueryDefinition } from './Query' const DOMAIN = 'Mapper' -const applyDefaultsHooks = [ - 'beforeCreate', - 'beforeCreateMany' -] -const validatingHooks = [ - 'beforeCreate', - 'beforeCreateMany', - 'beforeUpdate', - 'beforeUpdateAll', - 'beforeUpdateMany' -] -const makeNotify = function (num) { +const applyDefaultsHooks = ['beforeCreate', 'beforeCreateMany'] +const validatingHooks = ['beforeCreate', 'beforeCreateMany', 'beforeUpdate', 'beforeUpdateAll', 'beforeUpdateMany'] + +function makeNotify (num) { return function (...args) { const opts = args[args.length - num] const op = opts.op @@ -32,12 +19,12 @@ const makeNotify = function (num) { if (applyDefaultsHooks.indexOf(op) !== -1 && opts.applyDefaults !== false) { const schema = this.getSchema() - if (schema && schema.applyDefaults) { + if (schema?.applyDefaults) { let toProcess = args[0] if (!utils.isArray(toProcess)) { toProcess = [toProcess] } - toProcess.forEach((record) => { + toProcess.forEach(record => { schema.applyDefaults(record) }) } @@ -59,7 +46,7 @@ const makeNotify = function (num) { // Abort lifecycle due to validation errors if (errors) { - const err = new Error('validation failed') + const err = new TsDataError('validation failed') err.errors = errors return utils.reject(err) } @@ -127,7 +114,7 @@ const LIFECYCLE_METHODS = { }, updateMany: { adapterArgs (mapper, records, opts) { - return [records.map((record) => mapper.toJSON(record, opts)), opts] + return [records.map(record => mapper.toJSON(record, opts)), opts] }, beforeAssign: 0, defaults: [[], {}], @@ -135,28 +122,49 @@ const LIFECYCLE_METHODS = { } } -const MAPPER_DEFAULTS = { +export interface MapperOpts { + name?: string + + [customAttr: string]: any + + endpoint?: string + + onConflict?: 'skip' + + relations?: any + + type?: string + + schema?: SchemaDefinition | Schema + + recordClass?: typeof Record | boolean + + wrap?: boolean + + methods?: { [name: string]: Function } + + scopes?: any + + mapperClass?: typeof Mapper + /** * Hash of registered adapters. Don't modify directly. Use * {@link Mapper#registerAdapter} instead. * * @default {} - * @name Mapper#_adapters * @since 3.0.0 * @tutorial ["http://www.js-data.io/v3.0/docs/connecting-to-a-data-source","Connecting to a data source"] */ - _adapters: {}, + _adapters?: {} /** * Whether {@link Mapper#beforeCreate} and {@link Mapper#beforeCreateMany} * should automatically receive default values according to the Mapper's schema. * * @default true - * @name Mapper#applyDefaults * @since 3.0.0 - * @type {boolean} */ - applyDefaults: true, + applyDefaults?: boolean /** * Whether to augment {@link Mapper#recordClass} with ES5 getters and setters @@ -166,62 +174,52 @@ const MAPPER_DEFAULTS = { * property, and is `true` by default. * * @default true - * @name Mapper#applySchema * @since 3.0.0 - * @type {boolean} */ - applySchema: true, + applySchema?: boolean /** * The name of the registered adapter that this Mapper should used by default. * * @default "http" - * @name Mapper#defaultAdapter * @since 3.0.0 * @tutorial ["http://www.js-data.io/v3.0/docs/connecting-to-a-data-source","Connecting to a data source"] - * @type {string} */ - defaultAdapter: 'http', + defaultAdapter?: string /** * The field used as the unique identifier on records handled by this Mapper. * * @default id - * @name Mapper#idAttribute * @since 3.0.0 - * @type {string} */ - idAttribute: 'id', + idAttribute?: string + + properties?: { [name: string]: PropertyDefinition } /** * Whether records created from this mapper keep changeHistory on property changes. * * @default true - * @name Mapper#keepChangeHistory * @since 3.0.0 - * @type {boolean} */ - keepChangeHistory: true, + keepChangeHistory?: boolean /** * Whether this Mapper should emit operational events. * * @default true - * @name Mapper#notify * @since 3.0.0 - * @type {boolean} */ - notify: true, + notify?: boolean /** * Whether to skip validation when the Record instances are created. * * @default false - * @name Mapper#noValidate * @since 3.0.0 - * @type {boolean} */ - noValidate: false, + noValidate?: boolean /** * Whether {@link Mapper#create}, {@link Mapper#createMany}, @@ -235,26 +233,35 @@ const MAPPER_DEFAULTS = { * instance data. * * @default false - * @name Mapper#raw * @since 3.0.0 - * @type {boolean} */ - raw: false, + raw?: boolean /** * Whether records created from this mapper automatically validate their properties * when their properties are modified. * * @default true - * @name Mapper#validateOnSet * @since 3.0.0 - * @type {boolean} */ + validateOnSet?: boolean +} + +const MAPPER_DEFAULTS: MapperOpts = { + _adapters: {}, + applyDefaults: true, + applySchema: true, + defaultAdapter: 'http', + idAttribute: 'id', + keepChangeHistory: true, + notify: true, + noValidate: false, + raw: false, validateOnSet: true } /** - * The core of JSData's [ORM/ODM][orm] implementation. Given a minimum amout of + * The core of JSData's [ORM/ODM][orm] implementation. Given a minimum amount of * meta information about a resource, a Mapper can perform generic CRUD * operations against that resource. Apart from its configuration, a Mapper is * stateless. The particulars of various persistence layers have been abstracted @@ -304,207 +311,191 @@ const MAPPER_DEFAULTS = { * @tutorial ["http://www.js-data.io/v3.0/docs/components-of-jsdata#mapper","Components of JSData: Mapper"] * @tutorial ["http://www.js-data.io/v3.0/docs/modeling-your-data","Modeling your data"] */ -function Mapper (opts) { - utils.classCallCheck(this, Mapper) - Component.call(this) - opts || (opts = {}) - - // Prepare certain properties to be non-enumerable - Object.defineProperties(this, { - _adapters: { - value: undefined, - writable: true - }, - - /** - * The {@link Container} that holds this Mapper. __Do not modify.__ - * - * @name Mapper#lifecycleMethods - * @since 3.0.0 - * @type {Object} - */ - datastore: { - value: undefined, - writable: true - }, - - /** - * The meta information describing this Mapper's available lifecycle - * methods. __Do not modify.__ - * - * @name Mapper#lifecycleMethods - * @since 3.0.0 - * @type {Object} - */ - lifecycleMethods: { - value: LIFECYCLE_METHODS - }, - - /** - * Set to `false` to force the Mapper to work with POJO objects only. - * - * @example - * // Use POJOs only. - * import { Mapper, Record } from 'js-data'; - * const UserMapper = new Mapper({ recordClass: false }); - * UserMapper.recordClass // false; - * const user = UserMapper.createRecord(); - * user instanceof Record; // false - * - * @example - * // Set to a custom class to have records wrapped in your custom class. - * import { Mapper, Record } from 'js-data'; - * // Custom class - * class User { - * constructor (props = {}) { - * for (var key in props) { - * if (props.hasOwnProperty(key)) { - * this[key] = props[key]; - * } - * } - * } - * } - * const UserMapper = new Mapper({ recordClass: User }); - * UserMapper.recordClass; // function User() {} - * const user = UserMapper.createRecord(); - * user instanceof Record; // false - * user instanceof User; // true - * - * - * @example - * // Extend the {@link Record} class. - * import { Mapper, Record } from 'js-data'; - * // Custom class - * class User extends Record { - * constructor () { - * super(props); - * } - * } - * const UserMapper = new Mapper({ recordClass: User }); - * UserMapper.recordClass; // function User() {} - * const user = UserMapper.createRecord(); - * user instanceof Record; // true - * user instanceof User; // true - * - * @name Mapper#recordClass - * @default {@link Record} - * @see Record - * @since 3.0.0 - */ - recordClass: { - value: undefined, - writable: true - }, - - /** - * This Mapper's {@link Schema}. - * - * @example Mapper#schema - * const JSData = require('js-data'); - * const { Mapper } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const UserMapper = new Mapper({ - * name: 'user', - * schema: { - * properties: { - * id: { type: 'number' }, - * first: { type: 'string', track: true }, - * last: { type: 'string', track: true }, - * role: { type: 'string', track: true, required: true }, - * age: { type: 'integer', track: true }, - * is_active: { type: 'number' } - * } - * } - * }); - * const user = UserMapper.createRecord({ - * id: 1, - * name: 'John', - * role: 'admin' - * }); - * user.on('change', function (user, changes) { - * console.log(changes); - * }); - * user.on('change:role', function (user, value) { - * console.log('change:role - ' + value); - * }); - * user.role = 'owner'; - * - * @name Mapper#schema - * @see Schema - * @since 3.0.0 - * @type {Schema} - */ - schema: { - value: undefined, - writable: true - } - }) - - // Apply user-provided configuration - utils.fillIn(this, opts) - // Fill in any missing options with the defaults - utils.fillIn(this, utils.copy(MAPPER_DEFAULTS)) +export default class Mapper extends Component { + idAttribute: string; + name: string; /** - * The name for this Mapper. This is the minimum amount of meta information - * required for a Mapper to be able to execute CRUD operations for a - * Resource. + * This Mapper's {@link Schema}. * - * @name Mapper#name + * @example Mapper#schema + * const JSData = require('js-data'); + * const { Mapper } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const UserMapper = new Mapper({ + * name: 'user', + * schema: { + * properties: { + * id: { type: 'number' }, + * first: { type: 'string', track: true }, + * last: { type: 'string', track: true }, + * role: { type: 'string', track: true, required: true }, + * age: { type: 'integer', track: true }, + * is_active: { type: 'number' } + * } + * } + * }); + * const user = UserMapper.createRecord({ + * id: 1, + * name: 'John', + * role: 'admin' + * }); + * user.on('change', function (user, changes) { + * console.log(changes); + * }); + * user.on('change:role', function (user, value) { + * console.log('change:role - ' + value); + * }); + * user.role = 'owner'; + * + * @name Mapper#schema + * @see Schema * @since 3.0.0 - * @type {string} + * @type {Schema} */ - if (!this.name) { - throw utils.err(`new ${DOMAIN}`, 'opts.name')(400, 'string', this.name) - } + schema: Schema; + /** + * Set to `false` to force the Mapper to work with POJO objects only. + * + * @example + * // Use POJOs only. + * import { Mapper, Record } from 'js-data'; + * const UserMapper = new Mapper({ recordClass: false }); + * UserMapper.recordClass // false; + * const user = UserMapper.createRecord(); + * user instanceof Record; // false + * + * @example + * // Set to a custom class to have records wrapped in your custom class. + * import { Mapper, Record } from 'js-data'; + * // Custom class + * class User { + * constructor (props = {}) { + * for (var key in props) { + * if (props.hasOwnProperty(key)) { + * this[key] = props[key]; + * } + * } + * } + * } + * const UserMapper = new Mapper({ recordClass: User }); + * UserMapper.recordClass; // function User() {} + * const user = UserMapper.createRecord(); + * user instanceof Record; // false + * user instanceof User; // true + * + * + * @example + * // Extend the {@link Record} class. + * import { Mapper, Record } from 'js-data'; + * // Custom class + * class User extends Record { + * constructor () { + * super(props); + * } + * } + * const UserMapper = new Mapper({ recordClass: User }); + * UserMapper.recordClass; // function User() {} + * const user = UserMapper.createRecord(); + * user instanceof Record; // true + * user instanceof User; // true + * + * @name Mapper#recordClass + * @default {@link Record} + * @see Record + * @since 3.0.0 + */ + recordClass: typeof Record | Function | false | any; + methods: any; + applySchema: any; + relationList: any; + defaultAdapter: any; + relationFields: any; + _adapters: any; + relations: any; + /** + * The meta information describing this Mapper's available lifecycle + * methods. __Do not modify.__ + * + * @name Mapper#lifecycleMethods + * @since 3.0.0 + * @type {Object} + */ + lifecycleMethods = LIFECYCLE_METHODS; - // Setup schema, with an empty default schema if necessary - if (this.schema) { - this.schema.type || (this.schema.type = 'object') - if (!(this.schema instanceof Schema)) { - this.schema = new Schema(this.schema || { type: 'object' }) - } - } + /** + * The {@link Container} that holds this Mapper. __Do not modify.__ + * + * @name Mapper#lifecycleMethods + * @since 3.0.0 + * @type {Object} + */ + datastore: any; + validateOnSet: any; + keepChangeHistory: any; - // Create a subclass of Record that's tied to this Mapper - if (this.recordClass === undefined) { - const superClass = Record - this.recordClass = superClass.extend({ - constructor: (function Record () { - var subClass = function Record (props, opts) { - utils.classCallCheck(this, subClass) - superClass.call(this, props, opts) - } - return subClass - })() - }) - } + constructor (opts: MapperOpts = {}) { + super() - if (this.recordClass) { - this.recordClass.mapper = this + // Apply user-provided configuration + utils.fillIn(this, opts) + // Fill in any missing options with the defaults + utils.fillIn(this, utils.copy(MAPPER_DEFAULTS)) /** - * Functions that should be added to the prototype of {@link Mapper#recordClass}. + * The name for this Mapper. This is the minimum amount of meta information + * required for a Mapper to be able to execute CRUD operations for a + * Resource. * - * @name Mapper#methods + * @name Mapper#name * @since 3.0.0 - * @type {Object} + * @type {string} */ - if (utils.isObject(this.methods)) { - utils.addHiddenPropsToTarget(this.recordClass.prototype, this.methods) + if (!this.name) { + throw utils.err(`new ${DOMAIN}`, 'opts.name')(400, 'string', this.name) } - // We can only apply the schema to the prototype of this.recordClass if the - // class extends Record - if (Object.isPrototypeOf.call(Record, this.recordClass) && this.schema && this.schema.apply && this.applySchema) { - this.schema.apply(this.recordClass.prototype) + // Setup schema, with an empty default schema if necessary + if (this.schema) { + this.schema.type = this.schema.type || 'object' + if (!(this.schema instanceof Schema)) { + this.schema = new Schema(this.schema || { type: 'object' }) + } } - } -} -export default Component.extend({ - constructor: Mapper, + // Create a subclass of Record that's tied to this Mapper + if (this.recordClass === undefined) { + // tslint:disable-next-line:max-classes-per-file + this.recordClass = class TiedRecord extends Record {} + } + + if (this.recordClass) { + this.recordClass.mapper = this + + /** + * Functions that should be added to the prototype of {@link Mapper#recordClass}. + * + * @name Mapper#methods + * @since 3.0.0 + * @type {Object} + */ + if (utils.isObject(this.methods)) { + utils.addHiddenPropsToTarget(this.recordClass.prototype, this.methods) + } + + // We can only apply the schema to the prototype of this.recordClass if the + // class extends Record + if ( + Record.prototype.isPrototypeOf(Object.create(this.recordClass.prototype)) && + this.schema && + this.schema.apply && + this.applySchema + ) { + this.schema.apply(this.recordClass.prototype) + } + } + } /** * Mapper lifecycle hook called by {@link Mapper#count}. If this method @@ -517,7 +508,7 @@ export default Component.extend({ * @param {*} result The result, if any. * @since 3.0.0 */ - afterCount: notify2, + afterCount = notify2; /** * Mapper lifecycle hook called by {@link Mapper#create}. If this method @@ -530,7 +521,7 @@ export default Component.extend({ * @param {*} result The result, if any. * @since 3.0.0 */ - afterCreate: notify2, + afterCreate = notify2; /** * Mapper lifecycle hook called by {@link Mapper#createMany}. If this method @@ -543,7 +534,7 @@ export default Component.extend({ * @param {*} result The result, if any. * @since 3.0.0 */ - afterCreateMany: notify2, + afterCreateMany = notify2; /** * Mapper lifecycle hook called by {@link Mapper#destroy}. If this method @@ -556,7 +547,7 @@ export default Component.extend({ * @param {*} result The result, if any. * @since 3.0.0 */ - afterDestroy: notify2, + afterDestroy = notify2; /** * Mapper lifecycle hook called by {@link Mapper#destroyAll}. If this method @@ -570,7 +561,7 @@ export default Component.extend({ * @param {*} result The result, if any. * @since 3.0.0 */ - afterDestroyAll: notify2, + afterDestroyAll = notify2; /** * Mapper lifecycle hook called by {@link Mapper#find}. If this method @@ -583,7 +574,7 @@ export default Component.extend({ * @param {*} result The result, if any. * @since 3.0.0 */ - afterFind: notify2, + afterFind = notify2; /** * Mapper lifecycle hook called by {@link Mapper#findAll}. If this method @@ -596,7 +587,7 @@ export default Component.extend({ * @param {*} result The result, if any. * @since 3.0.0 */ - afterFindAll: notify2, + afterFindAll = notify2; /** * Mapper lifecycle hook called by {@link Mapper#sum}. If this method @@ -609,7 +600,7 @@ export default Component.extend({ * @param {*} result The result, if any. * @since 3.0.0 */ - afterSum: notify2, + afterSum = notify2; /** * Mapper lifecycle hook called by {@link Mapper#update}. If this method @@ -623,7 +614,7 @@ export default Component.extend({ * @param {*} result The result, if any. * @since 3.0.0 */ - afterUpdate: notify2, + afterUpdate = notify2; /** * Mapper lifecycle hook called by {@link Mapper#updateAll}. If this method @@ -637,7 +628,7 @@ export default Component.extend({ * @param {*} result The result, if any. * @since 3.0.0 */ - afterUpdateAll: notify2, + afterUpdateAll = notify2; /** * Mapper lifecycle hook called by {@link Mapper#updateMany}. If this method @@ -650,7 +641,7 @@ export default Component.extend({ * @param {*} result The result, if any. * @since 3.0.0 */ - afterUpdateMany: notify2, + afterUpdateMany = notify2; /** * Mapper lifecycle hook called by {@link Mapper#create}. If this method @@ -662,7 +653,7 @@ export default Component.extend({ * @param {object} opts The `opts` argument passed to {@link Mapper#create}. * @since 3.0.0 */ - beforeCreate: notify, + beforeCreate = notify; /** * Mapper lifecycle hook called by {@link Mapper#createMany}. If this method @@ -674,7 +665,7 @@ export default Component.extend({ * @param {object} opts The `opts` argument passed to {@link Mapper#createMany}. * @since 3.0.0 */ - beforeCreateMany: notify, + beforeCreateMany = notify; /** * Mapper lifecycle hook called by {@link Mapper#count}. If this method @@ -686,7 +677,7 @@ export default Component.extend({ * @param {object} opts The `opts` argument passed to {@link Mapper#count}. * @since 3.0.0 */ - beforeCount: notify, + beforeCount = notify; /** * Mapper lifecycle hook called by {@link Mapper#destroy}. If this method @@ -698,7 +689,7 @@ export default Component.extend({ * @param {object} opts The `opts` argument passed to {@link Mapper#destroy}. * @since 3.0.0 */ - beforeDestroy: notify, + beforeDestroy = notify; /** * Mapper lifecycle hook called by {@link Mapper#destroyAll}. If this method @@ -710,7 +701,7 @@ export default Component.extend({ * @param {object} opts The `opts` argument passed to {@link Mapper#destroyAll}. * @since 3.0.0 */ - beforeDestroyAll: notify, + beforeDestroyAll = notify; /** * Mappers lifecycle hook called by {@link Mapper#find}. If this method @@ -722,7 +713,7 @@ export default Component.extend({ * @param {object} opts The `opts` argument passed to {@link Mapper#find}. * @since 3.0.0 */ - beforeFind: notify, + beforeFind = notify; /** * Mapper lifecycle hook called by {@link Mapper#findAll}. If this method @@ -734,7 +725,7 @@ export default Component.extend({ * @param {object} opts The `opts` argument passed to {@link Mapper#findAll}. * @since 3.0.0 */ - beforeFindAll: notify, + beforeFindAll = notify; /** * Mapper lifecycle hook called by {@link Mapper#sum}. If this method @@ -747,7 +738,7 @@ export default Component.extend({ * @param {object} opts The `opts` argument passed to {@link Mapper#sum}. * @since 3.0.0 */ - beforeSum: notify, + beforeSum = notify; /** * Mapper lifecycle hook called by {@link Mapper#update}. If this method @@ -760,7 +751,7 @@ export default Component.extend({ * @param {object} opts The `opts` argument passed to {@link Mapper#update}. * @since 3.0.0 */ - beforeUpdate: notify, + beforeUpdate = notify; /** * Mapper lifecycle hook called by {@link Mapper#updateAll}. If this method @@ -773,7 +764,7 @@ export default Component.extend({ * @param {object} opts The `opts` argument passed to {@link Mapper#updateAll}. * @since 3.0.0 */ - beforeUpdateAll: notify, + beforeUpdateAll = notify; /** * Mapper lifecycle hook called by {@link Mapper#updateMany}. If this method @@ -785,7 +776,7 @@ export default Component.extend({ * @param {object} opts The `opts` argument passed to {@link Mapper#updateMany}. * @since 3.0.0 */ - beforeUpdateMany: notify, + beforeUpdateMany = notify; /** * This method is called at the end of most lifecycle methods. It does the @@ -800,7 +791,7 @@ export default Component.extend({ * @private * @since 3.0.0 */ - _end (result, opts, skip) { + _end (result, opts, skip = false) { if (opts.raw) { utils._(result, opts) } @@ -817,7 +808,7 @@ export default Component.extend({ } } return result - }, + } /** * Define a belongsTo relationship. Only useful if you're managing your @@ -850,7 +841,7 @@ export default Component.extend({ */ belongsTo (relatedMapper, opts) { return belongsTo(relatedMapper, opts)(this) - }, + } /** * Select records according to the `query` argument and return the count. @@ -879,9 +870,9 @@ export default Component.extend({ * @returns {Promise} Resolves with the count of the selected records. * @since 3.0.0 */ - count (query, opts) { + count (query, opts?) { return this.crud('count', query, opts) - }, + } /** * Fired during {@link Mapper#create}. See @@ -915,6 +906,7 @@ export default Component.extend({ * @see Mapper~afterCreateListener * @see Mapper#create */ + /** * Callback signature for the {@link Mapper#event:afterCreate} event. * @@ -967,50 +959,54 @@ export default Component.extend({ * @returns {Promise} Resolves with the created record. * @since 3.0.0 */ - create (props, opts) { - // Default values for arguments - props || (props = {}) - opts || (opts = {}) + create (props: any = {}, opts: any = {}) { const originalRecord = props let parentRelationMap = {} - let adapterResponse = {} + let adapterResponse: any = {} // Fill in "opts" with the Mapper's configuration utils._(opts, this) opts.adapter = this.getAdapterName(opts) opts.op = 'beforeCreate' - return this._runHook(opts.op, props, opts).then((props) => { - opts.with || (opts.with = []) - return this._createParentRecordIfRequired(props, opts) - }).then((relationMap) => { - parentRelationMap = relationMap - }).then(() => { - opts.op = 'create' - return this._invokeAdapterMethod(opts.op, props, opts) - }).then((result) => { - adapterResponse = result - }).then(() => { - const createdProps = opts.raw ? adapterResponse.data : adapterResponse - - return this._createOrAssignChildRecordIfRequired(createdProps, { - opts, - parentRelationMap, - originalProps: props + return this._runHook(opts.op, props, opts) + .then(props => { + opts.with = opts.with || [] + return this._createParentRecordIfRequired(props, opts) }) - }).then((createdProps) => { - return this._commitChanges(originalRecord, createdProps) - }).then((record) => { - if (opts.raw) { - adapterResponse.data = record - } else { - adapterResponse = record - } - const result = this._end(adapterResponse, opts) - opts.op = 'afterCreate' - return this._runHook(opts.op, props, opts, result) - }) - }, + .then(relationMap => { + parentRelationMap = relationMap + }) + .then(() => { + opts.op = 'create' + return this._invokeAdapterMethod(opts.op, props, opts) + }) + .then(result => { + adapterResponse = result + }) + .then(() => { + const createdProps = opts.raw ? adapterResponse.data : adapterResponse + + return this._createOrAssignChildRecordIfRequired(createdProps, { + opts, + parentRelationMap, + originalProps: props + }) + }) + .then(createdProps => { + return this._commitChanges(originalRecord, createdProps) + }) + .then(record => { + if (opts.raw) { + adapterResponse.data = record + } else { + adapterResponse = record + } + const result = this._end(adapterResponse, opts) + opts.op = 'afterCreate' + return this._runHook(opts.op, props, opts, result) + }) + } _commitChanges (recordOrRecords, newValues) { if (utils.isArray(recordOrRecords)) { @@ -1024,7 +1020,7 @@ export default Component.extend({ } return recordOrRecords - }, + } /** * Use {@link Mapper#createRecord} instead. @@ -1036,9 +1032,9 @@ export default Component.extend({ * @see Mapper#createRecord * @since 3.0.0 */ - createInstance (props, opts) { + createInstance (props, opts?) { return this.createRecord(props, opts) - }, + } /** * Creates parent record for relation types like BelongsTo or HasMany with localKeys @@ -1063,13 +1059,13 @@ export default Component.extend({ tasks.push(def.createParentRecord(props, optsCopy)) }) - return utils.Promise.all(tasks).then(records => { + return Promise.all(tasks).then(records => { return relations.reduce((map, relation, index) => { relation.setLocalField(map, records[index]) return map }, {}) }) - }, + } /** * Creates child record for relation types like HasOne or HasMany with foreignKey @@ -1107,9 +1103,8 @@ export default Component.extend({ } }) - return utils.Promise.all(tasks) - .then(() => props) - }, + return Promise.all(tasks).then(() => props) + } /** * Fired during {@link Mapper#createMany}. See @@ -1143,6 +1138,7 @@ export default Component.extend({ * @see Mapper~afterCreateManyListener * @see Mapper#createMany */ + /** * Callback signature for the {@link Mapper#event:afterCreateMany} event. * @@ -1200,10 +1196,8 @@ export default Component.extend({ * @since 3.0.0 * @tutorial ["http://www.js-data.io/v3.0/docs/saving-data","Saving data"] */ - createMany (records, opts) { + createMany (records = [], opts: any = {}) { // Default values for arguments - records || (records = []) - opts || (opts = {}) const originalRecords = records let adapterResponse @@ -1213,85 +1207,98 @@ export default Component.extend({ // beforeCreateMany lifecycle hook opts.op = 'beforeCreateMany' - return this._runHook(opts.op, records, opts).then((records) => { - // Deep pre-create belongsTo relations - const belongsToRelationData = {} - opts.with || (opts.with = []) - let tasks = [] - utils.forEachRelation(this, opts, (def, optsCopy) => { - const relationData = records - .map((record) => def.getLocalField(record)) - .filter(Boolean) - if (def.type === belongsToType && relationData.length === records.length) { - // Create belongsTo relation first because we need a generated id to - // attach to the child - optsCopy.raw = false - tasks.push(def.createLinked(relationData, optsCopy).then((relatedRecords) => { - records.forEach((record, i) => def.setForeignKey(record, relatedRecords[i])) - }).then((relatedRecords) => { - def.setLocalField(belongsToRelationData, relatedRecords) - })) - } - }) - return utils.Promise.all(tasks).then(() => { - opts.op = 'createMany' - return this._invokeAdapterMethod(opts.op, records, opts) - }).then((result) => { - adapterResponse = result - }).then(() => { - const createdRecordsData = opts.raw ? adapterResponse.data : adapterResponse - - // Deep post-create hasOne relations - tasks = [] + return this._runHook(opts.op, records, opts) + .then(records => { + // Deep pre-create belongsTo relations + const belongsToRelationData = {} + opts.with = opts.with || [] + let tasks = [] utils.forEachRelation(this, opts, (def, optsCopy) => { - const relationData = records - .map((record) => def.getLocalField(record)) - .filter(Boolean) - if (relationData.length !== records.length) { - return + const relationData = records.map(record => def.getLocalField(record)).filter(Boolean) + if (def.type === belongsToType && relationData.length === records.length) { + // Create belongsTo relation first because we need a generated id to + // attach to the child + optsCopy.raw = false + tasks.push( + def + .createLinked(relationData, optsCopy) + .then(relatedRecords => { + records.forEach((record, i) => def.setForeignKey(record, relatedRecords[i])) + }) + .then(relatedRecords => { + def.setLocalField(belongsToRelationData, relatedRecords) + }) + ) } - - optsCopy.raw = false - const belongsToData = def.getLocalField(belongsToRelationData) - let task - // Create hasMany and hasOne after the main create because we needed - // a generated id to attach to these items - if (def.type === hasManyType) { - // Not supported - this.log('warn', 'deep createMany of hasMany type not supported!') - } else if (def.type === hasOneType) { - createdRecordsData.forEach((createdRecordData, i) => { - def.setForeignKey(createdRecordData, relationData[i]) - }) - task = def.getRelation().createMany(relationData, optsCopy).then((relatedData) => { - createdRecordsData.forEach((createdRecordData, i) => { - def.setLocalField(createdRecordData, relatedData[i]) - }) + }) + return Promise.all(tasks) + .then(() => { + opts.op = 'createMany' + return this._invokeAdapterMethod(opts.op, records, opts) + }) + .then(result => { + adapterResponse = result + }) + .then(() => { + const createdRecordsData = opts.raw ? adapterResponse.data : adapterResponse + + // Deep post-create hasOne relations + tasks = [] + utils.forEachRelation(this, opts, (def, optsCopy) => { + const relationData = records.map(record => def.getLocalField(record)).filter(Boolean) + if (relationData.length !== records.length) { + return + } + + optsCopy.raw = false + const belongsToData = def.getLocalField(belongsToRelationData) + let task + // Create hasMany and hasOne after the main create because we needed + // a generated id to attach to these items + if (def.type === hasManyType) { + // Not supported + this.log('warn', 'deep createMany of hasMany type not supported!') + } else if (def.type === hasOneType) { + createdRecordsData.forEach((createdRecordData, i) => { + def.setForeignKey(createdRecordData, relationData[i]) + }) + task = def + .getRelation() + .createMany(relationData, optsCopy) + .then(relatedData => { + createdRecordsData.forEach((createdRecordData, i) => { + def.setLocalField(createdRecordData, relatedData[i]) + }) + }) + } else if ( + def.type === belongsToType && + belongsToData && + belongsToData.length === createdRecordsData.length + ) { + createdRecordsData.forEach((createdRecordData, i) => { + def.setLocalField(createdRecordData, belongsToData[i]) + }) + } + if (task) { + tasks.push(task) + } }) - } else if (def.type === belongsToType && belongsToData && belongsToData.length === createdRecordsData.length) { - createdRecordsData.forEach((createdRecordData, i) => { - def.setLocalField(createdRecordData, belongsToData[i]) + return Promise.all(tasks).then(() => { + return this._commitChanges(originalRecords, createdRecordsData) }) - } - if (task) { - tasks.push(task) - } - }) - return utils.Promise.all(tasks).then(() => { - return this._commitChanges(originalRecords, createdRecordsData) - }) + }) }) - }).then((records) => { - if (opts.raw) { - adapterResponse.data = records - } else { - adapterResponse = records - } - const result = this._end(adapterResponse, opts) - opts.op = 'afterCreateMany' - return this._runHook(opts.op, records, opts, result) - }) - }, + .then(records => { + if (opts.raw) { + adapterResponse.data = records + } else { + adapterResponse = records + } + const result = this._end(adapterResponse, opts) + opts.op = 'afterCreateMany' + return this._runHook(opts.op, records, opts, result) + }) + } /** * Create an unsaved, uncached instance of this Mapper's @@ -1368,24 +1375,26 @@ export default Component.extend({ * @returns {Record|Record[]} The Record instance or Record instances. * @since 3.0.0 */ - createRecord (props, opts) { - props || (props = {}) + createRecord (props: any = {}, opts?): Record | Record[] | any { if (utils.isArray(props)) { - return props.map((_props) => this.createRecord(_props, opts)) + return props.map(_props => this.createRecord(_props, opts)) } if (!utils.isObject(props)) { throw utils.err(`${DOMAIN}#createRecord`, 'props')(400, 'array or object', props) } if (this.relationList) { - this.relationList.forEach(function (def) { + this.relationList.forEach(def => { def.ensureLinkedDataHasProperType(props, opts) }) } const RecordCtor = this.recordClass - return (!RecordCtor || props instanceof RecordCtor) ? props : new RecordCtor(props, opts) - }, + const result = !RecordCtor || props instanceof RecordCtor ? props : new RecordCtor(props, opts) + return result + // Record.mapper = this; + // return new Record(props); + } /** * Lifecycle invocation method. You probably won't call this method directly. @@ -1423,31 +1432,34 @@ export default Component.extend({ // before lifecycle hook op = opts.op = before - return utils.resolve(this[op](...args)).then((_value) => { - if (args[config.beforeAssign] !== undefined) { - // Allow for re-assignment from lifecycle hook - args[config.beforeAssign] = _value === undefined ? args[config.beforeAssign] : _value - } - // Now delegate to the adapter - op = opts.op = method - args = config.adapterArgs ? config.adapterArgs(this, ...args) : args - this.dbg(op, ...args) - return utils.resolve(this.getAdapter(adapter)[op](this, ...args)) - }).then((result) => { - // force noValidate on find/findAll - const noValidate = /find/.test(op) || opts.noValidate - const _opts = Object.assign({}, opts, { noValidate }) - - result = this._end(result, _opts, !!config.skip) - args.push(result) - // after lifecycle hook - op = opts.op = after - return utils.resolve(this[op](...args)).then((_result) => { - // Allow for re-assignment from lifecycle hook - return _result === undefined ? result : _result + return utils + .resolve(this[op](...args)) + .then(_value => { + if (args[config.beforeAssign] !== undefined) { + // Allow for re-assignment from lifecycle hook + args[config.beforeAssign] = _value === undefined ? args[config.beforeAssign] : _value + } + // Now delegate to the adapter + op = opts.op = method + args = config.adapterArgs ? config.adapterArgs(this, ...args) : args + this.dbg(op, ...args) + return utils.resolve(this.getAdapter(adapter)[op](this, ...args)) }) - }) - }, + .then(result => { + // force noValidate on find/findAll + const noValidate = /find/.test(op) || opts.noValidate + const _opts = Object.assign({}, opts, { noValidate }) + + result = this._end(result, _opts, !!config.skip) + args.push(result) + // after lifecycle hook + op = opts.op = after + return utils.resolve(this[op](...args)).then(_result => { + // Allow for re-assignment from lifecycle hook + return _result === undefined ? result : _result + }) + }) + } /** * Fired during {@link Mapper#destroy}. See @@ -1481,6 +1493,7 @@ export default Component.extend({ * @see Mapper~afterDestroyListener * @see Mapper#destroy */ + /** * Callback signature for the {@link Mapper#event:afterDestroy} event. * @@ -1532,9 +1545,9 @@ export default Component.extend({ * @since 3.0.0 * @tutorial ["http://www.js-data.io/v3.0/docs/saving-data","Saving data"] */ - destroy (id, opts) { + destroy (id: string | number, opts?) { return this.crud('destroy', id, opts) - }, + } /** * Fired during {@link Mapper#destroyAll}. See @@ -1568,6 +1581,7 @@ export default Component.extend({ * @see Mapper~afterDestroyAllListener * @see Mapper#destroyAll */ + /** * Callback signature for the {@link Mapper#event:afterDestroyAll} event. * @@ -1633,9 +1647,9 @@ export default Component.extend({ * @since 3.0.0 * @tutorial ["http://www.js-data.io/v3.0/docs/saving-data","Saving data"] */ - destroyAll (query, opts) { + destroyAll (query?, opts?) { return this.crud('destroyAll', query, opts) - }, + } /** * Fired during {@link Mapper#find}. See @@ -1669,6 +1683,7 @@ export default Component.extend({ * @see Mapper~afterFindListener * @see Mapper#find */ + /** * Callback signature for the {@link Mapper#event:afterFind} event. * @@ -1722,9 +1737,9 @@ export default Component.extend({ * @since 3.0.0 * @tutorial ["http://www.js-data.io/v3.0/docs/reading-data","Reading data"] */ - find (id, opts) { + find (id: string | number, opts?) { return this.crud('find', id, opts) - }, + } /** * Fired during {@link Mapper#findAll}. See @@ -1758,6 +1773,7 @@ export default Component.extend({ * @see Mapper~afterFindAllListener * @see Mapper#findAll */ + /** * Callback signature for the {@link Mapper#event:afterFindAll} event. * @@ -1815,9 +1831,9 @@ export default Component.extend({ * @since 3.0.0 * @tutorial ["http://www.js-data.io/v3.0/docs/reading-data","Reading data"] */ - findAll (query, opts) { + findAll (query, opts?) { return this.crud('findAll', query, opts) - }, + } /** * Return the registered adapter with the given name or the default adapter if @@ -1829,14 +1845,14 @@ export default Component.extend({ * @since 3.0.0 * @tutorial ["http://www.js-data.io/v3.0/docs/connecting-to-a-data-source","Connecting to a data source"] */ - getAdapter (name) { + getAdapter (name?: string) { this.dbg('getAdapter', 'name:', name) const adapter = this.getAdapterName(name) if (!adapter) { throw utils.err(`${DOMAIN}#getAdapter`, 'name')(400, 'string', name) } return this.getAdapters()[adapter] - }, + } /** * Return the name of a registered adapter based on the given name or options, @@ -1848,13 +1864,12 @@ export default Component.extend({ * @since 3.0.0 * @tutorial ["http://www.js-data.io/v3.0/docs/connecting-to-a-data-source","Connecting to a data source"] */ - getAdapterName (opts) { - opts || (opts = {}) + getAdapterName (opts: any = {}) { if (utils.isString(opts)) { opts = { adapter: opts } } return opts.adapter || opts.defaultAdapter - }, + } /** * Get the object of registered adapters for this Mapper. @@ -1866,7 +1881,7 @@ export default Component.extend({ */ getAdapters () { return this._adapters - }, + } /** * Returns this Mapper's {@link Schema}. @@ -1878,7 +1893,7 @@ export default Component.extend({ */ getSchema () { return this.schema - }, + } /** * Defines a hasMany relationship. Only useful if you're managing your @@ -1898,7 +1913,7 @@ export default Component.extend({ */ hasMany (relatedMapper, opts) { return hasMany(relatedMapper, opts)(this) - }, + } /** * Defines a hasOne relationship. Only useful if you're managing your Mappers @@ -1918,7 +1933,7 @@ export default Component.extend({ */ hasOne (relatedMapper, opts) { return hasOne(relatedMapper, opts)(this) - }, + } /** * Return whether `record` is an instance of this Mapper's recordClass. @@ -1939,7 +1954,7 @@ export default Component.extend({ is (record) { const recordClass = this.recordClass return recordClass ? record instanceof recordClass : false - }, + } /** * Register an adapter on this Mapper under the given name. @@ -1953,21 +1968,21 @@ export default Component.extend({ * @since 3.0.0 * @tutorial ["http://www.js-data.io/v3.0/docs/connecting-to-a-data-source","Connecting to a data source"] */ - registerAdapter (name, adapter, opts) { - opts || (opts = {}) + registerAdapter (name, adapter, opts: any = {}) { this.getAdapters()[name] = adapter // Optionally make it the default adapter for the target. if (opts === true || opts.default) { this.defaultAdapter = name } - }, + } _runHook (hookName, ...hookArgs) { const defaultValueIndex = hookName.indexOf('after') === 0 ? hookArgs.length - 1 : 0 - return utils.resolve(this[hookName](...hookArgs)) - .then((overridenResult) => overridenResult === undefined ? hookArgs[defaultValueIndex] : overridenResult) - }, + return utils + .resolve(this[hookName](...hookArgs)) + .then(overridenResult => (overridenResult === undefined ? hookArgs[defaultValueIndex] : overridenResult)) + } _invokeAdapterMethod (method, propsOrRecords, opts) { const conversionOptions = { with: opts.pass || [] } @@ -1982,7 +1997,7 @@ export default Component.extend({ } return this.getAdapter(opts.adapter)[method](this, object, opts) - }, + } /** * Select records according to the `query` argument, and aggregate the sum @@ -2012,9 +2027,9 @@ export default Component.extend({ * @returns {Promise} Resolves with the aggregated sum. * @since 3.0.0 */ - sum (field, query, opts) { + sum (field, query: QueryDefinition, opts?) { return this.crud('sum', field, query, opts) - }, + } /** * Return a plain object representation of the given record. Relations can @@ -2060,11 +2075,10 @@ export default Component.extend({ * @returns {Object|Object[]} POJO representation of the record or records. * @since 3.0.0 */ - toJSON (records, opts) { + toJSON (records, opts: any = {}) { let record - opts || (opts = {}) if (utils.isArray(records)) { - return records.map((record) => this.toJSON(record, opts)) + return records.map(record => this.toJSON(record, opts)) } else { record = records } @@ -2075,7 +2089,7 @@ export default Component.extend({ if (this && this.schema) { json = this.schema.pick(record) } else { - for (var key in record) { + for (const key in record) { if (relationFields.indexOf(key) === -1) { json[key] = utils.plainCopy(record[key]) } @@ -2095,9 +2109,12 @@ export default Component.extend({ if (relationData) { // The actual recursion if (utils.isArray(relationData)) { - def.setLocalField(json, relationData.map((item) => { - return def.getRelation().toJSON(item, optsCopy) - })) + def.setLocalField( + json, + relationData.map(item => { + return def.getRelation().toJSON(item, optsCopy) + }) + ) } else { def.setLocalField(json, def.getRelation().toJSON(relationData, optsCopy)) } @@ -2105,7 +2122,7 @@ export default Component.extend({ }) } return json - }, + } /** * Fired during {@link Mapper#update}. See @@ -2140,6 +2157,7 @@ export default Component.extend({ * @see Mapper~afterUpdateListener * @see Mapper#update */ + /** * Callback signature for the {@link Mapper#event:afterUpdate} event. * @@ -2192,9 +2210,9 @@ export default Component.extend({ * @since 3.0.0 * @tutorial ["http://www.js-data.io/v3.0/docs/saving-data","Saving data"] */ - update (id, props, opts) { + update (id, props, opts?) { return this.crud('update', id, props, opts) - }, + } /** * Fired during {@link Mapper#updateAll}. See @@ -2229,6 +2247,7 @@ export default Component.extend({ * @see Mapper~afterUpdateAllListener * @see Mapper#updateAll */ + /** * Callback signature for the {@link Mapper#event:afterUpdateAll} event. * @@ -2283,9 +2302,9 @@ export default Component.extend({ * @since 3.0.0 * @tutorial ["http://www.js-data.io/v3.0/docs/saving-data","Saving data"] */ - updateAll (props, query, opts) { + updateAll (props, query?: QueryDefinition, opts?) { return this.crud('updateAll', props, query, opts) - }, + } /** * Fired during {@link Mapper#updateMany}. See @@ -2319,6 +2338,7 @@ export default Component.extend({ * @see Mapper~afterUpdateManyListener * @see Mapper#updateMany */ + /** * Callback signature for the {@link Mapper#event:afterUpdateMany} event. * @@ -2368,9 +2388,9 @@ export default Component.extend({ * @since 3.0.0 * @tutorial ["http://www.js-data.io/v3.0/docs/saving-data","Saving data"] */ - updateMany (records, opts) { + updateMany (records, opts?) { return this.crud('updateMany', records, opts) - }, + } /** * Validate the given record or records according to this Mapper's @@ -2401,20 +2421,19 @@ export default Component.extend({ * @returns {Object[]} Array of errors or `undefined` if no errors. * @since 3.0.0 */ - validate (record, opts) { - opts || (opts = {}) + validate (record, opts: any = {}) { const schema = this.getSchema() if (!schema) { return } const _opts = utils.pick(opts, ['existingOnly']) if (utils.isArray(record)) { - const errors = record.map((_record) => schema.validate(_record, utils.pick(_opts, ['existingOnly']))) + const errors = record.map(_record => schema.validate(_record, utils.pick(_opts, ['existingOnly']))) return errors.some(Boolean) ? errors : undefined } return schema.validate(record, _opts) - }, + } /** * Method used to wrap data returned by an adapter with this Mapper's @@ -2456,7 +2475,7 @@ export default Component.extend({ */ wrap (data, opts) { return this.createRecord(data, opts) - }, + } /** * @ignore @@ -2469,7 +2488,7 @@ export default Component.extend({ if (utils.isObject(relations)) { relations = [relations] } - relations.forEach((def) => { + relations.forEach(def => { const relatedMapper = this.datastore.getMapperByName(_name) || _name def.getRelation = () => this.datastore.getMapper(_name) @@ -2482,7 +2501,7 @@ export default Component.extend({ }) }) } -}) +} /** * Create a subclass of this Mapper: diff --git a/src/Query.js b/src/Query.ts similarity index 88% rename from src/Query.js rename to src/Query.ts index 7d9dd87e..8034733a 100644 --- a/src/Query.js +++ b/src/Query.ts @@ -11,17 +11,29 @@ const reserved = { orderBy: '', skip: '', sort: '', - where: '' + where: '', + locale: '' } // Used by our JavaScript implementation of the LIKE operator const escapeRegExp = /([.*+?^=!:${}()|[\]/\\])/g const percentRegExp = /%/g const underscoreRegExp = /_/g -const escape = function (pattern) { + +function escape (pattern) { return pattern.replace(escapeRegExp, '\\$1') } +export interface QueryDefinition { + [attr: string]: any + where?: any + orderBy?: any + sort?: any + skip?: number + limit?: number + offset?: number +} + /** * A class used by the {@link Collection} class to build queries to be executed * against the collection's data. An instance of `Query` is returned by @@ -55,18 +67,7 @@ const escape = function (pattern) { * @param {Collection} collection The collection on which this query operates. * @since 3.0.0 */ -function Query (collection) { - utils.classCallCheck(this, Query) - - /** - * The {@link Collection} on which this query operates. - * - * @name Query#collection - * @since 3.0.0 - * @type {Collection} - */ - this.collection = collection - +export default class Query extends Component { /** * The current data result of this query. * @@ -74,11 +75,11 @@ function Query (collection) { * @since 3.0.0 * @type {Array} */ - this.data = null -} + private data = null; -export default Component.extend({ - constructor: Query, + constructor (public collection?) { + super() + } _applyWhereFromObject (where) { const fields = [] @@ -101,10 +102,10 @@ export default Component.extend({ ops, predicates } - }, + } _applyWhereFromArray (where) { - const groups = [] + const groups: any = [] where.forEach((_where, i) => { if (utils.isString(_where)) { return @@ -119,7 +120,7 @@ export default Component.extend({ }) groups.isArray = true return groups - }, + } _testObjectGroup (keep, first, group, item) { let i @@ -133,12 +134,12 @@ export default Component.extend({ op = isOr ? op.substr(1) : op const expr = this.evaluate(utils.get(item, fields[i]), op, predicates[i]) if (expr !== undefined) { - keep = first ? expr : (isOr ? keep || expr : keep && expr) + keep = first ? expr : isOr ? keep || expr : keep && expr } first = false } return { keep, first } - }, + } _testArrayGroup (keep, first, groups, item) { let i @@ -159,7 +160,7 @@ export default Component.extend({ first = result.first } return { keep, first } - }, + } /** * Find all entities between two boundaries. @@ -221,14 +222,13 @@ export default Component.extend({ * @returns {Query} A reference to itself for chaining. * @since 3.0.0 */ - between (leftKeys, rightKeys, opts) { - opts || (opts = {}) + between (leftKeys?, rightKeys?, opts: any = {}) { if (this.data) { throw utils.err(`${DOMAIN}#between`)(500, 'Cannot access index') } this.data = this.collection.getIndex(opts.index).between(leftKeys, rightKeys, opts) return this - }, + } /** * The comparison function used by the {@link Query} class. @@ -242,7 +242,7 @@ export default Component.extend({ * 1 if `a` should preceed `b`. * @since 3.0.0 */ - compare (orderBy, index, a, b) { + compare (orderBy, index, a, b, compare) { const def = orderBy[index] let cA = utils.get(a, def[0]) let cB = utils.get(b, def[0]) @@ -263,18 +263,22 @@ export default Component.extend({ cB = cA cA = temp } - if (cA < cB) { - return -1 - } else if (cA > cB) { - return 1 + /* Fix: compare by using collator */ + // let isNumeric = false + // if (utils.isNumber(cA) || utils.isNumber(cB)) { + // isNumeric = true + // } + const n = compare(cA, cB) + if (n === -1 || n === 1) { + return n } else { if (index < orderBy.length - 1) { - return this.compare(orderBy, index + 1, a, b) + return this.compare(orderBy, index + 1, a, b, compare) } else { return 0 } } - }, + } /** * Predicate evaluation function used by the {@link Query} class. @@ -287,7 +291,7 @@ export default Component.extend({ * @since 3.0.0 */ evaluate (value, op, predicate) { - const ops = this.constructor.ops + const ops = Query.ops if (ops[op]) { return ops[op](value, predicate) } @@ -296,7 +300,7 @@ export default Component.extend({ } else if (op.indexOf('notLike') === 0) { return this.like(predicate, op.substr(7)).exec(value) === null } - }, + } /** * Find the record or records that match the provided query or are accepted by @@ -345,14 +349,14 @@ export default Component.extend({ * .run(); * * @method Query#filter - * @param {(Object|Function)} [queryOrFn={}] Selection query or filter + * @param {(Object|Function)} [query={}] Selection query or filter * function. * @param {Function} [thisArg] Context to which to bind `queryOrFn` if * `queryOrFn` is a function. * @returns {Query} A reference to itself for chaining. * @since 3.0.0 */ - filter (query, thisArg) { + filter (query: QueryDefinition = {}, thisArg?: Function): Query { /** * Selection query as defined by JSData's [Query Syntax][querysyntax]. * @@ -437,10 +441,10 @@ export default Component.extend({ * @property {number} [skip] Alias for {@link query.offset}. * @property {string|Array[]} [sort] Alias for {@link query.orderBy}. * @property {Object} [where] See {@link query.where}. + * @property {String} [locale] See {@link query.locale}. * @since 3.0.0 * @tutorial ["http://www.js-data.io/v3.0/docs/query-syntax","JSData's Query Syntax"] */ - query || (query = {}) this.getData() if (utils.isObject(query)) { let where = {} @@ -481,7 +485,7 @@ export default Component.extend({ if (utils.isObject(query.where) || utils.isArray(query.where)) { where = query.where } - utils.forOwn(query, function (value, key) { + utils.forOwn(query, (value, key) => { if (!(key in reserved) && !(key in where)) { where[key] = { '==': value @@ -498,16 +502,14 @@ export default Component.extend({ } if (groups) { - this.data = this.data.filter((item, i) => this._testArrayGroup(true, true, groups, item).keep) + this.data = this.data.filter(item => this._testArrayGroup(true, true, groups, item).keep) } // Sort let orderBy = query.orderBy || query.sort if (utils.isString(orderBy)) { - orderBy = [ - [orderBy, 'ASC'] - ] + orderBy = [[orderBy, 'ASC']] } if (!utils.isArray(orderBy)) { orderBy = null @@ -543,12 +545,48 @@ export default Component.extend({ */ if (orderBy) { const index = 0 - orderBy.forEach(function (def, i) { + orderBy.forEach((def, i) => { if (utils.isString(def)) { orderBy[i] = [def, 'ASC'] } }) - this.data.sort((a, b) => this.compare(orderBy, index, a, b)) + let locale: string = utils.getDefaultLocale() + if (utils.isString(query.locale)) { + locale = query.locale + } + /** The locale params has to be explicitly set for the collator.compare to work. + * + * @example Order posts with specific locale, defaults to 'en' + * const JSData = require('js-data'); + * const { DataStore } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new DataStore(); + * store.defineMapper('post') + * const posts = [ + * { author: 'คลอน', age: 30, id: 5 }, + * { author: 'กลอน', age: 31, id: 6 }, + * { author: 'สาระ', age: 32, id: 7 }, + * { author: 'ศาลา', age: 33, id: 8 }, + * { author: 'จักรพรรณ', age: 33, id: 9 } + * ]; + * store.add('post', posts); + * const results = store.filter('post', { + * orderBy:[['author','ASC'],['id','DESC']], + * locale: 'th' + * }); + * console.log(results); + * + * @name query.locale + * @type {string} + * @see http://www.js-data.io/v4.0/docs/query-syntax + * @since 4.0.0 + */ + const collator = new Intl.Collator(locale, { + numeric: true + }) + + this.data.sort((a, b) => this.compare(orderBy, index, a, b, collator.compare)) } /** @@ -667,7 +705,7 @@ export default Component.extend({ this.data = this.data.filter(query, thisArg) } return this - }, + } /** * Iterate over all entities. @@ -678,10 +716,10 @@ export default Component.extend({ * @returns {Query} A reference to itself for chaining. * @since 3.0.0 */ - forEach (forEachFn, thisArg) { + forEach (forEachFn: Function, thisArg?) { this.getData().forEach(forEachFn, thisArg) return this - }, + } /** * Find the entity or entities that match the provided key. @@ -712,9 +750,7 @@ export default Component.extend({ * @returns {Query} A reference to itself for chaining. * @since 3.0.0 */ - get (keyList, opts) { - keyList || (keyList = []) - opts || (opts = {}) + get (keyList = [], opts: any = {}) { if (this.data) { throw utils.err(`${DOMAIN}#get`)(500, INDEX_ERR) } @@ -727,7 +763,7 @@ export default Component.extend({ } this.data = this.collection.getIndex(opts.index).get(keyList) return this - }, + } /** * Find the entity or entities that match the provided keyLists. @@ -748,8 +784,9 @@ export default Component.extend({ * @returns {Query} A reference to itself for chaining. * @since 3.0.0 */ + getAll(keyList?: [], opts?); getAll (...args) { - let opts = {} + let opts: any = {} if (this.data) { throw utils.err(`${DOMAIN}#getAll`)(500, INDEX_ERR) } @@ -760,14 +797,13 @@ export default Component.extend({ opts = args[args.length - 1] args.pop() } - const collection = this.collection - const index = collection.getIndex(opts.index) + const index = this.collection.getIndex(opts.index) this.data = [] - args.forEach((keyList) => { + args.forEach(keyList => { this.data = this.data.concat(index.get(keyList)) }) return this - }, + } /** * Return the current data result of this query. @@ -781,7 +817,7 @@ export default Component.extend({ this.data = this.collection.index.getAll() } return this.data - }, + } /** * Implementation used by the `like` operator. Takes a pattern and flags and @@ -794,8 +830,13 @@ export default Component.extend({ * @since 3.0.0 */ like (pattern, flags) { - return new RegExp(`^${(escape(pattern).replace(percentRegExp, '.*').replace(underscoreRegExp, '.'))}$`, flags) - }, + return new RegExp( + `^${escape(pattern) + .replace(percentRegExp, '.*') + .replace(underscoreRegExp, '.')}$`, + flags + ) + } /** * Limit the result. @@ -826,7 +867,7 @@ export default Component.extend({ const data = this.getData() this.data = data.slice(0, Math.min(data.length, num)) return this - }, + } /** * Apply a mapping function to the result data. @@ -860,10 +901,10 @@ export default Component.extend({ * @returns {Query} A reference to itself for chaining. * @since 3.0.0 */ - map (mapFn, thisArg) { + map (mapFn, thisArg?) { this.data = this.getData().map(mapFn, thisArg) return this - }, + } /** * Return the result of calling the specified function on each item in this @@ -874,16 +915,14 @@ export default Component.extend({ * * @method Query#mapCall * @param {string} funcName Name of function to call - * @parama {...*} [args] Remaining arguments to be passed to the function. + * @param args Remaining arguments to be passed to the function. * @returns {Query} A reference to itself for chaining. * @since 3.0.0 */ mapCall (funcName, ...args) { - this.data = this.getData().map(function (item) { - return item[funcName](...args) - }) + this.data = this.getData().map(item => item[funcName](...args)) return this - }, + } /** * Complete the execution of the query and return the resulting data. @@ -896,7 +935,7 @@ export default Component.extend({ const data = this.data this.data = null return data - }, + } /** * Skip a number of results. @@ -936,7 +975,7 @@ export default Component.extend({ } return this } -}, { + /** * The filtering operators supported by {@link Query#filter}, and which are * implemented by adapters (for the most part). @@ -1089,103 +1128,54 @@ export default Component.extend({ * @since 3.0.0 * @type {Object} */ - ops: { - '=': function (value, predicate) { - return value == predicate // eslint-disable-line + static ops = { + '=' (value, predicate) { + // tslint:disable-next-line:triple-equals + return value == predicate; // eslint-disable-line }, - '==': function (value, predicate) { - return value == predicate // eslint-disable-line + '==' (value, predicate) { + // tslint:disable-next-line:triple-equals + return value == predicate; // eslint-disable-line }, - '===': function (value, predicate) { + '===' (value, predicate) { return value === predicate }, - '!=': function (value, predicate) { - return value != predicate // eslint-disable-line + '!=' (value, predicate) { + // tslint:disable-next-line:triple-equals + return value != predicate; // eslint-disable-line }, - '!==': function (value, predicate) { + '!==' (value, predicate) { return value !== predicate }, - '>': function (value, predicate) { + '>' (value, predicate) { return value > predicate }, - '>=': function (value, predicate) { + '>=' (value, predicate) { return value >= predicate }, - '<': function (value, predicate) { + '<' (value, predicate) { return value < predicate }, - '<=': function (value, predicate) { + '<=' (value, predicate) { return value <= predicate }, - isectEmpty: function (value, predicate) { - return !utils.intersection((value || []), (predicate || [])).length + isectEmpty (value, predicate) { + return !utils.intersection(value || [], predicate || []).length }, - isectNotEmpty: function (value, predicate) { - return utils.intersection((value || []), (predicate || [])).length + isectNotEmpty (value, predicate) { + return utils.intersection(value || [], predicate || []).length }, - in: function (value, predicate) { + in (value, predicate) { return predicate.indexOf(value) !== -1 }, - notIn: function (value, predicate) { + notIn (value, predicate) { return predicate.indexOf(value) === -1 }, - contains: function (value, predicate) { + contains (value, predicate) { return (value || []).indexOf(predicate) !== -1 }, - notContains: function (value, predicate) { + notContains (value, predicate) { return (value || []).indexOf(predicate) === -1 } - } -}) - -/** - * Create a subclass of this Query: - * @example Query.extend - * const JSData = require('js-data'); - * const { Query } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * // Extend the class using ES2015 class syntax. - * class CustomQueryClass extends Query { - * foo () { return 'bar'; } - * static beep () { return 'boop'; } - * } - * const customQuery = new CustomQueryClass(); - * console.log(customQuery.foo()); - * console.log(CustomQueryClass.beep()); - * - * // Extend the class using alternate method. - * const OtherQueryClass = Query.extend({ - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }); - * const otherQuery = new OtherQueryClass(); - * console.log(otherQuery.foo()); - * console.log(OtherQueryClass.beep()); - * - * // Extend the class, providing a custom constructor. - * function AnotherQueryClass (collection) { - * Query.call(this, collection); - * this.created_at = new Date().getTime(); - * } - * Query.extend({ - * constructor: AnotherQueryClass, - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }); - * const anotherQuery = new AnotherQueryClass(); - * console.log(anotherQuery.created_at); - * console.log(anotherQuery.foo()); - * console.log(AnotherQueryClass.beep()); - * - * @method Query.extend - * @param {object} [props={}] Properties to add to the prototype of the - * subclass. - * @param {object} [props.constructor] Provide a custom constructor function - * to be used as the subclass itself. - * @param {object} [classProps={}] Static properties to add to the subclass. - * @returns {Constructor} Subclass of this Query class. - * @since 3.0.0 - */ + }; +} diff --git a/src/Record.js b/src/Record.ts similarity index 83% rename from src/Record.js rename to src/Record.ts index 0a55ce10..a61c855d 100644 --- a/src/Record.js +++ b/src/Record.ts @@ -1,19 +1,14 @@ import utils, { safeSetLink } from './utils' -import Component from './Component' import Settable from './Settable' -import { - hasManyType, - hasOneType -} from './decorators' +import { hasManyType, hasOneType } from './Relation' +import Mapper from './Mapper' const DOMAIN = 'Record' -const superMethod = function (mapper, name) { +function superMethod (mapper, name) { const store = mapper.datastore - if (store && store[name]) { - return function (...args) { - return store[name](mapper.name, ...args) - } + if (store?.[name]) { + return (...args) => store[name](mapper.name, ...args) } return mapper[name].bind(mapper) } @@ -110,7 +105,7 @@ const previousPath = 'previous' * console.log('user.isValid(): ' + user.isValid()); * * @class Record - * @extends Component + * @extends Settable * @param {object} [props] The initial properties of the new Record instance. * @param {object} [opts] Configuration options. * @param {boolean} [opts.noValidate=false] Whether to skip validation on the @@ -119,38 +114,38 @@ const previousPath = 'previous' * validation on properties after the Record has been initialized. * @since 3.0.0 */ -function Record (props, opts) { - utils.classCallCheck(this, Record) - Settable.call(this) - props || (props = {}) - opts || (opts = {}) - const _set = this._set - const mapper = this.constructor.mapper - - _set(creatingPath, true) - _set(noValidatePath, !!opts.noValidate) - _set(keepChangeHistoryPath, opts.keepChangeHistory === undefined ? (mapper ? mapper.keepChangeHistory : true) : opts.keepChangeHistory) - - // Set the idAttribute value first, if it exists. - const id = mapper ? utils.get(props, mapper.idAttribute) : undefined - if (id !== undefined) { - utils.set(this, mapper.idAttribute, id) - } +export default class Record extends Settable { + static mapper: Mapper; + + constructor (props: any = {}, opts: any = {}) { + super() + const _set = this._set + const mapper = (this.constructor as any).mapper + + _set(creatingPath, true) + _set(noValidatePath, !!opts.noValidate) + _set( + keepChangeHistoryPath, + opts.keepChangeHistory === undefined ? (mapper ? mapper.keepChangeHistory : true) : opts.keepChangeHistory + ) + + // Set the idAttribute value first, if it exists. + const id = mapper ? utils.get(props, mapper.idAttribute) : undefined + if (id !== undefined) { + utils.set(this, mapper.idAttribute, id) + } - utils.fillIn(this, props) - _set(creatingPath, false) - if (opts.validateOnSet !== undefined) { - _set(noValidatePath, !opts.validateOnSet) - } else if (mapper && mapper.validateOnSet !== undefined) { - _set(noValidatePath, !mapper.validateOnSet) - } else { - _set(noValidatePath, false) + utils.fillIn(this, props) + _set(creatingPath, false) + if (opts.validateOnSet !== undefined) { + _set(noValidatePath, !opts.validateOnSet) + } else if (mapper?.validateOnSet !== undefined) { + _set(noValidatePath, !mapper.validateOnSet) + } else { + _set(noValidatePath, false) + } + _set(previousPath, mapper ? mapper.toJSON(props) : utils.plainCopy(props)) } - _set(previousPath, mapper ? mapper.toJSON(props) : utils.plainCopy(props)) -} - -export default Component.extend({ - constructor: Record, /** * Returns the {@link Mapper} paired with this record's class, if any. @@ -160,12 +155,12 @@ export default Component.extend({ * @since 3.0.0 */ _mapper () { - const mapper = this.constructor.mapper + const mapper = (this.constructor as any).mapper if (!mapper) { throw utils.err(`${DOMAIN}#_mapper`, '')(404, 'mapper') } return mapper - }, + } /** * Lifecycle hook. @@ -175,7 +170,7 @@ export default Component.extend({ * @param {object} opts The `opts` argument passed to {@link Record#loadRelations}. * @since 3.0.0 */ - afterLoadRelations () {}, + afterLoadRelations (relations: string[], opts?) {} /** * Lifecycle hook. @@ -185,7 +180,7 @@ export default Component.extend({ * @param {object} opts The `opts` argument passed to {@link Record#loadRelations}. * @since 3.0.0 */ - beforeLoadRelations () {}, + beforeLoadRelations (relations: string[], opts?) {} /** * Return the change history of this record since it was instantiated or @@ -196,7 +191,7 @@ export default Component.extend({ */ changeHistory () { return (this._get('history') || []).slice() - }, + } /** * Return changes to this record since it was instantiated or @@ -222,10 +217,9 @@ export default Component.extend({ * instantiated or its {@link Record#commit} method was last called. * @since 3.0.0 */ - changes (opts) { - opts || (opts = {}) + changes (opts: any = {}) { return utils.diffObjects(typeof this.toJSON === 'function' ? this.toJSON(opts) : this, this._get('previous'), opts) - }, + } /** * Make the record's current in-memory state it's only state, with any @@ -249,12 +243,12 @@ export default Component.extend({ * @param {object} [opts] Configuration options. Passed to {@link Record#toJSON}. * @since 3.0.0 */ - commit (opts) { + commit (opts?) { this._set('changed') // unset this._set('changing', false) this._set('history', []) // clear history this._set('previous', this.toJSON(opts)) - }, + } /** * Call {@link Mapper#destroy} using this record's primary key. @@ -279,11 +273,10 @@ export default Component.extend({ * primary key of this record. * @since 3.0.0 */ - destroy (opts) { - opts || (opts = {}) + destroy (opts: any = {}) { const mapper = this._mapper() return superMethod(mapper, 'destroy')(utils.get(this, mapper.idAttribute), opts) - }, + } /** * Return the value at the given path for this instance. @@ -303,9 +296,9 @@ export default Component.extend({ * @returns {*} Value at path. * @since 3.0.0 */ - 'get' (key) { + get (key) { return utils.get(this, key) - }, + } /** * Return whether this record has changed since it was instantiated or @@ -332,10 +325,13 @@ export default Component.extend({ * instantiated or since its {@link Record#commit} method was called. * @since 3.0.0 */ - hasChanges (opts) { + hasChanges (opts?) { const quickHasChanges = !!(this._get('changed') || []).length - return quickHasChanges || utils.areDifferent(typeof this.toJSON === 'function' ? this.toJSON(opts) : this, this._get('previous'), opts) - }, + return ( + quickHasChanges || + utils.areDifferent(typeof this.toJSON === 'function' ? this.toJSON(opts) : this, this._get('previous'), opts) + ) + } /** * Return whether the record is unsaved. Records that have primary keys are @@ -358,9 +354,9 @@ export default Component.extend({ * @returns {boolean} Whether the record is unsaved. * @since 3.0.0 */ - isNew (opts) { + isNew (opts?) { return utils.get(this, this._mapper().idAttribute) === undefined - }, + } /** * Return whether the record in its current state passes validation. @@ -394,7 +390,7 @@ export default Component.extend({ */ isValid (opts) { return !this._mapper().validate(this, opts) - }, + } removeInverseRelation (currentParent, id, inverseDef, idAttribute) { if (inverseDef.type === hasOneType) { @@ -403,12 +399,12 @@ export default Component.extend({ // e.g. remove comment from otherPost.comments const children = utils.get(currentParent, inverseDef.localField) if (id === undefined) { - utils.remove(children, (child) => child === this) + utils.remove(children, child => child === this) } else { - utils.remove(children, (child) => child === this || id === utils.get(child, idAttribute)) + utils.remove(children, child => child === this || id === utils.get(child, idAttribute)) } } - }, + } setupInverseRelation (record, id, inverseDef, idAttribute) { // Update (set) inverse relation @@ -419,12 +415,12 @@ export default Component.extend({ // e.g. add comment to somePost.comments const children = utils.get(record, inverseDef.localField) if (id === undefined) { - utils.noDupeAdd(children, this, (child) => child === this) + utils.noDupeAdd(children, this, child => child === this) } else { - utils.noDupeAdd(children, this, (child) => child === this || id === utils.get(child, idAttribute)) + utils.noDupeAdd(children, this, child => child === this || id === utils.get(child, idAttribute)) } } - }, + } /** * Lazy load relations of this record, to be attached to the record once their @@ -473,16 +469,13 @@ export default Component.extend({ * attached. * @since 3.0.0 */ - loadRelations (relations, opts) { + loadRelations (relations: string[] | string | any = [], opts: any = {}) { let op const mapper = this._mapper() - // Default values for arguments - relations || (relations = []) if (utils.isString(relations)) { relations = [relations] } - opts || (opts = {}) opts.with = relations // Fill in "opts" with the Model's configuration @@ -491,64 +484,73 @@ export default Component.extend({ // beforeLoadRelations lifecycle hook op = opts.op = 'beforeLoadRelations' - return utils.resolve(this[op](relations, opts)).then(() => { - // Now delegate to the adapter - op = opts.op = 'loadRelations' - mapper.dbg(op, this, relations, opts) - const tasks = [] - let task - utils.forEachRelation(mapper, opts, (def, optsCopy) => { - const relatedMapper = def.getRelation() - optsCopy.raw = false - if (utils.isFunction(def.load)) { - task = def.load(mapper, def, this, opts) - } else if (def.type === 'hasMany' || def.type === 'hasOne') { - if (def.foreignKey) { - task = superMethod(relatedMapper, 'findAll')({ - [def.foreignKey]: utils.get(this, mapper.idAttribute) - }, optsCopy).then(function (relatedData) { - if (def.type === 'hasOne') { - return relatedData.length ? relatedData[0] : undefined - } - return relatedData - }) - } else if (def.localKeys) { - task = superMethod(relatedMapper, 'findAll')({ - where: { - [relatedMapper.idAttribute]: { - in: utils.get(this, def.localKeys) + return utils + .resolve(this[op](relations, opts)) + .then(() => { + // Now delegate to the adapter + op = opts.op = 'loadRelations' + mapper.dbg(op, this, relations, opts) + const tasks = [] + let task + utils.forEachRelation(mapper, opts, (def, optsCopy) => { + const relatedMapper = def.getRelation() + optsCopy.raw = false + if (utils.isFunction(def.load)) { + task = def.load(mapper, def, this, opts) + } else if (def.type === 'hasMany' || def.type === 'hasOne') { + if (def.foreignKey) { + task = superMethod(relatedMapper, 'findAll')( + { + [def.foreignKey]: utils.get(this, mapper.idAttribute) + }, + optsCopy + ).then(relatedData => + def.type === 'hasOne' ? (relatedData.length ? relatedData[0] : undefined) : relatedData + ) + } else if (def.localKeys) { + task = superMethod( + relatedMapper, + 'findAll' + )({ + where: { + [relatedMapper.idAttribute]: { + in: utils.get(this, def.localKeys) + } } - } - }) - } else if (def.foreignKeys) { - task = superMethod(relatedMapper, 'findAll')({ - where: { - [def.foreignKeys]: { - contains: utils.get(this, mapper.idAttribute) - } - } - }, opts) + }) + } else if (def.foreignKeys) { + task = superMethod(relatedMapper, 'findAll')( + { + where: { + [def.foreignKeys]: { + contains: utils.get(this, mapper.idAttribute) + } + } + }, + opts + ) + } + } else if (def.type === 'belongsTo') { + const key = utils.get(this, def.foreignKey) + if (utils.isSorN(key)) { + task = superMethod(relatedMapper, 'find')(key, optsCopy) + } } - } else if (def.type === 'belongsTo') { - const key = utils.get(this, def.foreignKey) - if (utils.isSorN(key)) { - task = superMethod(relatedMapper, 'find')(key, optsCopy) + if (task) { + task = task.then(relatedData => { + def.setLocalField(this, relatedData) + }) + tasks.push(task) } - } - if (task) { - task = task.then((relatedData) => { - def.setLocalField(this, relatedData) - }) - tasks.push(task) - } + }) + return Promise.all(tasks) }) - return Promise.all(tasks) - }).then(() => { - // afterLoadRelations lifecycle hook - op = opts.op = 'afterLoadRelations' - return utils.resolve(this[op](relations, opts)).then(() => this) - }) - }, + .then(() => { + // afterLoadRelations lifecycle hook + op = opts.op = 'afterLoadRelations' + return utils.resolve(this[op](relations, opts)).then(() => this) + }) + } /** * Return the properties with which this record was instantiated. @@ -579,7 +581,7 @@ export default Component.extend({ return this._get(`previous.${key}`) } return this._get('previous') - }, + } /** * Revert changes to this record back to the properties it had when it was @@ -606,12 +608,16 @@ export default Component.extend({ * denoting properties that should not be reverted. * @since 3.0.0 */ - revert (opts) { + revert (opts: any = {}) { const previous = this._get('previous') - opts || (opts = {}) - opts.preserve || (opts.preserve = []) + opts.preserve = opts.preserve || [] utils.forOwn(this, (value, key) => { - if (key !== this._mapper().idAttribute && !Object.hasOwnProperty.call(previous, key) && Object.hasOwnProperty.call(this, key) && opts.preserve.indexOf(key) === -1) { + if ( + key !== this._mapper().idAttribute && + !previous.hasOwnProperty(key) && + this.hasOwnProperty(key) && + opts.preserve.indexOf(key) === -1 + ) { delete this[key] } }) @@ -621,7 +627,7 @@ export default Component.extend({ } }) this.commit() - }, + } /** * Delegates to {@link Mapper#create} or {@link Mapper#update}. @@ -657,13 +663,12 @@ export default Component.extend({ * {@link Mapper#update}. * @since 3.0.0 */ - save (opts) { - opts || (opts = {}) + save (opts: any = {}) { const mapper = this._mapper() const id = utils.get(this, mapper.idAttribute) - let props = this + let props: any = this - const postProcess = (result) => { + const postProcess = result => { const record = opts.raw ? result.data : result if (record) { utils.deepMixIn(this, record) @@ -682,7 +687,7 @@ export default Component.extend({ utils.fillIn(props, changes.changed) } return superMethod(mapper, 'update')(id, props, opts).then(postProcess) - }, + } /** * Set the value for a given key, or the values for the given keys if "key" is @@ -713,11 +718,11 @@ export default Component.extend({ * @param {boolean} [opts.silent=false] Whether to trigger change events. * @since 3.0.0 */ - 'set' (key, value, opts) { + set (key: string | any, value?, opts?) { if (utils.isObject(key)) { opts = value } - opts || (opts = {}) + opts = opts || {} if (opts.silent) { this._set('silent', true) } @@ -725,7 +730,7 @@ export default Component.extend({ if (!this._get('eventId')) { this._set('silent') // unset } - }, + } /** * Return a plain object representation of this record. If the class from @@ -760,8 +765,8 @@ export default Component.extend({ * @returns {Object} Plain object representation of this record. * @since 3.0.0 */ - toJSON (opts) { - const mapper = this.constructor.mapper + toJSON (opts?) { + const mapper = (this.constructor as typeof Record).mapper if (mapper) { return mapper.toJSON(this, opts) } else { @@ -771,7 +776,7 @@ export default Component.extend({ }) return json } - }, + } /** * Unset the value for a given key. Triggers change events on those properties @@ -798,9 +803,9 @@ export default Component.extend({ * @param {boolean} [opts.silent=false] Whether to trigger change events. * @since 3.0.0 */ - unset (key, opts) { + unset (key: string, opts?) { this.set(key, undefined, opts) - }, + } /** * Validate this record based on its current properties. @@ -834,12 +839,12 @@ export default Component.extend({ validate (opts) { return this._mapper().validate(this, opts) } -}, { - creatingPath, - noValidatePath, - keepChangeHistoryPath, - previousPath -}) + + static creatingPath = creatingPath; + static noValidatePath = noValidatePath; + static keepChangeHistoryPath = keepChangeHistoryPath; + static previousPath = previousPath; +} /** * Allow records to emit events. diff --git a/src/Relation.js b/src/Relation.ts similarity index 78% rename from src/Relation.js rename to src/Relation.ts index 798142aa..1e91f381 100644 --- a/src/Relation.js +++ b/src/Relation.ts @@ -7,30 +7,40 @@ export const hasOneType = 'hasOne' const DOMAIN = 'Relation' -export function Relation (relatedMapper, options = {}) { - utils.classCallCheck(this, Relation) +export interface RelationOpts { + type?: string +} - options.type = this.constructor.TYPE_NAME - this.validateOptions(relatedMapper, options) +export abstract class Relation { + protected TYPE_NAME = DOMAIN; + protected add; + protected mapper; + protected relation; + name: string; + private readonly localField; + private readonly localKey; + protected foreignKey; + protected relatedMapper; + protected inverse; + + constructor (relatedMapper, options: RelationOpts = {}) { + options.type = (this.constructor as any).TYPE_NAME + this.validateOptions(relatedMapper, options) + + if (typeof relatedMapper === 'object') { + this.relatedMapper = relatedMapper + } - if (typeof relatedMapper === 'object') { - Object.defineProperty(this, 'relatedMapper', { value: relatedMapper }) + utils.fillIn(this, options) } - Object.defineProperty(this, 'inverse', { writable: true }) - utils.fillIn(this, options) -} - -Relation.extend = utils.extend - -utils.addHiddenPropsToTarget(Relation.prototype, { get canAutoAddLinks () { return this.add === undefined || !!this.add - }, + } get relatedCollection () { return this.mapper.datastore.getCollection(this.relation) - }, + } validateOptions (related, opts) { const DOMAIN_ERR = `new ${DOMAIN}` @@ -40,7 +50,7 @@ utils.addHiddenPropsToTarget(Relation.prototype, { throw utils.err(DOMAIN_ERR, 'opts.localField')(400, 'string', localField) } - const foreignKey = opts.foreignKey = opts.foreignKey || opts.localKey + const foreignKey = (opts.foreignKey = opts.foreignKey || opts.localKey) if (!foreignKey && (opts.type === belongsToType || opts.type === hasOneType)) { throw utils.err(DOMAIN_ERR, 'opts.foreignKey')(400, 'string', foreignKey) } @@ -55,29 +65,29 @@ utils.addHiddenPropsToTarget(Relation.prototype, { } else { throw utils.err(DOMAIN_ERR, 'related')(400, 'Mapper or string', related) } - }, + } assignTo (mapper) { this.name = mapper.name Object.defineProperty(this, 'mapper', { value: mapper }) - mapper.relationList || Object.defineProperty(mapper, 'relationList', { value: [] }) - mapper.relationFields || Object.defineProperty(mapper, 'relationFields', { value: [] }) + if (!mapper.relationList) Object.defineProperty(mapper, 'relationList', { value: [] }) + if (!mapper.relationFields) Object.defineProperty(mapper, 'relationFields', { value: [] }) mapper.relationList.push(this) mapper.relationFields.push(this.localField) - }, + } - canFindLinkFor () { + canFindLinkFor (record?) { return !!(this.foreignKey || this.localKey) - }, + } getRelation () { return this.relatedMapper - }, + } getForeignKey (record) { return utils.get(record, this.mapper.idAttribute) - }, + } setForeignKey (record, relatedRecord) { if (!record || !relatedRecord) { @@ -85,7 +95,7 @@ utils.addHiddenPropsToTarget(Relation.prototype, { } this._setForeignKey(record, relatedRecord) - }, + } _setForeignKey (record, relatedRecords) { const idAttribute = this.mapper.idAttribute @@ -94,18 +104,18 @@ utils.addHiddenPropsToTarget(Relation.prototype, { relatedRecords = [relatedRecords] } - relatedRecords.forEach((relatedRecord) => { + relatedRecords.forEach(relatedRecord => { utils.set(relatedRecord, this.foreignKey, utils.get(record, idAttribute)) }) - }, + } getLocalField (record) { return utils.get(record, this.localField) - }, + } setLocalField (record, relatedData) { return utils.set(record, this.localField, relatedData) - }, + } getInverse (mapper) { if (!this.inverse) { @@ -113,25 +123,25 @@ utils.addHiddenPropsToTarget(Relation.prototype, { } return this.inverse - }, + } findInverseRelation (mapper) { - this.getRelation().relationList.forEach((def) => { + this.getRelation().relationList.forEach(def => { if (def.getRelation() === mapper && this.isInversedTo(def) && this !== def) { this.inverse = def return true } }) - }, + } isInversedTo (def) { return !def.foreignKey || def.foreignKey === this.foreignKey - }, + } addLinkedRecords (records) { const datastore = this.mapper.datastore - records.forEach((record) => { + records.forEach(record => { let relatedData = this.getLocalField(record) if (utils.isFunction(this.add)) { @@ -150,14 +160,14 @@ utils.addHiddenPropsToTarget(Relation.prototype, { this.setLocalField(record, relatedData) } }) - }, + } removeLinkedRecords (relatedMapper, records) { const localField = this.localField - records.forEach((record) => { + records.forEach(record => { utils.set(record, localField, undefined) }) - }, + } linkRecord (record, relatedRecord) { const relatedId = utils.get(relatedRecord, this.mapper.idAttribute) @@ -180,7 +190,7 @@ utils.addHiddenPropsToTarget(Relation.prototype, { } return relatedRecord - }, + } // e.g. user hasMany post via "foreignKey", so find all posts of user findExistingLinksByForeignKey (id) { @@ -190,7 +200,7 @@ utils.addHiddenPropsToTarget(Relation.prototype, { return this.relatedCollection.filter({ [this.foreignKey]: id }) - }, + } ensureLinkedDataHasProperType (props, opts) { const relatedMapper = this.getRelation() @@ -203,27 +213,34 @@ utils.addHiddenPropsToTarget(Relation.prototype, { if (relationData && !relatedMapper.is(relationData)) { utils.set(props, this.localField, relatedMapper.createRecord(relationData, opts)) } - }, + } isRequiresParentId () { return false - }, + } isRequiresChildId () { return false - }, + } createChildRecord (props, relationData, opts) { this.setForeignKey(props, relationData) - return this.createLinked(relationData, opts).then((result) => { + return this.createLinked(relationData, opts).then(result => { this.setLocalField(props, result) }) - }, + } createLinked (props, opts) { const create = utils.isArray(props) ? 'createMany' : 'create' return this.getRelation()[create](props, opts) } -}) + + abstract findExistingLinksFor(relatedMapper, record); + abstract findExistingLinksFor(...record); + + static belongsTo; + static hasMany; + static hasOne; +} diff --git a/src/Relation/BelongsTo.js b/src/Relation/BelongsTo.ts similarity index 83% rename from src/Relation/BelongsTo.js rename to src/Relation/BelongsTo.ts index 9d23df8e..890fa2a0 100644 --- a/src/Relation/BelongsTo.js +++ b/src/Relation/BelongsTo.ts @@ -1,14 +1,14 @@ import utils from '../utils' import { Relation } from '../Relation' -export const BelongsToRelation = Relation.extend({ +export class BelongsToRelation extends Relation { getForeignKey (record) { return utils.get(record, this.foreignKey) - }, + } _setForeignKey (record, relatedRecord) { utils.set(record, this.foreignKey, utils.get(relatedRecord, this.getRelation().idAttribute)) - }, + } findExistingLinksFor (record) { // console.log('\tBelongsTo#findExistingLinksFor', record) @@ -19,23 +19,23 @@ export const BelongsToRelation = Relation.extend({ if (relatedId !== undefined && relatedId !== null) { return this.relatedCollection.get(relatedId) } - }, + } isRequiresParentId () { return true - }, + } createParentRecord (props, opts) { const relationData = this.getLocalField(props) - return this.createLinked(relationData, opts).then((record) => { + return this.createLinked(relationData, opts).then(record => { this.setForeignKey(props, record) }) - }, + } createChildRecord () { throw new Error('"BelongsTo" relation does not support child creation as it cannot have children.') } -}, { - TYPE_NAME: 'belongsTo' -}) + + static TYPE_NAME = 'belongsTo'; +} diff --git a/src/Relation/HasMany.js b/src/Relation/HasMany.ts similarity index 80% rename from src/Relation/HasMany.js rename to src/Relation/HasMany.ts index d60944bd..7e8ecae7 100644 --- a/src/Relation/HasMany.js +++ b/src/Relation/HasMany.ts @@ -1,21 +1,23 @@ import utils from '../utils' import { Relation } from '../Relation' -export const HasManyRelation = Relation.extend({ +export class HasManyRelation extends Relation { + foreignKeys: any; + localKeys: any; validateOptions (related, opts) { - Relation.prototype.validateOptions.call(this, related, opts) + super.validateOptions(related, opts) const { localKeys, foreignKeys, foreignKey } = opts if (!foreignKey && !localKeys && !foreignKeys) { throw utils.err('new Relation', 'opts.')(400, 'string', foreignKey) } - }, + } canFindLinkFor (record) { const hasForeignKeys = this.foreignKey || this.foreignKeys return !!(hasForeignKeys || (this.localKeys && utils.get(record, this.localKeys))) - }, + } linkRecord (record, relatedRecords) { const relatedCollection = this.relatedCollection @@ -23,10 +25,13 @@ export const HasManyRelation = Relation.extend({ const foreignKey = this.foreignKey const unsaved = this.relatedCollection.unsaved() - return relatedRecords.map((relatedRecord) => { + return relatedRecords.map(relatedRecord => { const relatedId = relatedCollection.recordId(relatedRecord) - if ((relatedId === undefined && unsaved.indexOf(relatedRecord) === -1) || relatedRecord !== relatedCollection.get(relatedId)) { + if ( + (relatedId === undefined && unsaved.indexOf(relatedRecord) === -1) || + relatedRecord !== relatedCollection.get(relatedId) + ) { if (foreignKey) { // TODO: slow, could be optimized? But user loses hook this.setForeignKey(record, relatedRecord) @@ -38,7 +43,7 @@ export const HasManyRelation = Relation.extend({ return relatedRecord }) - }, + } findExistingLinksFor (record) { const id = utils.get(record, this.mapper.idAttribute) @@ -53,10 +58,10 @@ export const HasManyRelation = Relation.extend({ records = this.findExistingLinksByForeignKeys(id) } - if (records && records.length) { + if (records?.length) { return records } - }, + } // e.g. user hasMany group via "foreignKeys", so find all users of a group findExistingLinksByLocalKeys (ids) { @@ -67,7 +72,7 @@ export const HasManyRelation = Relation.extend({ } } }) - }, + } // e.g. group hasMany user via "localKeys", so find all groups that own a user findExistingLinksByForeignKeys (id) { @@ -78,28 +83,32 @@ export const HasManyRelation = Relation.extend({ } } }) - }, + } isRequiresParentId () { return !!this.localKeys && this.localKeys.length > 0 - }, + } isRequiresChildId () { return !!this.foreignKey - }, + } createParentRecord (props, opts) { const relationData = this.getLocalField(props) const foreignIdField = this.getRelation().idAttribute - return this.createLinked(relationData, opts).then((records) => { - utils.set(props, this.localKeys, records.map((record) => utils.get(record, foreignIdField))) + return this.createLinked(relationData, opts).then(records => { + utils.set( + props, + this.localKeys, + records.map(record => utils.get(record, foreignIdField)) + ) }) - }, + } createLinked (props, opts) { return this.getRelation().createMany(props, opts) } -}, { - TYPE_NAME: 'hasMany' -}) + + static TYPE_NAME = 'hasMany'; +} diff --git a/src/Relation/HasOne.js b/src/Relation/HasOne.ts similarity index 73% rename from src/Relation/HasOne.js rename to src/Relation/HasOne.ts index d1bb90f1..c8aaad2a 100644 --- a/src/Relation/HasOne.js +++ b/src/Relation/HasOne.ts @@ -1,19 +1,19 @@ import utils from '../utils' import { Relation } from '../Relation' -export const HasOneRelation = Relation.extend({ +export class HasOneRelation extends Relation { findExistingLinksFor (relatedMapper, record) { const recordId = utils.get(record, relatedMapper.idAttribute) const records = this.findExistingLinksByForeignKey(recordId) - if (records && records.length) { + if (records?.length) { return records[0] } - }, + } isRequiresChildId () { return true } -}, { - TYPE_NAME: 'hasOne' -}) + + static TYPE_NAME = 'hasOne'; +} diff --git a/src/Schema.js b/src/Schema.ts similarity index 79% rename from src/Schema.js rename to src/Schema.ts index 35070f61..5a33d231 100644 --- a/src/Schema.js +++ b/src/Schema.ts @@ -1,5 +1,6 @@ import utils from './utils' import Component from './Component' +import { TsDataError } from './TsDataError' const DOMAIN = 'Schema' @@ -27,7 +28,7 @@ const types = { /** * @ignore */ -const segmentToString = function (segment, prev) { +function segmentToString (segment, prev) { let str = '' if (segment) { if (utils.isNumber(segment)) { @@ -44,11 +45,10 @@ const segmentToString = function (segment, prev) { /** * @ignore */ -const makePath = function (opts) { - opts || (opts = {}) +function makePath (opts: any = {}) { let path = '' const segments = opts.path || [] - segments.forEach(function (segment) { + segments.forEach(segment => { path += segmentToString(segment, path) }) path += segmentToString(opts.prop, path) @@ -58,7 +58,7 @@ const makePath = function (opts) { /** * @ignore */ -const makeError = function (actual, expected, opts) { +function makeError (actual, expected, opts) { return { expected, actual: '' + actual, @@ -69,14 +69,14 @@ const makeError = function (actual, expected, opts) { /** * @ignore */ -const addError = function (actual, expected, opts, errors) { +function addError (actual, expected, opts, errors) { errors.push(makeError(actual, expected, opts)) } /** * @ignore */ -const maxLengthCommon = function (keyword, value, schema, opts) { +function maxLengthCommon (keyword, value, schema, opts) { const max = schema[keyword] if (value.length > max) { return makeError(value.length, `length no more than ${max}`, opts) @@ -86,7 +86,7 @@ const maxLengthCommon = function (keyword, value, schema, opts) { /** * @ignore */ -const minLengthCommon = function (keyword, value, schema, opts) { +function minLengthCommon (keyword, value, schema, opts) { const min = schema[keyword] if (value.length < min) { return makeError(value.length, `length no less than ${min}`, opts) @@ -117,7 +117,7 @@ const validationKeywords = { */ allOf (value, schema, opts) { let allErrors = [] - schema.allOf.forEach(function (_schema) { + schema.allOf.forEach(_schema => { allErrors = allErrors.concat(validate(value, _schema, opts) || []) }) return allErrors.length ? allErrors : undefined @@ -142,7 +142,7 @@ const validationKeywords = { anyOf (value, schema, opts) { let validated = false let allErrors = [] - schema.anyOf.forEach(function (_schema) { + schema.anyOf.forEach(_schema => { const errors = validate(value, _schema, opts) if (errors) { allErrors = allErrors.concat(errors) @@ -180,13 +180,14 @@ const validationKeywords = { */ enum (value, schema, opts) { const possibleValues = schema.enum - if (utils.findIndex(possibleValues, (item) => utils.deepEqual(item, value)) === -1) { + if (utils.findIndex(possibleValues, item => utils.deepEqual(item, value)) === -1) { return makeError(value, `one of (${possibleValues.join(', ')})`, opts) } }, /** - * Validates each of the provided array values against a schema or an array of schemas defined by the Schema's `items` keyword + * Validates each of the provided array values against a schema or an array of schemas defined by the Schema's + * `items` keyword * see http://json-schema.org/latest/json-schema-validation.html#anchor37 for validation rules. * * @name Schema.validationKeywords.items @@ -196,14 +197,13 @@ const validationKeywords = { * @param {object} [opts] Configuration options. * @returns {(array|undefined)} Array of errors or `undefined` if valid. */ - items (value, schema, opts) { - opts || (opts = {}) + items (value, schema, opts: any = {}) { // TODO: additionalItems let items = schema.items let errors = [] const checkingTuple = utils.isArray(items) const length = value.length - for (var prop = 0; prop < length; prop++) { + for (let prop = 0; prop < length; prop++) { if (checkingTuple) { // Validating a tuple, instead of just checking each item against the // same schema @@ -276,7 +276,8 @@ const validationKeywords = { }, /** - * Validates the count of the provided object's properties against a maximum value defined in the Schema's `maxProperties` keyword. + * Validates the count of the provided object's properties against a maximum value defined in the Schema's + * `maxProperties` keyword. * Validation succeeds if the object's property count is less than, or equal to the value of this keyword. * see http://json-schema.org/latest/json-schema-validation.html#anchor54 * @@ -358,7 +359,8 @@ const validationKeywords = { }, /** - * Validates the count of the provided object's properties against a minimum value defined in the Schema's `minProperties` keyword. + * Validates the count of the provided object's properties against a minimum value defined in the Schema's + * `minProperties` keyword. * Validation succeeds if the object's property count is greater than, or equal to the value of this keyword. * see http://json-schema.org/latest/json-schema-validation.html#anchor57 * @@ -402,7 +404,8 @@ const validationKeywords = { /** * Validates the provided value is not valid with any of the schemas defined in the Schema's `not` keyword. - * An instance is valid against this keyword if and only if it is NOT valid against the schemas in this keyword's value. + * An instance is valid against this keyword if and only if it is NOT valid against the schemas in this keyword's + * value. * * see http://json-schema.org/latest/json-schema-validation.html#anchor91 * @name Schema.validationKeywords.not @@ -421,7 +424,8 @@ const validationKeywords = { /** * Validates the provided value is valid with one and only one of the schemas defined in the Schema's `oneOf` keyword. - * An instance is valid against this keyword if and only if it is valid against a single schemas in this keyword's value. + * An instance is valid against this keyword if and only if it is valid against a single schemas in this keyword's + * value. * * see http://json-schema.org/latest/json-schema-validation.html#anchor88 * @name Schema.validationKeywords.oneOf @@ -434,7 +438,7 @@ const validationKeywords = { oneOf (value, schema, opts) { let validated = false let allErrors = [] - schema.oneOf.forEach(function (_schema) { + schema.oneOf.forEach(_schema => { const errors = validate(value, _schema, opts) if (errors) { allErrors = allErrors.concat(errors) @@ -482,9 +486,7 @@ const validationKeywords = { * @param {object} [opts] Configuration options. * @returns {(array|undefined)} Array of errors or `undefined` if valid. */ - properties (value, schema, opts) { - opts || (opts = {}) - + properties (value, schema, opts: any = {}) { if (utils.isArray(value)) { return } @@ -502,15 +504,15 @@ const validationKeywords = { const patternProperties = schema.patternProperties || {} let errors = [] - utils.forOwn(properties, function (_schema, prop) { + utils.forOwn(properties, (_schema, prop) => { opts.prop = prop errors = errors.concat(validate(value[prop], _schema, opts) || []) validated.push(prop) }) const toValidate = utils.omit(value, validated) - utils.forOwn(patternProperties, function (_schema, pattern) { - utils.forOwn(toValidate, function (undef, prop) { + utils.forOwn(patternProperties, (_schema, pattern) => { + utils.forOwn(toValidate, (undef, prop) => { if (prop.match(pattern)) { opts.prop = prop errors = errors.concat(validate(value[prop], _schema, opts) || []) @@ -529,7 +531,7 @@ const validationKeywords = { } } else if (utils.isObject(additionalProperties)) { // Otherwise, validate according to provided schema - keys.forEach(function (prop) { + keys.forEach(prop => { opts.prop = prop errors = errors.concat(validate(value[prop], additionalProperties, opts) || []) }) @@ -549,12 +551,11 @@ const validationKeywords = { * @param {object} [opts] Configuration options. * @returns {(array|undefined)} Array of errors or `undefined` if valid. */ - required (value, schema, opts) { - opts || (opts = {}) + required (value, schema, opts: any = {}) { const required = schema.required const errors = [] if (!opts.existingOnly) { - required.forEach(function (prop) { + required.forEach(prop => { if (utils.get(value, prop) === undefined) { const prevProp = opts.prop opts.prop = prop @@ -567,7 +568,8 @@ const validationKeywords = { }, /** - * Validates the provided value's type is equal to the type, or array of types, defined in the Schema's `type` keyword. + * Validates the provided value's type is equal to the type, or array of types, defined in the Schema's `type` + * keyword. * see http://json-schema.org/latest/json-schema-validation.html#anchor79 * * @name Schema.validationKeywords.type @@ -585,7 +587,7 @@ const validationKeywords = { type = [type] } // Try to match the value against an expected type - type.forEach(function (_type) { + type.forEach(_type => { // TODO: throw an error if type is not defined if (types[_type](value, schema, opts)) { // Matched a type @@ -595,7 +597,11 @@ const validationKeywords = { }) // Value did not match any expected type if (!validType) { - return makeError(value !== undefined && value !== null ? typeof value : '' + value, `one of (${type.join(', ')})`, opts) + return makeError( + value !== undefined && value !== null ? typeof value : '' + value, + `one of (${type.join(', ')})`, + opts + ) } // Run keyword validators for matched type // http://json-schema.org/latest/json-schema-validation.html#anchor12 @@ -618,7 +624,7 @@ const validationKeywords = { * @returns {(array|undefined)} Array of errors or `undefined` if valid. */ uniqueItems (value, schema, opts) { - if (value && value.length && schema.uniqueItems) { + if (value?.length && schema.uniqueItems) { const length = value.length let item, i, j // Check n - 1 items @@ -639,9 +645,9 @@ const validationKeywords = { /** * @ignore */ -const runOps = function (ops, value, schema, opts) { +function runOps (ops, value, schema, opts) { let errors = [] - ops.forEach(function (op) { + ops.forEach(op => { if (schema[op] !== undefined) { errors = errors.concat(validationKeywords[op](value, schema, opts) || []) } @@ -719,9 +725,7 @@ const STRING_OPS = ['maxLength', 'minLength', 'pattern'] * http://json-schema.org/latest/json-schema-validation.html#anchor75 * @ignore */ -const validateAny = function (value, schema, opts) { - return runOps(ANY_OPS, value, schema, opts) -} +const validateAny = (value, schema, opts) => runOps(ANY_OPS, value, schema, opts) /** * Validates the provided value against a given Schema according to the http://json-schema.org/ v4 specification. @@ -733,10 +737,9 @@ const validateAny = function (value, schema, opts) { * @param {object} [opts] Configuration options. * @returns {(array|undefined)} Array of errors or `undefined` if valid. */ -const validate = function (value, schema, opts) { +const validate = (value, schema, opts: any = {}) => { let errors = [] - opts || (opts = {}) - opts.ctx || (opts.ctx = { value, schema }) + opts.ctx = opts.ctx || { value, schema } let shouldPop const prevProp = opts.prop if (schema === undefined) { @@ -812,11 +815,12 @@ const validationFailureMsg = 'validation failed' */ const typeGroupValidators = { /** - * Validates the provided value against the schema using all of the validation keywords specific to instances of an array. + * Validates the provided value against the schema using all of the validation keywords specific to instances of an + * array. * The validation keywords for the type `array` are: - *``` + * ``` * ['items', 'maxItems', 'minItems', 'uniqueItems'] - *``` + * ``` * see http://json-schema.org/latest/json-schema-validation.html#anchor25 * * @name Schema.typeGroupValidators.array @@ -826,16 +830,15 @@ const typeGroupValidators = { * @param {object} [opts] Configuration options. * @returns {(array|undefined)} Array of errors or `undefined` if valid. */ - array: function (value, schema, opts) { - return runOps(ARRAY_OPS, value, schema, opts) - }, + array: (value, schema, opts?) => runOps(ARRAY_OPS, value, schema, opts), /** - * Validates the provided value against the schema using all of the validation keywords specific to instances of an integer. + * Validates the provided value against the schema using all of the validation keywords specific to instances of an + * integer. * The validation keywords for the type `integer` are: - *``` + * ``` * ['multipleOf', 'maximum', 'minimum'] - *``` + * ``` * @name Schema.typeGroupValidators.integer * @method * @param {*} value Number to be validated. @@ -843,17 +846,17 @@ const typeGroupValidators = { * @param {object} [opts] Configuration options. * @returns {(array|undefined)} Array of errors or `undefined` if valid. */ - integer: function (value, schema, opts) { + integer: (value, schema, opts) => // Additional validations for numerics are the same - return typeGroupValidators.numeric(value, schema, opts) - }, + typeGroupValidators.numeric(value, schema, opts), /** - * Validates the provided value against the schema using all of the validation keywords specific to instances of an number. + * Validates the provided value against the schema using all of the validation keywords specific to instances of an + * number. * The validation keywords for the type `number` are: - *``` + * ``` * ['multipleOf', 'maximum', 'minimum'] - *``` + * ``` * @name Schema.typeGroupValidators.number * @method * @param {*} value Number to be validated. @@ -861,17 +864,17 @@ const typeGroupValidators = { * @param {object} [opts] Configuration options. * @returns {(array|undefined)} Array of errors or `undefined` if valid. */ - number: function (value, schema, opts) { + number: (value, schema, opts) => // Additional validations for numerics are the same - return typeGroupValidators.numeric(value, schema, opts) - }, + typeGroupValidators.numeric(value, schema, opts), /** - * Validates the provided value against the schema using all of the validation keywords specific to instances of a number or integer. + * Validates the provided value against the schema using all of the validation keywords specific to instances of a + * number or integer. * The validation keywords for the type `numeric` are: - *``` + * ``` * ['multipleOf', 'maximum', 'minimum'] - *``` + * ``` * See http://json-schema.org/latest/json-schema-validation.html#anchor13. * * @name Schema.typeGroupValidators.numeric @@ -881,16 +884,15 @@ const typeGroupValidators = { * @param {object} [opts] Configuration options. * @returns {(array|undefined)} Array of errors or `undefined` if valid. */ - numeric: function (value, schema, opts) { - return runOps(NUMERIC_OPS, value, schema, opts) - }, + numeric: (value, schema, opts) => runOps(NUMERIC_OPS, value, schema, opts), /** - * Validates the provided value against the schema using all of the validation keywords specific to instances of an object. + * Validates the provided value against the schema using all of the validation keywords specific to instances of an + * object. * The validation keywords for the type `object` are: - *``` + * ``` * ['maxProperties', 'minProperties', 'required', 'properties', 'dependencies'] - *``` + * ``` * See http://json-schema.org/latest/json-schema-validation.html#anchor53. * * @name Schema.typeGroupValidators.object @@ -900,16 +902,15 @@ const typeGroupValidators = { * @param {object} [opts] Configuration options. * @returns {(array|undefined)} Array of errors or `undefined` if valid. */ - object: function (value, schema, opts) { - return runOps(OBJECT_OPS, value, schema, opts) - }, + object: (value, schema, opts) => runOps(OBJECT_OPS, value, schema, opts), /** - * Validates the provided value against the schema using all of the validation keywords specific to instances of an string. + * Validates the provided value against the schema using all of the validation keywords specific to instances of an + * string. * The validation keywords for the type `string` are: - *``` + * ``` * ['maxLength', 'minLength', 'pattern'] - *``` + * ``` * See http://json-schema.org/latest/json-schema-validation.html#anchor25. * * @name Schema.typeGroupValidators.string @@ -919,9 +920,39 @@ const typeGroupValidators = { * @param {object} [opts] Configuration options. * @returns {(array|undefined)} Array of errors or `undefined` if valid. */ - string: function (value, schema, opts) { - return runOps(STRING_OPS, value, schema, opts) - } + string: (value, schema, opts?) => runOps(STRING_OPS, value, schema, opts) +} + +export interface PropertyDefinition { + type: string | string[] + track?: boolean + description?: string + indexed?: boolean + items?: PropertyDefinition + minItems?: number + uniqueItems?: boolean + extends?: Schema + get?: Function + properties?: { [name: string]: PropertyDefinition } + required?: string[] | boolean + maximum?: number + exclusiveMaximum?: boolean + minimum?: number + exclusiveMinimum?: boolean + additionalProperties?: boolean +} + +export interface SchemaDefinition { + type?: string + description?: string + $schema?: string + title?: string + properties?: { [name: string]: PropertyDefinition | any } + extends?: SchemaDefinition | Schema + items?: SchemaDefinition | Schema + track?: boolean + additionalProperties? + required?: string[] } /** @@ -940,41 +971,59 @@ const typeGroupValidators = { * }); * PostSchema.validate({ title: 1234 }); * + * @example + * const JSData = require('js-data'); + * const { Schema } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * class CustomSchemaClass extends Schema { + * foo () { return 'bar'; } + * static beep () { return 'boop'; } + * } + * const customSchema = new CustomSchemaClass(); + * console.log(customSchema.foo()); + * console.log(CustomSchemaClass.beep()); + * * @class Schema * @extends Component * @param {object} definition Schema definition according to json-schema.org */ -function Schema (definition) { - definition || (definition = {}) - // TODO: schema validation - utils.fillIn(this, definition) - - if (this.type === 'object') { - this.properties = this.properties || {} - utils.forOwn(this.properties, (_definition, prop) => { - if (!(_definition instanceof Schema)) { - this.properties[prop] = new Schema(_definition) - } - }) - } else if (this.type === 'array' && this.items && !(this.items instanceof Schema)) { - this.items = new Schema(this.items) - } - if (this.extends && !(this.extends instanceof Schema)) { - this.extends = new Schema(this.extends) - } - ['allOf', 'anyOf', 'oneOf'].forEach((validationKeyword) => { - if (this[validationKeyword]) { - this[validationKeyword].forEach((_definition, i) => { +export default class Schema extends Component { + type: string; + properties: any; + private readonly extends: Schema; + private readonly items: Schema; + private readonly track: any; + private readonly additionalProperties: any; + + constructor (definition: SchemaDefinition = {}) { + super() + // TODO: schema validation + utils.fillIn(this, definition) + + if (this.type === 'object') { + this.properties = this.properties || {} + utils.forOwn(this.properties, (_definition, prop) => { if (!(_definition instanceof Schema)) { - this[validationKeyword][i] = new Schema(_definition) + this.properties[prop] = new Schema(_definition) } }) + } else if (this.type === 'array' && this.items && !(this.items instanceof Schema)) { + this.items = new Schema(this.items) } - }) -} - -export default Component.extend({ - constructor: Schema, + if (this.extends && !(this.extends instanceof Schema)) { + this.extends = new Schema(this.extends) + } + ['allOf', 'anyOf', 'oneOf'].forEach(validationKeyword => { + if (this[validationKeyword]) { + this[validationKeyword].forEach((_definition, i) => { + if (!(_definition instanceof Schema)) { + this[validationKeyword][i] = new Schema(_definition) + } + }) + } + }) + } /** * This adds ES5 getters/setters to the target based on the "properties" in @@ -984,22 +1033,18 @@ export default Component.extend({ * @name Schema#apply * @method * @param {object} target The prototype to which to apply this schema. + * @param opts */ - apply (target, opts) { - opts || (opts = {}) - opts.getter || (opts.getter = '_get') - opts.setter || (opts.setter = '_set') - opts.unsetter || (opts.unsetter = '_unset') - opts.track || (opts.track = this.track) + apply (target, opts: any = {}) { + opts.getter = opts.getter || '_get' + opts.setter = opts.setter || '_set' + opts.unsetter = opts.unsetter || '_unset' + opts.track = opts.track || this.track const properties = this.properties || {} utils.forOwn(properties, (schema, prop) => { - Object.defineProperty( - target, - prop, - this.makeDescriptor(prop, schema, opts) - ) + Object.defineProperty(target, prop, this.makeDescriptor(prop, schema, opts)) }) - }, + } /** * Apply default values to the target object for missing values. @@ -1014,8 +1059,8 @@ export default Component.extend({ } const properties = this.properties || {} const hasSet = utils.isFunction(target.set) || utils.isFunction(target._set) - utils.forOwn(properties, function (schema, prop) { - if (Object.hasOwnProperty.call(schema, 'default') && utils.get(target, prop) === undefined) { + utils.forOwn(properties, (schema, prop) => { + if (schema.hasOwnProperty('default') && utils.get(target, prop) === undefined) { if (hasSet) { target.set(prop, utils.plainCopy(schema.default), { silent: true }) } else { @@ -1034,7 +1079,7 @@ export default Component.extend({ schema.applyDefaults(utils.get(target, prop)) } }) - }, + } /** * Assemble a property descriptor for tracking and validating changes to @@ -1052,12 +1097,109 @@ export default Component.extend({ * @returns {object} A property descriptor for the given schema. */ makeDescriptor (prop, schema, opts) { - const descriptor = { + const descriptor: any = { // Better to allow configurability, but at the user's own risk configurable: true, // These properties are enumerable by default, but regardless of their // enumerability, they won't be "own" properties of individual records - enumerable: schema.enumerable === undefined ? true : !!schema.enumerable + enumerable: schema.enumerable === undefined ? true : !!schema.enumerable, + get () { + return this._get(keyPath) + }, + set (value) { + // These are accessed a lot + const _get = this[getter] + const _set = this[setter] + const _unset = this[unsetter] + // Optionally check that the new value passes validation + if (!_get(noValidatePath)) { + const errors = schema.validate(value, { path: [prop] }) + if (errors) { + // Immediately throw an error, preventing the record from getting into + // an invalid state + const error = new TsDataError(validationFailureMsg) + error.errors = errors + throw error + } + } + // TODO: Make it so tracking can be turned on for all properties instead of + // only per-property + if (track && !_get(creatingPath)) { + // previous is versioned on database commit + // props are versioned on set() + const previous = _get(previousPath) + const current = _get(keyPath) + let changing = _get(changingPath) + let changed = _get(changedPath) + + if (!changing) { + // Track properties that are changing in the current event loop + changed = [] + } + + // Add changing properties to this array once at most + const index = changed.indexOf(prop) + if (current !== value && index === -1) { + changed.push(prop) + } + if (previous === value) { + if (index >= 0) { + changed.splice(index, 1) + } + } + // No changes in current event loop + if (!changed.length) { + changing = false + _unset(changingPath) + _unset(changedPath) + // Cancel pending change event + if (_get(eventIdPath)) { + clearTimeout(_get(eventIdPath)) + _unset(eventIdPath) + } + } + // Changes detected in current event loop + if (!changing && changed.length) { + _set(changedPath, changed) + _set(changingPath, true) + // Saving the timeout id allows us to batch all changes in the same + // event loop into a single "change" + // TODO: Optimize + _set( + eventIdPath, + setTimeout(() => { + // Previous event loop where changes were gathered has ended, so + // notify any listeners of those changes and prepare for any new + // changes + _unset(changedPath) + _unset(eventIdPath) + _unset(changingPath) + // TODO: Optimize + if (!_get(silentPath)) { + let i + for (i = 0; i < changed.length; i++) { + this.emit('change:' + changed[i], this, utils.get(this, changed[i])) + } + + const changes = utils.diffObjects({ [prop]: value }, { [prop]: current }) + + if (_get(keepChangeHistoryPath)) { + const changeRecord = utils.plainCopy(changes) + changeRecord.timestamp = new Date().getTime() + let changeHistory = _get(changeHistoryPath) + if (!changeHistory) _set(changeHistoryPath, (changeHistory = [])) + changeHistory.push(changeRecord) + } + this.emit('change', this, changes) + } + _unset(silentPath) + }, 0) + ) + } + } + _set(keyPath, value) + return value + } } // Cache a few strings for optimal performance const keyPath = `props.${prop}` @@ -1067,10 +1209,6 @@ export default Component.extend({ const unsetter = opts.unsetter const track = utils.isBoolean(opts.track) ? opts.track : schema.track - descriptor.get = function () { - return this._get(keyPath) - } - if (utils.isFunction(schema.get)) { const originalGet = descriptor.get descriptor.get = function () { @@ -1078,98 +1216,6 @@ export default Component.extend({ } } - descriptor.set = function (value) { - // These are accessed a lot - const _get = this[getter] - const _set = this[setter] - const _unset = this[unsetter] - // Optionally check that the new value passes validation - if (!_get(noValidatePath)) { - const errors = schema.validate(value, { path: [prop] }) - if (errors) { - // Immediately throw an error, preventing the record from getting into - // an invalid state - const error = new Error(validationFailureMsg) - error.errors = errors - throw error - } - } - // TODO: Make it so tracking can be turned on for all properties instead of - // only per-property - if (track && !_get(creatingPath)) { - // previous is versioned on database commit - // props are versioned on set() - const previous = _get(previousPath) - const current = _get(keyPath) - let changing = _get(changingPath) - let changed = _get(changedPath) - - if (!changing) { - // Track properties that are changing in the current event loop - changed = [] - } - - // Add changing properties to this array once at most - const index = changed.indexOf(prop) - if (current !== value && index === -1) { - changed.push(prop) - } - if (previous === value) { - if (index >= 0) { - changed.splice(index, 1) - } - } - // No changes in current event loop - if (!changed.length) { - changing = false - _unset(changingPath) - _unset(changedPath) - // Cancel pending change event - if (_get(eventIdPath)) { - clearTimeout(_get(eventIdPath)) - _unset(eventIdPath) - } - } - // Changes detected in current event loop - if (!changing && changed.length) { - _set(changedPath, changed) - _set(changingPath, true) - // Saving the timeout id allows us to batch all changes in the same - // event loop into a single "change" - // TODO: Optimize - _set(eventIdPath, setTimeout(() => { - // Previous event loop where changes were gathered has ended, so - // notify any listeners of those changes and prepare for any new - // changes - _unset(changedPath) - _unset(eventIdPath) - _unset(changingPath) - // TODO: Optimize - if (!_get(silentPath)) { - let i - for (i = 0; i < changed.length; i++) { - this.emit('change:' + changed[i], this, utils.get(this, changed[i])) - } - - const changes = utils.diffObjects({ [prop]: value }, { [prop]: current }) - - if (_get(keepChangeHistoryPath)) { - const changeRecord = utils.plainCopy(changes) - changeRecord.timestamp = new Date().getTime() - let changeHistory = _get(changeHistoryPath) - !changeHistory && _set(changeHistoryPath, (changeHistory = [])) - changeHistory.push(changeRecord) - } - this.emit('change', this, changes) - } - _unset(silentPath) - }, 0)) - } - } - _set(keyPath, value) - return value - } - if (utils.isFunction(schema.set)) { const originalSet = descriptor.set descriptor.set = function (value) { @@ -1178,7 +1224,7 @@ export default Component.extend({ } return descriptor - }, + } /** * Create a copy of the given value that contains only the properties defined @@ -1189,7 +1235,7 @@ export default Component.extend({ * @param {*} value The value to copy. * @returns {*} The copy. */ - pick (value) { + pick (value, opts?) { if (value === undefined) { return } @@ -1206,7 +1252,7 @@ export default Component.extend({ } // Conditionally copy properties not defined in "properties" if (this.additionalProperties) { - for (var key in value) { + for (const key in value) { if (!properties[key]) { copy[key] = utils.plainCopy(value[key]) } @@ -1214,7 +1260,7 @@ export default Component.extend({ } return copy } else if (this.type === 'array') { - return value.map((item) => { + return value.map(item => { const _copy = this.items ? this.items.pick(item) : {} if (this.extends) { utils.fillIn(_copy, this.extends.pick(item)) @@ -1223,7 +1269,7 @@ export default Component.extend({ }) } return utils.plainCopy(value) - }, + } /** * Validate the provided value against this schema. @@ -1234,69 +1280,17 @@ export default Component.extend({ * @param {object} [opts] Configuration options. * @returns {(array|undefined)} Array of errors or `undefined` if valid. */ - validate (value, opts) { + validate (value, opts?) { return validate(value, this, opts) } -}, { - ANY_OPS, - ARRAY_OPS, - NUMERIC_OPS, - OBJECT_OPS, - STRING_OPS, - typeGroupValidators, - types, - validate, - validationKeywords -}) -/** - * Create a subclass of this Schema: - * @example Schema.extend - * const JSData = require('js-data'); - * const { Schema } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * // Extend the class using ES2015 class syntax. - * class CustomSchemaClass extends Schema { - * foo () { return 'bar'; } - * static beep () { return 'boop'; } - * } - * const customSchema = new CustomSchemaClass(); - * console.log(customSchema.foo()); - * console.log(CustomSchemaClass.beep()); - * - * // Extend the class using alternate method. - * const OtherSchemaClass = Schema.extend({ - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }); - * const otherSchema = new OtherSchemaClass(); - * console.log(otherSchema.foo()); - * console.log(OtherSchemaClass.beep()); - * - * // Extend the class, providing a custom constructor. - * function AnotherSchemaClass () { - * Schema.call(this); - * this.created_at = new Date().getTime(); - * } - * Schema.extend({ - * constructor: AnotherSchemaClass, - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }); - * const anotherSchema = new AnotherSchemaClass(); - * console.log(anotherSchema.created_at); - * console.log(anotherSchema.foo()); - * console.log(AnotherSchemaClass.beep()); - * - * @method Schema.extend - * @param {object} [props={}] Properties to add to the prototype of the - * subclass. - * @param {object} [props.constructor] Provide a custom constructor function - * to be used as the subclass itself. - * @param {object} [classProps={}] Static properties to add to the subclass. - * @returns {Constructor} Subclass of this Schema class. - * @since 3.0.0 - */ + static ANY_OPS = ANY_OPS; + static ARRAY_OPS = ARRAY_OPS; + static NUMERIC_OPS = NUMERIC_OPS; + static OBJECT_OPS = OBJECT_OPS; + static STRING_OPS = STRING_OPS; + static typeGroupValidators = typeGroupValidators; + static types = types; + static validate = validate; + static validationKeywords: any = validationKeywords; +} diff --git a/src/Settable.js b/src/Settable.js deleted file mode 100644 index 45cb8bdb..00000000 --- a/src/Settable.js +++ /dev/null @@ -1,113 +0,0 @@ -import utils from './utils' - -/** - * A base class which gives instances private properties. - * - * Typically you won't instantiate this class directly, but you may find it - * useful as an abstract class for your own components. - * - * See {@link Settable.extend} for an example of using {@link Settable} as a - * base class. - * - *```javascript - * import {Settable} from 'js-data' - * ``` - * - * @class Settable - * @returns {Settable} A new {@link Settable} instance. - * @since 3.0.0 - */ -export default function Settable () { - const _props = {} - Object.defineProperties(this, { - /** - * Get a private property of this instance. - * - * __Don't use the method unless you know what you're doing.__ - * - * @method Settable#_get - * @param {string} key The property to retrieve. - * @returns {*} The value of the property. - * @since 3.0.0 - */ - _get: { value (key) { return utils.get(_props, key) } }, - - /** - * Set a private property of this instance. - * - * __Don't use the method unless you know what you're doing.__ - * - * @method __Don't use the method unless you know what you're doing.__#_set - * @param {(string|Object)} key The key or path to the property. Can also - * pass in an object of key/value pairs, which will all be set on the instance. - * @param {*} [value] The value to set. - * @since 3.0.0 - */ - _set: { value (key, value) { return utils.set(_props, key, value) } }, - - /** - * Unset a private property of this instance. - * - * __Don't use the method unless you know what you're doing.__ - * - * @method __Don't use the method unless you know what you're doing.__#_unset - * @param {string} key The property to unset. - * @since 3.0.0 - */ - _unset: { value (key) { return utils.unset(_props, key) } } - }) -} - -/** - * Create a subclass of this Settable: - * - * @example Settable.extend - * const JSData = require('js-data'); - * const { Settable } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * // Extend the class using ES2015 class syntax. - * class CustomSettableClass extends Settable { - * foo () { return 'bar'; } - * static beep () { return 'boop'; } - * } - * const customSettable = new CustomSettableClass(); - * console.log(customSettable.foo()); - * console.log(CustomSettableClass.beep()); - * - * // Extend the class using alternate method. - * const OtherSettableClass = Settable.extend({ - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }); - * const otherSettable = new OtherSettableClass(); - * console.log(otherSettable.foo()); - * console.log(OtherSettableClass.beep()); - * - * // Extend the class, providing a custom constructor. - * function AnotherSettableClass () { - * Settable.call(this); - * this.created_at = new Date().getTime(); - * } - * Settable.extend({ - * constructor: AnotherSettableClass, - * foo () { return 'bar'; } - * }, { - * beep () { return 'boop'; } - * }) - * const anotherSettable = new AnotherSettableClass(); - * console.log(anotherSettable.created_at); - * console.log(anotherSettable.foo()); - * console.log(AnotherSettableClass.beep()); - * - * @method Settable.extend - * @param {object} [props={}] Properties to add to the prototype of the - * subclass. - * @param {object} [props.constructor] Provide a custom constructor function - * to be used as the subclass itself. - * @param {object} [classProps={}] Static properties to add to the subclass. - * @returns {Constructor} Subclass of this Settable class. - * @since 3.0.0 - */ -Settable.extend = utils.extend diff --git a/src/Settable.ts b/src/Settable.ts new file mode 100644 index 00000000..1201d317 --- /dev/null +++ b/src/Settable.ts @@ -0,0 +1,83 @@ +import utils from './utils' + +/** + * A base class which gives instances private properties. + * + * Typically you won't instantiate this class directly, but you may find it + * useful as an abstract class for your own components. + * + * @example + * import {Settable} from 'js-data'; + * + * class CustomSettableClass extends Settable { + * foo () { return 'bar'; } + * static beep () { return 'boop'; } + * } + * + * const customSettable = new CustomSettableClass(); + * console.log(customSettable.foo()); + * console.log(CustomSettableClass.beep()); + * + * @since 3.0.0 + */ +export default class Settable { + [customAttr: string]: any; + + /** + * Get a private property of this instance. + * + * __Don't use the method unless you know what you're doing.__ + * + * @method Settable#_get + * @param {string} key The property to retrieve. + * @returns {*} The value of the property. + * @since 3.0.0 + */ + protected _get: (key: string) => any; + + /** + * Set a private property of this instance. + * + * __Don't use the method unless you know what you're doing.__ + * + * @method __Don't use the method unless you know what you're doing.__#_set + * @param {(string|Object)} key The key or path to the property. Can also + * pass in an object of key/value pairs, which will all be set on the instance. + * @param {*} [value] The value to set. + * @since 3.0.0 + */ + protected _set: (key, value?) => any; + + /** + * Unset a private property of this instance. + * + * __Don't use the method unless you know what you're doing.__ + * + * @method __Don't use the method unless you know what you're doing.__#_unset + * @param {string} key The property to unset. + * @since 3.0.0 + */ + protected _unset: (key) => any; + + constructor () { + const _props = {} + + Object.defineProperties(this, { + _get: { + value (key) { + return utils.get(_props, key) + } + }, + _set: { + value (key, value) { + return utils.set(_props, key, value) + } + }, + _unset: { + value (key) { + return utils.unset(_props, key) + } + } + }) + } +} diff --git a/src/SimpleStore.js b/src/SimpleStore.ts similarity index 92% rename from src/SimpleStore.js rename to src/SimpleStore.ts index 87047197..205086ec 100644 --- a/src/SimpleStore.js +++ b/src/SimpleStore.ts @@ -1,263 +1,25 @@ import utils from './utils' -import { - belongsToType, - hasManyType, - hasOneType -} from './decorators' -import { proxiedMapperMethods, Container } from './Container' +import { belongsToType, hasManyType, hasOneType } from './decorators' +import { Container, proxiedMapperMethods } from './Container' import Collection from './Collection' +import { MapperOpts } from './Mapper' +import Schema from './Schema' const DOMAIN = 'SimpleStore' const proxiedCollectionMethods = [ - /** - * Wrapper for {@link Collection#add}. - * - * @example SimpleStore#add - * const JSData = require('js-data'); - * const { SimpleStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new SimpleStore(); - * store.defineMapper('book'); - * - * // Add one book to the in-memory store: - * store.add('book', { id: 1, title: 'Respect your Data' }); - * // Add multiple books to the in-memory store: - * store.add('book', [ - * { id: 2, title: 'Easy data recipes' }, - * { id: 3, title: 'Active Record 101' } - * ]); - * - * @fires SimpleStore#add - * @method SimpleStore#add - * @param {(string|number)} name Name of the {@link Mapper} to target. - * @param {(Object|Object[]|Record|Record[])} data See {@link Collection#add}. - * @param {object} [opts] Configuration options. See {@link Collection#add}. - * @returns {(Object|Object[]|Record|Record[])} See {@link Collection#add}. - * @see Collection#add - * @see Collection#add - * @since 3.0.0 - */ 'add', - - /** - * Wrapper for {@link Collection#between}. - * - * @example - * // Get all users ages 18 to 30 - * const users = store.between('user', 18, 30, { index: 'age' }); - * - * @example - * // Same as above - * const users = store.between('user', [18], [30], { index: 'age' }); - * - * @method SimpleStore#between - * @param {(string|number)} name Name of the {@link Mapper} to target. - * @param {array} leftKeys See {@link Collection#between}. - * @param {array} rightKeys See {@link Collection#between}. - * @param {object} [opts] Configuration options. See {@link Collection#between}. - * @returns {Object[]|Record[]} See {@link Collection#between}. - * @see Collection#between - * @see Collection#between - * @since 3.0.0 - */ 'between', - - /** - * Wrapper for {@link Collection#createIndex}. - * - * @example - * // Index users by age - * store.createIndex('user', 'age'); - * - * @example - * // Index users by status and role - * store.createIndex('user', 'statusAndRole', ['status', 'role']); - * - * @method SimpleStore#createIndex - * @param {(string|number)} name Name of the {@link Mapper} to target. - * @param {string} name See {@link Collection#createIndex}. - * @param {string[]} [fieldList] See {@link Collection#createIndex}. - * @see Collection#createIndex - * @see Collection#createIndex - * @since 3.0.0 - */ 'createIndex', - - /** - * Wrapper for {@link Collection#filter}. - * - * @example SimpleStore#filter - * const JSData = require('js-data'); - * const { SimpleStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new SimpleStore(); - * store.defineMapper('post'); - * store.add('post', [ - * { id: 1, status: 'draft', created_at_timestamp: new Date().getTime() } - * ]); - * - * // Get the draft posts created less than three months ago - * let posts = store.filter('post', { - * where: { - * status: { - * '==': 'draft' - * }, - * created_at_timestamp: { - * '>=': (new Date().getTime() - (1000 \* 60 \* 60 \* 24 \* 30 \* 3)) // 3 months ago - * } - * } - * }); - * console.log(posts); - * - * // Use a custom filter function - * posts = store.filter('post', function (post) { return post.id % 2 === 0 }); - * - * @method SimpleStore#filter - * @param {(string|number)} name Name of the {@link Mapper} to target. - * @param {(Object|Function)} [queryOrFn={}] See {@link Collection#filter}. - * @param {object} [thisArg] See {@link Collection#filter}. - * @returns {Array} See {@link Collection#filter}. - * @see Collection#filter - * @see Collection#filter - * @since 3.0.0 - */ 'filter', - - /** - * Wrapper for {@link Collection#get}. - * - * @example SimpleStore#get - * const JSData = require('js-data'); - * const { SimpleStore } = JSData; - * console.log('Using JSData v' + JSData.version.full); - * - * const store = new SimpleStore(); - * store.defineMapper('post'); - * store.add('post', [ - * { id: 1, status: 'draft', created_at_timestamp: new Date().getTime() } - * ]); - * - * console.log(store.get('post', 1)); // {...} - * console.log(store.get('post', 2)); // undefined - * - * @method SimpleStore#get - * @param {(string|number)} name Name of the {@link Mapper} to target. - * @param {(string|number)} id See {@link Collection#get}. - * @returns {(Object|Record)} See {@link Collection#get}. - * @see Collection#get - * @see Collection#get - * @since 3.0.0 - */ 'get', - - /** - * Wrapper for {@link Collection#getAll}. - * - * @example - * // Get the posts where "status" is "draft" or "inReview" - * const posts = store.getAll('post', 'draft', 'inReview', { index: 'status' }); - * - * @example - * // Same as above - * const posts = store.getAll('post', ['draft'], ['inReview'], { index: 'status' }); - * - * @method SimpleStore#getAll - * @param {(string|number)} name Name of the {@link Mapper} to target. - * @param {...Array} [keyList] See {@link Collection#getAll}. - * @param {object} [opts] See {@link Collection#getAll}. - * @returns {Array} See {@link Collection#getAll}. - * @see Collection#getAll - * @see Collection#getAll - * @since 3.0.0 - */ 'getAll', - - /** - * Wrapper for {@link Collection#prune}. - * - * @method SimpleStore#prune - * @param {object} [opts] See {@link Collection#prune}. - * @returns {Array} See {@link Collection#prune}. - * @see Collection#prune - * @see Collection#prune - * @since 3.0.0 - */ 'prune', - - /** - * Wrapper for {@link Collection#query}. - * - * @example - * // Grab page 2 of users between ages 18 and 30 - * store.query('user') - * .between(18, 30, { index: 'age' }) // between ages 18 and 30 - * .skip(10) // second page - * .limit(10) // page size - * .run(); - * - * @method SimpleStore#query - * @param {(string|number)} name Name of the {@link Mapper} to target. - * @returns {Query} See {@link Collection#query}. - * @see Collection#query - * @see Collection#query - * @since 3.0.0 - */ 'query', - - /** - * Wrapper for {@link Collection#toJSON}. - * - * @example - * store.defineMapper('post', { - * schema: { - * properties: { - * id: { type: 'number' }, - * title: { type: 'string' } - * } - * } - * }); - * store.add('post', [ - * { id: 1, status: 'published', title: 'Respect your Data' }, - * { id: 2, status: 'draft', title: 'Connecting to a data source' } - * ]); - * console.log(store.toJSON('post')); - * const draftsJSON = store.query('post') - * .filter({ status: 'draft' }) - * .mapCall('toJSON') - * .run(); - * - * @method SimpleStore#toJSON - * @param {(string|number)} name Name of the {@link Mapper} to target. - * @param {object} [opts] See {@link Collection#toJSON}. - * @returns {Array} See {@link Collection#toJSON}. - * @see Collection#toJSON - * @see Collection#toJSON - * @since 3.0.0 - */ 'toJSON', - - /** - * Wrapper for {@link Collection#unsaved}. - * - * @method SimpleStore#unsaved - * @returns {Array} See {@link Collection#unsaved}. - * @see Collection#unsaved - * @see Collection#unsaved - * @since 3.0.0 - */ 'unsaved' ] -const ownMethodsForScoping = [ - 'addToCache', - 'cachedFind', - 'cachedFindAll', - 'cacheFind', - 'cacheFindAll', - 'hashQuery' -] +const ownMethodsForScoping = ['addToCache', 'cachedFind', 'cachedFindAll', 'cacheFind', 'cacheFindAll', 'hashQuery'] const cachedFn = function (name, hashOrId, opts) { const cached = this._completedQueries[name][hashOrId] @@ -267,6 +29,32 @@ const cachedFn = function (name, hashOrId, opts) { return cached } +export interface SimpleStoreOpts { + /** + * Whether to use the pending query if a `find` request for the specified + * record is currently underway. Can be set to `true`, `false`, or to a + * function that returns `true` or `false`. + * + * @default true + * @name SimpleStore#usePendingFind + * @since 3.0.0 + * @type {boolean|Function} + */ + usePendingFind?: boolean | Function + + /** + * Whether to use the pending query if a `findAll` request for the given query + * is currently underway. Can be set to `true`, `false`, or to a function that + * returns `true` or `false`. + * + * @default true + * @name SimpleStore#usePendingFindAll + * @since 3.0.0 + * @type {boolean|Function} + */ + usePendingFindAll?: boolean | Function +} + const SIMPLESTORE_DEFAULTS = { /** * Whether to use the pending query if a `find` request for the specified @@ -347,22 +135,18 @@ const SIMPLESTORE_DEFAULTS = { * @tutorial ["http://www.js-data.io/v3.0/docs/working-with-the-SimpleStore","Working with the SimpleStore"] * @tutorial ["http://www.js-data.io/v3.0/docs/jsdata-and-the-browser","Notes on using JSData in the Browser"] */ -function SimpleStore (opts) { - utils.classCallCheck(this, SimpleStore) - - opts || (opts = {}) - // Fill in any missing options with the defaults - utils.fillIn(opts, SIMPLESTORE_DEFAULTS) - Container.call(this, opts) - - this.collectionClass = this.collectionClass || Collection - this._collections = {} - this._pendingQueries = {} - this._completedQueries = {} -} - -const props = { - constructor: SimpleStore, +export default class SimpleStore extends Container { + collectionClass: typeof Collection; + _collections: { [name: string]: Collection } = {}; + _completedQueries = {}; + _pendingQueries = {}; + usePendingFind: boolean; + usePendingFindAll: boolean; + + constructor (opts: SimpleStoreOpts = {}) { + super({ ...SIMPLESTORE_DEFAULTS, ...opts }) + this.collectionClass = this.collectionClass || Collection + } /** * Internal method used to handle Mapper responses. @@ -386,7 +170,7 @@ const props = { } } return result - }, + } /** * Register a new event listener on this SimpleStore. @@ -436,7 +220,7 @@ const props = { _onCollectionEvent (name, ...args) { const type = args.shift() this.emit(type, name, ...args) - }, + } /** * This method takes the data received from {@link SimpleStore#find}, @@ -482,7 +266,7 @@ const props = { */ addToCache (name, data, opts) { return this.getCollection(name).add(data, opts) - }, + } /** * Return the store scoped to a particular mapper/collection pair. @@ -509,13 +293,11 @@ const props = { * @since 3.0.0 */ as (name) { - const props = {} + const props: any = {} const original = this - const methods = ownMethodsForScoping - .concat(proxiedMapperMethods) - .concat(proxiedCollectionMethods) + const methods = ownMethodsForScoping.concat(proxiedMapperMethods).concat(proxiedCollectionMethods) - methods.forEach(function (method) { + methods.forEach(method => { props[method] = { writable: true, value (...args) { @@ -536,7 +318,7 @@ const props = { } } return Object.create(this, props) - }, + } /** * Retrieve a cached `find` result, if any. This method is called during @@ -582,7 +364,7 @@ const props = { * @param {object} opts The `opts` argument passed to {@link SimpleStore#find}. * @since 3.0.0 */ - cachedFind: cachedFn, + cachedFind = cachedFn /** * Retrieve a cached `findAll` result, if any. This method is called during @@ -629,7 +411,7 @@ const props = { * @param {object} opts The `opts` argument passed to {@link SimpleStore#findAll}. * @since 3.0.0 */ - cachedFindAll: cachedFn, + cachedFindAll = cachedFn /** * Mark a {@link Mapper#find} result as cached by adding an entry to @@ -678,7 +460,7 @@ const props = { */ cacheFind (name, data, id, opts) { this._completedQueries[name][id] = (name, id, opts) => this.get(name, id) - }, + } /** * Mark a {@link Mapper#findAll} result as cached by adding an entry to @@ -728,7 +510,7 @@ const props = { */ cacheFindAll (name, data, hash, opts) { this._completedQueries[name][hash] = (name, hash, opts) => this.filter(name, utils.fromJson(hash)) - }, + } /** * Remove __all__ records from the in-memory store and reset @@ -747,7 +529,7 @@ const props = { this._completedQueries[name] = {} }) return removed - }, + } /** * Fired during {@link SimpleStore#create}. See @@ -782,6 +564,7 @@ const props = { * @see SimpleStore~afterCreateListener * @see SimpleStore#create */ + /** * Callback signature for the {@link SimpleStore#event:afterCreate} event. * @@ -835,11 +618,9 @@ const props = { * @returns {Promise} Resolves with the result of the create. * @since 3.0.0 */ - create (name, record, opts) { - opts || (opts = {}) - return Container.prototype.create.call(this, name, record, opts) - .then((result) => this._end(name, result, opts)) - }, + create (name, record, opts: any = {}) { + return super.create(name, record, opts).then(result => this._end(name, result, opts)) + } /** * Fired during {@link SimpleStore#createMany}. See @@ -874,6 +655,7 @@ const props = { * @see SimpleStore~afterCreateManyListener * @see SimpleStore#createMany */ + /** * Callback signature for the {@link SimpleStore#event:afterCreateMany} event. * @@ -932,39 +714,37 @@ const props = { * @returns {Promise} Resolves with the result of the create. * @since 3.0.0 */ - createMany (name, records, opts) { - opts || (opts = {}) - return Container.prototype.createMany.call(this, name, records, opts) - .then((result) => this._end(name, result, opts)) - }, + createMany (name, records, opts: any = {}) { + return super.createMany(name, records, opts).then(result => this._end(name, result, opts)) + } - defineMapper (name, opts) { + defineMapper (name, opts: MapperOpts = {}) { const self = this - const mapper = Container.prototype.defineMapper.call(self, name, opts) + const mapper = super.defineMapper(name, opts) self._pendingQueries[name] = {} self._completedQueries[name] = {} - mapper.relationList || Object.defineProperty(mapper, 'relationList', { value: [] }) + if (!mapper.relationList) Object.defineProperty(mapper, 'relationList', { value: [] }) - const collectionOpts = { + const collectionOpts: any = { // Make sure the collection has somewhere to store "added" timestamps _added: {}, // Give the collection a reference to this SimpleStore - datastore: self, + datastore: this, // The mapper tied to the collection mapper } - if (opts && ('onConflict' in opts)) { + if (opts && 'onConflict' in opts) { collectionOpts.onConflict = opts.onConflict } // The SimpleStore uses a subclass of Collection that is "SimpleStore-aware" - const collection = self._collections[name] = new self.collectionClass(null, collectionOpts) // eslint-disable-line + const collection = (self._collections[name] = new self.collectionClass(null, collectionOpts)) - const schema = mapper.schema || {} + const schema = mapper.schema || ({} as Schema) const properties = schema.properties || {} // TODO: Make it possible index nested properties? - utils.forOwn(properties, function (opts, prop) { + utils.forOwn(properties, (opts, prop) => { if (opts.indexed) { collection.createIndex(prop) } @@ -978,12 +758,12 @@ const props = { } }) - collection.on('all', function (...args) { + collection.on('all', (...args) => { self._onCollectionEvent(name, ...args) }) return mapper - }, + } /** * Fired during {@link SimpleStore#destroy}. See @@ -1018,6 +798,7 @@ const props = { * @see SimpleStore~afterDestroyListener * @see SimpleStore#destroy */ + /** * Callback signature for the {@link SimpleStore#event:afterDestroy} event. * @@ -1076,9 +857,8 @@ const props = { * @returns {Promise} Resolves when the destroy operation completes. * @since 3.0.0 */ - destroy (name, id, opts) { - opts || (opts = {}) - return Container.prototype.destroy.call(this, name, id, opts).then((result) => { + destroy (name, id, opts: any = {}) { + return super.destroy(name, id, opts).then(result => { const record = this.getCollection(name).remove(id, opts) if (opts.raw) { @@ -1090,7 +870,7 @@ const props = { delete this._completedQueries[name][id] return result }) - }, + } /** * Fired during {@link SimpleStore#destroyAll}. See @@ -1125,6 +905,7 @@ const props = { * @see SimpleStore~afterDestroyAllListener * @see SimpleStore#destroyAll */ + /** * Callback signature for the {@link SimpleStore#event:afterDestroyAll} event. * @@ -1181,9 +962,8 @@ const props = { * @returns {Promise} Resolves when the delete completes. * @since 3.0.0 */ - destroyAll (name, query, opts) { - opts || (opts = {}) - return Container.prototype.destroyAll.call(this, name, query, opts).then((result) => { + destroyAll (name, query, opts: any = {}) { + return super.destroyAll(name, query, opts).then(result => { const records = this.getCollection(name).removeAll(query, opts) if (opts.raw) { @@ -1196,17 +976,17 @@ const props = { delete this._completedQueries[name][hash] return result }) - }, + } eject (name, id, opts) { console.warn('DEPRECATED: "eject" is deprecated, use "remove" instead') return this.remove(name, id, opts) - }, + } ejectAll (name, query, opts) { console.warn('DEPRECATED: "ejectAll" is deprecated, use "removeAll" instead') return this.removeAll(name, query, opts) - }, + } /** * Fired during {@link SimpleStore#find}. See @@ -1241,6 +1021,7 @@ const props = { * @see SimpleStore~afterFindListener * @see SimpleStore#find */ + /** * Callback signature for the {@link SimpleStore#event:afterFind} event. * @@ -1291,34 +1072,38 @@ const props = { * @returns {Promise} Resolves with the result, if any. * @since 3.0.0 */ - find (name, id, opts) { - opts || (opts = {}) + find (name, id, opts: any = {}) { const mapper = this.getMapper(name) const pendingQuery = this._pendingQueries[name][id] const usePendingFind = opts.usePendingFind === undefined ? this.usePendingFind : opts.usePendingFind utils._(opts, mapper) - if (pendingQuery && (utils.isFunction(usePendingFind) ? usePendingFind.call(this, name, id, opts) : usePendingFind)) { + if ( + pendingQuery && + (utils.isFunction(usePendingFind) ? usePendingFind.call(this, name, id, opts) : usePendingFind) + ) { return pendingQuery } const item = this.cachedFind(name, id, opts) if (opts.force || !item) { - const promise = this._pendingQueries[name][id] = Container.prototype.find.call(this, name, id, opts) - return promise - .then((result) => { + const promise = (this._pendingQueries[name][id] = super.find(name, id, opts)) + return promise.then( + result => { delete this._pendingQueries[name][id] result = this._end(name, result, opts) this.cacheFind(name, result, id, opts) return result - }, (err) => { + }, + err => { delete this._pendingQueries[name][id] return utils.reject(err) - }) + } + ) } return utils.resolve(item) - }, + } /** * Fired during {@link SimpleStore#findAll}. See @@ -1353,6 +1138,7 @@ const props = { * @see SimpleStore~afterFindAllListener * @see SimpleStore#findAll */ + /** * Callback signature for the {@link SimpleStore#event:afterFindAll} event. * @@ -1403,55 +1189,57 @@ const props = { * @returns {Promise} Resolves with the result, if any. * @since 3.0.0 */ - findAll (name, query, opts) { - opts || (opts = {}) + findAll (name, query, opts: any = {}) { const mapper = this.getMapper(name) const hash = this.hashQuery(name, query, opts) const pendingQuery = this._pendingQueries[name][hash] const usePendingFindAll = opts.usePendingFindAll === undefined ? this.usePendingFindAll : opts.usePendingFindAll utils._(opts, mapper) - if (pendingQuery && (utils.isFunction(usePendingFindAll) ? usePendingFindAll.call(this, name, query, opts) : usePendingFindAll)) { + if ( + pendingQuery && + (utils.isFunction(usePendingFindAll) ? usePendingFindAll.call(this, name, query, opts) : usePendingFindAll) + ) { return pendingQuery } const items = this.cachedFindAll(name, hash, opts) if (opts.force || !items) { - const promise = this._pendingQueries[name][hash] = Container.prototype.findAll.call(this, name, query, opts) - return promise - .then((result) => { + const promise = (this._pendingQueries[name][hash] = super.findAll(name, query, opts)) + return promise.then( + result => { delete this._pendingQueries[name][hash] result = this._end(name, result, opts) this.cacheFindAll(name, result, hash, opts) return result - }, (err) => { + }, + err => { delete this._pendingQueries[name][hash] return utils.reject(err) - }) + } + ) } return utils.resolve(items) - }, + } /** * Return the {@link Collection} with the given name, if for some * reason you need a direct reference to the collection. * - * @method SimpleStore#getCollection * @param {string} name Name of the {@link Collection} to retrieve. - * @returns {Collection} * @since 3.0.0 * @throws {Error} Thrown if the specified {@link Collection} does not * exist. */ - getCollection (name) { + getCollection (name): Collection { const collection = this._collections[name] if (!collection) { throw utils.err(`${DOMAIN}#getCollection`, name)(404, 'collection') } return collection - }, + } /** * Hashing function used to cache {@link SimpleStore#find} and @@ -1470,12 +1258,12 @@ const props = { */ hashQuery (name, query, opts) { return utils.toJson(query || {}) - }, + } inject (name, records, opts) { console.warn('DEPRECATED: "inject" is deprecated, use "add" instead') return this.add(name, records, opts) - }, + } /** * Wrapper for {@link Collection#remove}. Removes the specified @@ -1506,13 +1294,13 @@ const props = { * @see Collection#add * @since 3.0.0 */ - remove (name, id, opts) { + remove (name, id, opts?) { const record = this.getCollection(name).remove(id, opts) if (record) { this.removeRelated(name, [record], opts) } return record - }, + } /** * Wrapper for {@link Collection#removeAll}. Removes the selected @@ -1558,7 +1346,7 @@ const props = { this.removeRelated(name, records, opts) } return records - }, + } /** * Remove from the store {@link Record}s that are related to the provided @@ -1579,7 +1367,7 @@ const props = { records = [records] } utils.forEachRelation(this.getMapper(name), opts, (def, optsCopy) => { - records.forEach((record) => { + records.forEach(record => { let relatedData let query if (def.foreignKey && (def.type === hasOneType || def.type === hasManyType)) { @@ -1617,7 +1405,7 @@ const props = { } }) }) - }, + } /** * Fired during {@link SimpleStore#update}. See @@ -1653,6 +1441,7 @@ const props = { * @see SimpleStore~afterUpdateListener * @see SimpleStore#update */ + /** * Callback signature for the {@link SimpleStore#event:afterUpdate} event. * @@ -1705,11 +1494,9 @@ const props = { * @returns {Promise} Resolves with the result of the update. * @since 3.0.0 */ - update (name, id, record, opts) { - opts || (opts = {}) - return Container.prototype.update.call(this, name, id, record, opts) - .then((result) => this._end(name, result, opts)) - }, + update (name, id, record, opts: any = {}) { + return super.update(name, id, record, opts).then(result => this._end(name, result, opts)) + } /** * Fired during {@link SimpleStore#updateAll}. See @@ -1745,6 +1532,7 @@ const props = { * @see SimpleStore~afterUpdateAllListener * @see SimpleStore#updateAll */ + /** * Callback signature for the {@link SimpleStore#event:afterUpdateAll} event. * @@ -1797,11 +1585,9 @@ const props = { * @returns {Promise} Resolves with the result of the update. * @since 3.0.0 */ - updateAll (name, props, query, opts) { - opts || (opts = {}) - return Container.prototype.updateAll.call(this, name, props, query, opts) - .then((result) => this._end(name, result, opts)) - }, + updateAll (name, props, query, opts: any = {}) { + return super.updateAll(name, props, query, opts).then(result => this._end(name, result, opts)) + } /** * Fired during {@link SimpleStore#updateMany}. See @@ -1836,6 +1622,7 @@ const props = { * @see SimpleStore~afterUpdateManyListener * @see SimpleStore#updateMany */ + /** * Callback signature for the {@link SimpleStore#event:afterUpdateMany} event. * @@ -1889,20 +1676,272 @@ const props = { * @returns {Promise} Resolves with the result of the update. * @since 3.0.0 */ - updateMany (name, records, opts) { - opts || (opts = {}) - return Container.prototype.updateMany.call(this, name, records, opts) - .then((result) => this._end(name, result, opts)) + updateMany (name, records, opts: any = {}) { + return super.updateMany(name, records, opts).then(result => this._end(name, result, opts)) + } + + /** + * Wrapper for {@link Collection#add}. + * + * @example SimpleStore#add + * const JSData = require('js-data'); + * const { SimpleStore } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new SimpleStore(); + * store.defineMapper('book'); + * + * // Add one book to the in-memory store: + * store.add('book', { id: 1, title: 'Respect your Data' }); + * // Add multiple books to the in-memory store: + * store.add('book', [ + * { id: 2, title: 'Easy data recipes' }, + * { id: 3, title: 'Active Record 101' } + * ]); + * + * @fires SimpleStore#add + * @method SimpleStore#add + * @param {(string|number)} name Name of the {@link Mapper} to target. + * @param {(Object|Object[]|Record|Record[])} records See {@link Collection#add}. + * @param {object} [opts] Configuration options. See {@link Collection#add}. + * @returns {(Object|Object[]|Record|Record[])} See {@link Collection#add}. + * @see Collection#add + * @see Collection#add + * @since 3.0.0 + */ + add (name, records, opts?) { + return this.getCollection(name).add(records, opts) + } + + /** + * Wrapper for {@link Collection#between}. + * + * @example + * // Get all users ages 18 to 30 + * const users = store.between('user', 18, 30, { index: 'age' }); + * + * @example + * // Same as above + * const users = store.between('user', [18], [30], { index: 'age' }); + * + * @method SimpleStore#between + * @param {(string|number)} name Name of the {@link Mapper} to target. + * @param {array} leftKeys See {@link Collection#between}. + * @param {array} rightKeys See {@link Collection#between}. + * @param {object} [opts] Configuration options. See {@link Collection#between}. + * @returns {Object[]|Record[]} See {@link Collection#between}. + * @see Collection#between + * @see Collection#between + * @since 3.0.0 + */ + between (name, leftKeys, rightKeys, opts) { + return this.getCollection(name).between(leftKeys, rightKeys, opts) + } + + /** + * Wrapper for {@link Collection#createIndex}. + * + * @example + * // Index users by age + * store.createIndex('user', 'age'); + * + * @example + * // Index users by status and role + * store.createIndex('user', 'statusAndRole', ['status', 'role']); + * + * @method SimpleStore#createIndex + * @param {(string|number)} name Name of the {@link Mapper} to target. + * @param {string} indexName See {@link Collection#createIndex}. + * @param {string[]} [fieldList] See {@link Collection#createIndex}. + * @param {object} [opts] Configuration options. See {@link Collection#between}. + * @see Collection#createIndex + * @see Collection#createIndex + * @since 3.0.0 + */ + createIndex (name: string | number, indexName: string, fieldList?: string[], opts?) { + return this.getCollection(name).createIndex(indexName, fieldList, opts) + } + + /** + * Wrapper for {@link Collection#filter}. + * + * @example SimpleStore#filter + * const JSData = require('js-data'); + * const { SimpleStore } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new SimpleStore(); + * store.defineMapper('post'); + * store.add('post', [ + * { id: 1, status: 'draft', created_at_timestamp: new Date().getTime() } + * ]); + * + * // Get the draft posts created less than three months ago + * let posts = store.filter('post', { + * where: { + * status: { + * '==': 'draft' + * }, + * created_at_timestamp: { + * '>=': (new Date().getTime() - (1000 \* 60 \* 60 \* 24 \* 30 \* 3)) // 3 months ago + * } + * } + * }); + * console.log(posts); + * + * // Use a custom filter function + * posts = store.filter('post', function (post) { return post.id % 2 === 0 }); + * + * @method SimpleStore#filter + * @param {(string|number)} name Name of the {@link Mapper} to target. + * @param {(Object|Function)} [queryOrFn={}] See {@link Collection#filter}. + * @param {object} [thisArg] See {@link Collection#filter}. + * @returns {Array} See {@link Collection#filter}. + * @see Collection#filter + * @see Collection#filter + * @since 3.0.0 + */ + filter (name, queryOrFn?, thisArg?) { + return this.getCollection(name).filter(queryOrFn, thisArg) + } + + /** + * Wrapper for {@link Collection#get}. + * + * @example SimpleStore#get + * const JSData = require('js-data'); + * const { SimpleStore } = JSData; + * console.log('Using JSData v' + JSData.version.full); + * + * const store = new SimpleStore(); + * store.defineMapper('post'); + * store.add('post', [ + * { id: 1, status: 'draft', created_at_timestamp: new Date().getTime() } + * ]); + * + * console.log(store.get('post', 1)); // {...} + * console.log(store.get('post', 2)); // undefined + * + * @method SimpleStore#get + * @param {(string|number)} name Name of the {@link Mapper} to target. + * @param {(string|number)} id See {@link Collection#get}. + * @returns {(Object|Record)} See {@link Collection#get}. + * @see Collection#get + * @see Collection#get + * @since 3.0.0 + */ + get (name, id) { + return this.getCollection(name).get(id) + } + + /** + * Wrapper for {@link Collection#getAll}. + * + * @example + * // Get the posts where "status" is "draft" or "inReview" + * const posts = store.getAll('post', 'draft', 'inReview', { index: 'status' }); + * + * @example + * // Same as above + * const posts = store.getAll('post', ['draft'], ['inReview'], { index: 'status' }); + * + * @method SimpleStore#getAll + * @param {(string|number)} name Name of the {@link Mapper} to target. + * @param {...Array} [keyList] See {@link Collection#getAll}. + * @param {object} [opts] See {@link Collection#getAll}. + * @returns {Array} See {@link Collection#getAll}. + * @see Collection#getAll + * @see Collection#getAll + * @since 3.0.0 + */ + getAll (name, ...args) { + return this.getCollection(name).getAll(...args) + } + + /** + * Wrapper for {@link Collection#prune}. + * + * @method SimpleStore#prune + * @param name + * @param {object} [opts] See {@link Collection#prune}. + * @returns {Array} See {@link Collection#prune}. + * @see Collection#prune + * @see Collection#prune + * @since 3.0.0 + */ + prune (name: string, opts?) { + return this.getCollection(name).prune(opts) + } + + /** + * Wrapper for {@link Collection#query}. + * + * @example + * // Grab page 2 of users between ages 18 and 30 + * store.query('user') + * .between(18, 30, { index: 'age' }) // between ages 18 and 30 + * .skip(10) // second page + * .limit(10) // page size + * .run(); + * + * @method SimpleStore#query + * @param {(string|number)} name Name of the {@link Mapper} to target. + * @returns {Query} See {@link Collection#query}. + * @see Collection#query + * @see Collection#query + * @since 3.0.0 + */ + query (name) { + return this.getCollection(name).query() } -} -proxiedCollectionMethods.forEach(function (method) { - props[method] = function (name, ...args) { - return this.getCollection(name)[method](...args) + /** + * Wrapper for {@link Collection#toJSON}. + * + * @example + * store.defineMapper('post', { + * schema: { + * properties: { + * id: { type: 'number' }, + * title: { type: 'string' } + * } + * } + * }); + * store.add('post', [ + * { id: 1, status: 'published', title: 'Respect your Data' }, + * { id: 2, status: 'draft', title: 'Connecting to a data source' } + * ]); + * console.log(store.toJSON('post')); + * const draftsJSON = store.query('post') + * .filter({ status: 'draft' }) + * .mapCall('toJSON') + * .run(); + * + * @method SimpleStore#toJSON + * @param {(string|number)} name Name of the {@link Mapper} to target. + * @param {object} [opts] See {@link Collection#toJSON}. + * @returns {Array} See {@link Collection#toJSON}. + * @see Collection#toJSON + * @see Collection#toJSON + * @since 3.0.0 + */ + toJSON (name, opts) { + return this.getCollection(name).toJSON(opts) } -}) -export default Container.extend(props) + /** + * Wrapper for {@link Collection#unsaved}. + * + * @method SimpleStore#unsaved + * @returns {Array} See {@link Collection#unsaved}. + * @see Collection#unsaved + * @see Collection#unsaved + * @since 3.0.0 + */ + unsaved (name, opts?) { + return this.getCollection(name).unsaved(opts) + } +} /** * Fired when a record changes. Only works for records that have tracked fields. diff --git a/src/TsDataError.ts b/src/TsDataError.ts new file mode 100644 index 00000000..5f905671 --- /dev/null +++ b/src/TsDataError.ts @@ -0,0 +1,3 @@ +export class TsDataError extends Error { + errors: any; +} diff --git a/src/decorators.js b/src/decorators.ts similarity index 84% rename from src/decorators.js rename to src/decorators.ts index 4aeec47f..e7fb2135 100644 --- a/src/decorators.js +++ b/src/decorators.ts @@ -1,10 +1,10 @@ import { Relation } from './relations' export { belongsToType, hasManyType, hasOneType } from './relations' + /** * BelongsTo relation decorator. You probably won't use this directly. * - * @name module:js-data.belongsTo * @method * @param {Mapper} related The relation the target belongs to. * @param {object} opts Configuration options. @@ -15,8 +15,8 @@ export { belongsToType, hasManyType, hasOneType } from './relations' * @returns {Function} Invocation function, which accepts the target as the only * parameter. */ -export const belongsTo = function (related, opts) { - return function (mapper) { +export function belongsTo (related, opts) { + return mapper => { Relation.belongsTo(related, opts).assignTo(mapper) } } @@ -24,7 +24,6 @@ export const belongsTo = function (related, opts) { /** * HasMany relation decorator. You probably won't use this directly. * - * @name module:js-data.hasMany * @method * @param {Mapper} related The relation of which the target has many. * @param {object} opts Configuration options. @@ -35,8 +34,8 @@ export const belongsTo = function (related, opts) { * @returns {Function} Invocation function, which accepts the target as the only * parameter. */ -export const hasMany = function (related, opts) { - return function (mapper) { +export function hasMany (related, opts) { + return mapper => { Relation.hasMany(related, opts).assignTo(mapper) } } @@ -44,7 +43,6 @@ export const hasMany = function (related, opts) { /** * HasOne relation decorator. You probably won't use this directly. * - * @name module:js-data.hasOne * @method * @param {Mapper} related The relation of which the target has one. * @param {object} opts Configuration options. @@ -55,8 +53,8 @@ export const hasMany = function (related, opts) { * @returns {Function} Invocation function, which accepts the target as the only * parameter. */ -export const hasOne = function (related, opts) { - return function (mapper) { +export function hasOne (related, opts) { + return mapper => { Relation.hasOne(related, opts).assignTo(mapper) } } diff --git a/src/index.js b/src/index.ts similarity index 88% rename from src/index.js rename to src/index.ts index ecbaa318..60ac42ec 100644 --- a/src/index.js +++ b/src/index.ts @@ -1,29 +1,14 @@ /** - * Registered as `js-data` in NPM and Bower. - * - * Also available from CDN.JS and JSDelivr. - * - * @module js-data + * Registered as `js-data` in NPM. * * @example Install from NPM - * npm i --save js-data@beta - * @example Install from Bower - * bower i --save js-data@3.0.0-beta.1 - * @example Install from CDN.JS - * - * @example Install from JSDelivr - * - * @example Load into your app via script tag - * - * + * npm i --save js-data + * @example Install from NPM + * yarn add js-data * @example Load into your app via CommonJS * var JSData = require('js-data'); * @example Load into your app via ES2015 Modules * import * as JSData from 'js-data'; - * @example Load into your app via AMD - * define('myApp', ['js-data'], function (JSData) { ... }); */ /** @@ -115,7 +100,7 @@ import DataStore from './DataStore' * @since 3.0.0 * @type {Constructor} */ -import Index from '../lib/mindex/index' +import Index from './mindex' /** * JSData's {@link LinkedCollection} class. Used by the {@link DataStore} diff --git a/lib/mindex/NOTICE b/src/mindex/NOTICE similarity index 100% rename from lib/mindex/NOTICE rename to src/mindex/NOTICE diff --git a/lib/mindex/_utils.js b/src/mindex/_utils.ts similarity index 68% rename from lib/mindex/_utils.js rename to src/mindex/_utils.ts index 3d453710..e88e5bd3 100644 --- a/lib/mindex/_utils.js +++ b/src/mindex/_utils.ts @@ -4,32 +4,21 @@ export function sort (a, b, hashCode) { // don't have the idAttribute field if (a === b) { return 0 - } - if (hashCode) { + } else if (hashCode) { a = hashCode(a) b = hashCode(b) } - if ((a === null && b === null) || (a === undefined && b === undefined)) { - return -1 - } - - if (a === null || a === undefined) { - return -1 - } - - if (b === null || b === undefined) { - return 1 - } - - if (a < b) { - return -1 - } - - if (a > b) { - return 1 - } - - return 0 + return (a === null && b === null) || (a === undefined && b === undefined) + ? -1 + : a === null || a === undefined + ? -1 + : b === null || b === undefined + ? 1 + : a < b + ? -1 + : a > b + ? 1 + : 0 } export function insertAt (array, index, value) { @@ -42,13 +31,14 @@ export function removeAt (array, index) { return array } -export function binarySearch (array, value, field) { +export function binarySearch (array, value, field?) { let lo = 0 let hi = array.length let compared let mid while (lo < hi) { + // tslint:disable-next-line:no-bitwise mid = ((lo + hi) / 2) | 0 compared = sort(value, array[mid], field) if (compared === 0) { diff --git a/lib/mindex/index.js b/src/mindex/index.ts similarity index 78% rename from lib/mindex/index.js rename to src/mindex/index.ts index e37f2869..89bf6b0a 100644 --- a/lib/mindex/index.js +++ b/src/mindex/index.ts @@ -20,25 +20,33 @@ import utils from '../../src/utils' import { binarySearch, insertAt, removeAt } from './_utils' -export default function Index (fieldList, opts) { - utils.classCallCheck(this, Index) - fieldList || (fieldList = []) +export interface IndexOpts { + fieldGetter? + hashCode? +} - if (!utils.isArray(fieldList)) { - throw new Error('fieldList must be an array.') - } +export default class Index { + fieldList: any[]; + fieldGetter: any; + hashCode: any; + isIndex: boolean; + keys: any[]; + values: any[]; + + constructor (fieldList = [], opts: IndexOpts = {}) { + if (!utils.isArray(fieldList)) { + throw new Error('fieldList must be an array.') + } - opts || (opts = {}) - this.fieldList = fieldList - this.fieldGetter = opts.fieldGetter - this.hashCode = opts.hashCode - this.isIndex = true - this.keys = [] - this.values = [] -} + this.fieldList = fieldList + this.fieldGetter = opts.fieldGetter + this.hashCode = opts.hashCode + this.isIndex = true + this.keys = [] + this.values = [] + } -utils.addHiddenPropsToTarget(Index.prototype, { - 'set' (keyList, value) { + set (keyList, value) { if (!utils.isArray(keyList)) { keyList = [keyList] } @@ -66,9 +74,9 @@ utils.addHiddenPropsToTarget(Index.prototype, { insertAt(this.values, pos.index, newIndex) } } - }, + } - 'get' (keyList) { + get (keyList?) { if (!utils.isArray(keyList)) { keyList = [keyList] } @@ -93,10 +101,9 @@ utils.addHiddenPropsToTarget(Index.prototype, { return [] } } - }, + } - getAll (opts) { - opts || (opts = {}) + getAll (opts: any = {}) { let results = [] const values = this.values if (opts.order === 'desc') { @@ -109,8 +116,7 @@ utils.addHiddenPropsToTarget(Index.prototype, { } } } else { - for (let i = 0; i < values.length; i++) { - const value = values[i] + for (const value of values) { if (value.isIndex) { results = results.concat(value.getAll(opts)) } else { @@ -119,20 +125,19 @@ utils.addHiddenPropsToTarget(Index.prototype, { } } return results - }, + } - visitAll (cb, thisArg) { - this.values.forEach(function (value) { + visitAll (cb, thisArg?) { + this.values.forEach(value => { if (value.isIndex) { value.visitAll(cb, thisArg) } else { value.forEach(cb, thisArg) } }) - }, + } - between (leftKeys, rightKeys, opts) { - opts || (opts = {}) + between (leftKeys, rightKeys, opts: any = {}) { if (!utils.isArray(leftKeys)) { leftKeys = [leftKeys] } @@ -153,7 +158,7 @@ utils.addHiddenPropsToTarget(Index.prototype, { } else { return results.slice(opts.offset) } - }, + } _between (leftKeys, rightKeys, opts) { let results = [] @@ -180,9 +185,13 @@ utils.addHiddenPropsToTarget(Index.prototype, { for (let i = pos.index; i < this.keys.length; i += 1) { if (rightKey !== undefined) { if (opts.rightInclusive) { - if (this.keys[i] > rightKey) { break } + if (this.keys[i] > rightKey) { + break + } } else { - if (this.keys[i] >= rightKey) { break } + if (this.keys[i] >= rightKey) { + break + } } } @@ -193,7 +202,7 @@ utils.addHiddenPropsToTarget(Index.prototype, { } if (opts.limit) { - if (results.length >= (opts.limit + opts.offset)) { + if (results.length >= opts.limit + opts.offset) { break } } @@ -201,13 +210,27 @@ utils.addHiddenPropsToTarget(Index.prototype, { } else { for (let i = pos.index; i < this.keys.length; i += 1) { const currKey = this.keys[i] - if (currKey > rightKey) { break } + if (currKey > rightKey) { + break + } if (this.values[i].isIndex) { if (currKey === leftKey) { - results = results.concat(this.values[i]._between(utils.copy(leftKeys), rightKeys.map(function () { return undefined }), opts)) + results = results.concat( + this.values[i]._between( + utils.copy(leftKeys), + rightKeys.map(() => undefined), + opts + ) + ) } else if (currKey === rightKey) { - results = results.concat(this.values[i]._between(leftKeys.map(function () { return undefined }), utils.copy(rightKeys), opts)) + results = results.concat( + this.values[i]._between( + leftKeys.map(() => undefined), + utils.copy(rightKeys), + opts + ) + ) } else { results = results.concat(this.values[i].getAll()) } @@ -216,7 +239,7 @@ utils.addHiddenPropsToTarget(Index.prototype, { } if (opts.limit) { - if (results.length >= (opts.limit + opts.offset)) { + if (results.length >= opts.limit + opts.offset) { break } } @@ -228,34 +251,23 @@ utils.addHiddenPropsToTarget(Index.prototype, { } else { return results } - }, + } peek () { - if (this.values.length) { - if (this.values[0].isIndex) { - return this.values[0].peek() - } else { - return this.values[0] - } - } - return [] - }, + return this.values.length ? (this.values[0].isIndex ? this.values[0].peek() : this.values[0]) : [] + } clear () { this.keys = [] this.values = [] - }, + } insertRecord (data) { - const keyList = this.fieldList.map(function (field) { - if (utils.isFunction(field)) { - return field(data) || undefined - } else { - return data[field] || undefined - } - }) + const keyList = this.fieldList.map(field => + utils.isFunction(field) ? field(data) || undefined : data[field] || undefined + ) this.set(keyList, data) - }, + } removeRecord (data) { let removed @@ -271,7 +283,7 @@ utils.addHiddenPropsToTarget(Index.prototype, { return false } } else { - let dataLocation = {} + let dataLocation: any = {} if (this.keys[i] === undefined || !isUnique) { for (let j = value.length - 1; j >= 0; j--) { if (value[j] === data) { @@ -297,7 +309,7 @@ utils.addHiddenPropsToTarget(Index.prototype, { } }) return removed ? data : undefined - }, + } updateRecord (data) { const removed = this.removeRecord(data) @@ -305,4 +317,4 @@ utils.addHiddenPropsToTarget(Index.prototype, { this.insertRecord(data) } } -}) +} diff --git a/src/relations.js b/src/relations.ts similarity index 88% rename from src/relations.js rename to src/relations.ts index 5e71c950..6080177b 100644 --- a/src/relations.js +++ b/src/relations.ts @@ -1,7 +1,7 @@ import { Relation } from './Relation' import { BelongsToRelation } from './Relation/BelongsTo' import { HasManyRelation } from './Relation/HasMany' -import { HasOneRelation } from './Relation/HasOne' +import { HasOneRelation } from './Relation/HasOne'; [BelongsToRelation, HasManyRelation, HasOneRelation].forEach(RelationType => { Relation[RelationType.TYPE_NAME] = (related, options) => new RelationType(related, options) diff --git a/src/utils.js b/src/utils.ts similarity index 81% rename from src/utils.js rename to src/utils.ts index 040ea9e7..22b86e62 100644 --- a/src/utils.js +++ b/src/utils.ts @@ -24,17 +24,15 @@ const objToString = Object.prototype.toString const PATH = /^(.+)\.(.+)$/ const ERRORS = { - '400' () { - return `expected: ${arguments[0]}, found: ${ - arguments[2] ? arguments[1] : typeof arguments[1] - }` + '400' (...args) { + return `expected: ${args[0]}, found: ${args[2] ? args[1] : typeof args[1]}` }, - '404' () { - return `${arguments[0]} not found` + '404' (...args) { + return `${args[0]} not found` } } -const toInteger = function (value) { +const toInteger = value => { if (!value) { return 0 } @@ -45,23 +43,19 @@ const toInteger = function (value) { return sign * MAX_INTEGER } const remainder = value % 1 - return value === value ? (remainder ? value - remainder : value) : 0 // eslint-disable-line + return value === value ? (remainder ? value - remainder : value) : 0; // eslint-disable-line } -const toStr = function (value) { - return objToString.call(value) -} +const toStr = value => objToString.call(value) -const isPlainObject = function (value) { - return !!value && typeof value === 'object' && value.constructor === Object -} +const isPlainObject = value => !!value && typeof value === 'object' && value.constructor === Object -const mkdirP = function (object, path) { +const mkdirP = (object, path) => { if (!path) { return object } const parts = path.split('.') - parts.forEach(function (key) { + parts.forEach(key => { if (!object[key]) { object[key] = {} } @@ -71,21 +65,6 @@ const mkdirP = function (object, path) { } const utils = { - /** - * Reference to the Promise constructor used by JSData. Defaults to - * `window.Promise` or `global.Promise`. - * - * @example Make JSData use a different `Promise` constructor - * import Promise from 'bluebird'; - * import { utils } from 'js-data'; - * utils.Promise = Promise; - * - * @name utils.Promise - * @since 3.0.0 - * @type {Function} - */ - Promise: Promise, - /** * Shallow copy properties that meet the following criteria from `src` to * `dest`: @@ -101,13 +80,8 @@ const utils = { * @since 3.0.0 */ _ (dest, src) { - utils.forOwn(src, function (value, key) { - if ( - key && - dest[key] === undefined && - !utils.isFunction(value) && - key.indexOf('_') !== 0 - ) { + utils.forOwn(src, (value, key) => { + if (key && dest[key] === undefined && !utils.isFunction(value) && key.indexOf('_') !== 0) { dest[key] = value } }) @@ -124,12 +98,11 @@ const utils = { * @private * @since 3.0.0 */ - _forRelation (opts, def, fn, thisArg) { + _forRelation (opts: any = {}, def, fn, thisArg) { const relationName = def.relation let containedName = null let index - opts || (opts = {}) - opts.with || (opts.with = []) + opts.with = opts.with || [] if ((index = utils._getIndex(opts.with, relationName)) >= 0) { containedName = relationName @@ -143,12 +116,12 @@ const utils = { } else if (!containedName) { return } - const optsCopy = {} + const optsCopy: any = {} utils.fillIn(optsCopy, def.getRelation()) utils.fillIn(optsCopy, opts) optsCopy.with = opts.with.slice() optsCopy._activeWith = optsCopy.with.splice(index, 1)[0] - optsCopy.with.forEach(function (relation, i) { + optsCopy.with.forEach((relation, i) => { if ( relation && relation.indexOf(containedName) === 0 && @@ -174,7 +147,7 @@ const utils = { */ _getIndex (list, relation) { let index = -1 - list.forEach(function (_relation, i) { + list.forEach((_relation, i) => { if (_relation === relation) { index = i return false @@ -210,7 +183,7 @@ const utils = { */ addHiddenPropsToTarget (target, props) { const map = {} - Object.keys(props).forEach(function (propName) { + Object.keys(props).forEach(propName => { const descriptor = Object.getOwnPropertyDescriptor(props, propName) descriptor.enumerable = false @@ -229,8 +202,8 @@ const utils = { * utils.areDifferent({ foo: 'bar' }, {}); // true * * @method utils.areDifferent - * @param {object} a Base object. - * @param {object} b Comparison object. + * @param newObject + * @param oldObject * @param {object} [opts] Configuration options. * @param {Function} [opts.equalsFn={@link utils.deepEqual}] Equality function. * @param {array} [opts.ignore=[]] Array of strings or RegExp of fields to ignore. @@ -238,42 +211,13 @@ const utils = { * @see utils.diffObjects * @since 3.0.0 */ - areDifferent (newObject, oldObject, opts) { - opts || (opts = {}) + areDifferent (newObject, oldObject, opts: any = {}) { const diff = utils.diffObjects(newObject, oldObject, opts) const diffCount = - Object.keys(diff.added).length + - Object.keys(diff.removed).length + - Object.keys(diff.changed).length + Object.keys(diff.added).length + Object.keys(diff.removed).length + Object.keys(diff.changed).length return diffCount > 0 }, - /** - * Verified that the given constructor is being invoked via `new`, as opposed - * to just being called like a normal function. - * - * @example - * import { utils } from 'js-data'; - * function Cat () { - * utils.classCallCheck(this, Cat); - * } - * const cat = new Cat(); // this is ok - * Cat(); // this throws an error - * - * @method utils.classCallCheck - * @param {*} instance Instance that is being constructed. - * @param {Constructor} ctor Constructor function used to construct the - * instance. - * @since 3.0.0 - * @throws {Error} Throws an error if the constructor is being improperly - * invoked. - */ - classCallCheck (instance, ctor) { - if (!(instance instanceof ctor)) { - throw utils.err(`${ctor.name}`)(500, 'Cannot call a class as a function') - } - }, - /** * Deep copy a value. * @@ -295,7 +239,7 @@ const utils = { * @returns {*} Deep copy of `from`. * @since 3.0.0 */ - copy (from, to, stackFrom, stackTo, blacklist, plain) { + copy (from, to?, stackFrom?, stackTo?, blacklist?, plain?) { if (!to) { to = from if (from) { @@ -310,23 +254,13 @@ const utils = { if (plain) { to = utils.copy(from, {}, stackFrom, stackTo, blacklist, plain) } else { - to = utils.copy( - from, - Object.create(Object.getPrototypeOf(from)), - stackFrom, - stackTo, - blacklist, - plain - ) + to = utils.copy(from, Object.create(Object.getPrototypeOf(from)), stackFrom, stackTo, blacklist, plain) } } } } else { if (from === to) { - throw utils.err(`${DOMAIN}.copy`)( - 500, - 'Cannot copy! Source and destination are identical.' - ) + throw utils.err(`${DOMAIN}.copy`)(500, 'Cannot copy! Source and destination are identical.') } stackFrom = stackFrom || [] @@ -347,14 +281,7 @@ const utils = { let i to.length = 0 for (i = 0; i < from.length; i++) { - result = utils.copy( - from[i], - null, - stackFrom, - stackTo, - blacklist, - plain - ) + result = utils.copy(from[i], null, stackFrom, stackTo, blacklist, plain) if (utils.isObject(from[i])) { stackFrom.push(from[i]) stackTo.push(result) @@ -365,23 +292,16 @@ const utils = { if (utils.isArray(to)) { to.length = 0 } else { - utils.forOwn(to, function (value, key) { + utils.forOwn(to, (value, key) => { delete to[key] }) } - for (var key in from) { - if (Object.hasOwnProperty.call(from, key)) { + for (const key in from) { + if (from.hasOwnProperty(key)) { if (utils.isBlacklisted(key, blacklist)) { continue } - result = utils.copy( - from[key], - null, - stackFrom, - stackTo, - blacklist, - plain - ) + result = utils.copy(from[key], null, stackFrom, stackTo, blacklist, plain) if (utils.isObject(from[key])) { stackFrom.push(from[key]) stackTo.push(result) @@ -412,13 +332,13 @@ const utils = { * @see utils.deepMixIn * @since 3.0.0 */ - deepFillIn (dest, source) { + deepFillIn (dest, source?) { if (source) { - utils.forOwn(source, function (value, key) { + utils.forOwn(source, (value, key) => { const existing = dest[key] if (isPlainObject(value) && isPlainObject(existing)) { utils.deepFillIn(existing, value) - } else if (!Object.hasOwnProperty.call(dest, key) || dest[key] === undefined) { + } else if (!dest.hasOwnProperty(key) || dest[key] === undefined) { dest[key] = value } }) @@ -443,9 +363,10 @@ const utils = { * @see utils.deepFillIn * @since 3.0.0 */ - deepMixIn (dest, source) { + deepMixIn (dest, source?) { if (source) { - for (var key in source) { + // tslint:disable-next-line:forin + for (const key in source) { const value = source[key] const existing = dest[key] if (isPlainObject(value) && isPlainObject(existing)) { @@ -480,8 +401,7 @@ const utils = { * @see utils.areDifferent * @since 3.0.0 */ - diffObjects (newObject, oldObject, opts) { - opts || (opts = {}) + diffObjects (newObject, oldObject, opts: any = {}) { let equalsFn = opts.equalsFn const blacklist = opts.ignore const diff = { @@ -493,15 +413,11 @@ const utils = { equalsFn = utils.deepEqual } - const newKeys = Object.keys(newObject).filter(function (key) { - return !utils.isBlacklisted(key, blacklist) - }) - const oldKeys = Object.keys(oldObject).filter(function (key) { - return !utils.isBlacklisted(key, blacklist) - }) + const newKeys = Object.keys(newObject).filter(key => !utils.isBlacklisted(key, blacklist)) + const oldKeys = Object.keys(oldObject).filter(key => !utils.isBlacklisted(key, blacklist)) // Check for properties that were added or changed - newKeys.forEach(function (key) { + newKeys.forEach(key => { const oldValue = oldObject[key] const newValue = newObject[key] if (equalsFn(oldValue, newValue)) { @@ -515,7 +431,7 @@ const utils = { }) // Check for properties that were removed - oldKeys.forEach(function (key) { + oldKeys.forEach(key => { const oldValue = oldObject[key] const newValue = newObject[key] if (newValue === undefined && oldValue !== undefined) { @@ -542,7 +458,8 @@ const utils = { * @since 3.0.0 */ equal (a, b) { - return a == b // eslint-disable-line + // tslint:disable-next-line:triple-equals + return a == b; // eslint-disable-line }, /** @@ -554,20 +471,17 @@ const utils = { * const errorFactory = utils.err('domain', 'target'); * const error400 = errorFactory(400, 'expected type', 'actual type'); * console.log(error400); // [Error: [domain:target] expected: expected type, found: string -http://www.js-data.io/v3.0/docs/errors#400] + * http://www.js-data.io/v3.0/docs/errors#400] * @method utils.err * @param {string} domain Namespace. * @param {string} target Target. * @returns {Function} Factory function. * @since 3.0.0 */ - err (domain, target) { - return function (code) { + err (domain, target?) { + return (code, ...args) => { const prefix = `[${domain}:${target}] ` - let message = ERRORS[code].apply( - null, - Array.prototype.slice.call(arguments, 1) - ) + let message = ERRORS[code].apply(null, args) message = `${prefix}${message} http://www.js-data.io/v3.0/docs/errors#${code}` return new Error(message) @@ -592,16 +506,12 @@ http://www.js-data.io/v3.0/docs/errors#${code}` * listeners. * @since 3.0.0 */ - eventify (target, getter, setter) { + eventify (target, getter?, setter?) { target = target || this let _events = {} if (!getter && !setter) { - getter = function () { - return _events - } - setter = function (value) { - _events = value - } + getter = () => _events + setter = value => (_events = value) } Object.defineProperties(target, { emit: { @@ -654,83 +564,6 @@ http://www.js-data.io/v3.0/docs/errors#${code}` }) }, - /** - * Used for sublcassing. Invoke this method in the context of a superclass to - * to produce a subclass based on `props` and `classProps`. - * - * @example - * import { utils } from 'js-data'; - * function Animal () {} - * Animal.extend = utils.extend; - * const Cat = Animal.extend({ - * say () { - * console.log('meow'); - * } - * }); - * const cat = new Cat(); - * cat instanceof Animal; // true - * cat instanceof Cat; // true - * cat.say(); // "meow" - * - * @method utils.extend - * @param {object} props Instance properties for the subclass. - * @param {object} [props.constructor] Provide a custom constructor function - * to use as the subclass. - * @param {object} props Static properties for the subclass. - * @returns {Constructor} A new subclass. - * @since 3.0.0 - */ - extend (props, classProps) { - const superClass = this - let subClass - - props || (props = {}) - classProps || (classProps = {}) - - if (Object.hasOwnProperty.call(props, 'constructor')) { - subClass = props.constructor - delete props.constructor - } else { - subClass = function (...args) { - utils.classCallCheck(this, subClass) - superClass.apply(this, args) - } - } - - // Setup inheritance of instance members - subClass.prototype = Object.create(superClass && superClass.prototype, { - constructor: { - configurable: true, - enumerable: false, - value: subClass, - writable: true - } - }) - - const obj = Object - // Setup inheritance of static members - if (obj.setPrototypeOf) { - obj.setPrototypeOf(subClass, superClass) - } else if (classProps.strictEs6Class) { - subClass.__proto__ = superClass // eslint-disable-line - } else { - utils.forOwn(superClass, function (value, key) { - subClass[key] = value - }) - } - if (!Object.hasOwnProperty.call(subClass, '__super__')) { - Object.defineProperty(subClass, '__super__', { - configurable: true, - value: superClass - }) - } - - utils.addHiddenPropsToTarget(subClass.prototype, props) - utils.fillIn(subClass, classProps) - - return subClass - }, - /** * Shallow copy own enumerable properties from `src` to `dest` that are on * `src` but are missing from `dest. @@ -744,14 +577,14 @@ http://www.js-data.io/v3.0/docs/errors#${code}` * * @method utils.fillIn * @param {object} dest The destination object. - * @param {object} source The source object. + * @param src * @see utils.deepFillIn * @see utils.deepMixIn * @since 3.0.0 */ fillIn (dest, src) { - utils.forOwn(src, function (value, key) { - if (!Object.hasOwnProperty.call(dest, key) || dest[key] === undefined) { + utils.forOwn(src, (value, key) => { + if (!dest.hasOwnProperty(key) || dest[key] === undefined) { dest[key] = value } }) @@ -784,7 +617,7 @@ http://www.js-data.io/v3.0/docs/errors#${code}` if (!array) { return index } - array.forEach(function (record, i) { + array.forEach((record, i) => { if (fn(record)) { index = i return false @@ -804,12 +637,12 @@ http://www.js-data.io/v3.0/docs/errors#${code}` * @param {*} thisArg Execution context for the callback function. * @since 3.0.0 */ - forEachRelation (mapper, opts, fn, thisArg) { + forEachRelation (mapper, opts, fn, thisArg?) { const relationList = mapper.relationList || [] if (!relationList.length) { return } - relationList.forEach(function (def) { + relationList.forEach(def => { utils._forRelation(opts, def, fn, thisArg) }) }, @@ -827,12 +660,12 @@ http://www.js-data.io/v3.0/docs/errors#${code}` * console.log(sum); // 5 * * @method utils.forOwn - * @param {object} object The object whose properties are to be enumerated. + * @param obj * @param {Function} fn Iteration function. * @param {object} [thisArg] Content to which to bind `fn`. * @since 3.0.0 */ - forOwn (obj, fn, thisArg) { + forOwn (obj, fn, thisArg?) { const keys = Object.keys(obj) const len = keys.length let i @@ -879,10 +712,14 @@ http://www.js-data.io/v3.0/docs/errors#${code}` * @see utils.set * @since 3.0.0 */ - get: function (object, prop) { + get (object, prop) { if (!prop) { return } + /* if prop is function, get the property by calling a function, passing an object as a parameter */ + if (utils.isFunction(prop)) { + return prop(object) + } const parts = prop.split('.') const last = parts.pop() @@ -925,12 +762,12 @@ http://www.js-data.io/v3.0/docs/errors#${code}` * @returns {Constructor} The superclass (grandparent constructor). * @since 3.0.0 */ - getSuper (instance, isCtor) { + getSuper (instance, isCtor?) { const ctor = isCtor ? instance : instance.constructor - if (Object.hasOwnProperty.call(ctor, '__super__')) { + if (ctor.hasOwnProperty('__super__')) { return ctor.__super__ } - return Object.getPrototypeOf(ctor) || ctor.__proto__ // eslint-disable-line + return Object.getPrototypeOf(ctor) || ctor.__proto__; // eslint-disable-line }, /** @@ -1012,11 +849,8 @@ http://www.js-data.io/v3.0/docs/errors#${code}` return false } let matches - for (var i = 0; i < blacklist.length; i++) { - if ( - (toStr(blacklist[i]) === REGEXP_TAG && blacklist[i].test(prop)) || - blacklist[i] === prop - ) { + for (const item of blacklist) { + if ((toStr(item) === REGEXP_TAG && item.test(prop)) || item === prop) { matches = prop return !!matches } @@ -1099,7 +933,8 @@ http://www.js-data.io/v3.0/docs/errors#${code}` * @since 3.0.0 */ isInteger (value) { - return toStr(value) === NUMBER_TAG && value == toInteger(value) // eslint-disable-line + // tslint:disable-next-line:triple-equals + return toStr(value) === NUMBER_TAG && value == toInteger(value); // eslint-disable-line }, /** @@ -1140,10 +975,7 @@ http://www.js-data.io/v3.0/docs/errors#${code}` */ isNumber (value) { const type = typeof value - return ( - type === 'number' || - (value && type === 'object' && toStr(value) === NUMBER_TAG) - ) + return type === 'number' || (value && type === 'object' && toStr(value) === NUMBER_TAG) }, /** @@ -1222,10 +1054,7 @@ http://www.js-data.io/v3.0/docs/errors#${code}` * @since 3.0.0 */ isString (value) { - return ( - typeof value === 'string' || - (value && typeof value === 'object' && toStr(value) === STRING_TAG) - ) + return typeof value === 'string' || (value && typeof value === 'object' && toStr(value) === STRING_TAG) }, /** @@ -1284,8 +1113,7 @@ http://www.js-data.io/v3.0/docs/errors#${code}` if (level === 'debug' && !this.debug) { return } - const prefix = `${level.toUpperCase()}: (${this.name || - this.constructor.name})` + const prefix = `${level.toUpperCase()}: (${this.name || this.constructor.name})` if (utils.isFunction(console[level])) { console[level](prefix, ...args) } else { @@ -1316,7 +1144,7 @@ http://www.js-data.io/v3.0/docs/errors#${code}` * @param {Function} fn Callback function passed to {@link utils.findIndex}. * @since 3.0.0 */ - noDupeAdd (array, record, fn) { + noDupeAdd (array, record?, fn?) { if (!array) { return } @@ -1345,7 +1173,7 @@ http://www.js-data.io/v3.0/docs/errors#${code}` */ omit (props, keys) { const _props = {} - utils.forOwn(props, function (value, key) { + utils.forOwn(props, (value, key) => { if (keys.indexOf(key) === -1) { _props[key] = value } @@ -1411,11 +1239,9 @@ http://www.js-data.io/v3.0/docs/errors#${code}` * @method utils.reject * @param {*} [value] Value with which to reject the Promise. * @returns {Promise} Promise reject with `value`. - * @see utils.Promise - * @since 3.0.0 */ reject (value) { - return utils.Promise.reject(value) + return Promise.reject(value) }, /** @@ -1432,7 +1258,7 @@ http://www.js-data.io/v3.0/docs/errors#${code}` * @param {array} array The array to search. * @param {Function} fn Checker function. */ - remove (array, fn) { + remove (array, fn?) { if (!array || !array.length) { return } @@ -1456,11 +1282,9 @@ http://www.js-data.io/v3.0/docs/errors#${code}` * * @param {*} [value] Value with which to resolve the Promise. * @returns {Promise} Promise resolved with `value`. - * @see utils.Promise - * @since 3.0.0 */ - resolve (value) { - return utils.Promise.resolve(value) + resolve (value?) { + return Promise.resolve(value) }, /** @@ -1502,9 +1326,9 @@ http://www.js-data.io/v3.0/docs/errors#${code}` * object. * @param {*} [value] The value to set. */ - set: function (object, path, value) { + set (object, path, value?, opts?) { if (utils.isObject(path)) { - utils.forOwn(path, function (value, _path) { + utils.forOwn(path, (value, _path) => { utils.set(object, _path, value) }) } else { @@ -1568,14 +1392,14 @@ http://www.js-data.io/v3.0/docs/errors#${code}` } } } else if (utils.isObject(a) && utils.isObject(b)) { - utils.forOwn(a, function (value, key) { + utils.forOwn(a, (value, key) => { if (!(_equal = utils.deepEqual(value, b[key]))) { // Exit loop early return false } }) if (_equal) { - utils.forOwn(b, function (value, key) { + utils.forOwn(b, (value, key) => { if (!(_equal = utils.deepEqual(value, a[key]))) { // Exit loop early return false @@ -1633,7 +1457,7 @@ http://www.js-data.io/v3.0/docs/errors#${code}` * @see utils.set * @since 3.0.0 */ - unset (object, path) { + unset (object, path: string) { const parts = path.split('.') const last = parts.pop() @@ -1647,19 +1471,34 @@ http://www.js-data.io/v3.0/docs/errors#${code}` } object[last] = undefined + }, + /** + * Gets default locale for the js-data context. + * + * @example + * import { utils } from 'js-data'; + * + * + * utils.getDefaultLocale(); + * + * @method utils.getDefaultLocale + * @since 4.0.0 + */ + getDefaultLocale () { + return 'en' } } -export const safeSetProp = function (record, field, value) { - if (record && record._set) { +export const safeSetProp = (record, field, value) => { + if (record?._set) { record._set(`props.${field}`, value) } else { utils.set(record, field, value) } } -export const safeSetLink = function (record, field, value) { - if (record && record._set) { +export const safeSetLink = (record, field, value) => { + if (record?._set) { record._set(`links.${field}`, value) } else { utils.set(record, field, value) diff --git a/test/_setup.js b/test/_setup.ts similarity index 84% rename from test/_setup.js rename to test/_setup.ts index 5370af3a..b1c82504 100644 --- a/test/_setup.js +++ b/test/_setup.ts @@ -1,8 +1,8 @@ import { assert } from 'chai' import * as JSData from '../src/index' -import sinon from 'sinon' +import sinon = require('sinon'); -assert.objectsEqual = function (a, b, msg) { +export function objectsEqual (a, b, msg?) { assert.deepEqual( JSON.parse(JSON.stringify(a)), JSON.parse(JSON.stringify(b)), @@ -10,7 +10,7 @@ assert.objectsEqual = function (a, b, msg) { ) } -assert.objectsNotEqual = function (a, b, msg) { +export function objectsNotEqual (a, b, msg?) { assert.notDeepEqual( JSON.parse(JSON.stringify(a)), JSON.parse(JSON.stringify(b)), @@ -18,34 +18,30 @@ assert.objectsNotEqual = function (a, b, msg) { ) } -assert.fail = function (msg) { +assert.fail = msg => { assert.equal('should not reach this!: ' + msg, 'failure') } // Setup global data once -export { - assert, - JSData, - sinon -} -export const TYPES_EXCEPT_STRING = [123, 123.123, null, undefined, {}, [], true, false, function () {}] -export const TYPES_EXCEPT_STRING_OR_ARRAY = [123, 123.123, null, undefined, {}, true, false, function () {}] -export const TYPES_EXCEPT_STRING_OR_NUMBER = [null, undefined, {}, [], true, false, function () {}] -export const TYPES_EXCEPT_STRING_OR_OBJECT = [123, 123.123, null, undefined, [], true, false, function () {}] -export const TYPES_EXCEPT_STRING_OR_NUMBER_OBJECT = [null, undefined, [], true, false, function () {}] -export const TYPES_EXCEPT_ARRAY = ['string', 123, 123.123, null, undefined, {}, true, false, function () {}] -export const TYPES_EXCEPT_STRING_OR_ARRAY_OR_NUMBER = [null, undefined, {}, true, false, function () {}] -export const TYPES_EXCEPT_NUMBER = ['string', null, undefined, {}, [], true, false, function () {}] -export const TYPES_EXCEPT_OBJECT = ['string', 123, 123.123, null, undefined, true, false, function () {}] -export const TYPES_EXCEPT_OBJECT_OR_ARRAY = ['string', 123, 123.123, null, undefined, true, false, function () {}] -export const TYPES_EXCEPT_BOOLEAN = ['string', 123, 123.123, null, undefined, {}, [], function () {}] +export { assert, JSData, sinon } +export const TYPES_EXCEPT_STRING = [123, 123.123, null, undefined, {}, [], true, false, () => {}] +export const TYPES_EXCEPT_STRING_OR_ARRAY = [123, 123.123, null, undefined, {}, true, false, () => {}] +export const TYPES_EXCEPT_STRING_OR_NUMBER = [null, undefined, {}, [], true, false, () => {}] +export const TYPES_EXCEPT_STRING_OR_OBJECT = [123, 123.123, null, undefined, [], true, false, () => {}] +export const TYPES_EXCEPT_STRING_OR_NUMBER_OBJECT = [null, undefined, [], true, false, () => {}] +export const TYPES_EXCEPT_ARRAY = ['string', 123, 123.123, null, undefined, {}, true, false, () => {}] +export const TYPES_EXCEPT_STRING_OR_ARRAY_OR_NUMBER = [null, undefined, {}, true, false, () => {}] +export const TYPES_EXCEPT_NUMBER = ['string', null, undefined, {}, [], true, false, () => {}] +export const TYPES_EXCEPT_OBJECT = ['string', 123, 123.123, null, undefined, true, false, () => {}] +export const TYPES_EXCEPT_OBJECT_OR_ARRAY = ['string', 123, 123.123, null, undefined, true, false, () => {}] +export const TYPES_EXCEPT_BOOLEAN = ['string', 123, 123.123, null, undefined, {}, [], () => {}] export const TYPES_EXCEPT_FUNCTION = ['string', 123, 123.123, null, undefined, {}, [], true, false] export function createRelation (name, defs) { return { [name]: defs } } -export function createStore (options) { +export function createStore (options?) { const store = new JSData.DataStore(options) registerInMemoryAdapterFor(store) @@ -60,8 +56,9 @@ export function createMapper (options) { } let idCounter = 1 + function generateId () { - return Date.now() + (idCounter++) + return Date.now() + idCounter++ } function createInMemoryAdapter () { @@ -111,9 +108,9 @@ beforeEach(function () { this.data.p3 = { author: 'Mike', age: 32, id: 7 } this.data.p4 = { author: 'Adam', age: 33, id: 8 } this.data.p5 = { author: 'Adam', age: 33, id: 9 } - const store = this.store = new JSData.DataStore({ + const store = (this.store = new JSData.DataStore({ linkRelations: true - }) + })) this.Post = store.defineMapper('post', { endpoint: '/posts' }) @@ -249,11 +246,7 @@ beforeEach(function () { name: 'John Anderson', id: 10, organizationId: 14, - comments: [ - this.data.comment11, - this.data.comment12, - this.data.comment13 - ], + comments: [this.data.comment11, this.data.comment12, this.data.comment13], organization: this.data.organization14, profile: this.data.profile15 } @@ -290,11 +283,7 @@ beforeEach(function () { this.data.organization15 = { name: 'Another Test Corp', id: 15, - users: [ - this.data.user16, - this.data.user17, - this.data.user18 - ] + users: [this.data.user16, this.data.user17, this.data.user18] } this.data.user19 = { id: 19, @@ -324,19 +313,20 @@ beforeEach(function () { } }) -after(function () { // eslint-disable-line - var tests = [] - var duration = 0 - var passed = 0 - var failed = 0 - this.test.parent.suites.forEach(function (suite) { - suite.tests.forEach(function (test) { +after(function () { + // eslint-disable-line + const tests = [] + let duration = 0 + let passed = 0 + let failed = 0 + this.test.parent.suites.forEach(suite => { + suite.tests.forEach((test: any) => { if (test.state !== 'passed' && test.state !== 'failed') { return } duration += test.duration - var report = { + const report = { name: suite.title + ':' + test.title, result: test.state === 'passed', message: test.state, @@ -355,13 +345,12 @@ after(function () { // eslint-disable-line }) }) try { - window.global_test_results = { - passed: passed, - failed: failed, + (window as any).global_test_results = { + passed, + failed, total: passed + failed, - duration: duration, - tests: tests + duration, + tests } - } catch (err) { - } + } catch (err) {} }) diff --git a/test/integration/collection.test.js b/test/integration/collection.test.ts similarity index 80% rename from test/integration/collection.test.js rename to test/integration/collection.test.ts index f0adfae6..388f88c5 100644 --- a/test/integration/collection.test.js +++ b/test/integration/collection.test.ts @@ -1,12 +1,9 @@ import { assert, JSData, sinon } from '../_setup' -describe('Collection integration tests', function () { - it('should emit add events', function (done) { +describe('Collection integration tests', () => { + it('should emit add events', done => { const mapper = new JSData.Mapper({ name: 'user' }) - const data = [ - mapper.createRecord({ id: 2, age: 19 }), - mapper.createRecord({ id: 1, age: 27 }) - ] + const data = [mapper.createRecord({ id: 2, age: 19 }), mapper.createRecord({ id: 1, age: 27 })] const collection = new JSData.Collection([], { mapper }) @@ -24,12 +21,9 @@ describe('Collection integration tests', function () { }, 30) }) - it('should not emit add events', function (done) { + it('should not emit add events', done => { const mapper = new JSData.Mapper({ name: 'user' }) - const data = [ - mapper.createRecord({ id: 2, age: 19 }), - mapper.createRecord({ id: 1, age: 27 }) - ] + const data = [mapper.createRecord({ id: 2, age: 19 }), mapper.createRecord({ id: 1, age: 27 })] const collection = new JSData.Collection(data, { mapper }) @@ -47,7 +41,7 @@ describe('Collection integration tests', function () { }, 30) }) - it('should emit remove events', function (done) { + it('should emit remove events', done => { const mapper = new JSData.Mapper({ name: 'user' }) const data = mapper.createRecord({ id: 2, age: 19 }) const collection = new JSData.Collection([], { @@ -68,12 +62,9 @@ describe('Collection integration tests', function () { }, 30) }) - it('should bubble up record events', function (done) { + it('should bubble up record events', done => { const mapper = new JSData.Mapper({ name: 'user' }) - const data = [ - mapper.createRecord({ id: 2, age: 19 }), - mapper.createRecord({ id: 1, age: 27 }) - ] + const data = [mapper.createRecord({ id: 2, age: 19 }), mapper.createRecord({ id: 1, age: 27 })] const collection = new JSData.Collection(data, { mapper }) @@ -86,17 +77,18 @@ describe('Collection integration tests', function () { assert(listener.calledOnce, 'listener should have been called once') assert.deepEqual(listener.firstCall.args, ['bar', 'biz', 'baz'], 'should have been called with the correct args') assert(listener2.calledOnce, 'listener2 should have been called once') - assert.deepEqual(listener2.firstCall.args, ['foo', 'bar', 'biz', 'baz'], 'should have been called with the correct args') + assert.deepEqual( + listener2.firstCall.args, + ['foo', 'bar', 'biz', 'baz'], + 'should have been called with the correct args' + ) done() }, 30) }) - it('should not bubble up record events', function (done) { + it('should not bubble up record events', done => { const mapper = new JSData.Mapper({ name: 'user' }) - const data = [ - mapper.createRecord({ id: 2, age: 19 }), - mapper.createRecord({ id: 1, age: 27 }) - ] + const data = [mapper.createRecord({ id: 2, age: 19 }), mapper.createRecord({ id: 1, age: 27 })] const collection = new JSData.Collection(data, { emitRecordEvents: false, mapper @@ -113,7 +105,7 @@ describe('Collection integration tests', function () { }, 30) }) - it('should bubble up change events (assignment operator)', function (done) { + it('should bubble up change events (assignment operator)', done => { let changed = false const store = new JSData.DataStore() store.defineMapper('foo', { @@ -139,7 +131,7 @@ describe('Collection integration tests', function () { foo.bar = 'baz' }) - it('should bubble up change events (setter method)', function (done) { + it('should bubble up change events (setter method)', done => { let changed = false const store = new JSData.DataStore() store.defineMapper('foo', { diff --git a/test/integration/datastore.test.js b/test/integration/datastore.test.ts similarity index 91% rename from test/integration/datastore.test.js rename to test/integration/datastore.test.ts index 558a7c52..6a51dcb2 100644 --- a/test/integration/datastore.test.js +++ b/test/integration/datastore.test.ts @@ -1,7 +1,7 @@ -import { assert, JSData } from '../_setup' +import { assert, JSData, objectsEqual } from '../_setup' -describe('DataStore integration tests', function () { - it('relation links should stay up-to-date', function () { +describe('DataStore integration tests', () => { + it('relation links should stay up-to-date', () => { const store = new JSData.DataStore() store.defineMapper('foo', { schema: { @@ -67,7 +67,7 @@ describe('DataStore integration tests', function () { assert.equal(bar88.foo_id, 66) assert.deepEqual(foo77.bars, []) }) - it('should allow enhanced relation getters', function () { + it('should allow enhanced relation getters', () => { let wasItActivated = false const store = new JSData.DataStore({ linkRelations: true @@ -107,7 +107,7 @@ describe('DataStore integration tests', function () { assert.equal(foo.bar.id, 1) assert(wasItActivated) }) - it('should configure enumerability and linking of relations', function () { + it('should configure enumerability and linking of relations', () => { const store = new JSData.DataStore() store.defineMapper('parent', { relations: { @@ -178,7 +178,11 @@ describe('DataStore integration tests', function () { assert(!foundParent, 'parent is NOT enumerable') foundParent = false for (k in otherChild) { - if (k === 'parent' && otherChild[k] === otherChild.parent && otherChild[k] === store.get('parent', otherChild.parentId)) { + if ( + k === 'parent' && + otherChild[k] === otherChild.parent && + otherChild[k] === store.get('parent', otherChild.parentId) + ) { foundParent = true } } @@ -230,7 +234,7 @@ describe('DataStore integration tests', function () { this.UserCollection.remove(22) assert(!this.ProfileCollection.get(21).user) }) - it('should emit change events', function (done) { + it('should emit change events', done => { const store = new JSData.DataStore() let handlersCalled = 0 store.defineMapper('foo', { @@ -244,7 +248,7 @@ describe('DataStore integration tests', function () { const foo = store.add('foo', { id: 1 }) assert.equal(foo.bar, undefined) - store.on('change', function (mapperName, record, changes) { + store.on('change', (mapperName, record, changes) => { assert.equal(mapperName, 'foo') assert.strictEqual(record, foo) try { @@ -255,7 +259,7 @@ describe('DataStore integration tests', function () { handlersCalled++ }) - store.getCollection('foo').on('change', function (record, changes) { + store.getCollection('foo').on('change', (record, changes) => { assert.strictEqual(record, foo) try { assert.deepEqual(changes, { added: { bar: 'baz' }, changed: {}, removed: {} }) @@ -275,14 +279,14 @@ describe('DataStore integration tests', function () { handlersCalled++ }) - store.on('change:bar', function (mapperName, record, value) { + store.on('change:bar', (mapperName, record, value) => { assert.equal(mapperName, 'foo') assert.strictEqual(record, foo) assert(value === 'baz' || value === 'beep') handlersCalled++ }) - store.getCollection('foo').on('change:bar', function (record, value) { + store.getCollection('foo').on('change:bar', (record, value) => { assert.strictEqual(record, foo) assert(value === 'baz' || value === 'beep') handlersCalled++ @@ -314,7 +318,7 @@ describe('DataStore integration tests', function () { } }, 500) }) - it('should add relations', function () { + it('should add relations', () => { const store = new JSData.DataStore() store.defineMapper('foo', { schema: { @@ -394,7 +398,7 @@ describe('DataStore integration tests', function () { assert.equal(store.unsaved('bar').length, 1) assert.equal(store.unsaved('foo').length, 1) }) - it('should correctly unlink inverse records', function () { + it('should correctly unlink inverse records', () => { const store = new JSData.DataStore() store.defineMapper('A', { @@ -429,28 +433,34 @@ describe('DataStore integration tests', function () { }) const aRecord = store.add('A', { uid: 'a1' }) - const bRecords = store.add('B', [{ uid: 'b1', a_uid: 'a1' }, { uid: 'b2', a_uid: 'a1' }]) - assert.objectsEqual(aRecord.b, bRecords) + const bRecords = store.add('B', [ + { uid: 'b1', a_uid: 'a1' }, + { uid: 'b2', a_uid: 'a1' } + ]) + objectsEqual(aRecord.b, bRecords) assert.strictEqual(bRecords[0].a, aRecord) assert.strictEqual(bRecords[1].a, aRecord) const aRecord2 = store.add('A', { uid: 'a2' }) - const bRecords2 = store.add('B', [{ uid: 'b3', a_uid: 'a2' }, { uid: 'b4', a_uid: 'a2' }]) - assert.objectsEqual(aRecord2.b, bRecords2) + const bRecords2 = store.add('B', [ + { uid: 'b3', a_uid: 'a2' }, + { uid: 'b4', a_uid: 'a2' } + ]) + objectsEqual(aRecord2.b, bRecords2) assert.strictEqual(bRecords2[0].a, aRecord2) assert.strictEqual(bRecords2[1].a, aRecord2) store.remove('B', 'b2') - assert.objectsEqual(aRecord.b, [bRecords[0]]) + objectsEqual(aRecord.b, [bRecords[0]]) assert.strictEqual(bRecords[0].a, aRecord) assert.strictEqual(bRecords[1].a, undefined) store.remove('A', 'a2') - assert.objectsEqual(aRecord2.b, []) + objectsEqual(aRecord2.b, []) assert.equal(bRecords2[0].a, undefined) assert.equal(bRecords2[1].a, undefined) }) - it('should add property accessors to prototype of target and allow relation re-assignment using defaults', function () { + it('should add property accessors to prototype of target and allow relation re-assignment using defaults', () => { const store = new JSData.DataStore() store.defineMapper('foo', { relations: { @@ -487,10 +497,9 @@ describe('DataStore integration tests', function () { assert.strictEqual(bar3.foo, foo) }) - it('should not create an inverseLink if no inverseRelationship is defined', function () { + it('should not create an inverseLink if no inverseRelationship is defined', () => { const store = new JSData.DataStore() - store.defineMapper('foo', { - }) + store.defineMapper('foo', {}) store.defineMapper('bar', { relations: { belongsTo: { @@ -506,7 +515,7 @@ describe('DataStore integration tests', function () { assert.strictEqual(bar._foo, foo) }) - it('should add property accessors to prototype of target and allow relation re-assignment using customizations', function () { + it('should add property accessors to prototype of target and allow relation re-assignment using customizations', () => { const store = new JSData.DataStore() store.defineMapper('foo', { relations: { @@ -542,7 +551,7 @@ describe('DataStore integration tests', function () { assert.strictEqual(bar2._foo, foo) assert.strictEqual(bar3._foo, foo) }) - it('should allow custom getter and setter', function () { + it('should allow custom getter and setter', () => { const store = new JSData.DataStore() store.defineMapper('foo', { relations: { @@ -560,11 +569,11 @@ describe('DataStore integration tests', function () { foo: { localField: '_foo', foreignKey: 'fooId', - get: function (Relation, bar, originalGet) { + get: (Relation, bar, originalGet) => { getCalled++ return originalGet() }, - set: function (Relation, bar, foo, originalSet) { + set: (Relation, bar, foo, originalSet) => { setCalled++ originalSet() } @@ -590,7 +599,7 @@ describe('DataStore integration tests', function () { assert.equal(getCalled, 11) assert.equal(setCalled, 4) }) - it('supports tree-like relations', function () { + it('supports tree-like relations', () => { const store = new JSData.DataStore() store.defineMapper('node', { @@ -654,7 +663,7 @@ describe('DataStore integration tests', function () { assert.deepEqual(nodes[4].children, []) }) - it('should find hasMany foreignKeys with custom idAttribute', function () { + it('should find hasMany foreignKeys with custom idAttribute', () => { const store = new JSData.DataStore() store.defineMapper('foo', { diff --git a/test/integration/schema.test.js b/test/integration/schema.test.js deleted file mode 100644 index d9635b87..00000000 --- a/test/integration/schema.test.js +++ /dev/null @@ -1,54 +0,0 @@ -import { assert, JSData } from '../_setup' - -describe('Mapper#update', function () { - it('should update', async function () { - const id = 1 - const props = { name: 'John' } - const propsUpdate = { name: 'Bill', foo: undefined } - let updateCalled = false - let createCalled = false - const schema = new JSData.Schema({ - type: 'object', - track: true, - properties: { - name: { type: 'string' }, - foo: { type: 'string' } - } - }) - const store = new JSData.DataStore() - store.registerAdapter('mock', { - update (mapper, _id, _props, Opts) { - updateCalled = true - return new Promise(function (resolve, reject) { - assert.strictEqual(mapper, User, 'should pass in the Mapper') - assert.deepEqual(_id, id, 'should pass in the id') - assert.deepEqual(_props, propsUpdate, 'should pass in the props') - assert.equal(Opts.raw, false, 'Opts are provided') - _props.foo = 'bar' - _props.id = id - resolve(_props) - }) - }, - create (mapper, _props, Opts) { - createCalled = true - return new Promise(function (resolve, reject) { - assert.strictEqual(mapper, User, 'should pass in the JSData.Mapper') - assert.objectsEqual(_props, props, 'should pass in the props') - assert(!Opts.raw, 'Opts are provided') - _props[mapper.idAttribute] = id - resolve(_props) - }) - } - }, { default: true }) - const User = store.defineMapper('user', { schema }) - const rec = store.createRecord('user', { name: 'John' }) - const user = await rec.save() - assert(createCalled, 'Adapter#create should have been called') - assert(user instanceof User.recordClass, 'user is a record') - user.name = 'Bill' - const u2 = await user.save() - assert(updateCalled, 'Adapter#update should have been called') - assert.equal(user.foo, 'bar', 'user has a new field') - assert(u2 instanceof User.recordClass, 'user is a record') - }) -}) diff --git a/test/integration/schema.test.ts b/test/integration/schema.test.ts new file mode 100644 index 00000000..dda0afdb --- /dev/null +++ b/test/integration/schema.test.ts @@ -0,0 +1,58 @@ +import { assert, JSData, objectsEqual } from '../_setup' + +describe('Mapper#update', () => { + it('should update', async () => { + const id = 1 + const props = { name: 'John' } + const propsUpdate = { name: 'Bill', foo: undefined } + let updateCalled = false + let createCalled = false + const schema = new JSData.Schema({ + type: 'object', + track: true, + properties: { + name: { type: 'string' }, + foo: { type: 'string' } + } + }) + const store = new JSData.DataStore() + store.registerAdapter( + 'mock', + { + update (mapper, _id, _props, Opts) { + updateCalled = true + return new Promise((resolve, reject) => { + assert.strictEqual(mapper, User, 'should pass in the Mapper') + assert.deepEqual(_id, id, 'should pass in the id') + assert.deepEqual(_props, propsUpdate, 'should pass in the props') + assert.equal(Opts.raw, false, 'Opts are provided') + _props.foo = 'bar' + _props.id = id + resolve(_props) + }) + }, + create (mapper, _props, Opts) { + createCalled = true + return new Promise((resolve, reject) => { + assert.strictEqual(mapper, User, 'should pass in the JSData.Mapper') + objectsEqual(_props, props, 'should pass in the props') + assert(!Opts.raw, 'Opts are provided') + _props[mapper.idAttribute] = id + resolve(_props) + }) + } + }, + { default: true } + ) + const User = store.defineMapper('user', { schema }) + const rec = store.createRecord('user', { name: 'John' }) + const user = await rec.save() + assert(createCalled, 'Adapter#create should have been called') + assert(user instanceof User.recordClass, 'user is a record') + user.name = 'Bill' + const u2 = await user.save() + assert(updateCalled, 'Adapter#update should have been called') + assert.equal(user.foo, 'bar', 'user has a new field') + assert(u2 instanceof User.recordClass, 'user is a record') + }) +}) diff --git a/test/unit/collection/add.test.js b/test/unit/collection/add.test.ts similarity index 67% rename from test/unit/collection/add.test.js rename to test/unit/collection/add.test.ts index ee81acd7..cfed5e98 100644 --- a/test/unit/collection/add.test.js +++ b/test/unit/collection/add.test.ts @@ -1,75 +1,105 @@ -import { assert, JSData, TYPES_EXCEPT_OBJECT_OR_ARRAY } from '../../_setup' +import { assert, JSData, objectsEqual, TYPES_EXCEPT_OBJECT_OR_ARRAY } from '../../_setup' -describe('Collection#add', function () { - it('should inject new items into the collection', function () { +describe('Collection#add', () => { + it('should inject new items into the collection', () => { const collection = new JSData.Collection() const user = collection.add({ id: 1 }) const users = collection.add([{ id: 2 }, { id: 3 }]) assert(collection.get(1) === user) - assert.deepEqual(collection.between([2], [3], { - rightInclusive: true - }), users) + assert.deepEqual( + collection.between([2], [3], { + rightInclusive: true + }), + users + ) }) it('should inject multiple items into the collection', function () { - assert.objectsEqual(this.PostCollection.add([ + objectsEqual(this.PostCollection.add([this.data.p1, this.data.p2, this.data.p3, this.data.p4]), [ this.data.p1, this.data.p2, this.data.p3, this.data.p4 - ]), [this.data.p1, this.data.p2, this.data.p3, this.data.p4]) + ]) - assert.objectsEqual(this.PostCollection.get(5), this.data.p1) - assert.objectsEqual(this.PostCollection.get(6), this.data.p2) - assert.objectsEqual(this.PostCollection.get(7), this.data.p3) - assert.objectsEqual(this.PostCollection.get(8), this.data.p4) + objectsEqual(this.PostCollection.get(5), this.data.p1) + objectsEqual(this.PostCollection.get(6), this.data.p2) + objectsEqual(this.PostCollection.get(7), this.data.p3) + objectsEqual(this.PostCollection.get(8), this.data.p4) }) it('should allow unsaved records into the collection', function () { - assert.objectsEqual(this.PostCollection.add([ - this.data.p1, - this.data.p2, - { author: 'Alice' }, - this.data.p3, - { author: 'Bob' }, - this.data.p4 - ]), [this.data.p1, this.data.p2, { author: 'Alice' }, this.data.p3, { author: 'Bob' }, this.data.p4]) + objectsEqual( + this.PostCollection.add([ + this.data.p1, + this.data.p2, + { author: 'Alice' }, + this.data.p3, + { author: 'Bob' }, + this.data.p4 + ]), + [this.data.p1, this.data.p2, { author: 'Alice' }, this.data.p3, { author: 'Bob' }, this.data.p4] + ) - assert.objectsEqual(this.PostCollection.get(5), this.data.p1) - assert.objectsEqual(this.PostCollection.get(6), this.data.p2) - assert.objectsEqual(this.PostCollection.get(7), this.data.p3) - assert.objectsEqual(this.PostCollection.get(8), this.data.p4) - assert.objectsEqual(this.PostCollection.filter({ - id: undefined - }).length, 2) - assert.objectsEqual(this.PostCollection.filter({ - id: undefined - })[0], { author: 'Bob' }) - assert.objectsEqual(this.PostCollection.filter({ - id: undefined - })[1], { author: 'Alice' }) - assert.objectsEqual(this.PostCollection.filter({ - id: undefined - })[0], { author: 'Bob' }) - assert.objectsEqual(this.PostCollection.filter().length, 6) + objectsEqual(this.PostCollection.get(5), this.data.p1) + objectsEqual(this.PostCollection.get(6), this.data.p2) + objectsEqual(this.PostCollection.get(7), this.data.p3) + objectsEqual(this.PostCollection.get(8), this.data.p4) + objectsEqual( + this.PostCollection.filter({ + id: undefined + }).length, + 2 + ) + objectsEqual( + this.PostCollection.filter({ + id: undefined + })[0], + { author: 'Bob' } + ) + objectsEqual( + this.PostCollection.filter({ + id: undefined + })[1], + { author: 'Alice' } + ) + objectsEqual( + this.PostCollection.filter({ + id: undefined + })[0], + { author: 'Bob' } + ) + objectsEqual(this.PostCollection.filter().length, 6) this.PostCollection.add({ author: 'Bob' }) - assert.objectsEqual(this.PostCollection.filter({ - id: undefined - }).length, 3) - assert.objectsEqual(this.PostCollection.filter({ - author: 'Bob' - }).length, 2) - assert.objectsEqual(this.PostCollection.filter().length, 7) + objectsEqual( + this.PostCollection.filter({ + id: undefined + }).length, + 3 + ) + objectsEqual( + this.PostCollection.filter({ + author: 'Bob' + }).length, + 2 + ) + objectsEqual(this.PostCollection.filter().length, 7) this.PostCollection.add({ author: 'Bob' }) - assert.objectsEqual(this.PostCollection.filter({ - id: undefined - }).length, 4) - assert.objectsEqual(this.PostCollection.filter({ - author: 'Bob' - }).length, 3) - assert.objectsEqual(this.PostCollection.filter().length, 8) + objectsEqual( + this.PostCollection.filter({ + id: undefined + }).length, + 4 + ) + objectsEqual( + this.PostCollection.filter({ + author: 'Bob' + }).length, + 3 + ) + objectsEqual(this.PostCollection.filter().length, 8) }) - it('should inject existing items into the collection and call Record#commit', function () { + it('should inject existing items into the collection and call Record#commit', () => { const collection = new JSData.Collection({ mapper: new JSData.Mapper({ name: 'user' }) }) const user = collection.add({ id: 1 }) @@ -83,15 +113,23 @@ describe('Collection#add', function () { assert(collection.get(1) === user, 'original reference should still be valid') assert(collection.get(1) === userAgain, 'new reference should be valid') assert(user === userAgain, 'both references should point to the same object') - assert.deepEqual(collection.between([2], [3], { - rightInclusive: true - }), users, 'injection of array should work') - assert.deepEqual(collection.between([2], [3], { - rightInclusive: true - }), usersAgain, 're-inject of array should work') + assert.deepEqual( + collection.between([2], [3], { + rightInclusive: true + }), + users, + 'injection of array should work' + ) + assert.deepEqual( + collection.between([2], [3], { + rightInclusive: true + }), + usersAgain, + 're-inject of array should work' + ) assert.deepEqual(users, usersAgain, 'inject arrays should be equal') }) - it('should insert a record into all indexes', function () { + it('should insert a record into all indexes', () => { const data = [ { id: 2, age: 19 }, { id: 1, age: 27 } @@ -102,20 +140,24 @@ describe('Collection#add', function () { assert(collection.get(1) === data[1]) assert.equal(collection.getAll(20, { index: 'age' }).length, 1) }) - it('should not require an id', function () { + it('should not require an id', () => { const collection = new JSData.Collection() assert.doesNotThrow(() => { collection.add({}) }) }) - it('should test opts.onConflict', function () { + it('should test opts.onConflict', () => { const collection = new JSData.Collection() collection.add({ id: 1 }) - assert.throws(() => { - collection.add({ id: 1 }, { onConflict: 'invalid_choice' }) - }, Error, '[Collection#add:opts.onConflict] expected: one of (merge, replace, skip), found: invalid_choice\nhttp://www.js-data.io/v3.0/docs/errors#400') + assert.throws( + () => { + collection.add({ id: 1 }, { onConflict: 'invalid_choice' }) + }, + Error, + '[Collection#add:opts.onConflict] expected: one of (merge, replace, skip), found: invalid_choice\nhttp://www.js-data.io/v3.0/docs/errors#400' + ) }) - it('should respect opts.noValidate', function () { + it('should respect opts.noValidate', () => { const mapper = new JSData.Mapper({ name: 'user', noValidate: false, @@ -136,15 +178,19 @@ describe('Collection#add', function () { // original noValidate prop value should be restored assert.equal(user._get('noValidate'), false) }) - it('should required an argument', function () { + it('should required an argument', () => { const collection = new JSData.Collection() - TYPES_EXCEPT_OBJECT_OR_ARRAY.forEach((value) => { - assert.throws(() => { - collection.add(value) - }, Error, `[Collection#add:records] expected: object or array, found: ${typeof value}\nhttp://www.js-data.io/v3.0/docs/errors#400`) + TYPES_EXCEPT_OBJECT_OR_ARRAY.forEach(value => { + assert.throws( + () => { + collection.add(value) + }, + Error, + `[Collection#add:records] expected: object or array, found: ${typeof value}\nhttp://www.js-data.io/v3.0/docs/errors#400` + ) }) }) - it('should replace existing items', function () { + it('should replace existing items', () => { const collection = new JSData.Collection({ mapper: new JSData.Mapper({ name: 'user' }) }) const user = collection.add({ id: 1, foo: 'bar', beep: 'boop' }) assert.equal(user.id, 1) @@ -184,7 +230,7 @@ describe('Collection#add', function () { let post = this.PostCollection.add(this.data.p1) post.foo = 'bar' post.beep = 'boop' - assert.objectsEqual(post, { + objectsEqual(post, { author: 'John', age: 30, id: 5, @@ -192,13 +238,13 @@ describe('Collection#add', function () { beep: 'boop' }) post = this.PostCollection.add(this.data.p1, { onConflict: 'replace' }) - assert.objectsEqual(post, { + objectsEqual(post, { author: 'John', age: 30, id: 5 }) }) - it('should keep existing items', function () { + it('should keep existing items', () => { const collection = new JSData.Collection({ mapper: new JSData.Mapper({ name: 'user' }) }) const user = collection.add({ id: 1, foo: 'bar', beep: 'boop' }) assert.equal(user.id, 1) @@ -230,7 +276,7 @@ describe('Collection#add', function () { }) it('should inject 1,000 items', function () { const users = [] - for (var i = 0; i < 1000; i++) { + for (let i = 0; i < 1000; i++) { users.push({ id: i, name: 'john smith #' + i, @@ -245,7 +291,7 @@ describe('Collection#add', function () { }) it.skip('should inject 10,000 items', function () { const users = [] - for (var i = 0; i < 10000; i++) { + for (let i = 0; i < 10000; i++) { users.push({ id: i, name: 'john smith #' + i, @@ -258,13 +304,13 @@ describe('Collection#add', function () { this.UserCollection.add(users) console.log('\tinject 10,000 users time taken: ', new Date().getTime() - start, 'ms') }) - it('should inject 1,000 items where there is an index on "age"', function () { + it('should inject 1,000 items where there is an index on "age"', () => { const collection = new JSData.Collection({ mapper: new JSData.Mapper({ name: 'user' }) }) collection.createIndex('age') collection.createIndex('created') collection.createIndex('updated') const users = [] - for (var i = 0; i < 1000; i++) { + for (let i = 0; i < 1000; i++) { users.push({ id: i, name: 'john smith #' + i, @@ -277,6 +323,7 @@ describe('Collection#add', function () { collection.add(users) // console.log('\tinject 1,000 users time taken: ', new Date().getTime() - start, 'ms') }) + // tslint:disable-next-line:only-arrow-functions it.skip('should inject 10,000 items where there is an index on "age"', function () { const store = new JSData.DataStore() store.defineMapper('user') @@ -284,7 +331,7 @@ describe('Collection#add', function () { store.createIndex('user', 'created') store.createIndex('user', 'updated') const users = [] - for (var i = 0; i < 10000; i++) { + for (let i = 0; i < 10000; i++) { users.push({ id: i, name: 'john smith #' + i, @@ -298,7 +345,7 @@ describe('Collection#add', function () { // console.log('\tinject 10,000 users time taken: ', new Date().getTime() - start, 'ms') // console.log('\tusers age 40-44', User.between(40, 45, { index: 'age' }).length) }) - it('should update a records relation when the inverse relation does not exist', function () { + it('should update a records relation when the inverse relation does not exist', () => { const store = new JSData.DataStore() store.defineMapper('user') store.defineMapper('post', { @@ -311,11 +358,16 @@ describe('Collection#add', function () { } } }) - const [user1, user2] = store.add('user', [{ - id: 1, name: 'John' - }, { - id: 2, name: 'Jane' - }]) + const [user1, user2] = store.add('user', [ + { + id: 1, + name: 'John' + }, + { + id: 2, + name: 'Jane' + } + ]) const post = store.add('post', { id: 2, title: 'foo', user_id: 1 }) assert.strictEqual(post.user, user1) store.add('post', { id: 2, title: 'foo', user_id: 2 }) diff --git a/test/unit/collection/between.test.js b/test/unit/collection/between.test.js deleted file mode 100644 index a00c11a0..00000000 --- a/test/unit/collection/between.test.js +++ /dev/null @@ -1,3 +0,0 @@ -describe('Collection#between', function () { - it('should work') -}) diff --git a/test/unit/collection/between.test.ts b/test/unit/collection/between.test.ts new file mode 100644 index 00000000..99944b6c --- /dev/null +++ b/test/unit/collection/between.test.ts @@ -0,0 +1,3 @@ +describe('Collection#between', () => { + it('should work') +}) diff --git a/test/unit/collection/createIndex.test.js b/test/unit/collection/createIndex.test.js deleted file mode 100644 index 4b62b7b3..00000000 --- a/test/unit/collection/createIndex.test.js +++ /dev/null @@ -1,3 +0,0 @@ -describe('Collection#createIndex', function () { - it('should work') -}) diff --git a/test/unit/collection/createIndex.test.ts b/test/unit/collection/createIndex.test.ts new file mode 100644 index 00000000..f32b0f5b --- /dev/null +++ b/test/unit/collection/createIndex.test.ts @@ -0,0 +1,3 @@ +describe('Collection#createIndex', () => { + it('should work') +}) diff --git a/test/unit/collection/filter.test.js b/test/unit/collection/filter.test.ts similarity index 62% rename from test/unit/collection/filter.test.js rename to test/unit/collection/filter.test.ts index 98477966..c161fb60 100644 --- a/test/unit/collection/filter.test.js +++ b/test/unit/collection/filter.test.ts @@ -1,6 +1,6 @@ -import { assert, JSData } from '../../_setup' +import { JSData, objectsEqual } from '../../_setup' -describe('Collection#filter', function () { +describe('Collection#filter', () => { // Most filter tests are on the Query class it('should work', function () { const collection = this.PostCollection @@ -15,9 +15,9 @@ describe('Collection#filter', function () { author: 'John' } - assert.objectsEqual(collection.filter(params), [p1], 'should default a string to "=="') + objectsEqual(collection.filter(params), [p1], 'should default a string to "=="') }) - it.skip('should allow use of scopes', function () { + it.skip('should allow use of scopes', () => { const store = new JSData.DataStore({ scopes: { defaultScope: { @@ -45,17 +45,26 @@ describe('Collection#filter', function () { { id: 7, foo: 'bar', beep: 'boop' }, { id: 8, foo: 'bar', beep: 'boop' } ]) - assert.objectsEqual(store.filter('foo', null, { - scope: ['second', 'limit'] - }), [foos[2]]) - assert.objectsEqual(store.filter('foo', null, { - scope: ['second'] - }), store.filter('foo', { - foo: 'bar', - beep: 'boop' - })) - assert.objectsEqual(store.filter('foo'), store.filter('foo', { - foo: 'bar' - })) + objectsEqual( + store.filter('foo', null, { + scope: ['second', 'limit'] + }), + [foos[2]] + ) + objectsEqual( + store.filter('foo', null, { + scope: ['second'] + }), + store.filter('foo', { + foo: 'bar', + beep: 'boop' + }) + ) + objectsEqual( + store.filter('foo'), + store.filter('foo', { + foo: 'bar' + }) + ) }) }) diff --git a/test/unit/collection/forEach.test.js b/test/unit/collection/forEach.test.ts similarity index 56% rename from test/unit/collection/forEach.test.js rename to test/unit/collection/forEach.test.ts index 81ebb338..3017f80d 100644 --- a/test/unit/collection/forEach.test.js +++ b/test/unit/collection/forEach.test.ts @@ -1,17 +1,13 @@ import { assert, JSData } from '../../_setup' -describe('Collection#forEach', function () { - it('should visit all data', function () { - const data = [ - { id: 2 }, - { id: 3 }, - { id: 1 } - ] +describe('Collection#forEach', () => { + it('should visit all data', () => { + const data = [{ id: 2 }, { id: 3 }, { id: 1 }] let count = 0 let prev let isInOrder = true const collection = new JSData.Collection(data) - collection.forEach(function (value) { + collection.forEach(value => { if (prev) { isInOrder = isInOrder && value.id > prev.id } @@ -19,25 +15,23 @@ describe('Collection#forEach', function () { count++ prev = value }) - assert.deepEqual(collection.getAll(), [ - { id: 1, visited: true }, - { id: 2, visited: true }, - { id: 3, visited: true } - ], 'data should all have been visited') + assert.deepEqual( + collection.getAll(), + [ + { id: 1, visited: true }, + { id: 2, visited: true }, + { id: 3, visited: true } + ], + 'data should all have been visited' + ) assert.equal(count, 3, 'should have taken 3 iterations to visit all data') assert(isInOrder, 'items should have been visited in order') }) - it('should forEach', function () { - const data = [ - { id: 2 }, - { id: 3 }, - { id: 1 } - ] + it('should forEach', () => { + const data = [{ id: 2 }, { id: 3 }, { id: 1 }] const collection = new JSData.Collection(data) let sum = 0 - const expectedSum = data.reduce(function (prev, curr) { - return prev + curr.id - }, 0) + const expectedSum = data.reduce((prev, curr) => prev + curr.id, 0) const ctx = {} collection.forEach(function (item) { sum = sum + item.id diff --git a/test/unit/collection/get.test.js b/test/unit/collection/get.test.ts similarity index 91% rename from test/unit/collection/get.test.js rename to test/unit/collection/get.test.ts index 23f230c3..ce4bb7d0 100644 --- a/test/unit/collection/get.test.js +++ b/test/unit/collection/get.test.ts @@ -1,6 +1,6 @@ import { assert } from '../../_setup' -describe('Collection#get', function () { +describe('Collection#get', () => { it('should get an item from the collection', function () { const user = this.UserCollection.add({ id: 1 }) assert(this.UserCollection.get(1) === user, 'should get the user from the collection') diff --git a/test/unit/collection/getAll.test.js b/test/unit/collection/getAll.test.ts similarity index 85% rename from test/unit/collection/getAll.test.js rename to test/unit/collection/getAll.test.ts index 5f6d1db3..d206ff8e 100644 --- a/test/unit/collection/getAll.test.js +++ b/test/unit/collection/getAll.test.ts @@ -1,7 +1,7 @@ -import { assert, JSData } from '../../_setup' +import { JSData, objectsEqual } from '../../_setup' -describe('Collection#getAll', function () { - it('should support complex queries', function () { +describe('Collection#getAll', () => { + it('should support complex queries', () => { const data = [ { id: 2, age: 18, role: 'admin' }, { id: 3, age: 19, role: 'admin' }, @@ -12,7 +12,7 @@ describe('Collection#getAll', function () { ] const collection = new JSData.Collection(data) collection.createIndex('ageRole', ['age', 'role']) - assert.objectsEqual( + objectsEqual( collection.getAll(19, { index: 'ageRole' }), [ { id: 3, age: 19, role: 'admin' }, @@ -21,7 +21,7 @@ describe('Collection#getAll', function () { ], 'should have found all of age:19 using 1 keyList' ) - assert.objectsEqual( + objectsEqual( collection.getAll([19, 'admin'], { index: 'ageRole' }), [ { id: 3, age: 19, role: 'admin' }, @@ -29,7 +29,7 @@ describe('Collection#getAll', function () { ], 'should have found age:19, role:admin' ) - assert.objectsEqual( + objectsEqual( collection.getAll([19, 'admin'], [19, 'owner'], { index: 'ageRole' }), [ { id: 3, age: 19, role: 'admin' }, @@ -38,7 +38,7 @@ describe('Collection#getAll', function () { ], 'should have found all of age:19 using 2 keyLists' ) - assert.objectsEqual( + objectsEqual( collection.getAll([19, 'admin'], 23, { index: 'ageRole' }), [ { id: 3, age: 19, role: 'admin' }, diff --git a/test/unit/collection/getIndex.test.js b/test/unit/collection/getIndex.test.ts similarity index 50% rename from test/unit/collection/getIndex.test.js rename to test/unit/collection/getIndex.test.ts index 14aa7c1d..fc7b277d 100644 --- a/test/unit/collection/getIndex.test.js +++ b/test/unit/collection/getIndex.test.ts @@ -1,7 +1,7 @@ import { assert, JSData } from '../../_setup' -describe('Collection#getIndex', function () { - it('should get an index', function () { +describe('Collection#getIndex', () => { + it('should get an index', () => { const collection = new JSData.Collection() collection.createIndex('age') assert.doesNotThrow(() => { @@ -10,10 +10,14 @@ describe('Collection#getIndex', function () { }) }) - it('should error if index does not exist', function () { + it('should error if index does not exist', () => { const collection = new JSData.Collection() - assert.throws(() => { - collection.getIndex('age') - }, Error, '[Collection#getIndex:age] index not found\nhttp://www.js-data.io/v3.0/docs/errors#404') + assert.throws( + () => { + collection.getIndex('age') + }, + Error, + '[Collection#getIndex:age] index not found\nhttp://www.js-data.io/v3.0/docs/errors#404' + ) }) }) diff --git a/test/unit/collection/index.test.js b/test/unit/collection/index.test.ts similarity index 70% rename from test/unit/collection/index.test.js rename to test/unit/collection/index.test.ts index 8affa77e..0908bde6 100644 --- a/test/unit/collection/index.test.js +++ b/test/unit/collection/index.test.ts @@ -1,42 +1,35 @@ import { assert, JSData, sinon } from '../../_setup' -describe('Collection', function () { - it('should be a constructor function', function () { +describe('Collection', () => { + it('should be a constructor function', () => { assert.equal(typeof JSData.Collection, 'function', 'should be a function') const collection = new JSData.Collection() assert(collection instanceof JSData.Collection, 'collection should be an instance') assert.equal(collection.recordId(), 'id', 'collection should get initialization properties') }) - it('should accept just opts', function () { + it('should accept just opts', () => { assert.doesNotThrow(() => { - new JSData.Collection({ idAttribute: 'id' }) // eslint-disable-line + // eslint-disable-next-line no-new + new JSData.Collection({ idAttribute: 'id' }) }) }) - it('should accept opts as string', function () { + it('should accept opts as string', () => { assert.doesNotThrow(() => { const collection = new JSData.Collection('_id') assert.equal(collection.idAttribute, '_id') }) }) - it('should accept initialization data', function () { - const data = [ - { id: 2 }, - { id: 3 }, - { id: 1 } - ] + it('should accept initialization data', () => { + const data = [{ id: 2 }, { id: 3 }, { id: 1 }] const collection = new JSData.Collection(data) assert.deepEqual(collection.getAll(), [data[2], data[0], data[1]], 'data should be in order') }) - it('should bubble up record events', function () { - const data = [ - { id: 2 }, - { id: 3 }, - { id: 1 } - ] + it('should bubble up record events', () => { + const data = [{ id: 2 }, { id: 3 }, { id: 1 }] const stub = sinon.stub() const stub2 = sinon.stub() const UserMapper = new JSData.Mapper({ name: 'user' }) @@ -53,13 +46,20 @@ describe('Collection', function () { assert.deepEqual(stub2.secondCall.args, ['foo', 2, 3]) }) - it('can make a subclass', function () { - const FooCollection = JSData.Collection.extend({ - foo () { return 'foo' } - }) + it('can make a subclass', () => { + class FooCollection extends JSData.Collection { + foo () { + return 'foo' + } + } + + // tslint:disable-next-line:max-classes-per-file class BarCollection extends JSData.Collection { - bar () { return 'bar' } + bar () { + return 'bar' + } } + const fooC = new FooCollection(null, { test: 'test' }) const barC = new BarCollection(null, { test: 'test' }) assert.equal(fooC.foo(), 'foo') diff --git a/test/unit/collection/limit.test.js b/test/unit/collection/limit.test.js deleted file mode 100644 index 85f6a216..00000000 --- a/test/unit/collection/limit.test.js +++ /dev/null @@ -1,34 +0,0 @@ -import { assert, JSData, TYPES_EXCEPT_NUMBER } from '../../_setup' - -describe('Collection#limit', function () { - it('should limit', function () { - const data = [ - { id: 2 }, - { id: 3 }, - { id: 1 } - ] - const collection = new JSData.Collection(data) - TYPES_EXCEPT_NUMBER.forEach(function (value) { - assert.throws(function () { - collection.limit(value) - }, Error, `[Query#limit:num] expected: number, found: ${typeof value}\nhttp://www.js-data.io/v3.0/docs/errors#400`) - }) - assert.deepEqual(collection.limit(1), [ - { id: 1 } - ], 'should have limited to 1') - assert.deepEqual(collection.limit(2), [ - { id: 1 }, - { id: 2 } - ], 'should have limited to 2') - assert.deepEqual(collection.limit(3), [ - { id: 1 }, - { id: 2 }, - { id: 3 } - ], 'should have limited to 3') - assert.deepEqual(collection.limit(4), [ - { id: 1 }, - { id: 2 }, - { id: 3 } - ], 'should have limited none') - }) -}) diff --git a/test/unit/collection/limit.test.ts b/test/unit/collection/limit.test.ts new file mode 100644 index 00000000..3471a3a7 --- /dev/null +++ b/test/unit/collection/limit.test.ts @@ -0,0 +1,21 @@ +import { assert, JSData, TYPES_EXCEPT_NUMBER } from '../../_setup' + +describe('Collection#limit', () => { + it('should limit', () => { + const data = [{ id: 2 }, { id: 3 }, { id: 1 }] + const collection = new JSData.Collection(data) + TYPES_EXCEPT_NUMBER.forEach(value => { + assert.throws( + () => { + collection.limit(value) + }, + Error, + `[Query#limit:num] expected: number, found: ${typeof value}\nhttp://www.js-data.io/v3.0/docs/errors#400` + ) + }) + assert.deepEqual(collection.limit(1), [{ id: 1 }], 'should have limited to 1') + assert.deepEqual(collection.limit(2), [{ id: 1 }, { id: 2 }], 'should have limited to 2') + assert.deepEqual(collection.limit(3), [{ id: 1 }, { id: 2 }, { id: 3 }], 'should have limited to 3') + assert.deepEqual(collection.limit(4), [{ id: 1 }, { id: 2 }, { id: 3 }], 'should have limited none') + }) +}) diff --git a/test/unit/collection/map.test.js b/test/unit/collection/map.test.ts similarity index 73% rename from test/unit/collection/map.test.js rename to test/unit/collection/map.test.ts index c68f7ebb..d7086a85 100644 --- a/test/unit/collection/map.test.js +++ b/test/unit/collection/map.test.ts @@ -1,12 +1,8 @@ import { assert, JSData } from '../../_setup' -describe('Collection#map', function () { - it('should map', function () { - const data = [ - { id: 2 }, - { id: 3 }, - { id: 1 } - ] +describe('Collection#map', () => { + it('should map', () => { + const data = [{ id: 2 }, { id: 3 }, { id: 1 }] const collection = new JSData.Collection(data) const ctx = {} const mapping = collection.map(function (item) { diff --git a/test/unit/collection/mapCall.test.js b/test/unit/collection/mapCall.test.js deleted file mode 100644 index 11555a4b..00000000 --- a/test/unit/collection/mapCall.test.js +++ /dev/null @@ -1,12 +0,0 @@ -import { assert, JSData } from '../../_setup' - -describe('Collection#mapCall', function () { - it('should map and call', function () { - const data = [ - { id: 1, getId () { return this.id } }, - { id: 2, getId () { return this.id } } - ] - const collection = new JSData.Collection(data) - assert.deepEqual(collection.mapCall('getId'), [1, 2]) - }) -}) diff --git a/test/unit/collection/mapCall.test.ts b/test/unit/collection/mapCall.test.ts new file mode 100644 index 00000000..24b60914 --- /dev/null +++ b/test/unit/collection/mapCall.test.ts @@ -0,0 +1,22 @@ +import { assert, JSData } from '../../_setup' + +describe('Collection#mapCall', () => { + it('should map and call', () => { + const data = [ + { + id: 1, + getId () { + return this.id + } + }, + { + id: 2, + getId () { + return this.id + } + } + ] + const collection = new JSData.Collection(data) + assert.deepEqual(collection.mapCall('getId'), [1, 2]) + }) +}) diff --git a/test/unit/collection/query.test.js b/test/unit/collection/query.test.js deleted file mode 100644 index 2394183e..00000000 --- a/test/unit/collection/query.test.js +++ /dev/null @@ -1,3 +0,0 @@ -describe('Collection#query', function () { - it('should work') -}) diff --git a/test/unit/collection/query.test.ts b/test/unit/collection/query.test.ts new file mode 100644 index 00000000..e2d4f10f --- /dev/null +++ b/test/unit/collection/query.test.ts @@ -0,0 +1,3 @@ +describe('Collection#query', () => { + it('should work') +}) diff --git a/test/unit/collection/recordId.test.js b/test/unit/collection/recordId.test.js deleted file mode 100644 index df54a2d2..00000000 --- a/test/unit/collection/recordId.test.js +++ /dev/null @@ -1,3 +0,0 @@ -describe('Collection#recordId', function () { - it('should work') -}) diff --git a/test/unit/collection/recordId.test.ts b/test/unit/collection/recordId.test.ts new file mode 100644 index 00000000..005c3717 --- /dev/null +++ b/test/unit/collection/recordId.test.ts @@ -0,0 +1,3 @@ +describe('Collection#recordId', () => { + it('should work') +}) diff --git a/test/unit/collection/reduce.test.js b/test/unit/collection/reduce.test.js deleted file mode 100644 index faade1a7..00000000 --- a/test/unit/collection/reduce.test.js +++ /dev/null @@ -1,19 +0,0 @@ -import { assert, JSData } from '../../_setup' - -describe('Collection#reduce', function () { - it('should reduce', function () { - const data = [ - { id: 2 }, - { id: 3 }, - { id: 1 } - ] - const collection = new JSData.Collection(data) - const expectedSum = data.reduce(function (prev, curr) { - return prev + curr.id - }, 0) - const reduction = collection.reduce(function (prev, item) { - return prev + item.id - }, 0) - assert.equal(reduction, expectedSum, 'should have correctly reduce the items to a single value') - }) -}) diff --git a/test/unit/collection/reduce.test.ts b/test/unit/collection/reduce.test.ts new file mode 100644 index 00000000..8b49c34a --- /dev/null +++ b/test/unit/collection/reduce.test.ts @@ -0,0 +1,11 @@ +import { assert, JSData } from '../../_setup' + +describe('Collection#reduce', () => { + it('should reduce', () => { + const data = [{ id: 2 }, { id: 3 }, { id: 1 }] + const collection = new JSData.Collection(data) + const expectedSum = data.reduce((prev, curr) => prev + curr.id, 0) + const reduction = collection.reduce((prev, item) => prev + item.id, 0) + assert.equal(reduction, expectedSum, 'should have correctly reduce the items to a single value') + }) +}) diff --git a/test/unit/collection/remove.test.js b/test/unit/collection/remove.test.js deleted file mode 100644 index 5c8941b0..00000000 --- a/test/unit/collection/remove.test.js +++ /dev/null @@ -1,109 +0,0 @@ -import { assert, JSData } from '../../_setup' - -describe('Collection#remove', function () { - it('should remove an item from the collection', function () { - this.UserCollection.createIndex('age') - const user = this.UserCollection.add({ id: 1, age: 30 }) - const user2 = this.UserCollection.add({ id: 2, age: 31 }) - const user3 = this.UserCollection.add({ id: 3, age: 32 }) - const users = [user, user2, user3] - assert(this.UserCollection.get(1) === user, 'user 1 is in the store') - assert(this.UserCollection.get(2) === user2, 'user 2 is in the store') - assert(this.UserCollection.get(3) === user3, 'user 3 is in the store') - assert.deepEqual(this.UserCollection.between([30], [32], { - rightInclusive: true, - index: 'age' - }), users, 'users can be selected by age index') - this.UserCollection.remove(1) - assert(!this.UserCollection.get(1), 'user 1 is no longer in the store') - users.shift() - assert.deepEqual(this.UserCollection.between([30], [32], { - rightInclusive: true, - index: 'age' - }), users, 'user 1 cannot be retrieved by index') - }) - - it('should remove plain records', function () { - const data = [ - { id: 1, getId () { return this.id } }, - { id: 2, getId () { return this.id } } - ] - const collection = new JSData.Collection(data) - const item = collection.get(1) - const removed = collection.remove(1) - assert.equal(item === removed, true) - }) - - it('should remove unsaved records', function () { - const alice = { author: 'Alice' } - const bob = this.store.createRecord('post', { author: 'Bob' }) - assert.objectsEqual(this.PostCollection.add([ - this.data.p1, - this.data.p2, - alice, - this.data.p3, - bob, - this.data.p4 - ]), [this.data.p1, this.data.p2, alice, this.data.p3, bob, this.data.p4]) - - assert.strictEqual(bob, this.PostCollection.filter({ - author: 'Bob' - })[0]) - assert.notStrictEqual(alice, this.PostCollection.filter({ - author: 'Alice' - })[0]) - - assert.objectsEqual(this.PostCollection.get(5), this.data.p1) - assert.objectsEqual(this.PostCollection.get(6), this.data.p2) - assert.objectsEqual(this.PostCollection.get(7), this.data.p3) - assert.objectsEqual(this.PostCollection.get(8), this.data.p4) - assert.objectsEqual(this.PostCollection.filter({ - id: undefined - }).length, 2) - assert.objectsEqual(this.PostCollection.filter({ - author: 'Bob' - }).length, 1) - assert.objectsEqual(this.PostCollection.filter().length, 6) - - let removedAlice = this.PostCollection.remove(alice) - assert.equal(removedAlice, undefined) - assert.objectsEqual(this.PostCollection.filter({ - author: 'Alice' - }).length, 1) - assert.objectsEqual(this.PostCollection.filter().length, 6) - removedAlice = this.PostCollection.remove(this.PostCollection.filter({ - author: 'Alice' - })[0]) - assert.objectsEqual(removedAlice, { author: 'Alice' }) - assert.objectsEqual(this.PostCollection.filter({ - author: 'Alice' - }).length, 0) - assert.objectsEqual(this.PostCollection.filter().length, 5) - assert.objectsEqual(this.PostCollection.filter({ - id: undefined - }).length, 1) - assert.objectsEqual(this.PostCollection.filter({ - author: 'Bob' - }).length, 1) - - this.PostCollection.add({ author: 'Bob' }) - assert.objectsEqual(this.PostCollection.filter({ - id: undefined - }).length, 2) - assert.objectsEqual(this.PostCollection.filter({ - author: 'Bob' - }).length, 2) - assert.objectsEqual(this.PostCollection.filter().length, 6) - - const removedBob = this.PostCollection.remove(bob) - assert.strictEqual(removedBob, bob) - - assert.objectsEqual(this.PostCollection.filter({ - id: undefined - }).length, 1) - assert.objectsEqual(this.PostCollection.filter({ - author: 'Bob' - }).length, 1) - assert.objectsEqual(this.PostCollection.filter().length, 5) - }) -}) diff --git a/test/unit/collection/remove.test.ts b/test/unit/collection/remove.test.ts new file mode 100644 index 00000000..b5b21487 --- /dev/null +++ b/test/unit/collection/remove.test.ts @@ -0,0 +1,165 @@ +import { assert, JSData, objectsEqual } from '../../_setup' + +describe('Collection#remove', () => { + it('should remove an item from the collection', function () { + this.UserCollection.createIndex('age') + const user = this.UserCollection.add({ id: 1, age: 30 }) + const user2 = this.UserCollection.add({ id: 2, age: 31 }) + const user3 = this.UserCollection.add({ id: 3, age: 32 }) + const users = [user, user2, user3] + assert(this.UserCollection.get(1) === user, 'user 1 is in the store') + assert(this.UserCollection.get(2) === user2, 'user 2 is in the store') + assert(this.UserCollection.get(3) === user3, 'user 3 is in the store') + assert.deepEqual( + this.UserCollection.between([30], [32], { + rightInclusive: true, + index: 'age' + }), + users, + 'users can be selected by age index' + ) + this.UserCollection.remove(1) + assert(!this.UserCollection.get(1), 'user 1 is no longer in the store') + users.shift() + assert.deepEqual( + this.UserCollection.between([30], [32], { + rightInclusive: true, + index: 'age' + }), + users, + 'user 1 cannot be retrieved by index' + ) + }) + + it('should remove plain records', () => { + const data = [ + { + id: 1, + getId () { + return this.id + } + }, + { + id: 2, + getId () { + return this.id + } + } + ] + const collection = new JSData.Collection(data) + const item = collection.get(1) + const removed = collection.remove(1) + assert.equal(item === removed, true) + }) + + it('should remove unsaved records', function () { + const alice = { author: 'Alice' } + const bob = this.store.createRecord('post', { author: 'Bob' }) + objectsEqual(this.PostCollection.add([this.data.p1, this.data.p2, alice, this.data.p3, bob, this.data.p4]), [ + this.data.p1, + this.data.p2, + alice, + this.data.p3, + bob, + this.data.p4 + ]) + + assert.strictEqual( + bob, + this.PostCollection.filter({ + author: 'Bob' + })[0] + ) + assert.notStrictEqual( + alice, + this.PostCollection.filter({ + author: 'Alice' + })[0] + ) + + objectsEqual(this.PostCollection.get(5), this.data.p1) + objectsEqual(this.PostCollection.get(6), this.data.p2) + objectsEqual(this.PostCollection.get(7), this.data.p3) + objectsEqual(this.PostCollection.get(8), this.data.p4) + objectsEqual( + this.PostCollection.filter({ + id: undefined + }).length, + 2 + ) + objectsEqual( + this.PostCollection.filter({ + author: 'Bob' + }).length, + 1 + ) + objectsEqual(this.PostCollection.filter().length, 6) + + let removedAlice = this.PostCollection.remove(alice) + assert.equal(removedAlice, undefined) + objectsEqual( + this.PostCollection.filter({ + author: 'Alice' + }).length, + 1 + ) + objectsEqual(this.PostCollection.filter().length, 6) + removedAlice = this.PostCollection.remove( + this.PostCollection.filter({ + author: 'Alice' + })[0] + ) + objectsEqual(removedAlice, { author: 'Alice' }) + objectsEqual( + this.PostCollection.filter({ + author: 'Alice' + }).length, + 0 + ) + objectsEqual(this.PostCollection.filter().length, 5) + objectsEqual( + this.PostCollection.filter({ + id: undefined + }).length, + 1 + ) + objectsEqual( + this.PostCollection.filter({ + author: 'Bob' + }).length, + 1 + ) + + this.PostCollection.add({ author: 'Bob' }) + objectsEqual( + this.PostCollection.filter({ + id: undefined + }).length, + 2 + ) + objectsEqual( + this.PostCollection.filter({ + author: 'Bob' + }).length, + 2 + ) + objectsEqual(this.PostCollection.filter().length, 6) + + const removedBob = this.PostCollection.remove(bob) + assert.strictEqual(removedBob, bob) + + objectsEqual( + this.PostCollection.filter({ + id: undefined + }).length, + 1 + ) + objectsEqual( + this.PostCollection.filter({ + author: 'Bob' + }).length, + 1 + ) + objectsEqual(this.PostCollection.filter().length, 5) + }) +}) diff --git a/test/unit/collection/removeAll.test.js b/test/unit/collection/removeAll.test.js deleted file mode 100644 index 4bc086b6..00000000 --- a/test/unit/collection/removeAll.test.js +++ /dev/null @@ -1,146 +0,0 @@ -import { assert } from '../../_setup' - -describe('Collection#removeAll', function () { - it('should eject items that meet the criteria from the store', function () { - this.User.debug = true - this.UserCollection.add([this.data.p1, this.data.p2, this.data.p3, this.data.p4, this.data.p5]) - assert(this.UserCollection.get(5)) - assert(this.UserCollection.get(6)) - assert(this.UserCollection.get(7)) - assert(this.UserCollection.get(8)) - assert(this.UserCollection.get(9)) - assert.doesNotThrow(() => { - this.UserCollection.removeAll({ where: { author: 'Adam' } }) - }) - assert(this.UserCollection.get(5)) - assert(this.UserCollection.get(6)) - assert(this.UserCollection.get(7)) - assert(!this.UserCollection.get(8)) - assert(!this.UserCollection.get(9)) - }) - it('should eject all items from the store', function () { - this.PostCollection.add([this.data.p1, this.data.p2, this.data.p3, this.data.p4]) - - assert.objectsEqual(this.PostCollection.get(5), this.data.p1) - assert.objectsEqual(this.PostCollection.get(6), this.data.p2) - assert.objectsEqual(this.PostCollection.get(7), this.data.p3) - assert.objectsEqual(this.PostCollection.get(8), this.data.p4) - - assert.doesNotThrow(() => { - this.PostCollection.removeAll() - }) - - assert(!this.PostCollection.get(5)) - assert(!this.PostCollection.get(6)) - assert(!this.PostCollection.get(7)) - assert(!this.PostCollection.get(8)) - }) - - it('should remove unsaved records', function () { - const alice = { author: 'Alice' } - const bob = this.store.createRecord('post', { author: 'Bob' }) - assert.objectsEqual(this.PostCollection.add([ - this.data.p1, - this.data.p2, - alice, - this.data.p3, - bob, - this.data.p4 - ]), [this.data.p1, this.data.p2, alice, this.data.p3, bob, this.data.p4]) - - assert.strictEqual(bob, this.PostCollection.filter({ - author: 'Bob' - })[0]) - assert.notStrictEqual(alice, this.PostCollection.filter({ - author: 'Alice' - })[0]) - - assert.objectsEqual(this.PostCollection.get(5), this.data.p1) - assert.objectsEqual(this.PostCollection.get(6), this.data.p2) - assert.objectsEqual(this.PostCollection.get(7), this.data.p3) - assert.objectsEqual(this.PostCollection.get(8), this.data.p4) - assert.objectsEqual(this.PostCollection.filter({ - id: undefined - }).length, 2) - assert.objectsEqual(this.PostCollection.filter({ - author: 'Bob' - }).length, 1) - assert.objectsEqual(this.PostCollection.filter().length, 6) - - let removedAlices = this.PostCollection.removeAll([alice]) - assert.equal(removedAlices.length, 0) - assert.objectsEqual(this.PostCollection.filter({ - author: 'Alice' - }).length, 1) - assert.objectsEqual(this.PostCollection.filter().length, 6) - removedAlices = this.PostCollection.removeAll(this.PostCollection.filter({ - author: 'Alice' - })) - assert.objectsEqual(removedAlices, [{ author: 'Alice' }]) - assert.objectsEqual(this.PostCollection.filter({ - author: 'Alice' - }).length, 0) - assert.objectsEqual(this.PostCollection.filter().length, 5) - assert.objectsEqual(this.PostCollection.filter({ - id: undefined - }).length, 1) - assert.objectsEqual(this.PostCollection.filter({ - author: 'Bob' - }).length, 1) - - const bob2 = this.PostCollection.add({ author: 'Bob' }) - assert.objectsEqual(this.PostCollection.filter({ - id: undefined - }).length, 2) - assert.objectsEqual(this.PostCollection.filter({ - author: 'Bob' - }).length, 2) - assert.objectsEqual(this.PostCollection.filter().length, 6) - - const removedBobs = this.PostCollection.removeAll([bob2, bob]) - assert.strictEqual(removedBobs[0], bob2) - assert.strictEqual(removedBobs[1], bob) - - assert.equal(this.PostCollection.filter({ - id: undefined - }).length, 0) - assert.equal(this.PostCollection.filter({ - author: 'Bob' - }).length, 0) - assert.objectsEqual(this.PostCollection.filter().length, 4) - }) - - it('should remove unsaved records with convenience method', function () { - const alice = { author: 'Alice' } - const bob = this.store.createRecord('post', { author: 'Bob' }) - assert.objectsEqual(this.PostCollection.add([ - this.data.p1, - this.data.p2, - alice, - this.data.p3, - bob, - this.data.p4 - ]), [this.data.p1, this.data.p2, alice, this.data.p3, bob, this.data.p4]) - const storeAlice = this.PostCollection.filter({ - author: 'Alice' - })[0] - - const bob2 = this.PostCollection.add({ author: 'Bob', num: 2 }) - - assert.equal(this.PostCollection.getAll().length, 7) - - const records = this.PostCollection.unsaved() - - assert.objectsEqual(records, [ - bob2, - bob, - storeAlice - ]) - - const removedRecords = this.PostCollection.prune() - - assert.equal(removedRecords.length, 3) - assert.equal(this.PostCollection.getAll().length, 4) - assert.objectsEqual(removedRecords, [bob2, bob, alice]) - }) -}) diff --git a/test/unit/collection/removeAll.test.ts b/test/unit/collection/removeAll.test.ts new file mode 100644 index 00000000..1f87602e --- /dev/null +++ b/test/unit/collection/removeAll.test.ts @@ -0,0 +1,180 @@ +import { assert, objectsEqual } from '../../_setup' + +describe('Collection#removeAll', () => { + it('should eject items that meet the criteria from the store', function () { + this.User.debug = true + this.UserCollection.add([this.data.p1, this.data.p2, this.data.p3, this.data.p4, this.data.p5]) + assert(this.UserCollection.get(5)) + assert(this.UserCollection.get(6)) + assert(this.UserCollection.get(7)) + assert(this.UserCollection.get(8)) + assert(this.UserCollection.get(9)) + assert.doesNotThrow(() => { + this.UserCollection.removeAll({ where: { author: 'Adam' } }) + }) + assert(this.UserCollection.get(5)) + assert(this.UserCollection.get(6)) + assert(this.UserCollection.get(7)) + assert(!this.UserCollection.get(8)) + assert(!this.UserCollection.get(9)) + }) + it('should eject all items from the store', function () { + this.PostCollection.add([this.data.p1, this.data.p2, this.data.p3, this.data.p4]) + + objectsEqual(this.PostCollection.get(5), this.data.p1) + objectsEqual(this.PostCollection.get(6), this.data.p2) + objectsEqual(this.PostCollection.get(7), this.data.p3) + objectsEqual(this.PostCollection.get(8), this.data.p4) + + assert.doesNotThrow(() => { + this.PostCollection.removeAll() + }) + + assert(!this.PostCollection.get(5)) + assert(!this.PostCollection.get(6)) + assert(!this.PostCollection.get(7)) + assert(!this.PostCollection.get(8)) + }) + + it('should remove unsaved records', function () { + const alice = { author: 'Alice' } + const bob = this.store.createRecord('post', { author: 'Bob' }) + objectsEqual(this.PostCollection.add([this.data.p1, this.data.p2, alice, this.data.p3, bob, this.data.p4]), [ + this.data.p1, + this.data.p2, + alice, + this.data.p3, + bob, + this.data.p4 + ]) + + assert.strictEqual( + bob, + this.PostCollection.filter({ + author: 'Bob' + })[0] + ) + assert.notStrictEqual( + alice, + this.PostCollection.filter({ + author: 'Alice' + })[0] + ) + + objectsEqual(this.PostCollection.get(5), this.data.p1) + objectsEqual(this.PostCollection.get(6), this.data.p2) + objectsEqual(this.PostCollection.get(7), this.data.p3) + objectsEqual(this.PostCollection.get(8), this.data.p4) + objectsEqual( + this.PostCollection.filter({ + id: undefined + }).length, + 2 + ) + objectsEqual( + this.PostCollection.filter({ + author: 'Bob' + }).length, + 1 + ) + objectsEqual(this.PostCollection.filter().length, 6) + + let removedAlices = this.PostCollection.removeAll([alice]) + assert.equal(removedAlices.length, 0) + objectsEqual( + this.PostCollection.filter({ + author: 'Alice' + }).length, + 1 + ) + objectsEqual(this.PostCollection.filter().length, 6) + removedAlices = this.PostCollection.removeAll( + this.PostCollection.filter({ + author: 'Alice' + }) + ) + objectsEqual(removedAlices, [{ author: 'Alice' }]) + objectsEqual( + this.PostCollection.filter({ + author: 'Alice' + }).length, + 0 + ) + objectsEqual(this.PostCollection.filter().length, 5) + objectsEqual( + this.PostCollection.filter({ + id: undefined + }).length, + 1 + ) + objectsEqual( + this.PostCollection.filter({ + author: 'Bob' + }).length, + 1 + ) + + const bob2 = this.PostCollection.add({ author: 'Bob' }) + objectsEqual( + this.PostCollection.filter({ + id: undefined + }).length, + 2 + ) + objectsEqual( + this.PostCollection.filter({ + author: 'Bob' + }).length, + 2 + ) + objectsEqual(this.PostCollection.filter().length, 6) + + const removedBobs = this.PostCollection.removeAll([bob2, bob]) + assert.strictEqual(removedBobs[0], bob2) + assert.strictEqual(removedBobs[1], bob) + + assert.equal( + this.PostCollection.filter({ + id: undefined + }).length, + 0 + ) + assert.equal( + this.PostCollection.filter({ + author: 'Bob' + }).length, + 0 + ) + objectsEqual(this.PostCollection.filter().length, 4) + }) + + it('should remove unsaved records with convenience method', function () { + const alice = { author: 'Alice' } + const bob = this.store.createRecord('post', { author: 'Bob' }) + objectsEqual(this.PostCollection.add([this.data.p1, this.data.p2, alice, this.data.p3, bob, this.data.p4]), [ + this.data.p1, + this.data.p2, + alice, + this.data.p3, + bob, + this.data.p4 + ]) + const storeAlice = this.PostCollection.filter({ + author: 'Alice' + })[0] + + const bob2 = this.PostCollection.add({ author: 'Bob', num: 2 }) + + assert.equal(this.PostCollection.getAll().length, 7) + + const records = this.PostCollection.unsaved() + + objectsEqual(records, [bob2, bob, storeAlice]) + + const removedRecords = this.PostCollection.prune() + + assert.equal(removedRecords.length, 3) + assert.equal(this.PostCollection.getAll().length, 4) + objectsEqual(removedRecords, [bob2, bob, alice]) + }) +}) diff --git a/test/unit/collection/skip.test.js b/test/unit/collection/skip.test.js deleted file mode 100644 index 8255d0d0..00000000 --- a/test/unit/collection/skip.test.js +++ /dev/null @@ -1,54 +0,0 @@ -import { assert, JSData, TYPES_EXCEPT_NUMBER } from '../../_setup' - -describe('Collection#skip', function () { - it('should skip', function () { - const data = [ - { id: 2 }, - { id: 3 }, - { id: 1 } - ] - const collection = new JSData.Collection(data) - TYPES_EXCEPT_NUMBER.forEach(function (value) { - assert.throws(function () { - collection.skip(value) - }, Error, `[Query#skip:num] expected: number, found: ${typeof value}\nhttp://www.js-data.io/v3.0/docs/errors#400`) - }) - assert.deepEqual(collection.skip(1), [ - { id: 2 }, - { id: 3 } - ], 'should have skipped 1') - assert.deepEqual(collection.skip(2), [ - { id: 3 } - ], 'should have skipped 2') - assert.deepEqual(collection.skip(3), [], 'should have skipped all') - assert.deepEqual(collection.skip(4), [], 'should have skipped all') - }) - it('should skip and limit', function () { - const data = [ - { id: 2 }, - { id: 3 }, - { id: 5 }, - { id: 6 }, - { id: 4 }, - { id: 1 } - ] - const collection = new JSData.Collection(data) - assert.deepEqual(collection.query().skip(1).limit(1).run(), [ - { id: 2 } - ], 'should have skipped 1 and limited to 1') - assert.deepEqual(collection.query().skip(4).limit(2).run(), [ - { id: 5 }, - { id: 6 } - ], 'should have skipped 4 and limited to 2') - assert.deepEqual(collection.query().skip(5).limit(3).run(), [ - { id: 6 } - ], 'should have skipped 5 and limited to 3') - assert.deepEqual(collection.query().skip(1).limit(7).run(), [ - { id: 2 }, - { id: 3 }, - { id: 4 }, - { id: 5 }, - { id: 6 } - ], 'should have skipped 1 and limited to 5') - }) -}) diff --git a/test/unit/collection/skip.test.ts b/test/unit/collection/skip.test.ts new file mode 100644 index 00000000..b4aefce6 --- /dev/null +++ b/test/unit/collection/skip.test.ts @@ -0,0 +1,61 @@ +import { assert, JSData, TYPES_EXCEPT_NUMBER } from '../../_setup' + +describe('Collection#skip', () => { + it('should skip', () => { + const data = [{ id: 2 }, { id: 3 }, { id: 1 }] + const collection = new JSData.Collection(data) + TYPES_EXCEPT_NUMBER.forEach(value => { + assert.throws( + () => { + collection.skip(value) + }, + Error, + `[Query#skip:num] expected: number, found: ${typeof value}\nhttp://www.js-data.io/v3.0/docs/errors#400` + ) + }) + assert.deepEqual(collection.skip(1), [{ id: 2 }, { id: 3 }], 'should have skipped 1') + assert.deepEqual(collection.skip(2), [{ id: 3 }], 'should have skipped 2') + assert.deepEqual(collection.skip(3), [], 'should have skipped all') + assert.deepEqual(collection.skip(4), [], 'should have skipped all') + }) + it('should skip and limit', () => { + const data = [{ id: 2 }, { id: 3 }, { id: 5 }, { id: 6 }, { id: 4 }, { id: 1 }] + const collection = new JSData.Collection(data) + assert.deepEqual( + collection + .query() + .skip(1) + .limit(1) + .run(), + [{ id: 2 }], + 'should have skipped 1 and limited to 1' + ) + assert.deepEqual( + collection + .query() + .skip(4) + .limit(2) + .run(), + [{ id: 5 }, { id: 6 }], + 'should have skipped 4 and limited to 2' + ) + assert.deepEqual( + collection + .query() + .skip(5) + .limit(3) + .run(), + [{ id: 6 }], + 'should have skipped 5 and limited to 3' + ) + assert.deepEqual( + collection + .query() + .skip(1) + .limit(7) + .run(), + [{ id: 2 }, { id: 3 }, { id: 4 }, { id: 5 }, { id: 6 }], + 'should have skipped 1 and limited to 5' + ) + }) +}) diff --git a/test/unit/collection/toJSON.test.js b/test/unit/collection/toJSON.test.ts similarity index 59% rename from test/unit/collection/toJSON.test.js rename to test/unit/collection/toJSON.test.ts index 8869e3ab..3da5a0ba 100644 --- a/test/unit/collection/toJSON.test.js +++ b/test/unit/collection/toJSON.test.ts @@ -1,11 +1,8 @@ import { assert, JSData } from '../../_setup' -describe('Collection#toJSON', function () { - it('should call toJSON on records in the collection', function () { - const data = [ - { id: 1 }, - { id: 2 } - ] +describe('Collection#toJSON', () => { + it('should call toJSON on records in the collection', () => { + const data = [{ id: 1 }, { id: 2 }] const UserMapper = new JSData.Mapper({ name: 'user' }) const collection = new JSData.Collection(data, { mapper: UserMapper }) assert.deepEqual(collection.toJSON(), [{ id: 1 }, { id: 2 }]) diff --git a/test/unit/collection/updateIndex.test.js b/test/unit/collection/updateIndex.test.ts similarity index 90% rename from test/unit/collection/updateIndex.test.js rename to test/unit/collection/updateIndex.test.ts index 07d29111..0b3d6961 100644 --- a/test/unit/collection/updateIndex.test.js +++ b/test/unit/collection/updateIndex.test.ts @@ -1,7 +1,7 @@ import { assert, JSData } from '../../_setup' -describe('Collection#updateIndex', function () { - it('should update record in a single index', function () { +describe('Collection#updateIndex', () => { + it('should update record in a single index', () => { const data = [ { id: 2, age: 19 }, { id: 1, age: 27 } diff --git a/test/unit/collection/updateIndexes.test.js b/test/unit/collection/updateIndexes.test.ts similarity index 84% rename from test/unit/collection/updateIndexes.test.js rename to test/unit/collection/updateIndexes.test.ts index 504dc38e..3681d71e 100644 --- a/test/unit/collection/updateIndexes.test.js +++ b/test/unit/collection/updateIndexes.test.ts @@ -1,7 +1,7 @@ import { assert, JSData } from '../../_setup' -describe('Collection#updateIndexes', function () { - it('should update a record in all indexes', function () { +describe('Collection#updateIndexes', () => { + it('should update a record in all indexes', () => { const data = [ { id: 2, age: 19 }, { id: 1, age: 27 } diff --git a/test/unit/component/index.test.js b/test/unit/component/index.test.ts similarity index 93% rename from test/unit/component/index.test.js rename to test/unit/component/index.test.ts index e0a677be..490998fc 100644 --- a/test/unit/component/index.test.js +++ b/test/unit/component/index.test.ts @@ -1,6 +1,6 @@ import { assert, JSData, sinon } from '../../_setup' -it('should work', function () { +it('should work', () => { assert.equal(typeof JSData.Component, 'function', 'should be a function') const component = new JSData.Component() assert(component instanceof JSData.Component, 'component should be an instance') diff --git a/test/unit/container/create.test.js b/test/unit/container/create.test.ts similarity index 73% rename from test/unit/container/create.test.js rename to test/unit/container/create.test.ts index 0a6925f7..14bf3ac5 100644 --- a/test/unit/container/create.test.js +++ b/test/unit/container/create.test.ts @@ -1,7 +1,7 @@ import { assert, JSData } from '../../_setup' -describe('Container#create', function () { - it('should be an instance method', function () { +describe('Container#create', () => { + it('should be an instance method', () => { const Container = JSData.Container const store = new Container() assert.equal(typeof store.create, 'function') diff --git a/test/unit/container/createMany.test.js b/test/unit/container/createMany.test.ts similarity index 73% rename from test/unit/container/createMany.test.js rename to test/unit/container/createMany.test.ts index 785ed06c..43a7f6a1 100644 --- a/test/unit/container/createMany.test.js +++ b/test/unit/container/createMany.test.ts @@ -1,7 +1,7 @@ import { assert, JSData } from '../../_setup' -describe('Container#createMany', function () { - it('should be an instance method', function () { +describe('Container#createMany', () => { + it('should be an instance method', () => { const Container = JSData.Container const store = new Container() assert.equal(typeof store.createMany, 'function') diff --git a/test/unit/container/createRecord.test.js b/test/unit/container/createRecord.test.ts similarity index 73% rename from test/unit/container/createRecord.test.js rename to test/unit/container/createRecord.test.ts index 2c2a77a2..71f4d747 100644 --- a/test/unit/container/createRecord.test.js +++ b/test/unit/container/createRecord.test.ts @@ -1,7 +1,7 @@ import { assert, JSData } from '../../_setup' -describe('Container#createRecord', function () { - it('should be an instance method', function () { +describe('Container#createRecord', () => { + it('should be an instance method', () => { const Container = JSData.Container const store = new Container() assert.equal(typeof store.createRecord, 'function') diff --git a/test/unit/container/defineMapper.test.js b/test/unit/container/defineMapper.test.ts similarity index 79% rename from test/unit/container/defineMapper.test.js rename to test/unit/container/defineMapper.test.ts index c1084e31..947e51cb 100644 --- a/test/unit/container/defineMapper.test.js +++ b/test/unit/container/defineMapper.test.ts @@ -1,13 +1,13 @@ import { assert, JSData } from '../../_setup' -describe('Container#defineMapper', function () { - it('should be an instance method', function () { +describe('Container#defineMapper', () => { + it('should be an instance method', () => { const Container = JSData.Container const store = new Container() assert.equal(typeof store.defineMapper, 'function') assert.strictEqual(store.defineMapper, Container.prototype.defineMapper) }) - it('should create a new mapper', function () { + it('should create a new mapper', () => { const Container = JSData.Container let container = new Container() let mapper = container.defineMapper('foo') @@ -23,6 +23,7 @@ describe('Container#defineMapper', function () { } } } + container = new Container({ mapperClass: Foo }) @@ -55,15 +56,23 @@ describe('Container#defineMapper', function () { assert.equal(mapper.foo, 'beep') assert.strictEqual(mapper.getAdapters(), container.getAdapters()) - assert.throws(function () { - mapper = container.defineMapper() - }, Error, '[Container#defineMapper:name] expected: string, found: undefined\nhttp://www.js-data.io/v3.0/docs/errors#400') + assert.throws( + () => { + mapper = container.defineMapper() + }, + Error, + '[Container#defineMapper:name] expected: string, found: undefined\nhttp://www.js-data.io/v3.0/docs/errors#400' + ) - assert.throws(function () { - mapper = container.defineMapper({ - foo: 'bar' - }) - }, Error, '[Container#defineMapper:name] expected: string, found: undefined\nhttp://www.js-data.io/v3.0/docs/errors#400') + assert.throws( + () => { + mapper = container.defineMapper({ + foo: 'bar' + }) + }, + Error, + '[Container#defineMapper:name] expected: string, found: undefined\nhttp://www.js-data.io/v3.0/docs/errors#400' + ) mapper = container.defineMapper({ foo: 'bar', @@ -71,7 +80,7 @@ describe('Container#defineMapper', function () { }) assert.equal(mapper.name, 'foo') }) - it('can get a scoped reference', function () { + it('can get a scoped reference', () => { const Container = JSData.Container const container = new Container() const fooMapper = container.defineMapper('foo') diff --git a/test/unit/container/destroy.test.js b/test/unit/container/destroy.test.ts similarity index 73% rename from test/unit/container/destroy.test.js rename to test/unit/container/destroy.test.ts index 75cd6132..d4753464 100644 --- a/test/unit/container/destroy.test.js +++ b/test/unit/container/destroy.test.ts @@ -1,7 +1,7 @@ import { assert, JSData } from '../../_setup' -describe('Container#destroy', function () { - it('should be an instance method', function () { +describe('Container#destroy', () => { + it('should be an instance method', () => { const Container = JSData.Container const store = new Container() assert.equal(typeof store.destroy, 'function') diff --git a/test/unit/container/destroyAll.test.js b/test/unit/container/destroyAll.test.ts similarity index 73% rename from test/unit/container/destroyAll.test.js rename to test/unit/container/destroyAll.test.ts index f3f4c4d3..3005fbe0 100644 --- a/test/unit/container/destroyAll.test.js +++ b/test/unit/container/destroyAll.test.ts @@ -1,7 +1,7 @@ import { assert, JSData } from '../../_setup' -describe('Container#destroyAll', function () { - it('should be an instance method', function () { +describe('Container#destroyAll', () => { + it('should be an instance method', () => { const Container = JSData.Container const store = new Container() assert.equal(typeof store.destroyAll, 'function') diff --git a/test/unit/container/find.test.js b/test/unit/container/find.test.ts similarity index 73% rename from test/unit/container/find.test.js rename to test/unit/container/find.test.ts index da851f53..7517616a 100644 --- a/test/unit/container/find.test.js +++ b/test/unit/container/find.test.ts @@ -1,7 +1,7 @@ import { assert, JSData } from '../../_setup' -describe('Container#find', function () { - it('should be an instance method', function () { +describe('Container#find', () => { + it('should be an instance method', () => { const Container = JSData.Container const store = new Container() assert.equal(typeof store.find, 'function') diff --git a/test/unit/container/findAll.test.js b/test/unit/container/findAll.test.ts similarity index 73% rename from test/unit/container/findAll.test.js rename to test/unit/container/findAll.test.ts index ed4431c1..ff2e6586 100644 --- a/test/unit/container/findAll.test.js +++ b/test/unit/container/findAll.test.ts @@ -1,7 +1,7 @@ import { assert, JSData } from '../../_setup' -describe('Container#findAll', function () { - it('should be an instance method', function () { +describe('Container#findAll', () => { + it('should be an instance method', () => { const Container = JSData.Container const store = new Container() assert.equal(typeof store.findAll, 'function') diff --git a/test/unit/container/getAdapter.test.js b/test/unit/container/getAdapter.test.ts similarity index 57% rename from test/unit/container/getAdapter.test.js rename to test/unit/container/getAdapter.test.ts index 03f1f835..ac04f1e0 100644 --- a/test/unit/container/getAdapter.test.js +++ b/test/unit/container/getAdapter.test.ts @@ -1,7 +1,7 @@ import { assert, JSData } from '../../_setup' -describe('Container#getAdapter', function () { - it('should get an adapter', function () { +describe('Container#getAdapter', () => { + it('should get an adapter', () => { const Container = JSData.Container const store = new Container() assert.equal(typeof store.getAdapter, 'function') @@ -10,8 +10,12 @@ describe('Container#getAdapter', function () { const adapter = {} store.registerAdapter('foo', adapter) assert.equal(store.getAdapter('foo') === adapter, true) - assert.throws(() => { - store.getAdapter() - }, Error, '[Container#getAdapter:name] expected: string, found: undefined\nhttp://www.js-data.io/v3.0/docs/errors#400') + assert.throws( + () => { + store.getAdapter() + }, + Error, + '[Container#getAdapter:name] expected: string, found: undefined\nhttp://www.js-data.io/v3.0/docs/errors#400' + ) }) }) diff --git a/test/unit/container/getAdapters.test.js b/test/unit/container/getAdapters.test.ts similarity index 71% rename from test/unit/container/getAdapters.test.js rename to test/unit/container/getAdapters.test.ts index db741c5f..c0565334 100644 --- a/test/unit/container/getAdapters.test.js +++ b/test/unit/container/getAdapters.test.ts @@ -1,13 +1,13 @@ import { assert, JSData } from '../../_setup' -describe('Container#getAdapters', function () { - it('should be an instance method', function () { +describe('Container#getAdapters', () => { + it('should be an instance method', () => { const Container = JSData.Container const store = new Container() assert.equal(typeof store.getAdapters, 'function') assert.strictEqual(store.getAdapters, Container.prototype.getAdapters) }) - it('should return the adapters of the container', function () { + it('should return the adapters of the container', () => { const Container = JSData.Container const container = new Container() assert.strictEqual(container.getAdapters(), container._adapters) diff --git a/test/unit/container/getMapper.test.js b/test/unit/container/getMapper.test.ts similarity index 57% rename from test/unit/container/getMapper.test.js rename to test/unit/container/getMapper.test.ts index d014e018..66e05c85 100644 --- a/test/unit/container/getMapper.test.js +++ b/test/unit/container/getMapper.test.ts @@ -1,19 +1,23 @@ import { assert, JSData } from '../../_setup' -describe('Container#getMapper', function () { - it('should be an instance method', function () { +describe('Container#getMapper', () => { + it('should be an instance method', () => { const Container = JSData.Container const store = new Container() assert.equal(typeof store.getMapper, 'function') assert.strictEqual(store.getMapper, Container.prototype.getMapper) }) - it('should return the specified mapper', function () { + it('should return the specified mapper', () => { const Container = JSData.Container const container = new Container() const foo = container.defineMapper('foo') assert.strictEqual(foo, container.getMapper('foo')) - assert.throws(function () { - container.getMapper('bar') - }, Error, '[Container#getMapper:bar] mapper not found\nhttp://www.js-data.io/v3.0/docs/errors#404') + assert.throws( + () => { + container.getMapper('bar') + }, + Error, + '[Container#getMapper:bar] mapper not found\nhttp://www.js-data.io/v3.0/docs/errors#404' + ) }) }) diff --git a/test/unit/container/index.test.js b/test/unit/container/index.test.ts similarity index 65% rename from test/unit/container/index.test.js rename to test/unit/container/index.test.ts index d723bae3..8ed89fdb 100644 --- a/test/unit/container/index.test.js +++ b/test/unit/container/index.test.ts @@ -1,7 +1,8 @@ import { assert, JSData, sinon } from '../../_setup' +import { proxiedMapperMethods } from '../../../src/Container' -describe('Container', function () { - it('should be a constructor function', function () { +describe('Container', () => { + it('should be a constructor function', () => { const Container = JSData.Container assert.equal(typeof Container, 'function') const container = new Container() @@ -11,9 +12,11 @@ describe('Container', function () { assert.deepEqual(container.mapperDefaults, {}) assert.strictEqual(container.mapperClass, JSData.Mapper) }) - it('should accept overrides', function () { + it('should accept overrides', () => { const Container = JSData.Container + class Foo {} + const container = new Container({ mapperClass: Foo, foo: 'bar', @@ -29,14 +32,14 @@ describe('Container', function () { }) assert.strictEqual(container.mapperClass, Foo) }) - it('should have events', function () { + it('should have events', () => { const store = new JSData.Container() const listener = sinon.stub() store.on('bar', listener) store.emit('bar') assert(listener.calledOnce) }) - it('should proxy Mapper events', function () { + it('should proxy Mapper events', () => { const store = new JSData.Container() store.defineMapper('user') const listener = sinon.stub() @@ -45,7 +48,7 @@ describe('Container', function () { assert(listener.calledOnce) assert.deepEqual(listener.firstCall.args, ['user', 'foo']) }) - it('should proxy all Mapper events', function () { + it('should proxy all Mapper events', () => { const store = new JSData.Container() store.defineMapper('user') const listener = sinon.stub() @@ -54,11 +57,19 @@ describe('Container', function () { assert(listener.calledOnce) assert.deepEqual(listener.firstCall.args, ['bar', 'user', 'foo']) }) - it('should proxy Mapper methods', function () { - const store = new JSData.Container() - store.defineMapper('user') - assert.doesNotThrow(() => { - assert.deepEqual(store.toJSON('user', { id: 1 }), { id: 1 }) + it('should proxy Mapper methods', () => { + const container = new JSData.Container() + const mapper = container.defineMapper('user') + proxiedMapperMethods.forEach(method => { + const errorMsg = `${method} called with wrong arguments` + sinon.replace(mapper, method, sinon.fake()) + if (method === 'getSchema') { + container[method]('user') + assert((mapper[method] as any).calledWithMatch(), errorMsg) + } else { + container[method]('user', { id: 1 }) + assert(mapper[method].calledWithMatch({ id: 1 }), errorMsg) + } }) }) }) diff --git a/test/unit/container/registerAdapter.test.js b/test/unit/container/registerAdapter.test.ts similarity index 86% rename from test/unit/container/registerAdapter.test.js rename to test/unit/container/registerAdapter.test.ts index 0592aa15..f19a59cc 100644 --- a/test/unit/container/registerAdapter.test.js +++ b/test/unit/container/registerAdapter.test.ts @@ -1,7 +1,7 @@ import { assert, JSData } from '../../_setup' -describe('Container#registerAdapter', function () { - it('should register an adapter', function () { +describe('Container#registerAdapter', () => { + it('should register an adapter', () => { const Container = JSData.Container const store = new Container() assert.equal(typeof store.registerAdapter, 'function') diff --git a/test/unit/container/update.test.js b/test/unit/container/update.test.ts similarity index 73% rename from test/unit/container/update.test.js rename to test/unit/container/update.test.ts index 2d704dcd..2441417f 100644 --- a/test/unit/container/update.test.js +++ b/test/unit/container/update.test.ts @@ -1,7 +1,7 @@ import { assert, JSData } from '../../_setup' -describe('Container#update', function () { - it('should be an instance method', function () { +describe('Container#update', () => { + it('should be an instance method', () => { const Container = JSData.Container const store = new Container() assert.equal(typeof store.update, 'function') diff --git a/test/unit/container/updateAll.test.js b/test/unit/container/updateAll.test.ts similarity index 74% rename from test/unit/container/updateAll.test.js rename to test/unit/container/updateAll.test.ts index 6145322b..00f2dcfd 100644 --- a/test/unit/container/updateAll.test.js +++ b/test/unit/container/updateAll.test.ts @@ -1,7 +1,7 @@ import { assert, JSData } from '../../_setup' -describe('Container#find', function () { - it('should be an instance method', function () { +describe('Container#find', () => { + it('should be an instance method', () => { const Container = JSData.Container const store = new Container() assert.equal(typeof store.updateAll, 'function') diff --git a/test/unit/container/updateMany.test.js b/test/unit/container/updateMany.test.ts similarity index 74% rename from test/unit/container/updateMany.test.js rename to test/unit/container/updateMany.test.ts index 27cdbad8..734cb2a0 100644 --- a/test/unit/container/updateMany.test.js +++ b/test/unit/container/updateMany.test.ts @@ -1,7 +1,7 @@ import { assert, JSData } from '../../_setup' -describe('Container#find', function () { - it('should be an instance method', function () { +describe('Container#find', () => { + it('should be an instance method', () => { const Container = JSData.Container const store = new Container() assert.equal(typeof store.updateMany, 'function') diff --git a/test/unit/datastore/collection_methods.test.js b/test/unit/datastore/collection_methods.test.ts similarity index 73% rename from test/unit/datastore/collection_methods.test.js rename to test/unit/datastore/collection_methods.test.ts index ddec8fdf..fef59a5b 100644 --- a/test/unit/datastore/collection_methods.test.js +++ b/test/unit/datastore/collection_methods.test.ts @@ -1,9 +1,9 @@ -import { assert } from '../../_setup' +import { assert, JSData, objectsEqual, sinon } from '../../_setup' -describe('DataStore collection methods', function () { +describe('DataStore collection methods', () => { it('add should work', function () { const user = this.store.add('user', { id: 1, name: 'John' }) - assert.objectsEqual(user, { id: 1, name: 'John' }) + objectsEqual(user, { id: 1, name: 'John' }) }) it('remove should remove relations', function () { const user = this.store.add('user', this.data.user10) @@ -84,24 +84,29 @@ describe('DataStore collection methods', function () { it('should delete cached findAll query on removeAll', function () { const query = { name: 'John' } let callCount = 0 - this.store.registerAdapter('mock', { - findAll () { - callCount++ - return Promise.resolve([{ id: 1, name: 'John' }]) - } - }, { default: true }) - return this.store.findAll('user', query) - .then((users) => { + this.store.registerAdapter( + 'mock', + { + findAll () { + callCount++ + return Promise.resolve([{ id: 1, name: 'John' }]) + } + }, + { default: true } + ) + return this.store + .findAll('user', query) + .then(users => { assert.equal(callCount, 1) return this.store.findAll('user', query) }) - .then((users) => { + .then(users => { // Query was only made once assert.equal(callCount, 1) this.store.removeAll('user', query) return this.store.findAll('user', query) }) - .then((users) => { + .then(users => { assert.equal(callCount, 2) }) }) @@ -109,37 +114,63 @@ describe('DataStore collection methods', function () { const queryOne = { name: 'Bob' } const queryTwo = { name: 'Alice' } let callCount = 0 - this.store.registerAdapter('mock', { - findAll () { - callCount++ - return Promise.resolve([]) - } - }, { default: true }) - return this.store.findAll('user', queryOne) - .then((users) => { + this.store.registerAdapter( + 'mock', + { + findAll () { + callCount++ + return Promise.resolve([]) + } + }, + { default: true } + ) + return this.store + .findAll('user', queryOne) + .then(users => { assert.equal(callCount, 1) return this.store.findAll('user', queryOne) }) - .then((users) => { + .then(users => { assert.equal(callCount, 1) return this.store.findAll('user', queryTwo) }) - .then((users) => { + .then(users => { assert.equal(callCount, 2) return this.store.findAll('user', queryTwo) }) - .then((users) => { + .then(users => { // Query was only made twice assert.equal(callCount, 2) this.store.removeAll('user') return this.store.findAll('user', queryOne) }) - .then((users) => { + .then(users => { assert.equal(callCount, 3) return this.store.findAll('user', queryTwo) }) - .then((users) => { + .then(users => { assert.equal(callCount, 4) }) }) + + it('should proxy Collection Methods', () => { + const store = new JSData.SimpleStore() + store.defineMapper('user') + const collection = store.getCollection('user') + + sinon.replace(collection, 'createIndex', sinon.fake()) + store.createIndex('user', 'statusAndRole', ['status', 'role']) + assert((collection.createIndex as any).calledWithMatch('statusAndRole', ['status', 'role']), + '[Collection.createIndex] called with wrong arguments') + + sinon.replace(collection, 'between', sinon.fake()) + store.between('user', [18], [30], { index: 'age' }) + assert((collection.between as any).calledWithMatch([18], [30], { index: 'age' }), + '[Collection.between] called with wrong arguments') + + sinon.replace(collection, 'toJSON', sinon.fake()) + store.toJSON('user', { id: 1 }) + assert((collection.toJSON as any).calledWithMatch({ id: 1 }), + '[Collection.toJSON] called with wrong arguments') + }) }) diff --git a/test/unit/datastore/create.test.js b/test/unit/datastore/create.test.ts similarity index 62% rename from test/unit/datastore/create.test.js rename to test/unit/datastore/create.test.ts index f9232da0..d818b0b4 100644 --- a/test/unit/datastore/create.test.js +++ b/test/unit/datastore/create.test.ts @@ -1,20 +1,24 @@ import { assert, JSData } from '../../_setup' -describe('DataStore#create', function () { - it('should be an instance method', function () { +describe('DataStore#create', () => { + it('should be an instance method', () => { const DataStore = JSData.DataStore const store = new DataStore() assert.equal(typeof store.create, 'function') assert.strictEqual(store.create, DataStore.prototype.create) }) it('should create', async function () { - const props = { name: 'John' } - this.store.registerAdapter('mock', { - create () { - props.id = 1 - return JSData.utils.resolve(props) - } - }, { default: true }) + const props: any = { name: 'John' } + this.store.registerAdapter( + 'mock', + { + create () { + props.id = 1 + return JSData.utils.resolve(props) + } + }, + { default: true } + ) const user = await this.store.create('user', props) assert(user[this.store.getMapper('user').idAttribute], 'new user has an id') assert(user instanceof this.store.getMapper('user').recordClass, 'user is a record') diff --git a/test/unit/datastore/createMany.test.js b/test/unit/datastore/createMany.test.ts similarity index 62% rename from test/unit/datastore/createMany.test.js rename to test/unit/datastore/createMany.test.ts index 041c195a..d9ff804e 100644 --- a/test/unit/datastore/createMany.test.js +++ b/test/unit/datastore/createMany.test.ts @@ -1,20 +1,24 @@ import { assert, JSData } from '../../_setup' -describe('DataStore#createMany', function () { - it('should be an instance method', function () { +describe('DataStore#createMany', () => { + it('should be an instance method', () => { const DataStore = JSData.DataStore const store = new DataStore() assert.equal(typeof store.createMany, 'function') assert.strictEqual(store.createMany, DataStore.prototype.createMany) }) it('should createMany', async function () { - const props = [{ name: 'John' }] - this.store.registerAdapter('mock', { - createMany () { - props[0].id = 1 - return JSData.utils.resolve(props) - } - }, { default: true }) + const props: any = [{ name: 'John' }] + this.store.registerAdapter( + 'mock', + { + createMany () { + props[0].id = 1 + return JSData.utils.resolve(props) + } + }, + { default: true } + ) const users = await this.store.createMany('user', props) assert(users[0][this.store.getMapper('user').idAttribute], 'new user has an id') assert(users[0] instanceof this.store.getMapper('user').recordClass, 'user is a record') diff --git a/test/unit/datastore/defineMapper.test.js b/test/unit/datastore/defineMapper.test.ts similarity index 83% rename from test/unit/datastore/defineMapper.test.js rename to test/unit/datastore/defineMapper.test.ts index 0e2cd584..214ebc26 100644 --- a/test/unit/datastore/defineMapper.test.js +++ b/test/unit/datastore/defineMapper.test.ts @@ -1,13 +1,13 @@ -import { assert, JSData } from '../../_setup' +import { assert, JSData, objectsEqual } from '../../_setup' -describe('DataStore#defineMapper', function () { - it('should be an instance method', function () { +describe('DataStore#defineMapper', () => { + it('should be an instance method', () => { const DataStore = JSData.DataStore const store = new DataStore() assert.equal(typeof store.defineMapper, 'function') assert.strictEqual(store.defineMapper, DataStore.prototype.defineMapper) }) - it('should create indexes for indexed properties', function () { + it('should create indexes for indexed properties', () => { const store = new JSData.DataStore() store.defineMapper('user', { schema: { @@ -27,8 +27,8 @@ describe('DataStore#defineMapper', function () { { id: 1, age: 23, role: 'owner' } ]) - assert.objectsEqual( - store.getAll('user', 19, { index: 'age' }).map(function (user) { + objectsEqual( + store.getAll('user', 19, { index: 'age' }).map(user => { return user.toJSON() }), [ @@ -39,7 +39,7 @@ describe('DataStore#defineMapper', function () { 'should have found all of age:19 using 1 keyList' ) }) - it('can get a scoped reference', function () { + it('can get a scoped reference', () => { const DataStore = JSData.DataStore const store = new DataStore() const fooMapper = store.defineMapper('foo') diff --git a/test/unit/datastore/destroy.test.js b/test/unit/datastore/destroy.test.ts similarity index 82% rename from test/unit/datastore/destroy.test.js rename to test/unit/datastore/destroy.test.ts index 428a72b2..c5eccce3 100644 --- a/test/unit/datastore/destroy.test.js +++ b/test/unit/datastore/destroy.test.ts @@ -1,7 +1,7 @@ import { assert, JSData } from '../../_setup' -describe('DataStore#destroy', function () { - it('should be an instance method', function () { +describe('DataStore#destroy', () => { + it('should be an instance method', () => { const DataStore = JSData.DataStore const store = new DataStore() assert.equal(typeof store.destroy, 'function') @@ -13,12 +13,16 @@ describe('DataStore#destroy', function () { this.store._pendingQueries.user[id] = new Date().getTime() this.store._completedQueries.user[id] = new Date().getTime() const user = this.store.add('user', { id, name: 'John' }) - this.store.registerAdapter('mock', { - destroy () { - destroyCalled = true - return JSData.utils.resolve() - } - }, { default: true }) + this.store.registerAdapter( + 'mock', + { + destroy () { + destroyCalled = true + return Promise.resolve() + } + }, + { default: true } + ) const result = await this.store.destroy('user', id) assert(destroyCalled, 'Adapter#destroy should have been called') assert(!this.store._pendingQueries.user[id]) @@ -32,14 +36,18 @@ describe('DataStore#destroy', function () { this.store._pendingQueries.user[id] = new Date().getTime() this.store._completedQueries.user[id] = new Date().getTime() const user = this.store.add('user', { id, name: 'John' }) - this.store.registerAdapter('mock', { - destroy () { - destroyCalled = true - return JSData.utils.resolve({ - deleted: 1 - }) - } - }, { default: true }) + this.store.registerAdapter( + 'mock', + { + destroy () { + destroyCalled = true + return Promise.resolve({ + deleted: 1 + }) + } + }, + { default: true } + ) const result = await this.store.destroy('user', id, { raw: true }) assert(destroyCalled, 'Adapter#destroy should have been called') assert(!this.store._pendingQueries.user[id]) @@ -54,12 +62,16 @@ describe('DataStore#destroy', function () { let destroyCalled this.store._pendingQueries.user[id] = new Date().getTime() this.store._completedQueries.user[id] = new Date().getTime() - this.store.registerAdapter('mock', { - destroy () { - destroyCalled = true - return JSData.utils.resolve() - } - }, { default: true }) + this.store.registerAdapter( + 'mock', + { + destroy () { + destroyCalled = true + return Promise.resolve() + } + }, + { default: true } + ) const user = this.store.add('user', this.data.user10) assert.strictEqual(this.store.get('profile', this.data.profile15.id).user, user) diff --git a/test/unit/datastore/destroyAll.test.js b/test/unit/datastore/destroyAll.test.ts similarity index 69% rename from test/unit/datastore/destroyAll.test.js rename to test/unit/datastore/destroyAll.test.ts index 0ce12eee..d76a1986 100644 --- a/test/unit/datastore/destroyAll.test.js +++ b/test/unit/datastore/destroyAll.test.ts @@ -1,7 +1,7 @@ -import { assert, JSData } from '../../_setup' +import { assert, JSData, objectsEqual } from '../../_setup' -describe('DataStore#destroyAll', function () { - it('should be an instance method', function () { +describe('DataStore#destroyAll', () => { + it('should be an instance method', () => { const DataStore = JSData.DataStore const store = new DataStore() assert.equal(typeof store.destroyAll, 'function') @@ -13,15 +13,19 @@ describe('DataStore#destroyAll', function () { this.store._pendingQueries.user[this.store.hashQuery('user', query)] = new Date().getTime() this.store._completedQueries.user[this.store.hashQuery('user', query)] = new Date().getTime() const users = this.store.add('user', [{ id: 1, name: 'John' }]) - this.store.registerAdapter('mock', { - destroyAll () { - destroyCalled = true - return JSData.utils.resolve() - } - }, { default: true }) + this.store.registerAdapter( + 'mock', + { + destroyAll () { + destroyCalled = true + return JSData.utils.resolve() + } + }, + { default: true } + ) const result = await this.store.destroyAll('user', query) assert(destroyCalled, 'Adapter#destroyAll should have been called') - assert.objectsEqual(result, users, 'returned data') + objectsEqual(result, users, 'returned data') }) it('should return raw', async function () { const query = { name: 'John' } @@ -29,14 +33,18 @@ describe('DataStore#destroyAll', function () { this.store._pendingQueries.user[this.store.hashQuery('user', query)] = new Date().getTime() this.store._completedQueries.user[this.store.hashQuery('user', query)] = new Date().getTime() const users = this.store.add('user', [{ id: 1, name: 'John' }]) - this.store.registerAdapter('mock', { - destroyAll () { - destroyCalled = true - return JSData.utils.resolve({ - deleted: 1 - }) - } - }, { default: true }) + this.store.registerAdapter( + 'mock', + { + destroyAll () { + destroyCalled = true + return JSData.utils.resolve({ + deleted: 1 + }) + } + }, + { default: true } + ) const result = await this.store.destroyAll('user', query, { raw: true }) assert(destroyCalled, 'Adapter#destroyAll should have been called') assert(!this.store._pendingQueries.user[this.store.hashQuery('user', query)]) @@ -44,6 +52,6 @@ describe('DataStore#destroyAll', function () { assert(!this.store.get('user', 1)) assert.equal(result.adapter, 'mock', 'should have adapter name in response') assert.equal(result.deleted, 1, 'should have other metadata in response') - assert.objectsEqual(result.data, users, 'ejected users should have been returned') + objectsEqual(result.data, users, 'ejected users should have been returned') }) }) diff --git a/test/unit/datastore/find.test.js b/test/unit/datastore/find.test.ts similarity index 58% rename from test/unit/datastore/find.test.js rename to test/unit/datastore/find.test.ts index 2334428f..c577513b 100644 --- a/test/unit/datastore/find.test.js +++ b/test/unit/datastore/find.test.ts @@ -1,7 +1,7 @@ -import { assert, JSData } from '../../_setup' +import { assert, JSData, objectsEqual } from '../../_setup' -describe('DataStore#find', function () { - it('should be an instance method', function () { +describe('DataStore#find', () => { + it('should be an instance method', () => { const DataStore = JSData.DataStore const store = new DataStore() assert.equal(typeof store.find, 'function') @@ -11,16 +11,20 @@ describe('DataStore#find', function () { const id = 1 const props = { id, name: 'John' } let callCount = 0 - this.store.registerAdapter('mock', { - find () { - callCount++ - return JSData.utils.resolve(props) - } - }, { default: true }) + this.store.registerAdapter( + 'mock', + { + find () { + callCount++ + return JSData.utils.resolve(props) + } + }, + { default: true } + ) const user = await this.store.find('user', id) assert.equal(callCount, 1, 'find should have been called once') assert.equal(typeof this.store._completedQueries.user[id], 'function') - assert.objectsEqual(user, props, 'user should have been found') + objectsEqual(user, props, 'user should have been found') assert(user instanceof this.User.recordClass, 'user is a record') assert.strictEqual(user, await this.store.find('user', id), 'should return the cached user') assert.equal(callCount, 1, 'find should have been called once') @@ -33,41 +37,46 @@ describe('DataStore#find', function () { const id = 1 const props = { id, name: 'John' } let callCount = 0 - this.store.registerAdapter('mock', { - find () { - callCount++ - return new Promise(function (resolve) { - setTimeout(function () { - resolve(props) - }, 300) - }) - } - }, { default: true }) - const users = await Promise.all([ - this.store.find('user', id), - this.store.find('user', id) - ]) + this.store.registerAdapter( + 'mock', + { + find () { + callCount++ + return new Promise(resolve => { + setTimeout(() => { + resolve(props) + }, 300) + }) + } + }, + { default: true } + ) + const users = await Promise.all([this.store.find('user', id), this.store.find('user', id)]) assert.equal(callCount, 1, 'find should have been called once') - assert.objectsEqual(users[0], props, 'user should have been found') - assert.objectsEqual(users[1], props, 'user should have been found') + objectsEqual(users[0], props, 'user should have been found') + objectsEqual(users[1], props, 'user should have been found') assert.strictEqual(users[0], users[1], 'users are the same object') }) it('should delete pending query on error', function () { const id = 1 let callCount = 0 - this.store.registerAdapter('mock', { - find () { - callCount++ - return new Promise(function (resolve, reject) { - setTimeout(function () { - reject(new Error('foo')) - }, 300) - }) - } - }, { default: true }) + this.store.registerAdapter( + 'mock', + { + find () { + callCount++ + return new Promise((resolve, reject) => { + setTimeout(() => { + reject(new Error('foo')) + }, 300) + }) + } + }, + { default: true } + ) const pendingQuery = this.store.find('user', id) assert(this.store._pendingQueries.user[id]) - return pendingQuery.catch((err) => { + return pendingQuery.catch(err => { assert.equal(callCount, 1, 'find should have been called once') assert(!this.store._pendingQueries.user[id]) assert.equal(err.message, 'foo') diff --git a/test/unit/datastore/findAll.test.js b/test/unit/datastore/findAll.test.ts similarity index 56% rename from test/unit/datastore/findAll.test.js rename to test/unit/datastore/findAll.test.ts index f0390c99..e078b366 100644 --- a/test/unit/datastore/findAll.test.js +++ b/test/unit/datastore/findAll.test.ts @@ -1,7 +1,7 @@ -import { assert, JSData } from '../../_setup' +import { assert, JSData, objectsEqual } from '../../_setup' -describe('DataStore#findAll', function () { - it('should be an instance method', function () { +describe('DataStore#findAll', () => { + it('should be an instance method', () => { const DataStore = JSData.DataStore const store = new DataStore() assert.equal(typeof store.findAll, 'function') @@ -11,45 +11,53 @@ describe('DataStore#findAll', function () { const query = { name: 'John' } const props = [{ id: 1, name: 'John' }] let callCount = 0 - this.store.registerAdapter('mock', { - findAll () { - callCount++ - return JSData.utils.resolve(props) - } - }, { default: true }) + this.store.registerAdapter( + 'mock', + { + findAll () { + callCount++ + return JSData.utils.resolve(props) + } + }, + { default: true } + ) const users = await this.store.findAll('user', query) assert.equal(callCount, 1, 'findAll should have been called once') assert.equal(typeof this.store._completedQueries.user[this.store.hashQuery('user', query)], 'function') - assert.objectsEqual(users, props, 'users should have been found') + objectsEqual(users, props, 'users should have been found') assert(users[0] instanceof this.User.recordClass, 'user is a record') - assert.objectsEqual(await this.store.findAll('user', query), users, 'should return the cached users') + objectsEqual(await this.store.findAll('user', query), users, 'should return the cached users') assert.equal(callCount, 1, 'findAll should have been called once') - assert.objectsEqual(await this.store.findAll('user', query, { force: true }), props, 'should make a new query') + objectsEqual(await this.store.findAll('user', query, { force: true }), props, 'should make a new query') assert.equal(callCount, 2, 'findAll should have been called twice') - assert.objectsEqual(await this.store.findAll('user', query), props, 'should return the cached users') + objectsEqual(await this.store.findAll('user', query), props, 'should return the cached users') assert.equal(callCount, 2, 'findAll should have been called twice') }) it('should findAll with scoped store', async function () { const query = { name: 'John' } const props = [{ id: 1, name: 'John' }] let callCount = 0 - this.store.registerAdapter('mock', { - findAll () { - callCount++ - return JSData.utils.resolve(props) - } - }, { default: true }) + this.store.registerAdapter( + 'mock', + { + findAll () { + callCount++ + return JSData.utils.resolve(props) + } + }, + { default: true } + ) const scopedStore = this.store.as('user') const users = await scopedStore.findAll(query) assert.equal(callCount, 1, 'findAll should have been called once') assert.equal(typeof scopedStore._completedQueries.user[scopedStore.hashQuery(query)], 'function') - assert.objectsEqual(users, props, 'users should have been found') + objectsEqual(users, props, 'users should have been found') assert(users[0] instanceof this.User.recordClass, 'user is a record') - assert.objectsEqual(await scopedStore.findAll(query), users, 'should return the cached users') + objectsEqual(await scopedStore.findAll(query), users, 'should return the cached users') assert.equal(callCount, 1, 'findAll should have been called once') - assert.objectsEqual(await scopedStore.findAll(query, { force: true }), props, 'should make a new query') + objectsEqual(await scopedStore.findAll(query, { force: true }), props, 'should make a new query') assert.equal(callCount, 2, 'findAll should have been called twice') - assert.objectsEqual(await scopedStore.findAll(query), props, 'should return the cached users') + objectsEqual(await scopedStore.findAll(query), props, 'should return the cached users') assert.equal(callCount, 2, 'findAll should have been called twice') assert.equal(scopedStore.getAll().length, 1, 'user should have been added to the store') }) @@ -57,41 +65,46 @@ describe('DataStore#findAll', function () { const query = { name: 'John' } const props = [{ id: 1, name: 'John' }] let callCount = 0 - this.store.registerAdapter('mock', { - findAll () { - callCount++ - return new Promise(function (resolve) { - setTimeout(function () { - resolve(props) - }, 300) - }) - } - }, { default: true }) - const results = await Promise.all([ - this.store.findAll('user', query), - this.store.findAll('user', query) - ]) + this.store.registerAdapter( + 'mock', + { + findAll () { + callCount++ + return new Promise(resolve => { + setTimeout(() => { + resolve(props) + }, 300) + }) + } + }, + { default: true } + ) + const results = await Promise.all([this.store.findAll('user', query), this.store.findAll('user', query)]) assert.equal(callCount, 1, 'findAll should have been called once') - assert.objectsEqual(results[0], props, 'users should have been found') - assert.objectsEqual(results[1], props, 'users should have been found') + objectsEqual(results[0], props, 'users should have been found') + objectsEqual(results[1], props, 'users should have been found') assert.strictEqual(results[0][0], results[1][0], 'users are the same object') }) it('should delete pending query on error', function () { const query = { name: 'John' } let callCount = 0 - this.store.registerAdapter('mock', { - findAll () { - callCount++ - return new Promise(function (resolve, reject) { - setTimeout(function () { - reject(new Error('foo')) - }, 300) - }) - } - }, { default: true }) + this.store.registerAdapter( + 'mock', + { + findAll () { + callCount++ + return new Promise((resolve, reject) => { + setTimeout(() => { + reject(new Error('foo')) + }, 300) + }) + } + }, + { default: true } + ) const pendingQuery = this.store.findAll('user', query) assert(this.store._pendingQueries.user[this.store.hashQuery('user', query)]) - return pendingQuery.catch((err) => { + return pendingQuery.catch(err => { assert.equal(callCount, 1, 'findAll should have been called once') assert(!this.store._pendingQueries.user[this.store.hashQuery('user', query)]) assert.equal(err.message, 'foo') diff --git a/test/unit/datastore/getCollection.test.js b/test/unit/datastore/getCollection.test.ts similarity index 57% rename from test/unit/datastore/getCollection.test.js rename to test/unit/datastore/getCollection.test.ts index 8eda1b4c..2b1d7a10 100644 --- a/test/unit/datastore/getCollection.test.js +++ b/test/unit/datastore/getCollection.test.ts @@ -1,7 +1,7 @@ import { assert, JSData } from '../../_setup' -describe('DataStore#getCollection', function () { - it('should work', function () { +describe('DataStore#getCollection', () => { + it('should work', () => { const DataStore = JSData.DataStore const store = new DataStore() assert.equal(typeof store.getCollection, 'function') @@ -10,8 +10,12 @@ describe('DataStore#getCollection', function () { store.defineMapper('user') assert.strictEqual(store._collections.user, store.getCollection('user')) - assert.throws(function () { - store.getCollection('foo') - }, Error, '[SimpleStore#getCollection:foo] collection not found\nhttp://www.js-data.io/v3.0/docs/errors#404') + assert.throws( + () => { + store.getCollection('foo') + }, + Error, + '[SimpleStore#getCollection:foo] collection not found\nhttp://www.js-data.io/v3.0/docs/errors#404' + ) }) }) diff --git a/test/unit/datastore/index.test.js b/test/unit/datastore/index.test.ts similarity index 82% rename from test/unit/datastore/index.test.js rename to test/unit/datastore/index.test.ts index 2f91b728..58e448f5 100644 --- a/test/unit/datastore/index.test.js +++ b/test/unit/datastore/index.test.ts @@ -1,14 +1,14 @@ import { assert, JSData, sinon } from '../../_setup' -describe('DataStore', function () { - it('should be a constructor function', function () { +describe('DataStore', () => { + it('should be a constructor function', () => { const DataStore = JSData.DataStore assert.equal(typeof DataStore, 'function') const store = new DataStore() assert(store instanceof DataStore) assert.strictEqual(JSData.utils.getSuper(store), JSData.SimpleStore) }) - it('should initialize with defaults', function () { + it('should initialize with defaults', () => { const DataStore = JSData.DataStore const store = new DataStore() assert.deepEqual(store._adapters, {}) @@ -18,13 +18,17 @@ describe('DataStore', function () { assert.strictEqual(store.mapperClass, JSData.Mapper) assert.strictEqual(store.collectionClass, JSData.LinkedCollection) }) - it('should accept overrides', function () { + it('should accept overrides', () => { const DataStore = JSData.DataStore + class Foo {} + + // tslint:disable-next-line:max-classes-per-file class Bar {} + const store = new DataStore({ mapperClass: Foo, - CollectionClass: Bar, + collectionClass: Bar, foo: 'bar', linkRelations: true, mapperDefaults: { @@ -39,17 +43,17 @@ describe('DataStore', function () { idAttribute: '_id' }) assert.strictEqual(store.mapperClass, Foo) - assert.strictEqual(store.CollectionClass, Bar) + assert.strictEqual(store.collectionClass, Bar) assert(store.linkRelations) }) - it('should have events', function () { + it('should have events', () => { const store = new JSData.DataStore() const listener = sinon.stub() store.on('bar', listener) store.emit('bar') assert(listener.calledOnce) }) - it('should proxy Mapper events', function () { + it('should proxy Mapper events', () => { const store = new JSData.DataStore() store.defineMapper('user') const listener = sinon.stub() @@ -58,7 +62,7 @@ describe('DataStore', function () { assert(listener.calledOnce) assert.deepEqual(listener.firstCall.args, ['user', 'foo']) }) - it('should proxy all Mapper events', function () { + it('should proxy all Mapper events', () => { const store = new JSData.DataStore() store.defineMapper('user') const listener = sinon.stub() @@ -67,7 +71,7 @@ describe('DataStore', function () { assert(listener.calledOnce) assert.deepEqual(listener.firstCall.args, ['bar', 'user', 'foo']) }) - it('should proxy Collection events', function () { + it('should proxy Collection events', () => { const store = new JSData.DataStore() store.defineMapper('user') const listener = sinon.stub() @@ -76,7 +80,7 @@ describe('DataStore', function () { assert(listener.calledOnce) assert.deepEqual(listener.firstCall.args, ['user', 'foo']) }) - it('should proxy all Collection events', function () { + it('should proxy all Collection events', () => { const store = new JSData.DataStore() store.defineMapper('user') const listener = sinon.stub() diff --git a/test/unit/datastore/update.test.js b/test/unit/datastore/update.test.ts similarity index 61% rename from test/unit/datastore/update.test.js rename to test/unit/datastore/update.test.ts index f85a08d9..f056dc32 100644 --- a/test/unit/datastore/update.test.js +++ b/test/unit/datastore/update.test.ts @@ -1,7 +1,7 @@ import { assert, JSData } from '../../_setup' -describe('DataStore#update', function () { - it('should be an instance method', function () { +describe('DataStore#update', () => { + it('should be an instance method', () => { const DataStore = JSData.DataStore const store = new DataStore() assert.equal(typeof store.update, 'function') @@ -9,13 +9,17 @@ describe('DataStore#update', function () { }) it('should update', async function () { const id = 1 - const props = { id, name: 'John' } - this.store.registerAdapter('mock', { - update () { - props.foo = 'bar' - return JSData.utils.resolve(props) - } - }, { default: true }) + const props: any = { id, name: 'John' } + this.store.registerAdapter( + 'mock', + { + update () { + props.foo = 'bar' + return JSData.utils.resolve(props) + } + }, + { default: true } + ) const user = await this.store.update('user', id, props) assert.equal(user.foo, 'bar', 'user was updated') assert(user instanceof this.store.getMapper('user').recordClass, 'user is a record') diff --git a/test/unit/datastore/updateAll.test.js b/test/unit/datastore/updateAll.test.ts similarity index 62% rename from test/unit/datastore/updateAll.test.js rename to test/unit/datastore/updateAll.test.ts index 6666a856..67b320a5 100644 --- a/test/unit/datastore/updateAll.test.js +++ b/test/unit/datastore/updateAll.test.ts @@ -1,7 +1,7 @@ import { assert, JSData } from '../../_setup' -describe('DataStore#updateAll', function () { - it('should be an instance method', function () { +describe('DataStore#updateAll', () => { + it('should be an instance method', () => { const DataStore = JSData.DataStore const store = new DataStore() assert.equal(typeof store.updateAll, 'function') @@ -9,13 +9,17 @@ describe('DataStore#updateAll', function () { }) it('should updateAll', async function () { const query = { name: 'John' } - const props = [{ id: 1, name: 'John' }] - this.store.registerAdapter('mock', { - updateAll () { - props[0].foo = 'bar' - return JSData.utils.resolve(props) - } - }, { default: true }) + const props: any = [{ id: 1, name: 'John' }] + this.store.registerAdapter( + 'mock', + { + updateAll () { + props[0].foo = 'bar' + return JSData.utils.resolve(props) + } + }, + { default: true } + ) const users = await this.store.updateAll('user', props, query) assert.equal(users[0].foo, 'bar', 'user was updated') assert(users[0] instanceof this.store.getMapper('user').recordClass, 'user is a record') diff --git a/test/unit/datastore/updateMany.test.js b/test/unit/datastore/updateMany.test.ts similarity index 60% rename from test/unit/datastore/updateMany.test.js rename to test/unit/datastore/updateMany.test.ts index b58a5cdd..b58e7005 100644 --- a/test/unit/datastore/updateMany.test.js +++ b/test/unit/datastore/updateMany.test.ts @@ -1,20 +1,24 @@ import { assert, JSData } from '../../_setup' -describe('DataStore#updateMany', function () { - it('should be an instance method', function () { +describe('DataStore#updateMany', () => { + it('should be an instance method', () => { const DataStore = JSData.DataStore const store = new DataStore() assert.equal(typeof store.updateMany, 'function') assert.strictEqual(store.updateMany, DataStore.prototype.updateMany) }) it('should updateMany', async function () { - const props = [{ id: 1, name: 'John' }] - this.store.registerAdapter('mock', { - updateMany () { - props[0].foo = 'bar' - return JSData.utils.resolve(props) - } - }, { default: true }) + const props: any = [{ id: 1, name: 'John' }] + this.store.registerAdapter( + 'mock', + { + updateMany () { + props[0].foo = 'bar' + return JSData.utils.resolve(props) + } + }, + { default: true } + ) const users = await this.store.updateMany('user', props) assert.equal(users[0].foo, 'bar', 'user was updated') assert(users[0] instanceof this.store.getMapper('user').recordClass, 'user is a record') diff --git a/test/unit/decorators/belongsTo.test.js b/test/unit/decorators/belongsTo.test.ts similarity index 56% rename from test/unit/decorators/belongsTo.test.js rename to test/unit/decorators/belongsTo.test.ts index 70d5a7c4..c6ec4045 100644 --- a/test/unit/decorators/belongsTo.test.js +++ b/test/unit/decorators/belongsTo.test.ts @@ -1,53 +1,69 @@ -import { assert, JSData, createStore, createRelation, sinon } from '../../_setup' +import { assert, createRelation, createStore, JSData, sinon } from '../../_setup' const { Mapper, belongsTo } = JSData -describe('JSData.belongsTo', function () { +describe('JSData.belongsTo', () => { let store - describe('configuration', function () { + describe('configuration', () => { let mapper, anotherMapper - beforeEach(function () { + beforeEach(() => { mapper = new Mapper({ name: 'foo' }) anotherMapper = new Mapper({ name: 'bar' }) }) - it('should throw error if "localField" is missed', function () { - assert.throws(() => { - belongsTo(anotherMapper, { foreignKey: 'fooId' })(mapper) - }, Error, '[new Relation:opts.localField] expected: string, found: undefined\nhttp://www.js-data.io/v3.0/docs/errors#400') + it('should throw error if "localField" is missed', () => { + assert.throws( + () => { + belongsTo(anotherMapper, { foreignKey: 'fooId' })(mapper) + }, + Error, + '[new Relation:opts.localField] expected: string, found: undefined\nhttp://www.js-data.io/v3.0/docs/errors#400' + ) }) - it('should throw error if "foreignKey" is missed', function () { - assert.throws(() => { - belongsTo(anotherMapper, { localField: 'bar' })(mapper) - }, Error, '[new Relation:opts.foreignKey] expected: string, found: undefined\nhttp://www.js-data.io/v3.0/docs/errors#400') + it('should throw error if "foreignKey" is missed', () => { + assert.throws( + () => { + belongsTo(anotherMapper, { localField: 'bar' })(mapper) + }, + Error, + '[new Relation:opts.foreignKey] expected: string, found: undefined\nhttp://www.js-data.io/v3.0/docs/errors#400' + ) }) - it('should throw error if related mapper is passed as string and "getRelation" option is not a function', function () { - assert.throws(() => { - belongsTo('anotherMapper', { localField: 'bar', foreignKey: 'fooId' })(mapper) - }, Error, '[new Relation:opts.getRelation] expected: function, found: undefined\nhttp://www.js-data.io/v3.0/docs/errors#400') + it('should throw error if related mapper is passed as string and "getRelation" option is not a function', () => { + assert.throws( + () => { + belongsTo('anotherMapper', { localField: 'bar', foreignKey: 'fooId' })(mapper) + }, + Error, + '[new Relation:opts.getRelation] expected: function, found: undefined\nhttp://www.js-data.io/v3.0/docs/errors#400' + ) }) - it('should throw error if related mapper is undefined', function () { - assert.throws(() => { - belongsTo(undefined, { localField: 'bar', foreignKey: 'fooId' })(mapper) - }, Error, '[new Relation:related] expected: Mapper or string, found: undefined\nhttp://www.js-data.io/v3.0/docs/errors#400') + it('should throw error if related mapper is undefined', () => { + assert.throws( + () => { + belongsTo(undefined, { localField: 'bar', foreignKey: 'fooId' })(mapper) + }, + Error, + '[new Relation:related] expected: Mapper or string, found: undefined\nhttp://www.js-data.io/v3.0/docs/errors#400' + ) }) - it('should not throw error if related mapper is a string and "getRelation" option is a function', function () { + it('should not throw error if related mapper is a string and "getRelation" option is a function', () => { assert.doesNotThrow(() => { belongsTo('another', { localField: 'bar', foreignKey: 'fooId', getRelation: () => anotherMapper })(mapper) }) }) }) - describe('when 2 way relation is defined (belongsTo + hasMany)', function () { + describe('when 2 way relation is defined (belongsTo + hasMany)', () => { let foos, bars - beforeEach(function () { + beforeEach(() => { store = createStore() store.defineMapper('foo', { relations: { @@ -60,30 +76,33 @@ describe('JSData.belongsTo', function () { } }) foos = store.add('foo', [{ id: 1 }, { id: 2 }]) - bars = store.add('bar', [{ id: 1, fooId: 1 }, { id: 2, fooId: 1 }]) + bars = store.add('bar', [ + { id: 1, fooId: 1 }, + { id: 2, fooId: 1 } + ]) }) - it('should add property accessors to prototype of target', function () { + it('should add property accessors to prototype of target', () => { const Foo = store.getMapper('foo').recordClass const Bar = store.getMapper('bar').recordClass - assert.isTrue(Object.hasOwnProperty.call(Foo.prototype, 'bars')) - assert.isTrue(Object.hasOwnProperty.call(Bar.prototype, 'foo')) + assert.isTrue(Foo.prototype.hasOwnProperty('bars')) + assert.isTrue(Bar.prototype.hasOwnProperty('foo')) }) - it('should automatically map relations when record is added to store', function () { + it('should automatically map relations when record is added to store', () => { assert.sameMembers(foos[0].bars, bars) assert.isTrue(bars.every(bar => bar.foo === foos[0])) }) - it('should allow relation re-assignment', function () { + it('should allow relation re-assignment', () => { bars[0].foo = foos[1] assert.sameMembers(foos[0].bars, [bars[1]]) assert.sameMembers(foos[1].bars, [bars[0]]) }) - it('should allow relation ids re-assignment', function () { + it('should allow relation ids re-assignment', () => { bars[0].fooId = foos[1].id assert.sameMembers(foos[0].bars, [bars[1]]) @@ -91,8 +110,8 @@ describe('JSData.belongsTo', function () { }) }) - describe('when one way relation is defined', function () { - beforeEach(function () { + describe('when one way relation is defined', () => { + beforeEach(() => { store = createStore() store.defineMapper('foo') store.defineMapper('bar', { @@ -102,7 +121,7 @@ describe('JSData.belongsTo', function () { }) }) - it('should not create an inverse link', function () { + it('should not create an inverse link', () => { const foo = store.add('foo', { id: 1 }) const bar = store.add('bar', { id: 1, fooId: 1 }) @@ -111,20 +130,20 @@ describe('JSData.belongsTo', function () { }) }) - describe('when getter/setter is specified for association', function () { + describe('when getter/setter is specified for association', () => { let getter, setter - beforeEach(function () { + beforeEach(() => { store = createStore() store.defineMapper('foo', { relations: { hasMany: createRelation('bar', { localField: 'bars', foreignKey: 'fooId' }) } }) - getter = sinon.spy(function (Relation, bar, originalGet) { + getter = sinon.spy((Relation, bar, originalGet) => { return originalGet() }) - setter = sinon.spy(function (Relation, bar, foo, originalSet) { + setter = sinon.spy((Relation, bar, foo, originalSet) => { originalSet() }) store.defineMapper('bar', { @@ -139,14 +158,14 @@ describe('JSData.belongsTo', function () { }) }) - it('should call custom getter each time relation is retrieved', function () { + it('should call custom getter each time relation is retrieved', () => { store.add('foo', { id: 1, name: 'test' }) store.add('bar', { id: 1, fooId: 1 }) assert.isTrue(getter.called) }) - it('should call custom setter each time relation is changed', function () { + it('should call custom setter each time relation is changed', () => { store.add('foo', { id: 1, name: 'test' }) const bar = store.add('bar', { id: 1, fooId: 1 }) diff --git a/test/unit/decorators/hasMany.test.js b/test/unit/decorators/hasMany.test.ts similarity index 55% rename from test/unit/decorators/hasMany.test.js rename to test/unit/decorators/hasMany.test.ts index c9071533..5364cb18 100644 --- a/test/unit/decorators/hasMany.test.js +++ b/test/unit/decorators/hasMany.test.ts @@ -1,45 +1,57 @@ -import { assert, JSData, createRelation as relation } from '../../_setup' +import { assert, createRelation as relation, JSData, objectsEqual } from '../../_setup' const { Mapper, hasMany, DataStore } = JSData -describe('JSData.hasMany', function () { - describe('configuration', function () { +describe('JSData.hasMany', () => { + describe('configuration', () => { let mapper, anotherMapper - beforeEach(function () { + beforeEach(() => { mapper = new Mapper({ name: 'foo' }) anotherMapper = new Mapper({ name: 'bar' }) }) - it('should throw error if passed "foreignKey" and "localField" is omitted', function () { - assert.throws(() => { - hasMany(anotherMapper, { foreignKey: 'foo_id' })(mapper) - }, Error, '[new Relation:opts.localField] expected: string, found: undefined\nhttp://www.js-data.io/v3.0/docs/errors#400') + it('should throw error if passed "foreignKey" and "localField" is omitted', () => { + assert.throws( + () => { + hasMany(anotherMapper, { foreignKey: 'foo_id' })(mapper) + }, + Error, + '[new Relation:opts.localField] expected: string, found: undefined\nhttp://www.js-data.io/v3.0/docs/errors#400' + ) }) - it('should throw error if passed "localField" and "foreignKey" is omitted', function () { - assert.throws(() => { - hasMany(anotherMapper, { localField: 'foo' })(mapper) - }, Error, '[new Relation:opts.] expected: string, found: undefined\nhttp://www.js-data.io/v3.0/docs/errors#400') + it('should throw error if passed "localField" and "foreignKey" is omitted', () => { + assert.throws( + () => { + hasMany(anotherMapper, { localField: 'foo' })(mapper) + }, + Error, + '[new Relation:opts.] expected: string, found: undefined\nhttp://www.js-data.io/v3.0/docs/errors#400' + ) }) - it('should throw error if passed relation name and "getRelation" is omitted', function () { - assert.throws(() => { - hasMany('anotherMapper', { localField: 'foo', foreignKey: 'foo_id' })(mapper) - }, Error, '[new Relation:opts.getRelation] expected: function, found: undefined\nhttp://www.js-data.io/v3.0/docs/errors#400') + it('should throw error if passed relation name and "getRelation" is omitted', () => { + assert.throws( + () => { + hasMany('anotherMapper', { localField: 'foo', foreignKey: 'foo_id' })(mapper) + }, + Error, + '[new Relation:opts.getRelation] expected: function, found: undefined\nhttp://www.js-data.io/v3.0/docs/errors#400' + ) }) - it('should not throw error if passed relation together with "getRelation" option', function () { + it('should not throw error if passed relation together with "getRelation" option', () => { assert.doesNotThrow(() => { hasMany('anotherMapper', { localField: 'foo', foreignKey: 'foo_id', getRelation: () => anotherMapper })(mapper) }) }) }) - describe('when relation is set up using "foreignKey"', function () { + describe('when relation is set up using "foreignKey"', () => { let store - beforeEach(function () { + beforeEach(() => { store = new DataStore() store.defineMapper('foo', { relations: { @@ -53,43 +65,52 @@ describe('JSData.hasMany', function () { }) }) - it('should add property accessors to prototype of target', function () { + it('should add property accessors to prototype of target', () => { const Foo = store.getMapper('foo').recordClass const Bar = store.getMapper('bar').recordClass - assert.isTrue(Object.hasOwnProperty.call(Foo.prototype, 'bars')) - assert.isTrue(Object.hasOwnProperty.call(Bar.prototype, 'foo')) + assert.isTrue(Foo.prototype.hasOwnProperty('bars')) + assert.isTrue(Bar.prototype.hasOwnProperty('foo')) }) - it('should return empty array for association if there is no linked records', function () { + it('should return empty array for association if there is no linked records', () => { const foo = store.add('foo', {}) - assert.objectsEqual(foo.bars, []) + objectsEqual(foo.bars, []) }) - it('should create association when related record is added to the store', function () { + it('should create association when related record is added to the store', () => { const foo = store.add('foo', { id: 1 }) - const bars = store.add('bar', [{ fooId: 1, id: 1 }, { fooId: 1, id: 2 }]) + const bars = store.add('bar', [ + { fooId: 1, id: 1 }, + { fooId: 1, id: 2 } + ]) - assert.objectsEqual(foo.bars, bars) + objectsEqual(foo.bars, bars) }) - it('should allow relation re-assignment', function () { + it('should allow relation re-assignment', () => { const foo = store.add('foo', { id: 1 }) - store.add('bar', [{ fooId: 1, id: 1 }, { fooId: 1, id: 2 }]) + store.add('bar', [ + { fooId: 1, id: 1 }, + { fooId: 1, id: 2 } + ]) const otherBars = store.add('bar', [{ id: 10 }]) foo.bars = otherBars - assert.objectsEqual(foo.bars, otherBars) - assert.objectsEqual(otherBars.map(bar => bar.fooId), [foo.id]) + objectsEqual(foo.bars, otherBars) + objectsEqual( + otherBars.map(bar => bar.fooId), + [foo.id] + ) }) }) - describe('when relation is set up using "localKeys"', function () { + describe('when relation is set up using "localKeys"', () => { let store - beforeEach(function () { + beforeEach(() => { store = new DataStore() store.defineMapper('foo', { relations: { @@ -103,28 +124,28 @@ describe('JSData.hasMany', function () { }) }) - it('should add property accessors to prototype of target', function () { + it('should add property accessors to prototype of target', () => { const Foo = store.getMapper('foo').recordClass const Bar = store.getMapper('bar').recordClass - assert.isTrue(Object.hasOwnProperty.call(Foo.prototype, 'bars')) - assert.isTrue(Object.hasOwnProperty.call(Bar.prototype, 'foos')) + assert.isTrue(Foo.prototype.hasOwnProperty('bars')) + assert.isTrue(Bar.prototype.hasOwnProperty('foos')) }) - it('should return empty array for association if there is no linked records', function () { + it('should return empty array for association if there is no linked records', () => { const foo = store.add('foo', {}) - assert.objectsEqual(foo.bars, []) + objectsEqual(foo.bars, []) }) - it('should create association when related record is added to the store', function () { + it('should create association when related record is added to the store', () => { const foo = store.add('foo', { id: 1, barIds: [1] }) const bars = store.add('bar', [{ id: 1 }, { id: 2 }]) - assert.objectsEqual(foo.bars, bars.slice(0, 1)) + objectsEqual(foo.bars, bars.slice(0, 1)) }) - it('should allow relation re-assignment', function () { + it('should allow relation re-assignment', () => { const foo = store.add('foo', { id: 1, barIds: [1] }) const anotherFoo = store.add('foo', { id: 2, barIds: [2, 3] }) const bars = store.add('bar', [{ id: 1 }, { id: 2 }, { id: 3 }]) @@ -132,16 +153,16 @@ describe('JSData.hasMany', function () { foo.bars = otherBars - assert.objectsEqual(foo.bars, otherBars) - assert.objectsEqual(otherBars[0].foos, otherBars[1].foos) - assert.objectsEqual(otherBars[0].foos, [anotherFoo, foo]) + objectsEqual(foo.bars, otherBars) + objectsEqual(otherBars[0].foos, otherBars[1].foos) + objectsEqual(otherBars[0].foos, [anotherFoo, foo]) }) }) - describe('when relation is set up using "foreignKeys" (reverse "localKeys")', function () { + describe('when relation is set up using "foreignKeys" (reverse "localKeys")', () => { let store - beforeEach(function () { + beforeEach(() => { store = new DataStore() store.defineMapper('foo', { relations: { @@ -155,45 +176,49 @@ describe('JSData.hasMany', function () { }) }) - it('should add property accessors to prototype of target', function () { + it('should add property accessors to prototype of target', () => { const Foo = store.getMapper('foo').recordClass const Bar = store.getMapper('bar').recordClass - assert.isTrue(Object.hasOwnProperty.call(Foo.prototype, 'bars')) - assert.isTrue(Object.hasOwnProperty.call(Bar.prototype, 'foos')) + assert.isTrue(Foo.prototype.hasOwnProperty('bars')) + assert.isTrue(Bar.prototype.hasOwnProperty('foos')) }) - it('should return empty array for association if there is no linked records', function () { + it('should return empty array for association if there is no linked records', () => { const foo = store.add('foo', {}) - assert.objectsEqual(foo.bars, []) + objectsEqual(foo.bars, []) }) - it('should create association when related record is added to the store', function () { + it('should create association when related record is added to the store', () => { const foo = store.add('foo', { id: 1 }) const bars = store.add('bar', [{ id: 1, fooIds: [1] }, { id: 2 }]) - assert.objectsEqual(foo.bars, bars.slice(0, 1)) + objectsEqual(foo.bars, bars.slice(0, 1)) }) - it('should allow relation re-assignment', function () { + it('should allow relation re-assignment', () => { const foo = store.add('foo', { id: 1 }) const anotherFoo = store.add('foo', { id: 2 }) - const bars = store.add('bar', [{ id: 1, fooIds: [1] }, { id: 2, fooIds: [2] }, { id: 3, fooIds: [2] }]) + const bars = store.add('bar', [ + { id: 1, fooIds: [1] }, + { id: 2, fooIds: [2] }, + { id: 3, fooIds: [2] } + ]) const otherBars = bars.slice(1) foo.bars = otherBars - assert.objectsEqual(foo.bars, otherBars) - assert.objectsEqual(otherBars[0].foos, otherBars[1].foos) - assert.objectsEqual(otherBars[0].foos, [anotherFoo, foo]) + objectsEqual(foo.bars, otherBars) + objectsEqual(otherBars[0].foos, otherBars[1].foos) + objectsEqual(otherBars[0].foos, [anotherFoo, foo]) }) }) - describe('when getter/setter is specified for association', function () { + describe('when getter/setter is specified for association', () => { let store, foo - beforeEach(function () { + beforeEach(() => { store = new DataStore() store.defineMapper('foo', { relations: { @@ -219,13 +244,13 @@ describe('JSData.hasMany', function () { store.add('bar', [{ id: 1, fooId: 1 }]) }) - it('sets related records according to implemented setter', function () { + it('sets related records according to implemented setter', () => { foo.bars = store.add('bar', [{ id: 2 }, { id: 3 }]) assert.equal(foo.bars, foo._bars) }) - it('gets related records according to implemented getter', function () { + it('gets related records according to implemented getter', () => { assert.equal(foo.bars, foo._bars) }) }) diff --git a/test/unit/index.test.js b/test/unit/index.test.js deleted file mode 100644 index e6538e22..00000000 --- a/test/unit/index.test.js +++ /dev/null @@ -1,21 +0,0 @@ -import { assert, JSData } from '../_setup' - -describe('JSData', function () { - it('has all the right exports', function () { - assert.equal(typeof JSData.belongsTo, 'function', 'has the belongsTo decorator') - assert.equal(typeof JSData.Collection, 'function', 'has the Collection class') - assert.equal(typeof JSData.Container, 'function', 'has the Container class') - assert.equal(typeof JSData.Index, 'function', 'has the Index class') - assert.equal(typeof JSData.DataStore, 'function', 'has the DataStore class') - assert.equal(typeof JSData.hasMany, 'function', 'has the hasMany decorator') - assert.equal(typeof JSData.hasOne, 'function', 'has the hasOne decorator') - assert.equal(typeof JSData.LinkedCollection, 'function', 'has the LinkedCollection class') - assert.equal(typeof JSData.Mapper, 'function', 'has the Mapper class') - assert.equal(typeof JSData.Query, 'function', 'has the Query class') - assert.equal(typeof JSData.Record, 'function', 'has the Record class') - assert.equal(typeof JSData.Schema, 'function', 'has the Schema class') - assert.equal(typeof JSData.Settable, 'function', 'has the Settable class') - assert.equal(typeof JSData.SimpleStore, 'function', 'has the SimpleStore class') - assert(JSData.version, 'has a version') - }) -}) diff --git a/test/unit/linkedCollection/add.test.js b/test/unit/linkedCollection/add.test.ts similarity index 87% rename from test/unit/linkedCollection/add.test.js rename to test/unit/linkedCollection/add.test.ts index 975e458d..c77216b5 100644 --- a/test/unit/linkedCollection/add.test.js +++ b/test/unit/linkedCollection/add.test.ts @@ -1,9 +1,9 @@ -import { assert, JSData } from '../../_setup' +import { assert, JSData, objectsEqual } from '../../_setup' -describe('LinkedCollection#add', function () { - it('should add', function () { +describe('LinkedCollection#add', () => { + it('should add', () => { const store = new JSData.DataStore() - const mapper = store.defineMapper('user') // eslint-disable-line + const mapper = store.defineMapper('user'); // eslint-disable-line const collection = store.getCollection('user') const user = collection.add({ id: 1 }) assert.equal(user.id, 1) @@ -83,10 +83,10 @@ describe('LinkedCollection#add', function () { this.UserCollection.add({ organizationId: 5, id: 1 }) this.OrganizationCollection.add({ id: 5 }) - assert.objectsEqual(this.UserCollection.get(1).organization, { id: 5 }) + objectsEqual(this.UserCollection.get(1).organization, { id: 5 }) - assert.objectsEqual(this.UserCollection.get(1).comments, []) - assert.objectsEqual(this.UserCollection.get(1).approvedComments, []) + objectsEqual(this.UserCollection.get(1).comments, []) + objectsEqual(this.UserCollection.get(1).approvedComments, []) this.CommentCollection.add({ approvedBy: 1, id: 23 }) @@ -98,7 +98,7 @@ describe('LinkedCollection#add', function () { assert.equal(0, this.UserCollection.get(1).comments.length) assert.equal(2, this.UserCollection.get(1).approvedComments.length) }) - it('should inject cyclic dependencies', function () { + it('should inject cyclic dependencies', () => { const store = new JSData.DataStore({ linkRelations: true }) @@ -118,39 +118,41 @@ describe('LinkedCollection#add', function () { } } }) - const injected = store.getCollection('foo').add([{ - id: 1, - children: [ - { - id: 2, - parentId: 1, - children: [ - { - id: 4, - parentId: 2 - }, - { - id: 5, - parentId: 2 - } - ] - }, - { - id: 3, - parentId: 1, - children: [ - { - id: 6, - parentId: 3 - }, - { - id: 7, - parentId: 3 - } - ] - } - ] - }]) + const injected = store.getCollection('foo').add([ + { + id: 1, + children: [ + { + id: 2, + parentId: 1, + children: [ + { + id: 4, + parentId: 2 + }, + { + id: 5, + parentId: 2 + } + ] + }, + { + id: 3, + parentId: 1, + children: [ + { + id: 6, + parentId: 3 + }, + { + id: 7, + parentId: 3 + } + ] + } + ] + } + ]) assert.equal(injected[0].id, 1) assert.equal(injected[0].children[0].id, 2) @@ -168,7 +170,7 @@ describe('LinkedCollection#add', function () { assert(store.getCollection('foo').get(6)) assert(store.getCollection('foo').get(7)) }) - it('should work when injecting child relations multiple times', function () { + it('should work when injecting child relations multiple times', () => { const store = new JSData.DataStore({ linkRelations: true }) @@ -195,10 +197,12 @@ describe('LinkedCollection#add', function () { store.add('parent', { id: 1, name: 'parent1', - children: [{ - id: 1, - name: 'child1' - }] + children: [ + { + id: 1, + name: 'child1' + } + ] }) assert(store.get('parent', 1).children[0] instanceof Child.recordClass) @@ -223,7 +227,7 @@ describe('LinkedCollection#add', function () { assert.deepEqual(store.filter('child', { parentId: 1 }), store.get('parent', 1).children) }) - it('should not auto-add relations where auto-add has been disabled', function () { + it('should not auto-add relations where auto-add has been disabled', () => { const store = new JSData.DataStore({ linkRelations: false }) @@ -263,7 +267,7 @@ describe('LinkedCollection#add', function () { assert.equal(foo.bars.length, 2) assert.deepEqual(store.getAll('bar'), [], 'nothing should have been injected') }) - it('should allow custom relation injection logic', function () { + it('should allow custom relation injection logic', () => { const store = new JSData.DataStore({ linkRelations: true }) @@ -275,7 +279,7 @@ describe('LinkedCollection#add', function () { foreignKey: 'fooId', add (store, relationDef, foo) { const bars = store.add(relationDef.relation, foo.test_bars) - bars.forEach(function (bar) { + bars.forEach(bar => { bar.beep = 'boop' }) delete foo.test_bars @@ -307,20 +311,24 @@ describe('LinkedCollection#add', function () { } ] }) - assert.objectsEqual(foo.bars, [ - { - id: 1, - fooId: 1, - beep: 'boop' - }, - { - id: 2, - fooId: 1, - beep: 'boop' - } - ], 'bars should have been added') + objectsEqual( + foo.bars, + [ + { + id: 1, + fooId: 1, + beep: 'boop' + }, + { + id: 2, + fooId: 1, + beep: 'boop' + } + ], + 'bars should have been added' + ) }) - it('should update links', function () { + it('should update links', () => { const store = new JSData.DataStore() store.defineMapper('foo', { relations: { @@ -364,7 +372,7 @@ describe('LinkedCollection#add', function () { }) it('should inject 1,000 items', function () { const users = [] - for (var i = 0; i < 1000; i++) { + for (let i = 0; i < 1000; i++) { users.push({ id: i, name: 'john smith #' + i, @@ -377,13 +385,13 @@ describe('LinkedCollection#add', function () { this.UserCollection.add(users) // console.log('\tinject 1,000 users time taken: ', new Date().getTime() - start, 'ms') }) - it('should inject 1,000 items where there is an index on "age"', function () { + it('should inject 1,000 items where there is an index on "age"', () => { const collection = new JSData.Collection({ mapper: new JSData.Mapper({ name: 'user' }) }) collection.createIndex('age') collection.createIndex('created') collection.createIndex('updated') const users = [] - for (var i = 0; i < 1000; i++) { + for (let i = 0; i < 1000; i++) { users.push({ id: i, name: 'john smith #' + i, diff --git a/test/unit/linkedCollection/index.test.js b/test/unit/linkedCollection/index.test.ts similarity index 68% rename from test/unit/linkedCollection/index.test.js rename to test/unit/linkedCollection/index.test.ts index 0338cc34..121aac1f 100644 --- a/test/unit/linkedCollection/index.test.js +++ b/test/unit/linkedCollection/index.test.ts @@ -1,7 +1,7 @@ -import { assert, JSData, sinon } from '../../_setup' +import { assert, JSData, objectsEqual, sinon } from '../../_setup' -describe('LinkedCollection', function () { - it('should create a linked collection', function (done) { +describe('LinkedCollection', () => { + it('should create a linked collection', done => { assert.equal(typeof JSData.LinkedCollection, 'function', 'should be a function') const store = new JSData.DataStore() const mapper = store.defineMapper('user', { @@ -16,19 +16,20 @@ describe('LinkedCollection', function () { assert(collection instanceof JSData.LinkedCollection, 'collection should be an instance') assert.equal(collection.recordId(), 'id', 'collection should get initialization properties') - const data = [ - { id: 2 }, - { id: 3 }, - { id: 1, name: 'John' } - ] + const data = [{ id: 2 }, { id: 3 }, { id: 1, name: 'John' }] collection.add(data) - assert.objectsEqual(collection.getAll(), [data[2], data[0], data[1]], 'data should be in order') + objectsEqual(collection.getAll(), [data[2], data[0], data[1]], 'data should be in order') - assert.throws(() => { - new JSData.LinkedCollection(null, { // eslint-disable-line - mapper: mapper - }) - }, Error, '[new LinkedCollection:opts.datastore] expected: DataStore, found: undefined\nhttp://www.js-data.io/v3.0/docs/errors#400') + assert.throws( + () => { + // eslint-disable-next-line no-new + new JSData.LinkedCollection(null, { + mapper + }) + }, + Error, + '[new LinkedCollection:opts.datastore] expected: DataStore, found: undefined\nhttp://www.js-data.io/v3.0/docs/errors#400' + ) const stub = sinon.stub() collection.on('all', stub) diff --git a/test/unit/linkedCollection/remove.test.js b/test/unit/linkedCollection/remove.test.ts similarity index 63% rename from test/unit/linkedCollection/remove.test.js rename to test/unit/linkedCollection/remove.test.ts index ff4cd811..5d8f676e 100644 --- a/test/unit/linkedCollection/remove.test.js +++ b/test/unit/linkedCollection/remove.test.ts @@ -1,6 +1,6 @@ import { assert } from '../../_setup' -describe('LinkedCollection#remove', function () { +describe('LinkedCollection#remove', () => { it('should remove an item from the collection', function () { this.UserCollection.createIndex('age') const user = this.UserCollection.add({ id: 1, age: 30 }) @@ -10,16 +10,24 @@ describe('LinkedCollection#remove', function () { assert.strictEqual(this.UserCollection.get(1), user, 'user 1 is in the store') assert.strictEqual(this.UserCollection.get(2), user2, 'user 2 is in the store') assert.strictEqual(this.UserCollection.get(3), user3, 'user 3 is in the store') - assert.deepEqual(this.UserCollection.between([30], [32], { - rightInclusive: true, - index: 'age' - }), users, 'users can be selected by age index') + assert.deepEqual( + this.UserCollection.between([30], [32], { + rightInclusive: true, + index: 'age' + }), + users, + 'users can be selected by age index' + ) this.UserCollection.remove(1) assert(!this.UserCollection.get(1), 'user 1 is no longer in the store') users.shift() - assert.deepEqual(this.UserCollection.between([30], [32], { - rightInclusive: true, - index: 'age' - }), users, 'user 1 cannot be retrieved by index') + assert.deepEqual( + this.UserCollection.between([30], [32], { + rightInclusive: true, + index: 'age' + }), + users, + 'user 1 cannot be retrieved by index' + ) }) }) diff --git a/test/unit/linkedCollection/removeAll.test.js b/test/unit/linkedCollection/removeAll.test.ts similarity index 75% rename from test/unit/linkedCollection/removeAll.test.js rename to test/unit/linkedCollection/removeAll.test.ts index 008445b1..113b57b8 100644 --- a/test/unit/linkedCollection/removeAll.test.js +++ b/test/unit/linkedCollection/removeAll.test.ts @@ -1,6 +1,6 @@ -import { assert } from '../../_setup' +import { assert, objectsEqual } from '../../_setup' -describe('LinkedCollection#removeAll', function () { +describe('LinkedCollection#removeAll', () => { it('should eject items that meet the criteria from the store', function () { this.User.debug = true this.UserCollection.add([this.data.p1, this.data.p2, this.data.p3, this.data.p4, this.data.p5]) @@ -21,10 +21,10 @@ describe('LinkedCollection#removeAll', function () { it('should eject all items from the store', function () { this.PostCollection.add([this.data.p1, this.data.p2, this.data.p3, this.data.p4]) - assert.objectsEqual(this.PostCollection.get(5), this.data.p1) - assert.objectsEqual(this.PostCollection.get(6), this.data.p2) - assert.objectsEqual(this.PostCollection.get(7), this.data.p3) - assert.objectsEqual(this.PostCollection.get(8), this.data.p4) + objectsEqual(this.PostCollection.get(5), this.data.p1) + objectsEqual(this.PostCollection.get(6), this.data.p2) + objectsEqual(this.PostCollection.get(7), this.data.p3) + objectsEqual(this.PostCollection.get(8), this.data.p4) assert.doesNotThrow(() => { this.PostCollection.removeAll() diff --git a/test/unit/mapper/count.test.js b/test/unit/mapper/count.test.ts similarity index 85% rename from test/unit/mapper/count.test.js rename to test/unit/mapper/count.test.ts index 13c3a760..217de2a1 100644 --- a/test/unit/mapper/count.test.js +++ b/test/unit/mapper/count.test.ts @@ -1,13 +1,13 @@ import { assert, JSData } from '../../_setup' -describe('Mapper#count', function () { - it('should be an instance method', function () { +describe('Mapper#count', () => { + it('should be an instance method', () => { const Mapper = JSData.Mapper const mapper = new Mapper({ name: 'foo' }) assert.equal(typeof mapper.count, 'function') assert.strictEqual(mapper.count, Mapper.prototype.count) }) - it('should count', async function () { + it('should count', async () => { const query = { id: 1 } let countCalled = false const User = new JSData.Mapper({ @@ -17,7 +17,7 @@ describe('Mapper#count', function () { User.registerAdapter('mock', { count (mapper, _query, Opts) { countCalled = true - return new Promise(function (resolve, reject) { + return new Promise((resolve, reject) => { assert.strictEqual(mapper, User, 'should pass in the Model') assert.deepEqual(_query, query, 'should pass in the query') assert.equal(Opts.raw, false, 'Opts are provided') @@ -29,7 +29,7 @@ describe('Mapper#count', function () { assert(countCalled, 'Adapter#count should have been called') assert.equal(count, 1, 'count should be 1') }) - it('should return raw', async function () { + it('should return raw', async () => { const query = { id: 1 } let countCalled = false const User = new JSData.Mapper({ @@ -40,7 +40,7 @@ describe('Mapper#count', function () { User.registerAdapter('mock', { count (mapper, _query, Opts) { countCalled = true - return new Promise(function (resolve, reject) { + return new Promise((resolve, reject) => { assert.strictEqual(mapper, User, 'should pass in the Model') assert.deepEqual(_query, query, 'should pass in the query') assert(Opts.raw, 'Opts are provided') diff --git a/test/unit/mapper/create.test.js b/test/unit/mapper/create.test.ts similarity index 56% rename from test/unit/mapper/create.test.js rename to test/unit/mapper/create.test.ts index d6650d0a..f6a263b5 100644 --- a/test/unit/mapper/create.test.js +++ b/test/unit/mapper/create.test.ts @@ -1,13 +1,13 @@ -import { assert, JSData } from '../../_setup' +import { assert, JSData, objectsEqual } from '../../_setup' -describe('Mapper#create', function () { - it('should be an instance method', function () { +describe('Mapper#create', () => { + it('should be an instance method', () => { const Mapper = JSData.Mapper const mapper = new Mapper({ name: 'foo' }) assert.equal(typeof mapper.create, 'function') assert.strictEqual(mapper.create, Mapper.prototype.create) }) - it('should create', async function () { + it('should create', async () => { const props = { name: 'John' } let createCalled = false const User = new JSData.Mapper({ @@ -17,9 +17,9 @@ describe('Mapper#create', function () { User.registerAdapter('mock', { create (mapper, _props, Opts) { createCalled = true - return new Promise(function (resolve, reject) { + return new Promise((resolve, reject) => { assert.strictEqual(mapper, User, 'should pass in the JSData.Mapper') - assert.objectsEqual(_props, props, 'should pass in the props') + objectsEqual(_props, props, 'should pass in the props') assert(!Opts.raw, 'Opts are provided') _props[mapper.idAttribute] = new Date().getTime() resolve(_props) @@ -31,7 +31,7 @@ describe('Mapper#create', function () { assert(user[User.idAttribute], 'new user has an id') assert(user instanceof User.recordClass, 'user is a record') }) - it('should create with defaults', async function () { + it('should create with defaults', async () => { const props = { name: 'John' } let createCalled = false const User = new JSData.Mapper({ @@ -47,9 +47,9 @@ describe('Mapper#create', function () { User.registerAdapter('mock', { create (mapper, _props, Opts) { createCalled = true - return new Promise(function (resolve, reject) { + return new Promise((resolve, reject) => { assert.strictEqual(mapper, User, 'should pass in the JSData.Mapper') - assert.objectsEqual(_props, props, 'should pass in the props') + objectsEqual(_props, props, 'should pass in the props') assert(!Opts.raw, 'Opts are provided') _props[mapper.idAttribute] = new Date().getTime() resolve(_props) @@ -62,7 +62,7 @@ describe('Mapper#create', function () { assert(user instanceof User.recordClass, 'user is a record') assert.equal(user.role, 'viewer', 'user should have default value') }) - it('should create without wrapping', async function () { + it('should create without wrapping', async () => { const props = { name: 'John' } let createCalled = false const User = new JSData.Mapper({ @@ -73,9 +73,9 @@ describe('Mapper#create', function () { User.registerAdapter('mock', { create (mapper, _props, Opts) { createCalled = true - return new Promise(function (resolve, reject) { + return new Promise((resolve, reject) => { assert.strictEqual(mapper, User, 'should pass in the JSData.Mapper') - assert.objectsEqual(_props, props, 'should pass in the props') + objectsEqual(_props, props, 'should pass in the props') assert(!Opts.raw, 'Opts are provided') _props[mapper.idAttribute] = new Date().getTime() resolve(_props) @@ -87,7 +87,7 @@ describe('Mapper#create', function () { assert(user[User.idAttribute], 'new user has an id') assert(!(user instanceof User.recordClass), 'user is NOT a record') }) - it('should return raw', async function () { + it('should return raw', async () => { const props = { name: 'John' } let createCalled = false const User = new JSData.Mapper({ @@ -98,9 +98,9 @@ describe('Mapper#create', function () { User.registerAdapter('mock', { create (mapper, _props, Opts) { createCalled = true - return new Promise(function (resolve, reject) { + return new Promise((resolve, reject) => { assert.strictEqual(mapper, User, 'should pass in the JSData.Mapper') - assert.objectsEqual(_props, props, 'should pass in the props') + objectsEqual(_props, props, 'should pass in the props') assert(Opts.raw, 'Opts are provided') _props[mapper.idAttribute] = new Date().getTime() resolve({ @@ -119,33 +119,37 @@ describe('Mapper#create', function () { }) it('should nested create everything in opts.with', async function () { const store = this.store - const createCalledCount = {} + const createCalledCount: any = {} - const incCreate = function (name) { - if (!Object.hasOwnProperty.call(createCalledCount, name)) { + const incCreate = name => { + if (!createCalledCount.hasOwnProperty(name)) { createCalledCount[name] = 0 } createCalledCount[name]++ } - const clear = function () { - for (var key in store._mappers) { + const clear = () => { + for (const key in store._mappers) { store.removeAll(key) } } - store.registerAdapter('mock', { - create (mapper, _props, Opts) { - incCreate(mapper.name) - _props[mapper.idAttribute] = new Date().getTime() - return Promise.resolve(_props) + store.registerAdapter( + 'mock', + { + create (mapper, _props, Opts) { + incCreate(mapper.name) + _props[mapper.idAttribute] = new Date().getTime() + return Promise.resolve(_props) + }, + createMany (mapper, _props, Opts) { + incCreate(mapper.name) + _props.forEach(__props => { + __props[mapper.idAttribute] = new Date().getTime() + }) + return Promise.resolve(_props) + } }, - createMany (mapper, _props, Opts) { - incCreate(mapper.name) - _props.forEach(function (__props) { - __props[mapper.idAttribute] = new Date().getTime() - }) - return Promise.resolve(_props) - } - }, { default: true }) + { default: true } + ) const userProps = { name: 'John', @@ -162,9 +166,13 @@ describe('Mapper#create', function () { } } - const group = await store.create('group', store.createRecord('group', { - users: [{ name: 'John' }] - }), { with: ['users'] }) + const group = await store.create( + 'group', + store.createRecord('group', { + users: [{ name: 'John' }] + }), + { with: ['users'] } + ) assert(group.users[0].id) assert.equal(group.users[0].name, 'John') @@ -173,134 +181,178 @@ describe('Mapper#create', function () { user = await store.createRecord('user', JSData.utils.plainCopy(userProps)).save({ with: [] }) assert(store.is('user', user), 'user should be a user record') assert.strictEqual(store.get('user', user.id), user, 'user should be in the store') - assert.objectsEqual(user.comments, [ - { - content: 'foo', - userId: user.id - } - ], 'user.comments should be an array with a comment') - assert.objectsEqual(store.getAll('comment'), [ - { - content: 'foo', - userId: user.id - } - ], 'comments should not be in the store') - assert.objectsEqual(user.profile, userProps.profile, 'user.profile should be undefined') - assert.objectsEqual(store.getAll('profile'), [ - userProps.profile - ], 'profile should not be in the store') - assert.objectsEqual(user.organization, userProps.organization) + objectsEqual( + user.comments, + [ + { + content: 'foo', + userId: user.id + } + ], + 'user.comments should be an array with a comment' + ) + objectsEqual( + store.getAll('comment'), + [ + { + content: 'foo', + userId: user.id + } + ], + 'comments should not be in the store' + ) + objectsEqual(user.profile, userProps.profile, 'user.profile should be undefined') + objectsEqual(store.getAll('profile'), [userProps.profile], 'profile should not be in the store') + objectsEqual(user.organization, userProps.organization) assert(!user.organizationId, 'user.organizationId should be undefined') - assert.objectsEqual(store.getAll('organization'), [userProps.organization], 'organization should be in the store') + objectsEqual(store.getAll('organization'), [userProps.organization], 'organization should be in the store') clear() user = await store.createRecord('user', JSData.utils.plainCopy(userProps)).save({ with: ['comments'] }) assert(store.is('user', user), 'user should be a user record') assert.strictEqual(store.get('user', user.id), user, 'user should be in the store') assert(store.is('comment', user.comments[0]), 'user.comments[0] should be a comment record') - assert.objectsEqual(store.getAll('comment'), user.comments, 'comments should be in the store') - assert.objectsEqual(user.profile, { - email: 'john@email.com' - }, 'user.profile should be undefined') - assert.objectsEqual(store.getAll('profile'), [userProps.profile], 'profile should not be in the store') - assert.objectsEqual(user.organization, userProps.organization) + objectsEqual(store.getAll('comment'), user.comments, 'comments should be in the store') + objectsEqual( + user.profile, + { + email: 'john@email.com' + }, + 'user.profile should be undefined' + ) + objectsEqual(store.getAll('profile'), [userProps.profile], 'profile should not be in the store') + objectsEqual(user.organization, userProps.organization) assert(!user.organizationId, 'user.organizationId should be undefined') - assert.objectsEqual(store.getAll('organization'), [userProps.organization], 'organization should be in the store') + objectsEqual(store.getAll('organization'), [userProps.organization], 'organization should be in the store') clear() - user = await store.create('user', store.createRecord('user', JSData.utils.plainCopy(userProps)), { with: ['comments', 'profile'] }) + user = await store.create('user', store.createRecord('user', JSData.utils.plainCopy(userProps)), { + with: ['comments', 'profile'] + }) assert(store.is('user', user), 'user should be a user record') assert.strictEqual(store.get('user', user.id), user, 'user should be in the store') assert(store.is('comment', user.comments[0]), 'user.comments[0] should be a comment record') - assert.objectsEqual(store.getAll('comment'), user.comments, 'comments should be in the store') + objectsEqual(store.getAll('comment'), user.comments, 'comments should be in the store') assert(store.is('profile', user.profile), 'user.profile should be a profile record') - assert.objectsEqual(store.getAll('profile'), [user.profile], 'profile should be in the store') - assert.objectsEqual(user.organization, userProps.organization) + objectsEqual(store.getAll('profile'), [user.profile], 'profile should be in the store') + objectsEqual(user.organization, userProps.organization) assert(!user.organizationId, 'user.organizationId should be undefined') - assert.objectsEqual(store.getAll('organization'), [userProps.organization], 'organization should be in the store') + objectsEqual(store.getAll('organization'), [userProps.organization], 'organization should be in the store') clear() - user = await store.create('user', store.createRecord('user', JSData.utils.plainCopy(userProps)), { with: ['comments', 'profile', 'organization'] }) + user = await store.create('user', store.createRecord('user', JSData.utils.plainCopy(userProps)), { + with: ['comments', 'profile', 'organization'] + }) assert(store.is('user', user), 'user should be a user record') assert.strictEqual(store.get('user', user.id), user, 'user should be in the store') assert(store.is('comment', user.comments[0]), 'user.comments[0] should be a comment record') - assert.objectsEqual(store.getAll('comment'), user.comments, 'comments should be in the store') + objectsEqual(store.getAll('comment'), user.comments, 'comments should be in the store') assert(store.is('profile', user.profile), 'user.profile should be a profile record') - assert.objectsEqual(store.getAll('profile'), [user.profile], 'profile should be in the store') + objectsEqual(store.getAll('profile'), [user.profile], 'profile should be in the store') assert(store.is('organization', user.organization), 'user.organization should be a organization record') assert.equal(store.getAll('organization')[0].id, user.organizationId, 'user.organizationId should be correct') - assert.objectsEqual(store.getAll('organization'), [user.organization], 'organization should be in the store') + objectsEqual(store.getAll('organization'), [user.organization], 'organization should be in the store') clear() // when props are NOT a record user = await store.create('user', JSData.utils.plainCopy(userProps), { with: [] }) assert(store.is('user', user), 'user should be a user record') assert.strictEqual(store.get('user', user.id), user, 'user should be in the store') - assert.objectsEqual(user.comments, [ - { - content: 'foo', - userId: user.id - } - ], 'user.comments should be an array with a comment') - assert.objectsEqual(store.getAll('comment'), [ + objectsEqual( + user.comments, + [ + { + content: 'foo', + userId: user.id + } + ], + 'user.comments should be an array with a comment' + ) + objectsEqual( + store.getAll('comment'), + [ + { + content: 'foo', + userId: user.id + } + ], + 'comments should not be in the store' + ) + objectsEqual( + user.profile, { - content: 'foo', + email: userProps.profile.email, userId: user.id - } - ], 'comments should not be in the store') - assert.objectsEqual(user.profile, { - email: userProps.profile.email, - userId: user.id - }, 'user.profile should not be undefined') - assert.objectsEqual(store.getAll('profile'), [{ - email: userProps.profile.email, - userId: user.id - }], 'profile should be in the store') + }, + 'user.profile should not be undefined' + ) + objectsEqual( + store.getAll('profile'), + [ + { + email: userProps.profile.email, + userId: user.id + } + ], + 'profile should be in the store' + ) assert(store.is('organization', user.organization), 'user.organization should be a organization record') assert.equal(store.getAll('organization')[0].id, user.organizationId, 'user.organizationId should be correct') - assert.objectsEqual(store.getAll('organization'), [user.organization], 'organization should be in the store') + objectsEqual(store.getAll('organization'), [user.organization], 'organization should be in the store') clear() user = await store.create('user', JSData.utils.plainCopy(userProps), { with: ['comments'] }) assert(store.is('user', user), 'user should be a user record') assert.strictEqual(store.get('user', user.id), user, 'user should be in the store') assert(store.is('comment', user.comments[0]), 'user.comments[0] should be a comment record') - assert.objectsEqual(store.getAll('comment'), user.comments, 'comments should be in the store') - assert.objectsEqual(user.profile, { - email: userProps.profile.email, - userId: user.id - }, 'user.profile should not be undefined') - assert.objectsEqual(store.getAll('profile'), [{ - email: userProps.profile.email, - userId: user.id - }], 'profile should be in the store') + objectsEqual(store.getAll('comment'), user.comments, 'comments should be in the store') + objectsEqual( + user.profile, + { + email: userProps.profile.email, + userId: user.id + }, + 'user.profile should not be undefined' + ) + objectsEqual( + store.getAll('profile'), + [ + { + email: userProps.profile.email, + userId: user.id + } + ], + 'profile should be in the store' + ) assert(store.is('organization', user.organization), 'user.organization should be a organization record') assert.equal(store.getAll('organization')[0].id, user.organizationId, 'user.organizationId should be correct') - assert.objectsEqual(store.getAll('organization'), [user.organization], 'organization should be in the store') + objectsEqual(store.getAll('organization'), [user.organization], 'organization should be in the store') clear() user = await store.create('user', JSData.utils.plainCopy(userProps), { with: ['comments', 'profile'] }) assert(store.is('user', user), 'user should be a user record') assert.strictEqual(store.get('user', user.id), user, 'user should be in the store') assert(store.is('comment', user.comments[0]), 'user.comments[0] should be a comment record') - assert.objectsEqual(store.getAll('comment'), user.comments, 'comments should be in the store') + objectsEqual(store.getAll('comment'), user.comments, 'comments should be in the store') assert(store.is('profile', user.profile), 'user.profile should be a profile record') - assert.objectsEqual(store.getAll('profile'), [user.profile], 'profile should be in the store') + objectsEqual(store.getAll('profile'), [user.profile], 'profile should be in the store') assert(store.is('organization', user.organization), 'user.organization should be a organization record') assert.equal(store.getAll('organization')[0].id, user.organizationId, 'user.organizationId should be correct') - assert.objectsEqual(store.getAll('organization'), [user.organization], 'organization should be in the store') + objectsEqual(store.getAll('organization'), [user.organization], 'organization should be in the store') clear() - user = await store.create('user', JSData.utils.plainCopy(userProps), { with: ['comments', 'profile', 'organization'] }) + user = await store.create('user', JSData.utils.plainCopy(userProps), { + with: ['comments', 'profile', 'organization'] + }) assert(store.is('user', user), 'user should be a user record') assert.strictEqual(store.get('user', user.id), user, 'user should be in the store') assert(store.is('comment', user.comments[0]), 'user.comments[0] should be a comment record') - assert.objectsEqual(store.getAll('comment'), user.comments, 'comments should be in the store') + objectsEqual(store.getAll('comment'), user.comments, 'comments should be in the store') assert(store.is('profile', user.profile), 'user.profile should be a profile record') - assert.objectsEqual(store.getAll('profile'), [user.profile], 'profile should be in the store') + objectsEqual(store.getAll('profile'), [user.profile], 'profile should be in the store') assert(store.is('organization', user.organization), 'user.organization should be a organization record') assert.equal(store.getAll('organization')[0].id, user.organizationId, 'user.organizationId should be correct') - assert.objectsEqual(store.getAll('organization'), [user.organization], 'organization should be in the store') + objectsEqual(store.getAll('organization'), [user.organization], 'organization should be in the store') clear() assert.equal(createCalledCount.user, 9) @@ -310,45 +362,49 @@ describe('Mapper#create', function () { }) it('should pass everything opts.pass', async function () { const store = this.store - const createCalledCount = {} + const createCalledCount: any = {} const utils = JSData.utils - const incCreate = function (name) { - if (!Object.hasOwnProperty.call(createCalledCount, name)) { + const incCreate = name => { + if (!createCalledCount.hasOwnProperty(name)) { createCalledCount[name] = 0 } createCalledCount[name]++ } - const clear = function () { - for (var key in store._mappers) { + const clear = () => { + for (const key in store._mappers) { store.removeAll(key) } } - store.registerAdapter('mock', { - create (mapper, _props, Opts) { - incCreate(mapper.name) - _props[mapper.idAttribute] = new Date().getTime() - mapper.relationFields.forEach(function (field) { - if (_props[field]) { - if (utils.isArray(_props[field])) { - _props[field].forEach(function (item) { - item.id = new Date().getTime() - }) - } else if (utils.isObject(_props[field])) { - _props[field].id = new Date().getTime() + store.registerAdapter( + 'mock', + { + create (mapper, _props, Opts) { + incCreate(mapper.name) + _props[mapper.idAttribute] = new Date().getTime() + mapper.relationFields.forEach(field => { + if (_props[field]) { + if (utils.isArray(_props[field])) { + _props[field].forEach(item => { + item.id = new Date().getTime() + }) + } else if (utils.isObject(_props[field])) { + _props[field].id = new Date().getTime() + } } - } - }) - return Promise.resolve(_props) + }) + return Promise.resolve(_props) + }, + createMany (mapper, _props, Opts) { + incCreate(mapper.name) + _props.forEach(__props => { + __props[mapper.idAttribute] = new Date().getTime() + }) + return Promise.resolve(_props) + } }, - createMany (mapper, _props, Opts) { - incCreate(mapper.name) - _props.forEach(function (__props) { - __props[mapper.idAttribute] = new Date().getTime() - }) - return Promise.resolve(_props) - } - }, { default: true }) + { default: true } + ) const userProps = { name: 'John', @@ -373,130 +429,174 @@ describe('Mapper#create', function () { user = await store.create('user', store.createRecord('user', JSData.utils.plainCopy(userProps)), { pass: [] }) assert(store.is('user', user), 'user should be a user record') assert.strictEqual(store.get('user', user.id), user, 'user should be in the store') - assert.objectsEqual(user.comments, [ - { - content: 'foo', - userId: user.id - } - ], 'user.comments should be an array') - assert.objectsEqual(store.getAll('comment'), [ - { - content: 'foo', - userId: user.id - } - ], 'comments should not be in the store') - assert.objectsEqual(user.profile, userProps.profile, 'user.profile should be a profile') - assert.objectsEqual(store.getAll('profile'), [userProps.profile], 'profile should be in the store') - assert.objectsEqual(user.organization, userProps.organization) + objectsEqual( + user.comments, + [ + { + content: 'foo', + userId: user.id + } + ], + 'user.comments should be an array' + ) + objectsEqual( + store.getAll('comment'), + [ + { + content: 'foo', + userId: user.id + } + ], + 'comments should not be in the store' + ) + objectsEqual(user.profile, userProps.profile, 'user.profile should be a profile') + objectsEqual(store.getAll('profile'), [userProps.profile], 'profile should be in the store') + objectsEqual(user.organization, userProps.organization) assert(!user.organizationId, 'user.organizationId should be undefined') - assert.objectsEqual(store.getAll('organization'), [userProps.organization], 'organization should be in the store') + objectsEqual(store.getAll('organization'), [userProps.organization], 'organization should be in the store') clear() - user = await store.create('user', store.createRecord('user', JSData.utils.plainCopy(userProps)), { pass: ['comments'] }) + user = await store.create('user', store.createRecord('user', JSData.utils.plainCopy(userProps)), { + pass: ['comments'] + }) assert(store.is('user', user), 'user should be a user record') assert.strictEqual(store.get('user', user.id), user, 'user should be in the store') assert(store.is('comment', user.comments[0]), 'user.comments[0] should be a comment record') - assert.objectsEqual(store.getAll('comment'), user.comments, 'comments should be in the store') - assert.objectsEqual(user.profile, userProps.profile, 'user.profile should be a profile') - assert.objectsEqual(store.getAll('profile'), [userProps.profile], 'profile should be in the store') - assert.objectsEqual(user.organization, userProps.organization) + objectsEqual(store.getAll('comment'), user.comments, 'comments should be in the store') + objectsEqual(user.profile, userProps.profile, 'user.profile should be a profile') + objectsEqual(store.getAll('profile'), [userProps.profile], 'profile should be in the store') + objectsEqual(user.organization, userProps.organization) assert(!user.organizationId, 'user.organizationId should be undefined') - assert.objectsEqual(store.getAll('organization'), [userProps.organization], 'organization should be in the store') + objectsEqual(store.getAll('organization'), [userProps.organization], 'organization should be in the store') clear() - user = await store.create('user', store.createRecord('user', JSData.utils.plainCopy(userProps)), { pass: ['comments', 'profile'] }) + user = await store.create('user', store.createRecord('user', JSData.utils.plainCopy(userProps)), { + pass: ['comments', 'profile'] + }) assert(store.is('user', user), 'user should be a user record') assert.strictEqual(store.get('user', user.id), user, 'user should be in the store') assert(store.is('comment', user.comments[0]), 'user.comments[0] should be a comment record') - assert.objectsEqual(store.getAll('comment'), user.comments, 'comments should be in the store') + objectsEqual(store.getAll('comment'), user.comments, 'comments should be in the store') assert(store.is('profile', user.profile), 'user.profile should be a profile record') - assert.objectsEqual(store.getAll('profile'), [user.profile], 'profile should be in the store') - assert.objectsEqual(user.organization, userProps.organization) + objectsEqual(store.getAll('profile'), [user.profile], 'profile should be in the store') + objectsEqual(user.organization, userProps.organization) assert(!user.organizationId, 'user.organizationId should be undefined') - assert.objectsEqual(store.getAll('organization'), [userProps.organization], 'organization should be in the store') + objectsEqual(store.getAll('organization'), [userProps.organization], 'organization should be in the store') clear() - user = await store.create('user', store.createRecord('user', JSData.utils.plainCopy(userProps)), { pass: ['comments', 'profile', 'organization'] }) + user = await store.create('user', store.createRecord('user', JSData.utils.plainCopy(userProps)), { + pass: ['comments', 'profile', 'organization'] + }) assert(store.is('user', user), 'user should be a user record') assert.strictEqual(store.get('user', user.id), user, 'user should be in the store') assert(store.is('comment', user.comments[0]), 'user.comments[0] should be a comment record') - assert.objectsEqual(store.getAll('comment'), user.comments, 'comments should be in the store') + objectsEqual(store.getAll('comment'), user.comments, 'comments should be in the store') assert(store.is('profile', user.profile), 'user.profile should be a profile record') - assert.objectsEqual(store.getAll('profile'), [user.profile], 'profile should be in the store') + objectsEqual(store.getAll('profile'), [user.profile], 'profile should be in the store') assert(store.is('organization', user.organization), 'user.organization should be a organization record') assert.equal(store.getAll('organization')[0].id, user.organizationId, 'user.organizationId should be correct') - assert.objectsEqual(store.getAll('organization'), [user.organization], 'organization should be in the store') + objectsEqual(store.getAll('organization'), [user.organization], 'organization should be in the store') clear() // when props are NOT a record user = await store.create('user', JSData.utils.plainCopy(userProps), { pass: [] }) assert(store.is('user', user), 'user should be a user record') assert.strictEqual(store.get('user', user.id), user, 'user should be in the store') - assert.objectsEqual(user.comments, [ - { - content: 'foo', - userId: user.id - } - ], 'user.comments should be there') - assert.objectsEqual(store.getAll('comment'), [ + objectsEqual( + user.comments, + [ + { + content: 'foo', + userId: user.id + } + ], + 'user.comments should be there' + ) + objectsEqual( + store.getAll('comment'), + [ + { + content: 'foo', + userId: user.id + } + ], + 'comments should not be in the store' + ) + objectsEqual( + user.profile, { - content: 'foo', + email: userProps.profile.email, userId: user.id - } - ], 'comments should not be in the store') - assert.objectsEqual(user.profile, { - email: userProps.profile.email, - userId: user.id - }, 'user.profile should be a profile') - assert.objectsEqual(store.getAll('profile'), [{ - email: userProps.profile.email, - userId: user.id - }], 'profile should be in the store') - assert.objectsEqual(user.organization, userProps.organization) + }, + 'user.profile should be a profile' + ) + objectsEqual( + store.getAll('profile'), + [ + { + email: userProps.profile.email, + userId: user.id + } + ], + 'profile should be in the store' + ) + objectsEqual(user.organization, userProps.organization) assert(!user.organizationId, 'user.organizationId should be undefined') - assert.objectsEqual(store.getAll('organization'), [userProps.organization], 'organization should be in the store') + objectsEqual(store.getAll('organization'), [userProps.organization], 'organization should be in the store') clear() user = await store.create('user', JSData.utils.plainCopy(userProps), { pass: ['comments'] }) assert(store.is('user', user), 'user should be a user record') assert.strictEqual(store.get('user', user.id), user, 'user should be in the store') assert(store.is('comment', user.comments[0]), 'user.comments[0] should be a comment record') - assert.objectsEqual(store.getAll('comment'), user.comments, 'comments should be in the store') - assert.objectsEqual(user.profile, { - email: userProps.profile.email, - userId: user.id - }, 'user.profile should be a profile') - assert.objectsEqual(store.getAll('profile'), [{ - email: userProps.profile.email, - userId: user.id - }], 'profile should be in the store') - assert.objectsEqual(user.organization, userProps.organization) + objectsEqual(store.getAll('comment'), user.comments, 'comments should be in the store') + objectsEqual( + user.profile, + { + email: userProps.profile.email, + userId: user.id + }, + 'user.profile should be a profile' + ) + objectsEqual( + store.getAll('profile'), + [ + { + email: userProps.profile.email, + userId: user.id + } + ], + 'profile should be in the store' + ) + objectsEqual(user.organization, userProps.organization) assert(!user.organizationId, 'user.organizationId should be undefined') - assert.objectsEqual(store.getAll('organization'), [userProps.organization], 'organization should be in the store') + objectsEqual(store.getAll('organization'), [userProps.organization], 'organization should be in the store') clear() user = await store.create('user', JSData.utils.plainCopy(userProps), { pass: ['comments', 'profile'] }) assert(store.is('user', user), 'user should be a user record') assert.strictEqual(store.get('user', user.id), user, 'user should be in the store') assert(store.is('comment', user.comments[0]), 'user.comments[0] should be a comment record') - assert.objectsEqual(store.getAll('comment'), user.comments, 'comments should be in the store') + objectsEqual(store.getAll('comment'), user.comments, 'comments should be in the store') assert(store.is('profile', user.profile), 'user.profile should be a profile record') - assert.objectsEqual(store.getAll('profile'), [user.profile], 'profile should be in the store') - assert.objectsEqual(user.organization, userProps.organization) + objectsEqual(store.getAll('profile'), [user.profile], 'profile should be in the store') + objectsEqual(user.organization, userProps.organization) assert(!user.organizationId, 'user.organizationId should be undefined') - assert.objectsEqual(store.getAll('organization'), [userProps.organization], 'organization should be in the store') + objectsEqual(store.getAll('organization'), [userProps.organization], 'organization should be in the store') clear() - user = await store.create('user', JSData.utils.plainCopy(userProps), { pass: ['comments', 'profile', 'organization'] }) + user = await store.create('user', JSData.utils.plainCopy(userProps), { + pass: ['comments', 'profile', 'organization'] + }) assert(store.is('user', user), 'user should be a user record') assert.strictEqual(store.get('user', user.id), user, 'user should be in the store') assert(store.is('comment', user.comments[0]), 'user.comments[0] should be a comment record') - assert.objectsEqual(store.getAll('comment'), user.comments, 'comments should be in the store') + objectsEqual(store.getAll('comment'), user.comments, 'comments should be in the store') assert(store.is('profile', user.profile), 'user.profile should be a profile record') - assert.objectsEqual(store.getAll('profile'), [user.profile], 'profile should be in the store') + objectsEqual(store.getAll('profile'), [user.profile], 'profile should be in the store') assert(store.is('organization', user.organization), 'user.organization should be a organization record') assert.equal(store.getAll('organization')[0].id, user.organizationId, 'user.organizationId should be correct') - assert.objectsEqual(store.getAll('organization'), [user.organization], 'organization should be in the store') + objectsEqual(store.getAll('organization'), [user.organization], 'organization should be in the store') clear() assert.equal(createCalledCount.user, 8) @@ -506,45 +606,49 @@ describe('Mapper#create', function () { }) it('should combine opts.with and opts.pass', async function () { const store = this.store - const createCalledCount = {} + const createCalledCount: any = {} const utils = JSData.utils - const incCreate = function (name) { - if (!Object.hasOwnProperty.call(createCalledCount, name)) { + const incCreate = name => { + if (!createCalledCount.hasOwnProperty(name)) { createCalledCount[name] = 0 } createCalledCount[name]++ } - const clear = function () { - for (var key in store._mappers) { + const clear = () => { + for (const key in store._mappers) { store.removeAll(key) } } - store.registerAdapter('mock', { - create (mapper, _props, Opts) { - incCreate(mapper.name) - _props[mapper.idAttribute] = new Date().getTime() - mapper.relationFields.forEach(function (field) { - if (_props[field]) { - if (utils.isArray(_props[field])) { - _props[field].forEach(function (item) { - item.id = new Date().getTime() - }) - } else if (utils.isObject(_props[field])) { - _props[field].id = new Date().getTime() + store.registerAdapter( + 'mock', + { + create (mapper, _props, Opts) { + incCreate(mapper.name) + _props[mapper.idAttribute] = new Date().getTime() + mapper.relationFields.forEach(field => { + if (_props[field]) { + if (utils.isArray(_props[field])) { + _props[field].forEach(item => { + item.id = new Date().getTime() + }) + } else if (utils.isObject(_props[field])) { + _props[field].id = new Date().getTime() + } } - } - }) - return Promise.resolve(_props) + }) + return Promise.resolve(_props) + }, + createMany (mapper, _props, Opts) { + incCreate(mapper.name) + _props.forEach(__props => { + __props[mapper.idAttribute] = new Date().getTime() + }) + return Promise.resolve(_props) + } }, - createMany (mapper, _props, Opts) { - incCreate(mapper.name) - _props.forEach(function (__props) { - __props[mapper.idAttribute] = new Date().getTime() - }) - return Promise.resolve(_props) - } - }, { default: true }) + { default: true } + ) const userProps = { name: 'John', @@ -565,130 +669,177 @@ describe('Mapper#create', function () { let user = await store.create('user', store.createRecord('user', JSData.utils.plainCopy(userProps)), { pass: [] }) assert(store.is('user', user), 'user should be a user record') assert.strictEqual(store.get('user', user.id), user, 'user should be in the store') - assert.objectsEqual(user.comments, [ - { - content: 'foo', - userId: user.id - } - ], 'user.comments should be an array') - assert.objectsEqual(store.getAll('comment'), [ - { - content: 'foo', - userId: user.id - } - ], 'comments should not be in the store') - assert.objectsEqual(user.profile, userProps.profile, 'user.profile should be a profile') - assert.objectsEqual(store.getAll('profile'), [userProps.profile], 'profile should be in the store') - assert.objectsEqual(user.organization, userProps.organization) + objectsEqual( + user.comments, + [ + { + content: 'foo', + userId: user.id + } + ], + 'user.comments should be an array' + ) + objectsEqual( + store.getAll('comment'), + [ + { + content: 'foo', + userId: user.id + } + ], + 'comments should not be in the store' + ) + objectsEqual(user.profile, userProps.profile, 'user.profile should be a profile') + objectsEqual(store.getAll('profile'), [userProps.profile], 'profile should be in the store') + objectsEqual(user.organization, userProps.organization) assert(!user.organizationId, 'user.organizationId should be undefined') - assert.objectsEqual(store.getAll('organization'), [userProps.organization], 'organization should be in the store') + objectsEqual(store.getAll('organization'), [userProps.organization], 'organization should be in the store') clear() - user = await store.create('user', store.createRecord('user', JSData.utils.plainCopy(userProps)), { pass: ['comments'] }) + user = await store.create('user', store.createRecord('user', JSData.utils.plainCopy(userProps)), { + pass: ['comments'] + }) assert(store.is('user', user), 'user should be a user record') assert.strictEqual(store.get('user', user.id), user, 'user should be in the store') assert(store.is('comment', user.comments[0]), 'user.comments[0] should be a comment record') - assert.objectsEqual(store.getAll('comment'), user.comments, 'comments should be in the store') - assert.objectsEqual(user.profile, userProps.profile, 'user.profile should be a profile') - assert.objectsEqual(store.getAll('profile'), [userProps.profile], 'profile should be in the store') - assert.objectsEqual(user.organization, userProps.organization) + objectsEqual(store.getAll('comment'), user.comments, 'comments should be in the store') + objectsEqual(user.profile, userProps.profile, 'user.profile should be a profile') + objectsEqual(store.getAll('profile'), [userProps.profile], 'profile should be in the store') + objectsEqual(user.organization, userProps.organization) assert(!user.organizationId, 'user.organizationId should be undefined') - assert.objectsEqual(store.getAll('organization'), [userProps.organization], 'organization should be in the store') + objectsEqual(store.getAll('organization'), [userProps.organization], 'organization should be in the store') clear() - user = await store.create('user', store.createRecord('user', JSData.utils.plainCopy(userProps)), { with: ['comments'], pass: ['profile'] }) + user = await store.create('user', store.createRecord('user', JSData.utils.plainCopy(userProps)), { + with: ['comments'], + pass: ['profile'] + }) assert(store.is('user', user), 'user should be a user record') assert.strictEqual(store.get('user', user.id), user, 'user should be in the store') assert(store.is('comment', user.comments[0]), 'user.comments[0] should be a comment record') - assert.objectsEqual(store.getAll('comment'), user.comments, 'comments should be in the store') + objectsEqual(store.getAll('comment'), user.comments, 'comments should be in the store') assert(store.is('profile', user.profile), 'user.profile should be a profile record') - assert.objectsEqual(store.getAll('profile'), [user.profile], 'profile should be in the store') - assert.objectsEqual(user.organization, userProps.organization) + objectsEqual(store.getAll('profile'), [user.profile], 'profile should be in the store') + objectsEqual(user.organization, userProps.organization) assert(!user.organizationId, 'user.organizationId should be undefined') - assert.objectsEqual(store.getAll('organization'), [userProps.organization], 'organization should be in the store') + objectsEqual(store.getAll('organization'), [userProps.organization], 'organization should be in the store') clear() - user = await store.create('user', store.createRecord('user', JSData.utils.plainCopy(userProps)), { with: ['comments', 'profile'], pass: ['organization'] }) + user = await store.create('user', store.createRecord('user', JSData.utils.plainCopy(userProps)), { + with: ['comments', 'profile'], + pass: ['organization'] + }) assert(store.is('user', user), 'user should be a user record') assert.strictEqual(store.get('user', user.id), user, 'user should be in the store') assert(store.is('comment', user.comments[0]), 'user.comments[0] should be a comment record') - assert.objectsEqual(store.getAll('comment'), user.comments, 'comments should be in the store') + objectsEqual(store.getAll('comment'), user.comments, 'comments should be in the store') assert(store.is('profile', user.profile), 'user.profile should be a profile record') - assert.objectsEqual(store.getAll('profile'), [user.profile], 'profile should be in the store') + objectsEqual(store.getAll('profile'), [user.profile], 'profile should be in the store') assert(store.is('organization', user.organization), 'user.organization should be a organization record') assert.equal(store.getAll('organization')[0].id, user.organizationId, 'user.organizationId should be correct') - assert.objectsEqual(store.getAll('organization'), [user.organization], 'organization should be in the store') + objectsEqual(store.getAll('organization'), [user.organization], 'organization should be in the store') clear() // when props are NOT a record user = await store.create('user', JSData.utils.plainCopy(userProps), { pass: [] }) assert(store.is('user', user), 'user should be a user record') assert.strictEqual(store.get('user', user.id), user, 'user should be in the store') - assert.objectsEqual(user.comments, [ - { - content: 'foo', - userId: user.id - } - ], 'user.comments should be an array') - assert.objectsEqual(store.getAll('comment'), [ + objectsEqual( + user.comments, + [ + { + content: 'foo', + userId: user.id + } + ], + 'user.comments should be an array' + ) + objectsEqual( + store.getAll('comment'), + [ + { + content: 'foo', + userId: user.id + } + ], + 'comments should not be in the store' + ) + objectsEqual( + user.profile, { - content: 'foo', + email: userProps.profile.email, userId: user.id - } - ], 'comments should not be in the store') - assert.objectsEqual(user.profile, { - email: userProps.profile.email, - userId: user.id - }, 'user.profile should be a profile') - assert.objectsEqual(store.getAll('profile'), [{ - email: userProps.profile.email, - userId: user.id - }], 'profile should be in the store') - assert.objectsEqual(user.organization, userProps.organization) + }, + 'user.profile should be a profile' + ) + objectsEqual( + store.getAll('profile'), + [ + { + email: userProps.profile.email, + userId: user.id + } + ], + 'profile should be in the store' + ) + objectsEqual(user.organization, userProps.organization) assert(!user.organizationId, 'user.organizationId should be undefined') - assert.objectsEqual(store.getAll('organization'), [userProps.organization], 'organization should be in the store') + objectsEqual(store.getAll('organization'), [userProps.organization], 'organization should be in the store') clear() user = await store.create('user', JSData.utils.plainCopy(userProps), { pass: ['comments'] }) assert(store.is('user', user), 'user should be a user record') assert.strictEqual(store.get('user', user.id), user, 'user should be in the store') assert(store.is('comment', user.comments[0]), 'user.comments[0] should be a comment record') - assert.objectsEqual(store.getAll('comment'), user.comments, 'comments should be in the store') - assert.objectsEqual(user.profile, { - email: userProps.profile.email, - userId: user.id - }, 'user.profile should be a profile') - assert.objectsEqual(store.getAll('profile'), [{ - email: userProps.profile.email, - userId: user.id - }], 'profile should be in the store') - assert.objectsEqual(user.organization, userProps.organization) + objectsEqual(store.getAll('comment'), user.comments, 'comments should be in the store') + objectsEqual( + user.profile, + { + email: userProps.profile.email, + userId: user.id + }, + 'user.profile should be a profile' + ) + objectsEqual( + store.getAll('profile'), + [ + { + email: userProps.profile.email, + userId: user.id + } + ], + 'profile should be in the store' + ) + objectsEqual(user.organization, userProps.organization) assert(!user.organizationId, 'user.organizationId should be undefined') - assert.objectsEqual(store.getAll('organization'), [userProps.organization], 'organization should be in the store') + objectsEqual(store.getAll('organization'), [userProps.organization], 'organization should be in the store') clear() user = await store.create('user', JSData.utils.plainCopy(userProps), { with: ['comments'], pass: ['profile'] }) assert(store.is('user', user), 'user should be a user record') assert.strictEqual(store.get('user', user.id), user, 'user should be in the store') assert(store.is('comment', user.comments[0]), 'user.comments[0] should be a comment record') - assert.objectsEqual(store.getAll('comment'), user.comments, 'comments should be in the store') + objectsEqual(store.getAll('comment'), user.comments, 'comments should be in the store') assert(store.is('profile', user.profile), 'user.profile should be a profile record') - assert.objectsEqual(store.getAll('profile'), [user.profile], 'profile should be in the store') - assert.objectsEqual(user.organization, userProps.organization) + objectsEqual(store.getAll('profile'), [user.profile], 'profile should be in the store') + objectsEqual(user.organization, userProps.organization) assert(!user.organizationId, 'user.organizationId should be undefined') - assert.objectsEqual(store.getAll('organization'), [userProps.organization], 'organization should be in the store') + objectsEqual(store.getAll('organization'), [userProps.organization], 'organization should be in the store') clear() - user = await store.create('user', JSData.utils.plainCopy(userProps), { with: ['comments', 'profile'], pass: ['organization'] }) + user = await store.create('user', JSData.utils.plainCopy(userProps), { + with: ['comments', 'profile'], + pass: ['organization'] + }) assert(store.is('user', user), 'user should be a user record') assert.strictEqual(store.get('user', user.id), user, 'user should be in the store') assert(store.is('comment', user.comments[0]), 'user.comments[0] should be a comment record') - assert.objectsEqual(store.getAll('comment'), user.comments, 'comments should be in the store') + objectsEqual(store.getAll('comment'), user.comments, 'comments should be in the store') assert(store.is('profile', user.profile), 'user.profile should be a profile record') - assert.objectsEqual(store.getAll('profile'), [user.profile], 'profile should be in the store') + objectsEqual(store.getAll('profile'), [user.profile], 'profile should be in the store') assert(store.is('organization', user.organization), 'user.organization should be a organization record') assert.equal(store.getAll('organization')[0].id, user.organizationId, 'user.organizationId should be correct') - assert.objectsEqual(store.getAll('organization'), [user.organization], 'organization should be in the store') + objectsEqual(store.getAll('organization'), [user.organization], 'organization should be in the store') clear() assert.equal(createCalledCount.user, 8) @@ -696,7 +847,7 @@ describe('Mapper#create', function () { assert.equal(createCalledCount.profile, 2) assert(!createCalledCount.organization) }) - it('should validate', async function () { + it('should validate', async () => { const props = { name: 1234, age: false } let createCalled = false let user @@ -720,7 +871,7 @@ describe('Mapper#create', function () { throw new Error('validation error should have been thrown!') } catch (err) { assert.equal(err.message, 'validation failed') - assert.objectsEqual(err.errors, [ + objectsEqual(err.errors, [ { actual: 'number', expected: 'one of (string)', @@ -737,7 +888,7 @@ describe('Mapper#create', function () { assert.equal(user, undefined, 'user was not created') assert.equal(props[User.idAttribute], undefined, 'props does NOT have an id') }) - it('should validate required', async function () { + it('should validate required', async () => { const props = {} let createCalled = false let user @@ -761,7 +912,7 @@ describe('Mapper#create', function () { throw new Error('validation error should have been thrown!') } catch (err) { assert.equal(err.message, 'validation failed') - assert.objectsEqual(err.errors, [ + objectsEqual(err.errors, [ { actual: 'undefined', expected: 'a value', @@ -778,7 +929,7 @@ describe('Mapper#create', function () { assert.equal(user, undefined, 'user was not created') assert.equal(props[User.idAttribute], undefined, 'props does NOT have an id') }) - it('should disallow extra props', async function () { + it('should disallow extra props', async () => { const props = { name: 'John', age: 30, @@ -824,7 +975,7 @@ describe('Mapper#create', function () { throw new Error('validation error should have been thrown!') } catch (err) { assert.equal(err.message, 'validation failed') - assert.objectsEqual(err.errors, [ + objectsEqual(err.errors, [ { actual: 'extra fields: baz', expected: 'no extra fields', diff --git a/test/unit/mapper/createMany.test.js b/test/unit/mapper/createMany.test.ts similarity index 56% rename from test/unit/mapper/createMany.test.js rename to test/unit/mapper/createMany.test.ts index 86a6cdfc..7ef5652b 100644 --- a/test/unit/mapper/createMany.test.js +++ b/test/unit/mapper/createMany.test.ts @@ -1,13 +1,13 @@ -import { assert, JSData } from '../../_setup' +import { assert, JSData, objectsEqual } from '../../_setup' -describe('Mapper#createMany', function () { - it('should be an instance method', function () { +describe('Mapper#createMany', () => { + it('should be an instance method', () => { const Mapper = JSData.Mapper const mapper = new Mapper({ name: 'foo' }) assert.equal(typeof mapper.createMany, 'function') assert.strictEqual(mapper.createMany, Mapper.prototype.createMany) }) - it('should createMany', async function () { + it('should createMany', async () => { const props = [{ name: 'John' }] let createCalled = false const UserMapper = new JSData.Mapper({ @@ -17,9 +17,9 @@ describe('Mapper#createMany', function () { UserMapper.registerAdapter('mock', { createMany (mapper, _props, Opts) { createCalled = true - return new Promise(function (resolve, reject) { + return new Promise((resolve, reject) => { assert.strictEqual(mapper, UserMapper, 'should pass in the Model') - assert.objectsEqual(_props, props, 'should pass in the props') + objectsEqual(_props, props, 'should pass in the props') _props[0][mapper.idAttribute] = new Date().getTime() resolve(_props) }) @@ -30,7 +30,7 @@ describe('Mapper#createMany', function () { assert(users[0][UserMapper.idAttribute], 'new user has an id') assert(users[0] instanceof UserMapper.recordClass, 'user is a record') }) - it('should return raw', async function () { + it('should return raw', async () => { const props = [{ name: 'John' }] let createCalled = false const User = new JSData.Mapper({ @@ -41,9 +41,9 @@ describe('Mapper#createMany', function () { User.registerAdapter('mock', { createMany (mapper, _props, Opts) { createCalled = true - return new Promise(function (resolve, reject) { + return new Promise((resolve, reject) => { assert.strictEqual(mapper, User, 'should pass in the Model') - assert.objectsEqual(_props, props, 'should pass in the props') + objectsEqual(_props, props, 'should pass in the props') assert.equal(Opts.raw, true, 'Opts are provided') _props[0][mapper.idAttribute] = new Date().getTime() resolve({ @@ -62,30 +62,36 @@ describe('Mapper#createMany', function () { }) it('should nested create everything in opts.with', async function () { const store = this.store - const createCalledCount = {} + const createCalledCount: any = {} let id = 1 - const incCreate = function (name) { - if (!Object.hasOwnProperty.call(createCalledCount, name)) { + const incCreate = name => { + if (!createCalledCount.hasOwnProperty(name)) { createCalledCount[name] = 0 } createCalledCount[name]++ } - const clear = function () { - for (var key in store._mappers) { + const clear = () => { + // tslint:disable-next-line:forin + for (const key in store._mappers) { store.removeAll(key) } } - store.registerAdapter('mock', { - createMany (mapper, _props, Opts) { - incCreate(mapper.name) - _props.forEach(function (__props) { - __props[mapper.idAttribute] = id - id++ - }) - return Promise.resolve(_props) - } - }, { default: true }) + store.registerAdapter( + 'mock', + { + createMany (mapper, _props, Opts) { + incCreate(mapper.name) + // tslint:disable-next-line:variable-name + _props.forEach(__props => { + __props[mapper.idAttribute] = id + id++ + }) + return Promise.resolve(_props) + } + }, + { default: true } + ) const userProps = [ { @@ -108,8 +114,8 @@ describe('Mapper#createMany', function () { } ] - const getProps = function () { - return JSData.utils.plainCopy(userProps).map(function (props) { + const getProps = () => { + return JSData.utils.plainCopy(userProps).map(props => { return store.createRecord('user', props) }) } @@ -120,14 +126,22 @@ describe('Mapper#createMany', function () { assert(store.is('user', users[1]), 'user 2 should be a user record') assert(store.get('user', users[0].id) === users[0], 'user 1 should be in the store') assert(store.get('user', users[1].id) === users[1], 'user 2 should be in the store') - assert.objectsEqual(users[0].profile, userProps[0].profile, 'users[0].profile should be a profile') - assert.objectsEqual(users[1].profile, userProps[1].profile, 'users[1].profile should be a profile') - assert.objectsEqual(store.getAll('profile'), [userProps[1].profile, userProps[0].profile], 'profiles should not be in the store') - assert.objectsEqual(users[0].organization, userProps[0].organization, 'users[0].organization should exist') - assert.objectsEqual(users[1].organization, userProps[1].organization, 'users[1].organization should exist') + objectsEqual(users[0].profile, userProps[0].profile, 'users[0].profile should be a profile') + objectsEqual(users[1].profile, userProps[1].profile, 'users[1].profile should be a profile') + objectsEqual( + store.getAll('profile'), + [userProps[1].profile, userProps[0].profile], + 'profiles should not be in the store' + ) + objectsEqual(users[0].organization, userProps[0].organization, 'users[0].organization should exist') + objectsEqual(users[1].organization, userProps[1].organization, 'users[1].organization should exist') assert(!users[0].organizationId, 'users[0].organizationId should be undefined') assert(!users[1].organizationId, 'users[1].organizationId should be undefined') - assert.objectsEqual(store.getAll('organization'), [userProps[1].organization, userProps[0].organization], 'organization should not be in the store') + objectsEqual( + store.getAll('organization'), + [userProps[1].organization, userProps[0].organization], + 'organization should not be in the store' + ) clear() users = await store.createMany('user', getProps(), { with: ['profile'] }) @@ -137,12 +151,16 @@ describe('Mapper#createMany', function () { assert(store.get('user', users[1].id) === users[1], 'users[1] should be in the store') assert(store.is('profile', users[0].profile), 'users[0].profile should be a profile record') assert(store.is('profile', users[1].profile), 'users[1].profile should be a profile record') - assert.objectsEqual(store.getAll('profile'), [users[0].profile, users[1].profile], 'profiles should be in the store') - assert.objectsEqual(users[0].organization, userProps[0].organization, 'users[0].organization should exist') - assert.objectsEqual(users[1].organization, userProps[1].organization, 'users[1].organization should exist') + objectsEqual(store.getAll('profile'), [users[0].profile, users[1].profile], 'profiles should be in the store') + objectsEqual(users[0].organization, userProps[0].organization, 'users[0].organization should exist') + objectsEqual(users[1].organization, userProps[1].organization, 'users[1].organization should exist') assert(!users[0].organizationId, 'users[0].organizationId should be undefined') assert(!users[1].organizationId, 'users[1].organizationId should be undefined') - assert.objectsEqual(store.getAll('organization'), [userProps[1].organization, userProps[0].organization], 'organizations should be in the store') + objectsEqual( + store.getAll('organization'), + [userProps[1].organization, userProps[0].organization], + 'organizations should be in the store' + ) clear() users = await store.createMany('user', getProps(), { with: ['profile', 'organization'] }) @@ -152,12 +170,24 @@ describe('Mapper#createMany', function () { assert(store.get('user', users[1].id) === users[1], 'users[1] should be in the store') assert(store.is('profile', users[0].profile), 'users[0].profile should be a profile record') assert(store.is('profile', users[1].profile), 'users[1].profile should be a profile record') - assert.objectsEqual(store.getAll('profile'), [users[0].profile, users[1].profile], 'profiles should be in the store') + objectsEqual(store.getAll('profile'), [users[0].profile, users[1].profile], 'profiles should be in the store') assert(store.is('organization', users[0].organization), 'users[0].organization should be a organization record') assert(store.is('organization', users[1].organization), 'users[1].organization should be a organization record') - assert.equal(store.getAll('organization')[0].id, users[0].organizationId, 'users[0].organizationId should be correct') - assert.equal(store.getAll('organization')[1].id, users[1].organizationId, 'users[1].organizationId should be correct') - assert.objectsEqual(store.getAll('organization'), [users[0].organization, users[1].organization], 'organizations should be in the store') + assert.equal( + store.getAll('organization')[0].id, + users[0].organizationId, + 'users[0].organizationId should be correct' + ) + assert.equal( + store.getAll('organization')[1].id, + users[1].organizationId, + 'users[1].organizationId should be correct' + ) + objectsEqual( + store.getAll('organization'), + [users[0].organization, users[1].organization], + 'organizations should be in the store' + ) clear() // when props are NOT a record @@ -166,30 +196,57 @@ describe('Mapper#createMany', function () { assert(store.is('user', users[1]), 'users[1] should be a user record') assert(store.get('user', users[0].id) === users[0], 'users[0] should be in the store') assert(store.get('user', users[1].id) === users[1], 'users[1] should be in the store') - assert.objectsEqual(users[0].profile, { - email: userProps[0].profile.email, - userId: users[0].id - }, 'users[0].profile should be a profile') - assert.objectsEqual(users[1].profile, { - email: userProps[1].profile.email, - userId: users[1].id - }, 'users[1].profile should be a profile') - assert.objectsEqual(store.getAll('profile'), [{ - email: userProps[1].profile.email, - userId: users[1].id - }, { - email: userProps[0].profile.email, - userId: users[0].id - }], 'profiles should be in the store') - assert.objectsEqual(users[0].organization, { - name: 'Company Inc' - }, 'users[0].organization should an organization') - assert.objectsEqual(users[1].organization, { - name: 'Company LLC' - }, 'users[1].organization should an organization') + objectsEqual( + users[0].profile, + { + email: userProps[0].profile.email, + userId: users[0].id + }, + 'users[0].profile should be a profile' + ) + objectsEqual( + users[1].profile, + { + email: userProps[1].profile.email, + userId: users[1].id + }, + 'users[1].profile should be a profile' + ) + objectsEqual( + store.getAll('profile'), + [ + { + email: userProps[1].profile.email, + userId: users[1].id + }, + { + email: userProps[0].profile.email, + userId: users[0].id + } + ], + 'profiles should be in the store' + ) + objectsEqual( + users[0].organization, + { + name: 'Company Inc' + }, + 'users[0].organization should an organization' + ) + objectsEqual( + users[1].organization, + { + name: 'Company LLC' + }, + 'users[1].organization should an organization' + ) assert(!users[0].organizationId, 'users[0].organizationId should be undefined') assert(!users[1].organizationId, 'users[1].organizationId should be undefined') - assert.objectsEqual(store.getAll('organization'), [userProps[1].organization, userProps[0].organization], 'organizations should be in the store') + objectsEqual( + store.getAll('organization'), + [userProps[1].organization, userProps[0].organization], + 'organizations should be in the store' + ) clear() users = await store.createMany('user', JSData.utils.copy(userProps), { with: ['profile'] }) @@ -199,16 +256,28 @@ describe('Mapper#createMany', function () { assert(store.get('user', users[1].id) === users[1], 'users[1] should be in the store') assert(store.is('profile', users[0].profile), 'users[0].profile should be a profile record') assert(store.is('profile', users[1].profile), 'users[1].profile should be a profile record') - assert.objectsEqual(store.getAll('profile'), [users[0].profile, users[1].profile], 'profiles should be in the store') - assert.objectsEqual(users[0].organization, { - name: 'Company Inc' - }, 'users[0].organization should an organization') - assert.objectsEqual(users[1].organization, { - name: 'Company LLC' - }, 'users[1].organization should an organization') + objectsEqual(store.getAll('profile'), [users[0].profile, users[1].profile], 'profiles should be in the store') + objectsEqual( + users[0].organization, + { + name: 'Company Inc' + }, + 'users[0].organization should an organization' + ) + objectsEqual( + users[1].organization, + { + name: 'Company LLC' + }, + 'users[1].organization should an organization' + ) assert(!users[0].organizationId, 'users[0].organizationId should be undefined') assert(!users[1].organizationId, 'users[1].organizationId should be undefined') - assert.objectsEqual(store.getAll('organization'), [userProps[1].organization, userProps[0].organization], 'organizations should be in the store') + objectsEqual( + store.getAll('organization'), + [userProps[1].organization, userProps[0].organization], + 'organizations should be in the store' + ) clear() users = await store.createMany('user', JSData.utils.copy(userProps), { with: ['profile', 'organization'] }) @@ -218,12 +287,24 @@ describe('Mapper#createMany', function () { assert(store.get('user', users[1].id) === users[1], 'users[1] should be in the store') assert(store.is('profile', users[0].profile), 'users[0].profile should be a profile record') assert(store.is('profile', users[1].profile), 'users[1].profile should be a profile record') - assert.objectsEqual(store.getAll('profile'), [users[0].profile, users[1].profile], 'profiles should be in the store') + objectsEqual(store.getAll('profile'), [users[0].profile, users[1].profile], 'profiles should be in the store') assert(store.is('organization', users[0].organization), 'users[0].organization should be a organization record') assert(store.is('organization', users[1].organization), 'users[1].organization should be a organization record') - assert.equal(store.getAll('organization')[0].id, users[0].organizationId, 'users[0].organizationId should be correct') - assert.equal(store.getAll('organization')[1].id, users[1].organizationId, 'users[1].organizationId should be correct') - assert.objectsEqual(store.getAll('organization'), [users[0].organization, users[1].organization], 'organizations should be in the store') + assert.equal( + store.getAll('organization')[0].id, + users[0].organizationId, + 'users[0].organizationId should be correct' + ) + assert.equal( + store.getAll('organization')[1].id, + users[1].organizationId, + 'users[1].organizationId should be correct' + ) + objectsEqual( + store.getAll('organization'), + [users[0].organization, users[1].organization], + 'organizations should be in the store' + ) clear() assert.equal(createCalledCount.user, 6) @@ -233,46 +314,53 @@ describe('Mapper#createMany', function () { }) it('should pass everything opts.pass', async function () { const store = this.store - const createCalledCount = {} + const createCalledCount: any = {} let id = 1 const utils = JSData.utils - const incCreate = function (name) { - if (!Object.hasOwnProperty.call(createCalledCount, name)) { + const incCreate = name => { + if (!createCalledCount.hasOwnProperty(name)) { createCalledCount[name] = 0 } createCalledCount[name]++ } - const clear = function () { - for (var key in store._mappers) { + const clear = () => { + // tslint:disable-next-line:forin + for (const key in store._mappers) { store.removeAll(key) } } - store.registerAdapter('mock', { - createMany (mapper, _props, Opts) { - incCreate(mapper.name) - _props.forEach(function (__props) { - __props[mapper.idAttribute] = id - id++ - }) - mapper.relationFields.forEach(function (field) { - _props.forEach(function (__props) { - if (__props[field]) { - if (utils.isArray(__props[field])) { - __props[field].forEach(function (item) { - item.id = id + store.registerAdapter( + 'mock', + { + createMany (mapper, _props, Opts) { + incCreate(mapper.name) + // tslint:disable-next-line:variable-name + _props.forEach(__props => { + __props[mapper.idAttribute] = id + id++ + }) + mapper.relationFields.forEach(field => { + // tslint:disable-next-line:variable-name + _props.forEach(__props => { + if (__props[field]) { + if (utils.isArray(__props[field])) { + __props[field].forEach(item => { + item.id = id + id++ + }) + } else if (utils.isObject(__props[field])) { + __props[field].id = id id++ - }) - } else if (utils.isObject(__props[field])) { - __props[field].id = id - id++ + } } - } + }) }) - }) - return Promise.resolve(_props) - } - }, { default: true }) + return Promise.resolve(_props) + } + }, + { default: true } + ) const userProps = [ { @@ -295,8 +383,8 @@ describe('Mapper#createMany', function () { } ] - const getProps = function () { - return JSData.utils.copy(userProps).map(function (props) { + const getProps = () => { + return JSData.utils.copy(userProps).map(props => { return store.createRecord('user', props) }) } @@ -307,14 +395,22 @@ describe('Mapper#createMany', function () { assert(store.is('user', users[1]), 'user 2 should be a user record') assert(store.get('user', users[0].id) === users[0], 'user 1 should be in the store') assert(store.get('user', users[1].id) === users[1], 'user 2 should be in the store') - assert.objectsEqual(users[0].profile, userProps[0].profile, 'users[0].profile should be a profile') - assert.objectsEqual(users[1].profile, userProps[1].profile, 'users[1].profile should be a profile') - assert.objectsEqual(store.getAll('profile'), [userProps[1].profile, userProps[0].profile], 'profiles should not be in the store') - assert.objectsEqual(users[0].organization, userProps[0].organization, 'users[0].organization should exist') - assert.objectsEqual(users[1].organization, userProps[1].organization, 'users[1].organization should exist') + objectsEqual(users[0].profile, userProps[0].profile, 'users[0].profile should be a profile') + objectsEqual(users[1].profile, userProps[1].profile, 'users[1].profile should be a profile') + objectsEqual( + store.getAll('profile'), + [userProps[1].profile, userProps[0].profile], + 'profiles should not be in the store' + ) + objectsEqual(users[0].organization, userProps[0].organization, 'users[0].organization should exist') + objectsEqual(users[1].organization, userProps[1].organization, 'users[1].organization should exist') assert(!users[0].organizationId, 'users[0].organizationId should be undefined') assert(!users[1].organizationId, 'users[1].organizationId should be undefined') - assert.objectsEqual(store.getAll('organization'), [userProps[1].organization, userProps[0].organization], 'organization should not be in the store') + objectsEqual( + store.getAll('organization'), + [userProps[1].organization, userProps[0].organization], + 'organization should not be in the store' + ) clear() users = await store.createMany('user', getProps(), { pass: ['profile'] }) @@ -324,12 +420,16 @@ describe('Mapper#createMany', function () { assert(store.get('user', users[1].id) === users[1], 'users[1] should be in the store') assert(store.is('profile', users[0].profile), 'users[0].profile should be a profile record') assert(store.is('profile', users[1].profile), 'users[1].profile should be a profile record') - assert.objectsEqual(store.getAll('profile'), [users[0].profile, users[1].profile], 'profiles should be in the store') - assert.objectsEqual(users[0].organization, userProps[0].organization, 'users[0].organization should exist') - assert.objectsEqual(users[1].organization, userProps[1].organization, 'users[1].organization should exist') + objectsEqual(store.getAll('profile'), [users[0].profile, users[1].profile], 'profiles should be in the store') + objectsEqual(users[0].organization, userProps[0].organization, 'users[0].organization should exist') + objectsEqual(users[1].organization, userProps[1].organization, 'users[1].organization should exist') assert(!users[0].organizationId, 'users[0].organizationId should be undefined') assert(!users[1].organizationId, 'users[1].organizationId should be undefined') - assert.objectsEqual(store.getAll('organization'), [userProps[1].organization, userProps[0].organization], 'organizations should be in the store') + objectsEqual( + store.getAll('organization'), + [userProps[1].organization, userProps[0].organization], + 'organizations should be in the store' + ) clear() users = await store.createMany('user', getProps(), { pass: ['profile', 'organization'] }) @@ -339,12 +439,24 @@ describe('Mapper#createMany', function () { assert(store.get('user', users[1].id) === users[1], 'users[1] should be in the store') assert(store.is('profile', users[0].profile), 'users[0].profile should be a profile record') assert(store.is('profile', users[1].profile), 'users[1].profile should be a profile record') - assert.objectsEqual(store.getAll('profile'), [users[0].profile, users[1].profile], 'profiles should be in the store') + objectsEqual(store.getAll('profile'), [users[0].profile, users[1].profile], 'profiles should be in the store') assert(store.is('organization', users[0].organization), 'users[0].organization should be a organization record') assert(store.is('organization', users[1].organization), 'users[1].organization should be a organization record') - assert.equal(store.getAll('organization')[0].id, users[0].organizationId, 'users[0].organizationId should be correct') - assert.equal(store.getAll('organization')[1].id, users[1].organizationId, 'users[1].organizationId should be correct') - assert.objectsEqual(store.getAll('organization'), [users[0].organization, users[1].organization], 'organizations should be in the store') + assert.equal( + store.getAll('organization')[0].id, + users[0].organizationId, + 'users[0].organizationId should be correct' + ) + assert.equal( + store.getAll('organization')[1].id, + users[1].organizationId, + 'users[1].organizationId should be correct' + ) + objectsEqual( + store.getAll('organization'), + [users[0].organization, users[1].organization], + 'organizations should be in the store' + ) clear() // when props are NOT a record @@ -353,30 +465,57 @@ describe('Mapper#createMany', function () { assert(store.is('user', users[1]), 'users[1] should be a user record') assert(store.get('user', users[0].id) === users[0], 'users[0] should be in the store') assert(store.get('user', users[1].id) === users[1], 'users[1] should be in the store') - assert.objectsEqual(users[0].profile, { - email: userProps[0].profile.email, - userId: users[0].id - }, 'users[0].profile should be a profile') - assert.objectsEqual(users[1].profile, { - email: userProps[1].profile.email, - userId: users[1].id - }, 'users[1].profile should be a profile') - assert.objectsEqual(store.getAll('profile'), [{ - email: userProps[1].profile.email, - userId: users[1].id - }, { - email: userProps[0].profile.email, - userId: users[0].id - }], 'profiles should be in the store') - assert.objectsEqual(users[0].organization, { - name: 'Company Inc' - }, 'users[0].organization should an organization') - assert.objectsEqual(users[1].organization, { - name: 'Company LLC' - }, 'users[1].organization should an organization') + objectsEqual( + users[0].profile, + { + email: userProps[0].profile.email, + userId: users[0].id + }, + 'users[0].profile should be a profile' + ) + objectsEqual( + users[1].profile, + { + email: userProps[1].profile.email, + userId: users[1].id + }, + 'users[1].profile should be a profile' + ) + objectsEqual( + store.getAll('profile'), + [ + { + email: userProps[1].profile.email, + userId: users[1].id + }, + { + email: userProps[0].profile.email, + userId: users[0].id + } + ], + 'profiles should be in the store' + ) + objectsEqual( + users[0].organization, + { + name: 'Company Inc' + }, + 'users[0].organization should an organization' + ) + objectsEqual( + users[1].organization, + { + name: 'Company LLC' + }, + 'users[1].organization should an organization' + ) assert(!users[0].organizationId, 'users[0].organizationId should be undefined') assert(!users[1].organizationId, 'users[1].organizationId should be undefined') - assert.objectsEqual(store.getAll('organization'), [userProps[1].organization, userProps[0].organization], 'organizations should be in the store') + objectsEqual( + store.getAll('organization'), + [userProps[1].organization, userProps[0].organization], + 'organizations should be in the store' + ) clear() users = await store.createMany('user', JSData.utils.copy(userProps), { pass: ['profile'] }) @@ -386,16 +525,28 @@ describe('Mapper#createMany', function () { assert(store.get('user', users[1].id) === users[1], 'users[1] should be in the store') assert(store.is('profile', users[0].profile), 'users[0].profile should be a profile record') assert(store.is('profile', users[1].profile), 'users[1].profile should be a profile record') - assert.objectsEqual(store.getAll('profile'), [users[0].profile, users[1].profile], 'profiles should be in the store') - assert.objectsEqual(users[0].organization, { - name: 'Company Inc' - }, 'users[0].organization should an organization') - assert.objectsEqual(users[1].organization, { - name: 'Company LLC' - }, 'users[1].organization should an organization') + objectsEqual(store.getAll('profile'), [users[0].profile, users[1].profile], 'profiles should be in the store') + objectsEqual( + users[0].organization, + { + name: 'Company Inc' + }, + 'users[0].organization should an organization' + ) + objectsEqual( + users[1].organization, + { + name: 'Company LLC' + }, + 'users[1].organization should an organization' + ) assert(!users[0].organizationId, 'users[0].organizationId should be undefined') assert(!users[1].organizationId, 'users[1].organizationId should be undefined') - assert.objectsEqual(store.getAll('organization'), [userProps[1].organization, userProps[0].organization], 'organizations should be in the store') + objectsEqual( + store.getAll('organization'), + [userProps[1].organization, userProps[0].organization], + 'organizations should be in the store' + ) clear() users = await store.createMany('user', JSData.utils.copy(userProps), { pass: ['profile', 'organization'] }) @@ -405,12 +556,24 @@ describe('Mapper#createMany', function () { assert(store.get('user', users[1].id) === users[1], 'users[1] should be in the store') assert(store.is('profile', users[0].profile), 'users[0].profile should be a profile record') assert(store.is('profile', users[1].profile), 'users[1].profile should be a profile record') - assert.objectsEqual(store.getAll('profile'), [users[0].profile, users[1].profile], 'profiles should be in the store') + objectsEqual(store.getAll('profile'), [users[0].profile, users[1].profile], 'profiles should be in the store') assert(store.is('organization', users[0].organization), 'users[0].organization should be a organization record') assert(store.is('organization', users[1].organization), 'users[1].organization should be a organization record') - assert.equal(store.getAll('organization')[0].id, users[0].organizationId, 'users[0].organizationId should be correct') - assert.equal(store.getAll('organization')[1].id, users[1].organizationId, 'users[1].organizationId should be correct') - assert.objectsEqual(store.getAll('organization'), [users[0].organization, users[1].organization], 'organizations should be in the store') + assert.equal( + store.getAll('organization')[0].id, + users[0].organizationId, + 'users[0].organizationId should be correct' + ) + assert.equal( + store.getAll('organization')[1].id, + users[1].organizationId, + 'users[1].organizationId should be correct' + ) + objectsEqual( + store.getAll('organization'), + [users[0].organization, users[1].organization], + 'organizations should be in the store' + ) clear() assert.equal(createCalledCount.user, 6) @@ -420,46 +583,53 @@ describe('Mapper#createMany', function () { }) it('should combine opts.with and opts.pass', async function () { const store = this.store - const createCalledCount = {} + const createCalledCount: any = {} let id = 1 const utils = JSData.utils - const incCreate = function (name) { - if (!Object.hasOwnProperty.call(createCalledCount, name)) { + const incCreate = name => { + if (!createCalledCount.hasOwnProperty(name)) { createCalledCount[name] = 0 } createCalledCount[name]++ } - const clear = function () { - for (var key in store._mappers) { + const clear = () => { + // tslint:disable-next-line:forin + for (const key in store._mappers) { store.removeAll(key) } } - store.registerAdapter('mock', { - createMany (mapper, _props, Opts) { - incCreate(mapper.name) - _props.forEach(function (__props) { - __props[mapper.idAttribute] = id - id++ - }) - mapper.relationFields.forEach(function (field) { - _props.forEach(function (__props) { - if (__props[field]) { - if (utils.isArray(__props[field])) { - __props[field].forEach(function (item) { - item.id = id + store.registerAdapter( + 'mock', + { + createMany (mapper, _props, Opts) { + incCreate(mapper.name) + // tslint:disable-next-line:variable-name + _props.forEach(__props => { + __props[mapper.idAttribute] = id + id++ + }) + mapper.relationFields.forEach(field => { + // tslint:disable-next-line:variable-name + _props.forEach(__props => { + if (__props[field]) { + if (utils.isArray(__props[field])) { + __props[field].forEach(item => { + item.id = id + id++ + }) + } else if (utils.isObject(__props[field])) { + __props[field].id = id id++ - }) - } else if (utils.isObject(__props[field])) { - __props[field].id = id - id++ + } } - } + }) }) - }) - return Promise.resolve(_props) - } - }, { default: true }) + return Promise.resolve(_props) + } + }, + { default: true } + ) const userProps = [ { @@ -482,8 +652,8 @@ describe('Mapper#createMany', function () { } ] - const getProps = function () { - return JSData.utils.copy(userProps).map(function (props) { + const getProps = () => { + return JSData.utils.copy(userProps).map(props => { return store.createRecord('user', props) }) } @@ -494,14 +664,22 @@ describe('Mapper#createMany', function () { assert(store.is('user', users[1]), 'user 2 should be a user record') assert(store.get('user', users[0].id) === users[0], 'user 1 should be in the store') assert(store.get('user', users[1].id) === users[1], 'user 2 should be in the store') - assert.objectsEqual(users[0].profile, userProps[0].profile, 'users[0].profile should be a profile') - assert.objectsEqual(users[1].profile, userProps[1].profile, 'users[1].profile should be a profile') - assert.objectsEqual(store.getAll('profile'), [userProps[1].profile, userProps[0].profile], 'profiles should not be in the store') - assert.objectsEqual(users[0].organization, userProps[0].organization, 'users[0].organization should exist') - assert.objectsEqual(users[1].organization, userProps[1].organization, 'users[1].organization should exist') + objectsEqual(users[0].profile, userProps[0].profile, 'users[0].profile should be a profile') + objectsEqual(users[1].profile, userProps[1].profile, 'users[1].profile should be a profile') + objectsEqual( + store.getAll('profile'), + [userProps[1].profile, userProps[0].profile], + 'profiles should not be in the store' + ) + objectsEqual(users[0].organization, userProps[0].organization, 'users[0].organization should exist') + objectsEqual(users[1].organization, userProps[1].organization, 'users[1].organization should exist') assert(!users[0].organizationId, 'users[0].organizationId should be undefined') assert(!users[1].organizationId, 'users[1].organizationId should be undefined') - assert.objectsEqual(store.getAll('organization'), [userProps[1].organization, userProps[0].organization], 'organization should not be in the store') + objectsEqual( + store.getAll('organization'), + [userProps[1].organization, userProps[0].organization], + 'organization should not be in the store' + ) clear() users = await store.createMany('user', getProps(), { with: ['profile'], pass: ['organization'] }) @@ -511,12 +689,24 @@ describe('Mapper#createMany', function () { assert(store.get('user', users[1].id) === users[1], 'users[1] should be in the store') assert(store.is('profile', users[0].profile), 'users[0].profile should be a profile record') assert(store.is('profile', users[1].profile), 'users[1].profile should be a profile record') - assert.objectsEqual(store.getAll('profile'), [users[0].profile, users[1].profile], 'profiles should be in the store') + objectsEqual(store.getAll('profile'), [users[0].profile, users[1].profile], 'profiles should be in the store') assert(store.is('organization', users[0].organization), 'users[0].organization should be a organization record') assert(store.is('organization', users[1].organization), 'users[1].organization should be a organization record') - assert.equal(store.getAll('organization')[0].id, users[0].organizationId, 'users[0].organizationId should be correct') - assert.equal(store.getAll('organization')[1].id, users[1].organizationId, 'users[1].organizationId should be correct') - assert.objectsEqual(store.getAll('organization'), [users[0].organization, users[1].organization], 'organizations should be in the store') + assert.equal( + store.getAll('organization')[0].id, + users[0].organizationId, + 'users[0].organizationId should be correct' + ) + assert.equal( + store.getAll('organization')[1].id, + users[1].organizationId, + 'users[1].organizationId should be correct' + ) + objectsEqual( + store.getAll('organization'), + [users[0].organization, users[1].organization], + 'organizations should be in the store' + ) clear() // when props are NOT a record @@ -525,30 +715,57 @@ describe('Mapper#createMany', function () { assert(store.is('user', users[1]), 'users[1] should be a user record') assert(store.get('user', users[0].id) === users[0], 'users[0] should be in the store') assert(store.get('user', users[1].id) === users[1], 'users[1] should be in the store') - assert.objectsEqual(users[0].profile, { - email: userProps[0].profile.email, - userId: users[0].id - }, 'users[0].profile should be a profile') - assert.objectsEqual(users[1].profile, { - email: userProps[1].profile.email, - userId: users[1].id - }, 'users[1].profile should be a profile') - assert.objectsEqual(store.getAll('profile'), [{ - email: userProps[1].profile.email, - userId: users[1].id - }, { - email: userProps[0].profile.email, - userId: users[0].id - }], 'profiles should be in the store') - assert.objectsEqual(users[0].organization, { - name: 'Company Inc' - }, 'users[0].organization should an organization') - assert.objectsEqual(users[1].organization, { - name: 'Company LLC' - }, 'users[1].organization should an organization') + objectsEqual( + users[0].profile, + { + email: userProps[0].profile.email, + userId: users[0].id + }, + 'users[0].profile should be a profile' + ) + objectsEqual( + users[1].profile, + { + email: userProps[1].profile.email, + userId: users[1].id + }, + 'users[1].profile should be a profile' + ) + objectsEqual( + store.getAll('profile'), + [ + { + email: userProps[1].profile.email, + userId: users[1].id + }, + { + email: userProps[0].profile.email, + userId: users[0].id + } + ], + 'profiles should be in the store' + ) + objectsEqual( + users[0].organization, + { + name: 'Company Inc' + }, + 'users[0].organization should an organization' + ) + objectsEqual( + users[1].organization, + { + name: 'Company LLC' + }, + 'users[1].organization should an organization' + ) assert(!users[0].organizationId, 'users[0].organizationId should be undefined') assert(!users[1].organizationId, 'users[1].organizationId should be undefined') - assert.objectsEqual(store.getAll('organization'), [userProps[1].organization, userProps[0].organization], 'organizations should be in the store') + objectsEqual( + store.getAll('organization'), + [userProps[1].organization, userProps[0].organization], + 'organizations should be in the store' + ) clear() users = await store.createMany('user', JSData.utils.copy(userProps), { with: ['profile'], pass: ['organization'] }) @@ -558,12 +775,24 @@ describe('Mapper#createMany', function () { assert(store.get('user', users[1].id) === users[1], 'users[1] should be in the store') assert(store.is('profile', users[0].profile), 'users[0].profile should be a profile record') assert(store.is('profile', users[1].profile), 'users[1].profile should be a profile record') - assert.objectsEqual(store.getAll('profile'), [users[0].profile, users[1].profile], 'profiles should be in the store') + objectsEqual(store.getAll('profile'), [users[0].profile, users[1].profile], 'profiles should be in the store') assert(store.is('organization', users[0].organization), 'users[0].organization should be a organization record') assert(store.is('organization', users[1].organization), 'users[1].organization should be a organization record') - assert.equal(store.getAll('organization')[0].id, users[0].organizationId, 'users[0].organizationId should be correct') - assert.equal(store.getAll('organization')[1].id, users[1].organizationId, 'users[1].organizationId should be correct') - assert.objectsEqual(store.getAll('organization'), [users[0].organization, users[1].organization], 'organizations should be in the store') + assert.equal( + store.getAll('organization')[0].id, + users[0].organizationId, + 'users[0].organizationId should be correct' + ) + assert.equal( + store.getAll('organization')[1].id, + users[1].organizationId, + 'users[1].organizationId should be correct' + ) + objectsEqual( + store.getAll('organization'), + [users[0].organization, users[1].organization], + 'organizations should be in the store' + ) clear() assert.equal(createCalledCount.user, 4) @@ -571,7 +800,7 @@ describe('Mapper#createMany', function () { assert.equal(createCalledCount.profile, 2) assert(!createCalledCount.organization) }) - it('should validate', async function () { + it('should validate', async () => { const props = [{ name: true }, {}, { name: 1234, age: 25 }] let createCalled = false let users @@ -595,7 +824,7 @@ describe('Mapper#createMany', function () { throw new Error('validation error should have been thrown!') } catch (err) { assert.equal(err.message, 'validation failed') - assert.objectsEqual(err.errors, [ + objectsEqual(err.errors, [ [ { actual: 'boolean', @@ -617,7 +846,7 @@ describe('Mapper#createMany', function () { assert.equal(users, undefined, 'users were not created') assert.equal(props[0][User.idAttribute], undefined, 'props[0] does NOT have an id') }) - it('should validate required', async function () { + it('should validate required', async () => { const props = [{ name: 'John' }, {}, { name: 'Sally', age: 25 }] let createCalled = false let users @@ -641,7 +870,7 @@ describe('Mapper#createMany', function () { throw new Error('validation error should have been thrown!') } catch (err) { assert.equal(err.message, 'validation failed') - assert.objectsEqual(err.errors, [ + objectsEqual(err.errors, [ [ { actual: 'undefined', diff --git a/test/unit/mapper/createRecord.test.js b/test/unit/mapper/createRecord.test.ts similarity index 84% rename from test/unit/mapper/createRecord.test.js rename to test/unit/mapper/createRecord.test.ts index 6e32f7ac..759ab2f2 100644 --- a/test/unit/mapper/createRecord.test.js +++ b/test/unit/mapper/createRecord.test.ts @@ -1,13 +1,13 @@ -import { assert, JSData, TYPES_EXCEPT_OBJECT_OR_ARRAY } from '../../_setup' +import { assert, JSData, objectsEqual, TYPES_EXCEPT_OBJECT_OR_ARRAY } from '../../_setup' -describe('Mapper#createRecord', function () { - it('should be an instance method', function () { +describe('Mapper#createRecord', () => { + it('should be an instance method', () => { const Mapper = JSData.Mapper const mapper = new Mapper({ name: 'foo' }) assert.equal(typeof mapper.createRecord, 'function') assert.strictEqual(mapper.createRecord, Mapper.prototype.createRecord) }) - it('should require an object or array', function () { + it('should require an object or array', () => { const Mapper = JSData.Mapper const mapper = new Mapper({ name: 'foo' }) assert.doesNotThrow(() => { @@ -15,7 +15,7 @@ describe('Mapper#createRecord', function () { mapper.createRecord({}) mapper.createRecord([{}]) }) - TYPES_EXCEPT_OBJECT_OR_ARRAY.forEach((value) => { + TYPES_EXCEPT_OBJECT_OR_ARRAY.forEach(value => { if (!value) { return } @@ -24,10 +24,11 @@ describe('Mapper#createRecord', function () { }, `[Mapper#createRecord:props] expected: array or object, found: ${typeof value}\nhttp://www.js-data.io/v3.0/docs/errors#400`) }) }) - it('should create an instance', function () { + it('should create an instance', () => { const store = new JSData.DataStore() + class Person extends JSData.Record { - constructor (props, opts) { + constructor (props, opts?) { super(props, opts) if (!this._get) { JSData.Record.call(this, props, opts) @@ -42,12 +43,14 @@ describe('Mapper#createRecord', function () { return `${this.first} ${this.last}` } } + const PersonMapper = store.defineMapper('person', { recordClass: Person }) + // tslint:disable-next-line:max-classes-per-file class Dog extends JSData.Record { - constructor (props, opts) { + constructor (props, opts?) { super(props, opts) if (!this._get) { JSData.Record.call(this, props, opts) @@ -58,13 +61,15 @@ describe('Mapper#createRecord', function () { return 'woof' } } + const DogMapper = store.defineMapper('dog', { recordClass: Dog, name: 'Dog' }) + // tslint:disable-next-line:max-classes-per-file class Cat extends JSData.Record { - constructor (props, opts) { + constructor (props?, opts?) { super(props, opts) if (!this._get) { JSData.Record.call(this, props, opts) @@ -75,6 +80,7 @@ describe('Mapper#createRecord', function () { return 'meow' } } + const CatMapper = store.defineMapper('cat', { name: 'Cat', recordClass: Cat @@ -105,12 +111,12 @@ describe('Mapper#createRecord', function () { assert.equal(cat.say(), 'meow') assert.equal(cat2.say(), 'meow') - assert.objectsEqual(person, { + objectsEqual(person, { first: 'John', last: 'Anderson' }) - assert.objectsEqual(dog, dogAttrs) - assert.objectsEqual(cat, {}) + objectsEqual(dog, dogAttrs) + objectsEqual(cat, {}) assert(person instanceof Person) assert(person2 instanceof Person) diff --git a/test/unit/mapper/destroy.test.js b/test/unit/mapper/destroy.test.ts similarity index 85% rename from test/unit/mapper/destroy.test.js rename to test/unit/mapper/destroy.test.ts index 1148b9d1..d482cb85 100644 --- a/test/unit/mapper/destroy.test.js +++ b/test/unit/mapper/destroy.test.ts @@ -1,13 +1,13 @@ import { assert, JSData } from '../../_setup' -describe('Mapper#createRecord', function () { - it('should be an instance method', function () { +describe('Mapper#createRecord', () => { + it('should be an instance method', () => { const Mapper = JSData.Mapper const mapper = new Mapper({ name: 'foo' }) assert.equal(typeof mapper.destroy, 'function') assert.strictEqual(mapper.destroy, Mapper.prototype.destroy) }) - it('should destroy', async function () { + it('should destroy', async () => { const id = 1 let destroyCalled = false const User = new JSData.Mapper({ @@ -17,7 +17,7 @@ describe('Mapper#createRecord', function () { User.registerAdapter('mock', { destroy (mapper, _id, Opts) { destroyCalled = true - return new Promise(function (resolve, reject) { + return new Promise((resolve, reject) => { assert.strictEqual(mapper, User, 'should pass in the Model') assert.deepEqual(_id, id, 'should pass in the id') assert.equal(Opts.raw, false, 'Opts are provided') @@ -29,7 +29,7 @@ describe('Mapper#createRecord', function () { assert(destroyCalled, 'Adapter#destroy should have been called') assert.equal(result, 'foo', 'returned data') }) - it('should return raw', async function () { + it('should return raw', async () => { const id = 1 let destroyCalled = false const User = new JSData.Mapper({ @@ -40,7 +40,7 @@ describe('Mapper#createRecord', function () { User.registerAdapter('mock', { destroy (mapper, _id, Opts) { destroyCalled = true - return new Promise(function (resolve, reject) { + return new Promise((resolve, reject) => { assert.strictEqual(mapper, User, 'should pass in the Model') assert.deepEqual(_id, id, 'should pass in the id') assert.equal(Opts.raw, true, 'Opts are provided') diff --git a/test/unit/mapper/destroyAll.test.js b/test/unit/mapper/destroyAll.test.ts similarity index 86% rename from test/unit/mapper/destroyAll.test.js rename to test/unit/mapper/destroyAll.test.ts index 7baaef77..621f07b9 100644 --- a/test/unit/mapper/destroyAll.test.js +++ b/test/unit/mapper/destroyAll.test.ts @@ -1,13 +1,13 @@ import { assert, JSData } from '../../_setup' -describe('Mapper#destroyAll', function () { - it('should be an instance method', function () { +describe('Mapper#destroyAll', () => { + it('should be an instance method', () => { const Mapper = JSData.Mapper const mapper = new Mapper({ name: 'foo' }) assert.equal(typeof mapper.destroyAll, 'function') assert.strictEqual(mapper.destroyAll, Mapper.prototype.destroyAll) }) - it('should destroyAll', async function () { + it('should destroyAll', async () => { const query = {} let destroyAllCalled = false const User = new JSData.Mapper({ @@ -17,7 +17,7 @@ describe('Mapper#destroyAll', function () { User.registerAdapter('mock', { destroyAll (mapper, _query, Opts) { destroyAllCalled = true - return new Promise(function (resolve, reject) { + return new Promise((resolve, reject) => { assert.strictEqual(mapper, User, 'should pass in the Model') assert.deepEqual(_query, query, 'should pass in the query') assert.equal(Opts.raw, false, 'Opts are provided') @@ -29,7 +29,7 @@ describe('Mapper#destroyAll', function () { assert(destroyAllCalled, 'Adapter#destroyAll should have been called') assert.equal(result, 'foo', 'returned data') }) - it('should return raw', async function () { + it('should return raw', async () => { const query = {} let destroyAllCalled = false const User = new JSData.Mapper({ @@ -40,7 +40,7 @@ describe('Mapper#destroyAll', function () { User.registerAdapter('mock', { destroyAll (mapper, _query, Opts) { destroyAllCalled = true - return new Promise(function (resolve, reject) { + return new Promise((resolve, reject) => { assert.strictEqual(mapper, User, 'should pass in the Model') assert.deepEqual(_query, query, 'should pass in the query') assert.equal(Opts.raw, true, 'Opts are provided') diff --git a/test/unit/mapper/find.test.js b/test/unit/mapper/find.test.ts similarity index 79% rename from test/unit/mapper/find.test.js rename to test/unit/mapper/find.test.ts index df402343..b6b46395 100644 --- a/test/unit/mapper/find.test.js +++ b/test/unit/mapper/find.test.ts @@ -1,13 +1,13 @@ -import { assert, JSData } from '../../_setup' +import { assert, JSData, objectsEqual } from '../../_setup' -describe('Mapper#find', function () { - it('should be an instance method', function () { +describe('Mapper#find', () => { + it('should be an instance method', () => { const Mapper = JSData.Mapper const mapper = new Mapper({ name: 'foo' }) assert.equal(typeof mapper.find, 'function') assert.strictEqual(mapper.find, Mapper.prototype.find) }) - it('should find', async function () { + it('should find', async () => { const id = 1 const props = { id, name: 'John' } let findCalled = false @@ -18,7 +18,7 @@ describe('Mapper#find', function () { User.registerAdapter('mock', { find (mapper, _id, Opts) { findCalled = true - return new Promise(function (resolve, reject) { + return new Promise((resolve, reject) => { assert.strictEqual(mapper, User, 'should pass in the Model') assert.deepEqual(_id, id, 'should pass in the id') assert.equal(Opts.raw, false, 'Opts are provided') @@ -28,10 +28,10 @@ describe('Mapper#find', function () { }) const user = await User.find(id) assert(findCalled, 'Adapter#find should have been called') - assert.objectsEqual(user, props, 'user should have been found') + objectsEqual(user, props, 'user should have been found') assert(user instanceof User.recordClass, 'user is a record') }) - it('should return raw', async function () { + it('should return raw', async () => { const id = 1 const props = { id, name: 'John' } let findCalled = false @@ -43,7 +43,7 @@ describe('Mapper#find', function () { User.registerAdapter('mock', { find (mapper, _id, Opts) { findCalled = true - return new Promise(function (resolve, reject) { + return new Promise((resolve, reject) => { assert.strictEqual(mapper, User, 'should pass in the Model') assert.deepEqual(_id, id, 'should pass in the id') assert.equal(Opts.raw, true, 'Opts are provided') @@ -56,7 +56,7 @@ describe('Mapper#find', function () { }) const data = await User.find(id) assert(findCalled, 'Adapter#find should have been called') - assert.objectsEqual(data.data, props, 'user should have been found') + objectsEqual(data.data, props, 'user should have been found') assert(data.data instanceof User.recordClass, 'user is a record') assert.equal(data.adapter, 'mock', 'should have adapter name in response') assert.equal(data.found, 1, 'should have other metadata in response') diff --git a/test/unit/mapper/findAll.test.js b/test/unit/mapper/findAll.test.ts similarity index 80% rename from test/unit/mapper/findAll.test.js rename to test/unit/mapper/findAll.test.ts index 92dc134c..6bbcda9a 100644 --- a/test/unit/mapper/findAll.test.js +++ b/test/unit/mapper/findAll.test.ts @@ -1,13 +1,13 @@ -import { assert, JSData } from '../../_setup' +import { assert, JSData, objectsEqual } from '../../_setup' -describe('Mapper#findAll', function () { - it('should be an instance method', function () { +describe('Mapper#findAll', () => { + it('should be an instance method', () => { const Mapper = JSData.Mapper const mapper = new Mapper({ name: 'foo' }) assert.equal(typeof mapper.findAll, 'function') assert.strictEqual(mapper.findAll, Mapper.prototype.findAll) }) - it('should findAll', async function () { + it('should findAll', async () => { const query = { id: 1 } const id = 1 const props = [{ id, name: 'John' }] @@ -19,7 +19,7 @@ describe('Mapper#findAll', function () { User.registerAdapter('mock', { findAll (mapper, _query, Opts) { findAllCalled = true - return new Promise(function (resolve, reject) { + return new Promise((resolve, reject) => { assert.strictEqual(mapper, User, 'should pass in the Model') assert.deepEqual(_query, query, 'should pass in the query') assert.equal(Opts.raw, false, 'Opts are provided') @@ -29,10 +29,10 @@ describe('Mapper#findAll', function () { }) const users = await User.findAll(query) assert(findAllCalled, 'Adapter#findAll should have been called') - assert.objectsEqual(users, props, 'user should have been found') + objectsEqual(users, props, 'user should have been found') assert(users[0] instanceof User.recordClass, 'user is a record') }) - it('should return raw', async function () { + it('should return raw', async () => { const query = { id: 1 } const id = 1 const props = [{ id, name: 'John' }] @@ -45,7 +45,7 @@ describe('Mapper#findAll', function () { User.registerAdapter('mock', { findAll (mapper, _query, Opts) { findAllCalled = true - return new Promise(function (resolve, reject) { + return new Promise((resolve, reject) => { assert.strictEqual(mapper, User, 'should pass in the Model') assert.deepEqual(_query, query, 'should pass in the query') assert.equal(Opts.raw, true, 'Opts are provided') @@ -58,7 +58,7 @@ describe('Mapper#findAll', function () { }) const data = await User.findAll(query) assert(findAllCalled, 'Adapter#findAll should have been called') - assert.objectsEqual(data.data, props, 'user should have been found') + objectsEqual(data.data, props, 'user should have been found') assert(data.data[0] instanceof User.recordClass, 'user is a record') assert.equal(data.adapter, 'mock', 'should have adapter name in response') assert.equal(data.found, 1, 'should have other metadata in response') diff --git a/test/unit/mapper/getAdapter.test.js b/test/unit/mapper/getAdapter.test.ts similarity index 66% rename from test/unit/mapper/getAdapter.test.js rename to test/unit/mapper/getAdapter.test.ts index f8e04880..bee470b9 100644 --- a/test/unit/mapper/getAdapter.test.js +++ b/test/unit/mapper/getAdapter.test.ts @@ -1,7 +1,7 @@ import { assert, JSData } from '../../_setup' -describe('Mapper#getAdapter', function () { - it('should get an adapter', function () { +describe('Mapper#getAdapter', () => { + it('should get an adapter', () => { const Mapper = JSData.Mapper const mapper = new Mapper({ name: 'user' }) assert.equal(typeof mapper.getAdapter, 'function') @@ -13,8 +13,12 @@ describe('Mapper#getAdapter', function () { assert.strictEqual(mapper.getAdapter('foo'), adapter) assert.strictEqual(mapper.getAdapter('bar'), adapter) assert.equal(mapper.defaultAdapter, 'bar') - assert.throws(() => { - mapper.getAdapter() - }, Error, '[Mapper#getAdapter:name] expected: string, found: undefined\nhttp://www.js-data.io/v3.0/docs/errors#400') + assert.throws( + () => { + mapper.getAdapter() + }, + Error, + '[Mapper#getAdapter:name] expected: string, found: undefined\nhttp://www.js-data.io/v3.0/docs/errors#400' + ) }) }) diff --git a/test/unit/mapper/index.test.js b/test/unit/mapper/index.test.ts similarity index 79% rename from test/unit/mapper/index.test.js rename to test/unit/mapper/index.test.ts index 76c220b3..1689908f 100644 --- a/test/unit/mapper/index.test.js +++ b/test/unit/mapper/index.test.ts @@ -1,29 +1,30 @@ import { assert, JSData, sinon } from '../../_setup' -describe('Mapper', function () { - it('should be a constructor function', function () { +describe('Mapper', () => { + it('should be a constructor function', () => { const Mapper = JSData.Mapper assert.equal(typeof Mapper, 'function') const mapper = new Mapper({ name: 'foo' }) assert.equal(mapper instanceof Mapper, true) }) - it('should require a name', function () { + it('should require a name', () => { assert.throws( () => { - new JSData.Mapper() // eslint-disable-line + // tslint:disable-next-line:no-unused-expression + new JSData.Mapper(); // eslint-disable-line }, Error, '[new Mapper:opts.name] expected: string, found: undefined\nhttp://www.js-data.io/v3.0/docs/errors#400' ) }) - it('should have events', function () { + it('should have events', () => { const User = new JSData.Mapper({ name: 'user' }) const listener = sinon.stub() User.on('bar', listener) User.emit('bar') assert.equal(listener.calledOnce, true) }) - it('should only work with known crud methods', function () { + it('should only work with known crud methods', () => { const User = new JSData.Mapper({ name: 'user' }) assert.throws( () => { @@ -33,7 +34,7 @@ describe('Mapper', function () { '[Mapper#crud:foobar] method not found\nhttp://www.js-data.io/v3.0/docs/errors#404' ) }) - it('should notify', function (done) { + it('should notify', done => { const stub = sinon.stub() const User = new JSData.Mapper({ name: 'user', notify: true }) User.on('beforeUpdate', stub) @@ -43,11 +44,11 @@ describe('Mapper', function () { done() }, 10) }) - it('should work without a record class', function () { + it('should work without a record class', () => { const User = new JSData.Mapper({ name: 'user', recordClass: false }) assert.equal(User.recordClass, false) }) - it('should add methods to record class', function () { + it('should add methods to record class', () => { const User = new JSData.Mapper({ name: 'user', methods: { diff --git a/test/unit/mapper/sum.test.js b/test/unit/mapper/sum.test.ts similarity index 78% rename from test/unit/mapper/sum.test.js rename to test/unit/mapper/sum.test.ts index 2089b658..ad679aa8 100644 --- a/test/unit/mapper/sum.test.js +++ b/test/unit/mapper/sum.test.ts @@ -1,23 +1,24 @@ -import { assert, JSData } from '../../_setup' +import { assert, JSData, objectsEqual } from '../../_setup' -describe('Mapper#sum', function () { - it('should be an instance method', function () { +describe('Mapper#sum', () => { + it('should be an instance method', () => { const Mapper = JSData.Mapper const mapper = new Mapper({ name: 'foo' }) assert.equal(typeof mapper.sum, 'function') assert.strictEqual(mapper.sum, Mapper.prototype.sum) }) - it('should sum', async function () { + it('should sum', async () => { const query = { id: 1 } let sumCalled = false - const User = new JSData.Mapper({ // eslint-disable-line + const User = new JSData.Mapper({ + // eslint-disable-line name: 'user', defaultAdapter: 'mock' }) User.registerAdapter('mock', { sum (mapper, _field, _query, Opts) { sumCalled = true - return new Promise(function (resolve, reject) { + return new Promise((resolve, reject) => { assert.strictEqual(mapper, User, 'should pass in the Model') assert.equal(_field, 'age', 'should pass in the field') assert.deepEqual(_query, query, 'should pass in the query') @@ -30,7 +31,7 @@ describe('Mapper#sum', function () { assert(sumCalled, 'Adapter#sum should have been called') assert.deepEqual(sum, 30, 'sum should be 30') }) - it('should return raw', async function () { + it('should return raw', async () => { const query = { id: 1 } let sumCalled = false const User = new JSData.Mapper({ @@ -41,7 +42,7 @@ describe('Mapper#sum', function () { User.registerAdapter('mock', { sum (mapper, _field, _query, Opts) { sumCalled = true - return new Promise(function (resolve, reject) { + return new Promise((resolve, reject) => { assert.strictEqual(mapper, User, 'should pass in the Model') assert.equal(_field, 'age', 'should pass in the field') assert.deepEqual(_query, query, 'should pass in the query') @@ -54,7 +55,7 @@ describe('Mapper#sum', function () { }) const data = await User.sum('age', query) assert(sumCalled, 'Adapter#sum should have been called') - assert.objectsEqual(data.data, 30, 'sum should be 30') + objectsEqual(data.data, 30, 'sum should be 30') assert.equal(data.adapter, 'mock', 'should have adapter name in response') }) }) diff --git a/test/unit/mapper/toJSON.test.js b/test/unit/mapper/toJSON.test.ts similarity index 62% rename from test/unit/mapper/toJSON.test.js rename to test/unit/mapper/toJSON.test.ts index 7a65c52f..2020a83c 100644 --- a/test/unit/mapper/toJSON.test.js +++ b/test/unit/mapper/toJSON.test.ts @@ -1,7 +1,7 @@ -import { assert, JSData } from '../../_setup' +import { assert, JSData, objectsEqual } from '../../_setup' -describe('Mapper#toJSON', function () { - it('should be an instance method', function () { +describe('Mapper#toJSON', () => { + it('should be an instance method', () => { const Mapper = JSData.Mapper const mapper = new Mapper({ name: 'user' }) assert.equal(typeof mapper.toJSON, 'function') @@ -9,7 +9,7 @@ describe('Mapper#toJSON', function () { }) it('should make json when not an instance', function () { const props = { name: 'John' } - assert.objectsEqual(this.User.toJSON(props), props, 'should return passed in data') + objectsEqual(this.User.toJSON(props), props, 'should return passed in data') const UserMapper = new JSData.Mapper({ name: 'user', @@ -32,12 +32,15 @@ describe('Mapper#toJSON', function () { foreignKey: 'userId' })(UserMapper) - assert.objectsEqual( - UserMapper.toJSON({ - name: 'John', - id: 1, - comments: [{ userId: 1 }] - }, { with: 'comments' }), + objectsEqual( + UserMapper.toJSON( + { + name: 'John', + id: 1, + comments: [{ userId: 1 }] + }, + { with: 'comments' } + ), { name: 'John', id: 1, @@ -45,7 +48,7 @@ describe('Mapper#toJSON', function () { } ) }) - it('should strictly keep schema props', function () { + it('should strictly keep schema props', () => { const UserMapper = new JSData.Mapper({ name: 'user', schema: { @@ -55,17 +58,20 @@ describe('Mapper#toJSON', function () { } } }) - const json = UserMapper.toJSON({ - name: 'John', - age: 30, - foo: 'bar' - }, { strict: true }) - assert.objectsEqual(json, { + const json = UserMapper.toJSON( + { + name: 'John', + age: 30, + foo: 'bar' + }, + { strict: true } + ) + objectsEqual(json, { name: 'John', age: 30 }) }) - it('should allow custom getters/setters', function () { + it('should allow custom getters/setters', () => { const UserMapper = new JSData.Mapper({ name: 'user', schema: { @@ -74,10 +80,10 @@ describe('Mapper#toJSON', function () { last: { type: 'string' }, name: { type: 'string', - get: function () { + get () { return `${this.first} ${this.last}` }, - set: function (value) { + set (value) { const parts = value.split(' ') this.first = parts[0] || this.first this.last = parts[1] || this.last @@ -93,18 +99,18 @@ describe('Mapper#toJSON', function () { }) assert.equal(user.name, 'John Anderson') }) - it('should make json when the record class does not have a mapper', function () { + it('should make json when the record class does not have a mapper', () => { const props = { name: 'John' } const record = new JSData.Record(props) assert.notStrictEqual(record.toJSON(), props, 'should not return passed in data') - assert.objectsEqual(record.toJSON(), props, 'should be deeply equal') + objectsEqual(record.toJSON(), props, 'should be deeply equal') }) it('should make json when an instance', function () { const props = { name: 'John', organizationId: 5 } const user = this.User.createRecord(props) assert(this.User.toJSON(user) !== props, 'should return copy of data') - assert.objectsEqual(this.User.toJSON(user), props, 'copy should equal passed in data') - assert.objectsEqual(user.toJSON(), props, 'copy should equal passed in data') + objectsEqual(this.User.toJSON(user), props, 'copy should equal passed in data') + objectsEqual(user.toJSON(), props, 'copy should equal passed in data') }) it('should keep only enumerable properties', function () { const props = { name: 'John' } @@ -122,8 +128,8 @@ describe('Mapper#toJSON', function () { name: 'John', foo: 'foo' } - assert.objectsEqual(this.User.toJSON(user), expected, 'should return enumerable properties') - assert.objectsEqual(user.toJSON(), expected, 'should return enumerable properties') + objectsEqual(this.User.toJSON(user), expected, 'should return enumerable properties') + objectsEqual(user.toJSON(), expected, 'should return enumerable properties') }) it('should work when not a Record instance', function () { const user = { @@ -140,8 +146,8 @@ describe('Mapper#toJSON', function () { } ] } - assert.objectsEqual(this.User.toJSON(user), { name: 'John' }, 'returned data should not have relations') - assert.objectsEqual(this.User.toJSON(user, { withAll: true }), user, 'returned data should have all relations') + objectsEqual(this.User.toJSON(user), { name: 'John' }, 'returned data should not have relations') + objectsEqual(this.User.toJSON(user, { withAll: true }), user, 'returned data should have all relations') }) it('should remove relations when an instance', function () { const user = this.store.add('user', { @@ -177,8 +183,8 @@ describe('Mapper#toJSON', function () { name: 'John', organizationId: 2 } - assert.objectsEqual(this.User.toJSON(user), expected, 'returned data should not have relations') - assert.objectsEqual(user.toJSON(), expected, 'returned data should not have relations') + objectsEqual(this.User.toJSON(user), expected, 'returned data should not have relations') + objectsEqual(user.toJSON(), expected, 'returned data should not have relations') }) it('should keep specified relations when an instance', function () { const store = this.store @@ -208,34 +214,50 @@ describe('Mapper#toJSON', function () { } ] }) - let expected = { + let expected: any = { id: 1, name: 'John', organizationId: 2, organization: user.organization.toJSON() } - assert.objectsEqual(this.User.toJSON(user, { - with: ['organization'] - }), expected, 'should keep organization') - assert.objectsEqual(user.toJSON({ - with: ['organization'] - }), expected, 'should keep organization') + objectsEqual( + this.User.toJSON(user, { + with: ['organization'] + }), + expected, + 'should keep organization' + ) + objectsEqual( + user.toJSON({ + with: ['organization'] + }), + expected, + 'should keep organization' + ) expected = { id: 1, name: 'John', organizationId: 2, organization: user.organization.toJSON(), - comments: user.comments.map((comment) => comment.toJSON()) + comments: user.comments.map(comment => comment.toJSON()) } - assert.objectsEqual(this.User.toJSON(user, { - with: ['organization', 'comments'] - }), expected, 'should keep organization and comments') - assert.objectsEqual(user.toJSON({ - with: ['organization', 'comments'] - }), expected, 'should keep organization and comments') + objectsEqual( + this.User.toJSON(user, { + with: ['organization', 'comments'] + }), + expected, + 'should keep organization and comments' + ) + objectsEqual( + user.toJSON({ + with: ['organization', 'comments'] + }), + expected, + 'should keep organization and comments' + ) expected = { id: 1, @@ -254,12 +276,20 @@ describe('Mapper#toJSON', function () { ] } - assert.objectsEqual(this.User.toJSON(user, { - with: ['organization', 'comments', 'comments.approvedByUser'] - }), expected, 'should keep organization and comments and comments.approvedByUser') - assert.objectsEqual(user.toJSON({ - with: ['organization', 'comments', 'comments.approvedByUser'] - }), expected, 'should keep organization and comments and comments.approvedByUser') + objectsEqual( + this.User.toJSON(user, { + with: ['organization', 'comments', 'comments.approvedByUser'] + }), + expected, + 'should keep organization and comments and comments.approvedByUser' + ) + objectsEqual( + user.toJSON({ + with: ['organization', 'comments', 'comments.approvedByUser'] + }), + expected, + 'should keep organization and comments and comments.approvedByUser' + ) expected = { id: 1, @@ -283,22 +313,20 @@ describe('Mapper#toJSON', function () { ] } - assert.objectsEqual(this.User.toJSON(user, { - with: [ - 'organization', - 'comments', - 'comments.approvedByUser', - 'comments.approvedByUser.organization' - ] - }), expected, 'should keep organization and comments and comments.approvedByUser and comments.approvedByUser.organization') + objectsEqual( + this.User.toJSON(user, { + with: ['organization', 'comments', 'comments.approvedByUser', 'comments.approvedByUser.organization'] + }), + expected, + 'should keep organization and comments and comments.approvedByUser and comments.approvedByUser.organization' + ) - assert.objectsEqual(user.toJSON({ - with: [ - 'organization', - 'comments', - 'comments.approvedByUser', - 'comments.approvedByUser.organization' - ] - }), expected, 'should keep organization and comments and comments.approvedByUser and comments.approvedByUser.organization') + objectsEqual( + user.toJSON({ + with: ['organization', 'comments', 'comments.approvedByUser', 'comments.approvedByUser.organization'] + }), + expected, + 'should keep organization and comments and comments.approvedByUser and comments.approvedByUser.organization' + ) }) }) diff --git a/test/unit/mapper/update.test.js b/test/unit/mapper/update.test.ts similarity index 91% rename from test/unit/mapper/update.test.js rename to test/unit/mapper/update.test.ts index f7823817..383b2260 100644 --- a/test/unit/mapper/update.test.js +++ b/test/unit/mapper/update.test.ts @@ -1,13 +1,13 @@ import { assert, JSData } from '../../_setup' -describe('Mapper#update', function () { - it('should be an instance method', function () { +describe('Mapper#update', () => { + it('should be an instance method', () => { const Mapper = JSData.Mapper const mapper = new Mapper({ name: 'foo' }) assert.equal(typeof mapper.update, 'function') assert.strictEqual(mapper.update, Mapper.prototype.update) }) - it('should update', async function () { + it('should update', async () => { const id = 1 const props = { name: 'John' } let updateCalled = false @@ -18,7 +18,7 @@ describe('Mapper#update', function () { User.registerAdapter('mock', { update (mapper, _id, _props, Opts) { updateCalled = true - return new Promise(function (resolve, reject) { + return new Promise((resolve, reject) => { assert.strictEqual(mapper, User, 'should pass in the Mapper') assert.deepEqual(_id, id, 'should pass in the id') assert.deepEqual(_props, props, 'should pass in the props') @@ -34,7 +34,7 @@ describe('Mapper#update', function () { assert.equal(user.foo, 'bar', 'user has a new field') assert(user instanceof User.recordClass, 'user is a record') }) - it('should return raw', async function () { + it('should return raw', async () => { const id = 1 const props = { name: 'John' } let updateCalled = false @@ -46,7 +46,7 @@ describe('Mapper#update', function () { User.registerAdapter('mock', { update (mapper, _id, _props, Opts) { updateCalled = true - return new Promise(function (resolve, reject) { + return new Promise((resolve, reject) => { assert.strictEqual(mapper, User, 'should pass in the Mapper') assert.deepEqual(_id, id, 'should pass in the id') assert.deepEqual(_props, props, 'should pass in the props') @@ -67,7 +67,7 @@ describe('Mapper#update', function () { assert.equal(data.adapter, 'mock', 'should have adapter name in response') assert.equal(data.updated, 1, 'should have other metadata in response') }) - it('should validate', async function () { + it('should validate', async () => { const props = { name: 1234 } let updateCalled = false let user @@ -102,7 +102,7 @@ describe('Mapper#update', function () { assert.equal(updateCalled, false, 'Adapter#update should NOT have been called') assert.equal(user, undefined, 'user was not updated') }) - it('should update nested', async function () { + it('should update nested', async () => { const props = { id: 1, addresses: [ diff --git a/test/unit/mapper/updateAll.test.js b/test/unit/mapper/updateAll.test.ts similarity index 90% rename from test/unit/mapper/updateAll.test.js rename to test/unit/mapper/updateAll.test.ts index aa60e3f4..0a49d1b2 100644 --- a/test/unit/mapper/updateAll.test.js +++ b/test/unit/mapper/updateAll.test.ts @@ -1,13 +1,13 @@ import { assert, JSData } from '../../_setup' -describe('Mapper#updateAll', function () { - it('should be an instance method', function () { +describe('Mapper#updateAll', () => { + it('should be an instance method', () => { const Mapper = JSData.Mapper const mapper = new Mapper({ name: 'foo' }) assert.equal(typeof mapper.updateAll, 'function') assert.strictEqual(mapper.updateAll, Mapper.prototype.updateAll) }) - it('should update', async function () { + it('should update', async () => { const id = 1 const query = { a: 'b' } const props = { name: 'John' } @@ -19,7 +19,7 @@ describe('Mapper#updateAll', function () { User.registerAdapter('mock', { updateAll (mapper, _props, _query, Opts) { updateAllCalled = true - return new Promise(function (resolve, reject) { + return new Promise((resolve, reject) => { assert.strictEqual(mapper, User, 'should pass in the Mapper') assert.deepEqual(_props, props, 'should pass in the props') assert.deepEqual(_query, query, 'should pass in the query') @@ -35,7 +35,7 @@ describe('Mapper#updateAll', function () { assert.equal(users[0].foo, 'bar', 'user has a new field') assert(users[0] instanceof User.recordClass, 'user is a record') }) - it('should return raw', async function () { + it('should return raw', async () => { const id = 1 const query = { a: 'b' } const props = { name: 'John' } @@ -48,7 +48,7 @@ describe('Mapper#updateAll', function () { User.registerAdapter('mock', { updateAll (mapper, _props, _query, Opts) { updateAllCalled = true - return new Promise(function (resolve, reject) { + return new Promise((resolve, reject) => { assert.strictEqual(mapper, User, 'should pass in the Mapper') assert.deepEqual(_props, props, 'should pass in the props') assert.deepEqual(_query, query, 'should pass in the query') @@ -69,7 +69,7 @@ describe('Mapper#updateAll', function () { assert.equal(data.adapter, 'mock', 'should have adapter name in response') assert.equal(data.updated, 1, 'should have other metadata in response') }) - it('should validate', async function () { + it('should validate', async () => { const props = { name: 1234 } let updateCalled = false let users diff --git a/test/unit/mapper/updateMany.test.js b/test/unit/mapper/updateMany.test.ts similarity index 90% rename from test/unit/mapper/updateMany.test.js rename to test/unit/mapper/updateMany.test.ts index ea758da2..f338c523 100644 --- a/test/unit/mapper/updateMany.test.js +++ b/test/unit/mapper/updateMany.test.ts @@ -1,13 +1,13 @@ import { assert, JSData } from '../../_setup' -describe('Mapper#updateMany', function () { - it('should be an instance method', function () { +describe('Mapper#updateMany', () => { + it('should be an instance method', () => { const Mapper = JSData.Mapper const mapper = new Mapper({ name: 'foo' }) assert.equal(typeof mapper.updateMany, 'function') assert.strictEqual(mapper.updateMany, Mapper.prototype.updateMany) }) - it('should update', async function () { + it('should update', async () => { const id = 1 const props = [{ id, name: 'John' }] let updateManyCalled = false @@ -18,7 +18,7 @@ describe('Mapper#updateMany', function () { User.registerAdapter('mock', { updateMany (mapper, _props, Opts) { updateManyCalled = true - return new Promise(function (resolve, reject) { + return new Promise((resolve, reject) => { assert.strictEqual(mapper, User, 'should pass in the Mapper') assert.deepEqual(_props, props, 'should pass in the props') assert.equal(Opts.raw, false, 'Opts are provided') @@ -32,7 +32,7 @@ describe('Mapper#updateMany', function () { assert.equal(users[0].foo, 'bar', 'user has a new field') assert(users[0] instanceof User.recordClass, 'user is a record') }) - it('should return raw', async function () { + it('should return raw', async () => { const id = 1 const props = [{ id, name: 'John' }] let updateManyCalled = false @@ -44,7 +44,7 @@ describe('Mapper#updateMany', function () { User.registerAdapter('mock', { updateMany (mapper, _props, Opts) { updateManyCalled = true - return new Promise(function (resolve, reject) { + return new Promise((resolve, reject) => { assert.strictEqual(mapper, User, 'should pass in the Mapper') assert.deepEqual(_props, props, 'should pass in the props') assert.equal(Opts.raw, true, 'Opts are provided') @@ -63,7 +63,7 @@ describe('Mapper#updateMany', function () { assert.equal(data.adapter, 'mock', 'should have adapter name in response') assert.equal(data.updated, 1, 'should have other metadata in response') }) - it('should validate', async function () { + it('should validate', async () => { const props = [ { id: 1, name: 1234 }, { id: 2, name: 'John' }, diff --git a/test/unit/mapper/validate.test.js b/test/unit/mapper/validate.test.ts similarity index 53% rename from test/unit/mapper/validate.test.js rename to test/unit/mapper/validate.test.ts index 3764bda5..1eccb4e2 100644 --- a/test/unit/mapper/validate.test.js +++ b/test/unit/mapper/validate.test.ts @@ -1,8 +1,8 @@ import { assert, JSData } from '../../_setup' import { productSchema } from '../schema/_productSchema' -describe('Mapper#validate', function () { - it('should validate a record', function () { +describe('Mapper#validate', () => { + it('should validate a record', () => { const ProductMapper = new JSData.Mapper({ name: 'product', schema: productSchema @@ -11,7 +11,7 @@ describe('Mapper#validate', function () { let errors = ProductMapper.validate({ id: 3, name: 'A blue mouse', - price: 25.50, + price: 25.5, dimensions: { length: 3.1, width: 1.0, @@ -25,20 +25,22 @@ describe('Mapper#validate', function () { assert(!errors) - errors = ProductMapper.validate([{ - id: 3, - name: 'A blue mouse', - price: 25.50, - dimensions: { - length: 3.1, - width: 1.0, - height: 1.0 - }, - warehouseLocation: { - latitude: 54.4, - longitude: -32.7 + errors = ProductMapper.validate([ + { + id: 3, + name: 'A blue mouse', + price: 25.5, + dimensions: { + length: 3.1, + width: 1.0, + height: 1.0 + }, + warehouseLocation: { + latitude: 54.4, + longitude: -32.7 + } } - }]) + ]) assert(!errors) @@ -56,43 +58,39 @@ describe('Mapper#validate', function () { longitude: -32.7 } }) - assert.deepEqual( - errors, + assert.deepEqual(errors, [ + { expected: 'a value', actual: 'undefined', path: 'name' }, + { expected: 'one of (number)', actual: 'string', path: 'price' }, + { expected: 'a value', actual: 'undefined', path: 'dimensions.width' }, + { expected: 'one of (number)', actual: 'string', path: 'dimensions.height' } + ]) + + errors = ProductMapper.validate([ + { + id: 3, + // name is missing + price: 'wrong top', + dimensions: { + length: 3.1, + // width is missing + height: 'should be a number' + }, + warehouseLocation: { + latitude: 54.4, + longitude: -32.7 + } + } + ]) + assert.deepEqual(errors, [ [ { expected: 'a value', actual: 'undefined', path: 'name' }, { expected: 'one of (number)', actual: 'string', path: 'price' }, { expected: 'a value', actual: 'undefined', path: 'dimensions.width' }, { expected: 'one of (number)', actual: 'string', path: 'dimensions.height' } ] - ) - - errors = ProductMapper.validate([{ - id: 3, - // name is missing - price: 'wrong top', - dimensions: { - length: 3.1, - // width is missing - height: 'should be a number' - }, - warehouseLocation: { - latitude: 54.4, - longitude: -32.7 - } - }]) - assert.deepEqual( - errors, - [ - [ - { expected: 'a value', actual: 'undefined', path: 'name' }, - { expected: 'one of (number)', actual: 'string', path: 'price' }, - { expected: 'a value', actual: 'undefined', path: 'dimensions.width' }, - { expected: 'one of (number)', actual: 'string', path: 'dimensions.height' } - ] - ] - ) + ]) }) - it('should validate based on json-schema.org rules', function () { + it('should validate based on json-schema.org rules', () => { const User = new JSData.Mapper({ name: 'user', schema: { @@ -115,33 +113,63 @@ describe('Mapper#validate', function () { assert.fail() } catch (err) { assert(err instanceof Error) - assert.deepEqual(err.errors, [{ actual: 'string', expected: 'one of (number)', path: 'age' }], 'should require a number') + assert.deepEqual( + err.errors, + [ + { + actual: 'string', + expected: 'one of (number)', + path: 'age' + } + ], + 'should require a number' + ) assert.equal(err.message, 'validation failed') } try { user.age = {} } catch (err) { assert(err instanceof Error) - assert.deepEqual(err.errors, [{ actual: 'object', expected: 'one of (number)', path: 'age' }], 'should require a number') + assert.deepEqual( + err.errors, + [ + { + actual: 'object', + expected: 'one of (number)', + path: 'age' + } + ], + 'should require a number' + ) assert.equal(err.message, 'validation failed') } - assert.doesNotThrow(function () { + assert.doesNotThrow(() => { user.age = undefined }, 'should accept undefined') try { user.title = 1234 } catch (err) { assert(err instanceof Error) - assert.deepEqual(err.errors, [{ actual: 'number', expected: 'one of (string, null)', path: 'title' }], 'should require a string or null') + assert.deepEqual( + err.errors, + [ + { + actual: 'number', + expected: 'one of (string, null)', + path: 'title' + } + ], + 'should require a string or null' + ) assert.equal(err.message, 'validation failed') } - assert.doesNotThrow(function () { + assert.doesNotThrow(() => { user.title = 'foo' }, 'should accept a string') - assert.doesNotThrow(function () { + assert.doesNotThrow(() => { user.title = null }, 'should accept null') - assert.doesNotThrow(function () { + assert.doesNotThrow(() => { user.title = undefined }, 'should accept undefined') @@ -150,11 +178,21 @@ describe('Mapper#validate', function () { user.set('foo', 'bar') } catch (err) { assert(err instanceof Error) - assert.deepEqual(err.errors, [{ actual: 'string', expected: 'one of (number)', path: 'age' }], 'should validate on create') + assert.deepEqual( + err.errors, + [ + { + actual: 'string', + expected: 'one of (number)', + path: 'age' + } + ], + 'should validate on create' + ) assert.equal(err.message, 'validation failed') } - assert.doesNotThrow(function () { + assert.doesNotThrow(() => { const user = User.createRecord({ age: 'foo' }, { noValidate: true }) user.set('foo', 'bar') }, 'should NOT validate on create') diff --git a/test/unit/mindex/index.test.js b/test/unit/mindex/index.test.ts similarity index 73% rename from test/unit/mindex/index.test.js rename to test/unit/mindex/index.test.ts index 22c26618..573ef9b4 100644 --- a/test/unit/mindex/index.test.js +++ b/test/unit/mindex/index.test.ts @@ -1,7 +1,7 @@ import { assert, JSData } from '../../_setup' -describe('Index', function () { - it('should be a constructor function', function () { +describe('Index', () => { + it('should be a constructor function', () => { assert.equal(typeof JSData.Index, 'function', 'should be a function') const index = new JSData.Index() assert(index instanceof JSData.Index, 'query should be an instance') diff --git a/test/unit/mindex/insertRecord.test.js b/test/unit/mindex/insertRecord.test.ts similarity index 85% rename from test/unit/mindex/insertRecord.test.js rename to test/unit/mindex/insertRecord.test.ts index d9bfabba..7474ed49 100644 --- a/test/unit/mindex/insertRecord.test.js +++ b/test/unit/mindex/insertRecord.test.ts @@ -1,7 +1,7 @@ -import { assert, JSData } from '../../_setup' +import { assert, JSData, objectsEqual } from '../../_setup' -describe('Index#insertRecord', function () { - it('should insert records', function () { +describe('Index#insertRecord', () => { + it('should insert records', () => { const index = new JSData.Index(['id'], { hashCode (obj) { return JSData.utils.get(obj, 'id') @@ -28,7 +28,7 @@ describe('Index#insertRecord', function () { index.insertRecord(record9) index.insertRecord(record10) - assert.objectsEqual(index.get(), [record5, record3]) + objectsEqual(index.get(), [record5, record3]) assert.deepEqual(index.keys, [undefined, 1, 2, 3, 5, 6, 7, 8, 10]) assert.deepEqual(index.values, [ [record5, record3], @@ -70,13 +70,6 @@ describe('Index#insertRecord', function () { ]) const records = index2.between([44], [98]) - assert.deepEqual(records, [ - record4, - record6, - record5, - record7, - record9, - record8 - ]) + assert.deepEqual(records, [record4, record6, record5, record7, record9, record8]) }) }) diff --git a/test/unit/query/between.test.js b/test/unit/query/between.test.js deleted file mode 100644 index 6133593d..00000000 --- a/test/unit/query/between.test.js +++ /dev/null @@ -1,65 +0,0 @@ -import { assert, JSData } from '../../_setup' - -describe('Query#between', function () { - it('should work', function () { - let result - const collection = new JSData.Collection() - - assert.throws(function () { - collection.query().filter().between().run() - }, Error) - - collection.createIndex('age') - collection.createIndex('role') - collection.createIndex('ageRole', ['age', 'role']) - - const data = [ - { id: 1, age: 30, role: 'dev' }, - { id: 2, age: 30, role: 'dev' }, - { id: 3, age: 30, role: 'admin' }, - { id: 4, age: 30, role: 'admin' }, - { id: 5, age: 30, role: 'dev' }, - { id: 6, age: 30, role: 'sup' }, - { id: 7, age: 32, role: 'sup' }, - { id: 8, age: 32, role: 'dev' }, - { id: 9, age: 32, role: 'admin' }, - { id: 10, age: 32, role: 'sup' }, - { id: 11, age: 32, role: 'sup' }, - { id: 12, age: 32, role: 'admin' }, - { id: 13, age: 33, role: 'dev' }, - { id: 14, age: 33, role: 'dev' }, - { id: 15, age: 33, role: 'admin' }, - { id: 16, age: 33, role: 'sup' }, - { id: 17, age: 33, role: 'dev' }, - { id: 18, age: 33, role: 'admin' } - ] - collection.add(data) - result = collection.query().between([32], [33], { index: 'age', leftInclusive: false }).run() - assert.deepEqual(result, []) - result = collection.query().between(['dev'], ['sup'], { index: 'role', leftInclusive: false }).run() - assert.deepEqual(result, []) - result = collection.query().between([32, 'admin'], [33, 'dev'], { index: 'ageRole', leftInclusive: false }).run() - assert.deepEqual(result, [data[7], data[6], data[9], data[10], data[14], data[17]]) - - result = collection.query().between([32], [33], { index: 'age' }).run() - assert.deepEqual(result, [data[6], data[7], data[8], data[9], data[10], data[11]]) - result = collection.query().between(['dev'], ['sup'], { index: 'role' }).run() - assert.deepEqual(result, [data[0], data[1], data[4], data[7], data[12], data[13], data[16]]) - result = collection.query().between([32, 'admin'], [33, 'dev'], { index: 'ageRole' }).run() - assert.deepEqual(result, [data[8], data[11], data[7], data[6], data[9], data[10], data[14], data[17]]) - - result = collection.query().between([32], [33], { index: 'age', rightInclusive: true }).run() - assert.deepEqual(result, [data[6], data[7], data[8], data[9], data[10], data[11], data[12], data[13], data[14], data[15], data[16], data[17]]) - result = collection.query().between(['dev'], ['sup'], { index: 'role', rightInclusive: true }).run() - assert.deepEqual(result, [data[0], data[1], data[4], data[7], data[12], data[13], data[16], data[5], data[6], data[9], data[10], data[15]]) - result = collection.query().between([32, 'admin'], [33, 'dev'], { index: 'ageRole', rightInclusive: true }).run() - assert.deepEqual(result, [data[8], data[11], data[7], data[6], data[9], data[10], data[14], data[17], data[12], data[13], data[16]]) - - result = collection.query().between([32], [33], { index: 'age', leftInclusive: false, rightInclusive: true }).run() - assert.deepEqual(result, [data[12], data[13], data[14], data[15], data[16], data[17]]) - result = collection.query().between(['dev'], ['sup'], { index: 'role', leftInclusive: false, rightInclusive: true }).run() - assert.deepEqual(result, [data[5], data[6], data[9], data[10], data[15]]) - result = collection.query().between([32, 'admin'], [33, 'dev'], { index: 'ageRole', leftInclusive: false, rightInclusive: true }).run() - assert.deepEqual(result, [data[7], data[6], data[9], data[10], data[14], data[17], data[12], data[13], data[16]]) - }) -}) diff --git a/test/unit/query/between.test.ts b/test/unit/query/between.test.ts new file mode 100644 index 00000000..abc590e5 --- /dev/null +++ b/test/unit/query/between.test.ts @@ -0,0 +1,151 @@ +import { assert, JSData } from '../../_setup' + +describe('Query#between', () => { + it('should work', () => { + let result + const collection = new JSData.Collection() + + assert.throws(() => { + collection + .query() + .filter() + .between() + .run() + }, Error) + + collection.createIndex('age') + collection.createIndex('role') + collection.createIndex('ageRole', ['age', 'role']) + + const data = [ + { id: 1, age: 30, role: 'dev' }, + { id: 2, age: 30, role: 'dev' }, + { id: 3, age: 30, role: 'admin' }, + { id: 4, age: 30, role: 'admin' }, + { id: 5, age: 30, role: 'dev' }, + { id: 6, age: 30, role: 'sup' }, + { id: 7, age: 32, role: 'sup' }, + { id: 8, age: 32, role: 'dev' }, + { id: 9, age: 32, role: 'admin' }, + { id: 10, age: 32, role: 'sup' }, + { id: 11, age: 32, role: 'sup' }, + { id: 12, age: 32, role: 'admin' }, + { id: 13, age: 33, role: 'dev' }, + { id: 14, age: 33, role: 'dev' }, + { id: 15, age: 33, role: 'admin' }, + { id: 16, age: 33, role: 'sup' }, + { id: 17, age: 33, role: 'dev' }, + { id: 18, age: 33, role: 'admin' } + ] + collection.add(data) + result = collection + .query() + .between([32], [33], { index: 'age', leftInclusive: false }) + .run() + assert.deepEqual(result, []) + result = collection + .query() + .between(['dev'], ['sup'], { index: 'role', leftInclusive: false }) + .run() + assert.deepEqual(result, []) + result = collection + .query() + .between([32, 'admin'], [33, 'dev'], { index: 'ageRole', leftInclusive: false }) + .run() + assert.deepEqual(result, [data[7], data[6], data[9], data[10], data[14], data[17]]) + + result = collection + .query() + .between([32], [33], { index: 'age' }) + .run() + assert.deepEqual(result, [data[6], data[7], data[8], data[9], data[10], data[11]]) + result = collection + .query() + .between(['dev'], ['sup'], { index: 'role' }) + .run() + assert.deepEqual(result, [data[0], data[1], data[4], data[7], data[12], data[13], data[16]]) + result = collection + .query() + .between([32, 'admin'], [33, 'dev'], { index: 'ageRole' }) + .run() + assert.deepEqual(result, [data[8], data[11], data[7], data[6], data[9], data[10], data[14], data[17]]) + + result = collection + .query() + .between([32], [33], { index: 'age', rightInclusive: true }) + .run() + assert.deepEqual(result, [ + data[6], + data[7], + data[8], + data[9], + data[10], + data[11], + data[12], + data[13], + data[14], + data[15], + data[16], + data[17] + ]) + result = collection + .query() + .between(['dev'], ['sup'], { index: 'role', rightInclusive: true }) + .run() + assert.deepEqual(result, [ + data[0], + data[1], + data[4], + data[7], + data[12], + data[13], + data[16], + data[5], + data[6], + data[9], + data[10], + data[15] + ]) + result = collection + .query() + .between([32, 'admin'], [33, 'dev'], { index: 'ageRole', rightInclusive: true }) + .run() + assert.deepEqual(result, [ + data[8], + data[11], + data[7], + data[6], + data[9], + data[10], + data[14], + data[17], + data[12], + data[13], + data[16] + ]) + + result = collection + .query() + .between([32], [33], { index: 'age', leftInclusive: false, rightInclusive: true }) + .run() + assert.deepEqual(result, [data[12], data[13], data[14], data[15], data[16], data[17]]) + result = collection + .query() + .between(['dev'], ['sup'], { + index: 'role', + leftInclusive: false, + rightInclusive: true + }) + .run() + assert.deepEqual(result, [data[5], data[6], data[9], data[10], data[15]]) + result = collection + .query() + .between([32, 'admin'], [33, 'dev'], { + index: 'ageRole', + leftInclusive: false, + rightInclusive: true + }) + .run() + assert.deepEqual(result, [data[7], data[6], data[9], data[10], data[14], data[17], data[12], data[13], data[16]]) + }) +}) diff --git a/test/unit/query/filter.test.js b/test/unit/query/filter.test.js deleted file mode 100644 index de17339b..00000000 --- a/test/unit/query/filter.test.js +++ /dev/null @@ -1,364 +0,0 @@ -import { assert, JSData } from '../../_setup' - -describe('Query#filter', function () { - it('should work', function () { - const collection = this.PostCollection - const p1 = this.data.p1 - const p2 = this.data.p2 - const p3 = this.data.p3 - const p4 = this.data.p4 - const p5 = this.data.p5 - - p1.roles = ['admin'] - p2.roles = ['admin', 'dev'] - p3.roles = ['admin', 'dev'] - p4.roles = [] - p5.roles = ['admin', 'dev', 'owner'] - - this.store.add('post', [p1, p2, p3, p4, p5]) - - let params = { - author: 'John' - } - - assert.objectsEqual(collection.query().filter(params).run(), [p1], 'should default a string to "=="') - - params = { - author: 'Adam', - id: 9 - } - - assert.objectsEqual(collection.query().filter(params).run(), [p5], 'should default a string to "=="') - - params = { - where: { - author: 'John' - } - } - - assert.objectsEqual(collection.query().filter(params).run(), [p1], 'should default a string to "=="') - - params.where.author = { - '==': 'John' - } - - assert.objectsEqual(collection.query().filter(params).run(), [p1], 'should accept normal "==" clause') - - params.where.author = { - '===': null - } - - assert.objectsEqual(collection.query().filter(params).run(), [], 'should accept normal "===" clause') - - params.where.author = { - '!=': 'John' - } - - assert.objectsEqual(collection.query().filter(params).run(), [p2, p3, p4, p5], 'should accept normal "!=" clause') - - params.where = { - age: { - '>': 31 - } - } - - assert.objectsEqual(collection.query().filter(params).run(), [p3, p4, p5], 'should accept normal ">" clause') - - params.where = { - age: { - '>=': 31 - } - } - - assert.objectsEqual(collection.query().filter(params).run(), [p2, p3, p4, p5], 'should accept normal ">=" clause') - - params.where = { - age: { - '<': 31 - } - } - - assert.objectsEqual(collection.query().filter(params).run(), [p1], 'should accept normal "<" clause') - - params.where = { - age: { - '>': 30, - '<': 33 - } - } - - assert.objectsEqual(collection.query().filter(params).run(), [p2, p3], 'should accept dual "<" and ">" clause') - - params.where = { - age: { - '|>': 30, - '|<': 33 - } - } - - assert.objectsEqual(collection.query().filter(params).run(), [p1, p2, p3, p4, p5], 'should accept or "<" and ">" clause') - - params.where = { - age: { - '|<=': 31 - }, - author: { - '|==': 'Adam' - } - } - - assert.objectsEqual(collection.query().filter(params).run(), [p1, p2, p4, p5], 'should accept or "<=" and "==" clause') - - params.where = { - age: { - '<=': 31 - } - } - - assert.objectsEqual(collection.query().filter(params).run(), [p1, p2], 'should accept normal "<=" clause') - - params.where = { - age: { - in: [30, 33] - }, - author: { - in: ['John', 'Sally', 'Adam'] - } - } - - assert.objectsEqual(collection.query().filter(params).run(), [p1, p4, p5], 'should accept normal "in" clause') - - params.where = { - author: { - in: 'John' - } - } - - assert.objectsEqual(collection.query().filter(params).run(), [p1], 'should accept normal "in" clause with a string') - - params.where = { - author: { - notIn: 'John' - } - } - - assert.objectsEqual(collection.query().filter(params).run(), [p2, p3, p4, p5], 'should accept normal "notIn" clause with a string') - - params.where = { - age: { - '|in': [31] - }, - id: { - '|in': [8] - } - } - - assert.objectsEqual(collection.query().filter(params).run(), [p2, p4], 'should accept and/or clause') - - params.where = { - id: { - notIn: [8] - } - } - - assert.objectsEqual(collection.query().filter(params).run(), [p1, p2, p3, p5], 'should accept notIn clause') - - params.where = { age: { garbage: 'should have no effect' } } - - assert.objectsEqual(collection.query().filter(params).run(), [p1, p2, p3, p4, p5], 'should return all elements') - - params.where = { author: { like: 'Ada%' } } - - assert.objectsEqual(collection.query().filter(params).run(), [p4, p5], 'should support like') - - params.where = { author: { like: '%a%' } } - - assert.objectsEqual(collection.query().filter(params).run(), [p2, p4, p5], 'should support like') - - params.where = { author: { notLike: 'Ada%' } } - - assert.objectsEqual(collection.query().filter(params).run(), [p1, p2, p3], 'should support notLike') - - params.where = { roles: { isectEmpty: ['admin'] } } - - assert.objectsEqual(collection.query().filter(params).run(), [p4], 'should support isectEmpty') - - params.where = { roles: { isectNotEmpty: ['admin'] } } - - assert.objectsEqual(collection.query().filter(params).run(), [p1, p2, p3, p5], 'should support isectNotEmpty') - - params.where = { roles: { notContains: 'admin' } } - - assert.objectsEqual(collection.query().filter(params).run(), [p4], 'should support notContains') - - params.where = { age: { '!==': 33 } } - - assert.objectsEqual(collection.query().filter(params).run(), [p1, p2, p3], 'should support !==') - - params = undefined - - assert.objectsEqual(collection.query().filter(params).run(), [p1, p2, p3, p4, p5], 'should do nothing') - - params = { offset: 4 } - - assert.objectsEqual(collection.query().filter(params).run(), [p5], 'should support offset') - - params = { - where: [ - { - roles: { - contains: 'admin' - } - }, - 'or', - { - age: { - '=': 30 - } - } - ] - } - assert.objectsEqual(collection.query().filter(params).run(), [p1, p2, p3, p5]) - - params = { - where: [ - { - roles: { - contains: 'admin' - }, - age: { - '=': 30 - } - }, - 'or', - { - roles: { - contains: 'owner' - } - } - ] - } - assert.objectsEqual(collection.query().filter(params).run(), [p1, p5]) - - params = { - where: [ - [ - { - roles: { - contains: 'admin' - }, - age: { - '=': 30 - } - }, - 'or', - { - author: { - '=': 'Mike' - } - } - ], - 'or', - { - roles: { - contains: 'owner' - }, - age: { - '=': 33 - } - } - ] - } - assert.objectsEqual(collection.query().filter(params).run(), [p1, p3, p5]) - }) - it('should allow custom filter function', function () { - const p1 = this.data.p1 - const p2 = this.data.p2 - const p3 = this.data.p3 - const p4 = this.data.p4 - this.store.add('post', [p1, p2, p3, p4]) - - assert.objectsEqual(this.store.query('post').filter(function (item) { - return item.author === 'John' || item.age % 30 === 1 - }).run(), [p1, p2], 'should keep p1 and p2') - }) - it('should filter by nested keys', function () { - const store = new JSData.DataStore() - store.defineMapper('thing') - const things = [ - { - id: 1, - foo: { - bar: 1 - } - }, - { - id: 2, - foo: { - bar: 2 - } - }, - { - id: 3, - foo: { - bar: 3 - } - }, - { - id: 4, - foo: { - bar: 4 - } - } - ] - - store.add('thing', things) - - const params = { - where: { - 'foo.bar': { - '>': 2 - } - } - } - - assert.objectsEqual(store.query('thing').filter(params).run(), [things[2], things[3]], 'should filter by a nested key') - }) - it('should support the "like" operator', function () { - const users = [ - { id: 1, name: 'foo' }, - { id: 2, name: 'xfoo' }, - { id: 3, name: 'foox' }, - { id: 4, name: 'xxfoo' }, - { id: 5, name: 'fooxx' }, - { id: 6, name: 'xxfooxx' }, - { id: 7, name: 'xxfooxxfooxx' }, - { id: 8, name: 'fooxxfoo' }, - { id: 9, name: 'fooxfoo' }, - { id: 10, name: 'fooxxfoox' } - ] - this.store.add('user', users) - - assert.objectsEqual(this.store.query('user').filter({ where: { name: { like: 'foo' } } }).run(), [users[0]], 'foo') - assert.objectsEqual(this.store.query('user').filter({ where: { name: { like: '_foo' } } }).run(), [users[1]], '_foo') - assert.objectsEqual(this.store.query('user').filter({ where: { name: { like: 'foo_' } } }).run(), [users[2]], 'foo_') - assert.objectsEqual(this.store.query('user').filter({ where: { name: { like: '%foo' } } }).run(), [users[0], users[1], users[3], users[7], users[8]], '%foo') - assert.objectsEqual(this.store.query('user').filter({ where: { name: { likei: 'FOO%' } } }).run(), [users[0], users[2], users[4], users[7], users[8], users[9]], 'FOO%') - assert.objectsEqual(this.store.query('user').filter({ where: { name: { like: '%foo%' } } }).run(), users, '%foo%') - assert.objectsEqual(this.store.query('user').filter({ where: { name: { like: '%foo%foo%' } } }).run(), [users[6], users[7], users[8], users[9]], '%foo%foo%') - assert.objectsEqual(this.store.query('user').filter({ where: { name: { like: 'foo%foo' } } }).run(), [users[7], users[8]], 'foo%foo') - assert.objectsEqual(this.store.query('user').filter({ where: { name: { like: 'foo_foo' } } }).run(), [users[8]], 'foo_foo') - assert.objectsEqual(this.store.query('user').filter({ where: { name: { like: 'foo%foo_' } } }).run(), [users[9]], 'foo%foo') - - assert.objectsEqual(this.store.query('user').filter({ where: { name: { notLike: 'foo' } } }).run(), [users[1], users[2], users[3], users[4], users[5], users[6], users[7], users[8], users[9]]) - assert.objectsEqual(this.store.query('user').filter({ where: { name: { notLike: '_foo' } } }).run(), [users[0], users[2], users[3], users[4], users[5], users[6], users[7], users[8], users[9]]) - assert.objectsEqual(this.store.query('user').filter({ where: { name: { notLike: 'foo_' } } }).run(), [users[0], users[1], users[3], users[4], users[5], users[6], users[7], users[8], users[9]]) - assert.objectsEqual(this.store.query('user').filter({ where: { name: { notLike: '%foo' } } }).run(), [users[2], users[4], users[5], users[6], users[9]]) - assert.objectsEqual(this.store.query('user').filter({ where: { name: { notLike: 'foo%' } } }).run(), [users[1], users[3], users[5], users[6]]) - assert.objectsEqual(this.store.query('user').filter({ where: { name: { notLike: '%foo%' } } }).run(), []) - assert.objectsEqual(this.store.query('user').filter({ where: { name: { notLike: '%foo%foo%' } } }).run(), [users[0], users[1], users[2], users[3], users[4], users[5]]) - assert.objectsEqual(this.store.query('user').filter({ where: { name: { notLike: 'foo%foo' } } }).run(), [users[0], users[1], users[2], users[3], users[4], users[5], users[6], users[9]]) - assert.objectsEqual(this.store.query('user').filter({ where: { name: { notLike: 'foo_foo' } } }).run(), [users[0], users[1], users[2], users[3], users[4], users[5], users[6], users[7], users[9]]) - assert.objectsEqual(this.store.query('user').filter({ where: { name: { notLike: 'foo%foo_' } } }).run(), [users[0], users[1], users[2], users[3], users[4], users[5], users[6], users[7], users[8]]) - }) -}) diff --git a/test/unit/query/filter.test.ts b/test/unit/query/filter.test.ts new file mode 100644 index 00000000..95a25544 --- /dev/null +++ b/test/unit/query/filter.test.ts @@ -0,0 +1,723 @@ +import { JSData, objectsEqual } from '../../_setup' +import { QueryDefinition } from '../../../src/Query' + +describe('Query#filter', () => { + it('should work', function () { + const collection = this.PostCollection + const p1 = this.data.p1 + const p2 = this.data.p2 + const p3 = this.data.p3 + const p4 = this.data.p4 + const p5 = this.data.p5 + + p1.roles = ['admin'] + p2.roles = ['admin', 'dev'] + p3.roles = ['admin', 'dev'] + p4.roles = [] + p5.roles = ['admin', 'dev', 'owner'] + + this.store.add('post', [p1, p2, p3, p4, p5]) + + let params: QueryDefinition = { + author: 'John' + } + + objectsEqual( + collection + .query() + .filter(params) + .run(), + [p1], + 'should default a string to "=="' + ) + + params = { + author: 'Adam', + id: 9 + } + + objectsEqual( + collection + .query() + .filter(params) + .run(), + [p5], + 'should default a string to "=="' + ) + + params = { + where: { + author: 'John' + } + } + + objectsEqual( + collection + .query() + .filter(params) + .run(), + [p1], + 'should default a string to "=="' + ) + + params.where.author = { + '==': 'John' + } + + objectsEqual( + collection + .query() + .filter(params) + .run(), + [p1], + 'should accept normal "==" clause' + ) + + params.where.author = { + '===': null + } + + objectsEqual( + collection + .query() + .filter(params) + .run(), + [], + 'should accept normal "===" clause' + ) + + params.where.author = { + '!=': 'John' + } + + objectsEqual( + collection + .query() + .filter(params) + .run(), + [p2, p3, p4, p5], + 'should accept normal "!=" clause' + ) + + params.where = { + age: { + '>': 31 + } + } + + objectsEqual( + collection + .query() + .filter(params) + .run(), + [p3, p4, p5], + 'should accept normal ">" clause' + ) + + params.where = { + age: { + '>=': 31 + } + } + + objectsEqual( + collection + .query() + .filter(params) + .run(), + [p2, p3, p4, p5], + 'should accept normal ">=" clause' + ) + + params.where = { + age: { + '<': 31 + } + } + + objectsEqual( + collection + .query() + .filter(params) + .run(), + [p1], + 'should accept normal "<" clause' + ) + + params.where = { + age: { + '>': 30, + '<': 33 + } + } + + objectsEqual( + collection + .query() + .filter(params) + .run(), + [p2, p3], + 'should accept dual "<" and ">" clause' + ) + + params.where = { + age: { + '|>': 30, + '|<': 33 + } + } + + objectsEqual( + collection + .query() + .filter(params) + .run(), + [p1, p2, p3, p4, p5], + 'should accept or "<" and ">" clause' + ) + + params.where = { + age: { + '|<=': 31 + }, + author: { + '|==': 'Adam' + } + } + + objectsEqual( + collection + .query() + .filter(params) + .run(), + [p1, p2, p4, p5], + 'should accept or "<=" and "==" clause' + ) + + params.where = { + age: { + '<=': 31 + } + } + + objectsEqual( + collection + .query() + .filter(params) + .run(), + [p1, p2], + 'should accept normal "<=" clause' + ) + + params.where = { + age: { + in: [30, 33] + }, + author: { + in: ['John', 'Sally', 'Adam'] + } + } + + objectsEqual( + collection + .query() + .filter(params) + .run(), + [p1, p4, p5], + 'should accept normal "in" clause' + ) + + params.where = { + author: { + in: 'John' + } + } + + objectsEqual( + collection + .query() + .filter(params) + .run(), + [p1], + 'should accept normal "in" clause with a string' + ) + + params.where = { + author: { + notIn: 'John' + } + } + + objectsEqual( + collection + .query() + .filter(params) + .run(), + [p2, p3, p4, p5], + 'should accept normal "notIn" clause with a string' + ) + + params.where = { + age: { + '|in': [31] + }, + id: { + '|in': [8] + } + } + + objectsEqual( + collection + .query() + .filter(params) + .run(), + [p2, p4], + 'should accept and/or clause' + ) + + params.where = { + id: { + notIn: [8] + } + } + + objectsEqual( + collection + .query() + .filter(params) + .run(), + [p1, p2, p3, p5], + 'should accept notIn clause' + ) + + params.where = { age: { garbage: 'should have no effect' } } + + objectsEqual( + collection + .query() + .filter(params) + .run(), + [p1, p2, p3, p4, p5], + 'should return all elements' + ) + + params.where = { author: { like: 'Ada%' } } + + objectsEqual( + collection + .query() + .filter(params) + .run(), + [p4, p5], + 'should support like' + ) + + params.where = { author: { like: '%a%' } } + + objectsEqual( + collection + .query() + .filter(params) + .run(), + [p2, p4, p5], + 'should support like' + ) + + params.where = { author: { notLike: 'Ada%' } } + + objectsEqual( + collection + .query() + .filter(params) + .run(), + [p1, p2, p3], + 'should support notLike' + ) + + params.where = { roles: { isectEmpty: ['admin'] } } + + objectsEqual( + collection + .query() + .filter(params) + .run(), + [p4], + 'should support isectEmpty' + ) + + params.where = { roles: { isectNotEmpty: ['admin'] } } + + objectsEqual( + collection + .query() + .filter(params) + .run(), + [p1, p2, p3, p5], + 'should support isectNotEmpty' + ) + + params.where = { roles: { notContains: 'admin' } } + + objectsEqual( + collection + .query() + .filter(params) + .run(), + [p4], + 'should support notContains' + ) + + params.where = { age: { '!==': 33 } } + + objectsEqual( + collection + .query() + .filter(params) + .run(), + [p1, p2, p3], + 'should support !==' + ) + + params = undefined + + objectsEqual( + collection + .query() + .filter(params) + .run(), + [p1, p2, p3, p4, p5], + 'should do nothing' + ) + + params = { offset: 4 } + + objectsEqual( + collection + .query() + .filter(params) + .run(), + [p5], + 'should support offset' + ) + + params = { + where: [ + { + roles: { + contains: 'admin' + } + }, + 'or', + { + age: { + '=': 30 + } + } + ] + } + objectsEqual( + collection + .query() + .filter(params) + .run(), + [p1, p2, p3, p5] + ) + + params = { + where: [ + { + roles: { + contains: 'admin' + }, + age: { + '=': 30 + } + }, + 'or', + { + roles: { + contains: 'owner' + } + } + ] + } + objectsEqual( + collection + .query() + .filter(params) + .run(), + [p1, p5] + ) + + params = { + where: [ + [ + { + roles: { + contains: 'admin' + }, + age: { + '=': 30 + } + }, + 'or', + { + author: { + '=': 'Mike' + } + } + ], + 'or', + { + roles: { + contains: 'owner' + }, + age: { + '=': 33 + } + } + ] + } + objectsEqual( + collection + .query() + .filter(params) + .run(), + [p1, p3, p5] + ) + }) + it('should allow custom filter function', function () { + const p1 = this.data.p1 + const p2 = this.data.p2 + const p3 = this.data.p3 + const p4 = this.data.p4 + this.store.add('post', [p1, p2, p3, p4]) + + objectsEqual( + this.store + .query('post') + .filter(item => { + return item.author === 'John' || item.age % 30 === 1 + }) + .run(), + [p1, p2], + 'should keep p1 and p2' + ) + }) + it('should filter by nested keys', () => { + const store = new JSData.DataStore() + store.defineMapper('thing') + const things = [ + { + id: 1, + foo: { + bar: 1 + } + }, + { + id: 2, + foo: { + bar: 2 + } + }, + { + id: 3, + foo: { + bar: 3 + } + }, + { + id: 4, + foo: { + bar: 4 + } + } + ] + + store.add('thing', things) + + const params = { + where: { + 'foo.bar': { + '>': 2 + } + } + } + + objectsEqual( + store + .query('thing') + .filter(params) + .run(), + [things[2], things[3]], + 'should filter by a nested key' + ) + }) + it('should support the "like" operator', function () { + const users = [ + { id: 1, name: 'foo' }, + { id: 2, name: 'xfoo' }, + { id: 3, name: 'foox' }, + { id: 4, name: 'xxfoo' }, + { id: 5, name: 'fooxx' }, + { id: 6, name: 'xxfooxx' }, + { id: 7, name: 'xxfooxxfooxx' }, + { id: 8, name: 'fooxxfoo' }, + { id: 9, name: 'fooxfoo' }, + { id: 10, name: 'fooxxfoox' } + ] + this.store.add('user', users) + + objectsEqual( + this.store + .query('user') + .filter({ where: { name: { like: 'foo' } } }) + .run(), + [users[0]], + 'foo' + ) + objectsEqual( + this.store + .query('user') + .filter({ where: { name: { like: '_foo' } } }) + .run(), + [users[1]], + '_foo' + ) + objectsEqual( + this.store + .query('user') + .filter({ where: { name: { like: 'foo_' } } }) + .run(), + [users[2]], + 'foo_' + ) + objectsEqual( + this.store + .query('user') + .filter({ where: { name: { like: '%foo' } } }) + .run(), + [users[0], users[1], users[3], users[7], users[8]], + '%foo' + ) + objectsEqual( + this.store + .query('user') + .filter({ where: { name: { likei: 'FOO%' } } }) + .run(), + [users[0], users[2], users[4], users[7], users[8], users[9]], + 'FOO%' + ) + objectsEqual( + this.store + .query('user') + .filter({ where: { name: { like: '%foo%' } } }) + .run(), + users, + '%foo%' + ) + objectsEqual( + this.store + .query('user') + .filter({ where: { name: { like: '%foo%foo%' } } }) + .run(), + [users[6], users[7], users[8], users[9]], + '%foo%foo%' + ) + objectsEqual( + this.store + .query('user') + .filter({ where: { name: { like: 'foo%foo' } } }) + .run(), + [users[7], users[8]], + 'foo%foo' + ) + objectsEqual( + this.store + .query('user') + .filter({ where: { name: { like: 'foo_foo' } } }) + .run(), + [users[8]], + 'foo_foo' + ) + objectsEqual( + this.store + .query('user') + .filter({ where: { name: { like: 'foo%foo_' } } }) + .run(), + [users[9]], + 'foo%foo' + ) + + objectsEqual( + this.store + .query('user') + .filter({ where: { name: { notLike: 'foo' } } }) + .run(), + [users[1], users[2], users[3], users[4], users[5], users[6], users[7], users[8], users[9]] + ) + objectsEqual( + this.store + .query('user') + .filter({ where: { name: { notLike: '_foo' } } }) + .run(), + [users[0], users[2], users[3], users[4], users[5], users[6], users[7], users[8], users[9]] + ) + objectsEqual( + this.store + .query('user') + .filter({ where: { name: { notLike: 'foo_' } } }) + .run(), + [users[0], users[1], users[3], users[4], users[5], users[6], users[7], users[8], users[9]] + ) + objectsEqual( + this.store + .query('user') + .filter({ where: { name: { notLike: '%foo' } } }) + .run(), + [users[2], users[4], users[5], users[6], users[9]] + ) + objectsEqual( + this.store + .query('user') + .filter({ where: { name: { notLike: 'foo%' } } }) + .run(), + [users[1], users[3], users[5], users[6]] + ) + objectsEqual( + this.store + .query('user') + .filter({ where: { name: { notLike: '%foo%' } } }) + .run(), + [] + ) + objectsEqual( + this.store + .query('user') + .filter({ where: { name: { notLike: '%foo%foo%' } } }) + .run(), + [users[0], users[1], users[2], users[3], users[4], users[5]] + ) + objectsEqual( + this.store + .query('user') + .filter({ where: { name: { notLike: 'foo%foo' } } }) + .run(), + [users[0], users[1], users[2], users[3], users[4], users[5], users[6], users[9]] + ) + objectsEqual( + this.store + .query('user') + .filter({ where: { name: { notLike: 'foo_foo' } } }) + .run(), + [users[0], users[1], users[2], users[3], users[4], users[5], users[6], users[7], users[9]] + ) + objectsEqual( + this.store + .query('user') + .filter({ where: { name: { notLike: 'foo%foo_' } } }) + .run(), + [users[0], users[1], users[2], users[3], users[4], users[5], users[6], users[7], users[8]] + ) + }) +}) diff --git a/test/unit/query/forEach.test.js b/test/unit/query/forEach.test.ts similarity index 74% rename from test/unit/query/forEach.test.js rename to test/unit/query/forEach.test.ts index b7c9be99..3e4fe2bb 100644 --- a/test/unit/query/forEach.test.js +++ b/test/unit/query/forEach.test.ts @@ -1,6 +1,6 @@ import { assert } from '../../_setup' -describe('Query#forEach', function () { +describe('Query#forEach', () => { it('should work', function () { const collection = this.PostCollection const p1 = this.data.p1 @@ -11,9 +11,12 @@ describe('Query#forEach', function () { this.store.add('post', [p1, p2, p3, p4, p5]) let count = 0 - collection.query().forEach(function () { - count++ - }).run() + collection + .query() + .forEach(() => { + count++ + }) + .run() assert.equal(count, 5) }) }) diff --git a/test/unit/query/get.test.js b/test/unit/query/get.test.ts similarity index 58% rename from test/unit/query/get.test.js rename to test/unit/query/get.test.ts index 2f7df879..16ccb122 100644 --- a/test/unit/query/get.test.js +++ b/test/unit/query/get.test.ts @@ -1,13 +1,17 @@ import { assert } from '../../_setup' -describe('Query#get', function () { +describe('Query#get', () => { it('should work') it('should not allow index access after operation', function () { const collection = this.PostCollection - assert.throws(function () { - collection.query().filter().get().run() + assert.throws(() => { + collection + .query() + .filter() + .get() + .run() }, Error) }) }) diff --git a/test/unit/query/getAll.test.js b/test/unit/query/getAll.test.ts similarity index 54% rename from test/unit/query/getAll.test.js rename to test/unit/query/getAll.test.ts index effcfb35..ffa30531 100644 --- a/test/unit/query/getAll.test.js +++ b/test/unit/query/getAll.test.ts @@ -1,13 +1,15 @@ import { assert } from '../../_setup' -describe('Query#getAll', function () { - it('should work') - +describe('Query#getAll', () => { it('should not allow index access after operation', function () { const collection = this.PostCollection - assert.throws(function () { - collection.query().filter().getAll().run() + assert.throws(() => { + collection + .query() + .filter() + .getAll() + .run() }, Error) }) }) diff --git a/test/unit/query/index.test.js b/test/unit/query/index.test.ts similarity index 59% rename from test/unit/query/index.test.js rename to test/unit/query/index.test.ts index 1e45743a..5dab670c 100644 --- a/test/unit/query/index.test.js +++ b/test/unit/query/index.test.ts @@ -1,27 +1,33 @@ import { assert, JSData } from '../../_setup' -describe('Query', function () { - it('should be a constructor function', function () { +describe('Query', () => { + it('should be a constructor function', () => { assert.equal(typeof JSData.Query, 'function', 'should be a function') const query = new JSData.Query() assert(query instanceof JSData.Query, 'query should be an instance') }) - it('can make a subclass', function () { - const FooQuery = JSData.Query.extend({ - foo () { return 'foo' } - }) + it('can make a subclass', () => { + class FooQuery extends JSData.Query { + foo () { + return 'foo' + } + } + + // tslint:disable-next-line:max-classes-per-file class BarQuery extends JSData.Query { - // This constructor is here so that the test will work in IE9 + _bar: string; + constructor (collection) { super(collection) - if (!BarQuery.__super__) { - JSData.Query.call(this, collection) - } + this._bar = 'bar' } - bar () { return 'bar' } + bar () { + return this._bar + } } + const fooQ = new FooQuery('test') const barQ = new BarQuery('test') assert.equal(fooQ.foo(), 'foo') diff --git a/test/unit/query/limit.test.js b/test/unit/query/limit.test.js deleted file mode 100644 index 68264980..00000000 --- a/test/unit/query/limit.test.js +++ /dev/null @@ -1,80 +0,0 @@ -import { assert } from '../../_setup' - -describe('Query#limit', function () { - it('should correctly apply "limit" predicates', function () { - const p1 = this.data.p1 - const p2 = this.data.p2 - const p3 = this.data.p3 - const p4 = this.data.p4 - this.store.add('post', [p1, p2, p3, p4]) - const params = { - limit: 1 - } - - assert.objectsEqual(this.store.query('post').filter(params).run(), [p1], 'should limit to 1') - assert.objectsEqual(this.store.query('post').limit(params.limit).run(), [p1], 'should limit to 1') - - params.limit = 2 - assert.objectsEqual(this.store.query('post').filter(params).run(), [p1, p2], 'should limit to 2') - assert.objectsEqual(this.store.query('post').limit(params.limit).run(), [p1, p2], 'should limit to 2') - - params.limit = 3 - assert.objectsEqual(this.store.query('post').filter(params).run(), [p1, p2, p3], 'should limit to 3') - assert.objectsEqual(this.store.query('post').limit(params.limit).run(), [p1, p2, p3], 'should limit to 3') - - params.limit = 4 - assert.objectsEqual(this.store.query('post').filter(params).run(), [p1, p2, p3, p4], 'should limit to 4') - assert.objectsEqual(this.store.query('post').limit(params.limit).run(), [p1, p2, p3, p4], 'should limit to 4') - }) - it('should correctly apply "limit" and "skip" predicates together', function () { - const p1 = this.data.p1 - const p2 = this.data.p2 - const p3 = this.data.p3 - const p4 = this.data.p4 - this.store.add('post', [p1, p2, p3, p4]) - const params = { - limit: 1, - skip: 1 - } - - assert.objectsEqual(this.store.query('post').filter(params).run(), [p2], 'should limit to 1 and skip 2') - assert.objectsEqual(this.store.query('post').skip(params.skip).limit(params.limit).run(), [p2], 'should limit to 1 and skip 2') - - params.limit = 2 - assert.objectsEqual(this.store.query('post').filter(params).run(), [p2, p3], 'should limit to 2 and skip 1') - assert.objectsEqual(this.store.query('post').skip(params.skip).limit(params.limit).run(), [p2, p3], 'should limit to 2 and skip 1') - - params.skip = 2 - assert.objectsEqual(this.store.query('post').filter(params).run(), [p3, p4], 'should limit to 2 and skip 2') - assert.objectsEqual(this.store.query('post').skip(params.skip).limit(params.limit).run(), [p3, p4], 'should limit to 2 and skip 2') - - params.limit = 1 - params.skip = 3 - assert.objectsEqual(this.store.query('post').filter(params).run(), [p4], 'should limit to 1 and skip 3') - assert.objectsEqual(this.store.query('post').skip(params.skip).limit(params.limit).run(), [p4], 'should limit to 1 and skip 3') - - params.limit = 8 - params.skip = 0 - assert.objectsEqual(this.store.query('post').filter(params).run(), [p1, p2, p3, p4], 'should return all items') - assert.objectsEqual(this.store.query('post').skip(params.skip).limit(params.limit).run(), [p1, p2, p3, p4], 'should return all items') - - params.limit = 1 - params.skip = 5 - assert.objectsEqual(this.store.query('post').filter(params).run(), [], 'should return nothing if skip if greater than the number of items') - assert.objectsEqual(this.store.query('post').skip(params.skip).limit(params.limit).run(), [], 'should return nothing if skip if greater than the number of items') - - params.limit = 8 - delete params.skip - assert.objectsEqual(this.store.query('post').filter(params).run(), [p1, p2, p3, p4], 'should return all items') - assert.throws(() => { - this.store.query('post').skip(params.skip).limit(params.limit).run() - }, Error, `[Query#skip:num] expected: number, found: ${typeof value}\nhttp://www.js-data.io/v3.0/docs/errors#400`) - - delete params.limit - params.skip = 5 - assert.objectsEqual(this.store.query('post').filter(params).run(), [], 'should return nothing if skip if greater than the number of items') - assert.throws(() => { - this.store.query('post').skip(params.skip).limit(params.limit).run() - }, Error, `[Query#limit:num] expected: number, found: ${typeof value}\nhttp://www.js-data.io/v3.0/docs/errors#400`) - }) -}) diff --git a/test/unit/query/limit.test.ts b/test/unit/query/limit.test.ts new file mode 100644 index 00000000..3bfbf086 --- /dev/null +++ b/test/unit/query/limit.test.ts @@ -0,0 +1,256 @@ +import { assert, objectsEqual } from '../../_setup' + +describe('Query#limit', () => { + it('should correctly apply "limit" predicates', function () { + const p1 = this.data.p1 + const p2 = this.data.p2 + const p3 = this.data.p3 + const p4 = this.data.p4 + this.store.add('post', [p1, p2, p3, p4]) + const params = { + limit: 1 + } + + objectsEqual( + this.store + .query('post') + .filter(params) + .run(), + [p1], + 'should limit to 1' + ) + objectsEqual( + this.store + .query('post') + .limit(params.limit) + .run(), + [p1], + 'should limit to 1' + ) + + params.limit = 2 + objectsEqual( + this.store + .query('post') + .filter(params) + .run(), + [p1, p2], + 'should limit to 2' + ) + objectsEqual( + this.store + .query('post') + .limit(params.limit) + .run(), + [p1, p2], + 'should limit to 2' + ) + + params.limit = 3 + objectsEqual( + this.store + .query('post') + .filter(params) + .run(), + [p1, p2, p3], + 'should limit to 3' + ) + objectsEqual( + this.store + .query('post') + .limit(params.limit) + .run(), + [p1, p2, p3], + 'should limit to 3' + ) + + params.limit = 4 + objectsEqual( + this.store + .query('post') + .filter(params) + .run(), + [p1, p2, p3, p4], + 'should limit to 4' + ) + objectsEqual( + this.store + .query('post') + .limit(params.limit) + .run(), + [p1, p2, p3, p4], + 'should limit to 4' + ) + }) + it('should correctly apply "limit" and "skip" predicates together', function () { + const p1 = this.data.p1 + const p2 = this.data.p2 + const p3 = this.data.p3 + const p4 = this.data.p4 + this.store.add('post', [p1, p2, p3, p4]) + const params = { + limit: 1, + skip: 1 + } + + objectsEqual( + this.store + .query('post') + .filter(params) + .run(), + [p2], + 'should limit to 1 and skip 2' + ) + objectsEqual( + this.store + .query('post') + .skip(params.skip) + .limit(params.limit) + .run(), + [p2], + 'should limit to 1 and skip 2' + ) + + params.limit = 2 + objectsEqual( + this.store + .query('post') + .filter(params) + .run(), + [p2, p3], + 'should limit to 2 and skip 1' + ) + objectsEqual( + this.store + .query('post') + .skip(params.skip) + .limit(params.limit) + .run(), + [p2, p3], + 'should limit to 2 and skip 1' + ) + + params.skip = 2 + objectsEqual( + this.store + .query('post') + .filter(params) + .run(), + [p3, p4], + 'should limit to 2 and skip 2' + ) + objectsEqual( + this.store + .query('post') + .skip(params.skip) + .limit(params.limit) + .run(), + [p3, p4], + 'should limit to 2 and skip 2' + ) + + params.limit = 1 + params.skip = 3 + objectsEqual( + this.store + .query('post') + .filter(params) + .run(), + [p4], + 'should limit to 1 and skip 3' + ) + objectsEqual( + this.store + .query('post') + .skip(params.skip) + .limit(params.limit) + .run(), + [p4], + 'should limit to 1 and skip 3' + ) + + params.limit = 8 + params.skip = 0 + objectsEqual( + this.store + .query('post') + .filter(params) + .run(), + [p1, p2, p3, p4], + 'should return all items' + ) + objectsEqual( + this.store + .query('post') + .skip(params.skip) + .limit(params.limit) + .run(), + [p1, p2, p3, p4], + 'should return all items' + ) + + params.limit = 1 + params.skip = 5 + objectsEqual( + this.store + .query('post') + .filter(params) + .run(), + [], + 'should return nothing if skip if greater than the number of items' + ) + objectsEqual( + this.store + .query('post') + .skip(params.skip) + .limit(params.limit) + .run(), + [], + 'should return nothing if skip if greater than the number of items' + ) + + params.limit = 8 + delete params.skip + objectsEqual( + this.store + .query('post') + .filter(params) + .run(), + [p1, p2, p3, p4], + 'should return all items' + ) + assert.throws( + () => { + this.store + .query('post') + .skip(params.skip) + .limit(params.limit) + .run() + }, + Error, + '[Query#skip:num] expected: number, found: undefined\nhttp://www.js-data.io/v3.0/docs/errors#400' + ) + + delete params.limit + params.skip = 5 + objectsEqual( + this.store + .query('post') + .filter(params) + .run(), + [], + 'should return nothing if skip if greater than the number of items' + ) + assert.throws( + () => { + this.store + .query('post') + .skip(params.skip) + .limit(params.limit) + .run() + }, + Error, + '[Query#limit:num] expected: number, found: undefined\nhttp://www.js-data.io/v3.0/docs/errors#400' + ) + }) +}) diff --git a/test/unit/query/map.test.js b/test/unit/query/map.test.ts similarity index 73% rename from test/unit/query/map.test.js rename to test/unit/query/map.test.ts index edadd228..7d10cbcd 100644 --- a/test/unit/query/map.test.js +++ b/test/unit/query/map.test.ts @@ -1,6 +1,6 @@ import { assert } from '../../_setup' -describe('Query#map', function () { +describe('Query#map', () => { it('should work', function () { const collection = this.PostCollection const p1 = this.data.p1 @@ -10,9 +10,10 @@ describe('Query#map', function () { const p5 = this.data.p5 this.store.add('post', [p1, p2, p3, p4, p5]) - const ids = collection.query().map(function (post) { - return post.id - }).run() + const ids = collection + .query() + .map(post => post.id) + .run() assert.deepEqual(ids, [5, 6, 7, 8, 9]) }) }) diff --git a/test/unit/query/mapCall.test.js b/test/unit/query/mapCall.test.js deleted file mode 100644 index 5c7ccc55..00000000 --- a/test/unit/query/mapCall.test.js +++ /dev/null @@ -1,12 +0,0 @@ -import { assert, JSData } from '../../_setup' - -describe('Query#mapCall', function () { - it('should map and call', function () { - const data = [ - { id: 1, getId () { return this.id } }, - { id: 2, getId () { return this.id } } - ] - const collection = new JSData.Collection(data) - assert.deepEqual(collection.query().mapCall('getId').run(), [1, 2]) - }) -}) diff --git a/test/unit/query/mapCall.test.ts b/test/unit/query/mapCall.test.ts new file mode 100644 index 00000000..f2ef3831 --- /dev/null +++ b/test/unit/query/mapCall.test.ts @@ -0,0 +1,28 @@ +import { assert, JSData } from '../../_setup' + +describe('Query#mapCall', () => { + it('should map and call', () => { + const data = [ + { + id: 1, + getId () { + return this.id + } + }, + { + id: 2, + getId () { + return this.id + } + } + ] + const collection = new JSData.Collection(data) + assert.deepEqual( + collection + .query() + .mapCall('getId') + .run(), + [1, 2] + ) + }) +}) diff --git a/test/unit/query/orderBy.test.js b/test/unit/query/orderBy.test.js deleted file mode 100644 index 7763c81c..00000000 --- a/test/unit/query/orderBy.test.js +++ /dev/null @@ -1,147 +0,0 @@ -import { assert, JSData } from '../../_setup' - -describe('Query#orderBy', function () { - it('should work', function () { - const collection = this.PostCollection - const p1 = this.data.p1 - const p2 = this.data.p2 - const p3 = this.data.p3 - const p4 = this.data.p4 - this.store.add('post', [p1, p2, p3, p4]) - - const params = { - orderBy: 'age' - } - - assert.objectsEqual(collection.query().filter(params).run(), [p1, p2, p3, p4], 'should accept a single string and sort in ascending order for numbers') - - params.orderBy = 'author' - - assert.objectsEqual(collection.query().filter(params).run(), [p4, p1, p3, p2], 'should accept a single string and sort in ascending for strings') - - params.orderBy = [ - ['age', 'DESC'] - ] - - assert.objectsEqual(collection.query().filter(params).run(), [p4, p3, p2, p1], 'should accept an array of an array and sort in descending for numbers') - - params.orderBy = [ - ['author', 'DESC'] - ] - - assert.objectsEqual(collection.query().filter(params).run(), [p2, p3, p1, p4], 'should accept an array of an array and sort in descending for strings') - - params.orderBy = ['age'] - - assert.objectsEqual(collection.query().filter(params).run(), [p1, p2, p3, p4], 'should accept an array of a string and sort in ascending for numbers') - - params.orderBy = ['author'] - - assert.objectsEqual(collection.query().filter(params).run(), [p4, p1, p3, p2], 'should accept an array of a string and sort in ascending for strings') - }) - it('should work with multiple orderBy', function () { - const store = new JSData.DataStore() - store.defineMapper('item') - const items = [ - { id: 1, test: 1, test2: 1 }, - { id: 2, test: 2, test2: 2 }, - { id: 3, test: 3, test2: 3 }, - { id: 4, test: 1, test2: 4 }, - { id: 5, test: 2, test2: 5 }, - { id: 6, test: 3, test2: 6 }, - { id: 7, test: 1, test2: 1 }, - { id: 8, test: 2, test2: 2 }, - { id: 9, test: 3, test2: 3 }, - { id: 10, test: 1, test2: 4 }, - { id: 11, test: 2, test2: 5 }, - { id: 12, test: 3, test2: 6 } - ] - store.add('item', items) - const params = {} - - params.orderBy = [ - ['test', 'DESC'], - ['test2', 'ASC'], - ['id', 'ASC'] - ] - - assert.objectsEqual(store.query('item').filter(params).run(), [ - items[2], - items[8], - items[5], - items[11], - items[1], - items[7], - items[4], - items[10], - items[0], - items[6], - items[3], - items[9] - ]) - - params.orderBy = [ - ['test', 'DESC'], - ['test2', 'ASC'], - ['id', 'DESC'] - ] - - assert.objectsEqual(store.query('item').filter(params).run(), [ - items[8], - items[2], - items[11], - items[5], - items[7], - items[1], - items[10], - items[4], - items[6], - items[0], - items[9], - items[3] - ]) - }) - it('should order by nested keys', function () { - const store = new JSData.DataStore() - store.defineMapper('thing') - const things = [ - { - id: 1, - foo: { - bar: 'f' - } - }, - { - id: 2, - foo: { - bar: 'a' - } - }, - { - id: 3, - foo: { - bar: 'c' - } - }, - { - id: 4, - foo: { - bar: 'b' - } - } - ] - - store.add('thing', things) - - let params = { - orderBy: [['foo.bar', 'ASC']] - } - - assert.objectsEqual(store.query('thing').filter(params).run(), [things[1], things[3], things[2], things[0]], 'should order by a nested key') - - params = { - orderBy: [['foo.bar', 'DESC']] - } - assert.objectsEqual(store.query('thing').filter(params).run(), [things[0], things[2], things[3], things[1]], 'should order by a nested key') - }) -}) diff --git a/test/unit/query/orderBy.test.ts b/test/unit/query/orderBy.test.ts new file mode 100644 index 00000000..4c5e77bb --- /dev/null +++ b/test/unit/query/orderBy.test.ts @@ -0,0 +1,374 @@ +import { JSData, objectsEqual } from '../../_setup' + +describe('Query#orderBy', () => { + it('should work', function () { + const collection = this.PostCollection + const p1 = this.data.p1 + const p2 = this.data.p2 + const p3 = this.data.p3 + const p4 = this.data.p4 + this.store.add('post', [p1, p2, p3, p4]) + + const params: any = { + orderBy: 'age' + } + + objectsEqual( + collection + .query() + .filter(params) + .run(), + [p1, p2, p3, p4], + 'should accept a single string and sort in ascending order for numbers' + ) + + params.orderBy = 'author' + + objectsEqual( + collection + .query() + .filter(params) + .run(), + [p4, p1, p3, p2], + 'should accept a single string and sort in ascending for strings' + ) + + params.orderBy = [['age', 'DESC']] + + objectsEqual( + collection + .query() + .filter(params) + .run(), + [p4, p3, p2, p1], + 'should accept an array of an array and sort in descending for numbers' + ) + + params.orderBy = [['author', 'DESC']] + + objectsEqual( + collection + .query() + .filter(params) + .run(), + [p2, p3, p1, p4], + 'should accept an array of an array and sort in descending for strings' + ) + + params.orderBy = ['age'] + + objectsEqual( + collection + .query() + .filter(params) + .run(), + [p1, p2, p3, p4], + 'should accept an array of a string and sort in ascending for numbers' + ) + + params.orderBy = ['author'] + + objectsEqual( + collection + .query() + .filter(params) + .run(), + [p4, p1, p3, p2], + 'should accept an array of a string and sort in ascending for strings' + ) + }) + it('should work with multiple orderBy', () => { + const store = new JSData.DataStore() + store.defineMapper('item') + const items = [ + { id: 1, test: 1, test2: 1 }, + { id: 2, test: 2, test2: 2 }, + { id: 3, test: 3, test2: 3 }, + { id: 4, test: 1, test2: 4 }, + { id: 5, test: 2, test2: 5 }, + { id: 6, test: 3, test2: 6 }, + { id: 7, test: 1, test2: 1 }, + { id: 8, test: 2, test2: 2 }, + { id: 9, test: 3, test2: 3 }, + { id: 10, test: 1, test2: 4 }, + { id: 11, test: 2, test2: 5 }, + { id: 12, test: 3, test2: 6 } + ] + store.add('item', items) + const params: any = {} + + params.orderBy = [ + ['test', 'DESC'], + ['test2', 'ASC'], + ['id', 'ASC'] + ] + + objectsEqual( + store + .query('item') + .filter(params) + .run(), + [ + items[2], + items[8], + items[5], + items[11], + items[1], + items[7], + items[4], + items[10], + items[0], + items[6], + items[3], + items[9] + ] + ) + + params.orderBy = [ + ['test', 'DESC'], + ['test2', 'ASC'], + ['id', 'DESC'] + ] + + objectsEqual( + store + .query('item') + .filter(params) + .run(), + [ + items[8], + items[2], + items[11], + items[5], + items[7], + items[1], + items[10], + items[4], + items[6], + items[0], + items[9], + items[3] + ] + ) + }) + it('should work with sorting de locality', function () { + const store = new JSData.DataStore() + store.defineMapper('item') + const items = [ + { test: 'a' }, + { test: 'z' }, + { test: 'ä' } + ] + store.add('item', items) + const params: any = {} + params.orderBy = [ + ['test', 'ASC'] + ] + // should work without locale param with best fit criteria + objectsEqual(store.query('item').filter(params).run(), [ + items[0], + items[2], + items[1] + ]) + // should work with locale param + params.locale = 'de' + objectsEqual(store.query('item').filter(params).run(), [ + items[0], + items[2], + items[1] + ]) + }) + // it('should work with sorting sv locality', function () { + // const store = new JSData.DataStore() + // store.defineMapper('item') + // const items = [ + // { test: 'a' }, + // { test: 'z' }, + // { test: 'ä' } + // ] + // store.add('item', items) + // const params: any = {} + // params.orderBy = [ + // ['test', 'ASC'] + // ] + // params.locale = 'sv' + // objectsEqual(store.query('item').filter(params).run(), [ + // items[0], + // items[1], + // items[2] + // ]) + // }) + it('should work with sorting thai locality', function () { + const store = new JSData.DataStore() + store.defineMapper('item') + const items = [ + { test: 'คลอน' }, + { test: 'กลอน' }, + { test: 'สาระ' }, + { test: 'ศาลา' }, + { test: 'จักรพรรณ' }, + { test: 'จักรพรรดิ' }, + { test: 'เก๋ง' }, + { test: 'เก้ง' }, + { test: 'เก็ง' }, + { test: 'เก่ง' } + ] + store.add('item', items) + const params: any = {} + params.orderBy = [ + ['test', 'ASC'] + ] + // should work without locale param with best fit criteria + objectsEqual(store.query('item').filter(params).run(), [ + items[1], + items[8], + items[9], + items[7], + items[6], + items[0], + items[4], + items[5], + items[3], + items[2] + ]) + // should work with locale param + params.locale = 'th' + objectsEqual(store.query('item').filter(params).run(), [ + items[1], + items[8], + items[9], + items[7], + items[6], + items[0], + items[4], + items[5], + items[3], + items[2] + ]) + }) + it('should order by nested keys', () => { + const store = new JSData.DataStore() + store.defineMapper('thing') + const things = [ + { + id: 1, + foo: { + bar: 'f' + } + }, + { + id: 2, + foo: { + bar: 'a' + } + }, + { + id: 3, + foo: { + bar: 'c' + } + }, + { + id: 4, + foo: { + bar: 'b' + } + } + ] + + store.add('thing', things) + + let params = { + orderBy: [['foo.bar', 'ASC']] + } + + objectsEqual( + store + .query('thing') + .filter(params) + .run(), + [things[1], things[3], things[2], things[0]], + 'should order by a nested key' + ) + + params = { + orderBy: [['foo.bar', 'DESC']] + } + objectsEqual( + store + .query('thing') + .filter(params) + .run(), + [things[0], things[2], things[3], things[1]], + 'should order by a nested key' + ) + }) + it('puts null and undefined values at the end of result', () => { + const store = new JSData.DataStore() + + store.defineMapper('nilOrderBy') + + const items = [ + { + id: 0, + count: 1 + }, + { + id: 1, + count: null + }, + { + id: 2, + count: 0 + }, + { + id: 3, + count: undefined + }, + { + id: 4, + count: 2 + }, + { + id: 5, + count: undefined + }, + { + id: 6, + count: null + }, + { + id: 7, + count: 10 + } + ] + + store.add('nilOrderBy', items) + + const paramsAsc = { + orderBy: [['count', 'ASC']] + } + + objectsEqual( + store + .query('nilOrderBy') + .filter(paramsAsc) + .run(), + [items[2], items[0], items[4], items[7], items[1], items[6], items[3], items[5]], + 'should order by a key ASC' + ) + + const paramsDesc = { + orderBy: [['count', 'DESC']] + } + + objectsEqual( + store + .query('nilOrderBy') + .filter(paramsDesc) + .run(), + [items[3], items[5], items[1], items[6], items[7], items[4], items[0], items[2]], + 'should order by a key DESC' + ) + }) +}) diff --git a/test/unit/query/skip.test.js b/test/unit/query/skip.test.js deleted file mode 100644 index b67d6b36..00000000 --- a/test/unit/query/skip.test.js +++ /dev/null @@ -1,29 +0,0 @@ -import { assert } from '../../_setup' - -describe('Query#skip', function () { - it('should correctly apply "skip" predicates', function () { - const p1 = this.data.p1 - const p2 = this.data.p2 - const p3 = this.data.p3 - const p4 = this.data.p4 - this.store.add('post', [p1, p2, p3, p4]) - const params = { - skip: 1 - } - - assert.objectsEqual(this.store.query('post').filter(params).run(), [p2, p3, p4], 'should skip 1') - assert.objectsEqual(this.store.query('post').skip(params.skip).run(), [p2, p3, p4], 'should skip 1') - - params.skip = 2 - assert.objectsEqual(this.store.query('post').filter(params).run(), [p3, p4], 'should skip 2') - assert.objectsEqual(this.store.query('post').skip(params.skip).run(), [p3, p4], 'should skip 2') - - params.skip = 3 - assert.objectsEqual(this.store.query('post').filter(params).run(), [p4], 'should skip 3') - assert.objectsEqual(this.store.query('post').skip(params.skip).run(), [p4], 'should skip 3') - - params.skip = 4 - assert.objectsEqual(this.store.query('post').filter(params).run(), [], 'should skip 4') - assert.objectsEqual(this.store.query('post').skip(params.skip).run(), [], 'should skip 4') - }) -}) diff --git a/test/unit/query/skip.test.ts b/test/unit/query/skip.test.ts new file mode 100644 index 00000000..d29f6c45 --- /dev/null +++ b/test/unit/query/skip.test.ts @@ -0,0 +1,85 @@ +import { objectsEqual } from '../../_setup' + +describe('Query#skip', () => { + it('should correctly apply "skip" predicates', function () { + const p1 = this.data.p1 + const p2 = this.data.p2 + const p3 = this.data.p3 + const p4 = this.data.p4 + this.store.add('post', [p1, p2, p3, p4]) + const params = { + skip: 1 + } + + objectsEqual( + this.store + .query('post') + .filter(params) + .run(), + [p2, p3, p4], + 'should skip 1' + ) + objectsEqual( + this.store + .query('post') + .skip(params.skip) + .run(), + [p2, p3, p4], + 'should skip 1' + ) + + params.skip = 2 + objectsEqual( + this.store + .query('post') + .filter(params) + .run(), + [p3, p4], + 'should skip 2' + ) + objectsEqual( + this.store + .query('post') + .skip(params.skip) + .run(), + [p3, p4], + 'should skip 2' + ) + + params.skip = 3 + objectsEqual( + this.store + .query('post') + .filter(params) + .run(), + [p4], + 'should skip 3' + ) + objectsEqual( + this.store + .query('post') + .skip(params.skip) + .run(), + [p4], + 'should skip 3' + ) + + params.skip = 4 + objectsEqual( + this.store + .query('post') + .filter(params) + .run(), + [], + 'should skip 4' + ) + objectsEqual( + this.store + .query('post') + .skip(params.skip) + .run(), + [], + 'should skip 4' + ) + }) +}) diff --git a/test/unit/record/changes.test.js b/test/unit/record/changes.test.ts similarity index 70% rename from test/unit/record/changes.test.js rename to test/unit/record/changes.test.ts index a5926e65..c4b52615 100644 --- a/test/unit/record/changes.test.js +++ b/test/unit/record/changes.test.ts @@ -1,29 +1,29 @@ -import { assert, JSData } from '../../_setup' +import { assert, JSData, objectsEqual } from '../../_setup' -describe('Record#changes', function () { - it('should be an instance method', function () { +describe('Record#changes', () => { + it('should be an instance method', () => { const Record = JSData.Record const record = new Record() assert.equal(typeof record.changes, 'function') assert.strictEqual(record.changes, Record.prototype.changes) }) it('should be empty right after an instance is created', function () { - const post = new this.Post.recordClass(this.data.p1) // eslint-disable-line - assert.objectsEqual(post.changes(), { + const post = new this.Post.recordClass(this.data.p1); // eslint-disable-line + objectsEqual(post.changes(), { added: {}, removed: {}, changed: {} }) }) it('should detect tracked field changes', function () { - const post = new this.Post.recordClass(this.data.p1) // eslint-disable-line - assert.objectsEqual(post.changes(), { + const post = new this.Post.recordClass(this.data.p1); // eslint-disable-line + objectsEqual(post.changes(), { added: {}, removed: {}, changed: {} }) post.author = 'Jake' - assert.objectsEqual(post.changes(), { + objectsEqual(post.changes(), { added: {}, removed: {}, changed: { @@ -32,14 +32,14 @@ describe('Record#changes', function () { }) }) it('should detect untracked field changes', function () { - const post = new this.Post.recordClass(this.data.p1) // eslint-disable-line - assert.objectsEqual(post.changes(), { + const post = new this.Post.recordClass(this.data.p1); // eslint-disable-line + objectsEqual(post.changes(), { added: {}, removed: {}, changed: {} }) post.foo = 'bar' - assert.objectsEqual(post.changes(), { + objectsEqual(post.changes(), { added: { foo: 'bar' }, @@ -60,13 +60,13 @@ describe('Record#changes', function () { } }) const post = PostMapper.createRecord(this.data.p1) - assert.objectsEqual(post.changes(), { + objectsEqual(post.changes(), { added: {}, removed: {}, changed: {} }) post.author = 'Jake' - assert.objectsEqual(post.changes(), { + objectsEqual(post.changes(), { added: {}, removed: {}, changed: { @@ -74,7 +74,7 @@ describe('Record#changes', function () { } }) post.author = 'John' - assert.objectsEqual(post.changes(), { + objectsEqual(post.changes(), { added: {}, removed: {}, changed: {} @@ -93,13 +93,13 @@ describe('Record#changes', function () { } }) const post = PostMapper.createRecord(this.data.p1) - assert.objectsEqual(post.changes(), { + objectsEqual(post.changes(), { added: {}, removed: {}, changed: {} }) post.author = 'Jake' - assert.objectsEqual(post.changes(), { + objectsEqual(post.changes(), { added: {}, removed: {}, changed: { @@ -107,7 +107,7 @@ describe('Record#changes', function () { } }) post.author = 'John' - assert.objectsEqual(post.changes(), { + objectsEqual(post.changes(), { added: {}, removed: {}, changed: {} diff --git a/test/unit/record/destroy.test.js b/test/unit/record/destroy.test.ts similarity index 80% rename from test/unit/record/destroy.test.js rename to test/unit/record/destroy.test.ts index 03030713..bb2a9548 100644 --- a/test/unit/record/destroy.test.js +++ b/test/unit/record/destroy.test.ts @@ -1,14 +1,14 @@ import { assert, JSData } from '../../_setup' -describe('Record#destroy', function () { - it('should be an instance method', function () { +describe('Record#destroy', () => { + it('should be an instance method', () => { const Record = JSData.Record const record = new Record() assert.equal(typeof record.destroy, 'function') assert.strictEqual(record.destroy, Record.prototype.destroy) }) - it('can destroy itself', async function () { + it('can destroy itself', async () => { const store = new JSData.DataStore() const mockAdapter = { destroy (mapper, id, opts) { @@ -17,7 +17,7 @@ describe('Record#destroy', function () { } } store.registerAdapter('mock', mockAdapter, { default: true }) - const FooMapper = store.defineMapper('foo') // eslint-disable-line + const FooMapper = store.defineMapper('foo'); // eslint-disable-line const foo = store.add('foo', { id: 1 }) let result = await foo.destroy() assert(!store.get('foo', 1)) diff --git a/test/unit/record/get.test.js b/test/unit/record/get.test.ts similarity index 65% rename from test/unit/record/get.test.js rename to test/unit/record/get.test.ts index c5484b05..0943cdf0 100644 --- a/test/unit/record/get.test.js +++ b/test/unit/record/get.test.ts @@ -1,21 +1,21 @@ import { assert, JSData } from '../../_setup' -describe('Record#changes', function () { - it('should be an instance method', function () { +describe('Record#changes', () => { + it('should be an instance method', () => { const Record = JSData.Record const record = new Record() assert.equal(typeof record.get, 'function') assert.strictEqual(record.get, Record.prototype.get) }) - it('should return a property', function () { + it('should return a property', () => { const user = new JSData.Record({ foo: 'bar' }) assert.equal(user.get('foo'), 'bar') }) - it('should return undefined if the property does not exist', function () { + it('should return undefined if the property does not exist', () => { const user = new JSData.Record() assert(!user.get('foo')) }) - it('should return a nested property', function () { + it('should return a nested property', () => { const user = new JSData.Record({ address: { state: 'TX' } }) assert.equal(user.get('address.state'), 'TX') }) diff --git a/test/unit/record/hasChanges.test.js b/test/unit/record/hasChanges.test.ts similarity index 77% rename from test/unit/record/hasChanges.test.js rename to test/unit/record/hasChanges.test.ts index 6eb07a37..d061112b 100644 --- a/test/unit/record/hasChanges.test.js +++ b/test/unit/record/hasChanges.test.ts @@ -1,14 +1,14 @@ import { assert, JSData, sinon } from '../../_setup' -describe('Record#hasChanges', function () { - it('should be an instance method', function () { +describe('Record#hasChanges', () => { + it('should be an instance method', () => { const Record = JSData.Record const record = new Record() assert.equal(typeof record.hasChanges, 'function') assert.strictEqual(record.hasChanges, Record.prototype.hasChanges) }) it('should detect when untracked fields are changed', function () { - const post = new this.Post.recordClass(this.data.p1) // eslint-disable-line + const post = new this.Post.recordClass(this.data.p1); // eslint-disable-line assert(!post.hasChanges()) post.author = 'Jake' assert(post.hasChanges()) @@ -33,17 +33,17 @@ describe('Record#hasChanges', function () { assert(post.hasChanges()) post.author = 'John' assert(!post.hasChanges()) - setTimeout(function () { + setTimeout(() => { assert.equal(listener.callCount, 0) done() }, 5) }) /* The previous test has a property set and changed back within a single event loop - * So no listener is ever called. - * This test checks that hasChanges() is still false (if the state is set back to the previous) - * even if both changes were registered and a listener was called on each change (twice in total). - */ + * So no listener is ever called. + * This test checks that hasChanges() is still false (if the state is set back to the previous) + * even if both changes were registered and a listener was called on each change (twice in total). + */ it('is not affected by timing', function (done) { const PostMapper = new JSData.Mapper({ @@ -62,12 +62,12 @@ describe('Record#hasChanges', function () { post.on('change', listener) post.author = 'Jake' assert(post.hasChanges()) - const secondSpec = function () { + const secondSpec = () => { assert.equal(listener.callCount, 2) assert(!post.hasChanges()) done() } - setTimeout(function () { + setTimeout(() => { assert.equal(listener.callCount, 1) post.author = 'John' setTimeout(secondSpec, 5) diff --git a/test/unit/record/index.test.js b/test/unit/record/index.test.ts similarity index 74% rename from test/unit/record/index.test.js rename to test/unit/record/index.test.ts index 1d61180f..d5c2eeaf 100644 --- a/test/unit/record/index.test.js +++ b/test/unit/record/index.test.ts @@ -1,15 +1,15 @@ -import { assert, JSData } from '../../_setup' +import { assert, JSData, objectsEqual } from '../../_setup' -describe('Record', function () { - it('should be a constructor function', function () { +describe('Record', () => { + it('should be a constructor function', () => { assert.equal(typeof JSData.Record, 'function', 'should be a function') let instance = new JSData.Record() assert(instance instanceof JSData.Record, 'instance should be an instance') instance = new JSData.Record({ foo: 'bar' }) - assert.objectsEqual(instance, { foo: 'bar' }, 'instance should get initialization properties') + objectsEqual(instance, { foo: 'bar' }, 'instance should get initialization properties') }) - it('should allow instance events (assignment operator)', function (done) { + it('should allow instance events (assignment operator)', done => { let changed = false const FooMapper = new JSData.Mapper({ name: 'foo', @@ -27,7 +27,7 @@ describe('Record', function () { } }, 1000) - foo.on('change', (Foo, foo) => { + foo.on('change', () => { changed = true done() }) @@ -35,7 +35,7 @@ describe('Record', function () { foo.bar = 'baz' }) - it('should allow instance events (setter method)', function (done) { + it('should allow instance events (setter method)', done => { let changed = false const FooMapper = new JSData.Mapper({ name: 'foo', @@ -53,7 +53,7 @@ describe('Record', function () { } }, 1000) - foo.on('change', (Foo, foo) => { + foo.on('change', () => { changed = true done() }) @@ -61,14 +61,18 @@ describe('Record', function () { foo.set('bar', 'baz') }) - it('should throw if a Record class does not have a Mapper', function () { + it('should throw if a Record class does not have a Mapper', () => { const record = new JSData.Record() - assert.throws(() => { - record._mapper() - }, Error, '[Record#_mapper:] mapper not found\nhttp://www.js-data.io/v3.0/docs/errors#404') + assert.throws( + () => { + record._mapper() + }, + Error, + '[Record#_mapper:] mapper not found\nhttp://www.js-data.io/v3.0/docs/errors#404' + ) }) - it('should throw a validation error on instantiation', function () { + it('should throw a validation error on instantiation', () => { const store = new JSData.DataStore() store.defineMapper('user', { schema: { @@ -92,7 +96,7 @@ describe('Record', function () { } }) - it('should skip validation on instantiation', function () { + it('should skip validation on instantiation', () => { const store = new JSData.DataStore() store.defineMapper('user', { schema: { @@ -102,12 +106,12 @@ describe('Record', function () { } } }) - assert.doesNotThrow(function () { + assert.doesNotThrow(() => { store.createRecord('user', { name: 1234, age: 30 }, { noValidate: true }) }) }) - it('should throw a validation error on property assignment', function () { + it('should throw a validation error on property assignment', () => { const store = new JSData.DataStore() store.defineMapper('user', { schema: { @@ -132,7 +136,7 @@ describe('Record', function () { } }) - it('should allow validtion on set to be disabled', function () { + it('should allow validtion on set to be disabled', () => { const store = new JSData.DataStore() store.defineMapper('user', { schema: { @@ -144,12 +148,12 @@ describe('Record', function () { validateOnSet: false }) const user = store.createRecord('user', { name: 'John', age: 30 }) - assert.doesNotThrow(function () { + assert.doesNotThrow(() => { user.name = 1234 }) }) - it('should be saved or unsaved', function () { + it('should be saved or unsaved', () => { const store = new JSData.DataStore() store.defineMapper('user') const user = store.createRecord('user', { id: 1 }) diff --git a/test/unit/record/loadRelations.test.js b/test/unit/record/loadRelations.test.ts similarity index 80% rename from test/unit/record/loadRelations.test.js rename to test/unit/record/loadRelations.test.ts index 71607d65..c17e32ff 100644 --- a/test/unit/record/loadRelations.test.js +++ b/test/unit/record/loadRelations.test.ts @@ -1,6 +1,6 @@ -import { assert, JSData } from '../../_setup' +import { assert, JSData, objectsEqual } from '../../_setup' -describe('Record#changes', function () { +describe('Record#changes', () => { const makeAdapter = function () { const self = this return { @@ -26,7 +26,7 @@ describe('Record#changes', function () { } } - it('should be an instance method', function () { + it('should be an instance method', () => { const Record = JSData.Record const record = new Record() assert.equal(typeof record.loadRelations, 'function') @@ -41,18 +41,24 @@ describe('Record#changes', function () { await user.loadRelations(['organization', 'profile', 'comments', 'group']) - assert.objectsEqual(user.organization, this.data.organization2) - assert.objectsEqual(user.profile, this.data.profile4) - assert.objectsEqual(user.comments, [this.data.comment3]) - assert.objectsEqual([user.groups[0].toJSON()], [this.data.group3]) + objectsEqual(user.organization, this.data.organization2) + objectsEqual(user.profile, this.data.profile4) + objectsEqual(user.comments, [this.data.comment3]) + objectsEqual([user.groups[0].toJSON()], [this.data.group3]) }) it('should load relations', async function () { const store = this.store const user = store.createRecord('user', this.data.user1) - store.registerAdapter('mock', { - findAll () { return Promise.resolve([]) } - }, { default: true }) + store.registerAdapter( + 'mock', + { + findAll () { + return Promise.resolve([]) + } + }, + { default: true } + ) await user.loadRelations(['profile']) @@ -67,7 +73,7 @@ describe('Record#changes', function () { await group.loadRelations(['user']) - assert.objectsEqual(group.users, [this.data.user1]) + objectsEqual(group.users, [this.data.user1]) }) it('should load belongsTo relations using a DataStore', async function () { @@ -78,11 +84,11 @@ describe('Record#changes', function () { await user.loadRelations('organization') - assert.objectsEqual(user.organization, this.data.organization2) + objectsEqual(user.organization, this.data.organization2) assert.strictEqual(user.organization, store.get('organization', user.organizationId)) }) - it('should load relations with custom load method', async function () { + it('should load relations with custom load method', async () => { const store = new JSData.DataStore() store.defineMapper('foo', { relations: { diff --git a/test/unit/record/on.test.js b/test/unit/record/on.test.ts similarity index 90% rename from test/unit/record/on.test.js rename to test/unit/record/on.test.ts index 1d6aec34..da1f87eb 100644 --- a/test/unit/record/on.test.js +++ b/test/unit/record/on.test.ts @@ -1,8 +1,9 @@ import { assert, JSData, sinon } from '../../_setup' + const { Record } = JSData -describe('Record#on("change")', function () { - it('Tracking changes to a single property', function (done) { +describe('Record#on("change")', () => { + it('Tracking changes to a single property', done => { const Store = new JSData.DataStore() const Foo = Store.defineMapper('foo', { schema: { @@ -16,9 +17,9 @@ describe('Record#on("change")', function () { const listener = sinon.stub() foo.on('change', listener) foo.name = 'new foo' - const secondSpec = function () { + const secondSpec = () => { foo.name = 'updated foo' - setTimeout(function () { + setTimeout(() => { const [record, changes] = listener.args[1] assert.equal(foo, record, "on 'change' listener called with record which was modified") assert.isTrue(listener.calledTwice, "on 'change' listener was called when modifying a property") @@ -28,7 +29,7 @@ describe('Record#on("change")', function () { done() }, 5) } - setTimeout(function () { + setTimeout(() => { const [record, changes] = listener.args[0] assert.equal(foo, record, "on 'change' listener called with record which was modified") assert.isTrue(listener.calledOnce, "on 'change' listener was called when modifying a property") @@ -39,7 +40,7 @@ describe('Record#on("change")', function () { }, 5) }) - it('keepChangeHistory: false', function (done) { + it('keepChangeHistory: false', done => { const Store = new JSData.DataStore() class FooRecord extends Record { @@ -76,7 +77,7 @@ describe('Record#on("change")', function () { bar.on('change', listener) foo.name = 'new foo' bar.name = 'new bar' - setTimeout(function () { + setTimeout(() => { assert.isTrue(listener.calledTwice, "on 'change' listener was called when modifying properties") assert.deepEqual(foo.changeHistory(), [], 'no changeHistory was stored if keepChangeHistory: false is set') assert.equal(bar.changeHistory().length, 1, 'if keepChangeHistory is true by default changeHistory is present') diff --git a/test/unit/record/previous.test.js b/test/unit/record/previous.test.ts similarity index 55% rename from test/unit/record/previous.test.js rename to test/unit/record/previous.test.ts index 577bd3ea..29d2d825 100644 --- a/test/unit/record/previous.test.js +++ b/test/unit/record/previous.test.ts @@ -1,22 +1,22 @@ -import { assert, JSData } from '../../_setup' +import { assert, JSData, objectsEqual, objectsNotEqual } from '../../_setup' -describe('Record#previous', function () { - it('should be an instance method', function () { +describe('Record#previous', () => { + it('should be an instance method', () => { const Record = JSData.Record const record = new Record() assert.equal(typeof record.previous, 'function') assert.strictEqual(record.previous, Record.prototype.previous) }) it('should hold previous data', function () { - const post = new this.Post.recordClass(this.data.p1) // eslint-disable-line - assert.objectsEqual(post, post.previous()) + const post = new this.Post.recordClass(this.data.p1); // eslint-disable-line + objectsEqual(post, post.previous()) post.foo = 'bar' - assert.objectsNotEqual(post, post.previous()) + objectsNotEqual(post, post.previous()) delete post.foo - assert.objectsEqual(post, post.previous()) + objectsEqual(post, post.previous()) }) it('should hold previous data for a specified key', function () { - const post = new this.Post.recordClass(this.data.p1) // eslint-disable-line + const post = new this.Post.recordClass(this.data.p1); // eslint-disable-line assert.equal('John', post.previous('author')) post.author = 'Arnold' assert.equal('John', post.previous('author')) diff --git a/test/unit/record/revert.test.js b/test/unit/record/revert.test.ts similarity index 66% rename from test/unit/record/revert.test.js rename to test/unit/record/revert.test.ts index a95923f2..a58e7c56 100644 --- a/test/unit/record/revert.test.js +++ b/test/unit/record/revert.test.ts @@ -1,20 +1,20 @@ -import { assert, JSData } from '../../_setup' +import { assert, JSData, objectsEqual } from '../../_setup' -describe('Record#revert', function () { - it('should be an instance method', function () { +describe('Record#revert', () => { + it('should be an instance method', () => { const Record = JSData.Record const record = new Record() assert.equal(typeof record.revert, 'function') assert.strictEqual(record.revert, Record.prototype.revert) }) it('should return the previous version of an item', function () { - const post = new this.Post.recordClass(this.data.p1) // eslint-disable-line + const post = new this.Post.recordClass(this.data.p1); // eslint-disable-line post.author = 'Jake' post.revert() - assert.objectsEqual(post, this.data.p1) + objectsEqual(post, this.data.p1) }) it('should preserve fields in the optional preserve array', function () { - const post = new this.Post.recordClass(this.data.p1) // eslint-disable-line + const post = new this.Post.recordClass(this.data.p1); // eslint-disable-line post.author = 'Jake' post.age = 20 post.revert({ preserve: ['age'] }) @@ -22,7 +22,7 @@ describe('Record#revert', function () { assert.equal(post.author, 'John', 'The author of the post should have been reverted') }) it('should revert key which has not been injected', function () { - const post = new this.Post.recordClass(this.data.p1) // eslint-disable-line + const post = new this.Post.recordClass(this.data.p1); // eslint-disable-line assert(!post.newProperty) post.newProperty = 'new Property' post.revert() diff --git a/test/unit/record/save.test.js b/test/unit/record/save.test.ts similarity index 76% rename from test/unit/record/save.test.js rename to test/unit/record/save.test.ts index b05e601a..1f26304a 100644 --- a/test/unit/record/save.test.js +++ b/test/unit/record/save.test.ts @@ -1,14 +1,14 @@ -import { assert, JSData } from '../../_setup' +import { assert, JSData, objectsEqual } from '../../_setup' -describe('Record#save', function () { - it('should be an instance method', function () { +describe('Record#save', () => { + it('should be an instance method', () => { const Record = JSData.Record const record = new Record() assert.equal(typeof record.save, 'function') assert.strictEqual(record.save, Record.prototype.save) }) - it('can create itself', async function () { + it('can create itself', async () => { let id = 1 const store = new JSData.DataStore() const mockAdapter = { @@ -22,7 +22,7 @@ describe('Record#save', function () { const FooMapper = store.defineMapper('foo') const foo = store.createRecord('foo', { foo: 'bar' }) const createdFoo = await foo.save() - assert.objectsEqual(createdFoo, { id: 1, foo: 'bar' }) + objectsEqual(createdFoo, { id: 1, foo: 'bar' }) assert(createdFoo instanceof FooMapper.recordClass) assert.strictEqual(foo, createdFoo) assert.strictEqual(store.get('foo', 1), createdFoo) @@ -31,11 +31,11 @@ describe('Record#save', function () { BarMapper.registerAdapter('mock', mockAdapter, { default: true }) const bar = BarMapper.createRecord({ bar: 'foo' }) const createdBar = await bar.save() - assert.objectsEqual(createdBar, { id: 2, bar: 'foo' }) + objectsEqual(createdBar, { id: 2, bar: 'foo' }) assert(createdBar instanceof BarMapper.recordClass) }) - it('can update itself', async function () { + it('can update itself', async () => { const store = new JSData.DataStore() const mockAdapter = { update (mapper, id, props, opts) { @@ -47,8 +47,8 @@ describe('Record#save', function () { const FooMapper = store.defineMapper('foo') const foo = store.add('foo', { id: 1, foo: 'bar' }) const updateFoo = await foo.save() - assert.objectsEqual(foo, { id: 1, foo: 'bar', beep: 'boop' }) - assert.objectsEqual(updateFoo, { id: 1, foo: 'bar', beep: 'boop' }) + objectsEqual(foo, { id: 1, foo: 'bar', beep: 'boop' }) + objectsEqual(updateFoo, { id: 1, foo: 'bar', beep: 'boop' }) assert(updateFoo instanceof FooMapper.recordClass) assert.strictEqual(store.get('foo', 1), updateFoo) assert.strictEqual(foo, updateFoo) @@ -57,14 +57,14 @@ describe('Record#save', function () { BarMapper.registerAdapter('mock', mockAdapter, { default: true }) const bar = BarMapper.createRecord({ id: 1, bar: 'foo' }) const updatedBar = await bar.save() - assert.objectsEqual(updatedBar, { id: 1, bar: 'foo', beep: 'boop' }) + objectsEqual(updatedBar, { id: 1, bar: 'foo', beep: 'boop' }) assert(updatedBar instanceof BarMapper.recordClass) }) - it('can update itself with changes only', async function () { + it('can update itself with changes only', async () => { const mockAdapter = { update (mapper, id, props, opts) { - assert.objectsEqual(props, { bar: 'bar', bing: 'bang', beep: null }) + objectsEqual(props, { bar: 'bar', bing: 'bang', beep: null }) props.id = 1 return Promise.resolve(JSON.parse(JSON.stringify(props))) } @@ -78,7 +78,7 @@ describe('Record#save', function () { bar.bar = 'bar' bar.beep = null const updatedBar = await bar.save({ changesOnly: true }) - assert.objectsEqual(updatedBar, { id: 1, bar: 'bar', bing: 'bang', beep: null }) + objectsEqual(updatedBar, { id: 1, bar: 'bar', bing: 'bang', beep: null }) assert(updatedBar instanceof BarMapper.recordClass) }) }) diff --git a/test/unit/record/set.test.js b/test/unit/record/set.test.ts similarity index 73% rename from test/unit/record/set.test.js rename to test/unit/record/set.test.ts index 002fdaf9..7a496c9f 100644 --- a/test/unit/record/set.test.js +++ b/test/unit/record/set.test.ts @@ -1,25 +1,25 @@ import { assert, JSData } from '../../_setup' -describe('Record#set', function () { - it('should be an instance method', function () { +describe('Record#set', () => { + it('should be an instance method', () => { const Record = JSData.Record const record = new Record() assert.equal(typeof record.save, 'function') assert.strictEqual(record.save, Record.prototype.save) }) - it('should set a property', function () { + it('should set a property', () => { const user = new JSData.Record() assert(!user.foo) user.set('foo', 'bar') assert.equal(user.foo, 'bar') }) - it('should set a nested property', function () { + it('should set a nested property', () => { const user = new JSData.Record() assert(!user.address) user.set('address.state', 'TX') assert.equal(user.address.state, 'TX') }) - it('should set multiple properties', function () { + it('should set multiple properties', () => { const user = new JSData.Record() assert(!user.foo) assert(!user.beep) @@ -30,7 +30,7 @@ describe('Record#set', function () { assert.equal(user.foo, 'bar') assert.equal(user.beep, 'boop') }) - it('should trigger change events', function (done) { + it('should trigger change events', done => { const UserMapper = new JSData.Mapper({ name: 'user', schema: { @@ -42,13 +42,13 @@ describe('Record#set', function () { }) let triggers = 0 const user = UserMapper.createRecord() - user.on('change', function () { + user.on('change', () => { triggers++ }) - user.on('change:foo', function () { + user.on('change:foo', () => { triggers++ }) - user.on('change:beep', function () { + user.on('change:beep', () => { triggers++ }) assert(!user.foo) @@ -59,12 +59,12 @@ describe('Record#set', function () { }) assert.equal(user.foo, 'bar') assert.equal(user.beep, 'boop') - setTimeout(function () { + setTimeout(() => { assert.equal(triggers, 3, 'three events should have fired') done() }, 10) }) - it('should support "silent" option', function (done) { + it('should support "silent" option', done => { const UserMapper = new JSData.Mapper({ name: 'user', schema: { @@ -76,24 +76,27 @@ describe('Record#set', function () { }) let triggers = 0 const user = UserMapper.createRecord() - user.on('change', function () { + user.on('change', () => { triggers++ }) - user.on('change:foo', function () { + user.on('change:foo', () => { triggers++ }) - user.on('change:beep', function () { + user.on('change:beep', () => { triggers++ }) assert(!user.foo) assert(!user.beep) - user.set({ - foo: 'bar' - }, { silent: true }) + user.set( + { + foo: 'bar' + }, + { silent: true } + ) user.set('beep', 'boop', { silent: true }) assert.equal(user.foo, 'bar') assert.equal(user.beep, 'boop') - setTimeout(function () { + setTimeout(() => { assert.equal(triggers, 0, 'no events should have fired') done() }, 10) diff --git a/test/unit/record/unset.test.js b/test/unit/record/unset.test.ts similarity index 75% rename from test/unit/record/unset.test.js rename to test/unit/record/unset.test.ts index 1fa157d8..7d2b1202 100644 --- a/test/unit/record/unset.test.js +++ b/test/unit/record/unset.test.ts @@ -1,25 +1,25 @@ import { assert, JSData } from '../../_setup' -describe('Record#unset', function () { - it('should be an instance method', function () { +describe('Record#unset', () => { + it('should be an instance method', () => { const Record = JSData.Record const record = new Record() assert.equal(typeof record.unset, 'function') assert.strictEqual(record.unset, Record.prototype.unset) }) - it('should unset a property', function () { + it('should unset a property', () => { const user = new JSData.Record({ foo: 'bar' }) assert.equal(user.foo, 'bar') user.unset('foo') assert(!user.foo) }) - it('should set a nested property', function () { + it('should set a nested property', () => { const user = new JSData.Record({ address: { state: 'TX' } }) assert.equal(user.address.state, 'TX') user.unset('address.state') assert(!user.address.state) }) - it('should trigger change events', function (done) { + it('should trigger change events', done => { const UserMapper = new JSData.Mapper({ name: 'user', schema: { @@ -31,13 +31,13 @@ describe('Record#unset', function () { }) let triggers = 0 const user = UserMapper.createRecord({ foo: 'bar', beep: 'boop' }) - user.on('change', function () { + user.on('change', () => { triggers++ }) - user.on('change:foo', function () { + user.on('change:foo', () => { triggers++ }) - user.on('change:beep', function () { + user.on('change:beep', () => { triggers++ }) assert.equal(user.foo, 'bar') @@ -46,12 +46,12 @@ describe('Record#unset', function () { user.unset('beep') assert(!user.foo) assert(!user.beep) - setTimeout(function () { + setTimeout(() => { assert.equal(triggers, 3, 'three events should have fired') done() }, 10) }) - it('should support "silent" option', function (done) { + it('should support "silent" option', done => { const UserMapper = new JSData.Mapper({ name: 'user', schema: { @@ -63,13 +63,13 @@ describe('Record#unset', function () { }) let triggers = 0 const user = UserMapper.createRecord({ foo: 'bar', beep: 'boop' }) - user.on('change', function () { + user.on('change', () => { triggers++ }) - user.on('change:foo', function () { + user.on('change:foo', () => { triggers++ }) - user.on('change:beep', function () { + user.on('change:beep', () => { triggers++ }) assert.equal(user.foo, 'bar') @@ -78,7 +78,7 @@ describe('Record#unset', function () { user.unset('beep', { silent: true }) assert(!user.foo) assert(!user.beep) - setTimeout(function () { + setTimeout(() => { assert.equal(triggers, 0, 'no events should have fired') done() }, 10) diff --git a/test/unit/record/validate.test.js b/test/unit/record/validate.test.js deleted file mode 100644 index 41f11244..00000000 --- a/test/unit/record/validate.test.js +++ /dev/null @@ -1,61 +0,0 @@ -import { assert, JSData } from '../../_setup' -import { productSchema } from '../schema/_productSchema' - -describe('Record#validate', function () { - it('should validate', function () { - const ProductMapper = new JSData.Mapper({ - name: 'product', - schema: productSchema - }) - - let product = ProductMapper.createRecord({ - id: 3, - name: 'A blue mouse', - price: 25.50, - dimensions: { - length: 3.1, - width: 1.0, - height: 1.0 - }, - warehouseLocation: { - latitude: 54.4, - longitude: -32.7 - } - }, { - noValidate: true - }) - - let errors = product.validate() - - assert(product.isValid()) - assert(!errors) - - product = ProductMapper.createRecord({ - id: 3, - // name is missing - price: 'wrong type', - dimensions: { - length: 3.1, - // width is missing - height: 'should be a number' - }, - warehouseLocation: { - latitude: 54.4, - longitude: -32.7 - } - }, { - noValidate: true - }) - errors = product.validate() - assert(!product.isValid()) - assert.deepEqual( - errors, - [ - { expected: 'a value', actual: 'undefined', path: 'name' }, - { expected: 'one of (number)', actual: 'string', path: 'price' }, - { expected: 'a value', actual: 'undefined', path: 'dimensions.width' }, - { expected: 'one of (number)', actual: 'string', path: 'dimensions.height' } - ] - ) - }) -}) diff --git a/test/unit/record/validate.test.ts b/test/unit/record/validate.test.ts new file mode 100644 index 00000000..6546107d --- /dev/null +++ b/test/unit/record/validate.test.ts @@ -0,0 +1,64 @@ +import { assert, JSData } from '../../_setup' +import { productSchema } from '../schema/_productSchema' + +describe('Record#validate', () => { + it('should validate', () => { + const ProductMapper = new JSData.Mapper({ + name: 'product', + schema: productSchema + }) + + let product = ProductMapper.createRecord( + { + id: 3, + name: 'A blue mouse', + price: 25.5, + dimensions: { + length: 3.1, + width: 1.0, + height: 1.0 + }, + warehouseLocation: { + latitude: 54.4, + longitude: -32.7 + } + }, + { + noValidate: true + } + ) + + let errors = product.validate() + + assert(product.isValid()) + assert(!errors) + + product = ProductMapper.createRecord( + { + id: 3, + // name is missing + price: 'wrong type', + dimensions: { + length: 3.1, + // width is missing + height: 'should be a number' + }, + warehouseLocation: { + latitude: 54.4, + longitude: -32.7 + } + }, + { + noValidate: true + } + ) + errors = product.validate() + assert(!product.isValid()) + assert.deepEqual(errors, [ + { expected: 'a value', actual: 'undefined', path: 'name' }, + { expected: 'one of (number)', actual: 'string', path: 'price' }, + { expected: 'a value', actual: 'undefined', path: 'dimensions.width' }, + { expected: 'one of (number)', actual: 'string', path: 'dimensions.height' } + ]) + }) +}) diff --git a/test/unit/schema/_productSchema.js b/test/unit/schema/_productSchema.ts similarity index 95% rename from test/unit/schema/_productSchema.js rename to test/unit/schema/_productSchema.ts index 1fe05fd6..29410b14 100644 --- a/test/unit/schema/_productSchema.js +++ b/test/unit/schema/_productSchema.ts @@ -1,7 +1,7 @@ export const productSchema = { $schema: 'http://json-schema.org/draft-04/schema#', title: 'Product', - description: 'A product from Acme\'s catalog', + description: "A product from Acme's catalog", type: 'object', properties: { id: { diff --git a/test/unit/schema/apply.test.js b/test/unit/schema/apply.test.ts similarity index 75% rename from test/unit/schema/apply.test.js rename to test/unit/schema/apply.test.ts index 61540c98..00da734e 100644 --- a/test/unit/schema/apply.test.js +++ b/test/unit/schema/apply.test.ts @@ -1,17 +1,18 @@ import { assert, JSData } from '../../_setup' import { productSchema } from './_productSchema' -describe('Schema.apply', function () { - it('has the right exports', function () { +describe('Schema.apply', () => { + it('has the right exports', () => { assert.isFunction(JSData.Schema.prototype.apply) }) - it('applies a property descriptor to the specified property', function () { - const Thing = JSData.Settable.extend() + it('applies a property descriptor to the specified property', () => { + class Thing extends JSData.Settable {} + const schema = new JSData.Schema(productSchema) schema.apply(Thing.prototype) - JSData.utils.forOwn(productSchema.properties, function (_schema, prop) { + JSData.utils.forOwn(productSchema.properties, (_schema, prop) => { const descriptor = Object.getOwnPropertyDescriptor(Thing.prototype, prop) assert.equal(!!descriptor.writable, false) assert.equal(descriptor.enumerable, true) diff --git a/test/unit/schema/index.test.js b/test/unit/schema/index.test.ts similarity index 68% rename from test/unit/schema/index.test.js rename to test/unit/schema/index.test.ts index 23f1c6fe..15936e14 100644 --- a/test/unit/schema/index.test.js +++ b/test/unit/schema/index.test.ts @@ -1,8 +1,8 @@ import { assert, JSData } from '../../_setup' import { productSchema } from './_productSchema' -describe('Schema', function () { - it('has the right exports', function () { +describe('Schema', () => { + it('has the right exports', () => { assert.equal(typeof JSData.Schema, 'function') assert.equal(typeof JSData.Schema.validate, 'function') assert(JSData.Schema.types) @@ -10,7 +10,7 @@ describe('Schema', function () { assert(JSData.Schema.typeGroupValidators) }) - it('should recursively instantiate schemas', function () { + it('should recursively instantiate schemas', () => { const schemaDef = JSData.utils.plainCopy(productSchema) schemaDef.properties.things = { type: 'array', @@ -19,22 +19,13 @@ describe('Schema', function () { } } schemaDef.properties.anyFoo = { - anyOf: [ - { type: 'number' }, - { type: 'string' } - ] + anyOf: [{ type: 'number' }, { type: 'string' }] } schemaDef.properties.allFoo = { - allOf: [ - { type: 'number' }, - { enum: [1, 2, 3] } - ] + allOf: [{ type: 'number' }, { enum: [1, 2, 3] }] } schemaDef.properties.oneFoo = { - oneOf: [ - { type: 'string' }, - { enum: [1, 2, 3] } - ] + oneOf: [{ type: 'string' }, { enum: [1, 2, 3] }] } const ProductSchema = new JSData.Schema(schemaDef) assert(ProductSchema instanceof JSData.Schema) @@ -54,13 +45,13 @@ describe('Schema', function () { assert(ProductSchema.properties.oneFoo.oneOf[1] instanceof JSData.Schema) }) - it('should validate', function () { + it('should validate', () => { const ProductSchema = new JSData.Schema(productSchema) let errors = ProductSchema.validate({ id: 3, name: 'A blue mouse', - price: 25.50, + price: 25.5, dimensions: { length: 3.1, width: 1.0, @@ -76,25 +67,13 @@ describe('Schema', function () { errors = ProductSchema.validate('foo') // return - assert.deepEqual( - errors, - [{ expected: 'one of (object)', actual: 'string', path: '' }] - ) + assert.deepEqual(errors, [{ expected: 'one of (object)', actual: 'string', path: '' }]) errors = ProductSchema.validate(45) - assert.deepEqual( - errors, - [{ expected: 'one of (object)', actual: 'number', path: '' }] - ) + assert.deepEqual(errors, [{ expected: 'one of (object)', actual: 'number', path: '' }]) errors = ProductSchema.validate(null) - assert.deepEqual( - errors, - [{ expected: 'one of (object)', actual: 'null', path: '' }] - ) + assert.deepEqual(errors, [{ expected: 'one of (object)', actual: 'null', path: '' }]) errors = ProductSchema.validate(true) - assert.deepEqual( - errors, - [{ expected: 'one of (object)', actual: 'boolean', path: '' }] - ) + assert.deepEqual(errors, [{ expected: 'one of (object)', actual: 'boolean', path: '' }]) errors = ProductSchema.validate(undefined) assert(!errors) errors = ProductSchema.validate({ @@ -111,14 +90,11 @@ describe('Schema', function () { longitude: -32.7 } }) - assert.deepEqual( - errors, - [ - { expected: 'a value', actual: 'undefined', path: 'name' }, - { expected: 'one of (number)', actual: 'string', path: 'price' }, - { expected: 'a value', actual: 'undefined', path: 'dimensions.width' }, - { expected: 'one of (number)', actual: 'string', path: 'dimensions.height' } - ] - ) + assert.deepEqual(errors, [ + { expected: 'a value', actual: 'undefined', path: 'name' }, + { expected: 'one of (number)', actual: 'string', path: 'price' }, + { expected: 'a value', actual: 'undefined', path: 'dimensions.width' }, + { expected: 'one of (number)', actual: 'string', path: 'dimensions.height' } + ]) }) }) diff --git a/test/unit/schema/pick.test.js b/test/unit/schema/pick.test.ts similarity index 94% rename from test/unit/schema/pick.test.js rename to test/unit/schema/pick.test.ts index f2294e5d..a3da80ae 100644 --- a/test/unit/schema/pick.test.js +++ b/test/unit/schema/pick.test.ts @@ -1,12 +1,12 @@ import { assert, JSData } from '../../_setup' import { productSchema } from './_productSchema' -describe('Schema.pick', function () { - it('has the right exports', function () { +describe('Schema.pick', () => { + it('has the right exports', () => { assert.isFunction(JSData.Schema.prototype.pick) }) - it('Copies a value based on the properties defined in the schema', function () { + it('Copies a value based on the properties defined in the schema', () => { const schema = new JSData.Schema(productSchema) const data = { @@ -34,7 +34,7 @@ describe('Schema.pick', function () { }) }) - it('Copies a value based on the items defined in the schema allowing extra properties', function () { + it('Copies a value based on the items defined in the schema allowing extra properties', () => { const schema = new JSData.Schema({ type: 'object', properties: { @@ -86,7 +86,7 @@ describe('Schema.pick', function () { }) }) - it('Copies a value based on the items defined in the schema disallowing extra properties', function () { + it('Copies a value based on the items defined in the schema disallowing extra properties', () => { const schema = new JSData.Schema({ type: 'object', properties: { @@ -136,7 +136,7 @@ describe('Schema.pick', function () { }) }) - it('Copies a value based on the parent schema', function () { + it('Copies a value based on the parent schema', () => { const schema = new JSData.Schema({ type: 'object', extends: productSchema, @@ -195,7 +195,7 @@ describe('Schema.pick', function () { }) }) - it('should ignore undefined properties', function () { + it('should ignore undefined properties', () => { const store = new JSData.DataStore() const countrySchema = new JSData.Schema({ diff --git a/test/unit/schema/typeGroupValidators/array.test.js b/test/unit/schema/typeGroupValidators/array.test.ts similarity index 89% rename from test/unit/schema/typeGroupValidators/array.test.js rename to test/unit/schema/typeGroupValidators/array.test.ts index b8bdd7df..04a8ce8d 100644 --- a/test/unit/schema/typeGroupValidators/array.test.js +++ b/test/unit/schema/typeGroupValidators/array.test.ts @@ -1,18 +1,18 @@ import { assert, JSData, sinon } from '../../../_setup' -describe('Schema.typeGroupValidators.array', function () { - it('executes correct validation keywords', function () { +describe('Schema.typeGroupValidators.array', () => { + it('executes correct validation keywords', () => { const forOwn = JSData.utils.forOwn const validationKeywords = JSData.Schema.validationKeywords const TARGET_KEYWORDS = ['items', 'maxItems', 'minItems', 'uniqueItems'] - forOwn(validationKeywords, function (func, key) { + forOwn(validationKeywords, (func, key) => { sinon.spy(validationKeywords, key) }) const array = JSData.Schema.typeGroupValidators.array - forOwn(validationKeywords, function (func, key) { + forOwn(validationKeywords, (func, key) => { assert.equal(func.callCount, 0, `${key} should not have been called yet`) }) @@ -80,7 +80,7 @@ describe('Schema.typeGroupValidators.array', function () { assert.equal(validationKeywords.minItems.callCount, 3) assert.equal(validationKeywords.uniqueItems.callCount, 3) - forOwn(validationKeywords, function (func, key) { + forOwn(validationKeywords, (func, key) => { if (TARGET_KEYWORDS.indexOf(key) === -1) { assert.equal(func.callCount, 0, `${key} should not have been called`) } diff --git a/test/unit/schema/typeGroupValidators/index.test.js b/test/unit/schema/typeGroupValidators/index.test.ts similarity index 51% rename from test/unit/schema/typeGroupValidators/index.test.js rename to test/unit/schema/typeGroupValidators/index.test.ts index fcadd292..4278b2ae 100644 --- a/test/unit/schema/typeGroupValidators/index.test.js +++ b/test/unit/schema/typeGroupValidators/index.test.ts @@ -1,28 +1,17 @@ import { assert, JSData } from '../../../_setup' -describe('Schema.typeGroupValidators', function () { - it('has the right default validators', function () { +describe('Schema.typeGroupValidators', () => { + it('has the right default validators', () => { const typeGroupValidators = JSData.Schema.typeGroupValidators - const EXPECTED_KEYS = [ - 'array', - 'integer', - 'number', - 'numeric', - 'object', - 'string' - ] - assert.deepEqual( - Object.keys(typeGroupValidators), - EXPECTED_KEYS, - 'has the expected keys' - ) + const EXPECTED_KEYS = ['array', 'integer', 'number', 'numeric', 'object', 'string'] + assert.deepEqual(Object.keys(typeGroupValidators), EXPECTED_KEYS, 'has the expected keys') }) - it('allows custom validation keywords', function () { + it('allows custom validation keywords', () => { const STRING_OPS = JSData.Schema.STRING_OPS const validationKeywords = JSData.Schema.validationKeywords STRING_OPS.push('foo') - validationKeywords.foo = function (value, schema, opts) { + validationKeywords.foo = (value, schema, opts) => { if (value !== 'bar') { return [ { @@ -44,36 +33,30 @@ describe('Schema.typeGroupValidators', function () { name: 1234 }) - assert.deepEqual( - errors, - [ - { - expected: 'a value', - actual: 'undefined', - path: 'thing' - }, - { - expected: 'one of (string)', - actual: 'number', - path: 'name' - } - ] - ) + assert.deepEqual(errors, [ + { + expected: 'a value', + actual: 'undefined', + path: 'thing' + }, + { + expected: 'one of (string)', + actual: 'number', + path: 'name' + } + ]) errors = schema.validate({ name: 'john', thing: 'baz' }) - assert.deepEqual( - errors, - [ - { - expected: 'bar', - actual: 'baz', - path: 'thing' - } - ] - ) + assert.deepEqual(errors, [ + { + expected: 'bar', + actual: 'baz', + path: 'thing' + } + ]) errors = schema.validate({ name: 'john', diff --git a/test/unit/schema/typeGroupValidators/string.test.js b/test/unit/schema/typeGroupValidators/string.test.ts similarity index 87% rename from test/unit/schema/typeGroupValidators/string.test.js rename to test/unit/schema/typeGroupValidators/string.test.ts index e39fd9e0..21dfa517 100644 --- a/test/unit/schema/typeGroupValidators/string.test.js +++ b/test/unit/schema/typeGroupValidators/string.test.ts @@ -1,18 +1,18 @@ import { assert, JSData, sinon } from '../../../_setup' -describe('Schema.typeGroupValidators.string', function () { - it('executes correct validation keywords', function () { +describe('Schema.typeGroupValidators.string', () => { + it('executes correct validation keywords', () => { const forOwn = JSData.utils.forOwn const validationKeywords = JSData.Schema.validationKeywords const TARGET_KEYWORDS = ['maxLength', 'minLength', 'pattern'] - forOwn(validationKeywords, function (func, key) { + forOwn(validationKeywords, (func, key) => { sinon.spy(validationKeywords, key) }) const string = JSData.Schema.typeGroupValidators.string - forOwn(validationKeywords, function (func, key) { + forOwn(validationKeywords, (func, key) => { assert.equal(func.callCount, 0, `${key} should not have been called yet`) }) @@ -64,7 +64,7 @@ describe('Schema.typeGroupValidators.string', function () { assert.equal(validationKeywords.maxLength.callCount, 3) assert.equal(validationKeywords.minLength.callCount, 3) - forOwn(validationKeywords, function (func, key) { + forOwn(validationKeywords, (func, key) => { if (TARGET_KEYWORDS.indexOf(key) === -1) { assert.equal(func.callCount, 0, `${key} should not have been called`) } diff --git a/test/unit/schema/validationKeywords/_allOf.js b/test/unit/schema/validationKeywords/_allOf.ts similarity index 100% rename from test/unit/schema/validationKeywords/_allOf.js rename to test/unit/schema/validationKeywords/_allOf.ts diff --git a/test/unit/schema/validationKeywords/_anyOf.js b/test/unit/schema/validationKeywords/_anyOf.ts similarity index 100% rename from test/unit/schema/validationKeywords/_anyOf.js rename to test/unit/schema/validationKeywords/_anyOf.ts diff --git a/test/unit/schema/validationKeywords/_definitions.js b/test/unit/schema/validationKeywords/_definitions.ts similarity index 100% rename from test/unit/schema/validationKeywords/_definitions.js rename to test/unit/schema/validationKeywords/_definitions.ts diff --git a/test/unit/schema/validationKeywords/_dependencies.js b/test/unit/schema/validationKeywords/_dependencies.ts similarity index 100% rename from test/unit/schema/validationKeywords/_dependencies.js rename to test/unit/schema/validationKeywords/_dependencies.ts diff --git a/test/unit/schema/validationKeywords/_enum.js b/test/unit/schema/validationKeywords/_enum.ts similarity index 100% rename from test/unit/schema/validationKeywords/_enum.js rename to test/unit/schema/validationKeywords/_enum.ts diff --git a/test/unit/schema/validationKeywords/_items.js b/test/unit/schema/validationKeywords/_items.ts similarity index 93% rename from test/unit/schema/validationKeywords/_items.js rename to test/unit/schema/validationKeywords/_items.ts index aa2c851b..5def5ef2 100644 --- a/test/unit/schema/validationKeywords/_items.js +++ b/test/unit/schema/validationKeywords/_items.ts @@ -25,10 +25,7 @@ export const itemsTests = [ { description: 'an array of schemas for items', schema: { - items: [ - { type: 'integer' }, - { type: 'string' } - ] + items: [{ type: 'integer' }, { type: 'string' }] }, tests: [ { @@ -103,8 +100,7 @@ export const additionalItemsTests = [ schema: { additionalItems: false }, tests: [ { - description: - 'items defaults to empty schema so everything is valid', + description: 'items defaults to empty schema so everything is valid', data: [1, 2, 3, 4, 5], valid: true }, diff --git a/test/unit/schema/validationKeywords/_maxItems.js b/test/unit/schema/validationKeywords/_maxItems.ts similarity index 100% rename from test/unit/schema/validationKeywords/_maxItems.js rename to test/unit/schema/validationKeywords/_maxItems.ts diff --git a/test/unit/schema/validationKeywords/_maxLength.js b/test/unit/schema/validationKeywords/_maxLength.ts similarity index 100% rename from test/unit/schema/validationKeywords/_maxLength.js rename to test/unit/schema/validationKeywords/_maxLength.ts diff --git a/test/unit/schema/validationKeywords/_maxProperties.js b/test/unit/schema/validationKeywords/_maxProperties.ts similarity index 100% rename from test/unit/schema/validationKeywords/_maxProperties.js rename to test/unit/schema/validationKeywords/_maxProperties.ts diff --git a/test/unit/schema/validationKeywords/_maximum.js b/test/unit/schema/validationKeywords/_maximum.ts similarity index 100% rename from test/unit/schema/validationKeywords/_maximum.js rename to test/unit/schema/validationKeywords/_maximum.ts diff --git a/test/unit/schema/validationKeywords/_minItems.js b/test/unit/schema/validationKeywords/_minItems.ts similarity index 100% rename from test/unit/schema/validationKeywords/_minItems.js rename to test/unit/schema/validationKeywords/_minItems.ts diff --git a/test/unit/schema/validationKeywords/_minLength.js b/test/unit/schema/validationKeywords/_minLength.ts similarity index 100% rename from test/unit/schema/validationKeywords/_minLength.js rename to test/unit/schema/validationKeywords/_minLength.ts diff --git a/test/unit/schema/validationKeywords/_minProperties.js b/test/unit/schema/validationKeywords/_minProperties.ts similarity index 100% rename from test/unit/schema/validationKeywords/_minProperties.js rename to test/unit/schema/validationKeywords/_minProperties.ts diff --git a/test/unit/schema/validationKeywords/_minimum.js b/test/unit/schema/validationKeywords/_minimum.ts similarity index 100% rename from test/unit/schema/validationKeywords/_minimum.js rename to test/unit/schema/validationKeywords/_minimum.ts diff --git a/test/unit/schema/validationKeywords/_multipleOf.js b/test/unit/schema/validationKeywords/_multipleOf.ts similarity index 100% rename from test/unit/schema/validationKeywords/_multipleOf.js rename to test/unit/schema/validationKeywords/_multipleOf.ts diff --git a/test/unit/schema/validationKeywords/_not.js b/test/unit/schema/validationKeywords/_not.ts similarity index 100% rename from test/unit/schema/validationKeywords/_not.js rename to test/unit/schema/validationKeywords/_not.ts diff --git a/test/unit/schema/validationKeywords/_oneOf.js b/test/unit/schema/validationKeywords/_oneOf.ts similarity index 100% rename from test/unit/schema/validationKeywords/_oneOf.js rename to test/unit/schema/validationKeywords/_oneOf.ts diff --git a/test/unit/schema/validationKeywords/_pattern.js b/test/unit/schema/validationKeywords/_pattern.ts similarity index 100% rename from test/unit/schema/validationKeywords/_pattern.js rename to test/unit/schema/validationKeywords/_pattern.ts diff --git a/test/unit/schema/validationKeywords/_patternProperties.js b/test/unit/schema/validationKeywords/_patternProperties.ts similarity index 96% rename from test/unit/schema/validationKeywords/_patternProperties.js rename to test/unit/schema/validationKeywords/_patternProperties.ts index 8529723c..b456358e 100644 --- a/test/unit/schema/validationKeywords/_patternProperties.js +++ b/test/unit/schema/validationKeywords/_patternProperties.ts @@ -1,7 +1,6 @@ export const patternPropertiesTests = [ { - description: - '"patternProperties" validates properties matching a regexp', + description: '"patternProperties" validates properties matching a regexp', schema: { type: 'object', patternProperties: { diff --git a/test/unit/schema/validationKeywords/_properties.js b/test/unit/schema/validationKeywords/_properties.ts similarity index 94% rename from test/unit/schema/validationKeywords/_properties.js rename to test/unit/schema/validationKeywords/_properties.ts index b506627b..22800a9e 100644 --- a/test/unit/schema/validationKeywords/_properties.js +++ b/test/unit/schema/validationKeywords/_properties.ts @@ -96,8 +96,7 @@ export const propertiesTests = [ export const additionalProperties = [ { - description: - 'when "additionalProperties" option is false', + description: 'when "additionalProperties" option is false', schema: { type: 'object', properties: { foo: {}, bar: {} }, @@ -128,8 +127,7 @@ export const additionalProperties = [ ] }, { - description: - 'when "additionalProperties" allows to pass "boolean" types', + description: 'when "additionalProperties" allows to pass "boolean" types', schema: { type: 'object', properties: { foo: {}, bar: {} }, @@ -155,7 +153,7 @@ export const additionalProperties = [ }, { description: - 'when schema does not have "properties" option but has "additionalProperties" which allows to pass boolean', + 'when schema does not have "properties" option but has "additionalProperties" which allows to pass boolean', schema: { type: 'object', additionalProperties: { type: 'boolean' } diff --git a/test/unit/schema/validationKeywords/_required.js b/test/unit/schema/validationKeywords/_required.ts similarity index 100% rename from test/unit/schema/validationKeywords/_required.js rename to test/unit/schema/validationKeywords/_required.ts diff --git a/test/unit/schema/validationKeywords/_type.js b/test/unit/schema/validationKeywords/_type.ts similarity index 100% rename from test/unit/schema/validationKeywords/_type.js rename to test/unit/schema/validationKeywords/_type.ts diff --git a/test/unit/schema/validationKeywords/_uniqueItems.js b/test/unit/schema/validationKeywords/_uniqueItems.ts similarity index 87% rename from test/unit/schema/validationKeywords/_uniqueItems.js rename to test/unit/schema/validationKeywords/_uniqueItems.ts index dd50da64..9e34fdf3 100644 --- a/test/unit/schema/validationKeywords/_uniqueItems.js +++ b/test/unit/schema/validationKeywords/_uniqueItems.ts @@ -15,7 +15,7 @@ export const uniqueItemsTests = [ }, { description: 'numbers are unique if mathematically unequal', - data: [1.0, 1.00, 1], + data: [1.0, 1.0, 1], valid: false }, { @@ -30,18 +30,12 @@ export const uniqueItemsTests = [ }, { description: 'unique array of nested objects is valid', - data: [ - { foo: { bar: { baz: true } } }, - { foo: { bar: { baz: false } } } - ], + data: [{ foo: { bar: { baz: true } } }, { foo: { bar: { baz: false } } }], valid: true }, { description: 'non-unique array of nested objects is invalid', - data: [ - { foo: { bar: { baz: true } } }, - { foo: { bar: { baz: true } } } - ], + data: [{ foo: { bar: { baz: true } } }, { foo: { bar: { baz: true } } }], valid: false }, { diff --git a/test/unit/schema/validationKeywords/index.test.js b/test/unit/schema/validationKeywords/index.test.ts similarity index 62% rename from test/unit/schema/validationKeywords/index.test.js rename to test/unit/schema/validationKeywords/index.test.ts index 7233b5e1..b8876afc 100644 --- a/test/unit/schema/validationKeywords/index.test.js +++ b/test/unit/schema/validationKeywords/index.test.ts @@ -16,20 +16,19 @@ import { uniqueItemsTests } from './_uniqueItems' import { maxPropertiesTests } from './_maxProperties' import { minPropertiesTests } from './_minProperties' import { requiredTests } from './_required' -import { propertiesTests, additionalProperties } from './_properties' +import { additionalProperties, propertiesTests } from './_properties' import { patternPropertiesTests } from './_patternProperties' -// import { dependenciesTests } from './_dependencies' - import { enumTests } from './_enum' import { typeTests } from './_type' import { allOfTests } from './_allOf' import { anyOfTests } from './_anyOf' import { oneOfTests } from './_oneOf' import { notTests } from './_not' +// import { dependenciesTests } from './_dependencies' // import { definitionsTests } from './_definitions' -describe('Schema.validationKeywords', function () { - it('has the right default keywords', function () { +describe('Schema.validationKeywords', () => { + it('has the right default keywords', () => { const validationKeywords = JSData.Schema.validationKeywords const EXPECTED_KEYS = [ 'allOf', @@ -54,20 +53,16 @@ describe('Schema.validationKeywords', function () { 'type', 'uniqueItems' ] - assert.deepEqual( - Object.keys(validationKeywords), - EXPECTED_KEYS, - 'has the expected keys' - ) + assert.deepEqual(Object.keys(validationKeywords), EXPECTED_KEYS, 'has the expected keys') }) }) -const validationTestRunner = function (suites, group) { - suites.forEach((suite) => { +const validationTestRunner = (suites, group?) => { + suites.forEach(suite => { const schema = new JSData.Schema(suite.schema) - describe(suite.description, function () { - suite.tests.forEach((test) => { - it(test.description, function () { + describe(suite.description, () => { + suite.tests.forEach(test => { + it(test.description, () => { const errors = group ? JSData.Schema.typeGroupValidators[group](test.data, schema) : JSData.Schema.validate(test.data, schema) @@ -80,104 +75,104 @@ const validationTestRunner = function (suites, group) { } // Numeric Tests -describe('Schema.validationKeywords.maximum', function () { +describe('Schema.validationKeywords.maximum', () => { validationTestRunner(maximumTests, 'numeric') }) -describe('Schema.validationKeywords.minimum', function () { +describe('Schema.validationKeywords.minimum', () => { validationTestRunner(minimumTests, 'numeric') }) -describe('Schema.validationKeywords.multipleOf', function () { +describe('Schema.validationKeywords.multipleOf', () => { validationTestRunner(multipleOfTests, 'numeric') }) // String Tests -describe('Schema.validationKeywords.pattern', function () { +describe('Schema.validationKeywords.pattern', () => { validationTestRunner(patternTests, 'string') }) -describe('Schema.validationKeywords.minLength', function () { +describe('Schema.validationKeywords.minLength', () => { validationTestRunner(minLengthTests, 'string') }) -describe('Schema.validationKeywords.maxLength', function () { +describe('Schema.validationKeywords.maxLength', () => { validationTestRunner(maxLengthTests, 'string') }) // Array Tests -describe('Schema.validationKeywords.items', function () { +describe('Schema.validationKeywords.items', () => { validationTestRunner(itemsTests, 'array') }) -describe('Schema.validationKeywords.maxItems', function () { +describe('Schema.validationKeywords.maxItems', () => { validationTestRunner(maxItemsTests, 'array') }) -describe('Schema.validationKeywords.minItems', function () { +describe('Schema.validationKeywords.minItems', () => { validationTestRunner(minItemsTests, 'array') }) -describe('Schema.validationKeywords.uniqueItems', function () { +describe('Schema.validationKeywords.uniqueItems', () => { validationTestRunner(uniqueItemsTests, 'array') }) // Object Tests -describe('Schema.validationKeywords.maxProperties', function () { +describe('Schema.validationKeywords.maxProperties', () => { validationTestRunner(maxPropertiesTests, 'object') }) -describe('Schema.validationKeywords.minProperties', function () { +describe('Schema.validationKeywords.minProperties', () => { validationTestRunner(minPropertiesTests, 'object') }) -describe('Schema.validationKeywords.required', function () { +describe('Schema.validationKeywords.required', () => { validationTestRunner(requiredTests, 'object') }) -describe('Schema.validationKeywords.properties', function () { +describe('Schema.validationKeywords.properties', () => { validationTestRunner(propertiesTests, 'object') validationTestRunner(patternPropertiesTests, 'object') validationTestRunner(additionalProperties, 'object') }) -describe('Schema.validationKeywords.dependencies', function () { +describe('Schema.validationKeywords.dependencies', () => { // validationTestRunner(dependenciesTests, 'object') }) // Any Instance Tests -describe('Schema.validationKeywords.enum', function () { +describe('Schema.validationKeywords.enum', () => { validationTestRunner(enumTests) }) -describe('Schema.validationKeywords.type', function () { +describe('Schema.validationKeywords.type', () => { validationTestRunner(typeTests) }) -describe('Schema.validationKeywords.allOf', function () { +describe('Schema.validationKeywords.allOf', () => { validationTestRunner(allOfTests) }) -describe('Schema.validationKeywords.anyOf', function () { - anyOfTests.forEach((suite) => { +describe('Schema.validationKeywords.anyOf', () => { + anyOfTests.forEach(suite => { const Schema = new JSData.Schema(suite.schema) - describe(suite.description, function () { - suite.tests.forEach((test) => { - it(test.description, function () { + describe(suite.description, () => { + suite.tests.forEach(test => { + it(test.description, () => { // let errors = JSData.Schema.validationKeywords.anyOf(test.data, Schema, {}) const errors = Schema.validate(test.data) - assert.equal(test.valid, !errors, errors) + assert.equal(test.valid, !errors, errors?.[0]) }) }) }) }) }) -describe('Schema.validationKeywords.oneOf', function () { +describe('Schema.validationKeywords.oneOf', () => { validationTestRunner(oneOfTests) }) -describe('Schema.validationKeywords.not', function () { +describe('Schema.validationKeywords.not', () => { validationTestRunner(notTests) }) diff --git a/test/unit/utils/areDifferent.test.js b/test/unit/utils/areDifferent.test.ts similarity index 72% rename from test/unit/utils/areDifferent.test.js rename to test/unit/utils/areDifferent.test.ts index 2e1013e6..57e5751a 100644 --- a/test/unit/utils/areDifferent.test.js +++ b/test/unit/utils/areDifferent.test.ts @@ -1,19 +1,20 @@ import { assert, JSData } from '../../_setup' + const utils = JSData.utils -describe('utils.areDifferent', function () { - it('should be a static method', function () { +describe('utils.areDifferent', () => { + it('should be a static method', () => { assert.equal(typeof utils.areDifferent, 'function', 'has the areDifferent method') }) - it('returns false for two different objects', function () { + it('returns false for two different objects', () => { const objA = { name: 'John', age: 30 } const objB = { name: 'John', age: 90 } const result = utils.areDifferent(objA, objB) assert.isTrue(result, 'the two objects are different') }) - it('returns true for two equal objects', function () { + it('returns true for two equal objects', () => { const objA = { name: 'John', age: 90 } const objB = { name: 'John', age: 90 } const result = utils.areDifferent(objA, objB) diff --git a/test/unit/utils/copy.test.js b/test/unit/utils/copy.test.ts similarity index 71% rename from test/unit/utils/copy.test.js rename to test/unit/utils/copy.test.ts index 7d207e90..6b590e04 100644 --- a/test/unit/utils/copy.test.js +++ b/test/unit/utils/copy.test.ts @@ -1,19 +1,20 @@ import { assert, JSData } from '../../_setup' + const utils = JSData.utils -describe('utils.copy', function () { - it('should be a static method', function () { +describe('utils.copy', () => { + it('should be a static method', () => { assert.equal(typeof utils.copy, 'function') assert.equal(typeof utils.plainCopy, 'function', 'has the plainCopy method') }) - it('can do a plain copy', function () { + it('can do a plain copy', () => { const plain = { name: 'John' } const result = utils.plainCopy(plain) assert.notStrictEqual(result, plain) }) - it('can do a plain copy excluding blacklisted properties', function () { + it('can do a plain copy excluding blacklisted properties', () => { const from = { name: 'John', spy: true, parent: { name: 'Mom', $hashKey: 13561 } } const to = {} const result = utils.copy(from, to, undefined, undefined, ['spy', /^\$/], true) @@ -23,22 +24,23 @@ describe('utils.copy', function () { assert.isUndefined(result.parent.$hashKey) }) - it('throws error if from and to are equal', function () { + it('throws error if from and to are equal', () => { const from = { name: 'John' } const to = from assert.throws(() => utils.copy(from, to), Error) }) - it('copy array like object to array', function () { + it('copy array like object to array', () => { const from = { 0: 'John', 1: 'Sara' } const to = ['Sam'] const result = utils.copy(from, to) assert.isArray(result) assert.lengthOf(result, 2) - assert.equal('John', result[0], 'Sara', result[1]) + assert.equal('John', result[0]) + assert.equal('Sara', result[1]) }) - it('copy object to non empty object, the to object properties should be removed', function () { + it('copy object to non empty object, the to object properties should be removed', () => { const from = { name: 'John' } const to = { id: 10 } const result = utils.copy(from, to) @@ -46,7 +48,7 @@ describe('utils.copy', function () { assert.equal('John', result.name) }) - const circ = { name: 'John' } + const circ: any = { name: 'John' } circ.circular = circ const srcObj = { @@ -56,9 +58,9 @@ describe('utils.copy', function () { bool: true }, objects: { - Number: new Number(), // eslint-disable-line - String: new String(), // eslint-disable-line - Boolean: new Boolean(), // eslint-disable-line + Number: Number(), // eslint-disable-line + String: String(), // eslint-disable-line + Boolean: Boolean(), // eslint-disable-line Date: new Date(), Regex: new RegExp('$.*', 'ig') }, @@ -71,31 +73,31 @@ describe('utils.copy', function () { } let objCopy - it('copies an object', function () { + it('copies an object', () => { objCopy = utils.copy(srcObj) assert.deepEqual(objCopy, srcObj) return assert.notStrictEqual(objCopy, srcObj) }) - it('copies nested objects recursively', function () { - return utils.forOwn(objCopy, function (nested, key) { + it('copies nested objects recursively', () => { + return utils.forOwn(objCopy, (nested, key) => { assert.deepEqual(nested, srcObj[key]) return assert.notStrictEqual(nested, srcObj[key]) }) }) - it('copies circular references', function () { + it('copies circular references', () => { assert.deepEqual(objCopy.circular, srcObj.circular) assert.notStrictEqual(objCopy.circular, srcObj.circular) }) - it("doesn't copy primitives, since you can't", function () { - return utils.forOwn(objCopy.primitives, function (value, key) { + it("doesn't copy primitives, since you can't", () => { + return utils.forOwn(objCopy.primitives, (value, key) => { return assert.strictEqual(value, srcObj.primitives[key]) }) }) - it('copies arrays recursively', function () { + it('copies arrays recursively', () => { assert.deepEqual(objCopy.structs.arrayOfPrimitives, srcObj.structs.arrayOfPrimitives) assert.notStrictEqual(objCopy.structs.arrayOfPrimitives, srcObj.structs.arrayOfPrimitives) @@ -103,7 +105,7 @@ describe('utils.copy', function () { assert.notStrictEqual(objCopy.structs.arrayOfObjects, srcObj.structs.arrayOfObjects) }) - it("doesn't copy class intances", function () { + it("doesn't copy class intances", () => { return assert.strictEqual(objCopy.structs.instance, srcObj.structs.instance) }) }) diff --git a/test/unit/utils/deepEqual.test.js b/test/unit/utils/deepEqual.test.ts similarity index 88% rename from test/unit/utils/deepEqual.test.js rename to test/unit/utils/deepEqual.test.ts index 660eab66..f01244ef 100644 --- a/test/unit/utils/deepEqual.test.js +++ b/test/unit/utils/deepEqual.test.ts @@ -1,12 +1,13 @@ import { assert, JSData } from '../../_setup' + const utils = JSData.utils -describe('utils.deepEqual', function () { - it('should be a static method', function () { +describe('utils.deepEqual', () => { + it('should be a static method', () => { assert.equal(typeof utils.deepEqual, 'function', 'has the deepEqual method') }) - it('does deep equal comparison', function () { + it('does deep equal comparison', () => { const objA = { name: 'John', age: 90 } const arrA = ['a', 'b', 'c'] const arrB = ['a', 'b', 'c', 'd', 'e'] @@ -23,7 +24,7 @@ describe('utils.deepEqual', function () { assert.isFalse(utils.deepEqual(arrA, arrB), 'arrA does not deep equal arrB') }) - it('compares identical objects', function () { + it('compares identical objects', () => { const objA = { name: 'John', id: 27, diff --git a/test/unit/utils/diffObjects.test.js b/test/unit/utils/diffObjects.test.ts similarity index 79% rename from test/unit/utils/diffObjects.test.js rename to test/unit/utils/diffObjects.test.ts index d65699fa..fe765708 100644 --- a/test/unit/utils/diffObjects.test.js +++ b/test/unit/utils/diffObjects.test.ts @@ -1,12 +1,13 @@ import { assert, JSData } from '../../_setup' + const utils = JSData.utils -describe('utils.diffObjects', function () { - it('should be a static method', function () { +describe('utils.diffObjects', () => { + it('should be a static method', () => { assert.equal(typeof utils.diffObjects, 'function', 'has the diffObjects method') }) - it('returns diff betwen two different objects', function () { + it('returns diff between two different objects', () => { const newObject = { name: 'John', age: 30, friends: 7 } const oldObject = { name: 'John', age: 90, id: 20 } const expected = { @@ -18,7 +19,7 @@ describe('utils.diffObjects', function () { assert.deepEqual(result, expected) }) - it('returns diff betwen two equal objects', function () { + it('returns diff between two equal objects', () => { const oldObject = { name: 'John', age: 90, friends: 7 } const newObject = { name: 'John', age: 90, friends: 7 } const expected = { diff --git a/test/unit/utils/equal.test.js b/test/unit/utils/equal.test.ts similarity index 74% rename from test/unit/utils/equal.test.js rename to test/unit/utils/equal.test.ts index ac112d90..e308081f 100644 --- a/test/unit/utils/equal.test.js +++ b/test/unit/utils/equal.test.ts @@ -1,12 +1,13 @@ import { assert, JSData } from '../../_setup' + const utils = JSData.utils -describe('utils.equal', function () { - it('should be a static method', function () { +describe('utils.equal', () => { + it('should be a static method', () => { assert.equal(typeof utils.equal, 'function', 'has the equal method') }) - it('returns true for equal values', function () { + it('returns true for equal values', () => { const objA = { name: 'John', age: 90 } assert.isTrue(utils.equal(1, '1'), '1 equals "1"') assert.isTrue(utils.equal(2, 2), '2 equals 2') @@ -14,7 +15,7 @@ describe('utils.equal', function () { assert.isTrue(utils.equal(objA, objA), objA + ' equals ' + objA) }) - it('returns false for two different values', function () { + it('returns false for two different values', () => { assert.isFalse(utils.equal(1, 2), '1 does not equal 2') assert.isFalse(utils.equal({}, {}), '{} does not equal {}') }) diff --git a/test/unit/utils/err.test.js b/test/unit/utils/err.test.ts similarity index 79% rename from test/unit/utils/err.test.js rename to test/unit/utils/err.test.ts index 055a5f50..e42f3205 100644 --- a/test/unit/utils/err.test.js +++ b/test/unit/utils/err.test.ts @@ -1,12 +1,13 @@ import { assert, JSData } from '../../_setup' + const utils = JSData.utils -describe('utils.err', function () { - it('should be a static method', function () { +describe('utils.err', () => { + it('should be a static method', () => { assert.equal(typeof utils.err, 'function', 'has the err method') }) - it('returns a wrapped function that will generate an Error for a given domain and target', function () { + it('returns a wrapped function that will generate an Error for a given domain and target', () => { const errorGenerator = utils.err('domain', 'target') const error400 = errorGenerator(400, 'expected type', 'actual type') assert(error400 instanceof Error) diff --git a/test/unit/utils/eventify.test.js b/test/unit/utils/eventify.test.ts similarity index 74% rename from test/unit/utils/eventify.test.js rename to test/unit/utils/eventify.test.ts index f2a686ee..161cf3ff 100644 --- a/test/unit/utils/eventify.test.js +++ b/test/unit/utils/eventify.test.ts @@ -1,13 +1,14 @@ import { assert, JSData, sinon } from '../../_setup' + const utils = JSData.utils -describe('utils.eventify', function () { - it('should be a static method', function () { +describe('utils.eventify', () => { + it('should be a static method', () => { assert.equal(typeof utils.eventify, 'function', 'has the eventify method') }) - it('adds on, off, emit events to the specified target', function () { - const user = { name: 'John' } + it('adds on, off, emit events to the specified target', () => { + const user: any = { name: 'John' } assert.isUndefined(user.on) assert.isUndefined(user.emit) assert.isUndefined(user.off) diff --git a/test/unit/utils/extendUtils.test.js b/test/unit/utils/extendUtils.test.ts similarity index 55% rename from test/unit/utils/extendUtils.test.js rename to test/unit/utils/extendUtils.test.ts index 5028657e..6a5db1fa 100644 --- a/test/unit/utils/extendUtils.test.js +++ b/test/unit/utils/extendUtils.test.ts @@ -1,29 +1,30 @@ import { assert, JSData } from '../../_setup' + const utils = JSData.utils -describe('utils.fillIn', function () { - it('should be a static method', function () { +describe('utils.fillIn', () => { + it('should be a static method', () => { assert.equal(typeof utils.fillIn, 'function', 'has the fillIn method') }) - it('Copy properties from `source` that are missing from `dest`', function () { - const dest = { name: 'John', age: 90, friend: { name: 'Sara' } } + it('Copy properties from `source` that are missing from `dest`', () => { + const dest = { name: 'John', age: 90, friend: { name: 'Sara' } as any } const src = { name: 'John', age: 0, spy: true, friend: { name: 'Sara', age: 20 } } - const expected = { name: 'John', age: 90, spy: true, friend: { name: 'Sara' } } + const expected = { name: 'John', age: 90, spy: true, friend: { name: 'Sara' } as any } utils.fillIn(dest, src) - assert.equal(expected.age, dest.age, 'age already set on dest is not overriden') + assert.equal(expected.age, dest.age, 'age already set on dest is not overridden') assert.isUndefined(expected.friend.age, 'missing nested property is not filled in') assert.deepEqual(expected, dest, 'sorce own properties shallow copied into dest only if missing') }) }) -describe('utils.deepFillIn', function () { - it('should be a static method', function () { +describe('utils.deepFillIn', () => { + it('should be a static method', () => { assert.equal(typeof utils.deepFillIn, 'function', 'has the deepFillIn method') }) - it('Recursivly copies properties from `source` that are missing on `dest`', function () { + it('Recursivly copies properties from `source` that are missing on `dest`', () => { const dest = { name: 'John', age: 90, friend: { name: 'Sara' } } const src = { name: 'John', age: 0, spy: true, friend: { name: 'Sara', age: 20 } } const expected = { name: 'John', age: 90, spy: true, friend: { name: 'Sara', age: 20 } } @@ -37,12 +38,12 @@ describe('utils.deepFillIn', function () { }) }) -describe('utils.deepMixIn', function () { - it('should be a static method', function () { +describe('utils.deepMixIn', () => { + it('should be a static method', () => { assert.equal(typeof utils.deepMixIn, 'function', 'has the deepMixIn decorator') }) - it('Recursively shallow copies properties from `source` to `dest`', function () { + it('Recursively shallow copies properties from `source` to `dest`', () => { const dest = { name: 'John', age: 90, friend: { name: 'Sara' } } const src = { name: 'John', age: 0, spy: true, friend: { name: 'Sara', age: 20 } } const expected = { name: 'John', age: 0, spy: true, friend: { name: 'Sara', age: 20 } } @@ -56,44 +57,12 @@ describe('utils.deepMixIn', function () { }) }) -describe('utils.extend', function () { - it('should be a static method', function () { - assert.equal(typeof utils.extend, 'function', 'has the extend method') - }) - - it('extend can be used to make a subclass', function () { - function Foo (name) { - this.name = name - this.whatsMyName = () => { - return this.name - } - } - Foo.extend = utils.extend - const Bar = Foo.extend({ bar: 'bar' }, { onlyOnBar: true }) - const barInstance = new Bar('FooBar') - const fooInstance = new Foo('Foo') - assert.isFunction(Bar, 'Bar is a function') - - assert.instanceOf(fooInstance, Foo, 'fooInstance is instance of Foo') - assert.notInstanceOf(fooInstance, Bar, 'fooInstance is not an instance of Bar') - assert.equal(Foo, utils.getSuper(barInstance, false), 'barInstance inherits from Foo') - - assert.instanceOf(barInstance, Bar, 'barInstance is instance of Bar') - assert.instanceOf(barInstance, Foo, 'barInstance is instance of Foo') - - assert.equal('FooBar', barInstance.name, 'Bar inherits properties from Foo') - assert.equal('FooBar', barInstance.whatsMyName(), 'Bar inherits methods from Foo') - - assert(typeof Foo.onlyOnBar === 'undefined' && typeof Bar.onlyOnBar === 'boolean', 'Bar contains properties not on Super (Foo)') - }) -}) - -describe('utils.getSuper', function () { - it('should be a static method', function () { +describe('utils.getSuper', () => { + it('should be a static method', () => { assert.equal(typeof utils.getSuper, 'function', 'has the getSuper method') }) - it('getSuper returns base class with ES2015 classes', function () { + it('getSuper returns base class with ES2015 classes', () => { class Foo {} class Bar extends Foo {} @@ -108,41 +77,24 @@ describe('utils.getSuper', function () { } }) - it('getSuper returns base class with utils.extend', function () { - function Foo () {} - Foo.extend = utils.extend - const Bar = Foo.extend() - const barInstance = new Bar() - assert.strictEqual(Foo, utils.getSuper(barInstance, false), 'barInstance inherited from Foo') - }) -}) - -describe('utils.classCallCheck', function () { - it('should be a static method', function () { - assert.equal(typeof utils.classCallCheck, 'function', 'has the classCallCheck method') - }) - - it('ensure instance is of a specified type', function () { - class Foo { } + it('getSuper returns base class with utils.extend', () => { + class Foo {} - class Bar extends Foo { } + class Bar extends Foo {} const barInstance = new Bar() - - utils.classCallCheck(barInstance, Foo) - utils.classCallCheck(barInstance, Bar) - assert.throws(() => utils.classCallCheck(barInstance, String), Error) + assert.strictEqual(Foo, utils.getSuper(barInstance, false), 'barInstance inherited from Foo') }) }) -describe('utils.addHiddenPropsToTarget', function () { - it('should be a static method', function () { +describe('utils.addHiddenPropsToTarget', () => { + it('should be a static method', () => { assert.equal(typeof utils.addHiddenPropsToTarget, 'function', 'has the addHiddenPropsToTarget method') }) - it('adds hidden properties to target', function () { + it('adds hidden properties to target', () => { const target = { name: 'John' } utils.addHiddenPropsToTarget(target, { age: 103 }) - assert.isFalse(Object.propertyIsEnumerable.call(target, 'age'), 'age on target is not enumerable.') + assert.isFalse(target.propertyIsEnumerable('age'), 'age on target is not enumerable.') }) }) diff --git a/test/unit/utils/forEachRelation.test.js b/test/unit/utils/forEachRelation.test.ts similarity index 83% rename from test/unit/utils/forEachRelation.test.js rename to test/unit/utils/forEachRelation.test.ts index 2cd5f61c..6cfdbc21 100644 --- a/test/unit/utils/forEachRelation.test.js +++ b/test/unit/utils/forEachRelation.test.ts @@ -1,8 +1,9 @@ import { assert, JSData } from '../../_setup' + const utils = JSData.utils -describe('utils.forEachRelation', function () { - it('should be a static method', function () { +describe('utils.forEachRelation', () => { + it('should be a static method', () => { assert.equal(typeof utils.forEachRelation, 'function', 'has the forEachRelation method') }) @@ -18,7 +19,7 @@ describe('utils.forEachRelation', function () { it('executes given fn for specific distinct relations defined in the given mapper', function () { const userMapper = this.User - const expectedRelations = userMapper.relationList.filter((x) => x.relation === 'comment') + const expectedRelations = userMapper.relationList.filter(x => x.relation === 'comment') const actualRelations = [] utils.forEachRelation(userMapper, { with: ['comment', 'comment.user', 'notexist'] }, (def, item) => { diff --git a/test/unit/utils/forOwn.test.js b/test/unit/utils/forOwn.test.ts similarity index 66% rename from test/unit/utils/forOwn.test.js rename to test/unit/utils/forOwn.test.ts index 8da981fd..6cce6012 100644 --- a/test/unit/utils/forOwn.test.js +++ b/test/unit/utils/forOwn.test.ts @@ -1,17 +1,18 @@ import { assert, JSData } from '../../_setup' + const utils = JSData.utils -describe('utils.forOwn', function () { - it('should be a static method', function () { +describe('utils.forOwn', () => { + it('should be a static method', () => { assert.equal(typeof utils.forOwn, 'function', 'has the forOwn method') }) - it('executes a given callback for each enumerable property of an object', function () { - const user = { name: 'John', age: 20, log: () => { } } + it('executes a given callback for each enumerable property of an object', () => { + const user = { name: 'John', age: 20, log: () => {} } const expectedProps = ['name', 'age', 'log'] const actualProps = [] utils.addHiddenPropsToTarget(user, { spy: true }) - utils.forOwn(user, function (value, key) { + utils.forOwn(user, (value, key) => { actualProps.push(key) }) assert.deepEqual(expectedProps, actualProps) diff --git a/test/unit/utils/index.test.js b/test/unit/utils/index.test.js deleted file mode 100644 index 192361b5..00000000 --- a/test/unit/utils/index.test.js +++ /dev/null @@ -1,144 +0,0 @@ -import { assert, JSData } from '../../_setup' -const utils = JSData.utils - -describe('utils', function () { - it('has the right exports', function () { - assert(utils) - }) -}) -describe('utils.get', function () { - it('should be a static method', function () { - assert.equal(typeof utils.get, 'function', 'has the [\'get\'] method') - }) - - it('returns a given property by name or path', function () { - const john = { name: 'John', age: 20, friend: { name: 'Sara' } } - assert.equal(john.name, utils.get(john, 'name')) - assert.equal(john.friend.name, utils.get(john, 'friend.name')) - assert.equal(undefined, utils.get(john, ''), 'null prop name returns undefined') - }) -}) - -describe('utils.findIndex', function () { - it('should be a static method', function () { - assert.equal(typeof utils.findIndex, 'function', 'has the findIndex method') - }) - - it('can find the last index based on given function', function () { - const john = { name: 'John', age: 20, spy: true } - const sara = { name: 'Sara', age: 25, spy: false } - const dan = { name: 'Dan', age: 20, spy: false } - const users = [john, sara, dan] - - assert.equal(1, utils.findIndex(users, (user) => user.age === 25)) - assert.equal(2, utils.findIndex(users, (user) => user.age > 19)) - assert.equal(2, utils.findIndex(users, (user) => !user.spy)) - assert.equal(0, utils.findIndex(users, (user) => user.name === 'John')) - assert.equal(-1, utils.findIndex(users, (user) => user.name === 'Jimmy')) - assert.equal(-1, utils.findIndex(null, (user) => user.name === 'Jimmy')) - }) -}) - -describe('utils.remove', function () { - it('should be a static method', function () { - assert.equal(typeof utils.remove, 'function', 'has the remove method') - }) - - it('can remove the last item found from an array based on a given function', function () { - const colors = ['red', 'green', 'yellow', 'red'] - assert.lengthOf(colors, 4) - utils.remove(null) - utils.remove(colors, (color) => color === 'red') - assert.lengthOf(colors, 3) - assert.equal('yellow', colors[2]) - utils.remove(colors, (color) => color === 'green') - utils.remove(colors, (color) => color === 'green') - assert.lengthOf(colors, 2) - assert.equal('yellow', colors[1]) - }) -}) - -describe('utils.noDupeAdd', function () { - it('should be a static method', function () { - assert.equal(typeof utils.noDupeAdd, 'function', 'has the noDupeAdd method') - }) - - it('only adds distinct items to array based on given checker function', function () { - const colors = ['red', 'green', 'yellow'] - assert.lengthOf(colors, 3) - utils.noDupeAdd(null) - utils.noDupeAdd(colors, 'red', (color) => color === 'red') - assert.lengthOf(colors, 3, "didn't add red because it already exists") - utils.noDupeAdd(colors, 'blue', (color) => color === 'blue') - assert.equal('blue', colors[3], 'added blue to end of array') - assert.lengthOf(colors, 4, 'added blue to array') - }) -}) -describe('utils.get', function () { - it('should be a static method', function () { - assert.equal(typeof utils.get, 'function', 'has the [\'get\'] method') - }) - - it('returns a given property by name or path', function () { - const john = { name: 'John', age: 20, friend: { name: 'Sara' } } - assert.equal(john.name, utils.get(john, 'name')) - assert.equal(john.friend.name, utils.get(john, 'friend.name')) - assert.equal(undefined, utils.get(john, ''), 'null prop name returns undefined') - }) -}) - -describe('utils.findIndex', function () { - it('should be a static method', function () { - assert.equal(typeof utils.findIndex, 'function', 'has the findIndex method') - }) - - it('can find the last index based on given function', function () { - const john = { name: 'John', age: 20, spy: true } - const sara = { name: 'Sara', age: 25, spy: false } - const dan = { name: 'Dan', age: 20, spy: false } - const users = [john, sara, dan] - - assert.equal(1, utils.findIndex(users, (user) => user.age === 25)) - assert.equal(2, utils.findIndex(users, (user) => user.age > 19)) - assert.equal(2, utils.findIndex(users, (user) => !user.spy)) - assert.equal(0, utils.findIndex(users, (user) => user.name === 'John')) - assert.equal(-1, utils.findIndex(users, (user) => user.name === 'Jimmy')) - assert.equal(-1, utils.findIndex(null, (user) => user.name === 'Jimmy')) - }) -}) - -describe('utils.remove', function () { - it('should be a static method', function () { - assert.equal(typeof utils.remove, 'function', 'has the remove method') - }) - - it('can remove the last item found from an array based on a given function', function () { - const colors = ['red', 'green', 'yellow', 'red'] - assert.lengthOf(colors, 4) - utils.remove(null) - utils.remove(colors, (color) => color === 'red') - assert.lengthOf(colors, 3) - assert.equal('yellow', colors[2]) - utils.remove(colors, (color) => color === 'green') - utils.remove(colors, (color) => color === 'green') - assert.lengthOf(colors, 2) - assert.equal('yellow', colors[1]) - }) -}) - -describe('utils.noDupeAdd', function () { - it('should be a static method', function () { - assert.equal(typeof utils.noDupeAdd, 'function', 'has the noDupeAdd method') - }) - - it('only adds distinct items to array based on given checker function', function () { - const colors = ['red', 'green', 'yellow'] - assert.lengthOf(colors, 3) - utils.noDupeAdd(null) - utils.noDupeAdd(colors, 'red', (color) => color === 'red') - assert.lengthOf(colors, 3, "didn't add red because it already exists") - utils.noDupeAdd(colors, 'blue', (color) => color === 'blue') - assert.equal('blue', colors[3], 'added blue to end of array') - assert.lengthOf(colors, 4, 'added blue to array') - }) -}) diff --git a/test/unit/utils/index.test.ts b/test/unit/utils/index.test.ts new file mode 100644 index 00000000..67bfabc8 --- /dev/null +++ b/test/unit/utils/index.test.ts @@ -0,0 +1,196 @@ +import { assert, JSData } from '../../_setup' + +const utils = JSData.utils + +describe('utils', () => { + it('has the right exports', () => { + assert(utils) + }) +}) +describe('utils.get', () => { + it('should be a static method', () => { + assert.equal(typeof utils.get, 'function', "has the ['get'] method") + }) + + it('returns a given property by name or path', () => { + const john = { name: 'John', age: 20, friend: { name: 'Sara' } } + assert.equal(john.name, utils.get(john, 'name')) + assert.equal(john.friend.name, utils.get(john, 'friend.name')) + assert.equal(undefined, utils.get(john, ''), 'null prop name returns undefined') + }) + it('returns a given property by callback', function () { + const john = { name: 'John', age: 20, friend: { name: 'Sara' } } + const callback = (prop) => { + return john[prop] + } + assert.equal(john.name, utils.get('name', callback)) + }) +}) + +describe('utils.findIndex', () => { + it('should be a static method', () => { + assert.equal(typeof utils.findIndex, 'function', 'has the findIndex method') + }) + + it('can find the last index based on given function', () => { + const john = { name: 'John', age: 20, spy: true } + const sara = { name: 'Sara', age: 25, spy: false } + const dan = { name: 'Dan', age: 20, spy: false } + const users = [john, sara, dan] + + assert.equal( + 1, + utils.findIndex(users, user => user.age === 25) + ) + assert.equal( + 2, + utils.findIndex(users, user => user.age > 19) + ) + assert.equal( + 2, + utils.findIndex(users, user => !user.spy) + ) + assert.equal( + 0, + utils.findIndex(users, user => user.name === 'John') + ) + assert.equal( + -1, + utils.findIndex(users, user => user.name === 'Jimmy') + ) + assert.equal( + -1, + utils.findIndex(null, user => user.name === 'Jimmy') + ) + }) +}) + +describe('utils.remove', () => { + it('should be a static method', () => { + assert.equal(typeof utils.remove, 'function', 'has the remove method') + }) + + it('can remove the last item found from an array based on a given function', () => { + const colors = ['red', 'green', 'yellow', 'red'] + assert.lengthOf(colors, 4) + utils.remove(null) + utils.remove(colors, color => color === 'red') + assert.lengthOf(colors, 3) + assert.equal('yellow', colors[2]) + utils.remove(colors, color => color === 'green') + utils.remove(colors, color => color === 'green') + assert.lengthOf(colors, 2) + assert.equal('yellow', colors[1]) + }) +}) + +describe('utils.noDupeAdd', () => { + it('should be a static method', () => { + assert.equal(typeof utils.noDupeAdd, 'function', 'has the noDupeAdd method') + }) + + it('only adds distinct items to array based on given checker function', () => { + const colors = ['red', 'green', 'yellow'] + assert.lengthOf(colors, 3) + utils.noDupeAdd(null) + utils.noDupeAdd(colors, 'red', color => color === 'red') + assert.lengthOf(colors, 3, "didn't add red because it already exists") + utils.noDupeAdd(colors, 'blue', color => color === 'blue') + assert.equal('blue', colors[3], 'added blue to end of array') + assert.lengthOf(colors, 4, 'added blue to array') + }) +}) +describe('utils.get', () => { + it('should be a static method', () => { + assert.equal(typeof utils.get, 'function', "has the ['get'] method") + }) + + it('returns a given property by name or path', () => { + const john = { name: 'John', age: 20, friend: { name: 'Sara' } } + assert.equal(john.name, utils.get(john, 'name')) + assert.equal(john.friend.name, utils.get(john, 'friend.name')) + assert.equal(undefined, utils.get(john, ''), 'null prop name returns undefined') + }) +}) + +describe('utils.findIndex', () => { + it('should be a static method', () => { + assert.equal(typeof utils.findIndex, 'function', 'has the findIndex method') + }) + + it('can find the last index based on given function', () => { + const john = { name: 'John', age: 20, spy: true } + const sara = { name: 'Sara', age: 25, spy: false } + const dan = { name: 'Dan', age: 20, spy: false } + const users = [john, sara, dan] + + assert.equal( + 1, + utils.findIndex(users, user => user.age === 25) + ) + assert.equal( + 2, + utils.findIndex(users, user => user.age > 19) + ) + assert.equal( + 2, + utils.findIndex(users, user => !user.spy) + ) + assert.equal( + 0, + utils.findIndex(users, user => user.name === 'John') + ) + assert.equal( + -1, + utils.findIndex(users, user => user.name === 'Jimmy') + ) + assert.equal( + -1, + utils.findIndex(null, user => user.name === 'Jimmy') + ) + }) +}) + +describe('utils.remove', () => { + it('should be a static method', () => { + assert.equal(typeof utils.remove, 'function', 'has the remove method') + }) + + it('can remove the last item found from an array based on a given function', () => { + const colors = ['red', 'green', 'yellow', 'red'] + assert.lengthOf(colors, 4) + utils.remove(null) + utils.remove(colors, color => color === 'red') + assert.lengthOf(colors, 3) + assert.equal('yellow', colors[2]) + utils.remove(colors, color => color === 'green') + utils.remove(colors, color => color === 'green') + assert.lengthOf(colors, 2) + assert.equal('yellow', colors[1]) + }) +}) + +describe('utils.noDupeAdd', () => { + it('should be a static method', () => { + assert.equal(typeof utils.noDupeAdd, 'function', 'has the noDupeAdd method') + }) + + it('only adds distinct items to array based on given checker function', () => { + const colors = ['red', 'green', 'yellow'] + assert.lengthOf(colors, 3) + utils.noDupeAdd(null) + utils.noDupeAdd(colors, 'red', color => color === 'red') + assert.lengthOf(colors, 3, "didn't add red because it already exists") + utils.noDupeAdd(colors, 'blue', color => color === 'blue') + assert.equal('blue', colors[3], 'added blue to end of array') + assert.lengthOf(colors, 4, 'added blue to array') + }) +}) +describe('utils.getDefaultLocale', function () { + it('should be a static method', function () { + assert.equal(typeof utils.getDefaultLocale, 'function', 'has the getDefaultLocale method') + }) + it('Default locale should be "en"', function () { + assert.equal('en', utils.getDefaultLocale()) + }) +}) diff --git a/test/unit/utils/intersection.test.js b/test/unit/utils/intersection.test.ts similarity index 84% rename from test/unit/utils/intersection.test.js rename to test/unit/utils/intersection.test.ts index aa6c411d..96923965 100644 --- a/test/unit/utils/intersection.test.js +++ b/test/unit/utils/intersection.test.ts @@ -1,12 +1,13 @@ import { assert, JSData } from '../../_setup' + const utils = JSData.utils -describe('utils.intersection', function () { - it('should be a static method', function () { +describe('utils.intersection', () => { + it('should be a static method', () => { assert.equal(typeof utils.isArray, 'function', 'has the intersection method') }) - it('intersects two arrays', function () { + it('intersects two arrays', () => { const arrA = ['green', 'red', 'blue', 'red'] const arrB = ['green', 'yellow', 'red'] const result = utils.intersection(arrA, arrB) @@ -14,7 +15,7 @@ describe('utils.intersection', function () { assert.includeMembers(result, ['green', 'red']) }) - it('intersect returns empty array when argument is undefined', function () { + it('intersect returns empty array when argument is undefined', () => { const arrA = ['green', 'red', 'blue'] const arrB = undefined const result = utils.intersection(arrA, arrB) diff --git a/test/unit/utils/isType.test.js b/test/unit/utils/isType.test.js deleted file mode 100644 index 9ce18f68..00000000 --- a/test/unit/utils/isType.test.js +++ /dev/null @@ -1,250 +0,0 @@ -import { assert, JSData } from '../../_setup' -const utils = JSData.utils - -describe('utils.isArray', function () { - it('should be a static method', function () { - assert.equal(typeof utils.isArray, 'function', 'has the isArray method') - }) - - it('isArray returns true for arrays', function () { - const arrays = [ - [1, 2], - [{}, {}], - new Array() // eslint-disable-line no-array-constructor - ] - arrays.forEach((arr) => { - assert.isArray(arr, arr + 'should be an array') - assert.isTrue(utils.isArray(arr)) - }) - }) - - it('isArray returns false for non arrays', function () { - const nonArrays = [ - 1, - 'string', - { 0: 0, 1: 1 } - ] - nonArrays.forEach((obj) => { - assert.isNotArray(obj, obj + 'should not be an array') - assert.isNotTrue(utils.isArray(obj)) - }) - }) -}) - -describe('utils.isBoolean', function () { - it('should be a static method', function () { - assert.equal(typeof utils.isBoolean, 'function', 'has the isBoolean method') - }) - - it('isBoolean returns true for boolean values', function () { - const trueVals = [true, false] - trueVals.forEach((val) => { - assert.isBoolean(val, val + ' is a boolean') - assert.isTrue(utils.isBoolean(val)) - }) - }) - - it('isBoolean returns false for non boolean values', function () { - const falseVals = ['123', 'true', 'false', 0, {}] - falseVals.forEach((val) => { - assert.isNotBoolean(val, val + ' is not a boolean') - assert.isNotTrue(utils.isBoolean(val)) - }) - }) -}) - -describe('utils.isFunction', function () { - it('should be a static method', function () { - assert.equal(typeof utils.isFunction, 'function', 'has the isFunction method') - }) - - it('isFunction returns true for function values', function () { - const trueVals = [function () { }, () => { }, console.log] - trueVals.forEach((val) => { - assert.isFunction(val, val + ' is a function') - assert.isTrue(utils.isFunction(val)) - }) - }) - - it('isFunction returns false for non function values', function () { - const falseVals = ['123', 'true', 'false', 0, {}] - falseVals.forEach((val) => { - assert.isNotFunction(val, val + ' is not be a function') - assert.isNotTrue(utils.isFunction(val)) - }) - }) -}) - -describe('utils.isInteger', function () { - it('should be a static method', function () { - assert.equal(typeof utils.isInteger, 'function', 'has the isInteger method') - }) - - it('isInteger returns true for function values', function () { - const trueVals = [1, 2, 5 / 1, -5, 0] - trueVals.forEach((val) => { - assert.isTrue(utils.isInteger(val), val + ' is an integer') - }) - }) - - it('isInteger returns false for non function values', function () { - const falseVals = ['1', 1.25, -1.3, 2 / 3, Infinity] - falseVals.forEach((val) => { - assert.isNotTrue(utils.isInteger(val), val + ' is not an integer') - }) - }) -}) - -describe('utils.isNull', function () { - it('should be a static method', function () { - assert.equal(typeof utils.isNull, 'function', 'has the isNull method') - }) - - it('isNull returns true for null values', function () { - const trueVals = [null, (() => { return null })()] - trueVals.forEach((val) => { - assert.isNull(val, val + ' is null') - assert.isTrue(utils.isNull(val), val + ' return null') - }) - }) - - it('isNull returns false for non null values', function () { - const falseVals = [0, 1, undefined, 'null', () => { }] - falseVals.forEach((val) => { - assert.isNotNull(val, val + ' is not null') - assert.isNotTrue(utils.isNull(val)) - }) - }) -}) - -describe('utils.isNumber', function () { - it('should be a static method', function () { - assert.equal(typeof utils.isNumber, 'function', 'has the isNumber method') - }) - - it('isNumber returns true for number values', function () { - const trueVals = [1, 1.45, -1.56, Infinity, new Number(100)] // eslint-disable-line - trueVals.forEach((val) => { - assert.isNumber(val, val + ' is a number') - assert.isTrue(utils.isNumber(val)) - }) - }) - - it('isNumber returns false for non function values', function () { - const falseVals = ['1', 'string', undefined, null, false] - falseVals.forEach((val) => { - assert.isNotNumber(val, val + ' is not a number') - assert.isNotTrue(utils.isNumber(val)) - }) - }) -}) - -describe('utils.isObject', function () { - it('should be a static method', function () { - assert.equal(typeof utils.isObject, 'function', 'has the isObject method') - }) - - it('isObject returns true for object values', function () { - const trueVals = [new Object(), {}] // eslint-disable-line - trueVals.forEach((val) => { - assert.isObject(val, val + ' is an object') - assert.isTrue(utils.isObject(val)) - }) - }) - - it('isObject returns false for non object values', function () { - const falseVals = [() => { }, 'string', 1, new String()] // eslint-disable-line - falseVals.forEach((val) => { - assert.isNotObject(val, val + ' is not an object') - assert.isNotTrue(utils.isObject(val)) - }) - }) -}) - -describe('utils.isRegExp', function () { - it('should be a static method', function () { - assert.equal(typeof utils.isRegExp, 'function', 'has the isFunction method') - }) - - it('isRegExp returns true for regex values', function () { - const trueVals = [/^\$.+$/ig, new RegExp('^\\$.+$', 'ig')] - trueVals.forEach((val) => { - assert.typeOf(val, 'regexp', val + ' is a regular expression') - assert.isTrue(utils.isRegExp(val)) - }) - }) - - it('isRegExp returns false for non regex values', function () { - const falseVals = ['', 'not-a-regex', 12, {}, () => { }] - falseVals.forEach((val) => { - assert.notTypeOf(val, 'regexp', val + ' is not a regular expression') - assert.isNotTrue(utils.isRegExp(val)) - }) - }) -}) - -describe('utils.isSorN', function () { - it('should be a static method', function () { - assert.equal(typeof utils.isSorN, 'function', 'has the isSorN method') - }) - - it('isSorN returns true for string or number values', function () { - const trueVals = ['', 1.65, -1, 0, 'string', Infinity] - trueVals.forEach((val) => { - assert(utils.isString(val) || utils.isNumber(val), val + ' is a string or number') - assert.isTrue(utils.isSorN(val)) - }) - }) - - it('isSorN returns false for non string nor number values', function () { - const falseVals = [{}, () => { }, []] - falseVals.forEach((val) => { - assert(!utils.isString(val) && !utils.isNumber(val), val + ' is not a string or number') - assert.isNotTrue(utils.isSorN(val)) - }) - }) -}) - -describe('utils.isString', function () { - it('should be a static method', function () { - assert.equal(typeof utils.isObject, 'function', 'has the isString method') - }) - - it('isString returns true for object values', function () { - const trueVals = ['string', new String(''), ''] // eslint-disable-line - trueVals.forEach((val) => { - assert.isString(val, val + ' is an object') - assert.isTrue(utils.isString(val)) - }) - }) - - it('isString returns false for non string values', function () { - const falseVals = [() => { }, 1, 1.2, /regex/, []] // eslint-disable-line - falseVals.forEach((val) => { - assert.isNotObject(val, val + ' is not a string') - assert.isNotTrue(utils.isString(val)) - }) - }) -}) - -describe('utils.isUndefined', function () { - it('should be a static method', function () { - assert.equal(typeof utils.isUndefined, 'function', 'has the isUndefined method') - }) - - it('isUndefined returns true for undefined values', function () { - const trueVals = [undefined, (() => { })()] - trueVals.forEach((val) => { - assert.isUndefined(val, val + ' is undefined') - assert.isTrue(utils.isUndefined(val)) - }) - }) - - it('isUndefined returns false for non undefined values', function () { - const falseVals = ['', {}, () => { }, null] - falseVals.forEach((val) => { - assert.isDefined(val, val + ' is not undefined') - assert.isNotTrue(utils.isUndefined(val)) - }) - }) -}) diff --git a/test/unit/utils/isType.test.ts b/test/unit/utils/isType.test.ts new file mode 100644 index 00000000..bcfd572d --- /dev/null +++ b/test/unit/utils/isType.test.ts @@ -0,0 +1,253 @@ +/* tslint:disable:no-unused-expression */ +import { assert, JSData } from '../../_setup' + +const utils = JSData.utils + +describe('utils.isArray', () => { + it('should be a static method', () => { + assert.equal(typeof utils.isArray, 'function', 'has the isArray method') + }) + + it('isArray returns true for arrays', () => { + const arrays = [ + [1, 2], + [{}, {}], + [] // eslint-disable-line no-array-constructor + ] + arrays.forEach(arr => { + assert.isArray(arr, arr + 'should be an array') + assert.isTrue(utils.isArray(arr)) + }) + }) + + it('isArray returns false for non arrays', () => { + const nonArrays = [1, 'string', { 0: 0, 1: 1 }] + nonArrays.forEach(obj => { + assert.isNotArray(obj, obj + 'should not be an array') + assert.isNotTrue(utils.isArray(obj)) + }) + }) +}) + +describe('utils.isBoolean', () => { + it('should be a static method', () => { + assert.equal(typeof utils.isBoolean, 'function', 'has the isBoolean method') + }) + + it('isBoolean returns true for boolean values', () => { + const trueVals = [true, false] + trueVals.forEach(val => { + assert.isBoolean(val, val + ' is a boolean') + assert.isTrue(utils.isBoolean(val)) + }) + }) + + it('isBoolean returns false for non boolean values', () => { + const falseVals = ['123', 'true', 'false', 0, {}] + falseVals.forEach(val => { + assert.isNotBoolean(val, val + ' is not a boolean') + assert.isNotTrue(utils.isBoolean(val)) + }) + }) +}) + +describe('utils.isFunction', () => { + it('should be a static method', () => { + assert.equal(typeof utils.isFunction, 'function', 'has the isFunction method') + }) + + it('isFunction returns true for function values', () => { + const trueVals = [() => {}, () => {}, console.log] + trueVals.forEach(val => { + assert.isFunction(val, val + ' is a function') + assert.isTrue(utils.isFunction(val)) + }) + }) + + it('isFunction returns false for non function values', () => { + const falseVals = ['123', 'true', 'false', 0, {}] + falseVals.forEach(val => { + assert.isNotFunction(val, val + ' is not be a function') + assert.isNotTrue(utils.isFunction(val)) + }) + }) +}) + +describe('utils.isInteger', () => { + it('should be a static method', () => { + assert.equal(typeof utils.isInteger, 'function', 'has the isInteger method') + }) + + it('isInteger returns true for function values', () => { + const trueVals = [1, 2, 5 / 1, -5, 0] + trueVals.forEach(val => { + assert.isTrue(utils.isInteger(val), val + ' is an integer') + }) + }) + + it('isInteger returns false for non function values', () => { + const falseVals = ['1', 1.25, -1.3, 2 / 3, Infinity] + falseVals.forEach(val => { + assert.isNotTrue(utils.isInteger(val), val + ' is not an integer') + }) + }) +}) + +describe('utils.isNull', () => { + it('should be a static method', () => { + assert.equal(typeof utils.isNull, 'function', 'has the isNull method') + }) + + it('isNull returns true for null values', () => { + const trueVals = [ + null, + (() => { + return null + })() + ] + trueVals.forEach(val => { + assert.isNull(val, val + ' is null') + assert.isTrue(utils.isNull(val), val + ' return null') + }) + }) + + it('isNull returns false for non null values', () => { + const falseVals = [0, 1, undefined, 'null', void (() => {})] + falseVals.forEach(val => { + assert.isNotNull(val, val + ' is not null') + assert.isNotTrue(utils.isNull(val)) + }) + }) +}) + +describe('utils.isNumber', () => { + it('should be a static method', () => { + assert.equal(typeof utils.isNumber, 'function', 'has the isNumber method') + }) + + it('isNumber returns true for number values', () => { + const trueVals = [1, 1.45, -1.56, Infinity, Number(100)]; // eslint-disable-line + trueVals.forEach(val => { + assert.isNumber(val, val + ' is a number') + assert.isTrue(utils.isNumber(val)) + }) + }) + + it('isNumber returns false for non function values', () => { + const falseVals = ['1', 'string', undefined, null, false] + falseVals.forEach(val => { + assert.isNotNumber(val, val + ' is not a number') + assert.isNotTrue(utils.isNumber(val)) + }) + }) +}) + +describe('utils.isObject', () => { + it('should be a static method', () => { + assert.equal(typeof utils.isObject, 'function', 'has the isObject method') + }) + + it('isObject returns true for object values', () => { + const trueVals = [{}, {}]; // eslint-disable-line + trueVals.forEach(val => { + assert.isObject(val, val + ' is an object') + assert.isTrue(utils.isObject(val)) + }) + }) + + it('isObject returns false for non object values', () => { + const falseVals = [() => {}, 'string', 1, String()]; // eslint-disable-line + falseVals.forEach(val => { + assert.isNotObject(val, val + ' is not an object') + assert.isNotTrue(utils.isObject(val)) + }) + }) +}) + +describe('utils.isRegExp', () => { + it('should be a static method', () => { + assert.equal(typeof utils.isRegExp, 'function', 'has the isFunction method') + }) + + it('isRegExp returns true for regex values', () => { + const trueVals = [/^\$.+$/gi, new RegExp('^\\$.+$', 'ig')] + trueVals.forEach(val => { + assert.typeOf(val, 'regexp', val + ' is a regular expression') + assert.isTrue(utils.isRegExp(val)) + }) + }) + + it('isRegExp returns false for non regex values', () => { + const falseVals = ['', 'not-a-regex', 12, {}, () => {}] + falseVals.forEach(val => { + assert.notTypeOf(val, 'regexp', val + ' is not a regular expression') + assert.isNotTrue(utils.isRegExp(val)) + }) + }) +}) + +describe('utils.isSorN', () => { + it('should be a static method', () => { + assert.equal(typeof utils.isSorN, 'function', 'has the isSorN method') + }) + + it('isSorN returns true for string or number values', () => { + const trueVals = ['', 1.65, -1, 0, 'string', Infinity] + trueVals.forEach(val => { + assert(utils.isString(val) || utils.isNumber(val), val + ' is a string or number') + assert.isTrue(utils.isSorN(val)) + }) + }) + + it('isSorN returns false for non string nor number values', () => { + const falseVals = [{}, () => {}, []] + falseVals.forEach(val => { + assert(!utils.isString(val) && !utils.isNumber(val), val + ' is not a string or number') + assert.isNotTrue(utils.isSorN(val)) + }) + }) +}) + +describe('utils.isString', () => { + it('should be a static method', () => { + assert.equal(typeof utils.isObject, 'function', 'has the isString method') + }) + + it('isString returns true for object values', () => { + const trueVals = ['string', String(''), '']; // eslint-disable-line + trueVals.forEach(val => { + assert.isString(val, val + ' is an object') + assert.isTrue(utils.isString(val)) + }) + }) + + it('isString returns false for non string values', () => { + const falseVals = [() => {}, 1, 1.2, /regex/, []]; // eslint-disable-line + falseVals.forEach(val => { + assert.isNotObject(val, val + ' is not a string') + assert.isNotTrue(utils.isString(val)) + }) + }) +}) + +describe('utils.isUndefined', () => { + it('should be a static method', () => { + assert.equal(typeof utils.isUndefined, 'function', 'has the isUndefined method') + }) + + it('isUndefined returns true for undefined values', () => { + const trueVals = [undefined, void (() => {})] + trueVals.forEach(val => { + assert.isUndefined(val, val + ' is undefined') + assert.isTrue(utils.isUndefined(val)) + }) + }) + + it('isUndefined returns false for non undefined values', () => { + const falseVals = ['', {}, () => {}, null] + falseVals.forEach(val => { + assert.isDefined(val, val + ' is not undefined') + assert.isNotTrue(utils.isUndefined(val)) + }) + }) +}) diff --git a/test/unit/utils/logify.test.js b/test/unit/utils/logify.test.ts similarity index 68% rename from test/unit/utils/logify.test.js rename to test/unit/utils/logify.test.ts index df192f4f..b2d24999 100644 --- a/test/unit/utils/logify.test.js +++ b/test/unit/utils/logify.test.ts @@ -1,13 +1,14 @@ import { assert, JSData, sinon } from '../../_setup' + const utils = JSData.utils -describe('utils.logify', function () { - it('should be a static method', function () { +describe('utils.logify', () => { + it('should be a static method', () => { assert.equal(typeof utils.logify, 'function', 'has the logify method') }) - it('adds hidden dbg and log methods to target', function () { - const user = { name: 'John' } + it('adds hidden dbg and log methods to target', () => { + const user: any = { name: 'John' } assert.isUndefined(user.dbg) assert.isUndefined(user.log) utils.logify(user) @@ -15,8 +16,8 @@ describe('utils.logify', function () { assert.isDefined(user.log) }) - it('logs message to the console with the specified log level', function () { - const user = { name: 'John' } + it('logs message to the console with the specified log level', () => { + const user: any = { name: 'John' } const infoStub = sinon.stub(console, 'info') const logStub = sinon.stub(console, 'log') utils.logify(user) @@ -28,19 +29,19 @@ describe('utils.logify', function () { logStub.restore() }) - it('logs debug messages only when `this.debug` is true', function () { - const user = { name: 'John' } + it('logs debug messages only when `this.debug` is true', () => { + const user: any = { name: 'John' } const prev = console.debug console.debug = sinon.stub() utils.logify(user) user.dbg('test dbg') user.log('debug') user.log('debug', 'test log debug') - assert(console.debug.notCalled, 'debug was not called') + assert((console.debug as any).notCalled, 'debug was not called') user.debug = true user.dbg('test dbg') user.log('debug', 'test log debug') - assert(console.debug.calledTwice, 'expected one call to console.debug') + assert((console.debug as any).calledTwice, 'expected one call to console.debug') console.debug = prev }) }) diff --git a/test/unit/utils/omit.test.js b/test/unit/utils/omit.test.ts similarity index 72% rename from test/unit/utils/omit.test.js rename to test/unit/utils/omit.test.ts index 85d6a1bb..2d4d7788 100644 --- a/test/unit/utils/omit.test.js +++ b/test/unit/utils/omit.test.ts @@ -1,12 +1,13 @@ import { assert, JSData } from '../../_setup' + const utils = JSData.utils -describe('utils.omit', function () { - it('should be a static method', function () { +describe('utils.omit', () => { + it('should be a static method', () => { assert.equal(typeof utils.omit, 'function', 'has the omit method') }) - it('Clones an object and omits specific properties', function () { + it('Clones an object and omits specific properties', () => { const src = { name: 'John', $hashKey: 1214910 } const actual = utils.omit(src, ['$hashKey']) const expected = { name: 'John' } @@ -14,30 +15,30 @@ describe('utils.omit', function () { }) }) -describe('utils.isBlacklisted', function () { - it('should be a static method', function () { +describe('utils.isBlacklisted', () => { + it('should be a static method', () => { assert.equal(typeof utils.isBlacklisted, 'function', 'has the isBlacklisted method') }) - it('matches a value against an array of strings or regular expressions', function () { + it('matches a value against an array of strings or regular expressions', () => { const valuesTocheck = ['$hashKey', 'id', '_hidden'] const blackList = [/^\$hashKey/g, /^_/g, 'id'] - valuesTocheck.forEach((v) => { + valuesTocheck.forEach(v => { assert(utils.isBlacklisted(v, blackList), `value ${v} found in blacklist ${blackList}`) }) - valuesTocheck.forEach((v) => { + valuesTocheck.forEach(v => { assert.isFalse(utils.isBlacklisted(v, ['hashKey', 'my_id']), `value ${v} not found in blacklist ${blackList}`) }) }) }) -describe('utils.pick', function () { - it('should be a static method', function () { +describe('utils.pick', () => { + it('should be a static method', () => { assert.equal(typeof utils.pick, 'function', 'has the pick method') }) - it('Shallow copies an object, but only include the properties specified', function () { + it('Shallow copies an object, but only include the properties specified', () => { const src = { name: 'John', $hashKey: 1214910 } const actual = utils.pick(src, ['$hashKey']) const expected = { $hashKey: 1214910 } diff --git a/test/unit/utils/promise.test.js b/test/unit/utils/promise.test.js deleted file mode 100644 index ce0fee0f..00000000 --- a/test/unit/utils/promise.test.js +++ /dev/null @@ -1,28 +0,0 @@ -import { assert, JSData, sinon } from '../../_setup' -const utils = JSData.utils - -describe('utils.resolve', function () { - it('should be a static method', function () { - assert.equal(typeof utils.resolve, 'function', 'has the resolve method') - }) - - it('returns a resolved promise with the specified value', function () { - const spy = sinon.spy(utils.Promise, 'resolve') - utils.resolve('test') - assert(spy.withArgs('test').calledOnce) - utils.Promise.resolve.restore() - }) -}) - -describe('utils.reject', function () { - it('should be a static method', function () { - assert.equal(typeof utils.reject, 'function', 'has the reject method') - }) - - it('returns a rejected promise with the specified err', function () { - const spy = sinon.stub(utils.Promise, 'reject') - utils.reject('rejecting for test') - assert(spy.withArgs('rejecting for test').calledOnce) - utils.Promise.reject.restore() - }) -}) diff --git a/test/unit/utils/serialize.test.js b/test/unit/utils/serialize.test.ts similarity index 83% rename from test/unit/utils/serialize.test.js rename to test/unit/utils/serialize.test.ts index ef024913..2555845d 100644 --- a/test/unit/utils/serialize.test.js +++ b/test/unit/utils/serialize.test.ts @@ -1,9 +1,9 @@ - import { assert, JSData } from '../../_setup' + const utils = JSData.utils -describe('utils.toJson', function () { - it('should be a static method', function () { +describe('utils.toJson', () => { + it('should be a static method', () => { assert.equal(typeof utils.toJson, 'function', 'has the toJson method') }) @@ -19,8 +19,8 @@ describe('utils.toJson', function () { }) }) -describe('utils.fromJson', function () { - it('should be a static method', function () { +describe('utils.fromJson', () => { + it('should be a static method', () => { assert.equal(typeof utils.fromJson, 'function', 'has the fromJson method') }) it('can deserialize an object', function () { diff --git a/test/unit/utils/set.test.js b/test/unit/utils/set.test.ts similarity index 67% rename from test/unit/utils/set.test.js rename to test/unit/utils/set.test.ts index 1e0bcb36..f22bbca8 100644 --- a/test/unit/utils/set.test.js +++ b/test/unit/utils/set.test.ts @@ -1,21 +1,22 @@ import { assert, JSData } from '../../_setup' + const utils = JSData.utils -describe('utils.set', function () { - it('should be a static method', function () { +describe('utils.set', () => { + it('should be a static method', () => { assert.equal(typeof utils.set, 'function', 'has the set method') }) - it('can set a value of an object at the provided key or path', function () { - const john = { name: 'John', age: 25, parent: { name: 'Mom', age: 50 } } + it('can set a value of an object at the provided key or path', () => { + const john: any = { name: 'John', age: 25, parent: { name: 'Mom', age: 50 } } utils.set(john, 'spy', true) utils.set(john, 'parent.age', 55) assert.equal(true, john.spy) assert.equal(55, john.parent.age) }) - it('can set a values of an object with a path/value map', function () { - const john = { name: 'John', age: 25, parent: { name: 'Mom', age: 50 } } + it('can set a values of an object with a path/value map', () => { + const john: any = { name: 'John', age: 25, parent: { name: 'Mom', age: 50 } } utils.set(john, { spy: true, parent: { age: 55 }, @@ -27,14 +28,14 @@ describe('utils.set', function () { }) }) -describe('utils.unset', function () { - it('should be a static method', function () { +describe('utils.unset', () => { + it('should be a static method', () => { assert.equal(typeof utils.unset, 'function', 'has the unset method') }) - it('can unSet a value of an object at the provided key or path', function () { + it('can unSet a value of an object at the provided key or path', () => { const john = { name: 'John', age: 25, spy: true, parent: { name: 'Mom', age: 50 } } - utils.unset(john, 'spy', true) + utils.unset(john, 'spy') utils.unset(john, 'parent.age') utils.unset(john, 'parent.notExist') assert.equal(null, john.spy) diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000..1e90e5e6 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es2015", + "sourceMap": true, + "allowJs": true + }, + "exclude": [ + "node_modules" + ], + "include": [ + "src", + "test", + "scripts", + "./rollup.config.js" + ] +} diff --git a/typings.json b/typings.json deleted file mode 100644 index 4440855c..00000000 --- a/typings.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "js-data", - "version": false, - "main": "./dist/js-data.d.ts", - "ambientDependencies": { - "es6-shim": "registry:dt/es6-shim" - } -}