Directus logo

Skill

rstore-nuxt-drizzle

expose Drizzle data in Nuxt applications

Covers Nuxt Database API Development Drizzle

Description

Use when exposing Drizzle-backed data in Nuxt, OR before writing a custom `server/api` route, Nitro `defineEventHandler`, H3 handler, or REST/CRUD endpoint that reads or writes a Drizzle table — prefer the module's generated endpoints, `allowTables`, `hooksForTable`, and `publishRstoreDrizzleRealtimeUpdate` over hand-rolled routes; also covers generating collections/API routes from schema, adding a new Drizzle table to the rstore API, fixing `Collection "<name>" is not allowed` errors, fetch/filter/paginate, create/update/delete, realtime, offline, and table-level access control; pair with `rstore-nuxt` for Nuxt integration and `rstore-vue` for collection/query/form behavior.

SKILL.md

Rstore Nuxt Drizzle

Generate rstore collections and API/runtime behavior from Drizzle schema metadata, then add realtime/offline and hook-based server controls as needed. Use this skill with the @rstore/nuxt skill for Nuxt module/runtime behavior and with the @rstore/vue skill for underlying collection/query/form semantics.

Documentation map

AreaDocumentation
Nuxt + Drizzle plugin overviewhttps://rstore.akryum.dev/plugins/nuxt-drizzle
Query and filter modelhttps://rstore.akryum.dev/guide/data/query
Relations behaviorhttps://rstore.akryum.dev/guide/schema/relations
Realtime subscriptionshttps://rstore.akryum.dev/guide/data/live
Offline behaviorhttps://rstore.akryum.dev/guide/data/offline
Plugin hooks and extension pointshttps://rstore.akryum.dev/guide/plugin/hooks
Related package skillsrstore-nuxt skill (@rstore/nuxt), rstore-vue skill (@rstore/vue)
Skill-local API references./references/index.md

Core concepts

PrimitivePurpose
rstoreDrizzle.drizzleConfigPathLocates Drizzle config file loaded by the module
drizzleConfig.schemaMust be a single importable schema file path
drizzleImportDefines server-side drizzle getter import used by generated handlers
#build/$rstore-drizzle-collectionsGenerated collections with inferred keys, meta, and relations
apiPathBase REST route for generated CRUD handlers
wsEnables websocket realtime handler and client plugin
offlineEnables offline sync plugins and sync config template values
rstoreDrizzleHooks / hooksForTable / allowTablesServer extension and access-control APIs

Quick start

export default defineNuxtConfig({
  modules: ['@rstore/nuxt-drizzle'],
  rstoreDrizzle: {
    drizzleImport: {
      name: 'useDrizzle',
      from: '~~/server/utils/drizzle',
    },
    apiPath: '/api/rstore',
  },
})

Also provide the server import the module expects by default:

// server/utils/drizzle.ts
export function useDrizzle() {
  // return your drizzle instance
}

Task workflow

  1. Confirm drizzle.config.ts exists and exports a config with string schema.
  2. Configure drizzleImport if not using ~~/server/utils/drizzle with useDrizzle.
  3. Let the module generate collections and handlers; avoid parallel manual CRUD layers.
  4. Query through rstore collection APIs using findOptions.where and supported drizzle params.
  5. Enable ws and/or offline only when required by product behavior.
  6. Add server-side restrictions/transforms via hook APIs (hooksForTable, allowTables, rstoreDrizzleHooks).
  7. When adding a new Drizzle table to a project that already calls allowTables, register the new table in the same allowTables([...]) list — once initialized the allow-list is permanent and unlisted tables throw Collection "<name>" is not allowed..
  8. For Nuxt module/runtime integration behavior, use the rstore-nuxt skill.
  9. For non-drizzle-specific store/query/form behavior, use the rstore-vue skill.

When you are tempted to write a custom endpoint

Before adding a server/api/*.ts handler, a defineEventHandler, or any custom REST route that touches a Drizzle table, decide which case applies:

  • Plain CRUD for an existing Drizzle table → stop. Use the generated endpoints under apiPath. Add logic via hooksForTable(table, { 'item.beforeCreate': ... }) or the matching *.before / *.after hook — don't fork into a parallel route.
  • Row-level access control, tenant scoping, soft-delete filters → use allowTables([...]) plus hooksForTable with *.before hooks calling transformQuery(({ where, extras }) => ...). A custom route would bypass both guards.
  • Bulk or direct Drizzle write the generated endpoints cannot express (multi-table transaction, raw SQL, migration-style script) → a custom route is fine, but call publishRstoreDrizzleRealtimeUpdate after the write so liveQuery subscribers stay in sync. See the Nuxt + Drizzle docs section on "Publishing realtime updates from direct Drizzle queries".
  • Non-CRUD RPC (trigger an external workflow, send an email, compute a derived value) → custom route is appropriate; it is outside rstore's scope.

Query and cache conventions

  • Prefer findOptions.where over the deprecated params.where.
  • Use findOptions.include for relation loading; relation include objects support where, orderBy, columns, limit, and nested include.
  • Use params.limit, offset, columns, orderBy, and keys to shape Drizzle-backed queries.
  • Use params.with only as a low-level Drizzle override; when both are provided, params.with takes precedence over findOptions.include.
  • Query params and request bodies are serialized with SuperJSON, so keep them serializable.
  • The runtime plugin parses createdAt and updatedAt string values into Date objects through collection defaults.
  • fetchRelations translates included relations into follow-up equality queries against the generated target collections.
  • Cache filtering for findFirst and findMany reuses the same where and orderBy semantics client-side.

Realtime and offline behavior

  • ws: true (or object form) enables websocket handler registration and client subscription plugin wiring.
  • Realtime subscriptions are keyed by collection, key, and where; exact filter shape impacts topic reuse.
  • On websocket reconnect, the runtime re-sends active subscriptions and triggers realtimeReconnectEventHook, which makes liveQuery refresh.
  • offline enables offline plugin generation and sync config wiring.
  • Offline sync expects stable keys and usable updatedAt comparison values.
  • offline.serializeDateValue exists for non-default date comparison serialization.

Server extension points

  • Use hooksForTable(table, hooks) to scope API hooks to a specific Drizzle table.
  • Use rstoreDrizzleHooks.hook(...) when the extension needs to work across multiple tables.
  • *.before hooks can call transformQuery(({ where, extras }) => ...) to add constraints before execution.
  • Use allowTables([...]) to deny access to unlisted generated collections.
  • Use the realtime.filter hook to reject websocket updates for a peer when row-level rules apply.

Guardrails

  1. If drizzle config is missing, module setup is skipped after warning.
  2. Non-string schema in drizzle config throws.
  3. Multi-field relations/references are not supported by current relation inference and throw.
  4. Renaming schema exports renames generated collection names.
  5. Composite keys serialize as value1::value2; mismatches here cause lookup/update issues.
  6. params.where is deprecated; use findOptions.where.
  7. allowTables flips the default from "all tables exposed" to "deny by default". After the first call, every new Drizzle table you add to the schema must also be added to allowTables — otherwise endpoints throw Collection "<name>" is not allowed. at runtime.
  8. Do not hand-write server/api/<table>/* CRUD routes for tables already exposed by the generated apiPath. Duplicate code paths drift, bypass allowTables / hooksForTable, and miss realtime publishing — extend behavior through hooks or use publishRstoreDrizzleRealtimeUpdate from a justified custom route.

References

TopicDescriptionReference
API indexFull map of Nuxt-Drizzle API/config referencesapi-index
rstoreDrizzle.drizzleConfigPathDrizzle config lookup pathapi-drizzle-config-path
rstoreDrizzle.drizzleImportServer drizzle getter import contractapi-drizzle-import
rstoreDrizzle.apiPathGenerated REST base pathapi-api-path
rstoreDrizzle.wsEnable websocket realtime integrationapi-ws
rstoreDrizzle.ws.apiPathOverride websocket endpoint pathapi-ws-api-path
rstoreDrizzle.offlineEnable offline sync integrationapi-offline
rstoreDrizzle.offline.serializeDateValueCustomize offline sync date serializationapi-offline-serialize-date-value
findOptions.includePrimary relation include optionapi-find-options-include
findOptions.wherePrimary drizzle filter optionapi-find-options-where
params.where (deprecated)Legacy filter locationapi-params-where
params.limitLimit rows in list queriesapi-params-limit
params.offsetOffset rows in list queriesapi-params-offset
params.withLow-level Drizzle relation overrideapi-params-with
params.columnsSelected column projectionapi-params-columns
params.orderBySort order format and behaviorapi-params-order-by
params.keysKey-constrained list fetchesapi-params-keys
filterWhereLocal cache condition evaluatorapi-filter-where
rstoreDrizzleHooksGlobal server/realtime hook busapi-rstore-drizzle-hooks
hooksForTableTable-scoped hook registration helperapi-hooks-for-table
allowTablesCollection allow-list access controlapi-allow-tables
publishRstoreDrizzleRealtimeUpdatePublish manual realtime updates for direct Drizzle writesapi-publish-rstore-drizzle-realtime-update
Base @rstore/nuxt skillNuxt module/runtime integration semanticsrstore-nuxt skill
Base @rstore/vue skillUnderlying collection/query/form semanticsrstore-vue skill

Further reading

© 2026 YourAI.tools. Every skill from an identity-verified publisher.

Independent catalog. Not affiliated with, endorsed by, or sponsored by Anthropic or any listed publisher. All trademarks belong to their respective owners.