check undefined node on build
This commit is contained in:
1 parent
e308d21837
commit
ae59c4b811
4 files changed
+97
-47
No files matched your search
+1
-1
Submodule src/behavior3 updated: 903993458f...98117afec4.
@@ -1,5 +1,15 @@
|
|||||||
import { EditNode, EditTree, useWorkspace } from "@/contexts/workspace-context";
|
import { EditNode, EditTree, useWorkspace } from "@/contexts/workspace-context";
|
||||||
import { NodeModel, TreeGraphData } from "@/misc/b3type";
|
import {
|
||||||
|
isBoolType,
|
||||||
|
isEnumType,
|
||||||
|
isExprType,
|
||||||
|
isFloatType,
|
||||||
|
isIntType,
|
||||||
|
isJsonType,
|
||||||
|
isStringType,
|
||||||
|
NodeModel,
|
||||||
|
TreeGraphData,
|
||||||
|
} from "@/misc/b3type";
|
||||||
import {
|
import {
|
||||||
checkNodeArgValue,
|
checkNodeArgValue,
|
||||||
checkOneof,
|
checkOneof,
|
||||||
@@ -132,14 +142,14 @@ const NodeInspector: FC = () => {
|
|||||||
form.setFieldValue(
|
form.setFieldValue(
|
||||||
name,
|
name,
|
||||||
(Array.isArray(value) ? value : []).map((item) => {
|
(Array.isArray(value) ? value : []).map((item) => {
|
||||||
if (type === "json") {
|
if (isJsonType(type)) {
|
||||||
return item === null ? "null" : JSON.stringify(item ?? arg.default, null, 2);
|
return item === null ? "null" : JSON.stringify(item ?? arg.default, null, 2);
|
||||||
} else {
|
} else {
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
} else if (type === "json") {
|
} else if (isJsonType(type)) {
|
||||||
form.setFieldValue(
|
form.setFieldValue(
|
||||||
name,
|
name,
|
||||||
value === null ? "null" : JSON.stringify(value ?? arg.default, null, 2)
|
value === null ? "null" : JSON.stringify(value ?? arg.default, null, 2)
|
||||||
@@ -249,7 +259,7 @@ const NodeInspector: FC = () => {
|
|||||||
const arr: unknown[] = [];
|
const arr: unknown[] = [];
|
||||||
if (Array.isArray(value)) {
|
if (Array.isArray(value)) {
|
||||||
value.forEach((item) => {
|
value.forEach((item) => {
|
||||||
if (type === "json") {
|
if (isJsonType(type)) {
|
||||||
try {
|
try {
|
||||||
arr.push(item === "null" ? null : JSON.parse(item));
|
arr.push(item === "null" ? null : JSON.parse(item));
|
||||||
} catch {
|
} catch {
|
||||||
@@ -261,7 +271,7 @@ const NodeInspector: FC = () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
data.args[arg.name] = arr;
|
data.args[arg.name] = arr;
|
||||||
} else if (type === "json") {
|
} else if (isJsonType(type)) {
|
||||||
try {
|
try {
|
||||||
data.args[arg.name] = value === "null" ? null : JSON.parse(value);
|
data.args[arg.name] = value === "null" ? null : JSON.parse(value);
|
||||||
} catch {
|
} catch {
|
||||||
@@ -546,9 +556,9 @@ const NodeInspector: FC = () => {
|
|||||||
validateTrigger={["onChange", "onBlur"]}
|
validateTrigger={["onChange", "onBlur"]}
|
||||||
style={{ width: "100%", marginBottom: 5 }}
|
style={{ width: "100%", marginBottom: 5 }}
|
||||||
initialValue={
|
initialValue={
|
||||||
type === "boolean" ? arg.default ?? false : arg.default
|
isBoolType(type) ? arg.default ?? false : arg.default
|
||||||
}
|
}
|
||||||
valuePropName={type === "boolean" ? "checked" : undefined}
|
valuePropName={isBoolType(type) ? "checked" : undefined}
|
||||||
rules={[
|
rules={[
|
||||||
{
|
{
|
||||||
required,
|
required,
|
||||||
@@ -556,7 +566,7 @@ const NodeInspector: FC = () => {
|
|||||||
},
|
},
|
||||||
() => ({
|
() => ({
|
||||||
validator(_, value) {
|
validator(_, value) {
|
||||||
if (type === "json") {
|
if (isJsonType(type)) {
|
||||||
try {
|
try {
|
||||||
if (value !== "null") {
|
if (value !== "null") {
|
||||||
JSON.parse(value);
|
JSON.parse(value);
|
||||||
@@ -576,29 +586,29 @@ const NodeInspector: FC = () => {
|
|||||||
}),
|
}),
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
{type === "string" && (
|
{isStringType(type) && (
|
||||||
<TextArea autoSize disabled={disabled} onBlur={form.submit} />
|
<TextArea autoSize disabled={disabled} onBlur={form.submit} />
|
||||||
)}
|
)}
|
||||||
{type === "json" && (
|
{isJsonType(type) && (
|
||||||
<TextArea autoSize disabled={disabled} onBlur={form.submit} />
|
<TextArea autoSize disabled={disabled} onBlur={form.submit} />
|
||||||
)}
|
)}
|
||||||
{type === "int" && (
|
{isIntType(type) && (
|
||||||
<InputNumber
|
<InputNumber
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
onBlur={form.submit}
|
onBlur={form.submit}
|
||||||
precision={0}
|
precision={0}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{type === "float" && (
|
{isFloatType(type) && (
|
||||||
<InputNumber disabled={disabled} onBlur={form.submit} />
|
<InputNumber disabled={disabled} onBlur={form.submit} />
|
||||||
)}
|
)}
|
||||||
{type === "boolean" && (
|
{isBoolType(type) && (
|
||||||
<Switch disabled={disabled} onChange={form.submit} />
|
<Switch disabled={disabled} onChange={form.submit} />
|
||||||
)}
|
)}
|
||||||
{type === "code" && (
|
{isExprType(type) && (
|
||||||
<Input disabled={disabled} onBlur={form.submit} />
|
<Input disabled={disabled} onBlur={form.submit} />
|
||||||
)}
|
)}
|
||||||
{type === "enum" && (
|
{isEnumType(type) && (
|
||||||
<Select
|
<Select
|
||||||
showSearch
|
showSearch
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
@@ -639,8 +649,8 @@ const NodeInspector: FC = () => {
|
|||||||
<Button
|
<Button
|
||||||
type="dashed"
|
type="dashed"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
add(arg.default ?? type === "boolean" ? false : "");
|
add(arg.default ?? isBoolType(type) ? false : "");
|
||||||
if (type === "boolean") {
|
if (isBoolType(type)) {
|
||||||
form.submit();
|
form.submit();
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
@@ -663,13 +673,13 @@ const NodeInspector: FC = () => {
|
|||||||
name={`args.${arg.name}`}
|
name={`args.${arg.name}`}
|
||||||
key={`args.${arg.name}`}
|
key={`args.${arg.name}`}
|
||||||
label={arg.desc}
|
label={arg.desc}
|
||||||
initialValue={type === "boolean" ? arg.default ?? false : arg.default}
|
initialValue={isBoolType(type) ? arg.default ?? false : arg.default}
|
||||||
valuePropName={type === "boolean" ? "checked" : undefined}
|
valuePropName={isBoolType(type) ? "checked" : undefined}
|
||||||
rules={[
|
rules={[
|
||||||
{ required, message: t("node.fileRequired", { field: arg.desc }) },
|
{ required, message: t("node.fileRequired", { field: arg.desc }) },
|
||||||
({ getFieldValue, setFieldValue, isFieldValidating, validateFields }) => ({
|
({ getFieldValue, setFieldValue, isFieldValidating, validateFields }) => ({
|
||||||
validator(_, value) {
|
validator(_, value) {
|
||||||
if (value && type === "json") {
|
if (value && isJsonType(type)) {
|
||||||
try {
|
try {
|
||||||
if (value !== "null") {
|
if (value !== "null") {
|
||||||
JSON.parse(value);
|
JSON.parse(value);
|
||||||
@@ -716,19 +726,21 @@ const NodeInspector: FC = () => {
|
|||||||
}),
|
}),
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
{type === "string" && (
|
{isStringType(type) && (
|
||||||
<TextArea autoSize disabled={disabled} onBlur={form.submit} />
|
<TextArea autoSize disabled={disabled} onBlur={form.submit} />
|
||||||
)}
|
)}
|
||||||
{type === "json" && (
|
{isJsonType(type) && (
|
||||||
<TextArea autoSize disabled={disabled} onBlur={form.submit} />
|
<TextArea autoSize disabled={disabled} onBlur={form.submit} />
|
||||||
)}
|
)}
|
||||||
{type === "int" && (
|
{isIntType(type) && (
|
||||||
<InputNumber disabled={disabled} onBlur={form.submit} precision={0} />
|
<InputNumber disabled={disabled} onBlur={form.submit} precision={0} />
|
||||||
)}
|
)}
|
||||||
{type === "float" && <InputNumber disabled={disabled} onBlur={form.submit} />}
|
{isFloatType(type) && (
|
||||||
{type === "boolean" && <Switch disabled={disabled} onChange={form.submit} />}
|
<InputNumber disabled={disabled} onBlur={form.submit} />
|
||||||
{type === "code" && <Input disabled={disabled} onBlur={form.submit} />}
|
)}
|
||||||
{type === "enum" && (
|
{isBoolType(type) && <Switch disabled={disabled} onChange={form.submit} />}
|
||||||
|
{isExprType(type) && <Input disabled={disabled} onBlur={form.submit} />}
|
||||||
|
{isEnumType(type) && (
|
||||||
<Select
|
<Select
|
||||||
showSearch
|
showSearch
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
|
|||||||
+16
-8
@@ -5,10 +5,10 @@ export type NodeType = "Action" | "Composite" | "Decorator" | "Condition" | "Oth
|
|||||||
export interface NodeArg {
|
export interface NodeArg {
|
||||||
name: string;
|
name: string;
|
||||||
type:
|
type:
|
||||||
| "boolean"
|
| "bool"
|
||||||
| "boolean?"
|
| "bool?"
|
||||||
| "boolean[]"
|
| "bool[]"
|
||||||
| "boolean[]?"
|
| "bool[]?"
|
||||||
| "int"
|
| "int"
|
||||||
| "int?"
|
| "int?"
|
||||||
| "int[]"
|
| "int[]"
|
||||||
@@ -29,16 +29,24 @@ export interface NodeArg {
|
|||||||
| "enum?"
|
| "enum?"
|
||||||
| "enum[]"
|
| "enum[]"
|
||||||
| "enum[]?"
|
| "enum[]?"
|
||||||
| "code"
|
| "expr"
|
||||||
| "code?"
|
| "expr?"
|
||||||
| "code[]"
|
| "expr[]"
|
||||||
| "code[]?";
|
| "expr[]?";
|
||||||
desc: string;
|
desc: string;
|
||||||
oneof?: string;
|
oneof?: string;
|
||||||
default?: unknown;
|
default?: unknown;
|
||||||
options?: { name: string; value: string | number }[];
|
options?: { name: string; value: string | number }[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const isIntType = (type: string) => type.startsWith("int");
|
||||||
|
export const isFloatType = (type: string) => type.startsWith("float");
|
||||||
|
export const isStringType = (type: string) => type.startsWith("string");
|
||||||
|
export const isBoolType = (type: string) => type.startsWith("bool");
|
||||||
|
export const isEnumType = (type: string) => type.startsWith("enum");
|
||||||
|
export const isExprType = (type: string) => type.startsWith("expr") || type.startsWith("code");
|
||||||
|
export const isJsonType = (type: string) => type.startsWith("json");
|
||||||
|
|
||||||
export interface NodeDef {
|
export interface NodeDef {
|
||||||
name: string;
|
name: string;
|
||||||
type: NodeType;
|
type: NodeType;
|
||||||
|
|||||||
+41
-11
@@ -1,5 +1,19 @@
|
|||||||
import { useWorkspace } from "@/contexts/workspace-context";
|
import { useWorkspace } from "@/contexts/workspace-context";
|
||||||
import { NodeArg, NodeDef, NodeModel, TreeGraphData, TreeModel } from "@/misc/b3type";
|
import {
|
||||||
|
isBoolType,
|
||||||
|
isEnumType,
|
||||||
|
isExprType,
|
||||||
|
isFloatType,
|
||||||
|
isIntType,
|
||||||
|
isJsonType,
|
||||||
|
isStringType,
|
||||||
|
NodeArg,
|
||||||
|
NodeDef,
|
||||||
|
NodeModel,
|
||||||
|
TreeGraphData,
|
||||||
|
TreeModel,
|
||||||
|
unknownNodeDef,
|
||||||
|
} from "@/misc/b3type";
|
||||||
import i18n from "@/misc/i18n";
|
import i18n from "@/misc/i18n";
|
||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
import { message } from "./hooks";
|
import { message } from "./hooks";
|
||||||
@@ -130,7 +144,7 @@ export const checkNodeArgValue = (
|
|||||||
) => {
|
) => {
|
||||||
let hasError = false;
|
let hasError = false;
|
||||||
const type = getNodeArgRawType(arg);
|
const type = getNodeArgRawType(arg);
|
||||||
if (type === "float") {
|
if (isFloatType(type)) {
|
||||||
const isNumber = typeof value === "number";
|
const isNumber = typeof value === "number";
|
||||||
const isOptional = value === undefined && isNodeArgOptional(arg);
|
const isOptional = value === undefined && isNodeArgOptional(arg);
|
||||||
if (!(isNumber || isOptional)) {
|
if (!(isNumber || isOptional)) {
|
||||||
@@ -139,7 +153,7 @@ export const checkNodeArgValue = (
|
|||||||
}
|
}
|
||||||
hasError = true;
|
hasError = true;
|
||||||
}
|
}
|
||||||
} else if (type === "int") {
|
} else if (isIntType(type)) {
|
||||||
const isInt = typeof value === "number" && value === Math.floor(value);
|
const isInt = typeof value === "number" && value === Math.floor(value);
|
||||||
const isOptional = value === undefined && isNodeArgOptional(arg);
|
const isOptional = value === undefined && isNodeArgOptional(arg);
|
||||||
if (!(isInt || isOptional)) {
|
if (!(isInt || isOptional)) {
|
||||||
@@ -148,7 +162,7 @@ export const checkNodeArgValue = (
|
|||||||
}
|
}
|
||||||
hasError = true;
|
hasError = true;
|
||||||
}
|
}
|
||||||
} else if (type === "string") {
|
} else if (isStringType(type)) {
|
||||||
const isString = typeof value === "string" && value;
|
const isString = typeof value === "string" && value;
|
||||||
const isOptional = (value === undefined || value === "") && isNodeArgOptional(arg);
|
const isOptional = (value === undefined || value === "") && isNodeArgOptional(arg);
|
||||||
if (!(isString || isOptional)) {
|
if (!(isString || isOptional)) {
|
||||||
@@ -157,7 +171,7 @@ export const checkNodeArgValue = (
|
|||||||
}
|
}
|
||||||
hasError = true;
|
hasError = true;
|
||||||
}
|
}
|
||||||
} else if (type === "enum") {
|
} else if (isEnumType(type)) {
|
||||||
const isEnum = !!arg.options?.find((option) => option.value === value);
|
const isEnum = !!arg.options?.find((option) => option.value === value);
|
||||||
const isOptional = value === undefined && isNodeArgOptional(arg);
|
const isOptional = value === undefined && isNodeArgOptional(arg);
|
||||||
if (!(isEnum || isOptional)) {
|
if (!(isEnum || isOptional)) {
|
||||||
@@ -166,16 +180,16 @@ export const checkNodeArgValue = (
|
|||||||
}
|
}
|
||||||
hasError = true;
|
hasError = true;
|
||||||
}
|
}
|
||||||
} else if (type === "code") {
|
} else if (isExprType(type)) {
|
||||||
const isCode = typeof value === "string" && value;
|
const isExpr = typeof value === "string" && value;
|
||||||
const isOptional = (value === undefined || value === "") && isNodeArgOptional(arg);
|
const isOptional = (value === undefined || value === "") && isNodeArgOptional(arg);
|
||||||
if (!(isCode || isOptional)) {
|
if (!(isExpr || isOptional)) {
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
error(data, `'${arg.name}=${JSON.stringify(value)}' is not a string`);
|
error(data, `'${arg.name}=${JSON.stringify(value)}' is not an expr string`);
|
||||||
}
|
}
|
||||||
hasError = true;
|
hasError = true;
|
||||||
}
|
}
|
||||||
} else if (type === "json") {
|
} else if (isJsonType(type)) {
|
||||||
const isJson = value !== undefined && value !== "";
|
const isJson = value !== undefined && value !== "";
|
||||||
const isOptional = isNodeArgOptional(arg);
|
const isOptional = isNodeArgOptional(arg);
|
||||||
if (!(isJson || isOptional)) {
|
if (!(isJson || isOptional)) {
|
||||||
@@ -184,6 +198,16 @@ export const checkNodeArgValue = (
|
|||||||
}
|
}
|
||||||
hasError = true;
|
hasError = true;
|
||||||
}
|
}
|
||||||
|
} else if (isBoolType(type)) {
|
||||||
|
const isBool = typeof value === "boolean" || value === undefined;
|
||||||
|
if (!isBool) {
|
||||||
|
if (verbose) {
|
||||||
|
error(data, `'${arg.name}=${JSON.stringify(value)}' is not a boolean`);
|
||||||
|
}
|
||||||
|
hasError = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
error(data, `unknown arg type '${arg.type}'`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return !hasError;
|
return !hasError;
|
||||||
@@ -240,8 +264,14 @@ export const checkNodeData = (data: NodeModel | null | undefined) => {
|
|||||||
if (!data) {
|
if (!data) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
let hasError = false;
|
|
||||||
const conf = useWorkspace.getState().getNodeDef(data.name);
|
const conf = useWorkspace.getState().getNodeDef(data.name);
|
||||||
|
if (conf.name === unknownNodeDef.name) {
|
||||||
|
error(data, `undefined node: ${data.name}`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let hasError = false;
|
||||||
|
|
||||||
if (conf.children !== undefined && conf.children !== -1) {
|
if (conf.children !== undefined && conf.children !== -1) {
|
||||||
const count = data.children?.length || 0;
|
const count = data.children?.length || 0;
|
||||||
if (conf.children !== count) {
|
if (conf.children !== count) {
|
||||||
|
|||||||
Reference in new issue
Block a user