@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
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
// The DynamoDB item layout of the event log. It's pure: it shapes items the way the AWS SDK's
|
|
2
|
+
// low-level client takes them, and imports nothing from the SDK.
|
|
3
|
+
//
|
|
4
|
+
// | Attribute | Type | Event item | Snapshot item (sk 0) | Head item (sk -1) |
|
|
5
|
+
// | ------------ | ---- | -------------- | -------------------- | ----------------- |
|
|
6
|
+
// | `pk` | S | entity ID | entity ID | entity ID |
|
|
7
|
+
// | `sk` | N | event sequence | `0` | `-1` |
|
|
8
|
+
// | `type` | S | event type | | |
|
|
9
|
+
// | `version` | N | event version | | |
|
|
10
|
+
// | `entityType` | S | entity type | entity type | |
|
|
11
|
+
// | `payload` | S | payload JSON | state JSON | |
|
|
12
|
+
// | `metadata` | S | metadata JSON | | |
|
|
13
|
+
// | `seq` | N | | snapshot sequence | |
|
|
14
|
+
// | `eventSeq` | N | | last event folded in | |
|
|
15
|
+
// | `head` | N | | | highest sequence |
|
|
16
|
+
// | `ttl` | N | optional | optional | optional |
|
|
17
|
+
import { eventId } from '../event.js';
|
|
18
|
+
import { EvtError } from '../errors.js';
|
|
19
|
+
import { DOCUMENT, checkInt64, int64Argument, invalid, safeIntegerArgument, } from '../fields.js';
|
|
20
|
+
import { parseJson } from '../json.js';
|
|
21
|
+
import { encodeMetadata, metadataFromJson } from '../metadata.js';
|
|
22
|
+
import { utf8Decode, utf8Encode, utf8Length } from '../utf8.js';
|
|
23
|
+
/** The sort key of a stream's inline snapshot. */
|
|
24
|
+
export const SNAPSHOT_SORT_KEY = 0n;
|
|
25
|
+
/** The sort key of a stream's head item. */
|
|
26
|
+
export const HEAD_SORT_KEY = -1n;
|
|
27
|
+
/** The sort key of a single-item view row. */
|
|
28
|
+
export const DEFAULT_VIEW_SORT_KEY = 'VIEW';
|
|
29
|
+
/** Encodes an event as an event-log item. `ttl` (Unix seconds) is written only when positive. */
|
|
30
|
+
export function eventItem(event, ttl) {
|
|
31
|
+
return withTtl({
|
|
32
|
+
pk: { S: event.entityId },
|
|
33
|
+
sk: { N: int64Argument(event.sequence, 'event.sequence').toString() },
|
|
34
|
+
type: { S: event.type },
|
|
35
|
+
version: { N: safeIntegerArgument(event.version, 'event.version').toString() },
|
|
36
|
+
entityType: { S: event.entityType },
|
|
37
|
+
payload: { S: payloadText(event.payload, 'event payload') },
|
|
38
|
+
metadata: { S: encodeMetadata(event.metadata) },
|
|
39
|
+
}, ttl);
|
|
40
|
+
}
|
|
41
|
+
/** Encodes a stream's inline snapshot item. `ttl` is written only when positive. */
|
|
42
|
+
export function snapshotItem(snapshot, ttl) {
|
|
43
|
+
return withTtl({
|
|
44
|
+
pk: { S: snapshot.entityId },
|
|
45
|
+
sk: { N: SNAPSHOT_SORT_KEY.toString() },
|
|
46
|
+
seq: { N: int64Argument(snapshot.sequence, 'snapshot.sequence').toString() },
|
|
47
|
+
eventSeq: { N: int64Argument(snapshot.eventSequence, 'snapshot.eventSequence').toString() },
|
|
48
|
+
entityType: { S: snapshot.entityType },
|
|
49
|
+
payload: { S: payloadText(snapshot.payload, 'snapshot payload') },
|
|
50
|
+
}, ttl);
|
|
51
|
+
}
|
|
52
|
+
/** Encodes a stream's head item. `ttl` is written only when positive. */
|
|
53
|
+
export function headItem(entityId, head, ttl) {
|
|
54
|
+
const item = {
|
|
55
|
+
pk: { S: entityId },
|
|
56
|
+
sk: { N: HEAD_SORT_KEY.toString() },
|
|
57
|
+
head: { N: int64Argument(head, 'head').toString() },
|
|
58
|
+
};
|
|
59
|
+
return withTtl(item, ttl);
|
|
60
|
+
}
|
|
61
|
+
/** Encodes a single-item view row: `pk = {entityType}#{entityId}`, `sk = "VIEW"`. */
|
|
62
|
+
export function viewItem(entityType, entityId, payload) {
|
|
63
|
+
return {
|
|
64
|
+
pk: { S: `${entityType}#${entityId}` },
|
|
65
|
+
sk: { S: DEFAULT_VIEW_SORT_KEY },
|
|
66
|
+
entityID: { S: entityId },
|
|
67
|
+
entityType: { S: entityType },
|
|
68
|
+
payload: { S: payloadText(payload, 'view payload') },
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Decodes an event-log item. Missing attributes other than the key are empty, and `metadata` must
|
|
73
|
+
* be present and not blank. A JSON `null` metadata is the zero value, as in Go.
|
|
74
|
+
*/
|
|
75
|
+
export function eventFromItem(item) {
|
|
76
|
+
const entityId = requiredString(item, 'pk');
|
|
77
|
+
const sequence = requiredNumber(item, 'sk');
|
|
78
|
+
const id = eventId(entityId, sequence);
|
|
79
|
+
const metadata = optionalString(item, 'metadata') ?? '';
|
|
80
|
+
if (metadata.trim() === '') {
|
|
81
|
+
throw invalid(`event ${id} has empty metadata`);
|
|
82
|
+
}
|
|
83
|
+
let decoded;
|
|
84
|
+
try {
|
|
85
|
+
decoded = metadataFromJson(parseJson(metadata, DOCUMENT));
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
throw new EvtError('invalidRecord', `event ${id} metadata: ${message(error)}`, { cause: error });
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
id,
|
|
92
|
+
sequence,
|
|
93
|
+
type: optionalString(item, 'type') ?? '',
|
|
94
|
+
version: safeInteger(optionalNumber(item, 'version') ?? 0n, 'version'),
|
|
95
|
+
entityId,
|
|
96
|
+
entityType: optionalString(item, 'entityType') ?? '',
|
|
97
|
+
payload: utf8Encode(optionalString(item, 'payload') ?? ''),
|
|
98
|
+
metadata: decoded,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
/** Decodes a stream's inline snapshot item. */
|
|
102
|
+
export function snapshotFromItem(item) {
|
|
103
|
+
return {
|
|
104
|
+
entityType: optionalString(item, 'entityType') ?? '',
|
|
105
|
+
entityId: requiredString(item, 'pk'),
|
|
106
|
+
sequence: optionalNumber(item, 'seq') ?? 0n,
|
|
107
|
+
eventSequence: optionalNumber(item, 'eventSeq') ?? 0n,
|
|
108
|
+
payload: utf8Encode(optionalString(item, 'payload') ?? ''),
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
/** Decodes a head item into its head and its `ttl`, if it has one. */
|
|
112
|
+
export function headFromItem(item) {
|
|
113
|
+
return { head: requiredNumber(item, 'head'), ttl: ttlFromItem(item) };
|
|
114
|
+
}
|
|
115
|
+
/** An item's `ttl` in Unix seconds, or undefined when it has none. */
|
|
116
|
+
export function ttlFromItem(item) {
|
|
117
|
+
const ttl = optionalNumber(item, 'ttl');
|
|
118
|
+
return ttl === undefined ? undefined : safeInteger(ttl, 'ttl');
|
|
119
|
+
}
|
|
120
|
+
/** Whether an item is a stream's inline snapshot (`sk = 0`). */
|
|
121
|
+
export function isSnapshotItem(item) {
|
|
122
|
+
return sortKey(item) === SNAPSHOT_SORT_KEY;
|
|
123
|
+
}
|
|
124
|
+
/** An item's numeric sort key, if it has one. */
|
|
125
|
+
export function sortKey(item) {
|
|
126
|
+
const sk = item['sk'];
|
|
127
|
+
if (sk === undefined || !('N' in sk)) {
|
|
128
|
+
return undefined;
|
|
129
|
+
}
|
|
130
|
+
return parseNumber(sk.N);
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* The `ttl` of an item written at `nowMs` (Unix milliseconds) under a retention of `retentionMs`:
|
|
134
|
+
* their sum in whole Unix seconds, rounded down after adding, as Go's `Time.Add(...).Unix()` is.
|
|
135
|
+
* Undefined, so no `ttl` is written, for a zero retention. A retention with a fraction of a
|
|
136
|
+
* millisecond is refused, because Go would count it.
|
|
137
|
+
*/
|
|
138
|
+
export function expiry(nowMs, retentionMs) {
|
|
139
|
+
if (!Number.isSafeInteger(nowMs) || !Number.isSafeInteger(retentionMs) || retentionMs < 0) {
|
|
140
|
+
throw new EvtError('invalidArgument', 'the clock and the retention must be whole, non-negative milliseconds: ' +
|
|
141
|
+
`${nowMs}, ${retentionMs}`);
|
|
142
|
+
}
|
|
143
|
+
if (retentionMs === 0) {
|
|
144
|
+
return undefined;
|
|
145
|
+
}
|
|
146
|
+
return Math.floor((nowMs + retentionMs) / 1000);
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* The size DynamoDB counts for an item: each attribute's name plus its value, in UTF-8 bytes. The
|
|
150
|
+
* commit budget measures every action with it.
|
|
151
|
+
*/
|
|
152
|
+
export function itemSize(item) {
|
|
153
|
+
let size = 0;
|
|
154
|
+
for (const [name, value] of Object.entries(item)) {
|
|
155
|
+
size += utf8Length(name) + valueSize(value);
|
|
156
|
+
}
|
|
157
|
+
return size;
|
|
158
|
+
}
|
|
159
|
+
function valueSize(value) {
|
|
160
|
+
if ('S' in value) {
|
|
161
|
+
return utf8Length(value.S);
|
|
162
|
+
}
|
|
163
|
+
if ('N' in value) {
|
|
164
|
+
return utf8Length(value.N);
|
|
165
|
+
}
|
|
166
|
+
if ('B' in value) {
|
|
167
|
+
return value.B.length;
|
|
168
|
+
}
|
|
169
|
+
if ('BOOL' in value || 'NULL' in value) {
|
|
170
|
+
return 1;
|
|
171
|
+
}
|
|
172
|
+
if ('M' in value) {
|
|
173
|
+
return 3 + itemSize(value.M) + Object.keys(value.M).length;
|
|
174
|
+
}
|
|
175
|
+
if ('L' in value) {
|
|
176
|
+
return value.L.reduce((size, entry) => size + 1 + valueSize(entry), 3);
|
|
177
|
+
}
|
|
178
|
+
if ('SS' in value) {
|
|
179
|
+
return value.SS.reduce((size, entry) => size + utf8Length(entry), 0);
|
|
180
|
+
}
|
|
181
|
+
if ('NS' in value) {
|
|
182
|
+
return value.NS.reduce((size, entry) => size + utf8Length(entry), 0);
|
|
183
|
+
}
|
|
184
|
+
return value.BS.reduce((size, entry) => size + entry.length, 0);
|
|
185
|
+
}
|
|
186
|
+
function withTtl(item, ttl) {
|
|
187
|
+
if (ttl !== undefined && safeIntegerArgument(ttl, 'ttl') > 0) {
|
|
188
|
+
item['ttl'] = { N: ttl.toString() };
|
|
189
|
+
}
|
|
190
|
+
return item;
|
|
191
|
+
}
|
|
192
|
+
// A payload is stored as a DynamoDB string, so it must be UTF-8. A null payload is stored empty.
|
|
193
|
+
function payloadText(payload, what) {
|
|
194
|
+
if (payload === null) {
|
|
195
|
+
return '';
|
|
196
|
+
}
|
|
197
|
+
try {
|
|
198
|
+
return utf8Decode(payload, what);
|
|
199
|
+
}
|
|
200
|
+
catch (error) {
|
|
201
|
+
const reason = `${what} is not valid UTF-8 and cannot be stored as a string`;
|
|
202
|
+
throw new EvtError('invalidArgument', reason, { cause: error });
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
function requiredString(item, name) {
|
|
206
|
+
const value = optionalString(item, name);
|
|
207
|
+
if (value === undefined) {
|
|
208
|
+
throw invalid(`item has no ${name} attribute`);
|
|
209
|
+
}
|
|
210
|
+
return value;
|
|
211
|
+
}
|
|
212
|
+
function requiredNumber(item, name) {
|
|
213
|
+
const value = optionalNumber(item, name);
|
|
214
|
+
if (value === undefined) {
|
|
215
|
+
throw invalid(`item has no ${name} attribute`);
|
|
216
|
+
}
|
|
217
|
+
return value;
|
|
218
|
+
}
|
|
219
|
+
function optionalString(item, name) {
|
|
220
|
+
const value = item[name];
|
|
221
|
+
if (value === undefined || 'NULL' in value) {
|
|
222
|
+
return undefined;
|
|
223
|
+
}
|
|
224
|
+
if (!('S' in value)) {
|
|
225
|
+
throw invalid(`attribute ${name} is not a string`);
|
|
226
|
+
}
|
|
227
|
+
return value.S;
|
|
228
|
+
}
|
|
229
|
+
function optionalNumber(item, name) {
|
|
230
|
+
const value = item[name];
|
|
231
|
+
if (value === undefined || 'NULL' in value) {
|
|
232
|
+
return undefined;
|
|
233
|
+
}
|
|
234
|
+
if (!('N' in value)) {
|
|
235
|
+
throw invalid(`attribute ${name} is not a number`);
|
|
236
|
+
}
|
|
237
|
+
const number = parseNumber(value.N);
|
|
238
|
+
if (number === undefined) {
|
|
239
|
+
throw invalid(`attribute ${name} is not an integer: ${value.N}`);
|
|
240
|
+
}
|
|
241
|
+
return number;
|
|
242
|
+
}
|
|
243
|
+
// An int64 in decimal, as strconv.ParseInt reads it: an optional sign, then digits.
|
|
244
|
+
function parseNumber(text) {
|
|
245
|
+
if (!/^[+-]?\d+$/.test(text)) {
|
|
246
|
+
return undefined;
|
|
247
|
+
}
|
|
248
|
+
try {
|
|
249
|
+
return checkInt64(BigInt(text), 'number');
|
|
250
|
+
}
|
|
251
|
+
catch {
|
|
252
|
+
return undefined;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
function safeInteger(value, name) {
|
|
256
|
+
if (value < BigInt(Number.MIN_SAFE_INTEGER) || value > BigInt(Number.MAX_SAFE_INTEGER)) {
|
|
257
|
+
throw invalid(`attribute ${name} is ${value}, past the integers it holds`);
|
|
258
|
+
}
|
|
259
|
+
return Number(value);
|
|
260
|
+
}
|
|
261
|
+
function message(error) {
|
|
262
|
+
return error instanceof Error ? error.message : String(error);
|
|
263
|
+
}
|
|
264
|
+
//# sourceMappingURL=item.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"item.js","sourceRoot":"","sources":["../../src/dynamodb/item.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAC9F,iEAAiE;AACjE,EAAE;AACF,sFAAsF;AACtF,sFAAsF;AACtF,sFAAsF;AACtF,sFAAsF;AACtF,sFAAsF;AACtF,sFAAsF;AACtF,sFAAsF;AACtF,sFAAsF;AACtF,sFAAsF;AACtF,sFAAsF;AACtF,sFAAsF;AACtF,sFAAsF;AACtF,sFAAsF;AAEtF,OAAO,EAAgD,OAAO,EAAC,MAAM,aAAa,CAAA;AAClF,OAAO,EAAC,QAAQ,EAAC,MAAM,cAAc,CAAA;AACrC,OAAO,EACL,QAAQ,EACR,UAAU,EACV,aAAa,EACb,OAAO,EACP,mBAAmB,GACpB,MAAM,cAAc,CAAA;AACrB,OAAO,EAAC,SAAS,EAAC,MAAM,YAAY,CAAA;AACpC,OAAO,EAAC,cAAc,EAAE,gBAAgB,EAAC,MAAM,gBAAgB,CAAA;AAC/D,OAAO,EAAC,UAAU,EAAE,UAAU,EAAE,UAAU,EAAC,MAAM,YAAY,CAAA;AAkB7D,kDAAkD;AAClD,MAAM,CAAC,MAAM,iBAAiB,GAAG,EAAE,CAAA;AAEnC,4CAA4C;AAC5C,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,EAAE,CAAA;AAEhC,8CAA8C;AAC9C,MAAM,CAAC,MAAM,qBAAqB,GAAG,MAAM,CAAA;AAE3C,iGAAiG;AACjG,MAAM,UAAU,SAAS,CAAC,KAAsB,EAAE,GAAY;IAC5D,OAAO,OAAO,CACZ;QACE,EAAE,EAAE,EAAC,CAAC,EAAE,KAAK,CAAC,QAAQ,EAAC;QACvB,EAAE,EAAE,EAAC,CAAC,EAAE,aAAa,CAAC,KAAK,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC,QAAQ,EAAE,EAAC;QACnE,IAAI,EAAE,EAAC,CAAC,EAAE,KAAK,CAAC,IAAI,EAAC;QACrB,OAAO,EAAE,EAAC,CAAC,EAAE,mBAAmB,CAAC,KAAK,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC,QAAQ,EAAE,EAAC;QAC5E,UAAU,EAAE,EAAC,CAAC,EAAE,KAAK,CAAC,UAAU,EAAC;QACjC,OAAO,EAAE,EAAC,CAAC,EAAE,WAAW,CAAC,KAAK,CAAC,OAAO,EAAE,eAAe,CAAC,EAAC;QACzD,QAAQ,EAAE,EAAC,CAAC,EAAE,cAAc,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAC;KAC9C,EACD,GAAG,CACJ,CAAA;AACH,CAAC;AAED,oFAAoF;AACpF,MAAM,UAAU,YAAY,CAAC,QAA4B,EAAE,GAAY;IACrE,OAAO,OAAO,CACZ;QACE,EAAE,EAAE,EAAC,CAAC,EAAE,QAAQ,CAAC,QAAQ,EAAC;QAC1B,EAAE,EAAE,EAAC,CAAC,EAAE,iBAAiB,CAAC,QAAQ,EAAE,EAAC;QACrC,GAAG,EAAE,EAAC,CAAC,EAAE,aAAa,CAAC,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,CAAC,CAAC,QAAQ,EAAE,EAAC;QAC1E,QAAQ,EAAE,EAAC,CAAC,EAAE,aAAa,CAAC,QAAQ,CAAC,aAAa,EAAE,wBAAwB,CAAC,CAAC,QAAQ,EAAE,EAAC;QACzF,UAAU,EAAE,EAAC,CAAC,EAAE,QAAQ,CAAC,UAAU,EAAC;QACpC,OAAO,EAAE,EAAC,CAAC,EAAE,WAAW,CAAC,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAC,EAAC;KAChE,EACD,GAAG,CACJ,CAAA;AACH,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,QAAQ,CAAC,QAAgB,EAAE,IAAY,EAAE,GAAY;IACnE,MAAM,IAAI,GAAS;QACjB,EAAE,EAAE,EAAC,CAAC,EAAE,QAAQ,EAAC;QACjB,EAAE,EAAE,EAAC,CAAC,EAAE,aAAa,CAAC,QAAQ,EAAE,EAAC;QACjC,IAAI,EAAE,EAAC,CAAC,EAAE,aAAa,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAC;KAClD,CAAA;IAED,OAAO,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;AAC3B,CAAC;AAED,qFAAqF;AACrF,MAAM,UAAU,QAAQ,CAAC,UAAkB,EAAE,QAAgB,EAAE,OAAmB;IAChF,OAAO;QACL,EAAE,EAAE,EAAC,CAAC,EAAE,GAAG,UAAU,IAAI,QAAQ,EAAE,EAAC;QACpC,EAAE,EAAE,EAAC,CAAC,EAAE,qBAAqB,EAAC;QAC9B,QAAQ,EAAE,EAAC,CAAC,EAAE,QAAQ,EAAC;QACvB,UAAU,EAAE,EAAC,CAAC,EAAE,UAAU,EAAC;QAC3B,OAAO,EAAE,EAAC,CAAC,EAAE,WAAW,CAAC,OAAO,EAAE,cAAc,CAAC,EAAC;KACnD,CAAA;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,IAAU;IACtC,MAAM,QAAQ,GAAG,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;IAC3C,MAAM,QAAQ,GAAG,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;IAC3C,MAAM,EAAE,GAAG,OAAO,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAA;IACtC,MAAM,QAAQ,GAAG,cAAc,CAAC,IAAI,EAAE,UAAU,CAAC,IAAI,EAAE,CAAA;IACvD,IAAI,QAAQ,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QAC3B,MAAM,OAAO,CAAC,SAAS,EAAE,qBAAqB,CAAC,CAAA;IACjD,CAAC;IAED,IAAI,OAAO,CAAA;IACX,IAAI,CAAC;QACH,OAAO,GAAG,gBAAgB,CAAC,SAAS,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAA;IAC3D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,QAAQ,CAAC,eAAe,EAAE,SAAS,EAAE,cAAc,OAAO,CAAC,KAAK,CAAC,EAAE,EAAE,EAAC,KAAK,EAAE,KAAK,EAAC,CAAC,CAAA;IAChG,CAAC;IAED,OAAO;QACL,EAAE;QACF,QAAQ;QACR,IAAI,EAAE,cAAc,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE;QACxC,OAAO,EAAE,WAAW,CAAC,cAAc,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,EAAE,SAAS,CAAC;QACtE,QAAQ;QACR,UAAU,EAAE,cAAc,CAAC,IAAI,EAAE,YAAY,CAAC,IAAI,EAAE;QACpD,OAAO,EAAE,UAAU,CAAC,cAAc,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,CAAC;QAC1D,QAAQ,EAAE,OAAO;KAClB,CAAA;AACH,CAAC;AAED,+CAA+C;AAC/C,MAAM,UAAU,gBAAgB,CAAC,IAAU;IACzC,OAAO;QACL,UAAU,EAAE,cAAc,CAAC,IAAI,EAAE,YAAY,CAAC,IAAI,EAAE;QACpD,QAAQ,EAAE,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC;QACpC,QAAQ,EAAE,cAAc,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE;QAC3C,aAAa,EAAE,cAAc,CAAC,IAAI,EAAE,UAAU,CAAC,IAAI,EAAE;QACrD,OAAO,EAAE,UAAU,CAAC,cAAc,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,CAAC;KAC3D,CAAA;AACH,CAAC;AAED,sEAAsE;AACtE,MAAM,UAAU,YAAY,CAAC,IAAU;IACrC,OAAO,EAAC,IAAI,EAAE,cAAc,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,GAAG,EAAE,WAAW,CAAC,IAAI,CAAC,EAAC,CAAA;AACrE,CAAC;AAED,sEAAsE;AACtE,MAAM,UAAU,WAAW,CAAC,IAAU;IACpC,MAAM,GAAG,GAAG,cAAc,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;IAEvC,OAAO,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;AAChE,CAAC;AAED,gEAAgE;AAChE,MAAM,UAAU,cAAc,CAAC,IAAU;IACvC,OAAO,OAAO,CAAC,IAAI,CAAC,KAAK,iBAAiB,CAAA;AAC5C,CAAC;AAED,iDAAiD;AACjD,MAAM,UAAU,OAAO,CAAC,IAAU;IAChC,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,CAAA;IACrB,IAAI,EAAE,KAAK,SAAS,IAAI,CAAC,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,CAAC;QACrC,OAAO,SAAS,CAAA;IAClB,CAAC;IAED,OAAO,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;AAC1B,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,MAAM,CAAC,KAAa,EAAE,WAAmB;IACvD,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,WAAW,CAAC,IAAI,WAAW,GAAG,CAAC,EAAE,CAAC;QAC1F,MAAM,IAAI,QAAQ,CAChB,iBAAiB,EACjB,wEAAwE;YACtE,GAAG,KAAK,KAAK,WAAW,EAAE,CAC7B,CAAA;IACH,CAAC;IACD,IAAI,WAAW,KAAK,CAAC,EAAE,CAAC;QACtB,OAAO,SAAS,CAAA;IAClB,CAAC;IAED,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,GAAG,WAAW,CAAC,GAAG,IAAI,CAAC,CAAA;AACjD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,QAAQ,CAAC,IAAU;IACjC,IAAI,IAAI,GAAG,CAAC,CAAA;IACZ,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACjD,IAAI,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC,CAAA;IAC7C,CAAC;IAED,OAAO,IAAI,CAAA;AACb,CAAC;AAED,SAAS,SAAS,CAAC,KAAqB;IACtC,IAAI,GAAG,IAAI,KAAK,EAAE,CAAC;QACjB,OAAO,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;IAC5B,CAAC;IACD,IAAI,GAAG,IAAI,KAAK,EAAE,CAAC;QACjB,OAAO,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;IAC5B,CAAC;IACD,IAAI,GAAG,IAAI,KAAK,EAAE,CAAC;QACjB,OAAO,KAAK,CAAC,CAAC,CAAC,MAAM,CAAA;IACvB,CAAC;IACD,IAAI,MAAM,IAAI,KAAK,IAAI,MAAM,IAAI,KAAK,EAAE,CAAC;QACvC,OAAO,CAAC,CAAA;IACV,CAAC;IACD,IAAI,GAAG,IAAI,KAAK,EAAE,CAAC;QACjB,OAAO,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAA;IAC5D,CAAC;IACD,IAAI,GAAG,IAAI,KAAK,EAAE,CAAC;QACjB,OAAO,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAA;IACxE,CAAC;IACD,IAAI,IAAI,IAAI,KAAK,EAAE,CAAC;QAClB,OAAO,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,GAAG,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAA;IACtE,CAAC;IACD,IAAI,IAAI,IAAI,KAAK,EAAE,CAAC;QAClB,OAAO,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,GAAG,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAA;IACtE,CAAC;IAED,OAAO,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;AACjE,CAAC;AAED,SAAS,OAAO,CAAC,IAAU,EAAE,GAAuB;IAClD,IAAI,GAAG,KAAK,SAAS,IAAI,mBAAmB,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QAC7D,IAAI,CAAC,KAAK,CAAC,GAAG,EAAC,CAAC,EAAE,GAAG,CAAC,QAAQ,EAAE,EAAC,CAAA;IACnC,CAAC;IAED,OAAO,IAAI,CAAA;AACb,CAAC;AAED,iGAAiG;AACjG,SAAS,WAAW,CAAC,OAA0B,EAAE,IAAY;IAC3D,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACrB,OAAO,EAAE,CAAA;IACX,CAAC;IAED,IAAI,CAAC;QACH,OAAO,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;IAClC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,MAAM,GAAG,GAAG,IAAI,sDAAsD,CAAA;QAC5E,MAAM,IAAI,QAAQ,CAAC,iBAAiB,EAAE,MAAM,EAAE,EAAC,KAAK,EAAE,KAAK,EAAC,CAAC,CAAA;IAC/D,CAAC;AACH,CAAC;AAED,SAAS,cAAc,CAAC,IAAU,EAAE,IAAY;IAC9C,MAAM,KAAK,GAAG,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;IACxC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,MAAM,OAAO,CAAC,eAAe,IAAI,YAAY,CAAC,CAAA;IAChD,CAAC;IAED,OAAO,KAAK,CAAA;AACd,CAAC;AAED,SAAS,cAAc,CAAC,IAAU,EAAE,IAAY;IAC9C,MAAM,KAAK,GAAG,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;IACxC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,MAAM,OAAO,CAAC,eAAe,IAAI,YAAY,CAAC,CAAA;IAChD,CAAC;IAED,OAAO,KAAK,CAAA;AACd,CAAC;AAED,SAAS,cAAc,CAAC,IAAU,EAAE,IAAY;IAC9C,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,CAAA;IACxB,IAAI,KAAK,KAAK,SAAS,IAAI,MAAM,IAAI,KAAK,EAAE,CAAC;QAC3C,OAAO,SAAS,CAAA;IAClB,CAAC;IACD,IAAI,CAAC,CAAC,GAAG,IAAI,KAAK,CAAC,EAAE,CAAC;QACpB,MAAM,OAAO,CAAC,aAAa,IAAI,kBAAkB,CAAC,CAAA;IACpD,CAAC;IAED,OAAO,KAAK,CAAC,CAAC,CAAA;AAChB,CAAC;AAED,SAAS,cAAc,CAAC,IAAU,EAAE,IAAY;IAC9C,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,CAAA;IACxB,IAAI,KAAK,KAAK,SAAS,IAAI,MAAM,IAAI,KAAK,EAAE,CAAC;QAC3C,OAAO,SAAS,CAAA;IAClB,CAAC;IACD,IAAI,CAAC,CAAC,GAAG,IAAI,KAAK,CAAC,EAAE,CAAC;QACpB,MAAM,OAAO,CAAC,aAAa,IAAI,kBAAkB,CAAC,CAAA;IACpD,CAAC;IAED,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;IACnC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,MAAM,OAAO,CAAC,aAAa,IAAI,uBAAuB,KAAK,CAAC,CAAC,EAAE,CAAC,CAAA;IAClE,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC;AAED,oFAAoF;AACpF,SAAS,WAAW,CAAC,IAAY;IAC/B,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC7B,OAAO,SAAS,CAAA;IAClB,CAAC;IAED,IAAI,CAAC;QACH,OAAO,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC,CAAA;IAC3C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAA;IAClB,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAAC,KAAa,EAAE,IAAY;IAC9C,IAAI,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,IAAI,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,EAAE,CAAC;QACvF,MAAM,OAAO,CAAC,aAAa,IAAI,OAAO,KAAK,8BAA8B,CAAC,CAAA;IAC5E,CAAC;IAED,OAAO,MAAM,CAAC,KAAK,CAAC,CAAA;AACtB,CAAC;AAED,SAAS,OAAO,CAAC,KAAc;IAC7B,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;AAC/D,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type FeatureManifest } from '../features.js';
|
|
2
|
+
import { type Item } from './item.js';
|
|
3
|
+
/** The partition key of the feature-marker row. */
|
|
4
|
+
export declare const FEATURES_PK = "SYSTEM#FEATURES";
|
|
5
|
+
/** The partition key of the rebuild-lock row, which every commit checks is absent. */
|
|
6
|
+
export declare const REBUILD_LOCK_PK = "SYSTEM#REBUILD";
|
|
7
|
+
/** Encodes a feature manifest as its marker item. Empty entity-type sets are left out. */
|
|
8
|
+
export declare function markerItem(manifest: FeatureManifest): Item;
|
|
9
|
+
/** Decodes a marker item. An absent text attribute is an empty map or set. */
|
|
10
|
+
export declare function manifestFromItem(item: Item): FeatureManifest;
|
|
11
|
+
//# sourceMappingURL=marker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"marker.d.ts","sourceRoot":"","sources":["../../src/dynamodb/marker.ts"],"names":[],"mappings":"AAWA,OAAO,EAAC,KAAK,eAAe,EAAiC,MAAM,gBAAgB,CAAA;AACnF,OAAO,EAAC,KAAK,IAAI,EAAoB,MAAM,WAAW,CAAA;AAEtD,mDAAmD;AACnD,eAAO,MAAM,WAAW,oBAAoB,CAAA;AAE5C,sFAAsF;AACtF,eAAO,MAAM,eAAe,mBAAmB,CAAA;AAE/C,0FAA0F;AAC1F,wBAAgB,UAAU,CAAC,QAAQ,EAAE,eAAe,GAAG,IAAI,CAgB1D;AAED,8EAA8E;AAC9E,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,IAAI,GAAG,eAAe,CAW5D"}
|
|
@@ -0,0 +1,56 @@
|
|
|
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
|
+
import { checkInt64, invalid } from '../fields.js';
|
|
11
|
+
import { decodeManifest, encodeManifest } from '../features.js';
|
|
12
|
+
import { SNAPSHOT_SORT_KEY } from './item.js';
|
|
13
|
+
/** The partition key of the feature-marker row. */
|
|
14
|
+
export const FEATURES_PK = 'SYSTEM#FEATURES';
|
|
15
|
+
/** The partition key of the rebuild-lock row, which every commit checks is absent. */
|
|
16
|
+
export const REBUILD_LOCK_PK = 'SYSTEM#REBUILD';
|
|
17
|
+
/** Encodes a feature manifest as its marker item. Empty entity-type sets are left out. */
|
|
18
|
+
export function markerItem(manifest) {
|
|
19
|
+
const texts = encodeManifest(manifest);
|
|
20
|
+
const item = {
|
|
21
|
+
pk: { S: FEATURES_PK },
|
|
22
|
+
sk: { N: SNAPSHOT_SORT_KEY.toString() },
|
|
23
|
+
version: { N: manifest.version.toString() },
|
|
24
|
+
features: { S: texts.features },
|
|
25
|
+
};
|
|
26
|
+
if (manifest.historyDependent.length > 0) {
|
|
27
|
+
item['historyDependent'] = { S: texts.historyDependent };
|
|
28
|
+
}
|
|
29
|
+
if (manifest.retention.length > 0) {
|
|
30
|
+
item['retention'] = { S: texts.retention };
|
|
31
|
+
}
|
|
32
|
+
return item;
|
|
33
|
+
}
|
|
34
|
+
/** Decodes a marker item. An absent text attribute is an empty map or set. */
|
|
35
|
+
export function manifestFromItem(item) {
|
|
36
|
+
const version = item['version'];
|
|
37
|
+
if (version === undefined || !('N' in version) || !/^\d+$/.test(version.N)) {
|
|
38
|
+
throw invalid('the feature marker has no version');
|
|
39
|
+
}
|
|
40
|
+
return decodeManifest(checkInt64(BigInt(version.N), 'the feature marker version'), {
|
|
41
|
+
features: text(item, 'features'),
|
|
42
|
+
historyDependent: text(item, 'historyDependent'),
|
|
43
|
+
retention: text(item, 'retention'),
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
function text(item, name) {
|
|
47
|
+
const value = item[name];
|
|
48
|
+
if (value === undefined) {
|
|
49
|
+
return '';
|
|
50
|
+
}
|
|
51
|
+
if (!('S' in value)) {
|
|
52
|
+
throw invalid(`the feature marker's ${name} attribute is not a string`);
|
|
53
|
+
}
|
|
54
|
+
return value.S;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=marker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"marker.js","sourceRoot":"","sources":["../../src/dynamodb/marker.ts"],"names":[],"mappings":"AAAA,6FAA6F;AAC7F,2BAA2B;AAC3B,EAAE;AACF,+FAA+F;AAC/F,+FAA+F;AAC/F,+FAA+F;AAC/F,+FAA+F;AAC/F,+FAA+F;AAC/F,+FAA+F;AAE/F,OAAO,EAAC,UAAU,EAAE,OAAO,EAAC,MAAM,cAAc,CAAA;AAChD,OAAO,EAAuB,cAAc,EAAE,cAAc,EAAC,MAAM,gBAAgB,CAAA;AACnF,OAAO,EAAY,iBAAiB,EAAC,MAAM,WAAW,CAAA;AAEtD,mDAAmD;AACnD,MAAM,CAAC,MAAM,WAAW,GAAG,iBAAiB,CAAA;AAE5C,sFAAsF;AACtF,MAAM,CAAC,MAAM,eAAe,GAAG,gBAAgB,CAAA;AAE/C,0FAA0F;AAC1F,MAAM,UAAU,UAAU,CAAC,QAAyB;IAClD,MAAM,KAAK,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAA;IACtC,MAAM,IAAI,GAAS;QACjB,EAAE,EAAE,EAAC,CAAC,EAAE,WAAW,EAAC;QACpB,EAAE,EAAE,EAAC,CAAC,EAAE,iBAAiB,CAAC,QAAQ,EAAE,EAAC;QACrC,OAAO,EAAE,EAAC,CAAC,EAAE,QAAQ,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAC;QACzC,QAAQ,EAAE,EAAC,CAAC,EAAE,KAAK,CAAC,QAAQ,EAAC;KAC9B,CAAA;IACD,IAAI,QAAQ,CAAC,gBAAgB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzC,IAAI,CAAC,kBAAkB,CAAC,GAAG,EAAC,CAAC,EAAE,KAAK,CAAC,gBAAgB,EAAC,CAAA;IACxD,CAAC;IACD,IAAI,QAAQ,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAClC,IAAI,CAAC,WAAW,CAAC,GAAG,EAAC,CAAC,EAAE,KAAK,CAAC,SAAS,EAAC,CAAA;IAC1C,CAAC;IAED,OAAO,IAAI,CAAA;AACb,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,gBAAgB,CAAC,IAAU;IACzC,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,CAAA;IAC/B,IAAI,OAAO,KAAK,SAAS,IAAI,CAAC,CAAC,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3E,MAAM,OAAO,CAAC,mCAAmC,CAAC,CAAA;IACpD,CAAC;IAED,OAAO,cAAc,CAAC,UAAU,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,4BAA4B,CAAC,EAAE;QACjF,QAAQ,EAAE,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC;QAChC,gBAAgB,EAAE,IAAI,CAAC,IAAI,EAAE,kBAAkB,CAAC;QAChD,SAAS,EAAE,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC;KACnC,CAAC,CAAA;AACJ,CAAC;AAED,SAAS,IAAI,CAAC,IAAU,EAAE,IAAY;IACpC,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,CAAA;IACxB,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,OAAO,EAAE,CAAA;IACX,CAAC;IACD,IAAI,CAAC,CAAC,GAAG,IAAI,KAAK,CAAC,EAAE,CAAC;QACpB,MAAM,OAAO,CAAC,wBAAwB,IAAI,4BAA4B,CAAC,CAAA;IACzE,CAAC;IAED,OAAO,KAAK,CAAC,CAAC,CAAA;AAChB,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { SerializedEvent, SerializedSnapshot } from '../event.js';
|
|
2
|
+
import { type CallOptions, type Commit, type Repository, type StoreInitializer } from '../repository.js';
|
|
3
|
+
import type { DynamoClient } from './client.js';
|
|
4
|
+
/** How a {@link DynamoRepository} reads and initializes its store. */
|
|
5
|
+
export interface DynamoRepositoryOptions {
|
|
6
|
+
/**
|
|
7
|
+
* Whether a write to a store that doesn't declare stream-heads initializes it, scanning the
|
|
8
|
+
* table to make sure it holds no data, instead of refusing with a
|
|
9
|
+
* {@link StoreNotInitializedError}. Off by default, so writers never need `dynamodb:Scan`:
|
|
10
|
+
* initialize a fresh store once, at deploy time, with {@link DynamoRepository.initialize}.
|
|
11
|
+
*/
|
|
12
|
+
lazyInitialization?: boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Whether event and snapshot reads are strongly consistent. On by default. Head reads, the
|
|
15
|
+
* failure-path probe, compaction and the feature marker always read consistently.
|
|
16
|
+
*/
|
|
17
|
+
consistentRead?: boolean;
|
|
18
|
+
/**
|
|
19
|
+
* How long the items of each entity type live, in whole milliseconds, keyed by entity type.
|
|
20
|
+
* Every event, snapshot and head item of a type with a positive retention carries a DynamoDB
|
|
21
|
+
* `ttl`, the write time plus the retention in Unix seconds, for the table's TTL to delete. A
|
|
22
|
+
* type that isn't listed, or has 0, is kept forever. TTL deletes items in no order, so retain
|
|
23
|
+
* only short-lived streams that nothing replays. Declare the retained types in the store's
|
|
24
|
+
* feature manifest too, from Go or Rust, so that their writers refuse read fences on them.
|
|
25
|
+
*/
|
|
26
|
+
retention?: Readonly<Record<string, number>> | ReadonlyMap<string, number>;
|
|
27
|
+
/**
|
|
28
|
+
* The clock that stamps `ttl`s and decides which have passed, in Unix milliseconds as
|
|
29
|
+
* `Date.now` gives them, never seconds. `Date.now` by default.
|
|
30
|
+
*/
|
|
31
|
+
clock?: () => number;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* A {@link Repository} on a DynamoDB event-log table, through the AWS SDK's low-level `DynamoDB`
|
|
35
|
+
* client or anything shaped like it ({@link DynamoClient}).
|
|
36
|
+
*
|
|
37
|
+
* The repository validates the store's feature manifest at its first write and caches the version
|
|
38
|
+
* it validated. Every commit and snapshot write checks that version, so when another writer
|
|
39
|
+
* declares a feature, the next write fails, validates the manifest again, and either refuses an
|
|
40
|
+
* unsupported feature or fails once with a retryable {@link FeatureManifestChangedError}.
|
|
41
|
+
*/
|
|
42
|
+
export declare class DynamoRepository implements Repository, StoreInitializer {
|
|
43
|
+
#private;
|
|
44
|
+
constructor(client: DynamoClient, eventsTable: string, options?: DynamoRepositoryOptions);
|
|
45
|
+
/** The events table this repository writes. */
|
|
46
|
+
get eventsTable(): string;
|
|
47
|
+
/**
|
|
48
|
+
* Declares stream-heads on a store that holds no data, and resolves `true` when this call
|
|
49
|
+
* declared it. It scans the table with strongly consistent reads, so run it once, at deploy
|
|
50
|
+
* time, with a role that may Scan. Concurrent initializations let exactly one declare.
|
|
51
|
+
*/
|
|
52
|
+
initialize(options?: CallOptions): Promise<boolean>;
|
|
53
|
+
commit(commit: Commit, options?: CallOptions): Promise<void>;
|
|
54
|
+
events(entityId: string, options?: CallOptions): Promise<SerializedEvent[]>;
|
|
55
|
+
eventsAfter(entityId: string, after: bigint, options?: CallOptions): Promise<SerializedEvent[]>;
|
|
56
|
+
latest(entityId: string, n: number, options?: CallOptions): Promise<SerializedEvent[]>;
|
|
57
|
+
snapshot(entityId: string, options?: CallOptions): Promise<SerializedSnapshot | null>;
|
|
58
|
+
putSnapshot(snapshot: SerializedSnapshot, options?: CallOptions): Promise<boolean>;
|
|
59
|
+
compactBelow(entityId: string, through: bigint, options?: CallOptions): Promise<number>;
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=repository.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../../src/dynamodb/repository.ts"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAC,eAAe,EAAE,kBAAkB,EAAC,MAAM,aAAa,CAAA;AASpE,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,MAAM,EACX,KAAK,UAAU,EACf,KAAK,gBAAgB,EAMtB,MAAM,kBAAkB,CAAA;AACzB,OAAO,KAAK,EAAC,YAAY,EAAqC,MAAM,aAAa,CAAA;AAoBjF,sEAAsE;AACtE,MAAM,WAAW,uBAAuB;IACtC;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC1E;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,MAAM,CAAA;CACrB;AAoBD;;;;;;;;GAQG;AACH,qBAAa,gBAAiB,YAAW,UAAU,EAAE,gBAAgB;;IAgBnE,YAAY,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,GAAE,uBAA4B,EAO3F;IAED,+CAA+C;IAC/C,IAAI,WAAW,IAAI,MAAM,CAExB;IAED;;;;OAIG;IACG,UAAU,CAAC,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAyBxD;IAEK,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAuBjE;IAEK,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAEhF;IAEK,WAAW,CACf,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,eAAe,EAAE,CAAC,CAa5B;IAEK,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAmB3F;IAEK,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAI1F;IAEK,WAAW,CAAC,QAAQ,EAAE,kBAAkB,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAgEvF;IAEK,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CA+C5F;CAyjBF"}
|