alepha
Version:
Easy-to-use modern TypeScript framework for building many kind of applications.
252 lines • 9.79 kB
TypeScript
import { Alepha, Atom, KIND, Primitive, Static, TSchema } from "alepha";
import { SecretProvider } from "alepha/crypto";
import { DateTimeProvider, DurationLike } from "alepha/datetime";
//#region ../../src/server/cookies/services/CookieParser.d.ts
declare class CookieParser {
parseRequestCookies(header: string): Record<string, string>;
serializeResponseCookies(cookies: Record<string, Cookie | null>, isHttps: boolean): string[];
cookieToString(name: string, cookie: Cookie, isHttps?: boolean): string;
}
//#endregion
//#region ../../src/server/cookies/providers/ServerCookiesProvider.d.ts
declare class ServerCookiesProvider {
protected readonly alepha: Alepha;
protected readonly log: import("alepha/logger").Logger;
protected readonly cookieParser: CookieParser;
protected readonly dateTimeProvider: DateTimeProvider;
protected readonly secretProvider: SecretProvider;
protected readonly ALGORITHM = "aes-256-gcm";
protected readonly IV_LENGTH = 16;
protected readonly AUTH_TAG_LENGTH = 16;
protected readonly SIGNATURE_LENGTH = 32;
readonly onRequest: import("alepha").HookPrimitive<"server:onRequest">;
readonly onAction: import("alepha").HookPrimitive<"action:onRequest">;
readonly onSend: import("alepha").HookPrimitive<"server:onSend">;
protected getCookiesFromContext(cookies?: Cookies): Cookies;
/**
* Namespaces a cookie name with the app's `APP_NAME` (lowercased) so that
* two Alepha apps sharing a cookie jar do not collide.
*
* Cookies are scoped by host + path only — never by port — so two apps on
* `localhost:3000` and `localhost:4000` would otherwise both read/write a
* cookie literally named `tokens` and silently clobber each other (and,
* because each encrypts with its own `APP_SECRET`, the foreign cookie fails
* to decrypt and gets deleted, logging the user out).
*
* When `APP_NAME` is unset the name is returned unchanged, so existing
* single-app deployments keep their current cookie names. Same convention as
* the `APP_NAME` prefix used by R2 storage and server-timing.
*
* Pass `prefix = false` to skip the namespace entirely — used for
* `persist: "cookie"` atoms, whose browser-side counterpart cannot see
* `APP_NAME` and therefore always uses the bare name. See
* `CookiePrimitiveOptions.prefix`.
*/
protected prefixName(name: string, prefix?: boolean): string;
getCookie<T extends TSchema>(name: string, options: CookiePrimitiveOptions<T>, contextCookies?: Cookies): Static<T> | undefined;
setCookie<T extends TSchema>(name: string, options: CookiePrimitiveOptions<T>, data: Static<T>, contextCookies?: Cookies): void;
deleteCookie<T extends TSchema>(name: string, contextCookies?: Cookies, prefix?: boolean): void;
protected encrypt(text: string): string;
protected decrypt(encryptedText: string): string;
/**
* Derives a 32-byte key from APP_SECRET via SHA-256.
* Accepts any string length — no padding or truncation needed.
*/
protected deriveKey(): Buffer;
protected sign(data: string): string;
}
//#endregion
//#region ../../src/server/cookies/primitives/$cookie.d.ts
/**
* Declares a type-safe, configurable HTTP cookie.
* This primitive provides methods to get, set, and delete the cookie
* within the server request/response cycle.
*/
declare const $cookie: {
<T extends TSchema>(options: CookiePrimitiveOptions<T>, extendedOptions?: Omit<CookiePrimitiveOptions<T>, "schema">): AbstractCookiePrimitive<T>;
[KIND]: typeof CookiePrimitive;
};
interface CookiePrimitiveOptions<T extends TSchema> {
/**
* The schema for the cookie's value, used for validation and type safety.
*/
schema: T;
/**
* The name of the cookie.
*/
name?: string;
/**
* The cookie's path. Defaults to "/".
*/
path?: string;
/**
* Time-to-live for the cookie. Maps to `Max-Age`.
*/
ttl?: DurationLike;
/**
* If true, the cookie is only sent over HTTPS. Defaults to true in production.
*/
secure?: boolean;
/**
* If true, the cookie cannot be accessed by client-side scripts.
*/
httpOnly?: boolean;
/**
* SameSite policy for the cookie. Defaults to "lax".
*/
sameSite?: "strict" | "lax" | "none";
/**
* The domain for the cookie.
*/
domain?: string;
/**
* If true, the cookie value will be compressed using zlib.
*/
compress?: boolean;
/**
* If true, the cookie value will be encrypted. Requires `COOKIE_SECRET` env var.
*/
encrypt?: boolean;
/**
* If true, the cookie will be signed to prevent tampering. Requires `COOKIE_SECRET` env var.
*/
sign?: boolean;
/**
* Optional key to link this cookie to an Atom, enabling automatic synchronization between the cookie and the Atom's state.
*/
key?: string;
/**
* Internal escape hatch: when explicitly set to `false`, the server skips
* the `APP_NAME` cookie-name namespace applied by
* `ServerCookiesProvider.prefixName()`.
*
* Used by `AtomCookiePersistence` so the cookie name the server
* reads/writes for a `persist: "cookie"` atom matches the bare name its
* browser variant uses — `APP_NAME` is not reachable client-side (not
* baked into the client bundle, not part of SSR hydration), so the
* browser can only ever use the bare atom key.
*
* Application code declaring `$cookie(...)` directly should leave this
* unset — it defaults to `true` (prefixed), matching every other cookie.
*/
prefix?: boolean;
}
interface AbstractCookiePrimitive<T extends TSchema> {
readonly name: string;
readonly options: CookiePrimitiveOptions<T>;
set(value: Static<T>, options?: {
cookies?: Cookies;
ttl?: DurationLike;
}): void;
get(options?: {
cookies?: Cookies;
}): Static<T> | undefined;
del(options?: {
cookies?: Cookies;
}): void;
}
declare class CookiePrimitive<T extends TSchema> extends Primitive<CookiePrimitiveOptions<T>> implements AbstractCookiePrimitive<T> {
protected readonly serverCookiesProvider: ServerCookiesProvider;
protected onInit(): void;
get schema(): T;
get name(): string;
/**
* Sets the cookie with the given value in the current request's response.
*/
set(value: Static<T>, options?: {
cookies?: Cookies;
ttl?: DurationLike;
}): void;
/**
* Gets the cookie value from the current request. Returns undefined if not found or invalid.
*/
get(options?: {
cookies?: Cookies;
}): Static<T> | undefined;
/**
* Deletes the cookie in the current request's response.
*/
del(options?: {
cookies?: Cookies;
}): void;
}
interface Cookies {
req: Record<string, string>;
res: Record<string, Cookie | null>;
}
interface Cookie {
value: string;
path?: string;
maxAge?: number;
secure?: boolean;
httpOnly?: boolean;
sameSite?: "strict" | "lax" | "none";
domain?: string;
}
//#endregion
//#region ../../src/server/cookies/providers/AtomCookiePersistence.d.ts
/**
* Binds every atom declared with `persist: "cookie"` to an HTTP cookie.
*
* - `server:onRequest` — seeds the request-scoped state from the cookie, so
* SSR renders with the persisted value.
* - `state:mutate` — writes the new value back as a Set-Cookie header.
* - `state:register` — an atom registering lazily *during* a request (first
* touched by an SSR render, after `server:onRequest` already ran) reads
* its cookie right away, so that render still sees the persisted value.
*
* Atoms are resolved from the `StateManager` registry
* (`alepha.store.listAtoms()`) on every request and every mutation, never
* from a map built up from `state:register` events. That event fires exactly
* once per atom and is never replayed, while `$module.register()` registers
* `atoms[]` BEFORE it wires `imports[]` and injects `services[]` — so the
* documented `$module({ atoms, imports: [AlephaServerCookies], services })`
* shape registers every atom before this provider exists. An event-sourced
* map would stay empty forever there, making `persist: "cookie"` a silent
* no-op in both directions. Reading the registry on demand is
* order-independent.
*
* The cookie is named after the atom key, lives 365 days, SameSite=lax,
* path "/". For custom cookie options (encryption, signing, custom TTL),
* declare an explicit `$cookie({ key: atom.key, ... })` binding instead.
*/
declare class AtomCookiePersistence {
protected readonly alepha: Alepha;
protected readonly log: import("alepha/logger").Logger;
protected readonly serverCookies: ServerCookiesProvider;
protected readonly onRequest: import("alepha").HookPrimitive<"server:onRequest">;
protected readonly onRegister: import("alepha").HookPrimitive<"state:register">;
protected readonly onMutate: import("alepha").HookPrimitive<"state:mutate">;
/**
* Every registered atom declared with `persist: "cookie"`, read live from
* the state manager's registry.
*/
protected cookieAtoms(): Array<Atom<any, any>>;
protected read(atom: Atom<any, any>, cookies?: Cookies): void;
protected cookieOptions(atom: Atom<any, any>): {
schema: any;
path: string;
sameSite: "lax";
ttl: DurationLike;
prefix: boolean;
};
}
//#endregion
//#region ../../src/server/cookies/index.d.ts
declare module "alepha/server" {
interface ServerRequest {
cookies: Cookies;
}
}
/**
* Server and browser-safe cookie handling.
*
* **Features:**
* - Cookie management on server and browser
*
* @module alepha.server.cookies
*/
declare const AlephaServerCookies: import("alepha").Service<import("alepha").Module>;
//#endregion
export { $cookie, AbstractCookiePrimitive, AlephaServerCookies, AtomCookiePersistence, Cookie, CookiePrimitive, CookiePrimitiveOptions, Cookies, ServerCookiesProvider };
//# sourceMappingURL=index.d.ts.map