@photon-grove/evt 0.1.0 → 0.1.1

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 (65) hide show
  1. package/README.md +50 -9
  2. package/dist/dynamodb/client.d.ts +83 -0
  3. package/dist/dynamodb/client.d.ts.map +1 -0
  4. package/dist/dynamodb/client.js +6 -0
  5. package/dist/dynamodb/client.js.map +1 -0
  6. package/dist/dynamodb/index.d.ts +5 -1
  7. package/dist/dynamodb/index.d.ts.map +1 -1
  8. package/dist/dynamodb/index.js +7 -3
  9. package/dist/dynamodb/index.js.map +1 -1
  10. package/dist/dynamodb/item.d.ts +2 -0
  11. package/dist/dynamodb/item.d.ts.map +1 -1
  12. package/dist/dynamodb/item.js +5 -4
  13. package/dist/dynamodb/item.js.map +1 -1
  14. package/dist/dynamodb/marker.d.ts +11 -0
  15. package/dist/dynamodb/marker.d.ts.map +1 -0
  16. package/dist/dynamodb/marker.js +56 -0
  17. package/dist/dynamodb/marker.js.map +1 -0
  18. package/dist/dynamodb/repository.d.ts +61 -0
  19. package/dist/dynamodb/repository.d.ts.map +1 -0
  20. package/dist/dynamodb/repository.js +731 -0
  21. package/dist/dynamodb/repository.js.map +1 -0
  22. package/dist/dynamodb/requests.d.ts +65 -0
  23. package/dist/dynamodb/requests.d.ts.map +1 -0
  24. package/dist/dynamodb/requests.js +179 -0
  25. package/dist/dynamodb/requests.js.map +1 -0
  26. package/dist/errors.d.ts +96 -2
  27. package/dist/errors.d.ts.map +1 -1
  28. package/dist/errors.js +103 -2
  29. package/dist/errors.js.map +1 -1
  30. package/dist/features.d.ts +55 -0
  31. package/dist/features.d.ts.map +1 -0
  32. package/dist/features.js +126 -0
  33. package/dist/features.js.map +1 -0
  34. package/dist/index.d.ts +3 -2
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +2 -1
  37. package/dist/index.js.map +1 -1
  38. package/dist/memory/index.d.ts +1 -1
  39. package/dist/memory/index.d.ts.map +1 -1
  40. package/dist/memory/index.js +1 -1
  41. package/dist/memory/index.js.map +1 -1
  42. package/dist/memory/repository.d.ts +38 -2
  43. package/dist/memory/repository.d.ts.map +1 -1
  44. package/dist/memory/repository.js +95 -6
  45. package/dist/memory/repository.js.map +1 -1
  46. package/dist/repository.d.ts +30 -1
  47. package/dist/repository.d.ts.map +1 -1
  48. package/dist/repository.js +3 -4
  49. package/dist/repository.js.map +1 -1
  50. package/dist/store.d.ts +3 -3
  51. package/dist/store.js +3 -3
  52. package/package.json +12 -3
  53. package/src/dynamodb/client.ts +102 -0
  54. package/src/dynamodb/index.ts +26 -2
  55. package/src/dynamodb/item.ts +6 -4
  56. package/src/dynamodb/marker.ts +64 -0
  57. package/src/dynamodb/repository.ts +1030 -0
  58. package/src/dynamodb/requests.ts +256 -0
  59. package/src/errors.ts +153 -2
  60. package/src/features.ts +175 -0
  61. package/src/index.ts +24 -1
  62. package/src/memory/index.ts +9 -1
  63. package/src/memory/repository.ts +156 -6
  64. package/src/repository.ts +34 -6
  65. package/src/store.ts +3 -3
@@ -2,6 +2,7 @@
2
2
  // same way: validation, the reserved namespaces, and the transaction budget.
3
3
  import { headActionSize, headUpdate } from './dynamodb/head.js';
4
4
  import { eventItem, itemSize, snapshotItem } from './dynamodb/item.js';
5
+ import { FEATURES_PK, REBUILD_LOCK_PK } from './dynamodb/marker.js';
5
6
  import { CommitTooLargeError, EvtError, ReservedEntityIdError } from './errors.js';
6
7
  import { eventId } from './event.js';
7
8
  import { MAX_COMMIT_ITEM_BYTES } from './snapshots.js';
@@ -14,9 +15,6 @@ export const RESERVED_PREFIXES = Object.freeze([
14
15
  'SYSTEM#',
15
16
  'command-outcome#',
16
17
  ]);
17
- // The control rows every commit checks: the feature marker and the rebuild lock.
18
- const FEATURES_ID = 'SYSTEM#FEATURES';
19
- const REBUILD_LOCK_ID = 'SYSTEM#REBUILD';
20
18
  /** Whether an entity ID is in a reserved namespace. */
21
19
  export function isReserved(entityId) {
22
20
  return RESERVED_PREFIXES.some((prefix) => entityId.startsWith(prefix));
@@ -79,7 +77,8 @@ export function validateCommit(commit) {
79
77
  * backend budgets a commit by these sizes, so an oversized commit fails the same way on each.
80
78
  */
81
79
  export function commitSizes(commit, ttl) {
82
- const sizes = [controlCheckSize(FEATURES_ID), controlCheckSize(REBUILD_LOCK_ID)];
80
+ // The control rows every commit checks: the feature marker and the rebuild lock.
81
+ const sizes = [controlCheckSize(FEATURES_PK), controlCheckSize(REBUILD_LOCK_PK)];
83
82
  const first = commit.events[0];
84
83
  const last = commit.events.at(-1);
85
84
  if (first === undefined || last === undefined) {
@@ -1 +1 @@
1
- {"version":3,"file":"repository.js","sourceRoot":"","sources":["../src/repository.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"repository.js","sourceRoot":"","sources":["../src/repository.ts"],"names":[],"mappings":"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"}
package/dist/store.d.ts CHANGED
@@ -94,9 +94,9 @@ export declare class Store {
94
94
  */
95
95
  execute<S, C, D extends EventDefinitions>(aggregate: Aggregate<S, C, D>, entityId: string, command: C, options?: ExecuteOptions): Promise<ExecuteResult<S>>;
96
96
  /**
97
- * Like {@link execute}, but loads and runs the command again after a retryable error (a
98
- * conflict), waiting {@link retryDelay} between attempts. When the attempts run out, the last
99
- * error is thrown. A rejection or a duplicate is a result, never retried.
97
+ * Like {@link execute}, but loads and runs the command again after a retryable error (see
98
+ * {@link isRetryable}), waiting {@link retryDelay} between attempts. When the attempts run out,
99
+ * the last error is thrown. A rejection or a duplicate is a result, never retried.
100
100
  */
101
101
  executeWithRetry<S, C, D extends EventDefinitions>(aggregate: Aggregate<S, C, D>, entityId: string, command: C, options?: RetryOptions): Promise<ExecuteResult<S>>;
102
102
  }
package/dist/store.js CHANGED
@@ -85,9 +85,9 @@ export class Store {
85
85
  return { kind: 'committed', state, events };
86
86
  }
87
87
  /**
88
- * Like {@link execute}, but loads and runs the command again after a retryable error (a
89
- * conflict), waiting {@link retryDelay} between attempts. When the attempts run out, the last
90
- * error is thrown. A rejection or a duplicate is a result, never retried.
88
+ * Like {@link execute}, but loads and runs the command again after a retryable error (see
89
+ * {@link isRetryable}), waiting {@link retryDelay} between attempts. When the attempts run out,
90
+ * the last error is thrown. A rejection or a duplicate is a result, never retried.
91
91
  */
92
92
  async executeWithRetry(aggregate, entityId, command, options = {}) {
93
93
  const policy = options.policy ?? DEFAULT_RETRY_POLICY;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@photon-grove/evt",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Event sourcing for TypeScript, wire-compatible with the Go and Rust evt implementations.",
5
5
  "keywords": [
6
6
  "event-sourcing",
@@ -44,14 +44,23 @@
44
44
  },
45
45
  "./package.json": "./package.json"
46
46
  },
47
+ "peerDependencies": {
48
+ "@aws-sdk/client-dynamodb": "^3.0.0"
49
+ },
50
+ "peerDependenciesMeta": {
51
+ "@aws-sdk/client-dynamodb": {
52
+ "optional": true
53
+ }
54
+ },
47
55
  "scripts": {
48
56
  "build": "tsc",
49
57
  "check": "tsc --noEmit && tsc -p tsconfig.test.json && oxlint --deny-warnings && node scripts/check-imports.ts",
50
58
  "test": "vitest run"
51
59
  },
52
60
  "devDependencies": {
53
- "@types/node": "^25.9.9",
54
- "oxlint": "1.88.0",
61
+ "@aws-sdk/client-dynamodb": "3.1161.0",
62
+ "@types/node": "^26.6.6",
63
+ "oxlint": "1.90.0",
55
64
  "typescript": "^7.0.2",
56
65
  "vitest": "5.0.5"
57
66
  }
@@ -0,0 +1,102 @@
1
+ // The DynamoDB calls the repository makes, as a structural interface. The AWS SDK's aggregated
2
+ // `DynamoDB` client (`@aws-sdk/client-dynamodb`) satisfies it, so this package imports nothing
3
+ // from the SDK. Requests and responses use the low-level `AttributeValue` maps, never the document
4
+ // client's marshalling, because the storage format pins every attribute's type.
5
+
6
+ import type {Item} from './item.js'
7
+
8
+ /** The options the repository passes with every call. */
9
+ export interface RequestOptions {
10
+ abortSignal?: AbortSignal
11
+ }
12
+
13
+ /** One action of a `TransactWriteItems` call. */
14
+ export interface TransactItem {
15
+ ConditionCheck?: ConditionCheckAction
16
+ Put?: PutAction
17
+ Update?: UpdateAction
18
+ Delete?: DeleteAction
19
+ }
20
+
21
+ /** The expression parts an action or a query may carry. */
22
+ export interface Expressions {
23
+ ConditionExpression?: string
24
+ ExpressionAttributeNames?: Record<string, string>
25
+ ExpressionAttributeValues?: Item
26
+ }
27
+
28
+ export interface ConditionCheckAction extends Expressions {
29
+ TableName: string
30
+ Key: Item
31
+ ConditionExpression: string
32
+ }
33
+
34
+ export interface PutAction extends Expressions {
35
+ TableName: string
36
+ Item: Item
37
+ }
38
+
39
+ export interface UpdateAction extends Expressions {
40
+ TableName: string
41
+ Key: Item
42
+ UpdateExpression: string
43
+ }
44
+
45
+ export interface DeleteAction extends Expressions {
46
+ TableName: string
47
+ Key: Item
48
+ }
49
+
50
+ export interface GetItemInput {
51
+ TableName: string
52
+ Key: Item
53
+ ConsistentRead?: boolean
54
+ ProjectionExpression?: string
55
+ ExpressionAttributeNames?: Record<string, string>
56
+ }
57
+
58
+ export interface PutItemInput extends Expressions {
59
+ TableName: string
60
+ Item: Item
61
+ }
62
+
63
+ export interface QueryInput {
64
+ TableName: string
65
+ KeyConditionExpression: string
66
+ ExpressionAttributeNames?: Record<string, string>
67
+ ExpressionAttributeValues: Item
68
+ ConsistentRead?: boolean
69
+ ProjectionExpression?: string
70
+ ScanIndexForward?: boolean
71
+ Limit?: number
72
+ ExclusiveStartKey?: Item
73
+ }
74
+
75
+ export interface ScanInput {
76
+ TableName: string
77
+ ConsistentRead?: boolean
78
+ ProjectionExpression?: string
79
+ Limit?: number
80
+ ExclusiveStartKey?: Item
81
+ }
82
+
83
+ /** A page of a query or a scan. Items come back as the SDK decodes them. */
84
+ export interface Page {
85
+ Items?: Record<string, unknown>[] | undefined
86
+ LastEvaluatedKey?: Record<string, unknown> | undefined
87
+ }
88
+
89
+ /** The calls {@link DynamoRepository} makes: the SDK's `DynamoDB` client has them all. */
90
+ export interface DynamoClient {
91
+ getItem(
92
+ input: GetItemInput,
93
+ options?: RequestOptions,
94
+ ): Promise<{Item?: Record<string, unknown> | undefined}>
95
+ putItem(input: PutItemInput, options?: RequestOptions): Promise<unknown>
96
+ query(input: QueryInput, options?: RequestOptions): Promise<Page>
97
+ scan(input: ScanInput, options?: RequestOptions): Promise<Page>
98
+ transactWriteItems(
99
+ input: {TransactItems: TransactItem[]},
100
+ options?: RequestOptions,
101
+ ): Promise<unknown>
102
+ }
@@ -1,5 +1,5 @@
1
- // @photon-grove/evt/dynamodb: the DynamoDB backend. So far it holds the item codec, which imports
2
- // nothing from the AWS SDK.
1
+ // @photon-grove/evt/dynamodb: the DynamoDB backend. It imports nothing from the AWS SDK: the
2
+ // repository takes the SDK's `DynamoDB` client, or anything shaped like it, as a DynamoClient.
3
3
 
4
4
  export {
5
5
  type AttributeValue,
@@ -17,5 +17,29 @@ export {
17
17
  snapshotFromItem,
18
18
  snapshotItem,
19
19
  sortKey,
20
+ ttlFromItem,
20
21
  viewItem,
21
22
  } from './item.js'
23
+ export {
24
+ type ConditionCheckAction,
25
+ type DeleteAction,
26
+ type DynamoClient,
27
+ type Expressions,
28
+ type GetItemInput,
29
+ type Page,
30
+ type PutAction,
31
+ type PutItemInput,
32
+ type QueryInput,
33
+ type RequestOptions,
34
+ type ScanInput,
35
+ type TransactItem,
36
+ type UpdateAction,
37
+ } from './client.js'
38
+ export {FEATURES_PK, REBUILD_LOCK_PK, manifestFromItem, markerItem} from './marker.js'
39
+ export {DynamoRepository, type DynamoRepositoryOptions} from './repository.js'
40
+ export {
41
+ type CommitTtl,
42
+ type SnapshotTtl,
43
+ commitTransaction,
44
+ snapshotTransaction,
45
+ } from './requests.js'
@@ -151,12 +151,14 @@ export function snapshotFromItem(item: Item): SerializedSnapshot {
151
151
 
152
152
  /** Decodes a head item into its head and its `ttl`, if it has one. */
153
153
  export function headFromItem(item: Item): {head: bigint; ttl: number | undefined} {
154
+ return {head: requiredNumber(item, 'head'), ttl: ttlFromItem(item)}
155
+ }
156
+
157
+ /** An item's `ttl` in Unix seconds, or undefined when it has none. */
158
+ export function ttlFromItem(item: Item): number | undefined {
154
159
  const ttl = optionalNumber(item, 'ttl')
155
160
 
156
- return {
157
- head: requiredNumber(item, 'head'),
158
- ttl: ttl === undefined ? undefined : safeInteger(ttl, 'ttl'),
159
- }
161
+ return ttl === undefined ? undefined : safeInteger(ttl, 'ttl')
160
162
  }
161
163
 
162
164
  /** Whether an item is a stream's inline snapshot (`sk = 0`). */
@@ -0,0 +1,64 @@
1
+ // The DynamoDB item of the feature-marker row. The control rows live in the reserved SYSTEM#
2
+ // namespace at sort key 0.
3
+ //
4
+ // | Attribute | Type | Feature-marker item (`pk = SYSTEM#FEATURES`, `sk = 0`) |
5
+ // | ------------------ | ---- | ------------------------------------------------------------ |
6
+ // | `version` | N | bumped on every change to the manifest |
7
+ // | `features` | S | JSON object, feature name → stored-format version, sorted |
8
+ // | `historyDependent` | S | JSON array of entity types, sorted. Absent when empty |
9
+ // | `retention` | S | JSON array of entity types, sorted. Absent when empty |
10
+
11
+ import {checkInt64, invalid} from '../fields.js'
12
+ import {type FeatureManifest, decodeManifest, encodeManifest} from '../features.js'
13
+ import {type Item, SNAPSHOT_SORT_KEY} from './item.js'
14
+
15
+ /** The partition key of the feature-marker row. */
16
+ export const FEATURES_PK = 'SYSTEM#FEATURES'
17
+
18
+ /** The partition key of the rebuild-lock row, which every commit checks is absent. */
19
+ export const REBUILD_LOCK_PK = 'SYSTEM#REBUILD'
20
+
21
+ /** Encodes a feature manifest as its marker item. Empty entity-type sets are left out. */
22
+ export function markerItem(manifest: FeatureManifest): Item {
23
+ const texts = encodeManifest(manifest)
24
+ const item: Item = {
25
+ pk: {S: FEATURES_PK},
26
+ sk: {N: SNAPSHOT_SORT_KEY.toString()},
27
+ version: {N: manifest.version.toString()},
28
+ features: {S: texts.features},
29
+ }
30
+ if (manifest.historyDependent.length > 0) {
31
+ item['historyDependent'] = {S: texts.historyDependent}
32
+ }
33
+ if (manifest.retention.length > 0) {
34
+ item['retention'] = {S: texts.retention}
35
+ }
36
+
37
+ return item
38
+ }
39
+
40
+ /** Decodes a marker item. An absent text attribute is an empty map or set. */
41
+ export function manifestFromItem(item: Item): FeatureManifest {
42
+ const version = item['version']
43
+ if (version === undefined || !('N' in version) || !/^\d+$/.test(version.N)) {
44
+ throw invalid('the feature marker has no version')
45
+ }
46
+
47
+ return decodeManifest(checkInt64(BigInt(version.N), 'the feature marker version'), {
48
+ features: text(item, 'features'),
49
+ historyDependent: text(item, 'historyDependent'),
50
+ retention: text(item, 'retention'),
51
+ })
52
+ }
53
+
54
+ function text(item: Item, name: string): string {
55
+ const value = item[name]
56
+ if (value === undefined) {
57
+ return ''
58
+ }
59
+ if (!('S' in value)) {
60
+ throw invalid(`the feature marker's ${name} attribute is not a string`)
61
+ }
62
+
63
+ return value.S
64
+ }