@hydranium/protocol 1.0.0-next.79 → 1.0.0-next.85
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/lib/client/data-port.d.ts +1 -1
- package/lib/data/data-server-protocol.d.ts +1 -1
- package/lib/errors.d.ts +3 -5
- package/lib/errors.d.ts.map +1 -1
- package/lib/errors.js +3 -5
- package/lib/errors.js.map +1 -1
- package/lib/model-server.d.ts +4 -3
- package/lib/model-server.d.ts.map +1 -1
- package/lib/model-service/args.d.ts +14 -13
- package/lib/model-service/args.d.ts.map +1 -1
- package/lib/model-service/based-on.d.ts +55 -0
- package/lib/model-service/based-on.d.ts.map +1 -0
- package/lib/model-service/based-on.js +34 -0
- package/lib/model-service/based-on.js.map +1 -0
- package/lib/model-service/index.d.ts +1 -0
- package/lib/model-service/index.d.ts.map +1 -1
- package/lib/model-service/index.js +1 -0
- package/lib/model-service/index.js.map +1 -1
- package/lib/transfer-document.d.ts +15 -5
- package/lib/transfer-document.d.ts.map +1 -1
- package/lib/transfer-document.js +14 -1
- package/lib/transfer-document.js.map +1 -1
- package/package.json +1 -1
- package/src/client/data-port.ts +1 -1
- package/src/data/data-server-protocol.ts +1 -1
- package/src/errors.ts +3 -5
- package/src/model-server.ts +4 -3
- package/src/model-service/args.ts +15 -13
- package/src/model-service/based-on.ts +60 -0
- package/src/model-service/index.ts +1 -0
- package/src/transfer-document.ts +22 -6
|
@@ -24,7 +24,7 @@ import type { ResolvedMessage } from '../messages/primitives';
|
|
|
24
24
|
* `DataServerProtocol` surface, so wrapping it would re-derive the framework's
|
|
25
25
|
* pass-throughs in a second place and lose the `as const satisfies keyof`
|
|
26
26
|
* method allowlists, which cannot drift. Everything a form or a tree actually
|
|
27
|
-
* does — the wire contract, the open/watch/update/close sequence, `
|
|
27
|
+
* does — the wire contract, the open/watch/update/close sequence, `basedOn`
|
|
28
28
|
* conflict handling, echo filtering by `sourceClientId` — is host-invariant and
|
|
29
29
|
* lives above this interface. What varies between hosts is exactly the four
|
|
30
30
|
* members below.
|
|
@@ -37,7 +37,7 @@ export interface DocumentServerProtocol<TTransfer extends TransferElement, TDiag
|
|
|
37
37
|
* (so concurrent editors share one built document) and returns the
|
|
38
38
|
* document at the server's configured target phase — the same shape
|
|
39
39
|
* {@link getModelDocument} returns, except that `version` is taken from
|
|
40
|
-
* the text-document store so the caller's first `
|
|
40
|
+
* the text-document store so the caller's first `basedOn` write
|
|
41
41
|
* cannot self-conflict. Idempotent in registration terms: opening an
|
|
42
42
|
* already-open document refreshes the client registration. Note it does
|
|
43
43
|
* NOT avoid a rebuild — a second client attaching triggers
|
package/lib/errors.d.ts
CHANGED
|
@@ -52,11 +52,9 @@ export interface ConflictErrorData extends HydraniumMessageData {
|
|
|
52
52
|
* `err.data` (the instance is reconstructed as a generic
|
|
53
53
|
* `ResponseError`, so subclass getters / fields do not survive).
|
|
54
54
|
*
|
|
55
|
-
* Detection is
|
|
56
|
-
* `TransferUpdateArgs` / `TransferSaveArgs`;
|
|
57
|
-
*
|
|
58
|
-
* posture, so headless / CLI / batch tooling with no meaningful based-on
|
|
59
|
-
* version can opt out explicitly.
|
|
55
|
+
* Detection is driven by the required `basedOn` field on
|
|
56
|
+
* `TransferUpdateArgs` / `TransferSaveArgs`; a caller with no meaningful
|
|
57
|
+
* based-on version passes `'anything'` and gets no gating.
|
|
60
58
|
*
|
|
61
59
|
* Three reasonable adopter recovery strategies:
|
|
62
60
|
*
|
package/lib/errors.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAiB,KAAK,oBAAoB,EAAe,MAAM,uBAAuB,CAAC;AAE9F;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,+IAG9B,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,mBAAmB,OAAO,CAAC;AAExC;;;GAGG;AACH,MAAM,WAAW,iBAAkB,SAAQ,oBAAoB;IAC5D,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,wDAAwD;IACxD,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,2EAA2E;IAC3E,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CACjC;AAED
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAiB,KAAK,oBAAoB,EAAe,MAAM,uBAAuB,CAAC;AAE9F;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,+IAG9B,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,mBAAmB,OAAO,CAAC;AAExC;;;GAGG;AACH,MAAM,WAAW,iBAAkB,SAAQ,oBAAoB;IAC5D,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,wDAAwD;IACxD,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,2EAA2E;IAC3E,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CACjC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,qBAAa,aAAc,SAAQ,aAAa,CAAC,iBAAiB,CAAC;gBACpD,GAAG,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM;IAgBvE,IAAI,GAAG,IAAI,MAAM,CAEhB;IAED;;;;;;;OAOG;IACH,IAAI,eAAe,IAAI,MAAM,CAE5B;IAED,iGAAiG;IACjG,IAAI,aAAa,IAAI,MAAM,CAE1B;CACH;AAOD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,aAAa,CAYtE"}
|
package/lib/errors.js
CHANGED
|
@@ -45,11 +45,9 @@ exports.CONFLICT_ERROR_CODE = 1001;
|
|
|
45
45
|
* `err.data` (the instance is reconstructed as a generic
|
|
46
46
|
* `ResponseError`, so subclass getters / fields do not survive).
|
|
47
47
|
*
|
|
48
|
-
* Detection is
|
|
49
|
-
* `TransferUpdateArgs` / `TransferSaveArgs`;
|
|
50
|
-
*
|
|
51
|
-
* posture, so headless / CLI / batch tooling with no meaningful based-on
|
|
52
|
-
* version can opt out explicitly.
|
|
48
|
+
* Detection is driven by the required `basedOn` field on
|
|
49
|
+
* `TransferUpdateArgs` / `TransferSaveArgs`; a caller with no meaningful
|
|
50
|
+
* based-on version passes `'anything'` and gets no gating.
|
|
53
51
|
*
|
|
54
52
|
* Three reasonable adopter recovery strategies:
|
|
55
53
|
*
|
package/lib/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;;
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;;AAiIlF,0CAYC;AA3ID,mDAA+C;AAC/C,sDAA8F;AAE9F;;;;;;;GAOG;AACU,QAAA,kBAAkB,GAAG,IAAA,0BAAa,EAC5C,uCAAuC,EACvC,0FAA0F,CAC5F,CAAC;AAEF;;;;;;;;GAQG;AACU,QAAA,mBAAmB,GAAG,IAAI,CAAC;AAcxC;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAa,aAAc,SAAQ,8BAAgC;IAChE,YAAY,GAAW,EAAE,eAAuB,EAAE,aAAqB;QACpE,MAAM,MAAM,GAAG,EAAE,GAAG,EAAE,eAAe,EAAE,aAAa,EAAE,CAAC;QACvD,uEAAuE;QACvE,wEAAwE;QACxE,mEAAmE;QACnE,KAAK,CAAC,2BAAmB,EAAE,0BAAkB,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,GAAG,MAAM,EAAE,GAAG,IAAA,wBAAW,EAAC,0BAAkB,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;QACzH,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;QAC5B,iEAAiE;QACjE,0EAA0E;QAC1E,qEAAqE;QACrE,gEAAgE;QAChE,yEAAyE;QACzE,SAAS;QACT,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC;IACxD,CAAC;IAED,IAAI,GAAG;QACJ,OAAO,IAAI,CAAC,IAAK,CAAC,GAAG,CAAC;IACzB,CAAC;IAED;;;;;;;OAOG;IACH,IAAI,eAAe;QAChB,OAAO,IAAI,CAAC,IAAK,CAAC,eAAe,CAAC;IACrC,CAAC;IAED,iGAAiG;IACjG,IAAI,aAAa;QACd,OAAO,IAAI,CAAC,IAAK,CAAC,aAAa,CAAC;IACnC,CAAC;CACH;AArCD,sCAqCC;AAED;;mCAEmC;AACnC,MAAM,6BAA6B,GAAG,yBAAyB,CAAC;AAEhE;;;;;;;;;;;;;;GAcG;AACH,SAAgB,eAAe,CAAC,KAAc;IAC3C,IAAI,CAAC,CAAC,KAAK,YAAY,KAAK,CAAC,EAAE,CAAC;QAC7B,OAAO,KAAK,CAAC;IAChB,CAAC;IACD,IAAI,KAAK,CAAC,IAAI,KAAK,eAAe,EAAE,CAAC;QAClC,OAAO,IAAI,CAAC;IACf,CAAC;IACD,MAAM,IAAI,GAAI,KAAyC,CAAC,IAAI,CAAC;IAC7D,IAAI,IAAI,KAAK,2BAAmB,EAAE,CAAC;QAChC,OAAO,IAAI,CAAC;IACf,CAAC;IACD,OAAO,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,6BAA6B,CAAC,CAAC;AACrG,CAAC"}
|
package/lib/model-server.d.ts
CHANGED
|
@@ -329,9 +329,10 @@ export interface FindNextNameArgs {
|
|
|
329
329
|
*/
|
|
330
330
|
uri: string;
|
|
331
331
|
/**
|
|
332
|
-
* The AST `$type` of the element being named. Collisions are
|
|
333
|
-
* among elements of that
|
|
334
|
-
*
|
|
332
|
+
* The AST `$type` of the element being named. Collisions are looked for
|
|
333
|
+
* among elements of that type and of any subtype of it, so a supertype
|
|
334
|
+
* names a uniqueness scope its concrete types share; the returned name may
|
|
335
|
+
* still be taken by an element outside that hierarchy.
|
|
335
336
|
*/
|
|
336
337
|
type: string;
|
|
337
338
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-server.d.ts","sourceRoot":"","sources":["../src/model-server.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"model-server.d.ts","sourceRoot":"","sources":["../src/model-server.ts"],"names":[],"mappings":"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"}
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
* `./model-server.ts` re-exports them, so an import from either path
|
|
18
18
|
* resolves.
|
|
19
19
|
*/
|
|
20
|
+
import type { BasedOn } from './based-on';
|
|
20
21
|
/** Identifies a client-document binding. Every facade operation carries these fields. */
|
|
21
22
|
export interface TransferClientArgs {
|
|
22
23
|
/** Document URI. */
|
|
@@ -36,15 +37,16 @@ export interface TransferUpdateArgs<T> extends TransferClientArgs {
|
|
|
36
37
|
/** Structured model root or its serialised textual form. */
|
|
37
38
|
model: T | string;
|
|
38
39
|
/**
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
40
|
+
* What this update was authored against. A `SnapshotVersion` is compared
|
|
41
|
+
* against the server's current text-document version for `uri` and throws
|
|
42
|
+
* `ConflictError` on mismatch; `'anything'` writes unconditionally.
|
|
43
|
+
*
|
|
44
|
+
* **Required so that an ungated write is a decision rather than an
|
|
45
|
+
* omission.** An optional gate is indistinguishable from a forgotten one at
|
|
46
|
+
* the call site, and a file of twenty writes hides the one that lost the
|
|
47
|
+
* field. Nothing else here can see that, since the defect is an absence.
|
|
46
48
|
*/
|
|
47
|
-
|
|
49
|
+
basedOn: BasedOn;
|
|
48
50
|
}
|
|
49
51
|
/**
|
|
50
52
|
* Persist a document to disk via the in-process facade. Same `model`
|
|
@@ -54,11 +56,10 @@ export interface TransferSaveArgs<T> extends TransferClientArgs {
|
|
|
54
56
|
/** Structured model root or its serialised textual form. */
|
|
55
57
|
model: T | string;
|
|
56
58
|
/**
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
* same `ConflictError` site.
|
|
59
|
+
* Same semantics and same requirement as {@link TransferUpdateArgs.basedOn}.
|
|
60
|
+
* `save` delegates the gating check to its inner `update`, so this field
|
|
61
|
+
* threads through to the same `ConflictError` site.
|
|
61
62
|
*/
|
|
62
|
-
|
|
63
|
+
basedOn: BasedOn;
|
|
63
64
|
}
|
|
64
65
|
//# sourceMappingURL=args.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../../src/model-service/args.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF;;;;;;;;;;GAUG;AAEH,yFAAyF;AACzF,MAAM,WAAW,kBAAkB;IAChC,oBAAoB;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,+DAA+D;IAC/D,QAAQ,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,kBAAkB,CAAC,CAAC,CAAE,SAAQ,kBAAkB;IAC9D,4DAA4D;IAC5D,KAAK,EAAE,CAAC,GAAG,MAAM,CAAC;IAClB
|
|
1
|
+
{"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../../src/model-service/args.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C,yFAAyF;AACzF,MAAM,WAAW,kBAAkB;IAChC,oBAAoB;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,+DAA+D;IAC/D,QAAQ,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,kBAAkB,CAAC,CAAC,CAAE,SAAQ,kBAAkB;IAC9D,4DAA4D;IAC5D,KAAK,EAAE,CAAC,GAAG,MAAM,CAAC;IAClB;;;;;;;;;OASG;IACH,OAAO,EAAE,OAAO,CAAC;CACnB;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB,CAAC,CAAC,CAAE,SAAQ,kBAAkB;IAC5D,4DAA4D;IAC5D,KAAK,EAAE,CAAC,GAAG,MAAM,CAAC;IAClB;;;;OAIG;IACH,OAAO,EAAE,OAAO,CAAC;CACnB"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* Copyright (c) 2026 EclipseSource and others.
|
|
3
|
+
*
|
|
4
|
+
* This program and the accompanying materials are made available under the
|
|
5
|
+
* terms of the MIT License which is available in the project root.
|
|
6
|
+
*
|
|
7
|
+
* SPDX-License-Identifier: MIT
|
|
8
|
+
********************************************************************************/
|
|
9
|
+
declare const snapshotMarker: unique symbol;
|
|
10
|
+
/**
|
|
11
|
+
* A text-document version that came out of a SNAPSHOT read: a document
|
|
12
|
+
* envelope's `version`, which cannot move once the envelope exists.
|
|
13
|
+
*
|
|
14
|
+
* A plain number at runtime, usable anywhere a number is, and it travels the
|
|
15
|
+
* wire as one. The marker exists only so the compiler can tell it apart from a
|
|
16
|
+
* version read off a LIVE document, which is the same number type and is the
|
|
17
|
+
* defect the conflict gate exists to prevent: read at write time it is whatever
|
|
18
|
+
* the server is at now, which is the number the gate is about to compare it
|
|
19
|
+
* against, so the gate passes unconditionally and a concurrent edit is
|
|
20
|
+
* overwritten with nothing logged.
|
|
21
|
+
*/
|
|
22
|
+
export type SnapshotVersion = number & {
|
|
23
|
+
readonly [snapshotMarker]: true;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* What a write declares it was based on: a version from a snapshot read, or
|
|
27
|
+
* `'anything'`.
|
|
28
|
+
*
|
|
29
|
+
* `'anything'` is a precondition that always holds — the write accepts whatever
|
|
30
|
+
* the server currently has, and therefore overwrites it. It is the honest
|
|
31
|
+
* answer wherever the write was authored against no particular server version,
|
|
32
|
+
* and a lie anywhere a reader handed the writer a document. The field carrying
|
|
33
|
+
* it is required, so an ungated write is a word someone chose rather than a
|
|
34
|
+
* field someone forgot.
|
|
35
|
+
*/
|
|
36
|
+
export type BasedOn = SnapshotVersion | 'anything';
|
|
37
|
+
/**
|
|
38
|
+
* Whether `basedOn` names a version, and so arms the gate.
|
|
39
|
+
*
|
|
40
|
+
* Branch on this rather than on `basedOn !== 'anything'`, which reads as "not
|
|
41
|
+
* based on anything" — the opposite of what the branch tests.
|
|
42
|
+
*/
|
|
43
|
+
export declare function isSnapshotVersion(basedOn: BasedOn): basedOn is SnapshotVersion;
|
|
44
|
+
/**
|
|
45
|
+
* Mark a version as having come from a snapshot read.
|
|
46
|
+
*
|
|
47
|
+
* **For the envelope constructors, not for callers.** Every door that builds a
|
|
48
|
+
* document envelope applies it on the way in, so anything a read returns
|
|
49
|
+
* already carries it and a writer never needs this. A caller reaching for it is
|
|
50
|
+
* asserting a provenance the compiler was about to deny — the read-late defect
|
|
51
|
+
* written out where a reviewer can see it.
|
|
52
|
+
*/
|
|
53
|
+
export declare function asSnapshotVersion(version: number): SnapshotVersion;
|
|
54
|
+
export {};
|
|
55
|
+
//# sourceMappingURL=based-on.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"based-on.d.ts","sourceRoot":"","sources":["../../src/model-service/based-on.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,CAAC,MAAM,cAAc,EAAE,OAAO,MAAM,CAAC;AAE5C;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG;IAAE,QAAQ,CAAC,CAAC,cAAc,CAAC,EAAE,IAAI,CAAA;CAAE,CAAC;AAE3E;;;;;;;;;;GAUG;AACH,MAAM,MAAM,OAAO,GAAG,eAAe,GAAG,UAAU,CAAC;AAEnD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,IAAI,eAAe,CAE9E;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,eAAe,CAElE"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/********************************************************************************
|
|
3
|
+
* Copyright (c) 2026 EclipseSource and others.
|
|
4
|
+
*
|
|
5
|
+
* This program and the accompanying materials are made available under the
|
|
6
|
+
* terms of the MIT License which is available in the project root.
|
|
7
|
+
*
|
|
8
|
+
* SPDX-License-Identifier: MIT
|
|
9
|
+
********************************************************************************/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.isSnapshotVersion = isSnapshotVersion;
|
|
12
|
+
exports.asSnapshotVersion = asSnapshotVersion;
|
|
13
|
+
/**
|
|
14
|
+
* Whether `basedOn` names a version, and so arms the gate.
|
|
15
|
+
*
|
|
16
|
+
* Branch on this rather than on `basedOn !== 'anything'`, which reads as "not
|
|
17
|
+
* based on anything" — the opposite of what the branch tests.
|
|
18
|
+
*/
|
|
19
|
+
function isSnapshotVersion(basedOn) {
|
|
20
|
+
return typeof basedOn === 'number';
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Mark a version as having come from a snapshot read.
|
|
24
|
+
*
|
|
25
|
+
* **For the envelope constructors, not for callers.** Every door that builds a
|
|
26
|
+
* document envelope applies it on the way in, so anything a read returns
|
|
27
|
+
* already carries it and a writer never needs this. A caller reaching for it is
|
|
28
|
+
* asserting a provenance the compiler was about to deny — the read-late defect
|
|
29
|
+
* written out where a reviewer can see it.
|
|
30
|
+
*/
|
|
31
|
+
function asSnapshotVersion(version) {
|
|
32
|
+
return version;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=based-on.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"based-on.js","sourceRoot":"","sources":["../../src/model-service/based-on.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;AAqClF,8CAEC;AAWD,8CAEC;AArBD;;;;;GAKG;AACH,SAAgB,iBAAiB,CAAC,OAAgB;IAC/C,OAAO,OAAO,OAAO,KAAK,QAAQ,CAAC;AACtC,CAAC;AAED;;;;;;;;GAQG;AACH,SAAgB,iBAAiB,CAAC,OAAe;IAC9C,OAAO,OAA0B,CAAC;AACrC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/model-service/index.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAOlF,cAAc,QAAQ,CAAC;AACvB,cAAc,uBAAuB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/model-service/index.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAOlF,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC;AAC3B,cAAc,uBAAuB,CAAC"}
|
|
@@ -27,5 +27,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
27
27
|
// argument types so both the framework facade and the data-server wire
|
|
28
28
|
// protocol can structurally agree on the lifecycle shape.
|
|
29
29
|
__exportStar(require("./args"), exports);
|
|
30
|
+
__exportStar(require("./based-on"), exports);
|
|
30
31
|
__exportStar(require("./reference-candidate"), exports);
|
|
31
32
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/model-service/index.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;;;;;;;;;;;;;;;AAElF,wEAAwE;AACxE,mEAAmE;AACnE,uEAAuE;AACvE,0DAA0D;AAE1D,yCAAuB;AACvB,wDAAsC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/model-service/index.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;;;;;;;;;;;;;;;AAElF,wEAAwE;AACxE,mEAAmE;AACnE,uEAAuE;AACvE,0DAA0D;AAE1D,yCAAuB;AACvB,6CAA2B;AAC3B,wDAAsC"}
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
********************************************************************************/
|
|
9
9
|
import type { TransferDiagnostic } from './transfer-diagnostic';
|
|
10
10
|
import type { TransferElement } from './transfer-element';
|
|
11
|
+
import { type SnapshotVersion } from './model-service/based-on';
|
|
11
12
|
/**
|
|
12
13
|
* Wire envelope exchanged between the model-server's data-server head and
|
|
13
14
|
* its clients. Carries a transfer-shaped root — never an AST root — plus
|
|
@@ -25,14 +26,14 @@ export interface TransferDocument<TTransfer extends TransferElement, TDiagnostic
|
|
|
25
26
|
uri: string;
|
|
26
27
|
/**
|
|
27
28
|
* The document version this snapshot was taken at — sourced from the
|
|
28
|
-
* server's text-document version counter.
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
29
|
+
* server's text-document version counter. A caller that mutates the document
|
|
30
|
+
* subsequently sends this straight back as `TransferUpdateArgs.basedOn` (or
|
|
31
|
+
* `TransferSaveArgs.basedOn`), and the server rejects a stale-based update
|
|
32
|
+
* with `ConflictError`.
|
|
32
33
|
*
|
|
33
34
|
* See `@hydranium/protocol#errors` for the conflict-detection contract.
|
|
34
35
|
*/
|
|
35
|
-
version:
|
|
36
|
+
version: SnapshotVersion;
|
|
36
37
|
/**
|
|
37
38
|
* Absent when the document does not exist — the server answers an unknown URI
|
|
38
39
|
* with a shaped envelope rather than an error, so absence is an ordinary
|
|
@@ -62,6 +63,15 @@ export declare namespace TransferDocument {
|
|
|
62
63
|
* with it.
|
|
63
64
|
*/
|
|
64
65
|
function assertLoaded<TTransfer extends TransferElement, TDiagnostic = TransferDiagnostic>(document: TransferDocument<TTransfer, TDiagnostic>): LoadedTransferDocument<TTransfer, TDiagnostic>;
|
|
66
|
+
/**
|
|
67
|
+
* The envelope for a document the server does not have — `root` absent, and
|
|
68
|
+
* the version a read of a URI the store never saw reports.
|
|
69
|
+
*
|
|
70
|
+
* Exists so the absent branch is built the same way the present one is: both
|
|
71
|
+
* doors mark the version as coming from a read, and neither asks a caller to
|
|
72
|
+
* do it.
|
|
73
|
+
*/
|
|
74
|
+
function absent<TTransfer extends TransferElement, TDiagnostic = TransferDiagnostic>(uri: string, diagnostics?: TDiagnostic[]): TransferDocument<TTransfer, TDiagnostic>;
|
|
65
75
|
/**
|
|
66
76
|
* Construct a {@link TransferDocument} envelope. `diagnostics` defaults
|
|
67
77
|
* to `[]` so test fixtures, fake protocol implementations, and the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transfer-document.d.ts","sourceRoot":"","sources":["../src/transfer-document.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"transfer-document.d.ts","sourceRoot":"","sources":["../src/transfer-document.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAqB,KAAK,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAEnF;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,gBAAgB,CAAC,SAAS,SAAS,eAAe,EAAE,WAAW,GAAG,kBAAkB;IAClG,GAAG,EAAE,MAAM,CAAC;IACZ;;;;;;;;OAQG;IACH,OAAO,EAAE,eAAe,CAAC;IACzB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,WAAW,EAAE,WAAW,EAAE,CAAC;CAC7B;AAED;;;GAGG;AACH,MAAM,MAAM,sBAAsB,CAAC,SAAS,SAAS,eAAe,EAAE,WAAW,GAAG,kBAAkB,IAAI,gBAAgB,CACvH,SAAS,EACT,WAAW,CACb,GAAG;IACD,IAAI,EAAE,SAAS,CAAC;CAClB,CAAC;AAEF,yBAAiB,gBAAgB,CAAC;IAC/B;;;OAGG;IACH,SAAgB,QAAQ,CAAC,SAAS,SAAS,eAAe,EAAE,WAAW,GAAG,kBAAkB,EACzF,QAAQ,EAAE,gBAAgB,CAAC,SAAS,EAAE,WAAW,CAAC,GAClD,QAAQ,IAAI,sBAAsB,CAAC,SAAS,EAAE,WAAW,CAAC,CAE5D;IAED;;;;;OAKG;IACH,SAAgB,YAAY,CAAC,SAAS,SAAS,eAAe,EAAE,WAAW,GAAG,kBAAkB,EAC7F,QAAQ,EAAE,gBAAgB,CAAC,SAAS,EAAE,WAAW,CAAC,GAClD,sBAAsB,CAAC,SAAS,EAAE,WAAW,CAAC,CAKhD;IAED;;;;;;;OAOG;IACH,SAAgB,MAAM,CAAC,SAAS,SAAS,eAAe,EAAE,WAAW,GAAG,kBAAkB,EACvF,GAAG,EAAE,MAAM,EACX,WAAW,GAAE,WAAW,EAAO,GAC/B,gBAAgB,CAAC,SAAS,EAAE,WAAW,CAAC,CAE1C;IAED;;;;;OAKG;IACH,SAAgB,MAAM,CAAC,SAAS,SAAS,eAAe,EAAE,WAAW,GAAG,kBAAkB,EACvF,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,SAAS,EACf,WAAW,GAAE,WAAW,EAAO,GAC/B,gBAAgB,CAAC,SAAS,EAAE,WAAW,CAAC,CAE1C;CACH"}
|
package/lib/transfer-document.js
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
********************************************************************************/
|
|
10
10
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
11
|
exports.TransferDocument = void 0;
|
|
12
|
+
const based_on_1 = require("./model-service/based-on");
|
|
12
13
|
var TransferDocument;
|
|
13
14
|
(function (TransferDocument) {
|
|
14
15
|
/**
|
|
@@ -32,6 +33,18 @@ var TransferDocument;
|
|
|
32
33
|
return document;
|
|
33
34
|
}
|
|
34
35
|
TransferDocument.assertLoaded = assertLoaded;
|
|
36
|
+
/**
|
|
37
|
+
* The envelope for a document the server does not have — `root` absent, and
|
|
38
|
+
* the version a read of a URI the store never saw reports.
|
|
39
|
+
*
|
|
40
|
+
* Exists so the absent branch is built the same way the present one is: both
|
|
41
|
+
* doors mark the version as coming from a read, and neither asks a caller to
|
|
42
|
+
* do it.
|
|
43
|
+
*/
|
|
44
|
+
function absent(uri, diagnostics = []) {
|
|
45
|
+
return { uri, version: (0, based_on_1.asSnapshotVersion)(0), root: undefined, diagnostics };
|
|
46
|
+
}
|
|
47
|
+
TransferDocument.absent = absent;
|
|
35
48
|
/**
|
|
36
49
|
* Construct a {@link TransferDocument} envelope. `diagnostics` defaults
|
|
37
50
|
* to `[]` so test fixtures, fake protocol implementations, and the
|
|
@@ -39,7 +52,7 @@ var TransferDocument;
|
|
|
39
52
|
* at every call site.
|
|
40
53
|
*/
|
|
41
54
|
function create(uri, version, root, diagnostics = []) {
|
|
42
|
-
return { uri, version, root, diagnostics };
|
|
55
|
+
return { uri, version: (0, based_on_1.asSnapshotVersion)(version), root, diagnostics };
|
|
43
56
|
}
|
|
44
57
|
TransferDocument.create = create;
|
|
45
58
|
})(TransferDocument || (exports.TransferDocument = TransferDocument = {}));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transfer-document.js","sourceRoot":"","sources":["../src/transfer-document.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;;
|
|
1
|
+
{"version":3,"file":"transfer-document.js","sourceRoot":"","sources":["../src/transfer-document.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;;AAIlF,uDAAmF;AAgDnF,IAAiB,gBAAgB,CAuDhC;AAvDD,WAAiB,gBAAgB;IAC9B;;;OAGG;IACH,SAAgB,QAAQ,CACrB,QAAkD;QAElD,OAAO,QAAQ,CAAC,IAAI,KAAK,SAAS,CAAC;IACtC,CAAC;IAJe,yBAAQ,WAIvB,CAAA;IAED;;;;;OAKG;IACH,SAAgB,YAAY,CACzB,QAAkD;QAElD,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CAAC,kBAAkB,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC;QACrD,CAAC;QACD,OAAO,QAAQ,CAAC;IACnB,CAAC;IAPe,6BAAY,eAO3B,CAAA;IAED;;;;;;;OAOG;IACH,SAAgB,MAAM,CACnB,GAAW,EACX,cAA6B,EAAE;QAE/B,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,IAAA,4BAAiB,EAAC,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC;IAC/E,CAAC;IALe,uBAAM,SAKrB,CAAA;IAED;;;;;OAKG;IACH,SAAgB,MAAM,CACnB,GAAW,EACX,OAAe,EACf,IAAe,EACf,cAA6B,EAAE;QAE/B,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,IAAA,4BAAiB,EAAC,OAAO,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;IAC1E,CAAC;IAPe,uBAAM,SAOrB,CAAA;AACJ,CAAC,EAvDgB,gBAAgB,gCAAhB,gBAAgB,QAuDhC"}
|
package/package.json
CHANGED
package/src/client/data-port.ts
CHANGED
|
@@ -26,7 +26,7 @@ import type { ResolvedMessage } from '../messages/primitives';
|
|
|
26
26
|
* `DataServerProtocol` surface, so wrapping it would re-derive the framework's
|
|
27
27
|
* pass-throughs in a second place and lose the `as const satisfies keyof`
|
|
28
28
|
* method allowlists, which cannot drift. Everything a form or a tree actually
|
|
29
|
-
* does — the wire contract, the open/watch/update/close sequence, `
|
|
29
|
+
* does — the wire contract, the open/watch/update/close sequence, `basedOn`
|
|
30
30
|
* conflict handling, echo filtering by `sourceClientId` — is host-invariant and
|
|
31
31
|
* lives above this interface. What varies between hosts is exactly the four
|
|
32
32
|
* members below.
|
|
@@ -51,7 +51,7 @@ export interface DocumentServerProtocol<TTransfer extends TransferElement, TDiag
|
|
|
51
51
|
* (so concurrent editors share one built document) and returns the
|
|
52
52
|
* document at the server's configured target phase — the same shape
|
|
53
53
|
* {@link getModelDocument} returns, except that `version` is taken from
|
|
54
|
-
* the text-document store so the caller's first `
|
|
54
|
+
* the text-document store so the caller's first `basedOn` write
|
|
55
55
|
* cannot self-conflict. Idempotent in registration terms: opening an
|
|
56
56
|
* already-open document refreshes the client registration. Note it does
|
|
57
57
|
* NOT avoid a rebuild — a second client attaching triggers
|
package/src/errors.ts
CHANGED
|
@@ -60,11 +60,9 @@ export interface ConflictErrorData extends HydraniumMessageData {
|
|
|
60
60
|
* `err.data` (the instance is reconstructed as a generic
|
|
61
61
|
* `ResponseError`, so subclass getters / fields do not survive).
|
|
62
62
|
*
|
|
63
|
-
* Detection is
|
|
64
|
-
* `TransferUpdateArgs` / `TransferSaveArgs`;
|
|
65
|
-
*
|
|
66
|
-
* posture, so headless / CLI / batch tooling with no meaningful based-on
|
|
67
|
-
* version can opt out explicitly.
|
|
63
|
+
* Detection is driven by the required `basedOn` field on
|
|
64
|
+
* `TransferUpdateArgs` / `TransferSaveArgs`; a caller with no meaningful
|
|
65
|
+
* based-on version passes `'anything'` and gets no gating.
|
|
68
66
|
*
|
|
69
67
|
* Three reasonable adopter recovery strategies:
|
|
70
68
|
*
|
package/src/model-server.ts
CHANGED
|
@@ -457,9 +457,10 @@ export interface FindNextNameArgs {
|
|
|
457
457
|
*/
|
|
458
458
|
uri: string;
|
|
459
459
|
/**
|
|
460
|
-
* The AST `$type` of the element being named. Collisions are
|
|
461
|
-
* among elements of that
|
|
462
|
-
*
|
|
460
|
+
* The AST `$type` of the element being named. Collisions are looked for
|
|
461
|
+
* among elements of that type and of any subtype of it, so a supertype
|
|
462
|
+
* names a uniqueness scope its concrete types share; the returned name may
|
|
463
|
+
* still be taken by an element outside that hierarchy.
|
|
463
464
|
*/
|
|
464
465
|
type: string;
|
|
465
466
|
/**
|
|
@@ -19,6 +19,8 @@
|
|
|
19
19
|
* resolves.
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
|
+
import type { BasedOn } from './based-on';
|
|
23
|
+
|
|
22
24
|
/** Identifies a client-document binding. Every facade operation carries these fields. */
|
|
23
25
|
export interface TransferClientArgs {
|
|
24
26
|
/** Document URI. */
|
|
@@ -39,15 +41,16 @@ export interface TransferUpdateArgs<T> extends TransferClientArgs {
|
|
|
39
41
|
/** Structured model root or its serialised textual form. */
|
|
40
42
|
model: T | string;
|
|
41
43
|
/**
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
44
|
+
* What this update was authored against. A `SnapshotVersion` is compared
|
|
45
|
+
* against the server's current text-document version for `uri` and throws
|
|
46
|
+
* `ConflictError` on mismatch; `'anything'` writes unconditionally.
|
|
47
|
+
*
|
|
48
|
+
* **Required so that an ungated write is a decision rather than an
|
|
49
|
+
* omission.** An optional gate is indistinguishable from a forgotten one at
|
|
50
|
+
* the call site, and a file of twenty writes hides the one that lost the
|
|
51
|
+
* field. Nothing else here can see that, since the defect is an absence.
|
|
49
52
|
*/
|
|
50
|
-
|
|
53
|
+
basedOn: BasedOn;
|
|
51
54
|
}
|
|
52
55
|
|
|
53
56
|
/**
|
|
@@ -58,10 +61,9 @@ export interface TransferSaveArgs<T> extends TransferClientArgs {
|
|
|
58
61
|
/** Structured model root or its serialised textual form. */
|
|
59
62
|
model: T | string;
|
|
60
63
|
/**
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
* same `ConflictError` site.
|
|
64
|
+
* Same semantics and same requirement as {@link TransferUpdateArgs.basedOn}.
|
|
65
|
+
* `save` delegates the gating check to its inner `update`, so this field
|
|
66
|
+
* threads through to the same `ConflictError` site.
|
|
65
67
|
*/
|
|
66
|
-
|
|
68
|
+
basedOn: BasedOn;
|
|
67
69
|
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* Copyright (c) 2026 EclipseSource and others.
|
|
3
|
+
*
|
|
4
|
+
* This program and the accompanying materials are made available under the
|
|
5
|
+
* terms of the MIT License which is available in the project root.
|
|
6
|
+
*
|
|
7
|
+
* SPDX-License-Identifier: MIT
|
|
8
|
+
********************************************************************************/
|
|
9
|
+
|
|
10
|
+
declare const snapshotMarker: unique symbol;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* A text-document version that came out of a SNAPSHOT read: a document
|
|
14
|
+
* envelope's `version`, which cannot move once the envelope exists.
|
|
15
|
+
*
|
|
16
|
+
* A plain number at runtime, usable anywhere a number is, and it travels the
|
|
17
|
+
* wire as one. The marker exists only so the compiler can tell it apart from a
|
|
18
|
+
* version read off a LIVE document, which is the same number type and is the
|
|
19
|
+
* defect the conflict gate exists to prevent: read at write time it is whatever
|
|
20
|
+
* the server is at now, which is the number the gate is about to compare it
|
|
21
|
+
* against, so the gate passes unconditionally and a concurrent edit is
|
|
22
|
+
* overwritten with nothing logged.
|
|
23
|
+
*/
|
|
24
|
+
export type SnapshotVersion = number & { readonly [snapshotMarker]: true };
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* What a write declares it was based on: a version from a snapshot read, or
|
|
28
|
+
* `'anything'`.
|
|
29
|
+
*
|
|
30
|
+
* `'anything'` is a precondition that always holds — the write accepts whatever
|
|
31
|
+
* the server currently has, and therefore overwrites it. It is the honest
|
|
32
|
+
* answer wherever the write was authored against no particular server version,
|
|
33
|
+
* and a lie anywhere a reader handed the writer a document. The field carrying
|
|
34
|
+
* it is required, so an ungated write is a word someone chose rather than a
|
|
35
|
+
* field someone forgot.
|
|
36
|
+
*/
|
|
37
|
+
export type BasedOn = SnapshotVersion | 'anything';
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Whether `basedOn` names a version, and so arms the gate.
|
|
41
|
+
*
|
|
42
|
+
* Branch on this rather than on `basedOn !== 'anything'`, which reads as "not
|
|
43
|
+
* based on anything" — the opposite of what the branch tests.
|
|
44
|
+
*/
|
|
45
|
+
export function isSnapshotVersion(basedOn: BasedOn): basedOn is SnapshotVersion {
|
|
46
|
+
return typeof basedOn === 'number';
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Mark a version as having come from a snapshot read.
|
|
51
|
+
*
|
|
52
|
+
* **For the envelope constructors, not for callers.** Every door that builds a
|
|
53
|
+
* document envelope applies it on the way in, so anything a read returns
|
|
54
|
+
* already carries it and a writer never needs this. A caller reaching for it is
|
|
55
|
+
* asserting a provenance the compiler was about to deny — the read-late defect
|
|
56
|
+
* written out where a reviewer can see it.
|
|
57
|
+
*/
|
|
58
|
+
export function asSnapshotVersion(version: number): SnapshotVersion {
|
|
59
|
+
return version as SnapshotVersion;
|
|
60
|
+
}
|
package/src/transfer-document.ts
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
import type { TransferDiagnostic } from './transfer-diagnostic';
|
|
11
11
|
import type { TransferElement } from './transfer-element';
|
|
12
|
+
import { asSnapshotVersion, type SnapshotVersion } from './model-service/based-on';
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* Wire envelope exchanged between the model-server's data-server head and
|
|
@@ -27,14 +28,14 @@ export interface TransferDocument<TTransfer extends TransferElement, TDiagnostic
|
|
|
27
28
|
uri: string;
|
|
28
29
|
/**
|
|
29
30
|
* The document version this snapshot was taken at — sourced from the
|
|
30
|
-
* server's text-document version counter.
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
31
|
+
* server's text-document version counter. A caller that mutates the document
|
|
32
|
+
* subsequently sends this straight back as `TransferUpdateArgs.basedOn` (or
|
|
33
|
+
* `TransferSaveArgs.basedOn`), and the server rejects a stale-based update
|
|
34
|
+
* with `ConflictError`.
|
|
34
35
|
*
|
|
35
36
|
* See `@hydranium/protocol#errors` for the conflict-detection contract.
|
|
36
37
|
*/
|
|
37
|
-
version:
|
|
38
|
+
version: SnapshotVersion;
|
|
38
39
|
/**
|
|
39
40
|
* Absent when the document does not exist — the server answers an unknown URI
|
|
40
41
|
* with a shaped envelope rather than an error, so absence is an ordinary
|
|
@@ -82,6 +83,21 @@ export namespace TransferDocument {
|
|
|
82
83
|
return document;
|
|
83
84
|
}
|
|
84
85
|
|
|
86
|
+
/**
|
|
87
|
+
* The envelope for a document the server does not have — `root` absent, and
|
|
88
|
+
* the version a read of a URI the store never saw reports.
|
|
89
|
+
*
|
|
90
|
+
* Exists so the absent branch is built the same way the present one is: both
|
|
91
|
+
* doors mark the version as coming from a read, and neither asks a caller to
|
|
92
|
+
* do it.
|
|
93
|
+
*/
|
|
94
|
+
export function absent<TTransfer extends TransferElement, TDiagnostic = TransferDiagnostic>(
|
|
95
|
+
uri: string,
|
|
96
|
+
diagnostics: TDiagnostic[] = []
|
|
97
|
+
): TransferDocument<TTransfer, TDiagnostic> {
|
|
98
|
+
return { uri, version: asSnapshotVersion(0), root: undefined, diagnostics };
|
|
99
|
+
}
|
|
100
|
+
|
|
85
101
|
/**
|
|
86
102
|
* Construct a {@link TransferDocument} envelope. `diagnostics` defaults
|
|
87
103
|
* to `[]` so test fixtures, fake protocol implementations, and the
|
|
@@ -94,6 +110,6 @@ export namespace TransferDocument {
|
|
|
94
110
|
root: TTransfer,
|
|
95
111
|
diagnostics: TDiagnostic[] = []
|
|
96
112
|
): TransferDocument<TTransfer, TDiagnostic> {
|
|
97
|
-
return { uri, version, root, diagnostics };
|
|
113
|
+
return { uri, version: asSnapshotVersion(version), root, diagnostics };
|
|
98
114
|
}
|
|
99
115
|
}
|