@forgeax/interface 0.9.1 → 0.9.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/package/browser/appHostBootstrap.js +7 -6
- package/dist/package/browser/core/panels/panel-action-registry.d.ts +4 -6
- package/dist/package/browser/core/panels/panel-action-registry.js +2 -62
- package/dist/package/browser/core/panels/panel-control-registry.d.ts +4 -6
- package/dist/package/browser/core/panels/panel-control-registry.js +2 -54
- package/dist/package/node/appHostBootstrap.js +7 -6
- package/dist/package/node/core/panels/panel-action-registry.js +2 -62
- package/dist/package/node/core/panels/panel-control-registry.js +2 -54
- package/package.json +2 -2
|
@@ -61,14 +61,12 @@ export async function bootstrapAppHost(overrides = {}) {
|
|
|
61
61
|
...m,
|
|
62
62
|
async setup(ctx) {
|
|
63
63
|
control.beginSetup(m);
|
|
64
|
-
const
|
|
64
|
+
const cleanups = [];
|
|
65
|
+
let pageCleanup;
|
|
65
66
|
try {
|
|
66
|
-
const cleanups = [];
|
|
67
|
-
let pageCleanup;
|
|
68
67
|
for (const menu of m.contributes?.menus ?? []) {
|
|
69
|
-
|
|
68
|
+
cleanups.push(host.menus.register(menu));
|
|
70
69
|
}
|
|
71
|
-
cleanups.push(...menuCleanups);
|
|
72
70
|
if (m.contributes?.panels) {
|
|
73
71
|
cleanups.push(control.contributePanels(m.id, m.contributes.panels));
|
|
74
72
|
}
|
|
@@ -100,7 +98,10 @@ export async function bootstrapAppHost(overrides = {}) {
|
|
|
100
98
|
};
|
|
101
99
|
}
|
|
102
100
|
catch (error) {
|
|
103
|
-
|
|
101
|
+
// Preserve the same page-close decision boundary on failed setup.
|
|
102
|
+
// A dirty page must not lose its surrounding contributions underneath it.
|
|
103
|
+
await pageCleanup?.();
|
|
104
|
+
for (const cleanup of cleanups.slice().reverse())
|
|
104
105
|
await cleanup();
|
|
105
106
|
throw error;
|
|
106
107
|
}
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import type { PanelActionContribution
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
}
|
|
6
|
-
export declare function createPanelActionRegistry(): PanelActionRegistry;
|
|
1
|
+
import { type PanelActionRegistry as Registry } from '@forgeax/app-shell/application';
|
|
2
|
+
import type { PanelActionContribution } from './types';
|
|
3
|
+
export type PanelActionRegistry = Registry<PanelActionContribution>;
|
|
4
|
+
export declare const createPanelActionRegistry: () => Registry<PanelActionContribution>;
|
|
@@ -1,62 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const listeners = new Set();
|
|
4
|
-
let cache = null;
|
|
5
|
-
let version = 0;
|
|
6
|
-
const emit = () => {
|
|
7
|
-
cache = null;
|
|
8
|
-
version++;
|
|
9
|
-
for (const listener of [...listeners])
|
|
10
|
-
listener();
|
|
11
|
-
};
|
|
12
|
-
// Batch-deferred notification: data mutations (push/splice) happen
|
|
13
|
-
// immediately so reads (list/all) always return fresh data, but listener
|
|
14
|
-
// notifications are deferred to a microtask. This avoids triggering
|
|
15
|
-
// forceStoreRerender (useSyncExternalStore) during React 19's commit
|
|
16
|
-
// phase, which otherwise causes "Maximum update depth exceeded".
|
|
17
|
-
let emitScheduled = false;
|
|
18
|
-
const scheduleEmit = () => {
|
|
19
|
-
cache = null;
|
|
20
|
-
if (emitScheduled)
|
|
21
|
-
return;
|
|
22
|
-
emitScheduled = true;
|
|
23
|
-
queueMicrotask(() => {
|
|
24
|
-
emitScheduled = false;
|
|
25
|
-
emit();
|
|
26
|
-
});
|
|
27
|
-
};
|
|
28
|
-
const all = () => {
|
|
29
|
-
if (cache)
|
|
30
|
-
return cache;
|
|
31
|
-
cache = entries.flatMap((entry) => entry.actions).sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
|
|
32
|
-
return cache;
|
|
33
|
-
};
|
|
34
|
-
return {
|
|
35
|
-
contribute(owner, actions) {
|
|
36
|
-
const entry = { owner, actions };
|
|
37
|
-
entries.push(entry);
|
|
38
|
-
scheduleEmit();
|
|
39
|
-
let removed = false;
|
|
40
|
-
return () => {
|
|
41
|
-
if (removed)
|
|
42
|
-
return;
|
|
43
|
-
removed = true;
|
|
44
|
-
const index = entries.indexOf(entry);
|
|
45
|
-
if (index >= 0)
|
|
46
|
-
entries.splice(index, 1);
|
|
47
|
-
scheduleEmit();
|
|
48
|
-
};
|
|
49
|
-
},
|
|
50
|
-
list(panelId) {
|
|
51
|
-
return all().filter((action) => action.panelId === panelId);
|
|
52
|
-
},
|
|
53
|
-
all,
|
|
54
|
-
onChange(listener) {
|
|
55
|
-
listeners.add(listener);
|
|
56
|
-
return () => { listeners.delete(listener); };
|
|
57
|
-
},
|
|
58
|
-
version() {
|
|
59
|
-
return version;
|
|
60
|
-
},
|
|
61
|
-
};
|
|
62
|
-
}
|
|
1
|
+
import { createPanelActionRegistry as createRegistry, } from '@forgeax/app-shell/application';
|
|
2
|
+
export const createPanelActionRegistry = (createRegistry);
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import type { PanelControlContribution
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
}
|
|
6
|
-
export declare function createPanelControlRegistry(): PanelControlRegistry;
|
|
1
|
+
import { type PanelControlRegistry as Registry } from '@forgeax/app-shell/application';
|
|
2
|
+
import type { PanelControlContribution } from './types';
|
|
3
|
+
export type PanelControlRegistry = Registry<PanelControlContribution>;
|
|
4
|
+
export declare const createPanelControlRegistry: () => Registry<PanelControlContribution>;
|
|
@@ -1,54 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const listeners = new Set();
|
|
4
|
-
let version = 0;
|
|
5
|
-
const emit = () => {
|
|
6
|
-
version++;
|
|
7
|
-
for (const listener of [...listeners])
|
|
8
|
-
listener();
|
|
9
|
-
};
|
|
10
|
-
// Batch-deferred notification: data mutations (push/splice) happen
|
|
11
|
-
// immediately so reads (list/get) always return fresh data, but listener
|
|
12
|
-
// notifications are deferred to a microtask. This avoids triggering
|
|
13
|
-
// forceStoreRerender (useSyncExternalStore) during React 19's commit
|
|
14
|
-
// phase, which otherwise causes "Maximum update depth exceeded".
|
|
15
|
-
let emitScheduled = false;
|
|
16
|
-
const scheduleEmit = () => {
|
|
17
|
-
if (emitScheduled)
|
|
18
|
-
return;
|
|
19
|
-
emitScheduled = true;
|
|
20
|
-
queueMicrotask(() => {
|
|
21
|
-
emitScheduled = false;
|
|
22
|
-
emit();
|
|
23
|
-
});
|
|
24
|
-
};
|
|
25
|
-
const list = () => entries.flatMap((entry) => entry.controls);
|
|
26
|
-
return {
|
|
27
|
-
contribute(owner, controls) {
|
|
28
|
-
const entry = { owner, controls };
|
|
29
|
-
entries.push(entry);
|
|
30
|
-
scheduleEmit();
|
|
31
|
-
let removed = false;
|
|
32
|
-
return () => {
|
|
33
|
-
if (removed)
|
|
34
|
-
return;
|
|
35
|
-
removed = true;
|
|
36
|
-
const index = entries.indexOf(entry);
|
|
37
|
-
if (index >= 0)
|
|
38
|
-
entries.splice(index, 1);
|
|
39
|
-
scheduleEmit();
|
|
40
|
-
};
|
|
41
|
-
},
|
|
42
|
-
get(id) {
|
|
43
|
-
return list().find((control) => control.id === id);
|
|
44
|
-
},
|
|
45
|
-
list,
|
|
46
|
-
onChange(listener) {
|
|
47
|
-
listeners.add(listener);
|
|
48
|
-
return () => { listeners.delete(listener); };
|
|
49
|
-
},
|
|
50
|
-
version() {
|
|
51
|
-
return version;
|
|
52
|
-
},
|
|
53
|
-
};
|
|
54
|
-
}
|
|
1
|
+
import { createPanelControlRegistry as createRegistry, } from '@forgeax/app-shell/application';
|
|
2
|
+
export const createPanelControlRegistry = (createRegistry);
|
|
@@ -61,14 +61,12 @@ export async function bootstrapAppHost(overrides = {}) {
|
|
|
61
61
|
...m,
|
|
62
62
|
async setup(ctx) {
|
|
63
63
|
control.beginSetup(m);
|
|
64
|
-
const
|
|
64
|
+
const cleanups = [];
|
|
65
|
+
let pageCleanup;
|
|
65
66
|
try {
|
|
66
|
-
const cleanups = [];
|
|
67
|
-
let pageCleanup;
|
|
68
67
|
for (const menu of m.contributes?.menus ?? []) {
|
|
69
|
-
|
|
68
|
+
cleanups.push(host.menus.register(menu));
|
|
70
69
|
}
|
|
71
|
-
cleanups.push(...menuCleanups);
|
|
72
70
|
if (m.contributes?.panels) {
|
|
73
71
|
cleanups.push(control.contributePanels(m.id, m.contributes.panels));
|
|
74
72
|
}
|
|
@@ -100,7 +98,10 @@ export async function bootstrapAppHost(overrides = {}) {
|
|
|
100
98
|
};
|
|
101
99
|
}
|
|
102
100
|
catch (error) {
|
|
103
|
-
|
|
101
|
+
// Preserve the same page-close decision boundary on failed setup.
|
|
102
|
+
// A dirty page must not lose its surrounding contributions underneath it.
|
|
103
|
+
await pageCleanup?.();
|
|
104
|
+
for (const cleanup of cleanups.slice().reverse())
|
|
104
105
|
await cleanup();
|
|
105
106
|
throw error;
|
|
106
107
|
}
|
|
@@ -1,62 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const listeners = new Set();
|
|
4
|
-
let cache = null;
|
|
5
|
-
let version = 0;
|
|
6
|
-
const emit = () => {
|
|
7
|
-
cache = null;
|
|
8
|
-
version++;
|
|
9
|
-
for (const listener of [...listeners])
|
|
10
|
-
listener();
|
|
11
|
-
};
|
|
12
|
-
// Batch-deferred notification: data mutations (push/splice) happen
|
|
13
|
-
// immediately so reads (list/all) always return fresh data, but listener
|
|
14
|
-
// notifications are deferred to a microtask. This avoids triggering
|
|
15
|
-
// forceStoreRerender (useSyncExternalStore) during React 19's commit
|
|
16
|
-
// phase, which otherwise causes "Maximum update depth exceeded".
|
|
17
|
-
let emitScheduled = false;
|
|
18
|
-
const scheduleEmit = () => {
|
|
19
|
-
cache = null;
|
|
20
|
-
if (emitScheduled)
|
|
21
|
-
return;
|
|
22
|
-
emitScheduled = true;
|
|
23
|
-
queueMicrotask(() => {
|
|
24
|
-
emitScheduled = false;
|
|
25
|
-
emit();
|
|
26
|
-
});
|
|
27
|
-
};
|
|
28
|
-
const all = () => {
|
|
29
|
-
if (cache)
|
|
30
|
-
return cache;
|
|
31
|
-
cache = entries.flatMap((entry) => entry.actions).sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
|
|
32
|
-
return cache;
|
|
33
|
-
};
|
|
34
|
-
return {
|
|
35
|
-
contribute(owner, actions) {
|
|
36
|
-
const entry = { owner, actions };
|
|
37
|
-
entries.push(entry);
|
|
38
|
-
scheduleEmit();
|
|
39
|
-
let removed = false;
|
|
40
|
-
return () => {
|
|
41
|
-
if (removed)
|
|
42
|
-
return;
|
|
43
|
-
removed = true;
|
|
44
|
-
const index = entries.indexOf(entry);
|
|
45
|
-
if (index >= 0)
|
|
46
|
-
entries.splice(index, 1);
|
|
47
|
-
scheduleEmit();
|
|
48
|
-
};
|
|
49
|
-
},
|
|
50
|
-
list(panelId) {
|
|
51
|
-
return all().filter((action) => action.panelId === panelId);
|
|
52
|
-
},
|
|
53
|
-
all,
|
|
54
|
-
onChange(listener) {
|
|
55
|
-
listeners.add(listener);
|
|
56
|
-
return () => { listeners.delete(listener); };
|
|
57
|
-
},
|
|
58
|
-
version() {
|
|
59
|
-
return version;
|
|
60
|
-
},
|
|
61
|
-
};
|
|
62
|
-
}
|
|
1
|
+
import { createPanelActionRegistry as createRegistry, } from '@forgeax/app-shell/application';
|
|
2
|
+
export const createPanelActionRegistry = (createRegistry);
|
|
@@ -1,54 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const listeners = new Set();
|
|
4
|
-
let version = 0;
|
|
5
|
-
const emit = () => {
|
|
6
|
-
version++;
|
|
7
|
-
for (const listener of [...listeners])
|
|
8
|
-
listener();
|
|
9
|
-
};
|
|
10
|
-
// Batch-deferred notification: data mutations (push/splice) happen
|
|
11
|
-
// immediately so reads (list/get) always return fresh data, but listener
|
|
12
|
-
// notifications are deferred to a microtask. This avoids triggering
|
|
13
|
-
// forceStoreRerender (useSyncExternalStore) during React 19's commit
|
|
14
|
-
// phase, which otherwise causes "Maximum update depth exceeded".
|
|
15
|
-
let emitScheduled = false;
|
|
16
|
-
const scheduleEmit = () => {
|
|
17
|
-
if (emitScheduled)
|
|
18
|
-
return;
|
|
19
|
-
emitScheduled = true;
|
|
20
|
-
queueMicrotask(() => {
|
|
21
|
-
emitScheduled = false;
|
|
22
|
-
emit();
|
|
23
|
-
});
|
|
24
|
-
};
|
|
25
|
-
const list = () => entries.flatMap((entry) => entry.controls);
|
|
26
|
-
return {
|
|
27
|
-
contribute(owner, controls) {
|
|
28
|
-
const entry = { owner, controls };
|
|
29
|
-
entries.push(entry);
|
|
30
|
-
scheduleEmit();
|
|
31
|
-
let removed = false;
|
|
32
|
-
return () => {
|
|
33
|
-
if (removed)
|
|
34
|
-
return;
|
|
35
|
-
removed = true;
|
|
36
|
-
const index = entries.indexOf(entry);
|
|
37
|
-
if (index >= 0)
|
|
38
|
-
entries.splice(index, 1);
|
|
39
|
-
scheduleEmit();
|
|
40
|
-
};
|
|
41
|
-
},
|
|
42
|
-
get(id) {
|
|
43
|
-
return list().find((control) => control.id === id);
|
|
44
|
-
},
|
|
45
|
-
list,
|
|
46
|
-
onChange(listener) {
|
|
47
|
-
listeners.add(listener);
|
|
48
|
-
return () => { listeners.delete(listener); };
|
|
49
|
-
},
|
|
50
|
-
version() {
|
|
51
|
-
return version;
|
|
52
|
-
},
|
|
53
|
-
};
|
|
54
|
-
}
|
|
1
|
+
import { createPanelControlRegistry as createRegistry, } from '@forgeax/app-shell/application';
|
|
2
|
+
export const createPanelControlRegistry = (createRegistry);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forgeax/interface",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "ForgeaX product interface shell and application composition boundary.",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -92,7 +92,7 @@
|
|
|
92
92
|
"lint:dep": "depcruise -c .dependency-cruiser.cjs src"
|
|
93
93
|
},
|
|
94
94
|
"dependencies": {
|
|
95
|
-
"@forgeax/app-shell": "0.
|
|
95
|
+
"@forgeax/app-shell": "0.89.0",
|
|
96
96
|
"@forgeax/extension-host": "0.3.2",
|
|
97
97
|
"@forgeax/extension-platform": "0.5.0",
|
|
98
98
|
"@forgeax/toolkit": "0.1.2",
|