@cordy/electro-generator 1.2.11 → 1.2.13
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.mjs +28 -24
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -71,8 +71,9 @@ contextBridge.exposeInMainWorld("electro", ${featureEntries.length > 0 ? `{\n${f
|
|
|
71
71
|
* Generate bridge type declarations for a specific view.
|
|
72
72
|
* Makes `window.electro` type-safe in the renderer.
|
|
73
73
|
*/
|
|
74
|
-
function generateBridgeTypes(
|
|
75
|
-
const allowedFeatures = features.filter((f) => policy.canAccess(
|
|
74
|
+
function generateBridgeTypes(view, features, policy) {
|
|
75
|
+
const allowedFeatures = features.filter((f) => policy.canAccess(view.name, f.id));
|
|
76
|
+
const bridgeModulePath = join(dirname(view.__source), "bridge.gen.ts");
|
|
76
77
|
const featureTypes = [];
|
|
77
78
|
for (const feature of allowedFeatures) {
|
|
78
79
|
const exposedServices = feature.services.filter((s) => s.scope === "exposed");
|
|
@@ -81,39 +82,42 @@ function generateBridgeTypes(viewName, features, policy) {
|
|
|
81
82
|
continue;
|
|
82
83
|
}
|
|
83
84
|
const serviceTypes = [];
|
|
84
|
-
for (const service of exposedServices) {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
}
|
|
89
|
-
const methodTypes = service.methods.map((m) => ` ${q(m)}(...args: unknown[]): Promise<unknown>;`).join("\n");
|
|
90
|
-
serviceTypes.push(` ${q(service.id)}: {\n${methodTypes}\n };`);
|
|
91
|
-
}
|
|
85
|
+
for (const service of exposedServices) if (service.exported) {
|
|
86
|
+
const importPath = toImportPathFrom(bridgeModulePath, service.filePath);
|
|
87
|
+
serviceTypes.push(` ${q(service.id)}: _SvcApi<typeof import("${importPath}").${service.varName}>;`);
|
|
88
|
+
} else serviceTypes.push(` ${q(service.id)}: unknown;`);
|
|
92
89
|
featureTypes.push(` ${q(feature.id)}: {\n${serviceTypes.join("\n")}\n };`);
|
|
93
90
|
}
|
|
94
|
-
const
|
|
95
|
-
for (const feature of allowedFeatures) for (const evt of feature.events ?? [])
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
91
|
+
const eventTypeEntries = [];
|
|
92
|
+
for (const feature of allowedFeatures) for (const evt of feature.events ?? []) {
|
|
93
|
+
const eventKey = `${feature.id}:${evt.id}`;
|
|
94
|
+
if (evt.exported) {
|
|
95
|
+
const importPath = toImportPathFrom(bridgeModulePath, evt.filePath);
|
|
96
|
+
eventTypeEntries.push(` ${JSON.stringify(eventKey)}: _EventPayload<typeof import("${importPath}").${evt.varName}>;`);
|
|
97
|
+
} else eventTypeEntries.push(` ${JSON.stringify(eventKey)}: unknown;`);
|
|
99
98
|
}
|
|
99
|
+
const eventMapTypes = eventTypeEntries.length > 0 ? `\ntype ElectroEventMap = {\n${eventTypeEntries.join("\n")}\n};` : "";
|
|
100
|
+
if (allowedFeatures.length > 0) if (eventTypeEntries.length > 0) featureTypes.push(` events: {\n on<K extends keyof ElectroEventMap>(channel: K, handler: (payload: ElectroEventMap[K]) => void): () => void;\n on(channel: string & {}, handler: (payload: unknown) => void): () => void;\n };`);
|
|
101
|
+
else featureTypes.push(` events: {\n on(channel: string & {}, handler: (payload: unknown) => void): () => void;\n };`);
|
|
100
102
|
const content = `${HEADER}
|
|
101
|
-
|
|
103
|
+
type _SvcApi<T> = T extends { api(): infer R } ? NonNullable<R> : never;
|
|
104
|
+
type _EventPayload<T> = T extends { payload(): infer P } ? P : unknown;${eventMapTypes}
|
|
102
105
|
|
|
103
|
-
|
|
104
|
-
interface Window {
|
|
105
|
-
electro: ElectroBridge;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
106
|
+
export interface ElectroBridge ${featureTypes.length > 0 ? `{\n${featureTypes.join("\n")}\n }` : "{}"}
|
|
108
107
|
`;
|
|
109
108
|
return {
|
|
110
|
-
path: `generated/views/${
|
|
109
|
+
path: `generated/views/${view.name}.bridge.d.ts`,
|
|
111
110
|
content
|
|
112
111
|
};
|
|
113
112
|
}
|
|
114
113
|
/** Calculate the import path from the generated env types file to a source file. */
|
|
114
|
+
function toImportPathFrom(outputFilePath, sourceFilePath) {
|
|
115
|
+
const importPath = relative(dirname(outputFilePath), sourceFilePath).replace(/\.(?:[cm]?tsx?|[cm]?jsx?)$/, "");
|
|
116
|
+
return importPath.startsWith(".") ? importPath : `./${importPath}`;
|
|
117
|
+
}
|
|
118
|
+
/** Calculate the import path from the generated env types file to a source file. */
|
|
115
119
|
function toImportPath(envTypesDir, sourceFilePath) {
|
|
116
|
-
const importPath = relative(dirname(join(envTypesDir, "electro-env.d.ts")), sourceFilePath).replace(/\.
|
|
120
|
+
const importPath = relative(dirname(join(envTypesDir, "electro-env.d.ts")), sourceFilePath).replace(/\.(?:[cm]?tsx?|[cm]?jsx?)$/, "");
|
|
117
121
|
return importPath.startsWith(".") ? importPath : `./${importPath}`;
|
|
118
122
|
}
|
|
119
123
|
const FEATURE_TYPES_HEADER = `// Auto-generated by Electro codegen. Do not edit.
|
|
@@ -238,7 +242,7 @@ function generate(input) {
|
|
|
238
242
|
const knownIds = new Set(scanResult.features.map((f) => f.id));
|
|
239
243
|
for (const fId of view.features ?? []) if (!knownIds.has(fId)) console.warn(`[generator] View "${view.name}" references unknown feature "${fId}"`);
|
|
240
244
|
files.push(generatePreload(view.name, scanResult.features, policy, view.preload));
|
|
241
|
-
files.push(generateBridgeTypes(view
|
|
245
|
+
files.push(generateBridgeTypes(view, scanResult.features, policy));
|
|
242
246
|
}
|
|
243
247
|
return {
|
|
244
248
|
files,
|
package/package.json
CHANGED