@elaraai/e3-cloud-files 1.0.94 → 1.0.97

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 (49) hide show
  1. package/README.md +129 -23
  2. package/dist/src/authoring.d.ts +61 -24
  3. package/dist/src/authoring.d.ts.map +1 -1
  4. package/dist/src/authoring.js +92 -48
  5. package/dist/src/authoring.js.map +1 -1
  6. package/dist/src/check/index.d.ts +3 -4
  7. package/dist/src/check/index.d.ts.map +1 -1
  8. package/dist/src/check/index.js +3 -4
  9. package/dist/src/check/index.js.map +1 -1
  10. package/dist/src/check.d.ts +44 -9
  11. package/dist/src/check.d.ts.map +1 -1
  12. package/dist/src/check.js +130 -53
  13. package/dist/src/check.js.map +1 -1
  14. package/dist/src/compat.d.ts +384 -0
  15. package/dist/src/compat.d.ts.map +1 -0
  16. package/dist/src/compat.js +258 -0
  17. package/dist/src/compat.js.map +1 -0
  18. package/dist/src/index.d.ts +12 -9
  19. package/dist/src/index.d.ts.map +1 -1
  20. package/dist/src/index.js +12 -9
  21. package/dist/src/index.js.map +1 -1
  22. package/dist/src/s3/index.d.ts.map +1 -1
  23. package/dist/src/s3/index.js +34 -12
  24. package/dist/src/s3/index.js.map +1 -1
  25. package/dist/src/storage/index.d.ts +72 -3
  26. package/dist/src/storage/index.d.ts.map +1 -1
  27. package/dist/src/storage/index.js +258 -13
  28. package/dist/src/storage/index.js.map +1 -1
  29. package/dist/src/sync/engine.d.ts +282 -49
  30. package/dist/src/sync/engine.d.ts.map +1 -1
  31. package/dist/src/sync/engine.js +599 -110
  32. package/dist/src/sync/engine.js.map +1 -1
  33. package/dist/src/sync/index.d.ts +3 -2
  34. package/dist/src/sync/index.d.ts.map +1 -1
  35. package/dist/src/sync/index.js +3 -2
  36. package/dist/src/sync/index.js.map +1 -1
  37. package/dist/src/sync/memory.d.ts +67 -12
  38. package/dist/src/sync/memory.d.ts.map +1 -1
  39. package/dist/src/sync/memory.js +248 -18
  40. package/dist/src/sync/memory.js.map +1 -1
  41. package/dist/src/sync/push.d.ts +56 -0
  42. package/dist/src/sync/push.d.ts.map +1 -0
  43. package/dist/src/sync/push.js +205 -0
  44. package/dist/src/sync/push.js.map +1 -0
  45. package/dist/test/typed.examples.d.ts +49 -0
  46. package/dist/test/typed.examples.d.ts.map +1 -0
  47. package/dist/test/typed.examples.js +58 -0
  48. package/dist/test/typed.examples.js.map +1 -0
  49. package/package.json +10 -6
@@ -2,7 +2,16 @@
2
2
  * Copyright (c) 2025 Elara AI Pty Ltd
3
3
  * Licensed under BSL 1.1. See LICENSE for details.
4
4
  */
5
- import { FilesUnreadableError, NO_LEDGER } from './engine.js';
5
+ /**
6
+ * The sync's ports in memory: a bucket, a workspace's inputs and records,
7
+ * and a ledger, for unit tests and for the portable suite every
8
+ * implementation runs.
9
+ *
10
+ * @packageDocumentation
11
+ */
12
+ import { createHash } from 'node:crypto';
13
+ import { decodeBeast2For, none, some, variant } from '@elaraai/east';
14
+ import { FilesUnreadableError, NO_LEDGER, } from './engine.js';
6
15
  /** Items as an async iterable, as a store's paged listing gives them. */
7
16
  function iterate(items) {
8
17
  return {
@@ -14,14 +23,44 @@ function iterate(items) {
14
23
  },
15
24
  };
16
25
  }
26
+ /** The bytes of a stream, whole. */
27
+ async function whole(stream) {
28
+ const chunks = [];
29
+ let length = 0;
30
+ for await (const chunk of stream) {
31
+ chunks.push(chunk);
32
+ length += chunk.length;
33
+ }
34
+ const bytes = new Uint8Array(length);
35
+ let at = 0;
36
+ for (const chunk of chunks) {
37
+ bytes.set(chunk, at);
38
+ at += chunk.length;
39
+ }
40
+ return bytes;
41
+ }
42
+ /** A value's SHA-256, hex. */
43
+ function sha256Of(bytes) {
44
+ return createHash('sha256').update(bytes).digest('hex');
45
+ }
46
+ /** How many rows a collection holds; null for a value that is none. */
47
+ function rowsOf(value) {
48
+ if (Array.isArray(value))
49
+ return BigInt(value.length);
50
+ if (value instanceof Map || value instanceof Set)
51
+ return BigInt(value.size);
52
+ return null;
53
+ }
17
54
  /** A bucket in memory: files by key, each with its time and an ETag that changes with its bytes. */
18
55
  export class MemoryBucket {
19
56
  #files = new Map();
20
57
  /** Why each file a reader may not read is refused, by key */
21
58
  #refused = new Map();
22
59
  #version = 0;
23
- /** How many times a file's bytes were read, for tests that hold a sync to reading only what changed */
60
+ /** How many times a file's bytes were read whole or streamed, for tests that hold a sync to reading only what changed */
24
61
  reads = 0;
62
+ /** How many ranges of files' bytes were read, for tests that hold a typed sync to reading a header first */
63
+ rangeReads = 0;
25
64
  /** How many listings were asked for, for tests that hold a sync to listing a prefix once */
26
65
  listings = 0;
27
66
  /**
@@ -36,10 +75,35 @@ export class MemoryBucket {
36
75
  this.#version += 1;
37
76
  this.#files.set(key, { bytes: data, modified, etag: `"${this.#version}-${data.length}"` });
38
77
  }
78
+ /**
79
+ * Writes a file's bytes again under a new ETag, as a multipart upload of
80
+ * the same bytes leaves it.
81
+ *
82
+ * @param key - Its key
83
+ */
84
+ touch(key) {
85
+ const file = this.#files.get(key);
86
+ if (file === undefined)
87
+ return;
88
+ this.#version += 1;
89
+ this.#files.set(key, { ...file, etag: `"${this.#version}-${file.bytes.length}-again"` });
90
+ }
39
91
  /** Deletes a file. */
40
92
  delete(key) {
41
93
  this.#files.delete(key);
42
94
  }
95
+ /** A file's bytes, for a test; undefined when there is none. */
96
+ get(key) {
97
+ return this.#files.get(key)?.bytes;
98
+ }
99
+ /** A file's ETag, as a listing gives it; undefined when there is none. */
100
+ etagOf(key) {
101
+ return this.#files.get(key)?.etag;
102
+ }
103
+ /** Every key, in order. */
104
+ keys() {
105
+ return [...this.#files.keys()].sort();
106
+ }
43
107
  /**
44
108
  * Makes a file unreadable, as an archived file, or one encrypted with a key
45
109
  * the reader may not use, is: listed, but refused when read.
@@ -64,8 +128,20 @@ export class MemoryBucket {
64
128
  const files = this.#files;
65
129
  const refused = this.#refused;
66
130
  const counted = () => { this.reads += 1; };
131
+ const ranged = () => { this.rangeReads += 1; };
67
132
  const listedOnce = () => { this.listings += 1; };
68
133
  const listed = (key, file) => ({ key: key.slice(prefix.length), size: file.bytes.length, modified: file.modified, etag: file.etag });
134
+ const readable = (object) => {
135
+ const file = files.get(prefix + object.key);
136
+ if (file === undefined)
137
+ throw new FilesUnreadableError(object.key, 'went while the sync read it');
138
+ if (file.etag !== object.etag)
139
+ throw new FilesUnreadableError(object.key, 'changed since it was listed: the next sync takes it');
140
+ const reason = refused.get(prefix + object.key);
141
+ if (reason !== undefined)
142
+ throw new FilesUnreadableError(object.key, reason);
143
+ return file;
144
+ };
69
145
  return {
70
146
  list(under, options = {}) {
71
147
  listedOnce();
@@ -79,30 +155,64 @@ export class MemoryBucket {
79
155
  return Promise.resolve(file === undefined ? null : listed(prefix + key, file));
80
156
  },
81
157
  read(object) {
82
- const file = files.get(prefix + object.key);
83
- if (file === undefined)
84
- return Promise.reject(new FilesUnreadableError(object.key, 'went while the sync read it'));
85
- if (file.etag !== object.etag)
86
- return Promise.reject(new FilesUnreadableError(object.key, 'changed since it was listed: the next sync takes it'));
87
- const reason = refused.get(prefix + object.key);
88
- if (reason !== undefined)
89
- return Promise.reject(new FilesUnreadableError(object.key, reason));
90
- counted();
91
- return Promise.resolve(file.bytes);
158
+ try {
159
+ const file = readable(object);
160
+ counted();
161
+ return Promise.resolve(file.bytes);
162
+ }
163
+ catch (err) {
164
+ return Promise.reject(err);
165
+ }
166
+ },
167
+ readRange(object, start, end) {
168
+ try {
169
+ const file = readable(object);
170
+ ranged();
171
+ return Promise.resolve(file.bytes.subarray(start, end));
172
+ }
173
+ catch (err) {
174
+ return Promise.reject(err);
175
+ }
176
+ },
177
+ open(object, options = {}) {
178
+ try {
179
+ const file = readable(object);
180
+ counted();
181
+ // A stream of chunks, as a bucket's body comes, from the byte asked
182
+ const chunks = [];
183
+ for (let at = options.start ?? 0; at < file.bytes.length; at += 1024)
184
+ chunks.push(file.bytes.subarray(at, Math.min(at + 1024, file.bytes.length)));
185
+ return Promise.resolve(iterate(chunks));
186
+ }
187
+ catch (err) {
188
+ return Promise.reject(err);
189
+ }
92
190
  },
93
191
  };
94
192
  }
95
193
  }
96
- /** A workspace's inputs in memory: what a sync wrote to each, and a hash of each value. */
194
+ /** A workspace's inputs and records in memory: what a sync wrote to each, and a hash of each value. */
97
195
  export class MemoryWorkspace {
98
- /** Each `file` or `latest` input's bytes */
196
+ /** Each untyped `file` or `latest` input's bytes */
99
197
  files = new Map();
198
+ /** Each typed input's value, decoded */
199
+ typed = new Map();
100
200
  /** Each `folder` input's entries */
101
201
  folders = new Map();
102
202
  /** Each `listing` input's rows */
103
203
  listings = new Map();
104
204
  /** How many times each input was written */
105
205
  writes = new Map();
206
+ /** Each record declared, by name: pending until seeded */
207
+ records = new Map();
208
+ /** Mutations that refuse every feed, by `record.mutation`, with what they answer */
209
+ refusing = new Map();
210
+ /** Mutations whose record is busy, by `record.mutation`: a feed waits, with the reason */
211
+ waiting = new Map();
212
+ /** Whether the next typed intake stops before it finishes, as a round's deadline stops one */
213
+ yieldNextIntake = false;
214
+ /** Each typed intake's SHA-256 and the hash it gave, so the same bytes give the same hash */
215
+ #memo = new Map();
106
216
  #values = new Map();
107
217
  #version = 0;
108
218
  /** Records a write, and answers the value's hash: a new one each time. */
@@ -116,10 +226,38 @@ export class MemoryWorkspace {
116
226
  /** Empties an input, as a deploy that resets the workspace's inputs does. */
117
227
  reset(input) {
118
228
  this.files.delete(input);
229
+ this.typed.delete(input);
119
230
  this.folders.delete(input);
120
231
  this.listings.delete(input);
121
232
  this.#values.delete(input);
122
233
  }
234
+ /**
235
+ * Declares a record with no state, pending until seeded, or with a state
236
+ * the package gave it (one commit, `$init`).
237
+ *
238
+ * @param name - The record
239
+ * @param state - Its initial state, if the package declares one
240
+ */
241
+ declareRecord(name, state) {
242
+ this.records.set(name, state === undefined ? { commits: [] } : { commits: [{ name: '$init', id: `${name}#1`, sha256: null }], state });
243
+ }
244
+ /**
245
+ * Mutates a record, as an app's user does: a commit by a mutation's name,
246
+ * its state replaced.
247
+ *
248
+ * @param record - The record
249
+ * @param mutation - The mutation's name
250
+ * @param state - The state after it
251
+ */
252
+ mutate(record, mutation, state) {
253
+ const kept = this.records.get(record);
254
+ if (kept === undefined || kept.commits.length === 0)
255
+ throw new Error(`record ${record} has no state yet`);
256
+ const id = `${record}#${kept.commits.length + 1}`;
257
+ kept.commits.push({ name: mutation, id, sha256: null });
258
+ kept.state = state;
259
+ return id;
260
+ }
123
261
  current(input) {
124
262
  return Promise.resolve(this.#values.get(input) ?? null);
125
263
  }
@@ -140,15 +278,107 @@ export class MemoryWorkspace {
140
278
  this.listings.set(input, new Map(rows));
141
279
  return Promise.resolve(this.#wrote(input));
142
280
  }
281
+ /** A typed file's bytes, read through the reader's stream, decoded as the type. */
282
+ async #decoded(file, type, source) {
283
+ let bytes;
284
+ try {
285
+ bytes = await whole(await source.open(file));
286
+ }
287
+ catch (err) {
288
+ if (err instanceof FilesUnreadableError)
289
+ return { reason: variant('unreadable', err.reason) };
290
+ throw err;
291
+ }
292
+ try {
293
+ return { bytes, sha256: sha256Of(bytes), value: decodeBeast2For(type)(bytes) };
294
+ }
295
+ catch (err) {
296
+ return { reason: variant('not_beast2', err instanceof Error ? err.message : String(err)) };
297
+ }
298
+ }
299
+ async takeTyped(input, file, type, source, options) {
300
+ const decoded = await this.#decoded(file, type, source);
301
+ if ('reason' in decoded)
302
+ return { status: 'refused', reason: decoded.reason };
303
+ const { sha256, value } = decoded;
304
+ if (this.yieldNextIntake && options.resume === undefined) {
305
+ this.yieldNextIntake = false;
306
+ return { status: 'yielded', taking: { key: file.key, etag: file.etag, sha256, staging: null } };
307
+ }
308
+ // The same bytes give the same value: the store's memo
309
+ let hash = this.#memo.get(`${input}\u0000${sha256}`);
310
+ if (hash === undefined) {
311
+ hash = this.#wrote(input);
312
+ this.#memo.set(`${input}\u0000${sha256}`, hash);
313
+ }
314
+ else {
315
+ this.#values.set(input, hash);
316
+ }
317
+ this.typed.set(input, value);
318
+ const rows = rowsOf(value);
319
+ return { status: 'taken', hash, sha256, taken: { key: file.key, type, rows: rows === null ? none : some(rows), how: variant('carried', null) } };
320
+ }
321
+ recordState(record) {
322
+ const kept = this.records.get(record);
323
+ if (kept === undefined)
324
+ return Promise.reject(new Error(`record ${record} is not declared`));
325
+ if (kept.commits.length === 0)
326
+ return Promise.resolve({ pending: true });
327
+ const head = kept.commits[kept.commits.length - 1];
328
+ let sinceSeed = null;
329
+ for (let i = kept.commits.length - 1; i >= 0; i--) {
330
+ const name = kept.commits[i].name;
331
+ if (name === '$init' || name === '$seed') {
332
+ sinceSeed = kept.commits.length - 1 - i;
333
+ break;
334
+ }
335
+ }
336
+ return Promise.resolve({ pending: false, head: head.id, sinceSeed });
337
+ }
338
+ async seed(record, file, type, source, options) {
339
+ const kept = this.records.get(record);
340
+ if (kept === undefined)
341
+ throw new Error(`record ${record} is not declared`);
342
+ const decoded = await this.#decoded(file, type, source);
343
+ if ('reason' in decoded)
344
+ return { status: 'refused', reason: decoded.reason };
345
+ const id = `${record}#${kept.commits.length + 1}`;
346
+ kept.commits.push({ name: options.genesis ? '$init' : '$seed', id, sha256: decoded.sha256 });
347
+ kept.state = decoded.value;
348
+ return { status: 'committed', commit: id, rows: rowsOf(decoded.value), sha256: decoded.sha256 };
349
+ }
350
+ async feed(record, mutation, file, type, source, options) {
351
+ const kept = this.records.get(record);
352
+ if (kept === undefined)
353
+ throw new Error(`record ${record} is not declared`);
354
+ if (kept.commits.length === 0)
355
+ return { status: 'waiting', reason: 'the record has no state yet' };
356
+ const decoded = await this.#decoded(file, type, source);
357
+ if ('reason' in decoded)
358
+ return { status: 'refused', reason: decoded.reason, sha256: '' };
359
+ // Once per delivery: bytes applied before, under any name, are applied no more
360
+ if (options.applied?.has(decoded.sha256) === true)
361
+ return { status: 'applied', sha256: decoded.sha256 };
362
+ const busy = this.waiting.get(`${record}.${mutation}`);
363
+ if (busy !== undefined)
364
+ return { status: 'waiting', reason: busy };
365
+ const refused = this.refusing.get(`${record}.${mutation}`);
366
+ if (refused !== undefined)
367
+ return { status: 'refused', reason: variant('mutation', refused), sha256: decoded.sha256 };
368
+ const id = `${record}#${kept.commits.length + 1}`;
369
+ kept.commits.push({ name: mutation, id, sha256: decoded.sha256 });
370
+ kept.state = decoded.value;
371
+ return { status: 'committed', commit: id, sha256: decoded.sha256 };
372
+ }
143
373
  }
144
374
  /** A ledger in memory. */
145
375
  export class MemoryLedger {
146
376
  #states = new Map();
147
- read(input) {
148
- return Promise.resolve(this.#states.get(input) ?? NO_LEDGER);
377
+ read(key) {
378
+ return Promise.resolve(this.#states.get(key) ?? NO_LEDGER);
149
379
  }
150
- write(input, state) {
151
- this.#states.set(input, { entries: new Map(state.entries), value: state.value, under: state.under });
380
+ write(key, state) {
381
+ this.#states.set(key, { ...state, entries: new Map(state.entries) });
152
382
  return Promise.resolve();
153
383
  }
154
384
  }
@@ -1 +1 @@
1
- {"version":3,"file":"memory.js","sourceRoot":"","sources":["../../../src/sync/memory.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"memory.js","sourceRoot":"","sources":["../../../src/sync/memory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Licensed under BSL 1.1. See LICENSE for details.
4
+ */
5
+ import { type FilesBinding, type FilesManifest, type FilesPushFile, type FilesPushRefusal, type FilesTarget } from '@elaraai/e3-cloud-types';
6
+ import type { FilesObject, LedgerState } from './engine.js';
7
+ /** What a push's plan is given. */
8
+ export interface PushPlanInput {
9
+ /** The declarations */
10
+ readonly manifest: FilesManifest;
11
+ /** Where each source's files are */
12
+ readonly bindings: readonly FilesBinding[];
13
+ /** The files offered: a file's own name, or its path relative to the directory it came from, with that directory's name */
14
+ readonly files: readonly FilesPushFile[];
15
+ /** The target every file is for, as `--as` names it; null to match each by its name */
16
+ readonly as: string | null;
17
+ /** What a target took last */
18
+ readonly ledger: (target: FilesTarget) => Promise<LedgerState>;
19
+ /**
20
+ * The greatest key a `latest` mapping's prefix holds that its glob
21
+ * matches, through the binding's reader; null for none. Absent, a
22
+ * `latest` file is not held to being the greatest.
23
+ */
24
+ readonly listGreatest?: (binding: FilesBinding, prefix: string, include: string | null) => Promise<FilesObject | null>;
25
+ /** A key's file in the source, for the unchanged check; absent, a file the ledger holds is unchanged by its hash alone */
26
+ readonly stat?: (binding: FilesBinding, key: string) => Promise<FilesObject | null>;
27
+ }
28
+ /** What a push does with one file, before its upload is added: its target, source and key, or why not. */
29
+ export type PushPlanOutcome = {
30
+ readonly kind: 'put';
31
+ readonly target: FilesTarget;
32
+ readonly source: string;
33
+ readonly key: string;
34
+ readonly binding: FilesBinding;
35
+ } | {
36
+ readonly kind: 'unchanged';
37
+ readonly target: FilesTarget;
38
+ readonly source: string;
39
+ readonly key: string;
40
+ } | {
41
+ readonly kind: 'refused';
42
+ readonly refusal: FilesPushRefusal;
43
+ };
44
+ /** A file's planned outcome. */
45
+ export interface PushPlannedFile {
46
+ readonly file: FilesPushFile;
47
+ readonly outcome: PushPlanOutcome;
48
+ }
49
+ /**
50
+ * Plans a push: see the module's documentation.
51
+ *
52
+ * @param input - The declarations, the bindings, the files, the target named, and the readers
53
+ * @returns Each file's outcome, in the files' order
54
+ */
55
+ export declare function planPush(input: PushPlanInput): Promise<PushPlannedFile[]>;
56
+ //# sourceMappingURL=push.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"push.d.ts","sourceRoot":"","sources":["../../../src/sync/push.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAoCH,OAAO,EAGL,KAAK,YAAY,EAAE,KAAK,aAAa,EAAqB,KAAK,aAAa,EAAE,KAAK,gBAAgB,EAAE,KAAK,WAAW,EACtH,MAAM,yBAAyB,CAAC;AAEjC,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE5D,mCAAmC;AACnC,MAAM,WAAW,aAAa;IAC5B,uBAAuB;IACvB,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC;IACjC,oCAAoC;IACpC,QAAQ,CAAC,QAAQ,EAAE,SAAS,YAAY,EAAE,CAAC;IAC3C,2HAA2H;IAC3H,QAAQ,CAAC,KAAK,EAAE,SAAS,aAAa,EAAE,CAAC;IACzC,uFAAuF;IACvF,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,8BAA8B;IAC9B,QAAQ,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;IAC/D;;;;OAIG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,KAAK,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IACvH,0HAA0H;IAC1H,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;CACrF;AAED,0GAA0G;AAC1G,MAAM,MAAM,eAAe,GACvB;IAAE,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAA;CAAE,GACrI;IAAE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAC3G;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,gBAAgB,CAAA;CAAE,CAAC;AAErE,gCAAgC;AAChC,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;CACnC;AAqDD;;;;;GAKG;AACH,wBAAsB,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAwG/E"}
@@ -0,0 +1,205 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Licensed under BSL 1.1. See LICENSE for details.
4
+ */
5
+ /**
6
+ * A push's plan: files from disk matched to the mappings that
7
+ * take them, checked, and each answered put (at a key of the mapping's),
8
+ * unchanged (the source holds those bytes already) or refused. Pure: the
9
+ * route and the local CLI share it, each giving it the declarations, the
10
+ * bindings, the ledgers and a listing of a `latest` prefix through its own
11
+ * reader. The plan writes nothing; how a put is uploaded (a signed URL, or
12
+ * the client's own credentials) is the caller's to add.
13
+ *
14
+ * Each target's ledger and each `latest` prefix's listing are read once a
15
+ * plan, however many files it offers.
16
+ *
17
+ * Matching, in order:
18
+ * 1. `as` names one target for every file (`orders`, `record:customers`,
19
+ * `mutation:prices.load_prices`; a bare name is an input's): a file goes
20
+ * to a `file` or `latest` mapping, a directory's files to a `folder`.
21
+ * 2. Else a file matches the one `file` mapping whose key's last segment is
22
+ * its name (an exact match, which comes first), or the one `latest`
23
+ * mapping under whose prefix it lands at its own name, its `include`
24
+ * matched; a directory's files match the one `folder` mapping, each at
25
+ * its relative path. Several candidates are `ambiguous`, none
26
+ * `no_mapping`; a file the mapping's `include` glob leaves out is
27
+ * `not_included`, since no sync would take it.
28
+ * 3. A typed mapping holds the file's header type to its own.
29
+ * 4. The mapping's limit holds the file's size.
30
+ * 5. A `latest` mapping refuses a file a greater key than its own would
31
+ * shadow.
32
+ * 6. A file whose bytes the ledger holds for its key, the key still carrying
33
+ * the ledger's ETag, is `unchanged`.
34
+ *
35
+ * @packageDocumentation
36
+ */
37
+ import { isTypeValueEqual, variant } from '@elaraai/east';
38
+ import { FILES_FILE_MAX_BYTES, FILES_FOLDER_ENTRY_MAX_BYTES, FILES_TYPED_VALUE_MAX_BYTES, filesTargetText, parseFilesTarget, sameFilesTarget, } from '@elaraai/e3-cloud-types';
39
+ import { globMatcher } from '../paths.js';
40
+ /** The last segment of a key. */
41
+ function lastSegment(key) {
42
+ return key.slice(key.lastIndexOf('/') + 1);
43
+ }
44
+ /** Whether a type is a collection's: an Array, Set or Dict root, which beast2 stores in segments of any number. */
45
+ function isCollection(type) {
46
+ return type.type === 'Array' || type.type === 'Set' || type.type === 'Dict';
47
+ }
48
+ /** The type a `file` or `latest` shape names; null for none. */
49
+ function namedType(mapping) {
50
+ const { shape } = mapping;
51
+ if (shape.type !== 'file' && shape.type !== 'latest')
52
+ return null;
53
+ return shape.value.type.type === 'some' ? shape.value.type.value : null;
54
+ }
55
+ /**
56
+ * The mappings a file of a name matches by its name: the `file` mappings
57
+ * whose key's last segment is the name, which are the exact matches; else
58
+ * the `latest` mappings whose glob matches it.
59
+ */
60
+ function byName(manifest, name) {
61
+ const exact = manifest.mappings.filter((m) => m.shape.type === 'file' && lastSegment(m.shape.value.key) === name);
62
+ if (exact.length > 0)
63
+ return exact;
64
+ return manifest.mappings.filter((m) => m.shape.type === 'latest' && globMatcher(m.shape.value.include.type === 'some' ? m.shape.value.include.value : null)(name));
65
+ }
66
+ /** The key a file lands at under a mapping. */
67
+ function keyUnder(mapping, file) {
68
+ const { shape } = mapping;
69
+ switch (shape.type) {
70
+ case 'file': return shape.value.key;
71
+ case 'latest':
72
+ case 'folder':
73
+ case 'listing':
74
+ return `${shape.value.prefix}${file.name}`;
75
+ }
76
+ }
77
+ /** The largest file a mapping takes, from the file's own type; null for a typed collection, which has no limit but its segments'. */
78
+ function limitOf(mapping, fileType) {
79
+ const { shape, target } = mapping;
80
+ if (shape.type === 'folder')
81
+ return FILES_FOLDER_ENTRY_MAX_BYTES;
82
+ if (shape.type === 'listing')
83
+ return 0;
84
+ const type = namedType(mapping);
85
+ if (type === null)
86
+ return FILES_FILE_MAX_BYTES;
87
+ if (target.type === 'mutation')
88
+ return FILES_TYPED_VALUE_MAX_BYTES;
89
+ return fileType !== null && isCollection(fileType) ? null : FILES_TYPED_VALUE_MAX_BYTES;
90
+ }
91
+ /**
92
+ * Plans a push: see the module's documentation.
93
+ *
94
+ * @param input - The declarations, the bindings, the files, the target named, and the readers
95
+ * @returns Each file's outcome, in the files' order
96
+ */
97
+ export async function planPush(input) {
98
+ const { manifest, bindings, files } = input;
99
+ const named = input.as === null ? null : parseFilesTarget(input.as);
100
+ const namedMapping = named === null ? null : manifest.mappings.find((m) => sameFilesTarget(m.target, named)) ?? null;
101
+ const bindingOf = (source) => bindings.find((b) => b.source === source);
102
+ // Each ledger and each listing read once a plan
103
+ const ledgers = new Map();
104
+ const ledgerOf = (target) => {
105
+ const text = filesTargetText(target);
106
+ let read = ledgers.get(text);
107
+ if (read === undefined)
108
+ ledgers.set(text, read = input.ledger(target));
109
+ return read;
110
+ };
111
+ const greatests = new Map();
112
+ const greatestOf = (binding, prefix, include) => {
113
+ const text = `${binding.source}\u0000${prefix}\u0000${include ?? ''}`;
114
+ let listed = greatests.get(text);
115
+ if (listed === undefined)
116
+ greatests.set(text, listed = input.listGreatest(binding, prefix, include));
117
+ return listed;
118
+ };
119
+ const planned = [];
120
+ for (const file of files) {
121
+ const refused = (refusal) => ({ file, outcome: { kind: 'refused', refusal } });
122
+ const fromDirectory = file.directory.type === 'some';
123
+ // 1, 2: the mapping
124
+ let mapping;
125
+ if (input.as !== null) {
126
+ if (namedMapping === null) {
127
+ planned.push(refused(variant('unknown_target', input.as)));
128
+ continue;
129
+ }
130
+ mapping = namedMapping;
131
+ }
132
+ else {
133
+ const candidates = fromDirectory
134
+ ? manifest.mappings.filter((m) => m.shape.type === 'folder')
135
+ : byName(manifest, file.name);
136
+ if (candidates.length === 0) {
137
+ planned.push(refused(variant('no_mapping', null)));
138
+ continue;
139
+ }
140
+ if (candidates.length > 1) {
141
+ planned.push(refused(variant('ambiguous', candidates.map((m) => m.target))));
142
+ continue;
143
+ }
144
+ mapping = candidates[0];
145
+ }
146
+ const { target, shape } = mapping;
147
+ const takesOne = shape.type === 'file' || shape.type === 'latest';
148
+ if (fromDirectory ? takesOne || shape.type === 'listing' : !takesOne) {
149
+ planned.push(refused(variant('shape_mismatch', { target, directory: fromDirectory })));
150
+ continue;
151
+ }
152
+ // A file the mapping's glob leaves out is put where no sync takes it
153
+ if ((shape.type === 'latest' || shape.type === 'folder') && shape.value.include.type === 'some' && !globMatcher(shape.value.include.value)(file.name)) {
154
+ planned.push(refused(variant('not_included', { target, include: shape.value.include.value })));
155
+ continue;
156
+ }
157
+ // 3: the type
158
+ const expected = namedType(mapping);
159
+ const actual = file.type.type === 'some' ? file.type.value : null;
160
+ if (expected !== null) {
161
+ if (actual === null) {
162
+ planned.push(refused(variant('not_beast2', { target, expected })));
163
+ continue;
164
+ }
165
+ if (!isTypeValueEqual(actual, expected)) {
166
+ planned.push(refused(variant('type_mismatch', { target, expected, actual })));
167
+ continue;
168
+ }
169
+ }
170
+ // 4: the size
171
+ const limit = limitOf(mapping, actual);
172
+ if (limit !== null && Number(file.size) > limit) {
173
+ planned.push(refused(variant('too_large', { target, size: file.size, limit: BigInt(limit) })));
174
+ continue;
175
+ }
176
+ const binding = bindingOf(mapping.source);
177
+ if (binding === undefined) {
178
+ // Held off by the caller: a push to an unbound source has nowhere to go
179
+ planned.push(refused(variant('unknown_target', `${filesTargetText(target)} (its source ${mapping.source} is not bound)`)));
180
+ continue;
181
+ }
182
+ const key = keyUnder(mapping, file);
183
+ // 5: the greatest key under a latest prefix
184
+ if (shape.type === 'latest' && input.listGreatest !== undefined) {
185
+ const greatest = await greatestOf(binding, shape.value.prefix, shape.value.include.type === 'some' ? shape.value.include.value : null);
186
+ if (greatest !== null && greatest.key > key) {
187
+ planned.push(refused(variant('not_latest', { target, greatest: greatest.key })));
188
+ continue;
189
+ }
190
+ }
191
+ // 6: unchanged, by the bytes' hash and the key's ETag
192
+ const ledger = await ledgerOf(target);
193
+ const held = ledger.entries.get(key);
194
+ if (held?.sha256 === file.sha256) {
195
+ const there = input.stat === undefined ? null : await input.stat(binding, key);
196
+ if (input.stat === undefined || (there !== null && there.etag === held.etag)) {
197
+ planned.push({ file, outcome: { kind: 'unchanged', target, source: mapping.source, key } });
198
+ continue;
199
+ }
200
+ }
201
+ planned.push({ file, outcome: { kind: 'put', target, source: mapping.source, key, binding } });
202
+ }
203
+ return planned;
204
+ }
205
+ //# sourceMappingURL=push.js.map