@_traeop_/electron-modular 1.0.7 → 1.0.8
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/@core/bootstrap/initialize-ipc/window-event-listeners.d.ts +1 -1
- package/dist/@core/bootstrap/initialize-ipc/window-event-listeners.js +35 -64
- package/dist/@core/container.d.ts +0 -5
- package/dist/@core/container.js +14 -25
- package/dist/@core/control-window/create.js +25 -43
- package/dist/@core/errors/index.d.ts +13 -9
- package/dist/@core/errors/index.js +20 -19
- package/package.json +1 -1
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { BrowserWindow } from "electron";
|
|
2
2
|
import type { TWindowManagerWithHandlers } from "../../types/window-manager.js";
|
|
3
|
-
export declare const attachWindowEventListeners: (
|
|
3
|
+
export declare const attachWindowEventListeners: (win: BrowserWindow, inst: TWindowManagerWithHandlers) => void;
|
|
@@ -1,90 +1,61 @@
|
|
|
1
1
|
const windowListeners = new WeakMap();
|
|
2
|
-
const EVENT_PREFIX = "on";
|
|
3
|
-
const WINDOW_PREFIX = "onWindow";
|
|
4
|
-
const WEB_CONTENTS_PREFIX = "onWebContents";
|
|
5
2
|
const getPrototypeMethodNames = (instance) => {
|
|
6
3
|
const names = new Set();
|
|
7
4
|
let proto = Object.getPrototypeOf(instance);
|
|
8
5
|
while (proto && proto !== Object.prototype) {
|
|
9
|
-
Object.getOwnPropertyNames(proto).forEach((
|
|
10
|
-
if (name !== "constructor") {
|
|
11
|
-
names.add(name);
|
|
12
|
-
}
|
|
13
|
-
});
|
|
6
|
+
Object.getOwnPropertyNames(proto).forEach((n) => n !== "constructor" && names.add(n));
|
|
14
7
|
proto = Object.getPrototypeOf(proto);
|
|
15
8
|
}
|
|
16
9
|
return Array.from(names);
|
|
17
10
|
};
|
|
18
|
-
const toEventName = (
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
.replace(WEB_CONTENTS_PREFIX, "")
|
|
22
|
-
.replace(EVENT_PREFIX, "");
|
|
23
|
-
return cleaned
|
|
11
|
+
const toEventName = (h) => {
|
|
12
|
+
const c = h.replace(/^(onWindow|onWebContents|on)/, "");
|
|
13
|
+
return c
|
|
24
14
|
.replace(/([a-z0-9])([A-Z])/g, "$1-$2")
|
|
25
15
|
.replace(/([A-Z])([A-Z][a-z])/g, "$1-$2")
|
|
26
16
|
.toLowerCase();
|
|
27
17
|
};
|
|
28
|
-
const
|
|
29
|
-
return name.startsWith(EVENT_PREFIX);
|
|
30
|
-
};
|
|
31
|
-
const isWebContentsHandler = (name) => {
|
|
32
|
-
return name.startsWith(WEB_CONTENTS_PREFIX);
|
|
33
|
-
};
|
|
34
|
-
const addListener = (emitter, eventName, listener) => {
|
|
35
|
-
emitter.on(eventName, listener);
|
|
36
|
-
return () => {
|
|
37
|
-
if (emitter.off) {
|
|
38
|
-
emitter.off(eventName, listener);
|
|
39
|
-
}
|
|
40
|
-
else if (emitter.removeListener) {
|
|
41
|
-
emitter.removeListener(eventName, listener);
|
|
42
|
-
}
|
|
43
|
-
};
|
|
44
|
-
};
|
|
45
|
-
const attachHandlersToEmitter = (emitter, browserWindow, windowInstance, handlerNames, filter) => {
|
|
18
|
+
const attachHandlersToEmitter = (emitter, win, inst, names, filter) => {
|
|
46
19
|
const cleanups = [];
|
|
47
|
-
for (const
|
|
48
|
-
if (!filter(
|
|
20
|
+
for (const name of names) {
|
|
21
|
+
if (!filter(name))
|
|
49
22
|
continue;
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
if (typeof handler !== "function") {
|
|
23
|
+
const h = inst[name];
|
|
24
|
+
if (typeof h !== "function")
|
|
53
25
|
continue;
|
|
54
|
-
|
|
55
|
-
const eventName = toEventName(handlerName);
|
|
26
|
+
const evt = toEventName(name);
|
|
56
27
|
const listener = (...args) => {
|
|
57
|
-
|
|
58
|
-
handler.apply(windowInstance, [browserWindow]);
|
|
59
|
-
}
|
|
60
|
-
else {
|
|
61
|
-
handler.apply(windowInstance, [...args, browserWindow]);
|
|
62
|
-
}
|
|
28
|
+
h.length <= 1 ? h.apply(inst, [win]) : h.apply(inst, [...args, win]);
|
|
63
29
|
};
|
|
64
|
-
|
|
30
|
+
emitter.on(evt, listener);
|
|
31
|
+
cleanups.push(() => {
|
|
32
|
+
emitter.off
|
|
33
|
+
? emitter.off(evt, listener)
|
|
34
|
+
: emitter.removeListener &&
|
|
35
|
+
emitter.removeListener(evt, listener);
|
|
36
|
+
});
|
|
65
37
|
}
|
|
66
38
|
return cleanups;
|
|
67
39
|
};
|
|
68
|
-
export const attachWindowEventListeners = (
|
|
69
|
-
const entry = windowListeners.get(
|
|
70
|
-
if (entry?.instance ===
|
|
40
|
+
export const attachWindowEventListeners = (win, inst) => {
|
|
41
|
+
const entry = windowListeners.get(win);
|
|
42
|
+
if (entry?.instance === inst)
|
|
71
43
|
return;
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
const
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
cleanup: [...windowCleanups, ...webContentsCleanups],
|
|
44
|
+
if (entry)
|
|
45
|
+
entry.cleanup.forEach((c) => c());
|
|
46
|
+
const names = getPrototypeMethodNames(inst).filter((n) => n.startsWith("on"));
|
|
47
|
+
const isWebContents = (n) => n.startsWith("onWebContents");
|
|
48
|
+
const winCleanups = attachHandlersToEmitter(win, win, inst, names, (n) => !isWebContents(n));
|
|
49
|
+
const webCleanups = attachHandlersToEmitter(win.webContents, win, inst, names, isWebContents);
|
|
50
|
+
windowListeners.set(win, {
|
|
51
|
+
instance: inst,
|
|
52
|
+
cleanup: [...winCleanups, ...webCleanups],
|
|
82
53
|
});
|
|
83
|
-
|
|
84
|
-
const
|
|
85
|
-
if (
|
|
86
|
-
|
|
87
|
-
windowListeners.delete(
|
|
54
|
+
win.once("closed", () => {
|
|
55
|
+
const e = windowListeners.get(win);
|
|
56
|
+
if (e) {
|
|
57
|
+
e.cleanup.forEach((c) => c());
|
|
58
|
+
windowListeners.delete(win);
|
|
88
59
|
}
|
|
89
60
|
});
|
|
90
61
|
};
|
|
@@ -22,10 +22,5 @@ export declare class Container {
|
|
|
22
22
|
private instantiateClassProvider;
|
|
23
23
|
private instantiateClassConstructor;
|
|
24
24
|
private resolveDependencies;
|
|
25
|
-
private isProviderObject;
|
|
26
|
-
private isFactoryProvider;
|
|
27
|
-
private isClassProvider;
|
|
28
|
-
private isValueProvider;
|
|
29
|
-
private isExistingProvider;
|
|
30
25
|
}
|
|
31
26
|
export declare const container: Container;
|
package/dist/@core/container.js
CHANGED
|
@@ -96,17 +96,25 @@ export class Container {
|
|
|
96
96
|
return undefined;
|
|
97
97
|
}
|
|
98
98
|
async instantiateProvider(moduleClass, token, provider) {
|
|
99
|
-
|
|
99
|
+
const isObj = typeof provider === "object" &&
|
|
100
|
+
provider !== null &&
|
|
101
|
+
"provide" in provider;
|
|
102
|
+
if (isObj &&
|
|
103
|
+
"useFactory" in provider &&
|
|
104
|
+
typeof provider.useFactory === "function") {
|
|
100
105
|
return this.instantiateFactoryProvider(moduleClass, token, provider);
|
|
101
106
|
}
|
|
102
|
-
if (
|
|
107
|
+
if (isObj &&
|
|
108
|
+
"useClass" in provider &&
|
|
109
|
+
typeof provider.useClass === "function") {
|
|
103
110
|
return this.instantiateClassProvider(moduleClass, token, provider);
|
|
104
111
|
}
|
|
105
|
-
if (
|
|
106
|
-
|
|
107
|
-
|
|
112
|
+
if (isObj && "useValue" in provider) {
|
|
113
|
+
const val = provider.useValue;
|
|
114
|
+
this.instances.set(token, val);
|
|
115
|
+
return val;
|
|
108
116
|
}
|
|
109
|
-
if (
|
|
117
|
+
if (isObj && "useExisting" in provider) {
|
|
110
118
|
const instance = await this.resolve(moduleClass, provider.useExisting);
|
|
111
119
|
if (instance !== undefined) {
|
|
112
120
|
this.instances.set(token, instance);
|
|
@@ -142,24 +150,5 @@ export class Container {
|
|
|
142
150
|
async resolveDependencies(moduleClass, dependencies) {
|
|
143
151
|
return Promise.all(dependencies.map((dep) => this.resolve(moduleClass, dep)));
|
|
144
152
|
}
|
|
145
|
-
isProviderObject(provider) {
|
|
146
|
-
return (typeof provider === "object" && provider !== null && "provide" in provider);
|
|
147
|
-
}
|
|
148
|
-
isFactoryProvider(provider) {
|
|
149
|
-
return (this.isProviderObject(provider) &&
|
|
150
|
-
"useFactory" in provider &&
|
|
151
|
-
typeof provider.useFactory === "function");
|
|
152
|
-
}
|
|
153
|
-
isClassProvider(provider) {
|
|
154
|
-
return (this.isProviderObject(provider) &&
|
|
155
|
-
"useClass" in provider &&
|
|
156
|
-
typeof provider.useClass === "function");
|
|
157
|
-
}
|
|
158
|
-
isValueProvider(provider) {
|
|
159
|
-
return this.isProviderObject(provider) && "useValue" in provider;
|
|
160
|
-
}
|
|
161
|
-
isExistingProvider(provider) {
|
|
162
|
-
return this.isProviderObject(provider) && "useExisting" in provider;
|
|
163
|
-
}
|
|
164
153
|
}
|
|
165
154
|
export const container = new Container();
|
|
@@ -3,79 +3,61 @@ import path from "node:path";
|
|
|
3
3
|
import { cacheWindows } from "./cache.js";
|
|
4
4
|
import { getWindow } from "./receive.js";
|
|
5
5
|
import { getSettings } from "../bootstrap/settings.js";
|
|
6
|
-
const
|
|
7
|
-
const csp = `
|
|
8
|
-
default-src 'self';
|
|
9
|
-
connect-src 'self' ${baseRestApi};
|
|
10
|
-
img-src * data:;
|
|
11
|
-
style-src 'self' 'unsafe-inline';
|
|
12
|
-
script-src 'self' ${isDev ? "'unsafe-inline'" : ""};
|
|
13
|
-
`
|
|
6
|
+
const setupCSP = (base, dev) => {
|
|
7
|
+
const csp = `default-src 'self'; connect-src 'self' ${base}; img-src * data:; style-src 'self' 'unsafe-inline'; script-src 'self' ${dev ? "'unsafe-inline'" : ""};`
|
|
14
8
|
.replace(/\s{2,}/g, " ")
|
|
15
9
|
.trim();
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
const setupContentSecurityPolicy = (baseRestApi, isDev) => {
|
|
19
|
-
const csp = createContentSecurityPolicy(baseRestApi, isDev);
|
|
20
|
-
session.defaultSession.webRequest.onHeadersReceived((details, callback) => {
|
|
21
|
-
callback({
|
|
10
|
+
session.defaultSession.webRequest.onHeadersReceived((d, cb) => {
|
|
11
|
+
cb({
|
|
22
12
|
responseHeaders: {
|
|
23
|
-
...
|
|
13
|
+
...d.responseHeaders,
|
|
24
14
|
"Content-Security-Policy": [csp],
|
|
25
15
|
},
|
|
26
16
|
});
|
|
27
17
|
});
|
|
28
18
|
};
|
|
29
|
-
const getAppPaths = (settings, isDev) => {
|
|
30
|
-
return {
|
|
31
|
-
ui: path.join(app.getAppPath(), `/${settings.folders.distRenderer}/index.html`),
|
|
32
|
-
preload: path.join(app.getAppPath(), isDev ? "." : "..", `/${settings.folders.distMain}/preload.cjs`),
|
|
33
|
-
};
|
|
34
|
-
};
|
|
35
19
|
export const createWindow = ({ hash, options, isCache, loadURL, }) => {
|
|
36
20
|
const settings = getSettings();
|
|
37
21
|
const isDev = process.env.NODE_ENV === "development";
|
|
38
|
-
const
|
|
39
|
-
|
|
22
|
+
const ui = path.join(app.getAppPath(), `/${settings.folders.distRenderer}/index.html`);
|
|
23
|
+
const preload = path.join(app.getAppPath(), isDev ? "." : "..", `/${settings.folders.distMain}/preload.cjs`);
|
|
24
|
+
if (!settings.baseRestApi)
|
|
40
25
|
console.warn('Warning: You have to add an environment variable called "process.env.BASE_REST_API"!');
|
|
41
|
-
|
|
42
|
-
if (!settings.localhostPort) {
|
|
26
|
+
if (!settings.localhostPort)
|
|
43
27
|
console.warn('Warning: You have to add an environment variable called "process.env.LOCALHOST_ELECTRON_SERVER_PORT"!');
|
|
44
|
-
}
|
|
45
28
|
if (hash && isCache) {
|
|
46
|
-
const
|
|
47
|
-
if (
|
|
48
|
-
|
|
49
|
-
return
|
|
29
|
+
const existing = getWindow(hash);
|
|
30
|
+
if (existing) {
|
|
31
|
+
existing.show();
|
|
32
|
+
return existing;
|
|
50
33
|
}
|
|
51
34
|
}
|
|
52
|
-
const
|
|
35
|
+
const win = new BrowserWindow({
|
|
53
36
|
...options,
|
|
54
37
|
webPreferences: {
|
|
55
|
-
preload
|
|
38
|
+
preload,
|
|
56
39
|
contextIsolation: true,
|
|
57
40
|
nodeIntegration: false,
|
|
58
41
|
...options?.webPreferences,
|
|
59
42
|
},
|
|
60
43
|
});
|
|
61
|
-
if (isCache && !loadURL)
|
|
62
|
-
|
|
63
|
-
}
|
|
44
|
+
if (isCache && !loadURL)
|
|
45
|
+
setupCSP(settings.baseRestApi, isDev);
|
|
64
46
|
if (loadURL) {
|
|
65
|
-
|
|
47
|
+
win.loadURL(loadURL);
|
|
66
48
|
}
|
|
67
49
|
else if (isDev) {
|
|
68
|
-
|
|
50
|
+
win.loadURL(`http://localhost:${settings.localhostPort}${hash ? `#${hash}` : ""}`);
|
|
69
51
|
}
|
|
70
52
|
else if (hash) {
|
|
71
|
-
|
|
53
|
+
win.loadFile(ui, { hash });
|
|
72
54
|
}
|
|
73
55
|
if (hash && isCache) {
|
|
74
|
-
cacheWindows.set(hash,
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
56
|
+
cacheWindows.set(hash, win);
|
|
57
|
+
win.on("close", (e) => {
|
|
58
|
+
e.preventDefault();
|
|
59
|
+
win.hide();
|
|
78
60
|
});
|
|
79
61
|
}
|
|
80
|
-
return
|
|
62
|
+
return win;
|
|
81
63
|
};
|
|
@@ -1,15 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
constructor(
|
|
1
|
+
declare class BaseError extends Error {
|
|
2
|
+
constructor(msg: string, name: string);
|
|
3
3
|
}
|
|
4
|
-
export declare class
|
|
5
|
-
constructor(
|
|
4
|
+
export declare class ModuleNotRegisteredError extends BaseError {
|
|
5
|
+
constructor(m: string);
|
|
6
6
|
}
|
|
7
|
-
export declare class
|
|
8
|
-
constructor(
|
|
7
|
+
export declare class ProviderNotFoundError extends BaseError {
|
|
8
|
+
constructor(t: string, m: string);
|
|
9
9
|
}
|
|
10
|
-
export declare class
|
|
11
|
-
constructor(
|
|
10
|
+
export declare class ModuleDecoratorMissingError extends BaseError {
|
|
11
|
+
constructor(m: string);
|
|
12
12
|
}
|
|
13
|
-
export declare class
|
|
13
|
+
export declare class InvalidProviderError extends BaseError {
|
|
14
|
+
constructor(m: string);
|
|
15
|
+
}
|
|
16
|
+
export declare class SettingsNotInitializedError extends BaseError {
|
|
14
17
|
constructor();
|
|
15
18
|
}
|
|
19
|
+
export {};
|
|
@@ -1,30 +1,31 @@
|
|
|
1
|
-
|
|
2
|
-
constructor(
|
|
3
|
-
super(
|
|
4
|
-
this.name =
|
|
1
|
+
class BaseError extends Error {
|
|
2
|
+
constructor(msg, name) {
|
|
3
|
+
super(msg);
|
|
4
|
+
this.name = name;
|
|
5
5
|
}
|
|
6
6
|
}
|
|
7
|
-
export class
|
|
8
|
-
constructor(
|
|
9
|
-
super(`
|
|
10
|
-
this.name = "ProviderNotFoundError";
|
|
7
|
+
export class ModuleNotRegisteredError extends BaseError {
|
|
8
|
+
constructor(m) {
|
|
9
|
+
super(`Module "${m}" is not registered in the container.`, "ModuleNotRegisteredError");
|
|
11
10
|
}
|
|
12
11
|
}
|
|
13
|
-
export class
|
|
14
|
-
constructor(
|
|
15
|
-
super(`
|
|
16
|
-
this.name = "ModuleDecoratorMissingError";
|
|
12
|
+
export class ProviderNotFoundError extends BaseError {
|
|
13
|
+
constructor(t, m) {
|
|
14
|
+
super(`Provider not found for token "${t}" in module "${m}" or its imports.`, "ProviderNotFoundError");
|
|
17
15
|
}
|
|
18
16
|
}
|
|
19
|
-
export class
|
|
20
|
-
constructor(
|
|
21
|
-
super(`
|
|
22
|
-
this.name = "InvalidProviderError";
|
|
17
|
+
export class ModuleDecoratorMissingError extends BaseError {
|
|
18
|
+
constructor(m) {
|
|
19
|
+
super(`Module ${m} does not have the @RgModule decorator`, "ModuleDecoratorMissingError");
|
|
23
20
|
}
|
|
24
21
|
}
|
|
25
|
-
export class
|
|
22
|
+
export class InvalidProviderError extends BaseError {
|
|
23
|
+
constructor(m) {
|
|
24
|
+
super(`Invalid provider definition registered in module ${m}`, "InvalidProviderError");
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
export class SettingsNotInitializedError extends BaseError {
|
|
26
28
|
constructor() {
|
|
27
|
-
super("App settings cache has not been initialized.");
|
|
28
|
-
this.name = "SettingsNotInitializedError";
|
|
29
|
+
super("App settings cache has not been initialized.", "SettingsNotInitializedError");
|
|
29
30
|
}
|
|
30
31
|
}
|
package/package.json
CHANGED