document-model 5.1.0 → 5.2.0-dev.2
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/dist/src/core/actions.d.ts +10 -2
- package/dist/src/core/actions.d.ts.map +1 -1
- package/dist/src/core/actions.js +8 -5
- package/dist/src/core/actions.js.map +1 -1
- package/dist/src/core/documents.d.ts +21 -3
- package/dist/src/core/documents.d.ts.map +1 -1
- package/dist/src/core/documents.js +73 -9
- package/dist/src/core/documents.js.map +1 -1
- package/dist/src/core/errors.d.ts.map +1 -1
- package/dist/src/core/errors.js +1 -2
- package/dist/src/core/errors.js.map +1 -1
- package/dist/src/core/files.js +4 -13
- package/dist/src/core/files.js.map +1 -1
- package/dist/src/core/header.d.ts +7 -11
- package/dist/src/core/header.d.ts.map +1 -1
- package/dist/src/core/header.js +45 -54
- package/dist/src/core/header.js.map +1 -1
- package/dist/src/core/operations.d.ts +16 -0
- package/dist/src/core/operations.d.ts.map +1 -1
- package/dist/src/core/operations.js +38 -0
- package/dist/src/core/operations.js.map +1 -1
- package/dist/src/core/ph-types.d.ts +64 -8
- package/dist/src/core/ph-types.d.ts.map +1 -1
- package/dist/src/core/ph-types.js.map +1 -1
- package/dist/src/core/reducer.d.ts +5 -3
- package/dist/src/core/reducer.d.ts.map +1 -1
- package/dist/src/core/reducer.js +61 -22
- package/dist/src/core/reducer.js.map +1 -1
- package/dist/src/core/schemas.d.ts +51 -107
- package/dist/src/core/schemas.d.ts.map +1 -1
- package/dist/src/core/schemas.js.map +1 -1
- package/dist/src/core/state.js +1 -1
- package/dist/src/core/state.js.map +1 -1
- package/dist/src/core/types.d.ts +39 -7
- package/dist/src/core/types.d.ts.map +1 -1
- package/dist/src/core/utils.d.ts +4 -0
- package/dist/src/core/utils.d.ts.map +1 -1
- package/dist/src/core/utils.js +8 -0
- package/dist/src/core/utils.js.map +1 -1
- package/dist/src/document-model/actions.d.ts.map +1 -1
- package/dist/src/document-model/actions.js +3 -1
- package/dist/src/document-model/actions.js.map +1 -1
- package/dist/src/document-model/document-schema.d.ts +32 -226
- package/dist/src/document-model/document-schema.d.ts.map +1 -1
- package/dist/src/document-model/reducers.d.ts.map +1 -1
- package/dist/src/document-model/reducers.js +5 -0
- package/dist/src/document-model/reducers.js.map +1 -1
- package/dist/src/document-model/schemas.d.ts +132 -392
- package/dist/src/document-model/schemas.d.ts.map +1 -1
- package/dist/src/document-model/schemas.js +1 -1
- package/dist/src/document-model/schemas.js.map +1 -1
- package/dist/src/document-model/types.d.ts +2 -0
- package/dist/src/document-model/types.d.ts.map +1 -1
- package/dist/src/document-model/validation.d.ts +25 -0
- package/dist/src/document-model/validation.d.ts.map +1 -1
- package/dist/src/document-model/validation.js +64 -3
- package/dist/src/document-model/validation.js.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/index.js.map +1 -1
- package/dist/test/document/crypto.test.js +28 -27
- package/dist/test/document/crypto.test.js.map +1 -1
- package/dist/test/document/event-vs-command.test.js +4 -1
- package/dist/test/document/event-vs-command.test.js.map +1 -1
- package/dist/test/document/operation-id.test.js +8 -45
- package/dist/test/document/operation-id.test.js.map +1 -1
- package/dist/test/document/reducer.test.js +4 -1
- package/dist/test/document/reducer.test.js.map +1 -1
- package/dist/test/document/skip-operations.test.js +4 -4
- package/dist/test/document/skip-operations.test.js.map +1 -1
- package/dist/test/document/undo-redo-v2.test.d.ts +2 -0
- package/dist/test/document/undo-redo-v2.test.d.ts.map +1 -0
- package/dist/test/document/undo-redo-v2.test.js +207 -0
- package/dist/test/document/undo-redo-v2.test.js.map +1 -0
- package/dist/test/document/undo-redo.test.js +23 -8
- package/dist/test/document/undo-redo.test.js.map +1 -1
- package/dist/test/document/utils.test.js +37 -22
- package/dist/test/document/utils.test.js.map +1 -1
- package/dist/test/document-helpers/groupOperationsByScope.test.js +9 -5
- package/dist/test/document-helpers/groupOperationsByScope.test.js.map +1 -1
- package/dist/test/document-helpers/removeExistingOperations.test.js +46 -31
- package/dist/test/document-helpers/removeExistingOperations.test.js.map +1 -1
- package/dist/test/document-helpers/skipHeaderOperations.test.js +7 -2
- package/dist/test/document-helpers/skipHeaderOperations.test.js.map +1 -1
- package/dist/test/document-helpers/utils.d.ts +6 -0
- package/dist/test/document-helpers/utils.d.ts.map +1 -1
- package/dist/test/document-helpers/utils.js +34 -0
- package/dist/test/document-helpers/utils.js.map +1 -1
- package/dist/test/document-model/replay.test.js +5 -5
- package/dist/test/document-model/replay.test.js.map +1 -1
- package/dist/test/document-model/skip-operations.test.js +1 -1
- package/dist/test/document-model/skip-operations.test.js.map +1 -1
- package/dist/test/document-model/validation.test.js +197 -1
- package/dist/test/document-model/validation.test.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
package/dist/src/core/header.js
CHANGED
|
@@ -4,56 +4,49 @@ import { generateId } from "./utils.js";
|
|
|
4
4
|
*/
|
|
5
5
|
const generateStablePayload = (parameters) => `${parameters.documentType}:${parameters.createdAtUtcIso}:${parameters.nonce}`;
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
7
|
+
* Creates a verification-only signer from a public key.
|
|
8
|
+
* This signer can only verify signatures, not sign data.
|
|
9
|
+
*
|
|
10
|
+
* @param pubKey - The public key to use for verification.
|
|
11
|
+
* @returns An ISigner that can only verify signatures.
|
|
8
12
|
*/
|
|
9
|
-
export
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
try {
|
|
38
|
-
isValid = await subtleCrypto.verify("Ed25519", this.publicCryptoKey, new Uint8Array(signature), new Uint8Array(data));
|
|
39
|
-
}
|
|
40
|
-
catch (error) {
|
|
41
|
-
throw new Error("invalid signature");
|
|
42
|
-
}
|
|
43
|
-
if (!isValid) {
|
|
44
|
-
throw new Error("invalid signature");
|
|
45
|
-
}
|
|
46
|
-
}
|
|
13
|
+
export function createVerificationSigner(pubKey) {
|
|
14
|
+
let cachedCryptoKey;
|
|
15
|
+
return {
|
|
16
|
+
async publicKey() {
|
|
17
|
+
return pubKey;
|
|
18
|
+
},
|
|
19
|
+
async sign(_data) {
|
|
20
|
+
throw new Error("verification-only signer cannot sign data");
|
|
21
|
+
},
|
|
22
|
+
async signAction(_action, _abortSignal) {
|
|
23
|
+
throw new Error("verification-only signer cannot sign actions");
|
|
24
|
+
},
|
|
25
|
+
async verify(data, signature) {
|
|
26
|
+
if (!cachedCryptoKey) {
|
|
27
|
+
cachedCryptoKey = await crypto.subtle.importKey("jwk", pubKey, { name: "ECDSA", namedCurve: "P-256" }, true, ["verify"]);
|
|
28
|
+
}
|
|
29
|
+
let isValid;
|
|
30
|
+
try {
|
|
31
|
+
isValid = await crypto.subtle.verify({ name: "ECDSA", hash: "SHA-256" }, cachedCryptoKey, new Uint8Array(signature), new Uint8Array(data));
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
throw new Error("invalid signature");
|
|
35
|
+
}
|
|
36
|
+
if (!isValid) {
|
|
37
|
+
throw new Error("invalid signature");
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
};
|
|
47
41
|
}
|
|
48
42
|
/**
|
|
49
|
-
* Creates a signer from a header.
|
|
43
|
+
* Creates a verification-only signer from a header.
|
|
50
44
|
*
|
|
51
45
|
* @param header - The header to create a signer from.
|
|
52
|
-
*
|
|
53
|
-
* @returns A signer for the header.
|
|
46
|
+
* @returns A signer that can verify the header's signature.
|
|
54
47
|
*/
|
|
55
|
-
const createSignerFromHeader =
|
|
56
|
-
return
|
|
48
|
+
const createSignerFromHeader = (header) => {
|
|
49
|
+
return createVerificationSigner(header.sig.publicKey);
|
|
57
50
|
};
|
|
58
51
|
/**
|
|
59
52
|
* Signs a header. Generally, this is not called directly, but rather through
|
|
@@ -99,8 +92,8 @@ export const verify = async (parameters, signature, signer) => {
|
|
|
99
92
|
* Validates a header signature.
|
|
100
93
|
*/
|
|
101
94
|
export const validateHeader = async (header) => {
|
|
102
|
-
const signer =
|
|
103
|
-
return
|
|
95
|
+
const signer = createSignerFromHeader(header);
|
|
96
|
+
return verify({
|
|
104
97
|
documentType: header.documentType,
|
|
105
98
|
createdAtUtcIso: header.createdAtUtcIso,
|
|
106
99
|
nonce: header.sig.nonce,
|
|
@@ -159,19 +152,17 @@ export const createSignedHeader = async (unsignedHeader, documentType, signer) =
|
|
|
159
152
|
documentType,
|
|
160
153
|
createdAtUtcIso: unsignedHeader.createdAtUtcIso,
|
|
161
154
|
// mutable fields
|
|
162
|
-
slug:
|
|
163
|
-
name:
|
|
164
|
-
branch:
|
|
165
|
-
revision:
|
|
166
|
-
document: 0,
|
|
167
|
-
},
|
|
155
|
+
slug: unsignedHeader.slug,
|
|
156
|
+
name: unsignedHeader.name,
|
|
157
|
+
branch: unsignedHeader.branch,
|
|
158
|
+
revision: unsignedHeader.revision,
|
|
168
159
|
lastModifiedAtUtcIso: unsignedHeader.lastModifiedAtUtcIso,
|
|
169
|
-
meta:
|
|
160
|
+
meta: unsignedHeader.meta,
|
|
170
161
|
};
|
|
171
162
|
};
|
|
172
163
|
/**
|
|
173
164
|
* Creates a signed header for a document. The document header requires a signer
|
|
174
|
-
* as the document id is a
|
|
165
|
+
* as the document id is a cryptographic signature.
|
|
175
166
|
*
|
|
176
167
|
* @param documentType - The type of the document.
|
|
177
168
|
* @param signer - The signer of the document.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"header.js","sourceRoot":"","sources":["../../../src/core/header.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExC;;GAEG;AACH,MAAM,qBAAqB,GAAG,CAAC,UAA6B,EAAU,EAAE,CACtE,GAAG,UAAU,CAAC,YAAY,IAAI,UAAU,CAAC,eAAe,IAAI,UAAU,CAAC,KAAK,EAAE,CAAC;AAEjF
|
|
1
|
+
{"version":3,"file":"header.js","sourceRoot":"","sources":["../../../src/core/header.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,6 +13,9 @@ export declare function setNameOperation<TDocument extends PHDocument>(document:
|
|
|
13
13
|
[scope: string]: number;
|
|
14
14
|
};
|
|
15
15
|
lastModifiedAtUtcIso: string;
|
|
16
|
+
protocolVersions?: {
|
|
17
|
+
[key: string]: number;
|
|
18
|
+
};
|
|
16
19
|
meta?: import("./ph-types.js").PHDocumentMeta;
|
|
17
20
|
};
|
|
18
21
|
};
|
|
@@ -22,6 +25,19 @@ export declare function undoOperation<TDocument extends PHDocument>(document: TD
|
|
|
22
25
|
skip: number;
|
|
23
26
|
reuseLastOperationIndex: boolean;
|
|
24
27
|
};
|
|
28
|
+
/**
|
|
29
|
+
* V2 of undoOperation for protocol version 2+.
|
|
30
|
+
* Key differences from undoOperation:
|
|
31
|
+
* - Never reuses operation index (always increments)
|
|
32
|
+
* - Always sets skip=1 (consecutive NOOPs are handled during rebuild/GC)
|
|
33
|
+
* - No complex skip calculation - simpler model where each UNDO is independent
|
|
34
|
+
*/
|
|
35
|
+
export declare function undoOperationV2<TDocument extends PHDocument>(document: TDocument, action: Action, skip: number): {
|
|
36
|
+
document: TDocument;
|
|
37
|
+
action: Action;
|
|
38
|
+
skip: number;
|
|
39
|
+
reuseLastOperationIndex: false;
|
|
40
|
+
};
|
|
25
41
|
export declare function redoOperation<TDocument extends PHDocument>(document: TDocument, action: Action, skip: number): {
|
|
26
42
|
document: TDocument;
|
|
27
43
|
action: Action;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"operations.d.ts","sourceRoot":"","sources":["../../../src/core/operations.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACrE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAGvD,wBAAgB,gBAAgB,CAAC,SAAS,SAAS,UAAU,EAC3D,QAAQ,EAAE,SAAS,EACnB,IAAI,EAAE,MAAM
|
|
1
|
+
{"version":3,"file":"operations.d.ts","sourceRoot":"","sources":["../../../src/core/operations.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACrE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAGvD,wBAAgB,gBAAgB,CAAC,SAAS,SAAS,UAAU,EAC3D,QAAQ,EAAE,SAAS,EACnB,IAAI,EAAE,MAAM;;;;;;;;;;;;;;;;;;EAGb;AAED,wBAAgB,aAAa,CAAC,SAAS,SAAS,UAAU,EACxD,QAAQ,EAAE,SAAS,EACnB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,GACX;IACD,QAAQ,EAAE,SAAS,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,uBAAuB,EAAE,OAAO,CAAC;CAClC,CA8CA;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,SAAS,SAAS,UAAU,EAC1D,QAAQ,EAAE,SAAS,EACnB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,GACX;IACD,QAAQ,EAAE,SAAS,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,uBAAuB,EAAE,KAAK,CAAC;CAChC,CAuCA;AAED,wBAAgB,aAAa,CAAC,SAAS,SAAS,UAAU,EACxD,QAAQ,EAAE,SAAS,EACnB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,GACX;IACD,QAAQ,EAAE,SAAS,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,uBAAuB,EAAE,OAAO,CAAC;CAClC,CA8CA;AAED,wBAAgB,kBAAkB,CAAC,MAAM,SAAS,WAAW,EAC3D,QAAQ,EAAE,UAAU,CAAC,MAAM,CAAC,EAC5B,MAAM,EAAE,oBAAoB,GAC3B,UAAU,CAAC,MAAM,CAAC,CAMpB"}
|
|
@@ -41,6 +41,44 @@ export function undoOperation(document, action, skip) {
|
|
|
41
41
|
}
|
|
42
42
|
});
|
|
43
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* V2 of undoOperation for protocol version 2+.
|
|
46
|
+
* Key differences from undoOperation:
|
|
47
|
+
* - Never reuses operation index (always increments)
|
|
48
|
+
* - Always sets skip=1 (consecutive NOOPs are handled during rebuild/GC)
|
|
49
|
+
* - No complex skip calculation - simpler model where each UNDO is independent
|
|
50
|
+
*/
|
|
51
|
+
export function undoOperationV2(document, action, skip) {
|
|
52
|
+
const { scope } = action;
|
|
53
|
+
const defaultResult = {
|
|
54
|
+
document,
|
|
55
|
+
action,
|
|
56
|
+
skip,
|
|
57
|
+
reuseLastOperationIndex: false,
|
|
58
|
+
};
|
|
59
|
+
return create(defaultResult, (draft) => {
|
|
60
|
+
const operations = document.operations[scope] || [];
|
|
61
|
+
const sortedOperations = sortOperations([...operations]);
|
|
62
|
+
// Count non-NOOP operations to determine if there's anything to undo
|
|
63
|
+
const nonNoopOps = sortedOperations.filter((op) => op.action.type !== "NOOP");
|
|
64
|
+
// Count consecutive NOOPs at the end (these represent pending undos)
|
|
65
|
+
let noopChainLength = 0;
|
|
66
|
+
for (let i = sortedOperations.length - 1; i >= 0; i--) {
|
|
67
|
+
if (sortedOperations[i].action.type === "NOOP") {
|
|
68
|
+
noopChainLength++;
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// Check if we can undo: need more non-NOOP ops than the current NOOP chain
|
|
75
|
+
if (nonNoopOps.length <= noopChainLength) {
|
|
76
|
+
throw new Error(`Cannot undo: no more operations to undo in scope history`);
|
|
77
|
+
}
|
|
78
|
+
draft.action = noop(scope);
|
|
79
|
+
draft.skip = 1;
|
|
80
|
+
});
|
|
81
|
+
}
|
|
44
82
|
export function redoOperation(document, action, skip) {
|
|
45
83
|
const { scope, input } = action;
|
|
46
84
|
const defaultResult = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"operations.js","sourceRoot":"","sources":["../../../src/core/operations.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"operations.js","sourceRoot":"","sources":["../../../src/core/operations.ts"],"names":[],"mappings":"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"}
|
|
@@ -62,6 +62,17 @@ export type PHDocumentHeader = {
|
|
|
62
62
|
* The timestamp of the last change in the document, in UTC ISO format.
|
|
63
63
|
**/
|
|
64
64
|
lastModifiedAtUtcIso: string;
|
|
65
|
+
/**
|
|
66
|
+
* This is a map from protocol name to version. A protocol can be any set of
|
|
67
|
+
* rules that are applied to the document.
|
|
68
|
+
*
|
|
69
|
+
* Examples of protocols include:
|
|
70
|
+
*
|
|
71
|
+
* - "base-reducer"
|
|
72
|
+
*/
|
|
73
|
+
protocolVersions?: {
|
|
74
|
+
[key: string]: number;
|
|
75
|
+
};
|
|
65
76
|
/** Meta information about the document. */
|
|
66
77
|
meta?: PHDocumentMeta;
|
|
67
78
|
};
|
|
@@ -91,8 +102,12 @@ export type HashConfig = {
|
|
|
91
102
|
* The document state of the document.
|
|
92
103
|
*/
|
|
93
104
|
export type PHDocumentState = {
|
|
94
|
-
/**
|
|
95
|
-
|
|
105
|
+
/**
|
|
106
|
+
* The current document model schema version of the document. This is used
|
|
107
|
+
* with the UPGRADE_DOCUMENT operation to specify the DocumentModelModule
|
|
108
|
+
* version to use for reducer execution.
|
|
109
|
+
*/
|
|
110
|
+
version: number;
|
|
96
111
|
/** Hash configuration for operation state verification */
|
|
97
112
|
hash: HashConfig;
|
|
98
113
|
/** True if and only if the document has been deleted */
|
|
@@ -191,25 +206,46 @@ export type Action = {
|
|
|
191
206
|
* @remarks
|
|
192
207
|
* Wraps an action with an index, to be added to the operations history of a Document.
|
|
193
208
|
* The `index` field is used to keep all operations in order and enable replaying the
|
|
194
|
-
* document's history from the beginning.
|
|
209
|
+
* document's history from the beginning. Note that indices and skips are relative to
|
|
210
|
+
* a specific reactor. Example below:
|
|
211
|
+
*
|
|
212
|
+
* For (index, skip, ts, action)
|
|
213
|
+
* A - [(0, 0, 1, "A0"), (1, 0, 2, "A1")]
|
|
214
|
+
* B - [(0, 0, 0, "B0"), (1, 0, 3, "B1")]
|
|
215
|
+
* ...
|
|
216
|
+
* B gets A's Operations Scenario:
|
|
217
|
+
* B' - [(0, 0, 0, "B0"), (1, 0, 3, "B1"), (2, 1, 1, "A0"), (3, 0, 2, "A1"), (4, 0, 3, "B1")]
|
|
218
|
+
* Then A needs to end up with:
|
|
219
|
+
* A' - [(0, 0, 1, "A0"), (1, 0, 2, "A1"), (2, 2, 0, "B0"), (3, 0, 1, "A0"), (4, 0, 2, "A1"), (5, 0, 3, "B1")]
|
|
220
|
+
* So that both A and B end up with the stream of actions (action):
|
|
221
|
+
* [("B0"), ("A0"), ("A1"), ("B1")]
|
|
195
222
|
*
|
|
196
223
|
* @typeParam A - The type of the action.
|
|
197
224
|
*/
|
|
198
225
|
export type Operation = {
|
|
199
|
-
/**
|
|
226
|
+
/**
|
|
227
|
+
* This is a stable id, derived from various document and action properties
|
|
228
|
+
* in deriveOperationId().
|
|
229
|
+
*
|
|
230
|
+
* It _cannot_ be an arbitrary string.
|
|
231
|
+
*
|
|
232
|
+
* It it also not unique per operation, as reshuffled operations will keep'
|
|
233
|
+
* the same id they had before they were reshuffled. This means that the
|
|
234
|
+
* IOperationStore may have multiple operations with the same operation id.
|
|
235
|
+
**/
|
|
236
|
+
id: string;
|
|
237
|
+
/** Position of the operation in the history. This is relative to a specific reactor -- they may not all agree on this value. */
|
|
200
238
|
index: number;
|
|
239
|
+
/** The number of operations skipped with this Operation. This is relative to a specific reactor -- they may not all agree on this value. */
|
|
240
|
+
skip: number;
|
|
201
241
|
/** Timestamp of when the operation was added */
|
|
202
242
|
timestampUtcMs: string;
|
|
203
243
|
/** Hash of the resulting document data after the operation */
|
|
204
244
|
hash: string;
|
|
205
|
-
/** The number of operations skipped with this Operation */
|
|
206
|
-
skip: number;
|
|
207
245
|
/** Error message for a failed action */
|
|
208
246
|
error?: string;
|
|
209
247
|
/** The resulting state after the operation */
|
|
210
248
|
resultingState?: string;
|
|
211
|
-
/** Unique operation id. This is distinct from the action id and can be undefined and assigned later. */
|
|
212
|
-
id?: string;
|
|
213
249
|
/**
|
|
214
250
|
* The action that was applied to the document to produce this operation.
|
|
215
251
|
*/
|
|
@@ -256,4 +292,24 @@ export type PHDocument<TState extends PHBaseState = PHBaseState> = {
|
|
|
256
292
|
*/
|
|
257
293
|
clipboard: Operation[];
|
|
258
294
|
};
|
|
295
|
+
/** Upgrade reducer transforms a document from one version to another */
|
|
296
|
+
export type UpgradeReducer<TFrom extends PHBaseState, TTo extends PHBaseState> = (document: PHDocument<TFrom>, action: Action) => PHDocument<TTo>;
|
|
297
|
+
type ModelVersion = number;
|
|
298
|
+
/** Metadata about a version transition */
|
|
299
|
+
export type UpgradeTransition = {
|
|
300
|
+
toVersion: ModelVersion;
|
|
301
|
+
upgradeReducer: UpgradeReducer<any, any>;
|
|
302
|
+
description?: string;
|
|
303
|
+
};
|
|
304
|
+
type TupleMember<T extends readonly unknown[]> = T[number];
|
|
305
|
+
/** Manifest declaring all supported versions and upgrade paths */
|
|
306
|
+
export type UpgradeManifest<TVersions extends readonly number[]> = {
|
|
307
|
+
documentType: string;
|
|
308
|
+
latestVersion: TupleMember<TVersions>;
|
|
309
|
+
supportedVersions: TVersions;
|
|
310
|
+
upgrades: {
|
|
311
|
+
[V in Exclude<TupleMember<TVersions>, 1> as `v${V}`]: UpgradeTransition;
|
|
312
|
+
};
|
|
313
|
+
};
|
|
314
|
+
export {};
|
|
259
315
|
//# sourceMappingURL=ph-types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ph-types.d.ts","sourceRoot":"","sources":["../../../src/core/ph-types.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD;;GAEG;AACH,MAAM,MAAM,uBAAuB,GAAG;IACpC;;QAEI;IACJ,SAAS,EAAE,UAAU,CAAC;IAEtB,0EAA0E;IAC1E,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,2CAA2C;AAC3C,MAAM,MAAM,cAAc,GAAG;IAC3B,6CAA6C;IAC7C,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B;;;;QAII;IACJ,EAAE,EAAE,MAAM,CAAC;IAEX;;;;QAII;IACJ,GAAG,EAAE,uBAAuB,CAAC;IAE7B;;;;;QAKI;IACJ,YAAY,EAAE,MAAM,CAAC;IAErB;;;;;QAKI;IACJ,eAAe,EAAE,MAAM,CAAC;IAExB,gCAAgC;IAChC,IAAI,EAAE,MAAM,CAAC;IAEb,gCAAgC;IAChC,IAAI,EAAE,MAAM,CAAC;IAEb,mCAAmC;IACnC,MAAM,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,QAAQ,EAAE;QACR,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;KACzB,CAAC;IAEF;;QAEI;IACJ,oBAAoB,EAAE,MAAM,CAAC;IAE7B,2CAA2C;IAC3C,IAAI,CAAC,EAAE,cAAc,CAAC;CACvB,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,WAAW,GAAG,EAAE,CAAC;AAG7B,eAAO,MAAM,mBAAmB,SAAS,CAAC;AAC1C,eAAO,MAAM,qBAAqB,WAAW,CAAC;AAC9C,eAAO,MAAM,qBAAqB,WAAW,CAAC;AAG9C,eAAO,MAAM,oBAAoB,WAAW,CAAC;AAC7C,eAAO,MAAM,iBAAiB,QAAQ,CAAC;AAEvC;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG;IACvB,4DAA4D;IAC5D,SAAS,EAAE,MAAM,CAAC;IAElB,sEAAsE;IACtE,QAAQ,EAAE,MAAM,CAAC;IAEjB,6CAA6C;IAC7C,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B
|
|
1
|
+
{"version":3,"file":"ph-types.d.ts","sourceRoot":"","sources":["../../../src/core/ph-types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ph-types.js","sourceRoot":"","sources":["../../../src/core/ph-types.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,8EAA8E;AAC9E,YAAY;AACZ,EAAE;AACF,4EAA4E;AAC5E,gDAAgD;AAChD,+EAA+E;
|
|
1
|
+
{"version":3,"file":"ph-types.js","sourceRoot":"","sources":["../../../src/core/ph-types.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,8EAA8E;AAC9E,YAAY;AACZ,EAAE;AACF,4EAA4E;AAC5E,gDAAgD;AAChD,+EAA+E;AAoG/E,mEAAmE;AACnE,MAAM,CAAC,MAAM,mBAAmB,GAAG,MAAM,CAAC;AAC1C,MAAM,CAAC,MAAM,qBAAqB,GAAG,QAAQ,CAAC;AAC9C,MAAM,CAAC,MAAM,qBAAqB,GAAG,QAAQ,CAAC;AAE9C,6DAA6D;AAC7D,MAAM,CAAC,MAAM,oBAAoB,GAAG,QAAQ,CAAC;AAC7C,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,CAAC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { type OperationContext } from "./actions.js";
|
|
1
2
|
import type { Action, DocumentOperations, Operation, PHBaseState, PHDocument, PHDocumentHeader } from "./ph-types.js";
|
|
2
3
|
import type { PruneActionInput, Reducer, ReducerOptions, ReplayDocumentOptions, SignalDispatch, SkipHeaderOperations, StateReducer } from "./types.js";
|
|
3
|
-
export declare function replayOperations<TState extends PHBaseState = PHBaseState>(initialState: TState, clearedOperations: DocumentOperations, stateReducer: StateReducer<TState>,
|
|
4
|
+
export declare function replayOperations<TState extends PHBaseState = PHBaseState>(initialState: TState, clearedOperations: DocumentOperations, stateReducer: StateReducer<TState>, header: PHDocumentHeader, dispatch?: SignalDispatch, documentReducer?: typeof baseReducer, skipHeaderOperations?: SkipHeaderOperations, options?: ReplayDocumentOptions): PHDocument<TState>;
|
|
4
5
|
/**
|
|
5
6
|
* Updates the document state based on the provided action.
|
|
6
7
|
*
|
|
@@ -8,9 +9,10 @@ export declare function replayOperations<TState extends PHBaseState = PHBaseStat
|
|
|
8
9
|
* @param action The action being applied to the document.
|
|
9
10
|
* @param skip The number of operations to skip before applying the action.
|
|
10
11
|
* @param reuseLastOperationIndex Whether to reuse the last operation index (used when a an UNDO operation is performed after an existing one).
|
|
12
|
+
* @param context The operation context for deterministic ID generation.
|
|
11
13
|
* @returns The updated document state.
|
|
12
14
|
*/
|
|
13
|
-
export declare function updateDocument<TDocument extends PHDocument>(document: TDocument, action: Action, reuseLastOperationIndex
|
|
15
|
+
export declare function updateDocument<TDocument extends PHDocument>(document: TDocument, action: Action, reuseLastOperationIndex: boolean, skip: number, context: OperationContext, operation?: Operation, skipIndexValidation?: boolean): TDocument;
|
|
14
16
|
/**
|
|
15
17
|
* Processes an UNDO or REDO action.
|
|
16
18
|
*
|
|
@@ -19,7 +21,7 @@ export declare function updateDocument<TDocument extends PHDocument>(document: T
|
|
|
19
21
|
* @param skip The number of operations to skip before applying the action.
|
|
20
22
|
* @returns The updated document, calculated skip value and transformed action (if applied).
|
|
21
23
|
*/
|
|
22
|
-
export declare function processUndoRedo<TState extends PHBaseState = PHBaseState>(document: PHDocument<TState>, action: Action, skip: number): {
|
|
24
|
+
export declare function processUndoRedo<TState extends PHBaseState = PHBaseState>(document: PHDocument<TState>, action: Action, skip: number, protocolVersion?: number): {
|
|
23
25
|
document: PHDocument<TState>;
|
|
24
26
|
action: Action;
|
|
25
27
|
skip: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reducer.d.ts","sourceRoot":"","sources":["../../../src/core/reducer.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"reducer.d.ts","sourceRoot":"","sources":["../../../src/core/reducer.ts"],"names":[],"mappings":"AACA,OAAO,EAKL,KAAK,gBAAgB,EACtB,MAAM,cAAc,CAAC;AAuBtB,OAAO,KAAK,EACV,MAAM,EACN,kBAAkB,EAClB,SAAS,EACT,WAAW,EACX,UAAU,EACV,gBAAgB,EACjB,MAAM,eAAe,CAAC;AAEvB,OAAO,KAAK,EACV,gBAAgB,EAChB,OAAO,EACP,cAAc,EACd,qBAAqB,EACrB,cAAc,EACd,oBAAoB,EACpB,YAAY,EACb,MAAM,YAAY,CAAC;AAGpB,wBAAgB,gBAAgB,CAAC,MAAM,SAAS,WAAW,GAAG,WAAW,EACvE,YAAY,EAAE,MAAM,EACpB,iBAAiB,EAAE,kBAAkB,EACrC,YAAY,EAAE,YAAY,CAAC,MAAM,CAAC,EAClC,MAAM,EAAE,gBAAgB,EACxB,QAAQ,CAAC,EAAE,cAAc,EACzB,eAAe,qBAAc,EAC7B,oBAAoB,GAAE,oBAAyB,EAC/C,OAAO,CAAC,EAAE,qBAAqB,GAC9B,UAAU,CAAC,MAAM,CAAC,CAcpB;AA8FD;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,SAAS,SAAS,UAAU,EACzD,QAAQ,EAAE,SAAS,EACnB,MAAM,EAAE,MAAM,EACd,uBAAuB,EAAE,OAAO,EAChC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,gBAAgB,EACzB,SAAS,CAAC,EAAE,SAAS,EACrB,mBAAmB,CAAC,EAAE,OAAO,GAC5B,SAAS,CAyBX;AA+BD;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,MAAM,SAAS,WAAW,GAAG,WAAW,EACtE,QAAQ,EAAE,UAAU,CAAC,MAAM,CAAC,EAC5B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,eAAe,SAAI,GAClB;IACD,QAAQ,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,uBAAuB,EAAE,OAAO,CAAC;CAClC,CAYA;AAoHD;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,MAAM,SAAS,WAAW,GAAG,WAAW,EAClE,QAAQ,EAAE,UAAU,CAAC,MAAM,CAAC,EAC5B,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,YAAY,CAAC,MAAM,CAAC,EACnC,QAAQ,CAAC,EAAE,cAAc,EACzB,OAAO,GAAE,cAAmB,GAC3B,UAAU,CAAC,MAAM,CAAC,CA+OpB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,aAAa,CAAC,MAAM,SAAS,WAAW,GAAG,WAAW,EACpE,YAAY,EAAE,YAAY,CAAC,MAAM,CAAC,EAClC,eAAe,qBAAc,GAC5B,OAAO,CAAC,MAAM,CAAC,CAUjB;AAED,wBAAgB,cAAc,CAAC,MAAM,SAAS,WAAW,GAAG,WAAW,EACrE,QAAQ,EAAE,UAAU,CAAC,MAAM,CAAC,EAC5B,KAAK,EAAE,gBAAgB,EACvB,cAAc,EAAE,YAAY,CAAC,MAAM,CAAC,GACnC,UAAU,CAAC,MAAM,CAAC,CAoEpB"}
|