@bonsae/nrg 0.21.1 → 0.22.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/LICENSE +21 -0
- package/README.md +2 -3
- package/package.json +14 -9
- package/schemas/labels.schema.json +15 -5
- package/server/index.cjs +2 -1346
- package/test/client/component/index.js +41 -224
- package/test/client/component/setup.js +201 -1475
- package/test/client/e2e/config.js +12 -0
- package/test/client/e2e/index.js +422 -199
- package/test/client/unit/index.js +19 -32
- package/test/client/unit/setup.js +28 -21
- package/test/server/integration/index.js +2 -26
- package/test/server/unit/index.js +2 -184
- package/types/client.d.ts +1 -259
- package/types/server.d.ts +1 -892
- package/types/test-client-component.d.ts +7 -143
- package/types/test-client-e2e.d.ts +0 -6
- package/types/test-client-unit.d.ts +11 -105
- package/types/test-server-integration.d.ts +73 -49
- package/types/test-server-unit.d.ts +26 -2
- package/types/vite.d.ts +2 -0
- package/vite/index.js +381 -150
- package/server/resources/nrg-client.js +0 -7495
- package/test/client/component/nrg.css +0 -1
- package/types/shims/brands.d.ts +0 -32
- package/types/shims/client/form/components/node-red-config-input.vue.d.ts +0 -125
- package/types/shims/client/form/components/node-red-editor-input.vue.d.ts +0 -124
- package/types/shims/client/form/components/node-red-input-label.vue.d.ts +0 -34
- package/types/shims/client/form/components/node-red-input.vue.d.ts +0 -123
- package/types/shims/client/form/components/node-red-json-schema-form.vue.d.ts +0 -772
- package/types/shims/client/form/components/node-red-select-input.vue.d.ts +0 -132
- package/types/shims/client/form/components/node-red-toggle.vue.d.ts +0 -36
- package/types/shims/client/form/components/node-red-typed-input.vue.d.ts +0 -151
- package/types/shims/client/globals.d.ts +0 -320
- package/types/shims/client/types.d.ts +0 -220
- package/types/shims/components.d.ts +0 -23
- package/types/shims/constants.d.ts +0 -4
- package/types/shims/schema-options.d.ts +0 -24
- package/types/shims/shims-vue.d.ts +0 -5
- package/types/shims/typebox.d.ts +0 -10
package/test/client/e2e/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
// src/test/client/e2e/index.ts
|
|
2
|
-
import
|
|
3
|
-
import
|
|
2
|
+
import fs15 from "fs";
|
|
3
|
+
import path14 from "path";
|
|
4
4
|
|
|
5
5
|
// src/test/client/e2e/environment.ts
|
|
6
|
-
import
|
|
7
|
-
import
|
|
6
|
+
import fs14 from "fs";
|
|
7
|
+
import path13 from "path";
|
|
8
8
|
|
|
9
9
|
// src/vite/server/build.ts
|
|
10
10
|
import { build as viteBuild } from "vite";
|
|
@@ -115,6 +115,26 @@ import dts from "vite-plugin-dts";
|
|
|
115
115
|
import fs from "fs";
|
|
116
116
|
import path from "path";
|
|
117
117
|
import ts from "typescript";
|
|
118
|
+
var RUNTIME_TYPE_REWRITES = {
|
|
119
|
+
"@bonsae/nrg/server": "@bonsae/nrg-runtime/server",
|
|
120
|
+
"@bonsae/nrg/client": "@bonsae/nrg-runtime/client"
|
|
121
|
+
};
|
|
122
|
+
function rewriteRuntimeTypeImports(outDir, entryNames) {
|
|
123
|
+
for (const name of entryNames) {
|
|
124
|
+
const dtsPath = path.join(outDir, `${name}.d.ts`);
|
|
125
|
+
if (!fs.existsSync(dtsPath)) continue;
|
|
126
|
+
const original = fs.readFileSync(dtsPath, "utf-8");
|
|
127
|
+
let rewritten = original;
|
|
128
|
+
for (const [from, to] of Object.entries(RUNTIME_TYPE_REWRITES)) {
|
|
129
|
+
const escaped = from.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
130
|
+
const re = new RegExp(`(['"])${escaped}\\1`, "g");
|
|
131
|
+
rewritten = rewritten.replace(re, `$1${to}$1`);
|
|
132
|
+
}
|
|
133
|
+
if (rewritten !== original) {
|
|
134
|
+
fs.writeFileSync(dtsPath, rewritten);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
118
138
|
function collectTsFiles(dir) {
|
|
119
139
|
if (!fs.existsSync(dir)) return [];
|
|
120
140
|
return fs.readdirSync(dir, { withFileTypes: true }).flatMap((dirent) => {
|
|
@@ -489,18 +509,23 @@ ${reexports}
|
|
|
489
509
|
}
|
|
490
510
|
|
|
491
511
|
// src/vite/server/plugins/output-wrapper.ts
|
|
492
|
-
function
|
|
512
|
+
function nrgServerSpecifier(isDev) {
|
|
513
|
+
return isDev ? "@bonsae/nrg/server" : "@bonsae/nrg-runtime/server";
|
|
514
|
+
}
|
|
515
|
+
function cjsWrapper(isDev = false) {
|
|
516
|
+
const serverSpecifier = nrgServerSpecifier(isDev);
|
|
493
517
|
return {
|
|
494
518
|
name: "vite-plugin-node-red:server:cjs-wrapper",
|
|
495
519
|
renderChunk(code, chunk, outputOptions) {
|
|
496
520
|
if (!chunk.isEntry || outputOptions.format !== "cjs") return null;
|
|
497
|
-
const footer = `(function(){var _exp=module.exports&&module.exports.__esModule?module.exports.default:module.exports;if(_exp&&typeof _exp==="object"&&Array.isArray(_exp.nodes)){var _nrg=require(
|
|
521
|
+
const footer = `(function(){var _exp=module.exports&&module.exports.__esModule?module.exports.default:module.exports;if(_exp&&typeof _exp==="object"&&Array.isArray(_exp.nodes)){var _nrg=require(${JSON.stringify(serverSpecifier)});module.exports=_nrg.registerTypes(_exp.nodes);}else if(typeof _exp==="function"&&Array.isArray(_exp.nodes)){module.exports=_exp;_exp.nodes.forEach(function(cls){if(cls&&cls.type){_exp[cls.type.replace(/(?:^|[-_])(\\w)/g,function(_,c){return c.toUpperCase();})] = cls;}});}})();`;
|
|
498
522
|
return { code: `${code}
|
|
499
523
|
${footer}`, map: null };
|
|
500
524
|
}
|
|
501
525
|
};
|
|
502
526
|
}
|
|
503
|
-
function esmWrapper() {
|
|
527
|
+
function esmWrapper(isDev = false) {
|
|
528
|
+
const serverSpecifier = nrgServerSpecifier(isDev);
|
|
504
529
|
return {
|
|
505
530
|
name: "vite-plugin-node-red:server:esm-wrapper",
|
|
506
531
|
renderChunk(code, chunk, outputOptions) {
|
|
@@ -526,7 +551,9 @@ function esmWrapper() {
|
|
|
526
551
|
`import { dirname as __nrgDirname } from "path";`,
|
|
527
552
|
`var __filename = __nrgFileURLToPath(import.meta.url);`,
|
|
528
553
|
`var __dirname = __nrgDirname(__filename);`,
|
|
529
|
-
`import { registerTypes as __nrgRegisterTypes } from
|
|
554
|
+
`import { registerTypes as __nrgRegisterTypes } from ${JSON.stringify(
|
|
555
|
+
serverSpecifier
|
|
556
|
+
)};`,
|
|
530
557
|
``
|
|
531
558
|
].join("\n");
|
|
532
559
|
const replacement = [
|
|
@@ -550,6 +577,12 @@ var nodeBuiltins = /* @__PURE__ */ new Set([
|
|
|
550
577
|
...builtinModules,
|
|
551
578
|
...builtinModules.map((m) => `node:${m}`)
|
|
552
579
|
]);
|
|
580
|
+
var RUNTIME_REWRITES = {
|
|
581
|
+
"@bonsae/nrg/server": "@bonsae/nrg-runtime/server"
|
|
582
|
+
};
|
|
583
|
+
var RUNTIME_VERSION_SOURCE = {
|
|
584
|
+
"@bonsae/nrg-runtime": "@bonsae/nrg"
|
|
585
|
+
};
|
|
553
586
|
function buildTypesPath(entryName) {
|
|
554
587
|
return `./${entryName}.d.ts`;
|
|
555
588
|
}
|
|
@@ -606,7 +639,8 @@ function packageJsonGenerator(options) {
|
|
|
606
639
|
bundled = [],
|
|
607
640
|
types = false,
|
|
608
641
|
entryNames = [],
|
|
609
|
-
format = "cjs"
|
|
642
|
+
format = "cjs",
|
|
643
|
+
isDev = false
|
|
610
644
|
} = options;
|
|
611
645
|
const trackedDependencies = /* @__PURE__ */ new Set();
|
|
612
646
|
return {
|
|
@@ -624,12 +658,13 @@ function packageJsonGenerator(options) {
|
|
|
624
658
|
if (nodeBuiltins.has(source)) {
|
|
625
659
|
return { id: source, external: true };
|
|
626
660
|
}
|
|
627
|
-
const
|
|
661
|
+
const resolved = isDev ? source : RUNTIME_REWRITES[source] ?? source;
|
|
662
|
+
const packageName = resolved.startsWith("@") ? resolved.split("/").slice(0, 2).join("/") : resolved.split("/")[0];
|
|
628
663
|
if (bundled.includes(packageName)) {
|
|
629
664
|
return null;
|
|
630
665
|
}
|
|
631
666
|
trackedDependencies.add(packageName);
|
|
632
|
-
return { id:
|
|
667
|
+
return { id: resolved, external: true };
|
|
633
668
|
}
|
|
634
669
|
},
|
|
635
670
|
closeBundle() {
|
|
@@ -642,14 +677,19 @@ function packageJsonGenerator(options) {
|
|
|
642
677
|
fs2.readFileSync(rootPackageJsonPath, "utf-8")
|
|
643
678
|
);
|
|
644
679
|
const sourceDeps = rootPackageJson.dependencies ?? {};
|
|
680
|
+
const devDeps = rootPackageJson.devDependencies ?? {};
|
|
645
681
|
const peerDeps = rootPackageJson.peerDependencies ?? {};
|
|
646
682
|
let distDependencies = {};
|
|
647
683
|
for (const dep of trackedDependencies) {
|
|
648
684
|
if (peerDeps[dep]) {
|
|
649
685
|
continue;
|
|
650
686
|
}
|
|
687
|
+
const versionSource = RUNTIME_VERSION_SOURCE[dep];
|
|
688
|
+
const sourceVersion = versionSource ? sourceDeps[versionSource] ?? devDeps[versionSource] : void 0;
|
|
651
689
|
if (sourceDeps[dep]) {
|
|
652
690
|
distDependencies[dep] = sourceDeps[dep];
|
|
691
|
+
} else if (sourceVersion) {
|
|
692
|
+
distDependencies[dep] = sourceVersion;
|
|
653
693
|
} else {
|
|
654
694
|
const dependencyPackageJsonPath = path2.resolve(
|
|
655
695
|
`./node_modules/${dep}/package.json`
|
|
@@ -736,9 +776,10 @@ async function build(serverOpts, buildContext) {
|
|
|
736
776
|
bundled,
|
|
737
777
|
types: types && !buildContext.isDev,
|
|
738
778
|
entryNames: Object.keys(entryPoints),
|
|
739
|
-
format
|
|
779
|
+
format,
|
|
780
|
+
isDev: buildContext.isDev
|
|
740
781
|
}),
|
|
741
|
-
isEsm ? esmWrapper() : cjsWrapper()
|
|
782
|
+
isEsm ? esmWrapper(buildContext.isDev) : cjsWrapper(buildContext.isDev)
|
|
742
783
|
];
|
|
743
784
|
if (types && !buildContext.isDev) {
|
|
744
785
|
plugins.push(
|
|
@@ -780,6 +821,9 @@ async function build(serverOpts, buildContext) {
|
|
|
780
821
|
};
|
|
781
822
|
try {
|
|
782
823
|
await viteBuild(config);
|
|
824
|
+
if (types && !buildContext.isDev) {
|
|
825
|
+
rewriteRuntimeTypeImports(buildContext.outDir, Object.keys(entryPoints));
|
|
826
|
+
}
|
|
783
827
|
if (isEsm) {
|
|
784
828
|
const bridgeCode = `'use strict';
|
|
785
829
|
// CJS bridge \u2014 auto-generated by @bonsae/nrg/vite
|
|
@@ -806,12 +850,13 @@ module.exports = function (RED) {
|
|
|
806
850
|
// src/vite/client/build.ts
|
|
807
851
|
import { build as viteBuild2 } from "vite";
|
|
808
852
|
import vue from "@vitejs/plugin-vue";
|
|
809
|
-
import
|
|
810
|
-
import
|
|
853
|
+
import fs10 from "fs";
|
|
854
|
+
import path10 from "path";
|
|
855
|
+
import crypto from "crypto";
|
|
811
856
|
|
|
812
857
|
// src/vite/client/plugins/help-generator.ts
|
|
813
|
-
import
|
|
814
|
-
import
|
|
858
|
+
import fs5 from "fs";
|
|
859
|
+
import path5 from "path";
|
|
815
860
|
import { pathToFileURL } from "url";
|
|
816
861
|
import { createRequire } from "module";
|
|
817
862
|
|
|
@@ -1042,8 +1087,127 @@ function getHelpTranslations(lang) {
|
|
|
1042
1087
|
return translations[lang] ?? translations["en-US"];
|
|
1043
1088
|
}
|
|
1044
1089
|
|
|
1090
|
+
// src/vite/client/plugins/unsafe-types.ts
|
|
1091
|
+
import ts2 from "typescript";
|
|
1092
|
+
import fs4 from "fs";
|
|
1093
|
+
import path4 from "path";
|
|
1094
|
+
var NRG_SERVER_MODULE = "@bonsae/nrg/server";
|
|
1095
|
+
function normalizeType(text) {
|
|
1096
|
+
return text.replace(/\s+/g, " ").trim();
|
|
1097
|
+
}
|
|
1098
|
+
function resolveImports(sf) {
|
|
1099
|
+
const defineSchema = /* @__PURE__ */ new Set();
|
|
1100
|
+
const schemaType = /* @__PURE__ */ new Set();
|
|
1101
|
+
sf.forEachChild((node) => {
|
|
1102
|
+
if (!ts2.isImportDeclaration(node) || !ts2.isStringLiteral(node.moduleSpecifier) || node.moduleSpecifier.text !== NRG_SERVER_MODULE || !node.importClause?.namedBindings || !ts2.isNamedImports(node.importClause.namedBindings)) {
|
|
1103
|
+
return;
|
|
1104
|
+
}
|
|
1105
|
+
for (const el of node.importClause.namedBindings.elements) {
|
|
1106
|
+
const imported = (el.propertyName ?? el.name).text;
|
|
1107
|
+
const local = el.name.text;
|
|
1108
|
+
if (imported === "defineSchema") defineSchema.add(local);
|
|
1109
|
+
if (imported === "SchemaType") schemaType.add(local);
|
|
1110
|
+
}
|
|
1111
|
+
});
|
|
1112
|
+
return { defineSchema, schemaType };
|
|
1113
|
+
}
|
|
1114
|
+
function staticPropName(name) {
|
|
1115
|
+
if (ts2.isIdentifier(name) || ts2.isStringLiteralLike(name)) return name.text;
|
|
1116
|
+
return void 0;
|
|
1117
|
+
}
|
|
1118
|
+
function unsafeTypeArg(node, sf, schemaType) {
|
|
1119
|
+
if (!ts2.isCallExpression(node) || !ts2.isPropertyAccessExpression(node.expression) || !ts2.isIdentifier(node.expression.expression) || !schemaType.has(node.expression.expression.text)) {
|
|
1120
|
+
return void 0;
|
|
1121
|
+
}
|
|
1122
|
+
const method = node.expression.name.text;
|
|
1123
|
+
if (method === "Unsafe" && node.typeArguments?.length) {
|
|
1124
|
+
return normalizeType(node.typeArguments[0].getText(sf));
|
|
1125
|
+
}
|
|
1126
|
+
if (method === "Array" && node.arguments.length) {
|
|
1127
|
+
const inner = unsafeTypeArg(node.arguments[0], sf, schemaType);
|
|
1128
|
+
if (inner) return `${inner}[]`;
|
|
1129
|
+
}
|
|
1130
|
+
return void 0;
|
|
1131
|
+
}
|
|
1132
|
+
function readSchemaCall(call, sf, schemaType) {
|
|
1133
|
+
const [propsArg, optsArg] = call.arguments;
|
|
1134
|
+
if (!propsArg || !optsArg || !ts2.isObjectLiteralExpression(propsArg) || !ts2.isObjectLiteralExpression(optsArg)) {
|
|
1135
|
+
return void 0;
|
|
1136
|
+
}
|
|
1137
|
+
let id;
|
|
1138
|
+
for (const p of optsArg.properties) {
|
|
1139
|
+
if (ts2.isPropertyAssignment(p) && staticPropName(p.name) === "$id" && ts2.isStringLiteralLike(p.initializer)) {
|
|
1140
|
+
id = p.initializer.text;
|
|
1141
|
+
}
|
|
1142
|
+
}
|
|
1143
|
+
if (!id) return void 0;
|
|
1144
|
+
const props = {};
|
|
1145
|
+
for (const p of propsArg.properties) {
|
|
1146
|
+
if (!ts2.isPropertyAssignment(p)) continue;
|
|
1147
|
+
const key = staticPropName(p.name);
|
|
1148
|
+
if (key === void 0) continue;
|
|
1149
|
+
const type = unsafeTypeArg(p.initializer, sf, schemaType);
|
|
1150
|
+
if (type) props[key] = type;
|
|
1151
|
+
}
|
|
1152
|
+
return { id, props };
|
|
1153
|
+
}
|
|
1154
|
+
function extractUnsafeTypesFromSource(fileName, code) {
|
|
1155
|
+
const out = /* @__PURE__ */ new Map();
|
|
1156
|
+
const sf = ts2.createSourceFile(fileName, code, ts2.ScriptTarget.Latest, true);
|
|
1157
|
+
const { defineSchema, schemaType } = resolveImports(sf);
|
|
1158
|
+
if (defineSchema.size === 0 || schemaType.size === 0) return out;
|
|
1159
|
+
const visit = (node) => {
|
|
1160
|
+
if (ts2.isCallExpression(node) && ts2.isIdentifier(node.expression) && defineSchema.has(node.expression.text)) {
|
|
1161
|
+
const result = readSchemaCall(node, sf, schemaType);
|
|
1162
|
+
if (result && Object.keys(result.props).length > 0) {
|
|
1163
|
+
if (out.has(result.id)) {
|
|
1164
|
+
throw new Error(
|
|
1165
|
+
`Duplicate schema $id "${result.id}" in ${fileName} \u2014 $id must be unique`
|
|
1166
|
+
);
|
|
1167
|
+
}
|
|
1168
|
+
out.set(result.id, result.props);
|
|
1169
|
+
}
|
|
1170
|
+
}
|
|
1171
|
+
ts2.forEachChild(node, visit);
|
|
1172
|
+
};
|
|
1173
|
+
visit(sf);
|
|
1174
|
+
return out;
|
|
1175
|
+
}
|
|
1176
|
+
function collectTsFiles2(dir) {
|
|
1177
|
+
const out = [];
|
|
1178
|
+
if (!fs4.existsSync(dir)) return out;
|
|
1179
|
+
for (const entry of fs4.readdirSync(dir, { withFileTypes: true })) {
|
|
1180
|
+
const full = path4.join(dir, entry.name);
|
|
1181
|
+
if (entry.isDirectory()) {
|
|
1182
|
+
if (entry.name === "node_modules") continue;
|
|
1183
|
+
out.push(...collectTsFiles2(full));
|
|
1184
|
+
} else if (entry.name.endsWith(".ts") && !entry.name.endsWith(".d.ts") && !entry.name.endsWith(".test.ts") && !entry.name.endsWith(".spec.ts")) {
|
|
1185
|
+
out.push(full);
|
|
1186
|
+
}
|
|
1187
|
+
}
|
|
1188
|
+
return out;
|
|
1189
|
+
}
|
|
1190
|
+
function extractUnsafeTypes(srcDir) {
|
|
1191
|
+
const merged = /* @__PURE__ */ new Map();
|
|
1192
|
+
for (const file of collectTsFiles2(srcDir).sort()) {
|
|
1193
|
+
const perFile = extractUnsafeTypesFromSource(
|
|
1194
|
+
file,
|
|
1195
|
+
fs4.readFileSync(file, "utf-8")
|
|
1196
|
+
);
|
|
1197
|
+
for (const [id, props] of perFile) {
|
|
1198
|
+
if (merged.has(id)) {
|
|
1199
|
+
throw new Error(
|
|
1200
|
+
`Duplicate schema $id "${id}" across ${srcDir} \u2014 $id must be unique`
|
|
1201
|
+
);
|
|
1202
|
+
}
|
|
1203
|
+
merged.set(id, props);
|
|
1204
|
+
}
|
|
1205
|
+
}
|
|
1206
|
+
return merged;
|
|
1207
|
+
}
|
|
1208
|
+
|
|
1045
1209
|
// src/vite/client/plugins/help-generator.ts
|
|
1046
|
-
function buildPropertyRow(name, schema, required, label) {
|
|
1210
|
+
function buildPropertyRow(name, schema, required, label, parsedType) {
|
|
1047
1211
|
let type = "";
|
|
1048
1212
|
if (schema["x-nrg-node-type"]) {
|
|
1049
1213
|
type = `NodeRef \u2192 ${schema["x-nrg-node-type"]}`;
|
|
@@ -1051,6 +1215,8 @@ function buildPropertyRow(name, schema, required, label) {
|
|
|
1051
1215
|
type = "TypedInput";
|
|
1052
1216
|
} else if (schema.type) {
|
|
1053
1217
|
type = String(schema.type);
|
|
1218
|
+
} else if (parsedType) {
|
|
1219
|
+
type = parsedType;
|
|
1054
1220
|
}
|
|
1055
1221
|
if (schema.enum) type += ` (${schema.enum.join(", ")})`;
|
|
1056
1222
|
const constraints = [];
|
|
@@ -1086,16 +1252,19 @@ function generateSchemaSection(options) {
|
|
|
1086
1252
|
t,
|
|
1087
1253
|
labels,
|
|
1088
1254
|
heading = "###",
|
|
1089
|
-
includeDefault = true
|
|
1255
|
+
includeDefault = true,
|
|
1256
|
+
unsafeTypes
|
|
1090
1257
|
} = options;
|
|
1091
1258
|
if (!schema?.properties) return "";
|
|
1259
|
+
const parsed = unsafeTypes?.get(schema.$id);
|
|
1092
1260
|
const required = new Set(schema.required ?? []);
|
|
1093
1261
|
const rows = Object.entries(schema.properties).filter(([key]) => !SKIP_FIELDS.has(key)).map(
|
|
1094
1262
|
([key, propSchema]) => buildPropertyRow(
|
|
1095
1263
|
key,
|
|
1096
1264
|
propSchema,
|
|
1097
1265
|
required.has(key),
|
|
1098
|
-
labels?.[key]
|
|
1266
|
+
labels?.[key],
|
|
1267
|
+
parsed?.[key]
|
|
1099
1268
|
)
|
|
1100
1269
|
);
|
|
1101
1270
|
if (rows.length === 0) return "";
|
|
@@ -1133,9 +1302,9 @@ ${table}
|
|
|
1133
1302
|
`;
|
|
1134
1303
|
}
|
|
1135
1304
|
function loadNodeLabels(labelPath) {
|
|
1136
|
-
if (!
|
|
1305
|
+
if (!fs5.existsSync(labelPath)) return {};
|
|
1137
1306
|
try {
|
|
1138
|
-
const raw = JSON.parse(
|
|
1307
|
+
const raw = JSON.parse(fs5.readFileSync(labelPath, "utf-8"));
|
|
1139
1308
|
return {
|
|
1140
1309
|
description: raw.description,
|
|
1141
1310
|
configs: raw.configs,
|
|
@@ -1147,7 +1316,7 @@ function loadNodeLabels(labelPath) {
|
|
|
1147
1316
|
return {};
|
|
1148
1317
|
}
|
|
1149
1318
|
}
|
|
1150
|
-
function generateHelpDoc(nodeClass, labels, t) {
|
|
1319
|
+
function generateHelpDoc(nodeClass, labels, t, unsafeTypes) {
|
|
1151
1320
|
const lines = [];
|
|
1152
1321
|
if (labels.description) {
|
|
1153
1322
|
lines.push(`<p>${labels.description}</p>`);
|
|
@@ -1156,14 +1325,16 @@ function generateHelpDoc(nodeClass, labels, t) {
|
|
|
1156
1325
|
title: t.sections.properties,
|
|
1157
1326
|
schema: nodeClass.configSchema,
|
|
1158
1327
|
t,
|
|
1159
|
-
labels: labels.configs
|
|
1328
|
+
labels: labels.configs,
|
|
1329
|
+
unsafeTypes
|
|
1160
1330
|
});
|
|
1161
1331
|
if (configSection) lines.push(configSection);
|
|
1162
1332
|
const credsSection = generateSchemaSection({
|
|
1163
1333
|
title: t.sections.credentials,
|
|
1164
1334
|
schema: nodeClass.credentialsSchema,
|
|
1165
1335
|
t,
|
|
1166
|
-
labels: labels.credentials
|
|
1336
|
+
labels: labels.credentials,
|
|
1337
|
+
unsafeTypes
|
|
1167
1338
|
});
|
|
1168
1339
|
if (credsSection) lines.push(credsSection);
|
|
1169
1340
|
if (nodeClass.inputSchema) {
|
|
@@ -1172,7 +1343,8 @@ function generateHelpDoc(nodeClass, labels, t) {
|
|
|
1172
1343
|
schema: nodeClass.inputSchema,
|
|
1173
1344
|
t,
|
|
1174
1345
|
labels: labels.input,
|
|
1175
|
-
includeDefault: false
|
|
1346
|
+
includeDefault: false,
|
|
1347
|
+
unsafeTypes
|
|
1176
1348
|
});
|
|
1177
1349
|
if (inputSection) lines.push(inputSection);
|
|
1178
1350
|
}
|
|
@@ -1189,7 +1361,8 @@ function generateHelpDoc(nodeClass, labels, t) {
|
|
|
1189
1361
|
t,
|
|
1190
1362
|
labels: portPropLabels,
|
|
1191
1363
|
heading: "####",
|
|
1192
|
-
includeDefault: false
|
|
1364
|
+
includeDefault: false,
|
|
1365
|
+
unsafeTypes
|
|
1193
1366
|
});
|
|
1194
1367
|
if (section) portSections.push(section);
|
|
1195
1368
|
});
|
|
@@ -1209,7 +1382,8 @@ ${portSections.join("\n")}`
|
|
|
1209
1382
|
t,
|
|
1210
1383
|
labels: portPropLabels,
|
|
1211
1384
|
heading: "####",
|
|
1212
|
-
includeDefault: false
|
|
1385
|
+
includeDefault: false,
|
|
1386
|
+
unsafeTypes
|
|
1213
1387
|
});
|
|
1214
1388
|
if (section) portSections.push(section);
|
|
1215
1389
|
}
|
|
@@ -1226,7 +1400,8 @@ ${portSections.join("\n")}`
|
|
|
1226
1400
|
schema: os3,
|
|
1227
1401
|
t,
|
|
1228
1402
|
labels: outputPropLabels,
|
|
1229
|
-
includeDefault: false
|
|
1403
|
+
includeDefault: false,
|
|
1404
|
+
unsafeTypes
|
|
1230
1405
|
});
|
|
1231
1406
|
if (section) lines.push(section);
|
|
1232
1407
|
}
|
|
@@ -1234,26 +1409,26 @@ ${portSections.join("\n")}`
|
|
|
1234
1409
|
return lines.join("\n").trim();
|
|
1235
1410
|
}
|
|
1236
1411
|
function discoverLanguages(labelsDir, nodeType) {
|
|
1237
|
-
const nodeLabelsDir =
|
|
1238
|
-
if (!
|
|
1239
|
-
return
|
|
1412
|
+
const nodeLabelsDir = path5.join(labelsDir, nodeType);
|
|
1413
|
+
if (!fs5.existsSync(nodeLabelsDir)) return [];
|
|
1414
|
+
return fs5.readdirSync(nodeLabelsDir).filter((f) => f.endsWith(".json")).map((f) => path5.basename(f, ".json"));
|
|
1240
1415
|
}
|
|
1241
1416
|
function helpGenerator(options) {
|
|
1242
|
-
const { outDir, localesOutDir, docsDir, labelsDir } = options;
|
|
1417
|
+
const { outDir, localesOutDir, docsDir, labelsDir, srcDir } = options;
|
|
1243
1418
|
return {
|
|
1244
1419
|
name: "vite-plugin-node-red:client:help-generator",
|
|
1245
1420
|
apply: "build",
|
|
1246
1421
|
enforce: "post",
|
|
1247
1422
|
async closeBundle() {
|
|
1248
|
-
const esmPath =
|
|
1249
|
-
const cjsPath =
|
|
1423
|
+
const esmPath = path5.resolve(outDir, "index.mjs");
|
|
1424
|
+
const cjsPath = path5.resolve(outDir, "index.js");
|
|
1250
1425
|
let packageFn;
|
|
1251
1426
|
try {
|
|
1252
|
-
if (
|
|
1427
|
+
if (fs5.existsSync(esmPath)) {
|
|
1253
1428
|
const fileUrl = pathToFileURL(esmPath).href + `?t=${Date.now()}`;
|
|
1254
1429
|
const mod = await import(fileUrl);
|
|
1255
1430
|
packageFn = mod?.default ?? mod;
|
|
1256
|
-
} else if (
|
|
1431
|
+
} else if (fs5.existsSync(cjsPath)) {
|
|
1257
1432
|
const require2 = createRequire(import.meta.url);
|
|
1258
1433
|
delete require2.cache[cjsPath];
|
|
1259
1434
|
const rawMod = require2(cjsPath);
|
|
@@ -1263,6 +1438,7 @@ function helpGenerator(options) {
|
|
|
1263
1438
|
return;
|
|
1264
1439
|
}
|
|
1265
1440
|
const nodeClasses = packageFn?.nodes ?? [];
|
|
1441
|
+
const unsafeTypes = srcDir ? extractUnsafeTypes(srcDir) : void 0;
|
|
1266
1442
|
const helpByLang = /* @__PURE__ */ new Map();
|
|
1267
1443
|
for (const NodeClass of nodeClasses) {
|
|
1268
1444
|
const type = NodeClass.type;
|
|
@@ -1270,13 +1446,13 @@ function helpGenerator(options) {
|
|
|
1270
1446
|
const languages = discoverLanguages(labelsDir, type);
|
|
1271
1447
|
if (!languages.includes("en-US")) languages.push("en-US");
|
|
1272
1448
|
for (const lang of languages) {
|
|
1273
|
-
const manualMd =
|
|
1274
|
-
const manualHtml =
|
|
1275
|
-
if (
|
|
1276
|
-
const labelPath =
|
|
1449
|
+
const manualMd = path5.join(docsDir, type, `${lang}.md`);
|
|
1450
|
+
const manualHtml = path5.join(docsDir, type, `${lang}.html`);
|
|
1451
|
+
if (fs5.existsSync(manualMd) || fs5.existsSync(manualHtml)) continue;
|
|
1452
|
+
const labelPath = path5.join(labelsDir, type, `${lang}.json`);
|
|
1277
1453
|
const labels = loadNodeLabels(labelPath);
|
|
1278
1454
|
const t = getHelpTranslations(lang);
|
|
1279
|
-
const content = generateHelpDoc(NodeClass, labels, t);
|
|
1455
|
+
const content = generateHelpDoc(NodeClass, labels, t, unsafeTypes);
|
|
1280
1456
|
if (!content) continue;
|
|
1281
1457
|
if (!helpByLang.has(lang)) helpByLang.set(lang, []);
|
|
1282
1458
|
helpByLang.get(lang).push(
|
|
@@ -1287,11 +1463,11 @@ ${content}
|
|
|
1287
1463
|
}
|
|
1288
1464
|
}
|
|
1289
1465
|
for (const [lang, scripts] of helpByLang) {
|
|
1290
|
-
const langDir =
|
|
1291
|
-
|
|
1292
|
-
const indexPath =
|
|
1293
|
-
const existing =
|
|
1294
|
-
|
|
1466
|
+
const langDir = path5.join(localesOutDir, lang);
|
|
1467
|
+
fs5.mkdirSync(langDir, { recursive: true });
|
|
1468
|
+
const indexPath = path5.join(langDir, "index.html");
|
|
1469
|
+
const existing = fs5.existsSync(indexPath) ? fs5.readFileSync(indexPath, "utf-8") : "";
|
|
1470
|
+
fs5.writeFileSync(
|
|
1295
1471
|
indexPath,
|
|
1296
1472
|
existing + (existing ? "\n" : "") + scripts.join("\n"),
|
|
1297
1473
|
"utf-8"
|
|
@@ -1303,8 +1479,8 @@ ${content}
|
|
|
1303
1479
|
|
|
1304
1480
|
// src/vite/client/plugins/html-generator.ts
|
|
1305
1481
|
import mime from "mime-types";
|
|
1306
|
-
import
|
|
1307
|
-
import
|
|
1482
|
+
import fs6 from "fs";
|
|
1483
|
+
import path6 from "path";
|
|
1308
1484
|
function htmlGenerator(options) {
|
|
1309
1485
|
const { packageName, licensePath } = options;
|
|
1310
1486
|
return {
|
|
@@ -1314,7 +1490,7 @@ function htmlGenerator(options) {
|
|
|
1314
1490
|
generateBundle(_, bundle) {
|
|
1315
1491
|
const resourcesTags = Object.keys(bundle).map((fileName) => {
|
|
1316
1492
|
const asset = bundle[fileName];
|
|
1317
|
-
const srcPath =
|
|
1493
|
+
const srcPath = path6.join(
|
|
1318
1494
|
"resources",
|
|
1319
1495
|
packageName,
|
|
1320
1496
|
fileName.replace(/^resources\/?/, "")
|
|
@@ -1342,8 +1518,8 @@ function htmlGenerator(options) {
|
|
|
1342
1518
|
return null;
|
|
1343
1519
|
}
|
|
1344
1520
|
}).filter(Boolean).join("\n");
|
|
1345
|
-
const licenseBanner = licensePath &&
|
|
1346
|
-
${
|
|
1521
|
+
const licenseBanner = licensePath && fs6.existsSync(licensePath) ? `<!--
|
|
1522
|
+
${fs6.readFileSync(licensePath, "utf-8")}
|
|
1347
1523
|
-->` : "";
|
|
1348
1524
|
this.emitFile({
|
|
1349
1525
|
type: "asset",
|
|
@@ -1356,8 +1532,8 @@ ${resourcesTags}`
|
|
|
1356
1532
|
}
|
|
1357
1533
|
|
|
1358
1534
|
// src/vite/client/plugins/locales-generator.ts
|
|
1359
|
-
import
|
|
1360
|
-
import
|
|
1535
|
+
import fs7 from "fs";
|
|
1536
|
+
import path7 from "path";
|
|
1361
1537
|
import { merge } from "es-toolkit";
|
|
1362
1538
|
function localesGenerator(options) {
|
|
1363
1539
|
const { outDir, docsDir, labelsDir } = options;
|
|
@@ -1740,17 +1916,17 @@ Supported: ${languages.join(", ")}`
|
|
|
1740
1916
|
}
|
|
1741
1917
|
function forEachFile(baseDir, fileExtensions, processFile) {
|
|
1742
1918
|
const langMap = /* @__PURE__ */ new Map();
|
|
1743
|
-
if (!
|
|
1744
|
-
const nodeDirs =
|
|
1919
|
+
if (!fs7.existsSync(baseDir)) return langMap;
|
|
1920
|
+
const nodeDirs = fs7.readdirSync(baseDir, { withFileTypes: true }).filter((d) => d.isDirectory());
|
|
1745
1921
|
for (const nodeDir of nodeDirs) {
|
|
1746
1922
|
const nodeType = nodeDir.name;
|
|
1747
|
-
const nodePath =
|
|
1748
|
-
const files =
|
|
1923
|
+
const nodePath = path7.join(baseDir, nodeType);
|
|
1924
|
+
const files = fs7.readdirSync(nodePath);
|
|
1749
1925
|
for (const file of files) {
|
|
1750
|
-
const ext =
|
|
1926
|
+
const ext = path7.extname(file);
|
|
1751
1927
|
if (!fileExtensions.includes(ext)) continue;
|
|
1752
|
-
const lang =
|
|
1753
|
-
const filePath =
|
|
1928
|
+
const lang = path7.basename(file, ext);
|
|
1929
|
+
const filePath = path7.join(nodePath, file);
|
|
1754
1930
|
validateLanguage(lang, filePath);
|
|
1755
1931
|
const value = processFile({ ext, filePath, nodeType });
|
|
1756
1932
|
if (value == null) continue;
|
|
@@ -1768,10 +1944,10 @@ Supported: ${languages.join(", ")}`
|
|
|
1768
1944
|
}
|
|
1769
1945
|
function writeOutput(langMap, fileName, serialize) {
|
|
1770
1946
|
for (const [lang, data] of langMap.entries()) {
|
|
1771
|
-
const langOutDir =
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1947
|
+
const langOutDir = path7.join(outDir, lang);
|
|
1948
|
+
fs7.mkdirSync(langOutDir, { recursive: true });
|
|
1949
|
+
fs7.writeFileSync(
|
|
1950
|
+
path7.join(langOutDir, fileName),
|
|
1775
1951
|
serialize(data),
|
|
1776
1952
|
"utf-8"
|
|
1777
1953
|
);
|
|
@@ -1783,7 +1959,7 @@ Supported: ${languages.join(", ")}`
|
|
|
1783
1959
|
({ ext, filePath, nodeType }) => {
|
|
1784
1960
|
const type = ext === ".html" ? "text/html" : ext === ".md" ? "text/markdown" : null;
|
|
1785
1961
|
if (!type) return null;
|
|
1786
|
-
const content =
|
|
1962
|
+
const content = fs7.readFileSync(filePath, "utf-8");
|
|
1787
1963
|
return [
|
|
1788
1964
|
`<script type="${type}" data-help-name="${nodeType}">
|
|
1789
1965
|
${content}
|
|
@@ -1800,7 +1976,7 @@ ${content}
|
|
|
1800
1976
|
labelsDir,
|
|
1801
1977
|
[".json"],
|
|
1802
1978
|
({ filePath, nodeType }) => {
|
|
1803
|
-
const parsed = JSON.parse(
|
|
1979
|
+
const parsed = JSON.parse(fs7.readFileSync(filePath, "utf-8"));
|
|
1804
1980
|
if (parsed[nodeType] && typeof parsed[nodeType] === "object") {
|
|
1805
1981
|
console.warn(
|
|
1806
1982
|
`[locales] Warning: "${filePath}" uses nested format (root key "${nodeType}"). Label files should be flat \u2014 the node type is added automatically. See https://bonsaedev.github.io/nrg/guide/building-and-running`
|
|
@@ -1850,8 +2026,8 @@ function minifier() {
|
|
|
1850
2026
|
// src/vite/client/plugins/node-definitions-inliner.ts
|
|
1851
2027
|
import { createRequire as createRequire2 } from "module";
|
|
1852
2028
|
import { pathToFileURL as pathToFileURL2 } from "url";
|
|
1853
|
-
import
|
|
1854
|
-
import
|
|
2029
|
+
import path8 from "path";
|
|
2030
|
+
import fs8 from "fs";
|
|
1855
2031
|
import mime2 from "mime-types";
|
|
1856
2032
|
var VIRTUAL_ID = "virtual:nrg/node-definitions";
|
|
1857
2033
|
var RESOLVED_ID = "\0" + VIRTUAL_ID;
|
|
@@ -1882,17 +2058,68 @@ function getCredentialsFromSchema(schema) {
|
|
|
1882
2058
|
return result;
|
|
1883
2059
|
}
|
|
1884
2060
|
function resolveIcon(iconsDir, type) {
|
|
1885
|
-
if (!
|
|
1886
|
-
return
|
|
1887
|
-
if (
|
|
2061
|
+
if (!fs8.existsSync(iconsDir)) return void 0;
|
|
2062
|
+
return fs8.readdirSync(iconsDir).find((f) => {
|
|
2063
|
+
if (path8.basename(f, path8.extname(f)) !== type) return false;
|
|
1888
2064
|
const mimeType = mime2.lookup(f);
|
|
1889
2065
|
return mimeType !== false && mimeType.startsWith("image/");
|
|
1890
2066
|
});
|
|
1891
2067
|
}
|
|
1892
|
-
|
|
2068
|
+
var RUNTIME_SPECIFIER = "@bonsae/nrg-runtime/server";
|
|
2069
|
+
var RUNTIME_SPECIFIER_RE = /(['"])@bonsae\/nrg-runtime\/server\1/g;
|
|
2070
|
+
function resolveRuntimeServer(serverOutDir) {
|
|
2071
|
+
const roots = [path8.join(serverOutDir, "index.js"), import.meta.url];
|
|
2072
|
+
for (const root of roots) {
|
|
2073
|
+
try {
|
|
2074
|
+
return createRequire2(root).resolve(RUNTIME_SPECIFIER);
|
|
2075
|
+
} catch {
|
|
2076
|
+
}
|
|
2077
|
+
}
|
|
2078
|
+
return void 0;
|
|
2079
|
+
}
|
|
2080
|
+
async function loadServerPackageExport(serverOutDir) {
|
|
2081
|
+
const esmEntryPath = path8.resolve(serverOutDir, "index.mjs");
|
|
2082
|
+
const cjsEntryPath = path8.resolve(serverOutDir, "index.js");
|
|
2083
|
+
const isEsm = fs8.existsSync(esmEntryPath);
|
|
2084
|
+
const entryPath = isEsm ? esmEntryPath : fs8.existsSync(cjsEntryPath) ? cjsEntryPath : void 0;
|
|
2085
|
+
if (!entryPath) return void 0;
|
|
2086
|
+
const code = fs8.readFileSync(entryPath, "utf-8");
|
|
2087
|
+
const runtimeServer = code.includes(RUNTIME_SPECIFIER) ? resolveRuntimeServer(serverOutDir) : void 0;
|
|
2088
|
+
let tempPath;
|
|
2089
|
+
let loadPath = entryPath;
|
|
2090
|
+
if (runtimeServer) {
|
|
2091
|
+
const replacement = isEsm ? JSON.stringify(pathToFileURL2(runtimeServer).href) : JSON.stringify(runtimeServer);
|
|
2092
|
+
const rewritten = code.replace(RUNTIME_SPECIFIER_RE, replacement);
|
|
2093
|
+
tempPath = path8.resolve(
|
|
2094
|
+
serverOutDir,
|
|
2095
|
+
`.nrg-server-${Date.now()}${isEsm ? ".mjs" : ".cjs"}`
|
|
2096
|
+
);
|
|
2097
|
+
fs8.writeFileSync(tempPath, rewritten);
|
|
2098
|
+
loadPath = tempPath;
|
|
2099
|
+
}
|
|
2100
|
+
const require2 = createRequire2(import.meta.url);
|
|
2101
|
+
try {
|
|
2102
|
+
if (isEsm) {
|
|
2103
|
+
const fileUrl = pathToFileURL2(loadPath).href + `?t=${Date.now()}`;
|
|
2104
|
+
const mod = await import(fileUrl);
|
|
2105
|
+
return mod?.default ?? mod;
|
|
2106
|
+
}
|
|
2107
|
+
delete require2.cache[loadPath];
|
|
2108
|
+
const rawMod = require2(loadPath);
|
|
2109
|
+
return rawMod?.default ?? rawMod;
|
|
2110
|
+
} finally {
|
|
2111
|
+
if (tempPath) {
|
|
2112
|
+
try {
|
|
2113
|
+
delete require2.cache[tempPath];
|
|
2114
|
+
fs8.rmSync(tempPath);
|
|
2115
|
+
} catch {
|
|
2116
|
+
}
|
|
2117
|
+
}
|
|
2118
|
+
}
|
|
2119
|
+
}
|
|
2120
|
+
function nodeDefinitionsInliner(serverOutDir, entryPath, iconsDir, componentsDir, nodesDir, hasUserEntry = true, cacheDir = path8.resolve("node_modules", ".nrg", "client")) {
|
|
1893
2121
|
let _nodeTypes = [];
|
|
1894
2122
|
let _definitions = {};
|
|
1895
|
-
const cacheDir = path7.resolve("node_modules", ".nrg", "client");
|
|
1896
2123
|
return {
|
|
1897
2124
|
name: "vite-plugin-node-red:client:node-definitions-inliner",
|
|
1898
2125
|
enforce: "pre",
|
|
@@ -1901,19 +2128,7 @@ function nodeDefinitionsInliner(serverOutDir, entryPath, iconsDir, componentsDir
|
|
|
1901
2128
|
async buildStart() {
|
|
1902
2129
|
_nodeTypes = [];
|
|
1903
2130
|
_definitions = {};
|
|
1904
|
-
const
|
|
1905
|
-
const cjsEntryPath = path7.resolve(serverOutDir, "index.js");
|
|
1906
|
-
let packageFn;
|
|
1907
|
-
if (fs7.existsSync(esmEntryPath)) {
|
|
1908
|
-
const fileUrl = pathToFileURL2(esmEntryPath).href + `?t=${Date.now()}`;
|
|
1909
|
-
const mod = await import(fileUrl);
|
|
1910
|
-
packageFn = mod?.default ?? mod;
|
|
1911
|
-
} else if (fs7.existsSync(cjsEntryPath)) {
|
|
1912
|
-
const require2 = createRequire2(import.meta.url);
|
|
1913
|
-
delete require2.cache[cjsEntryPath];
|
|
1914
|
-
const rawMod = require2(cjsEntryPath);
|
|
1915
|
-
packageFn = rawMod?.default ?? rawMod;
|
|
1916
|
-
}
|
|
2131
|
+
const packageFn = await loadServerPackageExport(serverOutDir);
|
|
1917
2132
|
const nodeClasses = packageFn?.nodes ?? [];
|
|
1918
2133
|
for (const NodeClass of nodeClasses) {
|
|
1919
2134
|
const type = NodeClass.type;
|
|
@@ -1944,19 +2159,22 @@ function nodeDefinitionsInliner(serverOutDir, entryPath, iconsDir, componentsDir
|
|
|
1944
2159
|
icon: iconsDir ? resolveIcon(iconsDir, type) : void 0,
|
|
1945
2160
|
inputs: NodeClass.inputs,
|
|
1946
2161
|
outputs: NodeClass.outputs,
|
|
2162
|
+
// Resolved server-side (Kind symbol intact) so the editor labels
|
|
2163
|
+
// named output ports without guessing from the serialized schema.
|
|
2164
|
+
outputPortNames: NodeClass.outputPortNames ?? void 0,
|
|
1947
2165
|
inputSchema,
|
|
1948
2166
|
outputsSchema
|
|
1949
2167
|
};
|
|
1950
2168
|
}
|
|
1951
2169
|
if (!hasUserEntry) {
|
|
1952
|
-
const nodesCache =
|
|
1953
|
-
if (
|
|
1954
|
-
|
|
2170
|
+
const nodesCache = path8.resolve(cacheDir, "nodes");
|
|
2171
|
+
if (fs8.existsSync(nodesCache)) {
|
|
2172
|
+
fs8.rmSync(nodesCache, { recursive: true });
|
|
1955
2173
|
}
|
|
1956
|
-
|
|
2174
|
+
fs8.mkdirSync(nodesCache, { recursive: true });
|
|
1957
2175
|
for (const type of _nodeTypes) {
|
|
1958
|
-
const userTsPath = nodesDir ?
|
|
1959
|
-
if (userTsPath &&
|
|
2176
|
+
const userTsPath = nodesDir ? path8.resolve(nodesDir, `${type}.ts`) : null;
|
|
2177
|
+
if (userTsPath && fs8.existsSync(userTsPath)) continue;
|
|
1960
2178
|
const content = [
|
|
1961
2179
|
`// auto-generated by nrg`,
|
|
1962
2180
|
`import { defineNode } from "@bonsae/nrg/client";`,
|
|
@@ -1966,13 +2184,13 @@ function nodeDefinitionsInliner(serverOutDir, entryPath, iconsDir, componentsDir
|
|
|
1966
2184
|
`});`,
|
|
1967
2185
|
``
|
|
1968
2186
|
].join("\n");
|
|
1969
|
-
|
|
2187
|
+
fs8.writeFileSync(path8.resolve(nodesCache, `${type}.ts`), content);
|
|
1970
2188
|
}
|
|
1971
2189
|
const entryContent = generateEntryCode("");
|
|
1972
|
-
|
|
2190
|
+
fs8.mkdirSync(path8.dirname(path8.resolve(cacheDir, "index.ts")), {
|
|
1973
2191
|
recursive: true
|
|
1974
2192
|
});
|
|
1975
|
-
|
|
2193
|
+
fs8.writeFileSync(path8.resolve(cacheDir, "index.ts"), entryContent);
|
|
1976
2194
|
}
|
|
1977
2195
|
},
|
|
1978
2196
|
resolveId(id) {
|
|
@@ -1995,12 +2213,12 @@ function nodeDefinitionsInliner(serverOutDir, entryPath, iconsDir, componentsDir
|
|
|
1995
2213
|
const nrgImports = /* @__PURE__ */ new Set(["__setSchemas"]);
|
|
1996
2214
|
const lines = [`import __nrgSchemas from "${VIRTUAL_ID}";`];
|
|
1997
2215
|
const postLines = [`__setSchemas(__nrgSchemas);`];
|
|
1998
|
-
if (componentsDir &&
|
|
2216
|
+
if (componentsDir && fs8.existsSync(componentsDir)) {
|
|
1999
2217
|
const formImports = [];
|
|
2000
2218
|
const formEntries = [];
|
|
2001
2219
|
for (const type of _nodeTypes) {
|
|
2002
|
-
const componentPath =
|
|
2003
|
-
if (
|
|
2220
|
+
const componentPath = path8.resolve(componentsDir, `${type}.vue`);
|
|
2221
|
+
if (fs8.existsSync(componentPath)) {
|
|
2004
2222
|
const varName = `__nrgForm_${type.replace(/-/g, "_")}`;
|
|
2005
2223
|
formImports.push(
|
|
2006
2224
|
`import ${varName} from ${JSON.stringify(componentPath)};`
|
|
@@ -2015,12 +2233,12 @@ function nodeDefinitionsInliner(serverOutDir, entryPath, iconsDir, componentsDir
|
|
|
2015
2233
|
}
|
|
2016
2234
|
}
|
|
2017
2235
|
if (!hasUserEntry) {
|
|
2018
|
-
const nodesCache =
|
|
2236
|
+
const nodesCache = path8.resolve(cacheDir, "nodes");
|
|
2019
2237
|
const defVarNames = [];
|
|
2020
2238
|
for (const type of _nodeTypes) {
|
|
2021
2239
|
const varName = `__nrgNodeDef_${type.replace(/-/g, "_")}`;
|
|
2022
|
-
const userTsPath = nodesDir ?
|
|
2023
|
-
const tsPath = userTsPath &&
|
|
2240
|
+
const userTsPath = nodesDir ? path8.resolve(nodesDir, `${type}.ts`) : null;
|
|
2241
|
+
const tsPath = userTsPath && fs8.existsSync(userTsPath) ? userTsPath : path8.resolve(nodesCache, `${type}.ts`);
|
|
2024
2242
|
lines.push(`import ${varName} from ${JSON.stringify(tsPath)};`);
|
|
2025
2243
|
defVarNames.push(varName);
|
|
2026
2244
|
}
|
|
@@ -2038,8 +2256,8 @@ function nodeDefinitionsInliner(serverOutDir, entryPath, iconsDir, componentsDir
|
|
|
2038
2256
|
}
|
|
2039
2257
|
|
|
2040
2258
|
// src/vite/client/plugins/static-copy.ts
|
|
2041
|
-
import
|
|
2042
|
-
import
|
|
2259
|
+
import fs9 from "fs";
|
|
2260
|
+
import path9 from "path";
|
|
2043
2261
|
function staticCopy(options) {
|
|
2044
2262
|
const { targets } = options;
|
|
2045
2263
|
return {
|
|
@@ -2048,23 +2266,23 @@ function staticCopy(options) {
|
|
|
2048
2266
|
enforce: "post",
|
|
2049
2267
|
closeBundle() {
|
|
2050
2268
|
for (const { src, dest } of targets) {
|
|
2051
|
-
if (!
|
|
2052
|
-
|
|
2053
|
-
const stat =
|
|
2269
|
+
if (!fs9.existsSync(src)) continue;
|
|
2270
|
+
fs9.mkdirSync(dest, { recursive: true });
|
|
2271
|
+
const stat = fs9.statSync(src);
|
|
2054
2272
|
if (stat.isDirectory()) {
|
|
2055
|
-
const files =
|
|
2273
|
+
const files = fs9.readdirSync(src);
|
|
2056
2274
|
for (const file of files) {
|
|
2057
|
-
const srcFile =
|
|
2058
|
-
const destFile =
|
|
2059
|
-
const fileStat =
|
|
2275
|
+
const srcFile = path9.join(src, file);
|
|
2276
|
+
const destFile = path9.join(dest, file);
|
|
2277
|
+
const fileStat = fs9.statSync(srcFile);
|
|
2060
2278
|
if (fileStat.isDirectory()) {
|
|
2061
|
-
|
|
2279
|
+
fs9.cpSync(srcFile, destFile, { recursive: true });
|
|
2062
2280
|
} else {
|
|
2063
|
-
|
|
2281
|
+
fs9.copyFileSync(srcFile, destFile);
|
|
2064
2282
|
}
|
|
2065
2283
|
}
|
|
2066
2284
|
} else {
|
|
2067
|
-
|
|
2285
|
+
fs9.copyFileSync(src, dest);
|
|
2068
2286
|
}
|
|
2069
2287
|
}
|
|
2070
2288
|
}
|
|
@@ -2072,6 +2290,11 @@ function staticCopy(options) {
|
|
|
2072
2290
|
}
|
|
2073
2291
|
|
|
2074
2292
|
// src/vite/client/build.ts
|
|
2293
|
+
function cacheKeyFor(outDir) {
|
|
2294
|
+
const abs = path10.resolve(outDir);
|
|
2295
|
+
const hash = crypto.createHash("sha1").update(abs).digest("hex").slice(0, 8);
|
|
2296
|
+
return `${path10.basename(abs) || "client"}-${hash}`;
|
|
2297
|
+
}
|
|
2075
2298
|
async function build2(clientBuildOptions, buildContext) {
|
|
2076
2299
|
const {
|
|
2077
2300
|
srcDir = "./client",
|
|
@@ -2085,74 +2308,81 @@ async function build2(clientBuildOptions, buildContext) {
|
|
|
2085
2308
|
globals = {},
|
|
2086
2309
|
manualChunks
|
|
2087
2310
|
} = clientBuildOptions;
|
|
2088
|
-
const
|
|
2311
|
+
const cacheDir = path10.resolve(
|
|
2312
|
+
"node_modules",
|
|
2313
|
+
".nrg",
|
|
2314
|
+
"client",
|
|
2315
|
+
cacheKeyFor(buildContext.outDir)
|
|
2316
|
+
);
|
|
2317
|
+
const physicalEntryPath = path10.resolve(srcDir, entry);
|
|
2089
2318
|
let entryPath;
|
|
2090
2319
|
let generatedEntry = false;
|
|
2091
|
-
if (
|
|
2320
|
+
if (fs10.existsSync(physicalEntryPath)) {
|
|
2092
2321
|
entryPath = physicalEntryPath;
|
|
2093
2322
|
} else {
|
|
2094
|
-
const
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
fs9.mkdirSync(cacheDir, { recursive: true });
|
|
2323
|
+
const cachedEntryPath = path10.resolve(cacheDir, entry);
|
|
2324
|
+
if (!fs10.existsSync(cacheDir)) {
|
|
2325
|
+
fs10.mkdirSync(cacheDir, { recursive: true });
|
|
2098
2326
|
}
|
|
2099
|
-
|
|
2327
|
+
fs10.writeFileSync(cachedEntryPath, "// auto-generated entry\n");
|
|
2100
2328
|
entryPath = cachedEntryPath;
|
|
2101
2329
|
generatedEntry = true;
|
|
2102
2330
|
}
|
|
2103
|
-
const iconsDir =
|
|
2104
|
-
staticDirs.icons ??
|
|
2331
|
+
const iconsDir = path10.resolve(
|
|
2332
|
+
staticDirs.icons ?? path10.join(path10.dirname(path10.resolve(srcDir)), "icons")
|
|
2105
2333
|
);
|
|
2106
2334
|
const plugins = [
|
|
2107
2335
|
vue(),
|
|
2108
2336
|
nodeDefinitionsInliner(
|
|
2109
2337
|
buildContext.outDir,
|
|
2110
2338
|
entryPath,
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
!generatedEntry
|
|
2339
|
+
fs10.existsSync(iconsDir) ? iconsDir : void 0,
|
|
2340
|
+
path10.resolve(srcDir, "components"),
|
|
2341
|
+
path10.resolve(srcDir, "nodes"),
|
|
2342
|
+
!generatedEntry,
|
|
2343
|
+
cacheDir
|
|
2115
2344
|
)
|
|
2116
2345
|
];
|
|
2117
2346
|
plugins.push(
|
|
2118
2347
|
htmlGenerator({
|
|
2119
2348
|
packageName: buildContext.packageName,
|
|
2120
|
-
licensePath: licensePath ?
|
|
2349
|
+
licensePath: licensePath ? path10.resolve(licensePath) : void 0
|
|
2121
2350
|
})
|
|
2122
2351
|
);
|
|
2123
2352
|
if (locales) {
|
|
2124
2353
|
const { docsDir = "./locales/docs", labelsDir = "./locales/labels" } = locales;
|
|
2125
|
-
const localesOutDir =
|
|
2354
|
+
const localesOutDir = path10.join(buildContext.outDir, "locales");
|
|
2126
2355
|
plugins.push(
|
|
2127
2356
|
localesGenerator({
|
|
2128
2357
|
outDir: localesOutDir,
|
|
2129
|
-
docsDir:
|
|
2130
|
-
labelsDir:
|
|
2358
|
+
docsDir: path10.resolve(docsDir),
|
|
2359
|
+
labelsDir: path10.resolve(labelsDir)
|
|
2131
2360
|
})
|
|
2132
2361
|
);
|
|
2133
2362
|
plugins.push(
|
|
2134
2363
|
helpGenerator({
|
|
2135
2364
|
outDir: buildContext.outDir,
|
|
2136
2365
|
localesOutDir,
|
|
2137
|
-
docsDir:
|
|
2138
|
-
labelsDir:
|
|
2366
|
+
docsDir: path10.resolve(docsDir),
|
|
2367
|
+
labelsDir: path10.resolve(labelsDir),
|
|
2368
|
+
srcDir: buildContext.serverSrcDir
|
|
2139
2369
|
})
|
|
2140
2370
|
);
|
|
2141
2371
|
}
|
|
2142
2372
|
const copyTargets = [];
|
|
2143
|
-
const publicDir =
|
|
2144
|
-
staticDirs.public ??
|
|
2373
|
+
const publicDir = path10.resolve(
|
|
2374
|
+
staticDirs.public ?? path10.join(srcDir, "public")
|
|
2145
2375
|
);
|
|
2146
|
-
if (
|
|
2376
|
+
if (fs10.existsSync(publicDir)) {
|
|
2147
2377
|
copyTargets.push({
|
|
2148
2378
|
src: publicDir,
|
|
2149
|
-
dest:
|
|
2379
|
+
dest: path10.join(buildContext.outDir, "resources")
|
|
2150
2380
|
});
|
|
2151
2381
|
}
|
|
2152
|
-
if (
|
|
2382
|
+
if (fs10.existsSync(iconsDir)) {
|
|
2153
2383
|
copyTargets.push({
|
|
2154
2384
|
src: iconsDir,
|
|
2155
|
-
dest:
|
|
2385
|
+
dest: path10.join(buildContext.outDir, "icons")
|
|
2156
2386
|
});
|
|
2157
2387
|
}
|
|
2158
2388
|
if (copyTargets.length > 0) {
|
|
@@ -2180,10 +2410,10 @@ async function build2(clientBuildOptions, buildContext) {
|
|
|
2180
2410
|
configFile: false,
|
|
2181
2411
|
logLevel: "warn",
|
|
2182
2412
|
base: `/resources/${buildContext.packageName}`,
|
|
2183
|
-
publicDir:
|
|
2413
|
+
publicDir: path10.resolve(srcDir, "public"),
|
|
2184
2414
|
resolve: {
|
|
2185
2415
|
alias: {
|
|
2186
|
-
"@":
|
|
2416
|
+
"@": path10.resolve(srcDir)
|
|
2187
2417
|
}
|
|
2188
2418
|
},
|
|
2189
2419
|
plugins,
|
|
@@ -2237,15 +2467,15 @@ async function build2(clientBuildOptions, buildContext) {
|
|
|
2237
2467
|
throw new BuildError("client", error);
|
|
2238
2468
|
} finally {
|
|
2239
2469
|
if (generatedEntry) {
|
|
2240
|
-
if (
|
|
2241
|
-
|
|
2470
|
+
if (fs10.existsSync(entryPath)) {
|
|
2471
|
+
fs10.unlinkSync(entryPath);
|
|
2242
2472
|
}
|
|
2243
2473
|
}
|
|
2244
2474
|
}
|
|
2245
2475
|
}
|
|
2246
2476
|
|
|
2247
2477
|
// src/vite/node-red-launcher/index.ts
|
|
2248
|
-
import
|
|
2478
|
+
import fs13 from "fs";
|
|
2249
2479
|
|
|
2250
2480
|
// src/vite/async-utils.ts
|
|
2251
2481
|
function withTimeout(promise, ms, fallback) {
|
|
@@ -2286,22 +2516,22 @@ async function retry(fn, options = {}) {
|
|
|
2286
2516
|
import { exec } from "child_process";
|
|
2287
2517
|
import { randomUUID } from "crypto";
|
|
2288
2518
|
import { createRequire as createRequire3 } from "module";
|
|
2289
|
-
import
|
|
2519
|
+
import fs11 from "fs";
|
|
2290
2520
|
import os from "os";
|
|
2291
|
-
import
|
|
2521
|
+
import path11 from "path";
|
|
2292
2522
|
function getNodeRedCommand(version) {
|
|
2293
2523
|
return version ? `node-red@${version}` : "node-red";
|
|
2294
2524
|
}
|
|
2295
2525
|
function resolveNodeRedFromLocalNodeModules() {
|
|
2296
2526
|
try {
|
|
2297
|
-
const require_ = createRequire3(
|
|
2527
|
+
const require_ = createRequire3(path11.join(process.cwd(), "package.json"));
|
|
2298
2528
|
const pkgJsonPath = require_.resolve("node-red/package.json");
|
|
2299
|
-
const pkgDir =
|
|
2300
|
-
const pkg = JSON.parse(
|
|
2529
|
+
const pkgDir = path11.dirname(pkgJsonPath);
|
|
2530
|
+
const pkg = JSON.parse(fs11.readFileSync(pkgJsonPath, "utf-8"));
|
|
2301
2531
|
const bin = typeof pkg.bin === "string" ? pkg.bin : pkg.bin?.["node-red"];
|
|
2302
2532
|
if (!bin) return null;
|
|
2303
|
-
const entry =
|
|
2304
|
-
return
|
|
2533
|
+
const entry = path11.resolve(pkgDir, bin);
|
|
2534
|
+
return fs11.existsSync(entry) ? entry : null;
|
|
2305
2535
|
} catch {
|
|
2306
2536
|
return null;
|
|
2307
2537
|
}
|
|
@@ -2326,11 +2556,11 @@ async function resolveNodeRed(options) {
|
|
|
2326
2556
|
logger2.info(
|
|
2327
2557
|
hasExplicitVersion ? `Using configured version (${version}), downloading via npx...` : `Not found locally, downloading via npx (this may take a while)...`
|
|
2328
2558
|
);
|
|
2329
|
-
const resolverScript =
|
|
2559
|
+
const resolverScript = path11.join(
|
|
2330
2560
|
os.tmpdir(),
|
|
2331
2561
|
`nrg-resolve-node-red-${process.pid}-${randomUUID()}.cjs`
|
|
2332
2562
|
);
|
|
2333
|
-
|
|
2563
|
+
fs11.writeFileSync(
|
|
2334
2564
|
resolverScript,
|
|
2335
2565
|
`const fs = require("fs");
|
|
2336
2566
|
const path = require("path");
|
|
@@ -2364,7 +2594,7 @@ for (const d of dirs) {
|
|
|
2364
2594
|
);
|
|
2365
2595
|
});
|
|
2366
2596
|
const entryPoint = stdout.trim();
|
|
2367
|
-
if (!entryPoint || !
|
|
2597
|
+
if (!entryPoint || !fs11.existsSync(entryPoint)) {
|
|
2368
2598
|
throw new NodeRedStartError(
|
|
2369
2599
|
new Error(
|
|
2370
2600
|
`Could not resolve node-red entry point: ${entryPoint || "(empty)"}`
|
|
@@ -2375,7 +2605,7 @@ for (const d of dirs) {
|
|
|
2375
2605
|
return entryPoint;
|
|
2376
2606
|
} finally {
|
|
2377
2607
|
try {
|
|
2378
|
-
|
|
2608
|
+
fs11.unlinkSync(resolverScript);
|
|
2379
2609
|
} catch {
|
|
2380
2610
|
}
|
|
2381
2611
|
}
|
|
@@ -2383,28 +2613,28 @@ for (const d of dirs) {
|
|
|
2383
2613
|
|
|
2384
2614
|
// src/vite/node-red-launcher/settings.ts
|
|
2385
2615
|
import { builtinModules as builtinModules2 } from "module";
|
|
2386
|
-
import
|
|
2616
|
+
import fs12 from "fs";
|
|
2387
2617
|
import os2 from "os";
|
|
2388
|
-
import
|
|
2618
|
+
import path12 from "path";
|
|
2389
2619
|
import { pathToFileURL as pathToFileURL3 } from "url";
|
|
2390
2620
|
import { build as esbuild } from "esbuild";
|
|
2391
2621
|
function findUserRuntimeSettingsFilepath(settingsFilepath, logger2) {
|
|
2392
2622
|
if (settingsFilepath) {
|
|
2393
|
-
const resolved2 =
|
|
2394
|
-
if (
|
|
2623
|
+
const resolved2 = path12.resolve(settingsFilepath);
|
|
2624
|
+
if (fs12.existsSync(resolved2)) {
|
|
2395
2625
|
return resolved2;
|
|
2396
2626
|
}
|
|
2397
2627
|
logger2.warn(`Settings file not found: ${settingsFilepath}`);
|
|
2398
2628
|
return null;
|
|
2399
2629
|
}
|
|
2400
|
-
const resolved =
|
|
2401
|
-
if (
|
|
2630
|
+
const resolved = path12.resolve("node-red.settings.ts");
|
|
2631
|
+
if (fs12.existsSync(resolved)) {
|
|
2402
2632
|
return resolved;
|
|
2403
2633
|
}
|
|
2404
2634
|
return null;
|
|
2405
2635
|
}
|
|
2406
2636
|
async function compileRuntimeSettingsFile(runtimeSettingsFilepath, port) {
|
|
2407
|
-
const compiledRuntimeSettingsFilepath =
|
|
2637
|
+
const compiledRuntimeSettingsFilepath = path12.join(
|
|
2408
2638
|
os2.tmpdir(),
|
|
2409
2639
|
`node-red.settings.${process.pid}-${port}.cjs`
|
|
2410
2640
|
);
|
|
@@ -2412,8 +2642,8 @@ async function compileRuntimeSettingsFile(runtimeSettingsFilepath, port) {
|
|
|
2412
2642
|
...builtinModules2,
|
|
2413
2643
|
...builtinModules2.map((m) => `node:${m}`)
|
|
2414
2644
|
];
|
|
2415
|
-
const settingsDir =
|
|
2416
|
-
const settingsFile = runtimeSettingsFilepath.split(
|
|
2645
|
+
const settingsDir = path12.dirname(runtimeSettingsFilepath).split(path12.sep).join("/");
|
|
2646
|
+
const settingsFile = runtimeSettingsFilepath.split(path12.sep).join("/");
|
|
2417
2647
|
await esbuild({
|
|
2418
2648
|
entryPoints: [runtimeSettingsFilepath],
|
|
2419
2649
|
outfile: compiledRuntimeSettingsFilepath,
|
|
@@ -2445,14 +2675,14 @@ async function generateRuntimeSettings(options) {
|
|
|
2445
2675
|
);
|
|
2446
2676
|
tempFiles.push(compiledRuntimeSettingsFilepath);
|
|
2447
2677
|
}
|
|
2448
|
-
const normalizedOutDir =
|
|
2449
|
-
const cwd = process.cwd().split(
|
|
2450
|
-
const userDir =
|
|
2678
|
+
const normalizedOutDir = path12.resolve(outDir).split(path12.sep).join("/");
|
|
2679
|
+
const cwd = process.cwd().split(path12.sep).join("/");
|
|
2680
|
+
const userDir = path12.resolve(cwd, ".node-red").split(path12.sep).join("/");
|
|
2451
2681
|
const userDirLiteral = JSON.stringify(userDir);
|
|
2452
2682
|
const outDirLiteral = JSON.stringify(normalizedOutDir);
|
|
2453
2683
|
const finalRuntimeSettingsFile = compiledRuntimeSettingsFilepath ? `
|
|
2454
2684
|
const compiledRuntimeSettings = require(${JSON.stringify(
|
|
2455
|
-
compiledRuntimeSettingsFilepath.split(
|
|
2685
|
+
compiledRuntimeSettingsFilepath.split(path12.sep).join("/")
|
|
2456
2686
|
)});
|
|
2457
2687
|
const settings = compiledRuntimeSettings.default || compiledRuntimeSettings;
|
|
2458
2688
|
settings.uiPort = ${port};
|
|
@@ -2484,11 +2714,11 @@ const settings = {
|
|
|
2484
2714
|
};
|
|
2485
2715
|
module.exports = settings;
|
|
2486
2716
|
`;
|
|
2487
|
-
const finalRuntimeSettingsFilepath =
|
|
2717
|
+
const finalRuntimeSettingsFilepath = path12.join(
|
|
2488
2718
|
os2.tmpdir(),
|
|
2489
2719
|
`node-red-settings-final-${process.pid}-${port}.cjs`
|
|
2490
2720
|
);
|
|
2491
|
-
|
|
2721
|
+
fs12.writeFileSync(finalRuntimeSettingsFilepath, finalRuntimeSettingsFile);
|
|
2492
2722
|
tempFiles.push(finalRuntimeSettingsFilepath);
|
|
2493
2723
|
return { filepath: finalRuntimeSettingsFilepath, tempFiles };
|
|
2494
2724
|
}
|
|
@@ -2713,7 +2943,7 @@ var NodeRedLauncher = class {
|
|
|
2713
2943
|
preferredPort: this.preferredPort,
|
|
2714
2944
|
logger: this.logger
|
|
2715
2945
|
});
|
|
2716
|
-
if (!this.nodeRedEntryPoint || !
|
|
2946
|
+
if (!this.nodeRedEntryPoint || !fs13.existsSync(this.nodeRedEntryPoint)) {
|
|
2717
2947
|
this.nodeRedEntryPoint = await resolveNodeRed({
|
|
2718
2948
|
version: this.options.runtime?.version,
|
|
2719
2949
|
logger: this.logger
|
|
@@ -2787,7 +3017,7 @@ var NodeRedLauncher = class {
|
|
|
2787
3017
|
cleanup() {
|
|
2788
3018
|
for (const file of this.tempFiles) {
|
|
2789
3019
|
try {
|
|
2790
|
-
|
|
3020
|
+
fs13.unlinkSync(file);
|
|
2791
3021
|
} catch {
|
|
2792
3022
|
}
|
|
2793
3023
|
}
|
|
@@ -2807,10 +3037,10 @@ var NodeRedTestEnvironment = class {
|
|
|
2807
3037
|
options;
|
|
2808
3038
|
constructor(options) {
|
|
2809
3039
|
this.options = options;
|
|
2810
|
-
this.projectDir =
|
|
2811
|
-
this.outDir =
|
|
2812
|
-
this.nodeRedDir =
|
|
2813
|
-
this.installedPkgDir =
|
|
3040
|
+
this.projectDir = path13.resolve(options.projectDir ?? process.cwd());
|
|
3041
|
+
this.outDir = path13.join(this.projectDir, "dist-e2e");
|
|
3042
|
+
this.nodeRedDir = path13.join(this.projectDir, ".node-red");
|
|
3043
|
+
this.installedPkgDir = path13.join(
|
|
2814
3044
|
this.nodeRedDir,
|
|
2815
3045
|
"node_modules",
|
|
2816
3046
|
options.packageName
|
|
@@ -2822,15 +3052,15 @@ var NodeRedTestEnvironment = class {
|
|
|
2822
3052
|
async setup() {
|
|
2823
3053
|
this.originalCwd = process.cwd();
|
|
2824
3054
|
process.chdir(this.projectDir);
|
|
2825
|
-
if (
|
|
2826
|
-
|
|
3055
|
+
if (fs14.existsSync(this.outDir)) fs14.rmSync(this.outDir, { recursive: true });
|
|
3056
|
+
fs14.mkdirSync(this.outDir, { recursive: true });
|
|
2827
3057
|
const buildContext = {
|
|
2828
3058
|
outDir: this.outDir,
|
|
2829
3059
|
packageName: this.options.packageName,
|
|
2830
3060
|
isDev: false
|
|
2831
3061
|
};
|
|
2832
3062
|
const serverOpts = {
|
|
2833
|
-
srcDir:
|
|
3063
|
+
srcDir: path13.join(this.projectDir, "src/server"),
|
|
2834
3064
|
entry: "index.ts",
|
|
2835
3065
|
format: "esm",
|
|
2836
3066
|
bundled: [],
|
|
@@ -2840,7 +3070,7 @@ var NodeRedTestEnvironment = class {
|
|
|
2840
3070
|
};
|
|
2841
3071
|
await build(serverOpts, buildContext);
|
|
2842
3072
|
const clientOpts = {
|
|
2843
|
-
srcDir:
|
|
3073
|
+
srcDir: path13.join(this.projectDir, "src/client"),
|
|
2844
3074
|
entry: "index.ts",
|
|
2845
3075
|
name: this.options.clientName ?? "NodeRedNodes",
|
|
2846
3076
|
format: "es",
|
|
@@ -2849,18 +3079,18 @@ var NodeRedTestEnvironment = class {
|
|
|
2849
3079
|
...this.options.client
|
|
2850
3080
|
};
|
|
2851
3081
|
await build2(clientOpts, buildContext);
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
3082
|
+
fs14.mkdirSync(this.installedPkgDir, { recursive: true });
|
|
3083
|
+
fs14.cpSync(this.outDir, this.installedPkgDir, { recursive: true });
|
|
3084
|
+
fs14.mkdirSync(this.nodeRedDir, { recursive: true });
|
|
3085
|
+
fs14.writeFileSync(
|
|
3086
|
+
path13.join(this.nodeRedDir, ".config.runtime.json"),
|
|
2857
3087
|
JSON.stringify({ telemetryEnabled: false })
|
|
2858
3088
|
);
|
|
2859
3089
|
const launcherOpts = {
|
|
2860
3090
|
runtime: { port: this.options.port ?? 1881 }
|
|
2861
3091
|
};
|
|
2862
3092
|
if (this.options.settingsFile) {
|
|
2863
|
-
launcherOpts.runtime.settingsFilepath =
|
|
3093
|
+
launcherOpts.runtime.settingsFilepath = path13.resolve(
|
|
2864
3094
|
this.projectDir,
|
|
2865
3095
|
this.options.settingsFile
|
|
2866
3096
|
);
|
|
@@ -2895,25 +3125,19 @@ var NodeRedTestEnvironment = class {
|
|
|
2895
3125
|
this.launcher.cleanup();
|
|
2896
3126
|
this.launcher = null;
|
|
2897
3127
|
}
|
|
2898
|
-
if (
|
|
2899
|
-
if (
|
|
2900
|
-
|
|
3128
|
+
if (fs14.existsSync(this.outDir)) fs14.rmSync(this.outDir, { recursive: true });
|
|
3129
|
+
if (fs14.existsSync(this.nodeRedDir)) {
|
|
3130
|
+
fs14.rmSync(this.nodeRedDir, { recursive: true });
|
|
2901
3131
|
}
|
|
2902
3132
|
this.port = null;
|
|
2903
3133
|
}
|
|
2904
3134
|
};
|
|
2905
3135
|
|
|
2906
3136
|
// src/test/client/e2e/index.ts
|
|
2907
|
-
var defaultConfig = {
|
|
2908
|
-
testTimeout: 6e4,
|
|
2909
|
-
hookTimeout: 12e4,
|
|
2910
|
-
globalSetup: ["@bonsae/nrg/test/client/e2e"],
|
|
2911
|
-
include: ["tests/client/e2e/**/*.test.ts"]
|
|
2912
|
-
};
|
|
2913
3137
|
var _env = null;
|
|
2914
3138
|
async function setup(options) {
|
|
2915
3139
|
const packageName = JSON.parse(
|
|
2916
|
-
|
|
3140
|
+
fs15.readFileSync(path14.join(process.cwd(), "package.json"), "utf-8")
|
|
2917
3141
|
).name;
|
|
2918
3142
|
_env = new NodeRedTestEnvironment({
|
|
2919
3143
|
packageName,
|
|
@@ -2945,8 +3169,8 @@ var NodeRedEditor = class {
|
|
|
2945
3169
|
errors = [];
|
|
2946
3170
|
screenshotDir;
|
|
2947
3171
|
async screenshot(name) {
|
|
2948
|
-
|
|
2949
|
-
const filePath =
|
|
3172
|
+
fs15.mkdirSync(this.screenshotDir, { recursive: true });
|
|
3173
|
+
const filePath = path14.join(this.screenshotDir, `${name}.png`);
|
|
2950
3174
|
await this.page.screenshot({ path: filePath, fullPage: true });
|
|
2951
3175
|
return filePath;
|
|
2952
3176
|
}
|
|
@@ -3350,7 +3574,6 @@ export {
|
|
|
3350
3574
|
NodeRedEditor,
|
|
3351
3575
|
NodeRedField,
|
|
3352
3576
|
NodeRedTestEnvironment,
|
|
3353
|
-
defaultConfig,
|
|
3354
3577
|
setup,
|
|
3355
3578
|
teardown
|
|
3356
3579
|
};
|