mirror of
https://github.com/bknd-io/bknd/
synced 2026-08-03 00:26:01 +00:00
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
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { datetimeStringLocal } from "core/utils";
|
||||
import { datetimeStringLocal } from "./dates";
|
||||
import colors from "picocolors";
|
||||
import { env } from "core";
|
||||
import { env } from "core/env";
|
||||
|
||||
function hasColors() {
|
||||
try {
|
||||
|
||||
@@ -13,3 +13,18 @@ export * from "./uuid";
|
||||
export * from "./test";
|
||||
export * from "./runtime";
|
||||
export * from "./numbers";
|
||||
export {
|
||||
s,
|
||||
stripMark,
|
||||
mark,
|
||||
stringIdentifier,
|
||||
SecretSchema,
|
||||
secret,
|
||||
parse,
|
||||
jsc,
|
||||
describeRoute,
|
||||
schemaToSpec,
|
||||
openAPISpecs,
|
||||
type ParseOptions,
|
||||
InvalidSchemaError,
|
||||
} from "./schema";
|
||||
|
||||
@@ -94,16 +94,14 @@ export function transformObject<T extends Record<string, any>, U>(
|
||||
object: T,
|
||||
transform: (value: T[keyof T], key: keyof T) => U | undefined,
|
||||
): { [K in keyof T]: U } {
|
||||
return Object.entries(object).reduce(
|
||||
(acc, [key, value]) => {
|
||||
const t = transform(value, key as keyof T);
|
||||
if (typeof t !== "undefined") {
|
||||
acc[key as keyof T] = t;
|
||||
}
|
||||
return acc;
|
||||
},
|
||||
{} as { [K in keyof T]: U },
|
||||
);
|
||||
const result = {} as { [K in keyof T]: U };
|
||||
for (const [key, value] of Object.entries(object) as [keyof T, T[keyof T]][]) {
|
||||
const t = transform(value, key);
|
||||
if (typeof t !== "undefined") {
|
||||
result[key] = t;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
export const objectTransform = transformObject;
|
||||
|
||||
@@ -419,3 +417,21 @@ export function pick<T extends object, K extends keyof T>(obj: T, keys: K[]): Pi
|
||||
{} as Pick<T, K>,
|
||||
);
|
||||
}
|
||||
|
||||
export function deepFreeze<T extends object>(object: T): T {
|
||||
if (Object.isFrozen(object)) return object;
|
||||
|
||||
// Retrieve the property names defined on object
|
||||
const propNames = Reflect.ownKeys(object);
|
||||
|
||||
// Freeze properties before freezing self
|
||||
for (const name of propNames) {
|
||||
const value = object[name];
|
||||
|
||||
if ((value && typeof value === "object") || typeof value === "function") {
|
||||
deepFreeze(value);
|
||||
}
|
||||
}
|
||||
|
||||
return Object.freeze(object);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
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 { secret, SecretSchema } from "./secret";
|
||||
|
||||
export { s };
|
||||
|
||||
export const stripMark = <O extends object>(o: O): O => o;
|
||||
export const mark = <O extends object>(o: O): O => o;
|
||||
|
||||
export const stringIdentifier = s.string({
|
||||
pattern: "^[a-zA-Z_][a-zA-Z0-9_]*$",
|
||||
minLength: 2,
|
||||
maxLength: 150,
|
||||
});
|
||||
|
||||
export class InvalidSchemaError extends Error {
|
||||
constructor(
|
||||
public schema: s.Schema,
|
||||
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)}`,
|
||||
);
|
||||
}
|
||||
|
||||
first() {
|
||||
return this.errors[0]!;
|
||||
}
|
||||
|
||||
firstToString() {
|
||||
const first = this.first();
|
||||
return `${first.error} at ${first.instanceLocation}`;
|
||||
}
|
||||
}
|
||||
|
||||
export type ParseOptions = {
|
||||
withDefaults?: boolean;
|
||||
withExtendedDefaults?: boolean;
|
||||
coerce?: boolean;
|
||||
coerceDropUnknown?: boolean;
|
||||
clone?: boolean;
|
||||
skipMark?: boolean; // @todo: do something with this
|
||||
forceParse?: boolean; // @todo: do something with this
|
||||
onError?: (errors: s.ErrorDetail[]) => void;
|
||||
};
|
||||
|
||||
export const cloneSchema = <S extends s.Schema>(schema: S): S => {
|
||||
const json = schema.toJSON();
|
||||
return s.fromSchema(json) as S;
|
||||
};
|
||||
|
||||
export function parse<S extends s.Schema, Options extends ParseOptions = ParseOptions>(
|
||||
_schema: S,
|
||||
v: unknown,
|
||||
opts?: Options,
|
||||
): Options extends { coerce: true } ? s.StaticCoerced<S> : s.Static<S> {
|
||||
const schema = (opts?.clone ? cloneSchema(_schema as any) : _schema) as s.Schema;
|
||||
let value =
|
||||
opts?.coerce !== false
|
||||
? schema.coerce(v, { dropUnknown: opts?.coerceDropUnknown ?? false })
|
||||
: v;
|
||||
if (opts?.withDefaults !== false) {
|
||||
value = schema.template(value, {
|
||||
withOptional: true,
|
||||
withExtendedOptional: opts?.withExtendedDefaults ?? false,
|
||||
});
|
||||
}
|
||||
|
||||
const result = _schema.validate(value, {
|
||||
shortCircuit: true,
|
||||
ignoreUnsupported: true,
|
||||
});
|
||||
if (!result.valid) {
|
||||
if (opts?.onError) {
|
||||
opts.onError(result.errors);
|
||||
} else {
|
||||
throw new InvalidSchemaError(schema, v, result.errors);
|
||||
}
|
||||
}
|
||||
|
||||
return value as any;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import { StringSchema, type IStringOptions } from "jsonv-ts";
|
||||
|
||||
export class SecretSchema<O extends IStringOptions> extends StringSchema<O> {}
|
||||
|
||||
export const secret = <O extends IStringOptions>(o?: O): SecretSchema<O> & O =>
|
||||
new SecretSchema(o) as any;
|
||||
Reference in New Issue
Block a user