event-store-adapter-js 2.2.167-snapshot.2 → 3.0.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.
- package/README.ja.md +41 -15
- package/README.md +42 -16
- package/dist/aggregate-id-value.d.ts +7 -0
- package/dist/aggregate-id-value.js +9 -0
- package/dist/aggregate-id.d.ts +7 -0
- package/dist/aggregate.d.ts +10 -0
- package/dist/dynamodb-event-store-input.d.ts +22 -0
- package/dist/dynamodb-event-store-input.js +2 -0
- package/dist/event-serializer.d.ts +7 -0
- package/dist/event-serializer.js +2 -0
- package/dist/event-store.d.ts +13 -11
- package/dist/event-store.js +15 -14
- package/dist/event.d.ts +10 -0
- package/dist/event.js +2 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/dist/internal/default-serializer.d.ts +7 -11
- package/dist/internal/default-serializer.js +6 -14
- package/dist/internal/default-shard-selector.d.ts +7 -0
- package/dist/internal/default-shard-selector.js +31 -0
- package/dist/internal/dynamodb-aggregate-key.d.ts +14 -0
- package/dist/internal/dynamodb-aggregate-key.js +23 -0
- package/dist/internal/dynamodb-delete-ttl-millis.d.ts +2 -0
- package/dist/internal/dynamodb-delete-ttl-millis.js +18 -0
- package/dist/internal/dynamodb-event-store.d.ts +36 -0
- package/dist/internal/dynamodb-event-store.js +360 -0
- package/dist/internal/dynamodb-snapshot-retention-executor.d.ts +27 -0
- package/dist/internal/dynamodb-snapshot-retention-executor.js +297 -0
- package/dist/internal/event-store-assertions.d.ts +5 -0
- package/dist/internal/event-store-assertions.js +21 -0
- package/dist/internal/json-converter.d.ts +2 -0
- package/dist/internal/json-converter.js +21 -0
- package/dist/internal/memory-event-store.d.ts +17 -0
- package/dist/internal/memory-event-store.js +126 -0
- package/dist/internal/spanner-aggregate-key.d.ts +13 -0
- package/dist/internal/spanner-aggregate-key.js +19 -0
- package/dist/internal/spanner-event-store.d.ts +46 -0
- package/dist/internal/spanner-event-store.js +440 -0
- package/dist/logger.d.ts +8 -0
- package/dist/logger.js +2 -0
- package/dist/memory-event-store-input.d.ts +6 -0
- package/dist/memory-event-store-input.js +2 -0
- package/dist/optimistic-lock-error.d.ts +4 -0
- package/dist/optimistic-lock-error.js +10 -0
- package/dist/shard-count.d.ts +7 -0
- package/dist/shard-count.js +9 -0
- package/dist/shard-id.d.ts +7 -0
- package/dist/shard-id.js +9 -0
- package/dist/shard-selector.d.ts +7 -0
- package/dist/shard-selector.js +2 -0
- package/dist/snapshot-serializer.d.ts +7 -0
- package/dist/snapshot-serializer.js +2 -0
- package/dist/spanner-event-store-input.d.ts +18 -0
- package/dist/spanner-event-store-input.js +2 -0
- package/dist/types.d.ts +10 -44
- package/dist/types.js +7 -12
- package/docs/DATABASE_SCHEMA.ja.md +3 -1
- package/docs/DATABASE_SCHEMA.md +3 -1
- package/docs/GCP_EVENT_INTEGRATION.ja.md +154 -0
- package/docs/MIGRATION_GUIDE_3.0.ja.md +65 -0
- package/docs/MIGRATION_GUIDE_3.0.md +65 -0
- package/docs/SPANNER_DATABASE_SCHEMA.ja.md +49 -0
- package/docs/SPANNER_DATABASE_SCHEMA.md +51 -0
- package/package.json +30 -16
- package/.github/CODEONWERS +0 -1
- package/.github/create-release-note-body.py +0 -40
- package/.github/create-release-note-header.py +0 -28
- package/.github/next-semver.py +0 -20
- package/.github/semver-level.py +0 -31
- package/.github/workflows/bump-version.yml +0 -97
- package/.github/workflows/ci.yml +0 -35
- package/.github/workflows/release.yml +0 -23
- package/.github/workflows/snapshot.yml +0 -38
- package/.mise.toml +0 -2
- package/.vscode/settings.json +0 -11
- package/biome.json +0 -27
- package/dist/event-store-options.d.ts +0 -11
- package/dist/event-store-with-options.d.ts +0 -6
- package/dist/internal/default-key-resolver.d.ts +0 -7
- package/dist/internal/default-key-resolver.js +0 -29
- package/dist/internal/event-store-for-dynamodb.d.ts +0 -42
- package/dist/internal/event-store-for-dynamodb.js +0 -455
- package/dist/internal/event-store-for-memory.d.ts +0 -12
- package/dist/internal/event-store-for-memory.js +0 -89
- package/jest.config.ts +0 -5
- package/renovate.json +0 -19
- package/scripts/run-claude.sh +0 -3
- package/scripts/run-codex.sh +0 -7
- package/src/event-store-options.ts +0 -31
- package/src/event-store-with-options.ts +0 -12
- package/src/event-store.ts +0 -91
- package/src/index.ts +0 -2
- package/src/internal/default-key-resolver.ts +0 -31
- package/src/internal/default-serializer.ts +0 -54
- package/src/internal/event-store-for-dynamodb.test.ts +0 -151
- package/src/internal/event-store-for-dynamodb.ts +0 -671
- package/src/internal/event-store-for-memory.test.ts +0 -90
- package/src/internal/event-store-for-memory.ts +0 -99
- package/src/internal/test/dynamodb-utils.ts +0 -154
- package/src/internal/test/user-account-event.ts +0 -64
- package/src/internal/test/user-account-id.ts +0 -17
- package/src/internal/test/user-account-repository.test.ts +0 -121
- package/src/internal/test/user-account-repository.ts +0 -36
- package/src/internal/test/user-account.ts +0 -109
- package/src/types.ts +0 -81
- package/tsconfig.json +0 -21
- /package/dist/{event-store-options.js → aggregate-id.js} +0 -0
- /package/dist/{event-store-with-options.js → aggregate.js} +0 -0
package/README.ja.md
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
# 導入方法
|
|
14
14
|
|
|
15
15
|
```shell
|
|
16
|
-
|
|
16
|
+
npm install event-store-adapter-js
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
# 使い方
|
|
@@ -58,22 +58,32 @@ class UserAccountRepository {
|
|
|
58
58
|
以下はリポジトリの使用例です。
|
|
59
59
|
|
|
60
60
|
```typescript
|
|
61
|
-
const eventStore =
|
|
61
|
+
const eventStore = EventStore.ofDynamoDB<
|
|
62
62
|
UserAccountId,
|
|
63
63
|
UserAccount,
|
|
64
64
|
UserAccountEvent
|
|
65
|
-
>(
|
|
66
|
-
dynamodbClient,
|
|
67
|
-
JOURNAL_TABLE_NAME,
|
|
68
|
-
SNAPSHOT_TABLE_NAME,
|
|
69
|
-
JOURNAL_AID_INDEX_NAME,
|
|
70
|
-
SNAPSHOTS_AID_INDEX_NAME,
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
65
|
+
>({
|
|
66
|
+
client: dynamodbClient,
|
|
67
|
+
journalTableName: JOURNAL_TABLE_NAME,
|
|
68
|
+
snapshotTableName: SNAPSHOT_TABLE_NAME,
|
|
69
|
+
journalAidIndexName: JOURNAL_AID_INDEX_NAME,
|
|
70
|
+
snapshotAidIndexName: SNAPSHOTS_AID_INDEX_NAME,
|
|
71
|
+
snapshotActiveTtlIndexName: SNAPSHOTS_ACTIVE_TTL_INDEX_NAME,
|
|
72
|
+
shardCount: 32,
|
|
73
|
+
eventConverter: convertJSONtoUserAccountEvent,
|
|
74
|
+
snapshotConverter: convertJSONToUserAccount,
|
|
75
|
+
});
|
|
75
76
|
// if you want to use in-memory event store, use the following code.
|
|
76
|
-
// const eventStore =
|
|
77
|
+
// const eventStore = EventStore.ofMemory<UserAccountId, UserAccount, UserAccountEvent>({});
|
|
78
|
+
// Cloud Spannerを使う場合は、呼び出し側で管理するDatabaseを渡します。
|
|
79
|
+
// const eventStore = EventStore.ofSpanner<UserAccountId, UserAccount, UserAccountEvent>({
|
|
80
|
+
// database: spannerDatabase,
|
|
81
|
+
// journalTableName: "journal",
|
|
82
|
+
// snapshotTableName: "snapshot",
|
|
83
|
+
// shardCount: 32,
|
|
84
|
+
// eventConverter: convertJSONtoUserAccountEvent,
|
|
85
|
+
// snapshotConverter: convertJSONToUserAccount,
|
|
86
|
+
// });
|
|
77
87
|
|
|
78
88
|
const userAccountRepository = new UserAccountRepository(eventStore);
|
|
79
89
|
|
|
@@ -98,13 +108,30 @@ expect(userAccount3.sequenceNumber).toEqual(2);
|
|
|
98
108
|
expect(userAccount3.version).toEqual(2);
|
|
99
109
|
```
|
|
100
110
|
|
|
111
|
+
## 開発
|
|
112
|
+
|
|
113
|
+
このリポジトリは pnpm workspace を使います。ライブラリパッケージは
|
|
114
|
+
`packages/library` に配置し、今後の example や test package の追加先として
|
|
115
|
+
`packages/examples` と `packages/tests` を予約しています。
|
|
116
|
+
|
|
117
|
+
```shell
|
|
118
|
+
pnpm install
|
|
119
|
+
pnpm run lint
|
|
120
|
+
pnpm run build
|
|
121
|
+
pnpm run test
|
|
122
|
+
pnpm run coverage
|
|
123
|
+
```
|
|
124
|
+
|
|
101
125
|
## テーブル仕様
|
|
102
126
|
|
|
103
127
|
[docs/DATABASE_SCHEMA.ja.md](docs/DATABASE_SCHEMA.ja.md)を参照してください。
|
|
104
128
|
|
|
129
|
+
Cloud Spannerについては[docs/SPANNER_DATABASE_SCHEMA.ja.md](docs/SPANNER_DATABASE_SCHEMA.ja.md)を参照してください。
|
|
130
|
+
|
|
105
131
|
## ライセンス
|
|
106
132
|
|
|
107
|
-
MIT
|
|
133
|
+
MIT と Apache-2.0 のデュアルライセンスです。詳細は
|
|
134
|
+
[LICENSE-MIT](LICENSE-MIT) と [LICENSE-APACHE](LICENSE-APACHE) を参照してください。
|
|
108
135
|
|
|
109
136
|
## 他の言語のための実装
|
|
110
137
|
|
|
@@ -116,4 +143,3 @@ MITライセンスです。詳細は[LICENSE](LICENSE)を参照してくださ
|
|
|
116
143
|
- [for JavaScript/TypeScript](https://github.com/j5ik2o/event-store-adapter-js)
|
|
117
144
|
- [for .NET](https://github.com/j5ik2o/event-store-adapter-dotnet)
|
|
118
145
|
- [for PHP](https://github.com/j5ik2o/event-store-adapter-php)
|
|
119
|
-
|
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ This library is designed to turn DynamoDB into an Event Store for CQRS/Event Sou
|
|
|
14
14
|
# Installation
|
|
15
15
|
|
|
16
16
|
```shell
|
|
17
|
-
|
|
17
|
+
npm install event-store-adapter-js
|
|
18
18
|
```
|
|
19
19
|
|
|
20
20
|
# Usage
|
|
@@ -61,22 +61,32 @@ class UserAccountRepository {
|
|
|
61
61
|
The following is an example of the repository usage.
|
|
62
62
|
|
|
63
63
|
```typescript
|
|
64
|
-
const eventStore =
|
|
64
|
+
const eventStore = EventStore.ofDynamoDB<
|
|
65
65
|
UserAccountId,
|
|
66
66
|
UserAccount,
|
|
67
67
|
UserAccountEvent
|
|
68
|
-
>(
|
|
69
|
-
dynamodbClient,
|
|
70
|
-
JOURNAL_TABLE_NAME,
|
|
71
|
-
SNAPSHOT_TABLE_NAME,
|
|
72
|
-
JOURNAL_AID_INDEX_NAME,
|
|
73
|
-
SNAPSHOTS_AID_INDEX_NAME,
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
68
|
+
>({
|
|
69
|
+
client: dynamodbClient,
|
|
70
|
+
journalTableName: JOURNAL_TABLE_NAME,
|
|
71
|
+
snapshotTableName: SNAPSHOT_TABLE_NAME,
|
|
72
|
+
journalAidIndexName: JOURNAL_AID_INDEX_NAME,
|
|
73
|
+
snapshotAidIndexName: SNAPSHOTS_AID_INDEX_NAME,
|
|
74
|
+
snapshotActiveTtlIndexName: SNAPSHOTS_ACTIVE_TTL_INDEX_NAME,
|
|
75
|
+
shardCount: 32,
|
|
76
|
+
eventConverter: convertJSONtoUserAccountEvent,
|
|
77
|
+
snapshotConverter: convertJSONToUserAccount,
|
|
78
|
+
});
|
|
78
79
|
// if you want to use in-memory event store, use the following code.
|
|
79
|
-
// const eventStore =
|
|
80
|
+
// const eventStore = EventStore.ofMemory<UserAccountId, UserAccount, UserAccountEvent>({});
|
|
81
|
+
// if you want to use Cloud Spanner, pass a caller-managed Database.
|
|
82
|
+
// const eventStore = EventStore.ofSpanner<UserAccountId, UserAccount, UserAccountEvent>({
|
|
83
|
+
// database: spannerDatabase,
|
|
84
|
+
// journalTableName: "journal",
|
|
85
|
+
// snapshotTableName: "snapshot",
|
|
86
|
+
// shardCount: 32,
|
|
87
|
+
// eventConverter: convertJSONtoUserAccountEvent,
|
|
88
|
+
// snapshotConverter: convertJSONToUserAccount,
|
|
89
|
+
// });
|
|
80
90
|
|
|
81
91
|
const userAccountRepository = new UserAccountRepository(eventStore);
|
|
82
92
|
|
|
@@ -101,19 +111,35 @@ expect(userAccount3.sequenceNumber).toEqual(2);
|
|
|
101
111
|
expect(userAccount3.version).toEqual(2);
|
|
102
112
|
```
|
|
103
113
|
|
|
114
|
+
## Development
|
|
115
|
+
|
|
116
|
+
This repository uses pnpm workspaces. The library package is located at
|
|
117
|
+
`packages/library`, with `packages/examples` and `packages/tests` reserved for
|
|
118
|
+
future example and test packages.
|
|
119
|
+
|
|
120
|
+
```shell
|
|
121
|
+
pnpm install
|
|
122
|
+
pnpm run lint
|
|
123
|
+
pnpm run build
|
|
124
|
+
pnpm run test
|
|
125
|
+
pnpm run coverage
|
|
126
|
+
```
|
|
127
|
+
|
|
104
128
|
## Table Specifications
|
|
105
129
|
|
|
106
130
|
See [docs/DATABASE_SCHEMA.md](docs/DATABASE_SCHEMA.md).
|
|
107
131
|
|
|
132
|
+
For Cloud Spanner, see [docs/SPANNER_DATABASE_SCHEMA.md](docs/SPANNER_DATABASE_SCHEMA.md).
|
|
133
|
+
|
|
108
134
|
## CQRS/Event Sourcing Example
|
|
109
135
|
|
|
110
136
|
See [j5ik2o/cqrs-es-example-js](https://github.com/j5ik2o/cqrs-es-example-js).
|
|
111
137
|
|
|
112
|
-
## License
|
|
138
|
+
## License
|
|
113
139
|
|
|
114
|
-
|
|
140
|
+
Dual-licensed under MIT and Apache-2.0.
|
|
141
|
+
See [LICENSE-MIT](LICENSE-MIT) and [LICENSE-APACHE](LICENSE-APACHE).
|
|
115
142
|
|
|
116
143
|
## Links
|
|
117
144
|
|
|
118
145
|
- [Common Documents](https://github.com/j5ik2o/event-store-adapter)
|
|
119
|
-
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
declare const aggregateIdValueBrand: unique symbol;
|
|
2
|
+
type AggregateIdValue = string & {
|
|
3
|
+
readonly [aggregateIdValueBrand]: "AggregateIdValue";
|
|
4
|
+
};
|
|
5
|
+
declare function createAggregateIdValue(value: string): AggregateIdValue;
|
|
6
|
+
export type { AggregateIdValue };
|
|
7
|
+
export { createAggregateIdValue };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createAggregateIdValue = createAggregateIdValue;
|
|
4
|
+
function createAggregateIdValue(value) {
|
|
5
|
+
if (value.length === 0) {
|
|
6
|
+
throw new Error("aggregateId value must be non-empty");
|
|
7
|
+
}
|
|
8
|
+
return value;
|
|
9
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { AggregateId } from "./aggregate-id";
|
|
2
|
+
interface Aggregate<This extends Aggregate<This, AID>, AID extends AggregateId> {
|
|
3
|
+
typeName: string;
|
|
4
|
+
id: AID;
|
|
5
|
+
sequenceNumber: number;
|
|
6
|
+
version: number;
|
|
7
|
+
withVersion(version: number): This;
|
|
8
|
+
updateVersion(version: (value: number) => number): This;
|
|
9
|
+
}
|
|
10
|
+
export type { Aggregate };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { DynamoDBClient } from "@aws-sdk/client-dynamodb";
|
|
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>> {
|
|
4
|
+
client: DynamoDBClient;
|
|
5
|
+
journalTableName: string;
|
|
6
|
+
snapshotTableName: string;
|
|
7
|
+
journalAidIndexName: string;
|
|
8
|
+
snapshotAidIndexName: string;
|
|
9
|
+
snapshotActiveTtlIndexName: string;
|
|
10
|
+
shardCount: number;
|
|
11
|
+
/** Converts the deserialized event JSON payload from unknown into an event. */
|
|
12
|
+
eventConverter: (json: unknown) => E;
|
|
13
|
+
/** Converts the deserialized snapshot JSON payload from unknown into an aggregate. */
|
|
14
|
+
snapshotConverter: (json: unknown) => A;
|
|
15
|
+
keepSnapshotCount?: number;
|
|
16
|
+
deleteTtlMillis?: number;
|
|
17
|
+
shardSelector?: ShardSelector<AID>;
|
|
18
|
+
eventSerializer?: EventSerializer<AID, E>;
|
|
19
|
+
snapshotSerializer?: SnapshotSerializer<AID, A>;
|
|
20
|
+
logger?: Logger;
|
|
21
|
+
}
|
|
22
|
+
export type { DynamoDBEventStoreInput };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { AggregateId } from "./aggregate-id";
|
|
2
|
+
import type { Event } from "./event";
|
|
3
|
+
interface EventSerializer<AID extends AggregateId, E extends Event<AID>> {
|
|
4
|
+
serialize(event: E): Uint8Array;
|
|
5
|
+
deserialize(bytes: Uint8Array, converter: (json: unknown) => E): E;
|
|
6
|
+
}
|
|
7
|
+
export type { EventSerializer };
|
package/dist/event-store.d.ts
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type
|
|
3
|
-
import type {
|
|
4
|
-
import type { Aggregate, AggregateId, Event
|
|
5
|
-
interface EventStore<AID extends AggregateId, A extends Aggregate<A, AID>, E extends Event<AID>> {
|
|
6
|
-
persistEvent(event: E,
|
|
1
|
+
import type { DynamoDBEventStoreInput } from "./dynamodb-event-store-input";
|
|
2
|
+
import type { MemoryEventStoreInput } from "./memory-event-store-input";
|
|
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
7
|
persistEventAndSnapshot(event: E, aggregate: A): Promise<void>;
|
|
8
8
|
getEventsByIdSinceSequenceNumber(id: AID, sequenceNumber: number): Promise<E[]>;
|
|
9
9
|
getLatestSnapshotById(id: AID): Promise<A | undefined>;
|
|
10
10
|
}
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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 {};
|
package/dist/event-store.js
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
3
|
+
exports.EventStore = void 0;
|
|
4
|
+
const dynamodb_event_store_1 = require("./internal/dynamodb-event-store");
|
|
5
|
+
const memory_event_store_1 = require("./internal/memory-event-store");
|
|
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
|
+
});
|
package/dist/event.d.ts
ADDED
package/dist/event.js
ADDED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -14,5 +14,9 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./dynamodb-event-store-input"), exports);
|
|
17
18
|
__exportStar(require("./event-store"), exports);
|
|
19
|
+
__exportStar(require("./memory-event-store-input"), exports);
|
|
20
|
+
__exportStar(require("./shard-id"), exports);
|
|
21
|
+
__exportStar(require("./spanner-event-store-input"), exports);
|
|
18
22
|
__exportStar(require("./types"), exports);
|
|
@@ -1,14 +1,10 @@
|
|
|
1
|
-
import type { Aggregate, AggregateId, Event
|
|
2
|
-
declare class JsonEventSerializer
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
deserialize(bytes: Uint8Array, converter: (json: any) => E): E;
|
|
6
|
-
serialize(event: E): Uint8Array;
|
|
1
|
+
import type { Aggregate, AggregateId, Event } from "../types";
|
|
2
|
+
declare class JsonEventSerializer {
|
|
3
|
+
deserialize<E>(bytes: Uint8Array, converter: (json: unknown) => E): E;
|
|
4
|
+
serialize<AID extends AggregateId, E extends Event<AID>>(event: E): Uint8Array;
|
|
7
5
|
}
|
|
8
|
-
declare class JsonSnapshotSerializer
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
deserialize(bytes: Uint8Array, converter: (json: any) => A): A;
|
|
12
|
-
serialize(aggregate: A): Uint8Array;
|
|
6
|
+
declare class JsonSnapshotSerializer {
|
|
7
|
+
deserialize<A>(bytes: Uint8Array, converter: (json: unknown) => A): A;
|
|
8
|
+
serialize<AID extends AggregateId, A extends Aggregate<A, AID>>(aggregate: A): Uint8Array;
|
|
13
9
|
}
|
|
14
10
|
export { JsonEventSerializer, JsonSnapshotSerializer };
|
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.JsonSnapshotSerializer = exports.JsonEventSerializer = void 0;
|
|
4
|
+
const encoder = new TextEncoder();
|
|
5
|
+
const decoder = new TextDecoder();
|
|
4
6
|
class JsonEventSerializer {
|
|
5
|
-
constructor() {
|
|
6
|
-
this.encoder = new TextEncoder();
|
|
7
|
-
this.decoder = new TextDecoder();
|
|
8
|
-
}
|
|
9
|
-
// biome-ignore lint/suspicious/noExplicitAny: JSON deserialization requires dynamic typing
|
|
10
7
|
deserialize(bytes, converter) {
|
|
11
|
-
const jsonString =
|
|
8
|
+
const jsonString = decoder.decode(bytes);
|
|
12
9
|
const json = JSON.parse(jsonString);
|
|
13
10
|
return converter(json);
|
|
14
11
|
}
|
|
@@ -17,18 +14,13 @@ class JsonEventSerializer {
|
|
|
17
14
|
type: event.typeName,
|
|
18
15
|
data: event,
|
|
19
16
|
});
|
|
20
|
-
return
|
|
17
|
+
return encoder.encode(jsonString);
|
|
21
18
|
}
|
|
22
19
|
}
|
|
23
20
|
exports.JsonEventSerializer = JsonEventSerializer;
|
|
24
21
|
class JsonSnapshotSerializer {
|
|
25
|
-
constructor() {
|
|
26
|
-
this.encoder = new TextEncoder();
|
|
27
|
-
this.decoder = new TextDecoder();
|
|
28
|
-
}
|
|
29
|
-
// biome-ignore lint/suspicious/noExplicitAny: JSON deserialization requires dynamic typing
|
|
30
22
|
deserialize(bytes, converter) {
|
|
31
|
-
const jsonString =
|
|
23
|
+
const jsonString = decoder.decode(bytes);
|
|
32
24
|
const obj = JSON.parse(jsonString);
|
|
33
25
|
return converter(obj);
|
|
34
26
|
}
|
|
@@ -37,7 +29,7 @@ class JsonSnapshotSerializer {
|
|
|
37
29
|
type: aggregate.typeName,
|
|
38
30
|
data: aggregate,
|
|
39
31
|
});
|
|
40
|
-
return
|
|
32
|
+
return encoder.encode(jsonString);
|
|
41
33
|
}
|
|
42
34
|
}
|
|
43
35
|
exports.JsonSnapshotSerializer = JsonSnapshotSerializer;
|
|
@@ -0,0 +1,7 @@
|
|
|
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 };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DefaultShardSelector = void 0;
|
|
4
|
+
const shard_id_1 = require("../shard-id");
|
|
5
|
+
class DefaultShardSelector {
|
|
6
|
+
selectShardId(aggregateId, shardCount) {
|
|
7
|
+
if (aggregateId === undefined || aggregateId === null) {
|
|
8
|
+
throw new Error(`aggregateId is undefined or null: ${aggregateId}`);
|
|
9
|
+
}
|
|
10
|
+
if (!Number.isSafeInteger(shardCount) || shardCount <= 0) {
|
|
11
|
+
throw new Error(`shardCount must be a positive safe integer, got ${shardCount}`);
|
|
12
|
+
}
|
|
13
|
+
const hash = this.hashString(aggregateId.asString());
|
|
14
|
+
return (0, shard_id_1.createShardId)(hash % shardCount);
|
|
15
|
+
}
|
|
16
|
+
hashString(str) {
|
|
17
|
+
// AggregateId.asString() is user code, so validate runtime values despite the TypeScript type.
|
|
18
|
+
if (typeof str !== "string") {
|
|
19
|
+
throw new Error(`str is not a string: ${str}`);
|
|
20
|
+
}
|
|
21
|
+
let hash = 0;
|
|
22
|
+
for (let i = 0; i < str.length; i++) {
|
|
23
|
+
const char = str.charCodeAt(i);
|
|
24
|
+
hash = (hash << 5) - hash + char;
|
|
25
|
+
// Keep the legacy DefaultKeyResolver result, using an explicit 32-bit mask instead of the opaque hash & hash idiom.
|
|
26
|
+
hash = hash & 0xffffffff;
|
|
27
|
+
}
|
|
28
|
+
return hash >>> 0;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
exports.DefaultShardSelector = DefaultShardSelector;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ShardCount } from "../shard-count";
|
|
2
|
+
import type { ShardId } from "../shard-id";
|
|
3
|
+
import type { ShardSelector } from "../shard-selector";
|
|
4
|
+
import type { AggregateId } from "../types";
|
|
5
|
+
declare class DynamoDBAggregateKey<AID extends AggregateId> {
|
|
6
|
+
readonly shardId: ShardId;
|
|
7
|
+
readonly aggregateId: AID;
|
|
8
|
+
readonly sequenceNumber: number;
|
|
9
|
+
private constructor();
|
|
10
|
+
static create<AID extends AggregateId>(aggregateId: AID, sequenceNumber: number, shardSelector: ShardSelector<AID>, shardCount: ShardCount): DynamoDBAggregateKey<AID>;
|
|
11
|
+
get partitionKeyValue(): string;
|
|
12
|
+
get sortKeyValue(): string;
|
|
13
|
+
}
|
|
14
|
+
export { DynamoDBAggregateKey };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DynamoDBAggregateKey = void 0;
|
|
4
|
+
class DynamoDBAggregateKey {
|
|
5
|
+
constructor(shardId, aggregateId, sequenceNumber) {
|
|
6
|
+
this.shardId = shardId;
|
|
7
|
+
this.aggregateId = aggregateId;
|
|
8
|
+
this.sequenceNumber = sequenceNumber;
|
|
9
|
+
}
|
|
10
|
+
static create(aggregateId, sequenceNumber, shardSelector, shardCount) {
|
|
11
|
+
if (!Number.isSafeInteger(sequenceNumber) || sequenceNumber < 0) {
|
|
12
|
+
throw new Error(`sequenceNumber must be a non-negative safe integer, got ${sequenceNumber}`);
|
|
13
|
+
}
|
|
14
|
+
return new DynamoDBAggregateKey(shardSelector.selectShardId(aggregateId, shardCount), aggregateId, sequenceNumber);
|
|
15
|
+
}
|
|
16
|
+
get partitionKeyValue() {
|
|
17
|
+
return `${this.aggregateId.typeName}-${this.shardId}`;
|
|
18
|
+
}
|
|
19
|
+
get sortKeyValue() {
|
|
20
|
+
return `${this.aggregateId.typeName}-${this.aggregateId.value}-${this.sequenceNumber}`;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
exports.DynamoDBAggregateKey = DynamoDBAggregateKey;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.normalizeDynamoDBDeleteTtlMillis = normalizeDynamoDBDeleteTtlMillis;
|
|
4
|
+
function normalizeDynamoDBDeleteTtlMillis(deleteTtlMillis) {
|
|
5
|
+
if (deleteTtlMillis === undefined) {
|
|
6
|
+
return undefined;
|
|
7
|
+
}
|
|
8
|
+
if (!Number.isFinite(deleteTtlMillis)) {
|
|
9
|
+
throw new Error(`deleteTtlMillis must be finite, got ${formatDeleteTtlMillis(deleteTtlMillis)}`);
|
|
10
|
+
}
|
|
11
|
+
if (deleteTtlMillis < 0 || Object.is(deleteTtlMillis, -0)) {
|
|
12
|
+
throw new Error(`deleteTtlMillis must be non-negative, got ${formatDeleteTtlMillis(deleteTtlMillis)}`);
|
|
13
|
+
}
|
|
14
|
+
return Math.floor(deleteTtlMillis);
|
|
15
|
+
}
|
|
16
|
+
function formatDeleteTtlMillis(deleteTtlMillis) {
|
|
17
|
+
return Object.is(deleteTtlMillis, -0) ? "-0" : String(deleteTtlMillis);
|
|
18
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { DynamoDBEventStoreInput } from "../dynamodb-event-store-input";
|
|
2
|
+
import type { EventStore } from "../event-store";
|
|
3
|
+
import { type Aggregate, type AggregateId, type Event } from "../types";
|
|
4
|
+
declare class DynamoDBEventStore<AID extends AggregateId, A extends Aggregate<A, AID>, E extends Event<AID>> implements EventStore<AID, A, E> {
|
|
5
|
+
private readonly dynamodbClient;
|
|
6
|
+
private readonly journalTableName;
|
|
7
|
+
private readonly snapshotTableName;
|
|
8
|
+
private readonly journalAidIndexName;
|
|
9
|
+
private readonly snapshotAidIndexName;
|
|
10
|
+
private readonly snapshotActiveTtlIndexName;
|
|
11
|
+
private readonly shardCount;
|
|
12
|
+
private readonly eventConverter;
|
|
13
|
+
private readonly snapshotConverter;
|
|
14
|
+
private readonly keepSnapshotCount;
|
|
15
|
+
private readonly deleteTtlMillis;
|
|
16
|
+
private readonly shardSelector;
|
|
17
|
+
private readonly eventSerializer;
|
|
18
|
+
private readonly snapshotSerializer;
|
|
19
|
+
private readonly logger;
|
|
20
|
+
constructor(input: DynamoDBEventStoreInput<AID, A, E>);
|
|
21
|
+
getEventsByIdSinceSequenceNumber(id: AID, sequenceNumber: number): Promise<E[]>;
|
|
22
|
+
getLatestSnapshotById(id: AID): Promise<A | undefined>;
|
|
23
|
+
persistEvent(event: E, expectedVersion: number): Promise<void>;
|
|
24
|
+
persistEventAndSnapshot(event: E, aggregate: A): Promise<void>;
|
|
25
|
+
private createEventAndSnapshot;
|
|
26
|
+
private updateEventAndSnapshotOpt;
|
|
27
|
+
private putJournal;
|
|
28
|
+
private putSnapshot;
|
|
29
|
+
private putRedundantSnapshot;
|
|
30
|
+
private updateSnapshot;
|
|
31
|
+
private purgeExcessSnapshots;
|
|
32
|
+
private assertConverter;
|
|
33
|
+
private parseShardCount;
|
|
34
|
+
private normalizeDeleteTtlMillis;
|
|
35
|
+
}
|
|
36
|
+
export { DynamoDBEventStore };
|