@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.
Files changed (57) hide show
  1. package/LICENSE.md +22 -0
  2. package/README.md +60 -0
  3. package/dist/boot/createDemoWorkbenchBootGraph.d.ts +9 -0
  4. package/dist/boot/createDemoWorkbenchBootGraph.js +180 -0
  5. package/dist/boot/createLegacyWorkbenchBootGraph.d.ts +34 -0
  6. package/dist/boot/createLegacyWorkbenchBootGraph.js +321 -0
  7. package/dist/boot/createWorkbenchBootSession.d.ts +23 -0
  8. package/dist/boot/createWorkbenchBootSession.js +90 -0
  9. package/dist/boot/index.d.ts +3 -0
  10. package/dist/boot/index.js +3 -0
  11. package/dist/index.d.ts +10 -0
  12. package/dist/index.js +9 -0
  13. package/dist/runtime.d.ts +7 -0
  14. package/dist/runtime.js +2 -0
  15. package/dist/workbench/browserDetachedWindowHost.d.ts +3 -0
  16. package/dist/workbench/browserDetachedWindowHost.js +69 -0
  17. package/dist/workbench/browserWorkbenchHostEvents.d.ts +3 -0
  18. package/dist/workbench/browserWorkbenchHostEvents.js +35 -0
  19. package/dist/workbench/createWorkbenchStore.d.ts +129 -0
  20. package/dist/workbench/createWorkbenchStore.js +50 -0
  21. package/dist/workbench/createWorkbenchStoreRuntime.d.ts +154 -0
  22. package/dist/workbench/createWorkbenchStoreRuntime.js +242 -0
  23. package/dist/workbench/createWorkspaceModeController.d.ts +36 -0
  24. package/dist/workbench/createWorkspaceModeController.js +168 -0
  25. package/dist/workbench/workbenchDetachedWindowHost.d.ts +16 -0
  26. package/dist/workbench/workbenchDetachedWindowHost.js +1 -0
  27. package/dist/workbench/workbenchFocusPersistence.d.ts +15 -0
  28. package/dist/workbench/workbenchFocusPersistence.js +44 -0
  29. package/dist/workbench/workbenchHistoryActions.d.ts +21 -0
  30. package/dist/workbench/workbenchHistoryActions.js +45 -0
  31. package/dist/workbench/workbenchHistoryRuntime.d.ts +16 -0
  32. package/dist/workbench/workbenchHistoryRuntime.js +42 -0
  33. package/dist/workbench/workbenchHostEvents.d.ts +13 -0
  34. package/dist/workbench/workbenchHostEvents.js +1 -0
  35. package/dist/workbench/workbenchLayoutActions.d.ts +84 -0
  36. package/dist/workbench/workbenchLayoutActions.js +191 -0
  37. package/dist/workbench/workbenchPersistenceRuntime.d.ts +39 -0
  38. package/dist/workbench/workbenchPersistenceRuntime.js +168 -0
  39. package/dist/workbench/workbenchShellActions.d.ts +24 -0
  40. package/dist/workbench/workbenchShellActions.js +63 -0
  41. package/dist/workbench/workbenchShellPersistence.d.ts +18 -0
  42. package/dist/workbench/workbenchShellPersistence.js +124 -0
  43. package/dist/workbench/workbenchStateFactory.d.ts +22 -0
  44. package/dist/workbench/workbenchStateFactory.js +47 -0
  45. package/dist/workbench/workbenchToolRuntimeActions.d.ts +23 -0
  46. package/dist/workbench/workbenchToolRuntimeActions.js +98 -0
  47. package/dist/workbench/workbenchToolRuntimeUiStore.d.ts +17 -0
  48. package/dist/workbench/workbenchToolRuntimeUiStore.js +85 -0
  49. package/dist/workbench/workbenchWindowRuntime.d.ts +19 -0
  50. package/dist/workbench/workbenchWindowRuntime.js +85 -0
  51. package/dist/workbench/workbenchWorkspaceActions.d.ts +30 -0
  52. package/dist/workbench/workbenchWorkspaceActions.js +55 -0
  53. package/dist/workbench/workspaceHistoryController.d.ts +28 -0
  54. package/dist/workbench/workspaceHistoryController.js +126 -0
  55. package/dist/workbench/workspaceSyncController.d.ts +20 -0
  56. package/dist/workbench/workspaceSyncController.js +105 -0
  57. 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
+ }