@bezoar/nuxt
@bezoar/nuxt
Nuxt module for bezoar. The module takes a kit build and gives the server a typed database service.
Install
pnpm add @bezoar/nuxt
Setup
// nuxt.config.ts
export default defineNuxtConfig({
modules: ["@bezoar/nuxt"],
bezoar: { build: "@acme/database", migrate: true },
});
build names a kit build: a package whose main entry is the index.mjs
that bezoar build wrote, or a path to that directory. The module adds
two virtual modules to the server build: #bezoar/build, which
re-exports the modules of the kit build, and #bezoar/service, the
service over its contract and its SQL. It writes a declaration of the
service into the build directory. useBezoar() and its types come from
the virtual service, so they are typed by the build. The modules are virtual
so that Nitro bundles them in dev as in production; the server plugin of
the module imports both.
Connection
The module reads runtimeConfig.bezoar. An environment variable sets
each member.
| Member | Variable | Meaning |
|---|---|---|
url |
NUXT_BEZOAR_URL |
The connection string, for the pg driver |
dataDir |
NUXT_BEZOAR_DATA_DIR |
The data directory, for the pglite driver |
driver |
NUXT_BEZOAR_DRIVER |
pg or pglite. Defaults to pg |
migrate |
NUXT_BEZOAR_MIGRATE |
Apply the migrations when the server starts |
seed |
NUXT_BEZOAR_SEED |
Run the seeds when the server starts |
roles |
NUXT_BEZOAR_ROLES |
Apply the grants when the server starts |
role |
NUXT_BEZOAR_ROLE |
The role the service is scoped to |
driver, migrate, seed, roles, and role can also be set in the
module options. A value in the runtime config wins.
The pg driver connects to a Postgres server and needs url. The pglite
driver runs Postgres in the process, on dataDir, or in memory when it is
empty. A server with the pg driver and no url fails to start.
In a server route
export default defineEventHandler(async (event) => {
const db = useBezoar();
const { day } = await getValidatedQuery(
event,
db.schema.validators.queries["events.list"].arguments.parse,
);
return db.events.list({ day });
});
useBezoar() is auto-imported on the server. It returns the same service
on every call, typed by the contract of the build, so db.events.list
completes, and its arguments and rows check. The service carries the query
builder of @bezoar/core, db.build, a kysely
typed by the tables of the build, so db.build.selectFrom("events")
completes as well.
AppBezoar, AppBezoarContract, AppBezoarQuery,
AppBezoarArguments<Q>, AppBezoarRow<Q>, and AppBezoarDatabase are the
types, also auto-imported.
Roles
A build with roles carries, for each role, the queries it may run. role
scopes the service of the app to one of them.
// nuxt.config.ts
export default defineNuxtConfig({
modules: ["@bezoar/nuxt"],
bezoar: { build: "@bbf/database", role: "web" },
});
useBezoar() then offers the queries of the role and no other, and its
type narrows to them: in the app of web, db.admin.events.update is a
type error. The queries run as the role: the pg driver opens a pool of
its own that takes the role on each connection, and the pglite driver a
second executor over the one database. The login user of the connection
string must be a member of the role. In production that user can be a
member of the role alone, and the database holds the scope whatever the
service does. In development on pglite, the one superuser takes the role,
and a query that reaches past it fails on your machine as it would in
production.
useBezoarOwner() is the service over every query as the login user, which
the plugin runs the startup work on. Without a role, it is useBezoar()
itself. AppBezoarRole is the role of the module options, as a type, or
undefined.
A login user that is a member of its role alone cannot migrate or grant.
An app over one sets migrate, roles, and seed to false, and the owner
of the database, another app or a deploy step, applies them.
Startup and shutdown
A server plugin makes the service when the server starts. With roles, it
declares the roles of the build first, through roles.declare of
@bezoar/core, so a migration can name one. With migrate, it applies the
migrations of the build, through migrate, under an advisory lock, so
instances that start together apply each migration once. With roles, it
then applies the grants, through roles. With seed, it runs the seeds
last. The startup work runs on useBezoarOwner(). When the server stops,
the plugin closes the connections. closeBezoar() closes them by hand.
Runtime
The pg driver needs a Node runtime, which the Node server presets of Nuxt
and the functions of Vercel are.
Related
bezoar: the runtime.@bezoar/kit: builds the contract the module adopts.
Version History
| Version | Released | Vue | License |
|---|---|---|---|
| 0.0.5 | ^3.0 | MIT | |
| 0.0.4 | ^3.0 | MIT | |
| 0.0.3 | ^3.0 | MIT | |
| 0.0.2 | ^3.0 | MIT | |
| 0.0.0 | MIT |
Pre-releases (1)
| Version | Released | License |
|---|---|---|
| 0.0.0-stage |