Merge remote-tracking branch 'origin/release/0.17' into feat/mcp

# Conflicts:
#	app/src/data/AppData.ts
#	app/src/data/server/query.ts
#	examples/cloudflare-worker/src/index.ts
This commit is contained in:
dswbx
2025-08-12 16:17:26 +02:00
68 changed files with 213 additions and 263 deletions

View File

@@ -4,7 +4,7 @@ import { DataApi, type DataApiOptions } from "data/api/DataApi";
import { decode } from "hono/jwt";
import { MediaApi, type MediaApiOptions } from "media/api/MediaApi";
import { SystemApi } from "modules/SystemApi";
import { omitKeys } from "core/utils";
import { omitKeys } from "bknd/utils";
import type { BaseModuleApiOptions } from "modules";
export type TApiUser = SafeUser;

View File

@@ -1,5 +1,5 @@
import type { CreateUserPayload } from "auth/AppAuth";
import { $console } from "core/utils";
import { $console } from "bknd/utils";
import { Event } from "core/events";
import type { em as prototypeEm } from "data/prototype";
import { Connection } from "data/connection/Connection";

View File

@@ -1,3 +1,5 @@
import { inspect } from "node:util";
export type BindingTypeMap = {
D1Database: D1Database;
KVNamespace: KVNamespace;
@@ -13,8 +15,9 @@ export function getBindings<T extends GetBindingType>(env: any, type: T): Bindin
for (const key in env) {
try {
if (
env[key] &&
((env[key] as any).constructor.name === type || String(env[key]) === `[object ${type}]`)
(env[key] as any).constructor.name === type ||
String(env[key]) === `[object ${type}]` ||
inspect(env[key]).includes(type)
) {
bindings.push({
key,

View File

@@ -18,7 +18,7 @@ describe("cf adapter", () => {
});
it("makes config", async () => {
const staticConfig = makeConfig(
const staticConfig = await makeConfig(
{
connection: { url: DB_URL },
initialConfig: { data: { basepath: DB_URL } },
@@ -28,7 +28,7 @@ describe("cf adapter", () => {
expect(staticConfig.initialConfig).toEqual({ data: { basepath: DB_URL } });
expect(staticConfig.connection).toBeDefined();
const dynamicConfig = makeConfig(
const dynamicConfig = await makeConfig(
{
app: (env) => ({
initialConfig: { data: { basepath: env.DB_URL } },

View File

@@ -5,9 +5,8 @@ import { Hono } from "hono";
import { serveStatic } from "hono/cloudflare-workers";
import { getFresh } from "./modes/fresh";
import { getCached } from "./modes/cached";
import { getDurable } from "./modes/durable";
import type { App } from "bknd";
import { $console } from "core/utils";
import type { App, MaybePromise } from "bknd";
import { $console } from "bknd/utils";
declare global {
namespace Cloudflare {
@@ -17,12 +16,11 @@ declare global {
export type CloudflareEnv = Cloudflare.Env;
export type CloudflareBkndConfig<Env = CloudflareEnv> = RuntimeBkndConfig<Env> & {
mode?: "warm" | "fresh" | "cache" | "durable";
bindings?: (args: Env) => {
mode?: "warm" | "fresh" | "cache";
bindings?: (args: Env) => MaybePromise<{
kv?: KVNamespace;
dobj?: DurableObjectNamespace;
db?: D1Database;
};
}>;
d1?: {
session?: boolean;
transport?: "header" | "cookie";
@@ -93,8 +91,6 @@ export function serve<Env extends CloudflareEnv = CloudflareEnv>(
case "cache":
app = await getCached(config, context);
break;
case "durable":
return await getDurable(config, context);
default:
throw new Error(`Unknown mode ${mode}`);
}

View File

@@ -9,7 +9,7 @@ import { d1Sqlite } from "./connection/D1Connection";
import type { CloudflareBkndConfig, CloudflareEnv } from ".";
import { App } from "bknd";
import type { Context, ExecutionContext } from "hono";
import { $console } from "core/utils";
import { $console } from "bknd/utils";
import { setCookie } from "hono/cookie";
export const constants = {
@@ -89,7 +89,7 @@ export function d1SessionHelper(config: CloudflareBkndConfig<any>) {
}
let media_registered: boolean = false;
export function makeConfig<Env extends CloudflareEnv = CloudflareEnv>(
export async function makeConfig<Env extends CloudflareEnv = CloudflareEnv>(
config: CloudflareBkndConfig<Env>,
args?: CfMakeConfigArgs<Env>,
) {
@@ -102,7 +102,7 @@ export function makeConfig<Env extends CloudflareEnv = CloudflareEnv>(
media_registered = true;
}
const appConfig = makeAdapterConfig(config, args?.env);
const appConfig = await makeAdapterConfig(config, args?.env);
// if connection instance is given, don't do anything
// other than checking if D1 session is defined
@@ -115,12 +115,12 @@ export function makeConfig<Env extends CloudflareEnv = CloudflareEnv>(
}
// if connection is given, try to open with unified sqlite adapter
} else if (appConfig.connection) {
appConfig.connection = sqlite(appConfig.connection);
appConfig.connection = sqlite(appConfig.connection) as any;
// if connection is not given, but env is set
// try to make D1 from bindings
} else if (args?.env) {
const bindings = config.bindings?.(args?.env);
const bindings = await config.bindings?.(args?.env);
const sessionHelper = d1SessionHelper(config);
const sessionId = sessionHelper.get(args.request);
let session: D1DatabaseSession | undefined;

View File

@@ -3,16 +3,16 @@
import { genericSqlite, type GenericSqliteConnection } from "bknd";
import type { QueryResult } from "kysely";
export type D1SqliteConnection = GenericSqliteConnection<D1Database>;
export type DoSqliteConnection = GenericSqliteConnection<DurableObjectState["storage"]["sql"]>;
export type DurableObjecSql = DurableObjectState["storage"]["sql"];
export type D1ConnectionConfig<DB extends DurableObjecSql> =
export type DoConnectionConfig<DB extends DurableObjecSql> =
| DurableObjectState
| {
sql: DB;
};
export function doSqlite<DB extends DurableObjecSql>(config: D1ConnectionConfig<DB>) {
export function doSqlite<DB extends DurableObjecSql>(config: DoConnectionConfig<DB>) {
const db = "sql" in config ? config.sql : config.storage.sql;
return genericSqlite(
@@ -21,7 +21,7 @@ export function doSqlite<DB extends DurableObjecSql>(config: D1ConnectionConfig<
(utils) => {
// must be async to work with the miniflare mock
const getStmt = async (sql: string, parameters?: any[] | readonly any[]) =>
await db.exec(sql, ...(parameters || []));
db.exec(sql, ...(parameters || []));
const mapResult = (
cursor: SqlStorageCursor<Record<string, SqlStorageValue>>,

View File

@@ -3,8 +3,8 @@ import { d1Sqlite, type D1ConnectionConfig } from "./connection/D1Connection";
export * from "./cloudflare-workers.adapter";
export { makeApp, getFresh } from "./modes/fresh";
export { getCached } from "./modes/cached";
export { DurableBkndApp, getDurable } from "./modes/durable";
export { d1Sqlite, type D1ConnectionConfig };
export { doSqlite, type DoConnectionConfig } from "./connection/DoConnection";
export {
getBinding,
getBindings,
@@ -15,6 +15,7 @@ export {
export { constants } from "./config";
export { StorageR2Adapter, registerMedia } from "./storage/StorageR2Adapter";
export { registries } from "bknd";
export { withPlatformProxy } from "./proxy";
// for compatibility with old code
export function d1<DB extends D1Database | D1DatabaseSession = D1Database>(

View File

@@ -8,7 +8,7 @@ export async function getCached<Env extends CloudflareEnv = CloudflareEnv>(
args: Context<Env>,
) {
const { env, ctx } = args;
const { kv } = config.bindings?.(env)!;
const { kv } = await config.bindings?.(env)!;
if (!kv) throw new Error("kv namespace is not defined in cloudflare.bindings");
const key = config.key ?? "app";

View File

@@ -1,134 +0,0 @@
import { DurableObject } from "cloudflare:workers";
import type { App, CreateAppConfig } from "bknd";
import { createRuntimeApp, makeConfig } from "bknd/adapter";
import type { CloudflareBkndConfig, Context, CloudflareEnv } from "../index";
import { constants, registerAsyncsExecutionContext } from "../config";
import { $console } from "core/utils";
export async function getDurable<Env extends CloudflareEnv = CloudflareEnv>(
config: CloudflareBkndConfig<Env>,
ctx: Context<Env>,
) {
const { dobj } = config.bindings?.(ctx.env)!;
if (!dobj) throw new Error("durable object is not defined in cloudflare.bindings");
const key = config.key ?? "app";
if ([config.onBuilt, config.beforeBuild].some((x) => x)) {
$console.warn("onBuilt and beforeBuild are not supported with DurableObject mode");
}
const start = performance.now();
const id = dobj.idFromName(key);
const stub = dobj.get(id) as unknown as DurableBkndApp;
const create_config = makeConfig(config, ctx.env);
const res = await stub.fire(ctx.request, {
config: create_config,
keepAliveSeconds: config.keepAliveSeconds,
});
const headers = new Headers(res.headers);
headers.set("X-TTDO", String(performance.now() - start));
return new Response(res.body, {
status: res.status,
statusText: res.statusText,
headers,
});
}
export class DurableBkndApp extends DurableObject {
protected id = Math.random().toString(36).slice(2);
protected app?: App;
protected interval?: any;
async fire(
request: Request,
options: {
config: CreateAppConfig;
html?: string;
keepAliveSeconds?: number;
setAdminHtml?: boolean;
},
) {
let buildtime = 0;
if (!this.app) {
const start = performance.now();
const config = options.config;
// change protocol to websocket if libsql
if (
config?.connection &&
"type" in config.connection &&
config.connection.type === "libsql"
) {
//config.connection.config.protocol = "wss";
}
this.app = await createRuntimeApp({
...config,
onBuilt: async (app) => {
registerAsyncsExecutionContext(app, this.ctx);
app.modules.server.get(constants.do_endpoint, async (c) => {
// @ts-ignore
const context: any = c.req.raw.cf ? c.req.raw.cf : c.env.cf;
return c.json({
id: this.id,
keepAliveSeconds: options?.keepAliveSeconds ?? 0,
colo: context.colo,
});
});
await this.onBuilt(app);
},
adminOptions: { html: options.html },
beforeBuild: async (app) => {
await this.beforeBuild(app);
},
});
buildtime = performance.now() - start;
}
if (options?.keepAliveSeconds) {
this.keepAlive(options.keepAliveSeconds);
}
const res = await this.app!.fetch(request);
const headers = new Headers(res.headers);
headers.set("X-BuildTime", buildtime.toString());
headers.set("X-DO-ID", this.id);
return new Response(res.body, {
status: res.status,
statusText: res.statusText,
headers,
});
}
async onBuilt(app: App) {}
async beforeBuild(app: App) {}
protected keepAlive(seconds: number) {
if (this.interval) {
clearInterval(this.interval);
}
let i = 0;
this.interval = setInterval(() => {
i += 1;
if (i === seconds) {
console.log("cleared");
clearInterval(this.interval);
// ping every 30 seconds
} else if (i % 30 === 0) {
console.log("ping");
this.app?.modules.ctx().connection.ping();
}
}, 1000);
}
}

View File

@@ -7,7 +7,7 @@ export async function makeApp<Env extends CloudflareEnv = CloudflareEnv>(
args?: CfMakeConfigArgs<Env>,
opts?: RuntimeOptions,
) {
return await createRuntimeApp<Env>(makeConfig(config, args), args?.env, opts);
return await createRuntimeApp<Env>(await makeConfig(config, args), args?.env, opts);
}
export async function getFresh<Env extends CloudflareEnv = CloudflareEnv>(

View File

@@ -0,0 +1,66 @@
import {
d1Sqlite,
getBinding,
registerMedia,
type CloudflareBkndConfig,
type CloudflareEnv,
} from ".";
import type { PlatformProxy } from "wrangler";
import process from "node:process";
export type WithPlatformProxyOptions = {
/**
* By default, proxy is used if the PROXY environment variable is set to 1.
* You can override/force this by setting this option.
*/
useProxy?: boolean;
};
export function withPlatformProxy<Env extends CloudflareEnv>(
config?: CloudflareBkndConfig<Env>,
opts?: WithPlatformProxyOptions,
) {
const use_proxy =
typeof opts?.useProxy === "boolean" ? opts.useProxy : process.env.PROXY === "1";
let proxy: PlatformProxy | undefined;
async function getEnv(env?: Env): Promise<Env> {
if (use_proxy) {
if (!proxy) {
const getPlatformProxy = await import("wrangler").then((mod) => mod.getPlatformProxy);
proxy = await getPlatformProxy();
setTimeout(proxy?.dispose, 1000);
}
return proxy.env as unknown as Env;
}
return env || ({} as Env);
}
return {
...config,
beforeBuild: async (app, registries) => {
if (!use_proxy) return;
const env = await getEnv();
registerMedia(env, registries);
await config?.beforeBuild?.(app, registries);
},
bindings: async (env) => {
return (await config?.bindings?.(await getEnv(env))) || {};
},
app: async (_env) => {
const env = await getEnv(_env);
if (config?.app === undefined && use_proxy) {
const binding = getBinding(env, "D1Database");
return {
connection: d1Sqlite({
binding: binding.value,
}),
};
} else if (typeof config?.app === "function") {
return config?.app(env);
}
return config?.app || {};
},
} satisfies CloudflareBkndConfig<Env>;
}

View File

@@ -1,4 +1,4 @@
import { registries, isDebug, guessMimeType } from "bknd";
import { registries as $registries, isDebug, guessMimeType } from "bknd";
import { getBindings } from "../bindings";
import { s } from "bknd/utils";
import { StorageAdapter, type FileBody } from "bknd";
@@ -12,7 +12,10 @@ export function makeSchema(bindings: string[] = []) {
);
}
export function registerMedia(env: Record<string, any>) {
export function registerMedia(
env: Record<string, any>,
registries: typeof $registries = $registries,
) {
const r2_bindings = getBindings(env, "R2Bucket");
registries.media.register(

View File

@@ -1,13 +1,21 @@
import { config as $config, App, type CreateAppConfig, Connection, guessMimeType } from "bknd";
import {
config as $config,
App,
type CreateAppConfig,
Connection,
guessMimeType,
type MaybePromise,
registries as $registries,
} from "bknd";
import { $console } from "bknd/utils";
import type { Context, MiddlewareHandler, Next } from "hono";
import type { AdminControllerOptions } from "modules/server/AdminController";
import type { Manifest } from "vite";
export type BkndConfig<Args = any> = CreateAppConfig & {
app?: CreateAppConfig | ((args: Args) => CreateAppConfig);
app?: CreateAppConfig | ((args: Args) => MaybePromise<CreateAppConfig>);
onBuilt?: (app: App) => Promise<void>;
beforeBuild?: (app: App) => Promise<void>;
beforeBuild?: (app: App, registries?: typeof $registries) => Promise<void>;
buildConfig?: Parameters<App["build"]>[0];
};
@@ -30,10 +38,10 @@ export type DefaultArgs = {
[key: string]: any;
};
export function makeConfig<Args = DefaultArgs>(
export async function makeConfig<Args = DefaultArgs>(
config: BkndConfig<Args>,
args?: Args,
): CreateAppConfig {
): Promise<CreateAppConfig> {
let additionalConfig: CreateAppConfig = {};
const { app, ...rest } = config;
if (app) {
@@ -41,7 +49,7 @@ export function makeConfig<Args = DefaultArgs>(
if (!args) {
throw new Error("args is required when config.app is a function");
}
additionalConfig = app(args);
additionalConfig = await app(args);
} else {
additionalConfig = app;
}
@@ -60,7 +68,7 @@ export async function createAdapterApp<Config extends BkndConfig = BkndConfig, A
const id = opts?.id ?? "app";
let app = apps.get(id);
if (!app || opts?.force) {
const appConfig = makeConfig(config, args);
const appConfig = await makeConfig(config, args);
if (!appConfig.connection || !Connection.isConnection(appConfig.connection)) {
let connection: Connection | undefined;
if (Connection.isConnection(config.connection)) {
@@ -68,7 +76,7 @@ export async function createAdapterApp<Config extends BkndConfig = BkndConfig, A
} else {
const sqlite = (await import("bknd/adapter/sqlite")).sqlite;
const conf = appConfig.connection ?? { url: ":memory:" };
connection = sqlite(conf);
connection = sqlite(conf) as any;
$console.info(`Using ${connection!.name} connection`, conf.url);
}
appConfig.connection = connection;
@@ -98,7 +106,7 @@ export async function createFrameworkApp<Args = DefaultArgs>(
);
}
await config.beforeBuild?.(app);
await config.beforeBuild?.(app, $registries);
await app.build(config.buildConfig);
}
@@ -131,7 +139,7 @@ export async function createRuntimeApp<Args = DefaultArgs>(
"sync",
);
await config.beforeBuild?.(app);
await config.beforeBuild?.(app, $registries);
await app.build(config.buildConfig);
}

View File

@@ -2,7 +2,7 @@ import type { DB, PrimaryFieldType } from "bknd";
import * as AuthPermissions from "auth/auth-permissions";
import type { AuthStrategy } from "auth/authenticate/strategies/Strategy";
import type { PasswordStrategy } from "auth/authenticate/strategies/PasswordStrategy";
import { $console, secureRandomString, transformObject } from "core/utils";
import { $console, secureRandomString, transformObject } from "bknd/utils";
import type { Entity, EntityManager } from "data/entities";
import { em, entity, enumm, type FieldSchema } from "data/prototype";
import { Module } from "modules/Module";

View File

@@ -1,6 +1,6 @@
import { AppAuth } from "auth/AppAuth";
import type { CreateUser, SafeUser, User, UserPool } from "auth/authenticate/Authenticator";
import { $console } from "core/utils";
import { $console } from "bknd/utils";
import { pick } from "lodash-es";
import {
InvalidConditionsException,

View File

@@ -1,11 +1,10 @@
import type { User } from "bknd";
import type { Authenticator } from "auth/authenticate/Authenticator";
import { InvalidCredentialsException } from "auth/errors";
import { hash, $console } from "core/utils";
import { hash, $console, s, parse, jsc } from "bknd/utils";
import { Hono } from "hono";
import { compare as bcryptCompare, genSalt as bcryptGenSalt, hash as bcryptHash } from "bcryptjs";
import { AuthStrategy } from "./Strategy";
import { s, parse, jsc } from "bknd/utils";
const schema = s
.object({

View File

@@ -1,5 +1,5 @@
import { Exception } from "core/errors";
import { $console, objectTransform } from "core/utils";
import { $console, objectTransform } from "bknd/utils";
import { Permission } from "core/security/Permission";
import type { Context } from "hono";
import type { ServerEnv } from "modules/Controller";

View File

@@ -1,7 +1,6 @@
import * as $p from "@clack/prompts";
import { overrideJson, overridePackageJson } from "cli/commands/create/npm";
import { typewriter, wait } from "cli/utils/cli";
import { uuid } from "core/utils";
import { overrideJson } from "cli/commands/create/npm";
import { typewriter } from "cli/utils/cli";
import c from "picocolors";
import type { Template, TemplateSetupCtx } from ".";
import { exec } from "cli/utils/sys";

View File

@@ -1,5 +1,5 @@
import path from "node:path";
import { $console } from "core/utils";
import { $console } from "bknd/utils";
import type { MiddlewareHandler } from "hono";
import open from "open";
import { fileExists, getRelativeDistPath } from "../../utils/sys";

View File

@@ -77,7 +77,7 @@ async function makeApp(config: MakeAppConfig) {
}
export async function makeConfigApp(_config: CliBkndConfig, platform?: Platform) {
const config = makeConfig(_config, process.env);
const config = await makeConfig(_config, process.env);
return makeApp({
...config,
server: { platform },

View File

@@ -9,9 +9,8 @@ import type { PasswordStrategy } from "auth/authenticate/strategies";
import { makeAppFromEnv } from "cli/commands/run";
import type { CliCommand } from "cli/types";
import { Argument } from "commander";
import { $console } from "core/utils";
import { $console, isBun } from "bknd/utils";
import c from "picocolors";
import { isBun } from "core/utils";
export const user: CliCommand = (program) => {
program

View File

@@ -1,4 +1,4 @@
import { $console } from "core/utils";
import { $console } from "bknd/utils";
import { execSync, exec as nodeExec } from "node:child_process";
import { readFile, writeFile as nodeWriteFile } from "node:fs/promises";
import path from "node:path";

View File

@@ -1,4 +1,4 @@
import { mergeObject, type RecursivePartial } from "core/utils";
import { mergeObject, type RecursivePartial } from "bknd/utils";
import type { IEmailDriver } from "./index";
export type MailchannelsEmailOptions = {

View File

@@ -1,6 +1,6 @@
import { type Event, type EventClass, InvalidEventReturn } from "./Event";
import { EventListener, type ListenerHandler, type ListenerMode } from "./EventListener";
import { $console } from "core/utils";
import { $console } from "bknd/utils";
export type RegisterListenerConfig =
| ListenerMode

View File

@@ -1,6 +1,6 @@
import type { TestRunner } from "core/test";
import { Connection, type FieldSpec } from "./Connection";
import { getPath } from "core/utils";
import { getPath } from "bknd/utils";
import * as proto from "data/prototype";
import { createApp } from "App";
import type { MaybePromise } from "core/types";

View File

@@ -1,4 +1,4 @@
import { objectTransform } from "core/utils";
import { objectTransform } from "bknd/utils";
import { MediaField, mediaFieldConfigSchema } from "../media/MediaField";
import { FieldClassMap } from "data/fields";
import { RelationClassMap, RelationFieldClassMap } from "data/relations";

View File

@@ -1,6 +1,6 @@
import type { Entity, EntityManager, TEntityType } from "data/entities";
import type { EntityRelation } from "data/relations";
import { autoFormatString } from "core/utils";
import { autoFormatString } from "bknd/utils";
import { usersFields } from "auth/auth-entities";
import { mediaFields } from "media/media-entities";

View File

@@ -1,5 +1,5 @@
import { isDebug } from "core/env";
import { pick } from "core/utils";
import { pick } from "bknd/utils";
import type { Connection } from "data/connection";
import type {
Compilable,

View File

@@ -1,4 +1,4 @@
import { $console } from "core/utils";
import { $console } from "bknd/utils";
import type { Entity, EntityData } from "../Entity";
import type { EntityManager } from "../EntityManager";
import { Result, type ResultJSON, type ResultOptions } from "../Result";

View File

@@ -1,5 +1,5 @@
import type { DB as DefaultDB, PrimaryFieldType } from "bknd";
import { $console } from "core/utils";
import { $console } from "bknd/utils";
import { type EmitsEvents, EventManager } from "core/events";
import { type SelectQueryBuilder, sql } from "kysely";
import { InvalidSearchParamsException } from "../../errors";

View File

@@ -2,7 +2,7 @@ import type { Entity, EntityData } from "../Entity";
import type { EntityManager } from "../EntityManager";
import { Result, type ResultJSON, type ResultOptions } from "../Result";
import type { Compilable, SelectQueryBuilder } from "kysely";
import { $console, ensureInt } from "core/utils";
import { $console, ensureInt } from "bknd/utils";
export type RepositoryResultOptions = ResultOptions & {
silent?: boolean;

View File

@@ -1,4 +1,4 @@
import { isObject } from "core/utils";
import { isObject } from "bknd/utils";
import type { KyselyJsonFrom } from "data/relations/EntityRelation";
import type { RepoQuery } from "data/server/query";

View File

@@ -1,8 +1,7 @@
import { omitKeys } from "core/utils";
import { omitKeys, s } from "bknd/utils";
import type { EntityManager } from "data/entities";
import { TransformPersistFailedException } from "../errors";
import { Field, type TActionContext, type TRenderContext, baseFieldConfigSchema } from "./Field";
import { s } from "bknd/utils";
export const booleanFieldConfigSchema = s
.strictObject({

View File

@@ -1,9 +1,7 @@
import { dayjs } from "core/utils";
import { dayjs, $console, s } from "bknd/utils";
import type { EntityManager } from "../entities";
import { Field, type TActionContext, type TRenderContext, baseFieldConfigSchema } from "./Field";
import { $console } from "core/utils";
import type { TFieldTSType } from "data/entities/EntityTypescript";
import { s } from "bknd/utils";
export const dateFieldConfigSchema = s
.strictObject({

View File

@@ -1,4 +1,4 @@
import { omitKeys } from "core/utils";
import { omitKeys } from "bknd/utils";
import type { EntityManager } from "data/entities";
import { TransformPersistFailedException } from "../errors";
import { baseFieldConfigSchema, Field, type TActionContext, type TRenderContext } from "./Field";

View File

@@ -1,4 +1,4 @@
import { omitKeys } from "core/utils";
import { omitKeys } from "bknd/utils";
import type { EntityManager } from "data/entities";
import { TransformPersistFailedException } from "../errors";
import { Field, type TActionContext, type TRenderContext, baseFieldConfigSchema } from "./Field";

View File

@@ -1,5 +1,5 @@
import { type Schema as JsonSchema, Validator } from "@cfworker/json-schema";
import { objectToJsLiteral } from "core/utils";
import { objectToJsLiteral } from "bknd/utils";
import type { EntityManager } from "data/entities";
import { TransformPersistFailedException } from "../errors";
import { Field, type TActionContext, type TRenderContext, baseFieldConfigSchema } from "./Field";

View File

@@ -2,8 +2,7 @@ import type { EntityManager } from "data/entities";
import { TransformPersistFailedException } from "../errors";
import { Field, type TActionContext, type TRenderContext, baseFieldConfigSchema } from "./Field";
import type { TFieldTSType } from "data/entities/EntityTypescript";
import { s } from "bknd/utils";
import { omitKeys } from "core/utils";
import { s, omitKeys } from "bknd/utils";
export const numberFieldConfigSchema = s
.strictObject({

View File

@@ -1,8 +1,7 @@
import type { EntityManager } from "data/entities";
import { omitKeys } from "core/utils";
import { omitKeys, s } from "bknd/utils";
import { TransformPersistFailedException } from "../errors";
import { Field, type TActionContext, baseFieldConfigSchema } from "./Field";
import { s } from "bknd/utils";
export const textFieldConfigSchema = s
.strictObject({

View File

@@ -1,4 +1,4 @@
import { transformObject } from "core/utils";
import { transformObject } from "bknd/utils";
import { Entity } from "data/entities";
import type { Field } from "data/fields";
import { FIELDS, RELATIONS, type TAppDataEntity, type TAppDataRelation } from "data/data-schema";

View File

@@ -1,6 +1,5 @@
import { transformObject } from "core/utils";
import { transformObject, s } from "bknd/utils";
import { TaskMap, TriggerMap } from "flows";
import { s } from "bknd/utils";
export const TASKS = {
...TaskMap,

View File

@@ -2,7 +2,7 @@ import { Event, EventManager, type ListenerHandler } from "core/events";
import type { EmitsEvents } from "core/events";
import type { Task, TaskResult } from "../tasks/Task";
import type { Flow } from "./Flow";
import { $console } from "core/utils";
import { $console } from "bknd/utils";
export type TaskLog = TaskResult & {
task: Task;

View File

@@ -1,4 +1,4 @@
import { $console, transformObject } from "core/utils";
import { $console, transformObject } from "bknd/utils";
import { type TaskMapType, TriggerMap } from "../index";
import type { Task } from "../tasks/Task";
import { Condition, TaskConnection } from "../tasks/TaskConnection";

View File

@@ -1,5 +1,5 @@
import type { Task } from "../../tasks/Task";
import { $console } from "core/utils";
import { $console } from "bknd/utils";
export class RuntimeExecutor {
async run(

View File

@@ -1,8 +1,7 @@
import type { EventManager } from "core/events";
import type { Flow } from "../Flow";
import { Trigger } from "./Trigger";
import { $console } from "core/utils";
import { s } from "bknd/utils";
import { $console, s } from "bknd/utils";
export class EventTrigger extends Trigger<typeof EventTrigger.schema> {
override type = "event";

View File

@@ -1,4 +1,4 @@
import { objectCleanEmpty, uuid } from "core/utils";
import { objectCleanEmpty, uuid } from "bknd/utils";
import { get } from "lodash-es";
import type { Task, TaskResult } from "./Task";

View File

@@ -1,6 +1,5 @@
import { Task } from "../Task";
import { $console } from "core/utils";
import { s } from "bknd/utils";
import { $console, s } from "bknd/utils";
export class LogTask extends Task<typeof LogTask.schema> {
type = "log";

View File

@@ -39,6 +39,7 @@ export { registries } from "modules/registries";
/**
* Core
*/
export type { MaybePromise } from "core/types";
export { Exception, BkndError } from "core/errors";
export { isDebug, env } from "core/env";
export { type PrimaryFieldType, config, type DB, type AppEntity } from "core/config";

View File

@@ -1,5 +1,5 @@
import type { AppEntity, FileUploadedEventData, StorageAdapter } from "bknd";
import { $console } from "core/utils";
import { $console } from "bknd/utils";
import type { Entity, EntityManager } from "data/entities";
import { Storage } from "media/storage/Storage";
import { Module } from "modules/Module";

View File

@@ -1,5 +1,5 @@
import { type EmitsEvents, EventManager } from "core/events";
import { $console, isFile, detectImageDimensions } from "core/utils";
import { $console, isFile, detectImageDimensions } from "bknd/utils";
import { isMimeType } from "media/storage/mime-types-tiny";
import * as StorageEvents from "./events";
import type { FileUploadedEventData } from "./events";

View File

@@ -1,7 +1,6 @@
import { hash, pickHeaders } from "core/utils";
import { hash, pickHeaders, s, parse } from "bknd/utils";
import type { FileBody, FileListObject, FileMeta } from "../../Storage";
import { StorageAdapter } from "../../StorageAdapter";
import { s, parse } from "bknd/utils";
export const cloudinaryAdapterConfig = s.object(
{

View File

@@ -1,4 +1,4 @@
import { transformObject } from "core/utils";
import { transformObject } from "bknd/utils";
import type { Kysely } from "kysely";
import { set } from "lodash-es";

View File

@@ -1,6 +1,6 @@
import { type NotificationData, notifications } from "@mantine/notifications";
import type { Api } from "Api";
import { ucFirst } from "core/utils";
import { ucFirst } from "bknd/utils";
import type { ModuleConfigs } from "modules";
import type { ResponseObject } from "modules/ModuleApi";
import type { ConfigUpdateResponse } from "modules/server/SystemController";

View File

@@ -1,9 +1,9 @@
import { autoFormatString, omitKeys } from "core/utils";
import { autoFormatString, omitKeys } from "bknd/utils";
import { type Draft, Draft2019, type JsonSchema } from "json-schema-library";
import type { JSONSchema } from "json-schema-to-ts";
import type { JSONSchemaType } from "json-schema-to-ts/lib/types/definitions/jsonSchema";
export { isEqual, getPath } from "core/utils/objects";
export { isEqual, getPath } from "bknd/utils";
export function isNotDefined(value: any) {
return value === null || value === undefined || value === "";