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:
dswbx
2025-08-01 15:55:59 +02:00
committed by GitHub
parent daaaae82b6
commit a298b65abf
430 changed files with 15041 additions and 12375 deletions

View File

@@ -1,62 +1,61 @@
import { get, has, omit, set } from "lodash-es";
import {
Default,
type Static,
type TObject,
getFullPathKeys,
mergeObjectWith,
parse,
stripMark,
} from "../utils";
import { type s, parse, stripMark, getFullPathKeys, mergeObjectWith, deepFreeze } from "bknd/utils";
export type SchemaObjectOptions<Schema extends TObject> = {
onUpdate?: (config: Static<Schema>) => void | Promise<void>;
export type SchemaObjectOptions<Schema extends s.Schema> = {
onUpdate?: (config: s.Static<Schema>) => void | Promise<void>;
onBeforeUpdate?: (
from: Static<Schema>,
to: Static<Schema>,
) => Static<Schema> | Promise<Static<Schema>>;
from: s.Static<Schema>,
to: s.Static<Schema>,
) => s.Static<Schema> | Promise<s.Static<Schema>>;
restrictPaths?: string[];
overwritePaths?: (RegExp | string)[];
forceParse?: boolean;
};
export class SchemaObject<Schema extends TObject> {
private readonly _default: Partial<Static<Schema>>;
private _value: Static<Schema>;
private _config: Static<Schema>;
type TSchema = s.ObjectSchema<any>;
export class SchemaObject<Schema extends TSchema = TSchema> {
private readonly _default: Partial<s.Static<Schema>>;
private _value: s.Static<Schema>;
private _config: s.Static<Schema>;
private _restriction_bypass: boolean = false;
constructor(
private _schema: Schema,
initial?: Partial<Static<Schema>>,
initial?: Partial<s.Static<Schema>>,
private options?: SchemaObjectOptions<Schema>,
) {
this._default = Default(_schema, {} as any) as any;
this._value = initial
? parse(_schema, structuredClone(initial as any), {
forceParse: this.isForceParse(),
skipMark: this.isForceParse(),
})
: this._default;
this._config = Object.freeze(this._value);
this._default = deepFreeze(_schema.template({}, { withOptional: true }) as any);
this._value = deepFreeze(
parse(_schema, structuredClone(initial ?? {}), {
withDefaults: true,
//withExtendedDefaults: true,
forceParse: this.isForceParse(),
skipMark: this.isForceParse(),
}),
);
this._config = deepFreeze(this._value);
}
protected isForceParse(): boolean {
return this.options?.forceParse ?? true;
}
default(): Static<Schema> {
default() {
return this._default;
}
private async onBeforeUpdate(from: Static<Schema>, to: Static<Schema>): Promise<Static<Schema>> {
private async onBeforeUpdate(
from: s.Static<Schema>,
to: s.Static<Schema>,
): Promise<s.Static<Schema>> {
if (this.options?.onBeforeUpdate) {
return this.options.onBeforeUpdate(from, to);
}
return to;
}
get(options?: { stripMark?: boolean }): Static<Schema> {
get(options?: { stripMark?: boolean }): s.Static<Schema> {
if (options?.stripMark) {
return stripMark(this._config);
}
@@ -68,8 +67,9 @@ export class SchemaObject<Schema extends TObject> {
return structuredClone(this._config);
}
async set(config: Static<Schema>, noEmit?: boolean): Promise<Static<Schema>> {
async set(config: s.Static<Schema>, noEmit?: boolean): Promise<s.Static<Schema>> {
const valid = parse(this._schema, structuredClone(config) as any, {
coerce: false,
forceParse: true,
skipMark: this.isForceParse(),
});
@@ -77,8 +77,8 @@ export class SchemaObject<Schema extends TObject> {
// regardless of "noEmit" this should always be triggered
const updatedConfig = await this.onBeforeUpdate(this._config, valid);
this._value = updatedConfig;
this._config = Object.freeze(updatedConfig);
this._value = deepFreeze(updatedConfig);
this._config = deepFreeze(updatedConfig);
if (noEmit !== true) {
await this.options?.onUpdate?.(this._config);
@@ -118,9 +118,9 @@ export class SchemaObject<Schema extends TObject> {
return;
}
async patch(path: string, value: any): Promise<[Partial<Static<Schema>>, Static<Schema>]> {
async patch(path: string, value: any): Promise<[Partial<s.Static<Schema>>, s.Static<Schema>]> {
const current = this.clone();
const partial = path.length > 0 ? (set({}, path, value) as Partial<Static<Schema>>) : value;
const partial = path.length > 0 ? (set({}, path, value) as Partial<s.Static<Schema>>) : value;
this.throwIfRestricted(partial);
@@ -168,9 +168,12 @@ export class SchemaObject<Schema extends TObject> {
return [partial, newConfig];
}
async overwrite(path: string, value: any): Promise<[Partial<Static<Schema>>, Static<Schema>]> {
async overwrite(
path: string,
value: any,
): Promise<[Partial<s.Static<Schema>>, s.Static<Schema>]> {
const current = this.clone();
const partial = path.length > 0 ? (set({}, path, value) as Partial<Static<Schema>>) : value;
const partial = path.length > 0 ? (set({}, path, value) as Partial<s.Static<Schema>>) : value;
this.throwIfRestricted(partial);
@@ -194,7 +197,7 @@ export class SchemaObject<Schema extends TObject> {
return has(this._config, path);
}
async remove(path: string): Promise<[Partial<Static<Schema>>, Static<Schema>]> {
async remove(path: string): Promise<[Partial<s.Static<Schema>>, s.Static<Schema>]> {
this.throwIfRestricted(path);
if (!this.has(path)) {
@@ -202,9 +205,9 @@ export class SchemaObject<Schema extends TObject> {
}
const current = this.clone();
const removed = get(current, path) as Partial<Static<Schema>>;
const removed = get(current, path) as Partial<s.Static<Schema>>;
const config = omit(current, path);
const newConfig = await this.set(config);
const newConfig = await this.set(config as any);
return [removed, newConfig];
}
}

View File

@@ -1,4 +1,4 @@
import type { PrimaryFieldType } from "core";
import type { PrimaryFieldType } from "core/config";
export type Primitive = PrimaryFieldType | string | number | boolean;
export function isPrimitive(value: any): value is Primitive {

View File

@@ -1,52 +0,0 @@
import { mergeObject } from "core/utils";
//export { jsc, type Options, type Hook } from "./validator";
import * as s from "jsonv-ts";
export { validator as jsc, type Options } from "jsonv-ts/hono";
export { describeRoute, schemaToSpec, openAPISpecs } from "jsonv-ts/hono";
export { s };
export class InvalidSchemaError extends Error {
constructor(
public schema: s.TAnySchema,
public value: unknown,
public errors: s.ErrorDetail[] = [],
) {
super(
`Invalid schema given for ${JSON.stringify(value, null, 2)}\n\n` +
`Error: ${JSON.stringify(errors[0], null, 2)}`,
);
}
}
export type ParseOptions = {
withDefaults?: boolean;
coerse?: boolean;
clone?: boolean;
};
export const cloneSchema = <S extends s.TSchema>(schema: S): S => {
const json = schema.toJSON();
return s.fromSchema(json) as S;
};
export function parse<S extends s.TAnySchema>(
_schema: S,
v: unknown,
opts: ParseOptions = {},
): s.StaticCoerced<S> {
const schema = (opts.clone ? cloneSchema(_schema as any) : _schema) as s.TSchema;
const value = opts.coerse !== false ? schema.coerce(v) : v;
const result = schema.validate(value, {
shortCircuit: true,
ignoreUnsupported: true,
});
if (!result.valid) throw new InvalidSchemaError(schema, v, result.errors);
if (opts.withDefaults) {
return mergeObject(schema.template({ withOptional: true }), value) as any;
}
return value as any;
}

View File

@@ -1,63 +0,0 @@
import type { Context, Env, Input, MiddlewareHandler, ValidationTargets } from "hono";
import { validator as honoValidator } from "hono/validator";
import type { Static, StaticCoerced, TAnySchema } from "jsonv-ts";
export type Options = {
coerce?: boolean;
includeSchema?: boolean;
};
type ValidationResult = {
valid: boolean;
errors: {
keywordLocation: string;
instanceLocation: string;
error: string;
data?: unknown;
}[];
};
export type Hook<T, E extends Env, P extends string> = (
result: { result: ValidationResult; data: T },
c: Context<E, P>,
) => Response | Promise<Response> | void;
export const validator = <
// @todo: somehow hono prevents the usage of TSchema
Schema extends TAnySchema,
Target extends keyof ValidationTargets,
E extends Env,
P extends string,
Opts extends Options = Options,
Out = Opts extends { coerce: false } ? Static<Schema> : StaticCoerced<Schema>,
I extends Input = {
in: { [K in Target]: Static<Schema> };
out: { [K in Target]: Out };
},
>(
target: Target,
schema: Schema,
options?: Opts,
hook?: Hook<Out, E, P>,
): MiddlewareHandler<E, P, I> => {
// @ts-expect-error not typed well
return honoValidator(target, async (_value, c) => {
const value = options?.coerce !== false ? schema.coerce(_value) : _value;
// @ts-ignore
const result = schema.validate(value);
if (!result.valid) {
return c.json({ ...result, schema }, 400);
}
if (hook) {
const hookResult = hook({ result, data: value as Out }, c);
if (hookResult) {
return hookResult;
}
}
return value as Out;
});
};
export const jsc = validator;