@bonsae/nrg 0.13.1 → 0.14.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/vite/index.js CHANGED
@@ -88,7 +88,9 @@ function mergeOptions(defaults, overrides) {
88
88
  for (const key of Object.keys(overrides)) {
89
89
  const overrideVal = overrides[key];
90
90
  const defaultVal = defaults[key];
91
- if (overrideVal !== void 0 && !Array.isArray(overrideVal) && !Array.isArray(defaultVal) && typeof overrideVal === "object" && typeof defaultVal === "object" && overrideVal !== null && defaultVal !== null) {
91
+ if (overrideVal !== void 0 && Array.isArray(overrideVal) && Array.isArray(defaultVal)) {
92
+ result[key] = [.../* @__PURE__ */ new Set([...defaultVal, ...overrideVal])];
93
+ } else if (overrideVal !== void 0 && !Array.isArray(overrideVal) && !Array.isArray(defaultVal) && typeof overrideVal === "object" && typeof defaultVal === "object" && overrideVal !== null && defaultVal !== null) {
92
94
  result[key] = mergeOptions(
93
95
  defaultVal,
94
96
  overrideVal
@@ -105,7 +107,7 @@ import { spawn } from "child_process";
105
107
  import getPort from "get-port";
106
108
  import detect from "detect-port";
107
109
  import { builtinModules } from "module";
108
- import treeKill2 from "tree-kill";
110
+ import treeKill from "tree-kill";
109
111
  import fs2 from "fs";
110
112
  import os from "os";
111
113
  import path2 from "path";
@@ -290,7 +292,7 @@ var NodeRedLauncher = class {
290
292
  return "node-red";
291
293
  }
292
294
  findRuntimeSettingsFilepath() {
293
- const runtimeSettingsFilepath = this.options.runtime.settingsFilepath;
295
+ const runtimeSettingsFilepath = this.options.runtime?.settingsFilepath;
294
296
  if (runtimeSettingsFilepath) {
295
297
  const resolved2 = path2.resolve(runtimeSettingsFilepath);
296
298
  if (fs2.existsSync(resolved2)) {
@@ -426,7 +428,7 @@ module.exports = settings;
426
428
  }
427
429
  if (line.includes("Started flows") || line.includes("Server now running")) {
428
430
  this.isReady = true;
429
- resolve();
431
+ resolve(void 0);
430
432
  }
431
433
  }
432
434
  });
@@ -451,7 +453,7 @@ module.exports = settings;
451
453
  )
452
454
  );
453
455
  }
454
- resolve();
456
+ resolve(void 0);
455
457
  });
456
458
  } catch (error) {
457
459
  reject(new NodeRedStartError(error));
@@ -465,7 +467,7 @@ module.exports = settings;
465
467
  if (this.process) {
466
468
  const pid = this.process.pid;
467
469
  if (pid) {
468
- treeKill2(pid, "SIGKILL");
470
+ treeKill(pid, "SIGKILL");
469
471
  }
470
472
  this.process = null;
471
473
  }
@@ -483,15 +485,15 @@ module.exports = settings;
483
485
  const stopProcess = new Promise((resolve) => {
484
486
  this.process.once("exit", () => {
485
487
  this.process = null;
486
- resolve();
488
+ resolve(void 0);
487
489
  });
488
- treeKill2(pid, "SIGTERM", (error) => {
490
+ treeKill(pid, "SIGTERM", (error) => {
489
491
  if (error) {
490
492
  try {
491
493
  process.kill(pid, "SIGTERM");
492
494
  } catch {
493
495
  this.process = null;
494
- resolve();
496
+ resolve(void 0);
495
497
  }
496
498
  }
497
499
  });
@@ -501,9 +503,9 @@ module.exports = settings;
501
503
  } catch {
502
504
  this.logger.warn("Graceful shutdown timed out, force killing...");
503
505
  await new Promise((resolve) => {
504
- treeKill2(pid, "SIGKILL", () => {
506
+ treeKill(pid, "SIGKILL", () => {
505
507
  this.process = null;
506
- resolve();
508
+ resolve(void 0);
507
509
  });
508
510
  });
509
511
  }
@@ -522,7 +524,7 @@ module.exports = settings;
522
524
  );
523
525
  if (pid) {
524
526
  await new Promise((resolve) => {
525
- treeKill2(pid, "SIGKILL", () => resolve());
527
+ treeKill(pid, "SIGKILL", () => resolve());
526
528
  });
527
529
  await new Promise((resolve) => setTimeout(resolve, 1e3));
528
530
  }
@@ -546,6 +548,7 @@ module.exports = settings;
546
548
 
547
549
  // src/vite/plugins/server.ts
548
550
  import chokidar from "chokidar";
551
+ import treeKill2 from "tree-kill";
549
552
  import path12 from "path";
550
553
 
551
554
  // src/vite/server/build.ts
@@ -711,6 +714,32 @@ function getSchemaReferences(filePath) {
711
714
  }
712
715
  return result;
713
716
  }
717
+ function getFactoryInfo(filePath) {
718
+ const content = fs3.readFileSync(filePath, "utf-8");
719
+ const source = ts.createSourceFile(
720
+ filePath,
721
+ content,
722
+ ts.ScriptTarget.ESNext,
723
+ true
724
+ );
725
+ for (const stmt of source.statements) {
726
+ if (ts.isExportAssignment(stmt) && stmt.expression && ts.isCallExpression(stmt.expression)) {
727
+ const callee = stmt.expression.expression;
728
+ if (ts.isIdentifier(callee)) {
729
+ if (callee.text === "defineIONode" || callee.text === "defineConfigNode") {
730
+ return { factoryName: callee.text };
731
+ }
732
+ }
733
+ }
734
+ }
735
+ return null;
736
+ }
737
+ function buildTypeArg(schemaMap, semanticName) {
738
+ const names = schemaMap.get(semanticName);
739
+ if (!names || names.length === 0) return "any";
740
+ if (names.length === 1) return `Infer<typeof ${names[0]}>`;
741
+ return `[${names.map((n) => `Infer<typeof ${n}>`).join(", ")}]`;
742
+ }
714
743
  function buildNodeReexports(srcDir, entryFile) {
715
744
  const nodesDir = path3.join(srcDir, "nodes");
716
745
  const nodeFiles = collectTsFiles(nodesDir);
@@ -719,15 +748,68 @@ function buildNodeReexports(srcDir, entryFile) {
719
748
  const relPath = rel.startsWith(".") ? rel : `./${rel}`;
720
749
  const specifier = relPath.replace(/\.ts$/, "");
721
750
  const ns = toPascalCase(path3.basename(file, ".ts"));
722
- const lines = [`export { default as ${ns} } from "${specifier}";`];
723
- const typePairs = getNodeTypeExports(file);
724
- if (typePairs.length > 0) {
725
- const prefixed = typePairs.map(
726
- ({ localName, semanticName }) => `${localName} as ${ns}${semanticName}`
727
- ).join(", ");
728
- lines.push(`export type { ${prefixed} } from "${specifier}";`);
729
- }
730
751
  const schemaRefs = getSchemaReferences(file);
752
+ const factoryInfo = getFactoryInfo(file);
753
+ const lines = [];
754
+ if (factoryInfo) {
755
+ const interfaceName = factoryInfo.factoryName === "defineIONode" ? "IIONode" : "IConfigNode";
756
+ lines.push(`import _${ns} from "${specifier}";`);
757
+ const schemaMap = /* @__PURE__ */ new Map();
758
+ for (const ref of schemaRefs) {
759
+ const key = ref.tupleProp ?? ref.semanticName;
760
+ if (!schemaMap.has(key)) schemaMap.set(key, []);
761
+ schemaMap.get(key).push(ref.localName);
762
+ }
763
+ const hasSchemas = schemaMap.size > 0;
764
+ const nrgImports = ["NodeConstructor", interfaceName];
765
+ if (hasSchemas) nrgImports.push("Infer");
766
+ lines.push(
767
+ `import type { ${nrgImports.join(", ")} } from "@bonsae/nrg/server";`
768
+ );
769
+ if (hasSchemas) {
770
+ const bySource2 = /* @__PURE__ */ new Map();
771
+ for (const ref of schemaRefs) {
772
+ const resolvedSource = path3.relative(
773
+ path3.dirname(entryFile),
774
+ path3.resolve(path3.dirname(file), ref.importSource)
775
+ ).replace(/\\/g, "/");
776
+ const sourceSpecifier = resolvedSource.startsWith(".") ? resolvedSource : `./${resolvedSource}`;
777
+ if (!bySource2.has(sourceSpecifier))
778
+ bySource2.set(sourceSpecifier, []);
779
+ const list = bySource2.get(sourceSpecifier);
780
+ if (!list.includes(ref.localName)) list.push(ref.localName);
781
+ }
782
+ for (const [source, names] of bySource2) {
783
+ lines.push(`import type { ${names.join(", ")} } from "${source}";`);
784
+ }
785
+ }
786
+ let typeArgs;
787
+ if (factoryInfo.factoryName === "defineIONode") {
788
+ typeArgs = [
789
+ buildTypeArg(schemaMap, "ConfigSchema"),
790
+ buildTypeArg(schemaMap, "CredentialsSchema"),
791
+ buildTypeArg(schemaMap, "InputSchema"),
792
+ buildTypeArg(schemaMap, "OutputsSchema")
793
+ ].join(", ");
794
+ } else {
795
+ typeArgs = [
796
+ buildTypeArg(schemaMap, "ConfigSchema"),
797
+ buildTypeArg(schemaMap, "CredentialsSchema")
798
+ ].join(", ");
799
+ }
800
+ lines.push(
801
+ `export const ${ns}: NodeConstructor<${interfaceName}<${typeArgs}>> = _${ns};`
802
+ );
803
+ } else {
804
+ lines.push(`export { default as ${ns} } from "${specifier}";`);
805
+ const typePairs = getNodeTypeExports(file);
806
+ if (typePairs.length > 0) {
807
+ const prefixed = typePairs.map(
808
+ ({ localName, semanticName }) => `${localName} as ${ns}${semanticName}`
809
+ ).join(", ");
810
+ lines.push(`export type { ${prefixed} } from "${specifier}";`);
811
+ }
812
+ }
731
813
  const bySource = /* @__PURE__ */ new Map();
732
814
  for (const ref of schemaRefs) {
733
815
  const resolvedSource = path3.relative(
@@ -1038,10 +1120,10 @@ async function build(serverOpts, buildContext) {
1038
1120
  srcDir = "./server",
1039
1121
  entry = "index.ts",
1040
1122
  format = "esm",
1123
+ external = [],
1041
1124
  bundled = [],
1042
1125
  types = true,
1043
- nodeTarget = "node22",
1044
- plugins: userPlugins = []
1126
+ nodeTarget = "node22"
1045
1127
  } = serverOpts;
1046
1128
  const entries = Array.isArray(entry) ? entry : [entry];
1047
1129
  const resolvedSrcDir = path5.resolve(srcDir);
@@ -1066,8 +1148,7 @@ async function build(serverOpts, buildContext) {
1066
1148
  entryNames: Object.keys(entryPoints),
1067
1149
  format
1068
1150
  }),
1069
- isEsm ? esmWrapper() : cjsWrapper(),
1070
- ...userPlugins
1151
+ isEsm ? esmWrapper() : cjsWrapper()
1071
1152
  ];
1072
1153
  if (types && !buildContext.isDev) {
1073
1154
  plugins.push(
@@ -1092,6 +1173,7 @@ async function build(serverOpts, buildContext) {
1092
1173
  formats: [isEsm ? "es" : "cjs"]
1093
1174
  },
1094
1175
  rollupOptions: {
1176
+ external,
1095
1177
  output: {
1096
1178
  entryFileNames: isEsm ? "[name].mjs" : "[name].js",
1097
1179
  exports: isEsm ? void 0 : "auto",
@@ -1664,6 +1746,7 @@ ${resourcesTags}`
1664
1746
  // src/vite/client/plugins/locales-generator.ts
1665
1747
  import fs8 from "fs";
1666
1748
  import path8 from "path";
1749
+ import { merge } from "es-toolkit";
1667
1750
  function localesGenerator(options) {
1668
1751
  const { outDir, docsDir, labelsDir } = options;
1669
1752
  const languages = [
@@ -1678,6 +1761,108 @@ function localesGenerator(options) {
1678
1761
  "zh-CN",
1679
1762
  "zh-TW"
1680
1763
  ];
1764
+ const frameworkLabels = {
1765
+ "en-US": {
1766
+ configs: { name: "Name" },
1767
+ toggles: {
1768
+ validateInput: "Validate Input",
1769
+ validateOutput: "Validate Output",
1770
+ errorPort: "Error Port",
1771
+ completePort: "Complete Port",
1772
+ statusPort: "Status Port"
1773
+ }
1774
+ },
1775
+ de: {
1776
+ configs: { name: "Name" },
1777
+ toggles: {
1778
+ validateInput: "Eingabe validieren",
1779
+ validateOutput: "Ausgabe validieren",
1780
+ errorPort: "Fehler-Port",
1781
+ completePort: "Abschluss-Port",
1782
+ statusPort: "Status-Port"
1783
+ }
1784
+ },
1785
+ "es-ES": {
1786
+ configs: { name: "Nombre" },
1787
+ toggles: {
1788
+ validateInput: "Validar entrada",
1789
+ validateOutput: "Validar salida",
1790
+ errorPort: "Puerto de error",
1791
+ completePort: "Puerto de completado",
1792
+ statusPort: "Puerto de estado"
1793
+ }
1794
+ },
1795
+ fr: {
1796
+ configs: { name: "Nom" },
1797
+ toggles: {
1798
+ validateInput: "Valider l'entr\xE9e",
1799
+ validateOutput: "Valider la sortie",
1800
+ errorPort: "Port d'erreur",
1801
+ completePort: "Port de compl\xE9tion",
1802
+ statusPort: "Port de statut"
1803
+ }
1804
+ },
1805
+ ko: {
1806
+ configs: { name: "\uC774\uB984" },
1807
+ toggles: {
1808
+ validateInput: "\uC785\uB825 \uAC80\uC99D",
1809
+ validateOutput: "\uCD9C\uB825 \uAC80\uC99D",
1810
+ errorPort: "\uC624\uB958 \uD3EC\uD2B8",
1811
+ completePort: "\uC644\uB8CC \uD3EC\uD2B8",
1812
+ statusPort: "\uC0C1\uD0DC \uD3EC\uD2B8"
1813
+ }
1814
+ },
1815
+ "pt-BR": {
1816
+ configs: { name: "Nome" },
1817
+ toggles: {
1818
+ validateInput: "Validar Entrada",
1819
+ validateOutput: "Validar Sa\xEDda",
1820
+ errorPort: "Porta de Erro",
1821
+ completePort: "Porta de Conclus\xE3o",
1822
+ statusPort: "Porta de Status"
1823
+ }
1824
+ },
1825
+ ru: {
1826
+ configs: { name: "\u0418\u043C\u044F" },
1827
+ toggles: {
1828
+ validateInput: "\u041F\u0440\u043E\u0432\u0435\u0440\u0438\u0442\u044C \u0432\u0445\u043E\u0434",
1829
+ validateOutput: "\u041F\u0440\u043E\u0432\u0435\u0440\u0438\u0442\u044C \u0432\u044B\u0445\u043E\u0434",
1830
+ errorPort: "\u041F\u043E\u0440\u0442 \u043E\u0448\u0438\u0431\u043A\u0438",
1831
+ completePort: "\u041F\u043E\u0440\u0442 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043D\u0438\u044F",
1832
+ statusPort: "\u041F\u043E\u0440\u0442 \u0441\u0442\u0430\u0442\u0443\u0441\u0430"
1833
+ }
1834
+ },
1835
+ ja: {
1836
+ configs: { name: "\u540D\u524D" },
1837
+ toggles: {
1838
+ validateInput: "\u5165\u529B\u691C\u8A3C",
1839
+ validateOutput: "\u51FA\u529B\u691C\u8A3C",
1840
+ errorPort: "\u30A8\u30E9\u30FC\u30DD\u30FC\u30C8",
1841
+ completePort: "\u5B8C\u4E86\u30DD\u30FC\u30C8",
1842
+ statusPort: "\u30B9\u30C6\u30FC\u30BF\u30B9\u30DD\u30FC\u30C8"
1843
+ }
1844
+ },
1845
+ "zh-CN": {
1846
+ configs: { name: "\u540D\u79F0" },
1847
+ toggles: {
1848
+ validateInput: "\u9A8C\u8BC1\u8F93\u5165",
1849
+ validateOutput: "\u9A8C\u8BC1\u8F93\u51FA",
1850
+ errorPort: "\u9519\u8BEF\u7AEF\u53E3",
1851
+ completePort: "\u5B8C\u6210\u7AEF\u53E3",
1852
+ statusPort: "\u72B6\u6001\u7AEF\u53E3"
1853
+ }
1854
+ },
1855
+ "zh-TW": {
1856
+ configs: { name: "\u540D\u7A31" },
1857
+ toggles: {
1858
+ validateInput: "\u9A57\u8B49\u8F38\u5165",
1859
+ validateOutput: "\u9A57\u8B49\u8F38\u51FA",
1860
+ errorPort: "\u932F\u8AA4\u7AEF\u53E3",
1861
+ completePort: "\u5B8C\u6210\u7AEF\u53E3",
1862
+ statusPort: "\u72C0\u614B\u7AEF\u53E3"
1863
+ }
1864
+ }
1865
+ };
1681
1866
  return {
1682
1867
  name: "vite-plugin-node-red:client:locales-generator",
1683
1868
  apply: "build",
@@ -1762,6 +1947,15 @@ ${content}
1762
1947
  return parsed;
1763
1948
  }
1764
1949
  );
1950
+ for (const [lang, nodeTypes] of labelLangs.entries()) {
1951
+ const defaults = frameworkLabels[lang] ?? frameworkLabels["en-US"];
1952
+ for (const nodeType of Object.keys(nodeTypes)) {
1953
+ nodeTypes[nodeType] = merge(
1954
+ structuredClone(defaults),
1955
+ nodeTypes[nodeType]
1956
+ );
1957
+ }
1958
+ }
1765
1959
  writeOutput(
1766
1960
  labelLangs,
1767
1961
  "index.json",
@@ -2025,10 +2219,9 @@ async function build2(clientBuildOptions, buildContext) {
2025
2219
  licensePath = "./LICENSE",
2026
2220
  locales,
2027
2221
  staticDirs = {},
2028
- external = ["jquery", "node-red", "vue"],
2029
- globals = { jquery: "$", "node-red": "RED", vue: "Vue" },
2030
- manualChunks,
2031
- plugins: userPlugins = []
2222
+ external = [],
2223
+ globals = {},
2224
+ manualChunks
2032
2225
  } = clientBuildOptions;
2033
2226
  const physicalEntryPath = path11.resolve(srcDir, entry);
2034
2227
  let entryPath;
@@ -2057,8 +2250,7 @@ async function build2(clientBuildOptions, buildContext) {
2057
2250
  path11.resolve(srcDir, "components"),
2058
2251
  path11.resolve(srcDir, "nodes"),
2059
2252
  !generatedEntry
2060
- ),
2061
- ...userPlugins
2253
+ )
2062
2254
  ];
2063
2255
  plugins.push(
2064
2256
  htmlGenerator({
@@ -2385,7 +2577,7 @@ function serverPlugin(options) {
2385
2577
  const pid = nodeRedLauncher.pid;
2386
2578
  if (pid) {
2387
2579
  try {
2388
- treeKill(pid, "SIGKILL");
2580
+ treeKill2(pid, "SIGKILL");
2389
2581
  } catch {
2390
2582
  }
2391
2583
  }