@ddd-ts/event-sourcing-firestore 0.0.36 → 0.0.38

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 (95) hide show
  1. package/LICENSE +21 -0
  2. package/dist/_virtual/_rolldown/runtime.js +29 -0
  3. package/dist/firestore.event-lake.aggregate-store.d.ts +4 -8
  4. package/dist/firestore.event-lake.aggregate-store.d.ts.map +1 -1
  5. package/dist/firestore.event-lake.aggregate-store.js +35 -33
  6. package/dist/firestore.event-lake.aggregate-store.mjs +36 -0
  7. package/dist/firestore.event-lake.storage-layer.d.ts +2 -2
  8. package/dist/firestore.event-lake.storage-layer.d.ts.map +1 -1
  9. package/dist/firestore.event-lake.storage-layer.js +67 -117
  10. package/dist/firestore.event-lake.storage-layer.mjs +65 -0
  11. package/dist/firestore.event-lake.store.d.ts +1 -1
  12. package/dist/firestore.event-lake.store.d.ts.map +1 -1
  13. package/dist/firestore.event-lake.store.js +14 -12
  14. package/dist/firestore.event-lake.store.mjs +13 -0
  15. package/dist/firestore.event-stream.aggregate-store.d.ts +2 -2
  16. package/dist/firestore.event-stream.aggregate-store.d.ts.map +1 -1
  17. package/dist/firestore.event-stream.aggregate-store.js +35 -37
  18. package/dist/firestore.event-stream.aggregate-store.mjs +36 -0
  19. package/dist/firestore.event-stream.storage-layer.d.ts +2 -2
  20. package/dist/firestore.event-stream.storage-layer.d.ts.map +1 -1
  21. package/dist/firestore.event-stream.storage-layer.js +67 -110
  22. package/dist/firestore.event-stream.storage-layer.mjs +65 -0
  23. package/dist/firestore.event-stream.store.d.ts +1 -1
  24. package/dist/firestore.event-stream.store.d.ts.map +1 -1
  25. package/dist/firestore.event-stream.store.js +14 -12
  26. package/dist/firestore.event-stream.store.mjs +13 -0
  27. package/dist/firestore.projected-stream.reader.d.ts +1 -1
  28. package/dist/firestore.projected-stream.reader.d.ts.map +1 -1
  29. package/dist/firestore.projected-stream.reader.js +35 -37
  30. package/dist/firestore.projected-stream.reader.mjs +34 -0
  31. package/dist/firestore.projected-stream.storage-layer.d.ts +1 -1
  32. package/dist/firestore.projected-stream.storage-layer.d.ts.map +1 -1
  33. package/dist/firestore.projected-stream.storage-layer.js +119 -140
  34. package/dist/firestore.projected-stream.storage-layer.mjs +118 -0
  35. package/dist/firestore.snapshotter.js +36 -40
  36. package/dist/firestore.snapshotter.mjs +35 -0
  37. package/dist/index.js +30 -32
  38. package/dist/index.mjs +12 -0
  39. package/dist/projection/firestore.projector.d.ts +1 -1
  40. package/dist/projection/firestore.projector.d.ts.map +1 -1
  41. package/dist/projection/firestore.projector.js +477 -630
  42. package/dist/projection/firestore.projector.mjs +479 -0
  43. package/dist/projection/testkit/case-fixture.d.ts.map +1 -1
  44. package/dist/projection/testkit.d.ts +1 -1
  45. package/dist/projection/testkit.d.ts.map +1 -1
  46. package/package.json +43 -32
  47. package/dist/firestore.event-lake.aggregate-store.js.map +0 -1
  48. package/dist/firestore.event-lake.aggregate-store.spec.js +0 -58
  49. package/dist/firestore.event-lake.aggregate-store.spec.js.map +0 -1
  50. package/dist/firestore.event-lake.storage-layer.js.map +0 -1
  51. package/dist/firestore.event-lake.store.js.map +0 -1
  52. package/dist/firestore.event-lake.store.spec.js +0 -50
  53. package/dist/firestore.event-lake.store.spec.js.map +0 -1
  54. package/dist/firestore.event-stream-store.spec.js +0 -50
  55. package/dist/firestore.event-stream-store.spec.js.map +0 -1
  56. package/dist/firestore.event-stream.aggregate-store.js.map +0 -1
  57. package/dist/firestore.event-stream.aggregate-store.spec.js +0 -54
  58. package/dist/firestore.event-stream.aggregate-store.spec.js.map +0 -1
  59. package/dist/firestore.event-stream.storage-layer.js.map +0 -1
  60. package/dist/firestore.event-stream.store.js.map +0 -1
  61. package/dist/firestore.projected-stream.reader.js.map +0 -1
  62. package/dist/firestore.projected-stream.reader.spec.js +0 -54
  63. package/dist/firestore.projected-stream.reader.spec.js.map +0 -1
  64. package/dist/firestore.projected-stream.storage-layer.js.map +0 -1
  65. package/dist/firestore.snapshotter.js.map +0 -1
  66. package/dist/index.js.map +0 -1
  67. package/dist/projection/cases/attempts.spec.js +0 -42
  68. package/dist/projection/cases/attempts.spec.js.map +0 -1
  69. package/dist/projection/cases/batchlast.spec.js +0 -51
  70. package/dist/projection/cases/batchlast.spec.js.map +0 -1
  71. package/dist/projection/cases/bigshuffle.spec.js +0 -59
  72. package/dist/projection/cases/bigshuffle.spec.js.map +0 -1
  73. package/dist/projection/cases/burst.spec.js +0 -38
  74. package/dist/projection/cases/burst.spec.js.map +0 -1
  75. package/dist/projection/cases/claimtimeout.spec.js +0 -40
  76. package/dist/projection/cases/claimtimeout.spec.js.map +0 -1
  77. package/dist/projection/cases/concurrency.spec.js +0 -49
  78. package/dist/projection/cases/concurrency.spec.js.map +0 -1
  79. package/dist/projection/cases/deduplicate.spec.js +0 -22
  80. package/dist/projection/cases/deduplicate.spec.js.map +0 -1
  81. package/dist/projection/cases/defer.spec.js +0 -44
  82. package/dist/projection/cases/defer.spec.js.map +0 -1
  83. package/dist/projection/cases/lock.spec.js +0 -91
  84. package/dist/projection/cases/lock.spec.js.map +0 -1
  85. package/dist/projection/cases/skip.spec.js +0 -86
  86. package/dist/projection/cases/skip.spec.js.map +0 -1
  87. package/dist/projection/cases/stress.spec.js +0 -73
  88. package/dist/projection/cases/stress.spec.js.map +0 -1
  89. package/dist/projection/firestore.projector.js.map +0 -1
  90. package/dist/projection/testkit/case-fixture.js +0 -341
  91. package/dist/projection/testkit/case-fixture.js.map +0 -1
  92. package/dist/projection/testkit.js +0 -77
  93. package/dist/projection/testkit.js.map +0 -1
  94. package/dist/projection/trace.decorator.js +0 -35
  95. package/dist/projection/trace.decorator.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"firestore.event-lake.aggregate-store.spec.js","sourceRoot":"","sources":["../src/firestore.event-lake.aggregate-store.spec.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,OAAO,CAAC,GAAG,CAAC,uBAAuB,GAAG,gBAAgB,CAAC;AACvD,mDAAqC;AAErC,uCAMsB;AACtB,6DAGiC;AACjC,iGAA0F;AAE1F,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;AAEvB,QAAQ,CAAC,kCAAkC,EAAE,GAAG,EAAE;IAChD,MAAM,GAAG,GAAG,EAAE,CAAC,aAAa,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC,CAAC;IACvD,MAAM,QAAQ,GAAG,GAAG,CAAC,SAAS,EAAE,CAAC;IAEjC,MAAM,cAEJ,SAAQ,uEAAmC;QAC3C,SAAS,CAAC,QAAW;YACnB,OAAO,aAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,CAAC;QACzE,CAAC;KACF;IAED,IAAA,mCAA4B,EAAC;QAC3B,WAAW,EAAE,IAAI,+CAA6B,CAAC,QAAQ,CAAC;QACxD,iBAAiB,EAAE,CAAC,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE;YACrD,OAAO,IAAI,cAAc,CACvB,QAAQ,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,EACnC,UAAU,EACV,QAAQ,CACT,CAAC;QACJ,CAAC;QACD,QAAQ,EAAE,CACR,IAAY,EACZ,UAA0B,EAC1B,EAAE,CAAC,IAAI,gCAAc,CAAI,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,UAAU,CAAC;KAClE,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["process.env.FIRESTORE_EMULATOR_HOST = \"localhost:8080\";\nimport * as fb from \"firebase-admin\";\n\nimport {\n EventLakeAggregateStoreSuite,\n IEventSourced,\n IIdentifiable,\n LakeId,\n type ISerializer,\n} from \"@ddd-ts/core\";\nimport {\n FirestoreStore,\n FirestoreTransactionPerformer,\n} from \"@ddd-ts/store-firestore\";\nimport { FirestoreEventLakeAggregateStore } from \"./firestore.event-lake.aggregate-store\";\n\njest.setTimeout(10000);\n\ndescribe(\"FirestoreEventLakeAggregateStore\", () => {\n const app = fb.initializeApp({ projectId: \"demo-es\" });\n const database = app.firestore();\n\n class AggregateStore<\n T extends IEventSourced & IIdentifiable,\n > extends FirestoreEventLakeAggregateStore<T> {\n getLakeId(instance: T): LakeId {\n return LakeId.from(instance.constructor.name, instance.id.serialize());\n }\n }\n\n EventLakeAggregateStoreSuite({\n transaction: new FirestoreTransactionPerformer(database),\n getAggregateStore: (AGGREGATE, serializer, eventBus) => {\n return new AggregateStore(\n database.collection(AGGREGATE.name),\n serializer,\n eventBus,\n );\n },\n getStore: <T extends IIdentifiable>(\n name: string,\n serializer: ISerializer<T>,\n ) => new FirestoreStore<T>(database.collection(name), serializer),\n });\n});\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"firestore.event-lake.storage-layer.js","sourceRoot":"","sources":["../src/firestore.event-lake.storage-layer.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n LakeId,\n EventId,\n type ISerializedChange,\n type ISerializedFact,\n EventLakeStorageLayer,\n} from \"@ddd-ts/core\";\nimport { ISerializedSavedChange } from \"@ddd-ts/core/dist/interfaces/es-event\";\n\nimport {\n DefaultConverter,\n FirestoreTransaction,\n} from \"@ddd-ts/store-firestore\";\nimport * as fb from \"firebase-admin\";\n\nexport const serverTimestamp = fb.firestore.FieldValue.serverTimestamp;\n\nexport class FirestoreEventLakeStorageLayer implements EventLakeStorageLayer {\n constructor(\n public readonly firestore: fb.firestore.Firestore,\n public readonly converter = new DefaultConverter(),\n ) {}\n\n getCollection(lakeId: LakeId) {\n return this.firestore\n .collection(\"event-store\")\n .doc(\"Lakes\")\n .collection(lakeId.shardType)\n .doc(lakeId.shardId)\n .collection(\"events\");\n }\n\n async append(\n lakeId: LakeId,\n changes: ISerializedChange[],\n trx: FirestoreTransaction,\n ) {\n const collection = this.getCollection(lakeId);\n\n const result: ISerializedSavedChange[] = [];\n\n for (const change of changes) {\n const revision = trx.increment();\n const storageChange = {\n eventId: change.id,\n name: change.name,\n payload: change.payload,\n occurredAt: serverTimestamp(),\n version: change.version,\n revision,\n };\n\n const ref = collection.doc(change.id);\n trx.transaction.create(ref, this.converter.toFirestore(storageChange));\n\n result.push({\n ...change,\n ref: ref.path,\n revision,\n occurredAt: undefined,\n });\n }\n\n return result;\n }\n\n async *read(\n lakeId: LakeId,\n startAfter?: EventId,\n endAt?: EventId,\n ): AsyncIterable<ISerializedFact> {\n const collection = this.getCollection(lakeId);\n\n const [start, end] = await Promise.all([\n startAfter ? collection.doc(startAfter.serialize()).get() : null,\n endAt ? collection.doc(endAt.serialize()).get() : null,\n ]);\n\n if (startAfter && !start?.exists) {\n throw new Error(`StartAfter event not found: ${startAfter}`);\n }\n\n if (endAt && !end?.exists) {\n throw new Error(`EndAt event not found: ${endAt}`);\n }\n\n let query = collection\n .orderBy(\"occurredAt\", \"asc\")\n .orderBy(\"revision\", \"asc\");\n\n if (start) {\n query = query.startAfter(start);\n }\n\n if (endAt) {\n query = query.endAt(end);\n }\n\n for await (const event of query.stream()) {\n const e = event as any as fb.firestore.QueryDocumentSnapshot<any>;\n const data = this.converter.fromFirestore(e);\n yield {\n id: data.eventId,\n ref: e.ref.path,\n revision: data.revision,\n name: data.name,\n $name: data.name,\n payload: data.payload,\n occurredAt: data.occurredAt,\n version: data.version ?? 1,\n } as ISerializedFact;\n }\n }\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"firestore.event-lake.store.js","sourceRoot":"","sources":["../src/firestore.event-lake.store.ts"],"names":[],"mappings":";;;AAAA,uCAAgF;AAChF,6FAAsF;AAGtF,MAAa,uBAEX,SAAQ,qBAAqB;IAC7B,YACE,SAAoB,EACpB,UAA8B,EAC9B,QAAoB;QAEpB,KAAK,CAAC,IAAI,mEAA8B,CAAC,SAAS,CAAC,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC;IAC7E,CAAC;CACF;AAVD,0DAUC","sourcesContent":["import { EventLakeStore, IEsEvent, IEventBus, ISerializer } from \"@ddd-ts/core\";\nimport { FirestoreEventLakeStorageLayer } from \"./firestore.event-lake.storage-layer\";\nimport { Firestore } from \"firebase-admin/firestore\";\n\nexport class FirestoreEventLakeStore<\n Event extends IEsEvent,\n> extends EventLakeStore<Event> {\n constructor(\n firestore: Firestore,\n serializer: ISerializer<Event>,\n eventBus?: IEventBus,\n ) {\n super(new FirestoreEventLakeStorageLayer(firestore), serializer, eventBus);\n }\n}\n"]}
@@ -1,50 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- Object.defineProperty(exports, "__esModule", { value: true });
36
- process.env.FIRESTORE_EMULATOR_HOST = "localhost:8080";
37
- const fb = __importStar(require("firebase-admin"));
38
- const store_firestore_1 = require("@ddd-ts/store-firestore");
39
- const core_1 = require("@ddd-ts/core");
40
- const firestore_event_lake_storage_layer_1 = require("./firestore.event-lake.storage-layer");
41
- jest.setTimeout(10000);
42
- describe("FirestoreEventLakeStore", () => {
43
- const app = fb.initializeApp({ projectId: "demo-es" });
44
- const firestore = app.firestore();
45
- (0, core_1.EventLakeStoreSuite)({
46
- transaction: new store_firestore_1.FirestoreTransactionPerformer(firestore),
47
- lakeStorageLayer: new firestore_event_lake_storage_layer_1.FirestoreEventLakeStorageLayer(firestore),
48
- });
49
- });
50
- //# sourceMappingURL=firestore.event-lake.store.spec.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"firestore.event-lake.store.spec.js","sourceRoot":"","sources":["../src/firestore.event-lake.store.spec.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,OAAO,CAAC,GAAG,CAAC,uBAAuB,GAAG,gBAAgB,CAAC;AACvD,mDAAqC;AAErC,6DAAwE;AACxE,uCAAmD;AACnD,6FAAsF;AAEtF,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;AAEvB,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;IACvC,MAAM,GAAG,GAAG,EAAE,CAAC,aAAa,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC,CAAC;IACvD,MAAM,SAAS,GAAG,GAAG,CAAC,SAAS,EAAE,CAAC;IAElC,IAAA,0BAAmB,EAAC;QAClB,WAAW,EAAE,IAAI,+CAA6B,CAAC,SAAS,CAAC;QACzD,gBAAgB,EAAE,IAAI,mEAA8B,CAAC,SAAS,CAAC;KAChE,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["process.env.FIRESTORE_EMULATOR_HOST = \"localhost:8080\";\nimport * as fb from \"firebase-admin\";\n\nimport { FirestoreTransactionPerformer } from \"@ddd-ts/store-firestore\";\nimport { EventLakeStoreSuite } from \"@ddd-ts/core\";\nimport { FirestoreEventLakeStorageLayer } from \"./firestore.event-lake.storage-layer\";\n\njest.setTimeout(10000);\n\ndescribe(\"FirestoreEventLakeStore\", () => {\n const app = fb.initializeApp({ projectId: \"demo-es\" });\n const firestore = app.firestore();\n\n EventLakeStoreSuite({\n transaction: new FirestoreTransactionPerformer(firestore),\n lakeStorageLayer: new FirestoreEventLakeStorageLayer(firestore),\n });\n});\n"]}
@@ -1,50 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- Object.defineProperty(exports, "__esModule", { value: true });
36
- process.env.FIRESTORE_EMULATOR_HOST = "localhost:8080";
37
- const fb = __importStar(require("firebase-admin"));
38
- const store_firestore_1 = require("@ddd-ts/store-firestore");
39
- const core_1 = require("@ddd-ts/core");
40
- const firestore_event_stream_storage_layer_1 = require("./firestore.event-stream.storage-layer");
41
- jest.setTimeout(10000);
42
- describe("FirestoreEventStreamStore", () => {
43
- const app = fb.initializeApp({ projectId: "demo-es" });
44
- const firestore = app.firestore();
45
- (0, core_1.EventStreamStoreSuite)({
46
- transaction: new store_firestore_1.FirestoreTransactionPerformer(firestore),
47
- streamStorageLayer: new firestore_event_stream_storage_layer_1.FirestoreEventStreamStorageLayer(firestore),
48
- });
49
- });
50
- //# sourceMappingURL=firestore.event-stream-store.spec.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"firestore.event-stream-store.spec.js","sourceRoot":"","sources":["../src/firestore.event-stream-store.spec.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,OAAO,CAAC,GAAG,CAAC,uBAAuB,GAAG,gBAAgB,CAAC;AACvD,mDAAqC;AAErC,6DAAwE;AACxE,uCAAqD;AACrD,iGAA0F;AAE1F,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;AAEvB,QAAQ,CAAC,2BAA2B,EAAE,GAAG,EAAE;IACzC,MAAM,GAAG,GAAG,EAAE,CAAC,aAAa,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC,CAAC;IACvD,MAAM,SAAS,GAAG,GAAG,CAAC,SAAS,EAAE,CAAC;IAElC,IAAA,4BAAqB,EAAC;QACpB,WAAW,EAAE,IAAI,+CAA6B,CAAC,SAAS,CAAC;QACzD,kBAAkB,EAAE,IAAI,uEAAgC,CAAC,SAAS,CAAC;KACpE,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["process.env.FIRESTORE_EMULATOR_HOST = \"localhost:8080\";\nimport * as fb from \"firebase-admin\";\n\nimport { FirestoreTransactionPerformer } from \"@ddd-ts/store-firestore\";\nimport { EventStreamStoreSuite } from \"@ddd-ts/core\";\nimport { FirestoreEventStreamStorageLayer } from \"./firestore.event-stream.storage-layer\";\n\njest.setTimeout(10000);\n\ndescribe(\"FirestoreEventStreamStore\", () => {\n const app = fb.initializeApp({ projectId: \"demo-es\" });\n const firestore = app.firestore();\n\n EventStreamStoreSuite({\n transaction: new FirestoreTransactionPerformer(firestore),\n streamStorageLayer: new FirestoreEventStreamStorageLayer(firestore),\n });\n});\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"firestore.event-stream.aggregate-store.js","sourceRoot":"","sources":["../src/firestore.event-stream.aggregate-store.ts"],"names":[],"mappings":";;;AACA,uCAYsB;AACtB,6DAAwE;AAExE,mEAA+D;AAC/D,iGAA0F;AAGnF,MAAM,sCAAsC,GAAG,CAGpD,SAAY,EACZ,EAAE;IACF,OAAO,MAAM,mCAAoC,SAAQ,kCAExD;QACC,YACE,SAAoB,EACpB,UACuC,EACvC,QAAoB;YAEpB,MAAM,WAAW,GAAG,IAAI,4CAAoB,CAC1C,SAAS,CAAC,IAAI,EACd,SAAS,EACT,UAAU,CACX,CAAC;YACF,KAAK,CAAC,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC;QACtD,CAAC;QAED,SAAS,CAAC,KAA0B;YAClC,OAAO,SAAS,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACpC,CAAC;QAED,WAAW,CAAC,EAAyB;YACnC,OAAO,eAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,EAAE,CAAC,SAAS,EAAE,CAAC,CAAC;QACvD,CAAC;KACF,CAAC;AACJ,CAAC,CAAC;AA9BW,QAAA,sCAAsC,0CA8BjD;AAEF,MAAsB,kCAEpB,SAAQ,gCAA4B;IAElB;IACA;IACA;IACA;IAJlB,YACkB,SAAoB,EACpB,UAAmC,EACnC,WAAoC,EACpC,QAAoB;QAEpC,MAAM,YAAY,GAAG,IAAI,uEAAgC,CAAC,SAAS,CAAC,CAAC;QACrE,MAAM,WAAW,GAAG,IAAI,+CAA6B,CAAC,SAAS,CAAC,CAAC;QACjE,MAAM,WAAW,GAAG,IAAI,uBAAgB,CACtC,YAAY,EACZ,UAAU,EACV,QAAQ,CACT,CAAC;QACF,KAAK,CAAC,WAAW,EAAE,WAAW,EAAE,WAAW,CAAC,CAAC;QAZ7B,cAAS,GAAT,SAAS,CAAW;QACpB,eAAU,GAAV,UAAU,CAAyB;QACnC,gBAAW,GAAX,WAAW,CAAyB;QACpC,aAAQ,GAAR,QAAQ,CAAY;IAUtC,CAAC;CACF;AAlBD,gFAkBC","sourcesContent":["import { HasTrait } from \"@ddd-ts/traits\";\nimport {\n StreamId,\n EventsOf,\n EventSourced,\n type Identifiable,\n type IEventBus,\n EventStreamStore,\n EventStreamAggregateStore,\n ISerializer,\n IEventSourced,\n IIdentifiable,\n EventOf,\n} from \"@ddd-ts/core\";\nimport { FirestoreTransactionPerformer } from \"@ddd-ts/store-firestore\";\n\nimport { FirestoreSnapshotter } from \"./firestore.snapshotter\";\nimport { FirestoreEventStreamStorageLayer } from \"./firestore.event-stream.storage-layer\";\nimport { Firestore } from \"firebase-admin/firestore\";\n\nexport const MakeFirestoreEventStreamAggregateStore = <\n A extends HasTrait<typeof EventSourced> & HasTrait<typeof Identifiable>,\n>(\n AGGREGATE: A,\n) => {\n return class $FirestoreEventStreamAggregateStore extends FirestoreEventStreamAggregateStore<\n InstanceType<A>\n > {\n constructor(\n firestore: Firestore,\n serializer: ISerializer<InstanceType<A>> &\n ISerializer<EventOf<InstanceType<A>>>,\n eventBus?: IEventBus,\n ) {\n const snapshotter = new FirestoreSnapshotter<InstanceType<A>>(\n AGGREGATE.name,\n firestore,\n serializer,\n );\n super(firestore, serializer, snapshotter, eventBus);\n }\n\n loadFirst(event: EventsOf<A>[number]): InstanceType<A> {\n return AGGREGATE.loadFirst(event);\n }\n\n getStreamId(id: InstanceType<A>[\"id\"]): StreamId {\n return StreamId.from(AGGREGATE.name, id.serialize());\n }\n };\n};\n\nexport abstract class FirestoreEventStreamAggregateStore<\n A extends IEventSourced & IIdentifiable,\n> extends EventStreamAggregateStore<A> {\n constructor(\n public readonly firestore: Firestore,\n public readonly serializer: ISerializer<EventOf<A>>,\n public readonly snapshotter: FirestoreSnapshotter<A>,\n public readonly eventBus?: IEventBus,\n ) {\n const storageLayer = new FirestoreEventStreamStorageLayer(firestore);\n const transaction = new FirestoreTransactionPerformer(firestore);\n const streamStore = new EventStreamStore<EventOf<A>>(\n storageLayer,\n serializer,\n eventBus,\n );\n super(streamStore, transaction, snapshotter);\n }\n}\n"]}
@@ -1,54 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- Object.defineProperty(exports, "__esModule", { value: true });
36
- process.env.FIRESTORE_EMULATOR_HOST = "localhost:8080";
37
- const fb = __importStar(require("firebase-admin"));
38
- const core_1 = require("@ddd-ts/core");
39
- const store_firestore_1 = require("@ddd-ts/store-firestore");
40
- const firestore_event_stream_aggregate_store_1 = require("./firestore.event-stream.aggregate-store");
41
- jest.setTimeout(10000);
42
- describe("FirestoreEventStreamAggregateStore", () => {
43
- const app = fb.initializeApp({ projectId: "demo-es" });
44
- const database = app.firestore();
45
- (0, core_1.EventStreamAggregateStoreSuite)({
46
- transaction: new store_firestore_1.FirestoreTransactionPerformer(database),
47
- getAggregateStore: (AGGREGATE, serializer, eventBus) => {
48
- const Store = (0, firestore_event_stream_aggregate_store_1.MakeFirestoreEventStreamAggregateStore)(AGGREGATE);
49
- return new Store(database, serializer, eventBus);
50
- },
51
- getStore: (name, serializer) => new store_firestore_1.FirestoreStore(database.collection(name), serializer),
52
- });
53
- });
54
- //# sourceMappingURL=firestore.event-stream.aggregate-store.spec.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"firestore.event-stream.aggregate-store.spec.js","sourceRoot":"","sources":["../src/firestore.event-stream.aggregate-store.spec.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,OAAO,CAAC,GAAG,CAAC,uBAAuB,GAAG,gBAAgB,CAAC;AACvD,mDAAqC;AAErC,uCAIsB;AACtB,6DAGiC;AACjC,qGAAkG;AAElG,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;AAEvB,QAAQ,CAAC,oCAAoC,EAAE,GAAG,EAAE;IAClD,MAAM,GAAG,GAAG,EAAE,CAAC,aAAa,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC,CAAC;IACvD,MAAM,QAAQ,GAAG,GAAG,CAAC,SAAS,EAAE,CAAC;IAEjC,IAAA,qCAA8B,EAAC;QAC7B,WAAW,EAAE,IAAI,+CAA6B,CAAC,QAAQ,CAAC;QACxD,iBAAiB,EAAE,CAAC,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE;YACrD,MAAM,KAAK,GAAG,IAAA,+EAAsC,EAAC,SAAS,CAAC,CAAC;YAChE,OAAO,IAAI,KAAK,CAAC,QAAQ,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC;QACnD,CAAC;QACD,QAAQ,EAAE,CACR,IAAY,EACZ,UAA0B,EAC1B,EAAE,CAAC,IAAI,gCAAc,CAAI,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,UAAU,CAAC;KAClE,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["process.env.FIRESTORE_EMULATOR_HOST = \"localhost:8080\";\nimport * as fb from \"firebase-admin\";\n\nimport {\n EventStreamAggregateStoreSuite,\n IIdentifiable,\n type ISerializer,\n} from \"@ddd-ts/core\";\nimport {\n FirestoreStore,\n FirestoreTransactionPerformer,\n} from \"@ddd-ts/store-firestore\";\nimport { MakeFirestoreEventStreamAggregateStore } from \"./firestore.event-stream.aggregate-store\";\n\njest.setTimeout(10000);\n\ndescribe(\"FirestoreEventStreamAggregateStore\", () => {\n const app = fb.initializeApp({ projectId: \"demo-es\" });\n const database = app.firestore();\n\n EventStreamAggregateStoreSuite({\n transaction: new FirestoreTransactionPerformer(database),\n getAggregateStore: (AGGREGATE, serializer, eventBus) => {\n const Store = MakeFirestoreEventStreamAggregateStore(AGGREGATE);\n return new Store(database, serializer, eventBus);\n },\n getStore: <T extends IIdentifiable>(\n name: string,\n serializer: ISerializer<T>,\n ) => new FirestoreStore<T>(database.collection(name), serializer),\n });\n});\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"firestore.event-stream.storage-layer.js","sourceRoot":"","sources":["../src/firestore.event-stream.storage-layer.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n StreamId,\n type ISerializedChange,\n type ISerializedFact,\n EventStreamStorageLayer,\n} from \"@ddd-ts/core\";\nimport { ISerializedSavedChange } from \"@ddd-ts/core/dist/interfaces/es-event\";\n\nimport {\n DefaultConverter,\n FirestoreTransaction,\n} from \"@ddd-ts/store-firestore\";\nimport * as fb from \"firebase-admin\";\n\nexport const serverTimestamp = fb.firestore.FieldValue.serverTimestamp;\n\nexport class FirestoreEventStreamStorageLayer\n implements EventStreamStorageLayer\n{\n constructor(\n public readonly firestore: fb.firestore.Firestore,\n public readonly converter = new DefaultConverter(),\n ) {}\n\n isLocalRevisionOutdatedError(error: unknown): boolean {\n return (\n typeof error === \"object\" &&\n error !== null &&\n \"code\" in error &&\n error.code === 6\n );\n }\n\n getCollection(streamId: StreamId) {\n return this.firestore\n .collection(\"event-store\")\n .doc(streamId.aggregateType)\n .collection(\"streams\")\n .doc(streamId.aggregateId)\n .collection(\"events\");\n }\n\n async append(\n streamId: StreamId,\n changes: ISerializedChange[],\n expectedRevision: number,\n trx: FirestoreTransaction,\n ) {\n const collection = this.getCollection(streamId);\n const result: ISerializedSavedChange[] = [];\n\n let revision = expectedRevision + 1;\n for (const change of changes) {\n const storageChange = {\n aggregateType: streamId.aggregateType,\n eventId: change.id,\n aggregateId: streamId.aggregateId,\n revision: revision,\n name: change.name,\n payload: change.payload,\n occurredAt: serverTimestamp(),\n version: change.version,\n };\n\n const ref = collection.doc(`${revision}`);\n\n result.push({\n ...change,\n ref: ref.path,\n revision: revision,\n occurredAt: undefined,\n });\n\n trx.transaction.create(ref, this.converter.toFirestore(storageChange));\n revision++;\n }\n\n return result;\n }\n\n async *read(\n streamId: StreamId,\n startAt?: number,\n ): AsyncIterable<ISerializedFact> {\n const collection = this.getCollection(streamId);\n\n const query = collection\n .where(\"revision\", \">=\", startAt || 0)\n .orderBy(\"revision\", \"asc\");\n\n for await (const event of query.stream()) {\n const e = event as any as fb.firestore.QueryDocumentSnapshot<any>;\n const data = this.converter.fromFirestore(e);\n yield {\n id: data.eventId,\n ref: e.ref.path,\n revision: data.revision,\n name: data.name,\n $name: data.name,\n payload: data.payload,\n occurredAt: data.occurredAt,\n version: data.version ?? 1,\n };\n }\n }\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"firestore.event-stream.store.js","sourceRoot":"","sources":["../src/firestore.event-stream.store.ts"],"names":[],"mappings":";;;AAAA,uCAKsB;AACtB,iGAA0F;AAG1F,MAAa,yBAEX,SAAQ,uBAAuB;IAC/B,YACE,SAAoB,EACpB,UAA8B,EAC9B,QAAoB;QAEpB,KAAK,CACH,IAAI,uEAAgC,CAAC,SAAS,CAAC,EAC/C,UAAU,EACV,QAAQ,CACT,CAAC;IACJ,CAAC;CACF;AAdD,8DAcC","sourcesContent":["import {\n EventStreamStore,\n IEsEvent,\n IEventBus,\n ISerializer,\n} from \"@ddd-ts/core\";\nimport { FirestoreEventStreamStorageLayer } from \"./firestore.event-stream.storage-layer\";\nimport { Firestore } from \"firebase-admin/firestore\";\n\nexport class FirestoreEventStreamStore<\n Event extends IEsEvent,\n> extends EventStreamStore<Event> {\n constructor(\n firestore: Firestore,\n serializer: ISerializer<Event>,\n eventBus?: IEventBus,\n ) {\n super(\n new FirestoreEventStreamStorageLayer(firestore),\n serializer,\n eventBus,\n );\n }\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"firestore.projected-stream.reader.js","sourceRoot":"","sources":["../src/firestore.projected-stream.reader.ts"],"names":[],"mappings":";;;AAAA,uCASsB;AAEtB,yGAAkG;AAElG,MAAa,8BAEX,SAAQ,4BAA4B;IACpC,OAAO,CAAuC;IAC9C,UAAU,CAAqB;IAC/B,YAAY,SAAoB,EAAE,UAA8B;QAC9D,MAAM,OAAO,GAAG,IAAI,+EAAoC,CAAC,SAAS,CAAC,CAAC;QACpE,KAAK,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QAC3B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,WAAgC;QAC9C,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;QAChE,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,UAAoC,CAAC,CAAC;IACtE,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,MAAc;QACtB,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAClD,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,OAAO,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,UAAU,CAE5C,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,KAAK,CACT,eAAgC,EAChC,KAAa,EACb,UAAmB,EACnB,KAAc,EACd,KAAc;QAEd,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CACzC,eAAe,EACf,KAAK,EACL,UAAU,EACV,KAAK,EACL,KAAK,CACN,CAAC;QACF,OAAO,OAAO,CAAC,GAAG,CAChB,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAC/C,CAAC;IACX,CAAC;IAED,KAAK,CAAC,CAAC,IAAI,CACT,eAAgC,EAChC,KAAa,EACb,UAAmB,EACnB,KAAc;QAEd,IAAI,KAAK,EAAE,MAAM,UAAU,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,CAC9C,eAAe,EACf,KAAK,EACL,UAAU,EACV,KAAK,CACN,EAAE,CAAC;YACF,MAAM,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,UAAU,CAA4B,CAAC;QAC3E,CAAC;IACH,CAAC;CACF;AA7DD,wEA6DC","sourcesContent":["import {\n Cursor,\n IEsEvent,\n IFact,\n ISavedChange,\n ISerializedSavedChange,\n ISerializer,\n ProjectedStream,\n ProjectedStreamReader,\n} from \"@ddd-ts/core\";\nimport { Firestore } from \"firebase-admin/firestore\";\nimport { FirestoreProjectedStreamStorageLayer } from \"./firestore.projected-stream.storage-layer\";\n\nexport class FirestoreProjectedStreamReader<\n Event extends IEsEvent,\n> extends ProjectedStreamReader<Event> {\n storage: FirestoreProjectedStreamStorageLayer;\n serializer: ISerializer<Event>;\n constructor(firestore: Firestore, serializer: ISerializer<Event>) {\n const storage = new FirestoreProjectedStreamStorageLayer(firestore);\n super(storage, serializer);\n this.storage = storage;\n this.serializer = serializer;\n }\n\n async getCursor(savedChange: ISavedChange<Event>) {\n const serialized = await this.serializer.serialize(savedChange);\n return this.storage.getCursor(serialized as ISerializedSavedChange);\n }\n\n async get(cursor: Cursor) {\n const serialized = await this.storage.get(cursor);\n if (!serialized) {\n return undefined;\n }\n return this.serializer.deserialize(serialized) as unknown as Promise<\n IFact<Event>\n >;\n }\n\n async slice(\n projectedStream: ProjectedStream,\n shard: string,\n startAfter?: Cursor,\n endAt?: Cursor,\n limit?: number,\n ) {\n const serialized = await this.storage.slice(\n projectedStream,\n shard,\n startAfter,\n endAt,\n limit,\n );\n return Promise.all(\n serialized.map((s) => this.serializer.deserialize(s)),\n ) as any;\n }\n\n async *read(\n projectedStream: ProjectedStream,\n shard: string,\n startAfter?: Cursor,\n endAt?: Cursor,\n ) {\n for await (const serialized of this.storage.read(\n projectedStream,\n shard,\n startAfter,\n endAt,\n )) {\n yield this.serializer.deserialize(serialized) as unknown as IFact<Event>;\n }\n }\n}\n"]}
@@ -1,54 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- Object.defineProperty(exports, "__esModule", { value: true });
36
- process.env.FIRESTORE_EMULATOR_HOST = "localhost:8080";
37
- const fb = __importStar(require("firebase-admin"));
38
- const store_firestore_1 = require("@ddd-ts/store-firestore");
39
- const core_1 = require("@ddd-ts/core");
40
- const firestore_event_lake_storage_layer_1 = require("./firestore.event-lake.storage-layer");
41
- const firestore_event_stream_storage_layer_1 = require("./firestore.event-stream.storage-layer");
42
- const firestore_projected_stream_storage_layer_1 = require("./firestore.projected-stream.storage-layer");
43
- jest.setTimeout(10000);
44
- describe("FirestoreProjectedStreamReader", () => {
45
- const app = fb.initializeApp({ projectId: "demo-es" });
46
- const firestore = app.firestore();
47
- (0, core_1.ProjectedStreamReaderSuite)({
48
- transaction: new store_firestore_1.FirestoreTransactionPerformer(firestore),
49
- lakeStorageLayer: new firestore_event_lake_storage_layer_1.FirestoreEventLakeStorageLayer(firestore),
50
- streamStorageLayer: new firestore_event_stream_storage_layer_1.FirestoreEventStreamStorageLayer(firestore),
51
- readerStorageLayer: new firestore_projected_stream_storage_layer_1.FirestoreProjectedStreamStorageLayer(firestore),
52
- });
53
- });
54
- //# sourceMappingURL=firestore.projected-stream.reader.spec.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"firestore.projected-stream.reader.spec.js","sourceRoot":"","sources":["../src/firestore.projected-stream.reader.spec.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,OAAO,CAAC,GAAG,CAAC,uBAAuB,GAAG,gBAAgB,CAAC;AACvD,mDAAqC;AAErC,6DAAwE;AACxE,uCAA0D;AAE1D,6FAAsF;AACtF,iGAA0F;AAC1F,yGAAkG;AAElG,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;AAEvB,QAAQ,CAAC,gCAAgC,EAAE,GAAG,EAAE;IAC9C,MAAM,GAAG,GAAG,EAAE,CAAC,aAAa,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC,CAAC;IACvD,MAAM,SAAS,GAAG,GAAG,CAAC,SAAS,EAAE,CAAC;IAElC,IAAA,iCAA0B,EAAC;QACzB,WAAW,EAAE,IAAI,+CAA6B,CAAC,SAAS,CAAC;QACzD,gBAAgB,EAAE,IAAI,mEAA8B,CAAC,SAAS,CAAC;QAC/D,kBAAkB,EAAE,IAAI,uEAAgC,CAAC,SAAS,CAAC;QACnE,kBAAkB,EAAE,IAAI,+EAAoC,CAAC,SAAS,CAAC;KACxE,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["process.env.FIRESTORE_EMULATOR_HOST = \"localhost:8080\";\nimport * as fb from \"firebase-admin\";\n\nimport { FirestoreTransactionPerformer } from \"@ddd-ts/store-firestore\";\nimport { ProjectedStreamReaderSuite } from \"@ddd-ts/core\";\n\nimport { FirestoreEventLakeStorageLayer } from \"./firestore.event-lake.storage-layer\";\nimport { FirestoreEventStreamStorageLayer } from \"./firestore.event-stream.storage-layer\";\nimport { FirestoreProjectedStreamStorageLayer } from \"./firestore.projected-stream.storage-layer\";\n\njest.setTimeout(10000);\n\ndescribe(\"FirestoreProjectedStreamReader\", () => {\n const app = fb.initializeApp({ projectId: \"demo-es\" });\n const firestore = app.firestore();\n\n ProjectedStreamReaderSuite({\n transaction: new FirestoreTransactionPerformer(firestore),\n lakeStorageLayer: new FirestoreEventLakeStorageLayer(firestore),\n streamStorageLayer: new FirestoreEventStreamStorageLayer(firestore),\n readerStorageLayer: new FirestoreProjectedStreamStorageLayer(firestore),\n });\n});\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"firestore.projected-stream.storage-layer.js","sourceRoot":"","sources":["../src/firestore.projected-stream.storage-layer.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n ISerializedFact,\n ISerializedSavedChange,\n LakeSource,\n ProjectedStream,\n ProjectedStreamStorageLayer,\n StreamSource,\n} from \"@ddd-ts/core\";\nimport { DefaultConverter } from \"@ddd-ts/store-firestore\";\nimport {\n Filter,\n Firestore,\n QueryDocumentSnapshot,\n Timestamp,\n} from \"firebase-admin/firestore\";\nimport { MicrosecondTimestamp } from \"@ddd-ts/shape\";\nimport { Cursor } from \"@ddd-ts/core/dist/components/cursor\";\n\nexport class FirestoreLakeSourceFilter {\n filter(shard: string, lakeSource: LakeSource) {\n return Filter.and(\n Filter.where(`payload.${lakeSource.shardKey}`, \"==\", shard),\n Filter.where(\"name\", \"in\", lakeSource.events),\n );\n }\n}\n\nexport class FirestoreStreamSourceFilter {\n filter(shard: string, streamSource: StreamSource) {\n return Filter.and(\n Filter.where(\"aggregateType\", \"==\", streamSource.aggregateType),\n Filter.where(`payload.${streamSource.shardKey}`, \"==\", shard),\n Filter.where(\"name\", \"in\", streamSource.events),\n );\n }\n}\n\nexport class FirestoreProjectedStreamStorageLayer\n implements ProjectedStreamStorageLayer\n{\n constructor(\n private readonly firestore: Firestore,\n public readonly converter = new DefaultConverter(),\n ) {}\n\n async *read(\n projectedStream: ProjectedStream,\n shard: string,\n startAfter?: Cursor,\n endAt?: Cursor,\n ) {\n let query = this.firestore\n .collectionGroup(\"events\")\n .orderBy(\"occurredAt\")\n .orderBy(\"revision\");\n\n const filters = projectedStream.sources.map((source) => {\n if (source instanceof LakeSource) {\n return new FirestoreLakeSourceFilter().filter(shard, source);\n }\n if (source instanceof StreamSource) {\n return new FirestoreStreamSourceFilter().filter(shard, source);\n }\n throw new Error(\"Unknown source type\");\n });\n\n query = query.where(Filter.or(...filters));\n\n if (startAfter) {\n const ts = this.microsecondToTimestamp(startAfter.occurredAt);\n query = query.startAfter(ts, startAfter.revision);\n }\n\n if (endAt) {\n const ts = this.microsecondToTimestamp(endAt.occurredAt);\n query = query.endAt(ts, endAt.revision);\n }\n\n for await (const doc of query.stream() as AsyncIterable<QueryDocumentSnapshot>) {\n const data = this.converter.fromFirestore(doc);\n yield {\n id: data.eventId,\n ref: doc.ref.path,\n revision: data.revision,\n name: data.name,\n $name: data.name,\n payload: data.payload,\n occurredAt: data.occurredAt,\n version: data.version ?? 1,\n };\n }\n }\n public microsecondToTimestamp(microseconds: MicrosecondTimestamp) {\n const seconds = BigInt(microseconds.micros) / 1_000_000n;\n const nanoseconds = (BigInt(microseconds.micros) % 1_000_000n) * 1000n; // Convert to nanoseconds\n return new Timestamp(Number(seconds), Number(nanoseconds));\n }\n\n async get(cursor: Cursor) {\n const doc = await this.firestore.doc(cursor.ref).get();\n if (!doc.exists) {\n return undefined;\n }\n const data = this.converter.fromFirestoreSnapshot(doc) as any;\n return {\n id: data.eventId,\n ref: doc.ref.path,\n revision: data.revision,\n name: data.name,\n $name: data.name,\n payload: data.payload,\n occurredAt: data.occurredAt,\n version: data.version ?? 1,\n } as ISerializedFact;\n }\n\n async getCursor(\n savedChange: ISerializedSavedChange,\n ): Promise<Cursor | undefined> {\n const doc = await this.firestore.doc(savedChange.ref).get();\n if (!doc.exists) {\n return undefined;\n }\n const data = this.converter.fromFirestoreSnapshot(doc) as any;\n return Cursor.deserialize({\n eventId: data.eventId,\n ref: doc.ref.path,\n occurredAt: data.occurredAt,\n revision: data.revision,\n });\n }\n\n async slice(\n projectedStream: ProjectedStream,\n shard: string,\n startAfter?: Cursor,\n endAt?: Cursor,\n limit?: number,\n ) {\n let query = this.firestore\n .collectionGroup(\"events\")\n .orderBy(\"occurredAt\")\n .orderBy(\"revision\");\n\n const filters = projectedStream.sources.map((source) => {\n if (source instanceof LakeSource) {\n return new FirestoreLakeSourceFilter().filter(shard, source);\n }\n if (source instanceof StreamSource) {\n return new FirestoreStreamSourceFilter().filter(shard, source);\n }\n throw new Error(\"Unknown source type\");\n });\n\n query = query.where(Filter.or(...filters));\n\n if (startAfter) {\n const ts = this.microsecondToTimestamp(startAfter.occurredAt);\n query = query.startAfter(ts, startAfter.revision);\n }\n\n if (endAt) {\n const ts = this.microsecondToTimestamp(endAt.occurredAt);\n query = query.endAt(ts, endAt.revision);\n }\n\n if (limit) {\n query = query.limit(limit);\n }\n\n const all = await query.get();\n\n return all.docs.map((doc) => {\n const data = this.converter.fromFirestore(doc);\n return {\n id: data.eventId,\n ref: doc.ref.path,\n revision: data.revision,\n name: data.name,\n $name: data.name,\n payload: data.payload,\n occurredAt: data.occurredAt,\n version: data.version ?? 1,\n } as ISerializedFact;\n });\n }\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"firestore.snapshotter.js","sourceRoot":"","sources":["../src/firestore.snapshotter.ts"],"names":[],"mappings":";;;AAKA,6DAAyD;AAEzD,MAAM,kBAAkB;IAEH;IACA;IAFnB,YACmB,UAA0B,EAC1B,aAAqB;QADrB,eAAU,GAAV,UAAU,CAAgB;QAC1B,kBAAa,GAAb,aAAa,CAAQ;IACrC,CAAC;IAEJ,KAAK,CAAC,SAAS,CAAC,QAAW;QACzB,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QAC7D,OAAO;YACL,GAAG,UAAU;YACb,KAAK,EAAE,IAAI,CAAC,aAAa;YACzB,QAAQ,EAAE,QAAQ,CAAC,oBAAoB;SACxC,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,UAAe;QAC/B,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,EAAE,GAAG,UAAU,CAAC;QAC5C,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC;YACjD,KAAK,EAAE,IAAI,CAAC,aAAa;YACzB,GAAG,OAAO;SACX,CAAC,CAAC;QACH,QAAQ,CAAC,oBAAoB,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;QACjD,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF;AAED,MAAa,oBAEX,SAAQ,gCAAiB;IACzB,YACE,aAAqB,EACrB,QAAqC,EACrC,UAA0B;QAE1B,MAAM,UAAU,GAAG,QAAQ;aACxB,UAAU,CAAC,aAAa,CAAC;aACzB,GAAG,CAAC,aAAa,CAAC;aAClB,UAAU,CAAC,SAAS,CAAC,CAAC;QACzB,KAAK,CACH,UAAU,EACV,IAAI,kBAAkB,CAAC,UAAU,EAAE,aAAa,CAAC,EACjD,aAAa,CACd,CAAC;IACJ,CAAC;CACF;AAlBD,oDAkBC","sourcesContent":["import {\n type IEventSourced,\n type IIdentifiable,\n type ISerializer,\n} from \"@ddd-ts/core\";\nimport { FirestoreStore } from \"@ddd-ts/store-firestore\";\n\nclass SnapshotSerializer<A extends IEventSourced & IIdentifiable> {\n constructor(\n private readonly serializer: ISerializer<A>,\n private readonly aggregateType: string,\n ) {}\n\n async serialize(instance: A) {\n const serialized = await this.serializer.serialize(instance);\n return {\n ...serialized,\n $name: this.aggregateType,\n revision: instance.acknowledgedRevision,\n };\n }\n\n async deserialize(serialized: any) {\n const { revision, ...content } = serialized;\n const instance = await this.serializer.deserialize({\n $name: this.aggregateType,\n ...content,\n });\n instance.acknowledgedRevision = Number(revision);\n return instance;\n }\n}\n\nexport class FirestoreSnapshotter<\n A extends IEventSourced & IIdentifiable,\n> extends FirestoreStore<A> {\n constructor(\n aggregateType: string,\n database: FirebaseFirestore.Firestore,\n serializer: ISerializer<A>,\n ) {\n const collection = database\n .collection(\"event-store\")\n .doc(aggregateType)\n .collection(\"streams\");\n super(\n collection,\n new SnapshotSerializer(serializer, aggregateType),\n aggregateType,\n );\n }\n}\n"]}
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,2FAAsF;AAA7E,oJAAA,8BAA8B,OAAA;AACvC,2EAAuE;AAA9D,qIAAA,uBAAuB,OAAA;AAChC,+FAA0F;AAAjF,wJAAA,gCAAgC,OAAA;AACzC,+EAA2E;AAAlE,yIAAA,yBAAyB,OAAA;AAElC,mGAGkD;AAFhD,4JAAA,kCAAkC,OAAA;AAClC,gKAAA,sCAAsC,OAAA;AAGxC,+FAGgD;AAF9C,wJAAA,gCAAgC,OAAA;AAChC,4JAAA,oCAAoC,OAAA;AAGtC,uGAIoD;AAHlD,gKAAA,oCAAoC,OAAA;AACpC,qJAAA,yBAAyB,OAAA;AACzB,uJAAA,2BAA2B,OAAA;AAG7B,yFAAqF;AAA5E,mJAAA,8BAA8B,OAAA;AAEvC,iEAA+D;AAAtD,6HAAA,oBAAoB,OAAA;AAE7B,wEAM0C;AALxC,yHAAA,kBAAkB,OAAA;AAClB,0HAAA,mBAAmB,OAAA;AACnB,2GAAA,IAAI,OAAA;AACJ,2HAAA,oBAAoB,OAAA;AACpB,gHAAA,SAAS,OAAA","sourcesContent":["export { FirestoreEventLakeStorageLayer } from \"./firestore.event-lake.storage-layer\";\nexport { FirestoreEventLakeStore } from \"./firestore.event-lake.store\";\nexport { FirestoreEventStreamStorageLayer } from \"./firestore.event-stream.storage-layer\";\nexport { FirestoreEventStreamStore } from \"./firestore.event-stream.store\";\n\nexport {\n FirestoreEventStreamAggregateStore,\n MakeFirestoreEventStreamAggregateStore,\n} from \"./firestore.event-stream.aggregate-store\";\n\nexport {\n FirestoreEventLakeAggregateStore,\n MakeFirestoreEventLakeAggregateStore,\n} from \"./firestore.event-lake.aggregate-store\";\n\nexport {\n FirestoreProjectedStreamStorageLayer,\n FirestoreLakeSourceFilter,\n FirestoreStreamSourceFilter,\n} from \"./firestore.projected-stream.storage-layer\";\n\nexport { FirestoreProjectedStreamReader } from \"./firestore.projected-stream.reader\";\n\nexport { FirestoreSnapshotter } from \"./firestore.snapshotter\";\n\nexport {\n FirestoreProjector,\n FirestoreQueueStore,\n Task,\n AlreadyEnqueuedError,\n ClaimerId,\n} from \"./projection/firestore.projector\";\n"]}
@@ -1,42 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const case_fixture_1 = require("../testkit/case-fixture");
4
- const test = (0, case_fixture_1.caseFixture)("Breathing", {
5
- projector: {
6
- retry: { attempts: 3, minDelay: 10, maxDelay: 10, backoff: 1 },
7
- enqueue: { batchSize: 100 },
8
- },
9
- });
10
- test.describe(() => {
11
- it("will attempt multiple retries when handler explicitely fails", async () => {
12
- const { events, act, control, assert } = await test.setup();
13
- const [account, opened] = events.open(`${test.name}_1`);
14
- await act.save(account);
15
- // Only one handle call, but we will fail multiple times inside
16
- const operation = act.handle(opened);
17
- const first = await control.suspend(opened);
18
- first.fail(new Error("first"));
19
- const second = await control.suspend(opened);
20
- second.fail(new Error("second"));
21
- const catched = await control.suspend(opened);
22
- catched.resume();
23
- await operation;
24
- await assert.cashflow(account.id).toHave({ id: account.id, flow: 0 });
25
- });
26
- it("but if we exceed the max attempts, the operation should fail", async () => {
27
- const { events, act, control, assert } = await test.setup();
28
- const [account, opened] = events.open(`${test.name}_2`);
29
- await act.save(account);
30
- const operation = act.handle(opened);
31
- const first = await control.suspend(opened);
32
- first.fail(new Error("first"));
33
- const second = await control.suspend(opened);
34
- second.fail(new Error("second"));
35
- // This is the third failure, which exceeds the max attempts of 3
36
- const third = await control.suspend(opened);
37
- third.fail(new Error("third"));
38
- await operation.catch(() => { });
39
- await assert.cashflow(account.id).toNotExist();
40
- });
41
- });
42
- //# sourceMappingURL=attempts.spec.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"attempts.spec.js","sourceRoot":"","sources":["../../../src/projection/cases/attempts.spec.ts"],"names":[],"mappings":"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","sourcesContent":["import { caseFixture } from \"../testkit/case-fixture\";\n\nconst test = caseFixture(\"Breathing\", {\n projector: {\n retry: { attempts: 3, minDelay: 10, maxDelay: 10, backoff: 1 },\n enqueue: { batchSize: 100 },\n },\n});\n\ntest.describe(() => {\n it(\"will attempt multiple retries when handler explicitely fails\", async () => {\n const { events, act, control, assert } = await test.setup();\n\n const [account, opened] = events.open(`${test.name}_1`);\n await act.save(account);\n\n // Only one handle call, but we will fail multiple times inside\n const operation = act.handle(opened);\n\n const first = await control.suspend(opened);\n first.fail(new Error(\"first\"));\n\n const second = await control.suspend(opened);\n second.fail(new Error(\"second\"));\n\n const catched = await control.suspend(opened);\n catched.resume();\n\n await operation;\n\n await assert.cashflow(account.id).toHave({ id: account.id, flow: 0 });\n });\n\n it(\"but if we exceed the max attempts, the operation should fail\", async () => {\n const { events, act, control, assert } = await test.setup();\n\n const [account, opened] = events.open(`${test.name}_2`);\n await act.save(account);\n\n const operation = act.handle(opened);\n\n const first = await control.suspend(opened);\n first.fail(new Error(\"first\"));\n\n const second = await control.suspend(opened);\n second.fail(new Error(\"second\"));\n\n // This is the third failure, which exceeds the max attempts of 3\n const third = await control.suspend(opened);\n third.fail(new Error(\"third\"));\n\n await operation.catch(() => {});\n\n await assert.cashflow(account.id).toNotExist();\n });\n});\n"]}
@@ -1,51 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const case_fixture_1 = require("../testkit/case-fixture");
4
- const test = (0, case_fixture_1.caseFixture)("BatchLast");
5
- test.describe(() => {
6
- it("applies only the last rename in sequence", async () => {
7
- const { events, act, assert } = await test.setup();
8
- const [account, opened] = events.open(test.name);
9
- await act.save(account);
10
- await act.handle(opened);
11
- // Those will be skipped because they are not the last in sequence
12
- account.rename("First Name");
13
- account.rename("Second Name");
14
- // This will be applied
15
- const final = account.rename("Final Name");
16
- await act.save(account);
17
- await act.handle(final);
18
- await assert.cashflow(account.id).toHave({
19
- id: account.id,
20
- flow: 0,
21
- name: "Final Name",
22
- all_names: ["Final Name"],
23
- ops_trace: [opened.id, final.id],
24
- });
25
- });
26
- it("will apply last rename of batch", async () => {
27
- const { events, act, assert } = await test.setup();
28
- const [account, opened] = events.open("SimpleBatching_DSL");
29
- await act.save(account);
30
- await act.handle(opened);
31
- account.rename("New Name A");
32
- account.rename("New Name B");
33
- account.rename("New Name C");
34
- const r1 = account.rename("New Name 1");
35
- await act.save(account);
36
- await act.handle(r1);
37
- account.rename("New Name H");
38
- account.rename("New Name I");
39
- account.rename("New Name J");
40
- const r2 = account.rename("New Name 2");
41
- await act.save(account);
42
- await act.handle(r2);
43
- await assert.cashflow(account.id).toHave({
44
- id: account.id,
45
- flow: 0,
46
- name: "New Name 2",
47
- all_names: ["New Name 1", "New Name 2"],
48
- });
49
- });
50
- });
51
- //# sourceMappingURL=batchlast.spec.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"batchlast.spec.js","sourceRoot":"","sources":["../../../src/projection/cases/batchlast.spec.ts"],"names":[],"mappings":";;AAAA,0DAAsD;AAEtD,MAAM,IAAI,GAAG,IAAA,0BAAW,EAAC,WAAW,CAAC,CAAC;AAEtC,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE;IACjB,EAAE,CAAC,0CAA0C,EAAE,KAAK,IAAI,EAAE;QACxD,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;QAEnD,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAEjD,MAAM,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACxB,MAAM,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAEzB,kEAAkE;QAClE,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QAC7B,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;QAE9B,uBAAuB;QACvB,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QAE3C,MAAM,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAExB,MAAM,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAExB,MAAM,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC;YACvC,EAAE,EAAE,OAAO,CAAC,EAAE;YACd,IAAI,EAAE,CAAC;YACP,IAAI,EAAE,YAAY;YAClB,SAAS,EAAE,CAAC,YAAY,CAAC;YACzB,SAAS,EAAE,CAAC,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,EAAE,CAAC;SACjC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iCAAiC,EAAE,KAAK,IAAI,EAAE;QAC/C,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;QAEnD,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAC5D,MAAM,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACxB,MAAM,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAEzB,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QAC7B,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QAC7B,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QAC7B,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QACxC,MAAM,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAExB,MAAM,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAErB,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QAC7B,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QAC7B,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QAC7B,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QACxC,MAAM,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAExB,MAAM,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAErB,MAAM,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC;YACvC,EAAE,EAAE,OAAO,CAAC,EAAE;YACd,IAAI,EAAE,CAAC;YACP,IAAI,EAAE,YAAY;YAClB,SAAS,EAAE,CAAC,YAAY,EAAE,YAAY,CAAC;SACxC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { caseFixture } from \"../testkit/case-fixture\";\n\nconst test = caseFixture(\"BatchLast\");\n\ntest.describe(() => {\n it(\"applies only the last rename in sequence\", async () => {\n const { events, act, assert } = await test.setup();\n\n const [account, opened] = events.open(test.name);\n\n await act.save(account);\n await act.handle(opened);\n\n // Those will be skipped because they are not the last in sequence\n account.rename(\"First Name\");\n account.rename(\"Second Name\");\n\n // This will be applied\n const final = account.rename(\"Final Name\");\n\n await act.save(account);\n\n await act.handle(final);\n\n await assert.cashflow(account.id).toHave({\n id: account.id,\n flow: 0,\n name: \"Final Name\",\n all_names: [\"Final Name\"],\n ops_trace: [opened.id, final.id],\n });\n });\n\n it(\"will apply last rename of batch\", async () => {\n const { events, act, assert } = await test.setup();\n\n const [account, opened] = events.open(\"SimpleBatching_DSL\");\n await act.save(account);\n await act.handle(opened);\n\n account.rename(\"New Name A\");\n account.rename(\"New Name B\");\n account.rename(\"New Name C\");\n const r1 = account.rename(\"New Name 1\");\n await act.save(account);\n\n await act.handle(r1);\n\n account.rename(\"New Name H\");\n account.rename(\"New Name I\");\n account.rename(\"New Name J\");\n const r2 = account.rename(\"New Name 2\");\n await act.save(account);\n\n await act.handle(r2);\n\n await assert.cashflow(account.id).toHave({\n id: account.id,\n flow: 0,\n name: \"New Name 2\",\n all_names: [\"New Name 1\", \"New Name 2\"],\n });\n });\n});\n"]}
@@ -1,59 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const case_fixture_1 = require("../testkit/case-fixture");
4
- jest.setTimeout(20_000);
5
- const test = (0, case_fixture_1.caseFixture)("BigShuffle", {
6
- handlers: {
7
- AccountOpened: {
8
- chain: [case_fixture_1.traits.Context(), case_fixture_1.traits.Transaction(), case_fixture_1.traits.Parallel()],
9
- lock: case_fixture_1.locks.wholeAccount,
10
- },
11
- Deposited: {
12
- chain: [case_fixture_1.traits.Context(), case_fixture_1.traits.Parallel(), case_fixture_1.traits.Transaction()],
13
- lock: case_fixture_1.locks.accountAndEventId, // allows parallel deposits
14
- },
15
- Withdrawn: {
16
- chain: [case_fixture_1.traits.Context(), case_fixture_1.traits.Parallel(), case_fixture_1.traits.Transaction()],
17
- lock: case_fixture_1.locks.accountAndEventId, // allows parallel withdrawals
18
- },
19
- },
20
- });
21
- test.describe(() => {
22
- it("processes mixed events under load and matches expectations", async () => {
23
- const { events, act, cashflowStore } = await test.setup();
24
- const [account, opened] = events.open(test.name);
25
- await act.save(account);
26
- await act.handle(opened);
27
- // Generate 50 deposits of random amounts between 1 and 1000
28
- const deposits = [...Array(50).keys()].map(() => {
29
- const amount = Math.floor(Math.random() * 1000) + 1;
30
- return account.deposit(amount);
31
- });
32
- // Generate 50 withdrawals of random amounts between 1 and 100
33
- const withdrawals = [...Array(50).keys()].map(() => {
34
- const amount = Math.floor(Math.random() * 100) + 1;
35
- return account.withdraw(amount);
36
- });
37
- await act.save(account);
38
- // Generate 20 renames to simulate non-cashflow events
39
- const renames = [...Array(20).keys()].map((i) => account.rename(`StressTestName_${i.toString().padStart(3, "0")}`));
40
- await act.save(account);
41
- // Shuffle and handle all events in batches to simulate concurrency
42
- const eventsAll = [...deposits, ...withdrawals, ...renames].sort(() => Math.random() - 0.5);
43
- const batchSize = 25;
44
- const batches = [];
45
- for (let i = 0; i < eventsAll.length; i += batchSize) {
46
- batches.push(eventsAll.slice(i, i + batchSize));
47
- }
48
- // Process batches sequentially, but events within each batch concurrently
49
- await Promise.all(batches.map((batch) => Promise.all(batch.map((e) => act.handle(e)))));
50
- const cashflow = await cashflowStore.load(account.id);
51
- expect(cashflow).toBeDefined();
52
- // Calculate expected flow based on deposits and withdrawals
53
- const expectedFlow = deposits.reduce((s, d) => s + d.payload.amount, 0) +
54
- withdrawals.reduce((s, w) => s + w.payload.amount, 0);
55
- expect(cashflow.flow).toBe(expectedFlow);
56
- expect(cashflow.name).toBe("StressTestName_019");
57
- });
58
- });
59
- //# sourceMappingURL=bigshuffle.spec.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"bigshuffle.spec.js","sourceRoot":"","sources":["../../../src/projection/cases/bigshuffle.spec.ts"],"names":[],"mappings":"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","sourcesContent":["import { caseFixture, locks, traits } from \"../testkit/case-fixture\";\n\njest.setTimeout(20_000);\n\nconst test = caseFixture(\"BigShuffle\", {\n handlers: {\n AccountOpened: {\n chain: [traits.Context(), traits.Transaction(), traits.Parallel()],\n lock: locks.wholeAccount,\n },\n Deposited: {\n chain: [traits.Context(), traits.Parallel(), traits.Transaction()],\n lock: locks.accountAndEventId, // allows parallel deposits\n },\n Withdrawn: {\n chain: [traits.Context(), traits.Parallel(), traits.Transaction()],\n lock: locks.accountAndEventId, // allows parallel withdrawals\n },\n },\n});\n\ntest.describe(() => {\n it(\"processes mixed events under load and matches expectations\", async () => {\n const { events, act, cashflowStore } = await test.setup();\n\n const [account, opened] = events.open(test.name);\n await act.save(account);\n await act.handle(opened);\n\n // Generate 50 deposits of random amounts between 1 and 1000\n const deposits = [...Array(50).keys()].map(() => {\n const amount = Math.floor(Math.random() * 1000) + 1;\n return account.deposit(amount);\n });\n\n // Generate 50 withdrawals of random amounts between 1 and 100\n const withdrawals = [...Array(50).keys()].map(() => {\n const amount = Math.floor(Math.random() * 100) + 1;\n return account.withdraw(amount);\n });\n\n await act.save(account);\n\n // Generate 20 renames to simulate non-cashflow events\n const renames = [...Array(20).keys()].map((i) =>\n account.rename(`StressTestName_${i.toString().padStart(3, \"0\")}`),\n );\n await act.save(account);\n\n // Shuffle and handle all events in batches to simulate concurrency\n const eventsAll = [...deposits, ...withdrawals, ...renames].sort(\n () => Math.random() - 0.5,\n );\n const batchSize = 25;\n const batches: any[][] = [];\n for (let i = 0; i < eventsAll.length; i += batchSize) {\n batches.push(eventsAll.slice(i, i + batchSize));\n }\n\n // Process batches sequentially, but events within each batch concurrently\n await Promise.all(\n batches.map((batch) => Promise.all(batch.map((e) => act.handle(e)))),\n );\n\n const cashflow = await cashflowStore.load(account.id);\n expect(cashflow).toBeDefined();\n\n // Calculate expected flow based on deposits and withdrawals\n const expectedFlow =\n deposits.reduce((s, d: any) => s + d.payload.amount, 0) +\n withdrawals.reduce((s, w: any) => s + w.payload.amount, 0);\n\n expect(cashflow!.flow).toBe(expectedFlow);\n expect(cashflow!.name).toBe(\"StressTestName_019\");\n });\n});\n"]}
@@ -1,38 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const case_fixture_1 = require("../testkit/case-fixture");
4
- jest.setTimeout(120_000);
5
- const test = (0, case_fixture_1.caseFixture)("Burst", {
6
- handlers: {
7
- Deposited: {
8
- chain: [
9
- case_fixture_1.traits.Context(),
10
- case_fixture_1.traits.Transaction(),
11
- case_fixture_1.traits.Suspense(),
12
- case_fixture_1.traits.Parallel(),
13
- ],
14
- lock: case_fixture_1.locks.accountAndEventId,
15
- },
16
- },
17
- });
18
- test.describe(() => {
19
- it("supports many calls to handle, which will produce duplicate work but eventually converges", async () => {
20
- const { events, act, assert } = await test.setup();
21
- const [account, opened] = events.open(test.name);
22
- await act.save(account);
23
- await act.handle(opened);
24
- // first 50 deposits, each one its own handle call
25
- const deposits1 = [...Array(50).keys()].map((i) => account.deposit(i));
26
- await act.save(account);
27
- await Promise.all(deposits1.map((e) => act.handle(e)));
28
- // second 50 deposits, each one its own handle call
29
- const deposits2 = [...Array(50).keys()].map((i) => account.deposit(i + 50));
30
- await act.save(account);
31
- await Promise.all(deposits2.map((e) => act.handle(e)));
32
- // here we should have exactly the sum of all deposits, without duplicates or misses
33
- await assert
34
- .cashflow(account.id)
35
- .toHave({ id: account.id, flow: account.balance });
36
- });
37
- });
38
- //# sourceMappingURL=burst.spec.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"burst.spec.js","sourceRoot":"","sources":["../../../src/projection/cases/burst.spec.ts"],"names":[],"mappings":";;AAAA,0DAAqE;AAErE,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;AAEzB,MAAM,IAAI,GAAG,IAAA,0BAAW,EAAC,OAAO,EAAE;IAChC,QAAQ,EAAE;QACR,SAAS,EAAE;YACT,KAAK,EAAE;gBACL,qBAAM,CAAC,OAAO,EAAE;gBAChB,qBAAM,CAAC,WAAW,EAAE;gBACpB,qBAAM,CAAC,QAAQ,EAAE;gBACjB,qBAAM,CAAC,QAAQ,EAAE;aAClB;YACD,IAAI,EAAE,oBAAK,CAAC,iBAAiB;SAC9B;KACF;CACF,CAAC,CAAC;AAEH,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE;IACjB,EAAE,CAAC,2FAA2F,EAAE,KAAK,IAAI,EAAE;QACzG,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;QAEnD,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjD,MAAM,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACxB,MAAM,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAEzB,kDAAkD;QAClD,MAAM,SAAS,GAAG,CAAC,GAAG,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;QACvE,MAAM,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACxB,MAAM,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAEvD,mDAAmD;QACnD,MAAM,SAAS,GAAG,CAAC,GAAG,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QAC5E,MAAM,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACxB,MAAM,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAEvD,oFAAoF;QACpF,MAAM,MAAM;aACT,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;aACpB,MAAM,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { caseFixture, locks, traits } from \"../testkit/case-fixture\";\n\njest.setTimeout(120_000);\n\nconst test = caseFixture(\"Burst\", {\n handlers: {\n Deposited: {\n chain: [\n traits.Context(),\n traits.Transaction(),\n traits.Suspense(),\n traits.Parallel(),\n ],\n lock: locks.accountAndEventId,\n },\n },\n});\n\ntest.describe(() => {\n it(\"supports many calls to handle, which will produce duplicate work but eventually converges\", async () => {\n const { events, act, assert } = await test.setup();\n\n const [account, opened] = events.open(test.name);\n await act.save(account);\n await act.handle(opened);\n\n // first 50 deposits, each one its own handle call\n const deposits1 = [...Array(50).keys()].map((i) => account.deposit(i));\n await act.save(account);\n await Promise.all(deposits1.map((e) => act.handle(e)));\n\n // second 50 deposits, each one its own handle call\n const deposits2 = [...Array(50).keys()].map((i) => account.deposit(i + 50));\n await act.save(account);\n await Promise.all(deposits2.map((e) => act.handle(e)));\n\n // here we should have exactly the sum of all deposits, without duplicates or misses\n await assert\n .cashflow(account.id)\n .toHave({ id: account.id, flow: account.balance });\n });\n});\n"]}