@tita-agent/dsh-data-table 0.0.0-stage → 0.2.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/LICENSE +21 -0
- package/README.md +172 -2
- package/cordis.patch.yml +7 -0
- package/lib/client.js +16766 -0
- package/lib/contract-envelope.d.ts +91 -0
- package/lib/contract-envelope.js +106 -0
- package/lib/contract-layout.d.ts +130 -0
- package/lib/contract-layout.js +138 -0
- package/lib/contract-refs.d.ts +39 -0
- package/lib/contract-refs.js +9 -0
- package/lib/contract-version.d.ts +311 -0
- package/lib/contract-version.js +270 -0
- package/lib/contract-wire.d.ts +147 -0
- package/lib/contract-wire.js +99 -0
- package/lib/contracts.d.ts +12 -0
- package/lib/contracts.js +12 -0
- package/lib/types/audit.d.ts +42 -0
- package/lib/types/audit.js +39 -0
- package/lib/types/client/ProjectImportMenu.d.ts +30 -0
- package/lib/types/client/ProjectImportMenu.js +70 -0
- package/lib/types/client/SheetPanel.d.ts +33 -0
- package/lib/types/client/SheetPanel.js +1766 -0
- package/lib/types/client/SheetToggle.d.ts +18 -0
- package/lib/types/client/SheetToggle.js +26 -0
- package/lib/types/client/index.d.ts +15 -0
- package/lib/types/client/index.js +110 -0
- package/lib/types/client/persistence/changes.d.ts +15 -0
- package/lib/types/client/persistence/changes.js +51 -0
- package/lib/types/client/persistence/ids.d.ts +34 -0
- package/lib/types/client/persistence/ids.js +48 -0
- package/lib/types/client/persistence/merge.d.ts +35 -0
- package/lib/types/client/persistence/merge.js +362 -0
- package/lib/types/client/store.d.ts +61 -0
- package/lib/types/client/store.js +152 -0
- package/lib/types/client/surface-context.d.ts +27 -0
- package/lib/types/client/surface-context.js +104 -0
- package/lib/types/client/surface-control.d.ts +2 -0
- package/lib/types/client/surface-control.js +12 -0
- package/lib/types/client/transport/workbookApi.d.ts +159 -0
- package/lib/types/client/transport/workbookApi.js +246 -0
- package/lib/types/client/univer/StandaloneWorkbookPage.d.ts +5 -0
- package/lib/types/client/univer/StandaloneWorkbookPage.js +7 -0
- package/lib/types/client/univer/WorkbookCanvas.d.ts +40 -0
- package/lib/types/client/univer/WorkbookCanvas.js +87 -0
- package/lib/types/client/univer/WorkbookView.d.ts +3 -0
- package/lib/types/client/univer/WorkbookView.js +2 -0
- package/lib/types/client/univer/loader.d.ts +18 -0
- package/lib/types/client/univer/loader.js +81 -0
- package/lib/types/client/univer/standalone-entry.d.ts +1 -0
- package/lib/types/client/univer/standalone-entry.js +19 -0
- package/lib/types/client/versions/VersionChrome.d.ts +33 -0
- package/lib/types/client/versions/VersionChrome.js +21 -0
- package/lib/types/client/versions/inspect.d.ts +70 -0
- package/lib/types/client/versions/inspect.js +88 -0
- package/lib/types/client/versions/preview-decoration.d.ts +11 -0
- package/lib/types/client/versions/preview-decoration.js +54 -0
- package/lib/types/client/versions/records.d.ts +19 -0
- package/lib/types/client/versions/records.js +70 -0
- package/lib/types/client/workspace-host.d.ts +61 -0
- package/lib/types/client/workspace-host.js +124 -0
- package/lib/types/collaboration-hub.d.ts +31 -0
- package/lib/types/collaboration-hub.js +69 -0
- package/lib/types/contract/ids.d.ts +24 -0
- package/lib/types/contract/ids.js +46 -0
- package/lib/types/contract/mutations.d.ts +25 -0
- package/lib/types/contract/mutations.js +782 -0
- package/lib/types/contract/operations.d.ts +54 -0
- package/lib/types/contract/operations.js +203 -0
- package/lib/types/contract/snapshots.d.ts +176 -0
- package/lib/types/contract/snapshots.js +351 -0
- package/lib/types/contract/univer-api-catalog.d.ts +29 -0
- package/lib/types/contract/univer-api-catalog.js +264 -0
- package/lib/types/errors.d.ts +8 -0
- package/lib/types/errors.js +12 -0
- package/lib/types/http/assets-routes.d.ts +3 -0
- package/lib/types/http/assets-routes.js +169 -0
- package/lib/types/http/collaboration.d.ts +10 -0
- package/lib/types/http/collaboration.js +154 -0
- package/lib/types/http/history.d.ts +15 -0
- package/lib/types/http/history.js +134 -0
- package/lib/types/http/project-files.d.ts +79 -0
- package/lib/types/http/project-files.js +206 -0
- package/lib/types/http/project-scope.d.ts +50 -0
- package/lib/types/http/project-scope.js +52 -0
- package/lib/types/http/routes.d.ts +98 -0
- package/lib/types/http/routes.js +323 -0
- package/lib/types/http/standalone.d.ts +9 -0
- package/lib/types/http/standalone.js +31 -0
- package/lib/types/http/trunk.d.ts +10 -0
- package/lib/types/http/trunk.js +322 -0
- package/lib/types/http/worktree.d.ts +9 -0
- package/lib/types/http/worktree.js +145 -0
- package/lib/types/index.d.ts +18 -0
- package/lib/types/index.js +156 -0
- package/lib/types/invariant.d.ts +15 -0
- package/lib/types/invariant.js +15 -0
- package/lib/types/request-params.d.ts +21 -0
- package/lib/types/request-params.js +76 -0
- package/lib/types/store/paths.d.ts +68 -0
- package/lib/types/store/paths.js +148 -0
- package/lib/types/store/project.d.ts +88 -0
- package/lib/types/store/project.js +120 -0
- package/lib/types/store/read.d.ts +110 -0
- package/lib/types/store/read.js +404 -0
- package/lib/types/store/retention.d.ts +27 -0
- package/lib/types/store/retention.js +111 -0
- package/lib/types/store/write.d.ts +22 -0
- package/lib/types/store/write.js +210 -0
- package/lib/types/tools/arguments.d.ts +40 -0
- package/lib/types/tools/arguments.js +130 -0
- package/lib/types/tools/cells.d.ts +50 -0
- package/lib/types/tools/cells.js +298 -0
- package/lib/types/tools/index.d.ts +2 -0
- package/lib/types/tools/index.js +250 -0
- package/lib/types/tools/render.d.ts +47 -0
- package/lib/types/tools/render.js +290 -0
- package/lib/types/tools/univer-api.d.ts +18 -0
- package/lib/types/tools/univer-api.js +198 -0
- package/lib/types/tools/workbook-catalog.d.ts +3 -0
- package/lib/types/tools/workbook-catalog.js +83 -0
- package/lib/types/tools/workbook-edit.d.ts +192 -0
- package/lib/types/tools/workbook-edit.js +912 -0
- package/lib/types/tools/workbook-find.d.ts +11 -0
- package/lib/types/tools/workbook-find.js +89 -0
- package/lib/types/tools/workbook-history.d.ts +2 -0
- package/lib/types/tools/workbook-history.js +59 -0
- package/lib/types/tools/workbook-read.d.ts +21 -0
- package/lib/types/tools/workbook-read.js +204 -0
- package/lib/types/types.d.ts +377 -0
- package/lib/types/types.js +34 -0
- package/lib/types/univer/apply-operation.d.ts +14 -0
- package/lib/types/univer/apply-operation.js +398 -0
- package/lib/types/univer/chunk.d.ts +68 -0
- package/lib/types/univer/chunk.js +16 -0
- package/lib/types/univer/decoration.d.ts +34 -0
- package/lib/types/univer/decoration.js +88 -0
- package/lib/types/univer/diagnostics.d.ts +31 -0
- package/lib/types/univer/diagnostics.js +141 -0
- package/lib/types/univer/engine.d.ts +33 -0
- package/lib/types/univer/engine.js +338 -0
- package/lib/types/univer/entry.d.ts +8 -0
- package/lib/types/univer/entry.js +11 -0
- package/lib/types/univer/facade.d.ts +107 -0
- package/lib/types/univer/facade.js +1 -0
- package/lib/types/univer/fonts.d.ts +202 -0
- package/lib/types/univer/fonts.js +140 -0
- package/lib/types/univer/plugins/collaboration.d.ts +23 -0
- package/lib/types/univer/plugins/collaboration.js +47 -0
- package/lib/types/univer/plugins/export.d.ts +39 -0
- package/lib/types/univer/plugins/export.js +246 -0
- package/lib/types/univer/plugins/history.d.ts +24 -0
- package/lib/types/univer/plugins/history.js +50 -0
- package/lib/types/univer/plugins/version.d.ts +13 -0
- package/lib/types/univer/plugins/version.js +13 -0
- package/lib/types/version/diff.d.ts +36 -0
- package/lib/types/version/diff.js +156 -0
- package/lib/types/version/grouping.d.ts +7 -0
- package/lib/types/version/grouping.js +94 -0
- package/lib/types/version/records.d.ts +17 -0
- package/lib/types/version/records.js +102 -0
- package/lib/types/version/session.d.ts +36 -0
- package/lib/types/version/session.js +89 -0
- package/lib/types/version/summary.d.ts +24 -0
- package/lib/types/version/summary.js +111 -0
- package/lib/types/workbook-manager.d.ts +191 -0
- package/lib/types/workbook-manager.js +935 -0
- package/lib/types/xlsx-export-worker.d.ts +5 -0
- package/lib/types/xlsx-export-worker.js +24 -0
- package/lib/types/xlsx-export.d.ts +21 -0
- package/lib/types/xlsx-export.js +371 -0
- package/lib/types/xlsx-import-worker.d.ts +1 -0
- package/lib/types/xlsx-import-worker.js +19 -0
- package/lib/univer-client.js +690 -0
- package/lib/workbook-page.js +23826 -0
- package/lib/xlsx-export-worker.js +104 -0
- package/lib/xlsx-import-worker.js +46 -0
- package/package.json +106 -3
- package/src/audit.ts +58 -0
- package/src/client/ProjectImportMenu.tsx +100 -0
- package/src/client/SheetPanel.module.css +1578 -0
- package/src/client/SheetPanel.tsx +1934 -0
- package/src/client/SheetToggle.module.css +73 -0
- package/src/client/SheetToggle.tsx +65 -0
- package/src/client/contract.d.ts +19 -0
- package/src/client/index.ts +131 -0
- package/src/client/persistence/changes.ts +58 -0
- package/src/client/persistence/ids.ts +60 -0
- package/src/client/persistence/merge.ts +392 -0
- package/src/client/store.ts +188 -0
- package/src/client/surface-context.ts +123 -0
- package/src/client/surface-control.ts +13 -0
- package/src/client/transport/workbookApi.ts +355 -0
- package/src/client/univer/SheetView.module.css +110 -0
- package/src/client/univer/StandaloneWorkbookPage.module.css +8 -0
- package/src/client/univer/StandaloneWorkbookPage.tsx +15 -0
- package/src/client/univer/WorkbookCanvas.tsx +128 -0
- package/src/client/univer/WorkbookView.module.css +30 -0
- package/src/client/univer/WorkbookView.tsx +3 -0
- package/src/client/univer/loader.ts +90 -0
- package/src/client/univer/react-dom-client.d.ts +10 -0
- package/src/client/univer/standalone-entry.tsx +19 -0
- package/src/client/univer/standalone.css +12 -0
- package/src/client/univer/univer-locales.d.ts +89 -0
- package/src/client/univer/univer-modules.d.ts +26 -0
- package/src/client/versions/VersionChrome.tsx +114 -0
- package/src/client/versions/inspect.ts +138 -0
- package/src/client/versions/preview-decoration.ts +54 -0
- package/src/client/versions/records.ts +78 -0
- package/src/client/workspace-host.ts +147 -0
- package/src/collaboration-hub.ts +83 -0
- package/src/contract/ids.ts +50 -0
- package/src/contract/mutations.ts +791 -0
- package/src/contract/operations.ts +221 -0
- package/src/contract/snapshots.ts +383 -0
- package/src/contract/univer-api-catalog.ts +289 -0
- package/src/css-modules.d.ts +6 -0
- package/src/errors.ts +25 -0
- package/src/http/assets-routes.ts +177 -0
- package/src/http/collaboration.ts +144 -0
- package/src/http/history.ts +151 -0
- package/src/http/project-files.ts +227 -0
- package/src/http/project-scope.ts +77 -0
- package/src/http/routes.ts +364 -0
- package/src/http/standalone.ts +32 -0
- package/src/http/trunk.ts +322 -0
- package/src/http/worktree.ts +119 -0
- package/src/index.ts +165 -0
- package/src/invariant.ts +17 -0
- package/src/request-params.ts +92 -0
- package/src/store/paths.ts +165 -0
- package/src/store/project.ts +137 -0
- package/src/store/read.ts +454 -0
- package/src/store/retention.ts +106 -0
- package/src/store/write.ts +230 -0
- package/src/tools/arguments.ts +128 -0
- package/src/tools/cells.ts +298 -0
- package/src/tools/index.ts +274 -0
- package/src/tools/render.ts +301 -0
- package/src/tools/univer-api.ts +243 -0
- package/src/tools/workbook-catalog.ts +94 -0
- package/src/tools/workbook-edit.ts +987 -0
- package/src/tools/workbook-find.ts +80 -0
- package/src/tools/workbook-history.ts +63 -0
- package/src/tools/workbook-read.ts +210 -0
- package/src/types.ts +432 -0
- package/src/univer/apply-operation.ts +369 -0
- package/src/univer/chunk.ts +77 -0
- package/src/univer/decoration.ts +111 -0
- package/src/univer/diagnostics.ts +136 -0
- package/src/univer/engine.ts +370 -0
- package/src/univer/entry.ts +14 -0
- package/src/univer/facade.ts +91 -0
- package/src/univer/fonts.ts +148 -0
- package/src/univer/overrides.css +33 -0
- package/src/univer/plugins/collaboration.ts +47 -0
- package/src/univer/plugins/export.ts +236 -0
- package/src/univer/plugins/history.ts +49 -0
- package/src/univer/plugins/version.ts +13 -0
- package/src/version/diff.ts +169 -0
- package/src/version/grouping.ts +96 -0
- package/src/version/records.ts +113 -0
- package/src/version/session.ts +90 -0
- package/src/version/summary.ts +117 -0
- package/src/workbook-manager.ts +1111 -0
- package/src/xlsx-export-worker.ts +34 -0
- package/src/xlsx-export.ts +373 -0
- package/src/xlsx-import-worker.ts +30 -0
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resident host for the embedded Table workspace.
|
|
3
|
+
*
|
|
4
|
+
* The dock renders only the active tab's body (`DockSurface` → `renderTab`), so
|
|
5
|
+
* switching DSH tabs — or switching conversation sessions — unmounts the pane's
|
|
6
|
+
* React tree. When the workspace lived in that tree, every re-entry disposed the
|
|
7
|
+
* Univer engine, re-fetched the whole snapshot and rebuilt the sheet, which is
|
|
8
|
+
* exactly the "reloads on every visit" the panel used to show.
|
|
9
|
+
*
|
|
10
|
+
* The workspace therefore lives in one long-lived container that is created
|
|
11
|
+
* once and merely *moves* between the pane and an off-screen parking lot. Re-
|
|
12
|
+
* entering the tab re-parents the existing DOM and React tree, so the editor,
|
|
13
|
+
* its scroll position, its unsaved drafts and its collaboration stream all
|
|
14
|
+
* survive. A long stay in the parking lot releases it again, so the engine is
|
|
15
|
+
* not held for the life of the page either.
|
|
16
|
+
*
|
|
17
|
+
* The DOM access and the timer are injected so the adoption/parking bookkeeping
|
|
18
|
+
* can be tested without a browser (this repository has no DOM test
|
|
19
|
+
* environment).
|
|
20
|
+
*
|
|
21
|
+
* @module dsh-data-table/client/workspace-host
|
|
22
|
+
*/
|
|
23
|
+
/** How long a parked workspace is kept warm before it is released. */
|
|
24
|
+
export const PARKED_RELEASE_MS = 10 * 60 * 1000;
|
|
25
|
+
/** Off-screen geometry: keeps the engine's measured size while it is not shown. */
|
|
26
|
+
const PARKED_STYLE = 'position:fixed;left:-20000px;top:0;overflow:hidden;pointer-events:none;contain:strict;';
|
|
27
|
+
const ADOPTED_STYLE = 'width:100%;height:100%;min-width:0;min-height:0;display:flex;flex-direction:column;';
|
|
28
|
+
const domEnvironment = {
|
|
29
|
+
createContainer: () => {
|
|
30
|
+
const element = document.createElement('div');
|
|
31
|
+
element.setAttribute('data-data-table-workspace', '');
|
|
32
|
+
return element;
|
|
33
|
+
},
|
|
34
|
+
createParkingLot: () => {
|
|
35
|
+
const element = document.createElement('div');
|
|
36
|
+
element.setAttribute('data-data-table-parked', '');
|
|
37
|
+
element.style.cssText = `${PARKED_STYLE}width:0;height:0;`;
|
|
38
|
+
return element;
|
|
39
|
+
},
|
|
40
|
+
body: () => document.body,
|
|
41
|
+
schedule: (callback, delayMs) => globalThis.setTimeout(callback, delayMs),
|
|
42
|
+
cancel: handle => { globalThis.clearTimeout(handle); },
|
|
43
|
+
};
|
|
44
|
+
let environment = domEnvironment;
|
|
45
|
+
let container = null;
|
|
46
|
+
let parkingLot = null;
|
|
47
|
+
let releaseTimer = null;
|
|
48
|
+
let unmount = null;
|
|
49
|
+
/** Replace the DOM environment (tests only). Resets any resident workspace. */
|
|
50
|
+
export function setWorkspaceHostEnvironment(next) {
|
|
51
|
+
environment = next;
|
|
52
|
+
releaseTimer = null;
|
|
53
|
+
unmount = null;
|
|
54
|
+
container = null;
|
|
55
|
+
parkingLot = null;
|
|
56
|
+
}
|
|
57
|
+
/** The resident container, or null when nothing is resident. */
|
|
58
|
+
export function workspaceHostElement() {
|
|
59
|
+
return container;
|
|
60
|
+
}
|
|
61
|
+
/** Whether the resident workspace is currently parked off-screen. */
|
|
62
|
+
export function isWorkspaceHostParked() {
|
|
63
|
+
return container !== null && container.parentElement === parking();
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Put the resident workspace inside `target`, creating it on first use.
|
|
67
|
+
* @param target - the pane element that should display the workspace.
|
|
68
|
+
* @param mount - called once per workspace lifetime; may return a disposer.
|
|
69
|
+
* @returns the resident container.
|
|
70
|
+
*/
|
|
71
|
+
export function adoptWorkspaceHost(target, mount) {
|
|
72
|
+
if (container === null) {
|
|
73
|
+
container = environment.createContainer();
|
|
74
|
+
unmount = mount(container) ?? null;
|
|
75
|
+
}
|
|
76
|
+
cancelRelease();
|
|
77
|
+
if (container.parentElement === target)
|
|
78
|
+
return container;
|
|
79
|
+
container.style.cssText = ADOPTED_STYLE;
|
|
80
|
+
target.append(container);
|
|
81
|
+
return container;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Move the resident workspace off-screen without destroying it.
|
|
85
|
+
*
|
|
86
|
+
* Its measured size is kept so the engine sees no resize while parked; that is
|
|
87
|
+
* what makes re-adoption invisible instead of a relayout. The workspace is
|
|
88
|
+
* released after {@link PARKED_RELEASE_MS} so a tab the user has moved on from
|
|
89
|
+
* does not pin a whole engine for the life of the page.
|
|
90
|
+
*/
|
|
91
|
+
export function parkWorkspaceHost() {
|
|
92
|
+
if (container === null || container.parentElement === null)
|
|
93
|
+
return;
|
|
94
|
+
const rect = container.getBoundingClientRect();
|
|
95
|
+
container.style.cssText = `${PARKED_STYLE}width:${Math.max(Math.round(rect.width), 320)}px;height:${Math.max(Math.round(rect.height), 240)}px;`;
|
|
96
|
+
parking().append(container);
|
|
97
|
+
cancelRelease();
|
|
98
|
+
releaseTimer = environment.schedule(() => { releaseTimer = null; disposeWorkspaceHost(); }, PARKED_RELEASE_MS);
|
|
99
|
+
}
|
|
100
|
+
/** Release the resident workspace, unmounting its React tree. Safe when empty. */
|
|
101
|
+
export function disposeWorkspaceHost() {
|
|
102
|
+
cancelRelease();
|
|
103
|
+
const dispose = unmount;
|
|
104
|
+
unmount = null;
|
|
105
|
+
container?.remove();
|
|
106
|
+
parkingLot?.remove();
|
|
107
|
+
container = null;
|
|
108
|
+
parkingLot = null;
|
|
109
|
+
// Unmount last: the disposer tears down effects that may still touch the DOM.
|
|
110
|
+
dispose?.();
|
|
111
|
+
}
|
|
112
|
+
function cancelRelease() {
|
|
113
|
+
if (releaseTimer === null)
|
|
114
|
+
return;
|
|
115
|
+
environment.cancel(releaseTimer);
|
|
116
|
+
releaseTimer = null;
|
|
117
|
+
}
|
|
118
|
+
function parking() {
|
|
119
|
+
if (parkingLot === null || parkingLot.parentElement === null) {
|
|
120
|
+
parkingLot = environment.createParkingLot();
|
|
121
|
+
environment.body().append(parkingLot);
|
|
122
|
+
}
|
|
123
|
+
return parkingLot;
|
|
124
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-process collaboration transport for Datasheet.
|
|
3
|
+
*
|
|
4
|
+
* This is deliberately small and dependency-free. It provides the same
|
|
5
|
+
* server-to-client fan-out seam that a WebSocket/Univer collaboration server
|
|
6
|
+
* would provide, while keeping the DSH plugin self-contained. Durable state
|
|
7
|
+
* still lives in WorkbookManager; the hub is only a live notification layer.
|
|
8
|
+
*/
|
|
9
|
+
import type { WorkbookOperation, WorkbookPresence } from './types.ts';
|
|
10
|
+
export interface WorkbookCollaborationEvent {
|
|
11
|
+
workbookId: string;
|
|
12
|
+
operation: WorkbookOperation;
|
|
13
|
+
}
|
|
14
|
+
type WorkbookCollaborationListener = (event: WorkbookCollaborationEvent) => void;
|
|
15
|
+
export declare const MAX_LISTENERS_PER_WORKBOOK = 64;
|
|
16
|
+
export interface WorkbookPresenceEvent {
|
|
17
|
+
workbookId: string;
|
|
18
|
+
presence: WorkbookPresence;
|
|
19
|
+
}
|
|
20
|
+
type WorkbookPresenceListener = (event: WorkbookPresenceEvent) => void;
|
|
21
|
+
/** Presence is intentionally capped separately from durable operation streams. */
|
|
22
|
+
export declare const MAX_PRESENCE_LISTENERS_PER_WORKBOOK = 128;
|
|
23
|
+
/** Subscribe to committed operations for one workbook. */
|
|
24
|
+
export declare function subscribeWorkbookCollaboration(workbookId: string, listener: WorkbookCollaborationListener): () => void;
|
|
25
|
+
/** Fan out a committed operation to currently connected workbook sessions. */
|
|
26
|
+
export declare function publishWorkbookCollaboration(operation: WorkbookOperation): void;
|
|
27
|
+
/** Subscribe to ephemeral selection/editing state for one workbook. */
|
|
28
|
+
export declare function subscribeWorkbookPresence(workbookId: string, listener: WorkbookPresenceListener): () => void;
|
|
29
|
+
/** Fan out ephemeral presence without touching WorkbookManager or revision. */
|
|
30
|
+
export declare function publishWorkbookPresence(presence: WorkbookPresence): void;
|
|
31
|
+
export {};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-process collaboration transport for Datasheet.
|
|
3
|
+
*
|
|
4
|
+
* This is deliberately small and dependency-free. It provides the same
|
|
5
|
+
* server-to-client fan-out seam that a WebSocket/Univer collaboration server
|
|
6
|
+
* would provide, while keeping the DSH plugin self-contained. Durable state
|
|
7
|
+
* still lives in WorkbookManager; the hub is only a live notification layer.
|
|
8
|
+
*/
|
|
9
|
+
const listeners = new Map();
|
|
10
|
+
export const MAX_LISTENERS_PER_WORKBOOK = 64;
|
|
11
|
+
const presenceListeners = new Map();
|
|
12
|
+
/** Presence is intentionally capped separately from durable operation streams. */
|
|
13
|
+
export const MAX_PRESENCE_LISTENERS_PER_WORKBOOK = 128;
|
|
14
|
+
/** Subscribe to committed operations for one workbook. */
|
|
15
|
+
export function subscribeWorkbookCollaboration(workbookId, listener) {
|
|
16
|
+
const current = listeners.get(workbookId) ?? new Set();
|
|
17
|
+
if (current.size >= MAX_LISTENERS_PER_WORKBOOK) {
|
|
18
|
+
throw new Error(`工作簿协同连接数已达上限(最多 ${MAX_LISTENERS_PER_WORKBOOK} 个)`);
|
|
19
|
+
}
|
|
20
|
+
current.add(listener);
|
|
21
|
+
listeners.set(workbookId, current);
|
|
22
|
+
return () => {
|
|
23
|
+
current.delete(listener);
|
|
24
|
+
if (current.size === 0 && listeners.get(workbookId) === current)
|
|
25
|
+
listeners.delete(workbookId);
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
/** Fan out a committed operation to currently connected workbook sessions. */
|
|
29
|
+
export function publishWorkbookCollaboration(operation) {
|
|
30
|
+
const current = listeners.get(operation.workbookId);
|
|
31
|
+
if (current === undefined)
|
|
32
|
+
return;
|
|
33
|
+
const event = { workbookId: operation.workbookId, operation };
|
|
34
|
+
for (const listener of [...current]) {
|
|
35
|
+
try {
|
|
36
|
+
listener(event);
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
// A disconnected response must not affect persistence or other clients.
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/** Subscribe to ephemeral selection/editing state for one workbook. */
|
|
44
|
+
export function subscribeWorkbookPresence(workbookId, listener) {
|
|
45
|
+
const current = presenceListeners.get(workbookId) ?? new Set();
|
|
46
|
+
if (current.size >= MAX_PRESENCE_LISTENERS_PER_WORKBOOK) {
|
|
47
|
+
throw new Error(`工作簿 presence 连接数已达上限(最多 ${MAX_PRESENCE_LISTENERS_PER_WORKBOOK} 个)`);
|
|
48
|
+
}
|
|
49
|
+
current.add(listener);
|
|
50
|
+
presenceListeners.set(workbookId, current);
|
|
51
|
+
return () => {
|
|
52
|
+
current.delete(listener);
|
|
53
|
+
if (current.size === 0 && presenceListeners.get(workbookId) === current)
|
|
54
|
+
presenceListeners.delete(workbookId);
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
/** Fan out ephemeral presence without touching WorkbookManager or revision. */
|
|
58
|
+
export function publishWorkbookPresence(presence) {
|
|
59
|
+
const current = presenceListeners.get(presence.workbookId);
|
|
60
|
+
if (current === undefined)
|
|
61
|
+
return;
|
|
62
|
+
const event = { workbookId: presence.workbookId, presence };
|
|
63
|
+
for (const listener of [...current]) {
|
|
64
|
+
try {
|
|
65
|
+
listener(event);
|
|
66
|
+
}
|
|
67
|
+
catch { /* disconnected clients are harmless */ }
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalize a workbook id to a safe file name segment.
|
|
3
|
+
*
|
|
4
|
+
* The character set is the shared one (`storageSegment`), so a name that survives
|
|
5
|
+
* in one plugin survives in the next: it keeps 汉字 — the id *is* the file name,
|
|
6
|
+
* and a newly created workbook is named `yyyymmdd-中文名` (see `storageNameOf` in
|
|
7
|
+
* `tools/workbook-catalog.ts`) — while spaces, punctuation and path separators
|
|
8
|
+
* become `-`.
|
|
9
|
+
*
|
|
10
|
+
* Deliberately no date prefix and no truncation here: this runs on every lookup,
|
|
11
|
+
* including ids minted by earlier versions, and "normalizing" an existing id is
|
|
12
|
+
* renaming someone's file.
|
|
13
|
+
*/
|
|
14
|
+
export declare function normalizeWorkbookId(id: string): string;
|
|
15
|
+
/** Normalize an isolated worktree id to a safe file-name segment. */
|
|
16
|
+
export declare function normalizeWorktreeId(id: string): string;
|
|
17
|
+
/** Mint a fresh worktree id, for the callers that do not name one. */
|
|
18
|
+
export declare function newWorktreeId(): string;
|
|
19
|
+
/**
|
|
20
|
+
* Id of the Version that continues `previousVersionId`. A continuation keeps
|
|
21
|
+
* the `user-version:` prefix the store groups by, so it is a Version like any
|
|
22
|
+
* other rather than a second kind of thing.
|
|
23
|
+
*/
|
|
24
|
+
export declare function nextContinuationVersionId(workbookId: string, previousVersionId: string): string;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Identifier vocabulary of the workbook repository (docs/issue/0022 P0).
|
|
3
|
+
*
|
|
4
|
+
* Pure string work plus one id mint: it knows nothing about the disk, about
|
|
5
|
+
* Univer, or about Versions as a concept. It is the node half's vocabulary —
|
|
6
|
+
* the browser addresses ids as opaque strings and never mints a workbook,
|
|
7
|
+
* worktree or Version id — but nothing here reads or writes anything, so the
|
|
8
|
+
* split is about who *creates* ids, not about what they are.
|
|
9
|
+
*/
|
|
10
|
+
import { randomUUID } from 'node:crypto';
|
|
11
|
+
import { storageSegment } from '#contracts';
|
|
12
|
+
import { DEFAULT_WORKBOOK } from "../types.js";
|
|
13
|
+
/**
|
|
14
|
+
* Normalize a workbook id to a safe file name segment.
|
|
15
|
+
*
|
|
16
|
+
* The character set is the shared one (`storageSegment`), so a name that survives
|
|
17
|
+
* in one plugin survives in the next: it keeps 汉字 — the id *is* the file name,
|
|
18
|
+
* and a newly created workbook is named `yyyymmdd-中文名` (see `storageNameOf` in
|
|
19
|
+
* `tools/workbook-catalog.ts`) — while spaces, punctuation and path separators
|
|
20
|
+
* become `-`.
|
|
21
|
+
*
|
|
22
|
+
* Deliberately no date prefix and no truncation here: this runs on every lookup,
|
|
23
|
+
* including ids minted by earlier versions, and "normalizing" an existing id is
|
|
24
|
+
* renaming someone's file.
|
|
25
|
+
*/
|
|
26
|
+
export function normalizeWorkbookId(id) {
|
|
27
|
+
const safe = storageSegment(id);
|
|
28
|
+
return safe.length === 0 ? DEFAULT_WORKBOOK : safe;
|
|
29
|
+
}
|
|
30
|
+
/** Normalize an isolated worktree id to a safe file-name segment. */
|
|
31
|
+
export function normalizeWorktreeId(id) {
|
|
32
|
+
const safe = storageSegment(id);
|
|
33
|
+
return safe.length === 0 ? newWorktreeId() : safe;
|
|
34
|
+
}
|
|
35
|
+
/** Mint a fresh worktree id, for the callers that do not name one. */
|
|
36
|
+
export function newWorktreeId() {
|
|
37
|
+
return `wt-${randomUUID().slice(0, 8)}`;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Id of the Version that continues `previousVersionId`. A continuation keeps
|
|
41
|
+
* the `user-version:` prefix the store groups by, so it is a Version like any
|
|
42
|
+
* other rather than a second kind of thing.
|
|
43
|
+
*/
|
|
44
|
+
export function nextContinuationVersionId(workbookId, previousVersionId) {
|
|
45
|
+
return `user-version:${workbookId}:continuation:${previousVersionId.slice(-24)}:${randomUUID().slice(0, 8)}`;
|
|
46
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The snapshot mutator: one DSH operation in, the rewritten snapshot out
|
|
3
|
+
* (docs/issue/0022 P0/P1).
|
|
4
|
+
*
|
|
5
|
+
* Pure and Univer-free — it is the model's own answer to "what does this
|
|
6
|
+
* operation mean", and `store/read.ts` replays operations through it when a
|
|
7
|
+
* workbook's snapshot is older than its revision. It lives in `contract/`
|
|
8
|
+
* rather than in `store/` precisely because it is not about the disk: moving
|
|
9
|
+
* the read path into the store without it would have made `store/` import
|
|
10
|
+
* *up* into `workbook-manager`, which the architecture guard forbids.
|
|
11
|
+
*/
|
|
12
|
+
import { type WorkbookOperation, type WorkbookOperationPayload, type WorkbookOperationType, type WorkbookRange } from '../types.ts';
|
|
13
|
+
import { type WorkbookSnapshot } from './snapshots.ts';
|
|
14
|
+
/** Apply one DSH operation to a Univer-compatible snapshot. */
|
|
15
|
+
export declare function applyWorkbookOperation(snapshot: unknown, operation: WorkbookOperation): unknown;
|
|
16
|
+
/** Read a rectangular range as a compact 2D value matrix. */
|
|
17
|
+
export declare function validateSnapshotBounds(value: unknown): void;
|
|
18
|
+
/**
|
|
19
|
+
* Mirrored by the browser projection's `applyAppendRows`, which runs the same
|
|
20
|
+
* check against live Univer state. The hint names `headerRowIndex` because that
|
|
21
|
+
* is what unblocks a report sheet whose real header is not row 0.
|
|
22
|
+
*/
|
|
23
|
+
export declare function formatCells(root: WorkbookSnapshot, sheetRef: string | undefined, range: WorkbookRange | undefined, style: WorkbookOperationPayload['style']): void;
|
|
24
|
+
/** Resolve data-dependent children before an operation is persisted/replayed. */
|
|
25
|
+
export declare function resolveOperationPayload(snapshot: unknown, type: WorkbookOperationType, payload: WorkbookOperationPayload): WorkbookOperationPayload;
|