@sprucelabs/data-stores 12.0.14 → 13.0.0

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.
@@ -6,7 +6,9 @@ import { PrepareOptions, PrepareResults } from '../types/stores.types';
6
6
  declare type Response<FullSchema extends Schema, CreateEntityInstances extends boolean, IncludePrivateFields extends boolean, PF extends SchemaPublicFieldNames<FullSchema>, F extends SchemaFieldNames<FullSchema>> = IsDynamicSchema<FullSchema> extends true ? DynamicSchemaAllValues<FullSchema, CreateEntityInstances> : IncludePrivateFields extends false ? Pick<SchemaPublicValues<FullSchema, CreateEntityInstances>, PF> : Pick<SchemaAllValues<FullSchema, CreateEntityInstances>, F>;
7
7
  export default abstract class AbstractStore<FullSchema extends Schema, CreateSchema extends Schema = FullSchema, UpdateSchema extends Schema = CreateSchema, DatabaseSchema extends Schema = FullSchema, DatabaseRecord = SchemaValues<DatabaseSchema> & {
8
8
  id: string;
9
- }, QueryRecord = SchemaPartialValues<FullSchema>, FullRecord = SchemaValues<FullSchema>, CreateRecord = SchemaValues<CreateSchema>, UpdateRecord = SchemaValues<UpdateSchema>> extends AbstractMutexer {
9
+ }, QueryRecord = SchemaPartialValues<FullSchema>, FullRecord = SchemaValues<FullSchema>, CreateRecord = SchemaValues<CreateSchema>, UpdateRecord = SchemaValues<UpdateSchema> & {
10
+ $push?: Record<string, any>;
11
+ }> extends AbstractMutexer {
10
12
  abstract readonly name: string;
11
13
  protected abstract collectionName: string;
12
14
  protected abstract createSchema: CreateSchema;
@@ -36,6 +38,7 @@ export default abstract class AbstractStore<FullSchema extends Schema, CreateSch
36
38
  updateOne<IncludePrivateFields extends boolean = false, CreateEntityInstances extends boolean = false, F extends SchemaFieldNames<FullSchema> = SchemaFieldNames<FullSchema>, PF extends SchemaPublicFieldNames<FullSchema> = SchemaPublicFieldNames<FullSchema>>(query: QueryBuilder<QueryRecord>, updates: UpdateRecord, options?: PrepareOptions<IncludePrivateFields, FullSchema, F>): Promise<Response<FullSchema, CreateEntityInstances, IncludePrivateFields, PF, F>>;
37
39
  update(query: QueryBuilder<QueryRecord>, updates: UpdateRecord): Promise<number>;
38
40
  private findOneAndUpdate;
41
+ private pluckOperations;
39
42
  scramble(id: string): Promise<Response<FullSchema, false, false, SchemaPublicFieldNames<FullSchema>, Extract<keyof FullSchema["fields"], string>>>;
40
43
  private isScrambled;
41
44
  private generateScrambledRecord;
@@ -7,11 +7,32 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
+ var __rest = (this && this.__rest) || function (s, e) {
11
+ var t = {};
12
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
13
+ t[p] = s[p];
14
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
15
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
16
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
17
+ t[p[i]] = s[p[i]];
18
+ }
19
+ return t;
20
+ };
10
21
  import SchemaEntity, { normalizeSchemaValues, validateSchemaValues, } from '@sprucelabs/schema';
11
22
  import { SCRAMBLE_VALUE } from '../constants.js';
12
23
  import SpruceError from '../errors/SpruceError.js';
13
24
  import AbstractMutexer from '../mutexers/AbstractMutexer.js';
14
25
  import errorUtil from '../utilities/error.utility.js';
26
+ const operations = [
27
+ '$push',
28
+ '$inc',
29
+ '$min',
30
+ '$max',
31
+ '$mul',
32
+ '$push',
33
+ '$pull',
34
+ '$pop',
35
+ ];
15
36
  export default class AbstractStore extends AbstractMutexer {
16
37
  constructor(db, collectionName) {
17
38
  super();
@@ -171,8 +192,9 @@ export default class AbstractStore extends AbstractMutexer {
171
192
  }
172
193
  findOneAndUpdate(query, updates, notFoundHandler, options = {}) {
173
194
  return __awaiter(this, void 0, void 0, function* () {
195
+ const { ops, updates: initialUpdates } = this.pluckOperations(updates);
174
196
  try {
175
- const isScrambled = this.isScrambled(updates);
197
+ const isScrambled = this.isScrambled(initialUpdates);
176
198
  let current = yield this.findOne(query, options);
177
199
  if (!current) {
178
200
  current = yield notFoundHandler();
@@ -185,19 +207,22 @@ export default class AbstractStore extends AbstractMutexer {
185
207
  }
186
208
  if (!isScrambled) {
187
209
  //@ts-ignore
188
- validateSchemaValues(this.updateSchema, updates);
210
+ validateSchemaValues(this.updateSchema, initialUpdates);
189
211
  }
190
212
  const cleanedUpdates = !isScrambled && this.willUpdate
191
- ? yield this.willUpdate(updates, current)
192
- : updates;
213
+ ? yield this.willUpdate(initialUpdates, current)
214
+ : initialUpdates;
193
215
  const databaseRecord = Object.assign(Object.assign({}, current), cleanedUpdates);
194
- const toSave = isScrambled
216
+ const normalizedValues = isScrambled
195
217
  ? databaseRecord
196
218
  : normalizeSchemaValues(this.databaseSchema, databaseRecord, {
197
219
  shouldCreateEntityInstances: false,
198
220
  fields: Object.keys(cleanedUpdates),
199
221
  });
200
- const results = yield this.db.updateOne(this.collectionName, query, toSave);
222
+ for (const { name, value } of ops) {
223
+ normalizedValues[name] = value;
224
+ }
225
+ const results = yield this.db.updateOne(this.collectionName, query, normalizedValues);
201
226
  return this.prepareAndNormalizeRecord(results, options);
202
227
  }
203
228
  catch (err) {
@@ -211,6 +236,25 @@ export default class AbstractStore extends AbstractMutexer {
211
236
  }
212
237
  });
213
238
  }
239
+ pluckOperations(updates) {
240
+ const initialUpdates = __rest(updates, []);
241
+ const ops = operations
242
+ .map((name) => {
243
+ if (name in initialUpdates) {
244
+ //@ts-ignore
245
+ const value = initialUpdates[name];
246
+ //@ts-ignore
247
+ delete initialUpdates[name];
248
+ return {
249
+ name,
250
+ value,
251
+ };
252
+ }
253
+ return false;
254
+ })
255
+ .filter((o) => !!o);
256
+ return { ops, updates: initialUpdates };
257
+ }
214
258
  scramble(id) {
215
259
  return __awaiter(this, void 0, void 0, function* () {
216
260
  if (!this.scrambleFields) {
@@ -6,7 +6,9 @@ import { PrepareOptions, PrepareResults } from '../types/stores.types';
6
6
  declare type Response<FullSchema extends Schema, CreateEntityInstances extends boolean, IncludePrivateFields extends boolean, PF extends SchemaPublicFieldNames<FullSchema>, F extends SchemaFieldNames<FullSchema>> = IsDynamicSchema<FullSchema> extends true ? DynamicSchemaAllValues<FullSchema, CreateEntityInstances> : IncludePrivateFields extends false ? Pick<SchemaPublicValues<FullSchema, CreateEntityInstances>, PF> : Pick<SchemaAllValues<FullSchema, CreateEntityInstances>, F>;
7
7
  export default abstract class AbstractStore<FullSchema extends Schema, CreateSchema extends Schema = FullSchema, UpdateSchema extends Schema = CreateSchema, DatabaseSchema extends Schema = FullSchema, DatabaseRecord = SchemaValues<DatabaseSchema> & {
8
8
  id: string;
9
- }, QueryRecord = SchemaPartialValues<FullSchema>, FullRecord = SchemaValues<FullSchema>, CreateRecord = SchemaValues<CreateSchema>, UpdateRecord = SchemaValues<UpdateSchema>> extends AbstractMutexer {
9
+ }, QueryRecord = SchemaPartialValues<FullSchema>, FullRecord = SchemaValues<FullSchema>, CreateRecord = SchemaValues<CreateSchema>, UpdateRecord = SchemaValues<UpdateSchema> & {
10
+ $push?: Record<string, any>;
11
+ }> extends AbstractMutexer {
10
12
  abstract readonly name: string;
11
13
  protected abstract collectionName: string;
12
14
  protected abstract createSchema: CreateSchema;
@@ -36,6 +38,7 @@ export default abstract class AbstractStore<FullSchema extends Schema, CreateSch
36
38
  updateOne<IncludePrivateFields extends boolean = false, CreateEntityInstances extends boolean = false, F extends SchemaFieldNames<FullSchema> = SchemaFieldNames<FullSchema>, PF extends SchemaPublicFieldNames<FullSchema> = SchemaPublicFieldNames<FullSchema>>(query: QueryBuilder<QueryRecord>, updates: UpdateRecord, options?: PrepareOptions<IncludePrivateFields, FullSchema, F>): Promise<Response<FullSchema, CreateEntityInstances, IncludePrivateFields, PF, F>>;
37
39
  update(query: QueryBuilder<QueryRecord>, updates: UpdateRecord): Promise<number>;
38
40
  private findOneAndUpdate;
41
+ private pluckOperations;
39
42
  scramble(id: string): Promise<Response<FullSchema, false, false, SchemaPublicFieldNames<FullSchema>, Extract<keyof FullSchema["fields"], string>>>;
40
43
  private isScrambled;
41
44
  private generateScrambledRecord;
@@ -22,6 +22,17 @@ var __importStar = (this && this.__importStar) || function (mod) {
22
22
  __setModuleDefault(result, mod);
23
23
  return result;
24
24
  };
25
+ var __rest = (this && this.__rest) || function (s, e) {
26
+ var t = {};
27
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
28
+ t[p] = s[p];
29
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
30
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
31
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
32
+ t[p[i]] = s[p[i]];
33
+ }
34
+ return t;
35
+ };
25
36
  var __importDefault = (this && this.__importDefault) || function (mod) {
26
37
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
38
  };
@@ -31,6 +42,16 @@ const constants_1 = require("../constants");
31
42
  const SpruceError_1 = __importDefault(require("../errors/SpruceError"));
32
43
  const AbstractMutexer_1 = __importDefault(require("../mutexers/AbstractMutexer"));
33
44
  const error_utility_1 = __importDefault(require("../utilities/error.utility"));
45
+ const operations = [
46
+ '$push',
47
+ '$inc',
48
+ '$min',
49
+ '$max',
50
+ '$mul',
51
+ '$push',
52
+ '$pull',
53
+ '$pop',
54
+ ];
34
55
  class AbstractStore extends AbstractMutexer_1.default {
35
56
  constructor(db, collectionName) {
36
57
  super();
@@ -171,8 +192,9 @@ class AbstractStore extends AbstractMutexer_1.default {
171
192
  return this.db.update(this.collectionName, query, updates);
172
193
  }
173
194
  async findOneAndUpdate(query, updates, notFoundHandler, options = {}) {
195
+ const { ops, updates: initialUpdates } = this.pluckOperations(updates);
174
196
  try {
175
- const isScrambled = this.isScrambled(updates);
197
+ const isScrambled = this.isScrambled(initialUpdates);
176
198
  let current = await this.findOne(query, options);
177
199
  if (!current) {
178
200
  current = await notFoundHandler();
@@ -185,19 +207,22 @@ class AbstractStore extends AbstractMutexer_1.default {
185
207
  }
186
208
  if (!isScrambled) {
187
209
  //@ts-ignore
188
- (0, schema_1.validateSchemaValues)(this.updateSchema, updates);
210
+ (0, schema_1.validateSchemaValues)(this.updateSchema, initialUpdates);
189
211
  }
190
212
  const cleanedUpdates = !isScrambled && this.willUpdate
191
- ? await this.willUpdate(updates, current)
192
- : updates;
213
+ ? await this.willUpdate(initialUpdates, current)
214
+ : initialUpdates;
193
215
  const databaseRecord = Object.assign(Object.assign({}, current), cleanedUpdates);
194
- const toSave = isScrambled
216
+ const normalizedValues = isScrambled
195
217
  ? databaseRecord
196
218
  : (0, schema_1.normalizeSchemaValues)(this.databaseSchema, databaseRecord, {
197
219
  shouldCreateEntityInstances: false,
198
220
  fields: Object.keys(cleanedUpdates),
199
221
  });
200
- const results = await this.db.updateOne(this.collectionName, query, toSave);
222
+ for (const { name, value } of ops) {
223
+ normalizedValues[name] = value;
224
+ }
225
+ const results = await this.db.updateOne(this.collectionName, query, normalizedValues);
201
226
  return this.prepareAndNormalizeRecord(results, options);
202
227
  }
203
228
  catch (err) {
@@ -210,6 +235,25 @@ class AbstractStore extends AbstractMutexer_1.default {
210
235
  throw coded[0];
211
236
  }
212
237
  }
238
+ pluckOperations(updates) {
239
+ const initialUpdates = __rest(updates, []);
240
+ const ops = operations
241
+ .map((name) => {
242
+ if (name in initialUpdates) {
243
+ //@ts-ignore
244
+ const value = initialUpdates[name];
245
+ //@ts-ignore
246
+ delete initialUpdates[name];
247
+ return {
248
+ name,
249
+ value,
250
+ };
251
+ }
252
+ return false;
253
+ })
254
+ .filter((o) => !!o);
255
+ return { ops, updates: initialUpdates };
256
+ }
213
257
  async scramble(id) {
214
258
  if (!this.scrambleFields) {
215
259
  throw new SpruceError_1.default({ code: 'SCRAMBLE_NOT_CONFIGURED' });
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "12.0.14",
6
+ "version": "13.0.0",
7
7
  "files": [
8
8
  "build/**/*",
9
9
  "!build/__tests__",
@@ -73,10 +73,10 @@
73
73
  "dependencies": {
74
74
  "@sprucelabs/error": "^5.0.460",
75
75
  "@sprucelabs/schema": "^28.2.17",
76
- "@sprucelabs/spruce-core-schemas": "^29.1.12",
76
+ "@sprucelabs/spruce-core-schemas": "^30.0.0",
77
77
  "@sprucelabs/spruce-skill-utils": "^26.0.43",
78
78
  "globby": "^11.0.4",
79
- "just-clone": "^5.0.1",
79
+ "just-clone": "^5.1.0",
80
80
  "lodash": "^4.17.21",
81
81
  "mongodb": "^4.1.0",
82
82
  "nedb": "^1.8.0"