@ddd-ts-kit/testing 0.10.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/README.md +20 -0
  2. package/dist/contracts/job-store/a-job.d.ts +24 -0
  3. package/dist/contracts/job-store/a-job.d.ts.map +1 -0
  4. package/dist/contracts/job-store/a-job.js +28 -0
  5. package/dist/contracts/job-store/a-job.js.map +1 -0
  6. package/dist/contracts/job-store/claim-suite.d.ts +15 -0
  7. package/dist/contracts/job-store/claim-suite.d.ts.map +1 -0
  8. package/dist/contracts/job-store/claim-suite.js +126 -0
  9. package/dist/contracts/job-store/claim-suite.js.map +1 -0
  10. package/dist/contracts/job-store/job-fixtures.d.ts +5 -0
  11. package/dist/contracts/job-store/job-fixtures.d.ts.map +1 -0
  12. package/dist/contracts/job-store/job-fixtures.js +5 -0
  13. package/dist/contracts/job-store/job-fixtures.js.map +1 -0
  14. package/dist/contracts/job-store/job-store-under-contract.d.ts +61 -0
  15. package/dist/contracts/job-store/job-store-under-contract.d.ts.map +1 -0
  16. package/dist/contracts/job-store/job-store-under-contract.js +2 -0
  17. package/dist/contracts/job-store/job-store-under-contract.js.map +1 -0
  18. package/dist/contracts/job-store/keep-suite.d.ts +11 -0
  19. package/dist/contracts/job-store/keep-suite.d.ts.map +1 -0
  20. package/dist/contracts/job-store/keep-suite.js +55 -0
  21. package/dist/contracts/job-store/keep-suite.js.map +1 -0
  22. package/dist/contracts/job-store/later.d.ts +3 -0
  23. package/dist/contracts/job-store/later.d.ts.map +1 -0
  24. package/dist/contracts/job-store/later.js +6 -0
  25. package/dist/contracts/job-store/later.js.map +1 -0
  26. package/dist/contracts/job-store/report-suite.d.ts +12 -0
  27. package/dist/contracts/job-store/report-suite.d.ts.map +1 -0
  28. package/dist/contracts/job-store/report-suite.js +82 -0
  29. package/dist/contracts/job-store/report-suite.js.map +1 -0
  30. package/dist/contracts/job-store/transaction-suite.d.ts +23 -0
  31. package/dist/contracts/job-store/transaction-suite.d.ts.map +1 -0
  32. package/dist/contracts/job-store/transaction-suite.js +68 -0
  33. package/dist/contracts/job-store/transaction-suite.js.map +1 -0
  34. package/dist/contracts/job-store-contract.d.ts +24 -0
  35. package/dist/contracts/job-store-contract.d.ts.map +1 -0
  36. package/dist/contracts/job-store-contract.js +22 -0
  37. package/dist/contracts/job-store-contract.js.map +1 -0
  38. package/dist/contracts/process-store-contract.d.ts +28 -0
  39. package/dist/contracts/process-store-contract.d.ts.map +1 -0
  40. package/dist/contracts/process-store-contract.js +81 -0
  41. package/dist/contracts/process-store-contract.js.map +1 -0
  42. package/dist/contracts.d.ts +3 -0
  43. package/dist/contracts.d.ts.map +1 -1
  44. package/dist/contracts.js +2 -0
  45. package/dist/contracts.js.map +1 -1
  46. package/dist/index.d.ts +3 -0
  47. package/dist/index.d.ts.map +1 -1
  48. package/dist/index.js +2 -0
  49. package/dist/index.js.map +1 -1
  50. package/dist/processes/command-matcher.d.ts +8 -0
  51. package/dist/processes/command-matcher.d.ts.map +1 -0
  52. package/dist/processes/command-matcher.js +2 -0
  53. package/dist/processes/command-matcher.js.map +1 -0
  54. package/dist/processes/given-process.d.ts +18 -0
  55. package/dist/processes/given-process.d.ts.map +1 -0
  56. package/dist/processes/given-process.js +17 -0
  57. package/dist/processes/given-process.js.map +1 -0
  58. package/dist/processes/process-outcome.d.ts +20 -0
  59. package/dist/processes/process-outcome.d.ts.map +1 -0
  60. package/dist/processes/process-outcome.js +67 -0
  61. package/dist/processes/process-outcome.js.map +1 -0
  62. package/dist/scenarios/event-mismatches.d.ts.map +1 -1
  63. package/dist/scenarios/event-mismatches.js +1 -18
  64. package/dist/scenarios/event-mismatches.js.map +1 -1
  65. package/dist/scenarios/subset-differences.d.ts +3 -0
  66. package/dist/scenarios/subset-differences.d.ts.map +1 -0
  67. package/dist/scenarios/subset-differences.js +21 -0
  68. package/dist/scenarios/subset-differences.js.map +1 -0
  69. package/package.json +6 -5
@@ -0,0 +1,68 @@
1
+ import { ContractSuite } from '../contract-suite.js';
2
+ import { failureOf } from '../failure-of.js';
3
+ import { aJob } from './a-job.js';
4
+ import { LEASE_MS, NOW, QUEUE } from './job-fixtures.js';
5
+ class CommandRefused extends Error {
6
+ }
7
+ /**
8
+ * A job added inside a unit of work exists if and only if the unit of work committed; a job
9
+ * cancelled or revived inside one is cancelled or revived if and only if it committed.
10
+ */
11
+ export class TransactionSuite extends ContractSuite {
12
+ tests() {
13
+ this.adds();
14
+ this.cancels();
15
+ this.revives();
16
+ }
17
+ adds() {
18
+ this.it('leaves no job behind a unit of work that rolled back', async () => {
19
+ const failure = await failureOf(() => this.subject.unitOfWork.run(async () => {
20
+ await this.subject.store.add(aJob('job-1'));
21
+ throw new CommandRefused();
22
+ }));
23
+ this.expect(failure instanceof CommandRefused).toBe(true);
24
+ this.expect(await this.subject.store.find('job-1')).toBe(undefined);
25
+ this.expect(await this.claimed()).toEqual([]);
26
+ });
27
+ this.it('keeps the job of a unit of work that committed', async () => {
28
+ await this.subject.unitOfWork.run(() => this.subject.store.add(aJob('job-1')));
29
+ this.expect(await this.claimed()).toEqual(['job-1']);
30
+ });
31
+ }
32
+ cancels() {
33
+ this.it('leaves the job waiting when the unit of work that cancelled it rolled back', async () => {
34
+ await this.subject.store.add(aJob('job-1'));
35
+ await failureOf(() => this.subject.unitOfWork.run(async () => {
36
+ this.expect(await this.subject.store.cancel('job-1', NOW)).toBe(true);
37
+ throw new CommandRefused();
38
+ }));
39
+ this.expect((await this.subject.store.find('job-1'))?.status).toBe('waiting');
40
+ this.expect(await this.claimed()).toEqual(['job-1']);
41
+ });
42
+ this.it('cancels the job once the unit of work committed', async () => {
43
+ await this.subject.store.add(aJob('job-1'));
44
+ const cancelled = await this.subject.unitOfWork.run(() => this.subject.store.cancel('job-1', NOW));
45
+ this.expect([cancelled, (await this.subject.store.find('job-1'))?.status]).toEqual([true, 'cancelled']);
46
+ this.expect(await this.claimed()).toEqual([]);
47
+ });
48
+ }
49
+ revives() {
50
+ this.it('leaves the job dead when the unit of work that revived it rolled back', async () => {
51
+ await this.subject.store.add(aJob('job-1'));
52
+ await this.claimed();
53
+ await this.subject.store.fail({ id: 'job-1', attempt: 1 }, { errorCode: 'X', retryAt: null, at: NOW });
54
+ await failureOf(() => this.subject.unitOfWork.run(async () => {
55
+ this.expect(await this.subject.store.retryDead(['job-1'], NOW)).toBe(1);
56
+ throw new CommandRefused();
57
+ }));
58
+ this.expect((await this.subject.store.find('job-1'))?.status).toBe('dead');
59
+ this.expect(await this.subject.unitOfWork.run(() => this.subject.store.retryDead(['job-1'], NOW))).toBe(1);
60
+ this.expect((await this.subject.store.find('job-1'))?.status).toBe('waiting');
61
+ });
62
+ }
63
+ async claimed() {
64
+ const jobs = await this.subject.store.claim({ queue: QUEUE, limit: 10, now: NOW, leaseMs: LEASE_MS });
65
+ return jobs.map((job) => job.id);
66
+ }
67
+ }
68
+ //# sourceMappingURL=transaction-suite.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transaction-suite.js","sourceRoot":"","sources":["../../../src/contracts/job-store/transaction-suite.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import type { Awaitable } from './awaitable.js';
2
+ import type { ContractRunner } from './contract-runner.js';
3
+ import type { JobStoreUnderContract } from './job-store/job-store-under-contract.js';
4
+ import { type UnitOfWorkOfTheStore } from './job-store/transaction-suite.js';
5
+ export interface JobStoreContractOptions {
6
+ readonly name: string;
7
+ /** A fresh, empty store; called before each test. */
8
+ createStore(): Awaitable<JobStoreUnderContract>;
9
+ /**
10
+ * The unit of work the store is used in, over the same database and the same context as the
11
+ * store just created: the contract then proves that a job added inside it exists if and only
12
+ * if it committed.
13
+ */
14
+ readonly unitOfWork?: () => UnitOfWorkOfTheStore;
15
+ }
16
+ /**
17
+ * What every `JobStore` guarantees, whatever it runs on: due jobs handed out earliest first and
18
+ * each to one claim, a lease that brings back the job of a worker that died, reports heard only
19
+ * from the attempt that holds the job, retries, dead jobs and their revival, cancellation,
20
+ * idempotency keys, housekeeping, and the enqueue sharing the fate of the unit of work.
21
+ * The claims of the contract ask for a lease of `30000` milliseconds.
22
+ */
23
+ export declare function jobStoreContract(runner: ContractRunner, options: JobStoreContractOptions): void;
24
+ //# sourceMappingURL=job-store-contract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"job-store-contract.d.ts","sourceRoot":"","sources":["../../src/contracts/job-store-contract.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yCAAyC,CAAC;AAGrF,OAAO,EAAoB,KAAK,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AAE/F,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,qDAAqD;IACrD,WAAW,IAAI,SAAS,CAAC,qBAAqB,CAAC,CAAC;IAChD;;;;OAIG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,oBAAoB,CAAC;CAClD;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,uBAAuB,GAAG,IAAI,CAc/F"}
@@ -0,0 +1,22 @@
1
+ import { ClaimSuite } from './job-store/claim-suite.js';
2
+ import { KeepSuite } from './job-store/keep-suite.js';
3
+ import { ReportSuite } from './job-store/report-suite.js';
4
+ import { TransactionSuite } from './job-store/transaction-suite.js';
5
+ /**
6
+ * What every `JobStore` guarantees, whatever it runs on: due jobs handed out earliest first and
7
+ * each to one claim, a lease that brings back the job of a worker that died, reports heard only
8
+ * from the attempt that holds the job, retries, dead jobs and their revival, cancellation,
9
+ * idempotency keys, housekeeping, and the enqueue sharing the fate of the unit of work.
10
+ * The claims of the contract ask for a lease of `30000` milliseconds.
11
+ */
12
+ export function jobStoreContract(runner, options) {
13
+ const create = () => options.createStore();
14
+ new ClaimSuite(runner, create).describe(`${options.name} (job store contract: claims)`);
15
+ new ReportSuite(runner, create).describe(`${options.name} (job store contract: reports of an attempt)`);
16
+ new KeepSuite(runner, create).describe(`${options.name} (job store contract: cancellation and housekeeping)`);
17
+ const { unitOfWork } = options;
18
+ if (unitOfWork !== undefined) {
19
+ new TransactionSuite(runner, async () => ({ store: await create(), unitOfWork: unitOfWork() })).describe(`${options.name} (job store contract: in a unit of work)`);
20
+ }
21
+ }
22
+ //# sourceMappingURL=job-store-contract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"job-store-contract.js","sourceRoot":"","sources":["../../src/contracts/job-store-contract.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAExD,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAA6B,MAAM,kCAAkC,CAAC;AAc/F;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAsB,EAAE,OAAgC;IACvF,MAAM,MAAM,GAAG,GAAqC,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;IAE7E,IAAI,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,IAAI,+BAA+B,CAAC,CAAC;IACxF,IAAI,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,IAAI,8CAA8C,CAAC,CAAC;IACxG,IAAI,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,IAAI,sDAAsD,CAAC,CAAC;IAE9G,MAAM,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC;IAE/B,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;QAC7B,IAAI,gBAAgB,CAAC,MAAM,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,MAAM,EAAE,EAAE,UAAU,EAAE,UAAU,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CACtG,GAAG,OAAO,CAAC,IAAI,0CAA0C,CAC1D,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,28 @@
1
+ import type { StoredProcess } from '@ddd-ts-kit/kernel';
2
+ import type { Awaitable } from './awaitable.js';
3
+ import type { ContractRunner } from './contract-runner.js';
4
+ /** The process store port of the kernel, restated so that a store of any package fits. */
5
+ export interface ProcessStoreUnderContract {
6
+ load(name: string, id: string): Promise<StoredProcess | undefined>;
7
+ save(process: StoredProcess): Promise<void>;
8
+ }
9
+ /** The unit of work the store is used in, as the kernel port states it. */
10
+ interface UnitOfWorkOfTheStore {
11
+ run<T>(work: () => Promise<T>): Promise<T>;
12
+ }
13
+ export interface ProcessStoreContractOptions {
14
+ readonly name: string;
15
+ /** A fresh, empty store; called before each test. */
16
+ createStore(): Awaitable<ProcessStoreUnderContract>;
17
+ /** The unit of work over the same context as the store just created: the contract then proves that a rolled back save leaves nothing. */
18
+ readonly unitOfWork?: () => UnitOfWorkOfTheStore;
19
+ }
20
+ /**
21
+ * What every `ProcessStore` guarantees: an instance comes back as saved, JSON state, armed
22
+ * timeouts and end included; a save at a version that is not the next one is refused with the
23
+ * code `CONCURRENCY_CONFLICT`, also when two first saves race; and, in a unit of work, a save
24
+ * shares its fate.
25
+ */
26
+ export declare function processStoreContract(runner: ContractRunner, options: ProcessStoreContractOptions): void;
27
+ export {};
28
+ //# sourceMappingURL=process-store-contract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-store-contract.d.ts","sourceRoot":"","sources":["../../src/contracts/process-store-contract.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAI3D,0FAA0F;AAC1F,MAAM,WAAW,yBAAyB;IACxC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC,CAAC;IACnE,IAAI,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7C;AAED,2EAA2E;AAC3E,UAAU,oBAAoB;IAC5B,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CAC5C;AAED,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,qDAAqD;IACrD,WAAW,IAAI,SAAS,CAAC,yBAAyB,CAAC,CAAC;IACpD,yIAAyI;IACzI,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,oBAAoB,CAAC;CAClD;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,2BAA2B,GAAG,IAAI,CAEvG"}
@@ -0,0 +1,81 @@
1
+ import { ContractSuite } from './contract-suite.js';
2
+ import { failureOf } from './failure-of.js';
3
+ /**
4
+ * What every `ProcessStore` guarantees: an instance comes back as saved, JSON state, armed
5
+ * timeouts and end included; a save at a version that is not the next one is refused with the
6
+ * code `CONCURRENCY_CONFLICT`, also when two first saves race; and, in a unit of work, a save
7
+ * shares its fate.
8
+ */
9
+ export function processStoreContract(runner, options) {
10
+ new ProcessStoreSuite(runner, options).describe(`${options.name} (process store contract)`);
11
+ }
12
+ const NAME = 'billing.dunning';
13
+ class ProcessStoreSuite extends ContractSuite {
14
+ options;
15
+ constructor(runner, options) {
16
+ super(runner, () => options.createStore());
17
+ this.options = options;
18
+ }
19
+ tests() {
20
+ this.keeps();
21
+ this.refusesStaleVersions();
22
+ if (this.options.unitOfWork !== undefined) {
23
+ this.sharesTheUnitOfWork(this.options.unitOfWork);
24
+ }
25
+ }
26
+ keeps() {
27
+ this.it('knows no instance before it is saved, and gives one back as saved', async () => {
28
+ this.expect(await this.subject.load(NAME, 'invoice-1')).toBe(undefined);
29
+ await this.subject.save(anInstance(1));
30
+ this.expect(await this.subject.load(NAME, 'invoice-1')).toEqual(anInstance(1));
31
+ this.expect(await this.subject.load('billing.collection', 'invoice-1')).toBe(undefined);
32
+ });
33
+ this.it('keeps the next versions, the end and the timeouts', async () => {
34
+ await this.subject.save(anInstance(1));
35
+ await this.subject.save({ ...anInstance(2), ended: true, timeouts: {} });
36
+ this.expect(await this.subject.load(NAME, 'invoice-1')).toEqual({ ...anInstance(2), ended: true, timeouts: {} });
37
+ });
38
+ }
39
+ refusesStaleVersions() {
40
+ this.it('refuses a version that is not the next one', async () => {
41
+ await this.subject.save(anInstance(1));
42
+ const failures = [
43
+ await failureOf(() => this.subject.save(anInstance(1))),
44
+ await failureOf(() => this.subject.save(anInstance(3))),
45
+ ];
46
+ this.expect(failures.map(codeOf)).toEqual(['CONCURRENCY_CONFLICT', 'CONCURRENCY_CONFLICT']);
47
+ this.expect((await this.subject.load(NAME, 'invoice-1'))?.version).toBe(1);
48
+ });
49
+ this.it('lets one of two first saves of an instance win', async () => {
50
+ const outcomes = await Promise.all([
51
+ failureOf(() => this.subject.save(anInstance(1))),
52
+ failureOf(() => this.subject.save({ ...anInstance(1), state: { stage: 'other' } })),
53
+ ]);
54
+ this.expect(outcomes.filter((failure) => failure === undefined).length).toBe(1);
55
+ this.expect(outcomes.map(codeOf).filter((code) => code !== undefined)).toEqual(['CONCURRENCY_CONFLICT']);
56
+ });
57
+ }
58
+ sharesTheUnitOfWork(unitOfWork) {
59
+ this.it('leaves nothing behind a unit of work that rolled back', async () => {
60
+ await failureOf(() => unitOfWork().run(async () => {
61
+ await this.subject.save(anInstance(1));
62
+ throw new Error('the step failed');
63
+ }));
64
+ this.expect(await this.subject.load(NAME, 'invoice-1')).toBe(undefined);
65
+ });
66
+ }
67
+ }
68
+ function anInstance(version) {
69
+ return {
70
+ name: NAME,
71
+ id: 'invoice-1',
72
+ state: { stage: 'reminded', reminders: [1, 2], amount: 12.5, note: null },
73
+ version,
74
+ ended: false,
75
+ timeouts: { 'second-reminder': 'job-7' },
76
+ };
77
+ }
78
+ function codeOf(failure) {
79
+ return typeof failure === 'object' && failure !== null ? Reflect.get(failure, 'code') : undefined;
80
+ }
81
+ //# sourceMappingURL=process-store-contract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-store-contract.js","sourceRoot":"","sources":["../../src/contracts/process-store-contract.ts"],"names":[],"mappings":"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"}
@@ -18,6 +18,8 @@ export { jobSchedulerContract, type JobSchedulerContractOptions, type JobSchedul
18
18
  export { eventStoreContract, type EventStoreContractOptions } from './contracts/event-store-contract.js';
19
19
  export type { EventStoreUnderContract } from './contracts/event-store/event-store-under-contract.js';
20
20
  export { eventStoreUnitOfWorkContract, type EventStoreUnitOfWorkContractOptions, } from './contracts/event-store-unit-of-work-contract.js';
21
+ export { jobStoreContract, type JobStoreContractOptions } from './contracts/job-store-contract.js';
22
+ export type { JobStoreUnderContract } from './contracts/job-store/job-store-under-contract.js';
21
23
  export { lockContract, type LockContractOptions } from './contracts/lock-contract.js';
22
24
  export { loggerContract, type LoggerContractOptions } from './contracts/logger-contract.js';
23
25
  export type { CreateLogger } from './contracts/logger/create-logger.js';
@@ -25,6 +27,7 @@ export type { LoggedLine } from './contracts/logger/logged-line.js';
25
27
  export type { LoggerContractSetup } from './contracts/logger/logger-contract-setup.js';
26
28
  export type { LoggerUnderContract } from './contracts/logger/logger-under-contract.js';
27
29
  export { outboxStoreContract, type OutboxStoreContractOptions, type OutboxStoreUnderContract, } from './contracts/outbox-store-contract.js';
30
+ export { processStoreContract, type ProcessStoreContractOptions, type ProcessStoreUnderContract, } from './contracts/process-store-contract.js';
28
31
  export { processedEventStoreContract, type ProcessedEventStoreContractOptions, } from './contracts/processed-event-store-contract.js';
29
32
  export { rateLimiterContract, type RateLimiterContractOptions } from './contracts/rate-limiter-contract.js';
30
33
  export { readModelStoreContract, type ReadModelStoreContractOptions } from './contracts/read-model-store-contract.js';
@@ -1 +1 @@
1
- {"version":3,"file":"contracts.d.ts","sourceRoot":"","sources":["../src/contracts.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,KAAK,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACzF,YAAY,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC9D,OAAO,EACL,gBAAgB,EAChB,KAAK,uBAAuB,EAC5B,KAAK,sBAAsB,GAC5B,MAAM,kCAAkC,CAAC;AAC1C,YAAY,EAAE,YAAY,EAAE,MAAM,uCAAuC,CAAC;AAC1E,OAAO,EAAE,0BAA0B,EAAE,MAAM,sDAAsD,CAAC;AAClG,YAAY,EAAE,mBAAmB,EAAE,MAAM,+CAA+C,CAAC;AACzF,OAAO,EAAE,oBAAoB,EAAE,MAAM,gDAAgD,CAAC;AACtF,OAAO,EACL,gBAAgB,EAChB,KAAK,uBAAuB,EAC5B,KAAK,qBAAqB,GAC3B,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;AAC3E,YAAY,EAAE,0BAA0B,EAAE,MAAM,2DAA2D,CAAC;AAC5G,OAAO,EAAE,YAAY,EAAE,MAAM,2CAA2C,CAAC;AACzE,OAAO,EAAE,eAAe,EAAE,MAAM,+CAA+C,CAAC;AAChF,YAAY,EAAE,gBAAgB,EAAE,MAAM,+CAA+C,CAAC;AACtF,YAAY,EAAE,aAAa,EAAE,MAAM,4CAA4C,CAAC;AAChF,OAAO,EACL,oBAAoB,EACpB,KAAK,2BAA2B,EAChC,KAAK,yBAAyB,GAC/B,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,KAAK,yBAAyB,EAAE,MAAM,qCAAqC,CAAC;AACzG,YAAY,EAAE,uBAAuB,EAAE,MAAM,uDAAuD,CAAC;AACrG,OAAO,EACL,4BAA4B,EAC5B,KAAK,mCAAmC,GACzC,MAAM,kDAAkD,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,KAAK,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACtF,OAAO,EAAE,cAAc,EAAE,KAAK,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AAC5F,YAAY,EAAE,YAAY,EAAE,MAAM,qCAAqC,CAAC;AACxE,YAAY,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAC;AACpE,YAAY,EAAE,mBAAmB,EAAE,MAAM,6CAA6C,CAAC;AACvF,YAAY,EAAE,mBAAmB,EAAE,MAAM,6CAA6C,CAAC;AACvF,OAAO,EACL,mBAAmB,EACnB,KAAK,0BAA0B,EAC/B,KAAK,wBAAwB,GAC9B,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EACL,2BAA2B,EAC3B,KAAK,kCAAkC,GACxC,MAAM,+CAA+C,CAAC;AACvD,OAAO,EAAE,mBAAmB,EAAE,KAAK,0BAA0B,EAAE,MAAM,sCAAsC,CAAC;AAC5G,OAAO,EAAE,sBAAsB,EAAE,KAAK,6BAA6B,EAAE,MAAM,0CAA0C,CAAC;AACtH,YAAY,EAAE,2BAA2B,EAAE,MAAM,2DAA2D,CAAC;AAC7G,OAAO,EAAE,aAAa,EAAE,MAAM,2CAA2C,CAAC;AAC1E,OAAO,EAAE,kBAAkB,EAAE,KAAK,yBAAyB,EAAE,MAAM,oCAAoC,CAAC;AACxG,OAAO,EACL,uBAAuB,EACvB,KAAK,8BAA8B,GACpC,MAAM,0CAA0C,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAE,KAAK,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AAC1G,YAAY,EAAE,uBAAuB,EAAE,MAAM,yDAAyD,CAAC"}
1
+ {"version":3,"file":"contracts.d.ts","sourceRoot":"","sources":["../src/contracts.ts"],"names":[],"mappings":"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"}
package/dist/contracts.js CHANGED
@@ -10,9 +10,11 @@ export { followWithFetch } from './contracts/file-storage/follow-with-fetch.js';
10
10
  export { jobSchedulerContract, } from './contracts/job-scheduler-contract.js';
11
11
  export { eventStoreContract } from './contracts/event-store-contract.js';
12
12
  export { eventStoreUnitOfWorkContract, } from './contracts/event-store-unit-of-work-contract.js';
13
+ export { jobStoreContract } from './contracts/job-store-contract.js';
13
14
  export { lockContract } from './contracts/lock-contract.js';
14
15
  export { loggerContract } from './contracts/logger-contract.js';
15
16
  export { outboxStoreContract, } from './contracts/outbox-store-contract.js';
17
+ export { processStoreContract, } from './contracts/process-store-contract.js';
16
18
  export { processedEventStoreContract, } from './contracts/processed-event-store-contract.js';
17
19
  export { rateLimiterContract } from './contracts/rate-limiter-contract.js';
18
20
  export { readModelStoreContract } from './contracts/read-model-store-contract.js';
@@ -1 +1 @@
1
- {"version":3,"file":"contracts.js","sourceRoot":"","sources":["../src/contracts.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAA6B,MAAM,+BAA+B,CAAC;AAEzF,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC9D,OAAO,EACL,gBAAgB,GAGjB,MAAM,kCAAkC,CAAC;AAE1C,OAAO,EAAE,0BAA0B,EAAE,MAAM,sDAAsD,CAAC;AAElG,OAAO,EAAE,oBAAoB,EAAE,MAAM,gDAAgD,CAAC;AACtF,OAAO,EACL,gBAAgB,GAGjB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;AAE3E,OAAO,EAAE,YAAY,EAAE,MAAM,2CAA2C,CAAC;AACzE,OAAO,EAAE,eAAe,EAAE,MAAM,+CAA+C,CAAC;AAGhF,OAAO,EACL,oBAAoB,GAGrB,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAkC,MAAM,qCAAqC,CAAC;AAEzG,OAAO,EACL,4BAA4B,GAE7B,MAAM,kDAAkD,CAAC;AAC1D,OAAO,EAAE,YAAY,EAA4B,MAAM,8BAA8B,CAAC;AACtF,OAAO,EAAE,cAAc,EAA8B,MAAM,gCAAgC,CAAC;AAK5F,OAAO,EACL,mBAAmB,GAGpB,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EACL,2BAA2B,GAE5B,MAAM,+CAA+C,CAAC;AACvD,OAAO,EAAE,mBAAmB,EAAmC,MAAM,sCAAsC,CAAC;AAC5G,OAAO,EAAE,sBAAsB,EAAsC,MAAM,0CAA0C,CAAC;AAEtH,OAAO,EAAE,aAAa,EAAE,MAAM,2CAA2C,CAAC;AAC1E,OAAO,EAAE,kBAAkB,EAAkC,MAAM,oCAAoC,CAAC;AACxG,OAAO,EACL,uBAAuB,GAExB,MAAM,0CAA0C,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAkC,MAAM,sCAAsC,CAAC"}
1
+ {"version":3,"file":"contracts.js","sourceRoot":"","sources":["../src/contracts.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAA6B,MAAM,+BAA+B,CAAC;AAEzF,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC9D,OAAO,EACL,gBAAgB,GAGjB,MAAM,kCAAkC,CAAC;AAE1C,OAAO,EAAE,0BAA0B,EAAE,MAAM,sDAAsD,CAAC;AAElG,OAAO,EAAE,oBAAoB,EAAE,MAAM,gDAAgD,CAAC;AACtF,OAAO,EACL,gBAAgB,GAGjB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;AAE3E,OAAO,EAAE,YAAY,EAAE,MAAM,2CAA2C,CAAC;AACzE,OAAO,EAAE,eAAe,EAAE,MAAM,+CAA+C,CAAC;AAGhF,OAAO,EACL,oBAAoB,GAGrB,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAkC,MAAM,qCAAqC,CAAC;AAEzG,OAAO,EACL,4BAA4B,GAE7B,MAAM,kDAAkD,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAgC,MAAM,mCAAmC,CAAC;AAEnG,OAAO,EAAE,YAAY,EAA4B,MAAM,8BAA8B,CAAC;AACtF,OAAO,EAAE,cAAc,EAA8B,MAAM,gCAAgC,CAAC;AAK5F,OAAO,EACL,mBAAmB,GAGpB,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EACL,oBAAoB,GAGrB,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EACL,2BAA2B,GAE5B,MAAM,+CAA+C,CAAC;AACvD,OAAO,EAAE,mBAAmB,EAAmC,MAAM,sCAAsC,CAAC;AAC5G,OAAO,EAAE,sBAAsB,EAAsC,MAAM,0CAA0C,CAAC;AAEtH,OAAO,EAAE,aAAa,EAAE,MAAM,2CAA2C,CAAC;AAC1E,OAAO,EAAE,kBAAkB,EAAkC,MAAM,oCAAoC,CAAC;AACxG,OAAO,EACL,uBAAuB,GAExB,MAAM,0CAA0C,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAkC,MAAM,sCAAsC,CAAC"}
package/dist/index.d.ts CHANGED
@@ -15,6 +15,9 @@ export { scoped } from './execution/scoped.js';
15
15
  export { asTenant } from './execution/as-tenant.js';
16
16
  export { SessionBuilder } from './execution/session-builder.js';
17
17
  export { createTestBuses, type TestBuses, type TestBusesOptions } from './harness/create-test-buses.js';
18
+ export type { CommandMatcher } from './processes/command-matcher.js';
19
+ export { givenProcess, type ProcessScenario } from './processes/given-process.js';
20
+ export { ProcessOutcome } from './processes/process-outcome.js';
18
21
  export { expectSnapshotEquivalence } from './event-sourcing/expect-snapshot-equivalence.js';
19
22
  export { givenEvents } from './event-sourcing/given-events.js';
20
23
  export type { SnapshotEquivalence } from './event-sourcing/snapshot-equivalence.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC5E,YAAY,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,YAAY,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAC1C,YAAY,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AACzE,OAAO,EAAE,uBAAuB,EAAE,MAAM,0CAA0C,CAAC;AACnF,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,EAAE,eAAe,EAAE,KAAK,SAAS,EAAE,KAAK,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACxG,OAAO,EAAE,yBAAyB,EAAE,MAAM,iDAAiD,CAAC;AAC5F,OAAO,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AAC/D,YAAY,EAAE,mBAAmB,EAAE,MAAM,0CAA0C,CAAC;AACpF,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,YAAY,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAE,KAAK,yBAAyB,EAAE,MAAM,wCAAwC,CAAC;AAC5G,OAAO,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,YAAY,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AACjE,YAAY,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACnE,YAAY,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AACjE,YAAY,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAC7C,YAAY,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,KAAK,QAAQ,EAAE,MAAM,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC5E,YAAY,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,YAAY,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAC1C,YAAY,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AACzE,OAAO,EAAE,uBAAuB,EAAE,MAAM,0CAA0C,CAAC;AACnF,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,EAAE,eAAe,EAAE,KAAK,SAAS,EAAE,KAAK,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACxG,YAAY,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,YAAY,EAAE,KAAK,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAClF,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,EAAE,yBAAyB,EAAE,MAAM,iDAAiD,CAAC;AAC5F,OAAO,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AAC/D,YAAY,EAAE,mBAAmB,EAAE,MAAM,0CAA0C,CAAC;AACpF,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,YAAY,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAE,KAAK,yBAAyB,EAAE,MAAM,wCAAwC,CAAC;AAC5G,OAAO,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,YAAY,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AACjE,YAAY,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACnE,YAAY,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AACjE,YAAY,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAC7C,YAAY,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,KAAK,QAAQ,EAAE,MAAM,yBAAyB,CAAC"}
package/dist/index.js CHANGED
@@ -12,6 +12,8 @@ export { scoped } from './execution/scoped.js';
12
12
  export { asTenant } from './execution/as-tenant.js';
13
13
  export { SessionBuilder } from './execution/session-builder.js';
14
14
  export { createTestBuses } from './harness/create-test-buses.js';
15
+ export { givenProcess } from './processes/given-process.js';
16
+ export { ProcessOutcome } from './processes/process-outcome.js';
15
17
  export { expectSnapshotEquivalence } from './event-sourcing/expect-snapshot-equivalence.js';
16
18
  export { givenEvents } from './event-sourcing/given-events.js';
17
19
  export { expectRefusal } from './refusals/expect-refusal.js';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAE5E,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAEhD,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAE1C,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AACzE,OAAO,EAAE,uBAAuB,EAAE,MAAM,0CAA0C,CAAC;AACnF,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,EAAE,eAAe,EAAyC,MAAM,gCAAgC,CAAC;AACxG,OAAO,EAAE,yBAAyB,EAAE,MAAM,iDAAiD,CAAC;AAC5F,OAAO,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AAE/D,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAE7D,OAAO,EAAE,kBAAkB,EAAkC,MAAM,wCAAwC,CAAC;AAC5G,OAAO,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAK/D,OAAO,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAE7C,OAAO,EAAE,QAAQ,EAAiB,MAAM,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAE5E,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAEhD,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAE1C,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AACzE,OAAO,EAAE,uBAAuB,EAAE,MAAM,0CAA0C,CAAC;AACnF,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,EAAE,eAAe,EAAyC,MAAM,gCAAgC,CAAC;AAExG,OAAO,EAAE,YAAY,EAAwB,MAAM,8BAA8B,CAAC;AAClF,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,EAAE,yBAAyB,EAAE,MAAM,iDAAiD,CAAC;AAC5F,OAAO,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AAE/D,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAE7D,OAAO,EAAE,kBAAkB,EAAkC,MAAM,wCAAwC,CAAC;AAC5G,OAAO,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAK/D,OAAO,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAE7C,OAAO,EAAE,QAAQ,EAAiB,MAAM,yBAAyB,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { Command } from '@ddd-ts-kit/kernel';
2
+ type CommandClass = abstract new (...args: never[]) => Command<unknown>;
3
+ /** How an expected command is described: its class, or the properties that matter (a subset). */
4
+ export type CommandMatcher = CommandClass | {
5
+ readonly [property: string]: unknown;
6
+ };
7
+ export {};
8
+ //# sourceMappingURL=command-matcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-matcher.d.ts","sourceRoot":"","sources":["../../src/processes/command-matcher.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAElD,KAAK,YAAY,GAAG,QAAQ,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAExE,iGAAiG;AACjG,MAAM,MAAM,cAAc,GAAG,YAAY,GAAG;IAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=command-matcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-matcher.js","sourceRoot":"","sources":["../../src/processes/command-matcher.ts"],"names":[],"mappings":""}
@@ -0,0 +1,18 @@
1
+ import type { ProcessDecision } from '@ddd-ts-kit/kernel';
2
+ import { ProcessOutcome } from './process-outcome.js';
3
+ /** A step of a process, from the state it starts in. */
4
+ export interface ProcessScenario<State> {
5
+ when(step: (current: State | undefined) => ProcessDecision<State> | undefined): ProcessOutcome<State>;
6
+ }
7
+ /**
8
+ * Starts the spec of a step of a process manager from a state, or from none for an instance
9
+ * that does not exist yet: the step is a function of the state and of what happened, so it is
10
+ * tested without a store, a queue or a bus.
11
+ *
12
+ * givenProcess<ReminderState>(undefined)
13
+ * .when((current) => reminders.booked(event, current))
14
+ * .thenState({ appointmentId: 'a-1', stage: 'waiting' })
15
+ * .thenTimeouts([{ name: 'reminder-due', at: dueAt }]);
16
+ */
17
+ export declare function givenProcess<State>(current: State | undefined): ProcessScenario<State>;
18
+ //# sourceMappingURL=given-process.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"given-process.d.ts","sourceRoot":"","sources":["../../src/processes/given-process.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,wDAAwD;AACxD,MAAM,WAAW,eAAe,CAAC,KAAK;IACpC,IAAI,CAAC,IAAI,EAAE,CAAC,OAAO,EAAE,KAAK,GAAG,SAAS,KAAK,eAAe,CAAC,KAAK,CAAC,GAAG,SAAS,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;CACvG;AAED;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,GAAG,SAAS,GAAG,eAAe,CAAC,KAAK,CAAC,CAItF"}
@@ -0,0 +1,17 @@
1
+ import { ProcessOutcome } from './process-outcome.js';
2
+ /**
3
+ * Starts the spec of a step of a process manager from a state, or from none for an instance
4
+ * that does not exist yet: the step is a function of the state and of what happened, so it is
5
+ * tested without a store, a queue or a bus.
6
+ *
7
+ * givenProcess<ReminderState>(undefined)
8
+ * .when((current) => reminders.booked(event, current))
9
+ * .thenState({ appointmentId: 'a-1', stage: 'waiting' })
10
+ * .thenTimeouts([{ name: 'reminder-due', at: dueAt }]);
11
+ */
12
+ export function givenProcess(current) {
13
+ return {
14
+ when: (step) => new ProcessOutcome(step(current)),
15
+ };
16
+ }
17
+ //# sourceMappingURL=given-process.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"given-process.js","sourceRoot":"","sources":["../../src/processes/given-process.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAOtD;;;;;;;;;GASG;AACH,MAAM,UAAU,YAAY,CAAQ,OAA0B;IAC5D,OAAO;QACL,IAAI,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;KAClD,CAAC;AACJ,CAAC"}
@@ -0,0 +1,20 @@
1
+ import type { ProcessDecision, ProcessTimeout } from '@ddd-ts-kit/kernel';
2
+ import type { CommandMatcher } from './command-matcher.js';
3
+ /** What one step of a process decided, asserted without a store, a queue or a bus. Each assertion answers the outcome, to chain. */
4
+ export declare class ProcessOutcome<State> {
5
+ private readonly decision;
6
+ constructor(decision: ProcessDecision<State> | undefined);
7
+ /** The step ignored what it was given: no state saved, nothing sent. */
8
+ thenIgnored(): this;
9
+ /** Also asserts that the state survives the JSON the runner stores it as: a `Date` or a class instance does not. */
10
+ thenState(expected: State): this;
11
+ /** Exactly these commands, in order: each by its class or the properties that matter. */
12
+ thenCommands(expected: readonly CommandMatcher[]): this;
13
+ thenTimeouts(expected: readonly ProcessTimeout[]): this;
14
+ /** The names of the timeouts the step disarms. */
15
+ thenCancelled(expected: readonly string[]): this;
16
+ thenEnded(): this;
17
+ private decided;
18
+ private holds;
19
+ }
20
+ //# sourceMappingURL=process-outcome.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-outcome.d.ts","sourceRoot":"","sources":["../../src/processes/process-outcome.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAG1E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,oIAAoI;AACpI,qBAAa,cAAc,CAAC,KAAK;IACnB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAArC,YAA6B,QAAQ,EAAE,eAAe,CAAC,KAAK,CAAC,GAAG,SAAS,EAAI;IAE7E,wEAAwE;IACxE,WAAW,IAAI,IAAI,CAElB;IAED,oHAAoH;IACpH,SAAS,CAAC,QAAQ,EAAE,KAAK,GAAG,IAAI,CAa/B;IAED,yFAAyF;IACzF,YAAY,CAAC,QAAQ,EAAE,SAAS,cAAc,EAAE,GAAG,IAAI,CAStD;IAED,YAAY,CAAC,QAAQ,EAAE,SAAS,cAAc,EAAE,GAAG,IAAI,CAOtD;IAED,kDAAkD;IAClD,aAAa,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAO/C;IAED,SAAS,IAAI,IAAI,CAEhB;IAED,OAAO,CAAC,OAAO;IAQf,OAAO,CAAC,KAAK;CAOd"}
@@ -0,0 +1,67 @@
1
+ import { AssertionError } from 'node:assert';
2
+ import { isDeepStrictEqual } from 'node:util';
3
+ import { show } from '../scenarios/show.js';
4
+ import { subsetDifferences } from '../scenarios/subset-differences.js';
5
+ /** What one step of a process decided, asserted without a store, a queue or a bus. Each assertion answers the outcome, to chain. */
6
+ export class ProcessOutcome {
7
+ decision;
8
+ constructor(decision) {
9
+ this.decision = decision;
10
+ }
11
+ /** The step ignored what it was given: no state saved, nothing sent. */
12
+ thenIgnored() {
13
+ return this.holds(this.decision === undefined, `expected the step to ignore it, it decided ${show(this.decision)}`);
14
+ }
15
+ /** Also asserts that the state survives the JSON the runner stores it as: a `Date` or a class instance does not. */
16
+ thenState(expected) {
17
+ const state = this.decided().state;
18
+ const stored = state === undefined ? undefined : JSON.parse(JSON.stringify(state));
19
+ this.holds(isDeepStrictEqual(stored, state), `the state ${show(state)} is stored as JSON and read back as ${show(stored)}: keep it plain JSON data`);
20
+ return this.holds(isDeepStrictEqual(state, expected), `expected the state ${show(expected)}, decided ${show(state)}`);
21
+ }
22
+ /** Exactly these commands, in order: each by its class or the properties that matter. */
23
+ thenCommands(expected) {
24
+ const sent = this.decided().commands ?? [];
25
+ const lines = [
26
+ ...(sent.length === expected.length ? [] : [`expected ${expected.length} command(s), decided ${sent.length}`]),
27
+ ...expected.flatMap((matcher, index) => commandMismatches(sent[index], matcher, `command ${index}`)),
28
+ ];
29
+ return this.holds(lines.length === 0, lines.join('\n'));
30
+ }
31
+ thenTimeouts(expected) {
32
+ const armed = this.decided().timeouts ?? [];
33
+ return this.holds(isDeepStrictEqual(armed, expected), `expected the timeouts ${show(expected)}, decided ${show(armed)}`);
34
+ }
35
+ /** The names of the timeouts the step disarms. */
36
+ thenCancelled(expected) {
37
+ const cancelled = this.decided().cancel ?? [];
38
+ return this.holds(isDeepStrictEqual(cancelled, expected), `expected to disarm ${show(expected)}, decided ${show(cancelled)}`);
39
+ }
40
+ thenEnded() {
41
+ return this.holds(this.decided().ended === true, 'expected the process to end, it goes on');
42
+ }
43
+ decided() {
44
+ if (this.decision === undefined) {
45
+ throw new AssertionError({ message: 'expected a decision, the step ignored what it was given' });
46
+ }
47
+ return this.decision;
48
+ }
49
+ holds(condition, message) {
50
+ if (!condition) {
51
+ throw new AssertionError({ message });
52
+ }
53
+ return this;
54
+ }
55
+ }
56
+ function commandMismatches(command, matcher, where) {
57
+ if (command === undefined) {
58
+ return [`${where}: none was decided`];
59
+ }
60
+ if (typeof matcher === 'function') {
61
+ return command instanceof matcher
62
+ ? []
63
+ : [`${where}: expected an instance of ${matcher.name}, decided ${show(command)}`];
64
+ }
65
+ return subsetDifferences(command, matcher, where);
66
+ }
67
+ //# sourceMappingURL=process-outcome.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-outcome.js","sourceRoot":"","sources":["../../src/processes/process-outcome.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"event-mismatches.d.ts","sourceRoot":"","sources":["../../src/scenarios/event-mismatches.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAGvD,oGAAoG;AACpG,wBAAgB,eAAe,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAYlG"}
1
+ {"version":3,"file":"event-mismatches.d.ts","sourceRoot":"","sources":["../../src/scenarios/event-mismatches.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAIvD,oGAAoG;AACpG,wBAAgB,eAAe,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAYlG"}
@@ -1,6 +1,6 @@
1
- import { isDeepStrictEqual } from 'node:util';
2
1
  import { describeEvent } from './describe-event.js';
3
2
  import { show } from './show.js';
3
+ import { subsetDifferences } from './subset-differences.js';
4
4
  /** Why the event is not the one the matcher describes, one line per difference; none when it is. */
5
5
  export function eventMismatches(event, matcher, where) {
6
6
  if (typeof matcher === 'string') {
@@ -13,21 +13,4 @@ export function eventMismatches(event, matcher, where) {
13
13
  }
14
14
  return subsetDifferences(event, matcher, where);
15
15
  }
16
- function subsetDifferences(actual, expected, path) {
17
- if (isPlainObject(expected) && typeof actual === 'object' && actual !== null) {
18
- return Object.entries(expected).flatMap(([key, value]) => {
19
- // Reflect.get rather than a spread: an event class may expose a property through a getter.
20
- const recorded = Reflect.get(actual, key);
21
- return subsetDifferences(recorded, value, `${path}.${key}`);
22
- });
23
- }
24
- return isDeepStrictEqual(actual, expected) ? [] : [`${path}: expected ${show(expected)}, recorded ${show(actual)}`];
25
- }
26
- function isPlainObject(value) {
27
- if (typeof value !== 'object' || value === null) {
28
- return false;
29
- }
30
- const prototype = Object.getPrototypeOf(value);
31
- return prototype === Object.prototype || prototype === null;
32
- }
33
16
  //# sourceMappingURL=event-mismatches.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"event-mismatches.js","sourceRoot":"","sources":["../../src/scenarios/event-mismatches.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAE9C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,oGAAoG;AACpG,MAAM,UAAU,eAAe,CAAC,KAAkB,EAAE,OAAqB,EAAE,KAAa;IACtF,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QAChC,OAAO,OAAO,KAAK,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,mBAAmB,IAAI,CAAC,OAAO,CAAC,cAAc,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAClH,CAAC;IAED,IAAI,OAAO,OAAO,KAAK,UAAU,EAAE,CAAC;QAClC,OAAO,KAAK,YAAY,OAAO;YAC7B,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,CAAC,GAAG,KAAK,6BAA6B,OAAO,CAAC,IAAI,cAAc,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC9F,CAAC;IAED,OAAO,iBAAiB,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;AAClD,CAAC;AAED,SAAS,iBAAiB,CAAC,MAAe,EAAE,QAAiB,EAAE,IAAY;IACzE,IAAI,aAAa,CAAC,QAAQ,CAAC,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;QAC7E,OAAO,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE;YACvD,2FAA2F;YAC3F,MAAM,QAAQ,GAAY,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YAEnD,OAAO,iBAAiB,CAAC,QAAQ,EAAE,KAAK,EAAE,GAAG,IAAI,IAAI,GAAG,EAAE,CAAC,CAAC;QAC9D,CAAC,CAAC,CAAC;IACL,CAAC;IAED,OAAO,iBAAiB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,cAAc,IAAI,CAAC,QAAQ,CAAC,cAAc,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AACtH,CAAC;AAED,SAAS,aAAa,CAAC,KAAc;IACnC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QAChD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,SAAS,GAAY,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;IAExD,OAAO,SAAS,KAAK,MAAM,CAAC,SAAS,IAAI,SAAS,KAAK,IAAI,CAAC;AAC9D,CAAC"}
1
+ {"version":3,"file":"event-mismatches.js","sourceRoot":"","sources":["../../src/scenarios/event-mismatches.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAE5D,oGAAoG;AACpG,MAAM,UAAU,eAAe,CAAC,KAAkB,EAAE,OAAqB,EAAE,KAAa;IACtF,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QAChC,OAAO,OAAO,KAAK,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,mBAAmB,IAAI,CAAC,OAAO,CAAC,cAAc,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAClH,CAAC;IAED,IAAI,OAAO,OAAO,KAAK,UAAU,EAAE,CAAC;QAClC,OAAO,KAAK,YAAY,OAAO;YAC7B,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,CAAC,GAAG,KAAK,6BAA6B,OAAO,CAAC,IAAI,cAAc,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC9F,CAAC;IAED,OAAO,iBAAiB,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;AAClD,CAAC"}
@@ -0,0 +1,3 @@
1
+ /** Where `actual` differs from the properties `expected` names, one line each: a plain object of `expected` is a subset. */
2
+ export declare function subsetDifferences(actual: unknown, expected: unknown, path: string): string[];
3
+ //# sourceMappingURL=subset-differences.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subset-differences.d.ts","sourceRoot":"","sources":["../../src/scenarios/subset-differences.ts"],"names":[],"mappings":"AAGA,4HAA4H;AAC5H,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAW5F"}
@@ -0,0 +1,21 @@
1
+ import { isDeepStrictEqual } from 'node:util';
2
+ import { show } from './show.js';
3
+ /** Where `actual` differs from the properties `expected` names, one line each: a plain object of `expected` is a subset. */
4
+ export function subsetDifferences(actual, expected, path) {
5
+ if (isPlainObject(expected) && typeof actual === 'object' && actual !== null) {
6
+ return Object.entries(expected).flatMap(([key, value]) => {
7
+ // Reflect.get rather than a spread: an event class may expose a property through a getter.
8
+ const recorded = Reflect.get(actual, key);
9
+ return subsetDifferences(recorded, value, `${path}.${key}`);
10
+ });
11
+ }
12
+ return isDeepStrictEqual(actual, expected) ? [] : [`${path}: expected ${show(expected)}, recorded ${show(actual)}`];
13
+ }
14
+ function isPlainObject(value) {
15
+ if (typeof value !== 'object' || value === null) {
16
+ return false;
17
+ }
18
+ const prototype = Object.getPrototypeOf(value);
19
+ return prototype === Object.prototype || prototype === null;
20
+ }
21
+ //# sourceMappingURL=subset-differences.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subset-differences.js","sourceRoot":"","sources":["../../src/scenarios/subset-differences.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,4HAA4H;AAC5H,MAAM,UAAU,iBAAiB,CAAC,MAAe,EAAE,QAAiB,EAAE,IAAY;IAChF,IAAI,aAAa,CAAC,QAAQ,CAAC,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;QAC7E,OAAO,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE;YACvD,2FAA2F;YAC3F,MAAM,QAAQ,GAAY,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YAEnD,OAAO,iBAAiB,CAAC,QAAQ,EAAE,KAAK,EAAE,GAAG,IAAI,IAAI,GAAG,EAAE,CAAC,CAAC;QAC9D,CAAC,CAAC,CAAC;IACL,CAAC;IAED,OAAO,iBAAiB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,cAAc,IAAI,CAAC,QAAQ,CAAC,cAAc,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AACtH,CAAC;AAED,SAAS,aAAa,CAAC,KAAc;IACnC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QAChD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,SAAS,GAAY,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;IAExD,OAAO,SAAS,KAAK,MAAM,CAAC,SAAS,IAAI,SAAS,KAAK,IAAI,CAAC;AAC9D,CAAC"}