@amalgm/live 0.2.58 → 0.2.59
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/PURPOSE.md +15 -12
- package/dist/transfer/cargo.d.ts +11 -0
- package/dist/transfer/cargo.d.ts.map +1 -1
- package/dist/transfer/cargo.js +97 -23
- package/dist/transfer/cargo.js.map +1 -1
- package/dist/transfer/index.d.ts +1 -0
- package/dist/transfer/index.d.ts.map +1 -1
- package/dist/transfer/index.js +1 -0
- package/dist/transfer/index.js.map +1 -1
- package/dist/transfer/stream.d.ts +50 -0
- package/dist/transfer/stream.d.ts.map +1 -0
- package/dist/transfer/stream.js +78 -0
- package/dist/transfer/stream.js.map +1 -0
- package/dist-cjs/transfer/cargo.js +98 -23
- package/dist-cjs/transfer/cargo.js.map +1 -1
- package/dist-cjs/transfer/index.js +1 -0
- package/dist-cjs/transfer/index.js.map +1 -1
- package/dist-cjs/transfer/stream.js +81 -0
- package/dist-cjs/transfer/stream.js.map +1 -0
- package/package.json +1 -1
package/PURPOSE.md
CHANGED
|
@@ -186,24 +186,27 @@ its cutover.
|
|
|
186
186
|
neither act may weaken the other's result.
|
|
187
187
|
30. **Proof travels forward; disposable bytes need not.** Registration reads
|
|
188
188
|
every ordinary text or binary file through one bounded stream to classify
|
|
189
|
-
it
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
can recapture current ground; stale bytes can never be sealed or
|
|
197
|
-
published.
|
|
189
|
+
it and derive its content head. When cloud cargo is missing, that same
|
|
190
|
+
capture stream carries the verified bytes forward: bounded complete small
|
|
191
|
+
artifacts enter the cargo stream, while large-file blocks become durable
|
|
192
|
+
under their own digests as they are read and the authority seals the
|
|
193
|
+
manifest only after every named block exists. A graph-only Register
|
|
194
|
+
capture never copies or rereads ground merely to preserve bytes for a
|
|
195
|
+
later Upload stage. A typed source mismatch returns control to Register so
|
|
196
|
+
it can recapture current ground; stale bytes can never be sealed or
|
|
197
|
+
published. A final missing-cargo inventory remains the publication
|
|
198
|
+
guarantor and may reread ground only when fused transport was unavailable
|
|
199
|
+
or refused. During Add, ordinary text and binary bytes land directly in
|
|
198
200
|
their hidden staged destinations in manifest order while set-wide fetches
|
|
199
201
|
remain bounded and concurrent, so their whole-artifact proof advances from
|
|
200
202
|
arriving bytes without rereading staging; links and repository transports
|
|
201
203
|
keep their dedicated adapter/cache rails. No file type or size permits a
|
|
202
204
|
complete-file allocation in the bounded transfer path.
|
|
203
205
|
31. **A content block is not a round trip.** Text and binary retain independent
|
|
204
|
-
content-addressed block identities. Cold upload
|
|
205
|
-
artifacts in bounded cargo
|
|
206
|
-
|
|
206
|
+
content-addressed block identities. Cold upload moves complete small
|
|
207
|
+
artifacts in bounded cargo segments and adjacent missing large-file
|
|
208
|
+
blocks in bounded binary batches, while cold download merges packed spans.
|
|
209
|
+
Packing may reduce
|
|
207
210
|
transport work but can never weaken per-block verification, durable sealing,
|
|
208
211
|
or commit order.
|
|
209
212
|
32. **A content layout owns a cloud namespace.** A writer change that derives
|
package/dist/transfer/cargo.d.ts
CHANGED
|
@@ -52,6 +52,17 @@ export interface CargoStreamReceipt {
|
|
|
52
52
|
}
|
|
53
53
|
/** Pack items in order into segments within the byte and artifact bounds. */
|
|
54
54
|
export declare function planCargoSegments<T extends CargoItem>(items: readonly T[]): readonly CargoSegment<T>[];
|
|
55
|
+
/** A cargo stream whose items arrive while a walk is still discovering
|
|
56
|
+
* them. Full segments ship as they close; `add` applies backpressure when
|
|
57
|
+
* the shared window is full, and `flush` ships the final partial segment
|
|
58
|
+
* and settles every acknowledgement. After any rejection, `flush` still
|
|
59
|
+
* settles in-flight segments before rethrowing the first failure, so their
|
|
60
|
+
* sealed work stays durable for the resuming rerun. */
|
|
61
|
+
export interface CargoStream<T extends CargoItem> {
|
|
62
|
+
add(item: T): Promise<void>;
|
|
63
|
+
flush(): Promise<CargoStreamReceipt>;
|
|
64
|
+
}
|
|
65
|
+
export declare function openCargoStream<T extends CargoItem>(ports: CargoStreamPorts<T>, options?: CargoStreamOptions): CargoStream<T>;
|
|
55
66
|
/** Stream one cold set of small artifacts as bounded pipelined segments.
|
|
56
67
|
* Every item must come back sealed or the stream fails; a failure stops new
|
|
57
68
|
* admission, lets in-flight segments settle, and leaves their sealed work
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cargo.d.ts","sourceRoot":"","sources":["../../src/transfer/cargo.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAKH,eAAO,MAAM,mBAAmB,QAA4B,CAAC;AAC7D;;;uDAGuD;AACvD,eAAO,MAAM,uBAAuB,MAAM,CAAC;AAC3C;;;2EAG2E;AAC3E,eAAO,MAAM,4BAA4B,QAA0B,CAAC;AAEpE,MAAM,WAAW,SAAS;IACxB,gEAAgE;IAChE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,iDAAiD;IACjD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,YAAY,CAAC,CAAC,SAAS,SAAS;IAC/C,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,EAAE,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,gBAAgB,CAAC,CAAC,SAAS,SAAS;IACnD;;;uEAGmE;IACnE,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC,CAAC;CAC5D;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CACpC;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;
|
|
1
|
+
{"version":3,"file":"cargo.d.ts","sourceRoot":"","sources":["../../src/transfer/cargo.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAKH,eAAO,MAAM,mBAAmB,QAA4B,CAAC;AAC7D;;;uDAGuD;AACvD,eAAO,MAAM,uBAAuB,MAAM,CAAC;AAC3C;;;2EAG2E;AAC3E,eAAO,MAAM,4BAA4B,QAA0B,CAAC;AAEpE,MAAM,WAAW,SAAS;IACxB,gEAAgE;IAChE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,iDAAiD;IACjD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,YAAY,CAAC,CAAC,SAAS,SAAS;IAC/C,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,EAAE,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,gBAAgB,CAAC,CAAC,SAAS,SAAS;IACnD;;;uEAGmE;IACnE,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC,CAAC;CAC5D;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CACpC;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAcD,6EAA6E;AAC7E,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,SAAS,EACnD,KAAK,EAAE,SAAS,CAAC,EAAE,GAClB,SAAS,YAAY,CAAC,CAAC,CAAC,EAAE,CAiB5B;AAED;;;;;uDAKuD;AACvD,MAAM,WAAW,WAAW,CAAC,CAAC,SAAS,SAAS;IAC9C,GAAG,CAAC,IAAI,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,KAAK,IAAI,OAAO,CAAC,kBAAkB,CAAC,CAAC;CACtC;AAED,wBAAgB,eAAe,CAAC,CAAC,SAAS,SAAS,EACjD,KAAK,EAAE,gBAAgB,CAAC,CAAC,CAAC,EAC1B,OAAO,GAAE,kBAAuB,GAC/B,WAAW,CAAC,CAAC,CAAC,CAuEhB;AAED;;;qCAGqC;AACrC,wBAAsB,WAAW,CAAC,CAAC,SAAS,SAAS,EACnD,KAAK,EAAE,SAAS,CAAC,EAAE,EACnB,KAAK,EAAE,gBAAgB,CAAC,CAAC,CAAC,EAC1B,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,kBAAkB,CAAC,CAS7B"}
|
package/dist/transfer/cargo.js
CHANGED
|
@@ -26,21 +26,24 @@ export const CARGO_SEGMENT_ARTIFACTS = 256;
|
|
|
26
26
|
* fan-out, and worst-case payload residency (plaintext plus one encoded
|
|
27
27
|
* copy per in-flight segment) stays comfortably inside a 1-GiB runtime. */
|
|
28
28
|
export const CARGO_STREAM_IN_FLIGHT_BYTES = 4 * CARGO_SEGMENT_BYTES;
|
|
29
|
+
const assertCargoItem = (item) => {
|
|
30
|
+
if (typeof item.contentHash !== 'string' || item.contentHash.length === 0) {
|
|
31
|
+
throw new Error('cargo item is missing its content identity');
|
|
32
|
+
}
|
|
33
|
+
if (!Number.isSafeInteger(item.bytes) || item.bytes < 0) {
|
|
34
|
+
throw new Error('cargo item byte count is invalid');
|
|
35
|
+
}
|
|
36
|
+
if (item.bytes > CARGO_SEGMENT_BYTES) {
|
|
37
|
+
throw new Error('cargo item exceeds the segment byte bound');
|
|
38
|
+
}
|
|
39
|
+
};
|
|
29
40
|
/** Pack items in order into segments within the byte and artifact bounds. */
|
|
30
41
|
export function planCargoSegments(items) {
|
|
31
42
|
const segments = [];
|
|
32
43
|
let current = [];
|
|
33
44
|
let bytes = 0;
|
|
34
45
|
for (const item of items) {
|
|
35
|
-
|
|
36
|
-
throw new Error('cargo item is missing its content identity');
|
|
37
|
-
}
|
|
38
|
-
if (!Number.isSafeInteger(item.bytes) || item.bytes < 0) {
|
|
39
|
-
throw new Error('cargo item byte count is invalid');
|
|
40
|
-
}
|
|
41
|
-
if (item.bytes > CARGO_SEGMENT_BYTES) {
|
|
42
|
-
throw new Error('cargo item exceeds the segment byte bound');
|
|
43
|
-
}
|
|
46
|
+
assertCargoItem(item);
|
|
44
47
|
if (current.length > 0
|
|
45
48
|
&& (bytes + item.bytes > CARGO_SEGMENT_BYTES || current.length >= CARGO_SEGMENT_ARTIFACTS)) {
|
|
46
49
|
segments.push({ items: current, bytes });
|
|
@@ -54,24 +57,95 @@ export function planCargoSegments(items) {
|
|
|
54
57
|
segments.push({ items: current, bytes });
|
|
55
58
|
return segments;
|
|
56
59
|
}
|
|
60
|
+
export function openCargoStream(ports, options = {}) {
|
|
61
|
+
const lanes = options.lanes ?? DEFAULT_TRANSFER_CONCURRENCY;
|
|
62
|
+
const maxInFlightBytes = options.maxInFlightBytes ?? CARGO_STREAM_IN_FLIGHT_BYTES;
|
|
63
|
+
const inFlight = new Set();
|
|
64
|
+
let inFlightBytes = 0;
|
|
65
|
+
let failure;
|
|
66
|
+
let current = [];
|
|
67
|
+
let currentBytes = 0;
|
|
68
|
+
let segments = 0;
|
|
69
|
+
let artifacts = 0;
|
|
70
|
+
let bytes = 0;
|
|
71
|
+
const dispatch = async (segment) => {
|
|
72
|
+
const weight = Math.max(segment.bytes, 1);
|
|
73
|
+
while (failure === undefined
|
|
74
|
+
&& (inFlight.size >= lanes
|
|
75
|
+
|| (inFlight.size > 0 && inFlightBytes + weight > maxInFlightBytes))) {
|
|
76
|
+
await Promise.race(inFlight);
|
|
77
|
+
}
|
|
78
|
+
if (failure !== undefined)
|
|
79
|
+
throw failure.error;
|
|
80
|
+
inFlightBytes += weight;
|
|
81
|
+
const settled = (async () => {
|
|
82
|
+
const sealed = new Set(await ports.send(segment));
|
|
83
|
+
for (const item of segment.items) {
|
|
84
|
+
if (!sealed.has(item.contentHash)) {
|
|
85
|
+
throw new Error(`cargo authority did not seal ${item.contentHash}`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
segments += 1;
|
|
89
|
+
artifacts += segment.items.length;
|
|
90
|
+
bytes += segment.bytes;
|
|
91
|
+
})().then(() => { inFlight.delete(settled); inFlightBytes -= weight; }, (error) => {
|
|
92
|
+
inFlight.delete(settled);
|
|
93
|
+
inFlightBytes -= weight;
|
|
94
|
+
failure ??= { error };
|
|
95
|
+
});
|
|
96
|
+
inFlight.add(settled);
|
|
97
|
+
};
|
|
98
|
+
const closeCurrent = () => {
|
|
99
|
+
const segment = { items: current, bytes: currentBytes };
|
|
100
|
+
current = [];
|
|
101
|
+
currentBytes = 0;
|
|
102
|
+
return segment;
|
|
103
|
+
};
|
|
104
|
+
return {
|
|
105
|
+
async add(item) {
|
|
106
|
+
assertCargoItem(item);
|
|
107
|
+
if (failure !== undefined)
|
|
108
|
+
throw failure.error;
|
|
109
|
+
if (current.length > 0
|
|
110
|
+
&& (currentBytes + item.bytes > CARGO_SEGMENT_BYTES
|
|
111
|
+
|| current.length >= CARGO_SEGMENT_ARTIFACTS)) {
|
|
112
|
+
await dispatch(closeCurrent());
|
|
113
|
+
}
|
|
114
|
+
current.push(item);
|
|
115
|
+
currentBytes += item.bytes;
|
|
116
|
+
},
|
|
117
|
+
async flush() {
|
|
118
|
+
if (failure === undefined && current.length > 0) {
|
|
119
|
+
try {
|
|
120
|
+
await dispatch(closeCurrent());
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
// The failure is recorded; settle the window before rethrowing.
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
while (inFlight.size > 0)
|
|
127
|
+
await Promise.race(inFlight);
|
|
128
|
+
if (failure !== undefined)
|
|
129
|
+
throw failure.error;
|
|
130
|
+
return { segments, artifacts, bytes };
|
|
131
|
+
},
|
|
132
|
+
};
|
|
133
|
+
}
|
|
57
134
|
/** Stream one cold set of small artifacts as bounded pipelined segments.
|
|
58
135
|
* Every item must come back sealed or the stream fails; a failure stops new
|
|
59
136
|
* admission, lets in-flight segments settle, and leaves their sealed work
|
|
60
137
|
* durable for the resuming rerun. */
|
|
61
138
|
export async function streamCargo(items, ports, options = {}) {
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
bytes += segment.bytes;
|
|
74
|
-
});
|
|
75
|
-
return { segments: segments.length, artifacts, bytes };
|
|
139
|
+
for (const item of items)
|
|
140
|
+
assertCargoItem(item);
|
|
141
|
+
const stream = openCargoStream(ports, options);
|
|
142
|
+
try {
|
|
143
|
+
for (const item of items)
|
|
144
|
+
await stream.add(item);
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
// add() already recorded the failure; flush settles and rethrows it.
|
|
148
|
+
}
|
|
149
|
+
return stream.flush();
|
|
76
150
|
}
|
|
77
151
|
//# sourceMappingURL=cargo.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cargo.js","sourceRoot":"","sources":["../../src/transfer/cargo.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,EAAE,4BAA4B,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAEtF,MAAM,CAAC,MAAM,mBAAmB,GAAG,yBAAyB,CAAC;AAC7D;;;uDAGuD;AACvD,MAAM,CAAC,MAAM,uBAAuB,GAAG,GAAG,CAAC;AAC3C;;;2EAG2E;AAC3E,MAAM,CAAC,MAAM,4BAA4B,GAAG,CAAC,GAAG,mBAAmB,CAAC;AAiCpE,
|
|
1
|
+
{"version":3,"file":"cargo.js","sourceRoot":"","sources":["../../src/transfer/cargo.ts"],"names":[],"mappings":"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"}
|
package/dist/transfer/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/transfer/index.ts"],"names":[],"mappings":"AAAA,wDAAwD;AAExD,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/transfer/index.ts"],"names":[],"mappings":"AAAA,wDAAwD;AAExD,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC"}
|
package/dist/transfer/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/transfer/index.ts"],"names":[],"mappings":"AAAA,wDAAwD;AAExD,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/transfer/index.ts"],"names":[],"mappings":"AAAA,wDAAwD;AAExD,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One-read upload — capture and transport fused.
|
|
3
|
+
*
|
|
4
|
+
* The classic upload (`upload.ts`) needs the whole-file identity up front
|
|
5
|
+
* and a seekable source it may reread. This primitive serves the moment the
|
|
6
|
+
* bytes are first read: the identity is DISCOVERED while one sequential
|
|
7
|
+
* read proceeds. Each full transfer batch of verified blocks — addressed by
|
|
8
|
+
* their own digests, bound to no whole-file identity yet — rides the wire
|
|
9
|
+
* while the next batch is read, and only after the last byte proves the
|
|
10
|
+
* whole-file digest is the manifest sealed. An interrupted or torn stream
|
|
11
|
+
* leaves unreferenced blocks the authority already tolerates, never a
|
|
12
|
+
* sealed artifact; whether the streamed digest matches current ground is
|
|
13
|
+
* the host's stat law, exactly as for the classic capture. Registration
|
|
14
|
+
* owns entity identity — this primitive knows only content.
|
|
15
|
+
*
|
|
16
|
+
* Memory is bounded by construction: one batch on the wire while one batch
|
|
17
|
+
* is read, so a stream holds at most two transfer batches at once.
|
|
18
|
+
*/
|
|
19
|
+
import { type ContentChunk, type ContentManifest } from '../contracts/content.js';
|
|
20
|
+
import type { Sha256Hex } from '../entities/types.js';
|
|
21
|
+
export interface StreamSource {
|
|
22
|
+
/** Exact byte count the source will produce; a short read is refused. */
|
|
23
|
+
readonly bytes: number;
|
|
24
|
+
/** Return exactly `bytes` bytes beginning at `offset`. Called strictly in
|
|
25
|
+
* ascending offset order, never twice for the same span. */
|
|
26
|
+
read(offset: number, bytes: number): Promise<Uint8Array>;
|
|
27
|
+
}
|
|
28
|
+
/** Incremental whole-file digest, since the identity outlives any one call. */
|
|
29
|
+
export interface Sha256Stream {
|
|
30
|
+
update(bytes: Uint8Array): void;
|
|
31
|
+
digestHex(): string;
|
|
32
|
+
}
|
|
33
|
+
export interface StreamUploadPorts {
|
|
34
|
+
readonly sha256Hex: Sha256Hex;
|
|
35
|
+
createSha256(): Sha256Stream;
|
|
36
|
+
/** Store adjacent verified blocks addressed by their own digests. The
|
|
37
|
+
* blocks bind to no artifact yet; resolving means they are durable. */
|
|
38
|
+
putBlocks(chunks: readonly ContentChunk[], bytes: Uint8Array): Promise<void>;
|
|
39
|
+
/** Bind the discovered identity to its block list. The authority seals
|
|
40
|
+
* only when it holds every named block. */
|
|
41
|
+
sealManifest(manifest: ContentManifest): Promise<void>;
|
|
42
|
+
}
|
|
43
|
+
export interface StreamUploadReceipt {
|
|
44
|
+
readonly manifest: ContentManifest;
|
|
45
|
+
readonly uploadedChunks: number;
|
|
46
|
+
}
|
|
47
|
+
/** Upload one file's content from a single sequential read, discovering its
|
|
48
|
+
* identity along the way and sealing the manifest last. */
|
|
49
|
+
export declare function uploadStream(source: StreamSource, ports: StreamUploadPorts): Promise<StreamUploadReceipt>;
|
|
50
|
+
//# sourceMappingURL=stream.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../src/transfer/stream.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAGL,KAAK,YAAY,EACjB,KAAK,eAAe,EACrB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAGtD,MAAM,WAAW,YAAY;IAC3B,yEAAyE;IACzE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB;gEAC4D;IAC5D,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;CAC1D;AAED,+EAA+E;AAC/E,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;IAChC,SAAS,IAAI,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B,YAAY,IAAI,YAAY,CAAC;IAC7B;2EACuE;IACvE,SAAS,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7E;+CAC2C;IAC3C,YAAY,CAAC,QAAQ,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACxD;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;IACnC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACjC;AAwBD;2DAC2D;AAC3D,wBAAsB,YAAY,CAChC,MAAM,EAAE,YAAY,EACpB,KAAK,EAAE,iBAAiB,GACvB,OAAO,CAAC,mBAAmB,CAAC,CAoC9B"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One-read upload — capture and transport fused.
|
|
3
|
+
*
|
|
4
|
+
* The classic upload (`upload.ts`) needs the whole-file identity up front
|
|
5
|
+
* and a seekable source it may reread. This primitive serves the moment the
|
|
6
|
+
* bytes are first read: the identity is DISCOVERED while one sequential
|
|
7
|
+
* read proceeds. Each full transfer batch of verified blocks — addressed by
|
|
8
|
+
* their own digests, bound to no whole-file identity yet — rides the wire
|
|
9
|
+
* while the next batch is read, and only after the last byte proves the
|
|
10
|
+
* whole-file digest is the manifest sealed. An interrupted or torn stream
|
|
11
|
+
* leaves unreferenced blocks the authority already tolerates, never a
|
|
12
|
+
* sealed artifact; whether the streamed digest matches current ground is
|
|
13
|
+
* the host's stat law, exactly as for the classic capture. Registration
|
|
14
|
+
* owns entity identity — this primitive knows only content.
|
|
15
|
+
*
|
|
16
|
+
* Memory is bounded by construction: one batch on the wire while one batch
|
|
17
|
+
* is read, so a stream holds at most two transfer batches at once.
|
|
18
|
+
*/
|
|
19
|
+
import { chunkSizes, manifestFromChunks, } from '../contracts/content.js';
|
|
20
|
+
import { FILE_TRANSFER_BATCH_BYTES } from './batches.js';
|
|
21
|
+
const planStreamBatches = (totalBytes) => {
|
|
22
|
+
const batches = [];
|
|
23
|
+
let offset = 0;
|
|
24
|
+
for (const size of chunkSizes(totalBytes)) {
|
|
25
|
+
const prior = batches.at(-1);
|
|
26
|
+
if (prior && prior.bytes + size <= FILE_TRANSFER_BATCH_BYTES) {
|
|
27
|
+
prior.bytes += size;
|
|
28
|
+
prior.sizes.push(size);
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
batches.push({ offset, bytes: size, sizes: [size] });
|
|
32
|
+
}
|
|
33
|
+
offset += size;
|
|
34
|
+
}
|
|
35
|
+
return batches;
|
|
36
|
+
};
|
|
37
|
+
/** Upload one file's content from a single sequential read, discovering its
|
|
38
|
+
* identity along the way and sealing the manifest last. */
|
|
39
|
+
export async function uploadStream(source, ports) {
|
|
40
|
+
if (!Number.isSafeInteger(source.bytes) || source.bytes <= 0) {
|
|
41
|
+
throw new Error('stream upload source byte count is invalid');
|
|
42
|
+
}
|
|
43
|
+
const whole = ports.createSha256();
|
|
44
|
+
const chunks = [];
|
|
45
|
+
let inFlight;
|
|
46
|
+
try {
|
|
47
|
+
for (const batch of planStreamBatches(source.bytes)) {
|
|
48
|
+
const bytes = await source.read(batch.offset, batch.bytes);
|
|
49
|
+
if (!(bytes instanceof Uint8Array) || bytes.byteLength !== batch.bytes) {
|
|
50
|
+
throw new Error(`stream upload source returned the wrong byte count at offset ${batch.offset}`);
|
|
51
|
+
}
|
|
52
|
+
whole.update(bytes);
|
|
53
|
+
const batchChunks = [];
|
|
54
|
+
let within = 0;
|
|
55
|
+
for (const size of batch.sizes) {
|
|
56
|
+
batchChunks.push({ sha256: ports.sha256Hex(bytes.subarray(within, within + size)), bytes: size });
|
|
57
|
+
within += size;
|
|
58
|
+
}
|
|
59
|
+
chunks.push(...batchChunks);
|
|
60
|
+
await inFlight;
|
|
61
|
+
inFlight = ports.putBlocks(batchChunks, bytes);
|
|
62
|
+
}
|
|
63
|
+
await inFlight;
|
|
64
|
+
inFlight = undefined;
|
|
65
|
+
const checked = manifestFromChunks(whole.digestHex(), chunks);
|
|
66
|
+
if (!checked.ok)
|
|
67
|
+
throw new Error(checked.error);
|
|
68
|
+
await ports.sealManifest(checked.value);
|
|
69
|
+
return { manifest: checked.value, uploadedChunks: chunks.length };
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
// In-flight blocks settle before control returns, so the host may
|
|
73
|
+
// safely close file and network handles after rejection.
|
|
74
|
+
await inFlight?.catch(() => { });
|
|
75
|
+
throw error;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=stream.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream.js","sourceRoot":"","sources":["../../src/transfer/stream.ts"],"names":[],"mappings":"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"}
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
18
|
exports.CARGO_STREAM_IN_FLIGHT_BYTES = exports.CARGO_SEGMENT_ARTIFACTS = exports.CARGO_SEGMENT_BYTES = void 0;
|
|
19
19
|
exports.planCargoSegments = planCargoSegments;
|
|
20
|
+
exports.openCargoStream = openCargoStream;
|
|
20
21
|
exports.streamCargo = streamCargo;
|
|
21
22
|
const batches_js_1 = require("./batches.js");
|
|
22
23
|
const parallel_js_1 = require("./parallel.js");
|
|
@@ -31,21 +32,24 @@ exports.CARGO_SEGMENT_ARTIFACTS = 256;
|
|
|
31
32
|
* fan-out, and worst-case payload residency (plaintext plus one encoded
|
|
32
33
|
* copy per in-flight segment) stays comfortably inside a 1-GiB runtime. */
|
|
33
34
|
exports.CARGO_STREAM_IN_FLIGHT_BYTES = 4 * exports.CARGO_SEGMENT_BYTES;
|
|
35
|
+
const assertCargoItem = (item) => {
|
|
36
|
+
if (typeof item.contentHash !== 'string' || item.contentHash.length === 0) {
|
|
37
|
+
throw new Error('cargo item is missing its content identity');
|
|
38
|
+
}
|
|
39
|
+
if (!Number.isSafeInteger(item.bytes) || item.bytes < 0) {
|
|
40
|
+
throw new Error('cargo item byte count is invalid');
|
|
41
|
+
}
|
|
42
|
+
if (item.bytes > exports.CARGO_SEGMENT_BYTES) {
|
|
43
|
+
throw new Error('cargo item exceeds the segment byte bound');
|
|
44
|
+
}
|
|
45
|
+
};
|
|
34
46
|
/** Pack items in order into segments within the byte and artifact bounds. */
|
|
35
47
|
function planCargoSegments(items) {
|
|
36
48
|
const segments = [];
|
|
37
49
|
let current = [];
|
|
38
50
|
let bytes = 0;
|
|
39
51
|
for (const item of items) {
|
|
40
|
-
|
|
41
|
-
throw new Error('cargo item is missing its content identity');
|
|
42
|
-
}
|
|
43
|
-
if (!Number.isSafeInteger(item.bytes) || item.bytes < 0) {
|
|
44
|
-
throw new Error('cargo item byte count is invalid');
|
|
45
|
-
}
|
|
46
|
-
if (item.bytes > exports.CARGO_SEGMENT_BYTES) {
|
|
47
|
-
throw new Error('cargo item exceeds the segment byte bound');
|
|
48
|
-
}
|
|
52
|
+
assertCargoItem(item);
|
|
49
53
|
if (current.length > 0
|
|
50
54
|
&& (bytes + item.bytes > exports.CARGO_SEGMENT_BYTES || current.length >= exports.CARGO_SEGMENT_ARTIFACTS)) {
|
|
51
55
|
segments.push({ items: current, bytes });
|
|
@@ -59,24 +63,95 @@ function planCargoSegments(items) {
|
|
|
59
63
|
segments.push({ items: current, bytes });
|
|
60
64
|
return segments;
|
|
61
65
|
}
|
|
66
|
+
function openCargoStream(ports, options = {}) {
|
|
67
|
+
const lanes = options.lanes ?? parallel_js_1.DEFAULT_TRANSFER_CONCURRENCY;
|
|
68
|
+
const maxInFlightBytes = options.maxInFlightBytes ?? exports.CARGO_STREAM_IN_FLIGHT_BYTES;
|
|
69
|
+
const inFlight = new Set();
|
|
70
|
+
let inFlightBytes = 0;
|
|
71
|
+
let failure;
|
|
72
|
+
let current = [];
|
|
73
|
+
let currentBytes = 0;
|
|
74
|
+
let segments = 0;
|
|
75
|
+
let artifacts = 0;
|
|
76
|
+
let bytes = 0;
|
|
77
|
+
const dispatch = async (segment) => {
|
|
78
|
+
const weight = Math.max(segment.bytes, 1);
|
|
79
|
+
while (failure === undefined
|
|
80
|
+
&& (inFlight.size >= lanes
|
|
81
|
+
|| (inFlight.size > 0 && inFlightBytes + weight > maxInFlightBytes))) {
|
|
82
|
+
await Promise.race(inFlight);
|
|
83
|
+
}
|
|
84
|
+
if (failure !== undefined)
|
|
85
|
+
throw failure.error;
|
|
86
|
+
inFlightBytes += weight;
|
|
87
|
+
const settled = (async () => {
|
|
88
|
+
const sealed = new Set(await ports.send(segment));
|
|
89
|
+
for (const item of segment.items) {
|
|
90
|
+
if (!sealed.has(item.contentHash)) {
|
|
91
|
+
throw new Error(`cargo authority did not seal ${item.contentHash}`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
segments += 1;
|
|
95
|
+
artifacts += segment.items.length;
|
|
96
|
+
bytes += segment.bytes;
|
|
97
|
+
})().then(() => { inFlight.delete(settled); inFlightBytes -= weight; }, (error) => {
|
|
98
|
+
inFlight.delete(settled);
|
|
99
|
+
inFlightBytes -= weight;
|
|
100
|
+
failure ??= { error };
|
|
101
|
+
});
|
|
102
|
+
inFlight.add(settled);
|
|
103
|
+
};
|
|
104
|
+
const closeCurrent = () => {
|
|
105
|
+
const segment = { items: current, bytes: currentBytes };
|
|
106
|
+
current = [];
|
|
107
|
+
currentBytes = 0;
|
|
108
|
+
return segment;
|
|
109
|
+
};
|
|
110
|
+
return {
|
|
111
|
+
async add(item) {
|
|
112
|
+
assertCargoItem(item);
|
|
113
|
+
if (failure !== undefined)
|
|
114
|
+
throw failure.error;
|
|
115
|
+
if (current.length > 0
|
|
116
|
+
&& (currentBytes + item.bytes > exports.CARGO_SEGMENT_BYTES
|
|
117
|
+
|| current.length >= exports.CARGO_SEGMENT_ARTIFACTS)) {
|
|
118
|
+
await dispatch(closeCurrent());
|
|
119
|
+
}
|
|
120
|
+
current.push(item);
|
|
121
|
+
currentBytes += item.bytes;
|
|
122
|
+
},
|
|
123
|
+
async flush() {
|
|
124
|
+
if (failure === undefined && current.length > 0) {
|
|
125
|
+
try {
|
|
126
|
+
await dispatch(closeCurrent());
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
// The failure is recorded; settle the window before rethrowing.
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
while (inFlight.size > 0)
|
|
133
|
+
await Promise.race(inFlight);
|
|
134
|
+
if (failure !== undefined)
|
|
135
|
+
throw failure.error;
|
|
136
|
+
return { segments, artifacts, bytes };
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
}
|
|
62
140
|
/** Stream one cold set of small artifacts as bounded pipelined segments.
|
|
63
141
|
* Every item must come back sealed or the stream fails; a failure stops new
|
|
64
142
|
* admission, lets in-flight segments settle, and leaves their sealed work
|
|
65
143
|
* durable for the resuming rerun. */
|
|
66
144
|
async function streamCargo(items, ports, options = {}) {
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
bytes += segment.bytes;
|
|
79
|
-
});
|
|
80
|
-
return { segments: segments.length, artifacts, bytes };
|
|
145
|
+
for (const item of items)
|
|
146
|
+
assertCargoItem(item);
|
|
147
|
+
const stream = openCargoStream(ports, options);
|
|
148
|
+
try {
|
|
149
|
+
for (const item of items)
|
|
150
|
+
await stream.add(item);
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
// add() already recorded the failure; flush settles and rethrows it.
|
|
154
|
+
}
|
|
155
|
+
return stream.flush();
|
|
81
156
|
}
|
|
82
157
|
//# sourceMappingURL=cargo.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cargo.js","sourceRoot":"","sources":["../../src/transfer/cargo.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;GAcG;;;
|
|
1
|
+
{"version":3,"file":"cargo.js","sourceRoot":"","sources":["../../src/transfer/cargo.ts"],"names":[],"mappings":"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"}
|
|
@@ -17,6 +17,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
17
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
18
|
__exportStar(require("./artifacts.js"), exports);
|
|
19
19
|
__exportStar(require("./cargo.js"), exports);
|
|
20
|
+
__exportStar(require("./stream.js"), exports);
|
|
20
21
|
__exportStar(require("./upload.js"), exports);
|
|
21
22
|
__exportStar(require("./download.js"), exports);
|
|
22
23
|
__exportStar(require("./refs.js"), exports);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/transfer/index.ts"],"names":[],"mappings":";AAAA,wDAAwD;;;;;;;;;;;;;;;;AAExD,iDAA+B;AAC/B,6CAA2B;AAC3B,8CAA4B;AAC5B,gDAA8B;AAC9B,4CAA0B;AAC1B,8CAA4B"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/transfer/index.ts"],"names":[],"mappings":";AAAA,wDAAwD;;;;;;;;;;;;;;;;AAExD,iDAA+B;AAC/B,6CAA2B;AAC3B,8CAA4B;AAC5B,8CAA4B;AAC5B,gDAA8B;AAC9B,4CAA0B;AAC1B,8CAA4B"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* One-read upload — capture and transport fused.
|
|
4
|
+
*
|
|
5
|
+
* The classic upload (`upload.ts`) needs the whole-file identity up front
|
|
6
|
+
* and a seekable source it may reread. This primitive serves the moment the
|
|
7
|
+
* bytes are first read: the identity is DISCOVERED while one sequential
|
|
8
|
+
* read proceeds. Each full transfer batch of verified blocks — addressed by
|
|
9
|
+
* their own digests, bound to no whole-file identity yet — rides the wire
|
|
10
|
+
* while the next batch is read, and only after the last byte proves the
|
|
11
|
+
* whole-file digest is the manifest sealed. An interrupted or torn stream
|
|
12
|
+
* leaves unreferenced blocks the authority already tolerates, never a
|
|
13
|
+
* sealed artifact; whether the streamed digest matches current ground is
|
|
14
|
+
* the host's stat law, exactly as for the classic capture. Registration
|
|
15
|
+
* owns entity identity — this primitive knows only content.
|
|
16
|
+
*
|
|
17
|
+
* Memory is bounded by construction: one batch on the wire while one batch
|
|
18
|
+
* is read, so a stream holds at most two transfer batches at once.
|
|
19
|
+
*/
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
exports.uploadStream = uploadStream;
|
|
22
|
+
const content_js_1 = require("../contracts/content.js");
|
|
23
|
+
const batches_js_1 = require("./batches.js");
|
|
24
|
+
const planStreamBatches = (totalBytes) => {
|
|
25
|
+
const batches = [];
|
|
26
|
+
let offset = 0;
|
|
27
|
+
for (const size of (0, content_js_1.chunkSizes)(totalBytes)) {
|
|
28
|
+
const prior = batches.at(-1);
|
|
29
|
+
if (prior && prior.bytes + size <= batches_js_1.FILE_TRANSFER_BATCH_BYTES) {
|
|
30
|
+
prior.bytes += size;
|
|
31
|
+
prior.sizes.push(size);
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
batches.push({ offset, bytes: size, sizes: [size] });
|
|
35
|
+
}
|
|
36
|
+
offset += size;
|
|
37
|
+
}
|
|
38
|
+
return batches;
|
|
39
|
+
};
|
|
40
|
+
/** Upload one file's content from a single sequential read, discovering its
|
|
41
|
+
* identity along the way and sealing the manifest last. */
|
|
42
|
+
async function uploadStream(source, ports) {
|
|
43
|
+
if (!Number.isSafeInteger(source.bytes) || source.bytes <= 0) {
|
|
44
|
+
throw new Error('stream upload source byte count is invalid');
|
|
45
|
+
}
|
|
46
|
+
const whole = ports.createSha256();
|
|
47
|
+
const chunks = [];
|
|
48
|
+
let inFlight;
|
|
49
|
+
try {
|
|
50
|
+
for (const batch of planStreamBatches(source.bytes)) {
|
|
51
|
+
const bytes = await source.read(batch.offset, batch.bytes);
|
|
52
|
+
if (!(bytes instanceof Uint8Array) || bytes.byteLength !== batch.bytes) {
|
|
53
|
+
throw new Error(`stream upload source returned the wrong byte count at offset ${batch.offset}`);
|
|
54
|
+
}
|
|
55
|
+
whole.update(bytes);
|
|
56
|
+
const batchChunks = [];
|
|
57
|
+
let within = 0;
|
|
58
|
+
for (const size of batch.sizes) {
|
|
59
|
+
batchChunks.push({ sha256: ports.sha256Hex(bytes.subarray(within, within + size)), bytes: size });
|
|
60
|
+
within += size;
|
|
61
|
+
}
|
|
62
|
+
chunks.push(...batchChunks);
|
|
63
|
+
await inFlight;
|
|
64
|
+
inFlight = ports.putBlocks(batchChunks, bytes);
|
|
65
|
+
}
|
|
66
|
+
await inFlight;
|
|
67
|
+
inFlight = undefined;
|
|
68
|
+
const checked = (0, content_js_1.manifestFromChunks)(whole.digestHex(), chunks);
|
|
69
|
+
if (!checked.ok)
|
|
70
|
+
throw new Error(checked.error);
|
|
71
|
+
await ports.sealManifest(checked.value);
|
|
72
|
+
return { manifest: checked.value, uploadedChunks: chunks.length };
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
// In-flight blocks settle before control returns, so the host may
|
|
76
|
+
// safely close file and network handles after rejection.
|
|
77
|
+
await inFlight?.catch(() => { });
|
|
78
|
+
throw error;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=stream.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream.js","sourceRoot":"","sources":["../../src/transfer/stream.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@amalgm/live",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.59",
|
|
4
4
|
"description": "Portable realtime SDK for Amalgm — wire contracts, mutation discipline, and delivery state machines behind host-injected adapters.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist-cjs/index.js",
|