event-store-adapter-js 3.0.1 → 3.0.2-snapshot.2

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 (57) hide show
  1. package/README.ja.md +83 -39
  2. package/README.md +83 -39
  3. package/dist/aggregate-id.d.ts +3 -4
  4. package/dist/aggregate.d.ts +2 -2
  5. package/dist/dynamodb-event-store-input.d.ts +2 -2
  6. package/dist/event-serializer.d.ts +2 -2
  7. package/dist/event-store-error.d.ts +25 -0
  8. package/dist/event-store-error.js +43 -0
  9. package/dist/event-store.d.ts +9 -11
  10. package/dist/event-store.js +16 -11
  11. package/dist/event.d.ts +2 -2
  12. package/dist/index.d.ts +2 -0
  13. package/dist/index.js +2 -0
  14. package/dist/internal/default-serializer.d.ts +5 -5
  15. package/dist/internal/default-serializer.js +32 -29
  16. package/dist/internal/default-shard-selector.d.ts +3 -7
  17. package/dist/internal/default-shard-selector.js +24 -25
  18. package/dist/internal/dynamodb-aggregate-key.d.ts +10 -10
  19. package/dist/internal/dynamodb-aggregate-key.js +12 -19
  20. package/dist/internal/dynamodb-event-store.d.ts +2 -33
  21. package/dist/internal/dynamodb-event-store.js +230 -198
  22. package/dist/internal/dynamodb-snapshot-retention-executor.d.ts +4 -25
  23. package/dist/internal/dynamodb-snapshot-retention-executor.js +48 -53
  24. package/dist/internal/event-store-assertions.d.ts +3 -2
  25. package/dist/internal/event-store-assertions.js +8 -1
  26. package/dist/internal/json-converter.js +10 -7
  27. package/dist/internal/memory-event-store.d.ts +2 -14
  28. package/dist/internal/memory-event-store.js +91 -102
  29. package/dist/internal/spanner-aggregate-key.d.ts +9 -9
  30. package/dist/internal/spanner-aggregate-key.js +9 -16
  31. package/dist/internal/spanner-event-store.d.ts +2 -43
  32. package/dist/internal/spanner-event-store.js +229 -176
  33. package/dist/logger.d.ts +2 -2
  34. package/dist/memory-event-store-input.d.ts +2 -2
  35. package/dist/result.d.ts +11 -0
  36. package/dist/result.js +21 -0
  37. package/dist/shard-count.d.ts +5 -4
  38. package/dist/shard-count.js +11 -6
  39. package/dist/shard-id.d.ts +5 -4
  40. package/dist/shard-id.js +11 -6
  41. package/dist/shard-selector.d.ts +2 -2
  42. package/dist/snapshot-serializer.d.ts +2 -2
  43. package/dist/spanner-event-store-input.d.ts +2 -2
  44. package/dist/types.d.ts +4 -3
  45. package/dist/types.js +17 -7
  46. package/docs/GCP_EVENT_INTEGRATION.ja.md +3 -3
  47. package/docs/MIGRATION_GUIDE_3.0.ja.md +12 -6
  48. package/docs/MIGRATION_GUIDE_3.0.md +12 -6
  49. package/docs/MIGRATION_GUIDE_4.0.ja.md +141 -0
  50. package/docs/MIGRATION_GUIDE_4.0.md +141 -0
  51. package/docs/SPANNER_DATABASE_SCHEMA.ja.md +1 -1
  52. package/docs/SPANNER_DATABASE_SCHEMA.md +1 -1
  53. package/package.json +1 -1
  54. package/dist/aggregate-id-value.d.ts +0 -7
  55. package/dist/aggregate-id-value.js +0 -9
  56. package/dist/optimistic-lock-error.d.ts +0 -4
  57. package/dist/optimistic-lock-error.js +0 -10
package/README.ja.md CHANGED
@@ -21,44 +21,33 @@ npm install event-store-adapter-js
21
21
  EventStoreを使えば、Event Sourcing対応リポジトリを簡単に実装できます。
22
22
 
23
23
  ```typescript
24
- class UserAccountRepository {
25
- constructor(
26
- private readonly eventStore: EventStore<
27
- UserAccountId,
28
- UserAccount,
29
- UserAccountEvent
30
- >,
31
- ) {}
32
-
33
- async storeEvent(event: UserAccountEvent, version: number) {
34
- await this.eventStore.persistEvent(event, version);
35
- }
36
-
37
- async storeEventAndSnapshot(event: UserAccountEvent, snapshot: UserAccount) {
38
- await this.eventStore.persistEventAndSnapshot(event, snapshot);
39
- }
40
-
41
- async findById(id: UserAccountId): Promise<UserAccount | undefined> {
42
- const snapshot = await this.eventStore.getLatestSnapshotById(
43
- id,
44
- );
45
- if (snapshot === undefined) {
46
- return undefined;
47
- } else {
48
- const events = await this.eventStore.getEventsByIdSinceSequenceNumber(
49
- id,
50
- snapshot.sequenceNumber + 1,
51
- );
52
- return UserAccount.replay(events, snapshot);
53
- }
54
- }
55
- }
24
+ const UserAccountRepository = Object.freeze({
25
+ create(eventStore: EventStore<UserAccountId, UserAccount, UserAccountEvent>) {
26
+ return Object.freeze({
27
+ storeEvent: (event: UserAccountEvent, version: number) =>
28
+ eventStore.persistEvent(event, version),
29
+ storeEventAndSnapshot: (event: UserAccountEvent, snapshot: UserAccount) =>
30
+ eventStore.persistEventAndSnapshot(event, snapshot),
31
+ async findById(id: UserAccountId): Promise<UserAccount | undefined> {
32
+ const snapshot = await eventStore.getLatestSnapshotById(id);
33
+ if (snapshot === undefined) {
34
+ return undefined;
35
+ }
36
+ const events = await eventStore.getEventsByIdSinceSequenceNumber(
37
+ id,
38
+ snapshot.sequenceNumber + 1,
39
+ );
40
+ return UserAccount.replay(events, snapshot);
41
+ },
42
+ });
43
+ },
44
+ });
56
45
  ```
57
46
 
58
47
  以下はリポジトリの使用例です。
59
48
 
60
49
  ```typescript
61
- const eventStore = EventStore.ofDynamoDB<
50
+ const eventStore = EventStore.createDynamoDB<
62
51
  UserAccountId,
63
52
  UserAccount,
64
53
  UserAccountEvent
@@ -74,9 +63,9 @@ const eventStore = EventStore.ofDynamoDB<
74
63
  snapshotConverter: convertJSONToUserAccount,
75
64
  });
76
65
  // if you want to use in-memory event store, use the following code.
77
- // const eventStore = EventStore.ofMemory<UserAccountId, UserAccount, UserAccountEvent>({});
66
+ // const eventStore = EventStore.createMemory<UserAccountId, UserAccount, UserAccountEvent>({});
78
67
  // Cloud Spannerを使う場合は、呼び出し側で管理するDatabaseを渡します。
79
- // const eventStore = EventStore.ofSpanner<UserAccountId, UserAccount, UserAccountEvent>({
68
+ // const eventStore = EventStore.createSpanner<UserAccountId, UserAccount, UserAccountEvent>({
80
69
  // database: spannerDatabase,
81
70
  // journalTableName: "journal",
82
71
  // snapshotTableName: "snapshot",
@@ -85,17 +74,23 @@ const eventStore = EventStore.ofDynamoDB<
85
74
  // snapshotConverter: convertJSONToUserAccount,
86
75
  // });
87
76
 
88
- const userAccountRepository = new UserAccountRepository(eventStore);
77
+ const userAccountRepository = UserAccountRepository.create(eventStore);
89
78
 
90
- const id = new UserAccountId(ulid());
79
+ const id = UserAccountId.create(ulid());
91
80
  const name = "Alice";
92
81
  const [userAccount1, created] = UserAccount.create(id, name);
93
82
 
94
- await userAccountRepository.storeEventAndSnapshot(created, userAccount1);
83
+ const createdResult = await userAccountRepository.storeEventAndSnapshot(created, userAccount1);
84
+ if (createdResult.type === "err") {
85
+ throw new Error(createdResult.error.message);
86
+ }
95
87
 
96
88
  const [userAccount2, renamed] = userAccount1.rename("Bob");
97
89
 
98
- await userAccountRepository.storeEvent(renamed, userAccount2.version);
90
+ const renamedResult = await userAccountRepository.storeEvent(renamed, userAccount2.version);
91
+ if (renamedResult.type === "err") {
92
+ throw new Error(renamedResult.error.message);
93
+ }
99
94
 
100
95
  const userAccount3 = await userAccountRepository.findById(id);
101
96
  if (userAccount3 === undefined) {
@@ -108,6 +103,55 @@ expect(userAccount3.sequenceNumber).toEqual(2);
108
103
  expect(userAccount3.version).toEqual(2);
109
104
  ```
110
105
 
106
+ ## runtime brand と JSON 変換
107
+
108
+ サンプルのドメイン値は module-private な `unique symbol` brand を使い、
109
+ プロセス内で factory が生成した値と plain object を区別します。`typeName`
110
+ は JSON 境界の discriminant として残し、symbol brand は serialize されない
111
+ ため factory で復元します。
112
+
113
+ ```typescript
114
+ const USER_ACCOUNT_ID_BRAND: unique symbol = Symbol("UserAccountId");
115
+
116
+ type UserAccountId = AggregateId & {
117
+ typeName: "user-account";
118
+ readonly [USER_ACCOUNT_ID_BRAND]: true;
119
+ };
120
+
121
+ namespace UserAccountId {
122
+ export function create(value: string): UserAccountId {
123
+ return Object.freeze({
124
+ [USER_ACCOUNT_ID_BRAND]: true,
125
+ typeName: "user-account",
126
+ value,
127
+ asString: () => `user-account-${value}`,
128
+ });
129
+ }
130
+
131
+ export function is(value: unknown): value is UserAccountId {
132
+ return (
133
+ typeof value === "object" &&
134
+ value !== null &&
135
+ (value as Partial<UserAccountId>)[USER_ACCOUNT_ID_BRAND] === true
136
+ );
137
+ }
138
+
139
+ export function toJSON(value: UserAccountId) {
140
+ return { typeName: value.typeName, value: value.value };
141
+ }
142
+
143
+ export function fromJSON(json: { typeName: "user-account"; value: string }) {
144
+ return create(json.value);
145
+ }
146
+ }
147
+ ```
148
+
149
+ `JSON.stringify(...)` 後は symbol brand が消えます。EventStore の converter
150
+ ではドメイン側の `fromJSON(...)` を呼び、deserialize した event / snapshot
151
+ を再び branded value にしてください。`EventSerializer` と
152
+ `SnapshotSerializer` の API は変更せず、`deserialize(bytes, converter)` の
153
+ 契約どおり converter にドメイン復元を委ねます。
154
+
111
155
  ## 開発
112
156
 
113
157
  このリポジトリは pnpm workspace を使います。ライブラリパッケージは
package/README.md CHANGED
@@ -22,44 +22,33 @@ npm install event-store-adapter-js
22
22
  You can easily implement an Event Sourcing-enabled repository using EventStore.
23
23
 
24
24
  ```typescript
25
- class UserAccountRepository {
26
- constructor(
27
- private readonly eventStore: EventStore<
28
- UserAccountId,
29
- UserAccount,
30
- UserAccountEvent
31
- >,
32
- ) {}
33
-
34
- async storeEvent(event: UserAccountEvent, version: number) {
35
- await this.eventStore.persistEvent(event, version);
36
- }
37
-
38
- async storeEventAndSnapshot(event: UserAccountEvent, snapshot: UserAccount) {
39
- await this.eventStore.persistEventAndSnapshot(event, snapshot);
40
- }
41
-
42
- async findById(id: UserAccountId): Promise<UserAccount | undefined> {
43
- const snapshot = await this.eventStore.getLatestSnapshotById(
44
- id,
45
- );
46
- if (snapshot === undefined) {
47
- return undefined;
48
- } else {
49
- const events = await this.eventStore.getEventsByIdSinceSequenceNumber(
50
- id,
51
- snapshot.sequenceNumber + 1,
52
- );
53
- return UserAccount.replay(events, snapshot);
54
- }
55
- }
56
- }
25
+ const UserAccountRepository = Object.freeze({
26
+ create(eventStore: EventStore<UserAccountId, UserAccount, UserAccountEvent>) {
27
+ return Object.freeze({
28
+ storeEvent: (event: UserAccountEvent, version: number) =>
29
+ eventStore.persistEvent(event, version),
30
+ storeEventAndSnapshot: (event: UserAccountEvent, snapshot: UserAccount) =>
31
+ eventStore.persistEventAndSnapshot(event, snapshot),
32
+ async findById(id: UserAccountId): Promise<UserAccount | undefined> {
33
+ const snapshot = await eventStore.getLatestSnapshotById(id);
34
+ if (snapshot === undefined) {
35
+ return undefined;
36
+ }
37
+ const events = await eventStore.getEventsByIdSinceSequenceNumber(
38
+ id,
39
+ snapshot.sequenceNumber + 1,
40
+ );
41
+ return UserAccount.replay(events, snapshot);
42
+ },
43
+ });
44
+ },
45
+ });
57
46
  ```
58
47
 
59
48
  The following is an example of the repository usage.
60
49
 
61
50
  ```typescript
62
- const eventStore = EventStore.ofDynamoDB<
51
+ const eventStore = EventStore.createDynamoDB<
63
52
  UserAccountId,
64
53
  UserAccount,
65
54
  UserAccountEvent
@@ -75,9 +64,9 @@ const eventStore = EventStore.ofDynamoDB<
75
64
  snapshotConverter: convertJSONToUserAccount,
76
65
  });
77
66
  // if you want to use in-memory event store, use the following code.
78
- // const eventStore = EventStore.ofMemory<UserAccountId, UserAccount, UserAccountEvent>({});
67
+ // const eventStore = EventStore.createMemory<UserAccountId, UserAccount, UserAccountEvent>({});
79
68
  // if you want to use Cloud Spanner, pass a caller-managed Database.
80
- // const eventStore = EventStore.ofSpanner<UserAccountId, UserAccount, UserAccountEvent>({
69
+ // const eventStore = EventStore.createSpanner<UserAccountId, UserAccount, UserAccountEvent>({
81
70
  // database: spannerDatabase,
82
71
  // journalTableName: "journal",
83
72
  // snapshotTableName: "snapshot",
@@ -86,17 +75,23 @@ const eventStore = EventStore.ofDynamoDB<
86
75
  // snapshotConverter: convertJSONToUserAccount,
87
76
  // });
88
77
 
89
- const userAccountRepository = new UserAccountRepository(eventStore);
78
+ const userAccountRepository = UserAccountRepository.create(eventStore);
90
79
 
91
- const id = new UserAccountId(ulid());
80
+ const id = UserAccountId.create(ulid());
92
81
  const name = "Alice";
93
82
  const [userAccount1, created] = UserAccount.create(id, name);
94
83
 
95
- await userAccountRepository.storeEventAndSnapshot(created, userAccount1);
84
+ const createdResult = await userAccountRepository.storeEventAndSnapshot(created, userAccount1);
85
+ if (createdResult.type === "err") {
86
+ throw new Error(createdResult.error.message);
87
+ }
96
88
 
97
89
  const [userAccount2, renamed] = userAccount1.rename("Bob");
98
90
 
99
- await userAccountRepository.storeEvent(renamed, userAccount2.version);
91
+ const renamedResult = await userAccountRepository.storeEvent(renamed, userAccount2.version);
92
+ if (renamedResult.type === "err") {
93
+ throw new Error(renamedResult.error.message);
94
+ }
100
95
 
101
96
  const userAccount3 = await userAccountRepository.findById(id);
102
97
  if (userAccount3 === undefined) {
@@ -109,6 +104,55 @@ expect(userAccount3.sequenceNumber).toEqual(2);
109
104
  expect(userAccount3.version).toEqual(2);
110
105
  ```
111
106
 
107
+ ## Runtime brands and JSON conversion
108
+
109
+ The sample domain values use module-private `unique symbol` brands to tell
110
+ factory-created values apart from plain objects inside the current process.
111
+ `typeName` remains the JSON boundary discriminant; the symbol brand is not
112
+ serialized and must be restored by a factory.
113
+
114
+ ```typescript
115
+ const USER_ACCOUNT_ID_BRAND: unique symbol = Symbol("UserAccountId");
116
+
117
+ type UserAccountId = AggregateId & {
118
+ typeName: "user-account";
119
+ readonly [USER_ACCOUNT_ID_BRAND]: true;
120
+ };
121
+
122
+ namespace UserAccountId {
123
+ export function create(value: string): UserAccountId {
124
+ return Object.freeze({
125
+ [USER_ACCOUNT_ID_BRAND]: true,
126
+ typeName: "user-account",
127
+ value,
128
+ asString: () => `user-account-${value}`,
129
+ });
130
+ }
131
+
132
+ export function is(value: unknown): value is UserAccountId {
133
+ return (
134
+ typeof value === "object" &&
135
+ value !== null &&
136
+ (value as Partial<UserAccountId>)[USER_ACCOUNT_ID_BRAND] === true
137
+ );
138
+ }
139
+
140
+ export function toJSON(value: UserAccountId) {
141
+ return { typeName: value.typeName, value: value.value };
142
+ }
143
+
144
+ export function fromJSON(json: { typeName: "user-account"; value: string }) {
145
+ return create(json.value);
146
+ }
147
+ }
148
+ ```
149
+
150
+ `JSON.stringify(...)` drops the symbol brand. In EventStore converters, call the
151
+ domain `fromJSON(...)` function so deserialized events and snapshots become
152
+ branded values again. The `EventSerializer` and `SnapshotSerializer` APIs stay
153
+ unchanged; their `deserialize(bytes, converter)` contract still delegates
154
+ domain reconstruction to the converter.
155
+
112
156
  ## Development
113
157
 
114
158
  This repository uses pnpm workspaces. The library package is located at
@@ -1,7 +1,6 @@
1
- import type { AggregateIdValue } from "./aggregate-id-value";
2
- interface AggregateId {
1
+ type AggregateId = {
3
2
  typeName: string;
4
- value: AggregateIdValue;
3
+ value: string;
5
4
  asString: () => string;
6
- }
5
+ };
7
6
  export type { AggregateId };
@@ -1,10 +1,10 @@
1
1
  import type { AggregateId } from "./aggregate-id";
2
- interface Aggregate<This extends Aggregate<This, AID>, AID extends AggregateId> {
2
+ type Aggregate<This extends Aggregate<This, AID>, AID extends AggregateId> = {
3
3
  typeName: string;
4
4
  id: AID;
5
5
  sequenceNumber: number;
6
6
  version: number;
7
7
  withVersion(version: number): This;
8
8
  updateVersion(version: (value: number) => number): This;
9
- }
9
+ };
10
10
  export type { Aggregate };
@@ -1,6 +1,6 @@
1
1
  import type { DynamoDBClient } from "@aws-sdk/client-dynamodb";
2
2
  import type { Aggregate, AggregateId, Event, EventSerializer, Logger, ShardSelector, SnapshotSerializer } from "./types";
3
- interface DynamoDBEventStoreInput<AID extends AggregateId, A extends Aggregate<A, AID>, E extends Event<AID>> {
3
+ type DynamoDBEventStoreInput<AID extends AggregateId, A extends Aggregate<A, AID>, E extends Event<AID>> = {
4
4
  client: DynamoDBClient;
5
5
  journalTableName: string;
6
6
  snapshotTableName: string;
@@ -18,5 +18,5 @@ interface DynamoDBEventStoreInput<AID extends AggregateId, A extends Aggregate<A
18
18
  eventSerializer?: EventSerializer<AID, E>;
19
19
  snapshotSerializer?: SnapshotSerializer<AID, A>;
20
20
  logger?: Logger;
21
- }
21
+ };
22
22
  export type { DynamoDBEventStoreInput };
@@ -1,7 +1,7 @@
1
1
  import type { AggregateId } from "./aggregate-id";
2
2
  import type { Event } from "./event";
3
- interface EventSerializer<AID extends AggregateId, E extends Event<AID>> {
3
+ type EventSerializer<AID extends AggregateId, E extends Event<AID>> = {
4
4
  serialize(event: E): Uint8Array;
5
5
  deserialize(bytes: Uint8Array, converter: (json: unknown) => E): E;
6
- }
6
+ };
7
7
  export type { EventSerializer };
@@ -0,0 +1,25 @@
1
+ export type EventStoreError = {
2
+ type: "optimistic-lock-conflict";
3
+ message: string;
4
+ cause?: unknown;
5
+ } | {
6
+ type: "configuration-error";
7
+ fieldName: string;
8
+ message: string;
9
+ cause?: unknown;
10
+ } | {
11
+ type: "serialization-error";
12
+ operation: "serialize" | "deserialize";
13
+ message: string;
14
+ cause?: unknown;
15
+ } | {
16
+ type: "storage-error";
17
+ message: string;
18
+ cause?: unknown;
19
+ };
20
+ export declare namespace EventStoreError {
21
+ function optimisticLockConflict(message?: string, cause?: unknown): EventStoreError;
22
+ function configuration(fieldName: string, message: string, cause?: unknown): EventStoreError;
23
+ function serialization(operation: "serialize" | "deserialize", message: string, cause?: unknown): EventStoreError;
24
+ function storage(message: string, cause?: unknown): EventStoreError;
25
+ }
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EventStoreError = void 0;
4
+ var EventStoreError;
5
+ (function (EventStoreError) {
6
+ function optimisticLockConflict(message = "Optimistic locking failed", cause) {
7
+ return Object.freeze({
8
+ type: "optimistic-lock-conflict",
9
+ message,
10
+ cause,
11
+ });
12
+ }
13
+ EventStoreError.optimisticLockConflict = optimisticLockConflict;
14
+ function configuration(fieldName, message, cause) {
15
+ return Object.freeze({
16
+ type: "configuration-error",
17
+ fieldName,
18
+ message,
19
+ cause,
20
+ });
21
+ }
22
+ EventStoreError.configuration = configuration;
23
+ function serialization(operation, message, cause) {
24
+ return Object.freeze({
25
+ type: "serialization-error",
26
+ operation,
27
+ message,
28
+ cause,
29
+ });
30
+ }
31
+ EventStoreError.serialization = serialization;
32
+ function storage(message, cause) {
33
+ return Object.freeze({
34
+ type: "storage-error",
35
+ message,
36
+ cause,
37
+ });
38
+ }
39
+ EventStoreError.storage = storage;
40
+ })(EventStoreError || (exports.EventStoreError = EventStoreError = {}));
41
+ // Object.freeze mutates the existing EventStoreError namespace object in place;
42
+ // the returned reference is intentionally ignored to preserve the public binding.
43
+ Object.freeze(EventStoreError);
@@ -1,17 +1,15 @@
1
1
  import type { DynamoDBEventStoreInput } from "./dynamodb-event-store-input";
2
2
  import type { MemoryEventStoreInput } from "./memory-event-store-input";
3
3
  import type { SpannerEventStoreInput } from "./spanner-event-store-input";
4
- import type { Aggregate, AggregateId, Event } from "./types";
5
- export interface EventStore<AID extends AggregateId, A extends Aggregate<A, AID>, E extends Event<AID>> {
6
- persistEvent(event: E, expectedVersion: number): Promise<void>;
7
- persistEventAndSnapshot(event: E, aggregate: A): Promise<void>;
4
+ import type { Aggregate, AggregateId, Event, EventStoreError, Result } from "./types";
5
+ export type EventStore<AID extends AggregateId, A extends Aggregate<A, AID>, E extends Event<AID>> = {
6
+ persistEvent(event: E, expectedVersion: number): Promise<Result<void, EventStoreError>>;
7
+ persistEventAndSnapshot(event: E, aggregate: A): Promise<Result<void, EventStoreError>>;
8
8
  getEventsByIdSinceSequenceNumber(id: AID, sequenceNumber: number): Promise<E[]>;
9
9
  getLatestSnapshotById(id: AID): Promise<A | undefined>;
10
+ };
11
+ export declare namespace EventStore {
12
+ function createDynamoDB<AID extends AggregateId, A extends Aggregate<A, AID>, E extends Event<AID>>(input: DynamoDBEventStoreInput<AID, A, E>): EventStore<AID, A, E>;
13
+ function createMemory<AID extends AggregateId, A extends Aggregate<A, AID>, E extends Event<AID>>(input?: MemoryEventStoreInput<AID, A, E>): EventStore<AID, A, E>;
14
+ function createSpanner<AID extends AggregateId, A extends Aggregate<A, AID>, E extends Event<AID>>(input: SpannerEventStoreInput<AID, A, E>): EventStore<AID, A, E>;
10
15
  }
11
- type EventStoreConstructors = Readonly<{
12
- ofDynamoDB<AID extends AggregateId, A extends Aggregate<A, AID>, E extends Event<AID>>(input: DynamoDBEventStoreInput<AID, A, E>): EventStore<AID, A, E>;
13
- ofMemory<AID extends AggregateId, A extends Aggregate<A, AID>, E extends Event<AID>>(input?: MemoryEventStoreInput<AID, A, E>): EventStore<AID, A, E>;
14
- ofSpanner<AID extends AggregateId, A extends Aggregate<A, AID>, E extends Event<AID>>(input: SpannerEventStoreInput<AID, A, E>): EventStore<AID, A, E>;
15
- }>;
16
- export declare const EventStore: EventStoreConstructors;
17
- export {};
@@ -4,14 +4,19 @@ exports.EventStore = void 0;
4
4
  const dynamodb_event_store_1 = require("./internal/dynamodb-event-store");
5
5
  const memory_event_store_1 = require("./internal/memory-event-store");
6
6
  const spanner_event_store_1 = require("./internal/spanner-event-store");
7
- exports.EventStore = Object.freeze({
8
- ofDynamoDB(input) {
9
- return new dynamodb_event_store_1.DynamoDBEventStore(input);
10
- },
11
- ofMemory(input) {
12
- return new memory_event_store_1.MemoryEventStore(input !== null && input !== void 0 ? input : {});
13
- },
14
- ofSpanner(input) {
15
- return new spanner_event_store_1.SpannerEventStore(input);
16
- },
17
- });
7
+ var EventStore;
8
+ (function (EventStore) {
9
+ function createDynamoDB(input) {
10
+ return (0, dynamodb_event_store_1.createDynamoDBEventStore)(input);
11
+ }
12
+ EventStore.createDynamoDB = createDynamoDB;
13
+ function createMemory(input) {
14
+ return (0, memory_event_store_1.createMemoryEventStore)(input !== null && input !== void 0 ? input : {});
15
+ }
16
+ EventStore.createMemory = createMemory;
17
+ function createSpanner(input) {
18
+ return (0, spanner_event_store_1.createSpannerEventStore)(input);
19
+ }
20
+ EventStore.createSpanner = createSpanner;
21
+ })(EventStore || (exports.EventStore = EventStore = {}));
22
+ Object.freeze(EventStore);
package/dist/event.d.ts CHANGED
@@ -1,10 +1,10 @@
1
1
  import type { AggregateId } from "./aggregate-id";
2
- interface Event<AID extends AggregateId> {
2
+ type Event<AID extends AggregateId> = {
3
3
  typeName: string;
4
4
  id: string;
5
5
  aggregateId: AID;
6
6
  sequenceNumber: number;
7
7
  occurredAt: Date;
8
8
  isCreated: boolean;
9
- }
9
+ };
10
10
  export type { Event };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  export * from "./dynamodb-event-store-input";
2
2
  export * from "./event-store";
3
+ export * from "./event-store-error";
3
4
  export * from "./memory-event-store-input";
5
+ export * from "./result";
4
6
  export * from "./shard-id";
5
7
  export * from "./spanner-event-store-input";
6
8
  export * from "./types";
package/dist/index.js CHANGED
@@ -16,7 +16,9 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./dynamodb-event-store-input"), exports);
18
18
  __exportStar(require("./event-store"), exports);
19
+ __exportStar(require("./event-store-error"), exports);
19
20
  __exportStar(require("./memory-event-store-input"), exports);
21
+ __exportStar(require("./result"), exports);
20
22
  __exportStar(require("./shard-id"), exports);
21
23
  __exportStar(require("./spanner-event-store-input"), exports);
22
24
  __exportStar(require("./types"), exports);
@@ -1,10 +1,10 @@
1
1
  import type { Aggregate, AggregateId, Event } from "../types";
2
- declare class JsonEventSerializer {
2
+ declare function createJsonEventSerializer(): Readonly<{
3
3
  deserialize<E>(bytes: Uint8Array, converter: (json: unknown) => E): E;
4
4
  serialize<AID extends AggregateId, E extends Event<AID>>(event: E): Uint8Array;
5
- }
6
- declare class JsonSnapshotSerializer {
5
+ }>;
6
+ declare function createJsonSnapshotSerializer(): Readonly<{
7
7
  deserialize<A>(bytes: Uint8Array, converter: (json: unknown) => A): A;
8
8
  serialize<AID extends AggregateId, A extends Aggregate<A, AID>>(aggregate: A): Uint8Array;
9
- }
10
- export { JsonEventSerializer, JsonSnapshotSerializer };
9
+ }>;
10
+ export { createJsonEventSerializer, createJsonSnapshotSerializer };
@@ -1,35 +1,38 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.JsonSnapshotSerializer = exports.JsonEventSerializer = void 0;
3
+ exports.createJsonEventSerializer = createJsonEventSerializer;
4
+ exports.createJsonSnapshotSerializer = createJsonSnapshotSerializer;
4
5
  const encoder = new TextEncoder();
5
6
  const decoder = new TextDecoder();
6
- class JsonEventSerializer {
7
- deserialize(bytes, converter) {
8
- const jsonString = decoder.decode(bytes);
9
- const json = JSON.parse(jsonString);
10
- return converter(json);
11
- }
12
- serialize(event) {
13
- const jsonString = JSON.stringify({
14
- type: event.typeName,
15
- data: event,
16
- });
17
- return encoder.encode(jsonString);
18
- }
7
+ function createJsonEventSerializer() {
8
+ return Object.freeze({
9
+ deserialize(bytes, converter) {
10
+ const jsonString = decoder.decode(bytes);
11
+ const json = JSON.parse(jsonString);
12
+ return converter(json);
13
+ },
14
+ serialize(event) {
15
+ const jsonString = JSON.stringify({
16
+ type: event.typeName,
17
+ data: event,
18
+ });
19
+ return encoder.encode(jsonString);
20
+ },
21
+ });
19
22
  }
20
- exports.JsonEventSerializer = JsonEventSerializer;
21
- class JsonSnapshotSerializer {
22
- deserialize(bytes, converter) {
23
- const jsonString = decoder.decode(bytes);
24
- const obj = JSON.parse(jsonString);
25
- return converter(obj);
26
- }
27
- serialize(aggregate) {
28
- const jsonString = JSON.stringify({
29
- type: aggregate.typeName,
30
- data: aggregate,
31
- });
32
- return encoder.encode(jsonString);
33
- }
23
+ function createJsonSnapshotSerializer() {
24
+ return Object.freeze({
25
+ deserialize(bytes, converter) {
26
+ const jsonString = decoder.decode(bytes);
27
+ const obj = JSON.parse(jsonString);
28
+ return converter(obj);
29
+ },
30
+ serialize(aggregate) {
31
+ const jsonString = JSON.stringify({
32
+ type: aggregate.typeName,
33
+ data: aggregate,
34
+ });
35
+ return encoder.encode(jsonString);
36
+ },
37
+ });
34
38
  }
35
- exports.JsonSnapshotSerializer = JsonSnapshotSerializer;
@@ -1,7 +1,3 @@
1
- import { type ShardId } from "../shard-id";
2
- import type { AggregateId, ShardCount, ShardSelector } from "../types";
3
- declare class DefaultShardSelector<AID extends AggregateId> implements ShardSelector<AID> {
4
- selectShardId(aggregateId: AID, shardCount: ShardCount): ShardId;
5
- private hashString;
6
- }
7
- export { DefaultShardSelector };
1
+ import type { AggregateId, ShardSelector } from "../types";
2
+ declare function createDefaultShardSelector<AID extends AggregateId>(): ShardSelector<AID>;
3
+ export { createDefaultShardSelector };