@agentshouse/mdruntime 0.1.0-ca6edc1abd618 → 0.1.0-ca92b54804c33
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 +2 -2
- package/dist/adapter.d.ts +101 -70
- package/dist/adapter.d.ts.map +1 -1
- package/dist/attached-model.d.ts +3 -10
- package/dist/attached-model.d.ts.map +1 -1
- package/dist/attached-model.js +29 -47
- package/dist/bootstrap.d.ts +16 -14
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +272 -129
- package/dist/chain.d.ts +2 -1
- package/dist/chain.d.ts.map +1 -1
- package/dist/change.d.ts +1 -0
- package/dist/change.d.ts.map +1 -1
- package/dist/client.d.ts +13 -9
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +54 -6
- package/dist/collection.d.ts +7 -4
- package/dist/collection.d.ts.map +1 -1
- package/dist/collection.js +23 -17
- package/dist/compile.d.ts +1 -6
- package/dist/compile.d.ts.map +1 -1
- package/dist/compile.js +108 -243
- package/dist/connection.d.ts +14 -11
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +2264 -1933
- package/dist/context.d.ts +2 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +7 -0
- package/dist/conversation.d.ts +21 -17
- package/dist/conversation.d.ts.map +1 -1
- package/dist/conversation.js +405 -253
- package/dist/durability.d.ts +6 -1
- package/dist/durability.d.ts.map +1 -1
- package/dist/entry.d.ts +3 -2
- package/dist/entry.d.ts.map +1 -1
- package/dist/entry.js +18 -8
- package/dist/file.d.ts +2 -11
- package/dist/file.d.ts.map +1 -1
- package/dist/file.js +6 -4
- package/dist/host.d.ts +3 -7
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +26 -29
- package/dist/identity.d.ts +0 -1
- package/dist/identity.d.ts.map +1 -1
- package/dist/identity.js +0 -3
- package/dist/index.d.ts +12 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/job.d.ts +14 -0
- package/dist/job.d.ts.map +1 -0
- package/dist/job.js +28 -0
- package/dist/live.d.ts +5 -4
- package/dist/live.d.ts.map +1 -1
- package/dist/live.js +62 -20
- package/dist/media.d.ts +8 -0
- package/dist/media.d.ts.map +1 -0
- package/dist/media.js +218 -0
- package/dist/memory.d.ts +12 -5
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +216 -85
- package/dist/messages.d.ts +3 -3
- package/dist/messages.d.ts.map +1 -1
- package/dist/messages.js +20 -19
- package/dist/model.d.ts +8 -10
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +5 -17
- package/dist/observation.d.ts +3 -2
- package/dist/observation.d.ts.map +1 -1
- package/dist/observation.js +8 -3
- package/dist/outcome.d.ts +13 -5
- package/dist/outcome.d.ts.map +1 -1
- package/dist/outcome.js +16 -2
- package/dist/overlay.d.ts +1 -0
- package/dist/overlay.d.ts.map +1 -1
- package/dist/overlay.js +11 -0
- package/dist/paths.d.ts +1 -0
- package/dist/paths.d.ts.map +1 -1
- package/dist/paths.js +4 -0
- package/dist/query.d.ts +8 -207
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +3 -505
- package/dist/reach.d.ts +18 -11
- package/dist/reach.d.ts.map +1 -1
- package/dist/reach.js +195 -126
- package/dist/react.d.ts +3 -1
- package/dist/react.d.ts.map +1 -1
- package/dist/readiness.d.ts +3 -17
- package/dist/readiness.d.ts.map +1 -1
- package/dist/readiness.js +4 -10
- package/dist/recovery.d.ts +1 -0
- package/dist/recovery.d.ts.map +1 -1
- package/dist/recovery.js +35 -1
- package/dist/refresh.d.ts +7 -5
- package/dist/refresh.d.ts.map +1 -1
- package/dist/refresh.js +33 -5
- package/dist/replica.d.ts +10 -8
- package/dist/replica.d.ts.map +1 -1
- package/dist/replica.js +52 -20
- package/dist/room-draft.d.ts +21 -5
- package/dist/room-draft.d.ts.map +1 -1
- package/dist/room-draft.js +98 -51
- package/dist/rows.d.ts +18 -16
- package/dist/rows.d.ts.map +1 -1
- package/dist/rows.js +45 -153
- package/dist/save.d.ts +2 -0
- package/dist/save.d.ts.map +1 -1
- package/dist/save.js +22 -13
- package/dist/search.d.ts +12 -63
- package/dist/search.d.ts.map +1 -1
- package/dist/search.js +9 -52
- package/dist/shared.d.ts +0 -1
- package/dist/shared.d.ts.map +1 -1
- package/dist/shared.js +0 -10
- package/dist/status.d.ts +4 -5
- package/dist/status.d.ts.map +1 -1
- package/dist/status.js +3 -7
- package/dist/store.d.ts +101 -61
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +153 -161
- package/dist/stored.d.ts +66 -55
- package/dist/stored.d.ts.map +1 -1
- package/dist/stored.js +341 -273
- package/dist/tables.d.ts +90 -63
- package/dist/tables.d.ts.map +1 -1
- package/dist/tables.js +174 -98
- package/dist/transfer.d.ts +0 -5
- package/dist/transfer.d.ts.map +1 -1
- package/dist/validation.d.ts +3 -4
- package/dist/validation.d.ts.map +1 -1
- package/dist/validation.js +42 -100
- package/dist/windows.d.ts +1 -12
- package/dist/windows.d.ts.map +1 -1
- package/dist/windows.js +2 -75
- package/dist/wire.d.ts +17 -8
- package/dist/wire.d.ts.map +1 -1
- package/dist/wire.js +5 -2
- package/package.json +2 -2
- package/dist/fence.d.ts +0 -6
- package/dist/fence.d.ts.map +0 -1
- package/dist/fence.js +0 -10
- package/dist/fulltext.d.ts +0 -27
- package/dist/fulltext.d.ts.map +0 -1
- package/dist/fulltext.js +0 -368
- package/dist/reads.d.ts +0 -11
- package/dist/reads.d.ts.map +0 -1
- package/dist/reads.js +0 -100
- package/dist/words.d.ts +0 -19
- package/dist/words.d.ts.map +0 -1
- package/dist/words.js +0 -150
package/dist/compile.js
CHANGED
|
@@ -1,107 +1,36 @@
|
|
|
1
|
-
import { ARRAY_INDEX, parse, pointerSegments } from '@agentshouse/mdmodel';
|
|
1
|
+
import { ARRAY_INDEX, bodied, byCodePoint, compared, cursorOf, heldKind, parse, pointerSegments, sql, } from '@agentshouse/mdmodel';
|
|
2
2
|
import { binaryRecord } from './binary.js';
|
|
3
|
-
import { documentKey,
|
|
4
|
-
import {
|
|
3
|
+
import { documentKey, pathOfKey, roomOfKey } from './rows.js';
|
|
4
|
+
import { FROM_START, MAXIMUM_WINDOW } from './windows.js';
|
|
5
|
+
const { all, any, exists, fragment, grouped, joined, listed } = sql;
|
|
5
6
|
const VISIBLE = (alias) => `${alias}.visible = 1 AND ${alias}.present = 1 AND ${alias}.queried = 1`;
|
|
6
|
-
function
|
|
7
|
-
return
|
|
7
|
+
function located(alias) {
|
|
8
|
+
return fragment(`(SELECT k.locator FROM replica_keys k WHERE k.key = ${alias}.key)`);
|
|
8
9
|
}
|
|
9
|
-
function
|
|
10
|
-
return {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
function all(parts) {
|
|
16
|
-
return parts.length === 0 ? fragment('1') : joined(parts.map(grouped), ' AND ');
|
|
17
|
-
}
|
|
18
|
-
function any(parts) {
|
|
19
|
-
return parts.length === 0 ? fragment('0') : joined(parts.map(grouped), ' OR ');
|
|
20
|
-
}
|
|
21
|
-
function grouped(part) {
|
|
22
|
-
return { sql: `(${part.sql})`, bind: part.bind };
|
|
23
|
-
}
|
|
24
|
-
function list(values) {
|
|
25
|
-
return fragment(`(${values.map(() => '?').join(', ')})`, values);
|
|
26
|
-
}
|
|
27
|
-
function sqlValue(value) {
|
|
28
|
-
if (value === null)
|
|
29
|
-
return { kind: 'null', value: null };
|
|
30
|
-
if (typeof value === 'boolean')
|
|
31
|
-
return { kind: 'boolean', value: value ? 1 : 0 };
|
|
32
|
-
if (typeof value === 'number')
|
|
33
|
-
return { kind: 'number', value };
|
|
34
|
-
return { kind: 'string', value };
|
|
35
|
-
}
|
|
36
|
-
function same(alias, value) {
|
|
37
|
-
const held = sqlValue(value);
|
|
38
|
-
return held.kind === 'null'
|
|
39
|
-
? fragment(`${alias}.kind = 'null'`)
|
|
40
|
-
: fragment(`${alias}.kind = ? AND ${alias}.value = ?`, [held.kind, held.value]);
|
|
41
|
-
}
|
|
42
|
-
const BOUNDS = { gt: '>', gte: '>=', lt: '<', lte: '<=' };
|
|
43
|
-
function heldValues(doc, field, alias, where) {
|
|
44
|
-
return fragment(`SELECT 1 FROM replica_values ${alias} WHERE ${alias}.doc = ${doc}.id AND ${alias}.form = ? AND (${where.sql})`, [field, ...where.bind]);
|
|
45
|
-
}
|
|
46
|
-
function exists(part) {
|
|
47
|
-
return { sql: `EXISTS (${part.sql})`, bind: part.bind };
|
|
48
|
-
}
|
|
49
|
-
function matching(held, doc, field, values) {
|
|
50
|
-
return any(values.map((value) => any([
|
|
51
|
-
same(held, value),
|
|
52
|
-
all([
|
|
53
|
-
fragment(`${held}.kind = 'array'`),
|
|
54
|
-
exists(heldValues(doc, field, 'i', all([fragment(`i.held = ${held}.held AND i.item >= 0`), same('i', value)]))),
|
|
55
|
-
]),
|
|
56
|
-
])));
|
|
57
|
-
}
|
|
58
|
-
function tested(doc, field, test) {
|
|
59
|
-
const reached = exists(heldValues(doc, field, 'r', fragment('r.item = -1')));
|
|
60
|
-
if (test.op === 'exists')
|
|
61
|
-
return test.exists ? reached : fragment(`NOT ${reached.sql}`, reached.bind);
|
|
62
|
-
if (test.op === 'eq' || test.op === 'in') {
|
|
63
|
-
const values = test.op === 'eq' ? [test.value] : test.values;
|
|
64
|
-
return exists(heldValues(doc, field, 'v', any(values.map((value) => same('v', value)))));
|
|
65
|
-
}
|
|
66
|
-
if (test.op === 'ne' || test.op === 'nin') {
|
|
67
|
-
const values = test.op === 'ne' ? [test.value] : test.values;
|
|
68
|
-
const unmatched = matching('h', doc, field, values);
|
|
69
|
-
return any([
|
|
70
|
-
fragment(`NOT ${reached.sql}`, reached.bind),
|
|
71
|
-
exists(heldValues(doc, field, 'h', all([fragment('h.item = -1'), fragment(`NOT (${unmatched.sql})`, unmatched.bind)]))),
|
|
72
|
-
]);
|
|
73
|
-
}
|
|
74
|
-
if (test.op === 'range') {
|
|
75
|
-
return exists(heldValues(doc, field, 'v', all([
|
|
76
|
-
fragment('v.item = -1'),
|
|
77
|
-
...test.bounds.map(([operator, bound]) => {
|
|
78
|
-
const held = sqlValue(bound);
|
|
79
|
-
return fragment(`v.kind = ? AND v.value ${BOUNDS[operator]} ?`, [
|
|
80
|
-
held.kind,
|
|
81
|
-
held.value,
|
|
82
|
-
]);
|
|
83
|
-
}),
|
|
84
|
-
])));
|
|
85
|
-
}
|
|
86
|
-
if (test.op === 'all') {
|
|
87
|
-
return exists(heldValues(doc, field, 'h', all([
|
|
88
|
-
fragment("h.item = -1 AND h.kind = 'array'"),
|
|
89
|
-
...test.values.map((value) => exists(heldValues(doc, field, 'i', all([fragment('i.held = h.held AND i.item >= 0'), same('i', value)])))),
|
|
90
|
-
])));
|
|
91
|
-
}
|
|
92
|
-
return exists(heldValues(doc, field, 'v', fragment("v.item = -1 AND v.kind = 'array' AND v.size = ?", [test.size])));
|
|
10
|
+
function within(alias, path) {
|
|
11
|
+
return fragment(`(${alias}.path = ? OR (${alias}.path >= ? AND ${alias}.path < ?))`, [
|
|
12
|
+
path,
|
|
13
|
+
`${path}/`,
|
|
14
|
+
`${path}0`,
|
|
15
|
+
]);
|
|
93
16
|
}
|
|
94
|
-
function
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
return
|
|
99
|
-
|
|
17
|
+
function ancestors(area) {
|
|
18
|
+
const depth = area.path.split('/').length;
|
|
19
|
+
return area.open.flatMap((open) => {
|
|
20
|
+
const segments = open.split('/');
|
|
21
|
+
return segments.slice(depth - 1, -1).map((_, at) => segments.slice(0, depth + at).join('/'));
|
|
22
|
+
});
|
|
100
23
|
}
|
|
101
|
-
function
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
24
|
+
function fenced(alias, key, area, folders) {
|
|
25
|
+
const opened = any([
|
|
26
|
+
...area.open.map((open) => within(alias, open)),
|
|
27
|
+
...(folders ? ancestors(area).map((path) => fragment(`${alias}.path = ?`, [path])) : []),
|
|
28
|
+
]);
|
|
29
|
+
return all([
|
|
30
|
+
fragment(`${alias}.key = ?`, [key]),
|
|
31
|
+
within(alias, area.path),
|
|
32
|
+
fragment(`NOT ${grouped(opened).sql}`, opened.bind),
|
|
33
|
+
]);
|
|
105
34
|
}
|
|
106
35
|
function reached(bound, alias) {
|
|
107
36
|
const reach = bound.reach;
|
|
@@ -115,44 +44,38 @@ function reached(bound, alias) {
|
|
|
115
44
|
const key = bound.keys.get(roomOfKey(held));
|
|
116
45
|
return key === undefined ? [] : [[key, pathOfKey(held)]];
|
|
117
46
|
});
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
: [
|
|
123
|
-
fragment(`EXISTS (SELECT 1 FROM json_each(?) j WHERE j.value ->> 0 = ${alias}.key AND j.value ->> 1 = ${alias}.path)`, [JSON.stringify(documents)]),
|
|
124
|
-
]),
|
|
125
|
-
]);
|
|
126
|
-
}
|
|
127
|
-
function scoped(alias, scope) {
|
|
47
|
+
const outside = any(reach.areas.flatMap((area) => {
|
|
48
|
+
const key = bound.keys.get(area.room);
|
|
49
|
+
return key === undefined ? [] : [fenced(alias, key, area, false)];
|
|
50
|
+
}));
|
|
128
51
|
return all([
|
|
129
|
-
|
|
130
|
-
? []
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
fragment(`${alias}.path >= ? AND ${alias}.path < ?`, [
|
|
136
|
-
`${scope.pathPrefix}/`,
|
|
137
|
-
`${scope.pathPrefix}0`,
|
|
52
|
+
any([
|
|
53
|
+
...(rooms.length === 0 ? [] : [fragment(`${alias}.key IN ${listed(rooms).sql}`, rooms)]),
|
|
54
|
+
...(documents.length === 0
|
|
55
|
+
? []
|
|
56
|
+
: [
|
|
57
|
+
fragment(`EXISTS (SELECT 1 FROM json_each(?) j WHERE j.value ->> 0 = ${alias}.key AND j.value ->> 1 = ${alias}.path)`, [JSON.stringify(documents)]),
|
|
138
58
|
]),
|
|
139
|
-
|
|
140
|
-
...(
|
|
59
|
+
]),
|
|
60
|
+
...(reach.areas.length === 0 ? [] : [fragment(`NOT ${grouped(outside).sql}`, outside.bind)]),
|
|
141
61
|
]);
|
|
142
62
|
}
|
|
143
63
|
function related(bound, plan) {
|
|
144
64
|
const parts = [];
|
|
145
65
|
if (plan.hop !== null) {
|
|
146
66
|
parts.push(exists(joined([
|
|
147
|
-
fragment(`SELECT 1 FROM replica_links l JOIN replica_entries m ON m.key = d.key AND m.path = l.target AND ${VISIBLE('m')} WHERE l.doc = d.id AND l.kind = 'field' AND
|
|
148
|
-
grouped(
|
|
67
|
+
fragment(`SELECT 1 FROM replica_links l JOIN replica_entries m ON m.key = d.key AND m.path = l.target AND ${VISIBLE('m')} WHERE l.doc = d.id AND l.kind = 'field' AND`),
|
|
68
|
+
grouped(sql.placed('l', plan.hop.field, 'link')),
|
|
69
|
+
fragment('AND'),
|
|
70
|
+
grouped(all([sql.scoped('m', plan.hop), reached(bound, 'm')])),
|
|
149
71
|
], ' ')));
|
|
150
72
|
}
|
|
151
73
|
if (plan.backlinks !== null) {
|
|
152
74
|
const field = plan.backlinks.field;
|
|
153
75
|
parts.push(exists(joined([
|
|
154
|
-
fragment(`SELECT 1 FROM replica_links l JOIN replica_entries s ON s.id = l.doc AND ${VISIBLE('s')} WHERE l.key = d.key AND l.target = d.path AND l.kind = 'field'
|
|
155
|
-
grouped(
|
|
76
|
+
fragment(`SELECT 1 FROM replica_links l JOIN replica_entries s ON s.id = l.doc AND ${VISIBLE('s')} WHERE l.key = d.key AND l.target = d.path AND l.kind = 'field' AND`),
|
|
77
|
+
...(field === null ? [] : [grouped(sql.placed('l', field, 'link')), fragment('AND')]),
|
|
78
|
+
grouped(all([sql.scoped('s', plan.backlinks), reached(bound, 's')])),
|
|
156
79
|
], ' ')));
|
|
157
80
|
}
|
|
158
81
|
return parts;
|
|
@@ -160,11 +83,9 @@ function related(bound, plan) {
|
|
|
160
83
|
function filtered(bound, plan) {
|
|
161
84
|
const keys = bound.rooms.map(({ key }) => key);
|
|
162
85
|
return all([
|
|
163
|
-
fragment(`d.key IN ${
|
|
164
|
-
...(plan.paths === null ? [] : [fragment(`d.path IN ${list(plan.paths).sql}`, plan.paths)]),
|
|
165
|
-
...(plan.folder === null ? [] : [fragment('d.folder = ?', [plan.folder])]),
|
|
86
|
+
fragment(`d.key IN ${listed(keys).sql} AND ${VISIBLE('d')}`, keys),
|
|
166
87
|
reached(bound, 'd'),
|
|
167
|
-
|
|
88
|
+
sql.tests('d', plan),
|
|
168
89
|
...related(bound, plan),
|
|
169
90
|
]);
|
|
170
91
|
}
|
|
@@ -195,99 +116,25 @@ const GROUP_TIES = {
|
|
|
195
116
|
locale: undefined,
|
|
196
117
|
localeOptions: undefined,
|
|
197
118
|
};
|
|
198
|
-
function
|
|
199
|
-
if (value === null || value === undefined) {
|
|
200
|
-
return { placement: ordering.nulls === 'first' ? 0 : 2, klass: 0, scalar: null };
|
|
201
|
-
}
|
|
202
|
-
if (typeof value === 'boolean')
|
|
203
|
-
return { placement: 1, klass: 1, scalar: value ? 1 : 0 };
|
|
204
|
-
if (typeof value === 'number')
|
|
205
|
-
return { placement: 1, klass: 1, scalar: value };
|
|
206
|
-
if (typeof value === 'string')
|
|
207
|
-
return { placement: 1, klass: 2, scalar: value };
|
|
208
|
-
return { placement: 1, klass: 3, scalar: JSON.stringify(value) };
|
|
209
|
-
}
|
|
210
|
-
function placement(term) {
|
|
211
|
-
const nulls = term.ordering.nulls === 'first' ? 0 : 2;
|
|
212
|
-
return fragment(`CASE WHEN ${term.kind.sql} IS NULL OR ${term.kind.sql} = 'null' THEN ${nulls} ELSE 1 END`, [...term.kind.bind, ...term.kind.bind]);
|
|
213
|
-
}
|
|
214
|
-
function klass(term) {
|
|
215
|
-
return fragment(`CASE ${term.kind.sql} WHEN 'boolean' THEN 1 WHEN 'number' THEN 1 WHEN 'string' THEN 2 WHEN 'array' THEN 3 ELSE 4 END`, term.kind.bind);
|
|
216
|
-
}
|
|
217
|
-
function classed(term, which) {
|
|
218
|
-
const kinds = which === 1 ? "('boolean', 'number')" : which === 2 ? "('string')" : "('array')";
|
|
219
|
-
return fragment(`(CASE WHEN ${term.kind.sql} IN ${kinds} THEN ${term.value.sql} END)`, [
|
|
220
|
-
...term.kind.bind,
|
|
221
|
-
...term.value.bind,
|
|
222
|
-
]);
|
|
223
|
-
}
|
|
224
|
-
function collated(bound, term, which) {
|
|
225
|
-
if (which === 1)
|
|
226
|
-
return '';
|
|
227
|
-
const name = bound.collate(term.ordering, which === 3, term.total === true);
|
|
228
|
-
return name === null ? '' : ` COLLATE ${name}`;
|
|
229
|
-
}
|
|
230
|
-
function sorted(bound, term) {
|
|
231
|
-
const direction = term.ordering.direction === 'desc' ? 'DESC' : 'ASC';
|
|
232
|
-
return joined([
|
|
233
|
-
placement(term),
|
|
234
|
-
fragment(`${klass(term).sql} ${direction}`, klass(term).bind),
|
|
235
|
-
...[1, 2, 3].map((which) => {
|
|
236
|
-
const value = classed(term, which);
|
|
237
|
-
return fragment(`${value.sql}${collated(bound, term, which)} ${direction}`, value.bind);
|
|
238
|
-
}),
|
|
239
|
-
], ', ');
|
|
240
|
-
}
|
|
241
|
-
function beyond(bound, term, value) {
|
|
242
|
-
const held = classOf(value, term.ordering);
|
|
243
|
-
const place = placement(term);
|
|
244
|
-
if (held.placement !== 1) {
|
|
245
|
-
return {
|
|
246
|
-
beyond: fragment(`${place.sql} > ${held.placement}`, place.bind),
|
|
247
|
-
equal: fragment(`${place.sql} = ${held.placement}`, place.bind),
|
|
248
|
-
};
|
|
249
|
-
}
|
|
250
|
-
const after = term.ordering.direction === 'desc' ? '<' : '>';
|
|
251
|
-
const kind = klass(term);
|
|
252
|
-
const scalar = classed(term, held.klass);
|
|
253
|
-
const collation = collated(bound, term, held.klass);
|
|
254
|
-
return {
|
|
255
|
-
beyond: any([
|
|
256
|
-
fragment(`${place.sql} > 1`, place.bind),
|
|
257
|
-
all([
|
|
258
|
-
fragment(`${place.sql} = 1`, place.bind),
|
|
259
|
-
any([
|
|
260
|
-
fragment(`${kind.sql} ${after} ${held.klass}`, kind.bind),
|
|
261
|
-
all([
|
|
262
|
-
fragment(`${kind.sql} = ${held.klass}`, kind.bind),
|
|
263
|
-
fragment(`${scalar.sql} ${after} ?${collation}`, [...scalar.bind, held.scalar]),
|
|
264
|
-
]),
|
|
265
|
-
]),
|
|
266
|
-
]),
|
|
267
|
-
]),
|
|
268
|
-
equal: all([
|
|
269
|
-
fragment(`${place.sql} = 1 AND ${kind.sql} = ${held.klass}`, [...place.bind, ...kind.bind]),
|
|
270
|
-
fragment(`${scalar.sql} = ?${collation}`, [...scalar.bind, held.scalar]),
|
|
271
|
-
]),
|
|
272
|
-
};
|
|
273
|
-
}
|
|
274
|
-
function following(parts, tie) {
|
|
275
|
-
let condition = tie;
|
|
276
|
-
for (const part of [...parts].reverse()) {
|
|
277
|
-
condition = any([part.beyond, all([part.equal, condition])]);
|
|
278
|
-
}
|
|
279
|
-
return condition;
|
|
280
|
-
}
|
|
281
|
-
function keyTerm(bound, key, ordering, index) {
|
|
119
|
+
function keyTerm(key, ordering, index) {
|
|
282
120
|
if (key.of === 'field') {
|
|
283
121
|
const alias = `o${index}`;
|
|
284
122
|
return {
|
|
285
|
-
term: {
|
|
286
|
-
|
|
123
|
+
term: {
|
|
124
|
+
ordering,
|
|
125
|
+
kind: fragment(`${alias}.kind`),
|
|
126
|
+
value: fragment(`${alias}.value`),
|
|
127
|
+
instant: fragment(`${alias}.instant`),
|
|
128
|
+
},
|
|
129
|
+
join: joined([
|
|
130
|
+
fragment(`LEFT JOIN replica_values ${alias} ON ${alias}.doc = d.id AND `),
|
|
131
|
+
grouped(sql.placed(alias, key.field, 'exact')),
|
|
132
|
+
fragment(` AND ${alias}.item = -1 AND ${alias}.kind NOT IN ('object', 'undefined')`),
|
|
133
|
+
], ''),
|
|
287
134
|
};
|
|
288
135
|
}
|
|
289
136
|
const expression = key.of === 'room'
|
|
290
|
-
? located(
|
|
137
|
+
? located('d')
|
|
291
138
|
: key.of === 'path'
|
|
292
139
|
? fragment('d.path')
|
|
293
140
|
: key.of === 'type'
|
|
@@ -313,13 +160,20 @@ function decoded(kind, value) {
|
|
|
313
160
|
return JSON.parse(value);
|
|
314
161
|
return null;
|
|
315
162
|
}
|
|
163
|
+
function sortedValue(row, index) {
|
|
164
|
+
const kind = row[`k${index}`];
|
|
165
|
+
return sql.sortValue(kind, decoded(kind, row[`v${index}`]), row[`i${index}`]);
|
|
166
|
+
}
|
|
316
167
|
function decodedKey(key, row, index) {
|
|
317
168
|
if (key.of === 'field') {
|
|
318
169
|
const kind = row[`k${index}`];
|
|
319
|
-
return kind === null || kind === undefined ? undefined :
|
|
170
|
+
return kind === null || kind === undefined ? undefined : sortedValue(row, index);
|
|
320
171
|
}
|
|
321
172
|
return row[`v${index}`] ?? null;
|
|
322
173
|
}
|
|
174
|
+
function instantOf(term) {
|
|
175
|
+
return term.instant ?? fragment('NULL');
|
|
176
|
+
}
|
|
323
177
|
const registered = new WeakMap();
|
|
324
178
|
function hashed(text) {
|
|
325
179
|
let hash = 0x811c9dc5;
|
|
@@ -369,9 +223,6 @@ function collating(connection) {
|
|
|
369
223
|
return name;
|
|
370
224
|
};
|
|
371
225
|
}
|
|
372
|
-
function bodied(shape) {
|
|
373
|
-
return shape.sections !== null || shape.preamble || shape.markdown;
|
|
374
|
-
}
|
|
375
226
|
function masked(pointers) {
|
|
376
227
|
const root = { whole: false, members: new Map() };
|
|
377
228
|
for (const pointer of pointers) {
|
|
@@ -439,9 +290,7 @@ function documentOf(shape, room, row, linked) {
|
|
|
439
290
|
: {
|
|
440
291
|
binaryFile: binaryRecord(path, binary, revision ?? undefined),
|
|
441
292
|
}),
|
|
442
|
-
...(shape.markdown && content !== null
|
|
443
|
-
? { markdown: content }
|
|
444
|
-
: {}),
|
|
293
|
+
...(shape.markdown && content !== null ? { markdown: content } : {}),
|
|
445
294
|
...(shape.fileId ? { fileId } : {}),
|
|
446
295
|
...(shape.revision ? { revision } : {}),
|
|
447
296
|
};
|
|
@@ -464,7 +313,7 @@ function documentOf(shape, room, row, linked) {
|
|
|
464
313
|
? {}
|
|
465
314
|
: { sections: sectionsOf(body.sections, shape.sections) }),
|
|
466
315
|
...(shape.preamble && body !== null ? { preamble: body.preamble } : {}),
|
|
467
|
-
...(shape.markdown
|
|
316
|
+
...(shape.markdown ? { markdown: row.content } : {}),
|
|
468
317
|
...(shape.backlinks ? { backlinks: linked.get(documentKey(room, path)) ?? [] } : {}),
|
|
469
318
|
...(shape.change
|
|
470
319
|
? {
|
|
@@ -498,10 +347,10 @@ function backlinksOf(connection, bound, rows) {
|
|
|
498
347
|
return linked;
|
|
499
348
|
}
|
|
500
349
|
function documents(connection, bound, plan, shape, budget) {
|
|
501
|
-
const terms = shape.orderBy.map(({ key, options }, index) => keyTerm(
|
|
350
|
+
const terms = shape.orderBy.map(({ key, options }, index) => keyTerm(key, orderingOf(options), index));
|
|
502
351
|
const filter = filtered(bound, plan);
|
|
503
352
|
const cursor = plan.after?.values ?? null;
|
|
504
|
-
const room = located(
|
|
353
|
+
const room = located('d');
|
|
505
354
|
const tie = cursor === null
|
|
506
355
|
? null
|
|
507
356
|
: (() => {
|
|
@@ -517,19 +366,20 @@ function documents(connection, bound, plan, shape, budget) {
|
|
|
517
366
|
})();
|
|
518
367
|
const after = cursor === null || tie === null
|
|
519
368
|
? null
|
|
520
|
-
: following(terms.map(({ term }, index) => beyond(bound, term, cursor[index])), tie);
|
|
369
|
+
: sql.following(terms.map(({ term }, index) => sql.beyond(bound.collate, term, cursor[index])), tie);
|
|
521
370
|
const selected = joined([
|
|
522
371
|
fragment('SELECT d.id, d.key, d.path, d.type, d.binary, d.revision, d.fields, d.change, d.file_id'),
|
|
523
372
|
...terms.map(({ term }, index) => joined([
|
|
524
373
|
fragment(`, ${term.kind.sql} AS k${index}`, term.kind.bind),
|
|
525
374
|
fragment(`, ${term.value.sql} AS v${index}`, term.value.bind),
|
|
375
|
+
fragment(`, ${instantOf(term).sql} AS i${index}`, instantOf(term).bind),
|
|
526
376
|
], '')),
|
|
527
377
|
fragment(' FROM replica_entries d'),
|
|
528
378
|
...terms.flatMap(({ join }) => (join === null ? [] : [fragment(' '), join])),
|
|
529
379
|
fragment(' WHERE '),
|
|
530
380
|
after === null ? filter : all([filter, after]),
|
|
531
381
|
fragment(' ORDER BY '),
|
|
532
|
-
joined([...terms.map(({ term }) => sorted(bound, term)), room, fragment('d.path')], ', '),
|
|
382
|
+
joined([...terms.map(({ term }) => sql.sorted(bound.collate, term)), room, fragment('d.path')], ', '),
|
|
533
383
|
...(plan.limit === null ? [] : [fragment(' LIMIT ?', [plan.limit + 1])]),
|
|
534
384
|
], '');
|
|
535
385
|
const rows = connection.rows(selected.sql, selected.bind);
|
|
@@ -568,7 +418,7 @@ function withContent(connection, rows, budget) {
|
|
|
568
418
|
return rows;
|
|
569
419
|
const ids = rows.map((row) => row.id);
|
|
570
420
|
const sizes = new Map(connection
|
|
571
|
-
.rows(`SELECT id, octet_length(content) AS size FROM replica_entries WHERE id IN ${
|
|
421
|
+
.rows(`SELECT id, octet_length(content) AS size FROM replica_entries WHERE id IN ${listed(ids).sql}`, ids)
|
|
572
422
|
.map((row) => [row.id, Number(row.size ?? 0)]));
|
|
573
423
|
let cut = rows.length;
|
|
574
424
|
let spent = 0;
|
|
@@ -583,20 +433,30 @@ function withContent(connection, rows, budget) {
|
|
|
583
433
|
const kept = rows.slice(0, cut);
|
|
584
434
|
const read = kept.map((row) => row.id);
|
|
585
435
|
const held = new Map(connection
|
|
586
|
-
.rows(`SELECT id, content FROM replica_entries WHERE id IN ${
|
|
436
|
+
.rows(`SELECT id, content FROM replica_entries WHERE id IN ${listed(read).sql}`, read)
|
|
587
437
|
.map((row) => [row.id, row.content]));
|
|
588
438
|
return kept.map((row) => ({ ...row, content: held.get(row.id) ?? null }));
|
|
589
439
|
}
|
|
590
440
|
function storedFolders(bound, plan) {
|
|
591
|
-
if (plan.paths !== null || plan.
|
|
441
|
+
if (plan.paths !== null || plan.fileIds !== null)
|
|
442
|
+
return null;
|
|
443
|
+
if (plan.hop !== null || plan.backlinks !== null)
|
|
592
444
|
return null;
|
|
593
445
|
const whole = bound.rooms.filter(({ locator }) => bound.reach === null || bound.reach.rooms.includes(locator));
|
|
594
446
|
if (whole.length === 0)
|
|
595
447
|
return null;
|
|
596
448
|
const keys = whole.map(({ key }) => key);
|
|
597
449
|
const prefix = plan.root.pathPrefix;
|
|
450
|
+
const outside = (bound.reach?.areas ?? []).flatMap((area) => {
|
|
451
|
+
const key = bound.keys.get(area.room);
|
|
452
|
+
if (key === undefined)
|
|
453
|
+
return [];
|
|
454
|
+
const fence = fenced('f', key, area, true);
|
|
455
|
+
return [fragment(`NOT ${grouped(fence).sql}`, fence.bind)];
|
|
456
|
+
});
|
|
598
457
|
return all([
|
|
599
|
-
fragment(`f.key IN ${
|
|
458
|
+
fragment(`f.key IN ${listed(keys).sql} AND f.layer = 0 AND f.present = 1`, keys),
|
|
459
|
+
...outside,
|
|
600
460
|
...(prefix === null || prefix === ''
|
|
601
461
|
? []
|
|
602
462
|
: [
|
|
@@ -611,7 +471,7 @@ function storedFolders(bound, plan) {
|
|
|
611
471
|
}
|
|
612
472
|
function groups(connection, bound, plan, shape) {
|
|
613
473
|
const keyed = shape.groupBy.map((key, index) => {
|
|
614
|
-
const { term, join } = keyTerm(
|
|
474
|
+
const { term, join } = keyTerm(key, GROUP_ORDER, index);
|
|
615
475
|
const kind = fragment(`COALESCE(${term.kind.sql}, 'null')`, term.kind.bind);
|
|
616
476
|
return { term: { ...term, kind }, join };
|
|
617
477
|
});
|
|
@@ -621,6 +481,7 @@ function groups(connection, bound, plan, shape) {
|
|
|
621
481
|
joined(keyed.map(({ term }, index) => joined([
|
|
622
482
|
fragment(`${term.kind.sql} AS k${index}`, term.kind.bind),
|
|
623
483
|
fragment(`, ${term.value.sql} AS v${index}`, term.value.bind),
|
|
484
|
+
fragment(`, ${instantOf(term).sql} AS i${index}`, instantOf(term).bind),
|
|
624
485
|
], '')), ', '),
|
|
625
486
|
fragment(', 1 AS n FROM replica_entries d'),
|
|
626
487
|
...keyed.flatMap(({ join }) => (join === null ? [] : [fragment(' '), join])),
|
|
@@ -634,10 +495,15 @@ function groups(connection, bound, plan, shape) {
|
|
|
634
495
|
? inner
|
|
635
496
|
: joined([
|
|
636
497
|
inner,
|
|
637
|
-
fragment(" UNION ALL SELECT 'string' AS k0, f.path AS v0, 0 AS n FROM replica_folders f WHERE "),
|
|
498
|
+
fragment(" UNION ALL SELECT 'string' AS k0, f.path AS v0, NULL AS i0, 0 AS n FROM replica_folders f WHERE "),
|
|
638
499
|
folders,
|
|
639
500
|
], '');
|
|
640
|
-
const columns = keyed
|
|
501
|
+
const columns = keyed
|
|
502
|
+
.map((_, index) => `k${index}, min(v${index}) AS v${index}, i${index}`)
|
|
503
|
+
.join(', ');
|
|
504
|
+
const held = keyed
|
|
505
|
+
.map((_, index) => `k${index}, i${index}, CASE WHEN i${index} IS NULL THEN v${index} END`)
|
|
506
|
+
.join(', ');
|
|
641
507
|
const counted = {
|
|
642
508
|
ordering: { ...GROUP_ORDER },
|
|
643
509
|
kind: fragment("'number'"),
|
|
@@ -650,7 +516,7 @@ function groups(connection, bound, plan, shape) {
|
|
|
650
516
|
});
|
|
651
517
|
const ordered = shape.orderBy.map(({ by, direction }) => by === 'count'
|
|
652
518
|
? { ...counted, ordering: { ...GROUP_ORDER, direction } }
|
|
653
|
-
: outer(by, { ...GROUP_ORDER, direction }));
|
|
519
|
+
: { ...outer(by, { ...GROUP_ORDER, direction }), instant: fragment(`i${by}`) });
|
|
654
520
|
const ties = keyed.flatMap((_, index) => [
|
|
655
521
|
{ ...outer(index, GROUP_TIES), total: true },
|
|
656
522
|
{ ordering: GROUP_TIES, kind: fragment("'string'"), value: fragment(`k${index}`) },
|
|
@@ -660,19 +526,21 @@ function groups(connection, bound, plan, shape) {
|
|
|
660
526
|
? null
|
|
661
527
|
: cursor[shape.orderBy.length].flatMap((value) => [
|
|
662
528
|
value,
|
|
663
|
-
|
|
529
|
+
heldKind(value ?? null),
|
|
664
530
|
]);
|
|
665
531
|
const after = cursor === null || tieValues === null
|
|
666
532
|
? null
|
|
667
|
-
: following(ordered.map((term, index) => beyond(bound, term, cursor[index])), following(ties
|
|
668
|
-
|
|
533
|
+
: sql.following(ordered.map((term, index) => sql.beyond(bound.collate, term, cursor[index])), sql.following(ties
|
|
534
|
+
.slice(0, -1)
|
|
535
|
+
.map((term, index) => sql.beyond(bound.collate, term, tieValues[index])), sql.beyond(bound.collate, ties.at(-1), tieValues.at(-1)).beyond));
|
|
536
|
+
const grouping = joined([fragment(`SELECT ${columns}, sum(n) AS n FROM (`), source, fragment(`) GROUP BY ${held}`)], '');
|
|
669
537
|
const windowed = joined([
|
|
670
538
|
fragment('SELECT * FROM ('),
|
|
671
539
|
grouping,
|
|
672
540
|
fragment(')'),
|
|
673
541
|
...(after === null ? [] : [fragment(' WHERE '), after]),
|
|
674
542
|
fragment(' ORDER BY '),
|
|
675
|
-
joined([...ordered, ...ties].map((term) => sorted(bound, term)), ', '),
|
|
543
|
+
joined([...ordered, ...ties].map((term) => sql.sorted(bound.collate, term)), ', '),
|
|
676
544
|
...(plan.limit === null ? [] : [fragment(' LIMIT ?', [plan.limit + 1])]),
|
|
677
545
|
], '');
|
|
678
546
|
const rows = connection.rows(windowed.sql, windowed.bind);
|
|
@@ -685,7 +553,7 @@ function groups(connection, bound, plan, shape) {
|
|
|
685
553
|
: last === undefined
|
|
686
554
|
? (plan.after?.text ?? FROM_START)
|
|
687
555
|
: cursorOf([
|
|
688
|
-
...shape.orderBy.map(({ by }) => by === 'count' ? Number(last.n) :
|
|
556
|
+
...shape.orderBy.map(({ by }) => by === 'count' ? Number(last.n) : sortedValue(last, by)),
|
|
689
557
|
keyOf(last),
|
|
690
558
|
]);
|
|
691
559
|
const total = plan.total
|
|
@@ -705,9 +573,6 @@ function boundOf(connection, plan, rooms) {
|
|
|
705
573
|
collate: collating(connection),
|
|
706
574
|
};
|
|
707
575
|
}
|
|
708
|
-
export function selected(connection, plan, rooms) {
|
|
709
|
-
return filtered(boundOf(connection, plan, rooms), plan);
|
|
710
|
-
}
|
|
711
576
|
export function answerQuery(connection, plan, rooms, budget = null) {
|
|
712
577
|
const bound = boundOf(connection, plan, rooms);
|
|
713
578
|
if (rooms.length === 0) {
|
package/dist/connection.d.ts
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
|
+
import { type DocumentQuery, type GroupQuery } from '@agentshouse/mdmodel';
|
|
1
2
|
import { type TypesResult } from './model.js';
|
|
2
3
|
import { type Observation } from './observation.js';
|
|
3
|
-
import { type
|
|
4
|
+
import { type DocumentResult, type GroupResult, type PendingResult } from './query.js';
|
|
4
5
|
import { type EntrySeed } from './seed.js';
|
|
5
6
|
import { type SearchRequest, type SearchResult } from './search.js';
|
|
6
7
|
import { type Adapter, type Authorization, type Member, type ProviderRefusal, type ServiceMode } from './adapter.js';
|
|
7
8
|
import { type ChatDraftSurface, type ConversationAgent, type ConversationEntry, type ConversationOptions, type ConversationSurface, type ConversationView } from './conversation.js';
|
|
8
9
|
import { type WrittenBy } from './change.js';
|
|
9
10
|
import type { Open } from './open.js';
|
|
10
|
-
import { type BinaryLinkAnswer, type CallResult, type HeldBinaryAnswer, type HistoryAnswer, type QueueEntry, type Resolution } from './outcome.js';
|
|
11
|
+
import { type AttachAnswer, type BinaryLinkAnswer, type CallResult, type HeldBinaryAnswer, type HeldShownAnswer, type HistoryAnswer, type QueueEntry, type Resolution } from './outcome.js';
|
|
11
12
|
import { type Recovery } from './recovery.js';
|
|
12
13
|
import { type SaveRefusal } from './save.js';
|
|
13
14
|
import { type RoomDraft, type RoomDraftParts, type RoomDraftWrite } from './room-draft.js';
|
|
14
15
|
import { type SyncStatus } from './status.js';
|
|
15
|
-
import { type RuntimeShell } from './durability.js';
|
|
16
|
-
import { type CodeAvailability, type Persistence, type Readiness
|
|
16
|
+
import { type RuntimeShell, type UnsentWork } from './durability.js';
|
|
17
|
+
import { type CodeAvailability, type Persistence, type Readiness } from './readiness.js';
|
|
17
18
|
import type { RuntimeDatabase } from './tables.js';
|
|
18
19
|
import { type NarrowedView, type PortReach, type RuntimeView } from './reach.js';
|
|
19
20
|
export type AppTypedSelection = {
|
|
@@ -54,6 +55,7 @@ export type MdRuntimeOptions = {
|
|
|
54
55
|
authorization?: Authorization;
|
|
55
56
|
signal?: AbortSignal;
|
|
56
57
|
recovery?: Recovery;
|
|
58
|
+
usableWhenHeld?: readonly string[];
|
|
57
59
|
};
|
|
58
60
|
export type SaveResult = {
|
|
59
61
|
outcome: 'saved';
|
|
@@ -83,6 +85,8 @@ export type PresentationSurface = {
|
|
|
83
85
|
export type BinaryFileSurface = {
|
|
84
86
|
read(room: string, path: string, revision?: string): Promise<HeldBinaryAnswer>;
|
|
85
87
|
link(room: string, path: string, revision?: string): Promise<BinaryLinkAnswer>;
|
|
88
|
+
show(room: string, path: string, revision?: string): Promise<HeldShownAnswer>;
|
|
89
|
+
attach(room: string, file: File): Promise<AttachAnswer>;
|
|
86
90
|
part(file: string, part: number): Promise<Uint8Array | null>;
|
|
87
91
|
};
|
|
88
92
|
export type HistoryQuery = {
|
|
@@ -91,13 +95,13 @@ export type HistoryQuery = {
|
|
|
91
95
|
};
|
|
92
96
|
export type MdRuntime = {
|
|
93
97
|
loaded(): Promise<void>;
|
|
94
|
-
rooms(): readonly AppRoom[]
|
|
98
|
+
rooms(): Promise<readonly AppRoom[]>;
|
|
95
99
|
query: {
|
|
96
100
|
(query: DocumentQuery): Promise<DocumentResult | PendingResult>;
|
|
97
101
|
(query: GroupQuery): Promise<GroupResult | PendingResult>;
|
|
98
102
|
};
|
|
99
103
|
search(request: SearchRequest): Promise<SearchResult>;
|
|
100
|
-
types(locator: string): RoomSchemas
|
|
104
|
+
types(locator: string): Promise<RoomSchemas>;
|
|
101
105
|
roomDraft: RoomDraftSurface;
|
|
102
106
|
conversation: ConversationSurface;
|
|
103
107
|
chatDraft: ChatDraftSurface;
|
|
@@ -113,6 +117,8 @@ export type MdRuntime = {
|
|
|
113
117
|
persistence(): boolean;
|
|
114
118
|
retry(): Promise<void>;
|
|
115
119
|
cleanUp(): Promise<number>;
|
|
120
|
+
unsent(): Promise<readonly UnsentWork[]>;
|
|
121
|
+
reset(): Promise<void>;
|
|
116
122
|
observe: {
|
|
117
123
|
(topic: 'rooms'): Promise<Observation<readonly AppRoom[]>>;
|
|
118
124
|
(topic: 'readiness'): Promise<Observation<Readiness>>;
|
|
@@ -121,6 +127,7 @@ export type MdRuntime = {
|
|
|
121
127
|
(topic: 'sync-status'): Promise<Observation<SyncStatus>>;
|
|
122
128
|
(topic: 'service-mode'): Promise<Observation<ServiceMode>>;
|
|
123
129
|
(topic: 'member'): Promise<Observation<Member | null>>;
|
|
130
|
+
(topic: 'authority-changes'): Promise<Observation<number>>;
|
|
124
131
|
(topic: 'query', query: DocumentQuery): Promise<Observation<DocumentResult | PendingResult>>;
|
|
125
132
|
(topic: 'query', query: GroupQuery): Promise<Observation<GroupResult | PendingResult>>;
|
|
126
133
|
(topic: 'queue', locator: string): Promise<Observation<readonly QueueEntry[]>>;
|
|
@@ -132,19 +139,15 @@ export type MdRuntime = {
|
|
|
132
139
|
};
|
|
133
140
|
reauthorize(): Promise<void>;
|
|
134
141
|
};
|
|
135
|
-
export type RuntimeTopic = 'rooms' | 'readiness' | 'connection-refusal' | 'storage-loss' | 'sync-status' | 'service-mode' | 'member' | 'query' | 'queue' | 'room-drafts' | 'presentation' | 'conversation' | 'conversations' | 'agents';
|
|
142
|
+
export type RuntimeTopic = 'rooms' | 'readiness' | 'connection-refusal' | 'storage-loss' | 'sync-status' | 'service-mode' | 'member' | 'authority-changes' | 'query' | 'queue' | 'room-drafts' | 'presentation' | 'conversation' | 'conversations' | 'agents';
|
|
136
143
|
export type ReadinessPort = {
|
|
137
144
|
readonly target: string;
|
|
138
145
|
readonly code: CodeAvailability;
|
|
139
|
-
readonly space: Space | null;
|
|
140
|
-
readonly search: SearchObligation;
|
|
141
146
|
};
|
|
142
147
|
export type ComposedRuntime = RuntimeView & {
|
|
143
148
|
seed(entry: EntrySeed): void;
|
|
144
149
|
stop(): Promise<void>;
|
|
145
|
-
lose(locators: readonly string[]): Promise<void>;
|
|
146
150
|
persisted(answer: Persistence): void;
|
|
147
|
-
shown(onScreen: boolean): void;
|
|
148
151
|
within(reach: PortReach | null, port: ReadinessPort): NarrowedView;
|
|
149
152
|
};
|
|
150
153
|
export declare function composeRuntime(options: MdRuntimeOptions): ComposedRuntime;
|