Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: adds session options #12450

Merged
merged 15 commits into from
Nov 17, 2024
1 change: 1 addition & 0 deletions packages/astro/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@
"tinyexec": "^0.3.1",
"tsconfck": "^3.1.4",
"unist-util-visit": "^5.0.0",
"unstorage": "^1.12.0",
"vfile": "^6.0.3",
"vite": "6.0.0-beta.6",
"vitefu": "^1.0.3",
Expand Down
14 changes: 10 additions & 4 deletions packages/astro/src/config/index.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
import type { UserConfig as ViteUserConfig, UserConfigFn as ViteUserConfigFn } from 'vite';
import { createRouteManifest } from '../core/routing/index.js';
import type { AstroInlineConfig, AstroUserConfig, Locales } from '../types/public/config.js';
import type {
AstroInlineConfig,
AstroUserConfig,
Locales,
SessionDriverName,
} from '../types/public/config.js';
import { createDevelopmentManifest } from '../vite-plugin-astro-server/plugin.js';

/**
* See the full Astro Configuration API Documentation
* https://astro.build/config
*/
export function defineConfig<const TLocales extends Locales = never>(
config: AstroUserConfig<TLocales>,
) {
export function defineConfig<
const TLocales extends Locales = never,
const TDriver extends SessionDriverName = never,
>(config: AstroUserConfig<TLocales, TDriver>) {
return config;
}

Expand Down
19 changes: 19 additions & 0 deletions packages/astro/src/core/config/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,25 @@ export const AstroConfigSchema = z.object({
.boolean()
.optional()
.default(ASTRO_CONFIG_DEFAULTS.experimental.responsiveImages),
session: z
.object({
driver: z.string(),
options: z.record(z.any()).optional(),
cookieName: z.string().optional(),
cookieOptions: z
.object({
domain: z.string().optional(),
path: z.string().optional(),
expires: z.string().optional(),
maxAge: z.number().optional(),
httpOnly: z.boolean().optional(),
sameSite: z.string().optional(),
secure: z.boolean().optional(),
encode: z.string().optional(),
})
.optional(),
})
.optional(),
})
.strict(
`Invalid or outdated experimental feature.\nCheck for incorrect spelling or outdated Astro version.\nSee https://docs.astro.build/en/reference/configuration-reference/#experimental-flags for a list of all current experiments.`,
Expand Down
82 changes: 80 additions & 2 deletions packages/astro/src/types/public/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,17 @@ import type {
RemarkRehype,
ShikiConfig,
} from '@astrojs/markdown-remark';
import type { BuiltinDriverName, BuiltinDriverOptions } from 'unstorage';
import type { UserConfig as OriginalViteUserConfig, SSROptions as ViteSSROptions } from 'vite';
import type { ImageFit, ImageLayout } from '../../assets/types.js';
import type { RemotePattern } from '../../assets/utils/remotePattern.js';
import type { AssetsPrefix } from '../../core/app/types.js';
import type { AstroConfigType } from '../../core/config/schema.js';
import type { REDIRECT_STATUS_CODES } from '../../core/constants.js';
import type { AstroCookieSetOptions } from '../../core/cookies/cookies.js';
import type { Logger, LoggerLevel } from '../../core/logger/core.js';
import type { EnvSchema } from '../../env/schema.js';
import type { AstroIntegration } from './integrations.js';

export type Locales = (string | { codes: string[]; path: string })[];

type NormalizeLocales<T extends Locales> = {
Expand Down Expand Up @@ -95,6 +96,35 @@ export type ServerConfig = {
open?: string | boolean;
};

export type SessionDriverName = BuiltinDriverName | 'custom';

interface CommonSessionConfig {
/**
* The name of the session cookie
* @default `astro-session`
*/
cookieName?: string;
/**
* Additional options to pass to the session cookie
*/
cookieOptions?: AstroCookieSetOptions;
}

interface BuiltinSessionConfig<TDriver extends keyof BuiltinDriverOptions>
extends CommonSessionConfig {
driver: TDriver;
options?: BuiltinDriverOptions[TDriver];
}

interface CustomSessionConfig extends CommonSessionConfig {
/** Entrypoint for a custom session driver */
driver: string;
options?: Record<string, unknown>;
}

export type SessionConfig<TDriver extends SessionDriverName> =
TDriver extends keyof BuiltinDriverOptions ? BuiltinSessionConfig<TDriver> : CustomSessionConfig;

export interface ViteUserConfig extends OriginalViteUserConfig {
ssr?: ViteSSROptions;
}
Expand All @@ -112,7 +142,10 @@ export interface ViteUserConfig extends OriginalViteUserConfig {
* Docs: https://docs.astro.build/reference/configuration-reference/
*
* Generics do not follow semver and may change at any time.
*/ export interface AstroUserConfig<TLocales extends Locales = never> {
*/ export interface AstroUserConfig<
TLocales extends Locales = never,
TSession extends SessionDriverName = never,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm glad the generic defineConfig is used already :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it works great!

> {
/**
* @docs
* @kind heading
Expand Down Expand Up @@ -1864,6 +1897,51 @@ export interface ViteUserConfig extends OriginalViteUserConfig {
*/

responsiveImages?: boolean;

/**
* @docs
* @name experimental.session
* @type {SessionConfig}
* @version 5.0.0
* @description
*
* Enables support for sessions in Astro. Sessions are used to store user data across requests, such as user authentication state.
*
* When enabled you can access the `Astro.session` object to read and write data that persists across requests. You can configure the session driver using the [`session` option](#session), or use the default provided by your adapter.
*
* ```astro title=src/components/CartButton.astro
* ---
* export const prerender = false; // Not needed in 'server' mode
* const cart = await Astro.session.get('cart');
* ---
*
* <a href="/checkout">🛒 {cart?.length ?? 0} items</a>
*
* ```
* The object configures session management for your Astro site by specifying a `driver` as well as any `options` for your data storage.
*
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Link to RFC to learn more, maybe?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I'll do that once I have the stage 3 PR up

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

* You can specify [any driver from Unstorage](https://unstorage.unjs.io/drivers) or provide a custom config which will override your adapter's default.
*
* ```js title="astro.config.mjs"
* {
* experimental: {
* session: {
* // Required: the name of the Unstorage driver
* driver: "redis",
* // The required options depend on the driver
* options: {
* url: process.env.REDIS_URL,
* }
* }
* },
* }
* ```
*
* For more details, see [the Sessions RFC](https://github.com/withastro/roadmap/blob/sessions/proposals/0054-sessions.md).
*
*/

session?: SessionConfig<TSession>;
};
}

Expand Down
Loading
Loading