mirror of
https://github.com/shishantbiswas/bknd.git
synced 2026-03-17 12:56:05 +00:00
Release 0.16 (#196)
* initial refactor * fixes * test secrets extraction * updated lock * fix secret schema * updated schemas, fixed tests, skipping flow tests for now * added validator for rjsf, hook form via standard schema * removed @sinclair/typebox * remove unneeded vite dep * fix jsonv literal on Field.tsx * fix schema import path * fix schema modals * fix schema modals * fix json field form, replaced auth form * initial waku * finalize waku example * fix jsonv-ts version * fix schema updates with falsy values * fix media api to respect options' init, improve types * checking media controller test * checking media controller test * checking media controller test * clean up mediacontroller test * added cookie option `partitioned`, as well as cors `origin` to be array, option to enable `credentials` (#214) * added cookie option `partitioned`, as well as cors `origin` to be array, option to enable `credentials` * fix server test * fix data api (updated jsonv-ts) * enhance cloudflare image optimization plugin with new options and explain endpoint (#215) * feat: add ability to serve static by using dynamic imports (#197) * feat: add ability to serve static by using dynamic imports * serveStaticViaImport: make manifest optional * serveStaticViaImport: add error log * refactor/imports (#217) * refactored core and core/utils imports * refactored core and core/utils imports * refactored media imports * refactored auth imports * refactored data imports * updated package json exports, fixed mm config * fix tests * feat/deno (#219) * update bun version * fix module manager's em reference * add basic deno example * finalize * docs: fumadocs migration (#185) * feat(docs): initialize documentation structure with Fumadocs * feat(docs): remove home route and move /docs route to /route * feat(docs): add redirect to /start page * feat(docs): migrate Getting Started chapters * feat(docs): migrate Usage and Extending chapters * feat(callout): add CalloutCaution, CalloutDanger, CalloutInfo, and CalloutPositive * feat(layout): add Discord and GitHub links to documentation layout * feat(docs): add integration chapters draft * feat(docs): add modules chapters draft * refactor(mdx-components): remove unused Icon import * refactor(StackBlitz): enhance type safety by using unknown instead of any * refactor(layout): update navigation mode to 'top' in layout configuration * feat(docs): add @iconify/react package * docs(mdx-components): add Icon component to MDX components list * feat(docs): update Next.js integration guide * feat(docs): update React Router integration guide * feat(docs): update Astro integration guide * feat(docs): update Vite integration guide * fix(docs): update package manager initialization commands * feat(docs): migrate Modules chapters * chore(docs): update package.json with new devDependencies * feat(docs): migrate Integration Runtimes chapters * feat(docs): update Database usage chapter * feat(docs): restructure documentation paths * chore(docs): clean up unused imports and files in documentation * style(layout): revert navigation mode to previous state * fix(docs): routing for documentation structure * feat(openapi): add API documentation generation from OpenAPI schema * feat(docs): add icons to documentation pages * chore(dependencies): remove unused content-collections packages * fix(types): fix type error for attachFile in source.ts * feat(redirects): update root redirect destination to '/start' * feat(search): add static search functionality * chore(dependencies): update fumadocs-core and fumadocs-ui to latest versions * feat(search): add Powered by Orama link * feat(generate-openapi): add error handling for missing OpenAPI schema * feat(scripts): add OpenAPI generation to build process * feat(config): enable dynamic redirects and rewrites in development mode * feat(layout): add GitHub token support for improved API rate limits * feat(redirects): add 301 redirects for cloudflare pages * feat(docs): add Vercel redirects configuration * feat(config): enable standalone output for development environment * chore(layout): adjust layout settings * refactor(package): clean up ajv dependency versions * feat(docs): add twoslash support * refactor(layout): update DocsLayout import and navigation configuration * chore(layout): clean up layout.tsx by commenting out GithubInfo * fix(Search): add locale to search initialization * chore(package): update fumadocs and orama to latest versions * docs: add menu items descriptions * feat(layout): add GitHub URL to the layout component * feat(docs): add AutoTypeTable component to MDX components * feat(app): implement AutoTypeTable rendering for AppEvents type * docs(layout): switch callouts back to default components * fix(config): use __filename and __dirname for module paths * docs: add note about node.js 22 requirement * feat(styles): add custom color variables for light and dark themes * docs: add S3 setup instructions for media module * docs: fix typos and indentation in media module docs * docs: add local media adapter example for Node.js * docs(media): add S3/R2 URL format examples and fix typo * docs: add cross-links to initial config and seeding sections * indent numbered lists content, clarified media serve locations * fix mediacontroller tests * feat(layout): add AnimatedGridPattern component for dynamic background * style(layout): configure fancy ToC style ('clerk') * fix(AnimatedGridPattern): correct strokeDasharray type * docs: actualize docs * feat: add favicon * style(cloudflare): format code examples * feat(layout): add Github and Discord footer icons * feat(footer): add SVG social media icons for GitHub and Discord * docs: adjusted auto type table, added llm functions * added static deployment to cloudflare workers * docs: change cf redirects to proxy *.mdx instead of redirecting --------- Co-authored-by: dswbx <dennis.senn@gmx.ch> Co-authored-by: cameronapak <cameronandrewpak@gmail.com> * build: improve build script * add missing exports, fix EntityTypescript imports * media: Dropzone: add programmatic upload, additional events, loading state * schema object: disable extended defaults to allow empty config values * Feat/new docs deploy (#224) * test * try fixing pm * try fixing pm * fix docs on imports, export events correctly --------- Co-authored-by: Tim Seriakov <59409712+timseriakov@users.noreply.github.com> Co-authored-by: cameronapak <cameronandrewpak@gmail.com>
This commit is contained in:
@@ -1,4 +1,9 @@
|
||||
import { StringIdentifier, transformObject, ucFirstAllSnakeToPascalWithSpaces } from "core/utils";
|
||||
import {
|
||||
transformObject,
|
||||
ucFirstAllSnakeToPascalWithSpaces,
|
||||
s,
|
||||
stringIdentifier,
|
||||
} from "bknd/utils";
|
||||
import { useBkndAuth } from "ui/client/schema/auth/use-bknd-auth";
|
||||
import { Alert } from "ui/components/display/Alert";
|
||||
import { bkndModals } from "ui/modals";
|
||||
@@ -28,13 +33,9 @@ export function AuthRolesList() {
|
||||
bkndModals.open(
|
||||
"form",
|
||||
{
|
||||
schema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
name: StringIdentifier,
|
||||
},
|
||||
required: ["name"],
|
||||
},
|
||||
schema: s.strictObject({
|
||||
name: stringIdentifier,
|
||||
}),
|
||||
uiSchema: {
|
||||
name: {
|
||||
"ui:title": "Role name",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import clsx from "clsx";
|
||||
import { isDebug } from "core";
|
||||
import { isDebug } from "core/env";
|
||||
import { TbChevronDown, TbChevronUp } from "react-icons/tb";
|
||||
import { useBknd } from "ui/client/BkndProvider";
|
||||
import { useBkndAuth } from "ui/client/schema/auth/use-bknd-auth";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { isDebug } from "core";
|
||||
import { isDebug } from "core/env";
|
||||
import { autoFormatString } from "core/utils";
|
||||
import { type ChangeEvent, useState } from "react";
|
||||
import {
|
||||
@@ -64,8 +64,7 @@ function AuthStrategiesListInternal() {
|
||||
const config = $auth.config.strategies;
|
||||
const schema = $auth.schema.properties.strategies;
|
||||
const schemas = Object.fromEntries(
|
||||
// @ts-ignore
|
||||
$auth.schema.properties.strategies.additionalProperties.anyOf.map((s) => [
|
||||
$auth.schema.properties.strategies?.additionalProperties?.anyOf.map((s) => [
|
||||
s.properties.type.const,
|
||||
s,
|
||||
]),
|
||||
@@ -76,7 +75,12 @@ function AuthStrategiesListInternal() {
|
||||
}
|
||||
|
||||
return (
|
||||
<Form schema={schema} initialValues={config} onSubmit={handleSubmit} options={formOptions}>
|
||||
<Form
|
||||
schema={schema as any}
|
||||
initialValues={config}
|
||||
onSubmit={handleSubmit}
|
||||
options={formOptions}
|
||||
>
|
||||
<Subscribe
|
||||
selector={(state) => ({
|
||||
dirty: state.dirty,
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import { typeboxResolver } from "@hookform/resolvers/typebox";
|
||||
import { Input, Switch, Tooltip } from "@mantine/core";
|
||||
import { guardRoleSchema } from "auth/auth-schema";
|
||||
import { type Static, ucFirst } from "core/utils";
|
||||
import { ucFirst, type s } from "bknd/utils";
|
||||
import { forwardRef, useImperativeHandle } from "react";
|
||||
import { type UseControllerProps, useController, useForm } from "react-hook-form";
|
||||
import { useBknd } from "ui/client/bknd";
|
||||
import { Button } from "ui/components/buttons/Button";
|
||||
import { MantineSwitch } from "ui/components/form/hook-form-mantine/MantineSwitch";
|
||||
import { standardSchemaResolver } from "@hookform/resolvers/standard-schema";
|
||||
|
||||
const schema = guardRoleSchema;
|
||||
type Role = Static<typeof guardRoleSchema>;
|
||||
type Role = s.Static<typeof guardRoleSchema>;
|
||||
|
||||
export type AuthRoleFormRef = {
|
||||
getData: () => Role;
|
||||
@@ -33,7 +33,7 @@ export const AuthRoleForm = forwardRef<
|
||||
reset,
|
||||
getValues,
|
||||
} = useForm({
|
||||
resolver: typeboxResolver(schema),
|
||||
resolver: standardSchemaResolver(schema),
|
||||
defaultValues: role,
|
||||
});
|
||||
|
||||
@@ -87,7 +87,7 @@ const Permissions = ({
|
||||
const {
|
||||
field: { value, onChange: fieldOnChange, ...field },
|
||||
fieldState,
|
||||
} = useController<Static<typeof schema>, "permissions">({
|
||||
} = useController<s.Static<typeof schema>, "permissions">({
|
||||
name: "permissions",
|
||||
control,
|
||||
});
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
IconSettings,
|
||||
IconSwitchHorizontal,
|
||||
} from "@tabler/icons-react";
|
||||
import type { Entity, TEntityType } from "data";
|
||||
import type { Entity, TEntityType } from "bknd";
|
||||
import { TbDatabasePlus } from "react-icons/tb";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
import { useBkndData } from "ui/client/schema/data/use-bknd-data";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { PrimaryFieldType } from "core";
|
||||
import { ucFirst } from "core/utils";
|
||||
import type { Entity, EntityData, EntityRelation } from "data";
|
||||
import type { PrimaryFieldType } from "bknd";
|
||||
import { ucFirst } from "bknd/utils";
|
||||
import type { Entity, EntityData, EntityRelation } from "bknd";
|
||||
import { Fragment, useState } from "react";
|
||||
import { TbDots } from "react-icons/tb";
|
||||
import { useApiQuery, useEntityQuery } from "ui/client";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { EntityData } from "data";
|
||||
import type { EntityData } from "bknd";
|
||||
import { useState } from "react";
|
||||
import { useEntityMutate } from "ui/client";
|
||||
import { useBkndData } from "ui/client/schema/data/use-bknd-data";
|
||||
@@ -11,7 +11,7 @@ import { Breadcrumbs2 } from "ui/layouts/AppShell/Breadcrumbs2";
|
||||
import { routes, useNavigate } from "ui/lib/routes";
|
||||
import { EntityForm } from "ui/modules/data/components/EntityForm";
|
||||
import { useEntityForm } from "ui/modules/data/hooks/useEntityForm";
|
||||
import { s } from "core/object/schema";
|
||||
import { s } from "bknd/utils";
|
||||
|
||||
export function DataEntityCreate({ params }) {
|
||||
const { $data } = useBkndData();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { type Entity, repoQuery } from "data";
|
||||
import type { Entity } from "bknd";
|
||||
import { repoQuery } from "data/server/query";
|
||||
import { Fragment } from "react";
|
||||
import { TbDots } from "react-icons/tb";
|
||||
import { useApiQuery } from "ui/client";
|
||||
@@ -14,7 +15,7 @@ import * as AppShell from "ui/layouts/AppShell/AppShell";
|
||||
import { routes, useNavigate } from "ui/lib/routes";
|
||||
import { useCreateUserModal } from "ui/modules/auth/hooks/use-create-user-modal";
|
||||
import { EntityTable2 } from "ui/modules/data/components/EntityTable2";
|
||||
import { s } from "core/object/schema";
|
||||
import { s } from "bknd/utils";
|
||||
import { pick } from "core/utils/objects";
|
||||
|
||||
const searchSchema = s.partialObject({
|
||||
|
||||
@@ -4,8 +4,8 @@ import {
|
||||
IconCirclesRelation,
|
||||
IconSettings,
|
||||
} from "@tabler/icons-react";
|
||||
import { isDebug } from "core";
|
||||
import type { Entity } from "data";
|
||||
import { isDebug } from "core/env";
|
||||
import type { Entity } from "bknd";
|
||||
import { cloneDeep } from "lodash-es";
|
||||
import { useRef, useState } from "react";
|
||||
import {
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
import { typeboxResolver } from "@hookform/resolvers/typebox";
|
||||
import { Tabs, TextInput, Textarea, Tooltip, Switch } from "@mantine/core";
|
||||
import { useDisclosure } from "@mantine/hooks";
|
||||
import {
|
||||
Default,
|
||||
type Static,
|
||||
StringIdentifier,
|
||||
objectCleanEmpty,
|
||||
omitKeys,
|
||||
ucFirstAllSnakeToPascalWithSpaces,
|
||||
} from "core/utils";
|
||||
s,
|
||||
stringIdentifier,
|
||||
} from "bknd/utils";
|
||||
import {
|
||||
type TAppDataEntityFields,
|
||||
fieldsSchemaObject as originalFieldsSchemaObject,
|
||||
@@ -26,31 +24,26 @@ import { type SortableItemProps, SortableList } from "ui/components/list/Sortabl
|
||||
import { Popover } from "ui/components/overlay/Popover";
|
||||
import { type TFieldSpec, fieldSpecs } from "ui/modules/data/components/fields-specs";
|
||||
import { dataFieldsUiSchema } from "../../settings/routes/data.settings";
|
||||
import * as tbbox from "@sinclair/typebox";
|
||||
import { useRoutePathState } from "ui/hooks/use-route-path-state";
|
||||
import { MantineSelect } from "ui/components/form/hook-form-mantine/MantineSelect";
|
||||
import type { TPrimaryFieldFormat } from "data/fields/PrimaryField";
|
||||
const { Type } = tbbox;
|
||||
import { standardSchemaResolver } from "@hookform/resolvers/standard-schema";
|
||||
import ErrorBoundary from "ui/components/display/ErrorBoundary";
|
||||
|
||||
const fieldsSchemaObject = originalFieldsSchemaObject;
|
||||
const fieldsSchema = Type.Union(Object.values(fieldsSchemaObject));
|
||||
const fieldsSchema = s.anyOf(Object.values(fieldsSchemaObject));
|
||||
|
||||
const fieldSchema = Type.Object(
|
||||
{
|
||||
name: StringIdentifier,
|
||||
new: Type.Optional(Type.Boolean({ const: true })),
|
||||
field: fieldsSchema,
|
||||
},
|
||||
{
|
||||
additionalProperties: false,
|
||||
},
|
||||
);
|
||||
type TFieldSchema = Static<typeof fieldSchema>;
|
||||
|
||||
const schema = Type.Object({
|
||||
fields: Type.Array(fieldSchema),
|
||||
const fieldSchema = s.strictObject({
|
||||
name: stringIdentifier,
|
||||
new: s.boolean({ const: true }).optional(),
|
||||
field: fieldsSchema,
|
||||
});
|
||||
type TFieldsFormSchema = Static<typeof schema>;
|
||||
type TFieldSchema = s.Static<typeof fieldSchema>;
|
||||
|
||||
const schema = s.strictObject({
|
||||
fields: s.array(fieldSchema),
|
||||
});
|
||||
type TFieldsFormSchema = s.Static<typeof schema>;
|
||||
|
||||
const fieldTypes = Object.keys(fieldsSchemaObject);
|
||||
const defaultType = fieldTypes[0];
|
||||
@@ -58,7 +51,9 @@ const commonProps = ["label", "description", "required", "fillable", "hidden", "
|
||||
|
||||
function specificFieldSchema(type: keyof typeof fieldsSchemaObject) {
|
||||
//console.log("specificFieldSchema", type);
|
||||
return Type.Omit(fieldsSchemaObject[type]?.properties.config, commonProps);
|
||||
return s.object(
|
||||
omitKeys(fieldsSchemaObject[type]?.properties.config.properties, commonProps as any),
|
||||
);
|
||||
}
|
||||
|
||||
export type EntityFieldsFormProps = {
|
||||
@@ -100,7 +95,7 @@ export const EntityFieldsForm = forwardRef<EntityFieldsFormRef, EntityFieldsForm
|
||||
reset,
|
||||
} = useForm({
|
||||
mode: "all",
|
||||
resolver: typeboxResolver(schema),
|
||||
resolver: standardSchemaResolver(schema),
|
||||
defaultValues: {
|
||||
fields: entityFields,
|
||||
} as TFieldsFormSchema,
|
||||
@@ -135,15 +130,14 @@ export const EntityFieldsForm = forwardRef<EntityFieldsFormRef, EntityFieldsForm
|
||||
}));
|
||||
|
||||
function handleAppend(_type: keyof typeof fieldsSchemaObject) {
|
||||
const newField = {
|
||||
append({
|
||||
name: "",
|
||||
new: true,
|
||||
field: {
|
||||
type: _type,
|
||||
config: Default(fieldsSchemaObject[_type]?.properties.config, {}) as any,
|
||||
config: fieldsSchemaObject[_type]?.properties.config.template() as any,
|
||||
},
|
||||
};
|
||||
append(newField);
|
||||
});
|
||||
}
|
||||
|
||||
const formProps = {
|
||||
@@ -465,19 +459,17 @@ function EntityField({
|
||||
</Tabs.Panel>
|
||||
<Tabs.Panel value="specific">
|
||||
<div className="flex flex-col gap-2 pt-3 pb-1">
|
||||
<JsonSchemaForm
|
||||
key={type}
|
||||
schema={specificFieldSchema(type as any)}
|
||||
formData={specificData}
|
||||
uiSchema={dataFieldsUiSchema.config}
|
||||
className="legacy hide-required-mark fieldset-alternative mute-root"
|
||||
onChange={(value) => {
|
||||
setValue(`${prefix}.config`, {
|
||||
...getValues([`fields.${index}.config`])[0],
|
||||
...value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<ErrorBoundary fallback={`Error rendering JSON Schema for ${type}`}>
|
||||
<SpecificForm
|
||||
field={field}
|
||||
onChange={(value) => {
|
||||
setValue(`${prefix}.config`, {
|
||||
...getValues([`fields.${index}.config`])[0],
|
||||
...value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</ErrorBoundary>
|
||||
</div>
|
||||
</Tabs.Panel>
|
||||
<Tabs.Panel value="code">
|
||||
@@ -502,3 +494,25 @@ function EntityField({
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const SpecificForm = ({
|
||||
field,
|
||||
onChange,
|
||||
}: {
|
||||
field: FieldArrayWithId<TFieldsFormSchema, "fields", "id">;
|
||||
onChange: (value: any) => void;
|
||||
}) => {
|
||||
const type = field.field.type;
|
||||
const specificData = omit(field.field.config, commonProps);
|
||||
|
||||
return (
|
||||
<JsonSchemaForm
|
||||
key={type}
|
||||
schema={specificFieldSchema(type as any)?.toJSON()}
|
||||
formData={specificData}
|
||||
uiSchema={dataFieldsUiSchema.config}
|
||||
className="legacy hide-required-mark fieldset-alternative mute-root"
|
||||
onChange={onChange}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { IconHierarchy2 } from "@tabler/icons-react";
|
||||
import { isDebug } from "core";
|
||||
import { isDebug } from "core/env";
|
||||
import { TbSettings } from "react-icons/tb";
|
||||
import { useBknd } from "../../client/BkndProvider";
|
||||
import { IconButton } from "../../components/buttons/IconButton";
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import { typeboxResolver } from "@hookform/resolvers/typebox";
|
||||
import { TextInput } from "@mantine/core";
|
||||
import { useFocusTrap } from "@mantine/hooks";
|
||||
import { TypeRegistry } from "@sinclair/typebox";
|
||||
import { type Static, StringEnum, StringIdentifier, registerCustomTypeboxKinds } from "core/utils";
|
||||
import { TRIGGERS } from "flows/flows-schema";
|
||||
import { forwardRef, useState } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
@@ -16,18 +13,16 @@ import {
|
||||
ModalTitle,
|
||||
} from "../../../components/modal/Modal2";
|
||||
import { Step, Steps, useStepContext } from "../../../components/steps/Steps";
|
||||
import * as tbbox from "@sinclair/typebox";
|
||||
const { Type } = tbbox;
|
||||
|
||||
registerCustomTypeboxKinds(TypeRegistry);
|
||||
import { s, stringIdentifier } from "bknd/utils";
|
||||
import { standardSchemaResolver } from "@hookform/resolvers/standard-schema";
|
||||
|
||||
export type TCreateFlowModalSchema = any;
|
||||
const triggerNames = Object.keys(TRIGGERS) as unknown as (keyof typeof TRIGGERS)[];
|
||||
|
||||
const schema = Type.Object({
|
||||
name: StringIdentifier,
|
||||
trigger: StringEnum(triggerNames),
|
||||
mode: StringEnum(["async", "sync"]),
|
||||
const schema = s.strictObject({
|
||||
name: stringIdentifier,
|
||||
trigger: s.string({ enum: triggerNames }),
|
||||
mode: s.string({ enum: ["async", "sync"] }),
|
||||
});
|
||||
|
||||
export const FlowCreateModal = forwardRef<Modal2Ref>(function FlowCreateModal(props, ref) {
|
||||
@@ -61,16 +56,16 @@ export function StepCreate() {
|
||||
register,
|
||||
formState: { isValid, errors },
|
||||
} = useForm({
|
||||
resolver: typeboxResolver(schema),
|
||||
resolver: standardSchemaResolver(schema),
|
||||
defaultValues: {
|
||||
name: "",
|
||||
trigger: "manual",
|
||||
mode: "async",
|
||||
} as Static<typeof schema>,
|
||||
} as s.Static<typeof schema>,
|
||||
mode: "onSubmit",
|
||||
});
|
||||
|
||||
async function onSubmit(data: Static<typeof schema>) {
|
||||
async function onSubmit(data: s.Static<typeof schema>) {
|
||||
console.log(data, isValid);
|
||||
actions.flow.create(data.name, {
|
||||
trigger: {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { IconBrandAws, IconBrandCloudflare, IconCloud, IconServer } from "@tabler/icons-react";
|
||||
import { isDebug } from "core";
|
||||
import { isDebug } from "core/env";
|
||||
import { autoFormatString } from "core/utils";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
import { useBknd } from "ui/client/BkndProvider";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useHotkeys } from "@mantine/hooks";
|
||||
import { type TObject, ucFirst } from "core/utils";
|
||||
import { ucFirst, type s } from "bknd/utils";
|
||||
import { omit } from "lodash-es";
|
||||
import { type ReactNode, useMemo, useRef, useState } from "react";
|
||||
import { TbSettings } from "react-icons/tb";
|
||||
@@ -20,8 +20,8 @@ import { SettingNewModal, type SettingsNewModalProps } from "./SettingNewModal";
|
||||
import { SettingSchemaModal, type SettingsSchemaModalRef } from "./SettingSchemaModal";
|
||||
|
||||
export type SettingProps<
|
||||
Schema extends TObject = TObject,
|
||||
Props = Schema extends TObject<infer TProperties> ? TProperties : any,
|
||||
Schema extends s.ObjectSchema = s.ObjectSchema,
|
||||
Props = Schema extends s.ObjectSchema<infer TProperties> ? TProperties : any,
|
||||
> = {
|
||||
schema: Schema;
|
||||
config: any;
|
||||
@@ -44,7 +44,7 @@ export type SettingProps<
|
||||
};
|
||||
};
|
||||
|
||||
export function Setting<Schema extends TObject = any>({
|
||||
export function Setting<Schema extends s.ObjectSchema = s.ObjectSchema>({
|
||||
schema,
|
||||
uiSchema,
|
||||
config,
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import { useDisclosure, useFocusTrap } from "@mantine/hooks";
|
||||
import type { TObject } from "core/utils";
|
||||
import { omit } from "lodash-es";
|
||||
import { useRef, useState } from "react";
|
||||
import { TbCirclePlus, TbVariable } from "react-icons/tb";
|
||||
import { useBknd } from "ui/client/BkndProvider";
|
||||
import { Button } from "ui/components/buttons/Button";
|
||||
import * as Formy from "ui/components/form/Formy";
|
||||
@@ -10,9 +8,10 @@ import { JsonSchemaForm, type JsonSchemaFormRef } from "ui/components/form/json-
|
||||
import { Dropdown } from "ui/components/overlay/Dropdown";
|
||||
import { Modal } from "ui/components/overlay/Modal";
|
||||
import { useLocation } from "wouter";
|
||||
import type { s } from "bknd/utils";
|
||||
|
||||
export type SettingsNewModalProps = {
|
||||
schema: TObject;
|
||||
schema: s.ObjectSchema;
|
||||
uiSchema?: object;
|
||||
anyOfValues?: Record<string, { label: string; icon?: any }>;
|
||||
path: string[];
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import type { Static, TObject } from "core/utils";
|
||||
import type { JSONSchema7 } from "json-schema";
|
||||
import { cloneDeep, omit, pick } from "lodash-es";
|
||||
import { omitKeys, type s } from "bknd/utils";
|
||||
|
||||
export function extractSchema<
|
||||
Schema extends TObject,
|
||||
Schema extends s.ObjectSchema,
|
||||
Keys extends keyof Schema["properties"],
|
||||
Config extends Static<Schema>,
|
||||
Config extends s.Static<Schema>,
|
||||
>(
|
||||
schema: Schema,
|
||||
config: Config,
|
||||
@@ -22,13 +21,13 @@ export function extractSchema<
|
||||
},
|
||||
] {
|
||||
if (!schema.properties) {
|
||||
return [{ ...schema }, config, {} as any];
|
||||
return [{ ...schema.toJSON() }, config, {} as any];
|
||||
}
|
||||
|
||||
const newSchema = cloneDeep(schema);
|
||||
const newSchema = JSON.parse(JSON.stringify(schema));
|
||||
const updated = {
|
||||
...newSchema,
|
||||
properties: omit(newSchema.properties, keys),
|
||||
properties: omitKeys(newSchema.properties, keys),
|
||||
};
|
||||
if (updated.required) {
|
||||
updated.required = updated.required.filter((key) => !keys.includes(key as any));
|
||||
@@ -44,7 +43,7 @@ export function extractSchema<
|
||||
};
|
||||
}
|
||||
|
||||
const reducedConfig = omit(config, keys) as any;
|
||||
const reducedConfig = omitKeys(config, keys as string[]) as any;
|
||||
|
||||
return [updated, reducedConfig, extracted];
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import AppShellAccordionsTest from "ui/routes/test/tests/appshell-accordions-test";
|
||||
import JsonSchemaFormReactTest from "ui/routes/test/tests/json-schema-form-react-test";
|
||||
|
||||
import FormyTest from "ui/routes/test/tests/formy-test";
|
||||
import HtmlFormTest from "ui/routes/test/tests/html-form-test";
|
||||
@@ -49,7 +48,6 @@ const tests = {
|
||||
SWRAndAPI,
|
||||
SwrAndDataApi,
|
||||
DropzoneElementTest,
|
||||
JsonSchemaFormReactTest,
|
||||
JsonSchemaForm3,
|
||||
FormyTest,
|
||||
HtmlFormTest,
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { parse } from "core/utils";
|
||||
import { AppFlows } from "flows/AppFlows";
|
||||
import { useState } from "react";
|
||||
import { JsonViewer } from "../../../components/code/JsonViewer";
|
||||
import { JsonSchemaForm } from "../../../components/form/json-schema";
|
||||
import { Scrollable } from "../../../layouts/AppShell/AppShell";
|
||||
import { parse } from "bknd/utils";
|
||||
|
||||
export default function FlowCreateSchemaTest() {
|
||||
//const schema = flowsConfigSchema;
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
import { Form, type Validator } from "json-schema-form-react";
|
||||
import { useState } from "react";
|
||||
|
||||
import { type TSchema, Type } from "@sinclair/typebox";
|
||||
import { Value, type ValueError } from "@sinclair/typebox/value";
|
||||
|
||||
class TypeboxValidator implements Validator<ValueError> {
|
||||
async validate(schema: TSchema, data: any) {
|
||||
return Value.Check(schema, data) ? [] : [...Value.Errors(schema, data)];
|
||||
}
|
||||
}
|
||||
const validator = new TypeboxValidator();
|
||||
|
||||
const schema = Type.Object({
|
||||
name: Type.String(),
|
||||
age: Type.Optional(Type.Number()),
|
||||
});
|
||||
|
||||
export default function JsonSchemaFormReactTest() {
|
||||
const [data, setData] = useState(null);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form
|
||||
schema={schema}
|
||||
/*onChange={setData}
|
||||
onSubmit={setData}*/
|
||||
validator={validator}
|
||||
validationMode="change"
|
||||
>
|
||||
{({ errors, dirty, reset }) => (
|
||||
<>
|
||||
<div>
|
||||
<b>
|
||||
Form {dirty ? "*" : ""} (valid: {errors.length === 0 ? "valid" : "invalid"})
|
||||
</b>
|
||||
</div>
|
||||
<div>
|
||||
<input type="text" name="name" />
|
||||
<input type="number" name="age" />
|
||||
</div>
|
||||
<div>
|
||||
<button type="submit">submit</button>
|
||||
<button type="button" onClick={reset}>
|
||||
reset
|
||||
</button>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</Form>
|
||||
<pre>{JSON.stringify(data, null, 2)}</pre>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -73,7 +73,7 @@ export default function JsonSchemaForm3() {
|
||||
return (
|
||||
<Scrollable>
|
||||
<div className="flex flex-col p-3">
|
||||
<Form schema={_schema.auth} options={formOptions} />
|
||||
<Form schema={_schema.auth.toJSON()} options={formOptions} />
|
||||
|
||||
{/*<Form
|
||||
onChange={(data) => console.log("change", data)}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { typeboxResolver } from "@hookform/resolvers/typebox";
|
||||
import { standardSchemaResolver } from "@hookform/resolvers/standard-schema";
|
||||
import { TextInput } from "@mantine/core";
|
||||
import { Type } from "@sinclair/typebox";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { s } from "bknd/utils";
|
||||
|
||||
const schema = Type.Object({
|
||||
example: Type.Optional(Type.String()),
|
||||
exampleRequired: Type.String({ minLength: 2 }),
|
||||
const schema = s.object({
|
||||
example: s.string().optional(),
|
||||
exampleRequired: s.string({ minLength: 2 }),
|
||||
});
|
||||
|
||||
export default function ReactHookErrors() {
|
||||
@@ -15,8 +15,10 @@ export default function ReactHookErrors() {
|
||||
watch,
|
||||
formState: { errors },
|
||||
} = useForm({
|
||||
resolver: typeboxResolver(schema),
|
||||
resolver: standardSchemaResolver(schema),
|
||||
});
|
||||
const data = watch();
|
||||
|
||||
const onSubmit = (data) => console.log(data);
|
||||
|
||||
console.log(watch("example")); // watch input value by passing the name of it
|
||||
|
||||
Reference in New Issue
Block a user