Configuration Reference
Configuration Reference
Every module option, every resource registration field and every authorization key in one place. The guides explain when to use them; this page lists what exists.
Module options (autoApi in nuxt.config.ts)
export default defineNuxtConfig({
modules: ['@websideproject/nuxt-auto-api'],
autoApi: {
prefix: '/api',
plugins: '~/server/autoapi-plugins',
pagination: { defaultLimit: 20, maxLimit: 100 },
multiTenancy: { enabled: true, tenantIdField: 'organizationId' },
},
})
| Option | Default | Description |
|---|---|---|
prefix | '/api' | Route prefix for every generated route; the composables follow it |
plugins | — | Path to a server file exporting an array of plugins (recommended), or an inline array. Plugin System |
pagination.defaultLimit | 20 | Page size when ?limit is absent |
pagination.maxLimit | 100 | Largest ?limit; also caps ?include= and M2M pages. Pagination |
multiTenancy.enabled | false | Scope tenant tables to the caller's tenant; fail closed without one. Multi-Tenancy |
multiTenancy.tenantIdField | 'organizationId' | Tenant column (property key) on scoped tables |
multiTenancy.userTenantField | tenantIdField | Property of ctx.user holding the active tenant |
multiTenancy.scopedResources | '*' | '*' = every resource whose table has the column, or a list |
multiTenancy.excludedResources | [] | Never scoped (global tables that happen to have the column) |
authorization | — | Per-resource overrides of a module's auth config — strings/arrays only (serialized). Auth |
relations.maxDepth | 3 | Deepest ?include= nesting |
relations.maxIncludes | 20 | Relations per request |
relations.allowFieldSelection | true | ?include=author[id,name] |
relations.allowFiltering | true | Filters on to-many includes |
relations.allowPagination | true | limit / offset on to-many includes |
bulk.enabled | true | /:resource/bulk routes |
bulk.maxBatchSize | 100 | Items per bulk request |
bulk.transactional | true | All-or-nothing (not atomic on D1). Bulk Operations |
aggregations.enabled | true | /:resource/aggregate and ?aggregate= |
aggregations.allowGroupBy | true | groupBy |
aggregations.maxGroupByFields | 5 | Group-by columns per request |
hookConfig.errorHandling | 'log' for after-hooks | 'throw' surfaces after-hook errors. Before-hooks always throw |
hookConfig.timeout | 5000 | Milliseconds per hook |
hookConfig.parallel | false | Run a hook's handlers concurrently |
hiddenFields.global | [] | Columns never returned or queryable on any resource (e.g. passwordHash) |
hiddenFields.resources | {} | Same, per resource |
m2m | auto-detect | Junction detection and explicit relations. M2M |
debug | false | Log registration and plugin details at build time |
Not options: the database engine is the second argument of
initializeDatabase(db, engine) in a server plugin. database is accepted for older
configs but not read. hooks, exclude, include and multiTenancy.getTenantId / allowCrossTenantAccess /
requireTenant were removed and fail the build — see Upgrading.
Registering a resource
Resources are registered at build time, from a Nuxt module, through the autoApi:registerSchema hook:
// modules/blog/index.ts
import { createResolver, defineNuxtModule } from '@nuxt/kit'
import { createModuleImport } from '@websideproject/nuxt-auto-api'
export default defineNuxtModule({
meta: { name: 'blog' },
setup(_, nuxt) {
const { resolve } = createResolver(import.meta.url)
nuxt.hook('autoApi:registerSchema', (registry) => {
registry.register('posts', {
schema: createModuleImport(resolve('./schema'), 'posts'),
authorization: createModuleImport(resolve('./auth'), 'postsAuth'),
validation: createModuleImport(resolve('./validation'), 'postsValidation'),
hooks: createModuleImport(resolve('./hooks'), 'postsHooks'),
hiddenFields: ['internalNotes'],
protectedFields: ['authorId'],
})
})
},
})
| Field | Required | Description |
|---|---|---|
schema | ✅ | The Drizzle table, as createModuleImport(path, exportName) |
authorization | effectively ✅ | ResourceAuthConfig (below). Without it every request is refused and the build warns |
validation | — | { create?, update?, query? } Zod schemas; parts left out are generated from the table. Validation |
hooks | — | before* / after* lifecycle hooks. Lifecycle Hooks |
hiddenFields | — | Columns never returned and never usable in filter/sort/include |
protectedFields | — | Columns a request body can never set (silently dropped) — on top of the always-protected pk, tenant, soft-delete and audit columns |
metadata | — | Free-form, JSON-serializable data for tooling (the admin module reads it) |
schema, authorization, validation and hooks must be createModuleImport() references: the registry is
generated as code, so an inline function or Zod schema cannot be carried into it — passing one fails the build.
The resource name is the URL segment (/api/posts) and the key used everywhere else: in permissions.m2m, in
autoApi.authorization, in hiddenFields.resources, in the composables (useAutoApiList('posts')).
createModuleImport (auth.ts, hooks.ts, validation.ts and everything they import) are
not processed by Nitro's auto-imports: import what you use explicitly, read config from ctx.runtimeConfig
rather than useRuntimeConfig(), and avoid extensionless relative runtime imports — import from package subpaths
or use import type.Authorization (ResourceAuthConfig)
export const postsAuth: ResourceAuthConfig = {
permissions: {
read, create, update, delete, // PermissionValue — undeclared = denied
aggregate, // → read
restore, purge, viewDeleted, // → update / delete / restore
m2m: { requireUpdateOnRelated, requireUpdateToLink, relations: { [relation]: { check } } },
},
listFilter: (table, ctx) => SQL | undefined, // row visibility, every route
objectLevel: (row, ctx) => boolean, // per row; list rows failing it are dropped
fields: { [column]: { read?: PermissionValue, write?: PermissionValue } },
softDelete: { cascade: 'auto' | 'off', retentionDays: number, restore, purge, viewDeleted },
custom: { [endpointName]: { permissions: { read, create, update, delete } } },
}
PermissionValue = true · false · 'perm' · ['a', 'b'] · (ctx) => boolean | Promise<boolean> · an object
handled by a registered evaluator.
Recipes: Permissions Cookbook.
Generated routes
For a resource posts (prefix /api):
| Route | Operation → permission |
|---|---|
GET /api/posts | list → read |
GET /api/posts/:id | get → read |
POST /api/posts | create → create |
PATCH /api/posts/:id | update → update |
DELETE /api/posts/:id | delete → delete (?force=true → purge) |
POST /api/posts/:id/restore | → restore |
POST · PATCH · DELETE /api/posts/bulk | → create · update · delete per item |
GET /api/posts/aggregate | → aggregate |
GET /api/posts/:id/relations/:relation | → read on both |
POST /api/posts/:id/relations/:relation (sync), /add, DELETE …/remove, POST /api/posts/:id/relations/batch | → update here, read (or update) on the related resource |
GET /api/posts/permissions, GET /api/permissions | the caller's permissions |
GET /api/_m2m/junctions, /is-junction/:table, /detect/:resource | signed-in callers |
Package entry points
| Import | Contents |
|---|---|
@websideproject/nuxt-auto-api | the Nuxt module, createModuleImport, types (ResourceAuthConfig, HandlerContext, …) |
@websideproject/nuxt-auto-api/utils | server utils — also auto-imported in server code. Custom Endpoints |
@websideproject/nuxt-auto-api/plugins | built-in plugins, defineAutoApiPlugin, addContextExtender, addResourceHook, addGlobalHook, registerPermissionEvaluator |
@websideproject/nuxt-auto-api/database | initializeDatabase, getDatabaseAdapter, adapters |
@websideproject/nuxt-auto-api/composables | client composables and their types — also auto-imported. Frontend Composables |
@websideproject/nuxt-auto-api/schema/{sqlite,pg,mysql} | schema presets |
Plugin Catalog
This document lists all shipped plugins for @websideproject/nuxt-auto-api.
Handler Overrides
Sometimes a generated route is not enough — a resource needs an extra action (/users/:id/stats, /orders/:id/checkout) or a route with custom logic. Write it as a regular Nitro file with createEndpoint() bound to the resource: the auto-api pipeline (authentication, plugin middleware, the resource's permission gate, validation) runs before your handler.