@agentshouse/mdruntime 0.1.0-c94cfdbdb6f68 → 0.1.0-c95dc33df5c05
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 +19 -16
- package/dist/acceptance.d.ts +6 -0
- package/dist/acceptance.d.ts.map +1 -0
- package/dist/acceptance.js +389 -0
- package/dist/actions.d.ts +20 -0
- package/dist/actions.d.ts.map +1 -0
- package/dist/actions.js +250 -0
- package/dist/adapter.d.ts +140 -85
- package/dist/adapter.d.ts.map +1 -1
- package/dist/attached-model.d.ts +7 -10
- package/dist/attached-model.d.ts.map +1 -1
- package/dist/attached-model.js +40 -41
- package/dist/binary.d.ts +0 -5
- package/dist/binary.d.ts.map +1 -1
- package/dist/binary.js +1 -1
- package/dist/bootstrap.d.ts +30 -11
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +319 -111
- package/dist/cell.d.ts +6 -0
- package/dist/cell.d.ts.map +1 -0
- package/dist/cell.js +9 -0
- package/dist/chain.d.ts +12 -0
- package/dist/chain.d.ts.map +1 -0
- package/dist/chain.js +64 -0
- package/dist/change-set.d.ts +9 -16
- package/dist/change-set.d.ts.map +1 -1
- package/dist/change-set.js +11 -89
- package/dist/change.d.ts +32 -1
- package/dist/change.d.ts.map +1 -1
- package/dist/change.js +10 -1
- package/dist/chat-types.d.ts +5 -0
- package/dist/chat-types.d.ts.map +1 -0
- package/dist/chat-types.js +13 -0
- package/dist/client.d.ts +30 -11
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +83 -7
- package/dist/collection.d.ts +11 -21
- package/dist/collection.d.ts.map +1 -1
- package/dist/collection.js +39 -321
- package/dist/compile.d.ts +16 -0
- package/dist/compile.d.ts.map +1 -0
- package/dist/compile.js +717 -0
- package/dist/connection.d.ts +7 -137
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +98 -3600
- package/dist/context.d.ts +2 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/{chat/context.js → context.js} +1 -4
- package/dist/conversation-row.d.ts +33 -0
- package/dist/conversation-row.d.ts.map +1 -0
- package/dist/conversation-row.js +53 -0
- package/dist/conversation.d.ts +37 -18
- package/dist/conversation.d.ts.map +1 -1
- package/dist/conversation.js +573 -287
- package/dist/digest.d.ts +7 -0
- package/dist/digest.d.ts.map +1 -0
- package/dist/digest.js +113 -0
- package/dist/discovery.d.ts +10 -0
- package/dist/discovery.d.ts.map +1 -0
- package/dist/discovery.js +175 -0
- package/dist/durability.d.ts +16 -4
- package/dist/durability.d.ts.map +1 -1
- package/dist/durability.js +5 -0
- package/dist/entry.d.ts +5 -2
- package/dist/entry.d.ts.map +1 -1
- package/dist/entry.js +33 -29
- package/dist/figures.d.ts +48 -0
- package/dist/figures.d.ts.map +1 -0
- package/dist/figures.js +197 -0
- package/dist/file.d.ts +2 -19
- package/dist/file.d.ts.map +1 -1
- package/dist/file.js +7 -122
- package/dist/holdings.d.ts +29 -0
- package/dist/holdings.d.ts.map +1 -0
- package/dist/holdings.js +95 -0
- package/dist/host.d.ts +4 -7
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +67 -39
- package/dist/identity.d.ts +0 -2
- package/dist/identity.d.ts.map +1 -1
- package/dist/identity.js +0 -6
- package/dist/index.d.ts +31 -13
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -2
- package/dist/install.d.ts +56 -0
- package/dist/install.d.ts.map +1 -0
- package/dist/install.js +560 -0
- package/dist/job.d.ts +33 -0
- package/dist/job.d.ts.map +1 -0
- package/dist/job.js +54 -0
- package/dist/lifecycle.d.ts +7 -0
- package/dist/lifecycle.d.ts.map +1 -0
- package/dist/lifecycle.js +267 -0
- package/dist/listing.d.ts +53 -0
- package/dist/listing.d.ts.map +1 -0
- package/dist/listing.js +175 -0
- package/dist/live.d.ts +23 -0
- package/dist/live.d.ts.map +1 -0
- package/dist/live.js +165 -0
- package/dist/locks.d.ts +9 -0
- package/dist/locks.d.ts.map +1 -0
- package/dist/locks.js +61 -0
- package/dist/log.d.ts +1 -0
- package/dist/log.d.ts.map +1 -1
- package/dist/lost.d.ts +5 -0
- package/dist/lost.d.ts.map +1 -0
- package/dist/lost.js +61 -0
- 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 +14 -6
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +237 -105
- package/dist/messages.d.ts +52 -0
- package/dist/messages.d.ts.map +1 -0
- package/dist/messages.js +168 -0
- package/dist/model.d.ts +8 -10
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +6 -18
- package/dist/models.d.ts +14 -0
- package/dist/models.d.ts.map +1 -0
- package/dist/models.js +193 -0
- package/dist/name.d.ts +4 -0
- package/dist/name.d.ts.map +1 -0
- package/dist/name.js +122 -0
- package/dist/observation.d.ts +15 -2
- package/dist/observation.d.ts.map +1 -1
- package/dist/observation.js +91 -2
- package/dist/opened.d.ts +22 -0
- package/dist/opened.d.ts.map +1 -0
- package/dist/opened.js +107 -0
- package/dist/opening.d.ts +4 -0
- package/dist/opening.d.ts.map +1 -0
- package/dist/opening.js +56 -0
- package/dist/outcome.d.ts +44 -9
- package/dist/outcome.d.ts.map +1 -1
- package/dist/outcome.js +41 -2
- package/dist/overlay.d.ts +3 -5
- package/dist/overlay.d.ts.map +1 -1
- package/dist/overlay.js +98 -172
- package/dist/{chat/parts.d.ts → parts.d.ts} +11 -9
- package/dist/parts.d.ts.map +1 -0
- package/dist/{chat/parts.js → parts.js} +45 -46
- package/dist/paths.d.ts +1 -0
- package/dist/paths.d.ts.map +1 -1
- package/dist/paths.js +4 -0
- package/dist/preparation.d.ts +20 -0
- package/dist/preparation.d.ts.map +1 -0
- package/dist/preparation.js +226 -0
- package/dist/queries.d.ts +16 -0
- package/dist/queries.d.ts.map +1 -0
- package/dist/queries.js +272 -0
- package/dist/query.d.ts +21 -206
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +3 -493
- package/dist/{chat/questions.d.ts → questions.d.ts} +5 -2
- package/dist/questions.d.ts.map +1 -0
- package/dist/{chat/questions.js → questions.js} +12 -1
- package/dist/reach.d.ts +20 -9
- package/dist/reach.d.ts.map +1 -1
- package/dist/reach.js +278 -103
- package/dist/react.d.ts +10 -2
- package/dist/react.d.ts.map +1 -1
- package/dist/{chat/read.d.ts → read.d.ts} +2 -0
- package/dist/read.d.ts.map +1 -0
- package/dist/{chat/read.js → read.js} +4 -0
- package/dist/readiness.d.ts +14 -17
- package/dist/readiness.d.ts.map +1 -1
- package/dist/readiness.js +2 -8
- package/dist/reads.d.ts +35 -10
- package/dist/reads.d.ts.map +1 -1
- package/dist/reads.js +136 -84
- package/dist/recovery.d.ts +3 -2
- package/dist/recovery.d.ts.map +1 -1
- package/dist/recovery.js +43 -8
- package/dist/refresh.d.ts +18 -15
- package/dist/refresh.d.ts.map +1 -1
- package/dist/refresh.js +143 -58
- package/dist/refusal.d.ts +5 -0
- package/dist/refusal.d.ts.map +1 -0
- package/dist/refusal.js +56 -0
- package/dist/replica.d.ts +54 -36
- package/dist/replica.d.ts.map +1 -1
- package/dist/replica.js +313 -188
- package/dist/room-draft.d.ts +25 -6
- package/dist/room-draft.d.ts.map +1 -1
- package/dist/room-draft.js +158 -71
- package/dist/room-drafts.d.ts +24 -0
- package/dist/room-drafts.d.ts.map +1 -0
- package/dist/room-drafts.js +216 -0
- package/dist/rows.d.ts +31 -31
- package/dist/rows.d.ts.map +1 -1
- package/dist/rows.js +59 -123
- package/dist/runtime.d.ts +42 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +1 -0
- package/dist/save.d.ts +52 -14
- package/dist/save.d.ts.map +1 -1
- package/dist/save.js +518 -185
- package/dist/saves.d.ts +70 -0
- package/dist/saves.d.ts.map +1 -0
- package/dist/saves.js +1004 -0
- package/dist/search.d.ts +12 -95
- package/dist/search.d.ts.map +1 -1
- package/dist/search.js +10 -266
- package/dist/seed.d.ts +11 -2
- package/dist/seed.d.ts.map +1 -1
- package/dist/seed.js +71 -0
- package/dist/shared.d.ts +7 -3
- package/dist/shared.d.ts.map +1 -1
- package/dist/shared.js +119 -66
- package/dist/shown.d.ts +31 -0
- package/dist/shown.d.ts.map +1 -0
- package/dist/shown.js +294 -0
- package/dist/socket/admission.d.ts +7 -0
- package/dist/socket/admission.d.ts.map +1 -0
- package/dist/socket/admission.js +39 -0
- package/dist/socket/answers.d.ts +6 -0
- package/dist/socket/answers.d.ts.map +1 -0
- package/dist/socket/answers.js +20 -0
- package/dist/socket/lanes.d.ts +20 -0
- package/dist/socket/lanes.d.ts.map +1 -0
- package/dist/socket/lanes.js +77 -0
- package/dist/socket/reads.d.ts +10 -0
- package/dist/socket/reads.d.ts.map +1 -0
- package/dist/socket/reads.js +31 -0
- package/dist/socket/rooms.d.ts +43 -0
- package/dist/socket/rooms.d.ts.map +1 -0
- package/dist/socket/rooms.js +90 -0
- package/dist/socket/session.d.ts +39 -0
- package/dist/socket/session.d.ts.map +1 -0
- package/dist/socket/session.js +23 -0
- package/dist/socket.d.ts +70 -0
- package/dist/socket.d.ts.map +1 -0
- package/dist/socket.js +175 -0
- package/dist/source.d.ts +61 -0
- package/dist/source.d.ts.map +1 -0
- package/dist/source.js +81 -0
- package/dist/status.d.ts +4 -5
- package/dist/status.d.ts.map +1 -1
- package/dist/status.js +3 -7
- package/dist/store/fences.d.ts +16 -0
- package/dist/store/fences.d.ts.map +1 -0
- package/dist/store/fences.js +26 -0
- package/dist/store/installs.d.ts +30 -0
- package/dist/store/installs.d.ts.map +1 -0
- package/dist/store/installs.js +34 -0
- package/dist/store/readiness.d.ts +10 -0
- package/dist/store/readiness.d.ts.map +1 -0
- package/dist/store/readiness.js +52 -0
- package/dist/store/records.d.ts +212 -0
- package/dist/store/records.d.ts.map +1 -0
- package/dist/store/records.js +408 -0
- package/dist/store/room-held.d.ts +8 -0
- package/dist/store/room-held.d.ts.map +1 -0
- package/dist/store/room-held.js +17 -0
- package/dist/store/space.d.ts +11 -0
- package/dist/store/space.d.ts.map +1 -0
- package/dist/store/space.js +43 -0
- package/dist/store/watchers.d.ts +17 -0
- package/dist/store/watchers.d.ts.map +1 -0
- package/dist/store/watchers.js +57 -0
- package/dist/store/writes.d.ts +24 -0
- package/dist/store/writes.d.ts.map +1 -0
- package/dist/store/writes.js +125 -0
- package/dist/store.d.ts +106 -164
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +136 -752
- package/dist/stored.d.ts +156 -0
- package/dist/stored.d.ts.map +1 -0
- package/dist/stored.js +637 -0
- package/dist/surface.d.ts +88 -0
- package/dist/surface.d.ts.map +1 -0
- package/dist/surface.js +222 -0
- package/dist/sync.d.ts +20 -0
- package/dist/sync.d.ts.map +1 -0
- package/dist/sync.js +531 -0
- package/dist/tables.d.ts +415 -0
- package/dist/tables.d.ts.map +1 -0
- package/dist/tables.js +740 -0
- package/dist/tallies.d.ts +18 -0
- package/dist/tallies.d.ts.map +1 -0
- package/dist/tallies.js +129 -0
- package/dist/transfer.d.ts +0 -5
- package/dist/transfer.d.ts.map +1 -1
- package/dist/turn.d.ts +4 -2
- package/dist/turn.d.ts.map +1 -1
- package/dist/turn.js +46 -22
- package/dist/validation.d.ts +29 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +104 -0
- package/dist/windows.d.ts +1 -16
- package/dist/windows.d.ts.map +1 -1
- package/dist/windows.js +2 -79
- package/dist/wire.d.ts +34 -6
- package/dist/wire.d.ts.map +1 -1
- package/dist/wire.js +12 -2
- package/package.json +18 -19
- package/AGENTS.md +0 -299
- package/dist/chat/acts.d.ts +0 -33
- package/dist/chat/acts.d.ts.map +0 -1
- package/dist/chat/acts.js +0 -36
- package/dist/chat/context.d.ts +0 -3
- package/dist/chat/context.d.ts.map +0 -1
- package/dist/chat/earlier.d.ts +0 -10
- package/dist/chat/earlier.d.ts.map +0 -1
- package/dist/chat/earlier.js +0 -54
- package/dist/chat/input.d.ts +0 -9
- package/dist/chat/input.d.ts.map +0 -1
- package/dist/chat/input.js +0 -99
- package/dist/chat/kit.d.ts +0 -61
- package/dist/chat/kit.d.ts.map +0 -1
- package/dist/chat/kit.js +0 -123
- package/dist/chat/lasting.d.ts +0 -6
- package/dist/chat/lasting.d.ts.map +0 -1
- package/dist/chat/lasting.js +0 -19
- package/dist/chat/list.d.ts +0 -27
- package/dist/chat/list.d.ts.map +0 -1
- package/dist/chat/list.js +0 -99
- package/dist/chat/markdown.d.ts +0 -20
- package/dist/chat/markdown.d.ts.map +0 -1
- package/dist/chat/markdown.js +0 -188
- package/dist/chat/message.d.ts +0 -6
- package/dist/chat/message.d.ts.map +0 -1
- package/dist/chat/message.js +0 -192
- package/dist/chat/messages.d.ts +0 -22
- package/dist/chat/messages.d.ts.map +0 -1
- package/dist/chat/messages.js +0 -155
- package/dist/chat/name.d.ts +0 -6
- package/dist/chat/name.d.ts.map +0 -1
- package/dist/chat/name.js +0 -37
- package/dist/chat/opened.d.ts +0 -11
- package/dist/chat/opened.d.ts.map +0 -1
- package/dist/chat/opened.js +0 -17
- package/dist/chat/overlay.d.ts +0 -31
- package/dist/chat/overlay.d.ts.map +0 -1
- package/dist/chat/overlay.js +0 -97
- package/dist/chat/parts.d.ts.map +0 -1
- package/dist/chat/process.d.ts +0 -20
- package/dist/chat/process.d.ts.map +0 -1
- package/dist/chat/process.js +0 -32
- package/dist/chat/provider.d.ts +0 -63
- package/dist/chat/provider.d.ts.map +0 -1
- package/dist/chat/provider.js +0 -628
- package/dist/chat/question.d.ts +0 -9
- package/dist/chat/question.d.ts.map +0 -1
- package/dist/chat/question.js +0 -69
- package/dist/chat/questions.d.ts.map +0 -1
- package/dist/chat/read.d.ts.map +0 -1
- package/dist/chat/ready.d.ts +0 -34
- package/dist/chat/ready.d.ts.map +0 -1
- package/dist/chat/ready.js +0 -91
- package/dist/chat/style.d.ts +0 -4
- package/dist/chat/style.d.ts.map +0 -1
- package/dist/chat/style.js +0 -302
- package/dist/chat.d.ts +0 -14
- package/dist/chat.d.ts.map +0 -1
- package/dist/chat.js +0 -8
- package/dist/fence.d.ts +0 -6
- package/dist/fence.d.ts.map +0 -1
- package/dist/fence.js +0 -10
- package/dist/read-side.d.ts +0 -27
- package/dist/read-side.d.ts.map +0 -1
- package/dist/read-side.js +0 -824
package/dist/save.js
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { definitionOf } from './model.js';
|
|
2
|
-
import { apply, ATTACHMENT, links, parse, pointerSegments, references, relative, relativize, retarget, serialize, target, } from '@agentshouse/mdmodel';
|
|
3
|
-
import { immutable, queuedFile, departure, } from './change.js';
|
|
4
|
-
import {
|
|
2
|
+
import { apply, ARRAY_INDEX, ATTACHMENT, links, parse, pointerSegments, references, relative, relativize, retarget, roomReferences, serialize, target, } from '@agentshouse/mdmodel';
|
|
3
|
+
import { immutable, leaving, queuedFile, departure, } from './change.js';
|
|
4
|
+
import { collectionOf, documentsOf, governing, } from './collection.js';
|
|
5
5
|
import { changeBatchIdentity } from './identity.js';
|
|
6
|
-
import {
|
|
7
|
-
import { covered, normalize } from './paths.js';
|
|
8
|
-
import {
|
|
6
|
+
import { overlaying } from './overlay.js';
|
|
7
|
+
import { ancestors, covered, normalize } from './paths.js';
|
|
8
|
+
import { sorting } from './shared.js';
|
|
9
|
+
import { paced, ROW_WEIGHT, stepped } from './turn.js';
|
|
10
|
+
import { validatedCollection } from './validation.js';
|
|
9
11
|
function refuse(code, file, location) {
|
|
10
12
|
return {
|
|
11
13
|
kind: 'refused',
|
|
@@ -21,7 +23,7 @@ function repointed(document, definition, from, to, moves, settled) {
|
|
|
21
23
|
const parsed = parse(document.content, from);
|
|
22
24
|
if (!parsed.ok)
|
|
23
25
|
return [];
|
|
24
|
-
|
|
26
|
+
const changes = [];
|
|
25
27
|
const names = new Set();
|
|
26
28
|
for (const { pointer, value } of definition === undefined
|
|
27
29
|
? []
|
|
@@ -33,38 +35,39 @@ function repointed(document, definition, from, to, moves, settled) {
|
|
|
33
35
|
const destination = moves.get(named) ?? named;
|
|
34
36
|
if (target(to, value) === destination)
|
|
35
37
|
continue;
|
|
36
|
-
|
|
38
|
+
changes.push({
|
|
37
39
|
kind: 'reference',
|
|
38
40
|
pointer,
|
|
39
41
|
value: retarget(value, relative(to, destination)),
|
|
40
42
|
prior: value,
|
|
41
43
|
});
|
|
42
|
-
if (applied.outcome !== 'applied')
|
|
43
|
-
continue;
|
|
44
|
-
next = applied.document;
|
|
45
44
|
names.add(name);
|
|
46
45
|
}
|
|
46
|
+
if (changes.length === 0)
|
|
47
|
+
return [];
|
|
48
|
+
const applied = apply(parsed.document, changes);
|
|
49
|
+
if (applied.outcome !== 'applied')
|
|
50
|
+
return [];
|
|
51
|
+
const next = applied.document;
|
|
47
52
|
return [...names].map((name) => ({ kind: 'field', path: from, name, value: next.fields[name] }));
|
|
48
53
|
}
|
|
49
|
-
function edited(document,
|
|
50
|
-
|
|
54
|
+
function edited(document, changes) {
|
|
55
|
+
const parts = new Map();
|
|
51
56
|
for (const change of changes) {
|
|
52
|
-
if (change.
|
|
53
|
-
|
|
54
|
-
if (change.kind
|
|
55
|
-
|
|
56
|
-
const applied = apply(next, change.kind === 'preamble'
|
|
57
|
-
? { kind: 'preamble', value: change.value, prior: next.preamble }
|
|
58
|
-
: {
|
|
57
|
+
if (change.kind === 'preamble')
|
|
58
|
+
parts.set('preamble', { kind: 'preamble', value: change.value, prior: document.preamble });
|
|
59
|
+
if (change.kind === 'section')
|
|
60
|
+
parts.set(`section ${change.name}`, {
|
|
59
61
|
kind: 'section',
|
|
60
62
|
name: change.name,
|
|
61
63
|
value: change.value,
|
|
62
|
-
prior:
|
|
64
|
+
prior: document.sections[change.name] ?? '',
|
|
63
65
|
});
|
|
64
|
-
if (applied.outcome === 'applied')
|
|
65
|
-
next = applied.document;
|
|
66
66
|
}
|
|
67
|
-
|
|
67
|
+
if (parts.size === 0)
|
|
68
|
+
return document;
|
|
69
|
+
const applied = apply(document, [...parts.values()]);
|
|
70
|
+
return applied.outcome === 'applied' ? applied.document : document;
|
|
68
71
|
}
|
|
69
72
|
function bodies(path, before, after) {
|
|
70
73
|
const changes = [];
|
|
@@ -79,7 +82,7 @@ function bodies(path, before, after) {
|
|
|
79
82
|
return changes;
|
|
80
83
|
}
|
|
81
84
|
function relinks(path, moved, before, moves) {
|
|
82
|
-
|
|
85
|
+
const changes = [];
|
|
83
86
|
for (const link of links(before, path)) {
|
|
84
87
|
const destination = moves.get(link.target) ?? link.target;
|
|
85
88
|
if (destination === link.target && moved === path)
|
|
@@ -87,20 +90,23 @@ function relinks(path, moved, before, moves) {
|
|
|
87
90
|
const to = relative(moved, destination);
|
|
88
91
|
if (to === relative(path, link.target))
|
|
89
92
|
continue;
|
|
90
|
-
|
|
91
|
-
if (applied.outcome === 'refuse') {
|
|
92
|
-
return {
|
|
93
|
-
kind: 'refused',
|
|
94
|
-
refusal: {
|
|
95
|
-
code: applied.refusal.rule,
|
|
96
|
-
retryable: false,
|
|
97
|
-
file: path,
|
|
98
|
-
...(applied.refusal.location === undefined ? {} : { location: applied.refusal.location }),
|
|
99
|
-
},
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
after = applied.document;
|
|
93
|
+
changes.push({ kind: 'link', href: link.href, to });
|
|
103
94
|
}
|
|
95
|
+
if (changes.length === 0)
|
|
96
|
+
return { kind: 'changes', changes: [] };
|
|
97
|
+
const applied = apply(before, changes);
|
|
98
|
+
if (applied.outcome === 'refuse') {
|
|
99
|
+
return {
|
|
100
|
+
kind: 'refused',
|
|
101
|
+
refusal: {
|
|
102
|
+
code: applied.refusal.rule,
|
|
103
|
+
retryable: false,
|
|
104
|
+
file: path,
|
|
105
|
+
...(applied.refusal.location === undefined ? {} : { location: applied.refusal.location }),
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
const after = applied.document;
|
|
104
110
|
if (after === before)
|
|
105
111
|
return { kind: 'changes', changes: [] };
|
|
106
112
|
if (before.type === undefined) {
|
|
@@ -108,19 +114,14 @@ function relinks(path, moved, before, moves) {
|
|
|
108
114
|
}
|
|
109
115
|
return { kind: 'changes', changes: bodies(path, before, after) };
|
|
110
116
|
}
|
|
111
|
-
function
|
|
112
|
-
|
|
113
|
-
const item = merged[index];
|
|
114
|
-
if (item.path !== path)
|
|
115
|
-
continue;
|
|
116
|
-
if (item.kind === 'section' || item.kind === 'preamble')
|
|
117
|
-
merged.splice(index, 1);
|
|
118
|
-
}
|
|
117
|
+
function partKey(change) {
|
|
118
|
+
return change.kind === 'section' ? `section ${change.name}` : change.kind;
|
|
119
119
|
}
|
|
120
|
-
function rewrites(changes, visible) {
|
|
120
|
+
function* rewrites(changes, visible) {
|
|
121
121
|
const moves = new Map();
|
|
122
122
|
const settled = new Set();
|
|
123
|
-
|
|
123
|
+
const parts = new Map();
|
|
124
|
+
for (const [index, change] of changes.entries()) {
|
|
124
125
|
if (change.kind === 'move')
|
|
125
126
|
moves.set(change.path, change.to);
|
|
126
127
|
if (change.kind === 'remove' ||
|
|
@@ -131,54 +132,143 @@ function rewrites(changes, visible) {
|
|
|
131
132
|
}
|
|
132
133
|
if (change.kind === 'field')
|
|
133
134
|
settled.add(`${change.path} ${change.name}`);
|
|
135
|
+
if (isPart(change)) {
|
|
136
|
+
const held = parts.get(change.path);
|
|
137
|
+
if (held === undefined)
|
|
138
|
+
parts.set(change.path, [index]);
|
|
139
|
+
else
|
|
140
|
+
held.push(index);
|
|
141
|
+
}
|
|
134
142
|
}
|
|
135
143
|
if (moves.size === 0)
|
|
136
144
|
return { kind: 'changes', changes };
|
|
137
145
|
const merged = [...changes];
|
|
138
146
|
const added = [];
|
|
139
|
-
for (const [path, document] of documentsOf(visible.collection)) {
|
|
147
|
+
for (const [path, document] of yield* documentsOf(visible.collection)) {
|
|
140
148
|
if (settled.has(path))
|
|
141
149
|
continue;
|
|
142
150
|
const moved = moves.get(path) ?? path;
|
|
143
151
|
const definition = definitionOf(governing(visible.collection.composition, path), document.type);
|
|
144
|
-
|
|
145
|
-
|
|
152
|
+
const repointing = repointed(document, definition, path, moved, moves, settled);
|
|
153
|
+
added.push(...repointing);
|
|
154
|
+
const own = parts.get(path) ?? [];
|
|
155
|
+
const relinked = relinks(path, moved, edited(document, own.map((index) => merged[index])), moves);
|
|
146
156
|
if (relinked.kind === 'refused')
|
|
147
157
|
return relinked;
|
|
158
|
+
const keyed = new Map();
|
|
159
|
+
for (const index of own) {
|
|
160
|
+
const key = partKey(merged[index]);
|
|
161
|
+
if (!keyed.has(key))
|
|
162
|
+
keyed.set(key, index);
|
|
163
|
+
}
|
|
148
164
|
for (const change of relinked.changes) {
|
|
149
165
|
if (change.kind === 'replace') {
|
|
150
|
-
|
|
166
|
+
for (const index of own) {
|
|
167
|
+
const kind = merged[index]?.kind;
|
|
168
|
+
if (kind === 'section' || kind === 'preamble')
|
|
169
|
+
merged[index] = null;
|
|
170
|
+
}
|
|
151
171
|
added.push(change);
|
|
152
172
|
continue;
|
|
153
173
|
}
|
|
154
|
-
const index =
|
|
155
|
-
|
|
156
|
-
(change.kind !== 'section' || (item.kind === 'section' && item.name === change.name)));
|
|
157
|
-
if (index === -1)
|
|
174
|
+
const index = keyed.get(partKey(change));
|
|
175
|
+
if (index === undefined)
|
|
158
176
|
added.push(change);
|
|
159
177
|
else
|
|
160
178
|
merged[index] = change;
|
|
161
179
|
}
|
|
180
|
+
const text = visible.collection.text[path].length;
|
|
181
|
+
const rewritten = repointing.length > 0 || relinked.changes.length > 0;
|
|
182
|
+
yield ROW_WEIGHT + text + (rewritten ? text : 0);
|
|
162
183
|
}
|
|
163
|
-
return {
|
|
184
|
+
return {
|
|
185
|
+
kind: 'changes',
|
|
186
|
+
changes: [...added, ...merged.filter((change) => change !== null)],
|
|
187
|
+
};
|
|
164
188
|
}
|
|
165
|
-
function anticipated(changes, preconditions, rewritten, visible) {
|
|
166
|
-
const
|
|
189
|
+
function* anticipated(changes, preconditions, rewritten, visible) {
|
|
190
|
+
const given = new Set(changes);
|
|
191
|
+
const derived = rewritten.filter((change) => !given.has(change));
|
|
167
192
|
return {
|
|
168
193
|
changes: rewritten,
|
|
169
|
-
preconditions: [...preconditionsOf(derived, visible, []), ...preconditions],
|
|
194
|
+
preconditions: [...(yield* preconditionsOf(derived, visible, [])), ...preconditions],
|
|
170
195
|
};
|
|
171
196
|
}
|
|
172
|
-
export function providerRewritten(batch, visible) {
|
|
173
|
-
const rewritten = rewrites(batch.changes, visible);
|
|
197
|
+
export function* providerRewritten(batch, visible) {
|
|
198
|
+
const rewritten = yield* rewrites(batch.changes, visible);
|
|
174
199
|
if (rewritten.kind === 'refused')
|
|
175
200
|
return batch;
|
|
176
201
|
return {
|
|
177
202
|
...batch,
|
|
178
|
-
...anticipated(batch.changes, batch.preconditions, rewritten.changes, visible),
|
|
203
|
+
...(yield* anticipated(batch.changes, batch.preconditions, rewritten.changes, visible)),
|
|
179
204
|
};
|
|
180
205
|
}
|
|
181
|
-
function
|
|
206
|
+
function crossed(document, definition, path, to) {
|
|
207
|
+
const changes = [];
|
|
208
|
+
for (const link of links(document, path)) {
|
|
209
|
+
const written = to(link.target, link.href);
|
|
210
|
+
if (written !== undefined)
|
|
211
|
+
changes.push({ kind: 'link', href: link.href, to: written });
|
|
212
|
+
}
|
|
213
|
+
for (const { pointer, value } of definition === undefined
|
|
214
|
+
? []
|
|
215
|
+
: references(document, definition)) {
|
|
216
|
+
const named = target(path, value);
|
|
217
|
+
const written = named === null ? undefined : to(named, value);
|
|
218
|
+
if (written !== undefined) {
|
|
219
|
+
changes.push({ kind: 'reference', pointer, value: retarget(value, written), prior: value });
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
return changes;
|
|
223
|
+
}
|
|
224
|
+
function rewritten(path, document, changes) {
|
|
225
|
+
if (changes.length === 0)
|
|
226
|
+
return [];
|
|
227
|
+
const applied = apply(document, changes);
|
|
228
|
+
if (applied.outcome !== 'applied')
|
|
229
|
+
return [];
|
|
230
|
+
const after = applied.document;
|
|
231
|
+
if (document.type === undefined)
|
|
232
|
+
return [{ kind: 'replace', path, content: serialize(after) }];
|
|
233
|
+
const names = new Set(changes.flatMap((change) => change.kind === 'reference' ? [pointerSegments(change.pointer)[0] ?? ''] : []));
|
|
234
|
+
return [
|
|
235
|
+
...[...names].map((name) => ({ kind: 'field', path, name, value: after.fields[name] })),
|
|
236
|
+
...bodies(path, document, after),
|
|
237
|
+
];
|
|
238
|
+
}
|
|
239
|
+
function roomPathOf(handle, path) {
|
|
240
|
+
return `/rooms/${handle}/${path}`;
|
|
241
|
+
}
|
|
242
|
+
export function* leavingRewritten(batch, visible) {
|
|
243
|
+
const between = batch.between;
|
|
244
|
+
if (between === undefined)
|
|
245
|
+
return batch;
|
|
246
|
+
const moved = new Map(between.moves.map(({ path, to }) => [path, roomPathOf(between.destination.handle, to)]));
|
|
247
|
+
const derived = [];
|
|
248
|
+
for (const [path, document] of yield* documentsOf(visible.collection)) {
|
|
249
|
+
if (moved.has(path))
|
|
250
|
+
continue;
|
|
251
|
+
const definition = definitionOf(governing(visible.collection.composition, path), document.type);
|
|
252
|
+
derived.push(...rewritten(path, document, crossed(document, definition, path, (named) => moved.get(named))));
|
|
253
|
+
yield ROW_WEIGHT + visible.collection.text[path].length;
|
|
254
|
+
}
|
|
255
|
+
if (derived.length === 0)
|
|
256
|
+
return batch;
|
|
257
|
+
return {
|
|
258
|
+
...batch,
|
|
259
|
+
changes: [...derived, ...batch.changes],
|
|
260
|
+
preconditions: [...(yield* preconditionsOf(derived, visible, [])), ...batch.preconditions],
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
export function rewriting(batch, locator) {
|
|
264
|
+
return leaving(batch, locator) || batch.changes.some((change) => change.kind === 'move');
|
|
265
|
+
}
|
|
266
|
+
export function* effectiveIn(batch, locator, visible) {
|
|
267
|
+
return leaving(batch, locator)
|
|
268
|
+
? yield* leavingRewritten(batch, visible)
|
|
269
|
+
: yield* providerRewritten(batch, visible);
|
|
270
|
+
}
|
|
271
|
+
function* incoming(collection, removed, candidates) {
|
|
182
272
|
const found = new Map();
|
|
183
273
|
const note = (target, file) => {
|
|
184
274
|
if (!removed.has(target))
|
|
@@ -187,13 +277,20 @@ function incoming(collection, removed, candidates) {
|
|
|
187
277
|
referrers.add(file);
|
|
188
278
|
found.set(target, referrers);
|
|
189
279
|
};
|
|
190
|
-
const read =
|
|
191
|
-
|
|
192
|
-
|
|
280
|
+
const read = function* (paths) {
|
|
281
|
+
const seen = new Set();
|
|
282
|
+
for (const path of paths) {
|
|
283
|
+
if (seen.has(path))
|
|
284
|
+
continue;
|
|
285
|
+
seen.add(path);
|
|
193
286
|
const document = collection.document(path);
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
287
|
+
if (document !== undefined)
|
|
288
|
+
yield [path, document];
|
|
289
|
+
}
|
|
290
|
+
};
|
|
291
|
+
for (const [path, document] of candidates === null
|
|
292
|
+
? yield* documentsOf(collection)
|
|
293
|
+
: read(candidates)) {
|
|
197
294
|
const definition = definitionOf(governing(collection.composition, path), document.type);
|
|
198
295
|
for (const { value, to } of definition === undefined ? [] : references(document, definition)) {
|
|
199
296
|
if (to.includes(ATTACHMENT))
|
|
@@ -202,8 +299,9 @@ function incoming(collection, removed, candidates) {
|
|
|
202
299
|
if (named !== null)
|
|
203
300
|
note(named, path);
|
|
204
301
|
}
|
|
302
|
+
yield ROW_WEIGHT + collection.text[path].length;
|
|
205
303
|
}
|
|
206
|
-
const [first] =
|
|
304
|
+
const [first] = yield* sorting(found.keys());
|
|
207
305
|
if (first === undefined)
|
|
208
306
|
return null;
|
|
209
307
|
const every = new Set();
|
|
@@ -216,14 +314,16 @@ function incoming(collection, removed, candidates) {
|
|
|
216
314
|
code: 'referenced-missing-file',
|
|
217
315
|
retryable: false,
|
|
218
316
|
file: first,
|
|
219
|
-
referrers:
|
|
317
|
+
referrers: yield* sorting(every),
|
|
220
318
|
},
|
|
221
319
|
};
|
|
222
320
|
}
|
|
223
321
|
function affected(change) {
|
|
224
322
|
return change.kind === 'move' ? [change.path, change.to] : [change.path];
|
|
225
323
|
}
|
|
226
|
-
|
|
324
|
+
const WRITE = ['write'];
|
|
325
|
+
const MOVE_OUT = ['write', 'erase'];
|
|
326
|
+
function guard(changes, input, removing) {
|
|
227
327
|
const overridden = new Map();
|
|
228
328
|
const existing = {
|
|
229
329
|
has: (path) => overridden.get(path) ??
|
|
@@ -231,6 +331,7 @@ function guard(changes, input) {
|
|
|
231
331
|
add: (path) => void overridden.set(path, true),
|
|
232
332
|
delete: (path) => void overridden.set(path, false),
|
|
233
333
|
};
|
|
334
|
+
const occupied = (path) => input.folders.has(path) ? path : (ancestors(path).find((one) => existing.has(one)) ?? null);
|
|
234
335
|
for (const [index, change] of changes.entries()) {
|
|
235
336
|
for (const path of affected(change)) {
|
|
236
337
|
const normalized = normalize(path);
|
|
@@ -239,13 +340,14 @@ function guard(changes, input) {
|
|
|
239
340
|
if (covered(input.providerOwnedPaths, normalized)) {
|
|
240
341
|
return refuse('provider-owned-path', normalized);
|
|
241
342
|
}
|
|
242
|
-
const operation
|
|
243
|
-
|
|
244
|
-
|
|
343
|
+
for (const operation of change.kind === 'remove' ? removing : WRITE)
|
|
344
|
+
if (!input.local && !covered(input.operations[operation], normalized))
|
|
345
|
+
return refuse(`${operation}-grant`, normalized);
|
|
245
346
|
}
|
|
246
|
-
if (change.kind === 'create') {
|
|
247
|
-
|
|
248
|
-
|
|
347
|
+
if (change.kind === 'create' || change.kind === 'arrival') {
|
|
348
|
+
const taken = existing.has(change.path) ? change.path : occupied(change.path);
|
|
349
|
+
if (taken !== null)
|
|
350
|
+
return refuse('path-collision', taken);
|
|
249
351
|
existing.add(change.path);
|
|
250
352
|
continue;
|
|
251
353
|
}
|
|
@@ -255,6 +357,9 @@ function guard(changes, input) {
|
|
|
255
357
|
input.bases.some((base) => base.kind === 'absent' && base.path === change.path))) {
|
|
256
358
|
return refuse('path-collision', change.path);
|
|
257
359
|
}
|
|
360
|
+
const taken = occupied(change.path);
|
|
361
|
+
if (taken !== null)
|
|
362
|
+
return refuse('path-collision', taken);
|
|
258
363
|
if (!input.local &&
|
|
259
364
|
existing.has(change.path) &&
|
|
260
365
|
input.visible.revisions[departure(changes, index)] === undefined) {
|
|
@@ -266,8 +371,9 @@ function guard(changes, input) {
|
|
|
266
371
|
if (change.kind === 'move') {
|
|
267
372
|
if (!existing.has(change.path))
|
|
268
373
|
return refuse('path-absent', change.path);
|
|
269
|
-
|
|
270
|
-
|
|
374
|
+
const taken = existing.has(change.to) ? change.to : occupied(change.to);
|
|
375
|
+
if (taken !== null)
|
|
376
|
+
return refuse('path-collision', taken);
|
|
271
377
|
if (unrevised(input, change.path)) {
|
|
272
378
|
return refuse('unknown-revision', change.path);
|
|
273
379
|
}
|
|
@@ -303,7 +409,7 @@ export function queuedDocuments(queue) {
|
|
|
303
409
|
const paths = new Set();
|
|
304
410
|
for (const batch of queue) {
|
|
305
411
|
for (const change of batch.changes) {
|
|
306
|
-
if (change.kind === 'binary')
|
|
412
|
+
if (change.kind === 'binary' || (change.kind === 'arrival' && !('content' in change)))
|
|
307
413
|
continue;
|
|
308
414
|
if (change.kind === 'remove')
|
|
309
415
|
paths.delete(change.path);
|
|
@@ -332,7 +438,7 @@ function sameTarget(precondition, change) {
|
|
|
332
438
|
return ((precondition.kind !== 'field' && precondition.kind !== 'section') ||
|
|
333
439
|
((change.kind === 'field' || change.kind === 'section') && precondition.name === change.name));
|
|
334
440
|
}
|
|
335
|
-
function preconditionsOf(changes, visible, bases) {
|
|
441
|
+
function* preconditionsOf(changes, visible, bases) {
|
|
336
442
|
const preconditions = [];
|
|
337
443
|
const seen = new Set();
|
|
338
444
|
const add = (precondition) => {
|
|
@@ -343,6 +449,7 @@ function preconditionsOf(changes, visible, bases) {
|
|
|
343
449
|
preconditions.push(precondition);
|
|
344
450
|
};
|
|
345
451
|
for (const change of changes) {
|
|
452
|
+
yield ROW_WEIGHT;
|
|
346
453
|
if (change.kind === 'field' || change.kind === 'section' || change.kind === 'preamble') {
|
|
347
454
|
const based = bases.find((base) => sameTarget(base, change));
|
|
348
455
|
if (based !== undefined) {
|
|
@@ -390,10 +497,13 @@ function preconditionsOf(changes, visible, bases) {
|
|
|
390
497
|
function depth(path) {
|
|
391
498
|
return path.split('/').length;
|
|
392
499
|
}
|
|
393
|
-
function
|
|
500
|
+
function* exceeding(limits, changes, effective, resulting) {
|
|
394
501
|
const written = effective.map((change) => (change.kind === 'move' ? change.to : change.path));
|
|
395
502
|
const created = changes
|
|
396
|
-
.filter((change) => change.kind === 'create' ||
|
|
503
|
+
.filter((change) => change.kind === 'create' ||
|
|
504
|
+
change.kind === 'move' ||
|
|
505
|
+
change.kind === 'binary' ||
|
|
506
|
+
change.kind === 'arrival')
|
|
397
507
|
.map((change) => (change.kind === 'move' ? change.to : change.path));
|
|
398
508
|
for (const limit of limits) {
|
|
399
509
|
const value = limit.value;
|
|
@@ -407,9 +517,13 @@ function exceeded(limits, changes, effective, resulting) {
|
|
|
407
517
|
return refuse('provider-limit', undefined, limit.name);
|
|
408
518
|
}
|
|
409
519
|
if (limit.name === 'document-size') {
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
520
|
+
for (const path of written) {
|
|
521
|
+
const text = resulting.documents[path] ?? '';
|
|
522
|
+
if (new TextEncoder().encode(text).byteLength > value) {
|
|
523
|
+
return refuse('provider-limit', path, limit.name);
|
|
524
|
+
}
|
|
525
|
+
yield ROW_WEIGHT + text.length;
|
|
526
|
+
}
|
|
413
527
|
}
|
|
414
528
|
if (limit.name === 'path-length') {
|
|
415
529
|
const long = created.find((path) => path.length > value);
|
|
@@ -439,7 +553,7 @@ function relativeField(path, name, value, handle, definition) {
|
|
|
439
553
|
!opened.ok ||
|
|
440
554
|
!JSON.stringify(value ?? null).includes(`/rooms/${handle}/`))
|
|
441
555
|
return value;
|
|
442
|
-
const held = apply(opened.document, { kind: 'field', name, value, prior: undefined });
|
|
556
|
+
const held = apply(opened.document, [{ kind: 'field', name, value, prior: undefined }]);
|
|
443
557
|
if (held.outcome !== 'applied')
|
|
444
558
|
return value;
|
|
445
559
|
const result = relativize(held.document, path, handle, definition);
|
|
@@ -475,17 +589,6 @@ function relativeChanges(input) {
|
|
|
475
589
|
return { ...change, fields, sections };
|
|
476
590
|
});
|
|
477
591
|
}
|
|
478
|
-
function unmodeledType(collection, composition) {
|
|
479
|
-
if (available(composition))
|
|
480
|
-
return false;
|
|
481
|
-
for (const [path, document] of documentsOf(collection)) {
|
|
482
|
-
if (document.type !== undefined &&
|
|
483
|
-
document.type !== 'any' &&
|
|
484
|
-
governing(composition, path).status === 'unavailable')
|
|
485
|
-
return true;
|
|
486
|
-
}
|
|
487
|
-
return false;
|
|
488
|
-
}
|
|
489
592
|
function unqueueable(file) {
|
|
490
593
|
return { kind: 'refused', refusal: { code: 'unknown-revision', retryable: false, file } };
|
|
491
594
|
}
|
|
@@ -495,29 +598,44 @@ function isPart(change) {
|
|
|
495
598
|
function touched(change) {
|
|
496
599
|
return change.kind === 'move' ? [change.path, change.to] : [change.path];
|
|
497
600
|
}
|
|
498
|
-
function
|
|
601
|
+
function partsApplied(content, path, changes) {
|
|
499
602
|
const parsed = parse(content, path);
|
|
500
603
|
if (!parsed.ok)
|
|
501
604
|
return null;
|
|
502
605
|
const document = parsed.document;
|
|
503
|
-
const
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
606
|
+
const parts = new Map();
|
|
607
|
+
for (const change of changes) {
|
|
608
|
+
if (change.kind === 'field')
|
|
609
|
+
parts.set(`field ${change.name}`, {
|
|
610
|
+
kind: 'field',
|
|
611
|
+
name: change.name,
|
|
612
|
+
value: change.value,
|
|
613
|
+
prior: document.fields[change.name],
|
|
614
|
+
});
|
|
615
|
+
else if (change.kind === 'section')
|
|
616
|
+
parts.set(`section ${change.name}`, {
|
|
512
617
|
kind: 'section',
|
|
513
618
|
name: change.name,
|
|
514
619
|
value: change.value,
|
|
515
|
-
prior: document.sections[change.name],
|
|
516
|
-
}
|
|
517
|
-
|
|
620
|
+
prior: document.sections[change.name] ?? '',
|
|
621
|
+
});
|
|
622
|
+
else
|
|
623
|
+
parts.set('preamble', { kind: 'preamble', value: change.value, prior: document.preamble });
|
|
624
|
+
}
|
|
625
|
+
const applied = apply(document, [...parts.values()]);
|
|
518
626
|
return applied.outcome === 'applied' ? serialize(applied.document) : null;
|
|
519
627
|
}
|
|
520
|
-
function
|
|
628
|
+
function settledParts(changes, deferred) {
|
|
629
|
+
for (const [held, parts] of deferred) {
|
|
630
|
+
const content = partsApplied(held.content, held.path, parts);
|
|
631
|
+
if (content === null)
|
|
632
|
+
return held.path;
|
|
633
|
+
changes[changes.indexOf(held)] = { ...held, content };
|
|
634
|
+
}
|
|
635
|
+
deferred.clear();
|
|
636
|
+
return null;
|
|
637
|
+
}
|
|
638
|
+
function folded(changes, change, appending, deferred) {
|
|
521
639
|
const held = changes.find((item) => item.path === change.path && (item.kind === 'create' || item.kind === 'replace'));
|
|
522
640
|
const whole = held === undefined ? -1 : changes.indexOf(held);
|
|
523
641
|
const occupied = changes.some((item) => !isPart(item) && item !== held && touched(item).includes(change.path));
|
|
@@ -538,10 +656,11 @@ function folded(changes, change, appending) {
|
|
|
538
656
|
return 'appended';
|
|
539
657
|
}
|
|
540
658
|
if ('content' in held) {
|
|
541
|
-
const
|
|
542
|
-
if (
|
|
543
|
-
|
|
544
|
-
|
|
659
|
+
const parts = deferred.get(held);
|
|
660
|
+
if (parts === undefined)
|
|
661
|
+
deferred.set(held, [change]);
|
|
662
|
+
else
|
|
663
|
+
parts.push(change);
|
|
545
664
|
return 'folded';
|
|
546
665
|
}
|
|
547
666
|
if (change.kind === 'preamble')
|
|
@@ -572,17 +691,21 @@ function folded(changes, change, appending) {
|
|
|
572
691
|
changes.push(change);
|
|
573
692
|
return 'appended';
|
|
574
693
|
}
|
|
575
|
-
function relinked(batch, move, before, after, appending) {
|
|
576
|
-
const derived = rewrites([move], after);
|
|
694
|
+
function* relinked(batch, move, before, after, appending) {
|
|
695
|
+
const derived = yield* rewrites([move], after);
|
|
577
696
|
if (derived.kind === 'refused')
|
|
578
697
|
return derived;
|
|
579
698
|
const changes = [...batch.changes];
|
|
580
699
|
const appended = [];
|
|
581
700
|
let changed = false;
|
|
701
|
+
const deferred = new Map();
|
|
582
702
|
for (const change of derived.changes) {
|
|
583
703
|
if (change === move)
|
|
584
704
|
continue;
|
|
585
|
-
const
|
|
705
|
+
const unsettled = isPart(change) ? null : settledParts(changes, deferred);
|
|
706
|
+
if (unsettled !== null)
|
|
707
|
+
return unqueueable(unsettled);
|
|
708
|
+
const outcome = folded(changes, change, appending, deferred);
|
|
586
709
|
if (outcome === 'refused')
|
|
587
710
|
return unqueueable(change.path);
|
|
588
711
|
if (outcome === 'appended')
|
|
@@ -590,9 +713,13 @@ function relinked(batch, move, before, after, appending) {
|
|
|
590
713
|
if (outcome !== 'skipped')
|
|
591
714
|
changed = true;
|
|
592
715
|
}
|
|
716
|
+
const unsettled = settledParts(changes, deferred);
|
|
717
|
+
if (unsettled !== null)
|
|
718
|
+
return unqueueable(unsettled);
|
|
593
719
|
if (!changed)
|
|
594
720
|
return { kind: 'relinked', batch };
|
|
595
721
|
const held = new Set(batch.preconditions.map(identity));
|
|
722
|
+
const added = yield* preconditionsOf(appended, before, []);
|
|
596
723
|
return {
|
|
597
724
|
kind: 'relinked',
|
|
598
725
|
batch: immutable({
|
|
@@ -601,7 +728,7 @@ function relinked(batch, move, before, after, appending) {
|
|
|
601
728
|
changes,
|
|
602
729
|
preconditions: [
|
|
603
730
|
...batch.preconditions,
|
|
604
|
-
...
|
|
731
|
+
...added.filter((precondition) => !held.has(identity(precondition))),
|
|
605
732
|
],
|
|
606
733
|
}),
|
|
607
734
|
};
|
|
@@ -647,7 +774,7 @@ function withdrawnFile(batch, change, at) {
|
|
|
647
774
|
];
|
|
648
775
|
return immutable({ ...batch, id: changeBatchIdentity(), changes, preconditions });
|
|
649
776
|
}
|
|
650
|
-
export function
|
|
777
|
+
export function* requeuing(queue, changes, visible, changeable, state) {
|
|
651
778
|
const next = [...queue];
|
|
652
779
|
const origins = new Map();
|
|
653
780
|
const withdrawn = new Map();
|
|
@@ -670,19 +797,19 @@ export function requeued(queue, changes, visible, changeable, state) {
|
|
|
670
797
|
return unqueueable(change.path);
|
|
671
798
|
const following = next.slice(index);
|
|
672
799
|
const rebuilt = [];
|
|
673
|
-
let before = change.kind === 'move' ? state(next.slice(0, index)) : visible;
|
|
800
|
+
let before = change.kind === 'move' ? yield* state(next.slice(0, index)) : visible;
|
|
674
801
|
for (const [offset, batch] of following.entries()) {
|
|
675
802
|
let current = batch;
|
|
676
803
|
if (change.kind === 'move') {
|
|
677
|
-
const after = state(next.slice(0, index + offset + 1));
|
|
804
|
+
const after = yield* state(next.slice(0, index + offset + 1));
|
|
678
805
|
const appending = offset === 0 && created(batch, queuedFile(batch, change.path, held.localId));
|
|
679
|
-
const relinking = relinked(batch, change, before, after, appending);
|
|
806
|
+
const relinking = yield* relinked(batch, change, before, after, appending);
|
|
680
807
|
if (relinking.kind === 'refused')
|
|
681
808
|
return relinking;
|
|
682
809
|
current = relinking.batch;
|
|
683
810
|
before = after;
|
|
684
811
|
}
|
|
685
|
-
if (current !== batch && !open(batch))
|
|
812
|
+
if (current !== batch && (!open(batch) || batch.between !== undefined))
|
|
686
813
|
return unqueueable(change.path);
|
|
687
814
|
rebuilt.push(offset === 0
|
|
688
815
|
? withdrawnFile(current, change, queuedFile(current, change.path, held.localId))
|
|
@@ -723,10 +850,17 @@ export function joined(queue, owner, extra) {
|
|
|
723
850
|
if (clash !== undefined)
|
|
724
851
|
return unqueueable(clash);
|
|
725
852
|
const changes = [...owner.changes];
|
|
853
|
+
const deferred = new Map();
|
|
726
854
|
for (const change of extra.changes) {
|
|
727
|
-
|
|
855
|
+
const unsettled = isPart(change) ? null : settledParts(changes, deferred);
|
|
856
|
+
if (unsettled !== null)
|
|
857
|
+
return unqueueable(unsettled);
|
|
858
|
+
if (folded(changes, change, true, deferred) === 'refused')
|
|
728
859
|
return unqueueable(change.path);
|
|
729
860
|
}
|
|
861
|
+
const unsettled = settledParts(changes, deferred);
|
|
862
|
+
if (unsettled !== null)
|
|
863
|
+
return unqueueable(unsettled);
|
|
730
864
|
const held = new Set(owner.preconditions.map(covering));
|
|
731
865
|
const written = new Set(owner.changes.flatMap((change) => change.kind === 'create' || change.kind === 'replace' ? [change.path] : []));
|
|
732
866
|
const preconditions = [
|
|
@@ -745,59 +879,66 @@ export function joined(queue, owner, extra) {
|
|
|
745
879
|
});
|
|
746
880
|
return { kind: 'joined', batch, queue: queue.map((item) => (item === owner ? batch : item)) };
|
|
747
881
|
}
|
|
748
|
-
export function
|
|
882
|
+
export function* limiting(queue, batch, limits, state) {
|
|
749
883
|
const at = queue.indexOf(batch);
|
|
750
|
-
const
|
|
884
|
+
const rewritten = yield* providerRewritten(batch, yield* state(queue.slice(0, at)));
|
|
885
|
+
const limited = yield* exceeding(limits, batch.changes, rewritten.changes, yield* state(queue.slice(0, at + 1)));
|
|
751
886
|
return limited?.kind === 'refused' ? limited.refusal : null;
|
|
752
887
|
}
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
const
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
const
|
|
768
|
-
const
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
888
|
+
function typedText(content) {
|
|
889
|
+
if (content === undefined)
|
|
890
|
+
return false;
|
|
891
|
+
const parsed = parse(content);
|
|
892
|
+
return parsed.ok && parsed.document.type !== undefined && parsed.document.type !== 'any';
|
|
893
|
+
}
|
|
894
|
+
function touchedLibrary(resulting, touched, composition) {
|
|
895
|
+
const entries = touched
|
|
896
|
+
.flatMap((path) => {
|
|
897
|
+
const content = resulting.documents[path];
|
|
898
|
+
const binary = resulting.binaries[path] !== undefined;
|
|
899
|
+
return content === undefined && !binary ? [] : [{ path, content: content ?? null }];
|
|
900
|
+
})
|
|
901
|
+
.sort((left, right) => (left.path < right.path ? -1 : left.path > right.path ? 1 : 0));
|
|
902
|
+
const contents = new Map(entries.map(({ path, content }) => [path, content]));
|
|
903
|
+
const binaries = new Set(Object.keys(resulting.binaries).filter((path) => resulting.binaries[path] !== undefined));
|
|
904
|
+
return validatedCollection(() => Promise.resolve({ entries, next: null }), async (paths) => {
|
|
905
|
+
const known = new Map();
|
|
906
|
+
const pace = paced();
|
|
907
|
+
for (const path of paths) {
|
|
908
|
+
const content = contents.get(path);
|
|
909
|
+
if (binaries.has(path))
|
|
910
|
+
known.set(path, { type: undefined, binary: true });
|
|
911
|
+
else if (content !== undefined && content !== null) {
|
|
912
|
+
const read = parse(content, path);
|
|
913
|
+
if (read.ok)
|
|
914
|
+
known.set(path, { type: read.document.type ?? 'any', binary: false });
|
|
915
|
+
await pace(content.length + ROW_WEIGHT);
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
return known;
|
|
919
|
+
}, composition);
|
|
920
|
+
}
|
|
921
|
+
async function judging(visible, resulting, composition, validate, removed, touched) {
|
|
773
922
|
if (removed.size > 0) {
|
|
774
|
-
const
|
|
775
|
-
const referenced = incoming(collectionOf(resulting.documents, input.composition), removed, clean === null || referrers === null
|
|
776
|
-
? null
|
|
777
|
-
: [...referrers, ...differing(clean.text, resulting.documents)]);
|
|
923
|
+
const referenced = await stepped(incoming(collectionOf(resulting.documents, composition), removed, null));
|
|
778
924
|
if (referenced !== null)
|
|
779
925
|
return referenced;
|
|
780
926
|
}
|
|
781
|
-
const
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
const
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
const withoutModel = typedPaths.find((path) => governing(
|
|
927
|
+
const typedPaths = [];
|
|
928
|
+
const pace = paced();
|
|
929
|
+
for (const path of touched) {
|
|
930
|
+
const before = visible.documents[path];
|
|
931
|
+
const after = resulting.documents[path];
|
|
932
|
+
if (typedText(before) || typedText(after))
|
|
933
|
+
typedPaths.push(path);
|
|
934
|
+
await pace((before?.length ?? 0) + (after?.length ?? 0) + ROW_WEIGHT);
|
|
935
|
+
}
|
|
936
|
+
const withoutModel = typedPaths.find((path) => governing(composition, path).status === 'unavailable');
|
|
791
937
|
if (withoutModel !== undefined)
|
|
792
938
|
return refuse('model-unavailable', withoutModel);
|
|
793
|
-
const verdict =
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
: validateCollection(needsModel
|
|
797
|
-
? resulting.documents
|
|
798
|
-
: Object.fromEntries(touched.flatMap((path) => resulting.documents[path] === undefined
|
|
799
|
-
? []
|
|
800
|
-
: [[path, resulting.documents[path]]])), Object.keys(resulting.binaries), input.composition);
|
|
939
|
+
const verdict = typedPaths.length > 0
|
|
940
|
+
? await validate(resulting, touched)
|
|
941
|
+
: await touchedLibrary(resulting, touched, composition);
|
|
801
942
|
if (verdict.verdict === 'refuse') {
|
|
802
943
|
return {
|
|
803
944
|
kind: 'refused',
|
|
@@ -810,12 +951,92 @@ export function buildBatch(input) {
|
|
|
810
951
|
},
|
|
811
952
|
};
|
|
812
953
|
}
|
|
813
|
-
|
|
954
|
+
return {
|
|
955
|
+
kind: 'judged',
|
|
956
|
+
validated: typedPaths
|
|
957
|
+
.map((path) => governing(composition, path))
|
|
958
|
+
.find((model) => model.status !== 'unavailable'),
|
|
959
|
+
};
|
|
960
|
+
}
|
|
961
|
+
function placed(reference) {
|
|
962
|
+
const key = roomPathOf(reference.handle, reference.path);
|
|
963
|
+
if (reference.kind === 'link')
|
|
964
|
+
return `link ${key}`;
|
|
965
|
+
if (reference.kind === 'item')
|
|
966
|
+
return `section ${reference.section} ${key}`;
|
|
967
|
+
const pointer = reference.pointer
|
|
968
|
+
.split('/')
|
|
969
|
+
.map((segment) => (ARRAY_INDEX.test(segment) ? '-' : segment))
|
|
970
|
+
.join('/');
|
|
971
|
+
return `field ${pointer} ${key}`;
|
|
972
|
+
}
|
|
973
|
+
function roomReferencesIn(path, content, composition) {
|
|
974
|
+
if (content === undefined)
|
|
975
|
+
return [];
|
|
976
|
+
const parsed = parse(content, path);
|
|
977
|
+
if (!parsed.ok)
|
|
978
|
+
return [];
|
|
979
|
+
return roomReferences(parsed.document, definitionOf(governing(composition, path), parsed.document.type));
|
|
980
|
+
}
|
|
981
|
+
function* admittedRooms(changes, visible, resulting, composition) {
|
|
982
|
+
const from = new Map();
|
|
983
|
+
for (const [index, change] of changes.entries()) {
|
|
984
|
+
if (change.kind === 'move')
|
|
985
|
+
from.set(change.to, departure(changes, index));
|
|
986
|
+
}
|
|
987
|
+
for (const path of [...new Set(changes.flatMap(affected))].sort()) {
|
|
988
|
+
const now = resulting.documents[path];
|
|
989
|
+
if (now === undefined)
|
|
990
|
+
continue;
|
|
991
|
+
const held = new Set(roomReferencesIn(path, visible.documents[from.get(path) ?? path], composition).map(placed));
|
|
992
|
+
for (const reference of roomReferencesIn(path, now, composition)) {
|
|
993
|
+
if (reference.kind === 'link' || reference.crossRoom === true)
|
|
994
|
+
continue;
|
|
995
|
+
if (held.has(placed(reference)))
|
|
996
|
+
continue;
|
|
997
|
+
return refuse('unresolved-reference', path, reference.kind === 'field' ? reference.pointer : reference.section);
|
|
998
|
+
}
|
|
999
|
+
yield ROW_WEIGHT + now.length;
|
|
1000
|
+
}
|
|
1001
|
+
return null;
|
|
1002
|
+
}
|
|
1003
|
+
function validationOf(validated) {
|
|
1004
|
+
return validated === undefined
|
|
1005
|
+
? {}
|
|
1006
|
+
: {
|
|
1007
|
+
validation: {
|
|
1008
|
+
identity: validated.snapshot.identity,
|
|
1009
|
+
version: validated.snapshot.version,
|
|
1010
|
+
source: validated.status,
|
|
1011
|
+
},
|
|
1012
|
+
};
|
|
1013
|
+
}
|
|
1014
|
+
async function batching(input) {
|
|
1015
|
+
const changes = relativeChanges(input);
|
|
1016
|
+
const structural = changes.find((change) => change.kind === 'move' || change.kind === 'remove');
|
|
1017
|
+
if (structural !== undefined && input.unmodeled) {
|
|
1018
|
+
return refuse('model-unavailable', structural.path);
|
|
1019
|
+
}
|
|
1020
|
+
if (changes.length === 0)
|
|
1021
|
+
return refuse('no-change');
|
|
1022
|
+
const rewritten = await stepped(rewrites(changes, input.visible));
|
|
1023
|
+
if (rewritten.kind === 'refused')
|
|
1024
|
+
return rewritten;
|
|
1025
|
+
const refusal = guard(changes, input, WRITE);
|
|
1026
|
+
if (refusal !== null)
|
|
1027
|
+
return refusal;
|
|
1028
|
+
const preconditions = await stepped(preconditionsOf(changes, input.visible, input.bases));
|
|
1029
|
+
const predicted = await stepped(anticipated(changes, preconditions, rewritten.changes, input.visible));
|
|
1030
|
+
const resulting = await stepped(overlaying(input.visible, [{ id: '', baseRoomVersion: input.baseRoomVersion, ...predicted }]));
|
|
1031
|
+
const judged = await judging(input.visible, resulting, input.composition, input.validate, new Set(changes.filter((change) => change.kind === 'remove').map((change) => change.path)), [...new Set(predicted.changes.flatMap(affected))]);
|
|
1032
|
+
if (judged.kind === 'refused')
|
|
1033
|
+
return judged;
|
|
1034
|
+
const crossing = await stepped(admittedRooms(changes, input.visible, resulting, input.composition));
|
|
1035
|
+
if (crossing !== null)
|
|
1036
|
+
return crossing;
|
|
1037
|
+
const limited = await stepped(exceeding(input.providerLimits, changes, predicted.changes, resulting));
|
|
814
1038
|
if (limited !== null)
|
|
815
1039
|
return limited;
|
|
816
|
-
const validated = typedPaths
|
|
817
|
-
.map((path) => governing(input.composition, path))
|
|
818
|
-
.find((model) => model.status !== 'unavailable');
|
|
819
1040
|
return {
|
|
820
1041
|
kind: 'batch',
|
|
821
1042
|
batch: immutable({
|
|
@@ -824,15 +1045,127 @@ export function buildBatch(input) {
|
|
|
824
1045
|
changes,
|
|
825
1046
|
preconditions,
|
|
826
1047
|
...(input.writtenBy === undefined ? {} : { writtenBy: input.writtenBy }),
|
|
827
|
-
...(validated
|
|
828
|
-
? {}
|
|
829
|
-
: {
|
|
830
|
-
validation: {
|
|
831
|
-
identity: validated.snapshot.identity,
|
|
832
|
-
version: validated.snapshot.version,
|
|
833
|
-
source: validated.status,
|
|
834
|
-
},
|
|
835
|
-
}),
|
|
1048
|
+
...validationOf(judged.validated),
|
|
836
1049
|
}),
|
|
837
1050
|
};
|
|
838
1051
|
}
|
|
1052
|
+
export const MOVE_DOCUMENTS = 'move-documents';
|
|
1053
|
+
function heldAt(visible, path) {
|
|
1054
|
+
return visible.documents[path] !== undefined || visible.binaries[path] !== undefined;
|
|
1055
|
+
}
|
|
1056
|
+
function arrivingText(path, to, source, moved) {
|
|
1057
|
+
const content = source.visible.documents[path];
|
|
1058
|
+
const document = source.visible.collection.document(path);
|
|
1059
|
+
if (document === undefined)
|
|
1060
|
+
return content;
|
|
1061
|
+
const definition = definitionOf(governing(source.composition, path), document.type);
|
|
1062
|
+
const changes = crossed(document, definition, path, (named, href) => {
|
|
1063
|
+
const at = moved.get(named);
|
|
1064
|
+
if (at !== undefined)
|
|
1065
|
+
return target(to, href) === at ? undefined : relative(to, at);
|
|
1066
|
+
return heldAt(source.visible, named) ? roomPathOf(source.handle, named) : undefined;
|
|
1067
|
+
});
|
|
1068
|
+
if (changes.length === 0)
|
|
1069
|
+
return content;
|
|
1070
|
+
const applied = apply(document, changes);
|
|
1071
|
+
return applied.outcome === 'applied' ? serialize(applied.document) : content;
|
|
1072
|
+
}
|
|
1073
|
+
function arrivalOf({ path, to }, source, moved) {
|
|
1074
|
+
const { documents, revisions, fileIds, created, changes, binaries } = source.visible;
|
|
1075
|
+
const kept = {
|
|
1076
|
+
...(fileIds[path] === undefined ? {} : { fileId: fileIds[path] }),
|
|
1077
|
+
...(created[path] === undefined ? {} : { created: created[path] }),
|
|
1078
|
+
...(changes[path] === undefined ? {} : { change: changes[path] }),
|
|
1079
|
+
};
|
|
1080
|
+
const heads = {
|
|
1081
|
+
...(revisions[path] === undefined ? {} : { revision: revisions[path] }),
|
|
1082
|
+
...kept,
|
|
1083
|
+
};
|
|
1084
|
+
const binary = binaries[path];
|
|
1085
|
+
if (binary?.state === 'accepted') {
|
|
1086
|
+
const { byteLength, mediaType, sha256 } = binary;
|
|
1087
|
+
return {
|
|
1088
|
+
kind: 'arrival',
|
|
1089
|
+
path: to,
|
|
1090
|
+
binary: { byteLength, mediaType, sha256 },
|
|
1091
|
+
...heads,
|
|
1092
|
+
};
|
|
1093
|
+
}
|
|
1094
|
+
const content = arrivingText(path, to, source, moved);
|
|
1095
|
+
return {
|
|
1096
|
+
kind: 'arrival',
|
|
1097
|
+
path: to,
|
|
1098
|
+
content,
|
|
1099
|
+
...(content === documents[path] ? heads : kept),
|
|
1100
|
+
};
|
|
1101
|
+
}
|
|
1102
|
+
async function moving(input) {
|
|
1103
|
+
const { source, destination, moves } = input;
|
|
1104
|
+
if (moves.length === 0)
|
|
1105
|
+
return refuse('no-change');
|
|
1106
|
+
const removals = moves.map(({ path }) => ({ kind: 'remove', path }));
|
|
1107
|
+
const leaves = guard(removals, { ...source, local: input.local, bases: [] }, MOVE_OUT);
|
|
1108
|
+
if (leaves !== null)
|
|
1109
|
+
return leaves;
|
|
1110
|
+
const uploading = moves.find(({ path }) => source.visible.binaries[path]?.state === 'pending');
|
|
1111
|
+
if (uploading !== undefined)
|
|
1112
|
+
return refuse('unknown-revision', uploading.path);
|
|
1113
|
+
const moved = new Map(moves.map(({ path, to }) => [path, to]));
|
|
1114
|
+
const arrivals = moves.map((move) => arrivalOf(move, source, moved));
|
|
1115
|
+
const arrives = guard(arrivals, { ...destination, local: input.local, bases: [] }, WRITE);
|
|
1116
|
+
if (arrives !== null)
|
|
1117
|
+
return arrives;
|
|
1118
|
+
const bound = input.providerLimits.find((limit) => limit.name === MOVE_DOCUMENTS)?.value;
|
|
1119
|
+
if (typeof bound === 'number' && moves.length > bound) {
|
|
1120
|
+
return refuse('provider-limit', undefined, MOVE_DOCUMENTS);
|
|
1121
|
+
}
|
|
1122
|
+
if (source.unmodeled)
|
|
1123
|
+
return refuse('model-unavailable', moves[0].path);
|
|
1124
|
+
const id = changeBatchIdentity();
|
|
1125
|
+
const between = {
|
|
1126
|
+
source: { room: source.room, baseRoomVersion: source.baseRoomVersion },
|
|
1127
|
+
destination: {
|
|
1128
|
+
room: destination.room,
|
|
1129
|
+
baseRoomVersion: destination.baseRoomVersion,
|
|
1130
|
+
handle: destination.handle,
|
|
1131
|
+
},
|
|
1132
|
+
moves,
|
|
1133
|
+
};
|
|
1134
|
+
const written = input.writtenBy === undefined ? {} : { writtenBy: input.writtenBy };
|
|
1135
|
+
const leavingBatch = {
|
|
1136
|
+
id,
|
|
1137
|
+
baseRoomVersion: source.baseRoomVersion,
|
|
1138
|
+
changes: removals,
|
|
1139
|
+
preconditions: moves.map(({ path }) => existence(source.visible, path)),
|
|
1140
|
+
...written,
|
|
1141
|
+
between,
|
|
1142
|
+
};
|
|
1143
|
+
const effective = await stepped(leavingRewritten(leavingBatch, source.visible));
|
|
1144
|
+
const left = await stepped(overlaying(source.visible, [effective]));
|
|
1145
|
+
const sourceJudged = await judging(source.visible, left, source.composition, source.validate, new Set(moves.map(({ path }) => path)), [...new Set(effective.changes.map((change) => change.path))]);
|
|
1146
|
+
if (sourceJudged.kind === 'refused')
|
|
1147
|
+
return sourceJudged;
|
|
1148
|
+
const arrivingBatch = {
|
|
1149
|
+
id,
|
|
1150
|
+
baseRoomVersion: destination.baseRoomVersion,
|
|
1151
|
+
changes: arrivals,
|
|
1152
|
+
preconditions: moves.map(({ to }) => ({ kind: 'absent', path: to })),
|
|
1153
|
+
...written,
|
|
1154
|
+
between,
|
|
1155
|
+
};
|
|
1156
|
+
const arrived = await stepped(overlaying(destination.visible, [arrivingBatch]));
|
|
1157
|
+
const destinationJudged = await judging(destination.visible, arrived, destination.composition, destination.validate, new Set(), moves.map(({ to }) => to));
|
|
1158
|
+
if (destinationJudged.kind === 'refused')
|
|
1159
|
+
return destinationJudged;
|
|
1160
|
+
const limited = (await stepped(exceeding(input.providerLimits, removals, effective.changes, left))) ??
|
|
1161
|
+
(await stepped(exceeding(input.providerLimits, arrivals, arrivals, arrived)));
|
|
1162
|
+
if (limited !== null)
|
|
1163
|
+
return limited;
|
|
1164
|
+
return { kind: 'moved', leaving: immutable(leavingBatch), arriving: immutable(arrivingBatch) };
|
|
1165
|
+
}
|
|
1166
|
+
export function buildMove(input) {
|
|
1167
|
+
return moving(input);
|
|
1168
|
+
}
|
|
1169
|
+
export function buildBatch(input) {
|
|
1170
|
+
return batching(input);
|
|
1171
|
+
}
|