@photon-grove/evt 0.0.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.
- package/LICENSE +176 -0
- package/README.md +164 -1
- package/dist/aggregate.d.ts +83 -0
- package/dist/aggregate.d.ts.map +1 -0
- package/dist/aggregate.js +92 -0
- package/dist/aggregate.js.map +1 -0
- package/dist/base64.d.ts +8 -0
- package/dist/base64.d.ts.map +1 -0
- package/dist/base64.js +67 -0
- package/dist/base64.js.map +1 -0
- package/dist/codec.d.ts +56 -0
- package/dist/codec.d.ts.map +1 -0
- package/dist/codec.js +90 -0
- package/dist/codec.js.map +1 -0
- package/dist/commit-id.d.ts +3 -0
- package/dist/commit-id.d.ts.map +1 -0
- package/dist/commit-id.js +43 -0
- package/dist/commit-id.js.map +1 -0
- package/dist/dynamodb/client.d.ts +83 -0
- package/dist/dynamodb/client.d.ts.map +1 -0
- package/dist/dynamodb/client.js +6 -0
- package/dist/dynamodb/client.js.map +1 -0
- package/dist/dynamodb/head.d.ts +34 -0
- package/dist/dynamodb/head.d.ts.map +1 -0
- package/dist/dynamodb/head.js +62 -0
- package/dist/dynamodb/head.js.map +1 -0
- package/dist/dynamodb/index.d.ts +6 -0
- package/dist/dynamodb/index.d.ts.map +1 -0
- package/dist/dynamodb/index.js +8 -0
- package/dist/dynamodb/index.js.map +1 -0
- package/dist/dynamodb/item.d.ts +70 -0
- package/dist/dynamodb/item.d.ts.map +1 -0
- package/dist/dynamodb/item.js +264 -0
- package/dist/dynamodb/item.js.map +1 -0
- package/dist/dynamodb/marker.d.ts +11 -0
- package/dist/dynamodb/marker.d.ts.map +1 -0
- package/dist/dynamodb/marker.js +56 -0
- package/dist/dynamodb/marker.js.map +1 -0
- package/dist/dynamodb/repository.d.ts +61 -0
- package/dist/dynamodb/repository.d.ts.map +1 -0
- package/dist/dynamodb/repository.js +731 -0
- package/dist/dynamodb/repository.js.map +1 -0
- package/dist/dynamodb/requests.d.ts +65 -0
- package/dist/dynamodb/requests.d.ts.map +1 -0
- package/dist/dynamodb/requests.js +179 -0
- package/dist/dynamodb/requests.js.map +1 -0
- package/dist/envelope.d.ts +15 -0
- package/dist/envelope.d.ts.map +1 -0
- package/dist/envelope.js +59 -0
- package/dist/envelope.js.map +1 -0
- package/dist/errors.d.ts +205 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +240 -0
- package/dist/errors.js.map +1 -0
- package/dist/event.d.ts +47 -0
- package/dist/event.d.ts.map +1 -0
- package/dist/event.js +64 -0
- package/dist/event.js.map +1 -0
- package/dist/features.d.ts +55 -0
- package/dist/features.d.ts.map +1 -0
- package/dist/features.js +126 -0
- package/dist/features.js.map +1 -0
- package/dist/fields.d.ts +31 -0
- package/dist/fields.d.ts.map +1 -0
- package/dist/fields.js +105 -0
- package/dist/fields.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/json.d.ts +47 -0
- package/dist/json.d.ts.map +1 -0
- package/dist/json.js +458 -0
- package/dist/json.js.map +1 -0
- package/dist/memory/index.d.ts +2 -0
- package/dist/memory/index.d.ts.map +1 -0
- package/dist/memory/index.js +3 -0
- package/dist/memory/index.js.map +1 -0
- package/dist/memory/repository.d.ts +70 -0
- package/dist/memory/repository.d.ts.map +1 -0
- package/dist/memory/repository.js +308 -0
- package/dist/memory/repository.js.map +1 -0
- package/dist/metadata.d.ts +47 -0
- package/dist/metadata.d.ts.map +1 -0
- package/dist/metadata.js +75 -0
- package/dist/metadata.js.map +1 -0
- package/dist/repository.d.ts +131 -0
- package/dist/repository.d.ts.map +1 -0
- package/dist/repository.js +130 -0
- package/dist/repository.js.map +1 -0
- package/dist/retry.d.ts +25 -0
- package/dist/retry.d.ts.map +1 -0
- package/dist/retry.js +50 -0
- package/dist/retry.js.map +1 -0
- package/dist/snapshots.d.ts +21 -0
- package/dist/snapshots.d.ts.map +1 -0
- package/dist/snapshots.js +35 -0
- package/dist/snapshots.js.map +1 -0
- package/dist/store.d.ts +103 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +246 -0
- package/dist/store.js.map +1 -0
- package/dist/testing/equal.d.ts +22 -0
- package/dist/testing/equal.d.ts.map +1 -0
- package/dist/testing/equal.js +121 -0
- package/dist/testing/equal.js.map +1 -0
- package/dist/testing/index.d.ts +3 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +5 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/scenario.d.ts +136 -0
- package/dist/testing/scenario.d.ts.map +1 -0
- package/dist/testing/scenario.js +307 -0
- package/dist/testing/scenario.js.map +1 -0
- package/dist/utf8.d.ts +17 -0
- package/dist/utf8.d.ts.map +1 -0
- package/dist/utf8.js +82 -0
- package/dist/utf8.js.map +1 -0
- package/package.json +58 -2
- package/src/aggregate.ts +196 -0
- package/src/base64.ts +80 -0
- package/src/codec.ts +139 -0
- package/src/commit-id.ts +50 -0
- package/src/dynamodb/client.ts +102 -0
- package/src/dynamodb/head.ts +93 -0
- package/src/dynamodb/index.ts +45 -0
- package/src/dynamodb/item.ts +334 -0
- package/src/dynamodb/marker.ts +64 -0
- package/src/dynamodb/repository.ts +1030 -0
- package/src/dynamodb/requests.ts +256 -0
- package/src/envelope.ts +67 -0
- package/src/errors.ts +365 -0
- package/src/event.ts +117 -0
- package/src/features.ts +175 -0
- package/src/fields.ts +134 -0
- package/src/globals.d.ts +39 -0
- package/src/index.ts +98 -0
- package/src/json.ts +546 -0
- package/src/memory/index.ts +11 -0
- package/src/memory/repository.ts +463 -0
- package/src/metadata.ts +120 -0
- package/src/repository.ts +275 -0
- package/src/retry.ts +74 -0
- package/src/snapshots.ts +42 -0
- package/src/store.ts +377 -0
- package/src/testing/equal.ts +146 -0
- package/src/testing/index.ts +14 -0
- package/src/testing/scenario.ts +406 -0
- package/src/utf8.ts +92 -0
package/dist/errors.js
ADDED
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
// Every failure evt throws is an EvtError with a code, as the Rust crate returns its Error enum.
|
|
2
|
+
// Domain outcomes (a rejected command, a duplicate) are values, never errors. A failure with
|
|
3
|
+
// details has its own subclass, so `instanceof` narrows to its fields.
|
|
4
|
+
export class EvtError extends Error {
|
|
5
|
+
name = 'EvtError';
|
|
6
|
+
code;
|
|
7
|
+
constructor(code, message, options) {
|
|
8
|
+
super(message, options);
|
|
9
|
+
this.code = code;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
/** Optimistic concurrency failed on a written stream: its sequence or snapshot moved. */
|
|
13
|
+
export class ConflictError extends EvtError {
|
|
14
|
+
name = 'ConflictError';
|
|
15
|
+
code = 'conflict';
|
|
16
|
+
entityId;
|
|
17
|
+
constructor(entityId, detail) {
|
|
18
|
+
super('conflict', `conflict on entity ${entityId}: ${detail}`);
|
|
19
|
+
this.entityId = entityId;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
/** A commit's first event skips past the stream's head, or a load found a hole. A conflict. */
|
|
23
|
+
export class SequenceGapError extends EvtError {
|
|
24
|
+
name = 'SequenceGapError';
|
|
25
|
+
code = 'sequenceGap';
|
|
26
|
+
entityId;
|
|
27
|
+
/** The last sequence before the gap. */
|
|
28
|
+
after;
|
|
29
|
+
/** The sequence found next, which isn't `after + 1`. */
|
|
30
|
+
found;
|
|
31
|
+
constructor(entityId, after, found) {
|
|
32
|
+
super('sequenceGap', `conflict on entity ${entityId}: the stream skips from sequence ${after} to ${found}: it ` +
|
|
33
|
+
'was compacted during the load, or events expired');
|
|
34
|
+
this.entityId = entityId;
|
|
35
|
+
this.after = after;
|
|
36
|
+
this.found = found;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* A stream's head disagrees with its events or snapshot (ADR 0007): a writer appended without
|
|
41
|
+
* raising the head, events were deleted, a snapshot is ahead of the head, or a stream has data and
|
|
42
|
+
* no head. It isn't retryable: running the command again fails the same way. Repair is offline.
|
|
43
|
+
*/
|
|
44
|
+
export class StreamHeadDriftError extends EvtError {
|
|
45
|
+
name = 'StreamHeadDriftError';
|
|
46
|
+
code = 'streamHeadDrift';
|
|
47
|
+
entityId;
|
|
48
|
+
/** The stored head, or null when the stream has no head. */
|
|
49
|
+
stored;
|
|
50
|
+
/** The head its events and snapshot imply: the higher of the two. */
|
|
51
|
+
derived;
|
|
52
|
+
constructor(entityId, stored, derived) {
|
|
53
|
+
super('streamHeadDrift', `stream head drift on entity ${entityId}: stored head ${stored ?? 'absent'}, ` +
|
|
54
|
+
`derived head ${derived}`);
|
|
55
|
+
this.entityId = entityId;
|
|
56
|
+
this.stored = stored;
|
|
57
|
+
this.derived = derived;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/** The commit is over the transaction budget: too many actions, bytes, or bytes in one item. */
|
|
61
|
+
export class CommitTooLargeError extends EvtError {
|
|
62
|
+
name = 'CommitTooLargeError';
|
|
63
|
+
code = 'commitTooLarge';
|
|
64
|
+
actions;
|
|
65
|
+
bytes;
|
|
66
|
+
largestItem;
|
|
67
|
+
constructor(actions, bytes, largestItem) {
|
|
68
|
+
super('commitTooLarge', `commit exceeds transaction budget: ${actions} actions, ${bytes} bytes, ` +
|
|
69
|
+
`largest item ${largestItem}`);
|
|
70
|
+
this.actions = actions;
|
|
71
|
+
this.bytes = bytes;
|
|
72
|
+
this.largestItem = largestItem;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/** Compaction was refused because no snapshot covers the events it would delete. */
|
|
76
|
+
export class CompactionUncoveredError extends EvtError {
|
|
77
|
+
name = 'CompactionUncoveredError';
|
|
78
|
+
code = 'compactionUncovered';
|
|
79
|
+
entityId;
|
|
80
|
+
through;
|
|
81
|
+
/** The event sequence the stored snapshot covers, or null with no snapshot. */
|
|
82
|
+
covered;
|
|
83
|
+
constructor(entityId, through, covered) {
|
|
84
|
+
super('compactionUncovered', 'compaction refused: no durable snapshot covers the requested range ' +
|
|
85
|
+
`(entity ${entityId}, through ${through}, snapshot covers ${covered ?? 'nothing'})`);
|
|
86
|
+
this.entityId = entityId;
|
|
87
|
+
this.through = through;
|
|
88
|
+
this.covered = covered;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/** A write to an entity ID in a reserved namespace (`SYSTEM#`, `command-outcome#`). */
|
|
92
|
+
export class ReservedEntityIdError extends EvtError {
|
|
93
|
+
name = 'ReservedEntityIdError';
|
|
94
|
+
code = 'reservedEntityId';
|
|
95
|
+
entityId;
|
|
96
|
+
constructor(entityId) {
|
|
97
|
+
super('reservedEntityId', `entity ID ${entityId} is in a reserved namespace (SYSTEM#, command-outcome#)`);
|
|
98
|
+
this.entityId = entityId;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* The store's feature manifest declares pairs this package doesn't model, so it refuses to write:
|
|
103
|
+
* a commit, a snapshot write, compaction or initialization. Nothing was written.
|
|
104
|
+
*/
|
|
105
|
+
export class UnsupportedFeatureError extends EvtError {
|
|
106
|
+
name = 'UnsupportedFeatureError';
|
|
107
|
+
code = 'unsupportedFeature';
|
|
108
|
+
/** Every unsupported pair, sorted by name. */
|
|
109
|
+
unsupported;
|
|
110
|
+
constructor(unsupported) {
|
|
111
|
+
const pairs = unsupported.map((pair) => `${pair.name}@${pair.version}`).join(', ');
|
|
112
|
+
super('unsupportedFeature', `store declares unsupported features (${pairs}); refusing to write`);
|
|
113
|
+
this.unsupported = unsupported;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* The store holds data but its feature manifest doesn't declare stream-heads: its streams may have
|
|
118
|
+
* no head items, so a head-aware write could fail every stream. Migrate the store with every older
|
|
119
|
+
* writer stopped. Nothing was written.
|
|
120
|
+
*/
|
|
121
|
+
export class StreamHeadsNotMigratedError extends EvtError {
|
|
122
|
+
name = 'StreamHeadsNotMigratedError';
|
|
123
|
+
code = 'streamHeadsNotMigrated';
|
|
124
|
+
constructor() {
|
|
125
|
+
super('streamHeadsNotMigrated', 'store does not declare the stream-heads feature and holds data without per-stream head ' +
|
|
126
|
+
'items; migrate it before writing');
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* The store's feature manifest doesn't declare stream-heads, and this writer doesn't initialize a
|
|
131
|
+
* store itself (the DynamoDB default), so it refuses rather than scan the table to learn whether
|
|
132
|
+
* it's fresh. Initialize a fresh store once, at deploy time, or migrate one written before stream
|
|
133
|
+
* heads. Nothing was written.
|
|
134
|
+
*/
|
|
135
|
+
export class StoreNotInitializedError extends EvtError {
|
|
136
|
+
name = 'StoreNotInitializedError';
|
|
137
|
+
code = 'storeNotInitialized';
|
|
138
|
+
constructor() {
|
|
139
|
+
super('storeNotInitialized', 'store is not initialized: the feature manifest does not declare stream-heads; initialize ' +
|
|
140
|
+
'a fresh store, or migrate one written before stream heads, before writing');
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Another writer changed the store's feature manifest after this one validated it, so the commit's
|
|
145
|
+
* marker check failed. The writer has validated the new manifest, which it supports. Retryable.
|
|
146
|
+
* Nothing was written.
|
|
147
|
+
*/
|
|
148
|
+
export class FeatureManifestChangedError extends EvtError {
|
|
149
|
+
name = 'FeatureManifestChangedError';
|
|
150
|
+
code = 'featureManifestChanged';
|
|
151
|
+
constructor(options) {
|
|
152
|
+
super('featureManifestChanged', 'feature manifest changed under this writer', options);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* The backend refused the write for now, such as a DynamoDB transaction cancelled for throttling.
|
|
157
|
+
* Retryable, after a backoff. Nothing was written. The backend's error is its cause.
|
|
158
|
+
*/
|
|
159
|
+
export class TransientError extends EvtError {
|
|
160
|
+
name = 'TransientError';
|
|
161
|
+
code = 'transient';
|
|
162
|
+
constructor(detail, options) {
|
|
163
|
+
super('transient', `transient failure: ${detail}`, options);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* A projection rebuild holds the store, or one was force-released and no rebuild has finished
|
|
168
|
+
* since, so every commit is refused. Retryable: the command can run again once the rebuild ends.
|
|
169
|
+
*/
|
|
170
|
+
export class RebuildInProgressError extends EvtError {
|
|
171
|
+
name = 'RebuildInProgressError';
|
|
172
|
+
code = 'rebuildInProgress';
|
|
173
|
+
constructor() {
|
|
174
|
+
super('rebuildInProgress', 'a projection rebuild is in progress');
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Compaction was refused because the store declares the entity's type history-dependent: its
|
|
179
|
+
* projectors' rebuild replays the events compaction would delete. Nothing was deleted.
|
|
180
|
+
*/
|
|
181
|
+
export class HistoryDependentProjectionError extends EvtError {
|
|
182
|
+
name = 'HistoryDependentProjectionError';
|
|
183
|
+
code = 'historyDependentProjection';
|
|
184
|
+
entityType;
|
|
185
|
+
entityId;
|
|
186
|
+
constructor(entityType, entityId) {
|
|
187
|
+
super('historyDependentProjection', `entity type ${entityType} is declared history-dependent; compaction would delete the ` +
|
|
188
|
+
`commits its rebuild replays (entity ${entityId})`);
|
|
189
|
+
this.entityType = entityType;
|
|
190
|
+
this.entityId = entityId;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
/** A load failed closed on a stored event: an upcaster threw, or the payload didn't decode. */
|
|
194
|
+
export class ReplayError extends EvtError {
|
|
195
|
+
name = 'ReplayError';
|
|
196
|
+
code = 'replay';
|
|
197
|
+
eventType;
|
|
198
|
+
/** The stored version, or the version an earlier upcaster produced. */
|
|
199
|
+
version;
|
|
200
|
+
phase;
|
|
201
|
+
constructor(eventType, version, phase, detail, cause) {
|
|
202
|
+
const doing = phase === 'upcast' ? 'upcasting' : 'decoding';
|
|
203
|
+
super('replay', `replay failed while ${doing} ${eventType} v${version}: ${detail}`, { cause });
|
|
204
|
+
this.eventType = eventType;
|
|
205
|
+
this.version = version;
|
|
206
|
+
this.phase = phase;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
/** A load found a stored snapshot whose payload the aggregate's state codec doesn't decode. */
|
|
210
|
+
export class SnapshotError extends EvtError {
|
|
211
|
+
name = 'SnapshotError';
|
|
212
|
+
code = 'snapshot';
|
|
213
|
+
entityId;
|
|
214
|
+
constructor(entityId, cause) {
|
|
215
|
+
super('snapshot', `decoding snapshot for entity ${entityId}: ${messageOf(cause)}`, { cause });
|
|
216
|
+
this.entityId = entityId;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
/** Whether an error is an optimistic-concurrency conflict: a `conflict` or a `sequenceGap`. */
|
|
220
|
+
export function isConflict(error) {
|
|
221
|
+
return error instanceof EvtError && (error.code === 'conflict' || error.code === 'sequenceGap');
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Whether reloading and running the command again may succeed: after a conflict, while a rebuild
|
|
225
|
+
* holds the store, after the feature manifest changed under the writer, or after throttling.
|
|
226
|
+
*/
|
|
227
|
+
export function isRetryable(error) {
|
|
228
|
+
if (isConflict(error)) {
|
|
229
|
+
return true;
|
|
230
|
+
}
|
|
231
|
+
return (error instanceof EvtError &&
|
|
232
|
+
(error.code === 'rebuildInProgress' ||
|
|
233
|
+
error.code === 'featureManifestChanged' ||
|
|
234
|
+
error.code === 'transient'));
|
|
235
|
+
}
|
|
236
|
+
/** An error's message, or the value itself as text. */
|
|
237
|
+
export function messageOf(error) {
|
|
238
|
+
return error instanceof Error ? error.message : String(error);
|
|
239
|
+
}
|
|
240
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,iGAAiG;AACjG,6FAA6F;AAC7F,uEAAuE;AAsDvE,MAAM,OAAO,QAAS,SAAQ,KAAK;IACf,IAAI,GAAW,UAAU,CAAA;IAClC,IAAI,CAAc;IAE3B,YAAY,IAAkB,EAAE,OAAe,EAAE,OAA2B;QAC1E,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;QACvB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;IAClB,CAAC;CACF;AAED,yFAAyF;AACzF,MAAM,OAAO,aAAc,SAAQ,QAAQ;IACvB,IAAI,GAAG,eAAe,CAAA;IACtB,IAAI,GAAG,UAAU,CAAA;IAC1B,QAAQ,CAAQ;IAEzB,YAAY,QAAgB,EAAE,MAAc;QAC1C,KAAK,CAAC,UAAU,EAAE,sBAAsB,QAAQ,KAAK,MAAM,EAAE,CAAC,CAAA;QAC9D,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAA;IAC1B,CAAC;CACF;AAED,+FAA+F;AAC/F,MAAM,OAAO,gBAAiB,SAAQ,QAAQ;IAC1B,IAAI,GAAG,kBAAkB,CAAA;IACzB,IAAI,GAAG,aAAa,CAAA;IAC7B,QAAQ,CAAQ;IACzB,wCAAwC;IAC/B,KAAK,CAAQ;IACtB,wDAAwD;IAC/C,KAAK,CAAQ;IAEtB,YAAY,QAAgB,EAAE,KAAa,EAAE,KAAa;QACxD,KAAK,CACH,aAAa,EACb,sBAAsB,QAAQ,oCAAoC,KAAK,OAAO,KAAK,OAAO;YACxF,kDAAkD,CACrD,CAAA;QACD,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAA;QACxB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAA;QAClB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAA;IACpB,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,OAAO,oBAAqB,SAAQ,QAAQ;IAC9B,IAAI,GAAG,sBAAsB,CAAA;IAC7B,IAAI,GAAG,iBAAiB,CAAA;IACjC,QAAQ,CAAQ;IACzB,4DAA4D;IACnD,MAAM,CAAe;IAC9B,qEAAqE;IAC5D,OAAO,CAAQ;IAExB,YAAY,QAAgB,EAAE,MAAqB,EAAE,OAAe;QAClE,KAAK,CACH,iBAAiB,EACjB,+BAA+B,QAAQ,iBAAiB,MAAM,IAAI,QAAQ,IAAI;YAC5E,gBAAgB,OAAO,EAAE,CAC5B,CAAA;QACD,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAA;QACxB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;QACpB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;IACxB,CAAC;CACF;AAED,gGAAgG;AAChG,MAAM,OAAO,mBAAoB,SAAQ,QAAQ;IAC7B,IAAI,GAAG,qBAAqB,CAAA;IAC5B,IAAI,GAAG,gBAAgB,CAAA;IAChC,OAAO,CAAQ;IACf,KAAK,CAAQ;IACb,WAAW,CAAQ;IAE5B,YAAY,OAAe,EAAE,KAAa,EAAE,WAAmB;QAC7D,KAAK,CACH,gBAAgB,EAChB,sCAAsC,OAAO,aAAa,KAAK,UAAU;YACvE,gBAAgB,WAAW,EAAE,CAChC,CAAA;QACD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;QACtB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAA;QAClB,IAAI,CAAC,WAAW,GAAG,WAAW,CAAA;IAChC,CAAC;CACF;AAED,oFAAoF;AACpF,MAAM,OAAO,wBAAyB,SAAQ,QAAQ;IAClC,IAAI,GAAG,0BAA0B,CAAA;IACjC,IAAI,GAAG,qBAAqB,CAAA;IACrC,QAAQ,CAAQ;IAChB,OAAO,CAAQ;IACxB,+EAA+E;IACtE,OAAO,CAAe;IAE/B,YAAY,QAAgB,EAAE,OAAe,EAAE,OAAsB;QACnE,KAAK,CACH,qBAAqB,EACrB,qEAAqE;YACnE,WAAW,QAAQ,aAAa,OAAO,qBAAqB,OAAO,IAAI,SAAS,GAAG,CACtF,CAAA;QACD,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAA;QACxB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;QACtB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;IACxB,CAAC;CACF;AAED,uFAAuF;AACvF,MAAM,OAAO,qBAAsB,SAAQ,QAAQ;IAC/B,IAAI,GAAG,uBAAuB,CAAA;IAC9B,IAAI,GAAG,kBAAkB,CAAA;IAClC,QAAQ,CAAQ;IAEzB,YAAY,QAAgB;QAC1B,KAAK,CACH,kBAAkB,EAClB,aAAa,QAAQ,yDAAyD,CAC/E,CAAA;QACD,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAA;IAC1B,CAAC;CACF;AAQD;;;GAGG;AACH,MAAM,OAAO,uBAAwB,SAAQ,QAAQ;IACjC,IAAI,GAAG,yBAAyB,CAAA;IAChC,IAAI,GAAG,oBAAoB,CAAA;IAC7C,8CAA8C;IACrC,WAAW,CAAwB;IAE5C,YAAY,WAAmC;QAC7C,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAClF,KAAK,CAAC,oBAAoB,EAAE,wCAAwC,KAAK,sBAAsB,CAAC,CAAA;QAChG,IAAI,CAAC,WAAW,GAAG,WAAW,CAAA;IAChC,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,OAAO,2BAA4B,SAAQ,QAAQ;IACrC,IAAI,GAAG,6BAA6B,CAAA;IACpC,IAAI,GAAG,wBAAwB,CAAA;IAEjD;QACE,KAAK,CACH,wBAAwB,EACxB,yFAAyF;YACvF,kCAAkC,CACrC,CAAA;IACH,CAAC;CACF;AAED;;;;;GAKG;AACH,MAAM,OAAO,wBAAyB,SAAQ,QAAQ;IAClC,IAAI,GAAG,0BAA0B,CAAA;IACjC,IAAI,GAAG,qBAAqB,CAAA;IAE9C;QACE,KAAK,CACH,qBAAqB,EACrB,2FAA2F;YACzF,2EAA2E,CAC9E,CAAA;IACH,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,OAAO,2BAA4B,SAAQ,QAAQ;IACrC,IAAI,GAAG,6BAA6B,CAAA;IACpC,IAAI,GAAG,wBAAwB,CAAA;IAEjD,YAAY,OAA2B;QACrC,KAAK,CAAC,wBAAwB,EAAE,4CAA4C,EAAE,OAAO,CAAC,CAAA;IACxF,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,OAAO,cAAe,SAAQ,QAAQ;IACxB,IAAI,GAAG,gBAAgB,CAAA;IACvB,IAAI,GAAG,WAAW,CAAA;IAEpC,YAAY,MAAc,EAAE,OAA2B;QACrD,KAAK,CAAC,WAAW,EAAE,sBAAsB,MAAM,EAAE,EAAE,OAAO,CAAC,CAAA;IAC7D,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,OAAO,sBAAuB,SAAQ,QAAQ;IAChC,IAAI,GAAG,wBAAwB,CAAA;IAC/B,IAAI,GAAG,mBAAmB,CAAA;IAE5C;QACE,KAAK,CAAC,mBAAmB,EAAE,qCAAqC,CAAC,CAAA;IACnE,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,OAAO,+BAAgC,SAAQ,QAAQ;IACzC,IAAI,GAAG,iCAAiC,CAAA;IACxC,IAAI,GAAG,4BAA4B,CAAA;IAC5C,UAAU,CAAQ;IAClB,QAAQ,CAAQ;IAEzB,YAAY,UAAkB,EAAE,QAAgB;QAC9C,KAAK,CACH,4BAA4B,EAC5B,eAAe,UAAU,8DAA8D;YACrF,uCAAuC,QAAQ,GAAG,CACrD,CAAA;QACD,IAAI,CAAC,UAAU,GAAG,UAAU,CAAA;QAC5B,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAA;IAC1B,CAAC;CACF;AAED,+FAA+F;AAC/F,MAAM,OAAO,WAAY,SAAQ,QAAQ;IACrB,IAAI,GAAG,aAAa,CAAA;IACpB,IAAI,GAAG,QAAQ,CAAA;IACxB,SAAS,CAAQ;IAC1B,uEAAuE;IAC9D,OAAO,CAAQ;IACf,KAAK,CAAqB;IAEnC,YACE,SAAiB,EACjB,OAAe,EACf,KAA0B,EAC1B,MAAc,EACd,KAAe;QAEf,MAAM,KAAK,GAAG,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,UAAU,CAAA;QAC3D,KAAK,CAAC,QAAQ,EAAE,uBAAuB,KAAK,IAAI,SAAS,KAAK,OAAO,KAAK,MAAM,EAAE,EAAE,EAAC,KAAK,EAAC,CAAC,CAAA;QAC5F,IAAI,CAAC,SAAS,GAAG,SAAS,CAAA;QAC1B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;QACtB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAA;IACpB,CAAC;CACF;AAED,+FAA+F;AAC/F,MAAM,OAAO,aAAc,SAAQ,QAAQ;IACvB,IAAI,GAAG,eAAe,CAAA;IACtB,IAAI,GAAG,UAAU,CAAA;IAC1B,QAAQ,CAAQ;IAEzB,YAAY,QAAgB,EAAE,KAAc;QAC1C,KAAK,CAAC,UAAU,EAAE,gCAAgC,QAAQ,KAAK,SAAS,CAAC,KAAK,CAAC,EAAE,EAAE,EAAC,KAAK,EAAC,CAAC,CAAA;QAC3F,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAA;IAC1B,CAAC;CACF;AAED,+FAA+F;AAC/F,MAAM,UAAU,UAAU,CAAC,KAAc;IACvC,OAAO,KAAK,YAAY,QAAQ,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,UAAU,IAAI,KAAK,CAAC,IAAI,KAAK,aAAa,CAAC,CAAA;AACjG,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,KAAc;IACxC,IAAI,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QACtB,OAAO,IAAI,CAAA;IACb,CAAC;IAED,OAAO,CACL,KAAK,YAAY,QAAQ;QACzB,CAAC,KAAK,CAAC,IAAI,KAAK,mBAAmB;YACjC,KAAK,CAAC,IAAI,KAAK,wBAAwB;YACvC,KAAK,CAAC,IAAI,KAAK,WAAW,CAAC,CAC9B,CAAA;AACH,CAAC;AAED,uDAAuD;AACvD,MAAM,UAAU,SAAS,CAAC,KAAc;IACtC,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;AAC/D,CAAC"}
|
package/dist/event.d.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { type JsonObject } from './fields.js';
|
|
2
|
+
import { type Metadata } from './metadata.js';
|
|
3
|
+
/** An event as it is stored. Its JSON is the `detail` of a stream envelope. */
|
|
4
|
+
export interface SerializedEvent {
|
|
5
|
+
/** `{entityId}:{sequence}`. */
|
|
6
|
+
id: string;
|
|
7
|
+
/** The 1-based position of the event in its stream. */
|
|
8
|
+
sequence: bigint;
|
|
9
|
+
/** The event kind, such as `account:opened`. */
|
|
10
|
+
type: string;
|
|
11
|
+
/** The payload's schema version. */
|
|
12
|
+
version: number;
|
|
13
|
+
/** The stream the event belongs to. */
|
|
14
|
+
entityId: string;
|
|
15
|
+
/** The aggregate type of the entity. */
|
|
16
|
+
entityType: string;
|
|
17
|
+
/**
|
|
18
|
+
* The payload bytes, stored verbatim. Null only when decoded from a JSON `null`, which is
|
|
19
|
+
* written back as `null`, as Go does.
|
|
20
|
+
*/
|
|
21
|
+
payload: Uint8Array | null;
|
|
22
|
+
metadata: Metadata;
|
|
23
|
+
}
|
|
24
|
+
/** A snapshot of aggregate state. A stream keeps at most one, its latest. */
|
|
25
|
+
export interface SerializedSnapshot {
|
|
26
|
+
entityType: string;
|
|
27
|
+
entityId: string;
|
|
28
|
+
/** 1 for an entity's first snapshot, then one more for each. */
|
|
29
|
+
sequence: bigint;
|
|
30
|
+
/** The last event sequence folded into the snapshot. */
|
|
31
|
+
eventSequence: bigint;
|
|
32
|
+
/** The state's bytes, stored verbatim. Null only when decoded from a JSON `null`. */
|
|
33
|
+
payload: Uint8Array | null;
|
|
34
|
+
}
|
|
35
|
+
/** The event ID for a sequence of a stream: `{entityId}:{sequence}`. */
|
|
36
|
+
export declare function eventId(entityId: string, sequence: bigint): string;
|
|
37
|
+
/** Encodes an event as the JSON Go writes for it. */
|
|
38
|
+
export declare function encodeEvent(event: SerializedEvent): string;
|
|
39
|
+
/** Decodes an event's JSON leniently, as Go does. */
|
|
40
|
+
export declare function decodeEvent(json: string): SerializedEvent;
|
|
41
|
+
/** Encodes a snapshot as the JSON Go writes for it. Its entity ID key is `entityID`. */
|
|
42
|
+
export declare function encodeSnapshot(snapshot: SerializedSnapshot): string;
|
|
43
|
+
/** Decodes a snapshot's JSON leniently, as Go does. */
|
|
44
|
+
export declare function decodeSnapshot(json: string): SerializedSnapshot;
|
|
45
|
+
export declare function eventJson(event: SerializedEvent): object;
|
|
46
|
+
export declare function eventFromJson(value: JsonObject | null): SerializedEvent;
|
|
47
|
+
//# sourceMappingURL=event.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event.d.ts","sourceRoot":"","sources":["../src/event.ts"],"names":[],"mappings":"AAGA,OAAO,EASL,KAAK,UAAU,EAChB,MAAM,aAAa,CAAA;AAEpB,OAAO,EAAC,KAAK,QAAQ,EAAiC,MAAM,eAAe,CAAA;AAE3E,+EAA+E;AAC/E,MAAM,WAAW,eAAe;IAC9B,+BAA+B;IAC/B,EAAE,EAAE,MAAM,CAAA;IACV,uDAAuD;IACvD,QAAQ,EAAE,MAAM,CAAA;IAChB,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAA;IACZ,oCAAoC;IACpC,OAAO,EAAE,MAAM,CAAA;IACf,uCAAuC;IACvC,QAAQ,EAAE,MAAM,CAAA;IAChB,wCAAwC;IACxC,UAAU,EAAE,MAAM,CAAA;IAClB;;;OAGG;IACH,OAAO,EAAE,UAAU,GAAG,IAAI,CAAA;IAC1B,QAAQ,EAAE,QAAQ,CAAA;CACnB;AAED,6EAA6E;AAC7E,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,gEAAgE;IAChE,QAAQ,EAAE,MAAM,CAAA;IAChB,wDAAwD;IACxD,aAAa,EAAE,MAAM,CAAA;IACrB,qFAAqF;IACrF,OAAO,EAAE,UAAU,GAAG,IAAI,CAAA;CAC3B;AAED,wEAAwE;AACxE,wBAAgB,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAElE;AAED,qDAAqD;AACrD,wBAAgB,WAAW,CAAC,KAAK,EAAE,eAAe,GAAG,MAAM,CAE1D;AAED,qDAAqD;AACrD,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,CAEzD;AAED,wFAAwF;AACxF,wBAAgB,cAAc,CAAC,QAAQ,EAAE,kBAAkB,GAAG,MAAM,CAQnE;AAED,uDAAuD;AACvD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,CAU/D;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,eAAe,GAAG,MAAM,CAWxD;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,GAAG,eAAe,CAavE"}
|
package/dist/event.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// Serialized events and snapshots: the stored form every repository reads and writes, and their
|
|
2
|
+
// JSON encodings, which match Go's evt.SerializedEvent and evt.SerializedSnapshot.
|
|
3
|
+
import { DOCUMENT, bytesField, int64Argument, int64Field, objectOrNull, safeIntegerArgument, safeIntegerField, stringField, } from './fields.js';
|
|
4
|
+
import { parseJson, stringifyJson } from './json.js';
|
|
5
|
+
import { metadataFromJson, metadataJson } from './metadata.js';
|
|
6
|
+
/** The event ID for a sequence of a stream: `{entityId}:{sequence}`. */
|
|
7
|
+
export function eventId(entityId, sequence) {
|
|
8
|
+
return `${entityId}:${sequence}`;
|
|
9
|
+
}
|
|
10
|
+
/** Encodes an event as the JSON Go writes for it. */
|
|
11
|
+
export function encodeEvent(event) {
|
|
12
|
+
return stringifyJson(eventJson(event));
|
|
13
|
+
}
|
|
14
|
+
/** Decodes an event's JSON leniently, as Go does. */
|
|
15
|
+
export function decodeEvent(json) {
|
|
16
|
+
return eventFromJson(objectOrNull(parseJson(json, DOCUMENT), 'event'));
|
|
17
|
+
}
|
|
18
|
+
/** Encodes a snapshot as the JSON Go writes for it. Its entity ID key is `entityID`. */
|
|
19
|
+
export function encodeSnapshot(snapshot) {
|
|
20
|
+
return stringifyJson({
|
|
21
|
+
entityType: snapshot.entityType,
|
|
22
|
+
entityID: snapshot.entityId,
|
|
23
|
+
sequence: int64Argument(snapshot.sequence, 'snapshot.sequence'),
|
|
24
|
+
eventSequence: int64Argument(snapshot.eventSequence, 'snapshot.eventSequence'),
|
|
25
|
+
payload: snapshot.payload,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
/** Decodes a snapshot's JSON leniently, as Go does. */
|
|
29
|
+
export function decodeSnapshot(json) {
|
|
30
|
+
const object = objectOrNull(parseJson(json, DOCUMENT), 'snapshot') ?? new Map();
|
|
31
|
+
return {
|
|
32
|
+
entityType: stringField(object, 'entityType', 'snapshot'),
|
|
33
|
+
entityId: stringField(object, 'entityID', 'snapshot'),
|
|
34
|
+
sequence: int64Field(object, 'sequence', 'snapshot'),
|
|
35
|
+
eventSequence: int64Field(object, 'eventSequence', 'snapshot'),
|
|
36
|
+
payload: bytesField(object, 'payload', 'snapshot'),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
export function eventJson(event) {
|
|
40
|
+
return {
|
|
41
|
+
id: event.id,
|
|
42
|
+
sequence: int64Argument(event.sequence, 'event.sequence'),
|
|
43
|
+
type: event.type,
|
|
44
|
+
version: safeIntegerArgument(event.version, 'event.version'),
|
|
45
|
+
entityId: event.entityId,
|
|
46
|
+
entityType: event.entityType,
|
|
47
|
+
payload: event.payload,
|
|
48
|
+
metadata: metadataJson(event.metadata),
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
export function eventFromJson(value) {
|
|
52
|
+
const object = value ?? new Map();
|
|
53
|
+
return {
|
|
54
|
+
id: stringField(object, 'id', 'event'),
|
|
55
|
+
sequence: int64Field(object, 'sequence', 'event'),
|
|
56
|
+
type: stringField(object, 'type', 'event'),
|
|
57
|
+
version: safeIntegerField(object, 'version', 'event'),
|
|
58
|
+
entityId: stringField(object, 'entityId', 'event'),
|
|
59
|
+
entityType: stringField(object, 'entityType', 'event'),
|
|
60
|
+
payload: bytesField(object, 'payload', 'event'),
|
|
61
|
+
metadata: metadataFromJson(object.get('metadata')),
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=event.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event.js","sourceRoot":"","sources":["../src/event.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { type FeaturePair } from './errors.js';
|
|
2
|
+
/** The feature every writer models and requires: per-stream head items (ADR 0007). */
|
|
3
|
+
export declare const STREAM_HEADS_FEATURE = "stream-heads";
|
|
4
|
+
/** The stored-format version of {@link STREAM_HEADS_FEATURE} this package reads and writes. */
|
|
5
|
+
export declare const STREAM_HEADS_VERSION = 1;
|
|
6
|
+
/**
|
|
7
|
+
* The `(feature, stored-format version)` pairs this package models. The other features the
|
|
8
|
+
* storage format defines (`journal`, `journal-compaction`, `postgres-views`) are Rust-first, so a
|
|
9
|
+
* store that declares any of them is refused.
|
|
10
|
+
*/
|
|
11
|
+
export declare const SUPPORTED_FEATURES: readonly FeaturePair[];
|
|
12
|
+
/** The parsed marker row. A store with no marker row has no manifest. */
|
|
13
|
+
export interface FeatureManifest {
|
|
14
|
+
/** Bumped by exactly one on every declaration. */
|
|
15
|
+
readonly version: bigint;
|
|
16
|
+
/** Each declared feature's stored-format version. */
|
|
17
|
+
readonly features: ReadonlyMap<string, number>;
|
|
18
|
+
/** The entity types whose commit-wide projectors are history-dependent: never compacted. */
|
|
19
|
+
readonly historyDependent: readonly string[];
|
|
20
|
+
/** The entity types configured with retention: never fenced. */
|
|
21
|
+
readonly retention: readonly string[];
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Refuses a manifest that declares a pair this package doesn't model, listing every such pair,
|
|
25
|
+
* with an {@link UnsupportedFeatureError}.
|
|
26
|
+
*/
|
|
27
|
+
export declare function checkSupported(manifest: FeatureManifest | null): void;
|
|
28
|
+
/** Whether the manifest declares stream-heads at the version this package models. */
|
|
29
|
+
export declare function declaresStreamHeads(manifest: FeatureManifest | null): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Refuses a write to a store whose manifest declares an unsupported pair, or doesn't declare
|
|
32
|
+
* stream-heads, without declaring anything.
|
|
33
|
+
*/
|
|
34
|
+
export declare function checkWritable(manifest: FeatureManifest | null): void;
|
|
35
|
+
/** The manifest with stream-heads declared and its version bumped: a first writer's declaration. */
|
|
36
|
+
export declare function withStreamHeads(manifest: FeatureManifest | null): FeatureManifest;
|
|
37
|
+
/** A manifest's stored JSON texts, as the marker row holds them. */
|
|
38
|
+
export interface ManifestTexts {
|
|
39
|
+
/** A JSON object, feature name to stored-format version, keys sorted. `{}` when empty. */
|
|
40
|
+
features: string;
|
|
41
|
+
/** A JSON array of entity types, sorted by UTF-8 bytes and deduplicated. `[]` when empty. */
|
|
42
|
+
historyDependent: string;
|
|
43
|
+
/** Like `historyDependent`. */
|
|
44
|
+
retention: string;
|
|
45
|
+
}
|
|
46
|
+
/** Encodes a manifest's declarable parts as the marker row stores them. */
|
|
47
|
+
export declare function encodeManifest(manifest: FeatureManifest): ManifestTexts;
|
|
48
|
+
/**
|
|
49
|
+
* Decodes a marker row's stored texts. An empty text is an empty map or set, as an absent
|
|
50
|
+
* attribute is.
|
|
51
|
+
*/
|
|
52
|
+
export declare function decodeManifest(version: bigint, texts: ManifestTexts): FeatureManifest;
|
|
53
|
+
/** An entity-type set in its stored order: sorted by UTF-8 bytes and deduplicated. */
|
|
54
|
+
export declare function entityTypeSet(types: readonly string[]): string[];
|
|
55
|
+
//# sourceMappingURL=features.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"features.d.ts","sourceRoot":"","sources":["../src/features.ts"],"names":[],"mappings":"AAKA,OAAO,EAEL,KAAK,WAAW,EAGjB,MAAM,aAAa,CAAA;AAKpB,sFAAsF;AACtF,eAAO,MAAM,oBAAoB,iBAAiB,CAAA;AAElD,+FAA+F;AAC/F,eAAO,MAAM,oBAAoB,IAAI,CAAA;AAErC;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,EAAE,SAAS,WAAW,EAEnD,CAAA;AAKF,yEAAyE;AACzE,MAAM,WAAW,eAAe;IAC9B,kDAAkD;IAClD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,qDAAqD;IACrD,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC9C,4FAA4F;IAC5F,QAAQ,CAAC,gBAAgB,EAAE,SAAS,MAAM,EAAE,CAAA;IAC5C,gEAAgE;IAChE,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAA;CACtC;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,eAAe,GAAG,IAAI,GAAG,IAAI,CAWrE;AAED,qFAAqF;AACrF,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,eAAe,GAAG,IAAI,GAAG,OAAO,CAE7E;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,eAAe,GAAG,IAAI,GAAG,IAAI,CAKpE;AAED,oGAAoG;AACpG,wBAAgB,eAAe,CAAC,QAAQ,EAAE,eAAe,GAAG,IAAI,GAAG,eAAe,CAUjF;AAED,oEAAoE;AACpE,MAAM,WAAW,aAAa;IAC5B,0FAA0F;IAC1F,QAAQ,EAAE,MAAM,CAAA;IAChB,6FAA6F;IAC7F,gBAAgB,EAAE,MAAM,CAAA;IACxB,+BAA+B;IAC/B,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,2EAA2E;AAC3E,wBAAgB,cAAc,CAAC,QAAQ,EAAE,eAAe,GAAG,aAAa,CAMvE;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,GAAG,eAAe,CAOrF;AAED,sFAAsF;AACtF,wBAAgB,aAAa,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,CAMhE"}
|
package/dist/features.js
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
// The feature manifest a store keeps on its SYSTEM#FEATURES marker row (storage format, "Feature
|
|
2
|
+
// marker"): the extensions it declares, each at a stored-format version, and the entity types
|
|
3
|
+
// declared history-dependent or retained. A writer refuses a store that declares a pair it doesn't
|
|
4
|
+
// model, and every writer requires stream-heads.
|
|
5
|
+
import { EvtError, StreamHeadsNotMigratedError, UnsupportedFeatureError, } from './errors.js';
|
|
6
|
+
import { DOCUMENT, int64, invalid } from './fields.js';
|
|
7
|
+
import { parseJson, stringifyJson } from './json.js';
|
|
8
|
+
import { compareUtf8 } from './utf8.js';
|
|
9
|
+
/** The feature every writer models and requires: per-stream head items (ADR 0007). */
|
|
10
|
+
export const STREAM_HEADS_FEATURE = 'stream-heads';
|
|
11
|
+
/** The stored-format version of {@link STREAM_HEADS_FEATURE} this package reads and writes. */
|
|
12
|
+
export const STREAM_HEADS_VERSION = 1;
|
|
13
|
+
/**
|
|
14
|
+
* The `(feature, stored-format version)` pairs this package models. The other features the
|
|
15
|
+
* storage format defines (`journal`, `journal-compaction`, `postgres-views`) are Rust-first, so a
|
|
16
|
+
* store that declares any of them is refused.
|
|
17
|
+
*/
|
|
18
|
+
export const SUPPORTED_FEATURES = Object.freeze([
|
|
19
|
+
Object.freeze({ name: STREAM_HEADS_FEATURE, version: STREAM_HEADS_VERSION }),
|
|
20
|
+
]);
|
|
21
|
+
// What validation reads. Private, so no caller can add a pair to it.
|
|
22
|
+
const supported = new Map(SUPPORTED_FEATURES.map((pair) => [pair.name, pair.version]));
|
|
23
|
+
/**
|
|
24
|
+
* Refuses a manifest that declares a pair this package doesn't model, listing every such pair,
|
|
25
|
+
* with an {@link UnsupportedFeatureError}.
|
|
26
|
+
*/
|
|
27
|
+
export function checkSupported(manifest) {
|
|
28
|
+
const unsupported = [];
|
|
29
|
+
for (const [name, version] of sortedFeatures(manifest?.features ?? new Map())) {
|
|
30
|
+
if (supported.get(name) !== version) {
|
|
31
|
+
unsupported.push({ name, version });
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
if (unsupported.length > 0) {
|
|
35
|
+
throw new UnsupportedFeatureError(unsupported);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/** Whether the manifest declares stream-heads at the version this package models. */
|
|
39
|
+
export function declaresStreamHeads(manifest) {
|
|
40
|
+
return manifest?.features.get(STREAM_HEADS_FEATURE) === STREAM_HEADS_VERSION;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Refuses a write to a store whose manifest declares an unsupported pair, or doesn't declare
|
|
44
|
+
* stream-heads, without declaring anything.
|
|
45
|
+
*/
|
|
46
|
+
export function checkWritable(manifest) {
|
|
47
|
+
checkSupported(manifest);
|
|
48
|
+
if (!declaresStreamHeads(manifest)) {
|
|
49
|
+
throw new StreamHeadsNotMigratedError();
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/** The manifest with stream-heads declared and its version bumped: a first writer's declaration. */
|
|
53
|
+
export function withStreamHeads(manifest) {
|
|
54
|
+
const features = new Map(manifest?.features);
|
|
55
|
+
features.set(STREAM_HEADS_FEATURE, STREAM_HEADS_VERSION);
|
|
56
|
+
return {
|
|
57
|
+
version: (manifest?.version ?? 0n) + 1n,
|
|
58
|
+
features,
|
|
59
|
+
historyDependent: manifest?.historyDependent ?? [],
|
|
60
|
+
retention: manifest?.retention ?? [],
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/** Encodes a manifest's declarable parts as the marker row stores them. */
|
|
64
|
+
export function encodeManifest(manifest) {
|
|
65
|
+
return {
|
|
66
|
+
features: stringifyJson(new Map(manifest.features)),
|
|
67
|
+
historyDependent: stringifyJson(entityTypeSet(manifest.historyDependent)),
|
|
68
|
+
retention: stringifyJson(entityTypeSet(manifest.retention)),
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Decodes a marker row's stored texts. An empty text is an empty map or set, as an absent
|
|
73
|
+
* attribute is.
|
|
74
|
+
*/
|
|
75
|
+
export function decodeManifest(version, texts) {
|
|
76
|
+
return {
|
|
77
|
+
version,
|
|
78
|
+
features: texts.features === '' ? new Map() : parseFeatures(texts.features),
|
|
79
|
+
historyDependent: parseEntityTypes(texts.historyDependent, 'historyDependent'),
|
|
80
|
+
retention: parseEntityTypes(texts.retention, 'retention'),
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
/** An entity-type set in its stored order: sorted by UTF-8 bytes and deduplicated. */
|
|
84
|
+
export function entityTypeSet(types) {
|
|
85
|
+
// A fresh array, sorted in place: ES2022 has no toSorted.
|
|
86
|
+
const set = Array.from(new Set(types));
|
|
87
|
+
set.sort(compareUtf8);
|
|
88
|
+
return set;
|
|
89
|
+
}
|
|
90
|
+
function parseFeatures(text) {
|
|
91
|
+
const parsed = parseStored(text, 'features');
|
|
92
|
+
if (!(parsed instanceof Map)) {
|
|
93
|
+
throw invalid('the feature manifest is not a JSON object');
|
|
94
|
+
}
|
|
95
|
+
// Go and Rust read a version as an int64. One past the safe integers is no version this
|
|
96
|
+
// package models, so rounding it changes only the refusal's text.
|
|
97
|
+
const features = new Map();
|
|
98
|
+
for (const [name, version] of parsed) {
|
|
99
|
+
features.set(name, Number(int64(version, `the feature manifest's ${name} version`)));
|
|
100
|
+
}
|
|
101
|
+
return features;
|
|
102
|
+
}
|
|
103
|
+
function parseEntityTypes(text, what) {
|
|
104
|
+
if (text.trim() === '') {
|
|
105
|
+
return [];
|
|
106
|
+
}
|
|
107
|
+
const parsed = parseStored(text, what);
|
|
108
|
+
if (!Array.isArray(parsed) || parsed.some((entry) => typeof entry !== 'string')) {
|
|
109
|
+
throw invalid(`the ${what} set is not a JSON array of strings`);
|
|
110
|
+
}
|
|
111
|
+
return entityTypeSet(parsed);
|
|
112
|
+
}
|
|
113
|
+
function parseStored(text, what) {
|
|
114
|
+
try {
|
|
115
|
+
return parseJson(text, DOCUMENT);
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
throw new EvtError('invalidRecord', `the stored ${what} is not JSON`, { cause: error });
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
function sortedFeatures(features) {
|
|
122
|
+
const sorted = Array.from(features);
|
|
123
|
+
sorted.sort(([a], [b]) => compareUtf8(a, b));
|
|
124
|
+
return sorted;
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=features.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"features.js","sourceRoot":"","sources":["../src/features.ts"],"names":[],"mappings":"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"}
|
package/dist/fields.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { EvtError } from './errors.js';
|
|
2
|
+
import { type JsonValue, type ParseOptions } from './json.js';
|
|
3
|
+
export type JsonObject = Map<string, JsonValue>;
|
|
4
|
+
/** How evt parses its own documents: a repeated key is refused. */
|
|
5
|
+
export declare const DOCUMENT: ParseOptions;
|
|
6
|
+
export declare function invalid(message: string): EvtError;
|
|
7
|
+
/** An object, or null for JSON null. */
|
|
8
|
+
export declare function objectOrNull(value: JsonValue | undefined, what: string): JsonObject | null;
|
|
9
|
+
/** A string field, `""` when missing or null. */
|
|
10
|
+
export declare function stringField(object: JsonObject, name: string, what: string): string;
|
|
11
|
+
/** A string field that may be null (a Go `*string`). */
|
|
12
|
+
export declare function nullableString(object: JsonObject, name: string, what: string): string | null;
|
|
13
|
+
/** An int64 field, `0n` when missing or null. `1.0`, `1e3` and `"1"` are refused, as in Go. */
|
|
14
|
+
export declare function int64Field(object: JsonObject, name: string, what: string): bigint;
|
|
15
|
+
/** A small integer field, `0` when missing or null, refused if it isn't a safe integer. */
|
|
16
|
+
export declare function safeIntegerField(object: JsonObject, name: string, what: string): number;
|
|
17
|
+
/** Reads a JSON number as an int64. */
|
|
18
|
+
export declare function int64(value: JsonValue, what: string): bigint;
|
|
19
|
+
/** Refuses an integer outside int64. */
|
|
20
|
+
export declare function checkInt64(value: bigint, what: string): bigint;
|
|
21
|
+
/** Refuses to write an integer that no reader would read back as an int64. */
|
|
22
|
+
export declare function int64Argument(value: bigint, what: string): bigint;
|
|
23
|
+
/** Refuses to write a small integer that isn't a safe integer, such as 1.5 or NaN. */
|
|
24
|
+
export declare function safeIntegerArgument(value: number, what: string): number;
|
|
25
|
+
/** A base64 field (a Go `[]byte`), null when missing or null. */
|
|
26
|
+
export declare function bytesField(object: JsonObject, name: string, what: string): Uint8Array | null;
|
|
27
|
+
/**
|
|
28
|
+
* A Go `map[string]string`: null for a missing or null map, and `""` for a null value.
|
|
29
|
+
*/
|
|
30
|
+
export declare function stringMap(value: JsonValue | undefined, what: string): Map<string, string> | null;
|
|
31
|
+
//# sourceMappingURL=fields.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fields.d.ts","sourceRoot":"","sources":["../src/fields.ts"],"names":[],"mappings":"AAKA,OAAO,EAAC,QAAQ,EAAC,MAAM,aAAa,CAAA;AACpC,OAAO,EAAa,KAAK,SAAS,EAAE,KAAK,YAAY,EAAC,MAAM,WAAW,CAAA;AAEvE,MAAM,MAAM,UAAU,GAAG,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;AAM/C,mEAAmE;AACnE,eAAO,MAAM,QAAQ,EAAE,YAAwC,CAAA;AAE/D,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,QAAQ,CAEjD;AAED,wCAAwC;AACxC,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAS1F;AAED,iDAAiD;AACjD,wBAAgB,WAAW,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAElF;AAED,wDAAwD;AACxD,wBAAgB,cAAc,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAU5F;AAED,+FAA+F;AAC/F,wBAAgB,UAAU,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAOjF;AAED,2FAA2F;AAC3F,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAOvF;AAED,uCAAuC;AACvC,wBAAgB,KAAK,CAAC,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAM5D;AAED,wCAAwC;AACxC,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAM9D;AAED,8EAA8E;AAC9E,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAMjE;AAED,sFAAsF;AACtF,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAMvE;AAED,iEAAiE;AACjE,wBAAgB,UAAU,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAI5F;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAgBhG"}
|