@coderich/autograph 0.10.0 → 0.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/CHANGELOG.md +21 -3
  2. package/index.js +2 -6
  3. package/package.json +4 -4
  4. package/src/.DS_Store +0 -0
  5. package/src/core/EventEmitter.js +2 -4
  6. package/src/core/Resolver.js +43 -60
  7. package/src/core/Schema.js +3 -36
  8. package/src/data/.DS_Store +0 -0
  9. package/src/data/DataLoader.js +71 -32
  10. package/src/data/DataService.js +59 -58
  11. package/src/data/Field.js +71 -121
  12. package/src/data/Model.js +98 -108
  13. package/src/data/Pipeline.js +174 -0
  14. package/src/data/Type.js +19 -74
  15. package/src/driver/MongoDriver.js +21 -19
  16. package/src/graphql/.DS_Store +0 -0
  17. package/src/graphql/ast/Field.js +43 -24
  18. package/src/graphql/ast/Model.js +5 -16
  19. package/src/graphql/ast/Node.js +0 -25
  20. package/src/graphql/ast/Schema.js +107 -111
  21. package/src/graphql/extension/api.js +20 -18
  22. package/src/graphql/extension/framework.js +25 -33
  23. package/src/graphql/extension/type.js +2 -2
  24. package/src/query/Query.js +72 -14
  25. package/src/query/QueryBuilder.js +38 -30
  26. package/src/query/QueryBuilderTransaction.js +3 -3
  27. package/src/query/QueryResolver.js +92 -42
  28. package/src/query/QueryService.js +31 -34
  29. package/src/service/app.service.js +67 -9
  30. package/src/service/event.service.js +5 -79
  31. package/src/service/schema.service.js +5 -3
  32. package/src/core/Rule.js +0 -107
  33. package/src/core/SchemaDecorator.js +0 -46
  34. package/src/core/Transformer.js +0 -68
  35. package/src/data/Memoizer.js +0 -39
  36. package/src/data/ResultSet.js +0 -205
  37. package/src/data/stream/DataHydrator.js +0 -58
  38. package/src/data/stream/ResultSet.js +0 -34
  39. package/src/data/stream/ResultSetItem.js +0 -158
  40. package/src/data/stream/ResultSetItemProxy.js +0 -161
  41. package/src/graphql/ast/SchemaDecorator.js +0 -141
  42. package/src/graphql/directive/authz.directive.js +0 -84
@@ -1,46 +0,0 @@
1
- const Model = require('../data/Model');
2
- const SchemaDecorator = require('../graphql/ast/SchemaDecorator');
3
- const { identifyOnDeletes } = require('../service/schema.service');
4
- const { createSystemEvent } = require('../service/event.service');
5
-
6
- // Export class
7
- module.exports = class extends SchemaDecorator {
8
- constructor(schema, stores) {
9
- super(schema);
10
-
11
- // Create drivers
12
- this.drivers = Object.entries(stores).reduce((prev, [key, value]) => {
13
- const { Driver } = value;
14
-
15
- return Object.assign(prev, {
16
- [key]: {
17
- dao: new Driver(value, this),
18
- idKey: Driver.idKey,
19
- idValue: Driver.idValue,
20
- },
21
- });
22
- }, {});
23
- }
24
-
25
- setup() {
26
- return createSystemEvent('Setup', this, () => {
27
- const entities = this.models.filter(m => m.isEntity());
28
-
29
- // Create model indexes
30
- return Promise.all(entities.map(async (model) => {
31
- const key = model.getKey();
32
- const indexes = model.getIndexes();
33
- const driver = model.getDriver();
34
- if (driver.createCollection) await driver.createCollection(key);
35
- return driver.createIndexes(key, indexes);
36
- }));
37
- });
38
- }
39
-
40
- initialize() {
41
- super.initialize();
42
- this.models = super.getModels().map(model => new Model(this, model, this.drivers[model.getDriverName()]));
43
- this.models.forEach(model => model.referentialIntegrity(identifyOnDeletes(this.models, model)));
44
- return this;
45
- }
46
- };
@@ -1,68 +0,0 @@
1
- const { get, set, uniqWith } = require('lodash');
2
- const { map, serialize, castCmp, hashObject } = require('../service/app.service');
3
-
4
- const instances = {};
5
- let allInstances;
6
-
7
- const jsStringMethods = [
8
- 'charAt', 'charCodeAt', 'codePointAt', 'concat', 'indexOf', 'lastIndexOf', 'localeCompare',
9
- 'normalize', 'padEnd', 'padStart', 'repeat', 'replace', 'search', 'slice', 'split', 'substr', 'substring',
10
- 'toLocaleLowerCase', 'toLocaleUpperCase', 'toLowerCase', 'toString', 'toUpperCase', 'trim', 'trimEnd', 'trimStart', 'raw',
11
- ];
12
-
13
- class Transformer {
14
- constructor(thunk, options = {}) {
15
- const { ignoreNull = true, itemize = true } = (options || {});
16
-
17
- return Object.defineProperty((field, val, query) => {
18
- if (ignoreNull && val == null) return val;
19
- if (ignoreNull && itemize) return map(val, v => thunk(field, v, query));
20
- return thunk(field, val, query);
21
- }, 'type', { value: 'transformer' });
22
- }
23
-
24
- static factory(name, thunk, options = {}) {
25
- return Object.defineProperty(Transformer, name, {
26
- value: (...args) => Object.defineProperty(new Transformer(thunk(...args), options), 'method', { value: name }),
27
- writable: options.writable,
28
- enumerable: options.enumerable,
29
- })[name];
30
- }
31
-
32
- static extend(name, instance) {
33
- const invalidArg = () => { throw new Error('Invalid argument; expected Transformer factory instance'); };
34
- const { method = invalidArg(), type = invalidArg() } = instance;
35
- if (type !== 'transformer' || !Transformer[method]) invalidArg();
36
- return (instances[name] = instance);
37
- }
38
-
39
- static getInstances() {
40
- if (allInstances) return allInstances;
41
- const defaultTransformers = Object.entries(Transformer).map(([name, method]) => ({ name, instance: method() }));
42
- const customTransformers = Object.entries(instances).map(([name, instance]) => ({ name, instance }));
43
- const transformers = defaultTransformers.concat(customTransformers);
44
- allInstances = transformers.reduce((prev, { name, instance }) => Object.assign(prev, { [name]: instance }), {});
45
- return allInstances;
46
- }
47
- }
48
-
49
- // Factory methods
50
- const enumerables = ['toLowerCase', 'toUpperCase', 'trim', 'trimEnd', 'trimStart', 'toString'];
51
- jsStringMethods.forEach(name => Transformer.factory(name, (...args) => (f, v) => String(v)[name](...args), { enumerable: enumerables.indexOf(name) > -1 }));
52
- Transformer.factory('toTitleCase', () => (f, v) => v.replace(/\w\S*/g, w => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()), { enumerable: true });
53
- Transformer.factory('toLocaleTitleCase', (...args) => (f, v) => v.replace(/\w\S*/g, w => w.charAt(0).toLocaleUpperCase(...args) + w.slice(1).toLocaleLowerCase()));
54
- Transformer.factory('toSentenceCase', () => (f, v) => v.charAt(0).toUpperCase() + v.slice(1), { enumerable: true });
55
- Transformer.factory('toLocaleSentenceCase', (...args) => (f, v) => v.charAt(0).toLocaleUpperCase(...args) + v.slice(1));
56
- Transformer.factory('toId', () => (f, v) => f.getModel().idValue(v), { enumerable: true });
57
- Transformer.factory('toArray', () => (f, v) => (Array.isArray(v) ? v : [v]), { itemize: false, enumerable: true });
58
- Transformer.factory('toDate', () => (f, v) => new Date(v), { enumerable: true, writable: true });
59
- Transformer.factory('dedupe', () => (f, a) => uniqWith(a, (b, c) => hashObject(b) === hashObject(c)), { ignoreNull: false, enumerable: true });
60
- Transformer.factory('dedupeBy', key => (f, a) => uniqWith(a, (b, c) => hashObject(b[key]) === hashObject(c[key])), { ignoreNull: false, enumerable: true });
61
- Transformer.factory('timestamp', () => (f, v) => Date.now(), { enumerable: true });
62
- Transformer.factory('first', () => (f, v) => (Array.isArray(v) ? v[0] : v), { enumerable: true });
63
- Transformer.factory('get', path => (f, v) => get(v, path), { enumerable: true });
64
- Transformer.factory('set', path => (f, v) => set({}, path, v), { enumerable: true });
65
- Transformer.factory('cast', type => (f, v) => castCmp(type, v));
66
- Transformer.factory('serialize', () => (f, v) => serialize(f, v));
67
-
68
- module.exports = Transformer;
@@ -1,39 +0,0 @@
1
- /**
2
- * Memoizer.
3
- *
4
- * Keeps a memoized cache of function call results; executing them once and reusing the result.
5
- *
6
- * @param {Object} src - the object|function to memoize
7
- * @param {Array} whitelist - whitelist of src methods to memoize (defaults to enumerable functions)
8
- */
9
- module.exports = class Memoizer {
10
- constructor(src, whitelist = Object.keys(src).filter(k => typeof src[k] === 'function')) {
11
- const cache = {};
12
-
13
- return new Proxy(src, {
14
- // This gets called when accessing properties of an object
15
- get(target, prop, rec) {
16
- const value = Reflect.get(target, prop, rec);
17
-
18
- if (typeof value === 'function') {
19
- if (whitelist.indexOf(prop) === -1) return value.bind(target);
20
-
21
- return (...args) => {
22
- const key = `${prop}:${JSON.stringify(args)}`;
23
- cache[key] = Object.prototype.hasOwnProperty.call(cache, key) ? cache[key] : value.bind(target)(...args);
24
- return cache[key];
25
- };
26
- }
27
-
28
- return value;
29
- },
30
-
31
- // This gets called when src is a function
32
- apply(target, thisArg, args) {
33
- const key = JSON.stringify(args);
34
- cache[key] = Object.prototype.hasOwnProperty.call(cache, key) ? cache[key] : target.call(thisArg, ...args);
35
- return cache[key];
36
- },
37
- });
38
- }
39
- };
@@ -1,205 +0,0 @@
1
- const { get } = require('lodash');
2
- const DataService = require('./DataService');
3
- const { map, ensureArray, keyPaths, mapPromise, toGUID, hashObject } = require('../service/app.service');
4
-
5
- module.exports = class ResultSet {
6
- constructor(query, data, adjustForPagination = true) {
7
- if (data == null) return data;
8
- const { resolver, model, sort, first, after, last, before } = query.toObject();
9
- const fields = model.getFields().filter(f => f.getName() !== 'id');
10
-
11
- const rs = map(data, (doc) => {
12
- if (doc == null || typeof doc !== 'object') return doc;
13
-
14
- //
15
- const cache = new Map();
16
-
17
- const definition = fields.reduce((prev, field) => {
18
- const key = field.getKey();
19
- const name = field.getName();
20
- const $name = `$${name}`;
21
- const value = doc[key];
22
-
23
- // Field attributes
24
- prev[name] = {
25
- get() {
26
- if (cache.has(name)) return cache.get(name);
27
- let $value = field.deserialize(query, value);
28
- $value = $value != null && field.isEmbedded() ? new ResultSet(query.model(field.getModelRef()), $value, false) : $value;
29
- cache.set(name, $value);
30
- return $value;
31
- },
32
- set($value) {
33
- cache.set(name, $value);
34
- },
35
- enumerable: true,
36
- configurable: true, // Allows things like delete
37
- };
38
-
39
- // Hydrated field attributes
40
- prev[`$${name}`] = {
41
- get() {
42
- return (args = {}) => {
43
- // Ensure where clause
44
- args.where = args.where || {};
45
-
46
- // Cache
47
- const cacheKey = `${$name}-${hashObject(args)}`;
48
- if (cache.has(cacheKey)) return cache.get(cacheKey);
49
-
50
- const promise = new Promise((resolve, reject) => {
51
- (() => {
52
- const $value = this[name];
53
-
54
- if (field.isScalar() || field.isEmbedded()) return Promise.resolve($value);
55
-
56
- const modelRef = field.getModelRef();
57
-
58
- if (field.isArray()) {
59
- if (field.isVirtual()) {
60
- args.where[[field.getVirtualField()]] = this.id; // Is where[[field.getVirtualField()]] correct?
61
- return resolver.match(modelRef).merge(args).many();
62
- }
63
-
64
- // Not a "required" query + strip out nulls
65
- args.where.id = $value;
66
- return resolver.match(modelRef).merge(args).many();
67
- }
68
-
69
- if (field.isVirtual()) {
70
- args.where[[field.getVirtualField()]] = this.id;
71
- return resolver.match(modelRef).merge(args).one();
72
- }
73
-
74
- return resolver.match(modelRef).id($value).one({ required: field.isRequired() });
75
- })().then((results) => {
76
- if (results == null) return field.resolve(query, results); // Allow field to determine
77
- return mapPromise(results, result => field.resolve(query, result)).then(() => results); // Resolve the inside fields but still return "results"!!!!
78
- }).then((resolved) => {
79
- resolve(resolved);
80
- }).catch((e) => {
81
- reject(e);
82
- });
83
- });
84
-
85
- cache.set(cacheKey, promise);
86
- return promise;
87
- };
88
- },
89
- enumerable: false,
90
- };
91
-
92
- // Field count (let's assume it's a Connection Type - meaning dont try with anything else)
93
- prev[`$${name}:count`] = {
94
- get() {
95
- return (q = {}) => {
96
- q.where = q.where || {};
97
- if (field.isVirtual()) q.where[field.getVirtualField()] = this.id;
98
- else q.where.id = this[name];
99
- return resolver.match(field.getModelRef()).merge(q).count();
100
- };
101
- },
102
- enumerable: false,
103
- };
104
-
105
- return prev;
106
- }, {
107
- id: {
108
- get() { return doc.id || doc[model.idKey()]; },
109
- set(id) { doc.id = id; }, // Embedded array of documents need to set id
110
- enumerable: true,
111
- },
112
-
113
- $id: {
114
- get() { return toGUID(model.getName(), this.id); },
115
- enumerable: false,
116
- },
117
-
118
- $$cursor: {
119
- get() {
120
- const sortPaths = keyPaths(sort);
121
- const sortValues = sortPaths.reduce((prv, path) => Object.assign(prv, { [path]: get(this, path) }), {});
122
- const sortJSON = JSON.stringify(sortValues);
123
- return Buffer.from(sortJSON).toString('base64');
124
- },
125
- enumerable: false,
126
- },
127
-
128
- $$model: {
129
- value: model,
130
- enumerable: false,
131
- },
132
-
133
- $$isResultSetItem: {
134
- value: true,
135
- enumerable: false,
136
- },
137
-
138
- $$save: {
139
- get() { return input => resolver.match(model).id(this.id).save({ ...this, ...input }); },
140
- enumerable: false,
141
- },
142
-
143
- $$remove: {
144
- get() { return () => resolver.match(model).id(this.id).remove(); },
145
- enumerable: false,
146
- },
147
-
148
- $$delete: {
149
- get() { return () => resolver.match(model).id(this.id).delete(); },
150
- enumerable: false,
151
- },
152
-
153
- toObject: {
154
- get() {
155
- return () => map(this, obj => Object.entries(obj).reduce((prev, [key, value]) => {
156
- if (value === undefined) return prev;
157
- prev[key] = get(value, '$$isResultSet') ? value.toObject() : value;
158
- return prev;
159
- }, {}));
160
- },
161
- enumerable: false,
162
- configurable: true,
163
- },
164
- });
165
-
166
- // Create and return ResultSetItem
167
- return Object.defineProperties({}, definition);
168
- });
169
-
170
- let hasNextPage = false;
171
- let hasPreviousPage = false;
172
- if (adjustForPagination && rs.length) (({ hasPreviousPage, hasNextPage } = DataService.paginateResultSet(rs, first, after, last, before)));
173
-
174
- return Object.defineProperties(rs, {
175
- $$pageInfo: {
176
- get() {
177
- const edges = ensureArray(rs);
178
-
179
- return {
180
- startCursor: get(edges, '0.$$cursor', ''),
181
- endCursor: get(edges, `${edges.length - 1}.$$cursor`, ''),
182
- hasPreviousPage,
183
- hasNextPage,
184
- };
185
- },
186
- enumerable: false,
187
- },
188
- $$isResultSet: {
189
- value: true,
190
- enumerable: false,
191
- },
192
- toObject: {
193
- get() {
194
- return () => map(this, doc => Object.entries(doc).reduce((prev, [key, value]) => {
195
- if (value === undefined) return prev;
196
- prev[key] = get(value, '$$isResultSet') ? value.toObject() : value;
197
- return prev;
198
- }, {}));
199
- },
200
- enumerable: false,
201
- configurable: true,
202
- },
203
- });
204
- }
205
- };
@@ -1,58 +0,0 @@
1
- const { get } = require('lodash');
2
- const Stream = require('stream');
3
- const ResultSet = require('./ResultSet');
4
- const ResultSetItem = require('./ResultSetItemProxy');
5
- const { promiseChain, mapPromise, toKeyObj } = require('../../service/app.service');
6
-
7
- module.exports = class DataHydrator {
8
- constructor(query, data) {
9
- let { select = {} } = query.toObject();
10
- select = toKeyObj(select);
11
- return data instanceof Stream ? DataHydrator.stream(query, data, select) : DataHydrator.process(query, data, select);
12
- }
13
-
14
- static stream(query, stream, select) {
15
- const promises = [];
16
-
17
- return new Promise((resolve, reject) => {
18
- stream.on('data', (data) => {
19
- promises.push(DataHydrator.hydrate(query, data, select));
20
- });
21
-
22
- stream.on('error', reject);
23
-
24
- stream.on('end', () => {
25
- Promise.all(promises).then(results => resolve(new ResultSet(query, results)));
26
- });
27
- });
28
- }
29
-
30
- static process(query, data, select) {
31
- return mapPromise(data, d => DataHydrator.hydrate(query, d, select)).then(results => new ResultSet(query, results));
32
- }
33
-
34
- static hydrate(query, data, select) {
35
- const loopArray = Array.from(new Array(Math.max(0, ...Object.keys(select).map(key => key.split('.').length))));
36
-
37
- return new Promise((resolve, reject) => {
38
- const item = new ResultSetItem(query, data);
39
-
40
- return Promise.all(Object.keys(select).map((path) => {
41
- const arrPath = path.split('.');
42
-
43
- return Promise.all(loopArray.map((el, depth) => {
44
- const arr = arrPath.slice(0, depth);
45
- const $arr = arr.map(ele => `$${ele}`);
46
- const key = arr[depth];
47
-
48
- // id has special handling
49
- if (!key || key === 'id') return Promise.resolve();
50
-
51
- // Resolve all other attributes
52
- get(item, arr.join('.'));
53
- return promiseChain($arr.map($prop => chain => (chain.pop() || item)[$prop]()));
54
- }));
55
- })).then(() => resolve(item)).catch(e => reject(e));
56
- });
57
- }
58
- };
@@ -1,34 +0,0 @@
1
- const { get } = require('lodash');
2
- const DataService = require('../DataService');
3
- const { ensureArray } = require('../../service/app.service');
4
-
5
- module.exports = class ResultSet {
6
- constructor(query, data, adjustForPagination = true) {
7
- if (data == null) return data;
8
- const { first, after, last, before } = query.toObject();
9
-
10
- let hasNextPage = false;
11
- let hasPreviousPage = false;
12
- if (adjustForPagination && data.length) (({ hasPreviousPage, hasNextPage } = DataService.paginateResultSet(data, first, after, last, before)));
13
-
14
- return Object.defineProperties(data, {
15
- $$pageInfo: {
16
- get() {
17
- const edges = ensureArray(data);
18
-
19
- return {
20
- startCursor: get(edges, '0.$$cursor', ''),
21
- endCursor: get(edges, `${edges.length - 1}.$$cursor`, ''),
22
- hasPreviousPage,
23
- hasNextPage,
24
- };
25
- },
26
- enumerable: false,
27
- },
28
- $$isResultSet: {
29
- value: true,
30
- enumerable: false,
31
- },
32
- });
33
- }
34
- };
@@ -1,158 +0,0 @@
1
- const { get } = require('lodash');
2
- const ResultSet = require('./ResultSet');
3
- const { map, keyPaths, mapPromise, toGUID, hashObject } = require('../../service/app.service');
4
-
5
- module.exports = class ResultSetItem {
6
- constructor(query, doc) {
7
- if (doc == null) return doc;
8
-
9
- const cache = new Map();
10
- const { resolver, model, sort } = query.toObject();
11
- const fields = model.getFields().filter(f => f.getName() !== 'id');
12
-
13
- const definition = fields.reduce((prev, field) => {
14
- const name = field.getName();
15
- const $name = `$${name}`;
16
- const value = doc[name];
17
-
18
- // Field attributes
19
- prev[name] = {
20
- get() {
21
- if (cache.has(name)) return cache.get(name);
22
- let $value = field.deserialize(query, value);
23
-
24
- if ($value != null && field.isEmbedded()) {
25
- const newModel = field.getModelRef();
26
- const newQuery = query.model(newModel);
27
- const newFields = newModel.getFields().filter(f => f.getName() !== 'id');
28
- $value = new ResultSet(newQuery, map($value, v => new ResultSetItem(newQuery, v, newFields)), false);
29
- }
30
- cache.set(name, $value);
31
- return $value;
32
- },
33
- set($value) {
34
- cache.set(name, $value);
35
- },
36
- enumerable: true,
37
- configurable: true, // Allows things like delete
38
- };
39
-
40
- // Hydrated field attributes
41
- prev[`$${name}`] = {
42
- get() {
43
- return (args = {}) => {
44
- // Ensure where clause
45
- args.where = args.where || {};
46
-
47
- // Cache
48
- const cacheKey = `${$name}-${hashObject(args)}`;
49
- if (cache.has(cacheKey)) return cache.get(cacheKey);
50
-
51
- const promise = new Promise((resolve, reject) => {
52
- (() => {
53
- const $value = this[name];
54
-
55
- if (field.isScalar() || field.isEmbedded()) return Promise.resolve($value);
56
-
57
- const modelRef = field.getModelRef();
58
-
59
- if (field.isArray()) {
60
- if (field.isVirtual()) {
61
- args.where[[field.getVirtualField()]] = this.id; // Is where[[field.getVirtualField()]] correct?
62
- return resolver.match(modelRef).merge(args).many();
63
- }
64
-
65
- // Not a "required" query + strip out nulls
66
- args.where.id = $value;
67
- return resolver.match(modelRef).merge(args).many();
68
- }
69
-
70
- if (field.isVirtual()) {
71
- args.where[[field.getVirtualField()]] = this.id;
72
- return resolver.match(modelRef).merge(args).one();
73
- }
74
-
75
- return resolver.match(modelRef).id($value).one({ required: field.isRequired() });
76
- })().then((results) => {
77
- if (results == null) return field.resolve(query, results); // Allow field to determine
78
- return mapPromise(results, result => field.resolve(query, result)).then(() => results); // Resolve the inside fields but still return "results"!!!!
79
- }).then((resolved) => {
80
- resolve(resolved);
81
- }).catch((e) => {
82
- reject(e);
83
- });
84
- });
85
-
86
- cache.set(cacheKey, promise);
87
- return promise;
88
- };
89
- },
90
- enumerable: false,
91
- };
92
-
93
- // Field count (let's assume it's a Connection Type - meaning dont try with anything else)
94
- prev[`$${name}:count`] = {
95
- get() {
96
- return (q = {}) => {
97
- q.where = q.where || {};
98
- if (field.isVirtual()) q.where[field.getVirtualField()] = this.id;
99
- else q.where.id = this[name];
100
- return resolver.match(field.getModelRef()).merge(q).count();
101
- };
102
- },
103
- enumerable: false,
104
- };
105
-
106
- return prev;
107
- }, {
108
- id: {
109
- get() { return doc.id || doc[model.idKey()]; },
110
- set(id) { doc.id = id; }, // Embedded array of documents need to set id
111
- enumerable: true,
112
- },
113
-
114
- $id: {
115
- get() { return toGUID(model.getName(), this.id); },
116
- enumerable: false,
117
- },
118
-
119
- $$cursor: {
120
- get() {
121
- const sortPaths = keyPaths(sort);
122
- const sortValues = sortPaths.reduce((prv, path) => Object.assign(prv, { [path]: get(this, path) }), {});
123
- const sortJSON = JSON.stringify(sortValues);
124
- return Buffer.from(sortJSON).toString('base64');
125
- },
126
- enumerable: false,
127
- },
128
-
129
- $$model: {
130
- value: model,
131
- enumerable: false,
132
- },
133
-
134
- $$isResultSetItem: {
135
- value: true,
136
- enumerable: false,
137
- },
138
-
139
- $$save: {
140
- get() { return input => resolver.match(model).id(this.id).save({ ...this, ...input }); },
141
- enumerable: false,
142
- },
143
-
144
- $$remove: {
145
- get() { return () => resolver.match(model).id(this.id).remove(); },
146
- enumerable: false,
147
- },
148
-
149
- $$delete: {
150
- get() { return () => resolver.match(model).id(this.id).delete(); },
151
- enumerable: false,
152
- },
153
- });
154
-
155
- // Create and return ResultSetItem
156
- return Object.defineProperties(this, definition);
157
- }
158
- };