@elaraai/east-node-cli 1.0.76 → 1.0.78
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/README.md +126 -2
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +151 -18
- package/dist/cli.js.map +1 -1
- package/dist/emit-writer.d.ts +74 -0
- package/dist/emit-writer.d.ts.map +1 -0
- package/dist/emit-writer.js +159 -0
- package/dist/emit-writer.js.map +1 -0
- package/dist/merge.d.ts +48 -0
- package/dist/merge.d.ts.map +1 -0
- package/dist/merge.js +342 -0
- package/dist/merge.js.map +1 -0
- package/dist/runner.d.ts +53 -3
- package/dist/runner.d.ts.map +1 -1
- package/dist/runner.js +145 -232
- package/dist/runner.js.map +1 -1
- package/dist/runner.spec.js +559 -63
- package/dist/runner.spec.js.map +1 -1
- package/package.json +3 -3
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
|
+
* Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* The segment writer behind `run --emit` and `merge` (issue #770).
|
|
7
|
+
*
|
|
8
|
+
* Entries arrive one at a time and go out as segments of a streaming beast2
|
|
9
|
+
* writer on the output file: header at open, terminator and index at the
|
|
10
|
+
* finish, so every finished file is a complete canonical blob. Batches are
|
|
11
|
+
* re-sized byte-adaptively toward the paged-encode segment target from what
|
|
12
|
+
* the writer has actually emitted — the refinement `encodeBeast2PagedFor`
|
|
13
|
+
* applies, so a file written here segments exactly as that encoder segments
|
|
14
|
+
* the same value. Both commands write through this one class, which is what
|
|
15
|
+
* makes a merge's output byte-identical to the sink's for the same entries.
|
|
16
|
+
* Memory is one open batch whatever the output's size.
|
|
17
|
+
*/
|
|
18
|
+
import { closeSync, openSync, writeSync } from 'fs';
|
|
19
|
+
import { Beast2Writer, BEAST2_PAGED_BATCH_DEFAULT, BEAST2_PAGED_PROBE_BATCH, BEAST2_PAGED_TARGET_BYTES_DEFAULT } from '@elaraai/east';
|
|
20
|
+
/** Writes all of `bytes` to `fd` — `writeSync` may write fewer bytes than
|
|
21
|
+
* asked, and a silently short write would corrupt the file. */
|
|
22
|
+
function writeAll(fd, bytes) {
|
|
23
|
+
let written = 0;
|
|
24
|
+
while (written < bytes.length) {
|
|
25
|
+
written += writeSync(fd, bytes, written, bytes.length - written);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* A streaming, byte-adaptively batched writer of one canonical collection
|
|
30
|
+
* blob. Entries are elements (Array and Set) or `[key, value]` pairs (Dict).
|
|
31
|
+
*/
|
|
32
|
+
export class EmitFileWriter {
|
|
33
|
+
kind;
|
|
34
|
+
outType;
|
|
35
|
+
fd;
|
|
36
|
+
writer;
|
|
37
|
+
headerBytes = -1;
|
|
38
|
+
batch = [];
|
|
39
|
+
written = 0;
|
|
40
|
+
nextBatch = BEAST2_PAGED_BATCH_DEFAULT;
|
|
41
|
+
probed = false;
|
|
42
|
+
/**
|
|
43
|
+
* Opens `path` for writing and emits the blob's header.
|
|
44
|
+
*
|
|
45
|
+
* @param kind - the collection kind
|
|
46
|
+
* @param outType - the collection's wire type
|
|
47
|
+
* @param path - the output file
|
|
48
|
+
*/
|
|
49
|
+
constructor(kind, outType, path) {
|
|
50
|
+
this.kind = kind;
|
|
51
|
+
this.outType = outType;
|
|
52
|
+
this.fd = openSync(path, 'w');
|
|
53
|
+
// Frames deflate on worker threads (#763); the refinement below reads
|
|
54
|
+
// the emitted bytes through the writer's bounds.
|
|
55
|
+
this.writer = new Beast2Writer(outType, (bytes) => {
|
|
56
|
+
writeAll(this.fd, bytes);
|
|
57
|
+
if (this.headerBytes < 0)
|
|
58
|
+
this.headerBytes = bytes.length;
|
|
59
|
+
}, { parallel: true });
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Appends `entry` under the flush rule: a full batch goes out only now
|
|
63
|
+
* that an entry which will not fold into it has arrived, so the batch's
|
|
64
|
+
* last entry is always still open for a fold.
|
|
65
|
+
*
|
|
66
|
+
* @param entry - the element, or the `[key, value]` pair
|
|
67
|
+
*/
|
|
68
|
+
push(entry) {
|
|
69
|
+
if (this.batch.length >= this.nextBatch)
|
|
70
|
+
this.flush();
|
|
71
|
+
this.batch.push(entry);
|
|
72
|
+
this.probe();
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Seeds the batch size from a throwaway encode of the first entries, as
|
|
76
|
+
* `encodeBeast2PagedFor` does — the same probe, over the same count, so
|
|
77
|
+
* one value segments the same whether it was returned or emitted.
|
|
78
|
+
*
|
|
79
|
+
* Opening at the element cap instead made the first segment as many
|
|
80
|
+
* elements as the cap whatever they weighed: for rows above the target's
|
|
81
|
+
* share that is one oversized segment and every later boundary shifted,
|
|
82
|
+
* so the same Dict written both ways hashed differently. The probed
|
|
83
|
+
* entries are then drained through the refined size, exactly as the
|
|
84
|
+
* paged encoder pumps its own probe.
|
|
85
|
+
*/
|
|
86
|
+
probe() {
|
|
87
|
+
if (this.probed || this.batch.length < BEAST2_PAGED_PROBE_BATCH)
|
|
88
|
+
return;
|
|
89
|
+
this.probed = true;
|
|
90
|
+
let scratchBytes = 0;
|
|
91
|
+
const scratch = new Beast2Writer(this.outType, (bytes) => { scratchBytes += bytes.length; });
|
|
92
|
+
const scratchHeader = scratchBytes;
|
|
93
|
+
scratch.write(this.toValue(this.batch));
|
|
94
|
+
const avg = Math.max(1, (scratchBytes - scratchHeader) / this.batch.length);
|
|
95
|
+
this.nextBatch = Math.max(1, Math.min(BEAST2_PAGED_BATCH_DEFAULT, Math.floor(BEAST2_PAGED_TARGET_BYTES_DEFAULT / avg)));
|
|
96
|
+
if (this.nextBatch >= this.batch.length)
|
|
97
|
+
return;
|
|
98
|
+
// Wider than one probe batch: the entries held so far go out in
|
|
99
|
+
// refined-size segments, which is what the paged encoder writes.
|
|
100
|
+
const buffered = this.batch;
|
|
101
|
+
this.batch = [];
|
|
102
|
+
for (const item of buffered) {
|
|
103
|
+
if (this.batch.length >= this.nextBatch)
|
|
104
|
+
this.flush();
|
|
105
|
+
this.batch.push(item);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Replaces the open batch's last entry — where an adjacent equal key's
|
|
110
|
+
* fold lands.
|
|
111
|
+
*
|
|
112
|
+
* @param update - maps the last entry to its folded form
|
|
113
|
+
*/
|
|
114
|
+
foldLast(update) {
|
|
115
|
+
const at = this.batch.length - 1;
|
|
116
|
+
this.batch[at] = update(this.batch[at]);
|
|
117
|
+
}
|
|
118
|
+
/** Writes the open batch and finalizes the blob (terminator + index). */
|
|
119
|
+
finishClose() {
|
|
120
|
+
this.flush();
|
|
121
|
+
this.writer.finish();
|
|
122
|
+
closeSync(this.fd);
|
|
123
|
+
}
|
|
124
|
+
/** Closes the file without finalizing it — after an error, the partial
|
|
125
|
+
* output carries no terminator or index. */
|
|
126
|
+
closeAbandoned() {
|
|
127
|
+
closeSync(this.fd);
|
|
128
|
+
}
|
|
129
|
+
flush() {
|
|
130
|
+
if (this.batch.length === 0)
|
|
131
|
+
return;
|
|
132
|
+
this.writer.write(this.toValue(this.batch));
|
|
133
|
+
this.written += this.batch.length;
|
|
134
|
+
this.batch = [];
|
|
135
|
+
this.nextBatch = this.refineNext();
|
|
136
|
+
}
|
|
137
|
+
toValue(items) {
|
|
138
|
+
return this.kind === 'dict' ? new Map(items) : this.kind === 'set' ? new Set(items) : items;
|
|
139
|
+
}
|
|
140
|
+
/** The batch size the paged encoder would choose after `bytes` of body
|
|
141
|
+
* for `this.written` elements. */
|
|
142
|
+
refine(bytes) {
|
|
143
|
+
const avg = Math.max(1, Math.max(1, bytes - Math.max(0, this.headerBytes)) / this.written);
|
|
144
|
+
return Math.max(1, Math.min(BEAST2_PAGED_BATCH_DEFAULT, Math.floor(BEAST2_PAGED_TARGET_BYTES_DEFAULT / avg)));
|
|
145
|
+
}
|
|
146
|
+
/** The next batch size. With frames deflating on workers the bytes
|
|
147
|
+
* written are only known within bounds; the refinement is monotone in
|
|
148
|
+
* them, so agreeing bounds are the serial decision and disagreeing ones
|
|
149
|
+
* wait for the frames — the segmentation never depends on timing. */
|
|
150
|
+
refineNext() {
|
|
151
|
+
const { lo, hi } = this.writer.emittedBounds();
|
|
152
|
+
const next = this.refine(lo);
|
|
153
|
+
if (next === this.refine(hi))
|
|
154
|
+
return next;
|
|
155
|
+
this.writer.settle();
|
|
156
|
+
return this.refine(this.writer.emittedBounds().lo);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=emit-writer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emit-writer.js","sourceRoot":"","sources":["../src/emit-writer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,0BAA0B,EAAE,wBAAwB,EAAE,iCAAiC,EAAE,MAAM,eAAe,CAAC;AAGtI;gEACgE;AAChE,SAAS,QAAQ,CAAC,EAAU,EAAE,KAAiB;IAC3C,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,OAAO,OAAO,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;QAC5B,OAAO,IAAI,SAAS,CAAC,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,MAAM,GAAG,OAAO,CAAC,CAAC;IACrE,CAAC;AACL,CAAC;AAKD;;;GAGG;AACH,MAAM,OAAO,cAAc;IAgBM;IAAiC;IAf7C,EAAE,CAAS;IACX,MAAM,CAAe;IAC9B,WAAW,GAAG,CAAC,CAAC,CAAC;IACjB,KAAK,GAAc,EAAE,CAAC;IACtB,OAAO,GAAG,CAAC,CAAC;IACZ,SAAS,GAAG,0BAA0B,CAAC;IACvC,MAAM,GAAG,KAAK,CAAC;IAEvB;;;;;;OAMG;IACH,YAA6B,IAAc,EAAmB,OAAsB,EAAE,IAAY;QAArE,SAAI,GAAJ,IAAI,CAAU;QAAmB,YAAO,GAAP,OAAO,CAAe;QAChF,IAAI,CAAC,EAAE,GAAG,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QAC9B,sEAAsE;QACtE,iDAAiD;QACjD,IAAI,CAAC,MAAM,GAAG,IAAI,YAAY,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;YAC9C,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;YACzB,IAAI,IAAI,CAAC,WAAW,GAAG,CAAC;gBAAE,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC,MAAM,CAAC;QAC9D,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3B,CAAC;IAED;;;;;;OAMG;IACH,IAAI,CAAC,KAAc;QACf,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,IAAI,CAAC,SAAS;YAAE,IAAI,CAAC,KAAK,EAAE,CAAC;QACtD,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACvB,IAAI,CAAC,KAAK,EAAE,CAAC;IACjB,CAAC;IAED;;;;;;;;;;;OAWG;IACK,KAAK;QACT,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,wBAAwB;YAAE,OAAO;QACxE,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACnB,IAAI,YAAY,GAAG,CAAC,CAAC;QACrB,MAAM,OAAO,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,GAAG,YAAY,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7F,MAAM,aAAa,GAAG,YAAY,CAAC;QACnC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAU,CAAC,CAAC;QACjD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,YAAY,GAAG,aAAa,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAC5E,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,0BAA0B,EAAE,IAAI,CAAC,KAAK,CAAC,iCAAiC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;QACxH,IAAI,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM;YAAE,OAAO;QAChD,gEAAgE;QAChE,iEAAiE;QACjE,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC;QAC5B,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;QAChB,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;YAC1B,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,IAAI,CAAC,SAAS;gBAAE,IAAI,CAAC,KAAK,EAAE,CAAC;YACtD,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC;IACL,CAAC;IAED;;;;;OAKG;IACH,QAAQ,CAAC,MAAkC;QACvC,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;QACjC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5C,CAAC;IAED,yEAAyE;IACzE,WAAW;QACP,IAAI,CAAC,KAAK,EAAE,CAAC;QACb,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACrB,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACvB,CAAC;IAED;iDAC6C;IAC7C,cAAc;QACV,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACvB,CAAC;IAEO,KAAK;QACT,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QACpC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAU,CAAC,CAAC;QACrD,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;QAClC,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;QAChB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;IACvC,CAAC;IAEO,OAAO,CAAC,KAAgB;QAC5B,OAAO,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,KAA6B,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IACxH,CAAC;IAED;uCACmC;IAC3B,MAAM,CAAC,KAAa;QACxB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC;QAC3F,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,0BAA0B,EAAE,IAAI,CAAC,KAAK,CAAC,iCAAiC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;IAClH,CAAC;IAED;;;0EAGsE;IAC9D,UAAU;QACd,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC;QAC/C,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAC7B,IAAI,IAAI,KAAK,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YAAE,OAAO,IAAI,CAAC;QAC1C,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACrB,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC,EAAE,CAAC,CAAC;IACvD,CAAC;CACJ"}
|
package/dist/merge.d.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
|
+
* Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
|
|
4
|
+
*/
|
|
5
|
+
import type { PlatformFunction } from '@elaraai/east/internal';
|
|
6
|
+
/** Options accepted by {@link mergeBlobs}. */
|
|
7
|
+
export interface MergeBlobsOptions {
|
|
8
|
+
/** Dict inputs: an IR file (any format the IR positional accepts) holding
|
|
9
|
+
* a `(K, V, V) -> V` East function over the inputs' key and value types,
|
|
10
|
+
* compiled with `platformFns`. Equal keys fold with it in input order. */
|
|
11
|
+
mergePath?: string;
|
|
12
|
+
/** Set inputs: the first of equal elements stands. */
|
|
13
|
+
union?: boolean;
|
|
14
|
+
/** A beast2 blob of `Struct{from: Option<K>, to: Option<K>}` over the
|
|
15
|
+
* inputs' key type: only the keys in `[from, to)` merge; an absent
|
|
16
|
+
* bound is open. */
|
|
17
|
+
rangePath?: string;
|
|
18
|
+
/** The platforms the merge function compiles with. */
|
|
19
|
+
platformFns?: PlatformFunction[];
|
|
20
|
+
/** Print the account and timing on stderr. */
|
|
21
|
+
verbose?: boolean;
|
|
22
|
+
}
|
|
23
|
+
/** What a merge came to. */
|
|
24
|
+
export interface MergeBlobsStats {
|
|
25
|
+
/** Inputs merged. */
|
|
26
|
+
inputs: number;
|
|
27
|
+
/** Entries written to the output. */
|
|
28
|
+
entries: number;
|
|
29
|
+
/** Equal keys folded (merge) or collapsed (union). */
|
|
30
|
+
folds: number;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Merges sorted Set or Dict blobs of one type into one canonical blob — the
|
|
34
|
+
* `merge` command.
|
|
35
|
+
*
|
|
36
|
+
* @param inputPaths - the inputs, in the order equal keys fold; at least one
|
|
37
|
+
* @param outputPath - the output blob
|
|
38
|
+
* @param options - the fold, its platforms, the key range, verbosity
|
|
39
|
+
* @returns the account: inputs merged, entries written, keys folded
|
|
40
|
+
* @throws {Error} With the merge's message — an input of another type than
|
|
41
|
+
* input 0's, an Array input, keys that do not ascend, a fold whose
|
|
42
|
+
* signature does not match the inputs, a range blob of another shape than
|
|
43
|
+
* the bounds over the inputs' key type, a file that cannot be opened, a
|
|
44
|
+
* shared key without a fold — leaving the output unfinalised (no
|
|
45
|
+
* terminator or index).
|
|
46
|
+
*/
|
|
47
|
+
export declare function mergeBlobs(inputPaths: readonly string[], outputPath: string, options?: MergeBlobsOptions): MergeBlobsStats;
|
|
48
|
+
//# sourceMappingURL=merge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge.d.ts","sourceRoot":"","sources":["../src/merge.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAmDH,OAAO,KAAK,EAAiB,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAK9E,8CAA8C;AAC9C,MAAM,WAAW,iBAAiB;IAC9B;;+EAE2E;IAC3E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sDAAsD;IACtD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;yBAEqB;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sDAAsD;IACtD,WAAW,CAAC,EAAE,gBAAgB,EAAE,CAAC;IACjC,8CAA8C;IAC9C,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,4BAA4B;AAC5B,MAAM,WAAW,eAAe;IAC5B,qBAAqB;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,qCAAqC;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,sDAAsD;IACtD,KAAK,EAAE,MAAM,CAAC;CACjB;AA0LD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,UAAU,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,GAAE,iBAAsB,GAAG,eAAe,CAoG9H"}
|
package/dist/merge.js
ADDED
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
|
+
* Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* The blob merge behind `east-node merge` (issue #770).
|
|
7
|
+
*
|
|
8
|
+
* Canonical Set or Dict blobs of one type in — sorted, indexed beast2 v5
|
|
9
|
+
* collections, as every runner writes them — and one canonical blob out, in
|
|
10
|
+
* a single pass: every input is read segment by segment through positioned
|
|
11
|
+
* reads on its descriptor, a heap over the inputs' current entries yields
|
|
12
|
+
* keys in East order, and the output is written through the same segment
|
|
13
|
+
* writer as `run --emit`, so the file is byte-identical to what that sink
|
|
14
|
+
* writes for the same entries emitted ascending. Memory is one decoded
|
|
15
|
+
* segment per input plus one open batch; no temporary file is ever written.
|
|
16
|
+
*
|
|
17
|
+
* Equal keys across inputs fold in input order: with a merge function (Dict
|
|
18
|
+
* inputs) `acc = merge(key, acc, value)`; in union mode (Set inputs) the
|
|
19
|
+
* first element stands. Without a fold, an equal key is the duplicate error
|
|
20
|
+
* the emit sink raises. An input whose keys do not ascend, an input whose
|
|
21
|
+
* type is not input 0's, and an Array input are refused.
|
|
22
|
+
*
|
|
23
|
+
* With a key range (`--range`, a blob of `Struct{from: Option<K>, to:
|
|
24
|
+
* Option<K>}` over the inputs' key type) only the keys in `[from, to)`
|
|
25
|
+
* merge: every input is sought to the segment owning `from` through its
|
|
26
|
+
* fences and read up to the first key at or past `to`, so a unit over a
|
|
27
|
+
* range of a large output reads that range's share of each input, plus at
|
|
28
|
+
* most one segment. An absent bound is open; both absent is the whole merge.
|
|
29
|
+
*
|
|
30
|
+
* This is the fan-in of a partitioned task's keyed partials: e3 runs it as an
|
|
31
|
+
* ordinary execution on the task's runner, one unit per key range of a group
|
|
32
|
+
* of partials, and never decodes a partial itself. east-c and east-py merge
|
|
33
|
+
* through the same contract, so the three runners write the same bytes.
|
|
34
|
+
*/
|
|
35
|
+
import { closeSync, fstatSync, openSync, readFileSync, readSync } from 'fs';
|
|
36
|
+
import { OptionType, SortedMap, SortedSet, StructType, compareFor, decodeBeast2For, fromEastTypeValue, isTypeValueEqual, openBeast2LazyFor, printFor, readBeast2Extents, readBeast2HeaderType, readBeast2Type, toEastTypeValue, } from '@elaraai/east';
|
|
37
|
+
import { printTypeValue } from '@elaraai/east/internal';
|
|
38
|
+
import { EmitFileWriter } from './emit-writer.js';
|
|
39
|
+
import { duplicateMessage, formatFileSize, loadMergeFunction } from './runner.js';
|
|
40
|
+
/**
|
|
41
|
+
* Opens input `index` at `path`: reads its geometry and type, and prepares a
|
|
42
|
+
* segment-by-segment iteration of its entries — from the first key, or from
|
|
43
|
+
* a range's lower bound, whose owning segment the lazy value seeks through
|
|
44
|
+
* the fences.
|
|
45
|
+
*
|
|
46
|
+
* @param path - the blob
|
|
47
|
+
* @param index - the input's position, for messages
|
|
48
|
+
* @param expected - input 0's type, or `null` for input 0 itself
|
|
49
|
+
* @returns the opened input and its type
|
|
50
|
+
* @throws {Error} When the file cannot be opened (missing, unreadable, not
|
|
51
|
+
* a regular file), is not a blob (too short, or without the magic — the
|
|
52
|
+
* reader's own words), cannot be read as a canonical collection blob, or
|
|
53
|
+
* its type is not `expected`.
|
|
54
|
+
*/
|
|
55
|
+
function openInput(path, index, expected) {
|
|
56
|
+
let fd;
|
|
57
|
+
let size;
|
|
58
|
+
try {
|
|
59
|
+
fd = openSync(path, 'r');
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
throw new Error(`merge: input ${index} (${path}): cannot open the file`);
|
|
63
|
+
}
|
|
64
|
+
try {
|
|
65
|
+
const stat = fstatSync(fd);
|
|
66
|
+
if (!stat.isFile())
|
|
67
|
+
throw new Error('not a regular file');
|
|
68
|
+
size = stat.size;
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
closeSync(fd);
|
|
72
|
+
throw new Error(`merge: input ${index} (${path}): cannot open the file`);
|
|
73
|
+
}
|
|
74
|
+
const reader = {
|
|
75
|
+
size,
|
|
76
|
+
read(offset, length) {
|
|
77
|
+
const out = new Uint8Array(length);
|
|
78
|
+
let done = 0;
|
|
79
|
+
while (done < length) {
|
|
80
|
+
const n = readSync(fd, out, done, length - done, offset + done);
|
|
81
|
+
if (n === 0)
|
|
82
|
+
throw new Error(`beast2: short read at offset ${offset + done}`);
|
|
83
|
+
done += n;
|
|
84
|
+
}
|
|
85
|
+
return out;
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
const prefixed = (err) => new Error(`merge: input ${index} (${path}): ${err.message ?? String(err)}`);
|
|
89
|
+
let type;
|
|
90
|
+
let lazy;
|
|
91
|
+
try {
|
|
92
|
+
// The header first: a file too short for a blob, or one without the
|
|
93
|
+
// magic, is refused in the reader's words — the sentence east-c and
|
|
94
|
+
// east-py give for the same bytes — before the index is looked for.
|
|
95
|
+
readBeast2HeaderType(reader);
|
|
96
|
+
const extents = readBeast2Extents(reader);
|
|
97
|
+
type = extents.typeValue;
|
|
98
|
+
if (expected !== null && !isTypeValueEqual(type, expected)) {
|
|
99
|
+
closeSync(fd);
|
|
100
|
+
throw new Error(`merge: input ${index} (${path}) has type ${printTypeValue(type)}, expected ${printTypeValue(expected)} (input 0)`);
|
|
101
|
+
}
|
|
102
|
+
if (type.type !== 'Set' && type.type !== 'Dict') {
|
|
103
|
+
closeSync(fd);
|
|
104
|
+
throw new Error(`merge: inputs must be Set or Dict blobs, got ${type.type}`);
|
|
105
|
+
}
|
|
106
|
+
if (!extents.selfContained)
|
|
107
|
+
throw new Error('the blob is not self-contained');
|
|
108
|
+
lazy = openBeast2LazyFor(type, { frozen: true })(reader);
|
|
109
|
+
}
|
|
110
|
+
catch (err) {
|
|
111
|
+
const message = err.message ?? '';
|
|
112
|
+
if (message.startsWith('merge: '))
|
|
113
|
+
throw err;
|
|
114
|
+
closeSync(fd);
|
|
115
|
+
throw prefixed(err);
|
|
116
|
+
}
|
|
117
|
+
const dict = type.type === 'Dict';
|
|
118
|
+
return {
|
|
119
|
+
type,
|
|
120
|
+
close: () => closeSync(fd),
|
|
121
|
+
start: (range, cmp) => {
|
|
122
|
+
// The lazy value streams one decoded segment at a time, checking
|
|
123
|
+
// the ascent within and across segments as the eager decoder does;
|
|
124
|
+
// from a lower bound it starts at the segment owning it.
|
|
125
|
+
let iterator;
|
|
126
|
+
try {
|
|
127
|
+
iterator = dict
|
|
128
|
+
? lazy.entries(range.from)
|
|
129
|
+
: lazy.keys(range.from);
|
|
130
|
+
}
|
|
131
|
+
catch (err) {
|
|
132
|
+
throw prefixed(err);
|
|
133
|
+
}
|
|
134
|
+
let exhausted = false;
|
|
135
|
+
const input = {
|
|
136
|
+
head: null,
|
|
137
|
+
advance: () => {
|
|
138
|
+
if (exhausted)
|
|
139
|
+
return;
|
|
140
|
+
let next;
|
|
141
|
+
try {
|
|
142
|
+
next = iterator.next();
|
|
143
|
+
}
|
|
144
|
+
catch (err) {
|
|
145
|
+
throw prefixed(err);
|
|
146
|
+
}
|
|
147
|
+
if (next.done) {
|
|
148
|
+
exhausted = true;
|
|
149
|
+
input.head = null;
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
const [key, value] = dict ? next.value : [next.value, undefined];
|
|
153
|
+
// The first key at or past the upper bound ends the input.
|
|
154
|
+
if (range.to !== undefined && cmp(key, range.to) >= 0) {
|
|
155
|
+
exhausted = true;
|
|
156
|
+
input.head = null;
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
input.head = { key, value };
|
|
160
|
+
},
|
|
161
|
+
};
|
|
162
|
+
return input;
|
|
163
|
+
},
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Reads a `--range` blob: `Struct{from: Option<K>, to: Option<K>}` over the
|
|
168
|
+
* inputs' key type, self-describing, checked against that type.
|
|
169
|
+
*
|
|
170
|
+
* @param path - the blob
|
|
171
|
+
* @param keyType - the inputs' key (Dict) or element (Set) type
|
|
172
|
+
* @returns the bounds, an absent one `undefined`
|
|
173
|
+
* @throws {Error} When the file cannot be opened or read as a beast2 blob,
|
|
174
|
+
* or its type is not the bounds struct over the inputs' key type.
|
|
175
|
+
*/
|
|
176
|
+
function readRange(path, keyType) {
|
|
177
|
+
let bytes;
|
|
178
|
+
try {
|
|
179
|
+
bytes = new Uint8Array(readFileSync(path));
|
|
180
|
+
}
|
|
181
|
+
catch {
|
|
182
|
+
throw new Error(`merge: --range (${path}): cannot open the file`);
|
|
183
|
+
}
|
|
184
|
+
// The same shape east-c builds (merge.c) and e3-core writes
|
|
185
|
+
// (partitionExec.ts): the bounds struct over the key type.
|
|
186
|
+
const key = fromEastTypeValue(keyType);
|
|
187
|
+
const rangeType = toEastTypeValue(StructType({ from: OptionType(key), to: OptionType(key) }));
|
|
188
|
+
let type;
|
|
189
|
+
try {
|
|
190
|
+
type = readBeast2Type(bytes);
|
|
191
|
+
}
|
|
192
|
+
catch (err) {
|
|
193
|
+
throw new Error(`merge: --range (${path}): ${err.message ?? String(err)}`);
|
|
194
|
+
}
|
|
195
|
+
if (!isTypeValueEqual(type, rangeType)) {
|
|
196
|
+
throw new Error(`merge: --range (${path}) has type ${printTypeValue(type)}, expected ${printTypeValue(rangeType)} (bounds over the inputs' key type)`);
|
|
197
|
+
}
|
|
198
|
+
let bounds;
|
|
199
|
+
try {
|
|
200
|
+
bounds = decodeBeast2For(rangeType)(bytes);
|
|
201
|
+
}
|
|
202
|
+
catch (err) {
|
|
203
|
+
throw new Error(`merge: --range (${path}): ${err.message ?? String(err)}`);
|
|
204
|
+
}
|
|
205
|
+
return {
|
|
206
|
+
from: bounds.from.type === 'some' ? bounds.from.value : undefined,
|
|
207
|
+
to: bounds.to.type === 'some' ? bounds.to.value : undefined,
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Merges sorted Set or Dict blobs of one type into one canonical blob — the
|
|
212
|
+
* `merge` command.
|
|
213
|
+
*
|
|
214
|
+
* @param inputPaths - the inputs, in the order equal keys fold; at least one
|
|
215
|
+
* @param outputPath - the output blob
|
|
216
|
+
* @param options - the fold, its platforms, the key range, verbosity
|
|
217
|
+
* @returns the account: inputs merged, entries written, keys folded
|
|
218
|
+
* @throws {Error} With the merge's message — an input of another type than
|
|
219
|
+
* input 0's, an Array input, keys that do not ascend, a fold whose
|
|
220
|
+
* signature does not match the inputs, a range blob of another shape than
|
|
221
|
+
* the bounds over the inputs' key type, a file that cannot be opened, a
|
|
222
|
+
* shared key without a fold — leaving the output unfinalised (no
|
|
223
|
+
* terminator or index).
|
|
224
|
+
*/
|
|
225
|
+
export function mergeBlobs(inputPaths, outputPath, options = {}) {
|
|
226
|
+
const started = performance.now();
|
|
227
|
+
if (inputPaths.length === 0)
|
|
228
|
+
throw new Error('merge: at least one input is needed');
|
|
229
|
+
if (options.mergePath !== undefined && options.union) {
|
|
230
|
+
throw new Error('merge: --merge and --union are two folds — give one');
|
|
231
|
+
}
|
|
232
|
+
const opened = [];
|
|
233
|
+
const inputs = [];
|
|
234
|
+
let out = null;
|
|
235
|
+
let finished = false;
|
|
236
|
+
try {
|
|
237
|
+
const first = openInput(inputPaths[0], 0, null);
|
|
238
|
+
opened.push(first);
|
|
239
|
+
const type = first.type;
|
|
240
|
+
const kind = type.type === 'Dict' ? 'dict' : 'set';
|
|
241
|
+
if (options.mergePath !== undefined && kind !== 'dict')
|
|
242
|
+
throw new Error('--merge applies to Dict inputs only');
|
|
243
|
+
if (options.union && kind !== 'set')
|
|
244
|
+
throw new Error('--union applies to Set inputs only');
|
|
245
|
+
const keyType = (kind === 'dict' ? type.value.key : type.value);
|
|
246
|
+
const valueType = (kind === 'dict' ? type.value.value : null);
|
|
247
|
+
const merge = options.mergePath !== undefined
|
|
248
|
+
? loadMergeFunction(options.mergePath, keyType, valueType, options.platformFns ?? [], 'the inputs')
|
|
249
|
+
: null;
|
|
250
|
+
const union = options.union ?? false;
|
|
251
|
+
const range = options.rangePath !== undefined ? readRange(options.rangePath, keyType) : { from: undefined, to: undefined };
|
|
252
|
+
for (let i = 1; i < inputPaths.length; i++)
|
|
253
|
+
opened.push(openInput(inputPaths[i], i, type));
|
|
254
|
+
const cmp = compareFor(keyType);
|
|
255
|
+
const printKey = printFor(keyType);
|
|
256
|
+
for (const input of opened)
|
|
257
|
+
inputs.push(input.start(range, cmp));
|
|
258
|
+
for (const input of inputs)
|
|
259
|
+
input.advance();
|
|
260
|
+
// A binary min-heap over the inputs' current keys, ordered by (key,
|
|
261
|
+
// input index), so equal keys leave in input order.
|
|
262
|
+
const heap = [];
|
|
263
|
+
for (let i = 0; i < inputs.length; i++)
|
|
264
|
+
if (inputs[i].head !== null)
|
|
265
|
+
heap.push(i);
|
|
266
|
+
const before = (a, b) => {
|
|
267
|
+
const order = cmp(inputs[a].head.key, inputs[b].head.key);
|
|
268
|
+
return order < 0 || (order === 0 && a < b);
|
|
269
|
+
};
|
|
270
|
+
const siftDown = (at) => {
|
|
271
|
+
for (;;) {
|
|
272
|
+
const l = 2 * at + 1;
|
|
273
|
+
const r = l + 1;
|
|
274
|
+
let least = at;
|
|
275
|
+
if (l < heap.length && before(heap[l], heap[least]))
|
|
276
|
+
least = l;
|
|
277
|
+
if (r < heap.length && before(heap[r], heap[least]))
|
|
278
|
+
least = r;
|
|
279
|
+
if (least === at)
|
|
280
|
+
return;
|
|
281
|
+
[heap[at], heap[least]] = [heap[least], heap[at]];
|
|
282
|
+
at = least;
|
|
283
|
+
}
|
|
284
|
+
};
|
|
285
|
+
for (let i = (heap.length >> 1) - 1; i >= 0; i--)
|
|
286
|
+
siftDown(i);
|
|
287
|
+
out = new EmitFileWriter(kind, type, outputPath);
|
|
288
|
+
let entries = 0;
|
|
289
|
+
let folds = 0;
|
|
290
|
+
// The current key's entry is held until a greater key arrives, so
|
|
291
|
+
// every equal key folds into it before it is written.
|
|
292
|
+
let held = null;
|
|
293
|
+
const put = (entry) => {
|
|
294
|
+
out.push(kind === 'dict' ? [entry.key, entry.value] : entry.key);
|
|
295
|
+
entries++;
|
|
296
|
+
};
|
|
297
|
+
while (heap.length > 0) {
|
|
298
|
+
const input = inputs[heap[0]];
|
|
299
|
+
const { key, value } = input.head;
|
|
300
|
+
if (held !== null && cmp(held.key, key) === 0) {
|
|
301
|
+
if (merge !== null) {
|
|
302
|
+
held.value = merge(key, held.value, value);
|
|
303
|
+
}
|
|
304
|
+
else if (!union) {
|
|
305
|
+
throw new Error(duplicateMessage(kind, printKey, key));
|
|
306
|
+
}
|
|
307
|
+
folds++;
|
|
308
|
+
}
|
|
309
|
+
else {
|
|
310
|
+
if (held !== null)
|
|
311
|
+
put(held);
|
|
312
|
+
held = { key, value };
|
|
313
|
+
}
|
|
314
|
+
input.advance();
|
|
315
|
+
if (input.head === null) {
|
|
316
|
+
heap[0] = heap[heap.length - 1];
|
|
317
|
+
heap.pop();
|
|
318
|
+
}
|
|
319
|
+
if (heap.length > 0)
|
|
320
|
+
siftDown(0);
|
|
321
|
+
}
|
|
322
|
+
if (held !== null)
|
|
323
|
+
put(held);
|
|
324
|
+
out.finishClose();
|
|
325
|
+
finished = true;
|
|
326
|
+
const stats = { inputs: inputs.length, entries, folds };
|
|
327
|
+
if (options.verbose) {
|
|
328
|
+
console.error(`merge: ${stats.inputs} input(s), ${stats.entries} entries, ${stats.folds} fold(s)`);
|
|
329
|
+
console.error(`Output: ${outputPath} (${formatFileSize(outputPath)})`);
|
|
330
|
+
console.error('\nTiming:');
|
|
331
|
+
console.error(` Total: ${(performance.now() - started).toFixed(1).padStart(8)} ms`);
|
|
332
|
+
}
|
|
333
|
+
return stats;
|
|
334
|
+
}
|
|
335
|
+
finally {
|
|
336
|
+
for (const input of opened)
|
|
337
|
+
input.close();
|
|
338
|
+
if (out !== null && !finished)
|
|
339
|
+
out.closeAbandoned();
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
//# sourceMappingURL=merge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge.js","sourceRoot":"","sources":["../src/merge.ts"],"names":[],"mappings":"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"}
|
package/dist/runner.d.ts
CHANGED
|
@@ -2,8 +2,22 @@
|
|
|
2
2
|
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
3
|
* Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
|
|
4
4
|
*/
|
|
5
|
-
import type { PlatformFunction } from '@elaraai/east/internal';
|
|
5
|
+
import type { PlatformFunction, EastTypeValue } from '@elaraai/east/internal';
|
|
6
|
+
/** A file's size for the verbose account, or `?` when it cannot be read. @internal */
|
|
7
|
+
export declare function formatFileSize(path: string): string;
|
|
6
8
|
/** Streaming-execution options accepted by {@link runProgram}. */
|
|
9
|
+
/**
|
|
10
|
+
* A refusal of the command line itself — a flag combination, an output
|
|
11
|
+
* destination, a function shape the flags do not fit.
|
|
12
|
+
*
|
|
13
|
+
* These are the user's errors, not the program's, and east-c and east-py
|
|
14
|
+
* answer them with one sentence on stderr. Marking them lets the CLI do the
|
|
15
|
+
* same instead of printing the JS stack it prints for an error thrown from
|
|
16
|
+
* East or from a platform function, where the frames are the diagnosis.
|
|
17
|
+
*/
|
|
18
|
+
export declare class UsageError extends Error {
|
|
19
|
+
constructor(message: string);
|
|
20
|
+
}
|
|
7
21
|
export interface RunProgramOptions {
|
|
8
22
|
/** Enable verbose timing/memory output on stderr. */
|
|
9
23
|
verbose?: boolean;
|
|
@@ -12,11 +26,19 @@ export interface RunProgramOptions {
|
|
|
12
26
|
* collection kind; element/key/value types come from the emit
|
|
13
27
|
* parameter's function type. */
|
|
14
28
|
emit?: 'array' | 'set' | 'dict';
|
|
15
|
-
/** Feed
|
|
29
|
+
/** Feed these `-i` inputs (0-based) lazily — segment-by-segment
|
|
16
30
|
* iteration with O(segment) decoded memory — regardless of size.
|
|
17
31
|
* Element shapes the lazy contract excludes (nested mutable
|
|
18
32
|
* containers, vectors/matrices, functions) decode whole instead. */
|
|
19
|
-
|
|
33
|
+
streamInputs?: number[];
|
|
34
|
+
/** With `emit: 'dict'`: an IR file (any format the IR positional
|
|
35
|
+
* accepts) holding a `(K, V, V) -> V` East function over the emit
|
|
36
|
+
* parameter's key and value types, compiled with the run's platforms.
|
|
37
|
+
* Adjacent emissions with an equal key fold left with it, in emission
|
|
38
|
+
* order. */
|
|
39
|
+
merge?: string;
|
|
40
|
+
/** With `emit: 'set'`: adjacent equal elements collapse to the first. */
|
|
41
|
+
union?: boolean;
|
|
20
42
|
/** Open indexed beast2 collection inputs at or above this many bytes as
|
|
21
43
|
* lazy pager-backed values (0 disables). Defaults to 64 MiB, or the
|
|
22
44
|
* `EAST_LAZY_INPUT_BYTES` environment variable. Applies only to
|
|
@@ -34,4 +56,32 @@ export declare function lazyThreshold(options: RunProgramOptions): number;
|
|
|
34
56
|
* Runs an East IR program.
|
|
35
57
|
*/
|
|
36
58
|
export declare function runProgram(irPath: string, platformFns: PlatformFunction[], packages: string[], inputPaths: string[], outputPath?: string, options?: RunProgramOptions | boolean): Promise<unknown>;
|
|
59
|
+
/** A compiled `(K, V, V) -> V` fold of equal keys. */
|
|
60
|
+
export type MergeFunction = (key: unknown, acc: unknown, value: unknown) => unknown;
|
|
61
|
+
/**
|
|
62
|
+
* Loads a `--merge` function: an IR file holding a `(K, V, V) -> V` East
|
|
63
|
+
* function over the given key and value types, compiled with the run's
|
|
64
|
+
* platforms. Shared by the emit sink and the blob merge.
|
|
65
|
+
*
|
|
66
|
+
* @param path - the IR file (any format the IR positional accepts)
|
|
67
|
+
* @param keyType - the key type
|
|
68
|
+
* @param valueType - the value type
|
|
69
|
+
* @param platformFns - the run's platforms
|
|
70
|
+
* @param subject - what the function must match, for the message: `the emit
|
|
71
|
+
* parameter` or `the inputs`
|
|
72
|
+
* @returns the compiled merge function
|
|
73
|
+
* @throws {Error} When the IR is not a function of that shape, naming the
|
|
74
|
+
* expected and the actual types.
|
|
75
|
+
*/
|
|
76
|
+
export declare function loadMergeFunction(path: string, keyType: EastTypeValue, valueType: EastTypeValue, platformFns: PlatformFunction[], subject: string): MergeFunction;
|
|
77
|
+
/**
|
|
78
|
+
* The canonical duplicate-key error, identical across runners: the emit
|
|
79
|
+
* sink's, and the blob merge's when a key is shared without a fold.
|
|
80
|
+
*
|
|
81
|
+
* @param kind - the collection kind
|
|
82
|
+
* @param printKey - the key type's printer
|
|
83
|
+
* @param key - the repeated key
|
|
84
|
+
* @returns the message
|
|
85
|
+
*/
|
|
86
|
+
export declare function duplicateMessage(kind: 'set' | 'dict', printKey: (v: unknown) => string, key: unknown): string;
|
|
37
87
|
//# sourceMappingURL=runner.d.ts.map
|