@bonsae/nrg 0.21.2 → 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 -1358
- 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 +419 -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 -266
- package/types/server.d.ts +1 -900
- 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 +378 -150
- package/server/resources/nrg-client.js +0 -7493
- 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 -227
- 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/vite/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/vite/plugin.ts
|
|
2
|
-
import
|
|
2
|
+
import path15 from "path";
|
|
3
3
|
|
|
4
4
|
// src/vite/defaults.ts
|
|
5
5
|
var DEFAULT_OUTPUT_DIR = "./dist";
|
|
@@ -766,7 +766,7 @@ var NodeRedLauncher = class {
|
|
|
766
766
|
// src/vite/plugins/server.ts
|
|
767
767
|
import chokidar from "chokidar";
|
|
768
768
|
import treeKill2 from "tree-kill";
|
|
769
|
-
import
|
|
769
|
+
import path14 from "path";
|
|
770
770
|
|
|
771
771
|
// src/vite/server/build.ts
|
|
772
772
|
import { build as viteBuild } from "vite";
|
|
@@ -778,6 +778,26 @@ import dts from "vite-plugin-dts";
|
|
|
778
778
|
import fs5 from "fs";
|
|
779
779
|
import path4 from "path";
|
|
780
780
|
import ts from "typescript";
|
|
781
|
+
var RUNTIME_TYPE_REWRITES = {
|
|
782
|
+
"@bonsae/nrg/server": "@bonsae/nrg-runtime/server",
|
|
783
|
+
"@bonsae/nrg/client": "@bonsae/nrg-runtime/client"
|
|
784
|
+
};
|
|
785
|
+
function rewriteRuntimeTypeImports(outDir, entryNames) {
|
|
786
|
+
for (const name of entryNames) {
|
|
787
|
+
const dtsPath = path4.join(outDir, `${name}.d.ts`);
|
|
788
|
+
if (!fs5.existsSync(dtsPath)) continue;
|
|
789
|
+
const original = fs5.readFileSync(dtsPath, "utf-8");
|
|
790
|
+
let rewritten = original;
|
|
791
|
+
for (const [from, to] of Object.entries(RUNTIME_TYPE_REWRITES)) {
|
|
792
|
+
const escaped = from.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
793
|
+
const re = new RegExp(`(['"])${escaped}\\1`, "g");
|
|
794
|
+
rewritten = rewritten.replace(re, `$1${to}$1`);
|
|
795
|
+
}
|
|
796
|
+
if (rewritten !== original) {
|
|
797
|
+
fs5.writeFileSync(dtsPath, rewritten);
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
}
|
|
781
801
|
function collectTsFiles(dir) {
|
|
782
802
|
if (!fs5.existsSync(dir)) return [];
|
|
783
803
|
return fs5.readdirSync(dir, { withFileTypes: true }).flatMap((dirent) => {
|
|
@@ -1152,18 +1172,23 @@ ${reexports}
|
|
|
1152
1172
|
}
|
|
1153
1173
|
|
|
1154
1174
|
// src/vite/server/plugins/output-wrapper.ts
|
|
1155
|
-
function
|
|
1175
|
+
function nrgServerSpecifier(isDev) {
|
|
1176
|
+
return isDev ? "@bonsae/nrg/server" : "@bonsae/nrg-runtime/server";
|
|
1177
|
+
}
|
|
1178
|
+
function cjsWrapper(isDev = false) {
|
|
1179
|
+
const serverSpecifier = nrgServerSpecifier(isDev);
|
|
1156
1180
|
return {
|
|
1157
1181
|
name: "vite-plugin-node-red:server:cjs-wrapper",
|
|
1158
1182
|
renderChunk(code, chunk, outputOptions) {
|
|
1159
1183
|
if (!chunk.isEntry || outputOptions.format !== "cjs") return null;
|
|
1160
|
-
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(
|
|
1184
|
+
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;}});}})();`;
|
|
1161
1185
|
return { code: `${code}
|
|
1162
1186
|
${footer}`, map: null };
|
|
1163
1187
|
}
|
|
1164
1188
|
};
|
|
1165
1189
|
}
|
|
1166
|
-
function esmWrapper() {
|
|
1190
|
+
function esmWrapper(isDev = false) {
|
|
1191
|
+
const serverSpecifier = nrgServerSpecifier(isDev);
|
|
1167
1192
|
return {
|
|
1168
1193
|
name: "vite-plugin-node-red:server:esm-wrapper",
|
|
1169
1194
|
renderChunk(code, chunk, outputOptions) {
|
|
@@ -1189,7 +1214,9 @@ function esmWrapper() {
|
|
|
1189
1214
|
`import { dirname as __nrgDirname } from "path";`,
|
|
1190
1215
|
`var __filename = __nrgFileURLToPath(import.meta.url);`,
|
|
1191
1216
|
`var __dirname = __nrgDirname(__filename);`,
|
|
1192
|
-
`import { registerTypes as __nrgRegisterTypes } from
|
|
1217
|
+
`import { registerTypes as __nrgRegisterTypes } from ${JSON.stringify(
|
|
1218
|
+
serverSpecifier
|
|
1219
|
+
)};`,
|
|
1193
1220
|
``
|
|
1194
1221
|
].join("\n");
|
|
1195
1222
|
const replacement = [
|
|
@@ -1213,6 +1240,12 @@ var nodeBuiltins = /* @__PURE__ */ new Set([
|
|
|
1213
1240
|
...builtinModules2,
|
|
1214
1241
|
...builtinModules2.map((m) => `node:${m}`)
|
|
1215
1242
|
]);
|
|
1243
|
+
var RUNTIME_REWRITES = {
|
|
1244
|
+
"@bonsae/nrg/server": "@bonsae/nrg-runtime/server"
|
|
1245
|
+
};
|
|
1246
|
+
var RUNTIME_VERSION_SOURCE = {
|
|
1247
|
+
"@bonsae/nrg-runtime": "@bonsae/nrg"
|
|
1248
|
+
};
|
|
1216
1249
|
function buildTypesPath(entryName) {
|
|
1217
1250
|
return `./${entryName}.d.ts`;
|
|
1218
1251
|
}
|
|
@@ -1269,7 +1302,8 @@ function packageJsonGenerator(options) {
|
|
|
1269
1302
|
bundled = [],
|
|
1270
1303
|
types = false,
|
|
1271
1304
|
entryNames = [],
|
|
1272
|
-
format = "cjs"
|
|
1305
|
+
format = "cjs",
|
|
1306
|
+
isDev = false
|
|
1273
1307
|
} = options;
|
|
1274
1308
|
const trackedDependencies = /* @__PURE__ */ new Set();
|
|
1275
1309
|
return {
|
|
@@ -1287,12 +1321,13 @@ function packageJsonGenerator(options) {
|
|
|
1287
1321
|
if (nodeBuiltins.has(source)) {
|
|
1288
1322
|
return { id: source, external: true };
|
|
1289
1323
|
}
|
|
1290
|
-
const
|
|
1324
|
+
const resolved = isDev ? source : RUNTIME_REWRITES[source] ?? source;
|
|
1325
|
+
const packageName = resolved.startsWith("@") ? resolved.split("/").slice(0, 2).join("/") : resolved.split("/")[0];
|
|
1291
1326
|
if (bundled.includes(packageName)) {
|
|
1292
1327
|
return null;
|
|
1293
1328
|
}
|
|
1294
1329
|
trackedDependencies.add(packageName);
|
|
1295
|
-
return { id:
|
|
1330
|
+
return { id: resolved, external: true };
|
|
1296
1331
|
}
|
|
1297
1332
|
},
|
|
1298
1333
|
closeBundle() {
|
|
@@ -1305,14 +1340,19 @@ function packageJsonGenerator(options) {
|
|
|
1305
1340
|
fs6.readFileSync(rootPackageJsonPath, "utf-8")
|
|
1306
1341
|
);
|
|
1307
1342
|
const sourceDeps = rootPackageJson.dependencies ?? {};
|
|
1343
|
+
const devDeps = rootPackageJson.devDependencies ?? {};
|
|
1308
1344
|
const peerDeps = rootPackageJson.peerDependencies ?? {};
|
|
1309
1345
|
let distDependencies = {};
|
|
1310
1346
|
for (const dep of trackedDependencies) {
|
|
1311
1347
|
if (peerDeps[dep]) {
|
|
1312
1348
|
continue;
|
|
1313
1349
|
}
|
|
1350
|
+
const versionSource = RUNTIME_VERSION_SOURCE[dep];
|
|
1351
|
+
const sourceVersion = versionSource ? sourceDeps[versionSource] ?? devDeps[versionSource] : void 0;
|
|
1314
1352
|
if (sourceDeps[dep]) {
|
|
1315
1353
|
distDependencies[dep] = sourceDeps[dep];
|
|
1354
|
+
} else if (sourceVersion) {
|
|
1355
|
+
distDependencies[dep] = sourceVersion;
|
|
1316
1356
|
} else {
|
|
1317
1357
|
const dependencyPackageJsonPath = path5.resolve(
|
|
1318
1358
|
`./node_modules/${dep}/package.json`
|
|
@@ -1399,9 +1439,10 @@ async function build(serverOpts, buildContext) {
|
|
|
1399
1439
|
bundled,
|
|
1400
1440
|
types: types && !buildContext.isDev,
|
|
1401
1441
|
entryNames: Object.keys(entryPoints),
|
|
1402
|
-
format
|
|
1442
|
+
format,
|
|
1443
|
+
isDev: buildContext.isDev
|
|
1403
1444
|
}),
|
|
1404
|
-
isEsm ? esmWrapper() : cjsWrapper()
|
|
1445
|
+
isEsm ? esmWrapper(buildContext.isDev) : cjsWrapper(buildContext.isDev)
|
|
1405
1446
|
];
|
|
1406
1447
|
if (types && !buildContext.isDev) {
|
|
1407
1448
|
plugins.push(
|
|
@@ -1443,6 +1484,9 @@ async function build(serverOpts, buildContext) {
|
|
|
1443
1484
|
};
|
|
1444
1485
|
try {
|
|
1445
1486
|
await viteBuild(config);
|
|
1487
|
+
if (types && !buildContext.isDev) {
|
|
1488
|
+
rewriteRuntimeTypeImports(buildContext.outDir, Object.keys(entryPoints));
|
|
1489
|
+
}
|
|
1446
1490
|
if (isEsm) {
|
|
1447
1491
|
const bridgeCode = `'use strict';
|
|
1448
1492
|
// CJS bridge \u2014 auto-generated by @bonsae/nrg/vite
|
|
@@ -1469,12 +1513,13 @@ module.exports = function (RED) {
|
|
|
1469
1513
|
// src/vite/client/build.ts
|
|
1470
1514
|
import { build as viteBuild2 } from "vite";
|
|
1471
1515
|
import vue from "@vitejs/plugin-vue";
|
|
1472
|
-
import
|
|
1473
|
-
import
|
|
1516
|
+
import fs14 from "fs";
|
|
1517
|
+
import path13 from "path";
|
|
1518
|
+
import crypto from "crypto";
|
|
1474
1519
|
|
|
1475
1520
|
// src/vite/client/plugins/help-generator.ts
|
|
1476
|
-
import
|
|
1477
|
-
import
|
|
1521
|
+
import fs9 from "fs";
|
|
1522
|
+
import path8 from "path";
|
|
1478
1523
|
import { pathToFileURL as pathToFileURL2 } from "url";
|
|
1479
1524
|
import { createRequire as createRequire2 } from "module";
|
|
1480
1525
|
|
|
@@ -1705,8 +1750,127 @@ function getHelpTranslations(lang) {
|
|
|
1705
1750
|
return translations[lang] ?? translations["en-US"];
|
|
1706
1751
|
}
|
|
1707
1752
|
|
|
1753
|
+
// src/vite/client/plugins/unsafe-types.ts
|
|
1754
|
+
import ts2 from "typescript";
|
|
1755
|
+
import fs8 from "fs";
|
|
1756
|
+
import path7 from "path";
|
|
1757
|
+
var NRG_SERVER_MODULE = "@bonsae/nrg/server";
|
|
1758
|
+
function normalizeType(text) {
|
|
1759
|
+
return text.replace(/\s+/g, " ").trim();
|
|
1760
|
+
}
|
|
1761
|
+
function resolveImports(sf) {
|
|
1762
|
+
const defineSchema = /* @__PURE__ */ new Set();
|
|
1763
|
+
const schemaType = /* @__PURE__ */ new Set();
|
|
1764
|
+
sf.forEachChild((node) => {
|
|
1765
|
+
if (!ts2.isImportDeclaration(node) || !ts2.isStringLiteral(node.moduleSpecifier) || node.moduleSpecifier.text !== NRG_SERVER_MODULE || !node.importClause?.namedBindings || !ts2.isNamedImports(node.importClause.namedBindings)) {
|
|
1766
|
+
return;
|
|
1767
|
+
}
|
|
1768
|
+
for (const el of node.importClause.namedBindings.elements) {
|
|
1769
|
+
const imported = (el.propertyName ?? el.name).text;
|
|
1770
|
+
const local = el.name.text;
|
|
1771
|
+
if (imported === "defineSchema") defineSchema.add(local);
|
|
1772
|
+
if (imported === "SchemaType") schemaType.add(local);
|
|
1773
|
+
}
|
|
1774
|
+
});
|
|
1775
|
+
return { defineSchema, schemaType };
|
|
1776
|
+
}
|
|
1777
|
+
function staticPropName(name) {
|
|
1778
|
+
if (ts2.isIdentifier(name) || ts2.isStringLiteralLike(name)) return name.text;
|
|
1779
|
+
return void 0;
|
|
1780
|
+
}
|
|
1781
|
+
function unsafeTypeArg(node, sf, schemaType) {
|
|
1782
|
+
if (!ts2.isCallExpression(node) || !ts2.isPropertyAccessExpression(node.expression) || !ts2.isIdentifier(node.expression.expression) || !schemaType.has(node.expression.expression.text)) {
|
|
1783
|
+
return void 0;
|
|
1784
|
+
}
|
|
1785
|
+
const method = node.expression.name.text;
|
|
1786
|
+
if (method === "Unsafe" && node.typeArguments?.length) {
|
|
1787
|
+
return normalizeType(node.typeArguments[0].getText(sf));
|
|
1788
|
+
}
|
|
1789
|
+
if (method === "Array" && node.arguments.length) {
|
|
1790
|
+
const inner = unsafeTypeArg(node.arguments[0], sf, schemaType);
|
|
1791
|
+
if (inner) return `${inner}[]`;
|
|
1792
|
+
}
|
|
1793
|
+
return void 0;
|
|
1794
|
+
}
|
|
1795
|
+
function readSchemaCall(call, sf, schemaType) {
|
|
1796
|
+
const [propsArg, optsArg] = call.arguments;
|
|
1797
|
+
if (!propsArg || !optsArg || !ts2.isObjectLiteralExpression(propsArg) || !ts2.isObjectLiteralExpression(optsArg)) {
|
|
1798
|
+
return void 0;
|
|
1799
|
+
}
|
|
1800
|
+
let id;
|
|
1801
|
+
for (const p of optsArg.properties) {
|
|
1802
|
+
if (ts2.isPropertyAssignment(p) && staticPropName(p.name) === "$id" && ts2.isStringLiteralLike(p.initializer)) {
|
|
1803
|
+
id = p.initializer.text;
|
|
1804
|
+
}
|
|
1805
|
+
}
|
|
1806
|
+
if (!id) return void 0;
|
|
1807
|
+
const props = {};
|
|
1808
|
+
for (const p of propsArg.properties) {
|
|
1809
|
+
if (!ts2.isPropertyAssignment(p)) continue;
|
|
1810
|
+
const key = staticPropName(p.name);
|
|
1811
|
+
if (key === void 0) continue;
|
|
1812
|
+
const type = unsafeTypeArg(p.initializer, sf, schemaType);
|
|
1813
|
+
if (type) props[key] = type;
|
|
1814
|
+
}
|
|
1815
|
+
return { id, props };
|
|
1816
|
+
}
|
|
1817
|
+
function extractUnsafeTypesFromSource(fileName, code) {
|
|
1818
|
+
const out = /* @__PURE__ */ new Map();
|
|
1819
|
+
const sf = ts2.createSourceFile(fileName, code, ts2.ScriptTarget.Latest, true);
|
|
1820
|
+
const { defineSchema, schemaType } = resolveImports(sf);
|
|
1821
|
+
if (defineSchema.size === 0 || schemaType.size === 0) return out;
|
|
1822
|
+
const visit = (node) => {
|
|
1823
|
+
if (ts2.isCallExpression(node) && ts2.isIdentifier(node.expression) && defineSchema.has(node.expression.text)) {
|
|
1824
|
+
const result = readSchemaCall(node, sf, schemaType);
|
|
1825
|
+
if (result && Object.keys(result.props).length > 0) {
|
|
1826
|
+
if (out.has(result.id)) {
|
|
1827
|
+
throw new Error(
|
|
1828
|
+
`Duplicate schema $id "${result.id}" in ${fileName} \u2014 $id must be unique`
|
|
1829
|
+
);
|
|
1830
|
+
}
|
|
1831
|
+
out.set(result.id, result.props);
|
|
1832
|
+
}
|
|
1833
|
+
}
|
|
1834
|
+
ts2.forEachChild(node, visit);
|
|
1835
|
+
};
|
|
1836
|
+
visit(sf);
|
|
1837
|
+
return out;
|
|
1838
|
+
}
|
|
1839
|
+
function collectTsFiles2(dir) {
|
|
1840
|
+
const out = [];
|
|
1841
|
+
if (!fs8.existsSync(dir)) return out;
|
|
1842
|
+
for (const entry of fs8.readdirSync(dir, { withFileTypes: true })) {
|
|
1843
|
+
const full = path7.join(dir, entry.name);
|
|
1844
|
+
if (entry.isDirectory()) {
|
|
1845
|
+
if (entry.name === "node_modules") continue;
|
|
1846
|
+
out.push(...collectTsFiles2(full));
|
|
1847
|
+
} else if (entry.name.endsWith(".ts") && !entry.name.endsWith(".d.ts") && !entry.name.endsWith(".test.ts") && !entry.name.endsWith(".spec.ts")) {
|
|
1848
|
+
out.push(full);
|
|
1849
|
+
}
|
|
1850
|
+
}
|
|
1851
|
+
return out;
|
|
1852
|
+
}
|
|
1853
|
+
function extractUnsafeTypes(srcDir) {
|
|
1854
|
+
const merged = /* @__PURE__ */ new Map();
|
|
1855
|
+
for (const file of collectTsFiles2(srcDir).sort()) {
|
|
1856
|
+
const perFile = extractUnsafeTypesFromSource(
|
|
1857
|
+
file,
|
|
1858
|
+
fs8.readFileSync(file, "utf-8")
|
|
1859
|
+
);
|
|
1860
|
+
for (const [id, props] of perFile) {
|
|
1861
|
+
if (merged.has(id)) {
|
|
1862
|
+
throw new Error(
|
|
1863
|
+
`Duplicate schema $id "${id}" across ${srcDir} \u2014 $id must be unique`
|
|
1864
|
+
);
|
|
1865
|
+
}
|
|
1866
|
+
merged.set(id, props);
|
|
1867
|
+
}
|
|
1868
|
+
}
|
|
1869
|
+
return merged;
|
|
1870
|
+
}
|
|
1871
|
+
|
|
1708
1872
|
// src/vite/client/plugins/help-generator.ts
|
|
1709
|
-
function buildPropertyRow(name, schema, required, label) {
|
|
1873
|
+
function buildPropertyRow(name, schema, required, label, parsedType) {
|
|
1710
1874
|
let type = "";
|
|
1711
1875
|
if (schema["x-nrg-node-type"]) {
|
|
1712
1876
|
type = `NodeRef \u2192 ${schema["x-nrg-node-type"]}`;
|
|
@@ -1714,6 +1878,8 @@ function buildPropertyRow(name, schema, required, label) {
|
|
|
1714
1878
|
type = "TypedInput";
|
|
1715
1879
|
} else if (schema.type) {
|
|
1716
1880
|
type = String(schema.type);
|
|
1881
|
+
} else if (parsedType) {
|
|
1882
|
+
type = parsedType;
|
|
1717
1883
|
}
|
|
1718
1884
|
if (schema.enum) type += ` (${schema.enum.join(", ")})`;
|
|
1719
1885
|
const constraints = [];
|
|
@@ -1749,16 +1915,19 @@ function generateSchemaSection(options) {
|
|
|
1749
1915
|
t,
|
|
1750
1916
|
labels,
|
|
1751
1917
|
heading = "###",
|
|
1752
|
-
includeDefault = true
|
|
1918
|
+
includeDefault = true,
|
|
1919
|
+
unsafeTypes
|
|
1753
1920
|
} = options;
|
|
1754
1921
|
if (!schema?.properties) return "";
|
|
1922
|
+
const parsed = unsafeTypes?.get(schema.$id);
|
|
1755
1923
|
const required = new Set(schema.required ?? []);
|
|
1756
1924
|
const rows = Object.entries(schema.properties).filter(([key]) => !SKIP_FIELDS.has(key)).map(
|
|
1757
1925
|
([key, propSchema]) => buildPropertyRow(
|
|
1758
1926
|
key,
|
|
1759
1927
|
propSchema,
|
|
1760
1928
|
required.has(key),
|
|
1761
|
-
labels?.[key]
|
|
1929
|
+
labels?.[key],
|
|
1930
|
+
parsed?.[key]
|
|
1762
1931
|
)
|
|
1763
1932
|
);
|
|
1764
1933
|
if (rows.length === 0) return "";
|
|
@@ -1796,9 +1965,9 @@ ${table}
|
|
|
1796
1965
|
`;
|
|
1797
1966
|
}
|
|
1798
1967
|
function loadNodeLabels(labelPath) {
|
|
1799
|
-
if (!
|
|
1968
|
+
if (!fs9.existsSync(labelPath)) return {};
|
|
1800
1969
|
try {
|
|
1801
|
-
const raw = JSON.parse(
|
|
1970
|
+
const raw = JSON.parse(fs9.readFileSync(labelPath, "utf-8"));
|
|
1802
1971
|
return {
|
|
1803
1972
|
description: raw.description,
|
|
1804
1973
|
configs: raw.configs,
|
|
@@ -1810,7 +1979,7 @@ function loadNodeLabels(labelPath) {
|
|
|
1810
1979
|
return {};
|
|
1811
1980
|
}
|
|
1812
1981
|
}
|
|
1813
|
-
function generateHelpDoc(nodeClass, labels, t) {
|
|
1982
|
+
function generateHelpDoc(nodeClass, labels, t, unsafeTypes) {
|
|
1814
1983
|
const lines = [];
|
|
1815
1984
|
if (labels.description) {
|
|
1816
1985
|
lines.push(`<p>${labels.description}</p>`);
|
|
@@ -1819,14 +1988,16 @@ function generateHelpDoc(nodeClass, labels, t) {
|
|
|
1819
1988
|
title: t.sections.properties,
|
|
1820
1989
|
schema: nodeClass.configSchema,
|
|
1821
1990
|
t,
|
|
1822
|
-
labels: labels.configs
|
|
1991
|
+
labels: labels.configs,
|
|
1992
|
+
unsafeTypes
|
|
1823
1993
|
});
|
|
1824
1994
|
if (configSection) lines.push(configSection);
|
|
1825
1995
|
const credsSection = generateSchemaSection({
|
|
1826
1996
|
title: t.sections.credentials,
|
|
1827
1997
|
schema: nodeClass.credentialsSchema,
|
|
1828
1998
|
t,
|
|
1829
|
-
labels: labels.credentials
|
|
1999
|
+
labels: labels.credentials,
|
|
2000
|
+
unsafeTypes
|
|
1830
2001
|
});
|
|
1831
2002
|
if (credsSection) lines.push(credsSection);
|
|
1832
2003
|
if (nodeClass.inputSchema) {
|
|
@@ -1835,7 +2006,8 @@ function generateHelpDoc(nodeClass, labels, t) {
|
|
|
1835
2006
|
schema: nodeClass.inputSchema,
|
|
1836
2007
|
t,
|
|
1837
2008
|
labels: labels.input,
|
|
1838
|
-
includeDefault: false
|
|
2009
|
+
includeDefault: false,
|
|
2010
|
+
unsafeTypes
|
|
1839
2011
|
});
|
|
1840
2012
|
if (inputSection) lines.push(inputSection);
|
|
1841
2013
|
}
|
|
@@ -1852,7 +2024,8 @@ function generateHelpDoc(nodeClass, labels, t) {
|
|
|
1852
2024
|
t,
|
|
1853
2025
|
labels: portPropLabels,
|
|
1854
2026
|
heading: "####",
|
|
1855
|
-
includeDefault: false
|
|
2027
|
+
includeDefault: false,
|
|
2028
|
+
unsafeTypes
|
|
1856
2029
|
});
|
|
1857
2030
|
if (section) portSections.push(section);
|
|
1858
2031
|
});
|
|
@@ -1872,7 +2045,8 @@ ${portSections.join("\n")}`
|
|
|
1872
2045
|
t,
|
|
1873
2046
|
labels: portPropLabels,
|
|
1874
2047
|
heading: "####",
|
|
1875
|
-
includeDefault: false
|
|
2048
|
+
includeDefault: false,
|
|
2049
|
+
unsafeTypes
|
|
1876
2050
|
});
|
|
1877
2051
|
if (section) portSections.push(section);
|
|
1878
2052
|
}
|
|
@@ -1889,7 +2063,8 @@ ${portSections.join("\n")}`
|
|
|
1889
2063
|
schema: os3,
|
|
1890
2064
|
t,
|
|
1891
2065
|
labels: outputPropLabels,
|
|
1892
|
-
includeDefault: false
|
|
2066
|
+
includeDefault: false,
|
|
2067
|
+
unsafeTypes
|
|
1893
2068
|
});
|
|
1894
2069
|
if (section) lines.push(section);
|
|
1895
2070
|
}
|
|
@@ -1897,26 +2072,26 @@ ${portSections.join("\n")}`
|
|
|
1897
2072
|
return lines.join("\n").trim();
|
|
1898
2073
|
}
|
|
1899
2074
|
function discoverLanguages(labelsDir, nodeType) {
|
|
1900
|
-
const nodeLabelsDir =
|
|
1901
|
-
if (!
|
|
1902
|
-
return
|
|
2075
|
+
const nodeLabelsDir = path8.join(labelsDir, nodeType);
|
|
2076
|
+
if (!fs9.existsSync(nodeLabelsDir)) return [];
|
|
2077
|
+
return fs9.readdirSync(nodeLabelsDir).filter((f) => f.endsWith(".json")).map((f) => path8.basename(f, ".json"));
|
|
1903
2078
|
}
|
|
1904
2079
|
function helpGenerator(options) {
|
|
1905
|
-
const { outDir, localesOutDir, docsDir, labelsDir } = options;
|
|
2080
|
+
const { outDir, localesOutDir, docsDir, labelsDir, srcDir } = options;
|
|
1906
2081
|
return {
|
|
1907
2082
|
name: "vite-plugin-node-red:client:help-generator",
|
|
1908
2083
|
apply: "build",
|
|
1909
2084
|
enforce: "post",
|
|
1910
2085
|
async closeBundle() {
|
|
1911
|
-
const esmPath =
|
|
1912
|
-
const cjsPath =
|
|
2086
|
+
const esmPath = path8.resolve(outDir, "index.mjs");
|
|
2087
|
+
const cjsPath = path8.resolve(outDir, "index.js");
|
|
1913
2088
|
let packageFn;
|
|
1914
2089
|
try {
|
|
1915
|
-
if (
|
|
2090
|
+
if (fs9.existsSync(esmPath)) {
|
|
1916
2091
|
const fileUrl = pathToFileURL2(esmPath).href + `?t=${Date.now()}`;
|
|
1917
2092
|
const mod = await import(fileUrl);
|
|
1918
2093
|
packageFn = mod?.default ?? mod;
|
|
1919
|
-
} else if (
|
|
2094
|
+
} else if (fs9.existsSync(cjsPath)) {
|
|
1920
2095
|
const require2 = createRequire2(import.meta.url);
|
|
1921
2096
|
delete require2.cache[cjsPath];
|
|
1922
2097
|
const rawMod = require2(cjsPath);
|
|
@@ -1926,6 +2101,7 @@ function helpGenerator(options) {
|
|
|
1926
2101
|
return;
|
|
1927
2102
|
}
|
|
1928
2103
|
const nodeClasses = packageFn?.nodes ?? [];
|
|
2104
|
+
const unsafeTypes = srcDir ? extractUnsafeTypes(srcDir) : void 0;
|
|
1929
2105
|
const helpByLang = /* @__PURE__ */ new Map();
|
|
1930
2106
|
for (const NodeClass of nodeClasses) {
|
|
1931
2107
|
const type = NodeClass.type;
|
|
@@ -1933,13 +2109,13 @@ function helpGenerator(options) {
|
|
|
1933
2109
|
const languages = discoverLanguages(labelsDir, type);
|
|
1934
2110
|
if (!languages.includes("en-US")) languages.push("en-US");
|
|
1935
2111
|
for (const lang of languages) {
|
|
1936
|
-
const manualMd =
|
|
1937
|
-
const manualHtml =
|
|
1938
|
-
if (
|
|
1939
|
-
const labelPath =
|
|
2112
|
+
const manualMd = path8.join(docsDir, type, `${lang}.md`);
|
|
2113
|
+
const manualHtml = path8.join(docsDir, type, `${lang}.html`);
|
|
2114
|
+
if (fs9.existsSync(manualMd) || fs9.existsSync(manualHtml)) continue;
|
|
2115
|
+
const labelPath = path8.join(labelsDir, type, `${lang}.json`);
|
|
1940
2116
|
const labels = loadNodeLabels(labelPath);
|
|
1941
2117
|
const t = getHelpTranslations(lang);
|
|
1942
|
-
const content = generateHelpDoc(NodeClass, labels, t);
|
|
2118
|
+
const content = generateHelpDoc(NodeClass, labels, t, unsafeTypes);
|
|
1943
2119
|
if (!content) continue;
|
|
1944
2120
|
if (!helpByLang.has(lang)) helpByLang.set(lang, []);
|
|
1945
2121
|
helpByLang.get(lang).push(
|
|
@@ -1950,11 +2126,11 @@ ${content}
|
|
|
1950
2126
|
}
|
|
1951
2127
|
}
|
|
1952
2128
|
for (const [lang, scripts] of helpByLang) {
|
|
1953
|
-
const langDir =
|
|
1954
|
-
|
|
1955
|
-
const indexPath =
|
|
1956
|
-
const existing =
|
|
1957
|
-
|
|
2129
|
+
const langDir = path8.join(localesOutDir, lang);
|
|
2130
|
+
fs9.mkdirSync(langDir, { recursive: true });
|
|
2131
|
+
const indexPath = path8.join(langDir, "index.html");
|
|
2132
|
+
const existing = fs9.existsSync(indexPath) ? fs9.readFileSync(indexPath, "utf-8") : "";
|
|
2133
|
+
fs9.writeFileSync(
|
|
1958
2134
|
indexPath,
|
|
1959
2135
|
existing + (existing ? "\n" : "") + scripts.join("\n"),
|
|
1960
2136
|
"utf-8"
|
|
@@ -1966,8 +2142,8 @@ ${content}
|
|
|
1966
2142
|
|
|
1967
2143
|
// src/vite/client/plugins/html-generator.ts
|
|
1968
2144
|
import mime from "mime-types";
|
|
1969
|
-
import
|
|
1970
|
-
import
|
|
2145
|
+
import fs10 from "fs";
|
|
2146
|
+
import path9 from "path";
|
|
1971
2147
|
function htmlGenerator(options) {
|
|
1972
2148
|
const { packageName, licensePath } = options;
|
|
1973
2149
|
return {
|
|
@@ -1977,7 +2153,7 @@ function htmlGenerator(options) {
|
|
|
1977
2153
|
generateBundle(_, bundle) {
|
|
1978
2154
|
const resourcesTags = Object.keys(bundle).map((fileName) => {
|
|
1979
2155
|
const asset = bundle[fileName];
|
|
1980
|
-
const srcPath =
|
|
2156
|
+
const srcPath = path9.join(
|
|
1981
2157
|
"resources",
|
|
1982
2158
|
packageName,
|
|
1983
2159
|
fileName.replace(/^resources\/?/, "")
|
|
@@ -2005,8 +2181,8 @@ function htmlGenerator(options) {
|
|
|
2005
2181
|
return null;
|
|
2006
2182
|
}
|
|
2007
2183
|
}).filter(Boolean).join("\n");
|
|
2008
|
-
const licenseBanner = licensePath &&
|
|
2009
|
-
${
|
|
2184
|
+
const licenseBanner = licensePath && fs10.existsSync(licensePath) ? `<!--
|
|
2185
|
+
${fs10.readFileSync(licensePath, "utf-8")}
|
|
2010
2186
|
-->` : "";
|
|
2011
2187
|
this.emitFile({
|
|
2012
2188
|
type: "asset",
|
|
@@ -2019,8 +2195,8 @@ ${resourcesTags}`
|
|
|
2019
2195
|
}
|
|
2020
2196
|
|
|
2021
2197
|
// src/vite/client/plugins/locales-generator.ts
|
|
2022
|
-
import
|
|
2023
|
-
import
|
|
2198
|
+
import fs11 from "fs";
|
|
2199
|
+
import path10 from "path";
|
|
2024
2200
|
import { merge } from "es-toolkit";
|
|
2025
2201
|
function localesGenerator(options) {
|
|
2026
2202
|
const { outDir, docsDir, labelsDir } = options;
|
|
@@ -2403,17 +2579,17 @@ Supported: ${languages.join(", ")}`
|
|
|
2403
2579
|
}
|
|
2404
2580
|
function forEachFile(baseDir, fileExtensions, processFile) {
|
|
2405
2581
|
const langMap = /* @__PURE__ */ new Map();
|
|
2406
|
-
if (!
|
|
2407
|
-
const nodeDirs =
|
|
2582
|
+
if (!fs11.existsSync(baseDir)) return langMap;
|
|
2583
|
+
const nodeDirs = fs11.readdirSync(baseDir, { withFileTypes: true }).filter((d) => d.isDirectory());
|
|
2408
2584
|
for (const nodeDir of nodeDirs) {
|
|
2409
2585
|
const nodeType = nodeDir.name;
|
|
2410
|
-
const nodePath =
|
|
2411
|
-
const files =
|
|
2586
|
+
const nodePath = path10.join(baseDir, nodeType);
|
|
2587
|
+
const files = fs11.readdirSync(nodePath);
|
|
2412
2588
|
for (const file of files) {
|
|
2413
|
-
const ext =
|
|
2589
|
+
const ext = path10.extname(file);
|
|
2414
2590
|
if (!fileExtensions.includes(ext)) continue;
|
|
2415
|
-
const lang =
|
|
2416
|
-
const filePath =
|
|
2591
|
+
const lang = path10.basename(file, ext);
|
|
2592
|
+
const filePath = path10.join(nodePath, file);
|
|
2417
2593
|
validateLanguage(lang, filePath);
|
|
2418
2594
|
const value = processFile({ ext, filePath, nodeType });
|
|
2419
2595
|
if (value == null) continue;
|
|
@@ -2431,10 +2607,10 @@ Supported: ${languages.join(", ")}`
|
|
|
2431
2607
|
}
|
|
2432
2608
|
function writeOutput(langMap, fileName, serialize) {
|
|
2433
2609
|
for (const [lang, data] of langMap.entries()) {
|
|
2434
|
-
const langOutDir =
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2610
|
+
const langOutDir = path10.join(outDir, lang);
|
|
2611
|
+
fs11.mkdirSync(langOutDir, { recursive: true });
|
|
2612
|
+
fs11.writeFileSync(
|
|
2613
|
+
path10.join(langOutDir, fileName),
|
|
2438
2614
|
serialize(data),
|
|
2439
2615
|
"utf-8"
|
|
2440
2616
|
);
|
|
@@ -2446,7 +2622,7 @@ Supported: ${languages.join(", ")}`
|
|
|
2446
2622
|
({ ext, filePath, nodeType }) => {
|
|
2447
2623
|
const type = ext === ".html" ? "text/html" : ext === ".md" ? "text/markdown" : null;
|
|
2448
2624
|
if (!type) return null;
|
|
2449
|
-
const content =
|
|
2625
|
+
const content = fs11.readFileSync(filePath, "utf-8");
|
|
2450
2626
|
return [
|
|
2451
2627
|
`<script type="${type}" data-help-name="${nodeType}">
|
|
2452
2628
|
${content}
|
|
@@ -2463,7 +2639,7 @@ ${content}
|
|
|
2463
2639
|
labelsDir,
|
|
2464
2640
|
[".json"],
|
|
2465
2641
|
({ filePath, nodeType }) => {
|
|
2466
|
-
const parsed = JSON.parse(
|
|
2642
|
+
const parsed = JSON.parse(fs11.readFileSync(filePath, "utf-8"));
|
|
2467
2643
|
if (parsed[nodeType] && typeof parsed[nodeType] === "object") {
|
|
2468
2644
|
console.warn(
|
|
2469
2645
|
`[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`
|
|
@@ -2513,8 +2689,8 @@ function minifier() {
|
|
|
2513
2689
|
// src/vite/client/plugins/node-definitions-inliner.ts
|
|
2514
2690
|
import { createRequire as createRequire3 } from "module";
|
|
2515
2691
|
import { pathToFileURL as pathToFileURL3 } from "url";
|
|
2516
|
-
import
|
|
2517
|
-
import
|
|
2692
|
+
import path11 from "path";
|
|
2693
|
+
import fs12 from "fs";
|
|
2518
2694
|
import mime2 from "mime-types";
|
|
2519
2695
|
var VIRTUAL_ID = "virtual:nrg/node-definitions";
|
|
2520
2696
|
var RESOLVED_ID = "\0" + VIRTUAL_ID;
|
|
@@ -2545,17 +2721,68 @@ function getCredentialsFromSchema(schema) {
|
|
|
2545
2721
|
return result;
|
|
2546
2722
|
}
|
|
2547
2723
|
function resolveIcon(iconsDir, type) {
|
|
2548
|
-
if (!
|
|
2549
|
-
return
|
|
2550
|
-
if (
|
|
2724
|
+
if (!fs12.existsSync(iconsDir)) return void 0;
|
|
2725
|
+
return fs12.readdirSync(iconsDir).find((f) => {
|
|
2726
|
+
if (path11.basename(f, path11.extname(f)) !== type) return false;
|
|
2551
2727
|
const mimeType = mime2.lookup(f);
|
|
2552
2728
|
return mimeType !== false && mimeType.startsWith("image/");
|
|
2553
2729
|
});
|
|
2554
2730
|
}
|
|
2555
|
-
|
|
2731
|
+
var RUNTIME_SPECIFIER = "@bonsae/nrg-runtime/server";
|
|
2732
|
+
var RUNTIME_SPECIFIER_RE = /(['"])@bonsae\/nrg-runtime\/server\1/g;
|
|
2733
|
+
function resolveRuntimeServer(serverOutDir) {
|
|
2734
|
+
const roots = [path11.join(serverOutDir, "index.js"), import.meta.url];
|
|
2735
|
+
for (const root of roots) {
|
|
2736
|
+
try {
|
|
2737
|
+
return createRequire3(root).resolve(RUNTIME_SPECIFIER);
|
|
2738
|
+
} catch {
|
|
2739
|
+
}
|
|
2740
|
+
}
|
|
2741
|
+
return void 0;
|
|
2742
|
+
}
|
|
2743
|
+
async function loadServerPackageExport(serverOutDir) {
|
|
2744
|
+
const esmEntryPath = path11.resolve(serverOutDir, "index.mjs");
|
|
2745
|
+
const cjsEntryPath = path11.resolve(serverOutDir, "index.js");
|
|
2746
|
+
const isEsm = fs12.existsSync(esmEntryPath);
|
|
2747
|
+
const entryPath = isEsm ? esmEntryPath : fs12.existsSync(cjsEntryPath) ? cjsEntryPath : void 0;
|
|
2748
|
+
if (!entryPath) return void 0;
|
|
2749
|
+
const code = fs12.readFileSync(entryPath, "utf-8");
|
|
2750
|
+
const runtimeServer = code.includes(RUNTIME_SPECIFIER) ? resolveRuntimeServer(serverOutDir) : void 0;
|
|
2751
|
+
let tempPath;
|
|
2752
|
+
let loadPath = entryPath;
|
|
2753
|
+
if (runtimeServer) {
|
|
2754
|
+
const replacement = isEsm ? JSON.stringify(pathToFileURL3(runtimeServer).href) : JSON.stringify(runtimeServer);
|
|
2755
|
+
const rewritten = code.replace(RUNTIME_SPECIFIER_RE, replacement);
|
|
2756
|
+
tempPath = path11.resolve(
|
|
2757
|
+
serverOutDir,
|
|
2758
|
+
`.nrg-server-${Date.now()}${isEsm ? ".mjs" : ".cjs"}`
|
|
2759
|
+
);
|
|
2760
|
+
fs12.writeFileSync(tempPath, rewritten);
|
|
2761
|
+
loadPath = tempPath;
|
|
2762
|
+
}
|
|
2763
|
+
const require2 = createRequire3(import.meta.url);
|
|
2764
|
+
try {
|
|
2765
|
+
if (isEsm) {
|
|
2766
|
+
const fileUrl = pathToFileURL3(loadPath).href + `?t=${Date.now()}`;
|
|
2767
|
+
const mod = await import(fileUrl);
|
|
2768
|
+
return mod?.default ?? mod;
|
|
2769
|
+
}
|
|
2770
|
+
delete require2.cache[loadPath];
|
|
2771
|
+
const rawMod = require2(loadPath);
|
|
2772
|
+
return rawMod?.default ?? rawMod;
|
|
2773
|
+
} finally {
|
|
2774
|
+
if (tempPath) {
|
|
2775
|
+
try {
|
|
2776
|
+
delete require2.cache[tempPath];
|
|
2777
|
+
fs12.rmSync(tempPath);
|
|
2778
|
+
} catch {
|
|
2779
|
+
}
|
|
2780
|
+
}
|
|
2781
|
+
}
|
|
2782
|
+
}
|
|
2783
|
+
function nodeDefinitionsInliner(serverOutDir, entryPath, iconsDir, componentsDir, nodesDir, hasUserEntry = true, cacheDir = path11.resolve("node_modules", ".nrg", "client")) {
|
|
2556
2784
|
let _nodeTypes = [];
|
|
2557
2785
|
let _definitions = {};
|
|
2558
|
-
const cacheDir = path10.resolve("node_modules", ".nrg", "client");
|
|
2559
2786
|
return {
|
|
2560
2787
|
name: "vite-plugin-node-red:client:node-definitions-inliner",
|
|
2561
2788
|
enforce: "pre",
|
|
@@ -2564,19 +2791,7 @@ function nodeDefinitionsInliner(serverOutDir, entryPath, iconsDir, componentsDir
|
|
|
2564
2791
|
async buildStart() {
|
|
2565
2792
|
_nodeTypes = [];
|
|
2566
2793
|
_definitions = {};
|
|
2567
|
-
const
|
|
2568
|
-
const cjsEntryPath = path10.resolve(serverOutDir, "index.js");
|
|
2569
|
-
let packageFn;
|
|
2570
|
-
if (fs11.existsSync(esmEntryPath)) {
|
|
2571
|
-
const fileUrl = pathToFileURL3(esmEntryPath).href + `?t=${Date.now()}`;
|
|
2572
|
-
const mod = await import(fileUrl);
|
|
2573
|
-
packageFn = mod?.default ?? mod;
|
|
2574
|
-
} else if (fs11.existsSync(cjsEntryPath)) {
|
|
2575
|
-
const require2 = createRequire3(import.meta.url);
|
|
2576
|
-
delete require2.cache[cjsEntryPath];
|
|
2577
|
-
const rawMod = require2(cjsEntryPath);
|
|
2578
|
-
packageFn = rawMod?.default ?? rawMod;
|
|
2579
|
-
}
|
|
2794
|
+
const packageFn = await loadServerPackageExport(serverOutDir);
|
|
2580
2795
|
const nodeClasses = packageFn?.nodes ?? [];
|
|
2581
2796
|
for (const NodeClass of nodeClasses) {
|
|
2582
2797
|
const type = NodeClass.type;
|
|
@@ -2615,14 +2830,14 @@ function nodeDefinitionsInliner(serverOutDir, entryPath, iconsDir, componentsDir
|
|
|
2615
2830
|
};
|
|
2616
2831
|
}
|
|
2617
2832
|
if (!hasUserEntry) {
|
|
2618
|
-
const nodesCache =
|
|
2619
|
-
if (
|
|
2620
|
-
|
|
2833
|
+
const nodesCache = path11.resolve(cacheDir, "nodes");
|
|
2834
|
+
if (fs12.existsSync(nodesCache)) {
|
|
2835
|
+
fs12.rmSync(nodesCache, { recursive: true });
|
|
2621
2836
|
}
|
|
2622
|
-
|
|
2837
|
+
fs12.mkdirSync(nodesCache, { recursive: true });
|
|
2623
2838
|
for (const type of _nodeTypes) {
|
|
2624
|
-
const userTsPath = nodesDir ?
|
|
2625
|
-
if (userTsPath &&
|
|
2839
|
+
const userTsPath = nodesDir ? path11.resolve(nodesDir, `${type}.ts`) : null;
|
|
2840
|
+
if (userTsPath && fs12.existsSync(userTsPath)) continue;
|
|
2626
2841
|
const content = [
|
|
2627
2842
|
`// auto-generated by nrg`,
|
|
2628
2843
|
`import { defineNode } from "@bonsae/nrg/client";`,
|
|
@@ -2632,13 +2847,13 @@ function nodeDefinitionsInliner(serverOutDir, entryPath, iconsDir, componentsDir
|
|
|
2632
2847
|
`});`,
|
|
2633
2848
|
``
|
|
2634
2849
|
].join("\n");
|
|
2635
|
-
|
|
2850
|
+
fs12.writeFileSync(path11.resolve(nodesCache, `${type}.ts`), content);
|
|
2636
2851
|
}
|
|
2637
2852
|
const entryContent = generateEntryCode("");
|
|
2638
|
-
|
|
2853
|
+
fs12.mkdirSync(path11.dirname(path11.resolve(cacheDir, "index.ts")), {
|
|
2639
2854
|
recursive: true
|
|
2640
2855
|
});
|
|
2641
|
-
|
|
2856
|
+
fs12.writeFileSync(path11.resolve(cacheDir, "index.ts"), entryContent);
|
|
2642
2857
|
}
|
|
2643
2858
|
},
|
|
2644
2859
|
resolveId(id) {
|
|
@@ -2661,12 +2876,12 @@ function nodeDefinitionsInliner(serverOutDir, entryPath, iconsDir, componentsDir
|
|
|
2661
2876
|
const nrgImports = /* @__PURE__ */ new Set(["__setSchemas"]);
|
|
2662
2877
|
const lines = [`import __nrgSchemas from "${VIRTUAL_ID}";`];
|
|
2663
2878
|
const postLines = [`__setSchemas(__nrgSchemas);`];
|
|
2664
|
-
if (componentsDir &&
|
|
2879
|
+
if (componentsDir && fs12.existsSync(componentsDir)) {
|
|
2665
2880
|
const formImports = [];
|
|
2666
2881
|
const formEntries = [];
|
|
2667
2882
|
for (const type of _nodeTypes) {
|
|
2668
|
-
const componentPath =
|
|
2669
|
-
if (
|
|
2883
|
+
const componentPath = path11.resolve(componentsDir, `${type}.vue`);
|
|
2884
|
+
if (fs12.existsSync(componentPath)) {
|
|
2670
2885
|
const varName = `__nrgForm_${type.replace(/-/g, "_")}`;
|
|
2671
2886
|
formImports.push(
|
|
2672
2887
|
`import ${varName} from ${JSON.stringify(componentPath)};`
|
|
@@ -2681,12 +2896,12 @@ function nodeDefinitionsInliner(serverOutDir, entryPath, iconsDir, componentsDir
|
|
|
2681
2896
|
}
|
|
2682
2897
|
}
|
|
2683
2898
|
if (!hasUserEntry) {
|
|
2684
|
-
const nodesCache =
|
|
2899
|
+
const nodesCache = path11.resolve(cacheDir, "nodes");
|
|
2685
2900
|
const defVarNames = [];
|
|
2686
2901
|
for (const type of _nodeTypes) {
|
|
2687
2902
|
const varName = `__nrgNodeDef_${type.replace(/-/g, "_")}`;
|
|
2688
|
-
const userTsPath = nodesDir ?
|
|
2689
|
-
const tsPath = userTsPath &&
|
|
2903
|
+
const userTsPath = nodesDir ? path11.resolve(nodesDir, `${type}.ts`) : null;
|
|
2904
|
+
const tsPath = userTsPath && fs12.existsSync(userTsPath) ? userTsPath : path11.resolve(nodesCache, `${type}.ts`);
|
|
2690
2905
|
lines.push(`import ${varName} from ${JSON.stringify(tsPath)};`);
|
|
2691
2906
|
defVarNames.push(varName);
|
|
2692
2907
|
}
|
|
@@ -2704,8 +2919,8 @@ function nodeDefinitionsInliner(serverOutDir, entryPath, iconsDir, componentsDir
|
|
|
2704
2919
|
}
|
|
2705
2920
|
|
|
2706
2921
|
// src/vite/client/plugins/static-copy.ts
|
|
2707
|
-
import
|
|
2708
|
-
import
|
|
2922
|
+
import fs13 from "fs";
|
|
2923
|
+
import path12 from "path";
|
|
2709
2924
|
function staticCopy(options) {
|
|
2710
2925
|
const { targets } = options;
|
|
2711
2926
|
return {
|
|
@@ -2714,23 +2929,23 @@ function staticCopy(options) {
|
|
|
2714
2929
|
enforce: "post",
|
|
2715
2930
|
closeBundle() {
|
|
2716
2931
|
for (const { src, dest } of targets) {
|
|
2717
|
-
if (!
|
|
2718
|
-
|
|
2719
|
-
const stat =
|
|
2932
|
+
if (!fs13.existsSync(src)) continue;
|
|
2933
|
+
fs13.mkdirSync(dest, { recursive: true });
|
|
2934
|
+
const stat = fs13.statSync(src);
|
|
2720
2935
|
if (stat.isDirectory()) {
|
|
2721
|
-
const files =
|
|
2936
|
+
const files = fs13.readdirSync(src);
|
|
2722
2937
|
for (const file of files) {
|
|
2723
|
-
const srcFile =
|
|
2724
|
-
const destFile =
|
|
2725
|
-
const fileStat =
|
|
2938
|
+
const srcFile = path12.join(src, file);
|
|
2939
|
+
const destFile = path12.join(dest, file);
|
|
2940
|
+
const fileStat = fs13.statSync(srcFile);
|
|
2726
2941
|
if (fileStat.isDirectory()) {
|
|
2727
|
-
|
|
2942
|
+
fs13.cpSync(srcFile, destFile, { recursive: true });
|
|
2728
2943
|
} else {
|
|
2729
|
-
|
|
2944
|
+
fs13.copyFileSync(srcFile, destFile);
|
|
2730
2945
|
}
|
|
2731
2946
|
}
|
|
2732
2947
|
} else {
|
|
2733
|
-
|
|
2948
|
+
fs13.copyFileSync(src, dest);
|
|
2734
2949
|
}
|
|
2735
2950
|
}
|
|
2736
2951
|
}
|
|
@@ -2738,6 +2953,11 @@ function staticCopy(options) {
|
|
|
2738
2953
|
}
|
|
2739
2954
|
|
|
2740
2955
|
// src/vite/client/build.ts
|
|
2956
|
+
function cacheKeyFor(outDir) {
|
|
2957
|
+
const abs = path13.resolve(outDir);
|
|
2958
|
+
const hash = crypto.createHash("sha1").update(abs).digest("hex").slice(0, 8);
|
|
2959
|
+
return `${path13.basename(abs) || "client"}-${hash}`;
|
|
2960
|
+
}
|
|
2741
2961
|
async function build2(clientBuildOptions, buildContext) {
|
|
2742
2962
|
const {
|
|
2743
2963
|
srcDir = "./client",
|
|
@@ -2751,74 +2971,81 @@ async function build2(clientBuildOptions, buildContext) {
|
|
|
2751
2971
|
globals = {},
|
|
2752
2972
|
manualChunks
|
|
2753
2973
|
} = clientBuildOptions;
|
|
2754
|
-
const
|
|
2974
|
+
const cacheDir = path13.resolve(
|
|
2975
|
+
"node_modules",
|
|
2976
|
+
".nrg",
|
|
2977
|
+
"client",
|
|
2978
|
+
cacheKeyFor(buildContext.outDir)
|
|
2979
|
+
);
|
|
2980
|
+
const physicalEntryPath = path13.resolve(srcDir, entry);
|
|
2755
2981
|
let entryPath;
|
|
2756
2982
|
let generatedEntry = false;
|
|
2757
|
-
if (
|
|
2983
|
+
if (fs14.existsSync(physicalEntryPath)) {
|
|
2758
2984
|
entryPath = physicalEntryPath;
|
|
2759
2985
|
} else {
|
|
2760
|
-
const
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
fs13.mkdirSync(cacheDir, { recursive: true });
|
|
2986
|
+
const cachedEntryPath = path13.resolve(cacheDir, entry);
|
|
2987
|
+
if (!fs14.existsSync(cacheDir)) {
|
|
2988
|
+
fs14.mkdirSync(cacheDir, { recursive: true });
|
|
2764
2989
|
}
|
|
2765
|
-
|
|
2990
|
+
fs14.writeFileSync(cachedEntryPath, "// auto-generated entry\n");
|
|
2766
2991
|
entryPath = cachedEntryPath;
|
|
2767
2992
|
generatedEntry = true;
|
|
2768
2993
|
}
|
|
2769
|
-
const iconsDir =
|
|
2770
|
-
staticDirs.icons ??
|
|
2994
|
+
const iconsDir = path13.resolve(
|
|
2995
|
+
staticDirs.icons ?? path13.join(path13.dirname(path13.resolve(srcDir)), "icons")
|
|
2771
2996
|
);
|
|
2772
2997
|
const plugins = [
|
|
2773
2998
|
vue(),
|
|
2774
2999
|
nodeDefinitionsInliner(
|
|
2775
3000
|
buildContext.outDir,
|
|
2776
3001
|
entryPath,
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
!generatedEntry
|
|
3002
|
+
fs14.existsSync(iconsDir) ? iconsDir : void 0,
|
|
3003
|
+
path13.resolve(srcDir, "components"),
|
|
3004
|
+
path13.resolve(srcDir, "nodes"),
|
|
3005
|
+
!generatedEntry,
|
|
3006
|
+
cacheDir
|
|
2781
3007
|
)
|
|
2782
3008
|
];
|
|
2783
3009
|
plugins.push(
|
|
2784
3010
|
htmlGenerator({
|
|
2785
3011
|
packageName: buildContext.packageName,
|
|
2786
|
-
licensePath: licensePath ?
|
|
3012
|
+
licensePath: licensePath ? path13.resolve(licensePath) : void 0
|
|
2787
3013
|
})
|
|
2788
3014
|
);
|
|
2789
3015
|
if (locales) {
|
|
2790
3016
|
const { docsDir = "./locales/docs", labelsDir = "./locales/labels" } = locales;
|
|
2791
|
-
const localesOutDir =
|
|
3017
|
+
const localesOutDir = path13.join(buildContext.outDir, "locales");
|
|
2792
3018
|
plugins.push(
|
|
2793
3019
|
localesGenerator({
|
|
2794
3020
|
outDir: localesOutDir,
|
|
2795
|
-
docsDir:
|
|
2796
|
-
labelsDir:
|
|
3021
|
+
docsDir: path13.resolve(docsDir),
|
|
3022
|
+
labelsDir: path13.resolve(labelsDir)
|
|
2797
3023
|
})
|
|
2798
3024
|
);
|
|
2799
3025
|
plugins.push(
|
|
2800
3026
|
helpGenerator({
|
|
2801
3027
|
outDir: buildContext.outDir,
|
|
2802
3028
|
localesOutDir,
|
|
2803
|
-
docsDir:
|
|
2804
|
-
labelsDir:
|
|
3029
|
+
docsDir: path13.resolve(docsDir),
|
|
3030
|
+
labelsDir: path13.resolve(labelsDir),
|
|
3031
|
+
srcDir: buildContext.serverSrcDir
|
|
2805
3032
|
})
|
|
2806
3033
|
);
|
|
2807
3034
|
}
|
|
2808
3035
|
const copyTargets = [];
|
|
2809
|
-
const publicDir =
|
|
2810
|
-
staticDirs.public ??
|
|
3036
|
+
const publicDir = path13.resolve(
|
|
3037
|
+
staticDirs.public ?? path13.join(srcDir, "public")
|
|
2811
3038
|
);
|
|
2812
|
-
if (
|
|
3039
|
+
if (fs14.existsSync(publicDir)) {
|
|
2813
3040
|
copyTargets.push({
|
|
2814
3041
|
src: publicDir,
|
|
2815
|
-
dest:
|
|
3042
|
+
dest: path13.join(buildContext.outDir, "resources")
|
|
2816
3043
|
});
|
|
2817
3044
|
}
|
|
2818
|
-
if (
|
|
3045
|
+
if (fs14.existsSync(iconsDir)) {
|
|
2819
3046
|
copyTargets.push({
|
|
2820
3047
|
src: iconsDir,
|
|
2821
|
-
dest:
|
|
3048
|
+
dest: path13.join(buildContext.outDir, "icons")
|
|
2822
3049
|
});
|
|
2823
3050
|
}
|
|
2824
3051
|
if (copyTargets.length > 0) {
|
|
@@ -2846,10 +3073,10 @@ async function build2(clientBuildOptions, buildContext) {
|
|
|
2846
3073
|
configFile: false,
|
|
2847
3074
|
logLevel: "warn",
|
|
2848
3075
|
base: `/resources/${buildContext.packageName}`,
|
|
2849
|
-
publicDir:
|
|
3076
|
+
publicDir: path13.resolve(srcDir, "public"),
|
|
2850
3077
|
resolve: {
|
|
2851
3078
|
alias: {
|
|
2852
|
-
"@":
|
|
3079
|
+
"@": path13.resolve(srcDir)
|
|
2853
3080
|
}
|
|
2854
3081
|
},
|
|
2855
3082
|
plugins,
|
|
@@ -2903,8 +3130,8 @@ async function build2(clientBuildOptions, buildContext) {
|
|
|
2903
3130
|
throw new BuildError("client", error);
|
|
2904
3131
|
} finally {
|
|
2905
3132
|
if (generatedEntry) {
|
|
2906
|
-
if (
|
|
2907
|
-
|
|
3133
|
+
if (fs14.existsSync(entryPath)) {
|
|
3134
|
+
fs14.unlinkSync(entryPath);
|
|
2908
3135
|
}
|
|
2909
3136
|
}
|
|
2910
3137
|
}
|
|
@@ -3063,20 +3290,20 @@ function serverPlugin(options) {
|
|
|
3063
3290
|
});
|
|
3064
3291
|
logger.startGroup("Node-RED");
|
|
3065
3292
|
nodeRedLauncher.flushLogs();
|
|
3066
|
-
const serverSrcDir =
|
|
3293
|
+
const serverSrcDir = path14.resolve(
|
|
3067
3294
|
serverBuildOptions.srcDir ?? "./server"
|
|
3068
3295
|
);
|
|
3069
|
-
const clientSrcDir =
|
|
3296
|
+
const clientSrcDir = path14.resolve(
|
|
3070
3297
|
clientBuildOptions.srcDir ?? "./client"
|
|
3071
3298
|
);
|
|
3072
|
-
const localesDocsDir =
|
|
3299
|
+
const localesDocsDir = path14.resolve(
|
|
3073
3300
|
clientBuildOptions.locales?.docsDir ?? "./locales/docs"
|
|
3074
3301
|
);
|
|
3075
|
-
const localesLabelsDir =
|
|
3302
|
+
const localesLabelsDir = path14.resolve(
|
|
3076
3303
|
clientBuildOptions.locales?.labelsDir ?? "./locales/labels"
|
|
3077
3304
|
);
|
|
3078
|
-
const iconsDir =
|
|
3079
|
-
clientBuildOptions.staticDirs?.icons ??
|
|
3305
|
+
const iconsDir = path14.resolve(
|
|
3306
|
+
clientBuildOptions.staticDirs?.icons ?? path14.join(path14.dirname(clientSrcDir), "icons")
|
|
3080
3307
|
);
|
|
3081
3308
|
const watchPaths = [
|
|
3082
3309
|
serverSrcDir,
|
|
@@ -3096,7 +3323,7 @@ function serverPlugin(options) {
|
|
|
3096
3323
|
);
|
|
3097
3324
|
const handleFileChange = (file, event) => {
|
|
3098
3325
|
if (!initialStartDone) return;
|
|
3099
|
-
logger.info(`${event}: ${
|
|
3326
|
+
logger.info(`${event}: ${path14.relative(process.cwd(), file)}`);
|
|
3100
3327
|
debounceBeforeStart();
|
|
3101
3328
|
};
|
|
3102
3329
|
watcher.on("change", (file) => handleFileChange(file, "Changed"));
|
|
@@ -3190,11 +3417,12 @@ function nrg(options = {}) {
|
|
|
3190
3417
|
server.nodeRed
|
|
3191
3418
|
);
|
|
3192
3419
|
const extraFilesCopyTargets = build3.extraFilesCopyTargets ?? DEFAULT_EXTRA_FILES_COPY_TARGETS;
|
|
3193
|
-
const resolvedOutDir =
|
|
3420
|
+
const resolvedOutDir = path15.resolve(outDir);
|
|
3194
3421
|
const buildContext = {
|
|
3195
3422
|
outDir: resolvedOutDir,
|
|
3196
3423
|
packageName: getPackageName(),
|
|
3197
|
-
isDev: process.env.NODE_ENV === "development"
|
|
3424
|
+
isDev: process.env.NODE_ENV === "development",
|
|
3425
|
+
serverSrcDir: path15.resolve(serverBuildOptions.srcDir ?? "./server")
|
|
3198
3426
|
};
|
|
3199
3427
|
const nodeRedLauncher = new NodeRedLauncher(
|
|
3200
3428
|
resolvedOutDir,
|