diff --git a/astro.sidebar.ts b/astro.sidebar.ts index 41c2d2568ebc6..e2017c9447d35 100644 --- a/astro.sidebar.ts +++ b/astro.sidebar.ts @@ -137,6 +137,7 @@ export const sidebar = [ 'reference/content-loader-reference', 'reference/image-service-reference', 'reference/dev-toolbar-app-reference', + 'reference/session-driver-reference', 'reference/container-reference', 'reference/programmatic-reference', ], diff --git a/src/content/docs/en/guides/sessions.mdx b/src/content/docs/en/guides/sessions.mdx index 7f2d333af26a3..eb2c7f03c0737 100644 --- a/src/content/docs/en/guides/sessions.mdx +++ b/src/content/docs/en/guides/sessions.mdx @@ -28,13 +28,18 @@ const cart = await Astro.session?.get('cart'); Sessions require a storage driver to store the session data. The [Node](/en/guides/integrations-guide/node/#sessions), [Cloudflare](/en/guides/integrations-guide/cloudflare/#sessions), and [Netlify](/en/guides/integrations-guide/netlify/#sessions) adapters automatically configure a default driver for you, but other adapters currently require you to [specify a driver manually](/en/reference/configuration-reference/#sessiondriver). -```js title="astro.config.mjs" ins={4} - { - adapter: vercel(), - session: { - driver: "redis", - }, +```js title="astro.config.mjs" ins={7-9} ins=" sessionDrivers " +import { defineConfig, sessionDrivers } from 'astro/config' +import vercel from '@astrojs/vercel' + +export default defineConfig({ + adapter: vercel() + session: { + driver: sessionDrivers.redis({ + url: process.env.REDIS_URL + }), } +}) ``` diff --git a/src/content/docs/en/guides/upgrade-to/v6.mdx b/src/content/docs/en/guides/upgrade-to/v6.mdx index 2ce1a32ca1559..4318894f91161 100644 --- a/src/content/docs/en/guides/upgrade-to/v6.mdx +++ b/src/content/docs/en/guides/upgrade-to/v6.mdx @@ -304,6 +304,41 @@ console.log('astro:after-swap'); Learn more about all utilities available in the [View Transitions Router API Reference](/en/reference/modules/astro-transitions/). +### Deprecated: session driver string signature + + + +In Astro 5.x, any [unstorage provider](https://unstorage.unjs.io/drivers) name or a custom entrypoint could be provided to define a session driver, and options were also provided directly to the `session` configuration. However, we felt that this API was limited and inconsistent with other parts of the Astro config. + +Astro 6.0 deprecates the driver string signature and options in favor of a new object shape. + +#### What should I do? + +Update your session config to use the newly exported `sessionDrivers`: + +```js title="astro.config.mjs" del={1,6-9} ins={2,10-12} +import { defineConfig } from 'astro/config' +import { defineConfig, sessionDrivers } from 'astro/config' + +export default defineConfig({ + session: { + driver: 'redis', + options: { + url: process.env.REDIS_URL + }, + driver: sessionDrivers.redis({ + url: process.env.REDIS_URL + }), + cookie: { + secure: true + }, + ttl: 3600 + } +}) +``` + +Learn more about [available session drivers](/en/reference/session-driver-reference/#building-a-session-driver). + ## Removed The following features have now been entirely removed from the code base and can no longer be used. Some of these features may have continued to work in your project even after deprecation. Others may have silently had no effect. @@ -812,6 +847,8 @@ export const server = { ### Removed: schema function signature (Content Loader API) + + In Astro 5.x, a content loader could choose to define a schema as a function instead of defining a Zod schema object for validation. This is useful to dynamically generate the schema based on the configuration options or by introspecting an API. Astro 6.0 removes this signature and introduces a new `createSchema()` property as a replacement for those who still want to dynamically define a schema in their content loader. @@ -853,6 +890,34 @@ function myLoader() { Learn more about [`createSchema()`](/en/reference/content-loader-reference/#createschema) in the Content Loader API reference. +### Removed: session `test` driver + + + +In Astro 5.x, the internal session `test` driver was exported in the Astro config types, but it was not meant to be exposed for public use. + +Astro 6.0 removes the session `test` driver as it is no longer used internally to test `context.session`. + +#### What should I do? + +It is unlikely that you are using this internal API. If you do, you must remove any usage of the session `test` driver: + +```js title="astro.config.mjs" del={2,6-9} +import { defineConfig } from 'astro/config' +import { createMockStorage } from './utils' + +export default defineConfig({ + session: { + driver: 'test', + options: { + mockStorage: createMockStorage() + } + } +}) +``` + +Learn more about the [Session Driver API](/en/reference/session-driver-reference/). + ### Experimental Flags Experimental flags allow you to opt in to features while they are in early development. Astro may also use experimental flags to test breaking changes to default behavior. The following experimental flags have been removed in Astro 6.0 and are now stable, or the new default behavior. diff --git a/src/content/docs/en/reference/session-driver-reference.mdx b/src/content/docs/en/reference/session-driver-reference.mdx new file mode 100644 index 0000000000000..b3cddaf473443 --- /dev/null +++ b/src/content/docs/en/reference/session-driver-reference.mdx @@ -0,0 +1,191 @@ +--- +title: Astro Session Driver API +sidebar: + label: Session Driver API +i18nReady: true +tableOfContents: + minHeadingLevel: 2 + maxHeadingLevel: 4 +--- +import Since from '~/components/Since.astro'; + +Astro [sessions](/en/guides/sessions/) allow to share data between requests for on-demand rendered pages. They require an Astro Session Driver to store session data. + +## Built-in drivers + +Astro exports built-in session drivers from `astro/config`: + +```js +import { sessionDrivers } from 'astro/config' +``` + +Any [unstorage driver](https://unstorage.unjs.io/drivers) can be used, for example: + +```js title="astro.config.mjs" ins={5-7} ins=" sessionDrivers " +import { defineConfig, sessionDrivers } from 'astro/config' + +export default defineConfig({ + session: { + driver: sessionDrivers.redis({ + url: process.env.REDIS_URL + }), + } +}) +``` + +:::note +Some drivers may need extra packages to be installed. Some drivers may also require environment variables or credentials to be set. See the [Unstorage documentation](https://unstorage.unjs.io/drivers) for more information. +::: + +## Building a session driver + +A session driver is made of two parts: + +- The [driver config](#the-session-driver-config), which lets Astro know what implementation to use at runtime and what config to forward +- The [driver implementation](#the-session-driver-implementation), which handles the storage logic at runtime + +### The session driver config + +A `SessionDriverConfig` is an object containing a required runtime [`entrypoint`](#entrypoint) and an optional [`config`](#config). The preferred method for implementing it is to export a function that returns this object and takes the configuration as an optional parameter. + +The following example defines a memory driver config: + +```ts title="driver/config.ts" +import type { SessionDriverConfig } from 'astro' + +export interface Config { + max?: number; +} + +export function memoryDriver(config: Config = {}): SessionDriverConfig { + return { + entrypoint: new URL('./runtime.js', import.meta.url), + config, + } +} +``` + +It is then registered in the Astro config: + +```ts title="astro.config.ts" +import { defineConfig } from 'astro/config' +import { memoryDriver } from './driver/config' + +export default defineConfig({ + session: { + driver: memoryDriver({ + max: 500 + }) + } +}) +``` + +#### `entrypoint` + +

+ +**Type:** `string | URL` + +

+ +Defines the entrypoint for the [driver implementation](#the-session-driver-implementation). + +#### `config` + +

+ +**Type:** `Record | undefined` + +

+ +Defines the serializable config passed to [driver implementation](#the-session-driver-implementation) at runtime. + +### The session driver implementation + +A `SessionDriver` is an object responsible for [storing](#setitem), [retrieving](#getitem) and [deleting](#removeitem) data when [using sessions at runtime](/en/reference/api-reference/#session) (e.g. `context.session.set()`). You can implement it in your session driver module by exporting a default function that takes the [driver config](#config) as parameter. + +The following example implements a memory driver: + +```ts title="driver/runtime.ts" +import type { SessionDriver } from 'astro' +import type { Config } from './config' +import { LRUCache } from 'lru-cache' + +export default function(config: Config): SessionDriver { + const cache = new LRUCache({ max: config.max }) + return { + setItem: async (key, value) => { + cache.set(key, value) + }, + getItem: async (key) => { + return cache.get(key) + }, + removeItem: async (key) => { + cache.delete(key) + }, + } +} +``` + +#### `setItem()` + +

+ +**Type:** `(key: string, value: any) => Promise` + +

+ +Defines a function that sets session data by key. + +#### `getItem()` + +

+ +**Type:** `(key: string) => Promise` + +

+ +Defines a function that retrieves session data by key. + +#### `removeItem()` + +

+ +**Type:** `(key: string) => Promise` + +

+ +Defines a function that removes session data by key. + +## Unstorage compatibility + +Unstorage driver types are compatible with Astro's `SessionDriver` type. + +That means you can use an unstorage package export as an [entrypoint](#entrypoint). For example: + +```ts title="driver/config.ts" {5} +import type { SessionDriverConfig } from 'astro' + +export function configuredRedisDriver(): SessionDriverConfig { + return { + entrypoint: 'unstorage/drivers/redis', + config: { + tls: true + } + } +} +``` + +Alternatively, you can import and use an unstorage driver directly in the implementation. For example: + +```ts title="driver/runtime.ts" {2} +import type { SessionDriver } from 'astro' +import redisDriver from "unstorage/drivers/redis"; + +export default function(config): SessionDriver { + return redisDriver({ + ...config, + tls: true + }) +} +``` \ No newline at end of file