@bonsae/nrg 0.1.0 → 0.3.0
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/build/index.js +7 -0
- package/build/server/index.cjs +12 -1
- package/build/server/resources/nrg-client.js +9 -3
- package/build/vite/index.js +86 -61
- package/build/vite/utils.js +0 -4
- package/package.json +8 -1
- package/src/core/client/components/node-red-json-schema-form.vue +10 -0
- package/src/core/server/schemas/type.ts +16 -2
- package/src/index.ts +2 -0
- package/src/types.ts +189 -0
- package/src/utils.ts +20 -0
- package/src/vite/client/build.ts +1 -1
- package/src/vite/client/plugins/minifier.ts +9 -8
- package/src/vite/client/plugins/node-definitions-inliner.ts +107 -56
- package/src/vite/index.ts +1 -2
- package/src/vite/types.ts +0 -195
- package/src/vite/utils.ts +2 -33
package/build/index.js
ADDED
package/build/server/index.cjs
CHANGED
|
@@ -661,13 +661,24 @@ function NodeRef(nodeClass, options) {
|
|
|
661
661
|
};
|
|
662
662
|
}
|
|
663
663
|
function TypedInput(options) {
|
|
664
|
+
const { types, ...rest } = options ?? {};
|
|
664
665
|
return {
|
|
665
666
|
...TypedInputSchema,
|
|
666
|
-
...
|
|
667
|
+
...rest,
|
|
668
|
+
...types ? { "x-typed-types": types } : {},
|
|
667
669
|
[import_typebox.Kind]: "TypedInput"
|
|
668
670
|
};
|
|
669
671
|
}
|
|
672
|
+
var _OriginalString = import_typebox.Type.String.bind(import_typebox.Type);
|
|
673
|
+
function StringWithLang(options) {
|
|
674
|
+
const { lang, ...rest } = options ?? {};
|
|
675
|
+
return _OriginalString({
|
|
676
|
+
...rest,
|
|
677
|
+
...lang ? { "x-editor-language": lang } : {}
|
|
678
|
+
});
|
|
679
|
+
}
|
|
670
680
|
var SchemaType = Object.assign({}, import_typebox.Type, {
|
|
681
|
+
String: StringWithLang,
|
|
671
682
|
NodeRef,
|
|
672
683
|
TypedInput
|
|
673
684
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
(function(){var s=document.createElement("style");s.textContent="[data-v-e5c98949] .node-red-vue-input-error-message{color:var(--red-ui-text-color-error)}[data-v-e5c98949] .nrg-label{display:inline-block;width:100%;cursor:default}[data-v-e5c98949] .form-row input[type=text],[data-v-e5c98949] .form-row input[type=number],[data-v-e5c98949] .form-row input[type=password]{height:34px;padding:0 8px;box-sizing:border-box}.container[data-v-508cfdb8]{position:relative}.expand-button[data-v-508cfdb8]{position:absolute;top:-23px;right:0;z-index:10;transition:color .3s ease;cursor:pointer}.nrg-required[data-v-
|
|
1
|
+
(function(){var s=document.createElement("style");s.textContent="[data-v-e5c98949] .node-red-vue-input-error-message{color:var(--red-ui-text-color-error)}[data-v-e5c98949] .nrg-label{display:inline-block;width:100%;cursor:default}[data-v-e5c98949] .form-row input[type=text],[data-v-e5c98949] .form-row input[type=number],[data-v-e5c98949] .form-row input[type=password]{height:34px;padding:0 8px;box-sizing:border-box}.container[data-v-508cfdb8]{position:relative}.expand-button[data-v-508cfdb8]{position:absolute;top:-23px;right:0;z-index:10;transition:color .3s ease;cursor:pointer}.nrg-required[data-v-2a313890]{color:var(--red-ui-text-color-error);margin-left:2px}\n";document.head.appendChild(s);})();
|
|
2
2
|
import { defineComponent as je, resolveComponent as qe, openBlock as te, createElementBlock as re, Fragment as Ke, createElementVNode as ue, createCommentVNode as ge, createVNode as Vn, toDisplayString as Pe, withDirectives as ws, vShow as bs, renderList as fr, createTextVNode as pr, createBlock as ze, createApp as Es } from "/nrg/assets/vue.esm-browser.prod.js";
|
|
3
3
|
function Ss() {
|
|
4
4
|
}
|
|
@@ -6168,7 +6168,13 @@ function Dn(e, t, r) {
|
|
|
6168
6168
|
language: t["x-editor-language"]
|
|
6169
6169
|
} : { key: e, label: s, inputType: "text", required: r, htmlType: "text" };
|
|
6170
6170
|
default:
|
|
6171
|
-
return {
|
|
6171
|
+
return t["x-editor-language"] ? {
|
|
6172
|
+
key: e,
|
|
6173
|
+
label: s,
|
|
6174
|
+
inputType: "editor",
|
|
6175
|
+
required: r,
|
|
6176
|
+
language: t["x-editor-language"]
|
|
6177
|
+
} : {
|
|
6172
6178
|
key: e,
|
|
6173
6179
|
label: s,
|
|
6174
6180
|
inputType: "text",
|
|
@@ -6348,7 +6354,7 @@ function Bo(e, t, r, s, m, o) {
|
|
|
6348
6354
|
))
|
|
6349
6355
|
]);
|
|
6350
6356
|
}
|
|
6351
|
-
const Mn = /* @__PURE__ */ Ie(zo, [["render", Bo], ["__scopeId", "data-v-
|
|
6357
|
+
const Mn = /* @__PURE__ */ Ie(zo, [["render", Bo], ["__scopeId", "data-v-2a313890"]]), gs = {}, sr = {};
|
|
6352
6358
|
function Qo(e) {
|
|
6353
6359
|
Object.assign(gs, e);
|
|
6354
6360
|
}
|
package/build/vite/index.js
CHANGED
|
@@ -111,9 +111,6 @@ function mergeOptions(defaults, overrides) {
|
|
|
111
111
|
}
|
|
112
112
|
return result;
|
|
113
113
|
}
|
|
114
|
-
function defineRuntimeSettings(settings) {
|
|
115
|
-
return settings;
|
|
116
|
-
}
|
|
117
114
|
|
|
118
115
|
// src/vite/node-red-launcher.ts
|
|
119
116
|
import { spawn } from "child_process";
|
|
@@ -1183,14 +1180,15 @@ function minifier() {
|
|
|
1183
1180
|
return {
|
|
1184
1181
|
name: "vite-plugin-node-red:client:minifier",
|
|
1185
1182
|
apply: "build",
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1183
|
+
async generateBundle(_options, bundle) {
|
|
1184
|
+
for (const [fileName, chunk] of Object.entries(bundle)) {
|
|
1185
|
+
if (chunk.type === "chunk" && fileName.endsWith(".js")) {
|
|
1186
|
+
const result = await transform(chunk.code, {
|
|
1187
|
+
minify: true
|
|
1188
|
+
});
|
|
1189
|
+
chunk.code = result.code;
|
|
1190
|
+
chunk.map = null;
|
|
1192
1191
|
}
|
|
1193
|
-
return code;
|
|
1194
1192
|
}
|
|
1195
1193
|
}
|
|
1196
1194
|
};
|
|
@@ -1204,8 +1202,6 @@ import fs8 from "fs";
|
|
|
1204
1202
|
import mime2 from "mime-types";
|
|
1205
1203
|
var VIRTUAL_ID = "virtual:nrg/node-definitions";
|
|
1206
1204
|
var RESOLVED_ID = "\0" + VIRTUAL_ID;
|
|
1207
|
-
var VIRTUAL_ENTRY_ID = "virtual:nrg/client-entry";
|
|
1208
|
-
var RESOLVED_ENTRY_ID = "\0" + VIRTUAL_ENTRY_ID;
|
|
1209
1205
|
var SKIP_DEFAULTS = /* @__PURE__ */ new Set(["x", "y", "z", "g", "wires", "type", "id"]);
|
|
1210
1206
|
function getDefaultsFromSchema(schema) {
|
|
1211
1207
|
if (!schema?.properties) return void 0;
|
|
@@ -1243,6 +1239,7 @@ function resolveIcon(iconsDir, type) {
|
|
|
1243
1239
|
function nodeDefinitionsInliner(serverOutDir, entryPath, iconsDir, componentsDir, nodesDir, hasUserEntry = true) {
|
|
1244
1240
|
let _nodeTypes = [];
|
|
1245
1241
|
let _definitions = {};
|
|
1242
|
+
const cacheDir = path8.resolve("node_modules", ".nrg", "client");
|
|
1246
1243
|
return {
|
|
1247
1244
|
name: "vite-plugin-node-red:client:node-definitions-inliner",
|
|
1248
1245
|
enforce: "pre",
|
|
@@ -1302,64 +1299,93 @@ function nodeDefinitionsInliner(serverOutDir, entryPath, iconsDir, componentsDir
|
|
|
1302
1299
|
outputsSchema
|
|
1303
1300
|
};
|
|
1304
1301
|
}
|
|
1302
|
+
if (!hasUserEntry) {
|
|
1303
|
+
const nodesCache = path8.resolve(cacheDir, "nodes");
|
|
1304
|
+
if (fs8.existsSync(nodesCache)) {
|
|
1305
|
+
fs8.rmSync(nodesCache, { recursive: true });
|
|
1306
|
+
}
|
|
1307
|
+
fs8.mkdirSync(nodesCache, { recursive: true });
|
|
1308
|
+
for (const type of _nodeTypes) {
|
|
1309
|
+
const userTsPath = nodesDir ? path8.resolve(nodesDir, `${type}.ts`) : null;
|
|
1310
|
+
if (userTsPath && fs8.existsSync(userTsPath)) continue;
|
|
1311
|
+
const content = [
|
|
1312
|
+
`// auto-generated by nrg`,
|
|
1313
|
+
`import { defineNode } from "@bonsae/nrg/client";`,
|
|
1314
|
+
``,
|
|
1315
|
+
`export default defineNode({`,
|
|
1316
|
+
` type: ${JSON.stringify(type)},`,
|
|
1317
|
+
`});`,
|
|
1318
|
+
``
|
|
1319
|
+
].join("\n");
|
|
1320
|
+
fs8.writeFileSync(path8.resolve(nodesCache, `${type}.ts`), content);
|
|
1321
|
+
}
|
|
1322
|
+
const entryContent = generateEntryCode("");
|
|
1323
|
+
fs8.mkdirSync(path8.dirname(path8.resolve(cacheDir, "index.ts")), {
|
|
1324
|
+
recursive: true
|
|
1325
|
+
});
|
|
1326
|
+
fs8.writeFileSync(path8.resolve(cacheDir, "index.ts"), entryContent);
|
|
1327
|
+
}
|
|
1305
1328
|
},
|
|
1306
1329
|
resolveId(id) {
|
|
1307
1330
|
if (id === VIRTUAL_ID) return RESOLVED_ID;
|
|
1308
|
-
if (id === VIRTUAL_ENTRY_ID) return RESOLVED_ENTRY_ID;
|
|
1309
1331
|
},
|
|
1310
1332
|
load(id) {
|
|
1311
|
-
if (id ===
|
|
1312
|
-
|
|
1313
|
-
|
|
1333
|
+
if (id === RESOLVED_ID)
|
|
1334
|
+
return `export default ${JSON.stringify(_definitions)};`;
|
|
1335
|
+
if (!hasUserEntry && id === entryPath) {
|
|
1336
|
+
return generateEntryCode("");
|
|
1337
|
+
}
|
|
1314
1338
|
},
|
|
1315
1339
|
transform(code, id) {
|
|
1316
|
-
if (id !== entryPath
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
}
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
postLines.push(`__setForms({ ${formEntries.join(", ")} });`);
|
|
1340
|
+
if (id !== entryPath) return;
|
|
1341
|
+
if (!hasUserEntry) return;
|
|
1342
|
+
return { code: generateEntryCode(code), map: null };
|
|
1343
|
+
}
|
|
1344
|
+
};
|
|
1345
|
+
function generateEntryCode(userCode) {
|
|
1346
|
+
const nrgImports = /* @__PURE__ */ new Set(["__setSchemas"]);
|
|
1347
|
+
const lines = [`import __nrgSchemas from "${VIRTUAL_ID}";`];
|
|
1348
|
+
const postLines = [`__setSchemas(__nrgSchemas);`];
|
|
1349
|
+
if (componentsDir && fs8.existsSync(componentsDir)) {
|
|
1350
|
+
const formImports = [];
|
|
1351
|
+
const formEntries = [];
|
|
1352
|
+
for (const type of _nodeTypes) {
|
|
1353
|
+
const componentPath = path8.resolve(componentsDir, `${type}.vue`);
|
|
1354
|
+
if (fs8.existsSync(componentPath)) {
|
|
1355
|
+
const varName = `__nrgForm_${type.replace(/-/g, "_")}`;
|
|
1356
|
+
formImports.push(
|
|
1357
|
+
`import ${varName} from ${JSON.stringify(componentPath)};`
|
|
1358
|
+
);
|
|
1359
|
+
formEntries.push(`${JSON.stringify(type)}: ${varName}`);
|
|
1337
1360
|
}
|
|
1338
1361
|
}
|
|
1339
|
-
if (
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
const tsPath = nodesDir ? path8.resolve(nodesDir, `${type}.ts`) : null;
|
|
1344
|
-
if (tsPath && fs8.existsSync(tsPath)) {
|
|
1345
|
-
lines.push(`import ${varName} from ${JSON.stringify(tsPath)};`);
|
|
1346
|
-
} else {
|
|
1347
|
-
lines.push(`const ${varName} = { type: ${JSON.stringify(type)} };`);
|
|
1348
|
-
}
|
|
1349
|
-
defVarNames.push(varName);
|
|
1350
|
-
}
|
|
1351
|
-
if (defVarNames.length > 0) {
|
|
1352
|
-
nrgImports.add("registerTypes");
|
|
1353
|
-
postLines.push(`registerTypes([${defVarNames.join(", ")}]);`);
|
|
1354
|
-
}
|
|
1362
|
+
if (formImports.length > 0) {
|
|
1363
|
+
lines.push(...formImports);
|
|
1364
|
+
nrgImports.add("__setForms");
|
|
1365
|
+
postLines.push(`__setForms({ ${formEntries.join(", ")} });`);
|
|
1355
1366
|
}
|
|
1356
|
-
const importLine = `import { ${[...nrgImports].join(", ")} } from "@bonsae/nrg/client";`;
|
|
1357
|
-
lines.splice(1, 0, importLine);
|
|
1358
|
-
lines.push(...postLines);
|
|
1359
|
-
lines.push("");
|
|
1360
|
-
return { code: lines.join("\n") + code, map: null };
|
|
1361
1367
|
}
|
|
1362
|
-
|
|
1368
|
+
if (!hasUserEntry) {
|
|
1369
|
+
const nodesCache = path8.resolve(cacheDir, "nodes");
|
|
1370
|
+
const defVarNames = [];
|
|
1371
|
+
for (const type of _nodeTypes) {
|
|
1372
|
+
const varName = `__nrgNodeDef_${type.replace(/-/g, "_")}`;
|
|
1373
|
+
const userTsPath = nodesDir ? path8.resolve(nodesDir, `${type}.ts`) : null;
|
|
1374
|
+
const tsPath = userTsPath && fs8.existsSync(userTsPath) ? userTsPath : path8.resolve(nodesCache, `${type}.ts`);
|
|
1375
|
+
lines.push(`import ${varName} from ${JSON.stringify(tsPath)};`);
|
|
1376
|
+
defVarNames.push(varName);
|
|
1377
|
+
}
|
|
1378
|
+
if (defVarNames.length > 0) {
|
|
1379
|
+
nrgImports.add("registerTypes");
|
|
1380
|
+
postLines.push(`registerTypes([${defVarNames.join(", ")}]);`);
|
|
1381
|
+
}
|
|
1382
|
+
}
|
|
1383
|
+
const importLine = `import { ${[...nrgImports].join(", ")} } from "@bonsae/nrg/client";`;
|
|
1384
|
+
lines.splice(1, 0, importLine);
|
|
1385
|
+
lines.push(...postLines);
|
|
1386
|
+
lines.push("");
|
|
1387
|
+
return lines.join("\n") + userCode;
|
|
1388
|
+
}
|
|
1363
1389
|
}
|
|
1364
1390
|
|
|
1365
1391
|
// src/vite/client/plugins/static-copy.ts
|
|
@@ -1525,7 +1551,7 @@ async function build2(clientBuildOptions, buildContext) {
|
|
|
1525
1551
|
build: {
|
|
1526
1552
|
outDir: buildContext.outDir,
|
|
1527
1553
|
emptyOutDir: false,
|
|
1528
|
-
sourcemap: buildContext.isDev ? "inline" :
|
|
1554
|
+
sourcemap: buildContext.isDev ? "inline" : false,
|
|
1529
1555
|
minify: !buildContext.isDev && format !== "es",
|
|
1530
1556
|
copyPublicDir: false,
|
|
1531
1557
|
lib: {
|
|
@@ -1888,6 +1914,5 @@ function nodeRed(options = {}) {
|
|
|
1888
1914
|
];
|
|
1889
1915
|
}
|
|
1890
1916
|
export {
|
|
1891
|
-
defineRuntimeSettings,
|
|
1892
1917
|
nodeRed
|
|
1893
1918
|
};
|
package/build/vite/utils.js
CHANGED
|
@@ -48,13 +48,9 @@ function mergeOptions(defaults, overrides) {
|
|
|
48
48
|
}
|
|
49
49
|
return result;
|
|
50
50
|
}
|
|
51
|
-
function defineRuntimeSettings(settings) {
|
|
52
|
-
return settings;
|
|
53
|
-
}
|
|
54
51
|
export {
|
|
55
52
|
cleanDir,
|
|
56
53
|
copyFiles,
|
|
57
|
-
defineRuntimeSettings,
|
|
58
54
|
getPackageName,
|
|
59
55
|
mergeOptions
|
|
60
56
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bonsae/nrg",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "NRG framework — build Node-RED nodes with Vue 3, TypeScript, and JSON Schema",
|
|
5
5
|
"author": "Allan Oricil <allanoricil@duck.com>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -23,6 +23,9 @@
|
|
|
23
23
|
"lint:fix": "eslint src/ --fix",
|
|
24
24
|
"format": "prettier --write \"src/**/*.{ts,vue,json}\"",
|
|
25
25
|
"format:check": "prettier --check \"src/**/*.{ts,vue,json}\"",
|
|
26
|
+
"docs:dev": "pnpm --dir docs dev",
|
|
27
|
+
"docs:build": "pnpm --dir docs build",
|
|
28
|
+
"docs:preview": "pnpm --dir docs preview",
|
|
26
29
|
"prepare": "husky"
|
|
27
30
|
},
|
|
28
31
|
"files": [
|
|
@@ -30,6 +33,10 @@
|
|
|
30
33
|
"build/"
|
|
31
34
|
],
|
|
32
35
|
"exports": {
|
|
36
|
+
".": {
|
|
37
|
+
"types": "./src/index.ts",
|
|
38
|
+
"default": "./build/index.js"
|
|
39
|
+
},
|
|
33
40
|
"./server": {
|
|
34
41
|
"types": "./src/core/server/index.ts",
|
|
35
42
|
"require": "./build/server/index.cjs",
|
|
@@ -291,6 +291,16 @@ function buildField(
|
|
|
291
291
|
return { key, label, inputType: "text", required, htmlType: "text" };
|
|
292
292
|
|
|
293
293
|
default:
|
|
294
|
+
// string with editor language → code editor
|
|
295
|
+
if (schema["x-editor-language"]) {
|
|
296
|
+
return {
|
|
297
|
+
key,
|
|
298
|
+
label,
|
|
299
|
+
inputType: "editor",
|
|
300
|
+
required,
|
|
301
|
+
language: schema["x-editor-language"],
|
|
302
|
+
};
|
|
303
|
+
}
|
|
294
304
|
// string (or untyped)
|
|
295
305
|
return {
|
|
296
306
|
key,
|
|
@@ -26,15 +26,29 @@ function NodeRef<T extends new (...args: any[]) => any>(
|
|
|
26
26
|
} as unknown as TNodeRef<InstanceType<T>>;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
function TypedInput(
|
|
29
|
+
function TypedInput(
|
|
30
|
+
options?: SchemaOptions & { types?: string[] },
|
|
31
|
+
): TTypedInput {
|
|
32
|
+
const { types, ...rest } = options ?? {};
|
|
30
33
|
return {
|
|
31
34
|
...TypedInputSchema,
|
|
32
|
-
...
|
|
35
|
+
...rest,
|
|
36
|
+
...(types ? { "x-typed-types": types } : {}),
|
|
33
37
|
[Kind]: "TypedInput",
|
|
34
38
|
} as unknown as TTypedInput;
|
|
35
39
|
}
|
|
36
40
|
|
|
41
|
+
const _OriginalString = BaseType.String.bind(BaseType);
|
|
42
|
+
function StringWithLang(options?: SchemaOptions & { lang?: string }) {
|
|
43
|
+
const { lang, ...rest } = options ?? {};
|
|
44
|
+
return _OriginalString({
|
|
45
|
+
...rest,
|
|
46
|
+
...(lang ? { "x-editor-language": lang } : {}),
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
37
50
|
const SchemaType = Object.assign({}, BaseType, {
|
|
51
|
+
String: StringWithLang,
|
|
38
52
|
NodeRef,
|
|
39
53
|
TypedInput,
|
|
40
54
|
});
|
package/src/index.ts
ADDED
package/src/types.ts
ADDED
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import type { Http2ServerRequest } from "http2";
|
|
2
|
+
|
|
3
|
+
export interface NodeRedRuntimeSettings {
|
|
4
|
+
userDir?: string;
|
|
5
|
+
nodesDir?: string | string[];
|
|
6
|
+
flowFile?: string;
|
|
7
|
+
flowFilePretty?: boolean;
|
|
8
|
+
credentialSecret?: string | false;
|
|
9
|
+
requireHttps?: boolean;
|
|
10
|
+
https?:
|
|
11
|
+
| { key: string; cert: string }
|
|
12
|
+
| (() =>
|
|
13
|
+
| Promise<{ key: string; cert: string }>
|
|
14
|
+
| { key: string; cert: string });
|
|
15
|
+
httpsRefreshInterval?: number;
|
|
16
|
+
httpAdminRoot?: string;
|
|
17
|
+
httpNodeRoot?: string;
|
|
18
|
+
httpNodeCors?: { origin: string; methods: string };
|
|
19
|
+
httpStatic?: string | { path: string; root: string }[];
|
|
20
|
+
httpStaticRoot?: string;
|
|
21
|
+
httpAdminMiddleware?: (req: unknown, res: unknown, next: () => void) => void;
|
|
22
|
+
httpNodeMiddleware?: (req: unknown, res: unknown, next: () => void) => void;
|
|
23
|
+
httpServerOptions?: Record<string, unknown>;
|
|
24
|
+
adminAuth?: {
|
|
25
|
+
type?: "credentials" | "strategy";
|
|
26
|
+
users?: {
|
|
27
|
+
username: string;
|
|
28
|
+
password: string;
|
|
29
|
+
permissions?: string | string[];
|
|
30
|
+
}[];
|
|
31
|
+
default?: {
|
|
32
|
+
permissions?: string | string[];
|
|
33
|
+
};
|
|
34
|
+
tokens?: (
|
|
35
|
+
token: string,
|
|
36
|
+
) => Promise<{ user: string; permissions: string | string[] } | null>;
|
|
37
|
+
tokenHeader: "string";
|
|
38
|
+
sessionExpiryTime?: number;
|
|
39
|
+
[key: string]: unknown;
|
|
40
|
+
};
|
|
41
|
+
httpNodeAuth?: {
|
|
42
|
+
user?: string;
|
|
43
|
+
pass?: string;
|
|
44
|
+
};
|
|
45
|
+
httpStaticAuth?: {
|
|
46
|
+
user?: string;
|
|
47
|
+
pass?: string;
|
|
48
|
+
};
|
|
49
|
+
lang?:
|
|
50
|
+
| "en-US"
|
|
51
|
+
| "de"
|
|
52
|
+
| "es-ES"
|
|
53
|
+
| "fr"
|
|
54
|
+
| "ko"
|
|
55
|
+
| "pt-BR"
|
|
56
|
+
| "ru"
|
|
57
|
+
| "ja"
|
|
58
|
+
| "zh-CN"
|
|
59
|
+
| "zh-TW";
|
|
60
|
+
diagnostics?: {
|
|
61
|
+
enabled?: boolean;
|
|
62
|
+
ui?: boolean;
|
|
63
|
+
};
|
|
64
|
+
runtimeState?: {
|
|
65
|
+
enabled?: boolean;
|
|
66
|
+
ui?: boolean;
|
|
67
|
+
};
|
|
68
|
+
disableEditor?: boolean;
|
|
69
|
+
editorTheme?: {
|
|
70
|
+
page?: {
|
|
71
|
+
title?: string;
|
|
72
|
+
favicon?: string;
|
|
73
|
+
css?: string | string[];
|
|
74
|
+
scripts?: string | string[];
|
|
75
|
+
};
|
|
76
|
+
header?: {
|
|
77
|
+
title?: string;
|
|
78
|
+
image?: string;
|
|
79
|
+
url?: string;
|
|
80
|
+
};
|
|
81
|
+
deployButton?: {
|
|
82
|
+
type?: "simple" | "default";
|
|
83
|
+
label?: string;
|
|
84
|
+
icon?: string;
|
|
85
|
+
};
|
|
86
|
+
menu?: {
|
|
87
|
+
"menu-item-import-library"?: boolean;
|
|
88
|
+
"menu-item-export-library"?: boolean;
|
|
89
|
+
"menu-item-keyboard-shortcuts"?: boolean;
|
|
90
|
+
"menu-item-help"?: {
|
|
91
|
+
label?: string;
|
|
92
|
+
url?: string;
|
|
93
|
+
};
|
|
94
|
+
[menuItem: string]:
|
|
95
|
+
| boolean
|
|
96
|
+
| { label?: string; url?: string }
|
|
97
|
+
| undefined;
|
|
98
|
+
};
|
|
99
|
+
userMenu?: boolean;
|
|
100
|
+
login?: {
|
|
101
|
+
image?: string;
|
|
102
|
+
};
|
|
103
|
+
logout?: {
|
|
104
|
+
redirect?: string;
|
|
105
|
+
};
|
|
106
|
+
palette?: {
|
|
107
|
+
catalogues?: string[];
|
|
108
|
+
categories?: string[];
|
|
109
|
+
theme?: { category: string; type: string; color: string }[];
|
|
110
|
+
};
|
|
111
|
+
projects?: {
|
|
112
|
+
enabled?: boolean;
|
|
113
|
+
workflow?: {
|
|
114
|
+
mode: "manual" | "auto";
|
|
115
|
+
};
|
|
116
|
+
};
|
|
117
|
+
codeEditor?: {
|
|
118
|
+
lib?: "monaco" | "ace";
|
|
119
|
+
options?: Record<string, unknown>;
|
|
120
|
+
};
|
|
121
|
+
mermaid?: {
|
|
122
|
+
theme?: string;
|
|
123
|
+
};
|
|
124
|
+
tours?: boolean;
|
|
125
|
+
theme?: string;
|
|
126
|
+
[key: string]: unknown;
|
|
127
|
+
};
|
|
128
|
+
contextStorage?: {
|
|
129
|
+
default?: {
|
|
130
|
+
module?: "memory" | "localfilesystem" | object;
|
|
131
|
+
config?: Record<string, unknown>;
|
|
132
|
+
};
|
|
133
|
+
[store: string]:
|
|
134
|
+
| {
|
|
135
|
+
module?: "memory" | "localfilesystem" | object;
|
|
136
|
+
config?: Record<string, unknown>;
|
|
137
|
+
}
|
|
138
|
+
| undefined;
|
|
139
|
+
};
|
|
140
|
+
exportGlobalContextKeys?: boolean;
|
|
141
|
+
logging?: {
|
|
142
|
+
console?: {
|
|
143
|
+
level?: "fatal" | "error" | "warn" | "info" | "debug" | "trace" | "off";
|
|
144
|
+
metrics?: boolean;
|
|
145
|
+
audit?: boolean;
|
|
146
|
+
};
|
|
147
|
+
};
|
|
148
|
+
fileWorkingDirectory?: string;
|
|
149
|
+
functionExternalModules?: boolean;
|
|
150
|
+
functionGlobalContext?: Record<string, unknown>;
|
|
151
|
+
nodeMessageBufferMaxLength?: number;
|
|
152
|
+
functionTimeout?: number;
|
|
153
|
+
externalModules?: {
|
|
154
|
+
autoInstall?: boolean;
|
|
155
|
+
autoInstallRetry?: number;
|
|
156
|
+
palette?: {
|
|
157
|
+
allowInstall?: boolean;
|
|
158
|
+
allowUpdate?: boolean;
|
|
159
|
+
allowUpload?: boolean;
|
|
160
|
+
allowList?: string[];
|
|
161
|
+
denyList?: string[];
|
|
162
|
+
allowUpdateList?: string[];
|
|
163
|
+
denyUpdateList?: string[];
|
|
164
|
+
};
|
|
165
|
+
modules?: {
|
|
166
|
+
allowInstall?: boolean;
|
|
167
|
+
allowList?: string[];
|
|
168
|
+
denyList?: string[];
|
|
169
|
+
};
|
|
170
|
+
};
|
|
171
|
+
execMaxBufferSize?: number;
|
|
172
|
+
debugMaxLength?: number;
|
|
173
|
+
debugUseColors?: boolean;
|
|
174
|
+
httpRequestTimeout?: number;
|
|
175
|
+
mqttReconnectTime?: number;
|
|
176
|
+
serialReconnectTime?: number;
|
|
177
|
+
socketReconnectTime?: number;
|
|
178
|
+
socketTimeout?: number;
|
|
179
|
+
tcpMsgQueueSize?: number;
|
|
180
|
+
inboundWebSocketTimeout?: number;
|
|
181
|
+
tlsConfigDisableLocalFiles?: boolean;
|
|
182
|
+
webSocketNodeVerifyClient?: (info: {
|
|
183
|
+
origin: string;
|
|
184
|
+
req: Http2ServerRequest;
|
|
185
|
+
secure: boolean;
|
|
186
|
+
}) => boolean;
|
|
187
|
+
apiMaxLength?: string;
|
|
188
|
+
[key: string]: unknown;
|
|
189
|
+
}
|
package/src/utils.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { NodeRedRuntimeSettings } from "./types";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Type-safe helper for defining Node-RED runtime settings.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```typescript
|
|
8
|
+
* import { defineRuntimeSettings } from "@bonsae/nrg";
|
|
9
|
+
*
|
|
10
|
+
* export default defineRuntimeSettings({
|
|
11
|
+
* flowFile: "flows.json",
|
|
12
|
+
* flowFilePretty: true,
|
|
13
|
+
* });
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export function defineRuntimeSettings(
|
|
17
|
+
settings: NodeRedRuntimeSettings,
|
|
18
|
+
): NodeRedRuntimeSettings {
|
|
19
|
+
return settings;
|
|
20
|
+
}
|
package/src/vite/client/build.ts
CHANGED
|
@@ -173,7 +173,7 @@ async function build(
|
|
|
173
173
|
build: {
|
|
174
174
|
outDir: buildContext.outDir,
|
|
175
175
|
emptyOutDir: false,
|
|
176
|
-
sourcemap: buildContext.isDev ? "inline" :
|
|
176
|
+
sourcemap: buildContext.isDev ? "inline" : false,
|
|
177
177
|
minify: !buildContext.isDev && format !== "es",
|
|
178
178
|
copyPublicDir: false,
|
|
179
179
|
lib: {
|
|
@@ -6,15 +6,16 @@ function minifier(): Plugin {
|
|
|
6
6
|
name: "vite-plugin-node-red:client:minifier",
|
|
7
7
|
apply: "build",
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
async generateBundle(_options, bundle) {
|
|
10
|
+
for (const [fileName, chunk] of Object.entries(bundle)) {
|
|
11
|
+
if (chunk.type === "chunk" && fileName.endsWith(".js")) {
|
|
12
|
+
const result = await transform(chunk.code, {
|
|
13
|
+
minify: true,
|
|
14
|
+
});
|
|
15
|
+
chunk.code = result.code;
|
|
16
|
+
chunk.map = null as any;
|
|
15
17
|
}
|
|
16
|
-
|
|
17
|
-
},
|
|
18
|
+
}
|
|
18
19
|
},
|
|
19
20
|
};
|
|
20
21
|
}
|
|
@@ -8,9 +8,6 @@ import mime from "mime-types";
|
|
|
8
8
|
const VIRTUAL_ID = "virtual:nrg/node-definitions";
|
|
9
9
|
const RESOLVED_ID = "\0" + VIRTUAL_ID;
|
|
10
10
|
|
|
11
|
-
const VIRTUAL_ENTRY_ID = "virtual:nrg/client-entry";
|
|
12
|
-
const RESOLVED_ENTRY_ID = "\0" + VIRTUAL_ENTRY_ID;
|
|
13
|
-
|
|
14
11
|
const SKIP_DEFAULTS = new Set(["x", "y", "z", "g", "wires", "type", "id"]);
|
|
15
12
|
|
|
16
13
|
function getDefaultsFromSchema(
|
|
@@ -77,6 +74,8 @@ function nodeDefinitionsInliner(
|
|
|
77
74
|
): Plugin {
|
|
78
75
|
let _nodeTypes: string[] = [];
|
|
79
76
|
let _definitions: Record<string, any> = {};
|
|
77
|
+
// Cache directory for generated files (inside node_modules, gitignored)
|
|
78
|
+
const cacheDir = path.resolve("node_modules", ".nrg", "client");
|
|
80
79
|
|
|
81
80
|
return {
|
|
82
81
|
name: "vite-plugin-node-red:client:node-definitions-inliner",
|
|
@@ -145,80 +144,132 @@ function nodeDefinitionsInliner(
|
|
|
145
144
|
outputsSchema,
|
|
146
145
|
};
|
|
147
146
|
}
|
|
147
|
+
|
|
148
|
+
// When no user entry, generate node definition files in cache
|
|
149
|
+
// so they appear as separate files in browser devtools.
|
|
150
|
+
if (!hasUserEntry) {
|
|
151
|
+
const nodesCache = path.resolve(cacheDir, "nodes");
|
|
152
|
+
if (fs.existsSync(nodesCache)) {
|
|
153
|
+
fs.rmSync(nodesCache, { recursive: true });
|
|
154
|
+
}
|
|
155
|
+
fs.mkdirSync(nodesCache, { recursive: true });
|
|
156
|
+
|
|
157
|
+
for (const type of _nodeTypes) {
|
|
158
|
+
// Skip if user has a physical node definition file
|
|
159
|
+
const userTsPath = nodesDir
|
|
160
|
+
? path.resolve(nodesDir, `${type}.ts`)
|
|
161
|
+
: null;
|
|
162
|
+
if (userTsPath && fs.existsSync(userTsPath)) continue;
|
|
163
|
+
|
|
164
|
+
const content = [
|
|
165
|
+
`// auto-generated by nrg`,
|
|
166
|
+
`import { defineNode } from "@bonsae/nrg/client";`,
|
|
167
|
+
``,
|
|
168
|
+
`export default defineNode({`,
|
|
169
|
+
` type: ${JSON.stringify(type)},`,
|
|
170
|
+
`});`,
|
|
171
|
+
``,
|
|
172
|
+
].join("\n");
|
|
173
|
+
fs.writeFileSync(path.resolve(nodesCache, `${type}.ts`), content);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Also write the entry file to cache
|
|
177
|
+
const entryContent = generateEntryCode("");
|
|
178
|
+
fs.mkdirSync(path.dirname(path.resolve(cacheDir, "index.ts")), {
|
|
179
|
+
recursive: true,
|
|
180
|
+
});
|
|
181
|
+
fs.writeFileSync(path.resolve(cacheDir, "index.ts"), entryContent);
|
|
182
|
+
}
|
|
148
183
|
},
|
|
149
184
|
|
|
150
185
|
resolveId(id) {
|
|
151
186
|
if (id === VIRTUAL_ID) return RESOLVED_ID;
|
|
152
|
-
if (id === VIRTUAL_ENTRY_ID) return RESOLVED_ENTRY_ID;
|
|
153
187
|
},
|
|
154
188
|
|
|
155
189
|
load(id) {
|
|
156
|
-
if (id ===
|
|
157
|
-
|
|
158
|
-
|
|
190
|
+
if (id === RESOLVED_ID)
|
|
191
|
+
return `export default ${JSON.stringify(_definitions)};`;
|
|
192
|
+
|
|
193
|
+
// For auto-generated entries, return the generated code directly
|
|
194
|
+
// so the browser devtools shows the actual source instead of the
|
|
195
|
+
// placeholder comment on disk.
|
|
196
|
+
if (!hasUserEntry && id === entryPath) {
|
|
197
|
+
return generateEntryCode("");
|
|
198
|
+
}
|
|
159
199
|
},
|
|
160
200
|
|
|
161
201
|
transform(code, id) {
|
|
162
|
-
if (id !== entryPath
|
|
202
|
+
if (id !== entryPath) return;
|
|
203
|
+
// When the user provides their own entry, prepend the generated
|
|
204
|
+
// code to their source. For auto-generated entries, the load hook
|
|
205
|
+
// already returned the full code.
|
|
206
|
+
if (!hasUserEntry) return;
|
|
163
207
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
208
|
+
return { code: generateEntryCode(code), map: null };
|
|
209
|
+
},
|
|
210
|
+
};
|
|
167
211
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
212
|
+
function generateEntryCode(userCode: string): string {
|
|
213
|
+
const nrgImports = new Set<string>(["__setSchemas"]);
|
|
214
|
+
const lines = [`import __nrgSchemas from "${VIRTUAL_ID}";`];
|
|
215
|
+
const postLines: string[] = [`__setSchemas(__nrgSchemas);`];
|
|
172
216
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
formImports.push(
|
|
178
|
-
`import ${varName} from ${JSON.stringify(componentPath)};`,
|
|
179
|
-
);
|
|
180
|
-
formEntries.push(`${JSON.stringify(type)}: ${varName}`);
|
|
181
|
-
}
|
|
182
|
-
}
|
|
217
|
+
// Auto-detect form components by convention: {componentsDir}/{type}.vue
|
|
218
|
+
if (componentsDir && fs.existsSync(componentsDir)) {
|
|
219
|
+
const formImports: string[] = [];
|
|
220
|
+
const formEntries: string[] = [];
|
|
183
221
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
222
|
+
for (const type of _nodeTypes) {
|
|
223
|
+
const componentPath = path.resolve(componentsDir, `${type}.vue`);
|
|
224
|
+
if (fs.existsSync(componentPath)) {
|
|
225
|
+
const varName = `__nrgForm_${type.replace(/-/g, "_")}`;
|
|
226
|
+
formImports.push(
|
|
227
|
+
`import ${varName} from ${JSON.stringify(componentPath)};`,
|
|
228
|
+
);
|
|
229
|
+
formEntries.push(`${JSON.stringify(type)}: ${varName}`);
|
|
188
230
|
}
|
|
189
231
|
}
|
|
190
232
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
const tsPath = nodesDir ? path.resolve(nodesDir, `${type}.ts`) : null;
|
|
198
|
-
|
|
199
|
-
if (tsPath && fs.existsSync(tsPath)) {
|
|
200
|
-
lines.push(`import ${varName} from ${JSON.stringify(tsPath)};`);
|
|
201
|
-
} else {
|
|
202
|
-
lines.push(`const ${varName} = { type: ${JSON.stringify(type)} };`);
|
|
203
|
-
}
|
|
204
|
-
defVarNames.push(varName);
|
|
205
|
-
}
|
|
233
|
+
if (formImports.length > 0) {
|
|
234
|
+
lines.push(...formImports);
|
|
235
|
+
nrgImports.add("__setForms");
|
|
236
|
+
postLines.push(`__setForms({ ${formEntries.join(", ")} });`);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
206
239
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
240
|
+
// Auto-register only when no user entry was provided.
|
|
241
|
+
if (!hasUserEntry) {
|
|
242
|
+
const nodesCache = path.resolve(cacheDir, "nodes");
|
|
243
|
+
const defVarNames: string[] = [];
|
|
244
|
+
|
|
245
|
+
for (const type of _nodeTypes) {
|
|
246
|
+
const varName = `__nrgNodeDef_${type.replace(/-/g, "_")}`;
|
|
247
|
+
// Use physical file if user has one, otherwise use cached generated file
|
|
248
|
+
const userTsPath = nodesDir
|
|
249
|
+
? path.resolve(nodesDir, `${type}.ts`)
|
|
250
|
+
: null;
|
|
251
|
+
const tsPath =
|
|
252
|
+
userTsPath && fs.existsSync(userTsPath)
|
|
253
|
+
? userTsPath
|
|
254
|
+
: path.resolve(nodesCache, `${type}.ts`);
|
|
255
|
+
lines.push(`import ${varName} from ${JSON.stringify(tsPath)};`);
|
|
256
|
+
defVarNames.push(varName);
|
|
211
257
|
}
|
|
212
258
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
259
|
+
if (defVarNames.length > 0) {
|
|
260
|
+
nrgImports.add("registerTypes");
|
|
261
|
+
postLines.push(`registerTypes([${defVarNames.join(", ")}]);`);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
216
264
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
265
|
+
// Build the @bonsae/nrg/client import line
|
|
266
|
+
const importLine = `import { ${[...nrgImports].join(", ")} } from "@bonsae/nrg/client";`;
|
|
267
|
+
lines.splice(1, 0, importLine);
|
|
268
|
+
|
|
269
|
+
lines.push(...postLines);
|
|
270
|
+
lines.push("");
|
|
271
|
+
return lines.join("\n") + userCode;
|
|
272
|
+
}
|
|
222
273
|
}
|
|
223
274
|
|
|
224
275
|
export { nodeDefinitionsInliner };
|
package/src/vite/index.ts
CHANGED
package/src/vite/types.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { Plugin } from "vite";
|
|
2
2
|
import type { NodeRedLauncher } from "./node-red-launcher";
|
|
3
|
-
import type { Http2ServerRequest } from "http2";
|
|
4
3
|
|
|
5
4
|
interface BuildContext {
|
|
6
5
|
outDir: string;
|
|
@@ -105,199 +104,6 @@ interface NodeRedPluginOptions {
|
|
|
105
104
|
extraFilesCopyTargets?: CopyTarget[];
|
|
106
105
|
}
|
|
107
106
|
|
|
108
|
-
interface NodeRedRuntimeSettings {
|
|
109
|
-
// NOTE: commented out because the preferred port must be set using NodeRedLauncherOptions.runtime.port
|
|
110
|
-
// uiPort?: number;
|
|
111
|
-
// NOTE: commented out because the plugin set it to 127.0.0.1
|
|
112
|
-
// uiHost?: string;
|
|
113
|
-
userDir?: string;
|
|
114
|
-
nodesDir?: string | string[];
|
|
115
|
-
flowFile?: string;
|
|
116
|
-
flowFilePretty?: boolean;
|
|
117
|
-
credentialSecret?: string | false;
|
|
118
|
-
requireHttps?: boolean;
|
|
119
|
-
https?:
|
|
120
|
-
| { key: string; cert: string }
|
|
121
|
-
| (() =>
|
|
122
|
-
| Promise<{ key: string; cert: string }>
|
|
123
|
-
| { key: string; cert: string });
|
|
124
|
-
httpsRefreshInterval?: number;
|
|
125
|
-
httpAdminRoot?: string;
|
|
126
|
-
httpNodeRoot?: string;
|
|
127
|
-
httpNodeCors?: { origin: string; methods: string };
|
|
128
|
-
httpStatic?: string | { path: string; root: string }[];
|
|
129
|
-
httpStaticRoot?: string;
|
|
130
|
-
httpAdminMiddleware?: (req: unknown, res: unknown, next: () => void) => void;
|
|
131
|
-
httpNodeMiddleware?: (req: unknown, res: unknown, next: () => void) => void;
|
|
132
|
-
httpServerOptions?: Record<string, unknown>;
|
|
133
|
-
adminAuth?: {
|
|
134
|
-
type?: "credentials" | "strategy";
|
|
135
|
-
users?: {
|
|
136
|
-
username: string;
|
|
137
|
-
password: string;
|
|
138
|
-
permissions?: string | string[];
|
|
139
|
-
}[];
|
|
140
|
-
default?: {
|
|
141
|
-
permissions?: string | string[];
|
|
142
|
-
};
|
|
143
|
-
tokens?: (
|
|
144
|
-
token: string,
|
|
145
|
-
) => Promise<{ user: string; permissions: string | string[] } | null>;
|
|
146
|
-
tokenHeader: "string";
|
|
147
|
-
sessionExpiryTime?: number;
|
|
148
|
-
[key: string]: unknown;
|
|
149
|
-
};
|
|
150
|
-
httpNodeAuth?: {
|
|
151
|
-
user?: string;
|
|
152
|
-
pass?: string;
|
|
153
|
-
};
|
|
154
|
-
httpStaticAuth?: {
|
|
155
|
-
user?: string;
|
|
156
|
-
pass?: string;
|
|
157
|
-
};
|
|
158
|
-
lang?:
|
|
159
|
-
| "en-US"
|
|
160
|
-
| "de"
|
|
161
|
-
| "es-ES"
|
|
162
|
-
| "fr"
|
|
163
|
-
| "ko"
|
|
164
|
-
| "pt-BR"
|
|
165
|
-
| "ru"
|
|
166
|
-
| "ja"
|
|
167
|
-
| "zh-CN"
|
|
168
|
-
| "zh-TW";
|
|
169
|
-
diagnostics?: {
|
|
170
|
-
enabled?: boolean;
|
|
171
|
-
ui?: boolean;
|
|
172
|
-
};
|
|
173
|
-
runtimeState?: {
|
|
174
|
-
enabled?: boolean;
|
|
175
|
-
ui?: boolean;
|
|
176
|
-
};
|
|
177
|
-
disableEditor?: boolean;
|
|
178
|
-
editorTheme?: {
|
|
179
|
-
page?: {
|
|
180
|
-
title?: string;
|
|
181
|
-
favicon?: string;
|
|
182
|
-
css?: string | string[];
|
|
183
|
-
scripts?: string | string[];
|
|
184
|
-
};
|
|
185
|
-
header?: {
|
|
186
|
-
title?: string;
|
|
187
|
-
image?: string;
|
|
188
|
-
url?: string;
|
|
189
|
-
};
|
|
190
|
-
deployButton?: {
|
|
191
|
-
type?: "simple" | "default";
|
|
192
|
-
label?: string;
|
|
193
|
-
icon?: string;
|
|
194
|
-
};
|
|
195
|
-
menu?: {
|
|
196
|
-
"menu-item-import-library"?: boolean;
|
|
197
|
-
"menu-item-export-library"?: boolean;
|
|
198
|
-
"menu-item-keyboard-shortcuts"?: boolean;
|
|
199
|
-
"menu-item-help"?: {
|
|
200
|
-
label?: string;
|
|
201
|
-
url?: string;
|
|
202
|
-
};
|
|
203
|
-
[menuItem: string]:
|
|
204
|
-
| boolean
|
|
205
|
-
| { label?: string; url?: string }
|
|
206
|
-
| undefined;
|
|
207
|
-
};
|
|
208
|
-
userMenu?: boolean;
|
|
209
|
-
login?: {
|
|
210
|
-
image?: string;
|
|
211
|
-
};
|
|
212
|
-
logout?: {
|
|
213
|
-
redirect?: string;
|
|
214
|
-
};
|
|
215
|
-
palette?: {
|
|
216
|
-
catalogues?: string[];
|
|
217
|
-
categories?: string[];
|
|
218
|
-
theme?: { category: string; type: string; color: string }[];
|
|
219
|
-
};
|
|
220
|
-
projects?: {
|
|
221
|
-
enabled?: boolean;
|
|
222
|
-
workflow?: {
|
|
223
|
-
mode: "manual" | "auto";
|
|
224
|
-
};
|
|
225
|
-
};
|
|
226
|
-
codeEditor?: {
|
|
227
|
-
lib?: "monaco" | "ace";
|
|
228
|
-
// TODO: add monaco option types
|
|
229
|
-
options?: Record<string, unknown>;
|
|
230
|
-
};
|
|
231
|
-
mermaid?: {
|
|
232
|
-
theme?: string;
|
|
233
|
-
};
|
|
234
|
-
tours?: boolean;
|
|
235
|
-
theme?: string;
|
|
236
|
-
[key: string]: unknown;
|
|
237
|
-
};
|
|
238
|
-
contextStorage?: {
|
|
239
|
-
default?: {
|
|
240
|
-
module?: "memory" | "localfilesystem" | object;
|
|
241
|
-
config?: Record<string, unknown>;
|
|
242
|
-
};
|
|
243
|
-
[store: string]:
|
|
244
|
-
| {
|
|
245
|
-
module?: "memory" | "localfilesystem" | object;
|
|
246
|
-
config?: Record<string, unknown>;
|
|
247
|
-
}
|
|
248
|
-
| undefined;
|
|
249
|
-
};
|
|
250
|
-
exportGlobalContextKeys?: boolean;
|
|
251
|
-
logging?: {
|
|
252
|
-
console?: {
|
|
253
|
-
level?: "fatal" | "error" | "warn" | "info" | "debug" | "trace" | "off";
|
|
254
|
-
metrics?: boolean;
|
|
255
|
-
audit?: boolean;
|
|
256
|
-
};
|
|
257
|
-
};
|
|
258
|
-
fileWorkingDirectory?: string;
|
|
259
|
-
functionExternalModules?: boolean;
|
|
260
|
-
functionGlobalContext?: Record<string, unknown>;
|
|
261
|
-
nodeMessageBufferMaxLength?: number;
|
|
262
|
-
functionTimeout?: number;
|
|
263
|
-
externalModules?: {
|
|
264
|
-
autoInstall?: boolean;
|
|
265
|
-
autoInstallRetry?: number;
|
|
266
|
-
palette?: {
|
|
267
|
-
allowInstall?: boolean;
|
|
268
|
-
allowUpdate?: boolean;
|
|
269
|
-
allowUpload?: boolean;
|
|
270
|
-
allowList?: string[];
|
|
271
|
-
denyList?: string[];
|
|
272
|
-
allowUpdateList?: string[];
|
|
273
|
-
denyUpdateList?: string[];
|
|
274
|
-
};
|
|
275
|
-
modules?: {
|
|
276
|
-
allowInstall?: boolean;
|
|
277
|
-
allowList?: string[];
|
|
278
|
-
denyList?: string[];
|
|
279
|
-
};
|
|
280
|
-
};
|
|
281
|
-
execMaxBufferSize?: number;
|
|
282
|
-
debugMaxLength?: number;
|
|
283
|
-
debugUseColors?: boolean;
|
|
284
|
-
httpRequestTimeout?: number;
|
|
285
|
-
mqttReconnectTime?: number;
|
|
286
|
-
serialReconnectTime?: number;
|
|
287
|
-
socketReconnectTime?: number;
|
|
288
|
-
socketTimeout?: number;
|
|
289
|
-
tcpMsgQueueSize?: number;
|
|
290
|
-
inboundWebSocketTimeout?: number;
|
|
291
|
-
tlsConfigDisableLocalFiles?: boolean;
|
|
292
|
-
webSocketNodeVerifyClient?: (info: {
|
|
293
|
-
origin: string;
|
|
294
|
-
req: Http2ServerRequest;
|
|
295
|
-
secure: boolean;
|
|
296
|
-
}) => boolean;
|
|
297
|
-
apiMaxLength?: string;
|
|
298
|
-
[key: string]: unknown;
|
|
299
|
-
}
|
|
300
|
-
|
|
301
107
|
interface PackageJson {
|
|
302
108
|
name: string;
|
|
303
109
|
version: string;
|
|
@@ -362,7 +168,6 @@ export {
|
|
|
362
168
|
LoggerOptions,
|
|
363
169
|
NodeRedLauncherOptions,
|
|
364
170
|
NodeRedPluginOptions,
|
|
365
|
-
NodeRedRuntimeSettings,
|
|
366
171
|
PackageJson,
|
|
367
172
|
ServerBuildOptions,
|
|
368
173
|
ServerPluginOptions,
|
package/src/vite/utils.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import fs from "fs";
|
|
2
2
|
import path from "path";
|
|
3
|
-
import type {
|
|
3
|
+
import type { PackageJson } from "./types";
|
|
4
4
|
|
|
5
5
|
function cleanDir(dir: string) {
|
|
6
6
|
if (fs.existsSync(dir)) {
|
|
@@ -69,35 +69,4 @@ function mergeOptions<T extends Record<string, unknown>>(
|
|
|
69
69
|
return result;
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
|
|
73
|
-
* Define Node-RED runtime settings with full type support.
|
|
74
|
-
*
|
|
75
|
-
* Note: All paths should be absolute. Use `import.meta.dirname` or `__dirname` to resolve relative paths.
|
|
76
|
-
*
|
|
77
|
-
* @example
|
|
78
|
-
* ```typescript
|
|
79
|
-
* import { defineRuntimeSettings } from "./vite/utils";
|
|
80
|
-
* import path from "path";
|
|
81
|
-
*
|
|
82
|
-
* const __dirname = import.meta.dirname;
|
|
83
|
-
*
|
|
84
|
-
* export default defineRuntimeSettings({
|
|
85
|
-
* userDir: path.resolve(__dirname, ".node-red"),
|
|
86
|
-
* flowFile: "flows.json",
|
|
87
|
-
* httpStatic: path.resolve(__dirname, "public"),
|
|
88
|
-
* });
|
|
89
|
-
* ```
|
|
90
|
-
*/
|
|
91
|
-
function defineRuntimeSettings(
|
|
92
|
-
settings: NodeRedRuntimeSettings,
|
|
93
|
-
): NodeRedRuntimeSettings {
|
|
94
|
-
return settings;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
export {
|
|
98
|
-
cleanDir,
|
|
99
|
-
copyFiles,
|
|
100
|
-
defineRuntimeSettings,
|
|
101
|
-
getPackageName,
|
|
102
|
-
mergeOptions,
|
|
103
|
-
};
|
|
72
|
+
export { cleanDir, copyFiles, getPackageName, mergeOptions };
|