@cordy/electro 1.2.4 → 1.2.5
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/index.d.mts +111 -83
- package/dist/index.mjs +61 -3
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -16,90 +16,9 @@ declare enum FeatureStatus {
|
|
|
16
16
|
ERROR = "error"
|
|
17
17
|
}
|
|
18
18
|
//#endregion
|
|
19
|
-
//#region src/core/view/types.d.ts
|
|
20
|
-
type ViewId = string;
|
|
21
|
-
/** Runtime view registry entry — injected by CLI via __ELECTRO_VIEW_REGISTRY__. */
|
|
22
|
-
interface ViewRegistryEntry {
|
|
23
|
-
id: ViewId;
|
|
24
|
-
hasRenderer: boolean;
|
|
25
|
-
webPreferences?: Record<string, unknown>;
|
|
26
|
-
}
|
|
27
|
-
/** A WebContentsView augmented with `load()` for renderer-linked views. */
|
|
28
|
-
type ElectroView = WebContentsView & {
|
|
29
|
-
load(): Promise<void>;
|
|
30
|
-
};
|
|
31
|
-
/** Public interface — hides the View class. */
|
|
32
|
-
interface ViewInstance {
|
|
33
|
-
readonly id: ViewId;
|
|
34
|
-
/** Create the WebContentsView. Idempotent: returns existing if alive. */
|
|
35
|
-
create(): ElectroView;
|
|
36
|
-
/** Return the live ElectroView, or null if not yet created / destroyed. */
|
|
37
|
-
view(): ElectroView | null;
|
|
38
|
-
/** Destroy the WebContentsView and clear refs. */
|
|
39
|
-
destroy(): void;
|
|
40
|
-
}
|
|
41
|
-
//#endregion
|
|
42
|
-
//#region src/core/view/manager.d.ts
|
|
43
|
-
/**
|
|
44
|
-
* ViewManager — global registry for view instances.
|
|
45
|
-
*
|
|
46
|
-
* Views are registered at runtime startup and accessible from any feature.
|
|
47
|
-
* Views are idempotent: `get(id).create()` returns the same instance if alive.
|
|
48
|
-
*/
|
|
49
|
-
declare class ViewManager {
|
|
50
|
-
private readonly instances;
|
|
51
|
-
register(view: ViewInstance): void;
|
|
52
|
-
get(id: ViewId): ViewInstance | null;
|
|
53
|
-
destroyAll(): void;
|
|
54
|
-
}
|
|
55
|
-
//#endregion
|
|
56
|
-
//#region src/core/window/types.d.ts
|
|
57
|
-
type WindowId = string;
|
|
58
|
-
interface WindowConfig<TApi = void> {
|
|
59
|
-
id: WindowId;
|
|
60
|
-
options?: BaseWindowConstructorOptions;
|
|
61
|
-
api?: (window: BaseWindow) => TApi;
|
|
62
|
-
}
|
|
63
|
-
/** Base window interface (without API methods). */
|
|
64
|
-
interface WindowBase {
|
|
65
|
-
readonly id: WindowId;
|
|
66
|
-
/** Create the BaseWindow. Idempotent: returns existing if alive. */
|
|
67
|
-
create(): BaseWindow;
|
|
68
|
-
/** The live BaseWindow, or null if not yet created / destroyed. */
|
|
69
|
-
readonly window: BaseWindow | null;
|
|
70
|
-
/** Destroy the BaseWindow and clear refs. */
|
|
71
|
-
destroy(): void;
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Public interface — API methods are mixed directly onto the object.
|
|
75
|
-
* Access API methods directly: `window.show()` instead of `window.api?.show()`.
|
|
76
|
-
*/
|
|
77
|
-
type CreatedWindow<TApi = void> = WindowBase & (TApi extends void ? {} : TApi) & {
|
|
78
|
-
/** @internal Phantom type for API type inference. */readonly __apiType?: TApi;
|
|
79
|
-
};
|
|
80
|
-
/** Type-erased interface for managers. */
|
|
81
|
-
interface WindowInstance {
|
|
82
|
-
readonly id: WindowId;
|
|
83
|
-
create(): BaseWindow;
|
|
84
|
-
readonly window: BaseWindow | null;
|
|
85
|
-
destroy(): void;
|
|
86
|
-
}
|
|
87
|
-
//#endregion
|
|
88
|
-
//#region src/core/window/manager.d.ts
|
|
89
|
-
/**
|
|
90
|
-
* WindowManager — global registry for window instances.
|
|
91
|
-
*
|
|
92
|
-
* Windows are registered at runtime startup and accessible from any feature.
|
|
93
|
-
*/
|
|
94
|
-
declare class WindowManager {
|
|
95
|
-
private readonly instances;
|
|
96
|
-
register(window: WindowInstance): void;
|
|
97
|
-
get(id: WindowId): WindowInstance | null;
|
|
98
|
-
destroyAll(): void;
|
|
99
|
-
}
|
|
100
|
-
//#endregion
|
|
101
19
|
//#region src/core/event-bus/types.d.ts
|
|
102
20
|
type EventHandler = (payload: unknown) => void;
|
|
21
|
+
type EventInterceptor = (channel: string, payload: unknown) => void;
|
|
103
22
|
type EventSubscription = {
|
|
104
23
|
channel: string;
|
|
105
24
|
handler: EventHandler;
|
|
@@ -129,7 +48,10 @@ interface CreatedEvent<T = void> extends EventInstance {
|
|
|
129
48
|
//#region src/core/event-bus/event-bus.d.ts
|
|
130
49
|
declare class EventBus {
|
|
131
50
|
private readonly subscriptions;
|
|
51
|
+
private readonly interceptors;
|
|
132
52
|
publish(channel: string, payload?: unknown): void;
|
|
53
|
+
/** Register an interceptor that receives every published event. Returns an unsubscribe function. */
|
|
54
|
+
addInterceptor(fn: EventInterceptor): () => void;
|
|
133
55
|
subscribe(channel: string, handler: EventHandler, ownerId: string): () => void;
|
|
134
56
|
removeByOwner(ownerId: string): void;
|
|
135
57
|
}
|
|
@@ -376,6 +298,89 @@ declare class StateMachine<TState extends string> {
|
|
|
376
298
|
onTransition(cb: TransitionListener<TState>): () => void;
|
|
377
299
|
}
|
|
378
300
|
//#endregion
|
|
301
|
+
//#region src/core/view/types.d.ts
|
|
302
|
+
type ViewId = string;
|
|
303
|
+
/** Runtime view registry entry — injected by CLI via __ELECTRO_VIEW_REGISTRY__. */
|
|
304
|
+
interface ViewRegistryEntry {
|
|
305
|
+
id: ViewId;
|
|
306
|
+
hasRenderer: boolean;
|
|
307
|
+
features?: readonly string[];
|
|
308
|
+
webPreferences?: Record<string, unknown>;
|
|
309
|
+
}
|
|
310
|
+
/** A WebContentsView augmented with `load()` for renderer-linked views. */
|
|
311
|
+
type ElectroView = WebContentsView & {
|
|
312
|
+
load(): Promise<void>;
|
|
313
|
+
};
|
|
314
|
+
/** Public interface — hides the View class. */
|
|
315
|
+
interface ViewInstance {
|
|
316
|
+
readonly id: ViewId;
|
|
317
|
+
/** Create the WebContentsView. Idempotent: returns existing if alive. */
|
|
318
|
+
create(): ElectroView;
|
|
319
|
+
/** Return the live ElectroView, or null if not yet created / destroyed. */
|
|
320
|
+
view(): ElectroView | null;
|
|
321
|
+
/** Destroy the WebContentsView and clear refs. */
|
|
322
|
+
destroy(): void;
|
|
323
|
+
}
|
|
324
|
+
//#endregion
|
|
325
|
+
//#region src/core/view/manager.d.ts
|
|
326
|
+
/**
|
|
327
|
+
* ViewManager — global registry for view instances.
|
|
328
|
+
*
|
|
329
|
+
* Views are registered at runtime startup and accessible from any feature.
|
|
330
|
+
* Views are idempotent: `get(id).create()` returns the same instance if alive.
|
|
331
|
+
*/
|
|
332
|
+
declare class ViewManager {
|
|
333
|
+
private readonly instances;
|
|
334
|
+
register(view: ViewInstance): void;
|
|
335
|
+
get(id: ViewId): ViewInstance | null;
|
|
336
|
+
destroyAll(): void;
|
|
337
|
+
}
|
|
338
|
+
//#endregion
|
|
339
|
+
//#region src/core/window/types.d.ts
|
|
340
|
+
type WindowId = string;
|
|
341
|
+
interface WindowConfig<TApi = void> {
|
|
342
|
+
id: WindowId;
|
|
343
|
+
options?: BaseWindowConstructorOptions;
|
|
344
|
+
api?: (window: BaseWindow) => TApi;
|
|
345
|
+
}
|
|
346
|
+
/** Base window interface (without API methods). */
|
|
347
|
+
interface WindowBase {
|
|
348
|
+
readonly id: WindowId;
|
|
349
|
+
/** Create the BaseWindow. Idempotent: returns existing if alive. */
|
|
350
|
+
create(): BaseWindow;
|
|
351
|
+
/** The live BaseWindow, or null if not yet created / destroyed. */
|
|
352
|
+
readonly window: BaseWindow | null;
|
|
353
|
+
/** Destroy the BaseWindow and clear refs. */
|
|
354
|
+
destroy(): void;
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Public interface — API methods are mixed directly onto the object.
|
|
358
|
+
* Access API methods directly: `window.show()` instead of `window.api?.show()`.
|
|
359
|
+
*/
|
|
360
|
+
type CreatedWindow<TApi = void> = WindowBase & (TApi extends void ? {} : TApi) & {
|
|
361
|
+
/** @internal Phantom type for API type inference. */readonly __apiType?: TApi;
|
|
362
|
+
};
|
|
363
|
+
/** Type-erased interface for managers. */
|
|
364
|
+
interface WindowInstance {
|
|
365
|
+
readonly id: WindowId;
|
|
366
|
+
create(): BaseWindow;
|
|
367
|
+
readonly window: BaseWindow | null;
|
|
368
|
+
destroy(): void;
|
|
369
|
+
}
|
|
370
|
+
//#endregion
|
|
371
|
+
//#region src/core/window/manager.d.ts
|
|
372
|
+
/**
|
|
373
|
+
* WindowManager — global registry for window instances.
|
|
374
|
+
*
|
|
375
|
+
* Windows are registered at runtime startup and accessible from any feature.
|
|
376
|
+
*/
|
|
377
|
+
declare class WindowManager {
|
|
378
|
+
private readonly instances;
|
|
379
|
+
register(window: WindowInstance): void;
|
|
380
|
+
get(id: WindowId): WindowInstance | null;
|
|
381
|
+
destroyAll(): void;
|
|
382
|
+
}
|
|
383
|
+
//#endregion
|
|
379
384
|
//#region src/core/feature/manager.d.ts
|
|
380
385
|
declare class FeatureManager {
|
|
381
386
|
private logger;
|
|
@@ -679,6 +684,28 @@ declare class EventAccessor {
|
|
|
679
684
|
on(event: string, handler: EventHandler): () => void;
|
|
680
685
|
}
|
|
681
686
|
//#endregion
|
|
687
|
+
//#region src/core/event-bus/bridge.d.ts
|
|
688
|
+
/**
|
|
689
|
+
* Forwards EventBus publishes to renderer views via IPC.
|
|
690
|
+
*
|
|
691
|
+
* Respects deny-by-default policy: only views whose `features` array
|
|
692
|
+
* includes the publishing feature's ID receive the event.
|
|
693
|
+
*
|
|
694
|
+
* IPC channel format: `electro:event:{featureId}:{eventName}`
|
|
695
|
+
*/
|
|
696
|
+
declare class EventBridge {
|
|
697
|
+
private readonly eventBus;
|
|
698
|
+
private readonly viewManager;
|
|
699
|
+
private readonly viewFeatures;
|
|
700
|
+
private removeInterceptor;
|
|
701
|
+
constructor(eventBus: EventBus, viewManager: ViewManager, viewRegistry: readonly ViewRegistryEntry[]);
|
|
702
|
+
/** Start forwarding events to eligible views. */
|
|
703
|
+
start(): void;
|
|
704
|
+
/** Stop forwarding and clean up. */
|
|
705
|
+
stop(): void;
|
|
706
|
+
private forward;
|
|
707
|
+
}
|
|
708
|
+
//#endregion
|
|
682
709
|
//#region src/core/event-bus/helpers.d.ts
|
|
683
710
|
/**
|
|
684
711
|
* Creates a typed event definition.
|
|
@@ -746,6 +773,7 @@ declare class Runtime {
|
|
|
746
773
|
private readonly eventBus;
|
|
747
774
|
private readonly windowManager;
|
|
748
775
|
private readonly viewManager;
|
|
776
|
+
private readonly eventBridge;
|
|
749
777
|
constructor(config?: RuntimeConfig);
|
|
750
778
|
register(features: FeatureConfig<any> | FeatureConfig<any>[]): void;
|
|
751
779
|
start(): Promise<void>;
|
|
@@ -820,4 +848,4 @@ declare class PolicyEngine {
|
|
|
820
848
|
getViewNames(): string[];
|
|
821
849
|
}
|
|
822
850
|
//#endregion
|
|
823
|
-
export { type BaseContext, type CreatedEvent, type CreatedService, type CreatedTask, type CreatedWindow, type DefineConfigInput, type DefineRuntimeInput, type DefineViewInput, type ElectroConfig, type ElectroView, EventAccessor, type EventHandler, type EventId, type EventInstance, type EventSubscription, type FeatureConfig, type FeatureContext, type FeatureHandle, type FeatureId, type FeatureMap, FeatureStatus, type LogEntry, type LogHandler, type LoggerContext, PolicyDecision, PolicyEngine, type PolicyResult, Runtime, type RuntimeConfig, type RuntimeDefinition, RuntimeState, type ServiceConfig, type ServiceId, type ServiceInfo, type ServiceOwnerMap, ServiceScope, ServiceStatus, type StopMode, type TaskConfig, type TaskExecutionContext, type TaskHandle, type TaskId, TaskOverlapStrategy, type TaskOwnerMap, TaskRetryStrategy, TaskStatus, type TaskStatusInfo, type TypedContext, type ViewDefinition, type ViewId, type ViewInstance, type ViewMap, type ViewRegistryEntry, type WindowApiMap, type WindowConfig, type WindowId, type WindowInstance, createEvent, createFeature, createRuntime, createService, createTask, createWindow, defineConfig, defineRuntime, defineView };
|
|
851
|
+
export { type BaseContext, type CreatedEvent, type CreatedService, type CreatedTask, type CreatedWindow, type DefineConfigInput, type DefineRuntimeInput, type DefineViewInput, type ElectroConfig, type ElectroView, EventAccessor, EventBridge, type EventHandler, type EventId, type EventInstance, type EventInterceptor, type EventSubscription, type FeatureConfig, type FeatureContext, type FeatureHandle, type FeatureId, type FeatureMap, FeatureStatus, type LogEntry, type LogHandler, type LoggerContext, PolicyDecision, PolicyEngine, type PolicyResult, Runtime, type RuntimeConfig, type RuntimeDefinition, RuntimeState, type ServiceConfig, type ServiceId, type ServiceInfo, type ServiceOwnerMap, ServiceScope, ServiceStatus, type StopMode, type TaskConfig, type TaskExecutionContext, type TaskHandle, type TaskId, TaskOverlapStrategy, type TaskOwnerMap, TaskRetryStrategy, TaskStatus, type TaskStatusInfo, type TypedContext, type ViewDefinition, type ViewId, type ViewInstance, type ViewMap, type ViewRegistryEntry, type WindowApiMap, type WindowConfig, type WindowId, type WindowInstance, createEvent, createFeature, createRuntime, createService, createTask, createWindow, defineConfig, defineRuntime, defineView };
|
package/dist/index.mjs
CHANGED
|
@@ -96,6 +96,51 @@ var EventAccessor = class {
|
|
|
96
96
|
}
|
|
97
97
|
};
|
|
98
98
|
|
|
99
|
+
//#endregion
|
|
100
|
+
//#region src/core/event-bus/bridge.ts
|
|
101
|
+
/**
|
|
102
|
+
* Forwards EventBus publishes to renderer views via IPC.
|
|
103
|
+
*
|
|
104
|
+
* Respects deny-by-default policy: only views whose `features` array
|
|
105
|
+
* includes the publishing feature's ID receive the event.
|
|
106
|
+
*
|
|
107
|
+
* IPC channel format: `electro:event:{featureId}:{eventName}`
|
|
108
|
+
*/
|
|
109
|
+
var EventBridge = class {
|
|
110
|
+
viewFeatures;
|
|
111
|
+
removeInterceptor = null;
|
|
112
|
+
constructor(eventBus, viewManager, viewRegistry) {
|
|
113
|
+
this.eventBus = eventBus;
|
|
114
|
+
this.viewManager = viewManager;
|
|
115
|
+
this.viewFeatures = /* @__PURE__ */ new Map();
|
|
116
|
+
for (const entry of viewRegistry) if (entry.features && entry.features.length > 0) this.viewFeatures.set(entry.id, new Set(entry.features));
|
|
117
|
+
}
|
|
118
|
+
/** Start forwarding events to eligible views. */
|
|
119
|
+
start() {
|
|
120
|
+
if (this.removeInterceptor) return;
|
|
121
|
+
this.removeInterceptor = this.eventBus.addInterceptor((channel, payload) => this.forward(channel, payload));
|
|
122
|
+
}
|
|
123
|
+
/** Stop forwarding and clean up. */
|
|
124
|
+
stop() {
|
|
125
|
+
this.removeInterceptor?.();
|
|
126
|
+
this.removeInterceptor = null;
|
|
127
|
+
}
|
|
128
|
+
forward(channel, payload) {
|
|
129
|
+
const colonIdx = channel.indexOf(":");
|
|
130
|
+
if (colonIdx === -1) return;
|
|
131
|
+
const featureId = channel.slice(0, colonIdx);
|
|
132
|
+
const ipcChannel = `electro:event:${channel}`;
|
|
133
|
+
for (const [viewId, allowed] of this.viewFeatures) {
|
|
134
|
+
if (!allowed.has(featureId)) continue;
|
|
135
|
+
const view = this.viewManager.get(viewId)?.view();
|
|
136
|
+
if (!view || view.webContents.isDestroyed()) continue;
|
|
137
|
+
try {
|
|
138
|
+
view.webContents.send(ipcChannel, payload);
|
|
139
|
+
} catch {}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
|
|
99
144
|
//#endregion
|
|
100
145
|
//#region src/core/event-bus/helpers.ts
|
|
101
146
|
function createEvent(id, defaults) {
|
|
@@ -154,10 +199,18 @@ let RuntimeState = /* @__PURE__ */ function(RuntimeState) {
|
|
|
154
199
|
//#region src/core/event-bus/event-bus.ts
|
|
155
200
|
var EventBus = class {
|
|
156
201
|
subscriptions = /* @__PURE__ */ new Map();
|
|
202
|
+
interceptors = /* @__PURE__ */ new Set();
|
|
157
203
|
publish(channel, payload) {
|
|
158
204
|
const subs = this.subscriptions.get(channel);
|
|
159
|
-
if (
|
|
160
|
-
for (const
|
|
205
|
+
if (subs) for (const sub of subs) sub.handler(payload);
|
|
206
|
+
for (const interceptor of this.interceptors) interceptor(channel, payload);
|
|
207
|
+
}
|
|
208
|
+
/** Register an interceptor that receives every published event. Returns an unsubscribe function. */
|
|
209
|
+
addInterceptor(fn) {
|
|
210
|
+
this.interceptors.add(fn);
|
|
211
|
+
return () => {
|
|
212
|
+
this.interceptors.delete(fn);
|
|
213
|
+
};
|
|
161
214
|
}
|
|
162
215
|
subscribe(channel, handler, ownerId) {
|
|
163
216
|
const sub = {
|
|
@@ -991,6 +1044,7 @@ var Runtime = class {
|
|
|
991
1044
|
eventBus;
|
|
992
1045
|
windowManager;
|
|
993
1046
|
viewManager;
|
|
1047
|
+
eventBridge = null;
|
|
994
1048
|
constructor(config) {
|
|
995
1049
|
this.state = new StateMachine({
|
|
996
1050
|
transitions: RUNTIME_TRANSITIONS,
|
|
@@ -1007,6 +1061,7 @@ var Runtime = class {
|
|
|
1007
1061
|
this.viewManager = new ViewManager();
|
|
1008
1062
|
const viewRegistry = typeof __ELECTRO_VIEW_REGISTRY__ !== "undefined" ? __ELECTRO_VIEW_REGISTRY__ : [];
|
|
1009
1063
|
for (const entry of viewRegistry) this.viewManager.register(new View(entry));
|
|
1064
|
+
if (viewRegistry.some((v) => v.features && v.features.length > 0)) this.eventBridge = new EventBridge(this.eventBus, this.viewManager, viewRegistry);
|
|
1010
1065
|
this.featureManager.setWindowManager(this.windowManager);
|
|
1011
1066
|
this.featureManager.setViewManager(this.viewManager);
|
|
1012
1067
|
if (config?.features) this.featureManager.register(config.features);
|
|
@@ -1018,9 +1073,11 @@ var Runtime = class {
|
|
|
1018
1073
|
async start() {
|
|
1019
1074
|
this.state.transition(RuntimeState.STARTING);
|
|
1020
1075
|
try {
|
|
1076
|
+
this.eventBridge?.start();
|
|
1021
1077
|
await this.featureManager.bootstrap();
|
|
1022
1078
|
this.state.transition(RuntimeState.RUNNING);
|
|
1023
1079
|
} catch (err) {
|
|
1080
|
+
this.eventBridge?.stop();
|
|
1024
1081
|
this.state.transition(RuntimeState.FAILED);
|
|
1025
1082
|
throw err;
|
|
1026
1083
|
}
|
|
@@ -1028,6 +1085,7 @@ var Runtime = class {
|
|
|
1028
1085
|
async shutdown() {
|
|
1029
1086
|
this.state.assertState(RuntimeState.RUNNING);
|
|
1030
1087
|
this.state.transition(RuntimeState.STOPPING);
|
|
1088
|
+
this.eventBridge?.stop();
|
|
1031
1089
|
await this.featureManager.shutdown();
|
|
1032
1090
|
this.viewManager.destroyAll();
|
|
1033
1091
|
this.windowManager.destroyAll();
|
|
@@ -1624,4 +1682,4 @@ var PolicyEngine = class {
|
|
|
1624
1682
|
};
|
|
1625
1683
|
|
|
1626
1684
|
//#endregion
|
|
1627
|
-
export { EventAccessor, FeatureStatus, PolicyDecision, PolicyEngine, Runtime, RuntimeState, ServiceScope, ServiceStatus, TaskOverlapStrategy, TaskRetryStrategy, TaskStatus, createEvent, createFeature, createRuntime, createService, createTask, createWindow, defineConfig, defineRuntime, defineView };
|
|
1685
|
+
export { EventAccessor, EventBridge, FeatureStatus, PolicyDecision, PolicyEngine, Runtime, RuntimeState, ServiceScope, ServiceStatus, TaskOverlapStrategy, TaskRetryStrategy, TaskStatus, createEvent, createFeature, createRuntime, createService, createTask, createWindow, defineConfig, defineRuntime, defineView };
|