@elaraai/e3 1.0.78 → 1.0.80
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 +11 -2
- package/dist/src/browser.d.ts +5 -4
- package/dist/src/browser.d.ts.map +1 -1
- package/dist/src/browser.js +3 -2
- package/dist/src/browser.js.map +1 -1
- package/dist/src/dataset-file.d.ts +17 -19
- package/dist/src/dataset-file.d.ts.map +1 -1
- package/dist/src/dataset-file.js +26 -45
- package/dist/src/dataset-file.js.map +1 -1
- package/dist/src/export.d.ts +2 -3
- package/dist/src/export.d.ts.map +1 -1
- package/dist/src/export.js +150 -80
- package/dist/src/export.js.map +1 -1
- package/dist/src/export.spec.js +177 -57
- package/dist/src/export.spec.js.map +1 -1
- package/dist/src/function.spec.js +29 -58
- package/dist/src/function.spec.js.map +1 -1
- package/dist/src/functions-link.spec.js +19 -17
- package/dist/src/functions-link.spec.js.map +1 -1
- package/dist/src/index.d.ts +56 -8
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +11 -4
- package/dist/src/index.js.map +1 -1
- package/dist/src/input.d.ts +8 -5
- package/dist/src/input.d.ts.map +1 -1
- package/dist/src/input.js +8 -5
- package/dist/src/input.js.map +1 -1
- package/dist/src/migration.d.ts +172 -0
- package/dist/src/migration.d.ts.map +1 -0
- package/dist/src/migration.js +108 -0
- package/dist/src/migration.js.map +1 -0
- package/dist/src/migration.spec.d.ts +6 -0
- package/dist/src/migration.spec.d.ts.map +1 -0
- package/dist/src/migration.spec.js +197 -0
- package/dist/src/migration.spec.js.map +1 -0
- package/dist/src/mutation-programs.spec.d.ts +6 -0
- package/dist/src/mutation-programs.spec.d.ts.map +1 -0
- package/dist/src/mutation-programs.spec.js +310 -0
- package/dist/src/mutation-programs.spec.js.map +1 -0
- package/dist/src/mutation.d.ts +117 -9
- package/dist/src/mutation.d.ts.map +1 -1
- package/dist/src/mutation.js +104 -46
- package/dist/src/mutation.js.map +1 -1
- package/dist/src/open-beast-link.spec.js +10 -8
- package/dist/src/open-beast-link.spec.js.map +1 -1
- package/dist/src/output.d.ts +117 -0
- package/dist/src/output.d.ts.map +1 -0
- package/dist/src/output.js +119 -0
- package/dist/src/output.js.map +1 -0
- package/dist/src/package.d.ts +7 -5
- package/dist/src/package.d.ts.map +1 -1
- package/dist/src/package.js +98 -8
- package/dist/src/package.js.map +1 -1
- package/dist/src/package.spec.d.ts +6 -0
- package/dist/src/package.spec.d.ts.map +1 -0
- package/dist/src/package.spec.js +16 -0
- package/dist/src/package.spec.js.map +1 -0
- package/dist/src/record-guards.d.ts +41 -0
- package/dist/src/record-guards.d.ts.map +1 -0
- package/dist/src/record-guards.js +44 -0
- package/dist/src/record-guards.js.map +1 -0
- package/dist/src/record-index.d.ts +129 -0
- package/dist/src/record-index.d.ts.map +1 -0
- package/dist/src/record-index.js +144 -0
- package/dist/src/record-index.js.map +1 -0
- package/dist/src/record-index.spec.d.ts +6 -0
- package/dist/src/record-index.spec.d.ts.map +1 -0
- package/dist/src/record-index.spec.js +160 -0
- package/dist/src/record-index.spec.js.map +1 -0
- package/dist/src/record-programs.d.ts +128 -0
- package/dist/src/record-programs.d.ts.map +1 -0
- package/dist/src/record-programs.js +480 -0
- package/dist/src/record-programs.js.map +1 -0
- package/dist/src/record.d.ts.map +1 -1
- package/dist/src/record.js +2 -0
- package/dist/src/record.js.map +1 -1
- package/dist/src/record.spec.js +71 -13
- package/dist/src/record.spec.js.map +1 -1
- package/dist/src/runner.d.ts +6 -9
- package/dist/src/runner.d.ts.map +1 -1
- package/dist/src/runner.js +9 -25
- package/dist/src/runner.js.map +1 -1
- package/dist/src/runner.spec.js +16 -34
- package/dist/src/runner.spec.js.map +1 -1
- package/dist/src/sha256.d.ts +4 -3
- package/dist/src/sha256.d.ts.map +1 -1
- package/dist/src/sha256.js +20 -17
- package/dist/src/sha256.js.map +1 -1
- package/dist/src/sha256.spec.js +10 -0
- package/dist/src/sha256.spec.js.map +1 -1
- package/dist/src/task.d.ts +116 -251
- package/dist/src/task.d.ts.map +1 -1
- package/dist/src/task.js +169 -435
- package/dist/src/task.js.map +1 -1
- package/dist/src/task.spec.js +174 -489
- package/dist/src/task.spec.js.map +1 -1
- package/dist/src/types.d.ts +215 -23
- package/dist/src/types.d.ts.map +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1,160 @@
|
|
|
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
|
+
* `e3.recordIndex` — the declaration and the program built from it.
|
|
7
|
+
*
|
|
8
|
+
* Every guard here is a definition-time error: an index that is wrong is worse
|
|
9
|
+
* than no index, because the view it serves is quietly wrong rather than
|
|
10
|
+
* missing, so the refusals happen at the developer's desk.
|
|
11
|
+
*
|
|
12
|
+
* The build program is what actually runs, and its two load-bearing properties
|
|
13
|
+
* are asserted by running it: each row's entries come out as the row is read,
|
|
14
|
+
* keyed `{ik, k}` — index key first — for the runner's RunSorter to sort, and a
|
|
15
|
+
* multi-valued index emits one entry per element of the returned set, so an
|
|
16
|
+
* empty set is a row the index does not carry.
|
|
17
|
+
*/
|
|
18
|
+
import { describe, it } from 'node:test';
|
|
19
|
+
import assert from 'node:assert/strict';
|
|
20
|
+
import { DictType, East, IntegerType, NullType, SetType, SortedMap, StringType, StructType, compareFor, printType, } from '@elaraai/east';
|
|
21
|
+
import { record } from './record.js';
|
|
22
|
+
import { recordIndex } from './record-index.js';
|
|
23
|
+
import { indexBuildProgram } from './record-programs.js';
|
|
24
|
+
import { package_ } from './package.js';
|
|
25
|
+
const RowType = StructType({ status: StringType, due: IntegerType, title: StringType, tags: SetType(StringType) });
|
|
26
|
+
const StatusKeyType = StructType({ status: StringType, due: IntegerType });
|
|
27
|
+
const PlansType = DictType(StringType, RowType);
|
|
28
|
+
/** The `by_status` declaration: one key per row, with a covering projection. */
|
|
29
|
+
const statusKey = East.function([StringType, RowType], StatusKeyType, ($, _k, v) => ({ status: v.status, due: v.due }));
|
|
30
|
+
const titleOf = East.function([StringType, RowType], StringType, ($, _k, v) => v.title);
|
|
31
|
+
/** The `by_tag` declaration: many keys per row. */
|
|
32
|
+
const tagKeys = East.function([StringType, RowType], SetType(StringType), ($, _k, v) => v.tags);
|
|
33
|
+
const plans = () => record('plans', PlansType, new Map());
|
|
34
|
+
/** The `[entry, projection]` pairs a build program emits for `rows`. */
|
|
35
|
+
function emitted(recordType, def, rows) {
|
|
36
|
+
const out = [];
|
|
37
|
+
const run = indexBuildProgram(recordType, def).compile([]);
|
|
38
|
+
run(rows, (entry, value) => {
|
|
39
|
+
out.push([entry, value]);
|
|
40
|
+
return null;
|
|
41
|
+
});
|
|
42
|
+
return out;
|
|
43
|
+
}
|
|
44
|
+
const rows = new SortedMap([
|
|
45
|
+
['p1', { status: 'late', due: 3n, title: 'One', tags: new Set(['a', 'b']) }],
|
|
46
|
+
['p2', { status: 'ok', due: 1n, title: 'Two', tags: new Set(['b']) }],
|
|
47
|
+
['p3', { status: 'late', due: 2n, title: 'Three', tags: new Set() }],
|
|
48
|
+
], compareFor(StringType));
|
|
49
|
+
describe('recordIndex — the declaration', () => {
|
|
50
|
+
// The typed bindings below are half of each test: they compile only when the
|
|
51
|
+
// declaration carries the exact key and projection types, which are what
|
|
52
|
+
// type a window read through the index — and so every component rendering
|
|
53
|
+
// one. An erased EastType is assignable to none of them.
|
|
54
|
+
it('reads the index key and the projection off the declared functions', () => {
|
|
55
|
+
const index = recordIndex('by_status', plans(), { key: statusKey, value: titleOf });
|
|
56
|
+
const keyType = index.keyType;
|
|
57
|
+
const valueType = index.valueType;
|
|
58
|
+
assert.equal(index.kind, 'recordIndex');
|
|
59
|
+
assert.equal(index.name, 'by_status');
|
|
60
|
+
assert.equal(index.multi, false);
|
|
61
|
+
assert.equal(printType(keyType), printType(StatusKeyType));
|
|
62
|
+
assert.equal(printType(valueType), printType(StringType));
|
|
63
|
+
});
|
|
64
|
+
it('unwraps the element type of a multi-valued index, and carries no value by default', () => {
|
|
65
|
+
const index = recordIndex('by_tag', plans(), { keys: tagKeys });
|
|
66
|
+
const keyType = index.keyType;
|
|
67
|
+
const valueType = index.valueType;
|
|
68
|
+
assert.equal(index.multi, true);
|
|
69
|
+
assert.equal(printType(keyType), printType(StringType), 'the SET is unwrapped to its element');
|
|
70
|
+
assert.equal(printType(valueType), printType(NullType));
|
|
71
|
+
});
|
|
72
|
+
it('is collected onto its record by the package', () => {
|
|
73
|
+
const rec = plans();
|
|
74
|
+
const pkg = package_('planning', '1.0.0', rec, recordIndex('by_status', rec, { key: statusKey }), recordIndex('by_tag', rec, { keys: tagKeys }));
|
|
75
|
+
assert.deepEqual(Object.keys(pkg.records.plans.indexes).sort(), ['by_status', 'by_tag']);
|
|
76
|
+
});
|
|
77
|
+
describe('refuses, at definition time', () => {
|
|
78
|
+
it('the reserved name, a non-identifier name, and an empty one', () => {
|
|
79
|
+
assert.throws(() => recordIndex('primary', plans(), { key: statusKey }), /cannot be named 'primary'/);
|
|
80
|
+
assert.throws(() => recordIndex('by status', plans(), { key: statusKey }), /must be an identifier/);
|
|
81
|
+
assert.throws(() => recordIndex('', plans(), { key: statusKey }), /non-empty name/);
|
|
82
|
+
});
|
|
83
|
+
it('a name declared twice on the record', () => {
|
|
84
|
+
const rec = plans();
|
|
85
|
+
const first = recordIndex('by_status', rec, { key: statusKey });
|
|
86
|
+
const second = recordIndex('by_status', rec, { key: statusKey, value: titleOf });
|
|
87
|
+
// A record keeps one index per name. With two it would keep whichever
|
|
88
|
+
// came last, and a page through `by_status` would read the other one.
|
|
89
|
+
assert.throws(() => package_('planning', '1.0.0', rec, first, second), /record 'plans' declares two indexes named 'by_status'/);
|
|
90
|
+
// One declaration passed twice is one index.
|
|
91
|
+
assert.deepEqual(Object.keys(package_('planning', '1.0.0', rec, first, first).records.plans.indexes), ['by_status']);
|
|
92
|
+
// An assembled record carries its indexes, so the name is refused at once.
|
|
93
|
+
const assembled = package_('planning', '1.0.0', rec, first).records.plans;
|
|
94
|
+
assert.throws(() => recordIndex('by_status', assembled, { key: statusKey }), /already declared/);
|
|
95
|
+
});
|
|
96
|
+
it('both or neither of key and keys', () => {
|
|
97
|
+
assert.throws(() => recordIndex('both', plans(), { key: statusKey, keys: tagKeys }), /exactly one of 'key'/);
|
|
98
|
+
assert.throws(() => recordIndex('neither', plans(), {}), /exactly one of 'key'/);
|
|
99
|
+
});
|
|
100
|
+
it('a keys function that does not return a Set', () => {
|
|
101
|
+
assert.throws(() => recordIndex('flat', plans(), { keys: statusKey }), /must return a Set of index keys/);
|
|
102
|
+
});
|
|
103
|
+
it('a function whose parameters are not the record\'s entry', () => {
|
|
104
|
+
assert.throws(() => recordIndex('wrong', plans(), { key: East.function([IntegerType], StringType, ($, _x) => 'only one parameter') }), /must take the record's entry/);
|
|
105
|
+
assert.throws(() => recordIndex('wrong_value', plans(), {
|
|
106
|
+
key: statusKey,
|
|
107
|
+
value: East.function([StringType], StringType, ($, k) => k),
|
|
108
|
+
}), /'value' projection must take the record's entry/);
|
|
109
|
+
});
|
|
110
|
+
it('a record that is not a Dict — there is no entry to index', () => {
|
|
111
|
+
const flags = record('flags', SetType(StringType), new Set());
|
|
112
|
+
assert.throws(() => recordIndex('on_set', flags, { key: statusKey }), /indexes a Dict record/);
|
|
113
|
+
});
|
|
114
|
+
it('an async function, and one that reaches a platform function', () => {
|
|
115
|
+
assert.throws(
|
|
116
|
+
// Only a dynamic or cast caller reaches this — the typed surface
|
|
117
|
+
// refuses an async function — but a wrong index is a quietly wrong
|
|
118
|
+
// view, so the guard is a runtime one too.
|
|
119
|
+
() => recordIndex('async', plans(), {
|
|
120
|
+
key: East.asyncFunction([StringType, RowType], StringType, ($, k, _v) => k),
|
|
121
|
+
}), /must be a synchronous East function/);
|
|
122
|
+
// A synchronous platform call is an ordinary function IR, so only the
|
|
123
|
+
// walk over the body finds it — in the key function and the projection
|
|
124
|
+
// alike.
|
|
125
|
+
assert.throws(() => recordIndex('clock', plans(), {
|
|
126
|
+
key: East.function([StringType, RowType], IntegerType, ($, _k, v) => v.due.add(East.platform('time_now', [], IntegerType)())),
|
|
127
|
+
}), /'key' function must not call platform functions \(found 'time_now'\)/);
|
|
128
|
+
assert.throws(() => recordIndex('clock_value', plans(), {
|
|
129
|
+
key: statusKey,
|
|
130
|
+
value: East.function([StringType, RowType], IntegerType, ($, _k, _v) => East.platform('time_now', [], IntegerType)()),
|
|
131
|
+
}), /'value' projection must not call platform functions \(found 'time_now'\)/);
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
describe('recordIndex — the build program', () => {
|
|
136
|
+
it('emits each row\'s entry as it reads the row, index key first', () => {
|
|
137
|
+
const out = emitted(PlansType, recordIndex('by_status', plans(), { key: statusKey, value: titleOf }), rows);
|
|
138
|
+
assert.deepEqual(out, [
|
|
139
|
+
[{ ik: { status: 'late', due: 3n }, k: 'p1' }, 'One'],
|
|
140
|
+
[{ ik: { status: 'ok', due: 1n }, k: 'p2' }, 'Two'],
|
|
141
|
+
[{ ik: { status: 'late', due: 2n }, k: 'p3' }, 'Three'],
|
|
142
|
+
]);
|
|
143
|
+
});
|
|
144
|
+
it('emits one entry per element of a multi-valued key, and none for an empty set', () => {
|
|
145
|
+
const out = emitted(PlansType, recordIndex('by_tag', plans(), { keys: tagKeys }), rows);
|
|
146
|
+
assert.deepEqual(out, [
|
|
147
|
+
[{ ik: 'a', k: 'p1' }, null],
|
|
148
|
+
[{ ik: 'b', k: 'p1' }, null],
|
|
149
|
+
[{ ik: 'b', k: 'p2' }, null],
|
|
150
|
+
]);
|
|
151
|
+
});
|
|
152
|
+
it('carries Null where an index declares no projection', () => {
|
|
153
|
+
const out = emitted(PlansType, recordIndex('by_status', plans(), { key: statusKey }), rows);
|
|
154
|
+
assert.deepEqual(out.map(([, value]) => value), [null, null, null]);
|
|
155
|
+
});
|
|
156
|
+
it('emits nothing for an empty record', () => {
|
|
157
|
+
assert.deepEqual(emitted(PlansType, recordIndex('by_status', plans(), { key: statusKey }), new Map()), []);
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
//# sourceMappingURL=record-index.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"record-index.spec.js","sourceRoot":"","sources":["../../src/record-index.spec.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,128 @@
|
|
|
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 East programs a record's declarations generate.
|
|
7
|
+
*
|
|
8
|
+
* An author declares what an index keys on, how a mutation writes and how a
|
|
9
|
+
* migration changes a row; what actually runs is a program built from those
|
|
10
|
+
* declarations — an ordinary East function assembled at export time from the
|
|
11
|
+
* author's own expressions, as a stream task's output kind builds its merge
|
|
12
|
+
* function. It is linked and
|
|
13
|
+
* encoded like any other body, runs on the runner the author chose, and is
|
|
14
|
+
* what keeps e3 out of the business of evaluating user East: the engine runs a
|
|
15
|
+
* program and applies what it emits.
|
|
16
|
+
*
|
|
17
|
+
* @packageDocumentation
|
|
18
|
+
*/
|
|
19
|
+
import { type EastIR, type EastType } from '@elaraai/east';
|
|
20
|
+
import { type DeltaTarget } from '@elaraai/e3-types';
|
|
21
|
+
import type { MigrationDef, MutationDef, RecordDef, RecordIndexDef } from './types.js';
|
|
22
|
+
/**
|
|
23
|
+
* The entry key an index collection sorts under: `{ik, k}`.
|
|
24
|
+
*
|
|
25
|
+
* @remarks
|
|
26
|
+
* `ik` first, so every entry with one index key is a contiguous run — ordered
|
|
27
|
+
* by primary key inside it — and a range of index keys is one contiguous run
|
|
28
|
+
* too. Struct keys compare field by field in declaration order, which is what
|
|
29
|
+
* makes that true rather than merely intended.
|
|
30
|
+
*
|
|
31
|
+
* @param keyType - the record's primary key type
|
|
32
|
+
* @param indexKeyType - the index key
|
|
33
|
+
* @returns the entry key type
|
|
34
|
+
*/
|
|
35
|
+
export declare function indexEntryKeyType(keyType: EastType, indexKeyType: EastType): EastType;
|
|
36
|
+
/**
|
|
37
|
+
* The build program of an index: `(piece, emit) => Null`.
|
|
38
|
+
*
|
|
39
|
+
* @remarks
|
|
40
|
+
* Called with a piece of the primary — a whole small record, or one piece of a
|
|
41
|
+
* large one — it emits each row's index entries as it reads the row. Index
|
|
42
|
+
* order is not primary order, and need not be: the runner writes a `dict`
|
|
43
|
+
* output through its RunSorter, which sorts what it is given, so the program
|
|
44
|
+
* holds no more than the row in hand.
|
|
45
|
+
*
|
|
46
|
+
* The author's key and value functions are bound as function values and
|
|
47
|
+
* CALLED, never spliced into the loop: a spliced expression tree would be
|
|
48
|
+
* re-evaluated per reference and could capture the wrong bindings.
|
|
49
|
+
*
|
|
50
|
+
* @param recordType - the record's state type, `Dict<K, V>`
|
|
51
|
+
* @param def - the index declaration
|
|
52
|
+
* @returns the program's IR bundle
|
|
53
|
+
*/
|
|
54
|
+
export declare function indexBuildProgram(recordType: EastType, def: RecordIndexDef): EastIR<any, any>;
|
|
55
|
+
/**
|
|
56
|
+
* The program a `rows` or `rekey` migration runs over each piece of a record's
|
|
57
|
+
* state: `(piece, emit) => Null`.
|
|
58
|
+
*
|
|
59
|
+
* @remarks
|
|
60
|
+
* It calls the author's function on each row, or element, as it reads it, and
|
|
61
|
+
* emits what the function returns: a `rows` step under the row's own key, or
|
|
62
|
+
* in order over an Array; a `rekey` step under the key the function returns,
|
|
63
|
+
* or, over a Set, as the element it returns. The runner writes a `dict` or
|
|
64
|
+
* `set` output through its RunSorter, which sorts what it is given, and an
|
|
65
|
+
* `array` output in the order emitted, so the program holds no more than the
|
|
66
|
+
* row in hand.
|
|
67
|
+
*
|
|
68
|
+
* The author's function is bound as a function value and CALLED, never
|
|
69
|
+
* spliced: a spliced expression tree would be re-evaluated per reference and
|
|
70
|
+
* could capture the wrong bindings.
|
|
71
|
+
*
|
|
72
|
+
* @param def - the migration, a `rows` or `rekey` step
|
|
73
|
+
* @returns the program's IR bundle
|
|
74
|
+
* @throws {Error} When the step is a `value` step, whose own function runs.
|
|
75
|
+
*/
|
|
76
|
+
export declare function migrationProgram(def: MigrationDef): EastIR<any, any>;
|
|
77
|
+
/**
|
|
78
|
+
* The delta's targets for a record: its own collection, then each index.
|
|
79
|
+
*
|
|
80
|
+
* @remarks
|
|
81
|
+
* The names become the delta's variant cases, which is why `primary` is a
|
|
82
|
+
* reserved index name. Returned in the order the cases compare in — variant
|
|
83
|
+
* values order by case NAME — which is the order the delta holds their ops in.
|
|
84
|
+
*
|
|
85
|
+
* @param recordType - the record's state type, a Dict or a Set
|
|
86
|
+
* @param indexes - the record's index declarations
|
|
87
|
+
* @returns the targets, in canonical case order
|
|
88
|
+
*/
|
|
89
|
+
export declare function deltaTargets(recordType: EastType, indexes: readonly RecordIndexDef[]): DeltaTarget[];
|
|
90
|
+
/** Whether a record's own collection has a delta at all: one addressed by key,
|
|
91
|
+
* which is what lets a commit rebuild only the segments it touched. An Array
|
|
92
|
+
* record's patch is positional, and a scalar's is a replace. */
|
|
93
|
+
export declare function hasKeyedDelta(recordType: EastType): boolean;
|
|
94
|
+
/**
|
|
95
|
+
* The program every write form runs: `(State, …Args | Patch, Emit) => Null`.
|
|
96
|
+
*
|
|
97
|
+
* @remarks
|
|
98
|
+
* One program, three forms, one output — the mutation delta, emitted entry by
|
|
99
|
+
* entry as it is computed, in any order: the runner writes a `dict` output
|
|
100
|
+
* through its RunSorter, which sorts it. e3 stores the delta as segments and
|
|
101
|
+
* applies it one target segment at a time; it never evaluates the author's
|
|
102
|
+
* East itself, which is what keeps one rule for where user code runs and gives
|
|
103
|
+
* the three runtimes something to agree on byte for byte.
|
|
104
|
+
*
|
|
105
|
+
* The three forms differ only in how the per-key ops are reached — a diff of
|
|
106
|
+
* the reducer's result, the folded writes of an `edit` body, or the client's
|
|
107
|
+
* own patch — after which the tail is shared: for each touched key, emit its
|
|
108
|
+
* op, then resolve the old and new row and ask each index what its entry was
|
|
109
|
+
* and what it becomes.
|
|
110
|
+
*
|
|
111
|
+
* A write the state moved under — a patch whose `before` the record no longer
|
|
112
|
+
* holds, an update of a row that no longer matches, a delete or update of a
|
|
113
|
+
* key the record does not hold — is emitted as a {@link DELTA_CONFLICT} entry
|
|
114
|
+
* naming it, which sorts first, rather than failing the program: a caller
|
|
115
|
+
* resubmits a conflict and gives up on a failure.
|
|
116
|
+
*
|
|
117
|
+
* The author's functions are bound as function values and CALLED, never
|
|
118
|
+
* spliced: a spliced tree would be re-evaluated per reference and could
|
|
119
|
+
* capture the wrong bindings.
|
|
120
|
+
*
|
|
121
|
+
* @param rec - the record, carrying its indexes
|
|
122
|
+
* @param mut - the mutation declaration
|
|
123
|
+
* @returns the program's IR bundle
|
|
124
|
+
* @throws {Error} When the record's collection has no keyed delta, or an
|
|
125
|
+
* `edit` / `patch` mutation has no body where one is required.
|
|
126
|
+
*/
|
|
127
|
+
export declare function buildMutationProgram(rec: RecordDef, mut: MutationDef): EastIR<any, any>;
|
|
128
|
+
//# sourceMappingURL=record-programs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"record-programs.d.ts","sourceRoot":"","sources":["../../src/record-programs.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAaL,KAAK,MAAM,EACX,KAAK,QAAQ,EACd,MAAM,eAAe,CAAC;AACvB,OAAO,EAC6E,KAAK,WAAW,EACnG,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEvF;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,QAAQ,GAAG,QAAQ,CAErF;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,QAAQ,EAAE,GAAG,EAAE,cAAc,GAAG,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,CAoB7F;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,YAAY,GAAG,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,CA2BpE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,cAAc,EAAE,GAAG,WAAW,EAAE,CAapG;AAUD;;iEAEiE;AACjE,wBAAgB,aAAa,CAAC,UAAU,EAAE,QAAQ,GAAG,OAAO,CAG3D;AAkED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,SAAS,EAAE,GAAG,EAAE,WAAW,GAAG,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,CAwEvF"}
|