Merge pull request #146 from bknd-io/chore/optimize-tb

adjust typebox imports and enable TS incremental
This commit is contained in:
dswbx
2025-04-11 13:11:35 +02:00
committed by GitHub
69 changed files with 256 additions and 189 deletions
+2 -3
View File
@@ -1,7 +1,6 @@
import { describe, expect, test } from "bun:test";
import type { TObject, TString } from "@sinclair/typebox";
import { Registry } from "../../src/core/registry/Registry";
import { type TSchema, Type } from "../../src/core/utils";
import { type TObject, type TString, Type } from "@sinclair/typebox";
import { Registry } from "core";
type Constructor<T> = new (...args: any[]) => T;
@@ -1,6 +1,6 @@
import { describe, expect, test } from "bun:test";
import { SchemaObject } from "../../../src/core";
import { Type } from "../../../src/core/utils";
import { Type } from "@sinclair/typebox";
describe("SchemaObject", async () => {
test("basic", async () => {
@@ -1,5 +1,5 @@
import { describe, expect, test } from "bun:test";
import { Type } from "../../../../src/core/utils";
import { Type } from "@sinclair/typebox";
import { Entity, EntityIndex, Field } from "../../../../src/data";
class TestField extends Field {
+1 -1
View File
@@ -1,5 +1,5 @@
import { describe, expect, test } from "bun:test";
import { Type } from "../../src/core/utils";
import { Type } from "@sinclair/typebox";
import { Task } from "../../src/flows";
import { dynamic } from "../../src/flows/tasks/Task";
+2 -1
View File
@@ -1,7 +1,8 @@
import { describe, expect, test } from "bun:test";
import { Hono } from "hono";
import { Event, EventManager } from "../../src/core/events";
import { type Static, type StaticDecode, Type, parse } from "../../src/core/utils";
import { parse } from "../../src/core/utils";
import { type Static, type StaticDecode, Type } from "@sinclair/typebox";
import { EventTrigger, Flow, HttpTrigger, type InputsMap, Task } from "../../src/flows";
import { dynamic } from "../../src/flows/tasks/Task";
+2 -1
View File
@@ -1,7 +1,8 @@
// eslint-disable-next-line import/no-unresolved
import { describe, expect, test } from "bun:test";
import { isEqual } from "lodash-es";
import { type Static, Type, _jsonp, withDisabledConsole } from "../../src/core/utils";
import { _jsonp, withDisabledConsole } from "../../src/core/utils";
import { type Static, Type } from "@sinclair/typebox";
import { Condition, ExecutionEvent, FetchTask, Flow, LogTask, Task } from "../../src/flows";
/*beforeAll(disableConsoleLog);
+4 -3
View File
@@ -1,5 +1,6 @@
import { describe, expect, test } from "bun:test";
import { type TSchema, Type, stripMark } from "../../src/core/utils";
import { stripMark } from "../../src/core/utils";
import { type TSchema, Type } from "@sinclair/typebox";
import { EntityManager, em, entity, index, text } from "../../src/data";
import { DummyConnection } from "../../src/data/connection/DummyConnection";
import { Module } from "../../src/modules/Module";
@@ -9,10 +10,10 @@ function createModule<Schema extends TSchema>(schema: Schema) {
getSchema() {
return schema;
}
toJSON() {
override toJSON() {
return this.config;
}
useForceParse() {
override useForceParse() {
return true;
}
}
+2 -1
View File
@@ -1,5 +1,6 @@
import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
import { Type, disableConsoleLog, enableConsoleLog, stripMark } from "../../src/core/utils";
import { disableConsoleLog, enableConsoleLog, stripMark } from "../../src/core/utils";
import { Type } from "@sinclair/typebox";
import { entity, text } from "../../src/data";
import { Module } from "../../src/modules/Module";
import { ModuleManager, getDefaultConfig } from "../../src/modules/ModuleManager";
@@ -1,8 +1,10 @@
import { registries } from "bknd";
import { isDebug } from "bknd/core";
import { StringEnum, Type } from "bknd/utils";
import { StringEnum } from "bknd/utils";
import { guessMimeType as guess, StorageAdapter, type FileBody } from "bknd/media";
import { getBindings } from "../bindings";
import * as tb from "@sinclair/typebox";
const { Type } = tb;
export function makeSchema(bindings: string[] = []) {
return Type.Object(
@@ -1,7 +1,9 @@
import { readFile, readdir, stat, unlink, writeFile } from "node:fs/promises";
import { type Static, Type, isFile, parse } from "bknd/utils";
import { type Static, isFile, parse } from "bknd/utils";
import type { FileBody, FileListObject, FileMeta, FileUploadPayload } from "bknd/media";
import { StorageAdapter, guessMimeType as guess } from "bknd/media";
import * as tb from "@sinclair/typebox";
const { Type } = tb;
export const localAdapterConfig = Type.Object(
{
+3 -1
View File
@@ -1,9 +1,11 @@
import { type AppAuth, AuthPermissions, type SafeUser, type Strategy } from "auth";
import { tbValidator as tb } from "core";
import { Type, TypeInvalidError, parse, transformObject } from "core/utils";
import { TypeInvalidError, parse, transformObject } from "core/utils";
import { DataPermissions } from "data";
import type { Hono } from "hono";
import { Controller, type ServerEnv } from "modules/Controller";
import * as tbbox from "@sinclair/typebox";
const { Type } = tbbox;
export type AuthActionResponse = {
success: boolean;
+3 -1
View File
@@ -1,6 +1,8 @@
import { cookieConfig, jwtConfig } from "auth/authenticate/Authenticator";
import { CustomOAuthStrategy, OAuthStrategy, PasswordStrategy } from "auth/authenticate/strategies";
import { type Static, StringRecord, Type, objectTransform } from "core/utils";
import { type Static, StringRecord, objectTransform } from "core/utils";
import * as tbbox from "@sinclair/typebox";
const { Type } = tbbox;
export const Strategies = {
password: {
+9 -1
View File
@@ -1,12 +1,20 @@
import { $console, type DB, Exception, type PrimaryFieldType } from "core";
import { addFlashMessage } from "core/server/flash";
import { parse, runtimeSupports, type Static, StringEnum, type TObject, Type } from "core/utils";
import {
type Static,
StringEnum,
type TObject,
parse,
runtimeSupports,
} from "core/utils";
import type { Context, Hono } from "hono";
import { deleteCookie, getSignedCookie, setSignedCookie } from "hono/cookie";
import { sign, verify } from "hono/jwt";
import type { CookieOptions } from "hono/utils/cookie";
import type { ServerEnv } from "modules/Controller";
import { pick } from "lodash-es";
import * as tbbox from "@sinclair/typebox";
const { Type } = tbbox;
type Input = any; // workaround
export type JWTPayload = Parameters<typeof sign>[0];
@@ -1,8 +1,11 @@
import type { Authenticator, Strategy } from "auth";
import { tbValidator as tb } from "core";
import { hash, parse, type Static, StringEnum, Type } from "core/utils";
import { type Static, StringEnum, parse } from "core/utils";
import { hash } from "core/utils";
import { Hono } from "hono";
import { createStrategyAction, type StrategyActions } from "../Authenticator";
import { type StrategyActions, createStrategyAction } from "../Authenticator";
import * as tbbox from "@sinclair/typebox";
const { Type } = tbbox;
type LoginSchema = { username: string; password: string } | { email: string; password: string };
type RegisterSchema = { email: string; password: string; [key: string]: any };
@@ -1,6 +1,8 @@
import { type Static, StringEnum, Type } from "core/utils";
import { type Static, StringEnum } from "core/utils";
import * as tbbox from "@sinclair/typebox";
import type * as oauth from "oauth4webapi";
import { OAuthStrategy } from "./OAuthStrategy";
const { Type } = tbbox;
type SupportedTypes = "oauth2" | "oidc";
@@ -1,10 +1,12 @@
import type { AuthAction, Authenticator, Strategy } from "auth";
import { Exception, isDebug } from "core";
import { type Static, StringEnum, Type, filterKeys } from "core/utils";
import { type Static, StringEnum, filterKeys } from "core/utils";
import { type Context, Hono } from "hono";
import { getSignedCookie, setSignedCookie } from "hono/cookie";
import * as oauth from "oauth4webapi";
import * as issuers from "./issuers";
import * as tbbox from "@sinclair/typebox";
const { Type } = tbbox;
type ConfiguredIssuers = keyof typeof issuers;
type SupportedTypes = "oauth2" | "oidc";
+46 -53
View File
@@ -1,18 +1,11 @@
import {
Kind,
type ObjectOptions,
type SchemaOptions,
type Static,
type StaticDecode,
type StringOptions,
type TLiteral,
type TLiteralValue,
type TObject,
type TRecord,
type TSchema,
type TString,
Type,
import * as tb from "@sinclair/typebox";
import type {
TypeRegistry,
Static,
StaticDecode,
TSchema,
SchemaOptions,
TObject,
} from "@sinclair/typebox";
import {
DefaultErrorFunction,
@@ -43,7 +36,7 @@ const validationSymbol = Symbol("tb-parse-validation");
export class TypeInvalidError extends Error {
errors: ValueError[];
constructor(
public schema: TSchema,
public schema: tb.TSchema,
public data: unknown,
message?: string,
) {
@@ -92,25 +85,25 @@ export function mark(obj: any, validated = true) {
}
}
export function parse<Schema extends TSchema = TSchema>(
export function parse<Schema extends tb.TSchema = tb.TSchema>(
schema: Schema,
data: RecursivePartial<Static<Schema>>,
data: RecursivePartial<tb.Static<Schema>>,
options?: ParseOptions,
): Static<Schema> {
): tb.Static<Schema> {
if (!options?.forceParse && typeof data === "object" && validationSymbol in data) {
if (options?.useDefaults === false) {
return data as Static<typeof schema>;
return data as tb.Static<typeof schema>;
}
// this is important as defaults are expected
return Default(schema, data as any) as Static<Schema>;
return Default(schema, data as any) as tb.Static<Schema>;
}
const parsed = options?.useDefaults === false ? data : Default(schema, data);
if (Check(schema, parsed)) {
options?.skipMark !== true && mark(parsed, true);
return parsed as Static<typeof schema>;
return parsed as tb.Static<typeof schema>;
} else if (options?.onError) {
options.onError(Errors(schema, data));
} else {
@@ -121,24 +114,24 @@ export function parse<Schema extends TSchema = TSchema>(
return undefined as any;
}
export function parseDecode<Schema extends TSchema = TSchema>(
export function parseDecode<Schema extends tb.TSchema = tb.TSchema>(
schema: Schema,
data: RecursivePartial<StaticDecode<Schema>>,
): StaticDecode<Schema> {
data: RecursivePartial<tb.StaticDecode<Schema>>,
): tb.StaticDecode<Schema> {
const parsed = Default(schema, data);
if (Check(schema, parsed)) {
return parsed as StaticDecode<typeof schema>;
return parsed as tb.StaticDecode<typeof schema>;
}
throw new TypeInvalidError(schema, data);
}
export function strictParse<Schema extends TSchema = TSchema>(
export function strictParse<Schema extends tb.TSchema = tb.TSchema>(
schema: Schema,
data: Static<Schema>,
data: tb.Static<Schema>,
options?: ParseOptions,
): Static<Schema> {
): tb.Static<Schema> {
return parse(schema, data as any, options);
}
@@ -147,11 +140,14 @@ export function registerCustomTypeboxKinds(registry: typeof TypeRegistry) {
return typeof value === "string" && schema.enum.includes(value);
});
}
registerCustomTypeboxKinds(TypeRegistry);
registerCustomTypeboxKinds(tb.TypeRegistry);
export const StringEnum = <const T extends readonly string[]>(values: T, options?: StringOptions) =>
Type.Unsafe<T[number]>({
[Kind]: "StringEnum",
export const StringEnum = <const T extends readonly string[]>(
values: T,
options?: tb.StringOptions,
) =>
tb.Type.Unsafe<T[number]>({
[tb.Kind]: "StringEnum",
type: "string",
enum: values,
...options,
@@ -159,17 +155,25 @@ export const StringEnum = <const T extends readonly string[]>(values: T, options
// key value record compatible with RJSF and typebox inference
// acting like a Record, but using an Object with additionalProperties
export const StringRecord = <T extends TSchema>(properties: T, options?: ObjectOptions) =>
Type.Object({}, { ...options, additionalProperties: properties }) as unknown as TRecord<
TString,
export const StringRecord = <T extends tb.TSchema>(properties: T, options?: tb.ObjectOptions) =>
tb.Type.Object({}, { ...options, additionalProperties: properties }) as unknown as tb.TRecord<
tb.TString,
typeof properties
>;
// fixed value that only be what is given + prefilled
export const Const = <T extends TLiteralValue = TLiteralValue>(value: T, options?: SchemaOptions) =>
Type.Literal(value, { ...options, default: value, const: value, readOnly: true }) as TLiteral<T>;
export const Const = <T extends tb.TLiteralValue = tb.TLiteralValue>(
value: T,
options?: tb.SchemaOptions,
) =>
tb.Type.Literal(value, {
...options,
default: value,
const: value,
readOnly: true,
}) as tb.TLiteral<T>;
export const StringIdentifier = Type.String({
export const StringIdentifier = tb.Type.String({
pattern: "^[a-zA-Z_][a-zA-Z0-9_]*$",
minLength: 2,
maxLength: 150,
@@ -180,24 +184,13 @@ SetErrorFunction((error) => {
return error.schema.errorMessage;
}
if (error?.schema?.[Kind] === "StringEnum") {
if (error?.schema?.[tb.Kind] === "StringEnum") {
return `Expected: ${error.schema.enum.map((e) => `"${e}"`).join(", ")}`;
}
return DefaultErrorFunction(error);
});
export {
Type,
type Static,
type StaticDecode,
type TSchema,
Kind,
type TObject,
type ValueError,
type SchemaOptions,
Value,
Default,
Errors,
Check,
};
export type { Static, StaticDecode, TSchema, TObject, ValueError, SchemaOptions };
export { Value, Default, Errors, Check };
+3 -1
View File
@@ -1,5 +1,6 @@
import { $console, isDebug, tbValidator as tb } from "core";
import { StringEnum, Type } from "core/utils";
import { StringEnum } from "core/utils";
import * as tbbox from "@sinclair/typebox";
import {
DataPermissions,
type EntityData,
@@ -14,6 +15,7 @@ import type { ModuleBuildContext } from "modules";
import { Controller } from "modules/Controller";
import * as SystemPermissions from "modules/permissions";
import type { AppDataConfig } from "../data-schema";
const { Type } = tbbox;
export class DataController extends Controller {
constructor(
+26 -23
View File
@@ -1,4 +1,5 @@
import { type Static, StringRecord, Type, objectTransform } from "core/utils";
import { type Static, StringRecord, objectTransform } from "core/utils";
import * as tb from "@sinclair/typebox";
import {
FieldClassMap,
RelationClassMap,
@@ -18,35 +19,37 @@ export type FieldType = keyof typeof FIELDS;
export const RELATIONS = RelationClassMap;
export const fieldsSchemaObject = objectTransform(FIELDS, (field, name) => {
return Type.Object(
return tb.Type.Object(
{
type: Type.Const(name, { default: name, readOnly: true }),
config: Type.Optional(field.schema),
type: tb.Type.Const(name, { default: name, readOnly: true }),
config: tb.Type.Optional(field.schema),
},
{
title: name,
},
);
});
export const fieldsSchema = Type.Union(Object.values(fieldsSchemaObject));
export const fieldsSchema = tb.Type.Union(Object.values(fieldsSchemaObject));
export const entityFields = StringRecord(fieldsSchema);
export type TAppDataField = Static<typeof fieldsSchema>;
export type TAppDataEntityFields = Static<typeof entityFields>;
export const entitiesSchema = Type.Object({
type: Type.Optional(Type.String({ enum: entityTypes, default: "regular", readOnly: true })),
config: Type.Optional(entityConfigSchema),
fields: Type.Optional(entityFields),
export const entitiesSchema = tb.Type.Object({
type: tb.Type.Optional(
tb.Type.String({ enum: entityTypes, default: "regular", readOnly: true }),
),
config: tb.Type.Optional(entityConfigSchema),
fields: tb.Type.Optional(entityFields),
});
export type TAppDataEntity = Static<typeof entitiesSchema>;
export const relationsSchema = Object.entries(RelationClassMap).map(([name, relationClass]) => {
return Type.Object(
return tb.Type.Object(
{
type: Type.Const(name, { default: name, readOnly: true }),
source: Type.String(),
target: Type.String(),
config: Type.Optional(relationClass.schema),
type: tb.Type.Const(name, { default: name, readOnly: true }),
source: tb.Type.String(),
target: tb.Type.String(),
config: tb.Type.Optional(relationClass.schema),
},
{
title: name,
@@ -55,23 +58,23 @@ export const relationsSchema = Object.entries(RelationClassMap).map(([name, rela
});
export type TAppDataRelation = Static<(typeof relationsSchema)[number]>;
export const indicesSchema = Type.Object(
export const indicesSchema = tb.Type.Object(
{
entity: Type.String(),
fields: Type.Array(Type.String(), { minItems: 1 }),
unique: Type.Optional(Type.Boolean({ default: false })),
entity: tb.Type.String(),
fields: tb.Type.Array(tb.Type.String(), { minItems: 1 }),
unique: tb.Type.Optional(tb.Type.Boolean({ default: false })),
},
{
additionalProperties: false,
},
);
export const dataConfigSchema = Type.Object(
export const dataConfigSchema = tb.Type.Object(
{
basepath: Type.Optional(Type.String({ default: "/api/data" })),
entities: Type.Optional(StringRecord(entitiesSchema, { default: {} })),
relations: Type.Optional(StringRecord(Type.Union(relationsSchema), { default: {} })),
indices: Type.Optional(StringRecord(indicesSchema, { default: {} })),
basepath: tb.Type.Optional(tb.Type.String({ default: "/api/data" })),
entities: tb.Type.Optional(StringRecord(entitiesSchema, { default: {} })),
relations: tb.Type.Optional(StringRecord(tb.Type.Union(relationsSchema), { default: {} })),
indices: tb.Type.Optional(StringRecord(indicesSchema, { default: {} })),
},
{
additionalProperties: false,
+2 -1
View File
@@ -2,12 +2,13 @@ import { $console, config } from "core";
import {
type Static,
StringEnum,
Type,
parse,
snakeToPascalWithSpaces,
transformObject,
} from "core/utils";
import { type Field, PrimaryField, type TActionContext, type TRenderContext } from "../fields";
import * as tbbox from "@sinclair/typebox";
const { Type } = tbbox;
// @todo: entity must be migrated to typebox
export const entityConfigSchema = Type.Object(
+3 -1
View File
@@ -1,7 +1,9 @@
import { type Static, Type } from "core/utils";
import type { Static } from "core/utils";
import type { EntityManager } from "data";
import { TransformPersistFailedException } from "../errors";
import { Field, type TActionContext, type TRenderContext, baseFieldConfigSchema } from "./Field";
import * as tb from "@sinclair/typebox";
const { Type } = tb;
export const booleanFieldConfigSchema = Type.Composite([
Type.Object({
+3 -1
View File
@@ -1,7 +1,9 @@
import { type Static, StringEnum, Type, dayjs } from "core/utils";
import { type Static, StringEnum, dayjs } from "core/utils";
import type { EntityManager } from "../entities";
import { Field, type TActionContext, type TRenderContext, baseFieldConfigSchema } from "./Field";
import { $console } from "core";
import * as tbbox from "@sinclair/typebox";
const { Type } = tbbox;
export const dateFieldConfigSchema = Type.Composite(
[
+3 -1
View File
@@ -1,7 +1,9 @@
import { Const, type Static, StringEnum, Type } from "core/utils";
import { Const, type Static, StringEnum } from "core/utils";
import type { EntityManager } from "data";
import { TransformPersistFailedException } from "../errors";
import { baseFieldConfigSchema, Field, type TActionContext, type TRenderContext } from "./Field";
import * as tbbox from "@sinclair/typebox";
const { Type } = tbbox;
export const enumFieldConfigSchema = Type.Composite(
[
+2 -1
View File
@@ -4,13 +4,14 @@ import {
type Static,
StringEnum,
type TSchema,
Type,
TypeInvalidError,
} from "core/utils";
import type { HTMLInputTypeAttribute, InputHTMLAttributes } from "react";
import type { EntityManager } from "../entities";
import { InvalidFieldConfigException, TransformPersistFailedException } from "../errors";
import type { FieldSpec } from "data/connection/Connection";
import * as tbbox from "@sinclair/typebox";
const { Type } = tbbox;
// @todo: contexts need to be reworked
// e.g. "table" is irrelevant, because if read is not given, it fails
+3 -1
View File
@@ -1,7 +1,9 @@
import { type Static, Type } from "core/utils";
import type { Static } from "core/utils";
import type { EntityManager } from "data";
import { TransformPersistFailedException } from "../errors";
import { Field, type TActionContext, type TRenderContext, baseFieldConfigSchema } from "./Field";
import * as tbbox from "@sinclair/typebox";
const { Type } = tbbox;
export const jsonFieldConfigSchema = Type.Composite([baseFieldConfigSchema, Type.Object({})]);
+3 -1
View File
@@ -1,8 +1,10 @@
import { type Schema as JsonSchema, Validator } from "@cfworker/json-schema";
import { Default, FromSchema, type Static, Type } from "core/utils";
import { Default, FromSchema, type Static } from "core/utils";
import type { EntityManager } from "data";
import { TransformPersistFailedException } from "../errors";
import { Field, type TActionContext, type TRenderContext, baseFieldConfigSchema } from "./Field";
import * as tbbox from "@sinclair/typebox";
const { Type } = tbbox;
export const jsonSchemaFieldConfigSchema = Type.Composite(
[
+3 -1
View File
@@ -1,7 +1,9 @@
import { type Static, Type } from "core/utils";
import type { Static } from "core/utils";
import type { EntityManager } from "data";
import { TransformPersistFailedException } from "../errors";
import { Field, type TActionContext, type TRenderContext, baseFieldConfigSchema } from "./Field";
import * as tbbox from "@sinclair/typebox";
const { Type } = tbbox;
export const numberFieldConfigSchema = Type.Composite(
[
+3 -1
View File
@@ -1,6 +1,8 @@
import { config } from "core";
import { type Static, Type } from "core/utils";
import type { Static } from "core/utils";
import { Field, baseFieldConfigSchema } from "./Field";
import * as tbbox from "@sinclair/typebox";
const { Type } = tbbox;
export const primaryFieldConfigSchema = Type.Composite([
Type.Omit(baseFieldConfigSchema, ["required"]),
+3 -1
View File
@@ -1,7 +1,9 @@
import { type Static, Type } from "core/utils";
import type { EntityManager } from "data";
import type { Static } from "core/utils";
import { TransformPersistFailedException } from "../errors";
import { Field, type TActionContext, baseFieldConfigSchema } from "./Field";
import * as tb from "@sinclair/typebox";
const { Type } = tb;
export const textFieldConfigSchema = Type.Composite(
[
+3 -1
View File
@@ -1,5 +1,7 @@
import { type Static, Type } from "core/utils";
import type { Static } from "core/utils";
import { Field, baseFieldConfigSchema } from "./Field";
import * as tbbox from "@sinclair/typebox";
const { Type } = tbbox;
export const virtualFieldConfigSchema = Type.Composite([baseFieldConfigSchema, Type.Object({})]);
+3 -1
View File
@@ -1,4 +1,4 @@
import { type Static, Type, parse } from "core/utils";
import { type Static, parse } from "core/utils";
import type { ExpressionBuilder, SelectQueryBuilder } from "kysely";
import type { Entity, EntityData, EntityManager } from "../entities";
import {
@@ -8,6 +8,8 @@ import {
} from "../relations";
import type { RepoQuery } from "../server/data-query-impl";
import type { RelationType } from "./relation-types";
import * as tbbox from "@sinclair/typebox";
const { Type } = tbbox;
export type KyselyJsonFrom = any;
export type KyselyQueryBuilder = SelectQueryBuilder<any, any, any>;
+3 -1
View File
@@ -1,4 +1,4 @@
import { type Static, Type } from "core/utils";
import type { Static } from "core/utils";
import type { ExpressionBuilder } from "kysely";
import { Entity, type EntityManager } from "../entities";
import { type Field, PrimaryField } from "../fields";
@@ -7,6 +7,8 @@ import { EntityRelation, type KyselyQueryBuilder } from "./EntityRelation";
import { EntityRelationAnchor } from "./EntityRelationAnchor";
import { RelationField } from "./RelationField";
import { type RelationType, RelationTypes } from "./relation-types";
import * as tbbox from "@sinclair/typebox";
const { Type } = tbbox;
export type ManyToManyRelationConfig = Static<typeof ManyToManyRelation.schema>;
+4 -1
View File
@@ -1,5 +1,6 @@
import type { PrimaryFieldType } from "core";
import { snakeToPascalWithSpaces, type Static, Type } from "core/utils";
import { snakeToPascalWithSpaces } from "core/utils";
import type { Static } from "core/utils";
import type { ExpressionBuilder } from "kysely";
import type { Entity, EntityManager } from "../entities";
import type { RepoQuery } from "../server/data-query-impl";
@@ -8,6 +9,8 @@ import { EntityRelationAnchor } from "./EntityRelationAnchor";
import { RelationField, type RelationFieldBaseConfig } from "./RelationField";
import type { MutationInstructionResponse } from "./RelationMutator";
import { type RelationType, RelationTypes } from "./relation-types";
import * as tbbox from "@sinclair/typebox";
const { Type } = tbbox;
/**
* Source entity receives the mapping field
@@ -1,4 +1,4 @@
import { type Static, Type } from "core/utils";
import type { Static } from "core/utils";
import type { ExpressionBuilder } from "kysely";
import type { Entity, EntityManager } from "../entities";
import { NumberField, TextField } from "../fields";
@@ -6,6 +6,8 @@ import type { RepoQuery } from "../server/data-query-impl";
import { EntityRelation, type KyselyJsonFrom, type KyselyQueryBuilder } from "./EntityRelation";
import { EntityRelationAnchor } from "./EntityRelationAnchor";
import { type RelationType, RelationTypes } from "./relation-types";
import * as tbbox from "@sinclair/typebox";
const { Type } = tbbox;
export type PolymorphicRelationConfig = Static<typeof PolymorphicRelation.schema>;
+3 -1
View File
@@ -1,8 +1,10 @@
import { type Static, StringEnum, Type } from "core/utils";
import { type Static, StringEnum } from "core/utils";
import type { EntityManager } from "../entities";
import { Field, baseFieldConfigSchema } from "../fields";
import type { EntityRelation } from "./EntityRelation";
import type { EntityRelationAnchor } from "./EntityRelationAnchor";
import * as tbbox from "@sinclair/typebox";
const { Type } = tbbox;
const CASCADES = ["cascade", "set null", "set default", "restrict", "no action"] as const;
+3 -9
View File
@@ -1,14 +1,8 @@
import type { TThis } from "@sinclair/typebox";
import {
type SchemaOptions,
type Static,
type StaticDecode,
StringEnum,
Type,
Value,
isObject,
} from "core/utils";
import { type SchemaOptions, type StaticDecode, StringEnum, Value, isObject } from "core/utils";
import { WhereBuilder, type WhereQuery } from "../entities";
import * as tbbox from "@sinclair/typebox";
const { Type } = tbbox;
const NumberOrString = (options: SchemaOptions = {}) =>
Type.Transform(Type.Union([Type.Number(), Type.String()], options))
+3 -1
View File
@@ -1,5 +1,7 @@
import { Const, type Static, StringRecord, Type, transformObject } from "core/utils";
import { Const, type Static, StringRecord, transformObject } from "core/utils";
import { TaskMap, TriggerMap } from "flows";
import * as tbbox from "@sinclair/typebox";
const { Type } = tbbox;
export const TASKS = {
...TaskMap,
+2 -1
View File
@@ -1,8 +1,9 @@
import type { EventManager } from "core/events";
import { Type } from "core/utils";
import type { Flow } from "../Flow";
import { Trigger } from "./Trigger";
import { $console } from "core";
import * as tbbox from "@sinclair/typebox";
const { Type } = tbbox;
export class EventTrigger extends Trigger<typeof EventTrigger.schema> {
override type = "event";
+3 -1
View File
@@ -1,7 +1,9 @@
import { StringEnum, Type } from "core/utils";
import { StringEnum } from "core/utils";
import type { Context, Hono } from "hono";
import type { Flow } from "../Flow";
import { Trigger } from "./Trigger";
import * as tbbox from "@sinclair/typebox";
const { Type } = tbbox;
const httpMethods = ["GET", "POST", "PUT", "PATCH", "DELETE"] as const;
+3 -1
View File
@@ -1,6 +1,8 @@
import { type Static, StringEnum, Type, parse } from "core/utils";
import { type Static, StringEnum, parse } from "core/utils";
import type { Execution } from "../Execution";
import type { Flow } from "../Flow";
import * as tbbox from "@sinclair/typebox";
const { Type } = tbbox;
export class Trigger<Schema extends typeof Trigger.schema = typeof Trigger.schema> {
// @todo: remove this
+4 -1
View File
@@ -1,7 +1,10 @@
import type { StaticDecode, TSchema } from "@sinclair/typebox";
import { BkndError, SimpleRenderer } from "core";
import { parse, type Static, type TObject, Type, ucFirst, Value } from "core/utils";
import { type Static, type TObject, Value, parse, ucFirst } from "core/utils";
import type { InputsMap } from "../flows/Execution";
import * as tbbox from "@sinclair/typebox";
const { Type } = tbbox;
//type InstanceOf<T> = T extends new (...args: any) => infer R ? R : never;
export type TaskResult<Output = any> = {
start: Date;
+3 -2
View File
@@ -1,6 +1,7 @@
import { StringEnum, Type } from "core/utils";
import type { InputsMap } from "../../flows/Execution";
import { StringEnum } from "core/utils";
import { Task, dynamic } from "../Task";
import * as tbbox from "@sinclair/typebox";
const { Type } = tbbox;
const FetchMethods = ["GET", "POST", "PUT", "PATCH", "DELETE"];
+2 -1
View File
@@ -1,6 +1,7 @@
import { Type } from "core/utils";
import { Task } from "../Task";
import { $console } from "core";
import * as tbbox from "@sinclair/typebox";
const { Type } = tbbox;
export class LogTask extends Task<typeof LogTask.schema> {
type = "log";
+2 -1
View File
@@ -1,5 +1,6 @@
import { Type } from "core/utils";
import { Task } from "../Task";
import * as tbbox from "@sinclair/typebox";
const { Type } = tbbox;
export class RenderTask<Output extends Record<string, any>> extends Task<
typeof RenderTask.schema,
+2 -1
View File
@@ -1,6 +1,7 @@
import { Type } from "core/utils";
import { Flow } from "../../flows/Flow";
import { Task, dynamic } from "../Task";
import * as tbbox from "@sinclair/typebox";
const { Type } = tbbox;
export class SubFlowTask<Output extends Record<string, any>> extends Task<
typeof SubFlowTask.schema,
+3 -1
View File
@@ -1,5 +1,7 @@
import { type Static, Type } from "core/utils";
import type { Static } from "core/utils";
import { Field, baseFieldConfigSchema } from "data";
import * as tbbox from "@sinclair/typebox";
const { Type } = tbbox;
export const mediaFieldConfigSchema = Type.Composite([
Type.Object({
+3 -1
View File
@@ -1,10 +1,12 @@
import { isDebug, tbValidator as tb } from "core";
import { HttpStatus, Type, getFileFromContext, headersToObject } from "core/utils";
import { HttpStatus, getFileFromContext } from "core/utils";
import type { StorageAdapter } from "media";
import { StorageEvents, getRandomizedFilename } from "media";
import { Controller } from "modules/Controller";
import type { AppMedia } from "../AppMedia";
import { MediaField } from "../MediaField";
import * as tbbox from "@sinclair/typebox";
const { Type } = tbbox;
const booleanLike = Type.Transform(Type.String())
.Decode((v) => v === "1")
+3 -1
View File
@@ -1,6 +1,8 @@
import { Const, type Static, Type, objectTransform } from "core/utils";
import { Const, type Static, objectTransform } from "core/utils";
import { Adapters } from "media";
import { registries } from "modules/registries";
import * as tbbox from "@sinclair/typebox";
const { Type } = tbbox;
export const ADAPTERS = {
...Adapters,
@@ -1,7 +1,9 @@
import { hash, pickHeaders } from "core/utils";
import { type Static, Type, parse } from "core/utils";
import { type Static, parse } from "core/utils";
import type { FileBody, FileListObject, FileMeta } from "../../Storage";
import { StorageAdapter } from "../../StorageAdapter";
import * as tbbox from "@sinclair/typebox";
const { Type } = tbbox;
export const cloudinaryAdapterConfig = Type.Object(
{
@@ -7,10 +7,12 @@ import type {
PutObjectRequest,
} from "@aws-sdk/client-s3";
import { AwsClient, isDebug } from "core";
import { type Static, Type, isFile, parse, pickHeaders2 } from "core/utils";
import { type Static, isFile, parse, pickHeaders2 } from "core/utils";
import { transform } from "lodash-es";
import type { FileBody, FileListObject } from "../../Storage";
import { StorageAdapter } from "../../StorageAdapter";
import * as tbbox from "@sinclair/typebox";
const { Type } = tbbox;
export const s3AdapterConfig = Type.Object(
{
+2 -1
View File
@@ -6,7 +6,6 @@ import {
Default,
type Static,
StringEnum,
Type,
mark,
objectEach,
stripMark,
@@ -34,6 +33,8 @@ import { AppFlows } from "../flows/AppFlows";
import { AppMedia } from "../media/AppMedia";
import type { ServerEnv } from "./Controller";
import { Module, type ModuleBuildContext } from "./Module";
import * as tbbox from "@sinclair/typebox";
const { Type } = tbbox;
export type { ModuleBuildContext };
+4 -2
View File
@@ -1,7 +1,9 @@
import { $console, Exception, isDebug } from "core";
import { type Static, StringEnum, Type } from "core/utils";
import { Exception, isDebug, $console } from "core";
import { type Static, StringEnum } from "core/utils";
import { cors } from "hono/cors";
import { Module } from "modules/Module";
import * as tbbox from "@sinclair/typebox";
const { Type } = tbbox;
const serverMethods = ["GET", "POST", "PATCH", "PUT", "DELETE"];
+2 -1
View File
@@ -4,7 +4,6 @@ import type { App } from "App";
import { $console, tbValidator as tb } from "core";
import {
StringEnum,
Type,
TypeInvalidError,
datetimeStringLocal,
datetimeStringUTC,
@@ -14,6 +13,8 @@ import {
import { getRuntimeKey } from "core/utils";
import type { Context, Hono } from "hono";
import { Controller } from "modules/Controller";
import * as tbbox from "@sinclair/typebox";
const { Type } = tbbox;
import {
MODULE_NAMES,
+2 -1
View File
@@ -1,6 +1,7 @@
import { Type } from "core/utils";
import type { ModuleConfigs } from "modules/ModuleManager";
import type { OpenAPIV3 as OAS } from "openapi-types";
import * as tbbox from "@sinclair/typebox";
const { Type } = tbbox;
function prefixPaths(paths: OAS.PathsObject, prefix: string): OAS.PathsObject {
const result: OAS.PathsObject = {};
@@ -1,4 +1,4 @@
import { Type, TypeInvalidError, parse, transformObject } from "core/utils";
import { TypeInvalidError, parse, transformObject } from "core/utils";
import { constructEntity } from "data";
import {
type TAppDataEntity,
@@ -13,6 +13,8 @@ import {
import { useBknd } from "ui/client/bknd";
import type { TSchemaActions } from "ui/client/schema/actions";
import { bkndModals } from "ui/modals";
import * as tb from "@sinclair/typebox";
const { Type } = tb;
export function useBkndData() {
const { config, app, schema, actions: bkndActions } = useBknd();
+2 -1
View File
@@ -1,6 +1,5 @@
import type { AppAuthOAuthStrategy, AppAuthSchema } from "auth/auth-schema";
import clsx from "clsx";
import { Type } from "core/utils";
import { Form } from "json-schema-form-react";
import { transform } from "lodash-es";
import type { ComponentPropsWithoutRef } from "react";
@@ -11,6 +10,8 @@ import type { ValueError } from "@sinclair/typebox/value";
import { type TSchema, Value } from "core/utils";
import type { Validator } from "json-schema-form-react";
import { useTheme } from "ui/client/use-theme";
import * as tbbox from "@sinclair/typebox";
const { Type } = tbbox;
class TypeboxValidator implements Validator<ValueError> {
async validate(schema: TSchema, data: any) {
-1
View File
@@ -2,7 +2,6 @@ import {
type Static,
type StaticDecode,
type TSchema,
Type,
decodeSearch,
encodeSearch,
parseDecode,
@@ -1,6 +1,6 @@
import type { ModalProps } from "@mantine/core";
import type { ContextModalProps } from "@mantine/modals";
import { type Static, StringEnum, StringIdentifier, Type } from "core/utils";
import { type Static, StringEnum, StringIdentifier } from "core/utils";
import { entitiesSchema, fieldsSchema, relationsSchema } from "data/data-schema";
import { useState } from "react";
import { type Modal2Ref, ModalBody, ModalFooter, ModalTitle } from "ui/components/modal/Modal2";
@@ -11,6 +11,8 @@ import { StepEntityFields } from "./step.entity.fields";
import { StepRelation } from "./step.relation";
import { StepSelect } from "./step.select";
import Templates from "./templates/register";
import * as tbbox from "@sinclair/typebox";
const { Type } = tbbox;
export type CreateModalRef = Modal2Ref;
@@ -2,15 +2,9 @@ import { typeboxResolver } from "@hookform/resolvers/typebox";
import { Switch, TextInput } from "@mantine/core";
import { TypeRegistry } from "@sinclair/typebox";
import { IconDatabase } from "@tabler/icons-react";
import {
type Static,
StringEnum,
StringIdentifier,
Type,
registerCustomTypeboxKinds,
} from "core/utils";
import { type Static, StringEnum, StringIdentifier, registerCustomTypeboxKinds } from "core/utils";
import { ManyToOneRelation, type RelationType, RelationTypes } from "data";
import { type ReactNode, startTransition, useEffect } from "react";
import type { ReactNode } from "react";
import { type Control, type FieldValues, type UseFormRegister, useForm } from "react-hook-form";
import { TbRefresh } from "react-icons/tb";
import { useBknd } from "ui/client/bknd";
@@ -20,6 +14,8 @@ import { MantineSelect } from "ui/components/form/hook-form-mantine/MantineSelec
import { useStepContext } from "ui/components/steps/Steps";
import { useEvent } from "ui/hooks/use-event";
import { ModalBody, ModalFooter, type TCreateModalSchema } from "./CreateModal";
import * as tbbox from "@sinclair/typebox";
const { Type } = tbbox;
// @todo: check if this could become an issue
registerCustomTypeboxKinds(TypeRegistry);
@@ -1,13 +1,6 @@
import { typeboxResolver } from "@hookform/resolvers/typebox";
import { Radio, TextInput } from "@mantine/core";
import {
Default,
type Static,
StringEnum,
StringIdentifier,
Type,
transformObject,
} from "core/utils";
import { Default, type Static, StringEnum, StringIdentifier, transformObject } from "core/utils";
import type { MediaFieldConfig } from "media/MediaField";
import { useEffect, useState } from "react";
import { useForm } from "react-hook-form";
@@ -22,6 +15,8 @@ import {
type TFieldCreate,
useStepContext,
} from "../../CreateModal";
import * as tbbox from "@sinclair/typebox";
const { Type } = tbbox;
const schema = Type.Object({
entity: StringIdentifier,
@@ -1,9 +1,11 @@
import { Handle, type Node, type NodeProps, Position } from "@xyflow/react";
import { Const, Type, transformObject } from "core/utils";
import { Const, transformObject } from "core/utils";
import { type Trigger, TriggerMap } from "flows";
import type { IconType } from "react-icons";
import { TbCircleLetterT } from "react-icons/tb";
import { JsonSchemaForm } from "ui/components/form/json-schema";
import * as tbbox from "@sinclair/typebox";
const { Type } = tbbox;
export type TaskComponentProps = NodeProps<Node<{ trigger: Trigger }>> & {
Icon?: IconType;
@@ -4,7 +4,6 @@ import { useToggle } from "@mantine/hooks";
import { IconMinus, IconPlus, IconWorld } from "@tabler/icons-react";
import type { Node, NodeProps } from "@xyflow/react";
import type { Static } from "core/utils";
import { Type } from "core/utils";
import { FetchTask } from "flows";
import { useRef, useState } from "react";
import { useForm } from "react-hook-form";
@@ -15,6 +14,8 @@ import { MantineSelect } from "ui/components/form/hook-form-mantine/MantineSelec
import { type TFlowNodeData, useFlowSelector } from "../../../hooks/use-flow";
import { KeyValueInput } from "../../form/KeyValueInput";
import { BaseNode } from "../BaseNode";
import * as tbbox from "@sinclair/typebox";
const { Type } = tbbox;
const schema = Type.Composite([
FetchTask.schema,
@@ -1,20 +1,9 @@
import { typeboxResolver } from "@hookform/resolvers/typebox";
import { TextInput } from "@mantine/core";
import { TypeRegistry } from "@sinclair/typebox";
import { Clean } from "@sinclair/typebox/value";
import { type Node, type NodeProps, Position } from "@xyflow/react";
import {
Const,
type Static,
StringEnum,
Type,
registerCustomTypeboxKinds,
transformObject,
} from "core/utils";
import type { Node, NodeProps } from "@xyflow/react";
import { Const, type Static, registerCustomTypeboxKinds, transformObject } from "core/utils";
import { TriggerMap } from "flows";
import type { TAppFlowTriggerSchema } from "flows/AppFlows";
import { isEqual } from "lodash-es";
import { useEffect } from "react";
import { useForm } from "react-hook-form";
import { JsonViewer } from "ui/components/code/JsonViewer";
import { MantineSegmentedControl } from "ui/components/form/hook-form-mantine/MantineSegmentedControl";
@@ -22,6 +11,8 @@ import { MantineSelect } from "ui/components/form/hook-form-mantine/MantineSelec
import { useFlowCanvas, useFlowSelector } from "../../../hooks/use-flow";
import { BaseNode } from "../BaseNode";
import { Handle } from "../Handle";
import * as tb from "@sinclair/typebox";
const { Type, TypeRegistry } = tb;
// @todo: check if this could become an issue
registerCustomTypeboxKinds(TypeRegistry);
+1 -1
View File
@@ -1,6 +1,6 @@
import clsx from "clsx";
import { isDebug } from "core";
import { TbAlertCircle, TbChevronDown, TbChevronUp } from "react-icons/tb";
import { TbChevronDown, TbChevronUp } from "react-icons/tb";
import { useBknd } from "ui/client/BkndProvider";
import { useBkndAuth } from "ui/client/schema/auth/use-bknd-auth";
import { Button } from "ui/components/buttons/Button";
@@ -1,4 +1,3 @@
import { Type } from "core/utils";
import type { EntityData } from "data";
import { useState } from "react";
import { useEntityMutate } from "ui/client";
@@ -12,6 +11,8 @@ import { Breadcrumbs2 } from "ui/layouts/AppShell/Breadcrumbs2";
import { routes } from "ui/lib/routes";
import { EntityForm } from "ui/modules/data/components/EntityForm";
import { useEntityForm } from "ui/modules/data/hooks/useEntityForm";
import * as tbbox from "@sinclair/typebox";
const { Type } = tbbox;
export function DataEntityCreate({ params }) {
const { $data } = useBkndData();
@@ -1,4 +1,3 @@
import { Type } from "core/utils";
import { type Entity, querySchema } from "data";
import { Fragment } from "react";
import { TbDots } from "react-icons/tb";
@@ -15,6 +14,8 @@ 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 * as tbbox from "@sinclair/typebox";
const { Type } = tbbox;
// @todo: migrate to Typebox
const searchSchema = Type.Composite(
@@ -5,7 +5,6 @@ import {
Default,
type Static,
StringIdentifier,
Type,
objectCleanEmpty,
ucFirstAllSnakeToPascalWithSpaces,
} from "core/utils";
@@ -27,6 +26,8 @@ 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";
const { Type } = tbbox;
const fieldsSchemaObject = originalFieldsSchemaObject;
const fieldsSchema = Type.Union(Object.values(fieldsSchemaObject));
@@ -2,13 +2,7 @@ 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,
Type,
registerCustomTypeboxKinds,
} from "core/utils";
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";
@@ -22,6 +16,8 @@ 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);
+1
View File
@@ -2,6 +2,7 @@
"compilerOptions": {
"types": ["bun-types", "@cloudflare/workers-types"],
"composite": false,
"incremental": true,
"module": "ESNext",
"moduleResolution": "bundler",
"jsx": "react-jsx",