@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/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;
|
|
@@ -2607,19 +2822,22 @@ function nodeDefinitionsInliner(serverOutDir, entryPath, iconsDir, componentsDir
|
|
|
2607
2822
|
icon: iconsDir ? resolveIcon(iconsDir, type) : void 0,
|
|
2608
2823
|
inputs: NodeClass.inputs,
|
|
2609
2824
|
outputs: NodeClass.outputs,
|
|
2825
|
+
// Resolved server-side (Kind symbol intact) so the editor labels
|
|
2826
|
+
// named output ports without guessing from the serialized schema.
|
|
2827
|
+
outputPortNames: NodeClass.outputPortNames ?? void 0,
|
|
2610
2828
|
inputSchema,
|
|
2611
2829
|
outputsSchema
|
|
2612
2830
|
};
|
|
2613
2831
|
}
|
|
2614
2832
|
if (!hasUserEntry) {
|
|
2615
|
-
const nodesCache =
|
|
2616
|
-
if (
|
|
2617
|
-
|
|
2833
|
+
const nodesCache = path11.resolve(cacheDir, "nodes");
|
|
2834
|
+
if (fs12.existsSync(nodesCache)) {
|
|
2835
|
+
fs12.rmSync(nodesCache, { recursive: true });
|
|
2618
2836
|
}
|
|
2619
|
-
|
|
2837
|
+
fs12.mkdirSync(nodesCache, { recursive: true });
|
|
2620
2838
|
for (const type of _nodeTypes) {
|
|
2621
|
-
const userTsPath = nodesDir ?
|
|
2622
|
-
if (userTsPath &&
|
|
2839
|
+
const userTsPath = nodesDir ? path11.resolve(nodesDir, `${type}.ts`) : null;
|
|
2840
|
+
if (userTsPath && fs12.existsSync(userTsPath)) continue;
|
|
2623
2841
|
const content = [
|
|
2624
2842
|
`// auto-generated by nrg`,
|
|
2625
2843
|
`import { defineNode } from "@bonsae/nrg/client";`,
|
|
@@ -2629,13 +2847,13 @@ function nodeDefinitionsInliner(serverOutDir, entryPath, iconsDir, componentsDir
|
|
|
2629
2847
|
`});`,
|
|
2630
2848
|
``
|
|
2631
2849
|
].join("\n");
|
|
2632
|
-
|
|
2850
|
+
fs12.writeFileSync(path11.resolve(nodesCache, `${type}.ts`), content);
|
|
2633
2851
|
}
|
|
2634
2852
|
const entryContent = generateEntryCode("");
|
|
2635
|
-
|
|
2853
|
+
fs12.mkdirSync(path11.dirname(path11.resolve(cacheDir, "index.ts")), {
|
|
2636
2854
|
recursive: true
|
|
2637
2855
|
});
|
|
2638
|
-
|
|
2856
|
+
fs12.writeFileSync(path11.resolve(cacheDir, "index.ts"), entryContent);
|
|
2639
2857
|
}
|
|
2640
2858
|
},
|
|
2641
2859
|
resolveId(id) {
|
|
@@ -2658,12 +2876,12 @@ function nodeDefinitionsInliner(serverOutDir, entryPath, iconsDir, componentsDir
|
|
|
2658
2876
|
const nrgImports = /* @__PURE__ */ new Set(["__setSchemas"]);
|
|
2659
2877
|
const lines = [`import __nrgSchemas from "${VIRTUAL_ID}";`];
|
|
2660
2878
|
const postLines = [`__setSchemas(__nrgSchemas);`];
|
|
2661
|
-
if (componentsDir &&
|
|
2879
|
+
if (componentsDir && fs12.existsSync(componentsDir)) {
|
|
2662
2880
|
const formImports = [];
|
|
2663
2881
|
const formEntries = [];
|
|
2664
2882
|
for (const type of _nodeTypes) {
|
|
2665
|
-
const componentPath =
|
|
2666
|
-
if (
|
|
2883
|
+
const componentPath = path11.resolve(componentsDir, `${type}.vue`);
|
|
2884
|
+
if (fs12.existsSync(componentPath)) {
|
|
2667
2885
|
const varName = `__nrgForm_${type.replace(/-/g, "_")}`;
|
|
2668
2886
|
formImports.push(
|
|
2669
2887
|
`import ${varName} from ${JSON.stringify(componentPath)};`
|
|
@@ -2678,12 +2896,12 @@ function nodeDefinitionsInliner(serverOutDir, entryPath, iconsDir, componentsDir
|
|
|
2678
2896
|
}
|
|
2679
2897
|
}
|
|
2680
2898
|
if (!hasUserEntry) {
|
|
2681
|
-
const nodesCache =
|
|
2899
|
+
const nodesCache = path11.resolve(cacheDir, "nodes");
|
|
2682
2900
|
const defVarNames = [];
|
|
2683
2901
|
for (const type of _nodeTypes) {
|
|
2684
2902
|
const varName = `__nrgNodeDef_${type.replace(/-/g, "_")}`;
|
|
2685
|
-
const userTsPath = nodesDir ?
|
|
2686
|
-
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`);
|
|
2687
2905
|
lines.push(`import ${varName} from ${JSON.stringify(tsPath)};`);
|
|
2688
2906
|
defVarNames.push(varName);
|
|
2689
2907
|
}
|
|
@@ -2701,8 +2919,8 @@ function nodeDefinitionsInliner(serverOutDir, entryPath, iconsDir, componentsDir
|
|
|
2701
2919
|
}
|
|
2702
2920
|
|
|
2703
2921
|
// src/vite/client/plugins/static-copy.ts
|
|
2704
|
-
import
|
|
2705
|
-
import
|
|
2922
|
+
import fs13 from "fs";
|
|
2923
|
+
import path12 from "path";
|
|
2706
2924
|
function staticCopy(options) {
|
|
2707
2925
|
const { targets } = options;
|
|
2708
2926
|
return {
|
|
@@ -2711,23 +2929,23 @@ function staticCopy(options) {
|
|
|
2711
2929
|
enforce: "post",
|
|
2712
2930
|
closeBundle() {
|
|
2713
2931
|
for (const { src, dest } of targets) {
|
|
2714
|
-
if (!
|
|
2715
|
-
|
|
2716
|
-
const stat =
|
|
2932
|
+
if (!fs13.existsSync(src)) continue;
|
|
2933
|
+
fs13.mkdirSync(dest, { recursive: true });
|
|
2934
|
+
const stat = fs13.statSync(src);
|
|
2717
2935
|
if (stat.isDirectory()) {
|
|
2718
|
-
const files =
|
|
2936
|
+
const files = fs13.readdirSync(src);
|
|
2719
2937
|
for (const file of files) {
|
|
2720
|
-
const srcFile =
|
|
2721
|
-
const destFile =
|
|
2722
|
-
const fileStat =
|
|
2938
|
+
const srcFile = path12.join(src, file);
|
|
2939
|
+
const destFile = path12.join(dest, file);
|
|
2940
|
+
const fileStat = fs13.statSync(srcFile);
|
|
2723
2941
|
if (fileStat.isDirectory()) {
|
|
2724
|
-
|
|
2942
|
+
fs13.cpSync(srcFile, destFile, { recursive: true });
|
|
2725
2943
|
} else {
|
|
2726
|
-
|
|
2944
|
+
fs13.copyFileSync(srcFile, destFile);
|
|
2727
2945
|
}
|
|
2728
2946
|
}
|
|
2729
2947
|
} else {
|
|
2730
|
-
|
|
2948
|
+
fs13.copyFileSync(src, dest);
|
|
2731
2949
|
}
|
|
2732
2950
|
}
|
|
2733
2951
|
}
|
|
@@ -2735,6 +2953,11 @@ function staticCopy(options) {
|
|
|
2735
2953
|
}
|
|
2736
2954
|
|
|
2737
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
|
+
}
|
|
2738
2961
|
async function build2(clientBuildOptions, buildContext) {
|
|
2739
2962
|
const {
|
|
2740
2963
|
srcDir = "./client",
|
|
@@ -2748,74 +2971,81 @@ async function build2(clientBuildOptions, buildContext) {
|
|
|
2748
2971
|
globals = {},
|
|
2749
2972
|
manualChunks
|
|
2750
2973
|
} = clientBuildOptions;
|
|
2751
|
-
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);
|
|
2752
2981
|
let entryPath;
|
|
2753
2982
|
let generatedEntry = false;
|
|
2754
|
-
if (
|
|
2983
|
+
if (fs14.existsSync(physicalEntryPath)) {
|
|
2755
2984
|
entryPath = physicalEntryPath;
|
|
2756
2985
|
} else {
|
|
2757
|
-
const
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
fs13.mkdirSync(cacheDir, { recursive: true });
|
|
2986
|
+
const cachedEntryPath = path13.resolve(cacheDir, entry);
|
|
2987
|
+
if (!fs14.existsSync(cacheDir)) {
|
|
2988
|
+
fs14.mkdirSync(cacheDir, { recursive: true });
|
|
2761
2989
|
}
|
|
2762
|
-
|
|
2990
|
+
fs14.writeFileSync(cachedEntryPath, "// auto-generated entry\n");
|
|
2763
2991
|
entryPath = cachedEntryPath;
|
|
2764
2992
|
generatedEntry = true;
|
|
2765
2993
|
}
|
|
2766
|
-
const iconsDir =
|
|
2767
|
-
staticDirs.icons ??
|
|
2994
|
+
const iconsDir = path13.resolve(
|
|
2995
|
+
staticDirs.icons ?? path13.join(path13.dirname(path13.resolve(srcDir)), "icons")
|
|
2768
2996
|
);
|
|
2769
2997
|
const plugins = [
|
|
2770
2998
|
vue(),
|
|
2771
2999
|
nodeDefinitionsInliner(
|
|
2772
3000
|
buildContext.outDir,
|
|
2773
3001
|
entryPath,
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
!generatedEntry
|
|
3002
|
+
fs14.existsSync(iconsDir) ? iconsDir : void 0,
|
|
3003
|
+
path13.resolve(srcDir, "components"),
|
|
3004
|
+
path13.resolve(srcDir, "nodes"),
|
|
3005
|
+
!generatedEntry,
|
|
3006
|
+
cacheDir
|
|
2778
3007
|
)
|
|
2779
3008
|
];
|
|
2780
3009
|
plugins.push(
|
|
2781
3010
|
htmlGenerator({
|
|
2782
3011
|
packageName: buildContext.packageName,
|
|
2783
|
-
licensePath: licensePath ?
|
|
3012
|
+
licensePath: licensePath ? path13.resolve(licensePath) : void 0
|
|
2784
3013
|
})
|
|
2785
3014
|
);
|
|
2786
3015
|
if (locales) {
|
|
2787
3016
|
const { docsDir = "./locales/docs", labelsDir = "./locales/labels" } = locales;
|
|
2788
|
-
const localesOutDir =
|
|
3017
|
+
const localesOutDir = path13.join(buildContext.outDir, "locales");
|
|
2789
3018
|
plugins.push(
|
|
2790
3019
|
localesGenerator({
|
|
2791
3020
|
outDir: localesOutDir,
|
|
2792
|
-
docsDir:
|
|
2793
|
-
labelsDir:
|
|
3021
|
+
docsDir: path13.resolve(docsDir),
|
|
3022
|
+
labelsDir: path13.resolve(labelsDir)
|
|
2794
3023
|
})
|
|
2795
3024
|
);
|
|
2796
3025
|
plugins.push(
|
|
2797
3026
|
helpGenerator({
|
|
2798
3027
|
outDir: buildContext.outDir,
|
|
2799
3028
|
localesOutDir,
|
|
2800
|
-
docsDir:
|
|
2801
|
-
labelsDir:
|
|
3029
|
+
docsDir: path13.resolve(docsDir),
|
|
3030
|
+
labelsDir: path13.resolve(labelsDir),
|
|
3031
|
+
srcDir: buildContext.serverSrcDir
|
|
2802
3032
|
})
|
|
2803
3033
|
);
|
|
2804
3034
|
}
|
|
2805
3035
|
const copyTargets = [];
|
|
2806
|
-
const publicDir =
|
|
2807
|
-
staticDirs.public ??
|
|
3036
|
+
const publicDir = path13.resolve(
|
|
3037
|
+
staticDirs.public ?? path13.join(srcDir, "public")
|
|
2808
3038
|
);
|
|
2809
|
-
if (
|
|
3039
|
+
if (fs14.existsSync(publicDir)) {
|
|
2810
3040
|
copyTargets.push({
|
|
2811
3041
|
src: publicDir,
|
|
2812
|
-
dest:
|
|
3042
|
+
dest: path13.join(buildContext.outDir, "resources")
|
|
2813
3043
|
});
|
|
2814
3044
|
}
|
|
2815
|
-
if (
|
|
3045
|
+
if (fs14.existsSync(iconsDir)) {
|
|
2816
3046
|
copyTargets.push({
|
|
2817
3047
|
src: iconsDir,
|
|
2818
|
-
dest:
|
|
3048
|
+
dest: path13.join(buildContext.outDir, "icons")
|
|
2819
3049
|
});
|
|
2820
3050
|
}
|
|
2821
3051
|
if (copyTargets.length > 0) {
|
|
@@ -2843,10 +3073,10 @@ async function build2(clientBuildOptions, buildContext) {
|
|
|
2843
3073
|
configFile: false,
|
|
2844
3074
|
logLevel: "warn",
|
|
2845
3075
|
base: `/resources/${buildContext.packageName}`,
|
|
2846
|
-
publicDir:
|
|
3076
|
+
publicDir: path13.resolve(srcDir, "public"),
|
|
2847
3077
|
resolve: {
|
|
2848
3078
|
alias: {
|
|
2849
|
-
"@":
|
|
3079
|
+
"@": path13.resolve(srcDir)
|
|
2850
3080
|
}
|
|
2851
3081
|
},
|
|
2852
3082
|
plugins,
|
|
@@ -2900,8 +3130,8 @@ async function build2(clientBuildOptions, buildContext) {
|
|
|
2900
3130
|
throw new BuildError("client", error);
|
|
2901
3131
|
} finally {
|
|
2902
3132
|
if (generatedEntry) {
|
|
2903
|
-
if (
|
|
2904
|
-
|
|
3133
|
+
if (fs14.existsSync(entryPath)) {
|
|
3134
|
+
fs14.unlinkSync(entryPath);
|
|
2905
3135
|
}
|
|
2906
3136
|
}
|
|
2907
3137
|
}
|
|
@@ -3060,20 +3290,20 @@ function serverPlugin(options) {
|
|
|
3060
3290
|
});
|
|
3061
3291
|
logger.startGroup("Node-RED");
|
|
3062
3292
|
nodeRedLauncher.flushLogs();
|
|
3063
|
-
const serverSrcDir =
|
|
3293
|
+
const serverSrcDir = path14.resolve(
|
|
3064
3294
|
serverBuildOptions.srcDir ?? "./server"
|
|
3065
3295
|
);
|
|
3066
|
-
const clientSrcDir =
|
|
3296
|
+
const clientSrcDir = path14.resolve(
|
|
3067
3297
|
clientBuildOptions.srcDir ?? "./client"
|
|
3068
3298
|
);
|
|
3069
|
-
const localesDocsDir =
|
|
3299
|
+
const localesDocsDir = path14.resolve(
|
|
3070
3300
|
clientBuildOptions.locales?.docsDir ?? "./locales/docs"
|
|
3071
3301
|
);
|
|
3072
|
-
const localesLabelsDir =
|
|
3302
|
+
const localesLabelsDir = path14.resolve(
|
|
3073
3303
|
clientBuildOptions.locales?.labelsDir ?? "./locales/labels"
|
|
3074
3304
|
);
|
|
3075
|
-
const iconsDir =
|
|
3076
|
-
clientBuildOptions.staticDirs?.icons ??
|
|
3305
|
+
const iconsDir = path14.resolve(
|
|
3306
|
+
clientBuildOptions.staticDirs?.icons ?? path14.join(path14.dirname(clientSrcDir), "icons")
|
|
3077
3307
|
);
|
|
3078
3308
|
const watchPaths = [
|
|
3079
3309
|
serverSrcDir,
|
|
@@ -3093,7 +3323,7 @@ function serverPlugin(options) {
|
|
|
3093
3323
|
);
|
|
3094
3324
|
const handleFileChange = (file, event) => {
|
|
3095
3325
|
if (!initialStartDone) return;
|
|
3096
|
-
logger.info(`${event}: ${
|
|
3326
|
+
logger.info(`${event}: ${path14.relative(process.cwd(), file)}`);
|
|
3097
3327
|
debounceBeforeStart();
|
|
3098
3328
|
};
|
|
3099
3329
|
watcher.on("change", (file) => handleFileChange(file, "Changed"));
|
|
@@ -3187,11 +3417,12 @@ function nrg(options = {}) {
|
|
|
3187
3417
|
server.nodeRed
|
|
3188
3418
|
);
|
|
3189
3419
|
const extraFilesCopyTargets = build3.extraFilesCopyTargets ?? DEFAULT_EXTRA_FILES_COPY_TARGETS;
|
|
3190
|
-
const resolvedOutDir =
|
|
3420
|
+
const resolvedOutDir = path15.resolve(outDir);
|
|
3191
3421
|
const buildContext = {
|
|
3192
3422
|
outDir: resolvedOutDir,
|
|
3193
3423
|
packageName: getPackageName(),
|
|
3194
|
-
isDev: process.env.NODE_ENV === "development"
|
|
3424
|
+
isDev: process.env.NODE_ENV === "development",
|
|
3425
|
+
serverSrcDir: path15.resolve(serverBuildOptions.srcDir ?? "./server")
|
|
3195
3426
|
};
|
|
3196
3427
|
const nodeRedLauncher = new NodeRedLauncher(
|
|
3197
3428
|
resolvedOutDir,
|