feat: scaffold Astro + Tailwind project
This commit is contained in:
27
node_modules/astro/dist/core/session/config.d.ts
generated
vendored
Normal file
27
node_modules/astro/dist/core/session/config.d.ts
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
import * as z from 'zod/v4';
|
||||
export declare const SessionDriverConfigSchema: z.ZodObject<{
|
||||
config: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
|
||||
entrypoint: z.ZodUnion<readonly [z.ZodString, z.ZodCustom<URL, URL>]>;
|
||||
}, z.core.$strip>;
|
||||
export declare const SessionSchema: z.ZodObject<{
|
||||
driver: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
||||
config: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
|
||||
entrypoint: z.ZodUnion<readonly [z.ZodString, z.ZodCustom<URL, URL>]>;
|
||||
}, z.core.$strip>]>>;
|
||||
options: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
|
||||
cookie: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
|
||||
name: z.ZodOptional<z.ZodString>;
|
||||
domain: z.ZodOptional<z.ZodString>;
|
||||
path: z.ZodOptional<z.ZodString>;
|
||||
maxAge: z.ZodOptional<z.ZodNumber>;
|
||||
sameSite: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
|
||||
strict: "strict";
|
||||
lax: "lax";
|
||||
none: "none";
|
||||
}>, z.ZodBoolean]>>;
|
||||
secure: z.ZodOptional<z.ZodBoolean>;
|
||||
}, z.core.$strip>, z.ZodPipe<z.ZodString, z.ZodTransform<{
|
||||
name: string;
|
||||
}, string>>]>>;
|
||||
ttl: z.ZodOptional<z.ZodNumber>;
|
||||
}, z.core.$strip>;
|
||||
32
node_modules/astro/dist/core/session/config.js
generated
vendored
Normal file
32
node_modules/astro/dist/core/session/config.js
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
import * as z from "zod/v4";
|
||||
const SessionDriverConfigSchema = z.object({
|
||||
config: z.record(z.string(), z.any()).optional(),
|
||||
entrypoint: z.union([z.string(), z.instanceof(URL)])
|
||||
});
|
||||
const SessionSchema = z.object({
|
||||
driver: z.union([
|
||||
z.string().superRefine(() => {
|
||||
console.warn(
|
||||
`Using deprecated \`session.driver\` string signature. Learn how to migrate: https://docs.astro.build/en/guides/upgrade-to/v6/#deprecated-session-driver-string-signature`
|
||||
);
|
||||
}),
|
||||
SessionDriverConfigSchema
|
||||
]).optional(),
|
||||
options: z.record(z.string(), z.any()).optional(),
|
||||
cookie: z.union([
|
||||
z.object({
|
||||
name: z.string().optional(),
|
||||
domain: z.string().optional(),
|
||||
path: z.string().optional(),
|
||||
maxAge: z.number().optional(),
|
||||
sameSite: z.union([z.enum(["strict", "lax", "none"]), z.boolean()]).optional(),
|
||||
secure: z.boolean().optional()
|
||||
}),
|
||||
z.string().transform((name) => ({ name }))
|
||||
]).optional(),
|
||||
ttl: z.number().optional()
|
||||
});
|
||||
export {
|
||||
SessionDriverConfigSchema,
|
||||
SessionSchema
|
||||
};
|
||||
34
node_modules/astro/dist/core/session/drivers.d.ts
generated
vendored
Normal file
34
node_modules/astro/dist/core/session/drivers.d.ts
generated
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
import type { SessionDriverConfig } from './types.js';
|
||||
export declare const sessionDrivers: {
|
||||
http: (config?: import("unstorage/drivers/http").HTTPOptions | undefined) => SessionDriverConfig;
|
||||
fs: (config?: import("unstorage/drivers/fs").FSStorageOptions | undefined) => SessionDriverConfig;
|
||||
azureAppConfiguration: (config?: import("unstorage/drivers/azure-app-configuration").AzureAppConfigurationOptions | undefined) => SessionDriverConfig;
|
||||
azureCosmos: (config?: import("unstorage/drivers/azure-cosmos").AzureCosmosOptions | undefined) => SessionDriverConfig;
|
||||
azureKeyVault: (config?: import("unstorage/drivers/azure-key-vault").AzureKeyVaultOptions | undefined) => SessionDriverConfig;
|
||||
azureStorageBlob: (config?: import("unstorage/drivers/azure-storage-blob").AzureStorageBlobOptions | undefined) => SessionDriverConfig;
|
||||
azureStorageTable: (config?: import("unstorage/drivers/azure-storage-table").AzureStorageTableOptions | undefined) => SessionDriverConfig;
|
||||
capacitorPreferences: (config?: import("unstorage/drivers/capacitor-preferences").CapacitorPreferencesOptions | undefined) => SessionDriverConfig;
|
||||
cloudflareKVBinding: (config?: import("unstorage/drivers/cloudflare-kv-binding").KVOptions | undefined) => SessionDriverConfig;
|
||||
cloudflareKVHttp: (config?: import("unstorage/drivers/cloudflare-kv-http").KVHTTPOptions | undefined) => SessionDriverConfig;
|
||||
cloudflareR2Binding: (config?: import("unstorage/drivers/cloudflare-r2-binding").CloudflareR2Options | undefined) => SessionDriverConfig;
|
||||
db0: (config?: import("unstorage/drivers/db0").DB0DriverOptions | undefined) => SessionDriverConfig;
|
||||
denoKVNode: (config?: import("unstorage/drivers/deno-kv-node").DenoKvNodeOptions | undefined) => SessionDriverConfig;
|
||||
denoKV: (config?: import("unstorage/drivers/deno-kv").DenoKvOptions | undefined) => SessionDriverConfig;
|
||||
fsLite: (config?: import("unstorage/drivers/fs-lite").FSStorageOptions | undefined) => SessionDriverConfig;
|
||||
github: (config?: import("unstorage/drivers/github").GithubOptions | undefined) => SessionDriverConfig;
|
||||
indexedb: (config?: import("unstorage/drivers/indexedb").IDBKeyvalOptions | undefined) => SessionDriverConfig;
|
||||
localstorage: (config?: import("unstorage/drivers/localstorage").LocalStorageOptions | undefined) => SessionDriverConfig;
|
||||
lruCache: (config?: import("unstorage/drivers/lru-cache").LRUDriverOptions | undefined) => SessionDriverConfig;
|
||||
mongodb: (config?: import("unstorage/drivers/mongodb").MongoDbOptions | undefined) => SessionDriverConfig;
|
||||
netlifyBlobs: (config?: import("unstorage/drivers/netlify-blobs").NetlifyStoreOptions | undefined) => SessionDriverConfig;
|
||||
overlay: (config?: import("unstorage/drivers/overlay").OverlayStorageOptions | undefined) => SessionDriverConfig;
|
||||
planetscale: (config?: import("unstorage/drivers/planetscale").PlanetscaleDriverOptions | undefined) => SessionDriverConfig;
|
||||
redis: (config?: import("unstorage/drivers/redis").RedisOptions | undefined) => SessionDriverConfig;
|
||||
s3: (config?: import("unstorage/drivers/s3").S3DriverOptions | undefined) => SessionDriverConfig;
|
||||
sessionStorage: (config?: import("unstorage/drivers/session-storage").SessionStorageOptions | undefined) => SessionDriverConfig;
|
||||
uploadthing: (config?: import("unstorage/drivers/uploadthing").UploadThingOptions | undefined) => SessionDriverConfig;
|
||||
upstash: (config?: import("unstorage/drivers/upstash").UpstashOptions | undefined) => SessionDriverConfig;
|
||||
vercelBlob: (config?: import("unstorage/drivers/vercel-blob").VercelBlobOptions | undefined) => SessionDriverConfig;
|
||||
vercelKV: (config?: import("unstorage/drivers/vercel-kv").VercelKVOptions | undefined) => SessionDriverConfig;
|
||||
vercelRuntimeCache: (config?: import("unstorage/drivers/vercel-runtime-cache").VercelCacheOptions | undefined) => SessionDriverConfig;
|
||||
};
|
||||
20
node_modules/astro/dist/core/session/drivers.js
generated
vendored
Normal file
20
node_modules/astro/dist/core/session/drivers.js
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
import { builtinDrivers } from "unstorage";
|
||||
const unstorageDrivers = Object.fromEntries(
|
||||
Object.entries(builtinDrivers).filter(([name]) => !name.includes("-")).map(([name, entrypoint]) => [
|
||||
name,
|
||||
name === "fs" ? (config) => ({
|
||||
entrypoint: builtinDrivers.fsLite,
|
||||
config: {
|
||||
base: ".astro/session",
|
||||
...config
|
||||
}
|
||||
}) : (config) => ({
|
||||
entrypoint,
|
||||
config
|
||||
})
|
||||
])
|
||||
);
|
||||
const sessionDrivers = unstorageDrivers;
|
||||
export {
|
||||
sessionDrivers
|
||||
};
|
||||
11
node_modules/astro/dist/core/session/handler.d.ts
generated
vendored
Normal file
11
node_modules/astro/dist/core/session/handler.d.ts
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
import type { FetchState } from '../fetch/fetch-state.js';
|
||||
/**
|
||||
* Registers a session provider on the given `FetchState`. When
|
||||
* `state.resolve('session')` is first called, the `AstroSession` is
|
||||
* created lazily. When `state.finalizeAll()` runs, any mutations are
|
||||
* persisted.
|
||||
*
|
||||
* No-op (returns synchronously) if sessions are not configured on the
|
||||
* pipeline, avoiding promise allocation on the hot path.
|
||||
*/
|
||||
export declare function provideSession(state: FetchState): Promise<void> | void;
|
||||
33
node_modules/astro/dist/core/session/handler.js
generated
vendored
Normal file
33
node_modules/astro/dist/core/session/handler.js
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
import { PipelineFeatures } from "../base-pipeline.js";
|
||||
import { AstroSession, PERSIST_SYMBOL } from "./runtime.js";
|
||||
const SESSION_KEY = "session";
|
||||
function provideSession(state) {
|
||||
state.pipeline.usedFeatures |= PipelineFeatures.sessions;
|
||||
const pipeline = state.pipeline;
|
||||
const config = pipeline.manifest.sessionConfig;
|
||||
if (!config) return;
|
||||
return provideSessionAsync(state, config);
|
||||
}
|
||||
async function provideSessionAsync(state, config) {
|
||||
const pipeline = state.pipeline;
|
||||
const driverFactory = await pipeline.getSessionDriver();
|
||||
if (!driverFactory) return;
|
||||
state.provide(SESSION_KEY, {
|
||||
create() {
|
||||
const cookies = state.cookies;
|
||||
return new AstroSession({
|
||||
cookies,
|
||||
config,
|
||||
runtimeMode: pipeline.runtimeMode,
|
||||
driverFactory,
|
||||
mockStorage: null
|
||||
});
|
||||
},
|
||||
finalize(session) {
|
||||
return session[PERSIST_SYMBOL]();
|
||||
}
|
||||
});
|
||||
}
|
||||
export {
|
||||
provideSession
|
||||
};
|
||||
64
node_modules/astro/dist/core/session/runtime.d.ts
generated
vendored
Normal file
64
node_modules/astro/dist/core/session/runtime.d.ts
generated
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
import type { RuntimeMode } from '../../types/public/config.js';
|
||||
import type { AstroCookies } from '../cookies/cookies.js';
|
||||
import type { SessionDriverFactory } from './types.js';
|
||||
import type { SSRManifestSession } from '../app/types.js';
|
||||
import { type Storage } from 'unstorage';
|
||||
export declare const PERSIST_SYMBOL: unique symbol;
|
||||
export declare class AstroSession {
|
||||
#private;
|
||||
constructor({ cookies, config, runtimeMode, driverFactory, mockStorage, }: {
|
||||
cookies: AstroCookies;
|
||||
config: SSRManifestSession | undefined;
|
||||
runtimeMode: RuntimeMode;
|
||||
driverFactory: SessionDriverFactory | null;
|
||||
mockStorage: Storage | null;
|
||||
});
|
||||
/**
|
||||
* Gets a session value. Returns `undefined` if the session or value does not exist.
|
||||
*/
|
||||
get<T = void, K extends string = keyof App.SessionData | (string & {})>(key: K): Promise<(T extends void ? (K extends keyof App.SessionData ? App.SessionData[K] : any) : T) | undefined>;
|
||||
/**
|
||||
* Checks if a session value exists.
|
||||
*/
|
||||
has(key: string): Promise<boolean>;
|
||||
/**
|
||||
* Gets all session values.
|
||||
*/
|
||||
keys(): Promise<MapIterator<string>>;
|
||||
/**
|
||||
* Gets all session values.
|
||||
*/
|
||||
values(): Promise<any[]>;
|
||||
/**
|
||||
* Gets all session entries.
|
||||
*/
|
||||
entries(): Promise<any[][]>;
|
||||
/**
|
||||
* Deletes a session value.
|
||||
*/
|
||||
delete(key: string): void;
|
||||
/**
|
||||
* Sets a session value. The session is created if it does not exist.
|
||||
*/
|
||||
set<T = void, K extends string = keyof App.SessionData | (string & {})>(key: K, value: T extends void ? K extends keyof App.SessionData ? App.SessionData[K] : any : NoInfer<T>, { ttl }?: {
|
||||
ttl?: number;
|
||||
}): void;
|
||||
/**
|
||||
* Destroys the session, clearing the cookie and storage if it exists.
|
||||
*/
|
||||
destroy(): void;
|
||||
/**
|
||||
* Regenerates the session, creating a new session ID. The existing session data is preserved.
|
||||
*/
|
||||
regenerate(): Promise<void>;
|
||||
[PERSIST_SYMBOL](): Promise<void>;
|
||||
get sessionID(): string | undefined;
|
||||
/**
|
||||
* Loads a session from storage with the given ID, and replaces the current session.
|
||||
* Any changes made to the current session will be lost.
|
||||
* This is not normally needed, as the session is automatically loaded using the cookie.
|
||||
* However it can be used to restore a session where the ID has been recorded somewhere
|
||||
* else (e.g. in a database).
|
||||
*/
|
||||
load(sessionID: string): Promise<void>;
|
||||
}
|
||||
400
node_modules/astro/dist/core/session/runtime.js
generated
vendored
Normal file
400
node_modules/astro/dist/core/session/runtime.js
generated
vendored
Normal file
@@ -0,0 +1,400 @@
|
||||
import { stringify as rawStringify, unflatten as rawUnflatten } from "devalue";
|
||||
import { SessionStorageInitError, SessionStorageSaveError } from "../errors/errors-data.js";
|
||||
import { AstroError } from "../errors/index.js";
|
||||
import { createStorage } from "unstorage";
|
||||
const PERSIST_SYMBOL = /* @__PURE__ */ Symbol();
|
||||
const DEFAULT_COOKIE_NAME = "astro-session";
|
||||
const VALID_COOKIE_REGEX = /^[\w-]+$/;
|
||||
const unflatten = (parsed, _) => {
|
||||
return rawUnflatten(parsed, {
|
||||
URL: (href) => new URL(href)
|
||||
});
|
||||
};
|
||||
const stringify = (data, _) => {
|
||||
return rawStringify(data, {
|
||||
// Support URL objects
|
||||
URL: (val) => val instanceof URL && val.href
|
||||
});
|
||||
};
|
||||
class AstroSession {
|
||||
// The cookies object.
|
||||
#cookies;
|
||||
// The session configuration.
|
||||
#config;
|
||||
// The cookie config
|
||||
#cookieConfig;
|
||||
// The cookie name
|
||||
#cookieName;
|
||||
// The unstorage object for the session driver.
|
||||
#storage;
|
||||
#data;
|
||||
// The session ID. A v4 UUID.
|
||||
#sessionID;
|
||||
// Sessions to destroy. Needed because we won't have the old session ID after it's destroyed locally.
|
||||
#toDestroy = /* @__PURE__ */ new Set();
|
||||
// Session keys to delete. Used for partial data sets to avoid overwriting the deleted value.
|
||||
#toDelete = /* @__PURE__ */ new Set();
|
||||
// Whether the session is dirty and needs to be saved.
|
||||
#dirty = false;
|
||||
// Whether the session cookie has been set.
|
||||
#cookieSet = false;
|
||||
// Whether the session ID was sourced from a client cookie rather than freshly generated.
|
||||
#sessionIDFromCookie = false;
|
||||
// The local data is "partial" if it has not been loaded from storage yet and only
|
||||
// contains values that have been set or deleted in-memory locally.
|
||||
// We do this to avoid the need to block on loading data when it is only being set.
|
||||
// When we load the data from storage, we need to merge it with the local partial data,
|
||||
// preserving in-memory changes and deletions.
|
||||
#partial = true;
|
||||
// The driver factory function provided by the pipeline
|
||||
#driverFactory;
|
||||
static #sharedStorage = /* @__PURE__ */ new Map();
|
||||
constructor({
|
||||
cookies,
|
||||
config,
|
||||
runtimeMode,
|
||||
driverFactory,
|
||||
mockStorage
|
||||
}) {
|
||||
if (!config) {
|
||||
throw new AstroError({
|
||||
...SessionStorageInitError,
|
||||
message: SessionStorageInitError.message(
|
||||
"No driver was defined in the session configuration and the adapter did not provide a default driver."
|
||||
)
|
||||
});
|
||||
}
|
||||
this.#cookies = cookies;
|
||||
this.#driverFactory = driverFactory;
|
||||
const { cookie: cookieConfig = DEFAULT_COOKIE_NAME, ...configRest } = config;
|
||||
let cookieConfigObject;
|
||||
if (typeof cookieConfig === "object") {
|
||||
const { name = DEFAULT_COOKIE_NAME, ...rest } = cookieConfig;
|
||||
this.#cookieName = name;
|
||||
cookieConfigObject = rest;
|
||||
} else {
|
||||
this.#cookieName = cookieConfig || DEFAULT_COOKIE_NAME;
|
||||
}
|
||||
this.#cookieConfig = {
|
||||
sameSite: "lax",
|
||||
secure: runtimeMode === "production",
|
||||
path: "/",
|
||||
...cookieConfigObject,
|
||||
httpOnly: true
|
||||
};
|
||||
this.#config = configRest;
|
||||
if (mockStorage) {
|
||||
this.#storage = mockStorage;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Gets a session value. Returns `undefined` if the session or value does not exist.
|
||||
*/
|
||||
async get(key) {
|
||||
return (await this.#ensureData()).get(key)?.data;
|
||||
}
|
||||
/**
|
||||
* Checks if a session value exists.
|
||||
*/
|
||||
async has(key) {
|
||||
return (await this.#ensureData()).has(key);
|
||||
}
|
||||
/**
|
||||
* Gets all session values.
|
||||
*/
|
||||
async keys() {
|
||||
return (await this.#ensureData()).keys();
|
||||
}
|
||||
/**
|
||||
* Gets all session values.
|
||||
*/
|
||||
async values() {
|
||||
return [...(await this.#ensureData()).values()].map((entry) => entry.data);
|
||||
}
|
||||
/**
|
||||
* Gets all session entries.
|
||||
*/
|
||||
async entries() {
|
||||
return [...(await this.#ensureData()).entries()].map(([key, entry]) => [key, entry.data]);
|
||||
}
|
||||
/**
|
||||
* Deletes a session value.
|
||||
*/
|
||||
delete(key) {
|
||||
this.#data ??= /* @__PURE__ */ new Map();
|
||||
this.#data.delete(key);
|
||||
if (this.#partial) {
|
||||
this.#toDelete.add(key);
|
||||
}
|
||||
this.#dirty = true;
|
||||
}
|
||||
/**
|
||||
* Sets a session value. The session is created if it does not exist.
|
||||
*/
|
||||
set(key, value, { ttl } = {}) {
|
||||
if (!key) {
|
||||
throw new AstroError({
|
||||
...SessionStorageSaveError,
|
||||
message: "The session key was not provided."
|
||||
});
|
||||
}
|
||||
let cloned;
|
||||
try {
|
||||
cloned = unflatten(JSON.parse(stringify(value)));
|
||||
} catch (err) {
|
||||
throw new AstroError(
|
||||
{
|
||||
...SessionStorageSaveError,
|
||||
message: `The session data for ${key} could not be serialized.`,
|
||||
hint: "See the devalue library for all supported types: https://github.com/rich-harris/devalue"
|
||||
},
|
||||
{ cause: err }
|
||||
);
|
||||
}
|
||||
if (!this.#cookieSet) {
|
||||
this.#setCookie();
|
||||
this.#cookieSet = true;
|
||||
}
|
||||
this.#data ??= /* @__PURE__ */ new Map();
|
||||
const lifetime = ttl ?? this.#config.ttl;
|
||||
const expires = typeof lifetime === "number" ? Date.now() + lifetime * 1e3 : lifetime;
|
||||
this.#data.set(key, {
|
||||
data: cloned,
|
||||
expires
|
||||
});
|
||||
this.#dirty = true;
|
||||
}
|
||||
/**
|
||||
* Destroys the session, clearing the cookie and storage if it exists.
|
||||
*/
|
||||
destroy() {
|
||||
const sessionId = this.#sessionID ?? this.#cookies.get(this.#cookieName)?.value;
|
||||
if (sessionId) {
|
||||
this.#toDestroy.add(sessionId);
|
||||
}
|
||||
this.#cookies.delete(this.#cookieName, this.#cookieConfig);
|
||||
this.#sessionID = void 0;
|
||||
this.#data = void 0;
|
||||
this.#dirty = true;
|
||||
}
|
||||
/**
|
||||
* Regenerates the session, creating a new session ID. The existing session data is preserved.
|
||||
*/
|
||||
async regenerate() {
|
||||
let data = /* @__PURE__ */ new Map();
|
||||
try {
|
||||
data = await this.#ensureData();
|
||||
} catch (err) {
|
||||
console.error("Failed to load session data during regeneration:", err);
|
||||
}
|
||||
const oldSessionId = this.#sessionID;
|
||||
this.#sessionID = crypto.randomUUID();
|
||||
this.#sessionIDFromCookie = false;
|
||||
this.#data = data;
|
||||
this.#dirty = true;
|
||||
await this.#setCookie();
|
||||
if (oldSessionId && this.#storage) {
|
||||
this.#storage.removeItem(oldSessionId).catch((err) => {
|
||||
console.error("Failed to remove old session data:", err);
|
||||
});
|
||||
}
|
||||
}
|
||||
// Persists the session data to storage.
|
||||
// This is called automatically at the end of the request.
|
||||
// Uses a symbol to prevent users from calling it directly.
|
||||
async [PERSIST_SYMBOL]() {
|
||||
if (!this.#dirty && !this.#toDestroy.size) {
|
||||
return;
|
||||
}
|
||||
const storage = await this.#ensureStorage();
|
||||
if (this.#dirty && this.#data) {
|
||||
const data = await this.#ensureData();
|
||||
this.#toDelete.forEach((key2) => data.delete(key2));
|
||||
const key = this.#ensureSessionID();
|
||||
let serialized;
|
||||
try {
|
||||
serialized = stringify(data);
|
||||
} catch (err) {
|
||||
throw new AstroError(
|
||||
{
|
||||
...SessionStorageSaveError,
|
||||
message: SessionStorageSaveError.message(
|
||||
"The session data could not be serialized.",
|
||||
this.#config.driver
|
||||
)
|
||||
},
|
||||
{ cause: err }
|
||||
);
|
||||
}
|
||||
await storage.setItem(key, serialized);
|
||||
this.#dirty = false;
|
||||
}
|
||||
if (this.#toDestroy.size > 0) {
|
||||
const cleanupPromises = [...this.#toDestroy].map(
|
||||
(sessionId) => storage.removeItem(sessionId).catch((err) => {
|
||||
console.error("Failed to clean up session %s:", sessionId, err);
|
||||
})
|
||||
);
|
||||
await Promise.all(cleanupPromises);
|
||||
this.#toDestroy.clear();
|
||||
}
|
||||
}
|
||||
get sessionID() {
|
||||
return this.#sessionID;
|
||||
}
|
||||
/**
|
||||
* Loads a session from storage with the given ID, and replaces the current session.
|
||||
* Any changes made to the current session will be lost.
|
||||
* This is not normally needed, as the session is automatically loaded using the cookie.
|
||||
* However it can be used to restore a session where the ID has been recorded somewhere
|
||||
* else (e.g. in a database).
|
||||
*/
|
||||
async load(sessionID) {
|
||||
this.#sessionID = sessionID;
|
||||
this.#data = void 0;
|
||||
await this.#setCookie();
|
||||
await this.#ensureData();
|
||||
}
|
||||
/**
|
||||
* Sets the session cookie.
|
||||
*/
|
||||
async #setCookie() {
|
||||
if (!VALID_COOKIE_REGEX.test(this.#cookieName)) {
|
||||
throw new AstroError({
|
||||
...SessionStorageSaveError,
|
||||
message: "Invalid cookie name. Cookie names can only contain letters, numbers, and dashes."
|
||||
});
|
||||
}
|
||||
const value = this.#ensureSessionID();
|
||||
this.#cookies.set(this.#cookieName, value, this.#cookieConfig);
|
||||
}
|
||||
/**
|
||||
* Attempts to load the session data from storage, or creates a new data object if none exists.
|
||||
* If there is existing partial data, it will be merged into the new data object.
|
||||
*/
|
||||
async #ensureData() {
|
||||
if (this.#data && !this.#partial) {
|
||||
return this.#data;
|
||||
}
|
||||
this.#data ??= /* @__PURE__ */ new Map();
|
||||
if (!this.#sessionID && !this.#cookies.get(this.#cookieName)?.value) {
|
||||
this.#partial = false;
|
||||
return this.#data;
|
||||
}
|
||||
const storage = await this.#ensureStorage();
|
||||
const raw = await storage.get(this.#ensureSessionID());
|
||||
if (!raw) {
|
||||
if (this.#sessionIDFromCookie) {
|
||||
this.#sessionID = crypto.randomUUID();
|
||||
this.#sessionIDFromCookie = false;
|
||||
if (this.#cookieSet) {
|
||||
await this.#setCookie();
|
||||
}
|
||||
}
|
||||
return this.#data;
|
||||
}
|
||||
try {
|
||||
const storedMap = unflatten(raw);
|
||||
if (!(storedMap instanceof Map)) {
|
||||
await this.destroy();
|
||||
throw new AstroError({
|
||||
...SessionStorageInitError,
|
||||
message: SessionStorageInitError.message(
|
||||
"The session data was an invalid type.",
|
||||
this.#config.driver
|
||||
)
|
||||
});
|
||||
}
|
||||
const now = Date.now();
|
||||
for (const [key, value] of storedMap) {
|
||||
const expired = typeof value.expires === "number" && value.expires < now;
|
||||
if (!this.#data.has(key) && !this.#toDelete.has(key) && !expired) {
|
||||
this.#data.set(key, value);
|
||||
}
|
||||
}
|
||||
this.#partial = false;
|
||||
return this.#data;
|
||||
} catch (err) {
|
||||
await this.destroy();
|
||||
if (err instanceof AstroError) {
|
||||
throw err;
|
||||
}
|
||||
throw new AstroError(
|
||||
{
|
||||
...SessionStorageInitError,
|
||||
message: SessionStorageInitError.message(
|
||||
"The session data could not be parsed.",
|
||||
this.#config.driver
|
||||
)
|
||||
},
|
||||
{ cause: err }
|
||||
);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Returns the session ID, generating a new one if it does not exist.
|
||||
*/
|
||||
#ensureSessionID() {
|
||||
if (!this.#sessionID) {
|
||||
const cookieValue = this.#cookies.get(this.#cookieName)?.value;
|
||||
if (cookieValue) {
|
||||
this.#sessionID = cookieValue;
|
||||
this.#sessionIDFromCookie = true;
|
||||
} else {
|
||||
this.#sessionID = crypto.randomUUID();
|
||||
}
|
||||
}
|
||||
return this.#sessionID;
|
||||
}
|
||||
/**
|
||||
* Ensures the storage is initialized.
|
||||
* This is called automatically when a storage operation is needed.
|
||||
*/
|
||||
async #ensureStorage() {
|
||||
if (this.#storage) {
|
||||
return this.#storage;
|
||||
}
|
||||
if (AstroSession.#sharedStorage.has(this.#config.driver)) {
|
||||
this.#storage = AstroSession.#sharedStorage.get(this.#config.driver);
|
||||
return this.#storage;
|
||||
}
|
||||
if (!this.#driverFactory) {
|
||||
throw new AstroError({
|
||||
...SessionStorageInitError,
|
||||
message: SessionStorageInitError.message(
|
||||
"Astro could not load the driver correctly. Does it exist?",
|
||||
this.#config.driver
|
||||
)
|
||||
});
|
||||
}
|
||||
const driver = this.#driverFactory;
|
||||
try {
|
||||
this.#storage = createStorage({
|
||||
driver: {
|
||||
...driver(this.#config.options),
|
||||
// Unused methods
|
||||
hasItem() {
|
||||
return false;
|
||||
},
|
||||
getKeys() {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
});
|
||||
AstroSession.#sharedStorage.set(this.#config.driver, this.#storage);
|
||||
return this.#storage;
|
||||
} catch (err) {
|
||||
throw new AstroError(
|
||||
{
|
||||
...SessionStorageInitError,
|
||||
message: SessionStorageInitError.message("Unknown error", this.#config.driver)
|
||||
},
|
||||
{ cause: err }
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
export {
|
||||
AstroSession,
|
||||
PERSIST_SYMBOL
|
||||
};
|
||||
67
node_modules/astro/dist/core/session/types.d.ts
generated
vendored
Normal file
67
node_modules/astro/dist/core/session/types.d.ts
generated
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
import type { BuiltinDriverOptions } from 'unstorage';
|
||||
import type { AstroCookieSetOptions } from '../cookies/cookies.js';
|
||||
export interface SessionDriver {
|
||||
removeItem: (key: string) => Promise<void>;
|
||||
getItem: (key: string) => Promise<any>;
|
||||
setItem: (key: string, value: any) => Promise<void>;
|
||||
}
|
||||
export type SessionDriverFactory = (config: Record<string, any> | undefined) => SessionDriver;
|
||||
export interface SessionDriverConfig {
|
||||
/** Serializable options used by the driver implementation */
|
||||
config?: Record<string, any> | undefined;
|
||||
/** URL or package import */
|
||||
entrypoint: string | URL;
|
||||
}
|
||||
export interface NormalizedSessionDriverConfig {
|
||||
config: Record<string, any> | undefined;
|
||||
entrypoint: string;
|
||||
}
|
||||
/** @deprecated */
|
||||
export type SessionDriverName = keyof BuiltinDriverOptions | (string & {});
|
||||
export interface BaseSessionConfig {
|
||||
/**
|
||||
* Configures the session cookie. If set to a string, it will be used as the cookie name.
|
||||
* Alternatively, you can pass an object with additional options.
|
||||
*/
|
||||
cookie?: string | (Omit<AstroCookieSetOptions, 'httpOnly' | 'expires' | 'encode'> & {
|
||||
name?: string;
|
||||
});
|
||||
/**
|
||||
* Default session duration in seconds. If not set, the session will be stored until deleted, or until the cookie expires.
|
||||
*/
|
||||
ttl?: number;
|
||||
}
|
||||
interface DriverConfig<TDriver extends SessionDriverConfig> extends BaseSessionConfig {
|
||||
/** Config object for a session driver */
|
||||
driver: TDriver;
|
||||
/** @deprecated Pass options to the driver function directly. This will be removed in Astro 7 */
|
||||
options?: never;
|
||||
}
|
||||
interface UnstorageConfig<TDriver extends keyof BuiltinDriverOptions | undefined, TOptions = TDriver extends keyof BuiltinDriverOptions ? NoInfer<BuiltinDriverOptions[TDriver]> : undefined> extends BaseSessionConfig {
|
||||
/**
|
||||
* Entrypoint for an unstorage session driver
|
||||
* @deprecated Use `import { sessionDrivers } from 'astro/config'` instead. This will be removed in Astro 7
|
||||
*/
|
||||
driver?: TDriver;
|
||||
/**
|
||||
* Options for the unstorage driver
|
||||
* @deprecated Use `import { sessionDrivers } from 'astro/config'` instead. This will be removed in Astro 7
|
||||
*/
|
||||
options?: TOptions;
|
||||
}
|
||||
interface CustomConfig extends BaseSessionConfig {
|
||||
/**
|
||||
* Entrypoint for a custom session driver
|
||||
* @deprecated Use the object shape (type `SessionDriverConfig`). This will be removed in Astro 7
|
||||
*/
|
||||
driver?: string;
|
||||
/**
|
||||
* Options for the custom session driver
|
||||
* @deprecated Use the object shape (type `SessionDriverConfig`). This will be removed in Astro 7
|
||||
*/
|
||||
options?: Record<string, unknown>;
|
||||
}
|
||||
export type SessionConfig<TDriver extends SessionDriverName | SessionDriverConfig | undefined> = [
|
||||
TDriver
|
||||
] extends [never] ? UnstorageConfig<TDriver> : TDriver extends SessionDriverConfig ? DriverConfig<TDriver> : TDriver extends keyof BuiltinDriverOptions ? UnstorageConfig<TDriver> : CustomConfig;
|
||||
export {};
|
||||
0
node_modules/astro/dist/core/session/types.js
generated
vendored
Normal file
0
node_modules/astro/dist/core/session/types.js
generated
vendored
Normal file
7
node_modules/astro/dist/core/session/utils.d.ts
generated
vendored
Normal file
7
node_modules/astro/dist/core/session/utils.d.ts
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
import type { NormalizedSessionDriverConfig, SessionDriverConfig } from './types.js';
|
||||
import type { SSRManifestSession } from '../app/types.js';
|
||||
import type { AstroConfig } from '../../types/public/index.js';
|
||||
export declare function normalizeSessionDriverConfig(driver: string | SessionDriverConfig,
|
||||
/** @deprecated */
|
||||
options?: Record<string, any>): NormalizedSessionDriverConfig;
|
||||
export declare function sessionConfigToManifest(config: AstroConfig['session']): SSRManifestSession | undefined;
|
||||
49
node_modules/astro/dist/core/session/utils.js
generated
vendored
Normal file
49
node_modules/astro/dist/core/session/utils.js
generated
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
import { builtinDrivers } from "unstorage";
|
||||
import { fileURLToPath } from "node:url";
|
||||
function isUnstorageDriver(driver) {
|
||||
return driver in builtinDrivers;
|
||||
}
|
||||
function normalizeSessionDriverConfig(driver, options) {
|
||||
if (typeof driver !== "string") {
|
||||
return {
|
||||
entrypoint: driver.entrypoint instanceof URL ? fileURLToPath(driver.entrypoint) : driver.entrypoint,
|
||||
config: driver.config
|
||||
};
|
||||
}
|
||||
if (["fs", "fs-lite", "fsLite"].includes(driver)) {
|
||||
return {
|
||||
entrypoint: builtinDrivers.fsLite,
|
||||
config: {
|
||||
base: ".astro/session",
|
||||
...options
|
||||
}
|
||||
};
|
||||
}
|
||||
if (isUnstorageDriver(driver)) {
|
||||
return {
|
||||
entrypoint: builtinDrivers[driver],
|
||||
config: options
|
||||
};
|
||||
}
|
||||
return {
|
||||
entrypoint: driver,
|
||||
config: options
|
||||
};
|
||||
}
|
||||
function sessionConfigToManifest(config) {
|
||||
const sessionDriver = config?.driver;
|
||||
if (!config || !sessionDriver) {
|
||||
return void 0;
|
||||
}
|
||||
const driver = normalizeSessionDriverConfig(sessionDriver);
|
||||
return {
|
||||
driver: driver.entrypoint,
|
||||
options: driver.config,
|
||||
cookie: config.cookie,
|
||||
ttl: config.ttl
|
||||
};
|
||||
}
|
||||
export {
|
||||
normalizeSessionDriverConfig,
|
||||
sessionConfigToManifest
|
||||
};
|
||||
6
node_modules/astro/dist/core/session/vite-plugin.d.ts
generated
vendored
Normal file
6
node_modules/astro/dist/core/session/vite-plugin.d.ts
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
import type { Plugin as VitePlugin } from 'vite';
|
||||
import type { AstroSettings } from '../../types/astro.js';
|
||||
export declare const VIRTUAL_SESSION_DRIVER_ID = "virtual:astro:session-driver";
|
||||
export declare function vitePluginSessionDriver({ settings }: {
|
||||
settings: AstroSettings;
|
||||
}): VitePlugin;
|
||||
54
node_modules/astro/dist/core/session/vite-plugin.js
generated
vendored
Normal file
54
node_modules/astro/dist/core/session/vite-plugin.js
generated
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { SessionStorageInitError } from "../errors/errors-data.js";
|
||||
import { AstroError } from "../errors/index.js";
|
||||
import { normalizeSessionDriverConfig } from "./utils.js";
|
||||
const VIRTUAL_SESSION_DRIVER_ID = "virtual:astro:session-driver";
|
||||
const RESOLVED_VIRTUAL_SESSION_DRIVER_ID = "\0" + VIRTUAL_SESSION_DRIVER_ID;
|
||||
function vitePluginSessionDriver({ settings }) {
|
||||
return {
|
||||
name: VIRTUAL_SESSION_DRIVER_ID,
|
||||
enforce: "pre",
|
||||
resolveId: {
|
||||
filter: {
|
||||
id: new RegExp(`^${VIRTUAL_SESSION_DRIVER_ID}$`)
|
||||
},
|
||||
handler() {
|
||||
return RESOLVED_VIRTUAL_SESSION_DRIVER_ID;
|
||||
}
|
||||
},
|
||||
load: {
|
||||
filter: {
|
||||
id: new RegExp(`^${RESOLVED_VIRTUAL_SESSION_DRIVER_ID}$`)
|
||||
},
|
||||
async handler() {
|
||||
if (!settings.config.session?.driver) {
|
||||
return { code: "export default null;" };
|
||||
}
|
||||
const driver = normalizeSessionDriverConfig(
|
||||
settings.config.session.driver,
|
||||
settings.config.session.options
|
||||
);
|
||||
const importerPath = fileURLToPath(import.meta.url);
|
||||
const resolved = await this.resolve(driver.entrypoint, importerPath);
|
||||
if (!resolved) {
|
||||
throw new AstroError({
|
||||
...SessionStorageInitError,
|
||||
message: SessionStorageInitError.message(
|
||||
`Failed to resolve session driver: ${driver.entrypoint}`,
|
||||
driver.entrypoint
|
||||
)
|
||||
});
|
||||
}
|
||||
return {
|
||||
code: `import { default as _default } from '${resolved.id}';
|
||||
export * from '${resolved.id}';
|
||||
export default _default;`
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
export {
|
||||
VIRTUAL_SESSION_DRIVER_ID,
|
||||
vitePluginSessionDriver
|
||||
};
|
||||
Reference in New Issue
Block a user