diff --git a/app/__test__/core/object/utils.spec.ts b/app/__test__/core/object/utils.spec.ts deleted file mode 100644 index 03a572f..0000000 --- a/app/__test__/core/object/utils.spec.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { describe, expect, test } from "bun:test"; -import * as utils from "../../../src/core/utils/objects"; - -describe("object utils", () => { - test("flattenObject", () => { - const obj = { - a: { - b: { - c: 1, - a: ["a", "b", "c"] - } - }, - d: [1, 2, { e: 3 }] - }; - - console.log("flat", utils.flattenObject2(obj)); - expect(utils.flattenObject2(obj)).toEqual({ - "a.b.c": 1, - "a.b.a[0]": "a", - "a.b.a[1]": "b", - "a.b.a[2]": "c", - "d[0]": 1, - "d[1]": 2, - "d[2].e": 3 - }); - }); -}); diff --git a/app/package.json b/app/package.json index 4860cea..2b56aab 100644 --- a/app/package.json +++ b/app/package.json @@ -3,7 +3,7 @@ "type": "module", "sideEffects": false, "bin": "./dist/cli/index.js", - "version": "0.7.0-rc.4", + "version": "0.7.0-rc.5", "description": "Lightweight Firebase/Supabase alternative built to run anywhere — incl. Next.js, Remix, Astro, Cloudflare, Bun, Node, AWS Lambda & more.", "homepage": "https://bknd.io", "repository": { diff --git a/app/src/core/utils/objects.ts b/app/src/core/utils/objects.ts index ce37261..ab5b807 100644 --- a/app/src/core/utils/objects.ts +++ b/app/src/core/utils/objects.ts @@ -166,29 +166,6 @@ export function flattenObject(obj: any, parentKey = "", result: any = {}): any { return result; } -export function flattenObject2(obj: any, parentKey = "", result: any = {}): any { - for (const key in obj) { - if (key in obj) { - const newKey = parentKey ? `${parentKey}.${key}` : key; - if (typeof obj[key] === "object" && obj[key] !== null && !Array.isArray(obj[key])) { - flattenObject2(obj[key], newKey, result); - } else if (Array.isArray(obj[key])) { - obj[key].forEach((item, index) => { - const arrayKey = `${newKey}[${index}]`; - if (typeof item === "object" && item !== null) { - flattenObject2(item, arrayKey, result); - } else { - result[arrayKey] = item; - } - }); - } else { - result[newKey] = obj[key]; - } - } - } - return result; -} - export function objectDepth(object: object): number { let level = 1; for (const key in object) { diff --git a/app/src/ui/client/BkndProvider.tsx b/app/src/ui/client/BkndProvider.tsx index ba5b8a8..58dd4b8 100644 --- a/app/src/ui/client/BkndProvider.tsx +++ b/app/src/ui/client/BkndProvider.tsx @@ -1,10 +1,7 @@ -import { IconAlertHexagon } from "@tabler/icons-react"; import type { ModuleConfigs, ModuleSchemas } from "modules"; import { getDefaultConfig, getDefaultSchema } from "modules/ModuleManager"; import { createContext, startTransition, useContext, useEffect, useRef, useState } from "react"; import { useApi } from "ui/client"; -import { Button } from "ui/components/buttons/Button"; -import { Alert } from "ui/components/display/Alert"; import { type TSchemaActions, getSchemaActions } from "./schema/actions"; import { AppReduced } from "./utils/AppReduced"; @@ -14,7 +11,6 @@ type BkndContext = { config: ModuleConfigs; permissions: string[]; hasSecrets: boolean; - fetched: boolean; requireSecrets: () => Promise; actions: ReturnType; app: AppReduced; @@ -104,7 +100,7 @@ export function BkndProvider({ return ( {/*{error && ( diff --git a/app/src/ui/components/form/json-schema-form/AnyOfField.tsx b/app/src/ui/components/form/json-schema-form/AnyOfField.tsx index 2a526bd..601cc7e 100644 --- a/app/src/ui/components/form/json-schema-form/AnyOfField.tsx +++ b/app/src/ui/components/form/json-schema-form/AnyOfField.tsx @@ -22,7 +22,7 @@ export type AnyOfFieldContext = { select: (index: number | null) => void; options: string[]; errors: JsonError[]; - selectSchema: any; + selectSchema: JSONSchema; }; const AnyOfContext = createContext(undefined!); @@ -39,8 +39,9 @@ const Root = ({ path = "", schema: _schema, children }: AnyOfFieldRootProps) => const [selected, setSelected] = useState(matchedIndex > -1 ? matchedIndex : null); const options = schemas.map((s, i) => s.title ?? `Option ${i + 1}`); const selectSchema = { + type: "string", enum: options - }; + } satisfies JSONSchema; //console.log("AnyOf:root", { value, matchedIndex, selected, schema }); const selectedSchema = diff --git a/app/src/ui/components/form/json-schema-form/ArrayField.tsx b/app/src/ui/components/form/json-schema-form/ArrayField.tsx index 4102fb7..a24c62a 100644 --- a/app/src/ui/components/form/json-schema-form/ArrayField.tsx +++ b/app/src/ui/components/form/json-schema-form/ArrayField.tsx @@ -35,36 +35,36 @@ export const ArrayField = ({ }; } - const Wrapper = ({ children }) => ( - - {children} - - ); - + // if unique items with enum if (schema.uniqueItems && typeof schema.items === "object" && "enum" in schema.items) { return ( - - + { + onChange={(e: any) => { + // @ts-ignore const selected = Array.from(e.target.selectedOptions).map((o) => o.value); - console.log("selected", selected); setValue(pointer, selected); }} /> - + ); } return ( - + {value?.map((v, index: number) => { const pointer = `${path}/${index}`.replace(/\/+/g, "/"); - const [, , subschema] = getMultiSchemaMatched(schema.items, v); + let subschema = schema.items; + if (itemsMultiSchema) { + const [, , _subschema] = getMultiSchemaMatched(schema.items, v); + subschema = _subschema; + } + return (
); })} - {itemsMultiSchema ? ( - ({ - label: s!.title ?? `Option ${i + 1}`, - onClick: () => handleAdd(ctx.lib.getTemplate(undefined, s!)) - }))} - onClickItem={console.log} - > - - - ) : ( - - )} - +
+ {itemsMultiSchema ? ( + ({ + label: s!.title ?? `Option ${i + 1}`, + onClick: () => handleAdd(ctx.lib.getTemplate(undefined, s!)) + }))} + onClickItem={console.log} + > + + + ) : ( + + )} +
+ ); }; diff --git a/app/src/ui/components/form/json-schema-form/Field.tsx b/app/src/ui/components/form/json-schema-form/Field.tsx index 8d4acd3..1271d3d 100644 --- a/app/src/ui/components/form/json-schema-form/Field.tsx +++ b/app/src/ui/components/form/json-schema-form/Field.tsx @@ -5,7 +5,7 @@ import { ArrayField } from "./ArrayField"; import { FieldWrapper } from "./FieldWrapper"; import { useFieldContext } from "./Form"; import { ObjectField } from "./ObjectField"; -import { coerce, isType, isTypeSchema } from "./utils"; +import { coerce, enumToOptions, isType, isTypeSchema } from "./utils"; export type FieldProps = { name: string; @@ -77,17 +77,12 @@ export const FieldComponent = ({ schema, ...props }: { schema: JSONSchema } & ComponentPropsWithoutRef<"input">) => { - if (!schema || typeof schema === "boolean") return null; - //console.log("field", props.name, props.disabled); + if (!isTypeSchema(schema)) return null; if (schema.enum) { - if (!Array.isArray(schema.enum)) return null; - let options = schema.enum; - if (schema.enum.every((v) => typeof v === "string")) { - options = schema.enum.map((v, i) => ({ value: i, label: v })); - } - - return ; + return ( + + ); } if (isType(schema.type, ["number", "integer"])) { diff --git a/app/src/ui/components/form/json-schema-form/FieldWrapper.tsx b/app/src/ui/components/form/json-schema-form/FieldWrapper.tsx index 4e555ff..ccfd866 100644 --- a/app/src/ui/components/form/json-schema-form/FieldWrapper.tsx +++ b/app/src/ui/components/form/json-schema-form/FieldWrapper.tsx @@ -45,6 +45,7 @@ export function FieldWrapper({ > {debug && (
+ {/* @todo: use radix */} diff --git a/app/src/ui/components/form/json-schema-form/utils.ts b/app/src/ui/components/form/json-schema-form/utils.ts index b68c851..9df7848 100644 --- a/app/src/ui/components/form/json-schema-form/utils.ts +++ b/app/src/ui/components/form/json-schema-form/utils.ts @@ -223,3 +223,10 @@ export function omitSchema(_schema: Given, keys: strin export function isTypeSchema(schema?: JSONSchema): schema is Exclude { return typeof schema === "object" && "type" in schema && !isType(schema.type, "error"); } + +export function enumToOptions(_enum: any) { + if (!Array.isArray(_enum)) return []; + return _enum.map((v, i) => + typeof v === "string" ? { value: v, label: v } : { value: i, label: v } + ); +} diff --git a/app/src/ui/routes/test/tests/json-schema-form3.tsx b/app/src/ui/routes/test/tests/json-schema-form3.tsx index dad5d8d..9a44293 100644 --- a/app/src/ui/routes/test/tests/json-schema-form3.tsx +++ b/app/src/ui/routes/test/tests/json-schema-form3.tsx @@ -5,6 +5,7 @@ import { Field, Form, FormContextOverride, + FormDebug, ObjectField } from "ui/components/form/json-schema-form"; import { Scrollable } from "ui/layouts/AppShell/AppShell"; @@ -89,7 +90,7 @@ export default function JsonSchemaForm3() { > */} - {/*
- - */} + + + {/*
*/} {/**/} - + {/**/} {/*