@dimina-kit/electron-deck 0.1.0-dev.20260610082053
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 +39 -0
- package/dist/client/index.d.ts +20 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +310 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/layout-client.d.ts +51 -0
- package/dist/client/layout-client.d.ts.map +1 -0
- package/dist/electron-deck-DfFKeFEC.js +2295 -0
- package/dist/electron-deck-DfFKeFEC.js.map +1 -0
- package/dist/electron-deck.d.ts +57 -0
- package/dist/electron-deck.d.ts.map +1 -0
- package/dist/errors-NE2ig7L5.js +53 -0
- package/dist/errors-NE2ig7L5.js.map +1 -0
- package/dist/errors.d.ts +33 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/events.d.ts +14 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/host/capability.d.ts +50 -0
- package/dist/host/capability.d.ts.map +1 -0
- package/dist/host/control-bus.d.ts +92 -0
- package/dist/host/control-bus.d.ts.map +1 -0
- package/dist/host/index.d.ts +42 -0
- package/dist/host/index.d.ts.map +1 -0
- package/dist/host/index.js +2 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/internal/deck-app.d.ts +415 -0
- package/dist/internal/deck-app.d.ts.map +1 -0
- package/dist/internal/electron-types.d.ts +131 -0
- package/dist/internal/electron-types.d.ts.map +1 -0
- package/dist/internal/event-bus.d.ts +29 -0
- package/dist/internal/event-bus.d.ts.map +1 -0
- package/dist/internal/ipc-registry-memory.d.ts +25 -0
- package/dist/internal/ipc-registry-memory.d.ts.map +1 -0
- package/dist/internal/lifecycle-manager.d.ts +28 -0
- package/dist/internal/lifecycle-manager.d.ts.map +1 -0
- package/dist/internal/resource-registry.d.ts +9 -0
- package/dist/internal/resource-registry.d.ts.map +1 -0
- package/dist/internal/trust-set.d.ts +53 -0
- package/dist/internal/trust-set.d.ts.map +1 -0
- package/dist/internal/wire-transport.d.ts +159 -0
- package/dist/internal/wire-transport.d.ts.map +1 -0
- package/dist/main/compositor.d.ts +123 -0
- package/dist/main/compositor.d.ts.map +1 -0
- package/dist/main/connection.d.ts +37 -0
- package/dist/main/connection.d.ts.map +1 -0
- package/dist/main/debug-tap.d.ts +55 -0
- package/dist/main/debug-tap.d.ts.map +1 -0
- package/dist/main/disposable.d.ts +18 -0
- package/dist/main/disposable.d.ts.map +1 -0
- package/dist/main/index.d.ts +16 -0
- package/dist/main/index.d.ts.map +1 -0
- package/dist/main/index.js +152 -0
- package/dist/main/index.js.map +1 -0
- package/dist/main/logger.d.ts +15 -0
- package/dist/main/logger.d.ts.map +1 -0
- package/dist/main/scope.d.ts +52 -0
- package/dist/main/scope.d.ts.map +1 -0
- package/dist/main/view-handle.d.ts +131 -0
- package/dist/main/view-handle.d.ts.map +1 -0
- package/dist/preload/index.cjs +105 -0
- package/dist/preload/index.cjs.map +1 -0
- package/dist/preload/index.d.ts +43 -0
- package/dist/preload/index.d.ts.map +1 -0
- package/dist/preload/index.js +80 -0
- package/dist/preload/index.js.map +1 -0
- package/dist/protocol-BJqo-vP2.js +23 -0
- package/dist/protocol-BJqo-vP2.js.map +1 -0
- package/dist/shared/protocol.d.ts +76 -0
- package/dist/shared/protocol.d.ts.map +1 -0
- package/dist/types.d.ts +504 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/view-handle-CR-yWNfr.js +701 -0
- package/dist/view-handle-CR-yWNfr.js.map +1 -0
- package/package.json +86 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { DeckConfig, DeckOptions, Runtime } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* `electronDeck(config, options?)` 是 framework 唯一入口(见 README §3)。
|
|
4
|
+
*
|
|
5
|
+
* - Invalid config → reject `TypeError`,phase 不前进
|
|
6
|
+
* - Valid config → 装配 runtime + 调 `config.setup(runtime)` await 完成 →
|
|
7
|
+
* resolve。Phase 2 不接 Electron,resolve 后 framework 仍持有运行时;
|
|
8
|
+
* Phase 4 接 Electron app lifecycle 后,由 Electron event loop 撑住进程,
|
|
9
|
+
* `electronDeck()` 同样 resolve(host 的 main 文件不需 await 阻塞)。
|
|
10
|
+
*
|
|
11
|
+
* backend host(如 devtools)走 `electronDeck({ backend })`——backend 是
|
|
12
|
+
* {@link DeckConfig} 的字段,不再需要空 `{}` + options。
|
|
13
|
+
*
|
|
14
|
+
* `options` 是测试 / 非 Electron 环境用的注入点(见 {@link DeckOptions})。
|
|
15
|
+
* 生产路径不传 options:framework `await import('electron')` 取真 `ipcMain` /
|
|
16
|
+
* `BrowserWindow` / `WebContentsView`。
|
|
17
|
+
*/
|
|
18
|
+
export declare function electronDeck(config: DeckConfig, options?: DeckOptions): Promise<void>;
|
|
19
|
+
/**
|
|
20
|
+
* Synchronous launch handle for `electronDeck`.
|
|
21
|
+
*
|
|
22
|
+
* `electronDeck(config)` is `async` and internally `await app.start()` →
|
|
23
|
+
* `await app.whenReady()`. A host ESM main entry doing `await electronDeck(config)`
|
|
24
|
+
* SUSPENDS module evaluation on the whenReady gate — but Electron's `ready` only
|
|
25
|
+
* fires once module evaluation finishes, so the gate never resolves: HARD DEADLOCK.
|
|
26
|
+
*
|
|
27
|
+
* `startElectronDeck` returns a plain handle SYNCHRONOUSLY (NOT a thenable), so a
|
|
28
|
+
* host's top-level `await handle.ready` never sits on the whenReady gate. Assembly
|
|
29
|
+
* still runs STRICTLY AFTER `app.whenReady()` resolves (gating intact inside
|
|
30
|
+
* `app.start()`); `handle.ready` resolves with the {@link Runtime}; `handle.dispose()`
|
|
31
|
+
* tears the app down even if called before the in-flight start finished.
|
|
32
|
+
*
|
|
33
|
+
* Invalid config throws a `TypeError` synchronously (matching `electronDeck`'s
|
|
34
|
+
* validate-first contract) — the error surfaces, never silently deadlocks.
|
|
35
|
+
*/
|
|
36
|
+
export declare function startElectronDeck(config: DeckConfig, options?: DeckOptions): {
|
|
37
|
+
ready: Promise<Runtime>;
|
|
38
|
+
dispose(): Promise<void>;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Pure validation:不依赖 Electron / IPC / 任何 framework state,可单独 unit
|
|
42
|
+
* test。每一条检查对应 doc §3.3 字段约束。
|
|
43
|
+
*
|
|
44
|
+
* 验证语义保证:通过 validateConfig 的 config 不会在 framework Bind 阶段被拒。
|
|
45
|
+
* 含 HostEvent 来源、source 互斥、map vs array 等所有"shape 就绪"检查。
|
|
46
|
+
*
|
|
47
|
+
* @internal exported for tests
|
|
48
|
+
*/
|
|
49
|
+
export declare function validateConfig(config: DeckConfig): void;
|
|
50
|
+
/**
|
|
51
|
+
* publish-time guard:HostEvent 未在 `config.events` 中显式列出时阻止 publish。
|
|
52
|
+
* 避免 module-load-order 隐式注册。
|
|
53
|
+
*
|
|
54
|
+
* @internal exported for tests
|
|
55
|
+
*/
|
|
56
|
+
export declare function assertEventDeclared(declared: ReadonlySet<string>, eventName: string): void;
|
|
57
|
+
//# sourceMappingURL=electron-deck.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"electron-deck.d.ts","sourceRoot":"","sources":["../src/electron-deck.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAElE;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,YAAY,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAY3F;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,iBAAiB,CAChC,MAAM,EAAE,UAAU,EAClB,OAAO,CAAC,EAAE,WAAW,GACnB;IAAE,KAAK,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAAC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CAAE,CA4CvD;AAyED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CA6DvD;AAaD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAClC,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC,EAC7B,SAAS,EAAE,MAAM,GACf,IAAI,CAIN"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
//#region src/errors.ts
|
|
2
|
+
/**
|
|
3
|
+
* `defineEvent()` 创建的事件未在 `DeckConfig.events` 中显式列出时,
|
|
4
|
+
* `publish()` 会抛此错。避免 module-load-order 隐式注册。
|
|
5
|
+
*/
|
|
6
|
+
var UndeclaredHostEventError = class extends Error {
|
|
7
|
+
eventName;
|
|
8
|
+
constructor(eventName) {
|
|
9
|
+
super(`HostEvent "${eventName}" was not declared in DeckConfig.events. Add it to the events array so the framework knows to bind a transport for it.`);
|
|
10
|
+
this.name = "UndeclaredHostEventError";
|
|
11
|
+
this.eventName = eventName;
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* 在 Init / Bind 阶段调用 `HostEvent.publish()` 时抛 —— transport 尚未就绪。
|
|
16
|
+
* Setup / Ready 之后调用是安全的(fire-and-forget,无 replay)。
|
|
17
|
+
*/
|
|
18
|
+
var EventNotBoundError = class extends Error {
|
|
19
|
+
eventName;
|
|
20
|
+
constructor(eventName) {
|
|
21
|
+
super(`HostEvent "${eventName}" publish() called before transport is bound. publish() is safe only from Setup phase onward.`);
|
|
22
|
+
this.name = "EventNotBoundError";
|
|
23
|
+
this.eventName = eventName;
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* webview 调 `client.ready()` 时 framework bridge 不在 `window` 上(host preload
|
|
28
|
+
* 漏装 `exposeDeckBridge()`)。
|
|
29
|
+
*/
|
|
30
|
+
var DeckClientNotReadyError = class extends Error {
|
|
31
|
+
constructor(message = "Deck framework bridge is missing on window — did the host preload call exposeDeckBridge()?") {
|
|
32
|
+
super(message);
|
|
33
|
+
this.name = "DeckClientNotReadyError";
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* `client.invoke(name, ...)` 时远端 hostServices handler 抛错的封装。
|
|
38
|
+
* 保留原 error message,附带 remoteName / 可选 code 让 webview 侧便于分类。
|
|
39
|
+
*/
|
|
40
|
+
var DeckRemoteError = class extends Error {
|
|
41
|
+
remoteName;
|
|
42
|
+
code;
|
|
43
|
+
constructor(remoteName, message, code) {
|
|
44
|
+
super(message);
|
|
45
|
+
this.name = "DeckRemoteError";
|
|
46
|
+
this.remoteName = remoteName;
|
|
47
|
+
if (code !== void 0) this.code = code;
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
//#endregion
|
|
51
|
+
export { UndeclaredHostEventError as i, DeckRemoteError as n, EventNotBoundError as r, DeckClientNotReadyError as t };
|
|
52
|
+
|
|
53
|
+
//# sourceMappingURL=errors-NE2ig7L5.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors-NE2ig7L5.js","names":[],"sources":["../src/errors.ts"],"sourcesContent":["/**\n * `defineEvent()` 创建的事件未在 `DeckConfig.events` 中显式列出时,\n * `publish()` 会抛此错。避免 module-load-order 隐式注册。\n */\nexport class UndeclaredHostEventError extends Error {\n\treadonly eventName: string\n\tconstructor(eventName: string) {\n\t\tsuper(\n\t\t\t`HostEvent \"${eventName}\" was not declared in DeckConfig.events. ` +\n\t\t\t\t`Add it to the events array so the framework knows to bind a transport for it.`,\n\t\t)\n\t\tthis.name = 'UndeclaredHostEventError'\n\t\tthis.eventName = eventName\n\t}\n}\n\n/**\n * 在 Init / Bind 阶段调用 `HostEvent.publish()` 时抛 —— transport 尚未就绪。\n * Setup / Ready 之后调用是安全的(fire-and-forget,无 replay)。\n */\nexport class EventNotBoundError extends Error {\n\treadonly eventName: string\n\tconstructor(eventName: string) {\n\t\tsuper(\n\t\t\t`HostEvent \"${eventName}\" publish() called before transport is bound. ` +\n\t\t\t\t`publish() is safe only from Setup phase onward.`,\n\t\t)\n\t\tthis.name = 'EventNotBoundError'\n\t\tthis.eventName = eventName\n\t}\n}\n\n/**\n * webview 调 `client.ready()` 时 framework bridge 不在 `window` 上(host preload\n * 漏装 `exposeDeckBridge()`)。\n */\nexport class DeckClientNotReadyError extends Error {\n\tconstructor(message = 'Deck framework bridge is missing on window — did the host preload call exposeDeckBridge()?') {\n\t\tsuper(message)\n\t\tthis.name = 'DeckClientNotReadyError'\n\t}\n}\n\n/**\n * `client.invoke(name, ...)` 时远端 hostServices handler 抛错的封装。\n * 保留原 error message,附带 remoteName / 可选 code 让 webview 侧便于分类。\n */\nexport class DeckRemoteError extends Error {\n\treadonly remoteName: string\n\treadonly code?: string\n\tconstructor(remoteName: string, message: string, code?: string) {\n\t\tsuper(message)\n\t\tthis.name = 'DeckRemoteError'\n\t\tthis.remoteName = remoteName\n\t\tif (code !== undefined) this.code = code\n\t}\n}\n"],"mappings":";;;;;AAIA,IAAa,2BAAb,cAA8C,MAAM;CACnD;CACA,YAAY,WAAmB;EAC9B,MACC,cAAc,UAAU,uHAEzB;EACA,KAAK,OAAO;EACZ,KAAK,YAAY;CAClB;AACD;;;;;AAMA,IAAa,qBAAb,cAAwC,MAAM;CAC7C;CACA,YAAY,WAAmB;EAC9B,MACC,cAAc,UAAU,8FAEzB;EACA,KAAK,OAAO;EACZ,KAAK,YAAY;CAClB;AACD;;;;;AAMA,IAAa,0BAAb,cAA6C,MAAM;CAClD,YAAY,UAAU,8FAA8F;EACnH,MAAM,OAAO;EACb,KAAK,OAAO;CACb;AACD;;;;;AAMA,IAAa,kBAAb,cAAqC,MAAM;CAC1C;CACA;CACA,YAAY,YAAoB,SAAiB,MAAe;EAC/D,MAAM,OAAO;EACb,KAAK,OAAO;EACZ,KAAK,aAAa;EAClB,IAAI,SAAS,KAAA,GAAW,KAAK,OAAO;CACrC;AACD"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `defineEvent()` 创建的事件未在 `DeckConfig.events` 中显式列出时,
|
|
3
|
+
* `publish()` 会抛此错。避免 module-load-order 隐式注册。
|
|
4
|
+
*/
|
|
5
|
+
export declare class UndeclaredHostEventError extends Error {
|
|
6
|
+
readonly eventName: string;
|
|
7
|
+
constructor(eventName: string);
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* 在 Init / Bind 阶段调用 `HostEvent.publish()` 时抛 —— transport 尚未就绪。
|
|
11
|
+
* Setup / Ready 之后调用是安全的(fire-and-forget,无 replay)。
|
|
12
|
+
*/
|
|
13
|
+
export declare class EventNotBoundError extends Error {
|
|
14
|
+
readonly eventName: string;
|
|
15
|
+
constructor(eventName: string);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* webview 调 `client.ready()` 时 framework bridge 不在 `window` 上(host preload
|
|
19
|
+
* 漏装 `exposeDeckBridge()`)。
|
|
20
|
+
*/
|
|
21
|
+
export declare class DeckClientNotReadyError extends Error {
|
|
22
|
+
constructor(message?: string);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* `client.invoke(name, ...)` 时远端 hostServices handler 抛错的封装。
|
|
26
|
+
* 保留原 error message,附带 remoteName / 可选 code 让 webview 侧便于分类。
|
|
27
|
+
*/
|
|
28
|
+
export declare class DeckRemoteError extends Error {
|
|
29
|
+
readonly remoteName: string;
|
|
30
|
+
readonly code?: string;
|
|
31
|
+
constructor(remoteName: string, message: string, code?: string);
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,qBAAa,wBAAyB,SAAQ,KAAK;IAClD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;gBACd,SAAS,EAAE,MAAM;CAQ7B;AAED;;;GAGG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;IAC5C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;gBACd,SAAS,EAAE,MAAM;CAQ7B;AAED;;;GAGG;AACH,qBAAa,uBAAwB,SAAQ,KAAK;gBACrC,OAAO,SAA+F;CAIlH;AAED;;;GAGG;AACH,qBAAa,eAAgB,SAAQ,KAAK;IACzC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;gBACV,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM;CAM9D"}
|
package/dist/events.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { HostEvent, JsonValue } from './types.js';
|
|
2
|
+
export declare function defineEvent<P extends JsonValue>(name: string): HostEvent<P>;
|
|
3
|
+
/**
|
|
4
|
+
* 校验 `ev` 是否真的来自 `defineEvent()`。判定方式是 WeakMap 身份,而非
|
|
5
|
+
* `instanceof` —— 这样跨 vm.Context(同 module instance)也能工作。
|
|
6
|
+
*
|
|
7
|
+
* @internal
|
|
8
|
+
*/
|
|
9
|
+
export declare function isHostEvent(ev: unknown): ev is HostEvent<JsonValue>;
|
|
10
|
+
/** @internal framework 在 Bind 阶段调;同实例重复 bind 覆盖前任 */
|
|
11
|
+
export declare function bindHostEvent<P extends JsonValue>(event: HostEvent<P>, publisher: (payload: P) => void): void;
|
|
12
|
+
/** @internal framework 在 Cleanup 阶段调 */
|
|
13
|
+
export declare function unbindHostEvent<P extends JsonValue>(event: HostEvent<P>): void;
|
|
14
|
+
//# sourceMappingURL=events.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAc,SAAS,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AA0DlE,wBAAgB,WAAW,CAAC,CAAC,SAAS,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,CAK3E;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,EAAE,EAAE,OAAO,GAAG,EAAE,IAAI,SAAS,CAAC,SAAS,CAAC,CAGnE;AAED,qDAAqD;AACrD,wBAAgB,aAAa,CAAC,CAAC,SAAS,SAAS,EAChD,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC,EACnB,SAAS,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,IAAI,GAC7B,IAAI,CAQN;AAED,wCAAwC;AACxC,wBAAgB,eAAe,CAAC,CAAC,SAAS,SAAS,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,IAAI,CAM9E"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Capability grant registry — P4 Phase B.
|
|
3
|
+
*
|
|
4
|
+
* Default-DENY authorization for privileged control commands. A command is
|
|
5
|
+
* allowed for a sender ONLY while a LIVE grant naming that command (exact,
|
|
6
|
+
* whitelisted) is bound to that exact senderId. A grant dies the instant its
|
|
7
|
+
* `senderScope` generation ends: navigation soft-reuse (`reset`), window
|
|
8
|
+
* destroy (`closed`), or early `dispose()`.
|
|
9
|
+
*
|
|
10
|
+
* Each grant is a DISTINCT object stored in a Set, so two grants for the same
|
|
11
|
+
* senderId union their commands, and revoking one (its `senderScope` died)
|
|
12
|
+
* never touches another grant for that same senderId. The per-grant `revoked`
|
|
13
|
+
* guard makes a closed scope's revoke a no-op against a newly-issued grant —
|
|
14
|
+
* the wc.id-reuse safety property.
|
|
15
|
+
*
|
|
16
|
+
* @internal exported via `/host`.
|
|
17
|
+
*/
|
|
18
|
+
import type { Disposable } from '../types.js';
|
|
19
|
+
import type { Scope } from '../main/scope.js';
|
|
20
|
+
export interface Grant {
|
|
21
|
+
readonly senderId: number;
|
|
22
|
+
/** grant lifetime — revoked on this scope's reset/closed. */
|
|
23
|
+
readonly senderScope: Scope;
|
|
24
|
+
/**
|
|
25
|
+
* OPTIONAL — stored as the authorization boundary for FUTURE per-target
|
|
26
|
+
* view-command checks; the current grant gate authorizes by (senderId,
|
|
27
|
+
* command-name) only — no command resolves a target view yet, so targetScope is
|
|
28
|
+
* not consulted at dispatch. Reserved.
|
|
29
|
+
*/
|
|
30
|
+
readonly targetScope?: Scope;
|
|
31
|
+
readonly commands: ReadonlySet<string>;
|
|
32
|
+
}
|
|
33
|
+
export interface CapabilityPolicy {
|
|
34
|
+
/** true iff a LIVE grant exists with grant.senderId === senderId AND name ∈ grant.commands. default-DENY. */
|
|
35
|
+
allows(senderId: number, name: string): boolean;
|
|
36
|
+
}
|
|
37
|
+
export declare function createCapabilityRegistry(): {
|
|
38
|
+
policy: CapabilityPolicy;
|
|
39
|
+
issue(grant: Grant): Disposable;
|
|
40
|
+
/**
|
|
41
|
+
* Synchronously revoke EVERY live grant whose `grant.senderId === senderId`.
|
|
42
|
+
* Mirrors the trust path's synchronous window-'closed' revocation so a grant
|
|
43
|
+
* is gone the instant a wc is destroyed — before the async wcScope cascade
|
|
44
|
+
* fires `'closed'`. This closes the wc.id-reuse privilege-escalation window
|
|
45
|
+
* (a reused wc.id can never inherit the old, not-yet-revoked grant). Each
|
|
46
|
+
* per-grant `revoke` is idempotent, so the later async `'closed'` is a no-op.
|
|
47
|
+
*/
|
|
48
|
+
revokeBySenderId(senderId: number): void;
|
|
49
|
+
};
|
|
50
|
+
//# sourceMappingURL=capability.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capability.d.ts","sourceRoot":"","sources":["../../src/host/capability.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAC7C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAA;AAE7C,MAAM,WAAW,KAAK;IACrB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,6DAA6D;IAC7D,QAAQ,CAAC,WAAW,EAAE,KAAK,CAAA;IAC3B;;;;;OAKG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,KAAK,CAAA;IAC5B,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;CACtC;AAED,MAAM,WAAW,gBAAgB;IAChC,6GAA6G;IAC7G,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAA;CAC/C;AAED,wBAAgB,wBAAwB,IAAI;IAC3C,MAAM,EAAE,gBAAgB,CAAA;IACxB,KAAK,CAAC,KAAK,EAAE,KAAK,GAAG,UAAU,CAAA;IAC/B;;;;;;;OAOG;IACH,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;CACxC,CAsCA"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ControlBus — a thin, domain-neutral facade over the existing
|
|
3
|
+
* {@link WireTransport} + {@link EventBus} + an injectable refcount
|
|
4
|
+
* {@link TrustSet}.
|
|
5
|
+
*
|
|
6
|
+
* Three verbs, no new gating logic of its own:
|
|
7
|
+
*
|
|
8
|
+
* - `command(name, handler)` : webview → main RPC. The facade owns the single
|
|
9
|
+
* command table and exposes {@link ControlBus.dispatch}; the wire's
|
|
10
|
+
* `invokeHost` (and `invokeSimulator`) seam calls `dispatch(name, args)` so a
|
|
11
|
+
* real webview→main invoke (after the wire's sender + main-frame gate) lands on
|
|
12
|
+
* the registered handler. Callers never see the wire `kind`. Trust + main-frame
|
|
13
|
+
* gating are entirely the wire's (`handleInvoke`): a trusted main-frame sender
|
|
14
|
+
* reaches the handler, an untrusted sender → `DECK_UNTRUSTED_SENDER`, a
|
|
15
|
+
* sub-frame → `DECK_UNTRUSTED_FRAME`.
|
|
16
|
+
* - `event(name)` : main → webview push, default-deny. `name` is added to the
|
|
17
|
+
* declared-event allowlist the wire reads; `publish` goes through `bus.publish`
|
|
18
|
+
* → wire fanout (undeclared names are dropped by the wire). `dispose` revokes
|
|
19
|
+
* the declaration.
|
|
20
|
+
* - `trust(wc, owner)` : delegates to `trustSet.admit` (refcount membership owned
|
|
21
|
+
* by `owner` Scope, so the lease is released when the owner tears down).
|
|
22
|
+
*
|
|
23
|
+
* Real wiring (Bug C): the command table is the SOLE command authority. The
|
|
24
|
+
* production caller builds the {@link WireTransport} with
|
|
25
|
+
* `invokeHost = (name, args) => controlBus.dispatch(name, args)` (and the same
|
|
26
|
+
* for `invokeSimulator`, since the facade hides the kind), and `declaredEvents`
|
|
27
|
+
* reading {@link ControlBus.declaredEvents}. So a real IPC invoke reaches the
|
|
28
|
+
* command handler through the wire — not a private test-only seam. Any
|
|
29
|
+
* config-declared host services register into this SAME table via `command()`,
|
|
30
|
+
* so there is one namespace (the host keeps names unique), never two registries
|
|
31
|
+
* that can collide.
|
|
32
|
+
*
|
|
33
|
+
* @internal exported via `/host`.
|
|
34
|
+
*/
|
|
35
|
+
import type { Disposable, JsonValue } from '../types.js';
|
|
36
|
+
import type { EventBus } from '../internal/event-bus.js';
|
|
37
|
+
import type { InvokeCtx, MinimalWebContents, WireTransport } from '../internal/wire-transport.js';
|
|
38
|
+
import type { TrustSet } from '../internal/trust-set.js';
|
|
39
|
+
import type { Scope } from '../main/scope.js';
|
|
40
|
+
import type { CapabilityPolicy } from './capability.js';
|
|
41
|
+
export type { TrustSet };
|
|
42
|
+
export { createTrustSet } from '../internal/trust-set.js';
|
|
43
|
+
type CommandHandler = (...args: JsonValue[]) => JsonValue | Promise<JsonValue>;
|
|
44
|
+
export interface ControlBusEventHandle<P extends JsonValue> {
|
|
45
|
+
publish(payload: P): void;
|
|
46
|
+
dispose(): void;
|
|
47
|
+
}
|
|
48
|
+
export interface ControlBus {
|
|
49
|
+
/** Register a webview → main RPC handler under a domain-neutral `name`. */
|
|
50
|
+
command(name: string, handler: CommandHandler): Disposable;
|
|
51
|
+
/** Declare a main → webview push event (default-deny allowlist). */
|
|
52
|
+
event<P extends JsonValue>(name: string): ControlBusEventHandle<P>;
|
|
53
|
+
/** Admit a webContents into the refcount trust set, owned by `owner` Scope
|
|
54
|
+
* (the lease is released when `owner` resets/closes). */
|
|
55
|
+
trust(wc: MinimalWebContents, owner: Scope): Disposable;
|
|
56
|
+
/**
|
|
57
|
+
* Real wire entry point — the {@link WireTransport}'s `invokeHost` /
|
|
58
|
+
* `invokeSimulator` seam calls this with a domain-neutral `name` AFTER its
|
|
59
|
+
* trust + main-frame gate. Resolves the command table; throws if `name` is
|
|
60
|
+
* unregistered (the wire serialises that into an `InvokeFailure`). `ctx`
|
|
61
|
+
* carries the gated senderId (Phase B's grant gate reads it; Phase A passes
|
|
62
|
+
* it through unused).
|
|
63
|
+
*/
|
|
64
|
+
dispatch(name: string, args: readonly JsonValue[], ctx: InvokeCtx): Promise<JsonValue>;
|
|
65
|
+
/**
|
|
66
|
+
* Current declared-event allowlist snapshot — the wire's `declaredEvents`
|
|
67
|
+
* seam reads this (lazy, per publish) so default-deny tracks `event()` /
|
|
68
|
+
* `dispose()` in real time.
|
|
69
|
+
*/
|
|
70
|
+
declaredEvents(): readonly string[];
|
|
71
|
+
}
|
|
72
|
+
export interface CreateControlBusDeps {
|
|
73
|
+
/**
|
|
74
|
+
* Vestigial — the facade never calls into the wire from inside `dispatch` /
|
|
75
|
+
* `command` / `event` / `trust` (the wire is the one that calls `dispatch`,
|
|
76
|
+
* not the reverse). Made OPTIONAL so deck-app can construct the ControlBus
|
|
77
|
+
* BEFORE the WireTransport (which references the ControlBus from its
|
|
78
|
+
* `invokeHost` seam) — no circular dependency at construction time.
|
|
79
|
+
*/
|
|
80
|
+
readonly transport?: WireTransport;
|
|
81
|
+
readonly bus: EventBus;
|
|
82
|
+
readonly trustSet: TrustSet;
|
|
83
|
+
/**
|
|
84
|
+
* P4 Phase B — privileged-command grant gate. When provided, `dispatch`
|
|
85
|
+
* default-DENIES any command not authorized by a live grant for the gated
|
|
86
|
+
* `ctx.senderId`. Omitted → no gate (backward-compatible "trusted may
|
|
87
|
+
* dispatch" behaviour).
|
|
88
|
+
*/
|
|
89
|
+
readonly policy?: CapabilityPolicy;
|
|
90
|
+
}
|
|
91
|
+
export declare function createControlBus(deps: CreateControlBusDeps): ControlBus;
|
|
92
|
+
//# sourceMappingURL=control-bus.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"control-bus.d.ts","sourceRoot":"","sources":["../../src/host/control-bus.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACxD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAA;AAExD,OAAO,KAAK,EAAE,SAAS,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAA;AACjG,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAA;AACxD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AAEvD,YAAY,EAAE,QAAQ,EAAE,CAAA;AACxB,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAEzD,KAAK,cAAc,GAAG,CAAC,GAAG,IAAI,EAAE,SAAS,EAAE,KAAK,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC,CAAA;AAE9E,MAAM,WAAW,qBAAqB,CAAC,CAAC,SAAS,SAAS;IACzD,OAAO,CAAC,OAAO,EAAE,CAAC,GAAG,IAAI,CAAA;IACzB,OAAO,IAAI,IAAI,CAAA;CACf;AAED,MAAM,WAAW,UAAU;IAC1B,2EAA2E;IAC3E,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,UAAU,CAAA;IAC1D,oEAAoE;IACpE,KAAK,CAAC,CAAC,SAAS,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,qBAAqB,CAAC,CAAC,CAAC,CAAA;IAClE;8DAC0D;IAC1D,KAAK,CAAC,EAAE,EAAE,kBAAkB,EAAE,KAAK,EAAE,KAAK,GAAG,UAAU,CAAA;IACvD;;;;;;;OAOG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,SAAS,EAAE,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC,CAAA;IACtF;;;;OAIG;IACH,cAAc,IAAI,SAAS,MAAM,EAAE,CAAA;CACnC;AAED,MAAM,WAAW,oBAAoB;IACpC;;;;;;OAMG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,aAAa,CAAA;IAClC,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAA;IACtB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAA;IAC3B;;;;;OAKG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,gBAAgB,CAAA;CAClC;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,oBAAoB,GAAG,UAAU,CAgEvE"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@dimina-kit/electron-deck/host` — the cross-process host-shell transport.
|
|
3
|
+
*
|
|
4
|
+
* These are the transport pieces the `electronDeck()` entry (exported from this
|
|
5
|
+
* package's root, `@dimina-kit/electron-deck`) and domain backends construct to
|
|
6
|
+
* carry `hostServices` (trusted-webview RPC) and `events` (main→webview push)
|
|
7
|
+
* over a real Electron `ipcMain`:
|
|
8
|
+
*
|
|
9
|
+
* - `WireTransport` — the wire protocol (probe / invoke / event fanout)
|
|
10
|
+
* - `EventBus` — declared-event publisher fan-out
|
|
11
|
+
* - `InMemoryTypedIpcRegistry` — main-process handler/invoke registry the
|
|
12
|
+
* transport routes host/simulator kinds through
|
|
13
|
+
*
|
|
14
|
+
* The `electronDeck(config)` orchestration lives in this package's root entry
|
|
15
|
+
* (`@dimina-kit/electron-deck`, see `src/index.ts`); it stays domain-neutral and
|
|
16
|
+
* receives the domain assembly via an injected `RuntimeBackend`. Exposing the
|
|
17
|
+
* transport here lets a backend implementer assemble it. See
|
|
18
|
+
* packages/devtools/docs/workbench-model.md.
|
|
19
|
+
*/
|
|
20
|
+
export { WireTransport, type InvokeCtx, type MinimalIpcMain, type MinimalWebContents, type WireTransportDeps, } from '../internal/wire-transport.js';
|
|
21
|
+
export { EventBus } from '../internal/event-bus.js';
|
|
22
|
+
export { InMemoryTypedIpcRegistry } from '../internal/ipc-registry-memory.js';
|
|
23
|
+
/**
|
|
24
|
+
* Domain-neutral facade (`command` / `event` / `trust`) over the wire + bus +
|
|
25
|
+
* trust set, plus the refcount trust-set primitive it depends on.
|
|
26
|
+
*/
|
|
27
|
+
export { createControlBus, type ControlBus, type ControlBusEventHandle, type CreateControlBusDeps, } from './control-bus.js';
|
|
28
|
+
export { createTrustSet, type TrustSet, type TrustIndex } from '../internal/trust-set.js';
|
|
29
|
+
/**
|
|
30
|
+
* P4 Phase B — capability grant registry + policy (the privileged-command gate).
|
|
31
|
+
*/
|
|
32
|
+
export { createCapabilityRegistry, type CapabilityPolicy, type Grant, } from './capability.js';
|
|
33
|
+
/** Pure config validation (rejects malformed config before assembly). */
|
|
34
|
+
export { validateConfig } from '../electron-deck.js';
|
|
35
|
+
/**
|
|
36
|
+
* Backend-facing types. `RuntimeBackend` / `TrustedSenderRef` also flow through
|
|
37
|
+
* the root entry (`@dimina-kit/electron-deck`); re-exported here so a backend
|
|
38
|
+
* implementer has one import site alongside the transport pieces.
|
|
39
|
+
*/
|
|
40
|
+
export type { MinimalApp } from '../internal/electron-types.js';
|
|
41
|
+
export type { RuntimeBackend, TrustedSenderRef } from '../types.js';
|
|
42
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/host/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EACL,aAAa,EACb,KAAK,SAAS,EACd,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,GACvB,MAAM,+BAA+B,CAAA;AACtC,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAA;AACnD,OAAO,EAAE,wBAAwB,EAAE,MAAM,oCAAoC,CAAA;AAC7E;;;GAGG;AACH,OAAO,EACL,gBAAgB,EAChB,KAAK,UAAU,EACf,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,GAC1B,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAE,cAAc,EAAE,KAAK,QAAQ,EAAE,KAAK,UAAU,EAAE,MAAM,0BAA0B,CAAA;AACzF;;GAEG;AACH,OAAO,EACL,wBAAwB,EACxB,KAAK,gBAAgB,EACrB,KAAK,KAAK,GACX,MAAM,iBAAiB,CAAA;AACxB,yEAAyE;AACzE,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AACpD;;;;GAIG;AACH,YAAY,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAA;AAC/D,YAAY,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { a as WireTransport, c as InMemoryTypedIpcRegistry, i as createControlBus, l as EventBus, o as createCapabilityRegistry, r as validateConfig, s as createTrustSet } from "../electron-deck-DfFKeFEC.js";
|
|
2
|
+
export { EventBus, InMemoryTypedIpcRegistry, WireTransport, createCapabilityRegistry, createControlBus, createTrustSet, validateConfig };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA;AAC3B,cAAc,YAAY,CAAA;AAC1B,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AACpE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { i as UndeclaredHostEventError, n as DeckRemoteError, r as EventNotBoundError, t as DeckClientNotReadyError } from "./errors-NE2ig7L5.js";
|
|
2
|
+
import { n as startElectronDeck, t as electronDeck, u as defineEvent } from "./electron-deck-DfFKeFEC.js";
|
|
3
|
+
export { DeckClientNotReadyError, DeckRemoteError, EventNotBoundError, UndeclaredHostEventError, defineEvent, electronDeck, startElectronDeck };
|