@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.
Files changed (99) hide show
  1. package/README.md +11 -2
  2. package/dist/src/browser.d.ts +5 -4
  3. package/dist/src/browser.d.ts.map +1 -1
  4. package/dist/src/browser.js +3 -2
  5. package/dist/src/browser.js.map +1 -1
  6. package/dist/src/dataset-file.d.ts +17 -19
  7. package/dist/src/dataset-file.d.ts.map +1 -1
  8. package/dist/src/dataset-file.js +26 -45
  9. package/dist/src/dataset-file.js.map +1 -1
  10. package/dist/src/export.d.ts +2 -3
  11. package/dist/src/export.d.ts.map +1 -1
  12. package/dist/src/export.js +150 -80
  13. package/dist/src/export.js.map +1 -1
  14. package/dist/src/export.spec.js +177 -57
  15. package/dist/src/export.spec.js.map +1 -1
  16. package/dist/src/function.spec.js +29 -58
  17. package/dist/src/function.spec.js.map +1 -1
  18. package/dist/src/functions-link.spec.js +19 -17
  19. package/dist/src/functions-link.spec.js.map +1 -1
  20. package/dist/src/index.d.ts +56 -8
  21. package/dist/src/index.d.ts.map +1 -1
  22. package/dist/src/index.js +11 -4
  23. package/dist/src/index.js.map +1 -1
  24. package/dist/src/input.d.ts +8 -5
  25. package/dist/src/input.d.ts.map +1 -1
  26. package/dist/src/input.js +8 -5
  27. package/dist/src/input.js.map +1 -1
  28. package/dist/src/migration.d.ts +172 -0
  29. package/dist/src/migration.d.ts.map +1 -0
  30. package/dist/src/migration.js +108 -0
  31. package/dist/src/migration.js.map +1 -0
  32. package/dist/src/migration.spec.d.ts +6 -0
  33. package/dist/src/migration.spec.d.ts.map +1 -0
  34. package/dist/src/migration.spec.js +197 -0
  35. package/dist/src/migration.spec.js.map +1 -0
  36. package/dist/src/mutation-programs.spec.d.ts +6 -0
  37. package/dist/src/mutation-programs.spec.d.ts.map +1 -0
  38. package/dist/src/mutation-programs.spec.js +310 -0
  39. package/dist/src/mutation-programs.spec.js.map +1 -0
  40. package/dist/src/mutation.d.ts +117 -9
  41. package/dist/src/mutation.d.ts.map +1 -1
  42. package/dist/src/mutation.js +104 -46
  43. package/dist/src/mutation.js.map +1 -1
  44. package/dist/src/open-beast-link.spec.js +10 -8
  45. package/dist/src/open-beast-link.spec.js.map +1 -1
  46. package/dist/src/output.d.ts +117 -0
  47. package/dist/src/output.d.ts.map +1 -0
  48. package/dist/src/output.js +119 -0
  49. package/dist/src/output.js.map +1 -0
  50. package/dist/src/package.d.ts +7 -5
  51. package/dist/src/package.d.ts.map +1 -1
  52. package/dist/src/package.js +98 -8
  53. package/dist/src/package.js.map +1 -1
  54. package/dist/src/package.spec.d.ts +6 -0
  55. package/dist/src/package.spec.d.ts.map +1 -0
  56. package/dist/src/package.spec.js +16 -0
  57. package/dist/src/package.spec.js.map +1 -0
  58. package/dist/src/record-guards.d.ts +41 -0
  59. package/dist/src/record-guards.d.ts.map +1 -0
  60. package/dist/src/record-guards.js +44 -0
  61. package/dist/src/record-guards.js.map +1 -0
  62. package/dist/src/record-index.d.ts +129 -0
  63. package/dist/src/record-index.d.ts.map +1 -0
  64. package/dist/src/record-index.js +144 -0
  65. package/dist/src/record-index.js.map +1 -0
  66. package/dist/src/record-index.spec.d.ts +6 -0
  67. package/dist/src/record-index.spec.d.ts.map +1 -0
  68. package/dist/src/record-index.spec.js +160 -0
  69. package/dist/src/record-index.spec.js.map +1 -0
  70. package/dist/src/record-programs.d.ts +128 -0
  71. package/dist/src/record-programs.d.ts.map +1 -0
  72. package/dist/src/record-programs.js +480 -0
  73. package/dist/src/record-programs.js.map +1 -0
  74. package/dist/src/record.d.ts.map +1 -1
  75. package/dist/src/record.js +2 -0
  76. package/dist/src/record.js.map +1 -1
  77. package/dist/src/record.spec.js +71 -13
  78. package/dist/src/record.spec.js.map +1 -1
  79. package/dist/src/runner.d.ts +6 -9
  80. package/dist/src/runner.d.ts.map +1 -1
  81. package/dist/src/runner.js +9 -25
  82. package/dist/src/runner.js.map +1 -1
  83. package/dist/src/runner.spec.js +16 -34
  84. package/dist/src/runner.spec.js.map +1 -1
  85. package/dist/src/sha256.d.ts +7 -4
  86. package/dist/src/sha256.d.ts.map +1 -1
  87. package/dist/src/sha256.js +26 -18
  88. package/dist/src/sha256.js.map +1 -1
  89. package/dist/src/sha256.spec.js +10 -0
  90. package/dist/src/sha256.spec.js.map +1 -1
  91. package/dist/src/task.d.ts +116 -251
  92. package/dist/src/task.d.ts.map +1 -1
  93. package/dist/src/task.js +169 -435
  94. package/dist/src/task.js.map +1 -1
  95. package/dist/src/task.spec.js +174 -489
  96. package/dist/src/task.spec.js.map +1 -1
  97. package/dist/src/types.d.ts +215 -23
  98. package/dist/src/types.d.ts.map +1 -1
  99. 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"}