@declaro/data 2.0.0-beta.120 → 2.0.0-beta.125

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 (47) hide show
  1. package/dist/browser/index.js +14 -14
  2. package/dist/browser/index.js.map +11 -11
  3. package/dist/node/index.cjs +163 -45
  4. package/dist/node/index.cjs.map +11 -11
  5. package/dist/node/index.js +163 -45
  6. package/dist/node/index.js.map +11 -11
  7. package/dist/ts/application/model-controller.d.ts +22 -1
  8. package/dist/ts/application/model-controller.d.ts.map +1 -1
  9. package/dist/ts/domain/events/domain-event.d.ts +1 -1
  10. package/dist/ts/domain/events/domain-event.d.ts.map +1 -1
  11. package/dist/ts/domain/events/event-types.d.ts +10 -1
  12. package/dist/ts/domain/events/event-types.d.ts.map +1 -1
  13. package/dist/ts/domain/events/mutation-event.d.ts +5 -2
  14. package/dist/ts/domain/events/mutation-event.d.ts.map +1 -1
  15. package/dist/ts/domain/events/query-event.d.ts +4 -2
  16. package/dist/ts/domain/events/query-event.d.ts.map +1 -1
  17. package/dist/ts/domain/events/request-event.d.ts +17 -2
  18. package/dist/ts/domain/events/request-event.d.ts.map +1 -1
  19. package/dist/ts/domain/interfaces/repository.d.ts +26 -0
  20. package/dist/ts/domain/interfaces/repository.d.ts.map +1 -1
  21. package/dist/ts/domain/services/model-service.d.ts +19 -1
  22. package/dist/ts/domain/services/model-service.d.ts.map +1 -1
  23. package/dist/ts/domain/services/read-only-model-service.d.ts +19 -0
  24. package/dist/ts/domain/services/read-only-model-service.d.ts.map +1 -1
  25. package/dist/ts/test/mock/repositories/mock-memory-repository.d.ts +21 -3
  26. package/dist/ts/test/mock/repositories/mock-memory-repository.d.ts.map +1 -1
  27. package/dist/ts/test/mock/repositories/mock-memory-repository.trash.test.d.ts +2 -0
  28. package/dist/ts/test/mock/repositories/mock-memory-repository.trash.test.d.ts.map +1 -0
  29. package/package.json +5 -5
  30. package/src/application/model-controller.test.ts +191 -0
  31. package/src/application/model-controller.ts +44 -1
  32. package/src/domain/events/domain-event.ts +1 -1
  33. package/src/domain/events/event-types.ts +9 -0
  34. package/src/domain/events/mutation-event.test.ts +369 -17
  35. package/src/domain/events/mutation-event.ts +10 -2
  36. package/src/domain/events/query-event.test.ts +218 -18
  37. package/src/domain/events/query-event.ts +8 -2
  38. package/src/domain/events/request-event.test.ts +1 -1
  39. package/src/domain/events/request-event.ts +22 -7
  40. package/src/domain/interfaces/repository.ts +29 -0
  41. package/src/domain/services/model-service.normalization.test.ts +6 -6
  42. package/src/domain/services/model-service.test.ts +311 -7
  43. package/src/domain/services/model-service.ts +88 -1
  44. package/src/domain/services/read-only-model-service.test.ts +396 -0
  45. package/src/domain/services/read-only-model-service.ts +23 -3
  46. package/src/test/mock/repositories/mock-memory-repository.trash.test.ts +736 -0
  47. package/src/test/mock/repositories/mock-memory-repository.ts +146 -46
@@ -105,6 +105,22 @@ class ModelController extends ReadOnlyModelController {
105
105
  this.authValidator.validatePermissions((v) => v.someOf([createAndUpdateValidator, this.service.getDescriptor("write", "*").toString()]));
106
106
  return this.service.bulkUpsert(inputs, options);
107
107
  }
108
+ async permanentlyDeleteFromTrash(lookup) {
109
+ this.authValidator.validatePermissions((v) => v.someOf([
110
+ this.service.getDescriptor("permanently-delete-from-trash", "*").toString(),
111
+ this.service.getDescriptor("permanently-delete", "*").toString(),
112
+ this.service.getDescriptor("empty-trash", "*").toString()
113
+ ]));
114
+ return this.service.permanentlyDeleteFromTrash(lookup);
115
+ }
116
+ async permanentlyDelete(lookup) {
117
+ this.authValidator.validatePermissions((v) => v.someOf([this.service.getDescriptor("permanently-delete", "*").toString()]));
118
+ return this.service.permanentlyDelete(lookup);
119
+ }
120
+ async emptyTrash(filters) {
121
+ this.authValidator.validatePermissions((v) => v.someOf([this.service.getDescriptor("empty-trash", "*").toString()]));
122
+ return this.service.emptyTrash(filters);
123
+ }
108
124
  }
109
125
  // src/domain/events/domain-event.ts
110
126
  import { ActionDescriptor } from "@declaro/core";
@@ -219,17 +235,29 @@ var ModelMutationAction;
219
235
  ModelMutationAction2["Restore"] = "restore";
220
236
  ModelMutationAction2["BeforeRestore"] = "beforeRestore";
221
237
  ModelMutationAction2["AfterRestore"] = "afterRestore";
238
+ ModelMutationAction2["EmptyTrash"] = "emptyTrash";
239
+ ModelMutationAction2["BeforeEmptyTrash"] = "beforeEmptyTrash";
240
+ ModelMutationAction2["AfterEmptyTrash"] = "afterEmptyTrash";
241
+ ModelMutationAction2["PermanentlyDeleteFromTrash"] = "permanentlyDeleteFromTrash";
242
+ ModelMutationAction2["BeforePermanentlyDeleteFromTrash"] = "beforePermanentlyDeleteFromTrash";
243
+ ModelMutationAction2["AfterPermanentlyDeleteFromTrash"] = "afterPermanentlyDeleteFromTrash";
244
+ ModelMutationAction2["PermanentlyDelete"] = "permanentlyDelete";
245
+ ModelMutationAction2["BeforePermanentlyDelete"] = "beforePermanentlyDelete";
246
+ ModelMutationAction2["AfterPermanentlyDelete"] = "afterPermanentlyDelete";
222
247
  })(ModelMutationAction ||= {});
223
248
  // src/domain/events/request-event.ts
224
249
  class RequestEvent extends DomainEvent {
250
+ input;
225
251
  constructor(descriptor, input, meta = {}) {
226
252
  super({
227
- meta: {
228
- ...meta,
229
- input
230
- },
253
+ meta,
231
254
  descriptor
232
255
  });
256
+ this.input = input;
257
+ }
258
+ setInput(input) {
259
+ this.input = input;
260
+ return this;
233
261
  }
234
262
  setMeta(meta) {
235
263
  this.meta = { ...this.meta, ...meta };
@@ -239,6 +267,12 @@ class RequestEvent extends DomainEvent {
239
267
  this.data = result;
240
268
  return this;
241
269
  }
270
+ toJSON() {
271
+ return {
272
+ ...super.toJSON(),
273
+ input: this.input
274
+ };
275
+ }
242
276
  }
243
277
 
244
278
  // src/domain/events/mutation-event.ts
@@ -12641,7 +12675,7 @@ class ReadOnlyModelService extends BaseModelService {
12641
12675
  async load(lookup, options) {
12642
12676
  const beforeLoadEvent = new QueryEvent(this.getDescriptor("beforeLoad" /* BeforeLoad */, options?.scope), lookup);
12643
12677
  await this.emitter.emitAsync(beforeLoadEvent);
12644
- const details = await this.repository.load(lookup);
12678
+ const details = await this.repository.load(lookup, options);
12645
12679
  const afterLoadEvent = new QueryEvent(this.getDescriptor("afterLoad" /* AfterLoad */, options?.scope), lookup).setResult(details);
12646
12680
  await this.emitter.emitAsync(afterLoadEvent);
12647
12681
  return await this.normalizeDetail(details);
@@ -12649,7 +12683,7 @@ class ReadOnlyModelService extends BaseModelService {
12649
12683
  async loadMany(lookups, options) {
12650
12684
  const beforeLoadManyEvent = new QueryEvent(this.getDescriptor("beforeLoadMany" /* BeforeLoadMany */, options?.scope), lookups);
12651
12685
  await this.emitter.emitAsync(beforeLoadManyEvent);
12652
- const details = await this.repository.loadMany(lookups);
12686
+ const details = await this.repository.loadMany(lookups, options);
12653
12687
  const afterLoadManyEvent = new QueryEvent(this.getDescriptor("afterLoadMany" /* AfterLoadMany */, options?.scope), lookups).setResult(details);
12654
12688
  await this.emitter.emitAsync(afterLoadManyEvent);
12655
12689
  return await Promise.all(details.map((detail) => this.normalizeDetail(detail)));
@@ -12821,6 +12855,30 @@ class ModelService extends ReadOnlyModelService {
12821
12855
  await Promise.all(afterEvents.map((event) => this.emitter.emitAsync(event)));
12822
12856
  return await Promise.all(results.map((result) => this.normalizeDetail(result)));
12823
12857
  }
12858
+ async emptyTrash(filters) {
12859
+ const beforeEmptyTrashEvent = new MutationEvent(this.getDescriptor("beforeEmptyTrash" /* BeforeEmptyTrash */), filters);
12860
+ await this.emitter.emitAsync(beforeEmptyTrashEvent);
12861
+ const count = await this.repository.emptyTrash(filters);
12862
+ const afterEmptyTrashEvent = new MutationEvent(this.getDescriptor("afterEmptyTrash" /* AfterEmptyTrash */), filters).setResult(count);
12863
+ await this.emitter.emitAsync(afterEmptyTrashEvent);
12864
+ return count;
12865
+ }
12866
+ async permanentlyDeleteFromTrash(lookup) {
12867
+ const beforePermanentlyDeleteFromTrashEvent = new MutationEvent(this.getDescriptor("beforePermanentlyDeleteFromTrash" /* BeforePermanentlyDeleteFromTrash */), lookup);
12868
+ await this.emitter.emitAsync(beforePermanentlyDeleteFromTrashEvent);
12869
+ const result = await this.repository.permanentlyDeleteFromTrash(lookup);
12870
+ const afterPermanentlyDeleteFromTrashEvent = new MutationEvent(this.getDescriptor("afterPermanentlyDeleteFromTrash" /* AfterPermanentlyDeleteFromTrash */), lookup).setResult(result);
12871
+ await this.emitter.emitAsync(afterPermanentlyDeleteFromTrashEvent);
12872
+ return await this.normalizeSummary(result);
12873
+ }
12874
+ async permanentlyDelete(lookup) {
12875
+ const beforePermanentlyDeleteEvent = new MutationEvent(this.getDescriptor("beforePermanentlyDelete" /* BeforePermanentlyDelete */), lookup);
12876
+ await this.emitter.emitAsync(beforePermanentlyDeleteEvent);
12877
+ const result = await this.repository.permanentlyDelete(lookup);
12878
+ const afterPermanentlyDeleteEvent = new MutationEvent(this.getDescriptor("afterPermanentlyDelete" /* AfterPermanentlyDelete */), lookup).setResult(result);
12879
+ await this.emitter.emitAsync(afterPermanentlyDeleteEvent);
12880
+ return await this.normalizeSummary(result);
12881
+ }
12824
12882
  }
12825
12883
  // src/test/mock/models/mock-book-models.ts
12826
12884
  import { ModelSchema as ModelSchema2 } from "@declaro/core";
@@ -12870,15 +12928,39 @@ class MockMemoryRepository {
12870
12928
  throw new Error("Primary key must be specified for MockMemoryRepository");
12871
12929
  }
12872
12930
  }
12873
- async load(input) {
12931
+ findOne(lookup, map2) {
12932
+ if (typeof this.args.lookup === "function") {
12933
+ return Array.from(map2.values()).find((data) => this.args.lookup(data, lookup));
12934
+ } else {
12935
+ return map2.get(lookup[this.entityMetadata.primaryKey]);
12936
+ }
12937
+ }
12938
+ findOneWithKey(lookup, map2) {
12939
+ if (typeof this.args.lookup === "function") {
12940
+ const item = Array.from(map2.values()).find((data) => this.args.lookup(data, lookup));
12941
+ if (item) {
12942
+ return { item, key: item[this.entityMetadata.primaryKey] };
12943
+ }
12944
+ } else {
12945
+ const key = lookup[this.entityMetadata.primaryKey];
12946
+ const item = map2.get(key);
12947
+ if (item) {
12948
+ return { item, key };
12949
+ }
12950
+ }
12951
+ return;
12952
+ }
12953
+ async load(input, options = {}) {
12874
12954
  if (!this.entityMetadata?.primaryKey) {
12875
12955
  throw new Error("Primary key is not defined in the schema metadata");
12876
12956
  }
12877
12957
  let item;
12878
- if (typeof this.args.lookup === "function") {
12879
- item = Array.from(this.data.values()).find((data) => this.args.lookup(data, input));
12958
+ if (options.removedOnly) {
12959
+ item = this.findOne(input, this.trash);
12960
+ } else if (options.includeRemoved) {
12961
+ item = this.findOne(input, this.data) ?? this.findOne(input, this.trash);
12880
12962
  } else {
12881
- item = await this.data.get(input[this.entityMetadata.primaryKey]);
12963
+ item = this.findOne(input, this.data);
12882
12964
  }
12883
12965
  return item || null;
12884
12966
  }
@@ -12902,7 +12984,7 @@ class MockMemoryRepository {
12902
12984
  }
12903
12985
  async search(input, options) {
12904
12986
  const pagination = options?.pagination || { page: 1, pageSize: 25 };
12905
- let items = this.applyFilters(input);
12987
+ let items = this.applyFilters(input, options);
12906
12988
  if (options?.sort && Array.isArray(options.sort)) {
12907
12989
  items = items.sort((a, b) => {
12908
12990
  for (const sortField of options.sort) {
@@ -12940,45 +13022,25 @@ class MockMemoryRepository {
12940
13022
  if (!this.entityMetadata?.primaryKey) {
12941
13023
  throw new Error("Primary key is not defined in the schema metadata");
12942
13024
  }
12943
- let item;
12944
- let itemKey;
12945
- if (typeof this.args.lookup === "function") {
12946
- item = Array.from(this.data.values()).find((data) => this.args.lookup(data, lookup));
12947
- if (item) {
12948
- itemKey = item[this.entityMetadata.primaryKey];
12949
- }
12950
- } else {
12951
- itemKey = lookup[this.entityMetadata.primaryKey];
12952
- item = this.data.get(itemKey);
12953
- }
12954
- if (!item) {
13025
+ const found = this.findOneWithKey(lookup, this.data);
13026
+ if (!found) {
12955
13027
  throw new Error("Item not found");
12956
13028
  }
12957
- this.trash.set(itemKey, item);
12958
- this.data.delete(itemKey);
12959
- return item;
13029
+ this.trash.set(found.key, found.item);
13030
+ this.data.delete(found.key);
13031
+ return found.item;
12960
13032
  }
12961
13033
  async restore(lookup) {
12962
13034
  if (!this.entityMetadata?.primaryKey) {
12963
13035
  throw new Error("Primary key is not defined in the schema metadata");
12964
13036
  }
12965
- let item;
12966
- let itemKey;
12967
- if (typeof this.args.lookup === "function") {
12968
- item = Array.from(this.trash.values()).find((data) => this.args.lookup(data, lookup));
12969
- if (item) {
12970
- itemKey = item[this.entityMetadata.primaryKey];
12971
- }
12972
- } else {
12973
- itemKey = lookup[this.entityMetadata.primaryKey];
12974
- item = this.trash.get(itemKey);
12975
- }
12976
- if (!item) {
13037
+ const found = this.findOneWithKey(lookup, this.trash);
13038
+ if (!found) {
12977
13039
  throw new Error("Item not found in trash");
12978
13040
  }
12979
- this.trash.delete(itemKey);
12980
- this.data.set(itemKey, item);
12981
- return item;
13041
+ this.trash.delete(found.key);
13042
+ this.data.set(found.key, found.item);
13043
+ return found.item;
12982
13044
  }
12983
13045
  async create(input) {
12984
13046
  if (!this.entityMetadata?.primaryKey) {
@@ -13024,7 +13086,7 @@ class MockMemoryRepository {
13024
13086
  return updatedItem;
13025
13087
  }
13026
13088
  async count(search, options) {
13027
- const filteredItems = this.applyFilters(search);
13089
+ const filteredItems = this.applyFilters(search, options);
13028
13090
  return filteredItems.length;
13029
13091
  }
13030
13092
  async upsert(input, options) {
@@ -13043,8 +13105,64 @@ class MockMemoryRepository {
13043
13105
  async bulkUpsert(inputs, options) {
13044
13106
  return await Promise.all(inputs.map((input) => this.upsert(input, options)));
13045
13107
  }
13046
- applyFilters(input) {
13047
- return Array.from(this.data.values()).filter((item) => {
13108
+ async permanentlyDelete(lookup) {
13109
+ if (!this.entityMetadata?.primaryKey) {
13110
+ throw new Error("Primary key is not defined in the schema metadata");
13111
+ }
13112
+ const foundInData = this.findOneWithKey(lookup, this.data);
13113
+ if (foundInData) {
13114
+ this.data.delete(foundInData.key);
13115
+ return foundInData.item;
13116
+ }
13117
+ const foundInTrash = this.findOneWithKey(lookup, this.trash);
13118
+ if (foundInTrash) {
13119
+ this.trash.delete(foundInTrash.key);
13120
+ return foundInTrash.item;
13121
+ }
13122
+ throw new Error("Item not found");
13123
+ }
13124
+ async permanentlyDeleteFromTrash(lookup) {
13125
+ if (!this.entityMetadata?.primaryKey) {
13126
+ throw new Error("Primary key is not defined in the schema metadata");
13127
+ }
13128
+ const found = this.findOneWithKey(lookup, this.trash);
13129
+ if (!found) {
13130
+ throw new Error("Item not found in trash");
13131
+ }
13132
+ this.trash.delete(found.key);
13133
+ return found.item;
13134
+ }
13135
+ async emptyTrash(filters) {
13136
+ if (!filters || Object.keys(filters).length === 0) {
13137
+ const count = this.trash.size;
13138
+ this.trash.clear();
13139
+ return count;
13140
+ }
13141
+ const itemsToDelete = [];
13142
+ for (const [key, item] of this.trash.entries()) {
13143
+ if (typeof this.args.filter === "function") {
13144
+ if (this.args.filter(item, filters)) {
13145
+ itemsToDelete.push(key);
13146
+ }
13147
+ } else {
13148
+ itemsToDelete.push(key);
13149
+ }
13150
+ }
13151
+ for (const key of itemsToDelete) {
13152
+ this.trash.delete(key);
13153
+ }
13154
+ return itemsToDelete.length;
13155
+ }
13156
+ applyFilters(input, options) {
13157
+ let sourceItems;
13158
+ if (options?.removedOnly) {
13159
+ sourceItems = Array.from(this.trash.values());
13160
+ } else if (options?.includeRemoved) {
13161
+ sourceItems = [...Array.from(this.data.values()), ...Array.from(this.trash.values())];
13162
+ } else {
13163
+ sourceItems = Array.from(this.data.values());
13164
+ }
13165
+ return sourceItems.filter((item) => {
13048
13166
  if (typeof this.args.filter === "function") {
13049
13167
  return this.args.filter(item, input);
13050
13168
  } else {
@@ -13092,5 +13210,5 @@ export {
13092
13210
  BaseModelService
13093
13211
  };
13094
13212
 
13095
- //# debugId=90127405F5173D2664756E2164756E21
13213
+ //# debugId=4FCC17E6392BEFF464756E2164756E21
13096
13214
  //# sourceMappingURL=index.js.map