@bonsae/nrg 0.4.0 → 0.5.1
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/build/server/index.cjs +10 -17
- package/build/server/resources/nrg-client.js +3416 -3238
- package/build/vite/index.js +23 -9
- package/package.json +1 -1
- package/src/core/client/app.vue +2 -8
- package/src/core/client/components/node-red-config-input.vue +22 -0
- package/src/core/client/components/node-red-editor-input.vue +33 -9
- package/src/core/client/components/node-red-input-label.vue +53 -0
- package/src/core/client/components/node-red-input.vue +22 -0
- package/src/core/client/components/node-red-json-schema-form.vue +89 -44
- package/src/core/client/components/node-red-select-input.vue +22 -0
- package/src/core/client/components/node-red-typed-input.vue +22 -0
- package/src/core/client/index.ts +2 -0
- package/src/core/server/schemas/type.ts +5 -19
- package/src/core/server/schemas/types/index.ts +9 -1
- package/src/core/server/utils.ts +2 -2
- package/src/core/server/validator.ts +6 -2
- package/src/vite/client/build.ts +9 -7
- package/src/vite/client/plugins/node-definitions-inliner.ts +1 -1
- package/src/vite/plugins/build.ts +15 -3
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div style="display: flex; flex-direction: column; width: 100%">
|
|
3
|
+
<slot name="label">
|
|
4
|
+
<NodeRedInputLabel
|
|
5
|
+
v-if="label"
|
|
6
|
+
:label="label"
|
|
7
|
+
:icon="icon"
|
|
8
|
+
:required="required"
|
|
9
|
+
/>
|
|
10
|
+
</slot>
|
|
3
11
|
<input
|
|
4
12
|
ref="typedInput"
|
|
5
13
|
type="text"
|
|
@@ -14,9 +22,11 @@
|
|
|
14
22
|
|
|
15
23
|
<script lang="ts">
|
|
16
24
|
import { defineComponent } from "vue";
|
|
25
|
+
import NodeRedInputLabel from "./node-red-input-label.vue";
|
|
17
26
|
import { TYPED_INPUT_TYPES } from "../../constants";
|
|
18
27
|
|
|
19
28
|
export default defineComponent({
|
|
29
|
+
components: { NodeRedInputLabel },
|
|
20
30
|
props: {
|
|
21
31
|
value: {
|
|
22
32
|
type: Object,
|
|
@@ -43,6 +53,18 @@ export default defineComponent({
|
|
|
43
53
|
type: Array,
|
|
44
54
|
default: () => TYPED_INPUT_TYPES,
|
|
45
55
|
},
|
|
56
|
+
label: {
|
|
57
|
+
type: String,
|
|
58
|
+
default: "",
|
|
59
|
+
},
|
|
60
|
+
icon: {
|
|
61
|
+
type: String,
|
|
62
|
+
default: "",
|
|
63
|
+
},
|
|
64
|
+
required: {
|
|
65
|
+
type: Boolean,
|
|
66
|
+
default: false,
|
|
67
|
+
},
|
|
46
68
|
error: {
|
|
47
69
|
type: String,
|
|
48
70
|
default: "",
|
package/src/core/client/index.ts
CHANGED
|
@@ -8,6 +8,7 @@ import NodeRedTypedInput from "./components/node-red-typed-input.vue";
|
|
|
8
8
|
import NodeRedConfigInput from "./components/node-red-config-input.vue";
|
|
9
9
|
import NodeRedSelectInput from "./components/node-red-select-input.vue";
|
|
10
10
|
import NodeRedEditorInput from "./components/node-red-editor-input.vue";
|
|
11
|
+
import NodeRedInputLabel from "./components/node-red-input-label.vue";
|
|
11
12
|
import NodeRedJsonSchemaForm from "./components/node-red-json-schema-form.vue";
|
|
12
13
|
|
|
13
14
|
const _schemas: Record<string, any> = {};
|
|
@@ -163,6 +164,7 @@ function createNodeRedVueApp(
|
|
|
163
164
|
features,
|
|
164
165
|
});
|
|
165
166
|
|
|
167
|
+
app.component("NodeRedInputLabel", NodeRedInputLabel);
|
|
166
168
|
app.component("NodeRedInput", NodeRedInput);
|
|
167
169
|
app.component("NodeRedTypedInput", NodeRedTypedInput);
|
|
168
170
|
app.component("NodeRedConfigInput", NodeRedConfigInput);
|
|
@@ -15,40 +15,26 @@ function NodeRef<T extends new (...args: any[]) => any>(
|
|
|
15
15
|
options?: SchemaOptions,
|
|
16
16
|
): TNodeRef<InstanceType<T>> {
|
|
17
17
|
return {
|
|
18
|
-
...
|
|
18
|
+
...BaseType.String({
|
|
19
19
|
description:
|
|
20
20
|
options?.description || `Reference to ${(nodeClass as any).type}`,
|
|
21
21
|
format: "node-id",
|
|
22
22
|
}),
|
|
23
|
-
"node-type": (nodeClass as any).type,
|
|
23
|
+
"x-nrg-node-type": (nodeClass as any).type,
|
|
24
24
|
...options,
|
|
25
25
|
[Kind]: "NodeRef",
|
|
26
26
|
} as unknown as TNodeRef<InstanceType<T>>;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
function TypedInput(
|
|
30
|
-
options?: SchemaOptions & { types?: string[] },
|
|
31
|
-
): TTypedInput {
|
|
32
|
-
const { types, ...rest } = options ?? {};
|
|
29
|
+
function TypedInput(options?: SchemaOptions): TTypedInput {
|
|
33
30
|
return {
|
|
34
31
|
...TypedInputSchema,
|
|
35
|
-
...
|
|
36
|
-
...(types ? { "x-typed-types": types } : {}),
|
|
32
|
+
...options,
|
|
37
33
|
[Kind]: "TypedInput",
|
|
38
34
|
} as unknown as TTypedInput;
|
|
39
35
|
}
|
|
40
36
|
|
|
41
|
-
const _OriginalString = BaseType.String.bind(BaseType);
|
|
42
|
-
function StringWithLang(options?: SchemaOptions & { lang?: string }) {
|
|
43
|
-
const { lang, ...rest } = options ?? {};
|
|
44
|
-
return _OriginalString({
|
|
45
|
-
...rest,
|
|
46
|
-
...(lang ? { "x-editor-language": lang } : {}),
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
|
|
50
37
|
const SchemaType = Object.assign({}, BaseType, {
|
|
51
|
-
String: StringWithLang,
|
|
52
38
|
NodeRef,
|
|
53
39
|
TypedInput,
|
|
54
40
|
});
|
|
@@ -62,7 +48,7 @@ function markNonValidatable<T extends TSchema>(schema: T): T {
|
|
|
62
48
|
|
|
63
49
|
// NOTE: if the type is non serializable, like Functions or Constructor, we must skip validation and avoid applying defaults
|
|
64
50
|
if (hasInvalidType) {
|
|
65
|
-
(schema as any)["skip-validation"] = true;
|
|
51
|
+
(schema as any)["x-nrg-skip-validation"] = true;
|
|
66
52
|
|
|
67
53
|
if ((schema as any).default !== undefined) {
|
|
68
54
|
(schema as any)._default = (schema as any).default;
|
|
@@ -11,7 +11,7 @@ interface TNodeRef<T = any> extends TSchema {
|
|
|
11
11
|
[Kind]: "NodeRef";
|
|
12
12
|
static: T;
|
|
13
13
|
type: "string";
|
|
14
|
-
"node-type"?: string;
|
|
14
|
+
"x-nrg-node-type"?: string;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
type ResolveNodeRefs<T> =
|
|
@@ -37,9 +37,17 @@ interface TTypedInput extends TSchema {
|
|
|
37
37
|
};
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
interface NrgFormOptions {
|
|
41
|
+
icon?: string;
|
|
42
|
+
typedInputTypes?: string[];
|
|
43
|
+
editorLanguage?: string;
|
|
44
|
+
}
|
|
45
|
+
|
|
40
46
|
declare module "@sinclair/typebox" {
|
|
41
47
|
interface SchemaOptions {
|
|
42
48
|
exportable?: boolean;
|
|
49
|
+
"x-nrg-node-type"?: string;
|
|
50
|
+
"x-nrg-form"?: NrgFormOptions;
|
|
43
51
|
}
|
|
44
52
|
}
|
|
45
53
|
|
package/src/core/server/utils.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { TObject, SchemaOptions } from "@sinclair/typebox";
|
|
2
2
|
|
|
3
3
|
interface NodeSchemaOptions extends SchemaOptions {
|
|
4
|
-
"node-type"?: string;
|
|
4
|
+
"x-nrg-node-type"?: string;
|
|
5
5
|
default?: any;
|
|
6
6
|
format?: string;
|
|
7
7
|
}
|
|
@@ -25,7 +25,7 @@ function getDefaultsFromSchema(
|
|
|
25
25
|
required: false,
|
|
26
26
|
value: property.default ?? undefined,
|
|
27
27
|
// NOTE: I'm using a custom json schema keyword to determine the node type
|
|
28
|
-
type: property["node-type"],
|
|
28
|
+
type: property["x-nrg-node-type"],
|
|
29
29
|
};
|
|
30
30
|
}
|
|
31
31
|
|
|
@@ -5,9 +5,13 @@ class NodeRedValidator extends Validator {
|
|
|
5
5
|
constructor(RED: RED) {
|
|
6
6
|
super({
|
|
7
7
|
customKeywords: [
|
|
8
|
-
{ keyword: "skip-validation", schemaType: "boolean", valid: true },
|
|
9
8
|
{
|
|
10
|
-
keyword: "
|
|
9
|
+
keyword: "x-nrg-skip-validation",
|
|
10
|
+
schemaType: "boolean",
|
|
11
|
+
valid: true,
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
keyword: "x-nrg-node-type",
|
|
11
15
|
type: "string",
|
|
12
16
|
validate: (schemaValue: string, dataValue: string) => {
|
|
13
17
|
if (!dataValue) return true;
|
package/src/vite/client/build.ts
CHANGED
|
@@ -39,13 +39,15 @@ async function build(
|
|
|
39
39
|
if (fs.existsSync(physicalEntryPath)) {
|
|
40
40
|
entryPath = physicalEntryPath;
|
|
41
41
|
} else {
|
|
42
|
-
// No physical entry — create a minimal empty file
|
|
43
|
-
//
|
|
44
|
-
|
|
45
|
-
|
|
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 });
|
|
46
48
|
}
|
|
47
|
-
fs.writeFileSync(
|
|
48
|
-
entryPath =
|
|
49
|
+
fs.writeFileSync(cachedEntryPath, "// auto-generated entry\n");
|
|
50
|
+
entryPath = cachedEntryPath;
|
|
49
51
|
generatedEntry = true;
|
|
50
52
|
}
|
|
51
53
|
|
|
@@ -215,7 +217,7 @@ async function build(
|
|
|
215
217
|
throw new BuildError("client", error as Error);
|
|
216
218
|
} finally {
|
|
217
219
|
if (generatedEntry) {
|
|
218
|
-
fs.unlinkSync(
|
|
220
|
+
fs.unlinkSync(entryPath);
|
|
219
221
|
}
|
|
220
222
|
}
|
|
221
223
|
}
|
|
@@ -37,10 +37,22 @@ function buildPlugin(options: BuildPluginOptions): Plugin {
|
|
|
37
37
|
const tsconfigsToCheck = [serverTsconfig, clientTsconfig].filter((p) =>
|
|
38
38
|
fs.existsSync(p),
|
|
39
39
|
);
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
try {
|
|
41
|
+
for (const tsconfig of tsconfigsToCheck) {
|
|
42
|
+
execSync(`npx tsc -p ${tsconfig} --noEmit`, {
|
|
43
|
+
stdio: ["inherit", "pipe", "pipe"],
|
|
44
|
+
encoding: "utf-8",
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
logger.stopSpinner("Type checked");
|
|
48
|
+
} catch (e: any) {
|
|
49
|
+
logger.stopSpinner("Type check failed");
|
|
50
|
+
const output = (e.stdout || "") + (e.stderr || "");
|
|
51
|
+
if (output) {
|
|
52
|
+
console.error(output);
|
|
53
|
+
}
|
|
54
|
+
throw new BuildError("type-check", e);
|
|
42
55
|
}
|
|
43
|
-
logger.stopSpinner("Type checked");
|
|
44
56
|
|
|
45
57
|
logger.startSpinner("Cleaning");
|
|
46
58
|
cleanDir(buildContext.outDir);
|