electrodb 2.6.1 → 2.7.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.
package/index.d.ts CHANGED
@@ -156,8 +156,8 @@ export interface CollectionWhereOperations {
156
156
  begins: <T, A extends WhereAttributeSymbol<T>>(attr: A, value: T) => string;
157
157
  exists: <T, A extends WhereAttributeSymbol<T>>(attr: A) => string;
158
158
  notExists: <T, A extends WhereAttributeSymbol<T>>(attr: A) => string;
159
- contains: <T, A extends WhereAttributeSymbol<T>>(attr: A, value: T) => string;
160
- notContains: <T, A extends WhereAttributeSymbol<T>>(attr: A, value: T) => string;
159
+ contains: <T, A extends WhereAttributeSymbol<T>>(attr: A, value: A extends WhereAttributeSymbol<infer V> ? V extends Array<infer I> ? I : V : never) => string;
160
+ notContains: <T, A extends WhereAttributeSymbol<T>>(attr: A, value: A extends WhereAttributeSymbol<infer V> ? V extends Array<infer I> ? I : V : never) => string;
161
161
  value: <T, A extends WhereAttributeSymbol<T>>(attr: A, value: T) => string;
162
162
  name: <T, A extends WhereAttributeSymbol<T>>(attr: A) => string;
163
163
  size: <T, A extends WhereAttributeSymbol<T>>(attr: A) => string;
@@ -601,6 +601,11 @@ export type ElectroEventListener = (event: ElectroEvent) => void;
601
601
  // details: any;
602
602
  // };
603
603
 
604
+ export type EntityIdentifiers<E extends Entity<any, any, any, any>> =
605
+ E extends Entity<infer A, infer F, infer C, infer S>
606
+ ? AllTableIndexCompositeAttributes<A, F, C, S>
607
+ : never;
608
+
604
609
  export type EntityItem<E extends Entity<any, any, any, any>> =
605
610
  E extends Entity<infer A, infer F, infer C, infer S>
606
611
  ? ResponseItem<A, F, C, S>
@@ -621,9 +626,14 @@ export type BatchGetEntityItem<E extends Entity<any, any, any, any>> =
621
626
  ? ResponseItem<A, F, C, S>[]
622
627
  : never;
623
628
 
629
+ export type UpdateEntityResponseItem<E extends Entity<any, any, any, any>> =
630
+ E extends Entity<infer A, infer F, infer C, infer S>
631
+ ? AllTableIndexCompositeAttributes<A,F,C,S>
632
+ : never;
633
+
624
634
  export type UpdateEntityItem<E extends Entity<any, any, any, any>> =
625
635
  E extends Entity<infer A, infer F, infer C, infer S>
626
- ? Partial<ResponseItem<A,F,C,S>>
636
+ ? SetItem<A,F,C,S>
627
637
  : never;
628
638
 
629
639
  export type UpdateAddEntityItem<E extends Entity<any, any, any, any>> =
@@ -692,7 +702,7 @@ export type BatchGetResponse<E extends Entity<any, any, any, any>> =
692
702
  } : never;
693
703
 
694
704
  export type UpdateEntityResponse<E extends Entity<any, any, any, any>> = {
695
- data: UpdateEntityItem<E>;
705
+ data: UpdateEntityResponseItem<E>;
696
706
  }
697
707
  export type UpdateAddEntityResponse<E extends Entity<any, any, any, any>> = {
698
708
  data: UpdateAddEntityItem<E>;
@@ -793,7 +803,7 @@ export type UpdateRecordGoTransaction<ResponseType> = <T = ResponseType, Options
793
803
  export interface SetRecordActionOptionsTransaction<A extends string, F extends string, C extends string, S extends Schema<A,F,C>, SetAttr,IndexCompositeAttributes,TableItem> {
794
804
  commit: UpdateRecordGoTransaction<TableItem>;
795
805
  params: ParamRecord<UpdateQueryParams>;
796
- set: SetRecordTransaction<A,F,C,S, SetItem<A,F,C,S>,IndexCompositeAttributes,TableItem>;
806
+ set: SetRecordTransaction<A,F,C,S, SetItem<A,F,C,S>, IndexCompositeAttributes, TableItem>;
797
807
  remove: RemoveRecordTransaction<A,F,C,S, Array<keyof SetItem<A,F,C,S>>,IndexCompositeAttributes,TableItem>;
798
808
  add: SetRecordTransaction<A,F,C,S, AddItem<A,F,C,S>,IndexCompositeAttributes,TableItem>;
799
809
  subtract: SetRecordTransaction<A,F,C,S, SubtractItem<A,F,C,S>,IndexCompositeAttributes,TableItem>;
@@ -818,19 +828,19 @@ export interface BatchGetRecordOperationOptions<A extends string, F extends stri
818
828
  }
819
829
 
820
830
  export interface PutRecordOperationOptions<A extends string, F extends string, C extends string, S extends Schema<A,F,C>, ResponseType> {
821
- go: PutRecordGo<ResponseType, PutQueryOptions>;
831
+ go: PutRecordGo<ResponseType>;
822
832
  params: ParamRecord<PutQueryOptions>;
823
833
  where: WhereClause<A, F, C, S, Item<A, F, C, S, S["attributes"]>, PutRecordOperationOptions<A, F, C, S, ResponseType>>;
824
834
  }
825
835
 
826
836
  export interface UpsertRecordOperationOptions<A extends string, F extends string, C extends string, S extends Schema<A,F,C>, ResponseType> {
827
- go: PutRecordGo<ResponseType, UpdateQueryParams>;
837
+ go: UpsertRecordGo<ResponseType, AllTableIndexCompositeAttributes<A,F,C,S>>;
828
838
  params: ParamRecord<UpdateQueryParams>;
829
839
  where: WhereClause<A, F, C, S, Item<A, F, C, S, S["attributes"]>, UpsertRecordOperationOptions<A, F, C, S, ResponseType>>;
830
840
  }
831
841
 
832
842
  export interface DeleteRecordOperationOptions<A extends string, F extends string, C extends string, S extends Schema<A,F,C>, ResponseType> {
833
- go: DeleteRecordOperationGo<ResponseType, DeleteQueryOptions>;
843
+ go: DeleteRecordOperationGo<ResponseType, AllTableIndexCompositeAttributes<A,F,C,S>>;
834
844
  params: ParamRecord<DeleteQueryOptions>;
835
845
  where: WhereClause<A,F,C,S,Item<A,F,C,S,S["attributes"]>,DeleteRecordOperationOptions<A,F,C,S,ResponseType>>;
836
846
  }
@@ -841,9 +851,10 @@ export interface BatchWriteOperationOptions<A extends string, F extends string,
841
851
  }
842
852
 
843
853
  export interface SetRecordActionOptions<A extends string, F extends string, C extends string, S extends Schema<A,F,C>, SetAttr,IndexCompositeAttributes,TableItem> {
844
- go: UpdateRecordGo<TableItem>;
854
+ go: UpdateRecordGo<TableItem, AllTableIndexCompositeAttributes<A,F,C,S>>;
845
855
  params: ParamRecord<UpdateQueryParams>;
846
- set: SetRecord<A,F,C,S, SetItem<A,F,C,S>,IndexCompositeAttributes,TableItem>;
856
+ set: SetRecord<A,F,C,S, SetItem<A,F,C,S>,IndexCompositeAttributes, TableItem>;
857
+ // ifNotExists: SetRecord<A,F,C,S, SetItem<A,F,C,S>,IndexCompositeAttributes,TableItem>;
847
858
  remove: SetRecord<A,F,C,S, Array<keyof SetItem<A,F,C,S>>,IndexCompositeAttributes,TableItem>;
848
859
  add: SetRecord<A,F,C,S, AddItem<A,F,C,S>,IndexCompositeAttributes,TableItem>;
849
860
  subtract: SetRecord<A,F,C,S, SubtractItem<A,F,C,S>,IndexCompositeAttributes,TableItem>;
@@ -1005,7 +1016,7 @@ export interface DeleteQueryOptions extends QueryOptions {
1005
1016
  }
1006
1017
 
1007
1018
  export interface PutQueryOptions extends QueryOptions {
1008
- response?: "default" | "none" | 'all_old';
1019
+ response?: "default" | "none" | 'all_old' | 'all_new';
1009
1020
  }
1010
1021
 
1011
1022
  export interface ParamOptions {
@@ -1206,20 +1217,52 @@ export type ServiceQueryRecordsGo<ResponseType, Options = ServiceQueryGoTerminal
1206
1217
 
1207
1218
  export type QueryRecordsGo<ResponseType, Options = QueryOptions> = <T = ResponseType>(options?: Options) => Promise<{ data: T, cursor: string | null }>;
1208
1219
 
1209
- export type UpdateRecordGo<ResponseType> = <T = ResponseType, Options extends UpdateQueryOptions = UpdateQueryOptions>(options?: Options) =>
1220
+ export type UpdateRecordGo<ResponseType, Keys> = <T = ResponseType, Options extends UpdateQueryOptions = UpdateQueryOptions>(options?: Options) =>
1210
1221
  Options extends infer O
1211
1222
  ? 'response' extends keyof O
1212
- ? O['response'] extends 'all_new'
1213
- ? Promise<{data: T}>
1214
- : O['response'] extends 'all_old'
1215
- ? Promise<{data: T}>
1216
- : Promise<{data: Partial<T>}>
1217
- : Promise<{data: Partial<T>}>
1223
+ ? O['response'] extends 'all_new'
1224
+ ? Promise<{ data: T }>
1225
+ : O['response'] extends 'all_old'
1226
+ ? Promise<{ data: T }>
1227
+ : O['response'] extends 'default'
1228
+ ? Promise<{ data: Keys }>
1229
+ : O['response'] extends 'none'
1230
+ ? Promise<{ data: null }>
1231
+ : Promise<{ data: Partial<T> }>
1232
+ : Promise<{ data: Keys }>
1218
1233
  : never;
1219
1234
 
1220
- export type PutRecordGo<ResponseType, Options = QueryOptions> = <T = ResponseType>(options?: Options) => Promise<{ data: T }>;
1235
+ export type UpsertRecordGo<ResponseType, Keys> = <T = ResponseType, Options extends UpdateQueryOptions = UpdateQueryOptions>(options?: Options) =>
1236
+ Options extends infer O
1237
+ ? 'response' extends keyof O
1238
+ ? O['response'] extends 'all_new'
1239
+ ? Promise<{ data: T }>
1240
+ : O['response'] extends 'all_old'
1241
+ ? Promise<{ data: T }>
1242
+ : O['response'] extends 'default'
1243
+ ? Promise<{ data: Keys }>
1244
+ : O['response'] extends 'none'
1245
+ ? Promise<{ data: null }>
1246
+ : Promise<{ data: Partial<T> }>
1247
+ : Promise<{ data: Keys }>
1248
+ : never;
1221
1249
 
1222
- export type DeleteRecordOperationGo<ResponseType, Options = QueryOptions> = <T = ResponseType>(options?: Options) => Promise<{ data: T }>;
1250
+ export type PutRecordGo<ResponseType> = <T = ResponseType, Options extends PutQueryOptions = PutQueryOptions>(options?: Options) => Promise<{ data: T }>
1251
+
1252
+ export type DeleteRecordOperationGo<ResponseType, Keys> = <T = ResponseType, Options extends DeleteQueryOptions = DeleteQueryOptions>(options?: Options) =>
1253
+ Options extends infer O
1254
+ ? 'response' extends keyof O
1255
+ ? O['response'] extends 'all_new'
1256
+ ? Promise<{ data: T }>
1257
+ : O['response'] extends 'all_old'
1258
+ ? Promise<{ data: T }>
1259
+ : O['response'] extends 'default'
1260
+ ? Promise<{ data: Keys }>
1261
+ : O['response'] extends 'none'
1262
+ ? Promise<{ data: null }>
1263
+ : Promise<{ data: Partial<T> }>
1264
+ : Promise<{ data: Keys }>
1265
+ : never;
1223
1266
 
1224
1267
  export type BatchWriteGo<ResponseType> = <O extends BulkOptions>(options?: O) =>
1225
1268
  Promise<{ unprocessed: ResponseType }>
@@ -2419,8 +2462,8 @@ export interface WhereOperations<A extends string, F extends string, C extends s
2419
2462
  begins: <T, A extends WhereAttributeSymbol<T>>(attr: A, value: T) => string;
2420
2463
  exists: <A extends WhereAttributeSymbol<any>>(attr: A) => string;
2421
2464
  notExists: <A extends WhereAttributeSymbol<any>>(attr: A) => string;
2422
- contains: <T, A extends WhereAttributeSymbol<T>>(attr: A, value: T) => string;
2423
- notContains: <T, A extends WhereAttributeSymbol<T>>(attr: A, value: T) => string;
2465
+ contains: <T, A extends WhereAttributeSymbol<T>>(attr: A, value: A extends WhereAttributeSymbol<infer V> ? V extends Array<infer I> ? I : V : never) => string;
2466
+ notContains: <T, A extends WhereAttributeSymbol<T>>(attr: A, value: A extends WhereAttributeSymbol<infer V> ? V extends Array<infer I> ? I : V : never) => string;
2424
2467
  value: <T, A extends WhereAttributeSymbol<T>>(attr: A, value: A extends WhereAttributeSymbol<infer V> ? V : never) => A extends WhereAttributeSymbol<infer V> ? V : never;
2425
2468
  name: <A extends WhereAttributeSymbol<any>>(attr: A) => string;
2426
2469
  size: <T, A extends WhereAttributeSymbol<T>>(attr: A) => number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "electrodb",
3
- "version": "2.6.1",
3
+ "version": "2.7.0",
4
4
  "description": "A library to more easily create and interact with multiple entities and heretical relationships in dynamodb",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/src/clauses.js CHANGED
@@ -185,13 +185,17 @@ let clauses = {
185
185
  }
186
186
  try {
187
187
  const {pk, sk} = state.getCompositeAttributes();
188
+ const pkComposite = entity._expectFacets(facets, pk);
189
+ state.addOption('_includeOnResponseItem', pkComposite);
188
190
  return state
189
191
  .setMethod(MethodTypes.delete)
190
192
  .setType(QueryTypes.eq)
191
- .setPK(entity._expectFacets(facets, pk))
193
+ .setPK(pkComposite)
192
194
  .ifSK(() => {
193
195
  entity._expectFacets(facets, sk);
194
- state.setSK(state.buildQueryComposites(facets, sk));
196
+ const skComposite = state.buildQueryComposites(facets, sk);
197
+ state.setSK(skComposite);
198
+ state.addOption('_includeOnResponseItem', {...skComposite, ...pkComposite});
195
199
  });
196
200
  } catch(err) {
197
201
  state.setError(err);
@@ -215,13 +219,17 @@ let clauses = {
215
219
  if (sk) {
216
220
  filter.unsafeSet(FilterOperationNames.exists, sk);
217
221
  }
222
+ const pkComposite = entity._expectFacets(facets, attributes.pk);
223
+ state.addOption('_includeOnResponseItem', pkComposite);
218
224
  return state
219
225
  .setMethod(MethodTypes.delete)
220
226
  .setType(QueryTypes.eq)
221
- .setPK(entity._expectFacets(facets, attributes.pk))
227
+ .setPK(pkComposite)
222
228
  .ifSK(() => {
223
229
  entity._expectFacets(facets, attributes.sk);
224
- state.setSK(state.buildQueryComposites(facets, attributes.sk));
230
+ const skComposite = state.buildQueryComposites(facets, attributes.sk);
231
+ state.setSK(skComposite);
232
+ state.addOption('_includeOnResponseItem', {...skComposite, ...pkComposite});
225
233
  });
226
234
  } catch(err) {
227
235
  state.setError(err);
@@ -239,14 +247,18 @@ let clauses = {
239
247
  try {
240
248
  let record = entity.model.schema.checkCreate({...payload});
241
249
  const attributes = state.getCompositeAttributes();
250
+ const pkComposite = entity._expectFacets(record, attributes.pk);
251
+ state.addOption('_includeOnResponseItem', pkComposite);
242
252
  return state
243
253
  .setMethod(MethodTypes.upsert)
244
254
  .setType(QueryTypes.eq)
245
255
  .applyUpsert(record)
246
- .setPK(entity._expectFacets(record, attributes.pk))
256
+ .setPK(pkComposite)
247
257
  .ifSK(() => {
248
258
  entity._expectFacets(record, attributes.sk);
249
- state.setSK(entity._buildQueryFacets(record, attributes.sk));
259
+ const skComposite = entity._buildQueryFacets(record, attributes.sk);
260
+ state.setSK(skComposite);
261
+ state.addOption('_includeOnResponseItem', {...skComposite, ...pkComposite});
250
262
  })
251
263
  .whenOptions(({ state, options }) => {
252
264
  if (!state.getParams()) {
@@ -337,13 +349,17 @@ let clauses = {
337
349
  if (sk) {
338
350
  filter.unsafeSet(FilterOperationNames.exists, sk);
339
351
  }
352
+ const pkComposite = entity._expectFacets(facets, attributes.pk);
353
+ state.addOption('_includeOnResponseItem', pkComposite);
340
354
  return state
341
355
  .setMethod(MethodTypes.update)
342
356
  .setType(QueryTypes.eq)
343
- .setPK(entity._expectFacets(facets, attributes.pk))
357
+ .setPK(pkComposite)
344
358
  .ifSK(() => {
345
359
  entity._expectFacets(facets, attributes.sk);
346
- state.setSK(state.buildQueryComposites(facets, attributes.sk));
360
+ const skComposite = state.buildQueryComposites(facets, attributes.sk);
361
+ state.setSK(skComposite);
362
+ state.addOption('_includeOnResponseItem', {...skComposite, ...pkComposite});
347
363
  });
348
364
  } catch(err) {
349
365
  state.setError(err);
@@ -360,13 +376,17 @@ let clauses = {
360
376
  }
361
377
  try {
362
378
  const attributes = state.getCompositeAttributes();
379
+ const pkComposite = entity._expectFacets(facets, attributes.pk);
380
+ state.addOption('_includeOnResponseItem', pkComposite);
363
381
  return state
364
382
  .setMethod(MethodTypes.update)
365
383
  .setType(QueryTypes.eq)
366
- .setPK(entity._expectFacets(facets, attributes.pk))
384
+ .setPK(pkComposite)
367
385
  .ifSK(() => {
368
386
  entity._expectFacets(facets, attributes.sk);
369
- state.setSK(state.buildQueryComposites(facets, attributes.sk));
387
+ const skComposite = state.buildQueryComposites(facets, attributes.sk);
388
+ state.setSK(skComposite);
389
+ state.addOption('_includeOnResponseItem', {...pkComposite, ...skComposite});
370
390
  });
371
391
  } catch(err) {
372
392
  state.setError(err);
@@ -808,7 +828,8 @@ class ChainState {
808
828
  data: {},
809
829
  },
810
830
  upsert: {
811
- data: {}
831
+ data: {},
832
+ ifNotExists: {},
812
833
  },
813
834
  keys: {
814
835
  provided: [],
@@ -1018,8 +1039,12 @@ class ChainState {
1018
1039
  }
1019
1040
  }
1020
1041
 
1021
- applyUpsert(data = {}) {
1022
- this.query.upsert.data = {...this.query.upsert.data, ...data};
1042
+ applyUpsert(data = {}, { ifNotExists } = {}) {
1043
+ if (ifNotExists) {
1044
+ this.query.upsert.ifNotExists = {...this.query.upsert.ifNotExists, ...data};
1045
+ } else {
1046
+ this.query.upsert.data = {...this.query.upsert.data, ...data};
1047
+ }
1023
1048
  return this;
1024
1049
  }
1025
1050
 
package/src/entity.js CHANGED
@@ -673,7 +673,7 @@ class Entity {
673
673
  case MethodTypes.delete:
674
674
  case MethodTypes.remove:
675
675
  case MethodTypes.upsert:
676
- return this.formatResponse(response, index, {...config, _objectOnEmpty: true});
676
+ return this.formatResponse(response, index, { ...config, _objectOnEmpty: true });
677
677
  default:
678
678
  return this.formatResponse(response, index, config);
679
679
  }
@@ -814,7 +814,11 @@ class Entity {
814
814
  results = null;
815
815
  }
816
816
  } else if (config._objectOnEmpty) {
817
- return { data: {} };
817
+ return {
818
+ data: {
819
+ ...config._includeOnResponseItem,
820
+ }
821
+ };
818
822
  } else {
819
823
  results = null;
820
824
  }
@@ -1342,6 +1346,7 @@ class Entity {
1342
1346
  order: undefined,
1343
1347
  hydrate: false,
1344
1348
  hydrator: (_entity, _indexName, items) => items,
1349
+ _includeOnResponseItem: {},
1345
1350
  };
1346
1351
 
1347
1352
  return provided.filter(Boolean).reduce((config, option) => {
@@ -1503,6 +1508,13 @@ class Entity {
1503
1508
  config.hydrator = option.hydrator;
1504
1509
  }
1505
1510
 
1511
+ if (option._includeOnResponseItem) {
1512
+ config._includeOnResponseItem = {
1513
+ ...config._includeOnResponseItem,
1514
+ ...option._includeOnResponseItem,
1515
+ }
1516
+ }
1517
+
1506
1518
  config.page = Object.assign({}, config.page, option.page);
1507
1519
  config.params = Object.assign({}, config.params, option.params);
1508
1520
  return config;
@@ -1951,12 +1963,17 @@ class Entity {
1951
1963
  const { updatedKeys, setAttributes, indexKey } = this._getPutKeys(pk, sk && sk.facets, upsert.data);
1952
1964
  const upsertAttributes = this.model.schema.translateToFields(setAttributes);
1953
1965
  const keyNames = Object.keys(indexKey);
1954
- // update.set(this.identifiers.entity, this.getName());
1955
- // update.set(this.identifiers.version, this.getVersion());
1956
1966
  for (const field of [...Object.keys(upsertAttributes), ...Object.keys(updatedKeys)]) {
1957
1967
  const value = u.getFirstDefined(upsertAttributes[field], updatedKeys[field]);
1958
1968
  if (!keyNames.includes(field)) {
1959
- update.set(field, value);
1969
+ let operation = ItemOperations.set;
1970
+ const name = this.model.schema.translationForRetrieval[field];
1971
+ if (name) {
1972
+ if (this.model.schema.readOnlyAttributes.has(name)) {
1973
+ operation = ItemOperations.ifNotExists;
1974
+ }
1975
+ }
1976
+ update.set(field, value, operation);
1960
1977
  }
1961
1978
  }
1962
1979
 
package/src/schema.js CHANGED
@@ -1429,15 +1429,14 @@ class Schema {
1429
1429
  : attribute.getValidate(value);
1430
1430
  }
1431
1431
 
1432
- checkUpdate(payload = {}) {
1432
+ checkUpdate(payload = {}, { allowReadOnly } = {}) {
1433
1433
  let record = {};
1434
1434
  for (let [path, attribute] of this.traverser.getAll()) {
1435
1435
  let value = payload[path];
1436
1436
  if (value === undefined) {
1437
1437
  continue;
1438
1438
  }
1439
- if (attribute.readOnly) {
1440
- // todo: #electroerror
1439
+ if (attribute.readOnly && !allowReadOnly) {
1441
1440
  throw new e.ElectroAttributeValidationError(attribute.path, `Attribute "${attribute.path}" is Read-Only and cannot be updated`);
1442
1441
  } else {
1443
1442
  record[path] = attribute.getValidate(value);
package/src/types.js CHANGED
@@ -217,6 +217,7 @@ const ItemOperations = {
217
217
  "add": "add",
218
218
  "subtract": "subtract",
219
219
  "append": "append",
220
+ "ifNotExists": "ifNotExists"
220
221
  };
221
222
 
222
223
  const AttributeProxySymbol = Symbol("attribute_proxy");
package/src/update.js CHANGED
@@ -9,7 +9,7 @@ class UpdateExpression extends ExpressionState {
9
9
  remove: new Set(),
10
10
  add: new Set(),
11
11
  subtract: new Set(),
12
- delete: new Set()
12
+ delete: new Set(),
13
13
  };
14
14
  this.seen = new Map();
15
15
  this.type = BuilderTypes.update;
@@ -23,25 +23,33 @@ class UpdateExpression extends ExpressionState {
23
23
  this.operations[type].delete(expression);
24
24
  }
25
25
 
26
- set(name, value, operation) {
26
+ set(name, value, operation = ItemOperations.set) {
27
+ let operationToApply = operation;
28
+ if (operation === ItemOperations.ifNotExists) {
29
+ operationToApply = ItemOperations.set;
30
+ }
27
31
  const seen = this.seen.get(name);
28
32
  let n;
29
33
  let v;
30
34
  if (seen) {
31
35
  n = seen.name;
32
36
  v = seen.value;
33
- this.unadd(ItemOperations.set, seen.expression);
37
+ this.unadd(operationToApply, seen.expression);
38
+
34
39
  } else {
35
40
  n = this.setName({}, name, name);
36
41
  v = this.setValue(name, value);
37
42
  }
38
- const expression = `${n.prop} = ${v}`;
43
+ let expression = `${n.prop} = ${v}`;
44
+ if (operation === ItemOperations.ifNotExists) {
45
+ expression = `${n.prop} = if_not_exists(${n.prop}, ${v})`;
46
+ }
39
47
  this.seen.set(name, {
40
48
  name: n,
41
49
  value: v,
42
50
  expression,
43
51
  });
44
- this.add(operation || ItemOperations.set, expression);
52
+ this.add(operationToApply, expression);
45
53
  }
46
54
 
47
55
  remove(name) {