@requence/event-sourcing 1.0.3 → 1.1.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 (64) hide show
  1. package/README.md +1 -1
  2. package/dist/{chunk-8pchcyvm.js → chunk-04wqxaqs.js} +28 -18
  3. package/dist/chunk-04wqxaqs.js.map +10 -0
  4. package/dist/{chunk-3t1vzbab.js → chunk-263c07sn.js} +3 -2
  5. package/dist/{chunk-3t1vzbab.js.map → chunk-263c07sn.js.map} +3 -3
  6. package/dist/{chunk-x90g388y.js → chunk-2fe8jjdc.js} +1 -1
  7. package/dist/{chunk-qdczt68t.js → chunk-391m4mfp.js} +14 -2
  8. package/dist/chunk-391m4mfp.js.map +10 -0
  9. package/dist/{chunk-9psg50cb.js → chunk-6yrb30rx.js} +1 -1
  10. package/dist/{chunk-pmfzjavb.js → chunk-8qn1nqnh.js} +1 -1
  11. package/dist/{chunk-6n3jfg84.js → chunk-r601d5jm.js} +18 -18
  12. package/dist/{chunk-6n3jfg84.js.map → chunk-r601d5jm.js.map} +1 -1
  13. package/dist/{chunk-13wtyj2h.js → chunk-smy8mxvr.js} +37 -23
  14. package/dist/chunk-smy8mxvr.js.map +10 -0
  15. package/dist/{chunk-8ev7sb2v.js → chunk-th14wxh8.js} +7 -7
  16. package/dist/{chunk-8ev7sb2v.js.map → chunk-th14wxh8.js.map} +1 -1
  17. package/dist/{chunk-zf3x573k.js → chunk-yn2sjcg3.js} +36 -11
  18. package/dist/chunk-yn2sjcg3.js.map +10 -0
  19. package/dist/createAggregateRoot.js +9 -9
  20. package/dist/createCheckpointApi.d.ts +37 -2
  21. package/dist/createCheckpointApi.d.ts.map +1 -1
  22. package/dist/createCheckpointApi.js +2 -2
  23. package/dist/createEventStore.js +11 -11
  24. package/dist/createProcessManager.d.ts.map +1 -1
  25. package/dist/createProcessManager.js +4 -4
  26. package/dist/createProjection.js +5 -5
  27. package/dist/drizzle/index.d.ts.map +1 -1
  28. package/dist/drizzle/index.js +34 -28
  29. package/dist/drizzle/index.js.map +3 -3
  30. package/dist/drizzle/postgres.d.ts +17 -0
  31. package/dist/drizzle/postgres.d.ts.map +1 -1
  32. package/dist/drizzle/postgres.js +1 -1
  33. package/dist/errors.d.ts +6 -0
  34. package/dist/errors.d.ts.map +1 -1
  35. package/dist/errors.js +5 -3
  36. package/dist/errors.js.map +1 -1
  37. package/dist/index.js +25 -23
  38. package/dist/index.js.map +1 -1
  39. package/dist/memory/index.d.ts.map +1 -1
  40. package/dist/memory/index.js +21 -16
  41. package/dist/memory/index.js.map +3 -3
  42. package/dist/refresh.js +2 -2
  43. package/dist/replay.js +2 -2
  44. package/dist/snapshotGenerator.js +2 -2
  45. package/dist/tests/setup.d.ts +1 -0
  46. package/dist/tests/setup.d.ts.map +1 -1
  47. package/package.json +1 -1
  48. package/src/createCheckpointApi.ts +86 -10
  49. package/src/createEventStore.ts +23 -4
  50. package/src/createProcessManager.ts +71 -32
  51. package/src/drizzle/index.ts +19 -4
  52. package/src/drizzle/postgres.ts +3 -0
  53. package/src/errors.ts +12 -0
  54. package/src/memory/index.ts +10 -2
  55. package/src/tests/eventStore.spec.ts +28 -0
  56. package/src/tests/processManagerMultiInstance.spec.ts +86 -3
  57. package/src/tests/setup.ts +12 -2
  58. package/dist/chunk-13wtyj2h.js.map +0 -10
  59. package/dist/chunk-8pchcyvm.js.map +0 -10
  60. package/dist/chunk-qdczt68t.js.map +0 -10
  61. package/dist/chunk-zf3x573k.js.map +0 -10
  62. /package/dist/{chunk-x90g388y.js.map → chunk-2fe8jjdc.js.map} +0 -0
  63. /package/dist/{chunk-9psg50cb.js.map → chunk-6yrb30rx.js.map} +0 -0
  64. /package/dist/{chunk-pmfzjavb.js.map → chunk-8qn1nqnh.js.map} +0 -0
package/dist/errors.d.ts CHANGED
@@ -6,6 +6,12 @@ export declare class ConcurrencyError extends Error {
6
6
  id: string;
7
7
  }, expectedVersion: number, actualVersion: number);
8
8
  }
9
+ export declare class CheckpointConcurrencyError extends Error {
10
+ readonly checkpointType: 'projection' | 'processManager';
11
+ readonly name: string;
12
+ readonly expectedVersion: number | null;
13
+ constructor(checkpointType: 'projection' | 'processManager', name: string, expectedVersion: number | null);
14
+ }
9
15
  export declare class ValidationError extends Error {
10
16
  readonly zodError: z.ZodError;
11
17
  constructor(message: string, zodError: z.ZodError);
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,QAAQ,CAAA;AAEtB,OAAO,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAErE,qBAAa,gBAAiB,SAAQ,KAAK;gBAEvC,QAAQ,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,EACxC,eAAe,EAAE,MAAM,EACvB,aAAa,EAAE,MAAM;CAMxB;AAED,qBAAa,eAAgB,SAAQ,KAAK;aAGtB,QAAQ,EAAE,CAAC,CAAC,QAAQ;gBADpC,OAAO,EAAE,MAAM,EACC,QAAQ,EAAE,CAAC,CAAC,QAAQ;CAIvC;AAED,qBAAa,oBAAqB,SAAQ,eAAe;CAAG;AAE5D,qBAAa,iBAAkB,SAAQ,KAAK;CAAG;AAE/C,qBAAa,YAAY,CAAC,CAAC,SAAS,KAAK,CAAE,SAAQ,KAAK;aAEpC,iBAAiB,EAAE,MAAM;aACzB,WAAW,EAAE,MAAM;aACnB,QAAQ,EAAE,MAAM;aAChB,aAAa,EAAE,CAAC;gBAHhB,iBAAiB,EAAE,MAAM,EACzB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,CAAC;CAMnC;AAED,qBAAa,yBAA0B,SAAQ,KAAK;aAGhC,UAAU,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE;aAClD,KAAK,EAAE,WAAW,CAAC,GAAG,CAAC;gBAFvC,OAAO,EAAE,MAAM,EACC,UAAU,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,EAClD,KAAK,EAAE,WAAW,CAAC,GAAG,CAAC;CAI1C;AAED,qBAAa,mBAAoB,SAAQ,KAAK;CAAG;AAEjD,qBAAa,eAAgB,SAAQ,KAAK;CAAG;AAE7C,qBAAa,oCAAoC,CAC/C,CAAC,SAAS,KAAK,CACf,SAAQ,KAAK;aAEK,UAAU,EAAE,MAAM;aAClB,YAAY,EAAE,MAAM;aACpB,KAAK,EAAE,eAAe;aACtB,aAAa,EAAE,CAAC;gBAHhB,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,eAAe,EACtB,aAAa,EAAE,CAAC;CAMnC;AAED,qBAAa,wCAAwC,CACnD,CAAC,SAAS,KAAK,CACf,SAAQ,KAAK;aAEK,cAAc,EAAE,MAAM;aACtB,YAAY,EAAE,MAAM;aACpB,KAAK,EAAE,eAAe;aACtB,aAAa,EAAE,CAAC;gBAHhB,cAAc,EAAE,MAAM,EACtB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,eAAe,EACtB,aAAa,EAAE,CAAC;CAMnC"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,QAAQ,CAAA;AAEtB,OAAO,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAErE,qBAAa,gBAAiB,SAAQ,KAAK;gBAEvC,QAAQ,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,EACxC,eAAe,EAAE,MAAM,EACvB,aAAa,EAAE,MAAM;CAMxB;AAED,qBAAa,0BAA2B,SAAQ,KAAK;aAEjC,cAAc,EAAE,YAAY,GAAG,gBAAgB;aAC/C,IAAI,EAAE,MAAM;aACZ,eAAe,EAAE,MAAM,GAAG,IAAI;gBAF9B,cAAc,EAAE,YAAY,GAAG,gBAAgB,EAC/C,IAAI,EAAE,MAAM,EACZ,eAAe,EAAE,MAAM,GAAG,IAAI;CAMjD;AAED,qBAAa,eAAgB,SAAQ,KAAK;aAGtB,QAAQ,EAAE,CAAC,CAAC,QAAQ;gBADpC,OAAO,EAAE,MAAM,EACC,QAAQ,EAAE,CAAC,CAAC,QAAQ;CAIvC;AAED,qBAAa,oBAAqB,SAAQ,eAAe;CAAG;AAE5D,qBAAa,iBAAkB,SAAQ,KAAK;CAAG;AAE/C,qBAAa,YAAY,CAAC,CAAC,SAAS,KAAK,CAAE,SAAQ,KAAK;aAEpC,iBAAiB,EAAE,MAAM;aACzB,WAAW,EAAE,MAAM;aACnB,QAAQ,EAAE,MAAM;aAChB,aAAa,EAAE,CAAC;gBAHhB,iBAAiB,EAAE,MAAM,EACzB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,CAAC;CAMnC;AAED,qBAAa,yBAA0B,SAAQ,KAAK;aAGhC,UAAU,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE;aAClD,KAAK,EAAE,WAAW,CAAC,GAAG,CAAC;gBAFvC,OAAO,EAAE,MAAM,EACC,UAAU,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,EAClD,KAAK,EAAE,WAAW,CAAC,GAAG,CAAC;CAI1C;AAED,qBAAa,mBAAoB,SAAQ,KAAK;CAAG;AAEjD,qBAAa,eAAgB,SAAQ,KAAK;CAAG;AAE7C,qBAAa,oCAAoC,CAC/C,CAAC,SAAS,KAAK,CACf,SAAQ,KAAK;aAEK,UAAU,EAAE,MAAM;aAClB,YAAY,EAAE,MAAM;aACpB,KAAK,EAAE,eAAe;aACtB,aAAa,EAAE,CAAC;gBAHhB,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,eAAe,EACtB,aAAa,EAAE,CAAC;CAMnC;AAED,qBAAa,wCAAwC,CACnD,CAAC,SAAS,KAAK,CACf,SAAQ,KAAK;aAEK,cAAc,EAAE,MAAM;aACtB,YAAY,EAAE,MAAM;aACpB,KAAK,EAAE,eAAe;aACtB,aAAa,EAAE,CAAC;gBAHhB,cAAc,EAAE,MAAM,EACtB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,eAAe,EACtB,aAAa,EAAE,CAAC;CAMnC"}
package/dist/errors.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import {
2
+ CheckpointConcurrencyError,
2
3
  CommandError,
3
4
  ConcurrencyError,
4
5
  EventValidationError,
@@ -9,7 +10,7 @@ import {
9
10
  RefreshingSkipError,
10
11
  ReplaySkipError,
11
12
  ValidationError
12
- } from "./chunk-qdczt68t.js";
13
+ } from "./chunk-391m4mfp.js";
13
14
  export {
14
15
  ValidationError,
15
16
  ReplaySkipError,
@@ -20,7 +21,8 @@ export {
20
21
  InfiniteLoopError,
21
22
  EventValidationError,
22
23
  ConcurrencyError,
23
- CommandError
24
+ CommandError,
25
+ CheckpointConcurrencyError
24
26
  };
25
27
 
26
- //# debugId=42D38D47B374FF0964756E2164756E21
28
+ //# debugId=1EBB5F2728E5435464756E2164756E21
@@ -4,6 +4,6 @@
4
4
  "sourcesContent": [
5
5
  ],
6
6
  "mappings": "",
7
- "debugId": "42D38D47B374FF0964756E2164756E21",
7
+ "debugId": "1EBB5F2728E5435464756E2164756E21",
8
8
  "names": []
9
9
  }
package/dist/index.js CHANGED
@@ -4,35 +4,37 @@ import {
4
4
  } from "./chunk-jd4q8fcf.js";
5
5
  import {
6
6
  createEventStore
7
- } from "./chunk-8pchcyvm.js";
8
- import {
9
- getEventListenerInfo,
10
- isInsideEventListener
11
- } from "./chunk-24xjphpk.js";
12
- import"./chunk-ty9bhdvx.js";
7
+ } from "./chunk-04wqxaqs.js";
13
8
  import"./chunk-gq80tgvf.js";
14
9
  import {
15
10
  createAggregateRoot
16
- } from "./chunk-6n3jfg84.js";
17
- import"./chunk-z388cd25.js";
18
- import {
19
- getProjectionInfo,
20
- isInsideProjection
21
- } from "./chunk-8ev7sb2v.js";
11
+ } from "./chunk-r601d5jm.js";
22
12
  import {
23
13
  getProcessManagerInfo,
24
14
  isInsideProcessManager
25
- } from "./chunk-13wtyj2h.js";
15
+ } from "./chunk-smy8mxvr.js";
26
16
  import"./chunk-6q8mr1sg.js";
27
- import"./chunk-pmfzjavb.js";
28
- import {
29
- skipReplay
30
- } from "./chunk-x90g388y.js";
31
- import"./chunk-zf3x573k.js";
32
17
  import {
33
18
  skipRefreshing
34
- } from "./chunk-9psg50cb.js";
19
+ } from "./chunk-6yrb30rx.js";
20
+ import"./chunk-tfy01fah.js";
35
21
  import {
22
+ getProjectionInfo,
23
+ isInsideProjection
24
+ } from "./chunk-th14wxh8.js";
25
+ import"./chunk-yn2sjcg3.js";
26
+ import"./chunk-8qn1nqnh.js";
27
+ import"./chunk-ty9bhdvx.js";
28
+ import"./chunk-z388cd25.js";
29
+ import {
30
+ getEventListenerInfo,
31
+ isInsideEventListener
32
+ } from "./chunk-24xjphpk.js";
33
+ import {
34
+ skipReplay
35
+ } from "./chunk-2fe8jjdc.js";
36
+ import {
37
+ CheckpointConcurrencyError,
36
38
  CommandError,
37
39
  ConcurrencyError,
38
40
  EventValidationError,
@@ -43,8 +45,7 @@ import {
43
45
  RefreshingSkipError,
44
46
  ReplaySkipError,
45
47
  ValidationError
46
- } from "./chunk-qdczt68t.js";
47
- import"./chunk-tfy01fah.js";
48
+ } from "./chunk-391m4mfp.js";
48
49
  export {
49
50
  skipReplay,
50
51
  skipRefreshing,
@@ -67,7 +68,8 @@ export {
67
68
  InfiniteLoopError,
68
69
  EventValidationError,
69
70
  ConcurrencyError,
70
- CommandError
71
+ CommandError,
72
+ CheckpointConcurrencyError
71
73
  };
72
74
 
73
- //# debugId=5B4FCC65AE37B9EF64756E2164756E21
75
+ //# debugId=6C4703510F84795D64756E2164756E21
package/dist/index.js.map CHANGED
@@ -4,6 +4,6 @@
4
4
  "sourcesContent": [
5
5
  ],
6
6
  "mappings": "",
7
- "debugId": "5B4FCC65AE37B9EF64756E2164756E21",
7
+ "debugId": "6C4703510F84795D64756E2164756E21",
8
8
  "names": []
9
9
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/memory/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAA;AAWjE,OAAO,KAAK,EACV,UAAU,EACV,0CAA0C,EAC1C,cAAc,EACd,UAAU,EACX,MAAM,wBAAwB,CAAA;AAC/B,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAEvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAEjD,MAAM,MAAM,gBAAgB,GAAG,CAC7B,MAAM,EAAE,eAAe,EAAE,KACtB,YAAY,CAAC,IAAI,CAAC,CAAA;AAEvB,UAAU,sBAAsB,CAAC,IAAI,SAAS,gBAAgB;IAC5D,cAAc,EAAE,IAAI,EAAE,CAAA;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,gBAAgB,CAAC,EAAE,0CAA0C,CAAC,IAAI,CAAC,CAAC,kBAAkB,CAAC,CAAA;IACvF,kBAAkB,CAAC,EAAE,UAAU,CAAA;IAC/B,uBAAuB,CAAC,EAAE,UAAU,CAAA;IACpC,gBAAgB,CAAC,EAAE,gBAAgB,CAAA;CACpC;AAED,wBAAgB,gBAAgB,CAAC,KAAK,CAAC,IAAI,SAAS,gBAAgB,EAAE,EACpE,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EAClB,uBAAuB,EACvB,gBAAgB,EAChB,QAAQ,GACT,EAAE,sBAAsB,CAAC,IAAI,CAAC,GAAG,UAAU,CAC1C,cAAc,CAAC,IAAI,CAAC,EACpB,IAAI,EACJ,IAAI,CACL,CAkLA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/memory/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAA;AAWjE,OAAO,KAAK,EACV,UAAU,EACV,0CAA0C,EAC1C,cAAc,EACd,UAAU,EACX,MAAM,wBAAwB,CAAA;AAC/B,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAEvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAEjD,MAAM,MAAM,gBAAgB,GAAG,CAC7B,MAAM,EAAE,eAAe,EAAE,KACtB,YAAY,CAAC,IAAI,CAAC,CAAA;AAEvB,UAAU,sBAAsB,CAAC,IAAI,SAAS,gBAAgB;IAC5D,cAAc,EAAE,IAAI,EAAE,CAAA;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,gBAAgB,CAAC,EAAE,0CAA0C,CAAC,IAAI,CAAC,CAAC,kBAAkB,CAAC,CAAA;IACvF,kBAAkB,CAAC,EAAE,UAAU,CAAA;IAC/B,uBAAuB,CAAC,EAAE,UAAU,CAAA;IACpC,gBAAgB,CAAC,EAAE,gBAAgB,CAAA;CACpC;AAED,wBAAgB,gBAAgB,CAAC,KAAK,CAAC,IAAI,SAAS,gBAAgB,EAAE,EACpE,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EAClB,uBAAuB,EACvB,gBAAgB,EAChB,QAAQ,GACT,EAAE,sBAAsB,CAAC,IAAI,CAAC,GAAG,UAAU,CAC1C,cAAc,CAAC,IAAI,CAAC,EACpB,IAAI,EACJ,IAAI,CACL,CA0LA"}
@@ -4,25 +4,25 @@ import {
4
4
  } from "../chunk-jd4q8fcf.js";
5
5
  import {
6
6
  createEventStore
7
- } from "../chunk-8pchcyvm.js";
8
- import"../chunk-24xjphpk.js";
9
- import"../chunk-ty9bhdvx.js";
7
+ } from "../chunk-04wqxaqs.js";
10
8
  import"../chunk-gq80tgvf.js";
11
9
  import {
12
10
  createAggregateRoot
13
- } from "../chunk-6n3jfg84.js";
14
- import"../chunk-z388cd25.js";
15
- import"../chunk-8ev7sb2v.js";
16
- import"../chunk-13wtyj2h.js";
11
+ } from "../chunk-r601d5jm.js";
12
+ import"../chunk-smy8mxvr.js";
17
13
  import"../chunk-6q8mr1sg.js";
18
- import"../chunk-pmfzjavb.js";
19
- import"../chunk-x90g388y.js";
20
- import"../chunk-zf3x573k.js";
21
- import"../chunk-9psg50cb.js";
14
+ import"../chunk-6yrb30rx.js";
15
+ import"../chunk-tfy01fah.js";
16
+ import"../chunk-th14wxh8.js";
17
+ import"../chunk-yn2sjcg3.js";
18
+ import"../chunk-8qn1nqnh.js";
19
+ import"../chunk-ty9bhdvx.js";
20
+ import"../chunk-z388cd25.js";
21
+ import"../chunk-24xjphpk.js";
22
+ import"../chunk-2fe8jjdc.js";
22
23
  import {
23
24
  ConcurrencyError
24
- } from "../chunk-qdczt68t.js";
25
- import"../chunk-tfy01fah.js";
25
+ } from "../chunk-391m4mfp.js";
26
26
 
27
27
  // src/memory/index.ts
28
28
  function createEventStore2({
@@ -102,7 +102,7 @@ function createEventStore2({
102
102
  }
103
103
  }
104
104
  },
105
- upsert(checkpoint) {
105
+ upsert(checkpoint, expectedVersion) {
106
106
  let persisted;
107
107
  for (const c of checkpoints) {
108
108
  if (c.type === checkpoint.type && c.name === checkpoint.name) {
@@ -111,11 +111,16 @@ function createEventStore2({
111
111
  }
112
112
  }
113
113
  if (persisted) {
114
+ if (expectedVersion === null || persisted.version !== expectedVersion) {
115
+ return false;
116
+ }
114
117
  persisted.lastEventPosition = checkpoint.lastEventPosition;
115
118
  persisted.metadata = checkpoint.metadata;
119
+ persisted.version = checkpoint.version;
116
120
  } else {
117
- checkpoints.add(checkpoint);
121
+ checkpoints.add({ ...checkpoint });
118
122
  }
123
+ return true;
119
124
  },
120
125
  delete(type, name) {
121
126
  for (const checkpoint of checkpoints) {
@@ -175,4 +180,4 @@ export {
175
180
  createAggregateRoot
176
181
  };
177
182
 
178
- //# debugId=94478E1EDE4A6DEF64756E2164756E21
183
+ //# debugId=DB351FF2D489173564756E2164756E21
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../src/memory/index.ts"],
4
4
  "sourcesContent": [
5
- "import type { AnyAggregateRoot } from '../createAggregateRoot.ts'\nimport type { Checkpoint } from '../createCheckpointApi.ts'\nimport {\n type AggregateRootSnapshot,\n ConcurrencyError,\n type Event,\n type ProjectionSnapshot,\n createEventStore as createBaseEventStore,\n isStreamEvents,\n isStreamId,\n} from '../index.ts'\nimport type {\n EventStore,\n EventStoreParamsWithAggregateRootSnapshots,\n EventsFromRoot,\n OnProgress,\n} from '../createEventStore.ts'\nimport type { BaseOutputEvent, MaybePromise } from '../utilityTypes.js'\n\nexport { createAggregateRoot } from '../index.ts'\n\nexport type OnEventsAppended = (\n events: BaseOutputEvent[],\n) => MaybePromise<void>\n\ninterface MemoryEventStoreParams<Root extends AnyAggregateRoot> {\n aggregateRoots: Root[]\n autoInit?: boolean\n postProcessEvent?: EventStoreParamsWithAggregateRootSnapshots<Root>['postProcessEvent']\n onProjectionReplay?: OnProgress\n onProcessManagerRefresh?: OnProgress\n onEventsAppended?: OnEventsAppended\n}\n\nexport function createEventStore<const Root extends AnyAggregateRoot>({\n aggregateRoots,\n postProcessEvent,\n onProjectionReplay,\n onProcessManagerRefresh,\n onEventsAppended,\n autoInit,\n}: MemoryEventStoreParams<Root>): EventStore<\n EventsFromRoot<Root>,\n Root,\n true\n> {\n const events: Event[] = []\n const checkpoints = new Set<Checkpoint>()\n const aggregateRootSnapshots = new Map<string, AggregateRootSnapshot>()\n const projectionSnapshots = new Set<ProjectionSnapshot>()\n const projectionAppliedCount = new Map<string, number>()\n\n return createBaseEventStore({\n aggregateRoots,\n postProcessEvent,\n onProjectionReplay,\n onProcessManagerRefresh,\n autoInit,\n\n async *loadEvents(select, range) {\n let streamTypes: string[] | null = null\n let streamIds: string[] | null = null\n let eventTypes: string[] | null = null\n\n if (select) {\n const selects = Array.isArray(select) ? select : [select]\n streamTypes = selects.map((select) => select.stream)\n streamIds = selects\n .map((select) => (isStreamId(select) ? select.id : null))\n .filter(Boolean) as string[]\n eventTypes = selects.flatMap((select) =>\n isStreamEvents(select) ? select.events : [],\n )\n }\n\n const filteredEvents = events.filter((event) => {\n if (streamTypes?.length && !streamTypes.includes(event.streamType)) {\n return false\n }\n\n if (streamIds?.length && !streamIds.includes(event.streamId)) {\n return false\n }\n\n if (eventTypes?.length && !eventTypes.includes(event.type)) {\n return false\n }\n\n if (range?.from && event.position < range.from) {\n return false\n }\n\n if (range?.to && event.position > range.to) {\n return false\n }\n\n return true\n })\n\n for (const event of filteredEvents) {\n yield event\n }\n },\n\n appendEvents({ id, stream }, newEvents, expectedVersion) {\n const lastEvent = events.findLast(\n (e) => e.streamId === id && e.streamType === stream,\n )\n\n const currentVersion = lastEvent?.streamVersion ?? 0\n\n if (currentVersion !== expectedVersion) {\n throw new ConcurrencyError(\n { id, stream },\n expectedVersion,\n currentVersion,\n )\n }\n\n const extendedEvents: Event[] = newEvents.map((event, index) => ({\n ...event,\n createdAt: new Date(),\n position: events.length + index,\n streamId: id,\n streamType: stream,\n streamVersion: expectedVersion + index + 1,\n }))\n\n events.push(...extendedEvents)\n onEventsAppended?.(extendedEvents)\n return extendedEvents\n },\n\n checkpoint: {\n get(type, name) {\n for (const checkpoint of checkpoints) {\n if (checkpoint.type === type && checkpoint.name === name) {\n return checkpoint\n }\n }\n },\n upsert(checkpoint) {\n let persisted: Checkpoint | undefined\n for (const c of checkpoints) {\n if (c.type === checkpoint.type && c.name === checkpoint.name) {\n persisted = c\n break\n }\n }\n\n if (persisted) {\n persisted.lastEventPosition = checkpoint.lastEventPosition\n persisted.metadata = checkpoint.metadata\n } else {\n checkpoints.add(checkpoint)\n }\n },\n delete(type, name) {\n for (const checkpoint of checkpoints) {\n if (checkpoint.type === type && checkpoint.name === name) {\n checkpoints.delete(checkpoint)\n }\n }\n },\n },\n\n projectionSnapshot: {\n put(snapshot) {\n projectionSnapshots.add(snapshot)\n },\n get(select) {\n return Array.from(projectionSnapshots)\n .toReversed()\n .find(\n (snapshot) =>\n snapshot.projectionId === select.id &&\n snapshot.projectionType === select.projection,\n )\n },\n delete(target, fromPosition) {\n for (const snapshot of projectionSnapshots) {\n if (target.id && snapshot.projectionId !== target.id) {\n continue\n }\n\n if (snapshot.projectionType !== target.projection) {\n continue\n }\n\n if (fromPosition && snapshot.lastEventPosition < fromPosition) {\n continue\n }\n\n projectionSnapshots.delete(snapshot)\n }\n },\n incrementAppliedCount(select) {\n const key = `${select.projection}-${select.id}`\n const nextCount = (projectionAppliedCount.get(key) ?? 0) + 1\n projectionAppliedCount.set(key, nextCount)\n return nextCount\n },\n },\n\n aggregateRootSnapshot: {\n put(snapshot) {\n aggregateRootSnapshots.set(\n `${snapshot.streamType}:${snapshot.streamId}`,\n snapshot,\n )\n },\n get(select) {\n return aggregateRootSnapshots.get(`${select.stream}:${select.id}`)\n },\n delete(target, fromStreamVersion) {\n const key = `${target.stream}:${target.id}`\n const snapshot = aggregateRootSnapshots.get(key)\n if (snapshot && snapshot.streamVersion > fromStreamVersion) {\n aggregateRootSnapshots.delete(key)\n }\n },\n },\n }) as any\n}\n"
5
+ "import type { AnyAggregateRoot } from '../createAggregateRoot.ts'\nimport type { Checkpoint } from '../createCheckpointApi.ts'\nimport {\n type AggregateRootSnapshot,\n ConcurrencyError,\n type Event,\n type ProjectionSnapshot,\n createEventStore as createBaseEventStore,\n isStreamEvents,\n isStreamId,\n} from '../index.ts'\nimport type {\n EventStore,\n EventStoreParamsWithAggregateRootSnapshots,\n EventsFromRoot,\n OnProgress,\n} from '../createEventStore.ts'\nimport type { BaseOutputEvent, MaybePromise } from '../utilityTypes.js'\n\nexport { createAggregateRoot } from '../index.ts'\n\nexport type OnEventsAppended = (\n events: BaseOutputEvent[],\n) => MaybePromise<void>\n\ninterface MemoryEventStoreParams<Root extends AnyAggregateRoot> {\n aggregateRoots: Root[]\n autoInit?: boolean\n postProcessEvent?: EventStoreParamsWithAggregateRootSnapshots<Root>['postProcessEvent']\n onProjectionReplay?: OnProgress\n onProcessManagerRefresh?: OnProgress\n onEventsAppended?: OnEventsAppended\n}\n\nexport function createEventStore<const Root extends AnyAggregateRoot>({\n aggregateRoots,\n postProcessEvent,\n onProjectionReplay,\n onProcessManagerRefresh,\n onEventsAppended,\n autoInit,\n}: MemoryEventStoreParams<Root>): EventStore<\n EventsFromRoot<Root>,\n Root,\n true\n> {\n const events: Event[] = []\n const checkpoints = new Set<Checkpoint>()\n const aggregateRootSnapshots = new Map<string, AggregateRootSnapshot>()\n const projectionSnapshots = new Set<ProjectionSnapshot>()\n const projectionAppliedCount = new Map<string, number>()\n\n return createBaseEventStore({\n aggregateRoots,\n postProcessEvent,\n onProjectionReplay,\n onProcessManagerRefresh,\n autoInit,\n\n async *loadEvents(select, range) {\n let streamTypes: string[] | null = null\n let streamIds: string[] | null = null\n let eventTypes: string[] | null = null\n\n if (select) {\n const selects = Array.isArray(select) ? select : [select]\n streamTypes = selects.map((select) => select.stream)\n streamIds = selects\n .map((select) => (isStreamId(select) ? select.id : null))\n .filter(Boolean) as string[]\n eventTypes = selects.flatMap((select) =>\n isStreamEvents(select) ? select.events : [],\n )\n }\n\n const filteredEvents = events.filter((event) => {\n if (streamTypes?.length && !streamTypes.includes(event.streamType)) {\n return false\n }\n\n if (streamIds?.length && !streamIds.includes(event.streamId)) {\n return false\n }\n\n if (eventTypes?.length && !eventTypes.includes(event.type)) {\n return false\n }\n\n if (range?.from && event.position < range.from) {\n return false\n }\n\n if (range?.to && event.position > range.to) {\n return false\n }\n\n return true\n })\n\n for (const event of filteredEvents) {\n yield event\n }\n },\n\n appendEvents({ id, stream }, newEvents, expectedVersion) {\n const lastEvent = events.findLast(\n (e) => e.streamId === id && e.streamType === stream,\n )\n\n const currentVersion = lastEvent?.streamVersion ?? 0\n\n if (currentVersion !== expectedVersion) {\n throw new ConcurrencyError(\n { id, stream },\n expectedVersion,\n currentVersion,\n )\n }\n\n const extendedEvents: Event[] = newEvents.map((event, index) => ({\n ...event,\n createdAt: new Date(),\n position: events.length + index,\n streamId: id,\n streamType: stream,\n streamVersion: expectedVersion + index + 1,\n }))\n\n events.push(...extendedEvents)\n onEventsAppended?.(extendedEvents)\n return extendedEvents\n },\n\n checkpoint: {\n get(type, name) {\n for (const checkpoint of checkpoints) {\n if (checkpoint.type === type && checkpoint.name === name) {\n return checkpoint\n }\n }\n },\n upsert(checkpoint, expectedVersion) {\n let persisted: Checkpoint | undefined\n for (const c of checkpoints) {\n if (c.type === checkpoint.type && c.name === checkpoint.name) {\n persisted = c\n break\n }\n }\n\n if (persisted) {\n // Compare-and-swap: reject the write when another writer advanced the\n // checkpoint, or when the caller expected to create a fresh one.\n if (expectedVersion === null || persisted.version !== expectedVersion) {\n return false\n }\n persisted.lastEventPosition = checkpoint.lastEventPosition\n persisted.metadata = checkpoint.metadata\n persisted.version = checkpoint.version\n } else {\n checkpoints.add({ ...checkpoint })\n }\n\n return true\n },\n delete(type, name) {\n for (const checkpoint of checkpoints) {\n if (checkpoint.type === type && checkpoint.name === name) {\n checkpoints.delete(checkpoint)\n }\n }\n },\n },\n\n projectionSnapshot: {\n put(snapshot) {\n projectionSnapshots.add(snapshot)\n },\n get(select) {\n return Array.from(projectionSnapshots)\n .toReversed()\n .find(\n (snapshot) =>\n snapshot.projectionId === select.id &&\n snapshot.projectionType === select.projection,\n )\n },\n delete(target, fromPosition) {\n for (const snapshot of projectionSnapshots) {\n if (target.id && snapshot.projectionId !== target.id) {\n continue\n }\n\n if (snapshot.projectionType !== target.projection) {\n continue\n }\n\n if (fromPosition && snapshot.lastEventPosition < fromPosition) {\n continue\n }\n\n projectionSnapshots.delete(snapshot)\n }\n },\n incrementAppliedCount(select) {\n const key = `${select.projection}-${select.id}`\n const nextCount = (projectionAppliedCount.get(key) ?? 0) + 1\n projectionAppliedCount.set(key, nextCount)\n return nextCount\n },\n },\n\n aggregateRootSnapshot: {\n put(snapshot) {\n aggregateRootSnapshots.set(\n `${snapshot.streamType}:${snapshot.streamId}`,\n snapshot,\n )\n },\n get(select) {\n return aggregateRootSnapshots.get(`${select.stream}:${select.id}`)\n },\n delete(target, fromStreamVersion) {\n const key = `${target.stream}:${target.id}`\n const snapshot = aggregateRootSnapshots.get(key)\n if (snapshot && snapshot.streamVersion > fromStreamVersion) {\n aggregateRootSnapshots.delete(key)\n }\n },\n },\n }) as any\n}\n"
6
6
  ],
7
- "mappings": "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",
8
- "debugId": "94478E1EDE4A6DEF64756E2164756E21",
7
+ "mappings": "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",
8
+ "debugId": "DB351FF2D489173564756E2164756E21",
9
9
  "names": []
10
10
  }
package/dist/refresh.js CHANGED
@@ -2,8 +2,8 @@ import {
2
2
  isRefreshing,
3
3
  skipRefreshing,
4
4
  withRefreshing
5
- } from "./chunk-9psg50cb.js";
6
- import"./chunk-qdczt68t.js";
5
+ } from "./chunk-6yrb30rx.js";
6
+ import"./chunk-391m4mfp.js";
7
7
  export {
8
8
  withRefreshing,
9
9
  skipRefreshing,
package/dist/replay.js CHANGED
@@ -2,8 +2,8 @@ import {
2
2
  isReplaying,
3
3
  skipReplay,
4
4
  withReplaying
5
- } from "./chunk-x90g388y.js";
6
- import"./chunk-qdczt68t.js";
5
+ } from "./chunk-2fe8jjdc.js";
6
+ import"./chunk-391m4mfp.js";
7
7
  export {
8
8
  withReplaying,
9
9
  skipReplay,
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  createSnapshotGenerator
3
- } from "./chunk-pmfzjavb.js";
4
- import"./chunk-qdczt68t.js";
3
+ } from "./chunk-8qn1nqnh.js";
4
+ import"./chunk-391m4mfp.js";
5
5
  export {
6
6
  createSnapshotGenerator as default
7
7
  };
@@ -45,6 +45,7 @@ export declare function setupEventStore<const Root extends AnyAggregateRoot>(agg
45
45
  type: "projection" | "processManager";
46
46
  name: string;
47
47
  metadata: Record<string, any>;
48
+ version: number;
48
49
  }>;
49
50
  pseudoEventStore: Event[];
50
51
  pseudoAggregateRootSnapshotStore: Map<string, {
@@ -1 +1 @@
1
- {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/tests/setup.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAA;AAE1B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAA;AAEjE,OAAO,EAGL,KAAK,KAAK,EAMX,MAAM,aAAa,CAAA;AACpB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAE7C,wBAAgB,mBAAmB;;;;;;;;;;;;;;;;;iBAehB,MAAM;gBAGP,MAAM;;;;;;;;;;;;;IAIvB;AAED,wBAAgB,eAAe,CAAC,KAAK,CAAC,IAAI,SAAS,gBAAgB,EACjE,aAAa,EAAE,IAAI,GAAG,IAAI,EAAE,EAC5B,OAAO,CAAC,EAAE;IAAE,aAAa,CAAC,EAAE,KAAK,EAAE,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,WAAW,CAAA;CAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAyL9E"}
1
+ {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/tests/setup.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAA;AAE1B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAA;AAEjE,OAAO,EAGL,KAAK,KAAK,EAMX,MAAM,aAAa,CAAA;AACpB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAE7C,wBAAgB,mBAAmB;;;;;;;;;;;;;;;;;iBAehB,MAAM;gBAGP,MAAM;;;;;;;;;;;;;IAIvB;AAED,wBAAgB,eAAe,CAAC,KAAK,CAAC,IAAI,SAAS,gBAAgB,EACjE,aAAa,EAAE,IAAI,GAAG,IAAI,EAAE,EAC5B,OAAO,CAAC,EAAE;IAAE,aAAa,CAAC,EAAE,KAAK,EAAE,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,WAAW,CAAA;CAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmM9E"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@requence/event-sourcing",
3
- "version": "1.0.3",
3
+ "version": "1.1.0",
4
4
  "description": "Event sourcing primitives — aggregate roots, projections, process managers, and event listeners",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -1,7 +1,7 @@
1
1
  import z from 'zod/v4'
2
2
 
3
3
  import type { LoadEvents } from './createEventStore.ts'
4
- import { ValidationError } from './errors.ts'
4
+ import { CheckpointConcurrencyError, ValidationError } from './errors.ts'
5
5
  import type {
6
6
  BaseOutputEvent,
7
7
  MaybePromise,
@@ -13,6 +13,7 @@ const checkpointSchema = z.object({
13
13
  type: z.enum(['projection', 'processManager']),
14
14
  name: z.string(),
15
15
  metadata: z.record(z.string(), z.any()),
16
+ version: z.int(),
16
17
  })
17
18
 
18
19
  export type Checkpoint = z.output<typeof checkpointSchema>
@@ -26,7 +27,19 @@ export type CheckpointMethods = {
26
27
  type: 'projection' | 'processManager',
27
28
  name: string,
28
29
  ) => MaybePromise<void>
29
- upsert: (checkpoint: Checkpoint) => MaybePromise<void>
30
+ /**
31
+ * Persist a checkpoint using optimistic concurrency control.
32
+ *
33
+ * The write must only succeed if the currently stored version equals
34
+ * `expectedVersion` (or, when `expectedVersion` is `null`, if no checkpoint
35
+ * exists yet). `checkpoint.version` holds the version to store on success.
36
+ * Return `true` when the write was applied and `false` when it was rejected
37
+ * because another writer had advanced the checkpoint in the meantime.
38
+ */
39
+ upsert: (
40
+ checkpoint: Checkpoint,
41
+ expectedVersion: number | null,
42
+ ) => MaybePromise<boolean>
30
43
  }
31
44
 
32
45
  export function createCheckpointApi(
@@ -39,18 +52,81 @@ export function createCheckpointApi(
39
52
  applyAfter?: (event: BaseOutputEvent) => MaybePromise<void>
40
53
  },
41
54
  ) {
55
+ // In-memory view of the persisted checkpoint version. `null` means "no
56
+ // checkpoint has been written yet". It is kept in sync with the store on
57
+ // every load/upsert so optimistic-concurrency writes can detect when another
58
+ // instance has advanced the same checkpoint.
59
+ let version: number | null = null
60
+
42
61
  const api = {
43
62
  relatedStreamEvents: params.relatedStreamEvents,
44
63
  async clear() {
45
64
  await params.delete(params.type, params.name)
65
+ version = null
46
66
  },
47
- async upsert(event: BaseOutputEvent, metadata: Record<string, any> = {}) {
48
- await params.upsert({
49
- lastEventPosition: event.position,
50
- type: params.type,
51
- name: params.name,
52
- metadata,
53
- })
67
+ /**
68
+ * Load the persisted checkpoint and sync the local version. Returns the
69
+ * raw checkpoint (or `null`), so callers can rehydrate their own state
70
+ * (e.g. a process manager reloading its folded state) from it.
71
+ */
72
+ async load() {
73
+ const checkpoint = await params.get(params.type, params.name)
74
+ version = checkpoint?.version ?? null
75
+ return checkpoint ?? null
76
+ },
77
+ /**
78
+ * Persist the checkpoint position (and optional metadata) for the given
79
+ * event.
80
+ *
81
+ * - `'cas'` (compare-and-swap): the write must land on top of the exact
82
+ * version we last observed. If another writer advanced the checkpoint,
83
+ * the local version is refreshed and a {@link CheckpointConcurrencyError}
84
+ * is thrown so the caller can re-fold its state and retry. Used for
85
+ * process managers that fold state into the checkpoint.
86
+ * - `'monotonic'` (default): retries on conflict, skipping the write once
87
+ * the stored position already covers this event. Safe for cursors with
88
+ * no derived state (projections, stateless/after-effect writes).
89
+ */
90
+ async upsert(
91
+ event: BaseOutputEvent,
92
+ metadata: Record<string, any> = {},
93
+ mode: 'cas' | 'monotonic' = 'monotonic',
94
+ ) {
95
+ while (true) {
96
+ const expectedVersion = version
97
+ const nextVersion = (expectedVersion ?? -1) + 1
98
+ const committed = await params.upsert(
99
+ {
100
+ lastEventPosition: event.position,
101
+ type: params.type,
102
+ name: params.name,
103
+ metadata,
104
+ version: nextVersion,
105
+ },
106
+ expectedVersion,
107
+ )
108
+
109
+ if (committed) {
110
+ version = nextVersion
111
+ return
112
+ }
113
+
114
+ // Another writer advanced this checkpoint. Refresh our view of it.
115
+ const current = await api.load()
116
+
117
+ if (mode === 'cas') {
118
+ throw new CheckpointConcurrencyError(
119
+ params.type,
120
+ params.name,
121
+ expectedVersion,
122
+ )
123
+ }
124
+
125
+ // monotonic: the stored cursor already covers this event, nothing to do.
126
+ if (current && current.lastEventPosition >= event.position) {
127
+ return
128
+ }
129
+ }
54
130
  },
55
131
  async rehydrated(
56
132
  options: {
@@ -59,7 +135,7 @@ export function createCheckpointApi(
59
135
  onProgress?: (index: number, event: BaseOutputEvent) => void
60
136
  } = {},
61
137
  ) {
62
- const checkpoint = await params.get(params.type, params.name)
138
+ const checkpoint = await api.load()
63
139
  let startPosition = 0
64
140
  if (checkpoint) {
65
141
  const result = checkpointSchema.safeParse(checkpoint)
@@ -172,7 +172,7 @@ export function createEventStore<const Root extends AnyAggregateRoot>(
172
172
 
173
173
  let exclusiveEmitEventsChain: Promise<any> = Promise.resolve()
174
174
  const emitEvents: EmitEvents = async (events) => {
175
- exclusiveEmitEventsChain = exclusiveEmitEventsChain.then(async () => {
175
+ const result = exclusiveEmitEventsChain.then(async () => {
176
176
  await Promise.all(processManagers.values().map((pm) => pm.beginSession()))
177
177
 
178
178
  try {
@@ -200,7 +200,16 @@ export function createEventStore<const Root extends AnyAggregateRoot>(
200
200
  }
201
201
  })
202
202
 
203
- return exclusiveEmitEventsChain
203
+ // Advance the serialization chain but swallow this operation's outcome so a
204
+ // rejection is delivered only to its own caller. Chaining the next op onto a
205
+ // rejected promise would skip its callback and re-propagate the stale error,
206
+ // permanently poisoning every subsequent emit for the life of the process.
207
+ exclusiveEmitEventsChain = result.then(
208
+ () => undefined,
209
+ () => undefined,
210
+ )
211
+
212
+ return result
204
213
  }
205
214
 
206
215
  const loadEvents: LoadEvents = (select, range) => {
@@ -215,7 +224,7 @@ export function createEventStore<const Root extends AnyAggregateRoot>(
215
224
  expectedVersion,
216
225
  ) => {
217
226
  assertInitializing()
218
- exclusiveAppendEventsChain = exclusiveAppendEventsChain.then(async () => {
227
+ const result = exclusiveAppendEventsChain.then(async () => {
219
228
  if (events.length === 0) {
220
229
  return []
221
230
  }
@@ -241,7 +250,17 @@ export function createEventStore<const Root extends AnyAggregateRoot>(
241
250
  return params.appendEvents(streamId, processedEvents, expectedVersion)
242
251
  })
243
252
 
244
- return exclusiveAppendEventsChain
253
+ // Advance the serialization chain but swallow this operation's outcome so a
254
+ // rejection is delivered only to its own caller. Chaining the next append
255
+ // onto a rejected promise would skip its callback and re-propagate the stale
256
+ // error, permanently poisoning every subsequent append for the life of the
257
+ // process (a single ConcurrencyError would take down all writes).
258
+ exclusiveAppendEventsChain = result.then(
259
+ () => undefined,
260
+ () => undefined,
261
+ )
262
+
263
+ return result
245
264
  }
246
265
 
247
266
  for (const aggregateRoot of params.aggregateRoots as unknown as InternalAggregateRootApi[]) {