UNPKG

kolenkainc-honohub

Version:

The CMS for building apps and APIs with Hono

176 lines (175 loc) 6.45 kB
import type { AnyDrizzleDB } from "drizzle-graphql"; import type { Column, Table } from "drizzle-orm"; import type { Context, Env, Hono, Schema } from "hono"; import type { BlankSchema, Input } from "hono/types"; import type { JSONValue } from "hono/utils/types"; import type { Prettify, Promisify } from "./utils"; export type TableColumns<T extends Table> = keyof T["_"]["columns"]; /** Manage all aspects of a data collection */ export type CollectionConfig<T extends Table = Table> = { /** * The collection slug * @default tableName */ slug?: string; /** * The key to use for querying * @default pk Tables primary key */ queryKey?: Column<any, object, object>; schema: T; /** * Access control */ access?: <E extends Env = Env, P extends string = string, I extends Input = Input>(c: Context<E, P, I>) => Promisify<boolean>; /** * Default sort order */ defaultSort?: TableColumns<T> | `-${TableColumns<T> & string}`; /** * Fields to be searched via the full text search */ listSearchableFields?: TableColumns<T>[]; /** * Collection admin options */ admin?: Partial<CollectionAdminProps<T>>; /** * Pagination options * @default false */ pagination?: CollectionPagination | false; /** * Hooks to modify HonoHub functionality */ hooks?: Partial<CollectionHooks<T>>; plugins?: CollectionPlugin<T>[]; }; /** Sanitized collection configuration */ export type SanitizedCollection<T extends Table = Table> = Prettify<Required<Omit<CollectionConfig<T>, "defaultSort" | "admin">> & { defaultSort?: TableColumns<T> | `-${TableColumns<T> & string}`; admin: CollectionAdminProps<T> & { actions: CollectionAction<T>[]; }; }>; /** Collection pagination options */ export type CollectionPagination = { /** * Default limit for pagination * @default 10 * @minimum 1 * @maximum maxLimit */ defaultLimit: number; /** * Maximum limit for pagination * @minimum 1 */ maxLimit?: number; }; export type CollectionAdminProps<T extends Table = Table> = { /** * Label configuration */ label: string | { singular: string; plural: string; }; /** * Default columns to show in list view */ columns?: (TableColumns<T> | { name: TableColumns<T>; label: string; type?: string; })[]; fields?: (TableColumns<T> | { name: TableColumns<T>; label: string; type?: string; required?: boolean; description?: string; })[]; /** * Quick actions to perform on the collection from the UI * @default false */ actions?: boolean | CollectionAction<T>[]; }; export type CollectionAction<T extends Table = Table> = { name: string; label?: string; icon?: string; action: <Database extends AnyDrizzleDB<any> = AnyDrizzleDB<any>, E extends Env = Env, P extends string = string, I extends Input = Input>(props: { db: Database; items: unknown[]; context: Context<E, P, I>; config: SanitizedCollection<T>; }) => Promisify<void>; level?: boolean | { title: string; message: string; }; }; export type CollectionPlugin<T extends Table = Table> = { name: string; register?: (config: SanitizedCollection<T>) => SanitizedCollection<T> | undefined; bootstrap?: <E extends Env = Env, P extends Schema = BlankSchema, I extends string = string>(props: { app: Hono<E, P, I>; config: SanitizedCollection<T>; }) => Hono<E, P, I> | undefined; }; export type CollectionHooks<T extends Table = Table> = { beforeOperation: CollectionBeforeOperationHook[]; beforeValidate: CollectionBeforeValidateHook<T>[]; beforeChange: CollectionBeforeChangeHook<T>[]; afterChange: CollectionAfterChangeHook<T>[]; beforeRead: CollectionBeforeReadHook[]; afterRead: CollectionAfterReadHook<T>[]; beforeDelete: CollectionBeforeDeleteHook[]; afterDelete: CollectionAfterDeleteHook<T>[]; afterOperation: CollectionAfterOperationHook[]; }; export type CollectionBeforeOperationHook = <E extends Env = Env, P extends string = string, I extends Input = Input>(props: { context: Context<E, P, I>; }) => Promisify<void>; export type CollectionBeforeValidateHook<T extends Table = Table> = <E extends Env = Env, P extends string = string, I extends Input = Input>(props: { context: Context<E, P, I>; data: JSONValue; originalDoc?: T["$inferInsert"]; }) => Promisify<JSONValue>; export type CollectionBeforeChangeHook<T extends Table = Table> = <E extends Env = Env, P extends string = string, I extends Input = Input>(props: { context: Context<E, P, I>; data: T["$inferInsert"]; originalDoc?: T["$inferInsert"]; }) => Promisify<T["$inferInsert"]>; export type CollectionAfterChangeHook<T extends Table = Table> = <E extends Env = Env, P extends string = string, I extends Input = Input>(props: { context: Context<E, P, I>; doc: T["$inferInsert"]; previousDoc: T["$inferInsert"]; }) => Promisify<JSONValue | undefined>; export type CollectionBeforeReadHook = <E extends Env = Env, P extends string = string, I extends Input = Input>(props: { context: Context<E, P, I>; }) => Promisify<void>; export type CollectionAfterReadHook<T extends Table = Table> = <E extends Env = Env, P extends string = string, I extends Input = Input>(props: { context: Context<E, P, I>; doc: T["$inferInsert"] | { results: T["$inferInsert"][]; count: number; }; }) => Promisify<JSONValue | undefined>; export type CollectionBeforeDeleteHook = <E extends Env = Env, P extends string = string, I extends Input = Input>(props: { context: Context<E, P, I>; }) => Promisify<void>; /** * Runs immediately after the delete operation removes * records from the database. Returned values are discarded. */ export type CollectionAfterDeleteHook<T extends Table = Table> = <E extends Env = Env, P extends string = string, I extends Input = Input>(props: { context: Context<E, P, I>; doc: T["$inferInsert"]; }) => Promisify<JSONValue | undefined>; export type CollectionAfterOperationHook = <E extends Env = Env, P extends string = string, I extends Input = Input>(props: { context: Context<E, P, I>; result: unknown; }) => Promisify<JSONValue>;