brick.ts

@brickkit/crud

CRUD actions for a resource, with access rules, filters, and hooks.

llms.txt

@brickkit/crud exports 17 names: 1 function, 5 interfaces, 11 types.

import { crud } from "@brickkit/crud";

Functions

FunctionDescription
crudA plugin that gives a resource its CRUD actions: list, get, create, update, delete, findOne, count, and exists, with validated input and output…

crud

function crud<
  const F extends Fields,
  const O extends Operations = {},
>(
  options: CrudOptions<F, O>,
): CrudPlugin<F, O>

A plugin that gives a resource its CRUD actions: list, get, create, update, delete, findOne, count, and exists, with validated input and output, filters and sorting, and access rules. Install it with resource.use(crud({ ... })). The actions are named <resource>.<operation> and routed under /api/<resource>.

It denies by default: access is required. A column is hidden from reads, writes, and filters until its fields entry allows it.

Parameters

NameTypeDescription
optionsCrudOptions<F, O>fields (per column: read, create, update, filter operators, and sort), access ("public", or { authorize, scope }), operations to switch some off, routes to move or disable routes, hooks around create, update, and delete, and defaultLimit and maxLimit for lists.

Returns CrudPlugin<F, O> — The plugin, for resource.use, which returns the resource with its actions attached so they can be called in-process.

Example

import { crud } from "@brickkit/crud";

export const page = pagesService
  .resource({ name: "page", table: pages, id: pages.id })
  .use(
    crud({
      access: "public",
      fields: {
        id: { read: true, filter: ["eq", "in"] },
        title: { read: true, create: true, update: true, sort: true },
      },
    }),
  );

Source: packages/crud/src/index.ts:225

Interfaces

ColumnFieldPolicy

interface ColumnFieldPolicy

Properties

NameTypeDescription
read?boolean
create?boolean
update?boolean
filter?readonly FilterOperator[]
sort?boolean
schema?TSchema
resolve?never
scrub?(args: { value: any; ctx: ActionContext; }) => unknown | Promise<unknown>

Source: packages/crud/src/types.ts:26

CrudOptions

interface CrudOptions<F extends Fields = Fields, O extends Operations = Operations>

Properties

NameTypeDescription
fieldsF
operations?O
routes?PluginRoutes
defaultLimit?number
maxLimit?number
access| "public" | { authorize?: (args: CrudAuthorizeArgs<F>) => boolean | Promise<boolean>; scope?: (args: { operation: Operation; ctx: ActionContext; }) => SQL | undefined | Promise<SQL | undefined>; }
hooks?{ beforeCreate?: (args: { data: Record<string, unknown>; ctx: ActionContext; error: ErrorBuilder<Record<string, never>>; }) => void | Promise<void>; afterCreate?: (args: { row: Record<string, unknown>; ctx: ActionContex…

Source: packages/crud/src/types.ts:65

CrudTypes

interface CrudTypes<F, O>

Properties

NameTypeDescription
readonly tableunknown
readonly contextunknown
readonly resourceunknown
readonly apithis["table"] extends Table ? CrudAPI<this["table"], this["context"], F, O, this["resource"] extends { config: { id: infer I extends Column } } ? GetColumnData<I, "raw"> : this["table"]["$inferSelect"][keyof this["table…

Source: packages/crud/src/types.ts:394

DerivedFieldPolicy

interface DerivedFieldPolicy

Properties

NameTypeDescription
readtrue
schemaTSchema
resolve(args: { rows: readonly Readonly<Record<string, unknown>>[]; ctx: ActionContext; }) => readonly unknown[] | Promise<readonly unknown[]>One value per authorized parent row, in the same order.
create?false
update?false
filter?readonly []
sort?false
scrub?ColumnFieldPolicy["scrub"]

Source: packages/crud/src/types.ts:39

Query

interface Query<T extends Table, F, S extends readonly ReadKeys<T, F>[] | undefined = undefined, I extends readonly IncludeKeys<F>[] | undefined = undefined>

Properties

NameTypeDescription
select?S
include?I
where?Where<T, F>
orderBy?readonly { field: Extract<Keys<F, "sort">, keyof Row<T>>; direction: "asc" | "desc"; }[]
limit?number
offset?number
includeTotal?boolean

Source: packages/crud/src/types.ts:179

Types

CrudAPI

type CrudAPI<T extends Table, C, F, O, ID = Row<T>[keyof Row<T>]> = [
  O,
] extends [false]
  ? {}
  : Pick<
      AllAPI<T, C, F, ID>,
      { [K in Operation]: O extends Record<K, false> ? never : K }[Operation]
    >;

Source: packages/crud/src/types.ts:386

CrudAuthorizeArgs

type CrudAuthorizeArgs<F extends Fields = Fields> = {
  [K in Operation]: {
    operation: K;
    input: CrudInputs<F>[K];
    ctx: ActionContext;
  };
}[Operation];

Narrow operation and input together in an authorize callback.

Source: packages/crud/src/types.ts:242

CrudInputs

type CrudInputs<F extends Fields = Fields> = {
  list: { [K in keyof AuthorizeQuery<F>]: AuthorizeQuery<F>[K] };
  findOne: { [K in keyof AuthorizeQuery<F>]: AuthorizeQuery<F>[K] };
  get: {
    id: unknown;
    select?: readonly Exclude<AuthorizeKeys<F, "read">, IncludeKeys<F>>[];
    include?: readonly IncludeKeys<F>[];
  };
  create: AuthorizeWrite<F, "create">;
  update: { id: unknown; data: AuthorizeWrite<F, "update"> };
  delete: { id: unknown };
  count: { where?: AuthorizeQuery<F>["where"] };
  exists: { where?: AuthorizeQuery<F>["where"] };
};

Validated authorization inputs, indexed by CRUD operation.

Properties

NameTypeDescription
list{ [K in keyof AuthorizeQuery<F>]: AuthorizeQuery<F>[K] }
findOne{ [K in keyof AuthorizeQuery<F>]: AuthorizeQuery<F>[K] }
get{ id: unknown; select?: readonly Exclude<AuthorizeKeys<F, "read">, IncludeKeys<F>>[]; include?: readonly IncludeKeys<F>[]; }
createAuthorizeWrite<F, "create">
update{ id: unknown; data: AuthorizeWrite<F, "update"> }
delete{ id: unknown }
count{ where?: AuthorizeQuery<F>["where"] }
exists{ where?: AuthorizeQuery<F>["where"] }

Source: packages/crud/src/types.ts:227

CrudPlugin

type CrudPlugin<F extends Fields, O extends Operations> = ResourcePlugin<
  any,
  any,
  object
> & { readonly types: CrudTypes<F, O> };

Source: packages/crud/src/types.ts:410

FieldPolicy

type FieldPolicy = ColumnFieldPolicy | DerivedFieldPolicy;

Source: packages/crud/src/types.ts:53

Fields

type Fields = Readonly<Record<string, FieldPolicy>>;

Source: packages/crud/src/types.ts:54

FilterOperator

type FilterOperator =
  | "eq"
  | "ne"
  | "in"
  | "notIn"
  | "gt"
  | "gte"
  | "lt"
  | "lte"
  | "between"
  | "contains"
  | "startsWith"
  | "endsWith"
  | "isNull"
  | "isNotNull";

Source: packages/crud/src/types.ts:11

Operation

type Operation =
  | "list"
  | "get"
  | "create"
  | "update"
  | "delete"
  | "findOne"
  | "count"
  | "exists";

Source: packages/crud/src/types.ts:55

Operations

type Operations = false | Partial<Record<Operation, boolean>>;

Source: packages/crud/src/types.ts:64

ReadRow

type ReadRow<T extends Table, F> = {
  [K in ReadKeys<T, F>]: FieldValue<T, F, K>;
};

Source: packages/crud/src/types.ts:140

Where

type Where<T extends Table, F> = FilterWhere<F, Row<T>>;

Source: packages/crud/src/types.ts:178