edytor 5.0.0 → 7.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/dist/cloudflare/DocumentRoom.d.ts +77 -2
- package/dist/cloudflare/DocumentRoom.js +37 -1
- package/dist/cloudflare/index.d.ts +1 -1
- package/dist/cloudflare/index.js +1 -1
- package/dist/cloudflare/room/access.d.ts +6 -1
- package/dist/cloudflare/room/access.js +30 -4
- package/dist/cloudflare/room/admission.d.ts +11 -0
- package/dist/cloudflare/room/admission.js +43 -10
- package/dist/cloudflare/room/context.d.ts +73 -76
- package/dist/cloudflare/room/context.js +17 -6
- package/dist/cloudflare/room/forged.d.ts +1 -1
- package/dist/cloudflare/room/forged.js +11 -9
- package/dist/cloudflare/room/frames.d.ts +2 -0
- package/dist/cloudflare/room/frames.js +2 -0
- package/dist/cloudflare/room/presence.js +1 -4
- package/dist/cloudflare/room/reseed.d.ts +93 -0
- package/dist/cloudflare/room/reseed.js +500 -0
- package/dist/cloudflare/room/scheduler.d.ts +1 -1
- package/dist/cloudflare/room/scheduler.js +9 -1
- package/dist/cloudflare/room/shared.d.ts +10 -0
- package/dist/cloudflare/room/shared.js +10 -0
- package/dist/cloudflare/room/storage.d.ts +7 -0
- package/dist/cloudflare/room/storage.js +33 -1
- package/dist/components/Edytor.svelte +18 -3
- package/dist/components/Edytor.svelte.d.ts +10 -1
- package/dist/components/EdytorRoot.svelte +17 -0
- package/dist/components/EdytorRoot.svelte.d.ts +4 -0
- package/dist/components/Suggestion.svelte +1 -1
- package/dist/crdt/attribution/block.d.ts +3 -0
- package/dist/crdt/attribution/block.js +3 -2
- package/dist/crdt/doc/history.js +2 -3
- package/dist/crdt/doc/ops.d.ts +81 -0
- package/dist/crdt/doc/ops.js +1898 -0
- package/dist/crdt/doc/suggest.d.ts +6 -2
- package/dist/crdt/doc/suggest.js +6 -5
- package/dist/crdt/edytor-doc.d.ts +157 -157
- package/dist/crdt/edytor-doc.js +15 -43
- package/dist/crdt/engine-room.d.ts +4 -0
- package/dist/crdt/engine-room.js +6 -0
- package/dist/crdt/flow.d.ts +4 -46
- package/dist/crdt/flow.js +2 -262
- package/dist/crdt/index.d.ts +64 -75
- package/dist/crdt/operations.d.ts +1 -1
- package/dist/crdt/placement/resolve.d.ts +1 -1
- package/dist/crdt/protocol.d.ts +2 -2
- package/dist/crdt/protocol.js +2 -2
- package/dist/crdt/protocols/auth.d.ts +8 -1
- package/dist/crdt/protocols/auth.js +14 -1
- package/dist/crdt/protocols/awareness.js +46 -81
- package/dist/crdt/providers/index.d.ts +11 -22
- package/dist/crdt/providers/index.js +22 -3
- package/dist/crdt/providers/indexeddb.d.ts +6 -10
- package/dist/crdt/providers/indexeddb.js +10 -16
- package/dist/crdt/providers/room.d.ts +26 -0
- package/dist/crdt/providers/room.js +41 -12
- package/dist/crdt/providers/websocket.d.ts +10 -14
- package/dist/crdt/providers/websocket.js +43 -23
- package/dist/crdt/rangeDelete.d.ts +2 -47
- package/dist/crdt/rangeDelete.js +1 -169
- package/dist/crdt/reseed.d.ts +127 -0
- package/dist/crdt/reseed.js +533 -0
- package/dist/crdt/restore.d.ts +13 -1
- package/dist/crdt/restore.js +8 -3
- package/dist/crdt/schema.d.ts +6 -0
- package/dist/crdt/schema.js +6 -0
- package/dist/crdt/structs.d.ts +8 -11
- package/dist/crdt/structs.js +25 -44
- package/dist/crdt/text/index/build.d.ts +119 -0
- package/dist/crdt/text/index/build.js +2801 -0
- package/dist/crdt/text/index/shared.d.ts +2 -6
- package/dist/crdt/text/index/shared.js +2 -5
- package/dist/crdt/text/model.js +2 -3
- package/dist/crdt/text/runs.d.ts +9 -12
- package/dist/crdt/text/runs.js +2 -165
- package/dist/crdt/vendor/yjs/UPSTREAM.md +101 -5
- package/dist/crdt/vendor/yjs/dts/index.d.ts +1 -1
- package/dist/crdt/vendor/yjs/dts/utils/Transaction.d.ts +10 -10
- package/dist/crdt/vendor/yjs/dts/utils/encoding.d.ts +1 -0
- package/dist/crdt/vendor/yjs/src/index.js +1 -1
- package/dist/crdt/vendor/yjs/src/structs/Item.js +24 -13
- package/dist/crdt/vendor/yjs/src/utils/Transaction.js +12 -10
- package/dist/crdt/vendor/yjs/src/utils/encoding.js +42 -1
- package/dist/events/domTextOffset.d.ts +2 -0
- package/dist/events/domTextOffset.js +8 -0
- package/dist/export/forms.d.ts +50 -50
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/plugins/richtext/RichTextPlugin.svelte +63 -61
- package/dist/plugins/richtext/richTextOperations.js +26 -32
- package/dist/selection/selection.svelte.d.ts +1 -1
- package/dist/selection/selection.svelte.js +87 -106
- package/dist/selection/selection.utils.js +5 -8
- package/dist/session/commands.js +49 -51
- package/dist/session/handles.js +3 -7
- package/dist/surface/attributes.d.ts +3 -3
- package/dist/surface/attributes.js +2 -2
- package/dist/surface/observer.svelte.d.ts +7 -7
- package/dist/surface/observer.svelte.js +225 -336
- package/dist/surface/projector.svelte.js +2 -2
- package/dist/utils.d.ts +5 -0
- package/dist/utils.js +7 -0
- package/package.json +1 -1
- package/dist/crdt/doc/capability.d.ts +0 -56
- package/dist/crdt/doc/capability.js +0 -207
- package/dist/crdt/doc/content.d.ts +0 -16
- package/dist/crdt/doc/content.js +0 -77
- package/dist/crdt/doc/delete.d.ts +0 -15
- package/dist/crdt/doc/delete.js +0 -84
- package/dist/crdt/doc/layout.d.ts +0 -9
- package/dist/crdt/doc/layout.js +0 -178
- package/dist/crdt/doc/meta.d.ts +0 -19
- package/dist/crdt/doc/meta.js +0 -198
- package/dist/crdt/doc/moves.d.ts +0 -21
- package/dist/crdt/doc/moves.js +0 -274
- package/dist/crdt/doc/split-merge.d.ts +0 -10
- package/dist/crdt/doc/split-merge.js +0 -179
- package/dist/crdt/doc/steps.d.ts +0 -65
- package/dist/crdt/doc/steps.js +0 -311
- package/dist/crdt/text/index/cache.d.ts +0 -16
- package/dist/crdt/text/index/cache.js +0 -175
- package/dist/crdt/text/index/claims.d.ts +0 -18
- package/dist/crdt/text/index/claims.js +0 -203
- package/dist/crdt/text/index/fold.d.ts +0 -21
- package/dist/crdt/text/index/fold.js +0 -656
- package/dist/crdt/text/index/layout.d.ts +0 -22
- package/dist/crdt/text/index/layout.js +0 -258
- package/dist/crdt/text/index/placement.d.ts +0 -47
- package/dist/crdt/text/index/placement.js +0 -738
- package/dist/crdt/text/index/records.d.ts +0 -13
- package/dist/crdt/text/index/records.js +0 -139
- package/dist/crdt/text/index/report.d.ts +0 -18
- package/dist/crdt/text/index/report.js +0 -337
- package/dist/crdt/text/index/state.d.ts +0 -197
- package/dist/crdt/text/index/state.js +0 -116
- package/dist/crdt/text/index/streams.d.ts +0 -25
- package/dist/crdt/text/index/streams.js +0 -248
|
@@ -18,6 +18,7 @@ import type { RoomHistory } from './history.js';
|
|
|
18
18
|
import type { RoomMoves } from './moves.js';
|
|
19
19
|
import type { RoomPresence } from './presence.js';
|
|
20
20
|
import type { RoomPurge } from './purge.js';
|
|
21
|
+
import type { RoomReseed } from './reseed.js';
|
|
21
22
|
import type { ReplicaRegistry } from './replicas.js';
|
|
22
23
|
import type { Scheduler } from './scheduler.js';
|
|
23
24
|
import type { RoomStorage } from './storage.js';
|
|
@@ -157,34 +158,8 @@ export declare const crdt: {
|
|
|
157
158
|
api: object;
|
|
158
159
|
} & {
|
|
159
160
|
prepare: {
|
|
160
|
-
insertFlow: (target: import("../../index.js").FlowTarget, flow: import("../../index.js").Flow, view?: import("../../index.js").FlowView) => import("../../index.js").Prepared;
|
|
161
|
-
deleteRange: (from: import("../../index.js").DocPosition, to: import("../../index.js").DocPosition, view?: import("../../index.js").RangeView) => import("../../index.js").Prepared;
|
|
162
|
-
replaceRange: (from: import("../../index.js").DocPosition, to: import("../../index.js").DocPosition, view?: import("../../index.js").RangeView) => import("../../index.js").Prepared;
|
|
163
161
|
nestBlock: (id: import("../../index.js").BlockId, parent: import("../../index.js").BlockId) => import("../../index.js").Prepared;
|
|
164
162
|
deleteBlocks: (ids: readonly import("../../index.js").BlockId[]) => import("../../index.js").Prepared;
|
|
165
|
-
insertText: (id: import("../../index.js").BlockId, offset: number, text: string, marks?: Record<string, unknown>) => import("../../index.js").Prepared;
|
|
166
|
-
deleteText: (id: import("../../index.js").BlockId, offset: number, length: number) => import("../../index.js").Prepared;
|
|
167
|
-
formatRange: (id: import("../../index.js").BlockId, offset: number, length: number, marks: Record<string, unknown>) => import("../../index.js").Prepared;
|
|
168
|
-
clearMarks: (id: import("../../index.js").BlockId, offset: number, length: number) => import("../../index.js").Prepared;
|
|
169
|
-
insertInline: (id: import("../../index.js").BlockId, offset: number, atom: import("../../crdt/doc/content.js").NewInline) => import("../../index.js").Prepared;
|
|
170
|
-
removeInline: (id: import("../../index.js").BlockId, inlineId: string) => import("../../index.js").Prepared;
|
|
171
|
-
setBlockType: (id: import("../../index.js").BlockId, type: string) => import("../../index.js").Prepared;
|
|
172
|
-
patchData: (target: import("../../index.js").DataTarget, patches: readonly import("../../index.js").DataPatch[]) => import("../../index.js").Prepared;
|
|
173
|
-
setBlock: (id: import("../../index.js").BlockId, value: {
|
|
174
|
-
type?: string;
|
|
175
|
-
data?: Record<string, unknown>;
|
|
176
|
-
content?: (import("../../index.js").ContentItem | import("../../index.js").JSONText | import("../../index.js").JSONInlineBlock)[];
|
|
177
|
-
children?: (import("../../index.js").BlockSpec | import("../../index.js").JSONBlock)[];
|
|
178
|
-
}) => import("../../index.js").Prepared;
|
|
179
|
-
deleteBlock: (id: import("../../index.js").BlockId, opts?: {
|
|
180
|
-
keepChildren?: boolean;
|
|
181
|
-
}) => import("../../index.js").Prepared;
|
|
182
|
-
splitBlock: (id: import("../../index.js").BlockId, offset: number, newId: import("../../index.js").BlockId, tail?: import("../../index.js").SplitTail) => import("../../index.js").Prepared;
|
|
183
|
-
mergeBlocks: (fromId: import("../../index.js").BlockId, intoId: import("../../index.js").BlockId) => import("../../index.js").Prepared;
|
|
184
|
-
mergeBackward: (id: import("../../index.js").BlockId) => import("../../index.js").Prepared;
|
|
185
|
-
mergeForward: (id: import("../../index.js").BlockId) => import("../../index.js").Prepared;
|
|
186
|
-
placeBeside: (ids: readonly import("../../index.js").BlockId[], target: import("../../index.js").BlockId, side: "left" | "right", kind?: string) => import("../../index.js").Prepared;
|
|
187
|
-
wrapInLayout: (ids: readonly import("../../index.js").BlockId[], kind?: string, columns?: number) => import("../../index.js").Prepared;
|
|
188
163
|
insertBlocks: (dest: import("../../index.js").Destination, specs: readonly (import("../../index.js").BlockSpec | import("../../index.js").JSONBlock)[]) => import("../../index.js").Prepared;
|
|
189
164
|
moveBlocks: (ids: readonly import("../../index.js").BlockId[], dest: import("../../index.js").Destination) => import("../../index.js").Prepared;
|
|
190
165
|
unNestBlocks: (ids: readonly import("../../index.js").BlockId[]) => import("../../index.js").Prepared;
|
|
@@ -194,39 +169,39 @@ export declare const crdt: {
|
|
|
194
169
|
after?: readonly import("../../index.js").BlockSpec[];
|
|
195
170
|
}) => import("../../index.js").Prepared;
|
|
196
171
|
duplicateBlock: (id: import("../../index.js").BlockId, freshId?: (oldId: string, kind: "block" | "inline") => string) => import("../../index.js").Prepared;
|
|
172
|
+
placeBeside: (ids: readonly import("../../index.js").BlockId[], target: import("../../index.js").BlockId, side: "left" | "right", kind?: string) => import("../../index.js").Prepared;
|
|
173
|
+
wrapInLayout: (ids: readonly import("../../index.js").BlockId[], kind?: string, columns?: number) => import("../../index.js").Prepared;
|
|
174
|
+
splitBlock: (id: import("../../index.js").BlockId, offset: number, newId: import("../../index.js").BlockId, tail?: import("../../index.js").SplitTail) => import("../../index.js").Prepared;
|
|
175
|
+
mergeBlocks: (fromId: import("../../index.js").BlockId, intoId: import("../../index.js").BlockId) => import("../../index.js").Prepared;
|
|
176
|
+
mergeBackward: (id: import("../../index.js").BlockId) => import("../../index.js").Prepared;
|
|
177
|
+
mergeForward: (id: import("../../index.js").BlockId) => import("../../index.js").Prepared;
|
|
178
|
+
deleteBlock: (id: import("../../index.js").BlockId, opts?: {
|
|
179
|
+
keepChildren?: boolean;
|
|
180
|
+
}) => import("../../index.js").Prepared;
|
|
181
|
+
setBlockType: (id: import("../../index.js").BlockId, type: string) => import("../../index.js").Prepared;
|
|
182
|
+
patchData: (target: import("../../index.js").DataTarget, patches: readonly import("../../index.js").DataPatch[]) => import("../../index.js").Prepared;
|
|
183
|
+
setBlock: (id: import("../../index.js").BlockId, value: {
|
|
184
|
+
type?: string;
|
|
185
|
+
data?: Record<string, unknown>;
|
|
186
|
+
content?: (import("../../index.js").ContentItem | import("../../index.js").JSONText | import("../../index.js").JSONInlineBlock)[];
|
|
187
|
+
children?: (import("../../index.js").BlockSpec | import("../../index.js").JSONBlock)[];
|
|
188
|
+
}) => import("../../index.js").Prepared;
|
|
189
|
+
insertText: (id: import("../../index.js").BlockId, offset: number, text: string, marks?: Record<string, unknown>) => import("../../index.js").Prepared;
|
|
190
|
+
deleteText: (id: import("../../index.js").BlockId, offset: number, length: number) => import("../../index.js").Prepared;
|
|
191
|
+
formatRange: (id: import("../../index.js").BlockId, offset: number, length: number, marks: Record<string, unknown>) => import("../../index.js").Prepared;
|
|
192
|
+
clearMarks: (id: import("../../index.js").BlockId, offset: number, length: number) => import("../../index.js").Prepared;
|
|
193
|
+
insertInline: (id: import("../../index.js").BlockId, offset: number, atom: import("../../crdt/doc/ops.js").NewInline) => import("../../index.js").Prepared;
|
|
194
|
+
removeInline: (id: import("../../index.js").BlockId, inlineId: string) => import("../../index.js").Prepared;
|
|
195
|
+
insertFlow: (target: import("../../index.js").FlowTarget, flow: import("../../index.js").Flow, view?: import("../../index.js").FlowView) => import("../../index.js").Prepared;
|
|
196
|
+
deleteRange: (from: import("../../index.js").DocPosition, to: import("../../index.js").DocPosition, view?: import("../../index.js").RangeView) => import("../../index.js").Prepared;
|
|
197
|
+
replaceRange: (from: import("../../index.js").DocPosition, to: import("../../index.js").DocPosition, view?: import("../../index.js").RangeView) => import("../../index.js").Prepared;
|
|
197
198
|
};
|
|
198
199
|
apply: (p: import("../../index.js").Prepared, quiet?: boolean) => import("../../index.js").OpResult;
|
|
199
200
|
compose: (...parts: import("../../index.js").Prepared[]) => import("../../index.js").Prepared;
|
|
200
201
|
transact: <R>(fn: () => R, origin?: unknown) => R;
|
|
201
202
|
version: number;
|
|
202
|
-
insertFlow: (target: import("../../index.js").FlowTarget, flow: import("../../index.js").Flow, view?: import("../../index.js").FlowView | undefined) => import("../../index.js").OpResult;
|
|
203
|
-
deleteRange: (from: import("../../index.js").DocPosition, to: import("../../index.js").DocPosition, view?: import("../../index.js").RangeView | undefined) => import("../../index.js").OpResult;
|
|
204
|
-
replaceRange: (from: import("../../index.js").DocPosition, to: import("../../index.js").DocPosition, view?: import("../../index.js").RangeView | undefined) => import("../../index.js").OpResult;
|
|
205
203
|
nestBlock: (id: string, parent: string) => import("../../index.js").OpResult;
|
|
206
204
|
deleteBlocks: (ids: readonly string[]) => import("../../index.js").OpResult;
|
|
207
|
-
insertText: (id: string, offset: number, text: string, marks?: Record<string, unknown> | undefined) => import("../../index.js").OpResult;
|
|
208
|
-
deleteText: (id: string, offset: number, length: number) => import("../../index.js").OpResult;
|
|
209
|
-
formatRange: (id: string, offset: number, length: number, marks: Record<string, unknown>) => import("../../index.js").OpResult;
|
|
210
|
-
clearMarks: (id: string, offset: number, length: number) => import("../../index.js").OpResult;
|
|
211
|
-
insertInline: (id: string, offset: number, atom: import("../../crdt/doc/content.js").NewInline) => import("../../index.js").OpResult;
|
|
212
|
-
removeInline: (id: string, inlineId: string) => import("../../index.js").OpResult;
|
|
213
|
-
setBlockType: (id: string, type: string) => import("../../index.js").OpResult;
|
|
214
|
-
patchData: (target: import("../../index.js").DataTarget, patches: readonly import("../../index.js").DataPatch[]) => import("../../index.js").OpResult;
|
|
215
|
-
setBlock: (id: string, value: {
|
|
216
|
-
type?: string;
|
|
217
|
-
data?: Record<string, unknown>;
|
|
218
|
-
content?: (import("../../index.js").ContentItem | import("../../index.js").JSONText | import("../../index.js").JSONInlineBlock)[];
|
|
219
|
-
children?: (import("../../index.js").BlockSpec | import("../../index.js").JSONBlock)[];
|
|
220
|
-
}) => import("../../index.js").OpResult;
|
|
221
|
-
deleteBlock: (id: string, opts?: {
|
|
222
|
-
keepChildren?: boolean;
|
|
223
|
-
} | undefined) => import("../../index.js").OpResult;
|
|
224
|
-
splitBlock: (id: string, offset: number, newId: string, tail?: import("../../index.js").SplitTail | undefined) => import("../../index.js").OpResult;
|
|
225
|
-
mergeBlocks: (fromId: string, intoId: string) => import("../../index.js").OpResult;
|
|
226
|
-
mergeBackward: (id: string) => import("../../index.js").OpResult;
|
|
227
|
-
mergeForward: (id: string) => import("../../index.js").OpResult;
|
|
228
|
-
placeBeside: (ids: readonly string[], target: string, side: "left" | "right", kind?: string | undefined) => import("../../index.js").OpResult;
|
|
229
|
-
wrapInLayout: (ids: readonly string[], kind?: string | undefined, columns?: number | undefined) => import("../../index.js").OpResult;
|
|
230
205
|
insertBlocks: (dest: import("../../index.js").Destination, specs: readonly (import("../../index.js").JSONBlock | import("../../index.js").BlockSpec)[]) => import("../../index.js").OpResult;
|
|
231
206
|
moveBlocks: (ids: readonly string[], dest: import("../../index.js").Destination) => import("../../index.js").OpResult;
|
|
232
207
|
unNestBlocks: (ids: readonly string[]) => import("../../index.js").OpResult;
|
|
@@ -236,6 +211,32 @@ export declare const crdt: {
|
|
|
236
211
|
after?: readonly import("../../index.js").BlockSpec[];
|
|
237
212
|
} | undefined) => import("../../index.js").OpResult;
|
|
238
213
|
duplicateBlock: (id: string, freshId?: ((oldId: string, kind: "block" | "inline") => string) | undefined) => import("../../index.js").OpResult;
|
|
214
|
+
placeBeside: (ids: readonly string[], target: string, side: "left" | "right", kind?: string | undefined) => import("../../index.js").OpResult;
|
|
215
|
+
wrapInLayout: (ids: readonly string[], kind?: string | undefined, columns?: number | undefined) => import("../../index.js").OpResult;
|
|
216
|
+
splitBlock: (id: string, offset: number, newId: string, tail?: import("../../index.js").SplitTail | undefined) => import("../../index.js").OpResult;
|
|
217
|
+
mergeBlocks: (fromId: string, intoId: string) => import("../../index.js").OpResult;
|
|
218
|
+
mergeBackward: (id: string) => import("../../index.js").OpResult;
|
|
219
|
+
mergeForward: (id: string) => import("../../index.js").OpResult;
|
|
220
|
+
deleteBlock: (id: string, opts?: {
|
|
221
|
+
keepChildren?: boolean;
|
|
222
|
+
} | undefined) => import("../../index.js").OpResult;
|
|
223
|
+
setBlockType: (id: string, type: string) => import("../../index.js").OpResult;
|
|
224
|
+
patchData: (target: import("../../index.js").DataTarget, patches: readonly import("../../index.js").DataPatch[]) => import("../../index.js").OpResult;
|
|
225
|
+
setBlock: (id: string, value: {
|
|
226
|
+
type?: string;
|
|
227
|
+
data?: Record<string, unknown>;
|
|
228
|
+
content?: (import("../../index.js").ContentItem | import("../../index.js").JSONText | import("../../index.js").JSONInlineBlock)[];
|
|
229
|
+
children?: (import("../../index.js").BlockSpec | import("../../index.js").JSONBlock)[];
|
|
230
|
+
}) => import("../../index.js").OpResult;
|
|
231
|
+
insertText: (id: string, offset: number, text: string, marks?: Record<string, unknown> | undefined) => import("../../index.js").OpResult;
|
|
232
|
+
deleteText: (id: string, offset: number, length: number) => import("../../index.js").OpResult;
|
|
233
|
+
formatRange: (id: string, offset: number, length: number, marks: Record<string, unknown>) => import("../../index.js").OpResult;
|
|
234
|
+
clearMarks: (id: string, offset: number, length: number) => import("../../index.js").OpResult;
|
|
235
|
+
insertInline: (id: string, offset: number, atom: import("../../crdt/doc/ops.js").NewInline) => import("../../index.js").OpResult;
|
|
236
|
+
removeInline: (id: string, inlineId: string) => import("../../index.js").OpResult;
|
|
237
|
+
insertFlow: (target: import("../../index.js").FlowTarget, flow: import("../../index.js").Flow, view?: import("../../index.js").FlowView | undefined) => import("../../index.js").OpResult;
|
|
238
|
+
deleteRange: (from: import("../../index.js").DocPosition, to: import("../../index.js").DocPosition, view?: import("../../index.js").RangeView | undefined) => import("../../index.js").OpResult;
|
|
239
|
+
replaceRange: (from: import("../../index.js").DocPosition, to: import("../../index.js").DocPosition, view?: import("../../index.js").RangeView | undefined) => import("../../index.js").OpResult;
|
|
239
240
|
project: () => import("../../index.js").ProjectedDoc;
|
|
240
241
|
toJSON: (options?: {
|
|
241
242
|
suggestions?: boolean;
|
|
@@ -312,7 +313,7 @@ export declare const crdt: {
|
|
|
312
313
|
text: import("../../crdt/text/model.js").TextEngine;
|
|
313
314
|
}, horizon: import("../../crdt/purge.js").Horizon | null) => import("../index.js").PurgeReport;
|
|
314
315
|
horizonOf: (doc: E.EngineDoc) => import("../../crdt/purge.js").Horizon | null;
|
|
315
|
-
restoreTo: <Plan>(doc: E.EngineDoc, facade: import("../../crdt/restore.js").RestoreFacade<Plan>, json: JSONDoc) => import("../../crdt/restore.js").RestoreReport;
|
|
316
|
+
restoreTo: <Plan>(doc: E.EngineDoc, facade: import("../../crdt/restore.js").RestoreFacade<Plan>, json: JSONDoc, { rewrite, suggestions }?: import("../../crdt/restore.js").RestoreOptions<Plan>) => import("../../crdt/restore.js").RestoreReport;
|
|
316
317
|
model: {
|
|
317
318
|
REGISTRY_KEY: string;
|
|
318
319
|
registryOf: (doc: E.EngineDoc) => E.EngineNode;
|
|
@@ -407,17 +408,12 @@ export declare const crdt: {
|
|
|
407
408
|
loadError: unknown;
|
|
408
409
|
_storeTimeout: number;
|
|
409
410
|
_storeTimeoutId: ReturnType<typeof setTimeout> | null;
|
|
410
|
-
|
|
411
|
+
_unlisten: () => void;
|
|
411
412
|
awareness: import("../../index.js").Awareness;
|
|
412
413
|
bcconnected: boolean;
|
|
413
414
|
disableBc: boolean;
|
|
414
415
|
_ownsAwareness: boolean;
|
|
415
416
|
_bcSubscriber: (data: ArrayBuffer | Uint8Array, origin: unknown) => void;
|
|
416
|
-
_awarenessUpdateHandler: (updates: {
|
|
417
|
-
added: number[];
|
|
418
|
-
updated: number[];
|
|
419
|
-
removed: number[];
|
|
420
|
-
}, origin: unknown) => void;
|
|
421
417
|
get synced(): boolean;
|
|
422
418
|
messageHandlers: Record<number, import("../../crdt/providers/room.js").RoomMessageHandler</*elided*/ any>>;
|
|
423
419
|
readMessage: (buf: Uint8Array, emitSynced: boolean) => E.Encoder;
|
|
@@ -425,7 +421,7 @@ export declare const crdt: {
|
|
|
425
421
|
connectBc(): void;
|
|
426
422
|
disconnectBc(): void;
|
|
427
423
|
destroy(): Promise<void>;
|
|
428
|
-
emit<N extends "failed" | "
|
|
424
|
+
emit<N extends "failed" | "message-error" | "schema-mismatch" | "protocol-mismatch" | "synced" | "load-error">(name: N, args: Parameters<{
|
|
429
425
|
synced: (provider: /*elided*/ any) => void;
|
|
430
426
|
'protocol-mismatch': (mismatch: E.ProtocolMismatch, provider: /*elided*/ any) => void;
|
|
431
427
|
'load-error': (error: unknown, provider: /*elided*/ any) => void;
|
|
@@ -434,7 +430,7 @@ export declare const crdt: {
|
|
|
434
430
|
failed: (error: unknown, provider: /*elided*/ any) => void;
|
|
435
431
|
}[N]>): void;
|
|
436
432
|
_observers: Map<string, Set<any>>;
|
|
437
|
-
on<NAME extends "failed" | "
|
|
433
|
+
on<NAME extends "failed" | "message-error" | "schema-mismatch" | "protocol-mismatch" | "synced" | "load-error">(name: NAME, f: {
|
|
438
434
|
synced: (provider: /*elided*/ any) => void;
|
|
439
435
|
'protocol-mismatch': (mismatch: E.ProtocolMismatch, provider: /*elided*/ any) => void;
|
|
440
436
|
'load-error': (error: unknown, provider: /*elided*/ any) => void;
|
|
@@ -449,7 +445,7 @@ export declare const crdt: {
|
|
|
449
445
|
'schema-mismatch': (detail: E.SchemaMismatchDetail, provider: /*elided*/ any) => void;
|
|
450
446
|
failed: (error: unknown, provider: /*elided*/ any) => void;
|
|
451
447
|
}[NAME];
|
|
452
|
-
once<NAME extends "failed" | "
|
|
448
|
+
once<NAME extends "failed" | "message-error" | "schema-mismatch" | "protocol-mismatch" | "synced" | "load-error">(name: NAME, f: {
|
|
453
449
|
synced: (provider: /*elided*/ any) => void;
|
|
454
450
|
'protocol-mismatch': (mismatch: E.ProtocolMismatch, provider: /*elided*/ any) => void;
|
|
455
451
|
'load-error': (error: unknown, provider: /*elided*/ any) => void;
|
|
@@ -457,7 +453,7 @@ export declare const crdt: {
|
|
|
457
453
|
'schema-mismatch': (detail: E.SchemaMismatchDetail, provider: /*elided*/ any) => void;
|
|
458
454
|
failed: (error: unknown, provider: /*elided*/ any) => void;
|
|
459
455
|
}[NAME]): void;
|
|
460
|
-
off<NAME extends "failed" | "
|
|
456
|
+
off<NAME extends "failed" | "message-error" | "schema-mismatch" | "protocol-mismatch" | "synced" | "load-error">(name: NAME, f: {
|
|
461
457
|
synced: (provider: /*elided*/ any) => void;
|
|
462
458
|
'protocol-mismatch': (mismatch: E.ProtocolMismatch, provider: /*elided*/ any) => void;
|
|
463
459
|
'load-error': (error: unknown, provider: /*elided*/ any) => void;
|
|
@@ -508,6 +504,7 @@ export declare const crdt: {
|
|
|
508
504
|
deny(): void;
|
|
509
505
|
allow(): void;
|
|
510
506
|
};
|
|
507
|
+
_rebasing: boolean;
|
|
511
508
|
messageHandlers: Record<number, import("../../crdt/providers/room.js").RoomMessageHandler</*elided*/ any>>;
|
|
512
509
|
hasSynced: boolean;
|
|
513
510
|
whenSynced: Promise<unknown>;
|
|
@@ -518,14 +515,7 @@ export declare const crdt: {
|
|
|
518
515
|
_resync: ReturnType<typeof setInterval> | undefined;
|
|
519
516
|
_connectTimer: ReturnType<typeof setTimeout> | undefined;
|
|
520
517
|
_checkInterval: ReturnType<typeof setInterval>;
|
|
521
|
-
|
|
522
|
-
local: boolean;
|
|
523
|
-
}) => void;
|
|
524
|
-
_awarenessUpdateHandler: (updates: {
|
|
525
|
-
added: number[];
|
|
526
|
-
updated: number[];
|
|
527
|
-
removed: number[];
|
|
528
|
-
}, origin: unknown) => void;
|
|
518
|
+
_unlisten: () => void;
|
|
529
519
|
get url(): string;
|
|
530
520
|
get unsaved(): number;
|
|
531
521
|
get saved(): boolean;
|
|
@@ -535,11 +525,11 @@ export declare const crdt: {
|
|
|
535
525
|
destroy(): void;
|
|
536
526
|
disconnect(): void;
|
|
537
527
|
connect(): void;
|
|
538
|
-
emit<N extends "refused" | "status" | "failed" | "
|
|
528
|
+
emit<N extends "refused" | "status" | "failed" | "message-error" | "schema-mismatch" | "protocol-mismatch" | "synced" | "access" | "connection-close" | "connection-error" | "saved" | "permission-denied" | "expired" | "unreachable">(name: N, args: Parameters<E.WebsocketProviderEvents[N]>): void;
|
|
539
529
|
_observers: Map<string, Set<any>>;
|
|
540
|
-
on<NAME extends "refused" | "status" | "failed" | "
|
|
541
|
-
once<NAME extends "refused" | "status" | "failed" | "
|
|
542
|
-
off<NAME extends "refused" | "status" | "failed" | "
|
|
530
|
+
on<NAME extends "refused" | "status" | "failed" | "message-error" | "schema-mismatch" | "protocol-mismatch" | "synced" | "access" | "connection-close" | "connection-error" | "saved" | "permission-denied" | "expired" | "unreachable">(name: NAME, f: E.WebsocketProviderEvents[NAME]): E.WebsocketProviderEvents[NAME];
|
|
531
|
+
once<NAME extends "refused" | "status" | "failed" | "message-error" | "schema-mismatch" | "protocol-mismatch" | "synced" | "access" | "connection-close" | "connection-error" | "saved" | "permission-denied" | "expired" | "unreachable">(name: NAME, f: E.WebsocketProviderEvents[NAME]): void;
|
|
532
|
+
off<NAME extends "refused" | "status" | "failed" | "message-error" | "schema-mismatch" | "protocol-mismatch" | "synced" | "access" | "connection-close" | "connection-error" | "saved" | "permission-denied" | "expired" | "unreachable">(name: NAME, f: E.WebsocketProviderEvents[NAME]): void;
|
|
543
533
|
};
|
|
544
534
|
};
|
|
545
535
|
watchComments: (server: string | null, roomName: string, listener: (message: E.CommentMessage) => void) => (() => void);
|
|
@@ -656,6 +646,7 @@ export type RoomTables = {
|
|
|
656
646
|
late: string;
|
|
657
647
|
threads: string;
|
|
658
648
|
comments: string;
|
|
649
|
+
cuts: string;
|
|
659
650
|
};
|
|
660
651
|
/** The room's public diagnostics, kept on the `AttachedDocument` itself. */
|
|
661
652
|
export type RoomState = Pick<AttachedDocument, 'failure' | 'presence' | 'refusals' | 'refusalCounts' | 'origin'>;
|
|
@@ -725,6 +716,7 @@ export declare class RoomContext {
|
|
|
725
716
|
presence: RoomPresence;
|
|
726
717
|
access: RoomAccess;
|
|
727
718
|
comments: RoomComments;
|
|
719
|
+
reseed: RoomReseed;
|
|
728
720
|
constructor(ctx: DurableObjectState, options: AttachRoomOptions, limits: RoomLimits, state: RoomState);
|
|
729
721
|
/** The room's id: its name (`getByName`), else the object's id. */
|
|
730
722
|
get roomId(): string;
|
|
@@ -735,8 +727,11 @@ export declare class RoomContext {
|
|
|
735
727
|
/**
|
|
736
728
|
* A facade over `doc` obeying the room's block roles (`semantics`), its
|
|
737
729
|
* shared suggestions built: its `toJSON()` leaves the pending ones out.
|
|
730
|
+
* With `actor`, its writes are that actor's (a rebase's: `room.reseed.rebase`).
|
|
738
731
|
*/
|
|
739
|
-
facadeOf(doc: YDoc
|
|
732
|
+
facadeOf(doc: YDoc, actor?: {
|
|
733
|
+
id: string;
|
|
734
|
+
}): EdytorDoc;
|
|
740
735
|
/**
|
|
741
736
|
* The facade over the live document. Read while the room is idle, it
|
|
742
737
|
* first drops a direct write whose append failed (`heal`).
|
|
@@ -763,6 +758,8 @@ export declare class RoomContext {
|
|
|
763
758
|
log(entry: RoomLogEntry): void;
|
|
764
759
|
/** Send one frame — as chunks when it exceeds `maxFrameBytes` (bounded catch-up). */
|
|
765
760
|
send(ws: WebSocket, bytes: Uint8Array): void;
|
|
761
|
+
/** The open sockets of the current epoch: what the room relays to (`room.reseed.protocol`). */
|
|
762
|
+
sockets(): WebSocket[];
|
|
766
763
|
broadcast(bytes: Uint8Array, except: unknown): void;
|
|
767
764
|
close(ws: WebSocket, code: number, reason: string): void;
|
|
768
765
|
/** A refused frame is dropped whole and its socket closed (1008 policy violation). */
|
|
@@ -13,7 +13,7 @@ import { CLOSE } from '../../crdt/providers/room.js';
|
|
|
13
13
|
import { asEngineDoc } from '../../crdt/structs.js';
|
|
14
14
|
import { suggestionsOf } from '../../crdt/doc/suggest.js';
|
|
15
15
|
import { defaultSemantics, facadeConfigOf, semanticsDigest } from '../../crdt/semantics.js';
|
|
16
|
-
import { MAX_REFUSALS, ROOM_ORIGIN, SOCKET_TAG, noTimers } from './shared.js';
|
|
16
|
+
import { MAX_REFUSALS, ROOM_ORIGIN, SOCKET_TAG, STALE_TAG, noTimers } from './shared.js';
|
|
17
17
|
/** The engine API the room is built on (the Worker-safe CRDT entry). */
|
|
18
18
|
export const crdt = E.bindCrdt(Y);
|
|
19
19
|
export const sync = crdt.sync;
|
|
@@ -94,6 +94,7 @@ export class RoomContext {
|
|
|
94
94
|
presence;
|
|
95
95
|
access;
|
|
96
96
|
comments;
|
|
97
|
+
reseed;
|
|
97
98
|
#_facade = null;
|
|
98
99
|
#_lookups = null;
|
|
99
100
|
#_digest = null;
|
|
@@ -117,7 +118,8 @@ export class RoomContext {
|
|
|
117
118
|
moves: `${prefix}moves`,
|
|
118
119
|
late: `${prefix}late`,
|
|
119
120
|
threads: `${prefix}threads`,
|
|
120
|
-
comments: `${prefix}comments
|
|
121
|
+
comments: `${prefix}comments`,
|
|
122
|
+
cuts: `${prefix}cuts`
|
|
121
123
|
};
|
|
122
124
|
this.clock = options.now ?? Date.now;
|
|
123
125
|
}
|
|
@@ -137,9 +139,11 @@ export class RoomContext {
|
|
|
137
139
|
/**
|
|
138
140
|
* A facade over `doc` obeying the room's block roles (`semantics`), its
|
|
139
141
|
* shared suggestions built: its `toJSON()` leaves the pending ones out.
|
|
142
|
+
* With `actor`, its writes are that actor's (a rebase's: `room.reseed.rebase`).
|
|
140
143
|
*/
|
|
141
|
-
facadeOf(doc) {
|
|
142
|
-
const
|
|
144
|
+
facadeOf(doc, actor) {
|
|
145
|
+
const config = actor ? { ...this.lookups, actor: () => actor } : this.lookups;
|
|
146
|
+
const facade = crdt.doc.create(asEngineDoc(doc), config);
|
|
143
147
|
suggestionsOf(facade);
|
|
144
148
|
return facade;
|
|
145
149
|
}
|
|
@@ -259,10 +263,17 @@ export class RoomContext {
|
|
|
259
263
|
for (const piece of E.chunkFrame(bytes, this.limits.maxFrameBytes))
|
|
260
264
|
ws.send(piece);
|
|
261
265
|
}
|
|
266
|
+
/** The open sockets of the current epoch: what the room relays to (`room.reseed.protocol`). */
|
|
267
|
+
sockets() {
|
|
268
|
+
const stale = new Set(this.ctx.getWebSockets(STALE_TAG));
|
|
269
|
+
return this.ctx
|
|
270
|
+
.getWebSockets(SOCKET_TAG)
|
|
271
|
+
.filter((ws) => ws.readyState === WebSocket.OPEN && !stale.has(ws));
|
|
272
|
+
}
|
|
262
273
|
broadcast(bytes, except) {
|
|
263
274
|
const pieces = E.chunkFrame(bytes, this.limits.maxFrameBytes);
|
|
264
|
-
for (const ws of this.
|
|
265
|
-
if (ws === except
|
|
275
|
+
for (const ws of this.sockets()) {
|
|
276
|
+
if (ws === except)
|
|
266
277
|
continue;
|
|
267
278
|
try {
|
|
268
279
|
for (const piece of pieces)
|
|
@@ -9,7 +9,7 @@ export declare const isId: (value: unknown) => value is Id;
|
|
|
9
9
|
* The clients of a frame (but `skip`) that write a per-writer block mark
|
|
10
10
|
* of another writer: a struct whose key is `del.<n>` or `wd.<n>` on a
|
|
11
11
|
* block node, from a client other than `n`. Only `n` writes its mark.
|
|
12
|
-
* A struct in the purge horizon's root forges the room's.
|
|
12
|
+
* A struct in the purge horizon's root, or the epoch's, forges the room's.
|
|
13
13
|
*/
|
|
14
14
|
export declare const forgedWriters: (doc: YDoc, structs: Struct[], skip: Set<number>) => Set<number>;
|
|
15
15
|
/**
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Forged writes: what a frame writes or deletes that its sender may not —
|
|
3
3
|
* another writer's per-writer block mark (`room.marks.writer`), the purge
|
|
4
|
-
* horizon (the room's alone), another replica's binding or another user's
|
|
4
|
+
* horizon and the epoch (the room's alone), another replica's binding or another user's
|
|
5
5
|
* profile in the attribution root (`room.attribution.trust`). Pure reads of
|
|
6
6
|
* the room document and the frame; `Admission` strips or drops what they
|
|
7
7
|
* find.
|
|
8
8
|
*/
|
|
9
9
|
import { Y } from '../../crdt/engine.js';
|
|
10
|
-
import { ATTRIBUTION_ROOT, DEL_PREFIX, HORIZON_ROOT, REGISTRY_KEY, SUGGEST_ROOT, WITHDRAW_PREFIX } from '../../crdt/schema.js';
|
|
10
|
+
import { ATTRIBUTION_ROOT, DEL_PREFIX, EPOCH_ROOT, HORIZON_ROOT, REGISTRY_KEY, SUGGEST_ROOT, WITHDRAW_PREFIX } from '../../crdt/schema.js';
|
|
11
11
|
import { heldClock, runsOf, storedStruct, structAt } from './updates.js';
|
|
12
12
|
// ── Per-writer marks ──────────────────────────────────────────
|
|
13
13
|
/** The writer `n` of a per-writer block mark key (`del.<n>`, `wd.<n>`), or `null`. */
|
|
@@ -63,14 +63,16 @@ const isBlockNode = (doc, frame, parent) => {
|
|
|
63
63
|
const item = parent?._item;
|
|
64
64
|
return item?.parent === registry && registry !== undefined;
|
|
65
65
|
};
|
|
66
|
-
/**
|
|
67
|
-
|
|
68
|
-
|
|
66
|
+
/**
|
|
67
|
+
* Is `parent` (a {@link Place}'s) a root only the room writes: the purge
|
|
68
|
+
* horizon's, or the epoch's (`room.reseed.protocol`)?
|
|
69
|
+
*/
|
|
70
|
+
const isRoomRoot = (doc, parent) => [HORIZON_ROOT, EPOCH_ROOT].some((root) => parent === root || (parent != null && parent === doc.share.get(root)));
|
|
69
71
|
/**
|
|
70
72
|
* The clients of a frame (but `skip`) that write a per-writer block mark
|
|
71
73
|
* of another writer: a struct whose key is `del.<n>` or `wd.<n>` on a
|
|
72
74
|
* block node, from a client other than `n`. Only `n` writes its mark.
|
|
73
|
-
* A struct in the purge horizon's root forges the room's.
|
|
75
|
+
* A struct in the purge horizon's root, or the epoch's, forges the room's.
|
|
74
76
|
*/
|
|
75
77
|
export const forgedWriters = (doc, structs, skip) => {
|
|
76
78
|
const frame = runsOf(structs);
|
|
@@ -83,7 +85,7 @@ export const forgedWriters = (doc, structs, skip) => {
|
|
|
83
85
|
continue;
|
|
84
86
|
const place = placeOf(doc, frame, struct.id);
|
|
85
87
|
const writer = markWriter(place?.key);
|
|
86
|
-
if ((place !== null &&
|
|
88
|
+
if ((place !== null && isRoomRoot(doc, place.parent)) ||
|
|
87
89
|
(writer !== null && writer !== client && isBlockNode(doc, frame, place.parent))) {
|
|
88
90
|
forged.add(client);
|
|
89
91
|
}
|
|
@@ -113,8 +115,8 @@ export const forgedDeletes = (doc, ds, mayDelete) => {
|
|
|
113
115
|
break;
|
|
114
116
|
if (!(struct instanceof Y.Item) || struct.deleted)
|
|
115
117
|
continue;
|
|
116
|
-
// The purge horizon
|
|
117
|
-
if (!
|
|
118
|
+
// The purge horizon and the epoch are the room's alone.
|
|
119
|
+
if (!isRoomRoot(doc, struct.parent)) {
|
|
118
120
|
const writer = markWriter(struct.parentSub);
|
|
119
121
|
if (writer === null || mayDelete(writer))
|
|
120
122
|
continue;
|
|
@@ -29,6 +29,8 @@ export declare const readOnlyFrame: () => Uint8Array;
|
|
|
29
29
|
export declare const readOnlyDenialFrame: () => Uint8Array;
|
|
30
30
|
/** The denial of what a suggest-only socket may not write (stripped): it stays, and still syncs. */
|
|
31
31
|
export declare const suggestOnlyDenialFrame: () => Uint8Array;
|
|
32
|
+
/** The room's epoch, to a socket that dialed an older one (`room.reseed.protocol`). */
|
|
33
|
+
export declare const epochFrame: (epoch: number) => Uint8Array;
|
|
32
34
|
/** The socket's access, at the join and at a change in place (`write`, `suggest`, `comment`, `read`). */
|
|
33
35
|
export declare const accessFrame: (access: string) => Uint8Array;
|
|
34
36
|
/** A Step2 of what the room STORED: the engine's pending store (never stored) is left out. */
|
|
@@ -51,6 +51,8 @@ export const readOnlyFrame = () => E.frame(E.messageAuth, (e) => E.writeReadOnly
|
|
|
51
51
|
export const readOnlyDenialFrame = () => E.frame(E.messageAuth, (e) => E.writePermissionDenied(e, READ_ONLY_DENIAL));
|
|
52
52
|
/** The denial of what a suggest-only socket may not write (stripped): it stays, and still syncs. */
|
|
53
53
|
export const suggestOnlyDenialFrame = () => E.frame(E.messageAuth, (e) => E.writePermissionDenied(e, SUGGEST_ONLY_DENIAL));
|
|
54
|
+
/** The room's epoch, to a socket that dialed an older one (`room.reseed.protocol`). */
|
|
55
|
+
export const epochFrame = (epoch) => E.frame(E.messageAuth, (e) => E.writeEpoch(e, epoch));
|
|
54
56
|
/** The socket's access, at the join and at a change in place (`write`, `suggest`, `comment`, `read`). */
|
|
55
57
|
export const accessFrame = (access) => E.frame(E.messageAuth, (e) => E.writeAccess(e, access));
|
|
56
58
|
/** A Step2 of what the room STORED: the engine's pending store (never stored) is left out. */
|
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
* the socket goes.
|
|
8
8
|
*/
|
|
9
9
|
import { semanticsMismatch } from '../../crdt/semantics.js';
|
|
10
|
-
import { SOCKET_TAG } from './shared.js';
|
|
11
10
|
import { allowance } from './admission.js';
|
|
12
11
|
import { encodeJSON } from './context.js';
|
|
13
12
|
import { encodePresenceEntry, presenceFrame, presenceFrameOf } from './frames.js';
|
|
@@ -142,9 +141,7 @@ export class RoomPresence {
|
|
|
142
141
|
* replica, and {@link drain} sends each recipient's in one frame.
|
|
143
142
|
*/
|
|
144
143
|
fanOut(entries) {
|
|
145
|
-
const sockets = this.room.
|
|
146
|
-
.getWebSockets(SOCKET_TAG)
|
|
147
|
-
.filter((socket) => socket.readyState === WebSocket.OPEN);
|
|
144
|
+
const sockets = this.room.sockets();
|
|
148
145
|
if (sockets.length === 0)
|
|
149
146
|
return;
|
|
150
147
|
if (this.waiting.size === 0 && this.take(sockets.length)) {
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import * as E from '../../crdt/protocol.js';
|
|
2
|
+
import type { YDoc } from '../../crdt/index.js';
|
|
3
|
+
import type { Attachment, SocketIdentity } from '../DocumentRoom.js';
|
|
4
|
+
import type { Decoded } from './context.js';
|
|
5
|
+
import { type RoomContext } from './context.js';
|
|
6
|
+
/** An epoch a dial names (`?epoch=`; `new`: a document that holds nothing yet), or `null`. */
|
|
7
|
+
export declare const parseEpoch: (raw: string | null) => number | "new" | null;
|
|
8
|
+
export declare class RoomReseed {
|
|
9
|
+
#private;
|
|
10
|
+
private readonly room;
|
|
11
|
+
constructor(room: RoomContext);
|
|
12
|
+
/** The re-seed's settings (`null`: off). */
|
|
13
|
+
get config(): {
|
|
14
|
+
at: number;
|
|
15
|
+
idleMs: number;
|
|
16
|
+
gain: number;
|
|
17
|
+
force: number;
|
|
18
|
+
graceDays: number;
|
|
19
|
+
} | null;
|
|
20
|
+
/** The room's epoch: what its document says (`epoch.n`, which only the room writes), 0 before a re-seed. */
|
|
21
|
+
get epoch(): number;
|
|
22
|
+
/**
|
|
23
|
+
* A change was stored at `at` (`room.reseed.timing`): past the
|
|
24
|
+
* threshold the re-seed is due once nobody writes for `idleMs` (each
|
|
25
|
+
* change pushes it back), past `force` at once.
|
|
26
|
+
*/
|
|
27
|
+
noteChange(at: number): void;
|
|
28
|
+
/**
|
|
29
|
+
* The `reseed` task: the cuts past their grace go (`room.reseed.grace`),
|
|
30
|
+
* then it re-seeds when still due (past the threshold and the floor); a
|
|
31
|
+
* re-seed that failed is due again at the first change a minute later or
|
|
32
|
+
* more. It is due again when the oldest cut left expires.
|
|
33
|
+
*/
|
|
34
|
+
task(): void;
|
|
35
|
+
/**
|
|
36
|
+
* Re-seed now (`room.reseed.cut`): the new epoch replaces the rows, in
|
|
37
|
+
* one storage transaction with its cut; the replica registry, the
|
|
38
|
+
* purge's epochs and the last restore's step go (they name the old
|
|
39
|
+
* identities); the live document is rebuilt from the rows and every
|
|
40
|
+
* socket closed `4410`. `idle` (the task, once nobody wrote) waits while
|
|
41
|
+
* a suggestion is pending (an idle period later); `full` (the task, past
|
|
42
|
+
* `force` of the quota) drops them; both do nothing when the new epoch
|
|
43
|
+
* would give back less than `gain` (and wait for the document to grow by
|
|
44
|
+
* a quarter of `at` before trying again). `manual` (`reseed()`) runs
|
|
45
|
+
* whatever it gives back and drops them. Answers the new epoch, or `null`.
|
|
46
|
+
*/
|
|
47
|
+
run(mode: 'idle' | 'full' | 'manual'): number | null;
|
|
48
|
+
/**
|
|
49
|
+
* The door (`RoomAccess.accept`, `room.reseed.protocol`): a dial of
|
|
50
|
+
* epoch `asked` is current, stale (an older epoch whose cuts are kept),
|
|
51
|
+
* or closed: none, in a room that re-seeded, `1008` (a client that
|
|
52
|
+
* predates the re-seed); any other epoch the room cannot rebase (past
|
|
53
|
+
* the cuts kept, or later than its own: the room lost it), `4410`, so
|
|
54
|
+
* the client drops its copy and loads the room's.
|
|
55
|
+
*/
|
|
56
|
+
door(asked: number | 'new' | null): 'current' | 'stale' | {
|
|
57
|
+
code: number;
|
|
58
|
+
reason: string;
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* Whether `decoded`, from a socket of the current epoch, holds an older
|
|
62
|
+
* epoch's content (`room.reseed.protocol`): a struct of a client the
|
|
63
|
+
* cuts kept name, which the document holds nothing of (a tab took it
|
|
64
|
+
* from another tab of the old epoch). Its socket is closed `4410`.
|
|
65
|
+
*/
|
|
66
|
+
holdsOld(decoded: Decoded, doc: YDoc): boolean;
|
|
67
|
+
/** The largest frame a socket of an older epoch may send: its whole old document. */
|
|
68
|
+
get staleFrameBytes(): number;
|
|
69
|
+
/**
|
|
70
|
+
* A stale socket joined: one that may write is told the room's epoch
|
|
71
|
+
* (its provider then hands over its old document); any other has no
|
|
72
|
+
* edit to merge and is closed `4410`. Past its user's rebase rate it is
|
|
73
|
+
* closed `1011` before it uploads anything: its provider dials again
|
|
74
|
+
* later.
|
|
75
|
+
*/
|
|
76
|
+
join(ws: WebSocket, identity: SocketIdentity): void;
|
|
77
|
+
/**
|
|
78
|
+
* A stale socket's message: its old document (`messageRebase`) is
|
|
79
|
+
* rebased onto a copy of the current one, and what that wrote is
|
|
80
|
+
* admitted as an update of its user, from a client id of its own (the
|
|
81
|
+
* admission's quotas, access, validation and attribution, as any
|
|
82
|
+
* update); then it is closed `4410`. The merged state is kept per user
|
|
83
|
+
* and cut (`merged:<user>`), so another tab's upload merges nothing
|
|
84
|
+
* twice and another user's cannot claim it. A hand-over that cannot be
|
|
85
|
+
* read or rebased is dropped, its socket closed `4410` all the same (its
|
|
86
|
+
* client loads the room's document); past the rebase rate (one per user
|
|
87
|
+
* every ten seconds), `1011`, and the provider hands over again later.
|
|
88
|
+
* Anything else a stale socket sends is dropped.
|
|
89
|
+
*/
|
|
90
|
+
onStale(ws: WebSocket, attachment: Attachment, type: number, decoder: E.Decoder): void;
|
|
91
|
+
/** Drop the cuts older than the grace, with what their rebases merged (`room.reseed.grace`). */
|
|
92
|
+
prune(at: number): void;
|
|
93
|
+
}
|