@bonsae/nrg 0.6.1 → 0.6.2

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.
Files changed (84) hide show
  1. package/README.md +5 -5
  2. package/package.json +13 -77
  3. package/{src/core/client → shims}/components.d.ts +2 -0
  4. package/{src/tsconfig → tsconfig}/client.json +3 -3
  5. package/types/client.d.ts +37 -0
  6. package/types/index.d.ts +211 -0
  7. package/types/server.d.ts +2293 -0
  8. package/types/vite.d.ts +12 -0
  9. package/build/vite/utils.js +0 -56
  10. package/src/core/client/app.vue +0 -185
  11. package/src/core/client/components/node-red-config-input.vue +0 -79
  12. package/src/core/client/components/node-red-editor-input.vue +0 -307
  13. package/src/core/client/components/node-red-input-label.vue +0 -53
  14. package/src/core/client/components/node-red-input.vue +0 -93
  15. package/src/core/client/components/node-red-json-schema-form.vue +0 -444
  16. package/src/core/client/components/node-red-select-input.vue +0 -108
  17. package/src/core/client/components/node-red-toggle.vue +0 -115
  18. package/src/core/client/components/node-red-typed-input.vue +0 -158
  19. package/src/core/client/index.ts +0 -500
  20. package/src/core/client/tsconfig.json +0 -18
  21. package/src/core/constants.ts +0 -18
  22. package/src/core/errors.ts +0 -9
  23. package/src/core/server/api/index.ts +0 -1
  24. package/src/core/server/api/serve-nrg-resources.ts +0 -54
  25. package/src/core/server/index.ts +0 -191
  26. package/src/core/server/nodes/config-node.ts +0 -67
  27. package/src/core/server/nodes/factories.ts +0 -136
  28. package/src/core/server/nodes/index.ts +0 -5
  29. package/src/core/server/nodes/io-node.ts +0 -179
  30. package/src/core/server/nodes/node.ts +0 -259
  31. package/src/core/server/nodes/types/config-node.ts +0 -28
  32. package/src/core/server/nodes/types/factories.ts +0 -130
  33. package/src/core/server/nodes/types/index.ts +0 -4
  34. package/src/core/server/nodes/types/io-node.ts +0 -40
  35. package/src/core/server/nodes/types/node.ts +0 -41
  36. package/src/core/server/nodes/utils.ts +0 -106
  37. package/src/core/server/schemas/base.ts +0 -66
  38. package/src/core/server/schemas/index.ts +0 -3
  39. package/src/core/server/schemas/type.ts +0 -95
  40. package/src/core/server/schemas/types/index.ts +0 -82
  41. package/src/core/server/tsconfig.json +0 -17
  42. package/src/core/server/types/index.ts +0 -220
  43. package/src/core/server/utils.ts +0 -56
  44. package/src/core/server/validator.ts +0 -36
  45. package/src/core/validator.ts +0 -222
  46. package/src/index.ts +0 -2
  47. package/src/types.ts +0 -189
  48. package/src/utils.ts +0 -20
  49. package/src/vite/async-utils.ts +0 -61
  50. package/src/vite/client/build.ts +0 -227
  51. package/src/vite/client/index.ts +0 -1
  52. package/src/vite/client/plugins/html-generator.ts +0 -75
  53. package/src/vite/client/plugins/index.ts +0 -5
  54. package/src/vite/client/plugins/locales-generator.ts +0 -126
  55. package/src/vite/client/plugins/minifier.ts +0 -23
  56. package/src/vite/client/plugins/node-definitions-inliner.ts +0 -275
  57. package/src/vite/client/plugins/static-copy.ts +0 -43
  58. package/src/vite/defaults.ts +0 -77
  59. package/src/vite/errors.ts +0 -37
  60. package/src/vite/index.ts +0 -2
  61. package/src/vite/logger.ts +0 -94
  62. package/src/vite/node-red-launcher.ts +0 -344
  63. package/src/vite/plugin.ts +0 -61
  64. package/src/vite/plugins/build.ts +0 -85
  65. package/src/vite/plugins/index.ts +0 -2
  66. package/src/vite/plugins/server.ts +0 -267
  67. package/src/vite/server/build.ts +0 -124
  68. package/src/vite/server/index.ts +0 -1
  69. package/src/vite/server/plugins/index.ts +0 -3
  70. package/src/vite/server/plugins/output-wrapper.ts +0 -109
  71. package/src/vite/server/plugins/package-json-generator.ts +0 -203
  72. package/src/vite/server/plugins/type-generator.ts +0 -442
  73. package/src/vite/types.ts +0 -174
  74. package/src/vite/utils.ts +0 -72
  75. /package/{build/index.js → index.js} +0 -0
  76. /package/{build/server → server}/index.cjs +0 -0
  77. /package/{build/server → server}/resources/nrg-client.js +0 -0
  78. /package/{build/server → server}/resources/vue.esm-browser.js +0 -0
  79. /package/{build/server → server}/resources/vue.esm-browser.prod.js +0 -0
  80. /package/{src/core/client → shims}/globals.d.ts +0 -0
  81. /package/{src/core/client → shims}/shims-vue.d.ts +0 -0
  82. /package/{src/tsconfig → tsconfig}/base.json +0 -0
  83. /package/{src/tsconfig → tsconfig}/server.json +0 -0
  84. /package/{build/vite → vite}/index.js +0 -0
@@ -1,227 +0,0 @@
1
- import type { Plugin, InlineConfig } from "vite";
2
- import { build as viteBuild } from "vite";
3
- import vue from "@vitejs/plugin-vue";
4
- import fs from "fs";
5
- import path from "path";
6
- import { BuildError } from "../errors";
7
- import { logger } from "../logger";
8
- import type { ClientBuildOptions, BuildContext, CopyTarget } from "../types";
9
- import {
10
- htmlGenerator,
11
- localesGenerator,
12
- minifier,
13
- nodeDefinitionsInliner,
14
- staticCopy,
15
- } from "./plugins";
16
-
17
- async function build(
18
- clientBuildOptions: ClientBuildOptions,
19
- buildContext: BuildContext,
20
- ): Promise<void> {
21
- const {
22
- srcDir = "./client",
23
- entry = "index.ts",
24
- name = "NodeRedNodes",
25
- format = "es",
26
- licensePath = "./LICENSE",
27
- locales,
28
- staticDirs = {},
29
- external = ["jquery", "node-red", "vue"],
30
- globals = { jquery: "$", "node-red": "RED", vue: "Vue" },
31
- manualChunks,
32
- plugins: userPlugins = [],
33
- } = clientBuildOptions;
34
-
35
- const physicalEntryPath = path.resolve(srcDir, entry);
36
- let entryPath: string;
37
- let generatedEntry = false;
38
-
39
- if (fs.existsSync(physicalEntryPath)) {
40
- entryPath = physicalEntryPath;
41
- } else {
42
- // No physical entry — create a minimal empty file in the cache directory
43
- // so the file watcher on srcDir is not triggered by the create/delete cycle.
44
- const cacheDir = path.resolve("node_modules", ".nrg", "client");
45
- const cachedEntryPath = path.resolve(cacheDir, entry);
46
- if (!fs.existsSync(cacheDir)) {
47
- fs.mkdirSync(cacheDir, { recursive: true });
48
- }
49
- fs.writeFileSync(cachedEntryPath, "// auto-generated entry\n");
50
- entryPath = cachedEntryPath;
51
- generatedEntry = true;
52
- }
53
-
54
- const iconsDir = path.resolve(
55
- staticDirs.icons ?? path.join(path.dirname(path.resolve(srcDir)), "icons"),
56
- );
57
-
58
- const plugins: Plugin[] = [
59
- vue(),
60
- nodeDefinitionsInliner(
61
- buildContext.outDir,
62
- entryPath,
63
- fs.existsSync(iconsDir) ? iconsDir : undefined,
64
- path.resolve(srcDir, "components"),
65
- path.resolve(srcDir, "nodes"),
66
- !generatedEntry,
67
- ),
68
- ...userPlugins,
69
- ];
70
-
71
- plugins.push(
72
- htmlGenerator({
73
- packageName: buildContext.packageName,
74
- licensePath: licensePath ? path.resolve(licensePath) : undefined,
75
- }),
76
- );
77
-
78
- if (locales) {
79
- const {
80
- docsDir = "./locales/docs",
81
- labelsDir = "./locales/labels",
82
- languages = [
83
- "en-US",
84
- "de",
85
- "es-ES",
86
- "fr",
87
- "ko",
88
- "pt-BR",
89
- "ru",
90
- "ja",
91
- "zh-CN",
92
- "zh-TW",
93
- ],
94
- } = locales;
95
-
96
- plugins.push(
97
- localesGenerator({
98
- outDir: path.join(buildContext.outDir, "locales"),
99
- docsDir: path.resolve(docsDir),
100
- labelsDir: path.resolve(labelsDir),
101
- languages,
102
- }),
103
- );
104
- }
105
-
106
- const copyTargets: CopyTarget[] = [];
107
-
108
- const publicDir = path.resolve(
109
- staticDirs.public ?? path.join(srcDir, "public"),
110
- );
111
- if (fs.existsSync(publicDir)) {
112
- copyTargets.push({
113
- src: publicDir,
114
- dest: path.join(buildContext.outDir, "resources"),
115
- });
116
- }
117
-
118
- if (fs.existsSync(iconsDir)) {
119
- copyTargets.push({
120
- src: iconsDir,
121
- dest: path.join(buildContext.outDir, "icons"),
122
- });
123
- }
124
-
125
- if (copyTargets.length > 0) {
126
- plugins.push(staticCopy({ targets: copyTargets }));
127
- }
128
-
129
- if (!buildContext.isDev && format === "es") {
130
- plugins.push(minifier());
131
- }
132
-
133
- // Intercept '@bonsae/nrg/client' before Vite's resolver so it stays external.
134
- // Rollup's string-array external check runs against the *resolved* file path,
135
- // which wouldn't match the original specifier. 'vue' is handled by the
136
- // external array directly (Vite keeps the bare specifier for known packages).
137
- plugins.unshift({
138
- name: "nrg-client-external",
139
- enforce: "pre",
140
- resolveId(id) {
141
- if (id === "@bonsae/nrg/client")
142
- return { id: "@bonsae/nrg/client", external: true };
143
- },
144
- } as Plugin);
145
-
146
- const defaultManualChunks = (id: string): string | undefined => {
147
- if (!id.includes("node_modules")) return undefined;
148
-
149
- const parts = id
150
- .substring(id.lastIndexOf("node_modules/") + "node_modules/".length)
151
- .split("/");
152
-
153
- const pkgName = parts[0].startsWith("@")
154
- ? `${parts[0]}/${parts[1]}`
155
- : parts[0];
156
-
157
- if (["jsonpointer", "es-toolkit"].includes(pkgName)) return "vendor-utils";
158
- return "vendor";
159
- };
160
-
161
- const config: InlineConfig = {
162
- configFile: false,
163
- logLevel: "warn",
164
- base: `/${path.join("resources", buildContext.packageName)}`,
165
- publicDir: path.resolve(srcDir, "public"),
166
- resolve: {
167
- alias: {
168
- "@": path.resolve(srcDir),
169
- },
170
- },
171
- plugins,
172
- css: {
173
- devSourcemap: buildContext.isDev,
174
- },
175
- build: {
176
- outDir: buildContext.outDir,
177
- emptyOutDir: false,
178
- sourcemap: buildContext.isDev ? "inline" : false,
179
- minify: !buildContext.isDev && format !== "es",
180
- copyPublicDir: false,
181
- lib: {
182
- entry: entryPath,
183
- name,
184
- fileName: "index",
185
- formats: [format],
186
- },
187
- rollupOptions: {
188
- external,
189
- treeshake: false,
190
- output: {
191
- entryFileNames: path.join("resources", "index.[hash].js"),
192
- chunkFileNames: path.join("resources", "vendor.[hash].js"),
193
- assetFileNames: path.join("resources", "[name].[hash].[ext]"),
194
- globals,
195
- paths: {
196
- vue: "/nrg/assets/vue.esm-browser.prod.js",
197
- "@bonsae/nrg/client": "/nrg/assets/nrg-client.js",
198
- },
199
- sourcemapPathTransform: (relativeSourcePath) => {
200
- return relativeSourcePath.replace(/\/client\//g, "/");
201
- },
202
- manualChunks: manualChunks ?? defaultManualChunks,
203
- },
204
- },
205
- },
206
- define: {
207
- "process.env.NODE_ENV": JSON.stringify(
208
- buildContext.isDev ? "development" : "production",
209
- ),
210
- "process.env": {},
211
- },
212
- };
213
-
214
- try {
215
- await viteBuild(config);
216
- } catch (error) {
217
- throw new BuildError("client", error as Error);
218
- } finally {
219
- if (generatedEntry) {
220
- if (fs.existsSync(entryPath)) {
221
- fs.unlinkSync(entryPath);
222
- }
223
- }
224
- }
225
- }
226
-
227
- export { build };
@@ -1 +0,0 @@
1
- export { build } from "./build";
@@ -1,75 +0,0 @@
1
- import type { Plugin } from "vite";
2
- import mime from "mime-types";
3
- import fs from "fs";
4
- import path from "path";
5
-
6
- function htmlGenerator(options: {
7
- packageName: string;
8
- licensePath?: string;
9
- }): Plugin {
10
- const { packageName, licensePath } = options;
11
-
12
- return {
13
- name: "vite-plugin-node-red:client:html-generator",
14
- apply: "build",
15
- enforce: "post",
16
-
17
- generateBundle(_, bundle) {
18
- const resourcesTags = Object.keys(bundle)
19
- .map((fileName) => {
20
- const asset = bundle[fileName];
21
- const srcPath = path.join(
22
- "resources",
23
- packageName,
24
- fileName.replace(/^resources\/?/, ""),
25
- );
26
-
27
- const content =
28
- asset.type === "asset"
29
- ? asset.source
30
- : asset.type === "chunk"
31
- ? asset.code
32
- : null;
33
-
34
- if (typeof content !== "string" && !(content instanceof Uint8Array))
35
- return null;
36
-
37
- const mimeType = mime.lookup(fileName);
38
-
39
- switch (mimeType) {
40
- case "application/javascript":
41
- case "text/javascript":
42
- return `<script type="module" src="${srcPath}" defer></script>`;
43
- case "text/css":
44
- return `<link rel="stylesheet" href="${srcPath}">`;
45
- case "font/woff":
46
- case "font/woff2":
47
- case "application/font-woff":
48
- case "application/font-woff2":
49
- case "application/x-font-ttf":
50
- case "application/x-font-opentype":
51
- case "font/ttf":
52
- case "font/otf":
53
- return `<link rel="preload" as="font" href="${srcPath}" type="${mimeType}">`;
54
- default:
55
- return null;
56
- }
57
- })
58
- .filter(Boolean)
59
- .join("\n");
60
-
61
- const licenseBanner =
62
- licensePath && fs.existsSync(licensePath)
63
- ? `<!--\n${fs.readFileSync(licensePath, "utf-8")}\n-->`
64
- : "";
65
-
66
- this.emitFile({
67
- type: "asset",
68
- fileName: "index.html",
69
- source: `${licenseBanner}\n${resourcesTags}`,
70
- });
71
- },
72
- };
73
- }
74
-
75
- export { htmlGenerator };
@@ -1,5 +0,0 @@
1
- export { htmlGenerator } from "./html-generator";
2
- export { localesGenerator } from "./locales-generator";
3
- export { minifier } from "./minifier";
4
- export { nodeDefinitionsInliner } from "./node-definitions-inliner";
5
- export { staticCopy } from "./static-copy";
@@ -1,126 +0,0 @@
1
- import type { Plugin } from "vite";
2
- import fs from "fs";
3
- import path from "path";
4
-
5
- function localesGenerator(options: {
6
- outDir: string;
7
- docsDir: string;
8
- labelsDir: string;
9
- languages: string[];
10
- }): Plugin {
11
- const { outDir, docsDir, labelsDir, languages } = options;
12
-
13
- return {
14
- name: "vite-plugin-node-red:client:locales-generator",
15
- apply: "build",
16
- enforce: "post",
17
-
18
- closeBundle() {
19
- function validateLanguage(lang: string, filePath: string) {
20
- if (!languages.includes(lang)) {
21
- throw new Error(
22
- `[locales] Invalid language "${lang}" in "${filePath}".\n` +
23
- `Supported: ${languages.join(", ")}`,
24
- );
25
- }
26
- }
27
-
28
- function forEachFile<T>(
29
- baseDir: string,
30
- fileExtensions: string[],
31
- processFile: (params: {
32
- ext: string;
33
- filePath: string;
34
- nodeType: string;
35
- }) => T | null,
36
- ): Map<string, T extends unknown[] ? T : Record<string, T>> {
37
- const langMap = new Map();
38
-
39
- if (!fs.existsSync(baseDir)) return langMap;
40
-
41
- const nodeDirs = fs
42
- .readdirSync(baseDir, { withFileTypes: true })
43
- .filter((d) => d.isDirectory());
44
-
45
- for (const nodeDir of nodeDirs) {
46
- const nodeType = nodeDir.name;
47
- const nodePath = path.join(baseDir, nodeType);
48
- const files = fs.readdirSync(nodePath);
49
-
50
- for (const file of files) {
51
- const ext = path.extname(file);
52
- if (!fileExtensions.includes(ext)) continue;
53
-
54
- const lang = path.basename(file, ext);
55
- const filePath = path.join(nodePath, file);
56
- validateLanguage(lang, filePath);
57
-
58
- const value = processFile({ ext, filePath, nodeType });
59
- if (value == null) continue;
60
-
61
- if (!langMap.has(lang)) {
62
- langMap.set(lang, Array.isArray(value) ? [] : {});
63
- }
64
-
65
- if (Array.isArray(value)) {
66
- langMap.get(lang).push(...value);
67
- } else {
68
- langMap.get(lang)[nodeType] = value;
69
- }
70
- }
71
- }
72
-
73
- return langMap;
74
- }
75
-
76
- function writeOutput<T>(
77
- langMap: Map<string, T>,
78
- fileName: string,
79
- serialize: (value: T) => string,
80
- ) {
81
- for (const [lang, data] of langMap.entries()) {
82
- const langOutDir = path.join(outDir, lang);
83
- fs.mkdirSync(langOutDir, { recursive: true });
84
- fs.writeFileSync(
85
- path.join(langOutDir, fileName),
86
- serialize(data),
87
- "utf-8",
88
- );
89
- }
90
- }
91
-
92
- const docLangs = forEachFile(
93
- docsDir,
94
- [".html", ".md"],
95
- ({ ext, filePath, nodeType }) => {
96
- const type =
97
- ext === ".html"
98
- ? "text/html"
99
- : ext === ".md"
100
- ? "text/markdown"
101
- : null;
102
- if (!type) return null;
103
-
104
- const content = fs.readFileSync(filePath, "utf-8");
105
- return [
106
- `<script type="${type}" data-help-name="${nodeType}">\n${content}\n</script>`,
107
- ];
108
- },
109
- );
110
-
111
- writeOutput(docLangs, "index.html", (value: string[]) =>
112
- value.join("\n"),
113
- );
114
-
115
- const labelLangs = forEachFile(labelsDir, [".json"], ({ filePath }) =>
116
- JSON.parse(fs.readFileSync(filePath, "utf-8")),
117
- );
118
-
119
- writeOutput(labelLangs, "index.json", (value) =>
120
- JSON.stringify(value, null, 2),
121
- );
122
- },
123
- };
124
- }
125
-
126
- export { localesGenerator };
@@ -1,23 +0,0 @@
1
- import type { Plugin } from "vite";
2
- import { transform } from "esbuild";
3
-
4
- function minifier(): Plugin {
5
- return {
6
- name: "vite-plugin-node-red:client:minifier",
7
- apply: "build",
8
-
9
- async generateBundle(_options, bundle) {
10
- for (const [fileName, chunk] of Object.entries(bundle)) {
11
- if (chunk.type === "chunk" && fileName.endsWith(".js")) {
12
- const result = await transform(chunk.code, {
13
- minify: true,
14
- });
15
- chunk.code = result.code;
16
- chunk.map = null as any;
17
- }
18
- }
19
- },
20
- };
21
- }
22
-
23
- export { minifier };