@konitif/workbench-runtime 0.284.1
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.md +22 -0
- package/README.md +60 -0
- package/dist/boot/createDemoWorkbenchBootGraph.d.ts +9 -0
- package/dist/boot/createDemoWorkbenchBootGraph.js +180 -0
- package/dist/boot/createLegacyWorkbenchBootGraph.d.ts +34 -0
- package/dist/boot/createLegacyWorkbenchBootGraph.js +321 -0
- package/dist/boot/createWorkbenchBootSession.d.ts +23 -0
- package/dist/boot/createWorkbenchBootSession.js +90 -0
- package/dist/boot/index.d.ts +3 -0
- package/dist/boot/index.js +3 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +9 -0
- package/dist/runtime.d.ts +7 -0
- package/dist/runtime.js +2 -0
- package/dist/workbench/browserDetachedWindowHost.d.ts +3 -0
- package/dist/workbench/browserDetachedWindowHost.js +69 -0
- package/dist/workbench/browserWorkbenchHostEvents.d.ts +3 -0
- package/dist/workbench/browserWorkbenchHostEvents.js +35 -0
- package/dist/workbench/createWorkbenchStore.d.ts +129 -0
- package/dist/workbench/createWorkbenchStore.js +50 -0
- package/dist/workbench/createWorkbenchStoreRuntime.d.ts +154 -0
- package/dist/workbench/createWorkbenchStoreRuntime.js +242 -0
- package/dist/workbench/createWorkspaceModeController.d.ts +36 -0
- package/dist/workbench/createWorkspaceModeController.js +168 -0
- package/dist/workbench/workbenchDetachedWindowHost.d.ts +16 -0
- package/dist/workbench/workbenchDetachedWindowHost.js +1 -0
- package/dist/workbench/workbenchFocusPersistence.d.ts +15 -0
- package/dist/workbench/workbenchFocusPersistence.js +44 -0
- package/dist/workbench/workbenchHistoryActions.d.ts +21 -0
- package/dist/workbench/workbenchHistoryActions.js +45 -0
- package/dist/workbench/workbenchHistoryRuntime.d.ts +16 -0
- package/dist/workbench/workbenchHistoryRuntime.js +42 -0
- package/dist/workbench/workbenchHostEvents.d.ts +13 -0
- package/dist/workbench/workbenchHostEvents.js +1 -0
- package/dist/workbench/workbenchLayoutActions.d.ts +84 -0
- package/dist/workbench/workbenchLayoutActions.js +191 -0
- package/dist/workbench/workbenchPersistenceRuntime.d.ts +39 -0
- package/dist/workbench/workbenchPersistenceRuntime.js +168 -0
- package/dist/workbench/workbenchShellActions.d.ts +24 -0
- package/dist/workbench/workbenchShellActions.js +63 -0
- package/dist/workbench/workbenchShellPersistence.d.ts +18 -0
- package/dist/workbench/workbenchShellPersistence.js +124 -0
- package/dist/workbench/workbenchStateFactory.d.ts +22 -0
- package/dist/workbench/workbenchStateFactory.js +47 -0
- package/dist/workbench/workbenchToolRuntimeActions.d.ts +23 -0
- package/dist/workbench/workbenchToolRuntimeActions.js +98 -0
- package/dist/workbench/workbenchToolRuntimeUiStore.d.ts +17 -0
- package/dist/workbench/workbenchToolRuntimeUiStore.js +85 -0
- package/dist/workbench/workbenchWindowRuntime.d.ts +19 -0
- package/dist/workbench/workbenchWindowRuntime.js +85 -0
- package/dist/workbench/workbenchWorkspaceActions.d.ts +30 -0
- package/dist/workbench/workbenchWorkspaceActions.js +55 -0
- package/dist/workbench/workspaceHistoryController.d.ts +28 -0
- package/dist/workbench/workspaceHistoryController.js +126 -0
- package/dist/workbench/workspaceSyncController.d.ts +20 -0
- package/dist/workbench/workspaceSyncController.js +105 -0
- package/package.json +49 -0
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
const DEFAULT_MAX_HISTORY_ENTRIES = 100;
|
|
2
|
+
export function createWorkspaceHistoryController(options) {
|
|
3
|
+
const maxEntries = Math.max(1, Math.floor(options.maxEntries ?? DEFAULT_MAX_HISTORY_ENTRIES));
|
|
4
|
+
const buckets = {
|
|
5
|
+
app: createBucket(),
|
|
6
|
+
core: createBucket()
|
|
7
|
+
};
|
|
8
|
+
function getStatus() {
|
|
9
|
+
return {
|
|
10
|
+
app: {
|
|
11
|
+
canUndo: buckets.app.past.length > 0,
|
|
12
|
+
canRedo: buckets.app.future.length > 0
|
|
13
|
+
},
|
|
14
|
+
core: {
|
|
15
|
+
canUndo: buckets.core.past.length > 0,
|
|
16
|
+
canRedo: buckets.core.future.length > 0
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
function reset() {
|
|
21
|
+
resetBucket(buckets.app);
|
|
22
|
+
resetBucket(buckets.core);
|
|
23
|
+
}
|
|
24
|
+
function recordTransition(previousSnapshot, nextSnapshot, scope) {
|
|
25
|
+
if (scope === 'none' || !options.isChanged(previousSnapshot, nextSnapshot)) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
for (const channel of resolveChannels(scope)) {
|
|
29
|
+
const bucket = buckets[channel];
|
|
30
|
+
if (!bucket.shouldRecord) {
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
bucket.past = pushHistoryEntry(bucket.past, previousSnapshot);
|
|
34
|
+
bucket.future = [];
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function beginTransaction(channel, snapshot) {
|
|
38
|
+
const bucket = buckets[channel];
|
|
39
|
+
if (bucket.transaction) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
bucket.transaction = snapshot;
|
|
43
|
+
bucket.shouldRecord = false;
|
|
44
|
+
}
|
|
45
|
+
function commitTransaction(channel, currentSnapshot) {
|
|
46
|
+
const bucket = buckets[channel];
|
|
47
|
+
if (!bucket.transaction) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (options.isChanged(bucket.transaction, currentSnapshot)) {
|
|
51
|
+
bucket.past = pushHistoryEntry(bucket.past, bucket.transaction);
|
|
52
|
+
bucket.future = [];
|
|
53
|
+
}
|
|
54
|
+
bucket.transaction = null;
|
|
55
|
+
bucket.shouldRecord = true;
|
|
56
|
+
}
|
|
57
|
+
function cancelTransaction(channel) {
|
|
58
|
+
const bucket = buckets[channel];
|
|
59
|
+
const snapshot = bucket.transaction;
|
|
60
|
+
if (!snapshot) {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
bucket.transaction = null;
|
|
64
|
+
bucket.shouldRecord = true;
|
|
65
|
+
return snapshot;
|
|
66
|
+
}
|
|
67
|
+
function undo(channel, currentSnapshot) {
|
|
68
|
+
const bucket = buckets[channel];
|
|
69
|
+
const snapshot = bucket.past.length > 0 ? bucket.past[bucket.past.length - 1] : null;
|
|
70
|
+
if (!snapshot) {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
bucket.past = bucket.past.slice(0, -1);
|
|
74
|
+
bucket.future = pushHistoryEntry(bucket.future, currentSnapshot);
|
|
75
|
+
return snapshot;
|
|
76
|
+
}
|
|
77
|
+
function redo(channel, currentSnapshot) {
|
|
78
|
+
const bucket = buckets[channel];
|
|
79
|
+
const snapshot = bucket.future.length > 0 ? bucket.future[bucket.future.length - 1] : null;
|
|
80
|
+
if (!snapshot) {
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
bucket.future = bucket.future.slice(0, -1);
|
|
84
|
+
bucket.past = pushHistoryEntry(bucket.past, currentSnapshot);
|
|
85
|
+
return snapshot;
|
|
86
|
+
}
|
|
87
|
+
function pushHistoryEntry(entries, entry) {
|
|
88
|
+
return [...entries, entry].slice(-maxEntries);
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
getStatus,
|
|
92
|
+
reset,
|
|
93
|
+
recordTransition,
|
|
94
|
+
beginTransaction,
|
|
95
|
+
commitTransaction,
|
|
96
|
+
cancelTransaction,
|
|
97
|
+
undo,
|
|
98
|
+
redo
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
function createBucket() {
|
|
102
|
+
return {
|
|
103
|
+
past: [],
|
|
104
|
+
future: [],
|
|
105
|
+
transaction: null,
|
|
106
|
+
shouldRecord: true
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
function resetBucket(bucket) {
|
|
110
|
+
bucket.past = [];
|
|
111
|
+
bucket.future = [];
|
|
112
|
+
bucket.transaction = null;
|
|
113
|
+
bucket.shouldRecord = true;
|
|
114
|
+
}
|
|
115
|
+
function resolveChannels(scope) {
|
|
116
|
+
switch (scope) {
|
|
117
|
+
case 'app':
|
|
118
|
+
return ['app'];
|
|
119
|
+
case 'core':
|
|
120
|
+
return ['core'];
|
|
121
|
+
case 'both':
|
|
122
|
+
return ['app', 'core'];
|
|
123
|
+
case 'none':
|
|
124
|
+
return [];
|
|
125
|
+
}
|
|
126
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ShellState, Workspace, WorkspaceFocus } from '@konitif/workbench';
|
|
2
|
+
export interface WorkspaceSyncSnapshot {
|
|
3
|
+
workspace: Workspace;
|
|
4
|
+
shell?: ShellState;
|
|
5
|
+
focus?: WorkspaceFocus;
|
|
6
|
+
}
|
|
7
|
+
export interface WorkspaceSyncController {
|
|
8
|
+
publish(snapshot: WorkspaceSyncSnapshot): void;
|
|
9
|
+
subscribe(handler: (snapshot: WorkspaceSyncSnapshot) => void): void | (() => void);
|
|
10
|
+
/** Only the owner of this provider may close it. */
|
|
11
|
+
dispose?(): void;
|
|
12
|
+
}
|
|
13
|
+
interface BrowserWorkspaceSyncControllerOptions {
|
|
14
|
+
persistenceKey: string;
|
|
15
|
+
isEnabled?: () => boolean;
|
|
16
|
+
}
|
|
17
|
+
export declare function createBrowserWorkspaceSyncController(options: BrowserWorkspaceSyncControllerOptions): WorkspaceSyncController & {
|
|
18
|
+
dispose(): void;
|
|
19
|
+
};
|
|
20
|
+
export {};
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
export function createBrowserWorkspaceSyncController(options) {
|
|
2
|
+
const clientId = createWorkspaceSyncClientId(options.persistenceKey);
|
|
3
|
+
const channel = createWorkspaceSyncChannel(options.persistenceKey);
|
|
4
|
+
let lastPublishedSignature = '';
|
|
5
|
+
let localRevision = 0;
|
|
6
|
+
let acceptedAuthorityStamp = '';
|
|
7
|
+
let disposed = false;
|
|
8
|
+
return {
|
|
9
|
+
publish(snapshot) {
|
|
10
|
+
if (disposed || !isEnabled(options) || !channel) {
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
const signature = JSON.stringify(snapshot);
|
|
14
|
+
if (signature === lastPublishedSignature) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
lastPublishedSignature = signature;
|
|
18
|
+
localRevision += 1;
|
|
19
|
+
acceptedAuthorityStamp = createAuthorityStamp(localRevision, clientId);
|
|
20
|
+
channel.postMessage({
|
|
21
|
+
type: 'workbench.workspace.snapshot',
|
|
22
|
+
persistenceKey: options.persistenceKey,
|
|
23
|
+
clientId,
|
|
24
|
+
revision: localRevision,
|
|
25
|
+
workspace: snapshot.workspace,
|
|
26
|
+
shell: snapshot.shell,
|
|
27
|
+
focus: snapshot.focus
|
|
28
|
+
});
|
|
29
|
+
},
|
|
30
|
+
subscribe(handler) {
|
|
31
|
+
if (disposed || !channel) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
let active = true;
|
|
35
|
+
const receive = (event) => {
|
|
36
|
+
if (disposed || !active || channel.onmessage !== receive || !isEnabled(options)) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
const message = normalizeWorkspaceSyncMessage(event.data);
|
|
40
|
+
if (!message ||
|
|
41
|
+
message.persistenceKey !== options.persistenceKey ||
|
|
42
|
+
message.clientId === clientId) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
localRevision = Math.max(localRevision, message.revision);
|
|
46
|
+
const messageAuthorityStamp = createAuthorityStamp(message.revision, message.clientId);
|
|
47
|
+
if (messageAuthorityStamp <= acceptedAuthorityStamp) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
acceptedAuthorityStamp = messageAuthorityStamp;
|
|
51
|
+
handler({
|
|
52
|
+
workspace: message.workspace,
|
|
53
|
+
shell: message.shell,
|
|
54
|
+
focus: message.focus
|
|
55
|
+
});
|
|
56
|
+
};
|
|
57
|
+
channel.onmessage = receive;
|
|
58
|
+
return () => {
|
|
59
|
+
active = false;
|
|
60
|
+
if (channel.onmessage === receive)
|
|
61
|
+
channel.onmessage = null;
|
|
62
|
+
};
|
|
63
|
+
},
|
|
64
|
+
dispose() {
|
|
65
|
+
if (disposed)
|
|
66
|
+
return;
|
|
67
|
+
disposed = true;
|
|
68
|
+
if (channel) {
|
|
69
|
+
channel.onmessage = null;
|
|
70
|
+
channel.close();
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
function createWorkspaceSyncClientId(persistenceKey) {
|
|
76
|
+
const token = globalThis.crypto?.randomUUID?.() ?? Math.random().toString(36).slice(2);
|
|
77
|
+
return `${persistenceKey}:${token}`.replace(/[^a-zA-Z0-9._:-]/g, '_');
|
|
78
|
+
}
|
|
79
|
+
function createWorkspaceSyncChannel(persistenceKey) {
|
|
80
|
+
if (typeof window === 'undefined' || typeof BroadcastChannel === 'undefined') {
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
return new BroadcastChannel(`workbench.workspace:${persistenceKey}`);
|
|
84
|
+
}
|
|
85
|
+
function normalizeWorkspaceSyncMessage(input) {
|
|
86
|
+
if (!input || typeof input !== 'object' || Array.isArray(input)) {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
const record = input;
|
|
90
|
+
return record.type === 'workbench.workspace.snapshot' &&
|
|
91
|
+
typeof record.persistenceKey === 'string' &&
|
|
92
|
+
typeof record.clientId === 'string' &&
|
|
93
|
+
typeof record.revision === 'number' &&
|
|
94
|
+
Number.isSafeInteger(record.revision) &&
|
|
95
|
+
record.revision > 0 &&
|
|
96
|
+
!!record.workspace
|
|
97
|
+
? record
|
|
98
|
+
: null;
|
|
99
|
+
}
|
|
100
|
+
function createAuthorityStamp(revision, clientId) {
|
|
101
|
+
return `${revision.toString().padStart(16, '0')}:${clientId}`;
|
|
102
|
+
}
|
|
103
|
+
function isEnabled(options) {
|
|
104
|
+
return options.isEnabled?.() ?? true;
|
|
105
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@konitif/workbench-runtime",
|
|
3
|
+
"license": "PolyForm-Noncommercial-1.0.0",
|
|
4
|
+
"version": "0.284.1",
|
|
5
|
+
"description": "Reactive Svelte host adapter for KONITIF Workbench contracts with explicit runtime ports.",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/LeMouf/konitif-workbench-runtime.git"
|
|
9
|
+
},
|
|
10
|
+
"publishConfig": {
|
|
11
|
+
"access": "public",
|
|
12
|
+
"registry": "https://registry.npmjs.org/"
|
|
13
|
+
},
|
|
14
|
+
"private": false,
|
|
15
|
+
"type": "module",
|
|
16
|
+
"main": "./dist/index.js",
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"svelte": "./dist/index.js",
|
|
19
|
+
"exports": {
|
|
20
|
+
".": {
|
|
21
|
+
"types": "./dist/index.d.ts",
|
|
22
|
+
"import": "./dist/index.js",
|
|
23
|
+
"default": "./dist/index.js"
|
|
24
|
+
},
|
|
25
|
+
"./runtime": {
|
|
26
|
+
"types": "./dist/runtime.d.ts",
|
|
27
|
+
"import": "./dist/runtime.js",
|
|
28
|
+
"default": "./dist/runtime.js"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"files": [
|
|
32
|
+
"dist",
|
|
33
|
+
"LICENSE.md",
|
|
34
|
+
"README.md",
|
|
35
|
+
"package.json"
|
|
36
|
+
],
|
|
37
|
+
"scripts": {
|
|
38
|
+
"build": "node scripts/build.mjs",
|
|
39
|
+
"test": "node --test tests/*.test.mjs",
|
|
40
|
+
"verify:package": "node scripts/verify-package.mjs"
|
|
41
|
+
},
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"@konitif/workbench": "0.284.1",
|
|
44
|
+
"svelte": "^4.2.18"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"typescript": "5.9.3"
|
|
48
|
+
}
|
|
49
|
+
}
|