@elaraai/e3 1.0.79 → 1.0.81
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 +7 -4
- package/dist/src/sha256.d.ts.map +1 -1
- package/dist/src/sha256.js +26 -18
- 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,310 @@
|
|
|
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 three write forms and the one program each generates.
|
|
7
|
+
*
|
|
8
|
+
* What is asserted here is the DELTA — the program is only interesting for
|
|
9
|
+
* what it emits — so every test runs the compiled program, reads the
|
|
10
|
+
* `(key, op)` pairs off its emit, and sorts them by the delta's key as the
|
|
11
|
+
* runner's RunSorter does. Three properties are load-bearing and none is
|
|
12
|
+
* visible from the type: no key is emitted twice, since the delta is a dict
|
|
13
|
+
* with no merge; in the delta's canonical order every target's ops are one
|
|
14
|
+
* contiguous ascending run, since variant cases compare by NAME; and an index
|
|
15
|
+
* entry whose key MOVED is a delete plus an insert rather than an update,
|
|
16
|
+
* because `{ik, k}` is the entry's identity.
|
|
17
|
+
*/
|
|
18
|
+
import { describe, it } from 'node:test';
|
|
19
|
+
import assert from 'node:assert/strict';
|
|
20
|
+
import { DateTimeType, DictType, East, IntegerType, NullType, SetType, SortedMap, SortedSet, StringType, StructType, compareFor, variant, } from '@elaraai/east';
|
|
21
|
+
import { DELTA_CONFLICT, editTypeOf, mutationDeltaType } from '@elaraai/e3-types';
|
|
22
|
+
import e3 from './index.js';
|
|
23
|
+
import { record } from './record.js';
|
|
24
|
+
import { mutation } from './mutation.js';
|
|
25
|
+
import { recordIndex } from './record-index.js';
|
|
26
|
+
import { buildMutationProgram, deltaTargets } from './record-programs.js';
|
|
27
|
+
const RowType = StructType({ status: StringType, due: IntegerType, title: StringType });
|
|
28
|
+
const PlansType = DictType(StringType, RowType);
|
|
29
|
+
const StatusKeyType = StructType({ status: StringType, due: IntegerType });
|
|
30
|
+
const CountsType = DictType(StringType, IntegerType);
|
|
31
|
+
const FlagsType = SetType(StringType);
|
|
32
|
+
const plans = new SortedMap([
|
|
33
|
+
['p1', { status: 'late', due: 3n, title: 'One' }],
|
|
34
|
+
['p2', { status: 'ok', due: 1n, title: 'Two' }],
|
|
35
|
+
], compareFor(StringType));
|
|
36
|
+
const counts = new SortedMap([['a', 1n], ['b', 2n]], compareFor(StringType));
|
|
37
|
+
const flags = new SortedSet(['x', 'y'], compareFor(StringType));
|
|
38
|
+
/** A record carrying `by_status`: one entry per row, with a covering title. */
|
|
39
|
+
function indexedPlans() {
|
|
40
|
+
const rec = record('plans', PlansType, new Map());
|
|
41
|
+
const index = recordIndex('by_status', rec, {
|
|
42
|
+
key: East.function([StringType, RowType], StatusKeyType, ($, _k, v) => ({ status: v.status, due: v.due })),
|
|
43
|
+
value: East.function([StringType, RowType], StringType, ($, _k, v) => v.title),
|
|
44
|
+
});
|
|
45
|
+
rec.indexes[index.name] = index;
|
|
46
|
+
return rec;
|
|
47
|
+
}
|
|
48
|
+
/** The delta a mutation's program writes for `state` and `args`: the
|
|
49
|
+
* `(key, op)` pairs it emits, sorted by the delta's key as the runner sorts
|
|
50
|
+
* them, none emitted twice. */
|
|
51
|
+
function emitted(rec, mut, state, args) {
|
|
52
|
+
const out = [];
|
|
53
|
+
const run = buildMutationProgram(rec, mut).compile([]);
|
|
54
|
+
run(state, ...args, (key, op) => {
|
|
55
|
+
out.push([key, op]);
|
|
56
|
+
return null;
|
|
57
|
+
});
|
|
58
|
+
const delta = mutationDeltaType(deltaTargets(rec.type, Object.values(rec.indexes)));
|
|
59
|
+
const compare = compareFor(delta.key);
|
|
60
|
+
out.sort(([a], [b]) => compare(a, b));
|
|
61
|
+
for (let i = 1; i < out.length; i++) {
|
|
62
|
+
assert.notEqual(compare(out[i - 1][0], out[i][0]), 0, 'the delta is a dict with no merge: no key is emitted twice');
|
|
63
|
+
}
|
|
64
|
+
return out;
|
|
65
|
+
}
|
|
66
|
+
/** The detail of the conflict a delta opens with, or `undefined` when it opens
|
|
67
|
+
* with none. */
|
|
68
|
+
function conflictOf(out) {
|
|
69
|
+
const key = out[0]?.[0];
|
|
70
|
+
return key?.type === DELTA_CONFLICT ? key.value : undefined;
|
|
71
|
+
}
|
|
72
|
+
/** The delta's `(target, key)` / `(target, op-tag)` pairs, which is what the
|
|
73
|
+
* apply keys on — the payloads are asserted where they matter. */
|
|
74
|
+
function shape(out) {
|
|
75
|
+
return out.map(([key, op]) => {
|
|
76
|
+
const k = key;
|
|
77
|
+
const o = op;
|
|
78
|
+
return `${k.type}:${JSON.stringify(k.value, (_n, v) => (typeof v === 'bigint' ? String(v) : v))}=${o.value.type}`;
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
describe('the mutation delta — targets and canonical order', () => {
|
|
82
|
+
it('names the primary and every index, in the order their cases compare', () => {
|
|
83
|
+
const rec = indexedPlans();
|
|
84
|
+
assert.deepEqual(deltaTargets(rec.type, Object.values(rec.indexes)).map((t) => t.name), ['by_status', 'primary']);
|
|
85
|
+
});
|
|
86
|
+
it('writes every target\'s ops in one contiguous ascending run', () => {
|
|
87
|
+
const rec = indexedPlans();
|
|
88
|
+
const retitle = mutation.reduce('retitle', rec, East.function([PlansType, StringType, StringType], PlansType, ($, state, id, title) => {
|
|
89
|
+
const next = $.let(state.copy());
|
|
90
|
+
const row = $.let(next.get(id));
|
|
91
|
+
$(next.insertOrUpdate(id, { status: row.status, due: row.due, title }));
|
|
92
|
+
return next;
|
|
93
|
+
}));
|
|
94
|
+
assert.deepEqual(shape(emitted(rec, retitle, plans, ['p1', 'Renamed'])), [
|
|
95
|
+
'by_status:{"ik":{"status":"late","due":"3"},"k":"p1"}=update',
|
|
96
|
+
'primary:"p1"=update',
|
|
97
|
+
]);
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
describe('the reduce form', () => {
|
|
101
|
+
it('turns a whole-state replace into per-key ops', () => {
|
|
102
|
+
const rec = record('counts', CountsType, new Map());
|
|
103
|
+
const reset = mutation.reduce('reset', rec, East.function([CountsType], CountsType, ($) => {
|
|
104
|
+
const next = $.let(new Map(), CountsType);
|
|
105
|
+
$(next.insert('q', 42n));
|
|
106
|
+
return next;
|
|
107
|
+
}));
|
|
108
|
+
assert.deepEqual(shape(emitted(rec, reset, counts, [])), ['primary:"a"=delete', 'primary:"b"=delete', 'primary:"q"=insert']);
|
|
109
|
+
});
|
|
110
|
+
it('writes a Set record\'s delta too — the ops carry no value', () => {
|
|
111
|
+
const rec = record('flags', FlagsType, new Set());
|
|
112
|
+
const raise = mutation.reduce('raise', rec, East.function([FlagsType, StringType], FlagsType, ($, state, flag) => {
|
|
113
|
+
const next = $.let(state.copy());
|
|
114
|
+
$(next.insert(flag));
|
|
115
|
+
return next;
|
|
116
|
+
}));
|
|
117
|
+
const out = emitted(rec, raise, flags, ['z']);
|
|
118
|
+
assert.deepEqual(shape(out), ['primary:"z"=insert']);
|
|
119
|
+
assert.equal(out[0][1].value.value, null);
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
describe('the edit form', () => {
|
|
123
|
+
it('types the capability from the record: the documented bodies, verbatim, with no casts', () => {
|
|
124
|
+
// Two documented record examples, written as an author would — so they
|
|
125
|
+
// keep compiling. `edit` is typed from `e3.mutation.editType(plans.type)`,
|
|
126
|
+
// so `edit.set` checks the key and the whole row; a body that leaves a
|
|
127
|
+
// field out does not build.
|
|
128
|
+
const PlanType = StructType({
|
|
129
|
+
title: StringType, owner: StringType, status: StringType,
|
|
130
|
+
due: DateTimeType, resources: SetType(StringType),
|
|
131
|
+
});
|
|
132
|
+
const plans = e3.record('plans', DictType(StringType, PlanType), new Map());
|
|
133
|
+
// `edit` is typed from the record: edit.set(key, row), edit.delete(key),
|
|
134
|
+
// edit.update(key, patch) — each checked against the record's key and row.
|
|
135
|
+
const reschedule = e3.mutation.edit('reschedule', plans, East.function([plans.type, StringType, DateTimeType, e3.mutation.editType(plans.type)], NullType, ($, state, id, due, edit) => {
|
|
136
|
+
const plan = $.let(state.get(id)); // one segment decoded, not the record
|
|
137
|
+
$(edit.set(id, { title: plan.title, owner: plan.owner, status: plan.status, due, resources: plan.resources }));
|
|
138
|
+
}));
|
|
139
|
+
const StatusKeyType = StructType({ status: StringType, due: DateTimeType });
|
|
140
|
+
const byStatus = e3.recordIndex('by_status', plans, {
|
|
141
|
+
key: East.function([StringType, PlanType], StatusKeyType, ($, k, v) => ({ status: v.status, due: v.due })),
|
|
142
|
+
value: East.function([StringType, PlanType], StringType, ($, k, v) => v.title),
|
|
143
|
+
});
|
|
144
|
+
const byResource = e3.recordIndex('by_resource', plans, {
|
|
145
|
+
keys: East.function([StringType, PlanType], SetType(StringType), ($, k, v) => v.resources),
|
|
146
|
+
});
|
|
147
|
+
const pkg = e3.package('planning', '1.0.0', plans, reschedule, e3.mutation.patch(plans), byStatus, byResource);
|
|
148
|
+
assert.deepEqual(Object.keys(pkg.records.plans.indexes).sort(), ['by_resource', 'by_status']);
|
|
149
|
+
// And the body does what it says: the row moves in by_status, and
|
|
150
|
+
// by_resource — whose entry neither moved nor carries a value — is untouched.
|
|
151
|
+
const row = { title: 'Pour', owner: 'ana', status: 'late', due: new Date('2026-10-01T00:00:00Z'), resources: new Set(['crane']) };
|
|
152
|
+
const state = new SortedMap([['p1', row]], compareFor(StringType));
|
|
153
|
+
assert.deepEqual(shape(emitted(pkg.records.plans, reschedule, state, ['p1', new Date('2026-11-01T00:00:00Z')])), [
|
|
154
|
+
'by_status:{"ik":{"status":"late","due":"2026-10-01T00:00:00.000Z"},"k":"p1"}=delete',
|
|
155
|
+
'by_status:{"ik":{"status":"late","due":"2026-11-01T00:00:00.000Z"},"k":"p1"}=insert',
|
|
156
|
+
'primary:"p1"=update',
|
|
157
|
+
]);
|
|
158
|
+
});
|
|
159
|
+
const EditCounts = editTypeOf(CountsType);
|
|
160
|
+
const rec = record('counts', CountsType, new Map());
|
|
161
|
+
it('resolves a set against the record: an update where it is held, an insert where it is not', () => {
|
|
162
|
+
const write = mutation.edit('write', rec, East.function([CountsType, EditCounts], NullType, ($, _state, edit) => {
|
|
163
|
+
$(edit.set('a', 10n));
|
|
164
|
+
$(edit.set('z', 10n));
|
|
165
|
+
}));
|
|
166
|
+
assert.deepEqual(shape(emitted(rec, write, counts, [])), ['primary:"a"=update', 'primary:"z"=insert']);
|
|
167
|
+
});
|
|
168
|
+
it('folds an update after a set into the set value', () => {
|
|
169
|
+
const write = mutation.edit('write', rec, East.function([CountsType, EditCounts], NullType, ($, _state, edit) => {
|
|
170
|
+
$(edit.set('a', 10n));
|
|
171
|
+
$(edit.update('a', variant('replace', { before: 10n, after: 11n })));
|
|
172
|
+
}));
|
|
173
|
+
const out = emitted(rec, write, counts, []);
|
|
174
|
+
assert.deepEqual(shape(out), ['primary:"a"=update']);
|
|
175
|
+
assert.deepEqual(out[0][1].value.value.value, { before: 1n, after: 11n }, 'one op against the state, not two');
|
|
176
|
+
});
|
|
177
|
+
it('composes an update after an update', () => {
|
|
178
|
+
const write = mutation.edit('write', rec, East.function([CountsType, EditCounts], NullType, ($, _state, edit) => {
|
|
179
|
+
$(edit.update('b', variant('replace', { before: 2n, after: 5n })));
|
|
180
|
+
$(edit.update('b', variant('replace', { before: 5n, after: 7n })));
|
|
181
|
+
}));
|
|
182
|
+
const out = emitted(rec, write, counts, []);
|
|
183
|
+
assert.deepEqual(out[0][1].value.value.value, { before: 2n, after: 7n });
|
|
184
|
+
});
|
|
185
|
+
it('writes a conflict naming the key for a delete or update of one the record does not hold', () => {
|
|
186
|
+
assert.equal(conflictOf(emitted(rec, mutation.edit('delete', rec, East.function([CountsType, EditCounts], NullType, ($, _s, edit) => {
|
|
187
|
+
$(edit.delete('zz'));
|
|
188
|
+
})), counts, [])), 'delete of "zz", which the record does not hold');
|
|
189
|
+
assert.equal(conflictOf(emitted(rec, mutation.edit('update', rec, East.function([CountsType, EditCounts], NullType, ($, _s, edit) => {
|
|
190
|
+
$(edit.update('zz', variant('replace', { before: 1n, after: 2n })));
|
|
191
|
+
})), counts, [])), 'update of "zz", which the record does not hold');
|
|
192
|
+
});
|
|
193
|
+
it('writes nothing for a key the body created and deleted again', () => {
|
|
194
|
+
// The record never held `zz`, so creating and removing it changed nothing:
|
|
195
|
+
// folded into a delete, the pair would be refused as a stale write that no
|
|
196
|
+
// resubmission could ever get past.
|
|
197
|
+
const churn = mutation.edit('churn', rec, East.function([CountsType, EditCounts], NullType, ($, _state, edit) => {
|
|
198
|
+
$(edit.set('zz', 10n));
|
|
199
|
+
$(edit.delete('zz'));
|
|
200
|
+
}));
|
|
201
|
+
assert.deepEqual(shape(emitted(rec, churn, counts, [])), []);
|
|
202
|
+
});
|
|
203
|
+
it('deletes a held key the body set before deleting it', () => {
|
|
204
|
+
const drop = mutation.edit('drop', rec, East.function([CountsType, EditCounts], NullType, ($, _state, edit) => {
|
|
205
|
+
$(edit.set('a', 10n));
|
|
206
|
+
$(edit.delete('a'));
|
|
207
|
+
}));
|
|
208
|
+
assert.deepEqual(shape(emitted(rec, drop, counts, [])), ['primary:"a"=delete']);
|
|
209
|
+
});
|
|
210
|
+
it('refuses, at definition time, a body that is not (state, …args, edit) => Null', () => {
|
|
211
|
+
const rec2 = record('counts', CountsType, new Map());
|
|
212
|
+
assert.throws(() => mutation.edit('no_edit', rec2, East.function([CountsType, StringType], NullType, ($) => { void $; })), /LAST parameter must be the edit capability/);
|
|
213
|
+
assert.throws(() => mutation.edit('returns', rec2, East.function([CountsType, EditCounts], CountsType, ($, state) => state)), /returns Null/);
|
|
214
|
+
const scalar = record('n', IntegerType, 0n);
|
|
215
|
+
assert.throws(() => mutation.edit('scalar', scalar, East.function([IntegerType], NullType, ($) => { void $; })), /needs a Dict or Set record/);
|
|
216
|
+
});
|
|
217
|
+
});
|
|
218
|
+
describe('the patch form', () => {
|
|
219
|
+
const rec = record('counts', CountsType, new Map());
|
|
220
|
+
const patch = mutation.patch(rec);
|
|
221
|
+
it('takes one argument, the state\'s patch type, and is named patch by default', () => {
|
|
222
|
+
assert.equal(patch.name, 'patch');
|
|
223
|
+
assert.equal(patch.form, 'patch');
|
|
224
|
+
assert.equal(patch.argTypes.length, 1);
|
|
225
|
+
assert.equal(patch.body, undefined, 'there is no author body to ship');
|
|
226
|
+
});
|
|
227
|
+
it('carries a patch arm through as the primary ops', () => {
|
|
228
|
+
const ops = new SortedMap([['c', variant('insert', 3n)]], compareFor(StringType));
|
|
229
|
+
assert.deepEqual(shape(emitted(rec, patch, counts, [variant('patch', ops)])), ['primary:"c"=insert']);
|
|
230
|
+
});
|
|
231
|
+
it('turns a replace arm into the ops that differ, after checking its before', () => {
|
|
232
|
+
const after = new SortedMap([['a', 1n], ['c', 3n]], compareFor(StringType));
|
|
233
|
+
assert.deepEqual(shape(emitted(rec, patch, counts, [variant('replace', { before: counts, after })])), ['primary:"b"=delete', 'primary:"c"=insert']);
|
|
234
|
+
assert.equal(conflictOf(emitted(rec, patch, counts, [variant('replace', {
|
|
235
|
+
before: new SortedMap([['a', 99n]], compareFor(StringType)),
|
|
236
|
+
after,
|
|
237
|
+
})])), 'the patch replaces a state the record no longer holds');
|
|
238
|
+
});
|
|
239
|
+
});
|
|
240
|
+
describe('index maintenance inside the delta', () => {
|
|
241
|
+
const rec = indexedPlans();
|
|
242
|
+
const EditPlans = editTypeOf(PlansType);
|
|
243
|
+
it('moves an entry as a delete plus an insert when its index key changes', () => {
|
|
244
|
+
const move = mutation.edit('move', rec, East.function([PlansType, EditPlans], NullType, ($, state, edit) => {
|
|
245
|
+
const row = $.let(state.get('p1'));
|
|
246
|
+
$(edit.set('p1', { status: 'ok', due: row.due, title: row.title }));
|
|
247
|
+
}));
|
|
248
|
+
assert.deepEqual(shape(emitted(rec, move, plans, [])), [
|
|
249
|
+
'by_status:{"ik":{"status":"late","due":"3"},"k":"p1"}=delete',
|
|
250
|
+
'by_status:{"ik":{"status":"ok","due":"3"},"k":"p1"}=insert',
|
|
251
|
+
'primary:"p1"=update',
|
|
252
|
+
]);
|
|
253
|
+
});
|
|
254
|
+
it('updates an entry in place when only the covering projection changes', () => {
|
|
255
|
+
const retitle = mutation.edit('retitle', rec, East.function([PlansType, EditPlans], NullType, ($, state, edit) => {
|
|
256
|
+
const row = $.let(state.get('p2'));
|
|
257
|
+
$(edit.set('p2', { status: row.status, due: row.due, title: 'Renamed' }));
|
|
258
|
+
}));
|
|
259
|
+
assert.deepEqual(shape(emitted(rec, retitle, plans, [])), [
|
|
260
|
+
'by_status:{"ik":{"status":"ok","due":"1"},"k":"p2"}=update',
|
|
261
|
+
'primary:"p2"=update',
|
|
262
|
+
]);
|
|
263
|
+
});
|
|
264
|
+
it('writes a stale update as a conflict naming the key', () => {
|
|
265
|
+
// An indexed record applies the patch itself, to learn where the row's
|
|
266
|
+
// entries move. A row that no longer matches the patch is a stale write
|
|
267
|
+
// here exactly as it is where the engine applies an unindexed record's
|
|
268
|
+
// patch: a caller re-reads and resubmits a conflict, but gives up on a
|
|
269
|
+
// failed program.
|
|
270
|
+
const stale = new SortedMap([['p1', variant('update', variant('patch', {
|
|
271
|
+
status: variant('unchanged', null),
|
|
272
|
+
due: variant('unchanged', null),
|
|
273
|
+
title: variant('replace', { before: 'Not the title', after: 'Renamed' }),
|
|
274
|
+
}))]], compareFor(StringType));
|
|
275
|
+
assert.equal(conflictOf(emitted(rec, mutation.patch(rec), plans, [variant('patch', stale)])), 'update of "p1", whose row no longer matches the patch');
|
|
276
|
+
});
|
|
277
|
+
it('leaves the index alone when neither its key nor its projection moved', () => {
|
|
278
|
+
const rec2 = record('plans', PlansType, new Map());
|
|
279
|
+
const index = recordIndex('by_status', rec2, {
|
|
280
|
+
key: East.function([StringType, RowType], StatusKeyType, ($, _k, v) => ({ status: v.status, due: v.due })),
|
|
281
|
+
});
|
|
282
|
+
rec2.indexes[index.name] = index;
|
|
283
|
+
const retitle = mutation.edit('retitle', rec2, East.function([PlansType, editTypeOf(PlansType)], NullType, ($, state, edit) => {
|
|
284
|
+
const row = $.let(state.get('p2'));
|
|
285
|
+
$(edit.set('p2', { status: row.status, due: row.due, title: 'Renamed' }));
|
|
286
|
+
}));
|
|
287
|
+
assert.deepEqual(shape(emitted(rec2, retitle, plans, [])), ['primary:"p2"=update']);
|
|
288
|
+
});
|
|
289
|
+
it('carries a multi-valued index\'s entries one per element of the returned set', () => {
|
|
290
|
+
const TagRowType = StructType({ tags: SetType(StringType) });
|
|
291
|
+
const TaggedType = DictType(StringType, TagRowType);
|
|
292
|
+
const rec2 = record('tagged', TaggedType, new Map());
|
|
293
|
+
const index = recordIndex('by_tag', rec2, {
|
|
294
|
+
keys: East.function([StringType, TagRowType], SetType(StringType), ($, _k, v) => v.tags),
|
|
295
|
+
});
|
|
296
|
+
rec2.indexes[index.name] = index;
|
|
297
|
+
const retag = mutation.edit('retag', rec2, East.function([TaggedType, editTypeOf(TaggedType)], NullType, ($, _s, edit) => {
|
|
298
|
+
$(edit.set('t1', { tags: new Set(['b', 'c']) }));
|
|
299
|
+
}));
|
|
300
|
+
const state = new SortedMap([
|
|
301
|
+
['t1', { tags: new Set(['a', 'b']) }],
|
|
302
|
+
], compareFor(StringType));
|
|
303
|
+
assert.deepEqual(shape(emitted(rec2, retag, state, [])), [
|
|
304
|
+
'by_tag:{"ik":"a","k":"t1"}=delete',
|
|
305
|
+
'by_tag:{"ik":"c","k":"t1"}=insert',
|
|
306
|
+
'primary:"t1"=update',
|
|
307
|
+
]);
|
|
308
|
+
});
|
|
309
|
+
});
|
|
310
|
+
//# sourceMappingURL=mutation-programs.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mutation-programs.spec.js","sourceRoot":"","sources":["../../src/mutation-programs.spec.ts"],"names":[],"mappings":"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"}
|
package/dist/src/mutation.d.ts
CHANGED
|
@@ -6,16 +6,26 @@
|
|
|
6
6
|
* Mutation definitions for e3 packages — the write half of the record
|
|
7
7
|
* machinery (CQRS; `e3.function` is the read half).
|
|
8
8
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
9
|
+
* There are three write forms and they all commit the same thing: a mutation
|
|
10
|
+
* delta, the primary's and every index's changes addressed by key, which the
|
|
11
|
+
* engine applies segment by segment. They differ in how the author says what
|
|
12
|
+
* changed — a reducer over the whole state, a body writing through an `edit`
|
|
13
|
+
* capability, or a patch sent by whoever made the edit — and so in what a
|
|
14
|
+
* write costs.
|
|
15
|
+
*
|
|
16
|
+
* All three are pure East: purity is what makes retry-on-conflict safe, since
|
|
17
|
+
* the compare-and-swap loop can re-run against fresher state with no
|
|
18
|
+
* observable side effects. They are `e3.mutation.reduce`, `e3.mutation.edit`
|
|
19
|
+
* and `e3.mutation.patch`, beside `e3.mutation.editType`, the type of the
|
|
20
|
+
* `edit` capability.
|
|
13
21
|
*/
|
|
14
|
-
import type { CallableFunctionExpr, EastType, FunctionExpr } from '@elaraai/east';
|
|
22
|
+
import type { CallableFunctionExpr, EastType, FunctionExpr, PatchTypeOf } from '@elaraai/east';
|
|
23
|
+
import { NullType } from '@elaraai/east';
|
|
24
|
+
import { editTypeOf } from '@elaraai/e3-types';
|
|
15
25
|
import type { MutationDef, RecordDef } from './types.js';
|
|
16
26
|
import { type FunctionRunner } from './runner.js';
|
|
17
27
|
/**
|
|
18
|
-
* Defines a mutation that writes a record.
|
|
28
|
+
* Defines a mutation that writes a record by reducing its whole state.
|
|
19
29
|
*
|
|
20
30
|
* The reducer is an ordinary East function whose first parameter is the
|
|
21
31
|
* current state and whose return is the new state — both the record's type,
|
|
@@ -29,10 +39,16 @@ import { type FunctionRunner } from './runner.js';
|
|
|
29
39
|
* from a `.copy()` (or build it fresh) rather than mutating in place, which
|
|
30
40
|
* raises the uniform copy-first runtime error.
|
|
31
41
|
*
|
|
42
|
+
* The reducer sees the whole state, so its cost in the runner is the record's
|
|
43
|
+
* size however little it changes; only its write, for a Dict or Set record, is
|
|
44
|
+
* proportional to what it touched — any other record's state is written whole.
|
|
45
|
+
* {@link edit} is the form whose body reads only the entries it touches, and
|
|
46
|
+
* whose commit rewrites only the segments they live in.
|
|
47
|
+
*
|
|
32
48
|
* @typeParam Name - Mutation name (literal type)
|
|
33
49
|
* @typeParam T - The owning record's state type
|
|
34
50
|
* @typeParam Args - The EXTRA positional parameter types (after the state)
|
|
35
|
-
* @param name - Mutation name
|
|
51
|
+
* @param name - Mutation name: an identifier, unique within the record
|
|
36
52
|
* @param rec - The record this mutation writes
|
|
37
53
|
* @param fn - The reducer `(state, ...args) => state`
|
|
38
54
|
* @param config - Optional runner selection (known runtimes only, like e3.function)
|
|
@@ -42,7 +58,7 @@ import { type FunctionRunner } from './runner.js';
|
|
|
42
58
|
* ```ts
|
|
43
59
|
* const orders = e3.record('orders', OrdersType, new Map());
|
|
44
60
|
*
|
|
45
|
-
* const placeOrder = e3.mutation('place_order', orders,
|
|
61
|
+
* const placeOrder = e3.mutation.reduce('place_order', orders,
|
|
46
62
|
* East.function([OrdersType, OrderType], OrdersType, ($, state, order) => {
|
|
47
63
|
* $.if(state.has(order.id), $ => $.error(East.str`duplicate order ${order.id}`));
|
|
48
64
|
* const next = $.let(state.copy());
|
|
@@ -53,7 +69,99 @@ import { type FunctionRunner } from './runner.js';
|
|
|
53
69
|
* const pkg = e3.package('planning', '1.0.0', orders, placeOrder);
|
|
54
70
|
* ```
|
|
55
71
|
*/
|
|
56
|
-
|
|
72
|
+
declare function reduce<Name extends string, T extends EastType, Args extends EastType[]>(name: Name, rec: RecordDef<T>, fn: FunctionExpr<[T, ...Args], T> | CallableFunctionExpr<[T, ...Args], T>, config?: {
|
|
57
73
|
runner?: FunctionRunner;
|
|
58
74
|
}): MutationDef<Name, T, Args>;
|
|
75
|
+
/**
|
|
76
|
+
* Defines a mutation that writes a record through an `edit` capability — the
|
|
77
|
+
* lazy write.
|
|
78
|
+
*
|
|
79
|
+
* The body is `(state, ...args, edit) => Null`. It reads the state it is given
|
|
80
|
+
* — lazily, so a body that looks at ten entries of a two-million-entry record
|
|
81
|
+
* decodes the segments those ten live in and nothing else — and writes through
|
|
82
|
+
* `edit.set(key, value)`, `edit.delete(key)` and `edit.update(key, patch)`. It
|
|
83
|
+
* never returns a state, so its commit rewrites only the segments the entries
|
|
84
|
+
* it touched live in. The state reaches its runner as the record's manifest,
|
|
85
|
+
* the segments linked, so nothing on the way reads the record whole either.
|
|
86
|
+
*
|
|
87
|
+
* Repeated edits of one key fold: `set` after anything is that `set`; `update`
|
|
88
|
+
* after `set` applies to the set value; `update` after `update` composes;
|
|
89
|
+
* `delete` after anything is `delete`. A `set` of the value the record already
|
|
90
|
+
* holds is no change. A `delete` or `update` of a key the record does not hold
|
|
91
|
+
* is a conflict naming the key, exactly as applying such a patch would be.
|
|
92
|
+
*
|
|
93
|
+
* The purity rules of {@link reduce} apply unchanged.
|
|
94
|
+
*
|
|
95
|
+
* @typeParam Name - Mutation name (literal type)
|
|
96
|
+
* @typeParam T - The owning record's state type (a Dict)
|
|
97
|
+
* @typeParam Args - The EXTRA positional parameter types (between the state and the edit)
|
|
98
|
+
* @typeParam E - The edit capability's struct type, `e3.mutation.editType(T)`
|
|
99
|
+
* @param name - Mutation name: an identifier, unique within the record
|
|
100
|
+
* @param rec - The record this mutation writes
|
|
101
|
+
* @param fn - The body `(state, ...args, edit) => null`
|
|
102
|
+
* @param config - Optional runner selection (known runtimes only)
|
|
103
|
+
* @returns A MutationDef to pass to `e3.package`
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* ```ts
|
|
107
|
+
* const PlanType = StructType({ title: StringType, owner: StringType, due: DateTimeType });
|
|
108
|
+
* const plans = e3.record('plans', DictType(StringType, PlanType), new Map());
|
|
109
|
+
*
|
|
110
|
+
* // The edit capability is the body's LAST parameter; its type comes from
|
|
111
|
+
* // the record, so `edit.set` checks the key and the row.
|
|
112
|
+
* const reschedule = e3.mutation.edit('reschedule', plans,
|
|
113
|
+
* East.function([plans.type, StringType, DateTimeType, e3.mutation.editType(plans.type)], NullType,
|
|
114
|
+
* ($, state, id, due, edit) => {
|
|
115
|
+
* const plan = $.let(state.get(id));
|
|
116
|
+
* $(edit.set(id, { title: plan.title, owner: plan.owner, due }));
|
|
117
|
+
* }));
|
|
118
|
+
* ```
|
|
119
|
+
*/
|
|
120
|
+
declare function edit<Name extends string, T extends EastType, Args extends EastType[], E extends EastType>(name: Name, rec: RecordDef<T>, fn: FunctionExpr<[T, ...Args, E], NullType> | CallableFunctionExpr<[T, ...Args, E], NullType>, config?: {
|
|
121
|
+
runner?: FunctionRunner;
|
|
122
|
+
}): MutationDef<Name, T, Args>;
|
|
123
|
+
/**
|
|
124
|
+
* Defines the mutation that applies a patch a client computed — one door for
|
|
125
|
+
* interactive edits.
|
|
126
|
+
*
|
|
127
|
+
* There is no body: the argument IS the change, a `PatchType(State)` sent by
|
|
128
|
+
* whoever made the edit — so it is what a view's save should call, and what an
|
|
129
|
+
* integration sending diffs should call.
|
|
130
|
+
*
|
|
131
|
+
* On a record with no secondary index a patch of per-key changes IS the delta
|
|
132
|
+
* and no program runs at all, which makes it the only write whose cost is
|
|
133
|
+
* independent of the record's size: the touched keys are known before anything
|
|
134
|
+
* runs. Any other patch, such as one replacing the whole state, runs a program
|
|
135
|
+
* that checks it against the state, and on a record with indexes one run
|
|
136
|
+
* computes the index entries the change moves, since that is user East and
|
|
137
|
+
* only a runner evaluates it. That run reads the rows the patch touches, and a
|
|
138
|
+
* replace reads them all.
|
|
139
|
+
*
|
|
140
|
+
* @typeParam Name - Mutation name (literal type)
|
|
141
|
+
* @typeParam T - The owning record's state type (a Dict or a Set)
|
|
142
|
+
* @param rec - The record this mutation writes
|
|
143
|
+
* @param name - Mutation name: an identifier; defaults to `patch`
|
|
144
|
+
* @param config - Optional runner selection (known runtimes only)
|
|
145
|
+
* @returns A MutationDef to pass to `e3.package`
|
|
146
|
+
*
|
|
147
|
+
* @example
|
|
148
|
+
* ```ts
|
|
149
|
+
* const plans = e3.record('plans', DictType(StringType, PlanType), new Map());
|
|
150
|
+
* const pkg = e3.package('planning', '1.0.0', plans, e3.mutation.patch(plans));
|
|
151
|
+
* ```
|
|
152
|
+
*/
|
|
153
|
+
declare function patch<T extends EastType, Name extends string = 'patch'>(rec: RecordDef<T>, name?: Name, config?: {
|
|
154
|
+
runner?: FunctionRunner;
|
|
155
|
+
}): MutationDef<Name, T, [PatchTypeOf<T>]>;
|
|
156
|
+
/**
|
|
157
|
+
* The write forms of a record: {@link reduce}, {@link edit} and {@link patch},
|
|
158
|
+
* and `editType`, the type of the capability an `edit` body writes through.
|
|
159
|
+
*/
|
|
160
|
+
export declare const mutation: {
|
|
161
|
+
reduce: typeof reduce;
|
|
162
|
+
edit: typeof edit;
|
|
163
|
+
patch: typeof patch;
|
|
164
|
+
editType: typeof editTypeOf;
|
|
165
|
+
};
|
|
166
|
+
export {};
|
|
59
167
|
//# sourceMappingURL=mutation.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mutation.d.ts","sourceRoot":"","sources":["../../src/mutation.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH
|
|
1
|
+
{"version":3,"file":"mutation.d.ts","sourceRoot":"","sources":["../../src/mutation.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAEV,oBAAoB,EACpB,QAAQ,EACR,YAAY,EACZ,WAAW,EACZ,MAAM,eAAe,CAAC;AACvB,OAAO,EAAQ,QAAQ,EAAwB,MAAM,eAAe,CAAC;AACrE,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAGzD,OAAO,EAAmC,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAoDnF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,iBAAS,MAAM,CAAC,IAAI,SAAS,MAAM,EAAE,CAAC,SAAS,QAAQ,EAAE,IAAI,SAAS,QAAQ,EAAE,EAC9E,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC,EACjB,EAAE,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,GAAG,oBAAoB,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,EACzE,MAAM,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,cAAc,CAAA;CAAE,GACnC,WAAW,CAAC,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC;AAuC9B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,iBAAS,IAAI,CAAC,IAAI,SAAS,MAAM,EAAE,CAAC,SAAS,QAAQ,EAAE,IAAI,SAAS,QAAQ,EAAE,EAAE,CAAC,SAAS,QAAQ,EAChG,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC,EACjB,EAAE,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC,EAAE,QAAQ,CAAC,GAAG,oBAAoB,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC,EAAE,QAAQ,CAAC,EAC7F,MAAM,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,cAAc,CAAA;CAAE,GACnC,WAAW,CAAC,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC;AA0C9B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,iBAAS,KAAK,CAAC,CAAC,SAAS,QAAQ,EAAE,IAAI,SAAS,MAAM,GAAG,OAAO,EAC9D,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC,EACjB,IAAI,CAAC,EAAE,IAAI,EACX,MAAM,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,cAAc,CAAA;CAAE,GACnC,WAAW,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAqB1C;;;GAGG;AACH,eAAO,MAAM,QAAQ;;;;;CAAgD,CAAC"}
|