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

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 (31) hide show
  1. package/dist/browser/index.js +14 -14
  2. package/dist/browser/index.js.map +7 -7
  3. package/dist/node/index.cjs +150 -41
  4. package/dist/node/index.cjs.map +7 -7
  5. package/dist/node/index.js +150 -41
  6. package/dist/node/index.js.map +7 -7
  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/event-types.d.ts +10 -1
  10. package/dist/ts/domain/events/event-types.d.ts.map +1 -1
  11. package/dist/ts/domain/interfaces/repository.d.ts +26 -0
  12. package/dist/ts/domain/interfaces/repository.d.ts.map +1 -1
  13. package/dist/ts/domain/services/model-service.d.ts +19 -1
  14. package/dist/ts/domain/services/model-service.d.ts.map +1 -1
  15. package/dist/ts/domain/services/read-only-model-service.d.ts +19 -0
  16. package/dist/ts/domain/services/read-only-model-service.d.ts.map +1 -1
  17. package/dist/ts/test/mock/repositories/mock-memory-repository.d.ts +21 -3
  18. package/dist/ts/test/mock/repositories/mock-memory-repository.d.ts.map +1 -1
  19. package/dist/ts/test/mock/repositories/mock-memory-repository.trash.test.d.ts +2 -0
  20. package/dist/ts/test/mock/repositories/mock-memory-repository.trash.test.d.ts.map +1 -0
  21. package/package.json +5 -5
  22. package/src/application/model-controller.test.ts +191 -0
  23. package/src/application/model-controller.ts +44 -1
  24. package/src/domain/events/event-types.ts +9 -0
  25. package/src/domain/interfaces/repository.ts +29 -0
  26. package/src/domain/services/model-service.test.ts +307 -0
  27. package/src/domain/services/model-service.ts +88 -1
  28. package/src/domain/services/read-only-model-service.test.ts +396 -0
  29. package/src/domain/services/read-only-model-service.ts +23 -3
  30. package/src/test/mock/repositories/mock-memory-repository.trash.test.ts +736 -0
  31. 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,6 +235,15 @@ 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 {
@@ -12641,7 +12666,7 @@ class ReadOnlyModelService extends BaseModelService {
12641
12666
  async load(lookup, options) {
12642
12667
  const beforeLoadEvent = new QueryEvent(this.getDescriptor("beforeLoad" /* BeforeLoad */, options?.scope), lookup);
12643
12668
  await this.emitter.emitAsync(beforeLoadEvent);
12644
- const details = await this.repository.load(lookup);
12669
+ const details = await this.repository.load(lookup, options);
12645
12670
  const afterLoadEvent = new QueryEvent(this.getDescriptor("afterLoad" /* AfterLoad */, options?.scope), lookup).setResult(details);
12646
12671
  await this.emitter.emitAsync(afterLoadEvent);
12647
12672
  return await this.normalizeDetail(details);
@@ -12649,7 +12674,7 @@ class ReadOnlyModelService extends BaseModelService {
12649
12674
  async loadMany(lookups, options) {
12650
12675
  const beforeLoadManyEvent = new QueryEvent(this.getDescriptor("beforeLoadMany" /* BeforeLoadMany */, options?.scope), lookups);
12651
12676
  await this.emitter.emitAsync(beforeLoadManyEvent);
12652
- const details = await this.repository.loadMany(lookups);
12677
+ const details = await this.repository.loadMany(lookups, options);
12653
12678
  const afterLoadManyEvent = new QueryEvent(this.getDescriptor("afterLoadMany" /* AfterLoadMany */, options?.scope), lookups).setResult(details);
12654
12679
  await this.emitter.emitAsync(afterLoadManyEvent);
12655
12680
  return await Promise.all(details.map((detail) => this.normalizeDetail(detail)));
@@ -12821,6 +12846,30 @@ class ModelService extends ReadOnlyModelService {
12821
12846
  await Promise.all(afterEvents.map((event) => this.emitter.emitAsync(event)));
12822
12847
  return await Promise.all(results.map((result) => this.normalizeDetail(result)));
12823
12848
  }
12849
+ async emptyTrash(filters) {
12850
+ const beforeEmptyTrashEvent = new MutationEvent(this.getDescriptor("beforeEmptyTrash" /* BeforeEmptyTrash */), filters);
12851
+ await this.emitter.emitAsync(beforeEmptyTrashEvent);
12852
+ const count = await this.repository.emptyTrash(filters);
12853
+ const afterEmptyTrashEvent = new MutationEvent(this.getDescriptor("afterEmptyTrash" /* AfterEmptyTrash */), filters).setResult(count);
12854
+ await this.emitter.emitAsync(afterEmptyTrashEvent);
12855
+ return count;
12856
+ }
12857
+ async permanentlyDeleteFromTrash(lookup) {
12858
+ const beforePermanentlyDeleteFromTrashEvent = new MutationEvent(this.getDescriptor("beforePermanentlyDeleteFromTrash" /* BeforePermanentlyDeleteFromTrash */), lookup);
12859
+ await this.emitter.emitAsync(beforePermanentlyDeleteFromTrashEvent);
12860
+ const result = await this.repository.permanentlyDeleteFromTrash(lookup);
12861
+ const afterPermanentlyDeleteFromTrashEvent = new MutationEvent(this.getDescriptor("afterPermanentlyDeleteFromTrash" /* AfterPermanentlyDeleteFromTrash */), lookup).setResult(result);
12862
+ await this.emitter.emitAsync(afterPermanentlyDeleteFromTrashEvent);
12863
+ return await this.normalizeSummary(result);
12864
+ }
12865
+ async permanentlyDelete(lookup) {
12866
+ const beforePermanentlyDeleteEvent = new MutationEvent(this.getDescriptor("beforePermanentlyDelete" /* BeforePermanentlyDelete */), lookup);
12867
+ await this.emitter.emitAsync(beforePermanentlyDeleteEvent);
12868
+ const result = await this.repository.permanentlyDelete(lookup);
12869
+ const afterPermanentlyDeleteEvent = new MutationEvent(this.getDescriptor("afterPermanentlyDelete" /* AfterPermanentlyDelete */), lookup).setResult(result);
12870
+ await this.emitter.emitAsync(afterPermanentlyDeleteEvent);
12871
+ return await this.normalizeSummary(result);
12872
+ }
12824
12873
  }
12825
12874
  // src/test/mock/models/mock-book-models.ts
12826
12875
  import { ModelSchema as ModelSchema2 } from "@declaro/core";
@@ -12870,15 +12919,39 @@ class MockMemoryRepository {
12870
12919
  throw new Error("Primary key must be specified for MockMemoryRepository");
12871
12920
  }
12872
12921
  }
12873
- async load(input) {
12922
+ findOne(lookup, map2) {
12923
+ if (typeof this.args.lookup === "function") {
12924
+ return Array.from(map2.values()).find((data) => this.args.lookup(data, lookup));
12925
+ } else {
12926
+ return map2.get(lookup[this.entityMetadata.primaryKey]);
12927
+ }
12928
+ }
12929
+ findOneWithKey(lookup, map2) {
12930
+ if (typeof this.args.lookup === "function") {
12931
+ const item = Array.from(map2.values()).find((data) => this.args.lookup(data, lookup));
12932
+ if (item) {
12933
+ return { item, key: item[this.entityMetadata.primaryKey] };
12934
+ }
12935
+ } else {
12936
+ const key = lookup[this.entityMetadata.primaryKey];
12937
+ const item = map2.get(key);
12938
+ if (item) {
12939
+ return { item, key };
12940
+ }
12941
+ }
12942
+ return;
12943
+ }
12944
+ async load(input, options = {}) {
12874
12945
  if (!this.entityMetadata?.primaryKey) {
12875
12946
  throw new Error("Primary key is not defined in the schema metadata");
12876
12947
  }
12877
12948
  let item;
12878
- if (typeof this.args.lookup === "function") {
12879
- item = Array.from(this.data.values()).find((data) => this.args.lookup(data, input));
12949
+ if (options.removedOnly) {
12950
+ item = this.findOne(input, this.trash);
12951
+ } else if (options.includeRemoved) {
12952
+ item = this.findOne(input, this.data) ?? this.findOne(input, this.trash);
12880
12953
  } else {
12881
- item = await this.data.get(input[this.entityMetadata.primaryKey]);
12954
+ item = this.findOne(input, this.data);
12882
12955
  }
12883
12956
  return item || null;
12884
12957
  }
@@ -12902,7 +12975,7 @@ class MockMemoryRepository {
12902
12975
  }
12903
12976
  async search(input, options) {
12904
12977
  const pagination = options?.pagination || { page: 1, pageSize: 25 };
12905
- let items = this.applyFilters(input);
12978
+ let items = this.applyFilters(input, options);
12906
12979
  if (options?.sort && Array.isArray(options.sort)) {
12907
12980
  items = items.sort((a, b) => {
12908
12981
  for (const sortField of options.sort) {
@@ -12940,45 +13013,25 @@ class MockMemoryRepository {
12940
13013
  if (!this.entityMetadata?.primaryKey) {
12941
13014
  throw new Error("Primary key is not defined in the schema metadata");
12942
13015
  }
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) {
13016
+ const found = this.findOneWithKey(lookup, this.data);
13017
+ if (!found) {
12955
13018
  throw new Error("Item not found");
12956
13019
  }
12957
- this.trash.set(itemKey, item);
12958
- this.data.delete(itemKey);
12959
- return item;
13020
+ this.trash.set(found.key, found.item);
13021
+ this.data.delete(found.key);
13022
+ return found.item;
12960
13023
  }
12961
13024
  async restore(lookup) {
12962
13025
  if (!this.entityMetadata?.primaryKey) {
12963
13026
  throw new Error("Primary key is not defined in the schema metadata");
12964
13027
  }
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) {
13028
+ const found = this.findOneWithKey(lookup, this.trash);
13029
+ if (!found) {
12977
13030
  throw new Error("Item not found in trash");
12978
13031
  }
12979
- this.trash.delete(itemKey);
12980
- this.data.set(itemKey, item);
12981
- return item;
13032
+ this.trash.delete(found.key);
13033
+ this.data.set(found.key, found.item);
13034
+ return found.item;
12982
13035
  }
12983
13036
  async create(input) {
12984
13037
  if (!this.entityMetadata?.primaryKey) {
@@ -13024,7 +13077,7 @@ class MockMemoryRepository {
13024
13077
  return updatedItem;
13025
13078
  }
13026
13079
  async count(search, options) {
13027
- const filteredItems = this.applyFilters(search);
13080
+ const filteredItems = this.applyFilters(search, options);
13028
13081
  return filteredItems.length;
13029
13082
  }
13030
13083
  async upsert(input, options) {
@@ -13043,8 +13096,64 @@ class MockMemoryRepository {
13043
13096
  async bulkUpsert(inputs, options) {
13044
13097
  return await Promise.all(inputs.map((input) => this.upsert(input, options)));
13045
13098
  }
13046
- applyFilters(input) {
13047
- return Array.from(this.data.values()).filter((item) => {
13099
+ async permanentlyDelete(lookup) {
13100
+ if (!this.entityMetadata?.primaryKey) {
13101
+ throw new Error("Primary key is not defined in the schema metadata");
13102
+ }
13103
+ const foundInData = this.findOneWithKey(lookup, this.data);
13104
+ if (foundInData) {
13105
+ this.data.delete(foundInData.key);
13106
+ return foundInData.item;
13107
+ }
13108
+ const foundInTrash = this.findOneWithKey(lookup, this.trash);
13109
+ if (foundInTrash) {
13110
+ this.trash.delete(foundInTrash.key);
13111
+ return foundInTrash.item;
13112
+ }
13113
+ throw new Error("Item not found");
13114
+ }
13115
+ async permanentlyDeleteFromTrash(lookup) {
13116
+ if (!this.entityMetadata?.primaryKey) {
13117
+ throw new Error("Primary key is not defined in the schema metadata");
13118
+ }
13119
+ const found = this.findOneWithKey(lookup, this.trash);
13120
+ if (!found) {
13121
+ throw new Error("Item not found in trash");
13122
+ }
13123
+ this.trash.delete(found.key);
13124
+ return found.item;
13125
+ }
13126
+ async emptyTrash(filters) {
13127
+ if (!filters || Object.keys(filters).length === 0) {
13128
+ const count = this.trash.size;
13129
+ this.trash.clear();
13130
+ return count;
13131
+ }
13132
+ const itemsToDelete = [];
13133
+ for (const [key, item] of this.trash.entries()) {
13134
+ if (typeof this.args.filter === "function") {
13135
+ if (this.args.filter(item, filters)) {
13136
+ itemsToDelete.push(key);
13137
+ }
13138
+ } else {
13139
+ itemsToDelete.push(key);
13140
+ }
13141
+ }
13142
+ for (const key of itemsToDelete) {
13143
+ this.trash.delete(key);
13144
+ }
13145
+ return itemsToDelete.length;
13146
+ }
13147
+ applyFilters(input, options) {
13148
+ let sourceItems;
13149
+ if (options?.removedOnly) {
13150
+ sourceItems = Array.from(this.trash.values());
13151
+ } else if (options?.includeRemoved) {
13152
+ sourceItems = [...Array.from(this.data.values()), ...Array.from(this.trash.values())];
13153
+ } else {
13154
+ sourceItems = Array.from(this.data.values());
13155
+ }
13156
+ return sourceItems.filter((item) => {
13048
13157
  if (typeof this.args.filter === "function") {
13049
13158
  return this.args.filter(item, input);
13050
13159
  } else {
@@ -13092,5 +13201,5 @@ export {
13092
13201
  BaseModelService
13093
13202
  };
13094
13203
 
13095
- //# debugId=90127405F5173D2664756E2164756E21
13204
+ //# debugId=9D73859281C0828564756E2164756E21
13096
13205
  //# sourceMappingURL=index.js.map