@agentshouse/mdruntime 0.1.0-cfb2ae0107054 → 0.1.0-cfcbb238a5fa0
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/AGENTS.md +262 -262
- package/dist/acquisition.d.ts +14 -0
- package/dist/acquisition.d.ts.map +1 -0
- package/dist/acquisition.js +24 -0
- package/dist/adapter.d.ts +14 -7
- package/dist/adapter.d.ts.map +1 -1
- package/dist/bootstrap.d.ts +2 -1
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +4 -0
- package/dist/change-set.d.ts +2 -0
- package/dist/change-set.d.ts.map +1 -1
- package/dist/change-set.js +36 -10
- package/dist/chat/kit.d.ts +2 -1
- package/dist/chat/kit.d.ts.map +1 -1
- package/dist/chat/kit.js +3 -3
- package/dist/chat/list.d.ts +2 -1
- package/dist/chat/list.d.ts.map +1 -1
- package/dist/chat/list.js +4 -3
- package/dist/chat/message.d.ts.map +1 -1
- package/dist/chat/message.js +2 -2
- package/dist/chat/messages.d.ts +1 -0
- package/dist/chat/messages.d.ts.map +1 -1
- package/dist/chat/messages.js +4 -0
- package/dist/chat/provider.d.ts +1 -1
- package/dist/chat/provider.d.ts.map +1 -1
- package/dist/chat/provider.js +26 -17
- package/dist/chat/ready.d.ts +1 -0
- package/dist/chat/ready.d.ts.map +1 -1
- package/dist/chat/ready.js +2 -2
- package/dist/client.d.ts +10 -6
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +11 -2
- package/dist/collection.d.ts +17 -3
- package/dist/collection.d.ts.map +1 -1
- package/dist/collection.js +230 -19
- package/dist/connection.d.ts +23 -7
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +1065 -192
- package/dist/conversation.d.ts +11 -5
- package/dist/conversation.d.ts.map +1 -1
- package/dist/conversation.js +241 -100
- package/dist/durability.d.ts +7 -1
- package/dist/durability.d.ts.map +1 -1
- package/dist/entry.d.ts +2 -2
- package/dist/entry.d.ts.map +1 -1
- package/dist/entry.js +3 -3
- package/dist/host.d.ts +16 -2
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +82 -8
- package/dist/identity.d.ts +2 -0
- package/dist/identity.d.ts.map +1 -1
- package/dist/identity.js +6 -0
- package/dist/index.d.ts +8 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/memory.d.ts +7 -2
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +20 -7
- package/dist/model.d.ts +4 -2
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +10 -1
- package/dist/observation.d.ts +5 -2
- package/dist/observation.d.ts.map +1 -1
- package/dist/observation.js +22 -11
- package/dist/overlay.d.ts +2 -0
- package/dist/overlay.d.ts.map +1 -1
- package/dist/overlay.js +58 -55
- package/dist/query.d.ts +35 -3
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +8 -2
- package/dist/reach.d.ts +6 -3
- package/dist/reach.d.ts.map +1 -1
- package/dist/reach.js +16 -4
- package/dist/react.d.ts +7 -4
- package/dist/react.d.ts.map +1 -1
- package/dist/react.js +6 -4
- package/dist/read-side.d.ts +13 -6
- package/dist/read-side.d.ts.map +1 -1
- package/dist/read-side.js +285 -83
- package/dist/readiness.d.ts +53 -0
- package/dist/readiness.d.ts.map +1 -0
- package/dist/readiness.js +33 -0
- package/dist/reads.d.ts +11 -0
- package/dist/reads.d.ts.map +1 -0
- package/dist/reads.js +98 -0
- package/dist/recovery.d.ts +25 -0
- package/dist/recovery.d.ts.map +1 -0
- package/dist/recovery.js +197 -0
- package/dist/refresh.d.ts +4 -4
- package/dist/refresh.d.ts.map +1 -1
- package/dist/refresh.js +17 -10
- package/dist/replica.d.ts +1 -1
- package/dist/replica.d.ts.map +1 -1
- package/dist/replica.js +57 -20
- package/dist/room-draft.d.ts +13 -1
- package/dist/room-draft.d.ts.map +1 -1
- package/dist/room-draft.js +2 -2
- package/dist/rows.d.ts +5 -13
- package/dist/rows.d.ts.map +1 -1
- package/dist/rows.js +5 -13
- package/dist/save.d.ts +5 -0
- package/dist/save.d.ts.map +1 -1
- package/dist/save.js +36 -13
- package/dist/search.d.ts +36 -6
- package/dist/search.d.ts.map +1 -1
- package/dist/search.js +132 -46
- package/dist/seed.d.ts +16 -0
- package/dist/seed.d.ts.map +1 -0
- package/dist/seed.js +61 -0
- package/dist/shared.d.ts +11 -0
- package/dist/shared.d.ts.map +1 -0
- package/dist/shared.js +368 -0
- package/dist/status.d.ts +4 -0
- package/dist/status.d.ts.map +1 -1
- package/dist/store.d.ts +21 -5
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +157 -53
- package/dist/turn.d.ts +7 -0
- package/dist/turn.d.ts.map +1 -0
- package/dist/turn.js +45 -0
- package/dist/wire.d.ts +136 -32
- package/dist/wire.d.ts.map +1 -1
- package/dist/wire.js +48 -31
- package/package.json +2 -2
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
const COMPLETE_ROOMS = new Set(['complete', 'unadmitted']);
|
|
2
|
+
export const SETTLED_ROOMS = new Set([...COMPLETE_ROOMS, 'refused']);
|
|
3
|
+
export function readinessOf(facts) {
|
|
4
|
+
const { established, coverage: held, ...reported } = facts;
|
|
5
|
+
const settledConversations = held.conversations === 'complete' || held.conversations === 'undeclared';
|
|
6
|
+
const complete = held.listed &&
|
|
7
|
+
settledConversations &&
|
|
8
|
+
held.rooms.every((room) => COMPLETE_ROOMS.has(room.state));
|
|
9
|
+
const settled = held.listed &&
|
|
10
|
+
settledConversations &&
|
|
11
|
+
held.rooms.every((room) => SETTLED_ROOMS.has(room.state));
|
|
12
|
+
const coverage = { ...held, complete };
|
|
13
|
+
const stored = facts.code === 'stored';
|
|
14
|
+
const ready = stored && complete;
|
|
15
|
+
const usable = stored && (ready || established);
|
|
16
|
+
const status = ready
|
|
17
|
+
? 'ready'
|
|
18
|
+
: facts.capacity !== null
|
|
19
|
+
? 'paused'
|
|
20
|
+
: facts.lost && !established
|
|
21
|
+
? 'lost'
|
|
22
|
+
: settled && !complete
|
|
23
|
+
? 'refused'
|
|
24
|
+
: 'preparing';
|
|
25
|
+
return {
|
|
26
|
+
...reported,
|
|
27
|
+
coverage,
|
|
28
|
+
status,
|
|
29
|
+
ready,
|
|
30
|
+
usable,
|
|
31
|
+
durability: facts.persistence === 'granted' ? 'persistent' : 'best-effort',
|
|
32
|
+
};
|
|
33
|
+
}
|
package/dist/reads.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Adapter } from './adapter.js';
|
|
2
|
+
import type { Reads } from './bootstrap.js';
|
|
3
|
+
export type DoorReads = Reads & {
|
|
4
|
+
carried(locator: string): number;
|
|
5
|
+
finished(locator: string, turn: number): void;
|
|
6
|
+
opened(): void;
|
|
7
|
+
applied(): void;
|
|
8
|
+
lost(): void;
|
|
9
|
+
};
|
|
10
|
+
export declare function doorReads(adapter: Adapter, declaration: (locator: string) => unknown, generation: () => number): DoorReads;
|
|
11
|
+
//# sourceMappingURL=reads.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reads.d.ts","sourceRoot":"","sources":["../src/reads.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,OAAO,EAOR,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAE5C,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG;IAC9B,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;IACjC,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9C,MAAM,IAAI,IAAI,CAAC;IACf,OAAO,IAAI,IAAI,CAAC;IAChB,IAAI,IAAI,IAAI,CAAC;CACd,CAAC;AAiCF,wBAAgB,SAAS,CACvB,OAAO,EAAE,OAAO,EAChB,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,EACzC,UAAU,EAAE,MAAM,MAAM,GACvB,SAAS,CA0FX"}
|
package/dist/reads.js
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
function declaredAs(declaration) {
|
|
2
|
+
if (declaration === null || typeof declaration !== 'object')
|
|
3
|
+
return declaration;
|
|
4
|
+
const { roomVersion: _version, ...declared } = declaration;
|
|
5
|
+
return declared;
|
|
6
|
+
}
|
|
7
|
+
function sameHeld(one, other) {
|
|
8
|
+
return one?.documents === other?.documents && one?.revisions === other?.revisions;
|
|
9
|
+
}
|
|
10
|
+
function failed(answer) {
|
|
11
|
+
return answer?.kind === 'transport-uncertainty';
|
|
12
|
+
}
|
|
13
|
+
function continues(answer) {
|
|
14
|
+
const page = answer;
|
|
15
|
+
return page?.kind === 'net-advancement' && page.pageToken !== undefined;
|
|
16
|
+
}
|
|
17
|
+
export function doorReads(adapter, declaration, generation) {
|
|
18
|
+
const reading = new Map();
|
|
19
|
+
const taken = new Map();
|
|
20
|
+
let carrying = false;
|
|
21
|
+
function joined(read, authorization, request, ask) {
|
|
22
|
+
const key = `${read} ${request.locator} ${request.pageToken ?? ''}`;
|
|
23
|
+
const { held, ...named } = request;
|
|
24
|
+
const asked = JSON.stringify([declaredAs(declaration(request.locator)), named]);
|
|
25
|
+
const asking = generation();
|
|
26
|
+
const current = reading.get(key);
|
|
27
|
+
if (current !== undefined &&
|
|
28
|
+
current.authorization === authorization &&
|
|
29
|
+
current.asked === asked &&
|
|
30
|
+
sameHeld(current.held, held) &&
|
|
31
|
+
(!current.settled || current.holder < asking)) {
|
|
32
|
+
if (current.settled && !current.continued)
|
|
33
|
+
reading.delete(key);
|
|
34
|
+
else
|
|
35
|
+
current.holder = Math.max(current.holder, asking);
|
|
36
|
+
if (current.from === asking)
|
|
37
|
+
return current.answer;
|
|
38
|
+
const again = () => joined(read, authorization, request, ask);
|
|
39
|
+
return current.answer.then((answer) => {
|
|
40
|
+
if (failed(answer))
|
|
41
|
+
return again();
|
|
42
|
+
taken.set(request.locator, (taken.get(request.locator) ?? 0) + 1);
|
|
43
|
+
return answer;
|
|
44
|
+
}, again);
|
|
45
|
+
}
|
|
46
|
+
const answer = ask();
|
|
47
|
+
const sent = {
|
|
48
|
+
locator: request.locator,
|
|
49
|
+
authorization,
|
|
50
|
+
asked,
|
|
51
|
+
held,
|
|
52
|
+
answer,
|
|
53
|
+
from: asking,
|
|
54
|
+
holder: asking,
|
|
55
|
+
settled: false,
|
|
56
|
+
continued: false,
|
|
57
|
+
};
|
|
58
|
+
reading.set(key, sent);
|
|
59
|
+
const settled = (result, kept) => {
|
|
60
|
+
sent.settled = true;
|
|
61
|
+
sent.continued = kept && read === 'refresh' && continues(result);
|
|
62
|
+
if (reading.get(key) !== sent)
|
|
63
|
+
return;
|
|
64
|
+
const live = sent.holder === generation();
|
|
65
|
+
if (!kept || (live ? !sent.continued : !carrying))
|
|
66
|
+
reading.delete(key);
|
|
67
|
+
};
|
|
68
|
+
answer.then((result) => settled(result, !failed(result)), () => settled(null, false));
|
|
69
|
+
return answer;
|
|
70
|
+
}
|
|
71
|
+
return {
|
|
72
|
+
bootstrap: (authorization, request) => joined('bootstrap', authorization, request, () => adapter.bootstrap(authorization, request)),
|
|
73
|
+
refresh: (authorization, request) => joined('refresh', authorization, request, () => adapter.refresh(authorization, request)),
|
|
74
|
+
reached: (locator, roomVersion, target) => adapter.reached(locator, roomVersion, target),
|
|
75
|
+
carried: (locator) => taken.get(locator) ?? 0,
|
|
76
|
+
finished(locator, turn) {
|
|
77
|
+
for (const [key, held] of reading) {
|
|
78
|
+
if (held.locator !== locator || !held.settled || held.holder !== turn)
|
|
79
|
+
continue;
|
|
80
|
+
if (turn === generation() || !carrying)
|
|
81
|
+
reading.delete(key);
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
opened() {
|
|
85
|
+
carrying = true;
|
|
86
|
+
},
|
|
87
|
+
applied() {
|
|
88
|
+
carrying = false;
|
|
89
|
+
for (const [key, held] of reading) {
|
|
90
|
+
if (held.settled && held.holder !== generation())
|
|
91
|
+
reading.delete(key);
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
lost() {
|
|
95
|
+
reading.clear();
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export type Attempted = 'done' | 'again' | {
|
|
2
|
+
readonly at: number;
|
|
3
|
+
};
|
|
4
|
+
export type Attempt = (signal: AbortSignal) => Promise<Attempted>;
|
|
5
|
+
export type AttemptOptions = {
|
|
6
|
+
readonly at?: number;
|
|
7
|
+
readonly again?: boolean;
|
|
8
|
+
};
|
|
9
|
+
export type RecoveryOptions = {
|
|
10
|
+
readonly firstMs?: number;
|
|
11
|
+
readonly ceilingMs?: number;
|
|
12
|
+
readonly attempts?: number;
|
|
13
|
+
readonly inFlight?: number;
|
|
14
|
+
};
|
|
15
|
+
export type Recovery = {
|
|
16
|
+
attempt(intent: string, run: Attempt, options?: AttemptOptions): Promise<boolean>;
|
|
17
|
+
pending(intent: string): boolean;
|
|
18
|
+
resume(): void;
|
|
19
|
+
cancel(intent: string): void;
|
|
20
|
+
scope(inFlight?: number): Recovery;
|
|
21
|
+
retire(): Promise<void>;
|
|
22
|
+
};
|
|
23
|
+
export declare function retryDelay(tries: number, firstMs?: number, ceilingMs?: number): number;
|
|
24
|
+
export declare function createRecovery(options?: RecoveryOptions): Recovery;
|
|
25
|
+
//# sourceMappingURL=recovery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recovery.d.ts","sourceRoot":"","sources":["../src/recovery.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG;IAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnE,MAAM,MAAM,OAAO,GAAG,CAAC,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;AAElE,MAAM,MAAM,cAAc,GAAG;IAAE,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAEhF,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG;IACrB,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAClF,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;IACjC,MAAM,IAAI,IAAI,CAAC;IACf,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,KAAK,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;IACnC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACzB,CAAC;AAsBF,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,SAAW,EAAE,SAAS,SAAa,GAAG,MAAM,CAG5F;AAuKD,wBAAgB,cAAc,CAAC,OAAO,GAAE,eAAoB,GAAG,QAAQ,CAStE"}
|
package/dist/recovery.js
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
// A first retry waits about a second, so a passing failure clears before the next attempt.
|
|
2
|
+
const FIRST_MS = 1_000;
|
|
3
|
+
// Waits stop doubling at half a minute, so work resumes soon after a long failure ends.
|
|
4
|
+
const CEILING_MS = 30_000;
|
|
5
|
+
const ATTEMPTS = 8;
|
|
6
|
+
export function retryDelay(tries, firstMs = FIRST_MS, ceilingMs = CEILING_MS) {
|
|
7
|
+
const ceiling = Math.min(ceilingMs, firstMs * 2 ** tries);
|
|
8
|
+
return ceiling / 2 + (Math.random() * ceiling) / 2;
|
|
9
|
+
}
|
|
10
|
+
function owner(backoff, inFlight, release = () => { }) {
|
|
11
|
+
const intents = new Map();
|
|
12
|
+
const children = new Set();
|
|
13
|
+
const running = new Set();
|
|
14
|
+
const queued = [];
|
|
15
|
+
let free = inFlight;
|
|
16
|
+
let retired = false;
|
|
17
|
+
function finish(key, intent, done) {
|
|
18
|
+
if (intents.get(key) === intent)
|
|
19
|
+
intents.delete(key);
|
|
20
|
+
if (intent.timer !== null)
|
|
21
|
+
clearTimeout(intent.timer);
|
|
22
|
+
intent.timer = null;
|
|
23
|
+
intent.end(done);
|
|
24
|
+
}
|
|
25
|
+
function wait(key, intent, at, guided) {
|
|
26
|
+
if (intent.timer !== null)
|
|
27
|
+
clearTimeout(intent.timer);
|
|
28
|
+
intent.due = at;
|
|
29
|
+
intent.guided = guided;
|
|
30
|
+
intent.timer = setTimeout(() => {
|
|
31
|
+
intent.timer = null;
|
|
32
|
+
launch(key, intent);
|
|
33
|
+
}, Math.max(0, at - Date.now()));
|
|
34
|
+
}
|
|
35
|
+
function launch(key, intent) {
|
|
36
|
+
intent.due = null;
|
|
37
|
+
intent.guided = false;
|
|
38
|
+
const controller = new AbortController();
|
|
39
|
+
intent.controller = controller;
|
|
40
|
+
const run = start(key, intent, controller);
|
|
41
|
+
running.add(run);
|
|
42
|
+
void run.finally(() => running.delete(run));
|
|
43
|
+
}
|
|
44
|
+
async function start(key, intent, controller) {
|
|
45
|
+
while (free === 0)
|
|
46
|
+
await new Promise((admit) => queued.push(admit));
|
|
47
|
+
if (controller.signal.aborted) {
|
|
48
|
+
queued.shift()?.();
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
free -= 1;
|
|
52
|
+
const abandoned = new Promise((resolve) => {
|
|
53
|
+
controller.signal.addEventListener('abort', () => resolve(null), { once: true });
|
|
54
|
+
});
|
|
55
|
+
let result;
|
|
56
|
+
try {
|
|
57
|
+
result = await Promise.race([intent.run(controller.signal), abandoned]);
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
result = 'again';
|
|
61
|
+
}
|
|
62
|
+
finally {
|
|
63
|
+
free += 1;
|
|
64
|
+
queued.shift()?.();
|
|
65
|
+
}
|
|
66
|
+
if (result === null || controller.signal.aborted || intents.get(key) !== intent)
|
|
67
|
+
return;
|
|
68
|
+
intent.controller = null;
|
|
69
|
+
const again = intent.again;
|
|
70
|
+
intent.again = null;
|
|
71
|
+
if (result === 'done') {
|
|
72
|
+
intent.tries = 0;
|
|
73
|
+
if (again === null)
|
|
74
|
+
finish(key, intent, true);
|
|
75
|
+
else if (again === 'now')
|
|
76
|
+
launch(key, intent);
|
|
77
|
+
else
|
|
78
|
+
wait(key, intent, again, true);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
intent.tries += 1;
|
|
82
|
+
if (intent.tries >= backoff.attempts) {
|
|
83
|
+
finish(key, intent, false);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
if (result === 'again') {
|
|
87
|
+
const delay = retryDelay(intent.tries - 1, backoff.firstMs, backoff.ceilingMs);
|
|
88
|
+
wait(key, intent, Date.now() + delay, false);
|
|
89
|
+
}
|
|
90
|
+
else
|
|
91
|
+
wait(key, intent, result.at, true);
|
|
92
|
+
}
|
|
93
|
+
const recovery = {
|
|
94
|
+
attempt(key, run, options = {}) {
|
|
95
|
+
if (retired)
|
|
96
|
+
return Promise.resolve(false);
|
|
97
|
+
const held = intents.get(key);
|
|
98
|
+
if (held !== undefined) {
|
|
99
|
+
held.run = run;
|
|
100
|
+
if (held.controller !== null) {
|
|
101
|
+
const at = options.at;
|
|
102
|
+
held.again =
|
|
103
|
+
at === undefined || held.again === 'now'
|
|
104
|
+
? 'now'
|
|
105
|
+
: Math.min(at, held.again ?? Number.POSITIVE_INFINITY);
|
|
106
|
+
}
|
|
107
|
+
else if (held.due !== null && held.due <= Date.now()) {
|
|
108
|
+
if (held.timer !== null)
|
|
109
|
+
clearTimeout(held.timer);
|
|
110
|
+
held.timer = null;
|
|
111
|
+
launch(key, held);
|
|
112
|
+
}
|
|
113
|
+
else if (options.at !== undefined && (held.due === null || options.at < held.due)) {
|
|
114
|
+
wait(key, held, options.at, true);
|
|
115
|
+
}
|
|
116
|
+
return held.ended;
|
|
117
|
+
}
|
|
118
|
+
let end = () => { };
|
|
119
|
+
const ended = new Promise((resolve) => {
|
|
120
|
+
end = resolve;
|
|
121
|
+
});
|
|
122
|
+
const intent = {
|
|
123
|
+
run,
|
|
124
|
+
tries: 0,
|
|
125
|
+
timer: null,
|
|
126
|
+
due: null,
|
|
127
|
+
guided: false,
|
|
128
|
+
controller: null,
|
|
129
|
+
again: null,
|
|
130
|
+
ended,
|
|
131
|
+
end,
|
|
132
|
+
};
|
|
133
|
+
intents.set(key, intent);
|
|
134
|
+
if (options.at !== undefined)
|
|
135
|
+
wait(key, intent, options.at, true);
|
|
136
|
+
else if (options.again === true) {
|
|
137
|
+
intent.tries = 1;
|
|
138
|
+
wait(key, intent, Date.now() + retryDelay(0, backoff.firstMs, backoff.ceilingMs), false);
|
|
139
|
+
}
|
|
140
|
+
else
|
|
141
|
+
launch(key, intent);
|
|
142
|
+
return ended;
|
|
143
|
+
},
|
|
144
|
+
pending(key) {
|
|
145
|
+
const intent = intents.get(key);
|
|
146
|
+
return intent !== undefined && intent.controller === null;
|
|
147
|
+
},
|
|
148
|
+
resume() {
|
|
149
|
+
if (retired)
|
|
150
|
+
return;
|
|
151
|
+
for (const [key, intent] of [...intents]) {
|
|
152
|
+
if (intent.guided && intent.due !== null && intent.due > Date.now())
|
|
153
|
+
continue;
|
|
154
|
+
if (intent.timer !== null)
|
|
155
|
+
clearTimeout(intent.timer);
|
|
156
|
+
intent.timer = null;
|
|
157
|
+
intent.controller?.abort();
|
|
158
|
+
intent.again = null;
|
|
159
|
+
intent.tries = 0;
|
|
160
|
+
launch(key, intent);
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
cancel(key) {
|
|
164
|
+
const intent = intents.get(key);
|
|
165
|
+
if (intent === undefined)
|
|
166
|
+
return;
|
|
167
|
+
intent.controller?.abort();
|
|
168
|
+
finish(key, intent, false);
|
|
169
|
+
},
|
|
170
|
+
scope(bound = Infinity) {
|
|
171
|
+
const child = owner(backoff, bound, () => children.delete(child));
|
|
172
|
+
if (retired)
|
|
173
|
+
void child.retire();
|
|
174
|
+
else
|
|
175
|
+
children.add(child);
|
|
176
|
+
return child;
|
|
177
|
+
},
|
|
178
|
+
async retire() {
|
|
179
|
+
retired = true;
|
|
180
|
+
release();
|
|
181
|
+
for (const [key, intent] of [...intents]) {
|
|
182
|
+
intent.controller?.abort();
|
|
183
|
+
finish(key, intent, false);
|
|
184
|
+
}
|
|
185
|
+
await Promise.all([...children].map((child) => child.retire()));
|
|
186
|
+
await Promise.all(running);
|
|
187
|
+
},
|
|
188
|
+
};
|
|
189
|
+
return recovery;
|
|
190
|
+
}
|
|
191
|
+
export function createRecovery(options = {}) {
|
|
192
|
+
return owner({
|
|
193
|
+
firstMs: options.firstMs ?? FIRST_MS,
|
|
194
|
+
ceilingMs: options.ceilingMs ?? CEILING_MS,
|
|
195
|
+
attempts: options.attempts ?? ATTEMPTS,
|
|
196
|
+
}, options.inFlight ?? Infinity);
|
|
197
|
+
}
|
package/dist/refresh.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { Remodel } from './bootstrap.js';
|
|
1
|
+
import type { AdapterFailure, Authorization, RetryableRefusal } from './adapter.js';
|
|
2
|
+
import type { Reads, Remodel } from './bootstrap.js';
|
|
3
3
|
import { type ConfirmedLayer } from './replica.js';
|
|
4
4
|
import type { ReplicaRecord } from './store.js';
|
|
5
5
|
import { type Refused, type Unconfirmed } from './transfer.js';
|
|
@@ -19,6 +19,6 @@ export type RefreshOutcome = {
|
|
|
19
19
|
} | {
|
|
20
20
|
kind: 'beyond-horizon';
|
|
21
21
|
} | RetryableRefusal | Unconfirmed | Refused | AdapterFailure;
|
|
22
|
-
export declare function advancement(adapter:
|
|
23
|
-
export declare function refreshRoom(adapter:
|
|
22
|
+
export declare function advancement(adapter: Reads, authorization: Authorization, held: ReplicaRecord, remodel: Remodel, continuing: () => boolean): Promise<Advancement>;
|
|
23
|
+
export declare function refreshRoom(adapter: Reads, authorization: Authorization, confirmed: ConfirmedLayer, remodel: Remodel, continuing: () => boolean): Promise<RefreshOutcome>;
|
|
24
24
|
//# sourceMappingURL=refresh.d.ts.map
|
package/dist/refresh.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"refresh.d.ts","sourceRoot":"","sources":["../src/refresh.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"refresh.d.ts","sourceRoot":"","sources":["../src/refresh.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAe,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEjG,OAAO,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,EAAc,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAE/D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAe,KAAK,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5E,MAAM,MAAM,WAAW,GACnB;IAAE,IAAI,EAAE,eAAe,CAAA;CAAE,GACzB;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,MAAM,EAAE,aAAa,CAAA;CAAE,GAC3C;IAAE,IAAI,EAAE,gBAAgB,CAAA;CAAE,GAC1B,gBAAgB,GAChB,WAAW,GACX,cAAc,CAAC;AAEnB,MAAM,MAAM,cAAc,GACtB;IAAE,IAAI,EAAE,eAAe,CAAA;CAAE,GACzB;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,SAAS,EAAE,cAAc,CAAA;CAAE,GAC/C;IAAE,IAAI,EAAE,gBAAgB,CAAA;CAAE,GAC1B,gBAAgB,GAChB,WAAW,GACX,OAAO,GACP,cAAc,CAAC;AAEnB,wBAAsB,WAAW,CAC/B,OAAO,EAAE,KAAK,EACd,aAAa,EAAE,aAAa,EAC5B,IAAI,EAAE,aAAa,EACnB,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,MAAM,OAAO,GACxB,OAAO,CAAC,WAAW,CAAC,CA8EtB;AAED,wBAAsB,WAAW,CAC/B,OAAO,EAAE,KAAK,EACd,aAAa,EAAE,aAAa,EAC5B,SAAS,EAAE,cAAc,EACzB,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,MAAM,OAAO,GACxB,OAAO,CAAC,cAAc,CAAC,CAKzB"}
|
package/dist/refresh.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { acceptedBinaries } from './overlay.js';
|
|
2
2
|
import { readStaged } from './replica.js';
|
|
3
|
+
import { drafted, settled } from './shared.js';
|
|
3
4
|
import { unconfirmed } from './transfer.js';
|
|
4
5
|
export async function advancement(adapter, authorization, held, remodel, continuing) {
|
|
5
6
|
const locator = held.locator;
|
|
@@ -16,29 +17,34 @@ export async function advancement(adapter, authorization, held, remodel, continu
|
|
|
16
17
|
collection: held.model,
|
|
17
18
|
selection: held.selectionModel,
|
|
18
19
|
});
|
|
19
|
-
const documents =
|
|
20
|
-
const revisions =
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
-
const
|
|
20
|
+
const documents = drafted(held.documents);
|
|
21
|
+
const revisions = drafted(held.revisions);
|
|
22
|
+
const fileIds = drafted(held.fileIds);
|
|
23
|
+
const changes = drafted(held.changes);
|
|
24
|
+
const written = drafted(held.written);
|
|
25
|
+
const binaries = drafted(held.binaries);
|
|
24
26
|
const stage = (page) => {
|
|
25
27
|
for (const path of Object.keys(page.documents)) {
|
|
26
28
|
delete binaries[path];
|
|
29
|
+
delete fileIds[path];
|
|
27
30
|
delete changes[path];
|
|
28
31
|
written[path] = roomVersion;
|
|
29
32
|
}
|
|
30
33
|
for (const path of Object.keys(page.binaryFiles)) {
|
|
31
34
|
delete documents[path];
|
|
35
|
+
delete fileIds[path];
|
|
32
36
|
delete changes[path];
|
|
33
37
|
delete written[path];
|
|
34
38
|
}
|
|
35
39
|
Object.assign(documents, page.documents);
|
|
36
40
|
Object.assign(binaries, acceptedBinaries(page.binaryFiles));
|
|
37
41
|
Object.assign(revisions, page.revisions);
|
|
42
|
+
Object.assign(fileIds, page.fileIds);
|
|
38
43
|
Object.assign(changes, page.changes);
|
|
39
44
|
for (const path of page.removals) {
|
|
40
45
|
delete documents[path];
|
|
41
46
|
delete revisions[path];
|
|
47
|
+
delete fileIds[path];
|
|
42
48
|
delete changes[path];
|
|
43
49
|
delete written[path];
|
|
44
50
|
delete binaries[path];
|
|
@@ -71,11 +77,12 @@ export async function advancement(adapter, authorization, held, remodel, continu
|
|
|
71
77
|
model: models.collection,
|
|
72
78
|
selectionModel: models.selection,
|
|
73
79
|
roomVersion,
|
|
74
|
-
documents,
|
|
75
|
-
binaries,
|
|
76
|
-
revisions,
|
|
77
|
-
|
|
78
|
-
|
|
80
|
+
documents: settled(documents),
|
|
81
|
+
binaries: settled(binaries),
|
|
82
|
+
revisions: settled(revisions),
|
|
83
|
+
fileIds: settled(fileIds),
|
|
84
|
+
changes: settled(changes),
|
|
85
|
+
written: settled(written),
|
|
79
86
|
},
|
|
80
87
|
};
|
|
81
88
|
}
|
package/dist/replica.d.ts
CHANGED
|
@@ -31,7 +31,7 @@ type ReplayStep = {
|
|
|
31
31
|
export declare function compositionOf(record: ReplicaRecord): Composition;
|
|
32
32
|
export declare function confirmedOf(record: ReplicaRecord, previous?: ConfirmedLayer): ConfirmedLayer;
|
|
33
33
|
export declare function sameMembership(record: ReplicaRecord, other: ReplicaRecord): boolean;
|
|
34
|
-
export declare function readStaged(
|
|
34
|
+
export declare function readStaged(staged: ReplicaRecord, previous?: ConfirmedLayer): Staged;
|
|
35
35
|
export declare function readReclassified(record: ReplicaRecord, previous: ConfirmedLayer): Staged | {
|
|
36
36
|
kind: 'deferred';
|
|
37
37
|
};
|
package/dist/replica.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"replica.d.ts","sourceRoot":"","sources":["../src/replica.ts"],"names":[],"mappings":"AACA,OAAO,EAAmC,KAAK,WAAW,EAAqB,MAAM,aAAa,CAAC;AACnG,OAAO,
|
|
1
|
+
{"version":3,"file":"replica.d.ts","sourceRoot":"","sources":["../src/replica.ts"],"names":[],"mappings":"AACA,OAAO,EAAmC,KAAK,WAAW,EAAqB,MAAM,aAAa,CAAC;AACnG,OAAO,EAKL,KAAK,UAAU,EACf,KAAK,WAAW,EACjB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAML,KAAK,KAAK,EACX,MAAM,cAAc,CAAC;AAEtB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAE7C,MAAM,MAAM,cAAc,GAAG;IAC3B,MAAM,EAAE,aAAa,CAAC;IACtB,UAAU,EAAE,UAAU,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG;IACjC,UAAU,EAAE,UAAU,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,MAAM,GAAG;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,SAAS,EAAE,cAAc,CAAA;CAAE,GAAG,OAAO,CAAC;AAE7E,MAAM,MAAM,OAAO,GAAG;IACpB,SAAS,EAAE,cAAc,CAAC;IAC1B,KAAK,EAAE,SAAS,WAAW,EAAE,CAAC;IAC9B,OAAO,EAAE,YAAY,CAAC;IACtB,MAAM,EAAE,SAAS,UAAU,EAAE,CAAC;CAC/B,CAAC;AAEF,KAAK,UAAU,GAAG;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,KAAK,CAAC;IACd,KAAK,EAAE,KAAK,CAAC;IACb,SAAS,EAAE,WAAW,CAAC;IACvB,UAAU,CAAC,EAAE,UAAU,CAAC;CACzB,CAAC;AAEF,wBAAgB,aAAa,CAAC,MAAM,EAAE,aAAa,GAAG,WAAW,CAQhE;AAmBD,wBAAgB,WAAW,CAAC,MAAM,EAAE,aAAa,EAAE,QAAQ,CAAC,EAAE,cAAc,GAAG,cAAc,CAM5F;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,aAAa,GAAG,OAAO,CAKnF;AAYD,wBAAgB,UAAU,CAAC,MAAM,EAAE,aAAa,EAAE,QAAQ,CAAC,EAAE,cAAc,GAAG,MAAM,CA6BnF;AAED,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,aAAa,EACrB,QAAQ,EAAE,cAAc,GACvB,MAAM,GAAG;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,CAW/B;AAoBD,KAAK,QAAQ,GAAG,OAAO,CAAC,cAAc,EAAE;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC,CAAC;AAE9D,wBAAgB,aAAa,CAC3B,SAAS,EAAE,cAAc,EACzB,SAAS,EAAE,WAAW,EACtB,QAAQ,EAAE,QAAQ,EAClB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,GAChB,MAAM,CAoCR;AAgDD,wBAAgB,SAAS,CACvB,SAAS,EAAE,cAAc,EACzB,KAAK,EAAE,SAAS,WAAW,EAAE,EAC7B,QAAQ,CAAC,EAAE,OAAO,GACjB,OAAO,CA+BT;AA0ED,wBAAgB,MAAM,CACpB,KAAK,EAAE,WAAW,EAClB,SAAS,EAAE,cAAc,EACzB,OAAO,GAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAM,GAC7C,OAAO,CAoBT;AAED,wBAAgB,WAAW,CACzB,SAAS,EAAE,cAAc,EACzB,KAAK,EAAE,SAAS,WAAW,EAAE,EAC7B,YAAY,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,OAAO,EAC7C,KAAK,EAAE,OAAO,GACb,SAAS,WAAW,EAAE,CA2BxB"}
|
package/dist/replica.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { equalValue, parse } from '@agentshouse/mdmodel';
|
|
2
2
|
import { immutable, landing } from './change.js';
|
|
3
|
-
import { collectionOf, unreadable, validateCollection, } from './collection.js';
|
|
3
|
+
import { changedCleanly, collectionOf, unreadable, validateCollection, } from './collection.js';
|
|
4
4
|
import { acceptedBinaries, overlay, overlayChanged, sameLayerText, } from './overlay.js';
|
|
5
5
|
import { providerRewritten } from './save.js';
|
|
6
|
+
import { drafted, patched, settled, shared } from './shared.js';
|
|
6
7
|
export function compositionOf(record) {
|
|
7
8
|
return {
|
|
8
9
|
model: record.model,
|
|
@@ -11,23 +12,48 @@ export function compositionOf(record) {
|
|
|
11
12
|
: { roots: record.typedSelection.roots, model: record.selectionModel },
|
|
12
13
|
};
|
|
13
14
|
}
|
|
15
|
+
function held(record) {
|
|
16
|
+
const documents = shared(record.documents);
|
|
17
|
+
const binaries = shared(record.binaries);
|
|
18
|
+
const revisions = shared(record.revisions);
|
|
19
|
+
const fileIds = shared(record.fileIds);
|
|
20
|
+
const changes = shared(record.changes);
|
|
21
|
+
const written = shared(record.written);
|
|
22
|
+
return documents === record.documents &&
|
|
23
|
+
binaries === record.binaries &&
|
|
24
|
+
revisions === record.revisions &&
|
|
25
|
+
fileIds === record.fileIds &&
|
|
26
|
+
changes === record.changes &&
|
|
27
|
+
written === record.written
|
|
28
|
+
? record
|
|
29
|
+
: { ...record, documents, binaries, revisions, fileIds, changes, written };
|
|
30
|
+
}
|
|
14
31
|
export function confirmedOf(record, previous) {
|
|
32
|
+
const kept = held(record);
|
|
15
33
|
return {
|
|
16
|
-
record,
|
|
17
|
-
collection: collectionOf(
|
|
34
|
+
record: kept,
|
|
35
|
+
collection: collectionOf(kept.documents, compositionOf(kept), previous?.collection),
|
|
18
36
|
};
|
|
19
37
|
}
|
|
20
38
|
export function sameMembership(record, other) {
|
|
21
39
|
return (JSON.stringify(record.typedSelection?.roots ?? null) ===
|
|
22
40
|
JSON.stringify(other.typedSelection?.roots ?? null));
|
|
23
41
|
}
|
|
24
|
-
|
|
42
|
+
function cleanly(record, previous) {
|
|
43
|
+
if (previous === undefined)
|
|
44
|
+
return false;
|
|
45
|
+
const before = previous.record;
|
|
46
|
+
return changedCleanly({ text: record.documents, binaries: record.binaries }, { text: before.documents, binaries: before.binaries, composition: compositionOf(before) }, compositionOf(record));
|
|
47
|
+
}
|
|
48
|
+
export function readStaged(staged, previous) {
|
|
49
|
+
const record = held(staged);
|
|
25
50
|
const textChanged = previous === undefined || !sameLayerText(record, previous.record);
|
|
26
51
|
const modeled = record.model.status !== 'unavailable' || record.selectionModel.status !== 'unavailable';
|
|
27
52
|
if (modeled &&
|
|
28
53
|
(textChanged ||
|
|
29
54
|
record.model !== previous?.record.model ||
|
|
30
|
-
record.selectionModel !== previous?.record.selectionModel)
|
|
55
|
+
record.selectionModel !== previous?.record.selectionModel) &&
|
|
56
|
+
!cleanly(record, previous)) {
|
|
31
57
|
const verdict = validateCollection(record.documents, Object.keys(record.binaries), compositionOf(record));
|
|
32
58
|
if (verdict.verdict === 'refuse' && verdict.rule !== 'model-unavailable') {
|
|
33
59
|
return { kind: 'refused', refusal: verdict };
|
|
@@ -54,7 +80,7 @@ export function readReclassified(record, previous) {
|
|
|
54
80
|
: { kind: 'refused', refusal: verdict };
|
|
55
81
|
}
|
|
56
82
|
function returnedBinaries(held, submitted, accepted) {
|
|
57
|
-
const binaries =
|
|
83
|
+
const binaries = drafted(held);
|
|
58
84
|
for (const change of submitted.changes) {
|
|
59
85
|
if (change.kind !== 'move')
|
|
60
86
|
continue;
|
|
@@ -67,17 +93,22 @@ function returnedBinaries(held, submitted, accepted) {
|
|
|
67
93
|
Object.assign(binaries, acceptedBinaries(accepted.binaryFiles ?? {}));
|
|
68
94
|
for (const path of accepted.removals)
|
|
69
95
|
delete binaries[path];
|
|
70
|
-
return binaries;
|
|
96
|
+
return settled(binaries);
|
|
71
97
|
}
|
|
72
98
|
export function applyReturned(confirmed, submitted, accepted, roomVersion, writtenAt) {
|
|
73
|
-
const { documents, revisions, changes, removals } = accepted;
|
|
74
|
-
const nextDocuments =
|
|
75
|
-
const nextRevisions =
|
|
76
|
-
const
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
99
|
+
const { documents, revisions, fileIds, changes, removals } = accepted;
|
|
100
|
+
const nextDocuments = drafted(confirmed.record.documents);
|
|
101
|
+
const nextRevisions = drafted(confirmed.record.revisions);
|
|
102
|
+
const nextFileIds = drafted(confirmed.record.fileIds);
|
|
103
|
+
const nextChanges = drafted(confirmed.record.changes);
|
|
104
|
+
const nextWritten = drafted(confirmed.record.written);
|
|
105
|
+
Object.assign(nextDocuments, documents);
|
|
106
|
+
Object.assign(nextRevisions, revisions);
|
|
107
|
+
for (const path of Object.keys({ ...documents, ...revisions }))
|
|
108
|
+
delete nextFileIds[path];
|
|
109
|
+
Object.assign(nextFileIds, fileIds);
|
|
110
|
+
for (const path of Object.keys(documents))
|
|
111
|
+
nextWritten[path] = writtenAt;
|
|
81
112
|
for (const [path, revision] of Object.entries(revisions)) {
|
|
82
113
|
if (confirmed.record.revisions[path] !== revision)
|
|
83
114
|
delete nextChanges[path];
|
|
@@ -86,16 +117,18 @@ export function applyReturned(confirmed, submitted, accepted, roomVersion, writt
|
|
|
86
117
|
for (const path of removals) {
|
|
87
118
|
delete nextDocuments[path];
|
|
88
119
|
delete nextRevisions[path];
|
|
120
|
+
delete nextFileIds[path];
|
|
89
121
|
delete nextChanges[path];
|
|
90
122
|
delete nextWritten[path];
|
|
91
123
|
}
|
|
92
124
|
return readStaged({
|
|
93
125
|
...confirmed.record,
|
|
94
126
|
roomVersion,
|
|
95
|
-
documents: nextDocuments,
|
|
96
|
-
revisions: nextRevisions,
|
|
97
|
-
|
|
98
|
-
|
|
127
|
+
documents: settled(nextDocuments),
|
|
128
|
+
revisions: settled(nextRevisions),
|
|
129
|
+
fileIds: settled(nextFileIds),
|
|
130
|
+
changes: settled(nextChanges),
|
|
131
|
+
written: settled(nextWritten),
|
|
99
132
|
binaries: returnedBinaries(confirmed.record.binaries, submitted, accepted),
|
|
100
133
|
}, confirmed);
|
|
101
134
|
}
|
|
@@ -148,6 +181,7 @@ export function replicaOf(confirmed, queue, previous) {
|
|
|
148
181
|
documents: confirmed.record.documents,
|
|
149
182
|
binaries: confirmed.record.binaries,
|
|
150
183
|
revisions: confirmed.record.revisions,
|
|
184
|
+
fileIds: confirmed.record.fileIds,
|
|
151
185
|
changes: confirmed.record.changes,
|
|
152
186
|
collection: confirmed.collection,
|
|
153
187
|
},
|
|
@@ -238,7 +272,10 @@ function effects(change) {
|
|
|
238
272
|
return [{ kind: 'absent', path }];
|
|
239
273
|
}
|
|
240
274
|
export function landed(batch, confirmed, current = {}) {
|
|
241
|
-
const layer = {
|
|
275
|
+
const layer = {
|
|
276
|
+
...confirmed.record,
|
|
277
|
+
documents: patched(confirmed.record.documents, Object.entries(current)),
|
|
278
|
+
};
|
|
242
279
|
return batch.changes.every((change, index) => {
|
|
243
280
|
if (change.kind === 'replace' || (change.kind === 'create' && 'content' in change)) {
|
|
244
281
|
const at = landing(batch.changes, index, change.path);
|
package/dist/room-draft.d.ts
CHANGED
|
@@ -87,7 +87,7 @@ type ChangedUnderneath = {
|
|
|
87
87
|
readonly file?: string | null;
|
|
88
88
|
};
|
|
89
89
|
export type ReturnReason = ProviderRefusal & {
|
|
90
|
-
readonly kind: 'conflicted' | 'rejected' | 'expired' | 'withdrawn'
|
|
90
|
+
readonly kind: Open<'conflicted' | 'rejected' | 'expired' | 'withdrawn'>;
|
|
91
91
|
};
|
|
92
92
|
export declare function returnedBy(kind: 'expired' | 'withdrawn'): ReturnReason;
|
|
93
93
|
export type RoomDraft = {
|
|
@@ -130,6 +130,18 @@ export declare function underneath(parts: HeldParts, path: string, visible: Visi
|
|
|
130
130
|
export declare function heldFile(blob: Blob, base: string | null): Promise<HeldFile>;
|
|
131
131
|
export declare function binaryBase(visible: VisibleLayer | undefined, path: string): string | null;
|
|
132
132
|
export declare function changedParts(path: string, report: ChangedUnderneath): readonly ChangedPart[];
|
|
133
|
+
export type TextParts = {
|
|
134
|
+
readonly fields?: Readonly<Record<string, {
|
|
135
|
+
readonly value: unknown;
|
|
136
|
+
}>>;
|
|
137
|
+
readonly sections?: Readonly<Record<string, {
|
|
138
|
+
readonly value: string;
|
|
139
|
+
}>>;
|
|
140
|
+
readonly preamble?: {
|
|
141
|
+
readonly value: string;
|
|
142
|
+
};
|
|
143
|
+
};
|
|
144
|
+
export declare function partsAfter(markdown: string, parts: TextParts): string;
|
|
133
145
|
export declare function returnedInto(existing: HeldParts | undefined, returned: HeldParts): HeldParts;
|
|
134
146
|
export declare function moveTarget(move: {
|
|
135
147
|
readonly to: string;
|