From dc5fd659e0debc383f0da7b30b4075e3a10f63b5 Mon Sep 17 00:00:00 2001 From: Vittorio Esposito Date: Wed, 22 Jul 2026 12:23:19 +0200 Subject: [PATCH 1/2] docs: document custom storage drivers Explain that driver must be a built-in name or module path, with an example. Closes #3847. --- docs/1.docs/8.storage.md | 42 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/docs/1.docs/8.storage.md b/docs/1.docs/8.storage.md index f1d3fc750b..3dd1f2cdb8 100644 --- a/docs/1.docs/8.storage.md +++ b/docs/1.docs/8.storage.md @@ -101,6 +101,48 @@ Then, you can use the redis storage using the `useStorage("redis")` function. You can find the driver list on [unstorage documentation](https://unstorage.unjs.io/) with their configuration. :: +### Custom drivers + +The `driver` field accepts a built-in driver name (for example `"redis"`) or a **path** to a custom driver module. You cannot pass a driver function or object directly in config — Nitro imports drivers as separate modules so your config stays separate from runtime code. + +Create a driver file that default-exports a driver created with `defineDriver`: + +```ts [drivers/upstash.ts] +import { defineDriver } from "unstorage"; +import { upstashDriver } from "unstorage/drivers/upstash"; + +export default defineDriver((opts = {}) => { + const driver = upstashDriver(opts); + return { + ...driver, + async setItem(key, value, opts) { + const ttl = opts?.ttl ? { ...opts, ttl: Math.ceil(opts.ttl / 1000) } : opts; + return driver.setItem!(key, value, ttl); + }, + }; +}); +``` + +Reference it by path in your Nitro config: + +```ts [nitro.config.ts] +import { defineConfig } from "nitro"; + +export default defineConfig({ + storage: { + upstash: { + driver: "./drivers/upstash.ts", + url: process.env.KV_REST_API_URL, + token: process.env.KV_REST_API_TOKEN, + }, + }, +}); +``` + +Use a path relative to your project root (or an absolute path). Nitro bundles the driver for the server runtime. + +:read-more{to="https://unstorage.unjs.io/guide/custom-driver" title="unstorage custom driver guide"} + ### Development storage You can use the `devStorage` option to override storage configuration during development and prerendering. From f240faf54e6d4e54ee6a8886201e1e85c9e99055 Mon Sep 17 00:00:00 2001 From: Vittorio Esposito Date: Thu, 23 Jul 2026 20:44:11 +0200 Subject: [PATCH 2/2] docs: show custom storage driver from interface, not wrap Address review feedback: from-scratch drivers implement the unstorage interface; wrapping is only for patching existing drivers. Co-authored-by: Cursor --- docs/1.docs/8.storage.md | 47 ++++++++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/docs/1.docs/8.storage.md b/docs/1.docs/8.storage.md index 3dd1f2cdb8..a21aae3ac2 100644 --- a/docs/1.docs/8.storage.md +++ b/docs/1.docs/8.storage.md @@ -105,35 +105,52 @@ You can find the driver list on [unstorage documentation](https://unstorage.unjs The `driver` field accepts a built-in driver name (for example `"redis"`) or a **path** to a custom driver module. You cannot pass a driver function or object directly in config — Nitro imports drivers as separate modules so your config stays separate from runtime code. -Create a driver file that default-exports a driver created with `defineDriver`: +Create a driver file that **default-exports** a driver factory from `defineDriver`. To build a driver from scratch, implement the [unstorage driver interface](https://unstorage.unjs.io/guide/custom-driver) (`hasItem`, `getItem`, `setItem`, and so on): -```ts [drivers/upstash.ts] +```ts [drivers/kv.ts] import { defineDriver } from "unstorage"; -import { upstashDriver } from "unstorage/drivers/upstash"; -export default defineDriver((opts = {}) => { - const driver = upstashDriver(opts); +export default defineDriver((opts: { prefix?: string } = {}) => { + const data = new Map(); + const prefix = opts.prefix || ""; + return { - ...driver, - async setItem(key, value, opts) { - const ttl = opts?.ttl ? { ...opts, ttl: Math.ceil(opts.ttl / 1000) } : opts; - return driver.setItem!(key, value, ttl); + name: "kv", + options: opts, + hasItem(key) { + return data.has(prefix + key); + }, + getItem(key) { + return data.get(prefix + key) ?? null; + }, + setItem(key, value) { + data.set(prefix + key, value); + }, + removeItem(key) { + data.delete(prefix + key); + }, + getKeys() { + return [...data.keys()].map((k) => + prefix ? k.slice(prefix.length) : k, + ); + }, + clear() { + data.clear(); }, }; }); ``` -Reference it by path in your Nitro config: +Reference it by path in your Nitro config (options besides `driver` are passed into the factory): ```ts [nitro.config.ts] import { defineConfig } from "nitro"; export default defineConfig({ storage: { - upstash: { - driver: "./drivers/upstash.ts", - url: process.env.KV_REST_API_URL, - token: process.env.KV_REST_API_TOKEN, + kv: { + driver: "./drivers/kv.ts", + prefix: "app:", }, }, }); @@ -141,6 +158,8 @@ export default defineConfig({ Use a path relative to your project root (or an absolute path). Nitro bundles the driver for the server runtime. +To **patch** an existing unstorage driver instead of writing one from scratch, wrap it inside `defineDriver`, spread the base driver, and override only the methods you need. + :read-more{to="https://unstorage.unjs.io/guide/custom-driver" title="unstorage custom driver guide"} ### Development storage