@webda/core 3.6.0 → 3.8.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.
Files changed (109) hide show
  1. package/lib/application.d.ts +7 -1
  2. package/lib/application.js.map +1 -1
  3. package/lib/core.d.ts +9 -0
  4. package/lib/core.js +44 -1
  5. package/lib/core.js.map +1 -1
  6. package/lib/core.spec.js +5 -4
  7. package/lib/core.spec.js.map +1 -1
  8. package/lib/index.d.ts +5 -4
  9. package/lib/index.js +5 -4
  10. package/lib/index.js.map +1 -1
  11. package/lib/models/coremodel.d.ts +103 -12
  12. package/lib/models/coremodel.js +230 -33
  13. package/lib/models/coremodel.js.map +1 -1
  14. package/lib/models/coremodel.spec.js +21 -4
  15. package/lib/models/coremodel.spec.js.map +1 -1
  16. package/lib/models/ident.d.ts +2 -6
  17. package/lib/models/ident.js.map +1 -1
  18. package/lib/models/ident.spec.js.map +1 -1
  19. package/lib/models/relations.d.ts +24 -14
  20. package/lib/models/relations.js +36 -8
  21. package/lib/models/relations.js.map +1 -1
  22. package/lib/models/relations.spec.d.ts +12 -0
  23. package/lib/models/relations.spec.js +223 -0
  24. package/lib/models/relations.spec.js.map +1 -0
  25. package/lib/models/user.d.ts +2 -2
  26. package/lib/models/user.js.map +1 -1
  27. package/lib/services/asyncevents.d.ts +4 -3
  28. package/lib/services/asyncevents.js +17 -4
  29. package/lib/services/asyncevents.js.map +1 -1
  30. package/lib/services/authentication.js +1 -1
  31. package/lib/services/authentication.js.map +1 -1
  32. package/lib/services/binary.d.ts +26 -2
  33. package/lib/services/binary.js +160 -63
  34. package/lib/services/binary.js.map +1 -1
  35. package/lib/services/binary.spec.js +3 -1
  36. package/lib/services/binary.spec.js.map +1 -1
  37. package/lib/services/cloudbinary.d.ts +0 -18
  38. package/lib/services/cloudbinary.js +0 -94
  39. package/lib/services/cloudbinary.js.map +1 -1
  40. package/lib/services/cloudbinary.spec.js +18 -11
  41. package/lib/services/cloudbinary.spec.js.map +1 -1
  42. package/lib/services/domainservice.d.ts +2 -1
  43. package/lib/services/domainservice.js +13 -22
  44. package/lib/services/domainservice.js.map +1 -1
  45. package/lib/services/filebinary.js +1 -1
  46. package/lib/services/filebinary.js.map +1 -1
  47. package/lib/services/filebinary.spec.d.ts +1 -0
  48. package/lib/services/filebinary.spec.js +24 -2
  49. package/lib/services/filebinary.spec.js.map +1 -1
  50. package/lib/services/invitationservice.spec.js +3 -1
  51. package/lib/services/invitationservice.spec.js.map +1 -1
  52. package/lib/services/prometheus.js +1 -0
  53. package/lib/services/prometheus.js.map +1 -1
  54. package/lib/services/service.d.ts +0 -5
  55. package/lib/services/service.js +3 -34
  56. package/lib/services/service.js.map +1 -1
  57. package/lib/services/service.spec.js +2 -2
  58. package/lib/services/service.spec.js.map +1 -1
  59. package/lib/stores/aliasstore.js +5 -1
  60. package/lib/stores/aliasstore.js.map +1 -1
  61. package/lib/stores/file.js.map +1 -1
  62. package/lib/stores/mapper.d.ts +4 -4
  63. package/lib/stores/mapper.spec.js +1 -1
  64. package/lib/stores/mapper.spec.js.map +1 -1
  65. package/lib/stores/memory.spec.d.ts +1 -0
  66. package/lib/stores/memory.spec.js +28 -1
  67. package/lib/stores/memory.spec.js.map +1 -1
  68. package/lib/stores/modelmapper.d.ts +61 -0
  69. package/lib/stores/modelmapper.js +199 -0
  70. package/lib/stores/modelmapper.js.map +1 -0
  71. package/lib/stores/store.d.ts +33 -11
  72. package/lib/stores/store.js +155 -95
  73. package/lib/stores/store.js.map +1 -1
  74. package/lib/stores/store.spec.js +2 -2
  75. package/lib/stores/store.spec.js.map +1 -1
  76. package/lib/test.js +1 -1
  77. package/lib/test.js.map +1 -1
  78. package/lib/utils/case.d.ts +7 -0
  79. package/lib/utils/case.js +43 -0
  80. package/lib/utils/case.js.map +1 -0
  81. package/lib/utils/case.spec.d.ts +1 -0
  82. package/lib/utils/case.spec.js +50 -0
  83. package/lib/utils/case.spec.js.map +1 -0
  84. package/lib/utils/context.d.ts +3 -2
  85. package/lib/utils/context.js +6 -2
  86. package/lib/utils/context.js.map +1 -1
  87. package/lib/utils/cookie.spec.js +2 -2
  88. package/lib/utils/cookie.spec.js.map +1 -1
  89. package/lib/utils/esm.d.ts +9 -0
  90. package/lib/utils/esm.js +9 -0
  91. package/lib/utils/esm.js.map +1 -1
  92. package/lib/utils/httpcontext.d.ts +1 -1
  93. package/lib/utils/httpcontext.js +1 -0
  94. package/lib/utils/httpcontext.js.map +1 -1
  95. package/lib/utils/logger.spec.js +5 -2
  96. package/lib/utils/logger.spec.js.map +1 -1
  97. package/lib/utils/serializers.js +8 -1
  98. package/lib/utils/serializers.js.map +1 -1
  99. package/lib/utils/serializers.spec.js +6 -0
  100. package/lib/utils/serializers.spec.js.map +1 -1
  101. package/lib/utils/session.spec.js +1 -1
  102. package/lib/utils/session.spec.js.map +1 -1
  103. package/lib/utils/throttler.d.ts +22 -2
  104. package/lib/utils/throttler.js +35 -3
  105. package/lib/utils/throttler.js.map +1 -1
  106. package/lib/utils/throttler.spec.js +10 -2
  107. package/lib/utils/throttler.spec.js.map +1 -1
  108. package/package.json +10 -10
  109. package/webda.module.json +60 -26
@@ -57,6 +57,7 @@ export class StoreParameters extends ServiceParameters {
57
57
  this.forceModel ?? (this.forceModel = false);
58
58
  this.slowQueryThreshold ?? (this.slowQueryThreshold = 30000);
59
59
  this.modelAliases ?? (this.modelAliases = {});
60
+ this.additionalModels ?? (this.additionalModels = []);
60
61
  }
61
62
  }
62
63
  /**
@@ -139,6 +140,21 @@ class Store extends Service {
139
140
  if (!this.parameters.strict) {
140
141
  recursive(this._model.getHierarchy().children, 1);
141
142
  }
143
+ // Add additional models
144
+ if (this.parameters.additionalModels.length) {
145
+ // Strict mode is to only allow one model per store
146
+ if (this.parameters.strict) {
147
+ this.log("ERROR", "Cannot add additional models in strict mode");
148
+ }
149
+ else {
150
+ for (let modelType of this.parameters.additionalModels) {
151
+ const model = app.getModel(modelType);
152
+ this._modelsHierarchy[model.getIdentifier(false)] = 0;
153
+ this._modelsHierarchy[model.getIdentifier()] = 0;
154
+ recursive(model.getHierarchy().children, 1);
155
+ }
156
+ }
157
+ }
142
158
  if (this.getParameters().expose) {
143
159
  this.log("WARN", "Exposing a store is not recommended, use a DomainService instead to expose all your CoreModel");
144
160
  }
@@ -371,12 +387,7 @@ class Store extends Service {
371
387
  */
372
388
  initModel(object = {}) {
373
389
  var _a;
374
- if (object instanceof CoreModel) {
375
- object.__type ?? (object.__type = this.getWebda().getApplication().getModelFromInstance(object) || this._modelType);
376
- }
377
- else {
378
- object.__type ?? (object.__type = this._modelType);
379
- }
390
+ object.__type ?? (object.__type = this.getWebda().getApplication().getModelFromInstance(object) || this._modelType);
380
391
  // Make sure to send a model object
381
392
  if (!(object instanceof this._model)) {
382
393
  // Dynamic load type
@@ -391,11 +402,11 @@ class Store extends Service {
391
402
  if (!this.parameters.defaultModel) {
392
403
  throw new Error(`Unknown model ${object.__type} found for Store(${this.getName()})`);
393
404
  }
394
- object = this._model.factory(this._model, object);
405
+ object = this._model.factory(object);
395
406
  }
396
407
  }
397
408
  else {
398
- object = this._model.factory(this._model, object);
409
+ object = this._model.factory(object);
399
410
  }
400
411
  }
401
412
  if (!object.getUuid()) {
@@ -455,7 +466,7 @@ class Store extends Service {
455
466
  this.metrics.operations_total.inc({ operation: "increment" });
456
467
  await this._incrementAttributes(uid, params, updateDate);
457
468
  await this._cacheStore?._incrementAttributes(uid, params, updateDate);
458
- return this.emitSync("Store.PartialUpdated", {
469
+ this.emitSync("Store.PartialUpdated", {
459
470
  object_id: uid,
460
471
  store: this,
461
472
  updateDate,
@@ -463,6 +474,7 @@ class Store extends Service {
463
474
  increments: params
464
475
  }
465
476
  });
477
+ return updateDate;
466
478
  }
467
479
  /**
468
480
  * Helper function that call incrementAttributes
@@ -501,6 +513,7 @@ class Store extends Service {
501
513
  }
502
514
  }
503
515
  });
516
+ return updateDate;
504
517
  }
505
518
  /**
506
519
  * Remove an item from an array in the model
@@ -527,29 +540,48 @@ class Store extends Service {
527
540
  }
528
541
  }
529
542
  });
543
+ return updateDate;
530
544
  }
531
545
  /**
532
- * Get all results without pagination
546
+ * Iterate through the results
533
547
  *
534
548
  * This can be resource consuming
535
549
  *
536
550
  * @param query
537
551
  * @param context
538
552
  */
539
- async queryAll(query, context) {
540
- const res = [];
553
+ async *iterate(query = "", context) {
541
554
  if (query.includes("OFFSET")) {
542
- throw new Error("Cannot contain an OFFSET for queryAll method");
555
+ throw new Error("Cannot contain an OFFSET for iterate method");
543
556
  }
544
557
  let continuationToken;
545
558
  do {
546
559
  let q = query + (continuationToken !== undefined ? ` OFFSET "${continuationToken}"` : "");
547
560
  let page = await this.query(q, context);
561
+ for (let item of page.results) {
562
+ yield item;
563
+ }
548
564
  continuationToken = page.continuationToken;
549
- res.push(...page.results);
550
565
  } while (continuationToken);
566
+ }
567
+ // REFACTOR . >= 4
568
+ /**
569
+ * Query all the results
570
+ *
571
+ *
572
+ * @param query
573
+ * @param context
574
+ * @returns
575
+ * @deprecated use iterate instead
576
+ */
577
+ async queryAll(query, context) {
578
+ let res = [];
579
+ for await (let item of this.iterate(query, context)) {
580
+ res.push(item);
581
+ }
551
582
  return res;
552
583
  }
584
+ // END_REFACTOR
553
585
  /**
554
586
  * Check that __type Comparison is only used with = and CONTAINS
555
587
  * If CONTAINS is used, move __type to __types
@@ -718,30 +750,42 @@ class Store extends Service {
718
750
  async create(object, ctx = undefined) {
719
751
  object = this.initModel(object);
720
752
  // Dates should be store by the Store
721
- object._creationDate ?? (object._creationDate = new Date());
722
- object._lastUpdate = new Date();
753
+ if (!object._creationDate) {
754
+ object._creationDate = object._lastUpdate = new Date();
755
+ }
756
+ else {
757
+ object._lastUpdate = new Date();
758
+ }
723
759
  const ancestors = this.getWebda().getApplication().getModelHierarchy(object.__type).ancestors;
724
760
  object.__types = [object.__type, ...ancestors].filter(i => i !== "Webda/CoreModel" && i !== "CoreModel");
725
761
  if (ctx) {
726
762
  object.setContext(ctx);
727
763
  }
728
- await this.emitSync("Store.Save", {
764
+ // Handle object auto listener
765
+ const evt = {
729
766
  object: object,
730
767
  store: this,
731
768
  context: ctx
732
- });
733
- // Handle object auto listener
734
- await object._onSave();
769
+ };
770
+ await Promise.all([
771
+ this.emitSync("Store.Save", evt),
772
+ object?.__class.emitSync("Store.Save", evt),
773
+ object._onSave()
774
+ ]);
735
775
  this.metrics.operations_total.inc({ operation: "save" });
736
776
  let res = await this._save(object);
737
777
  await this._cacheStore?._save(object);
738
778
  object = this.initModel(res);
739
- await this.emitSync("Store.Saved", {
779
+ const evtSaved = {
740
780
  object: object,
741
781
  store: this,
742
782
  context: ctx
743
- });
744
- await object._onSaved();
783
+ };
784
+ await Promise.all([
785
+ this.emitSync("Store.Saved", evtSaved),
786
+ object?.__class.emitSync("Store.Saved", evtSaved),
787
+ object._onSaved()
788
+ ]);
745
789
  return object;
746
790
  }
747
791
  /**
@@ -863,30 +907,27 @@ class Store extends Service {
863
907
  }
864
908
  object._lastUpdate = new Date();
865
909
  this.metrics.operations_total.inc({ operation: "get" });
866
- let load = await this._getFromCache(object[this._uuidField], true);
910
+ const uuid = object.getUuid ? object.getUuid() : object[this._uuidField];
911
+ let load = await this._getFromCache(uuid, true);
867
912
  if (load.__type !== this._modelType && this.parameters.strict) {
868
- this.log("WARN", `Object '${object[this._uuidField]}' was not created by this store ${load.__type}:${this._modelType}`);
869
- throw new StoreNotFoundError(object[this._uuidField], this.getName());
913
+ this.log("WARN", `Object '${uuid}' was not created by this store ${load.__type}:${this._modelType}`);
914
+ throw new StoreNotFoundError(uuid, this.getName());
870
915
  }
871
916
  loaded = this.initModel(load);
872
917
  if (object instanceof CoreModel) {
873
918
  loaded.setContext(object.getContext());
874
919
  }
875
- if (partial) {
876
- await this.emitSync(`Store.PatchUpdate`, {
877
- object: loaded,
878
- store: this,
879
- update: object
880
- });
881
- }
882
- else {
883
- await this.emitSync(`Store.Update`, {
884
- object: loaded,
885
- store: this,
886
- update: object
887
- });
888
- }
889
- await loaded._onUpdate(object);
920
+ const update = object;
921
+ const evt = {
922
+ object: loaded,
923
+ store: this,
924
+ update
925
+ };
926
+ await Promise.all([
927
+ this.emitSync(partial ? `Store.PatchUpdate` : `Store.Update`, evt),
928
+ object?.__class?.emitSync(partial ? `Store.PatchUpdate` : `Store.Update`, evt),
929
+ loaded._onUpdate(object)
930
+ ]);
890
931
  let res;
891
932
  if (conditionField !== null) {
892
933
  conditionField ?? (conditionField = "_lastUpdate");
@@ -894,8 +935,10 @@ class Store extends Service {
894
935
  }
895
936
  if (partial) {
896
937
  this.metrics.operations_total.inc({ operation: "partialUpdate" });
897
- await this._patch(object, object[this._uuidField], conditionValue, conditionField);
898
- await this._cacheStore?._patch(object, object[this._uuidField], load._lastUpdate, "_lastUpdate");
938
+ await Promise.all([
939
+ this._patch(object, uuid, conditionValue, conditionField),
940
+ this._cacheStore?._patch(object, uuid, load._lastUpdate, "_lastUpdate")
941
+ ]);
899
942
  res = object;
900
943
  }
901
944
  else {
@@ -905,30 +948,27 @@ class Store extends Service {
905
948
  }
906
949
  object = this.initModel(object);
907
950
  this.metrics.operations_total.inc({ operation: "update" });
908
- res = await this._update(object, object[this._uuidField], conditionValue, conditionField);
909
- await this._cacheStore?._update(object, object[this._uuidField], load._lastUpdate, "_lastUpdate");
910
- }
911
- // Return updated
912
- for (let i in res) {
913
- loaded[i] = res[i];
914
- }
915
- for (let i in object) {
916
- loaded[i] = object[i];
917
- }
918
- saved = this.initModel(loaded);
919
- if (partial) {
920
- await this.emitSync(`Store.PatchUpdated`, {
921
- object: saved,
922
- store: this
923
- });
924
- }
925
- else {
926
- await this.emitSync(`Store.Updated`, {
927
- object: saved,
928
- store: this
929
- });
930
- }
931
- await saved._onUpdated();
951
+ res = (await Promise.all([
952
+ this._update(object, uuid, conditionValue, conditionField),
953
+ this._cacheStore?._update(object, uuid, load._lastUpdate, "_lastUpdate")
954
+ ]))[0];
955
+ }
956
+ // Reinit save
957
+ saved = this.initModel({
958
+ ...loaded,
959
+ ...res
960
+ });
961
+ const evtUpdated = {
962
+ object: saved,
963
+ store: this,
964
+ update,
965
+ previous: loaded
966
+ };
967
+ await Promise.all([
968
+ this.emitSync(partial ? `Store.PatchUpdated` : `Store.Updated`, evtUpdated),
969
+ saved?.__class.emitSync(partial ? `Store.PatchUpdated` : `Store.Updated`, evtUpdated),
970
+ saved._onUpdated()
971
+ ]);
932
972
  return saved;
933
973
  }
934
974
  /**
@@ -1133,12 +1173,16 @@ class Store extends Service {
1133
1173
  throw new UpdateConditionFailError(to_delete.getUuid(), writeConditionField, writeCondition);
1134
1174
  }
1135
1175
  }
1136
- // Send preevent
1137
- await this.emitSync("Store.Delete", {
1176
+ const evt = {
1138
1177
  object: to_delete,
1139
1178
  store: this
1140
- });
1141
- await to_delete._onDelete();
1179
+ };
1180
+ // Send preevent
1181
+ await Promise.all([
1182
+ this.emitSync("Store.Delete", evt),
1183
+ to_delete?.__class.emitSync("Store.Delete", evt),
1184
+ to_delete._onDelete()
1185
+ ]);
1142
1186
  // If async we just tag the object as deleted
1143
1187
  if (this.parameters.asyncDelete && !sync) {
1144
1188
  this.metrics.operations_total.inc({ operation: "partialUpdate" });
@@ -1156,11 +1200,15 @@ class Store extends Service {
1156
1200
  await this._cacheStore?._delete(to_delete.getUuid(), writeCondition, writeConditionField);
1157
1201
  }
1158
1202
  // Send post event
1159
- await this.emitSync("Store.Deleted", {
1203
+ const evtDeleted = {
1160
1204
  object: to_delete,
1161
1205
  store: this
1162
- });
1163
- await to_delete._onDeleted();
1206
+ };
1207
+ await Promise.all([
1208
+ this.emitSync("Store.Deleted", evtDeleted),
1209
+ to_delete.__class.emitSync("Store.Deleted", evtDeleted),
1210
+ to_delete._onDeleted()
1211
+ ]);
1164
1212
  }
1165
1213
  /**
1166
1214
  * By default we cannot know if the store will trigger or not
@@ -1224,12 +1272,12 @@ class Store extends Service {
1224
1272
  }
1225
1273
  object = this.initModel(object);
1226
1274
  object.setContext(ctx);
1227
- await this.emitSync("Store.Get", {
1275
+ const evt = {
1228
1276
  object: object,
1229
1277
  store: this,
1230
1278
  context: ctx
1231
- });
1232
- await object._onGet();
1279
+ };
1280
+ await Promise.all([this.emitSync("Store.Get", evt), object.__class.emitSync("Store.Get", evt), object._onGet()]);
1233
1281
  return object;
1234
1282
  }
1235
1283
  /**
@@ -1328,7 +1376,7 @@ class Store extends Service {
1328
1376
  async operationCreate(ctx, model) {
1329
1377
  let body = await ctx.getInput();
1330
1378
  const modelPrototype = this.getWebda().getApplication().getModel(model);
1331
- let object = modelPrototype.factory(modelPrototype, body, ctx);
1379
+ let object = modelPrototype.factory(body, ctx);
1332
1380
  object._creationDate = new Date();
1333
1381
  await object.checkAct(ctx, "create");
1334
1382
  try {
@@ -1343,12 +1391,13 @@ class Store extends Service {
1343
1391
  }
1344
1392
  await this.save(object, ctx);
1345
1393
  ctx.write(object);
1346
- await this.emitSync("Store.WebCreate", {
1394
+ const evt = {
1347
1395
  context: ctx,
1348
1396
  values: body,
1349
1397
  object: object,
1350
1398
  store: this
1351
- });
1399
+ };
1400
+ await Promise.all([object.__class.emitSync("Store.WebCreate", evt), this.emitSync("Store.WebCreate", evt)]);
1352
1401
  }
1353
1402
  /**
1354
1403
  * Handle obect action
@@ -1361,23 +1410,28 @@ class Store extends Service {
1361
1410
  throw new WebdaError.NotFound("Object not found or is deleted");
1362
1411
  }
1363
1412
  await object.checkAct(ctx, action);
1364
- await this.emitSync("Store.Action", {
1413
+ const evt = {
1365
1414
  action: action,
1366
1415
  object: object,
1367
1416
  store: this,
1368
1417
  context: ctx
1369
- });
1418
+ };
1419
+ await Promise.all([this.emitSync("Store.Action", evt), object.__class.emitSync("Store.Action", evt)]);
1370
1420
  const res = await object[action](ctx);
1371
1421
  if (res) {
1372
1422
  ctx.write(res);
1373
1423
  }
1374
- await this.emitSync("Store.Actioned", {
1424
+ const evtActioned = {
1375
1425
  action: action,
1376
1426
  object: object,
1377
1427
  store: this,
1378
1428
  context: ctx,
1379
1429
  result: res
1380
- });
1430
+ };
1431
+ await Promise.all([
1432
+ this.emitSync("Store.Actioned", evtActioned),
1433
+ object?.__class.emitSync("Store.Actioned", evtActioned)
1434
+ ]);
1381
1435
  }
1382
1436
  /**
1383
1437
  * Handle collection action
@@ -1385,23 +1439,25 @@ class Store extends Service {
1385
1439
  */
1386
1440
  async httpGlobalAction(ctx, model = this._model) {
1387
1441
  let action = ctx.getHttpContext().getUrl().split("/").pop();
1388
- await this.emitSync("Store.Action", {
1442
+ const evt = {
1389
1443
  action: action,
1390
1444
  store: this,
1391
1445
  context: ctx,
1392
1446
  model
1393
- });
1447
+ };
1448
+ await Promise.all([this.emitSync("Store.Action", evt), model.emitSync("Store.Action", evt)]);
1394
1449
  const res = await model[action](ctx);
1395
1450
  if (res) {
1396
1451
  ctx.write(res);
1397
1452
  }
1398
- await this.emitSync("Store.Actioned", {
1453
+ const evtActioned = {
1399
1454
  action: action,
1400
1455
  store: this,
1401
1456
  context: ctx,
1402
1457
  result: res,
1403
1458
  model
1404
- });
1459
+ };
1460
+ await Promise.all([this.emitSync("Store.Actioned", evtActioned), model?.emitSync("Store.Actioned", evtActioned)]);
1405
1461
  }
1406
1462
  /**
1407
1463
  * Handle HTTP Update for an object
@@ -1432,7 +1488,8 @@ class Store extends Service {
1432
1488
  delete updateObject[i];
1433
1489
  });
1434
1490
  updateObject.setContext(ctx);
1435
- updateObject.load(body);
1491
+ updateObject.setUuid(uuid);
1492
+ updateObject.load(body, false, false);
1436
1493
  await this.patch(updateObject);
1437
1494
  object = undefined;
1438
1495
  }
@@ -1457,13 +1514,14 @@ class Store extends Service {
1457
1514
  object = await this.update(updateObject);
1458
1515
  }
1459
1516
  ctx.write(object);
1460
- await this.emitSync("Store.WebUpdate", {
1517
+ const evt = {
1461
1518
  context: ctx,
1462
1519
  updates: body,
1463
1520
  object: object,
1464
1521
  store: this,
1465
1522
  method: ctx.getHttpContext().getMethod()
1466
- });
1523
+ };
1524
+ await Promise.all([object?.__class.emitSync("Store.WebUpdate", evt), this.emitSync("Store.WebUpdate", evt)]);
1467
1525
  }
1468
1526
  /**
1469
1527
  * Handle GET on object
@@ -1483,11 +1541,12 @@ class Store extends Service {
1483
1541
  }
1484
1542
  await object.checkAct(ctx, "get");
1485
1543
  ctx.write(object);
1486
- await this.emitSync("Store.WebGet", {
1544
+ const evt = {
1487
1545
  context: ctx,
1488
1546
  object: object,
1489
1547
  store: this
1490
- });
1548
+ };
1549
+ await Promise.all([this.emitSync("Store.WebGet", evt), object.__class.emitSync("Store.WebGet", evt)]);
1491
1550
  ctx.write(object);
1492
1551
  }
1493
1552
  /**
@@ -1507,11 +1566,12 @@ class Store extends Service {
1507
1566
  // Might still run into: Have trouble to handle the Content-Length on API Gateway so returning an empty object for now
1508
1567
  ctx.writeHead(204, { "Content-Length": "0" });
1509
1568
  await this.delete(uuid);
1510
- await this.emitSync("Store.WebDelete", {
1569
+ const evt = {
1511
1570
  context: ctx,
1512
1571
  object_id: uuid,
1513
1572
  store: this
1514
- });
1573
+ };
1574
+ await Promise.all([this.emitSync("Store.WebDelete", evt), object.__class.emitSync("Store.WebDelete", evt)]);
1515
1575
  }
1516
1576
  /**
1517
1577
  * Return the model uuid field