@orieljs/session 0.1.0-alpha.6 → 0.1.0-alpha.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/NOTICE CHANGED
@@ -10,3 +10,7 @@ The Oriel name and logo are not covered by that license; see TRADEMARKS.md
10
10
 
11
11
  @orieljs/support (and @orieljs/framework, which bundles it) includes transliteration data from
12
12
  voku/portable-ascii (https://github.com/voku/portable-ascii), Copyright (C) 2019 Lars Moelleken, MIT License.
13
+
14
+ @orieljs/notifications (and @orieljs/framework, which bundles it) includes the HTML and CSS of
15
+ Laravel's default notification mail (laravel/framework, https://github.com/laravel/framework),
16
+ Copyright (c) Taylor Otwell, MIT License.
package/README.md ADDED
@@ -0,0 +1,32 @@
1
+ # @orieljs/session
2
+
3
+ Sessions for Oriel: data kept for a user between requests, flash data for the next request only, and CSRF protection, as Laravel's sessions. Routes in the `web` middleware group have a session. It is part of `@orieljs/framework`, which every Oriel app already installs, and is re-exported from it. In an app, import it from `@orieljs/framework`; `@orieljs/session` is also published on its own.
4
+
5
+ ```bash
6
+ npm install @orieljs/framework
7
+ ```
8
+
9
+ ```ts title="app/Http/Controllers/ThemeController.ts"
10
+ import { redirect, request, session } from '@orieljs/framework'
11
+ import { Controller } from './Controller'
12
+
13
+ export class ThemeController extends Controller {
14
+ update() {
15
+ session().put('theme', request().input('theme', 'system'))
16
+
17
+ return redirect().back().with('status', 'Theme saved.')
18
+ }
19
+ }
20
+ ```
21
+
22
+ `session()` returns the current session (`get()`, `put()`, `push()`, `forget()`, `flash()`, the async `regenerate()`, …) and `session('theme', 'light')` reads one value. `old()` reads the input flashed by the previous request, `errors()` its validation errors, and `csrfToken()` the token the `VerifyCsrfToken` middleware checks. The drivers are `file`, `cookie`, `database`, `redis` and `array`.
23
+
24
+ Documentation: https://orieljs.vercel.app/docs/session
25
+
26
+ Status: early alpha. APIs will change.
27
+
28
+ ## License
29
+
30
+ Oriel is open-source software licensed under the Apache License 2.0 (Apache-2.0; see `LICENSE` and `NOTICE`). The Oriel name and logo are trademarks; see `TRADEMARKS.md`.
31
+
32
+ Website: https://orieljs.vercel.app
package/TRADEMARKS.md ADDED
@@ -0,0 +1,33 @@
1
+ # Oriel trademark policy
2
+
3
+ The Oriel code is open source under the Apache License 2.0. The **Oriel name and logo** are not: the license covers
4
+ the code only (section 6 of the license says so), and the name and logo stay with the project. This page explains
5
+ what you can and can't do with them. The goal is simple: people should always be able to tell what is the real Oriel
6
+ and what isn't.
7
+
8
+ ## You can, without asking
9
+
10
+ - Use, change, ship and sell the code, as the license allows.
11
+ - Say that your app or package is "built with Oriel", "for Oriel" or "compatible with Oriel".
12
+ - Name a package `oriel-<something>` or `<something>-for-oriel` when it works with Oriel, as long as it is clear that
13
+ it is not official (for example, don't publish it under the `@orieljs` npm scope).
14
+ - Use the name and logo to write about Oriel, teach it, or link to it, in articles, talks, videos and courses.
15
+ - Use the unmodified logo to point to the project, as it is (no recolouring, cropping or
16
+ distortion).
17
+
18
+ ## You can't, without written permission
19
+
20
+ - Call a fork, a modified copy or a competing product "Oriel", or anything likely to be confused with it.
21
+ - Use the name or logo as the name, logo or domain of your own product, company or service.
22
+ - Suggest that the Oriel project made, endorses or supports your work when it doesn't.
23
+ - Sell merchandise with the name or logo.
24
+
25
+ ## Forks
26
+
27
+ Forks are welcome. Please give yours a different name and logo, keep the `LICENSE` and `NOTICE` files, and say that
28
+ it is based on Oriel.
29
+
30
+ ## Questions
31
+
32
+ Open an issue at https://github.com/orieljs/framework or email meeeet.dev@gmail.com. If you're unsure whether a use
33
+ is fine, ask; the answer is usually yes.
package/dist/index.d.ts CHANGED
@@ -248,12 +248,13 @@ declare class VerifyCsrfToken implements Middleware {
248
248
  }
249
249
 
250
250
  /**
251
- * A read-only MessageBag over one bag of the flashed validation errors. Http flashes
251
+ * A MessageBag over one bag of the flashed validation errors (add() changes this bag, not the session). Http flashes
252
252
  * `errors: { [bag]: { field: string[] } }`; views read them with `errors().first('email')`.
253
253
  */
254
254
  declare class SessionMessageBag implements MessageBag {
255
255
  #private;
256
256
  constructor(messages?: Record<string, string[]>);
257
+ add(key: string, message: string): void;
257
258
  has(key: string): boolean;
258
259
  first(key?: string): string | undefined;
259
260
  get(key: string): string[];
package/dist/index.js CHANGED
@@ -683,7 +683,10 @@ var VerifyCsrfToken = class {
683
683
  var SessionMessageBag = class {
684
684
  #messages;
685
685
  constructor(messages = {}) {
686
- this.#messages = messages;
686
+ this.#messages = { ...messages };
687
+ }
688
+ add(key, message) {
689
+ this.#messages[key] = [...this.get(key), message];
687
690
  }
688
691
  has(key) {
689
692
  return this.get(key).length > 0;
@@ -770,6 +773,9 @@ var SessionServiceProvider = class extends ServiceProvider {
770
773
  "session"
771
774
  );
772
775
  this.app.singleton(SessionManager, (container) => new SessionManager(container));
776
+ this.app.onShutdown(async () => {
777
+ if (this.app.resolved(SessionManager)) await this.app.make(SessionManager).disconnect();
778
+ });
773
779
  this.app.scoped(Session4, (container) => container.make(SessionManager).build(container));
774
780
  }
775
781
  boot() {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../Store.ts","../handlers/ArraySessionHandler.ts","../handlers/FileSessionHandler.ts","../handlers/DatabaseSessionHandler.ts","../handlers/CookieSessionHandler.ts","../handlers/RedisSessionHandler.ts","../SessionManager.ts","../errors.ts","../middleware/StartSession.ts","../middleware/cookies.ts","../middleware/VerifyCsrfToken.ts","../equals.ts","../ViewErrorBag.ts","../facade.ts","../SessionServiceProvider.ts"],"sourcesContent":["import type { Encrypter, Session, SessionHandler } from '@orieljs/contracts'\nimport { Arr, Str } from '@orieljs/support'\n\ntype Attributes = Record<string, unknown>\n\nconst unique = (values: string[]): string[] => [...new Set(values)]\n\n/**\n * Laravel's Illuminate\\Session\\Store (and EncryptedStore when an Encrypter is given).\n * Attributes use dot notation, so 'url.intended' is stored as { url: { intended } }.\n * The payload is JSON: Dates become strings and class instances become plain objects.\n */\nexport class Store implements Session {\n #id = ''\n #name: string\n #attributes: Attributes = {}\n #started = false\n readonly #handler: SessionHandler\n readonly #encrypter: Encrypter | undefined\n\n constructor(name: string, handler: SessionHandler, id?: string, encrypter?: Encrypter) {\n this.#name = name\n this.#handler = handler\n this.#encrypter = encrypter\n this.setId(id)\n }\n\n /** Loads the session from the handler and makes sure it has a CSRF token. */\n async start(): Promise<void> {\n this.#attributes = { ...this.#attributes, ...(await this.#readFromHandler()) }\n if (!this.has('_token')) this.regenerateToken()\n this.#started = true\n }\n\n /** Ages the flash data and writes the session through the handler. */\n async save(): Promise<void> {\n this.ageFlashData()\n const payload = JSON.stringify(this.#attributes)\n await this.#handler.write(this.getId(), this.#encrypter === undefined ? payload : this.#encrypter.encrypt(payload, false))\n this.#started = false\n }\n\n /** Forgets last request's flash data and marks this request's flash data as old. */\n ageFlashData(): void {\n this.forget(...this.get<string[]>('_flash.old', []))\n this.put('_flash.old', this.get<string[]>('_flash.new', []))\n this.put('_flash.new', [])\n }\n\n all(): Attributes {\n return { ...this.#attributes }\n }\n\n only(keys: string[]): Attributes {\n return Arr.only(this.#attributes, keys)\n }\n\n except(keys: string[]): Attributes {\n return Arr.except(this.#attributes, keys)\n }\n\n /** Whether the key is present, even with a null value. */\n exists(...keys: string[]): boolean {\n return keys.every((key) => Arr.has(this.#attributes, key))\n }\n\n missing(...keys: string[]): boolean {\n return !this.exists(...keys)\n }\n\n /** Whether the key is present and not null/undefined. */\n has(key: string): boolean {\n const value = this.get<unknown>(key)\n return value !== undefined && value !== null\n }\n\n get<T = unknown>(key: string, defaultValue?: T): T {\n return Arr.get(this.#attributes, key, defaultValue)\n }\n\n pull<T = unknown>(key: string, defaultValue?: T): T {\n const value = this.get(key, defaultValue)\n this.forget(key)\n return value\n }\n\n put(key: string | Attributes, value?: unknown): void {\n const values = typeof key === 'string' ? { [key]: value } : key\n for (const [name, item] of Object.entries(values)) Arr.set(this.#attributes, name, item)\n }\n\n push(key: string, value: unknown): void {\n const list = this.get<unknown>(key, [])\n this.put(key, [...(Array.isArray(list) ? list : [list]), value])\n }\n\n increment(key: string, amount = 1): number {\n const value = Number(this.get(key, 0)) + amount\n this.put(key, value)\n return value\n }\n\n decrement(key: string, amount = 1): number {\n return this.increment(key, -amount)\n }\n\n forget(...keys: string[]): void {\n for (const key of keys) Arr.forget(this.#attributes, key)\n }\n\n /** Removes a key and returns its value. */\n remove<T = unknown>(key: string): T {\n return this.pull<T>(key)\n }\n\n flush(): void {\n this.#attributes = {}\n }\n\n /** Available on this request and the next one. */\n flash(key: string, value: unknown = true): void {\n this.put(key, value)\n this.push('_flash.new', key)\n this.#removeFromOldFlashData([key])\n }\n\n /** Available on this request only. */\n now(key: string, value: unknown): void {\n this.put(key, value)\n this.push('_flash.old', key)\n }\n\n /** Keeps all of last request's flash data for one more request. */\n reflash(): void {\n this.#mergeNewFlashes(this.get<string[]>('_flash.old', []))\n this.put('_flash.old', [])\n }\n\n /** Keeps some of last request's flash data for one more request. */\n keep(...keys: string[]): void {\n this.#mergeNewFlashes(keys)\n this.#removeFromOldFlashData(keys)\n }\n\n flashInput(input: Attributes): void {\n this.flash('_old_input', input)\n }\n\n hasOldInput(key?: string): boolean {\n const old = this.getOldInput<unknown>(key)\n return key === undefined ? typeof old === 'object' && old !== null && Object.keys(old).length > 0 : old !== undefined && old !== null\n }\n\n getOldInput<T = unknown>(key?: string, defaultValue?: T): T {\n return Arr.get(this.get<Attributes>('_old_input', {}), key, defaultValue)\n }\n\n token(): string {\n return this.get<string>('_token')\n }\n\n regenerateToken(): void {\n this.put('_token', Str.random(40))\n }\n\n /** New session id and CSRF token. With destroy, the old record is deleted. */\n async regenerate(destroy = false): Promise<void> {\n await this.migrate(destroy)\n this.regenerateToken()\n }\n\n /** New session id, keeping the data (and the CSRF token). With destroy, the old record is deleted. */\n async migrate(destroy = false): Promise<void> {\n if (destroy) await this.#handler.destroy(this.getId())\n ;(this.#handler as { setExists?(exists: boolean): void }).setExists?.(false)\n this.setId(this.#generateSessionId())\n }\n\n /** Flushes the data and migrates to a new id, destroying the old record. */\n async invalidate(): Promise<void> {\n this.flush()\n await this.migrate(true)\n }\n\n previousUrl(): string | undefined {\n return this.get<string | undefined>('_previous.url')\n }\n\n setPreviousUrl(url: string): void {\n this.put('_previous.url', url)\n }\n\n isStarted(): boolean {\n return this.#started\n }\n\n getName(): string {\n return this.#name\n }\n\n setName(name: string): void {\n this.#name = name\n }\n\n getId(): string {\n return this.#id\n }\n\n /** Invalid ids (anything but 40 alphanumerics) are replaced by a fresh one, so ids from cookies can't be forged. */\n setId(id: string | undefined | null): void {\n this.#id = this.isValidId(id) ? id : this.#generateSessionId()\n }\n\n isValidId(id: unknown): id is string {\n return typeof id === 'string' && /^[a-zA-Z0-9]{40}$/.test(id)\n }\n\n getHandler(): SessionHandler {\n return this.#handler\n }\n\n #generateSessionId(): string {\n return Str.random(40)\n }\n\n async #readFromHandler(): Promise<Attributes> {\n let data = await this.#handler.read(this.getId())\n if (data === '') return {}\n if (this.#encrypter !== undefined) {\n try {\n data = this.#encrypter.decrypt<string>(data, false)\n } catch {\n return {}\n }\n }\n try {\n const parsed: unknown = JSON.parse(data)\n return typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed) ? (parsed as Attributes) : {}\n } catch {\n return {}\n }\n }\n\n #mergeNewFlashes(keys: string[]): void {\n this.put('_flash.new', unique([...this.get<string[]>('_flash.new', []), ...keys]))\n }\n\n #removeFromOldFlashData(keys: string[]): void {\n this.put('_flash.old', this.get<string[]>('_flash.old', []).filter((key) => !keys.includes(key)))\n }\n}\n","import type { SessionHandler } from '@orieljs/contracts'\n\n/** Laravel's ArraySessionHandler: in-memory sessions (tests, `SESSION_DRIVER=array`). */\nexport class ArraySessionHandler implements SessionHandler {\n readonly #storage = new Map<string, { data: string; time: number }>()\n\n constructor(\n private readonly minutes: number,\n private readonly clock: () => number = Date.now,\n ) {}\n\n async read(id: string): Promise<string> {\n const session = this.#storage.get(id)\n if (session === undefined) return ''\n return session.time >= this.clock() - this.minutes * 60_000 ? session.data : ''\n }\n\n async write(id: string, data: string): Promise<void> {\n this.#storage.set(id, { data, time: this.clock() })\n }\n\n async destroy(id: string): Promise<void> {\n this.#storage.delete(id)\n }\n\n async gc(maxLifetimeSeconds: number): Promise<void> {\n const expiration = this.clock() - maxLifetimeSeconds * 1000\n for (const [id, session] of this.#storage) if (session.time <= expiration) this.#storage.delete(id)\n }\n\n /** The raw stored payload (for tests and debugging). */\n raw(id: string): string | undefined {\n return this.#storage.get(id)?.data\n }\n}\n","import { mkdir, readdir, readFile, rename, rm, stat, writeFile } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport type { SessionHandler } from '@orieljs/contracts'\nimport { Str } from '@orieljs/support'\n\nconst VALID_ID = /^[a-zA-Z0-9]{40}$/\n\n/**\n * Laravel's FileSessionHandler: one file per session in `path` (storage/framework/sessions).\n * Only 40-character alphanumeric ids are ever turned into a path, so an id can't escape the directory.\n */\nexport class FileSessionHandler implements SessionHandler {\n constructor(\n private readonly path: string,\n private readonly minutes: number,\n private readonly clock: () => number = Date.now,\n ) {}\n\n async read(id: string): Promise<string> {\n if (!VALID_ID.test(id)) return ''\n const file = join(this.path, id)\n try {\n const { mtimeMs } = await stat(file)\n if (mtimeMs < this.clock() - this.minutes * 60_000) return ''\n return await readFile(file, 'utf8')\n } catch {\n return ''\n }\n }\n\n async write(id: string, data: string): Promise<void> {\n if (!VALID_ID.test(id)) return\n await mkdir(this.path, { recursive: true })\n // Write then rename, so a concurrent read never sees a half-written file.\n const temporary = join(this.path, `.${id}.${Str.random(8)}.tmp`)\n await writeFile(temporary, data, 'utf8')\n await rename(temporary, join(this.path, id))\n }\n\n async destroy(id: string): Promise<void> {\n if (VALID_ID.test(id)) await rm(join(this.path, id), { force: true })\n }\n\n async gc(maxLifetimeSeconds: number): Promise<void> {\n const expiration = this.clock() - maxLifetimeSeconds * 1000\n const files = await readdir(this.path).catch(() => [] as string[])\n for (const file of files) {\n if (!VALID_ID.test(file)) continue\n const { mtimeMs } = await stat(join(this.path, file)).catch(() => ({ mtimeMs: Number.POSITIVE_INFINITY }))\n if (mtimeMs <= expiration) await rm(join(this.path, file), { force: true })\n }\n }\n}\n","import { AuthFactory, ExceptionHandler, HttpRequest, type Container, type DatabaseConnection, type Guard, type Row, type SessionHandler } from '@orieljs/contracts'\n\n/**\n * Laravel's DatabaseSessionHandler over the DatabaseManager contract: table `sessions` with `id`, `user_id`,\n * `ip_address`, `user_agent`, `payload` (base64) and `last_activity` (unix seconds). One instance per Store,\n * because `exists` is per-request state.\n */\nexport class DatabaseSessionHandler implements SessionHandler {\n #exists = false\n\n constructor(\n private readonly connection: () => DatabaseConnection,\n private readonly table: string,\n private readonly minutes: number,\n /** The current container, for the request (ip, user agent) and the logged-in user. */\n private readonly container: () => Container | undefined = () => undefined,\n private readonly clock: () => number = Date.now,\n ) {}\n\n async read(id: string): Promise<string> {\n const session = await this.#query().where('id', id).first()\n if (session === undefined) return ''\n this.#exists = true\n if (Number(session.last_activity) < this.#now() - this.minutes * 60) return ''\n return typeof session.payload === 'string' ? Buffer.from(session.payload, 'base64').toString('utf8') : ''\n }\n\n async write(id: string, data: string): Promise<void> {\n const payload = await this.#payload(data)\n if (this.#exists) {\n await this.#query().where('id', id).update(payload)\n return\n }\n try {\n await this.#query().insert({ id, ...payload })\n } catch {\n await this.#query().where('id', id).update(payload)\n }\n this.#exists = true\n }\n\n async destroy(id: string): Promise<void> {\n await this.#query().where('id', id).delete()\n }\n\n async gc(maxLifetimeSeconds: number): Promise<void> {\n await this.#query().where('last_activity', '<=', this.#now() - maxLifetimeSeconds).delete()\n }\n\n /** Called by Store.migrate(): the next write inserts a new row. */\n setExists(exists: boolean): void {\n this.#exists = exists\n }\n\n #query() {\n return this.connection().table<Row>(this.table)\n }\n\n #now(): number {\n return Math.floor(this.clock() / 1000)\n }\n\n async #payload(data: string): Promise<Row> {\n const payload: Row = { payload: Buffer.from(data, 'utf8').toString('base64'), last_activity: this.#now() }\n const container = this.container()\n if (container === undefined) return payload\n if (container.bound(HttpRequest)) {\n const request = container.make(HttpRequest)\n payload.ip_address = request.ip() ?? null\n payload.user_agent = (request.header('user-agent') ?? '').slice(0, 500)\n }\n if (container.bound(AuthFactory)) {\n // Only when the guard already holds a user, so writing a session never triggers a user query.\n const guard = await this.#guard(container)\n payload.user_id = guard?.hasUser() ? ((await guard.id()) ?? null) : null\n }\n return payload\n }\n\n /** The default guard, or undefined when it can't be built (the error is reported, not thrown). */\n async #guard(container: Container): Promise<Guard | undefined> {\n try {\n return container.make(AuthFactory).guard()\n } catch (error) {\n // A guard that can't be built must not take every web request down with it.\n try {\n if (container.bound(ExceptionHandler)) await container.make(ExceptionHandler).report(error)\n } catch {\n // A failing reporter must not bring the request down either.\n }\n return undefined\n }\n }\n}\n","import type { CookieJar, HttpRequest, SessionHandler } from '@orieljs/contracts'\n\n/**\n * Laravel's CookieSessionHandler: the whole session lives in a cookie named after the session id, queued on the\n * request's CookieJar (EncryptCookies encrypts it). The payload records its own expiry.\n */\nexport class CookieSessionHandler implements SessionHandler {\n constructor(\n private readonly jar: () => CookieJar,\n private readonly request: () => HttpRequest | undefined,\n private readonly minutes: number,\n private readonly expireOnClose = false,\n private readonly clock: () => number = Date.now,\n ) {}\n\n async read(id: string): Promise<string> {\n const value = this.request()?.cookie(id)\n if (value === undefined || value === '') return ''\n try {\n const decoded = JSON.parse(value) as { data?: unknown; expires?: unknown }\n return typeof decoded.data === 'string' && typeof decoded.expires === 'number' && decoded.expires >= this.#now()\n ? decoded.data\n : ''\n } catch {\n return ''\n }\n }\n\n async write(id: string, data: string): Promise<void> {\n const jar = this.jar()\n const value = JSON.stringify({ data, expires: this.#now() + this.minutes * 60 })\n jar.queue(jar.make(id, value, this.expireOnClose ? 0 : this.minutes))\n }\n\n async destroy(id: string): Promise<void> {\n const jar = this.jar()\n jar.queue(jar.forget(id))\n }\n\n async gc(): Promise<void> {}\n\n #now(): number {\n return Math.floor(this.clock() / 1000)\n }\n}\n","import type { SessionHandler } from '@orieljs/contracts'\n\n/** The part of an ioredis client the handler uses (an ioredis `Redis` satisfies it). */\nexport interface RedisSessionClient {\n get(key: string): Promise<string | null>\n set(key: string, value: string, mode: 'EX', seconds: number): Promise<unknown>\n del(key: string): Promise<number>\n}\n\n/** Sessions in Redis with a TTL of `minutes` (Laravel's redis driver, without going through the cache store). */\nexport class RedisSessionHandler implements SessionHandler {\n constructor(\n private readonly client: RedisSessionClient,\n private readonly minutes: number,\n private readonly prefix = 'oriel_session:',\n ) {}\n\n async read(id: string): Promise<string> {\n return (await this.client.get(this.prefix + id)) ?? ''\n }\n\n async write(id: string, data: string): Promise<void> {\n await this.client.set(this.prefix + id, data, 'EX', Math.max(1, this.minutes * 60))\n }\n\n async destroy(id: string): Promise<void> {\n await this.client.del(this.prefix + id)\n }\n\n /** Redis expires keys itself. */\n async gc(): Promise<void> {}\n}\n","import { Redis } from 'ioredis'\nimport {\n ConfigRepository,\n CookieJar,\n DatabaseManager,\n Encrypter,\n HttpRequest,\n type Container,\n type SessionHandler,\n} from '@orieljs/contracts'\nimport { ArraySessionHandler } from './handlers/ArraySessionHandler'\nimport { CookieSessionHandler } from './handlers/CookieSessionHandler'\nimport { DatabaseSessionHandler } from './handlers/DatabaseSessionHandler'\nimport { FileSessionHandler } from './handlers/FileSessionHandler'\nimport { RedisSessionHandler } from './handlers/RedisSessionHandler'\nimport { Store } from './Store'\n\n/** config/session.ts (Laravel 11's keys). */\nexport interface SessionConfig {\n driver?: string | null\n lifetime?: number\n expire_on_close?: boolean\n encrypt?: boolean\n files?: string\n connection?: string | null\n table?: string\n lottery?: [number, number]\n cookie?: string\n path?: string\n domain?: string | null\n secure?: boolean | null\n http_only?: boolean\n same_site?: 'lax' | 'strict' | 'none' | null\n}\n\n/** Builds a handler for a custom driver. Called once per Store (per request scope). */\nexport type SessionHandlerFactory = (container: Container, config: SessionConfig) => SessionHandler\n\n/** An entry of config('database.redis'). */\nexport interface RedisConnectionConfig {\n url?: string\n host?: string\n port?: number\n password?: string\n username?: string\n db?: number\n lazyConnect?: boolean\n}\n\n/** An ioredis client from a `database.redis.<name>` entry: its url, else host/port/password/db, else localhost. */\nexport function makeRedisClient(config: RedisConnectionConfig = {}): Redis {\n const options: Record<string, unknown> = {}\n for (const key of ['host', 'port', 'password', 'username', 'db', 'lazyConnect'] as const) if (config[key] !== undefined) options[key] = config[key]\n return typeof config.url === 'string' && config.url !== '' ? new Redis(config.url, options) : new Redis(options)\n}\n\n/**\n * Laravel's SessionManager. A root singleton: it keeps the handlers that may be shared between requests (array,\n * file, redis) and builds a new Store for each request scope (database and cookie handlers are per Store).\n */\nexport class SessionManager {\n readonly #custom = new Map<string, SessionHandlerFactory>()\n readonly #shared = new Map<string, SessionHandler>()\n #redis: Redis | undefined\n\n constructor(private readonly app: Container) {}\n\n getSessionConfig(): SessionConfig {\n return this.app.make(ConfigRepository).get<SessionConfig>('session', {})\n }\n\n getDefaultDriver(): string | undefined {\n return this.getSessionConfig().driver ?? undefined\n }\n\n /** Register a custom driver: Session.extend('mongo', (container, config) => new MongoHandler(...)). */\n extend(driver: string, factory: SessionHandlerFactory): this {\n this.#custom.set(driver, factory)\n return this\n }\n\n /** A new Store for `container` (the request or job scope). */\n build(container: Container, driver?: string): Store {\n const config = this.getSessionConfig()\n const handler = this.handler(driver ?? config.driver ?? 'array', container)\n const encrypter = config.encrypt === true ? container.make(Encrypter) : undefined\n return new Store(config.cookie ?? 'oriel_session', handler, undefined, encrypter)\n }\n\n handler(driver: string, container: Container): SessionHandler {\n const config = this.getSessionConfig()\n const lifetime = config.lifetime ?? 120\n const custom = this.#custom.get(driver)\n if (custom !== undefined) return custom(container, config)\n switch (driver) {\n case 'array':\n return this.#share('array', () => new ArraySessionHandler(lifetime))\n case 'file':\n return this.#share('file', () => new FileSessionHandler(config.files ?? 'storage/framework/sessions', lifetime))\n case 'redis':\n return this.#share('redis', () => new RedisSessionHandler(this.redis(), lifetime))\n case 'database':\n return new DatabaseSessionHandler(\n () => container.make(DatabaseManager).connection(config.connection ?? undefined),\n config.table ?? 'sessions',\n lifetime,\n () => container,\n )\n case 'cookie':\n return new CookieSessionHandler(\n () => container.make(CookieJar),\n () => (container.bound(HttpRequest) ? container.make(HttpRequest) : undefined),\n lifetime,\n config.expire_on_close === true,\n )\n default:\n throw new Error(`Driver [${driver}] not supported.`)\n }\n }\n\n /** The redis client for config('session.connection') (an entry of config('database.redis'), default 'default'). */\n redis(): Redis {\n if (this.#redis === undefined) {\n const name = this.getSessionConfig().connection ?? 'default'\n this.#redis = makeRedisClient(this.app.make(ConfigRepository).get<RedisConnectionConfig>(`database.redis.${name}`, {}))\n }\n return this.#redis\n }\n\n /** Closes the redis connection, if one was opened. */\n async disconnect(): Promise<void> {\n await this.#redis?.quit()\n this.#redis = undefined\n }\n\n #share(driver: string, make: () => SessionHandler): SessionHandler {\n let handler = this.#shared.get(driver)\n if (handler === undefined) {\n handler = make()\n this.#shared.set(driver, handler)\n }\n return handler\n }\n}\n","import type { OrielError } from '@orieljs/contracts'\n\n/** Laravel's TokenMismatchException: rendered as 419 by the exception handler. */\nexport class TokenMismatchError extends Error implements OrielError {\n readonly kind = 'TokenMismatch' as const\n readonly status = 419\n override readonly name = 'TokenMismatchError'\n constructor(message = 'CSRF token mismatch.') {\n super(message)\n }\n}\n","import { randomInt } from 'node:crypto'\nimport { ConfigRepository, Container, Session, type HttpRequest, type Middleware, type Next } from '@orieljs/contracts'\nimport { inject } from '@orieljs/container'\nimport type { SessionConfig } from '../SessionManager'\nimport type { Store } from '../Store'\nimport { attachCookie, sessionCookie } from './cookies'\n\n/**\n * Laravel's StartSession: loads the session named by the cookie, runs the request, remembers the previous URL,\n * sends the session cookie and saves the session. Http renders errors inside the pipeline, so the \"after\" part\n * always runs and flashed errors are saved.\n */\nexport class StartSession implements Middleware {\n readonly #container = inject(Container)\n readonly #config = inject(ConfigRepository)\n\n async handle(request: HttpRequest, next: Next): Promise<Response> {\n const config = this.#config.get<SessionConfig>('session', {})\n if (config.driver === undefined || config.driver === null) return next(request)\n\n const session = this.#container.make(Session) as Session & Partial<Pick<Store, 'setId' | 'getName' | 'getHandler'>>\n session.setId?.(request.cookie(session.getName?.() ?? config.cookie ?? 'oriel_session'))\n await session.start()\n await this.#collectGarbage(session, config)\n\n let response = await next(request)\n this.#storeCurrentUrl(request, session)\n response = attachCookie(\n response,\n sessionCookie(\n config,\n {\n name: (session as Partial<Pick<Store, 'getName'>>).getName?.() ?? config.cookie ?? 'oriel_session',\n value: session.getId(),\n httpOnly: config.http_only ?? true,\n },\n request,\n ),\n )\n await session.save()\n return response\n }\n\n /** Laravel's lottery: on average lottery[0] requests out of lottery[1] clean up expired sessions. */\n async #collectGarbage(session: Partial<Pick<Store, 'getHandler'>>, config: SessionConfig): Promise<void> {\n const [chances, outOf] = config.lottery ?? [2, 100]\n if (session.getHandler !== undefined && randomInt(1, outOf + 1) <= chances) {\n await session.getHandler().gc((config.lifetime ?? 120) * 60)\n }\n }\n\n #storeCurrentUrl(request: HttpRequest, session: Session): void {\n const prefetch = request.header('purpose') === 'prefetch' || request.header('sec-purpose') === 'prefetch'\n if (request.isMethod('GET') && !request.ajax() && !prefetch) session.setPreviousUrl(request.fullUrl())\n }\n}\n","import type { Cookie, HttpRequest } from '@orieljs/contracts'\nimport type { SessionConfig } from '../SessionManager'\n\n/** A minimal Set-Cookie serializer, Session never imports Cookie. */\nfunction serialize(cookie: Cookie): string {\n const parts = [`${cookie.name}=${encodeURIComponent(cookie.value)}`]\n if (cookie.minutes > 0) {\n parts.push(`Expires=${new Date(Date.now() + cookie.minutes * 60_000).toUTCString()}`, `Max-Age=${cookie.minutes * 60}`)\n }\n parts.push(`Path=${cookie.path}`)\n if (cookie.domain !== undefined && cookie.domain !== '') parts.push(`Domain=${cookie.domain}`)\n if (cookie.secure) parts.push('Secure')\n if (cookie.httpOnly) parts.push('HttpOnly')\n parts.push(`SameSite=${cookie.sameSite.charAt(0).toUpperCase()}${cookie.sameSite.slice(1)}`)\n return parts.join('; ')\n}\n\n/** Append the cookie's Set-Cookie straight onto the response (EncryptCookies encrypts response cookies). */\nexport function attachCookie(response: Response, cookie: Cookie): Response {\n const headers = new Headers(response.headers)\n headers.append('Set-Cookie', serialize(cookie))\n return new Response(response.body, { status: response.status, statusText: response.statusText, headers })\n}\n\n/**\n * Whether a cookie should be Secure. An explicit `true`/`false` always wins; when `secure` is null/undefined\n * (the default, ruling F6), it follows Symfony's `setSecureDefault`: Secure when the request itself is HTTPS.\n */\nfunction resolveSecure(secure: boolean | null | undefined, request: HttpRequest | undefined): boolean {\n return secure ?? (request !== undefined && request.url().startsWith('https:'))\n}\n\n/** Builds the session cookie (or XSRF-TOKEN) from session config, shared by StartSession and VerifyCsrfToken. */\nexport function sessionCookie(\n config: SessionConfig,\n options: { name: string; value: string; httpOnly: boolean },\n request?: HttpRequest,\n): Cookie {\n return {\n name: options.name,\n value: options.value,\n minutes: config.expire_on_close === true ? 0 : (config.lifetime ?? 120),\n path: config.path ?? '/',\n ...(config.domain ? { domain: config.domain } : {}),\n secure: resolveSecure(config.secure, request),\n httpOnly: options.httpOnly,\n sameSite: config.same_site ?? 'lax',\n }\n}\n","import {\n Application,\n ConfigRepository,\n Container,\n Encrypter,\n Session,\n type HttpRequest,\n type Middleware,\n type Next,\n} from '@orieljs/contracts'\nimport { inject } from '@orieljs/container'\nimport { Str } from '@orieljs/support'\nimport { equals } from '../equals'\nimport { TokenMismatchError } from '../errors'\nimport type { SessionConfig } from '../SessionManager'\nimport { attachCookie, sessionCookie } from './cookies'\n\n/**\n * Laravel's VerifyCsrfToken (ValidateCsrfToken). Reads pass; writes need the session token as `_token`,\n * `X-CSRF-TOKEN` or the encrypted `X-XSRF-TOKEN` header. Paths in `except` and config('http.csrf_except') skip the\n * check. Every passing response gets the `XSRF-TOKEN` cookie (readable by JavaScript).\n */\nexport class VerifyCsrfToken implements Middleware {\n /** URIs (wildcards allowed) excluded from the check, in addition to config('http.csrf_except'). */\n protected except: string[] = []\n\n /** Whether to send the XSRF-TOKEN cookie. */\n protected addHttpCookie = true\n\n readonly #container = inject(Container)\n readonly #config = inject(ConfigRepository)\n\n async handle(request: HttpRequest, next: Next): Promise<Response> {\n if (this.isReading(request) || this.runningUnitTests() || this.inExceptArray(request) || this.tokensMatch(request)) {\n const response = await next(request)\n return this.addHttpCookie ? this.addCookieToResponse(response, request) : response\n }\n throw new TokenMismatchError()\n }\n\n protected isReading(request: HttpRequest): boolean {\n return ['HEAD', 'GET', 'OPTIONS'].includes(request.method().toUpperCase())\n }\n\n protected runningUnitTests(): boolean {\n if (!this.#container.bound(Application)) return false\n const app = this.#container.make(Application)\n return app.runningInConsole() && app.runningUnitTests()\n }\n\n protected inExceptArray(request: HttpRequest): boolean {\n const configured = this.#config.get<unknown>('http.csrf_except', [])\n const patterns = [...this.except, ...(Array.isArray(configured) ? configured.map(String) : [])]\n return patterns.some((pattern) => {\n const trimmed = pattern === '/' ? pattern : pattern.replace(/^\\/+|\\/+$/g, '')\n return Str.is(trimmed, request.fullUrl()) || request.is(trimmed)\n })\n }\n\n protected tokensMatch(request: HttpRequest): boolean {\n const sessionToken = this.#container.make(Session).token()\n const token = this.getTokenFromRequest(request)\n return typeof sessionToken === 'string' && typeof token === 'string' && token !== '' && equals(sessionToken, token)\n }\n\n protected getTokenFromRequest(request: HttpRequest): string | undefined {\n const input = request.input<unknown>('_token')\n const token = (typeof input === 'string' && input !== '' ? input : undefined) ?? request.header('X-CSRF-TOKEN')\n if (token !== undefined && token !== '') return token\n const header = request.header('X-XSRF-TOKEN')\n if (header === undefined || header === '' || !this.#container.bound(Encrypter)) return undefined\n try {\n // The XSRF-TOKEN cookie was encrypted by EncryptCookies with its name prefix (40 hex chars + '|').\n return this.#container.make(Encrypter).decrypt<string>(header, false).slice(41)\n } catch {\n return undefined\n }\n }\n\n protected addCookieToResponse(response: Response, request: HttpRequest): Response {\n const token = this.#container.make(Session).token()\n // No token (e.g. invalidate() without regenerateToken()): skip rather than queue a literal \"undefined\" value.\n if (!token) return response\n const config = this.#config.get<SessionConfig>('session', {})\n return attachCookie(\n response,\n sessionCookie(config, { name: 'XSRF-TOKEN', value: token, httpOnly: false }, request),\n )\n }\n}\n","import { timingSafeEqual } from 'node:crypto'\n\n/** Constant-time string comparison (PHP's hash_equals). */\nexport function equals(known: string, user: string): boolean {\n const a = Buffer.from(known)\n const b = Buffer.from(user)\n return a.length === b.length && timingSafeEqual(a, b)\n}\n","import type { MessageBag } from '@orieljs/contracts'\n\n/**\n * A read-only MessageBag over one bag of the flashed validation errors. Http flashes\n * `errors: { [bag]: { field: string[] } }`; views read them with `errors().first('email')`.\n */\nexport class SessionMessageBag implements MessageBag {\n readonly #messages: Record<string, string[]>\n\n constructor(messages: Record<string, string[]> = {}) {\n this.#messages = messages\n }\n\n has(key: string): boolean {\n return this.get(key).length > 0\n }\n\n first(key?: string): string | undefined {\n return key === undefined ? this.all()[0] : this.get(key)[0]\n }\n\n get(key: string): string[] {\n const messages = Object.hasOwn(this.#messages, key) ? this.#messages[key] : undefined\n return Array.isArray(messages) ? messages.map(String) : []\n }\n\n all(): string[] {\n return Object.values(this.#messages).flatMap((messages) => (Array.isArray(messages) ? messages.map(String) : []))\n }\n\n isEmpty(): boolean {\n return this.count() === 0\n }\n\n count(): number {\n return this.all().length\n }\n\n toObject(): Record<string, string[]> {\n return Object.fromEntries(Object.keys(this.#messages).map((key) => [key, this.get(key)]))\n }\n}\n\n/** The bag named `bag` (default 'default') out of the session's flashed `errors` value. */\nexport function errorBagFrom(errors: unknown, bag = 'default'): SessionMessageBag {\n if (typeof errors !== 'object' || errors === null) return new SessionMessageBag()\n const messages = (errors as Record<string, unknown>)[bag]\n return new SessionMessageBag(typeof messages === 'object' && messages !== null ? (messages as Record<string, string[]>) : {})\n}\n","import { Application, Session } from '@orieljs/contracts'\nimport { currentContainer, inject } from '@orieljs/container'\nimport { facade } from '@orieljs/support'\nimport { SessionManager, type SessionHandlerFactory } from './SessionManager'\nimport { errorBagFrom, type SessionMessageBag } from './ViewErrorBag'\n\n/**\n * The current scope's session, or undefined where there is none: no container, no Session binding, or the\n * application itself (a console command, schedule:run, a mail view rendered outside a request). Session is scoped,\n * so resolving it on the application would throw.\n */\nfunction scopeSession(): Session | undefined {\n const container = currentContainer()\n if (container === undefined || !container.bound(Session)) return undefined\n if (container.bound(Application) && (container.make(Application) as unknown) === container) return undefined\n return container.make(Session)\n}\n\n/** The Session facade (the current request's session). `Session.extend()` registers a custom driver. */\nexport const SessionFacade = facade(Session, {\n extend: (driver: string, factory: SessionHandlerFactory): SessionManager => inject(SessionManager).extend(driver, factory),\n})\n\n/** session(): the store; session(key, default?): a value; session({ key: value }): put values. */\nexport function session(): Session\nexport function session(values: Record<string, unknown>): void\nexport function session<T = unknown>(key: string, defaultValue?: T): T\nexport function session(key?: string | Record<string, unknown>, defaultValue?: unknown): unknown {\n const store = inject(Session)\n if (key === undefined) return store\n if (typeof key === 'string') return store.get(key, defaultValue)\n store.put(key)\n return undefined\n}\n\n/** old(key?, default?): input flashed by the previous request (Laravel's old()). The default outside a request. */\nexport function old<T = unknown>(key?: string, defaultValue?: T): T {\n const store = scopeSession()\n return store === undefined ? (defaultValue as T) : store.getOldInput<T>(key, defaultValue)\n}\n\n/** csrfToken(): the session's CSRF token (Laravel's csrf_token()). */\nexport function csrfToken(): string {\n return inject(Session).token()\n}\n\n/**\n * errors(bag?): the validation errors flashed by the previous request, as a MessageBag. Empty outside a request,\n * so views rendered from a console command or a job (mail, TSX) can call it safely.\n */\nexport function errors(bag = 'default'): SessionMessageBag {\n return errorBagFrom(scopeSession()?.get('errors'), bag)\n}\n","import { Router, Session } from '@orieljs/contracts'\nimport { ServiceProvider } from '@orieljs/support'\nimport { StartSession } from './middleware/StartSession'\nimport { VerifyCsrfToken } from './middleware/VerifyCsrfToken'\nimport { SessionManager } from './SessionManager'\n\nexport class SessionServiceProvider extends ServiceProvider {\n override register(): void {\n // Laravel 11's config/session.php. The cookie name can't come from APP_NAME here (no env() in packages).\n this.mergeConfigFrom(\n {\n driver: 'database',\n lifetime: 120,\n expire_on_close: false,\n encrypt: false,\n files: this.app.storagePath('framework/sessions'),\n connection: null,\n table: 'sessions',\n lottery: [2, 100],\n cookie: 'oriel_session',\n path: '/',\n domain: null,\n secure: null,\n http_only: true,\n same_site: 'lax',\n },\n 'session',\n )\n this.app.singleton(SessionManager, (container) => new SessionManager(container))\n this.app.scoped(Session, (container) => container.make(SessionManager).build(container))\n }\n\n override boot(): void {\n if (!this.app.bound(Router)) return\n this.app.make(Router).pushMiddlewareToGroup('web', StartSession).pushMiddlewareToGroup('web', VerifyCsrfToken)\n }\n}\n"],"mappings":"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","names":["old","session","Str","session","HttpRequest","HttpRequest","ConfigRepository","ConfigRepository","session","ConfigRepository","Container","Encrypter","Session","inject","Str","inject","Container","ConfigRepository","Str","Session","Encrypter","errors","Application","Session","inject","Session","Application","inject","Session","Session"]}
1
+ {"version":3,"sources":["../Store.ts","../handlers/ArraySessionHandler.ts","../handlers/FileSessionHandler.ts","../handlers/DatabaseSessionHandler.ts","../handlers/CookieSessionHandler.ts","../handlers/RedisSessionHandler.ts","../SessionManager.ts","../errors.ts","../middleware/StartSession.ts","../middleware/cookies.ts","../middleware/VerifyCsrfToken.ts","../equals.ts","../ViewErrorBag.ts","../facade.ts","../SessionServiceProvider.ts"],"sourcesContent":["import type { Encrypter, Session, SessionHandler } from '@orieljs/contracts'\nimport { Arr, Str } from '@orieljs/support'\n\ntype Attributes = Record<string, unknown>\n\nconst unique = (values: string[]): string[] => [...new Set(values)]\n\n/**\n * Laravel's Illuminate\\Session\\Store (and EncryptedStore when an Encrypter is given).\n * Attributes use dot notation, so 'url.intended' is stored as { url: { intended } }.\n * The payload is JSON: Dates become strings and class instances become plain objects.\n */\nexport class Store implements Session {\n #id = ''\n #name: string\n #attributes: Attributes = {}\n #started = false\n readonly #handler: SessionHandler\n readonly #encrypter: Encrypter | undefined\n\n constructor(name: string, handler: SessionHandler, id?: string, encrypter?: Encrypter) {\n this.#name = name\n this.#handler = handler\n this.#encrypter = encrypter\n this.setId(id)\n }\n\n /** Loads the session from the handler and makes sure it has a CSRF token. */\n async start(): Promise<void> {\n this.#attributes = { ...this.#attributes, ...(await this.#readFromHandler()) }\n if (!this.has('_token')) this.regenerateToken()\n this.#started = true\n }\n\n /** Ages the flash data and writes the session through the handler. */\n async save(): Promise<void> {\n this.ageFlashData()\n const payload = JSON.stringify(this.#attributes)\n await this.#handler.write(this.getId(), this.#encrypter === undefined ? payload : this.#encrypter.encrypt(payload, false))\n this.#started = false\n }\n\n /** Forgets last request's flash data and marks this request's flash data as old. */\n ageFlashData(): void {\n this.forget(...this.get<string[]>('_flash.old', []))\n this.put('_flash.old', this.get<string[]>('_flash.new', []))\n this.put('_flash.new', [])\n }\n\n all(): Attributes {\n return { ...this.#attributes }\n }\n\n only(keys: string[]): Attributes {\n return Arr.only(this.#attributes, keys)\n }\n\n except(keys: string[]): Attributes {\n return Arr.except(this.#attributes, keys)\n }\n\n /** Whether the key is present, even with a null value. */\n exists(...keys: string[]): boolean {\n return keys.every((key) => Arr.has(this.#attributes, key))\n }\n\n missing(...keys: string[]): boolean {\n return !this.exists(...keys)\n }\n\n /** Whether the key is present and not null/undefined. */\n has(key: string): boolean {\n const value = this.get<unknown>(key)\n return value !== undefined && value !== null\n }\n\n get<T = unknown>(key: string, defaultValue?: T): T {\n return Arr.get(this.#attributes, key, defaultValue)\n }\n\n pull<T = unknown>(key: string, defaultValue?: T): T {\n const value = this.get(key, defaultValue)\n this.forget(key)\n return value\n }\n\n put(key: string | Attributes, value?: unknown): void {\n const values = typeof key === 'string' ? { [key]: value } : key\n for (const [name, item] of Object.entries(values)) Arr.set(this.#attributes, name, item)\n }\n\n push(key: string, value: unknown): void {\n const list = this.get<unknown>(key, [])\n this.put(key, [...(Array.isArray(list) ? list : [list]), value])\n }\n\n increment(key: string, amount = 1): number {\n const value = Number(this.get(key, 0)) + amount\n this.put(key, value)\n return value\n }\n\n decrement(key: string, amount = 1): number {\n return this.increment(key, -amount)\n }\n\n forget(...keys: string[]): void {\n for (const key of keys) Arr.forget(this.#attributes, key)\n }\n\n /** Removes a key and returns its value. */\n remove<T = unknown>(key: string): T {\n return this.pull<T>(key)\n }\n\n flush(): void {\n this.#attributes = {}\n }\n\n /** Available on this request and the next one. */\n flash(key: string, value: unknown = true): void {\n this.put(key, value)\n this.push('_flash.new', key)\n this.#removeFromOldFlashData([key])\n }\n\n /** Available on this request only. */\n now(key: string, value: unknown): void {\n this.put(key, value)\n this.push('_flash.old', key)\n }\n\n /** Keeps all of last request's flash data for one more request. */\n reflash(): void {\n this.#mergeNewFlashes(this.get<string[]>('_flash.old', []))\n this.put('_flash.old', [])\n }\n\n /** Keeps some of last request's flash data for one more request. */\n keep(...keys: string[]): void {\n this.#mergeNewFlashes(keys)\n this.#removeFromOldFlashData(keys)\n }\n\n flashInput(input: Attributes): void {\n this.flash('_old_input', input)\n }\n\n hasOldInput(key?: string): boolean {\n const old = this.getOldInput<unknown>(key)\n return key === undefined ? typeof old === 'object' && old !== null && Object.keys(old).length > 0 : old !== undefined && old !== null\n }\n\n getOldInput<T = unknown>(key?: string, defaultValue?: T): T {\n return Arr.get(this.get<Attributes>('_old_input', {}), key, defaultValue)\n }\n\n token(): string {\n return this.get<string>('_token')\n }\n\n regenerateToken(): void {\n this.put('_token', Str.random(40))\n }\n\n /** New session id and CSRF token. With destroy, the old record is deleted. */\n async regenerate(destroy = false): Promise<void> {\n await this.migrate(destroy)\n this.regenerateToken()\n }\n\n /** New session id, keeping the data (and the CSRF token). With destroy, the old record is deleted. */\n async migrate(destroy = false): Promise<void> {\n if (destroy) await this.#handler.destroy(this.getId())\n ;(this.#handler as { setExists?(exists: boolean): void }).setExists?.(false)\n this.setId(this.#generateSessionId())\n }\n\n /** Flushes the data and migrates to a new id, destroying the old record. */\n async invalidate(): Promise<void> {\n this.flush()\n await this.migrate(true)\n }\n\n previousUrl(): string | undefined {\n return this.get<string | undefined>('_previous.url')\n }\n\n setPreviousUrl(url: string): void {\n this.put('_previous.url', url)\n }\n\n isStarted(): boolean {\n return this.#started\n }\n\n getName(): string {\n return this.#name\n }\n\n setName(name: string): void {\n this.#name = name\n }\n\n getId(): string {\n return this.#id\n }\n\n /** Invalid ids (anything but 40 alphanumerics) are replaced by a fresh one, so ids from cookies can't be forged. */\n setId(id: string | undefined | null): void {\n this.#id = this.isValidId(id) ? id : this.#generateSessionId()\n }\n\n isValidId(id: unknown): id is string {\n return typeof id === 'string' && /^[a-zA-Z0-9]{40}$/.test(id)\n }\n\n getHandler(): SessionHandler {\n return this.#handler\n }\n\n #generateSessionId(): string {\n return Str.random(40)\n }\n\n async #readFromHandler(): Promise<Attributes> {\n let data = await this.#handler.read(this.getId())\n if (data === '') return {}\n if (this.#encrypter !== undefined) {\n try {\n data = this.#encrypter.decrypt<string>(data, false)\n } catch {\n return {}\n }\n }\n try {\n const parsed: unknown = JSON.parse(data)\n return typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed) ? (parsed as Attributes) : {}\n } catch {\n return {}\n }\n }\n\n #mergeNewFlashes(keys: string[]): void {\n this.put('_flash.new', unique([...this.get<string[]>('_flash.new', []), ...keys]))\n }\n\n #removeFromOldFlashData(keys: string[]): void {\n this.put('_flash.old', this.get<string[]>('_flash.old', []).filter((key) => !keys.includes(key)))\n }\n}\n","import type { SessionHandler } from '@orieljs/contracts'\n\n/** Laravel's ArraySessionHandler: in-memory sessions (tests, `SESSION_DRIVER=array`). */\nexport class ArraySessionHandler implements SessionHandler {\n readonly #storage = new Map<string, { data: string; time: number }>()\n\n constructor(\n private readonly minutes: number,\n private readonly clock: () => number = Date.now,\n ) {}\n\n async read(id: string): Promise<string> {\n const session = this.#storage.get(id)\n if (session === undefined) return ''\n return session.time >= this.clock() - this.minutes * 60_000 ? session.data : ''\n }\n\n async write(id: string, data: string): Promise<void> {\n this.#storage.set(id, { data, time: this.clock() })\n }\n\n async destroy(id: string): Promise<void> {\n this.#storage.delete(id)\n }\n\n async gc(maxLifetimeSeconds: number): Promise<void> {\n const expiration = this.clock() - maxLifetimeSeconds * 1000\n for (const [id, session] of this.#storage) if (session.time <= expiration) this.#storage.delete(id)\n }\n\n /** The raw stored payload (for tests and debugging). */\n raw(id: string): string | undefined {\n return this.#storage.get(id)?.data\n }\n}\n","import { mkdir, readdir, readFile, rename, rm, stat, writeFile } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport type { SessionHandler } from '@orieljs/contracts'\nimport { Str } from '@orieljs/support'\n\nconst VALID_ID = /^[a-zA-Z0-9]{40}$/\n\n/**\n * Laravel's FileSessionHandler: one file per session in `path` (storage/framework/sessions).\n * Only 40-character alphanumeric ids are ever turned into a path, so an id can't escape the directory.\n */\nexport class FileSessionHandler implements SessionHandler {\n constructor(\n private readonly path: string,\n private readonly minutes: number,\n private readonly clock: () => number = Date.now,\n ) {}\n\n async read(id: string): Promise<string> {\n if (!VALID_ID.test(id)) return ''\n const file = join(this.path, id)\n try {\n const { mtimeMs } = await stat(file)\n if (mtimeMs < this.clock() - this.minutes * 60_000) return ''\n return await readFile(file, 'utf8')\n } catch {\n return ''\n }\n }\n\n async write(id: string, data: string): Promise<void> {\n if (!VALID_ID.test(id)) return\n await mkdir(this.path, { recursive: true })\n // Write then rename, so a concurrent read never sees a half-written file.\n const temporary = join(this.path, `.${id}.${Str.random(8)}.tmp`)\n await writeFile(temporary, data, 'utf8')\n await rename(temporary, join(this.path, id))\n }\n\n async destroy(id: string): Promise<void> {\n if (VALID_ID.test(id)) await rm(join(this.path, id), { force: true })\n }\n\n async gc(maxLifetimeSeconds: number): Promise<void> {\n const expiration = this.clock() - maxLifetimeSeconds * 1000\n const files = await readdir(this.path).catch(() => [] as string[])\n for (const file of files) {\n if (!VALID_ID.test(file)) continue\n const { mtimeMs } = await stat(join(this.path, file)).catch(() => ({ mtimeMs: Number.POSITIVE_INFINITY }))\n if (mtimeMs <= expiration) await rm(join(this.path, file), { force: true })\n }\n }\n}\n","import { AuthFactory, ExceptionHandler, HttpRequest, type Container, type DatabaseConnection, type Guard, type Row, type SessionHandler } from '@orieljs/contracts'\n\n/**\n * Laravel's DatabaseSessionHandler over the DatabaseManager contract: table `sessions` with `id`, `user_id`,\n * `ip_address`, `user_agent`, `payload` (base64) and `last_activity` (unix seconds). One instance per Store,\n * because `exists` is per-request state.\n */\nexport class DatabaseSessionHandler implements SessionHandler {\n #exists = false\n\n constructor(\n private readonly connection: () => DatabaseConnection,\n private readonly table: string,\n private readonly minutes: number,\n /** The current container, for the request (ip, user agent) and the logged-in user. */\n private readonly container: () => Container | undefined = () => undefined,\n private readonly clock: () => number = Date.now,\n ) {}\n\n async read(id: string): Promise<string> {\n const session = await this.#query().where('id', id).first()\n if (session === undefined) return ''\n this.#exists = true\n if (Number(session.last_activity) < this.#now() - this.minutes * 60) return ''\n return typeof session.payload === 'string' ? Buffer.from(session.payload, 'base64').toString('utf8') : ''\n }\n\n async write(id: string, data: string): Promise<void> {\n const payload = await this.#payload(data)\n if (this.#exists) {\n await this.#query().where('id', id).update(payload)\n return\n }\n try {\n await this.#query().insert({ id, ...payload })\n } catch {\n await this.#query().where('id', id).update(payload)\n }\n this.#exists = true\n }\n\n async destroy(id: string): Promise<void> {\n await this.#query().where('id', id).delete()\n }\n\n async gc(maxLifetimeSeconds: number): Promise<void> {\n await this.#query().where('last_activity', '<=', this.#now() - maxLifetimeSeconds).delete()\n }\n\n /** Called by Store.migrate(): the next write inserts a new row. */\n setExists(exists: boolean): void {\n this.#exists = exists\n }\n\n #query() {\n return this.connection().table<Row>(this.table)\n }\n\n #now(): number {\n return Math.floor(this.clock() / 1000)\n }\n\n async #payload(data: string): Promise<Row> {\n const payload: Row = { payload: Buffer.from(data, 'utf8').toString('base64'), last_activity: this.#now() }\n const container = this.container()\n if (container === undefined) return payload\n if (container.bound(HttpRequest)) {\n const request = container.make(HttpRequest)\n payload.ip_address = request.ip() ?? null\n payload.user_agent = (request.header('user-agent') ?? '').slice(0, 500)\n }\n if (container.bound(AuthFactory)) {\n // Only when the guard already holds a user, so writing a session never triggers a user query.\n const guard = await this.#guard(container)\n payload.user_id = guard?.hasUser() ? ((await guard.id()) ?? null) : null\n }\n return payload\n }\n\n /** The default guard, or undefined when it can't be built (the error is reported, not thrown). */\n async #guard(container: Container): Promise<Guard | undefined> {\n try {\n return container.make(AuthFactory).guard()\n } catch (error) {\n // A guard that can't be built must not take every web request down with it.\n try {\n if (container.bound(ExceptionHandler)) await container.make(ExceptionHandler).report(error)\n } catch {\n // A failing reporter must not bring the request down either.\n }\n return undefined\n }\n }\n}\n","import type { CookieJar, HttpRequest, SessionHandler } from '@orieljs/contracts'\n\n/**\n * Laravel's CookieSessionHandler: the whole session lives in a cookie named after the session id, queued on the\n * request's CookieJar (EncryptCookies encrypts it). The payload records its own expiry.\n */\nexport class CookieSessionHandler implements SessionHandler {\n constructor(\n private readonly jar: () => CookieJar,\n private readonly request: () => HttpRequest | undefined,\n private readonly minutes: number,\n private readonly expireOnClose = false,\n private readonly clock: () => number = Date.now,\n ) {}\n\n async read(id: string): Promise<string> {\n const value = this.request()?.cookie(id)\n if (value === undefined || value === '') return ''\n try {\n const decoded = JSON.parse(value) as { data?: unknown; expires?: unknown }\n return typeof decoded.data === 'string' && typeof decoded.expires === 'number' && decoded.expires >= this.#now()\n ? decoded.data\n : ''\n } catch {\n return ''\n }\n }\n\n async write(id: string, data: string): Promise<void> {\n const jar = this.jar()\n const value = JSON.stringify({ data, expires: this.#now() + this.minutes * 60 })\n jar.queue(jar.make(id, value, this.expireOnClose ? 0 : this.minutes))\n }\n\n async destroy(id: string): Promise<void> {\n const jar = this.jar()\n jar.queue(jar.forget(id))\n }\n\n async gc(): Promise<void> {}\n\n #now(): number {\n return Math.floor(this.clock() / 1000)\n }\n}\n","import type { SessionHandler } from '@orieljs/contracts'\n\n/** The part of an ioredis client the handler uses (an ioredis `Redis` satisfies it). */\nexport interface RedisSessionClient {\n get(key: string): Promise<string | null>\n set(key: string, value: string, mode: 'EX', seconds: number): Promise<unknown>\n del(key: string): Promise<number>\n}\n\n/** Sessions in Redis with a TTL of `minutes` (Laravel's redis driver, without going through the cache store). */\nexport class RedisSessionHandler implements SessionHandler {\n constructor(\n private readonly client: RedisSessionClient,\n private readonly minutes: number,\n private readonly prefix = 'oriel_session:',\n ) {}\n\n async read(id: string): Promise<string> {\n return (await this.client.get(this.prefix + id)) ?? ''\n }\n\n async write(id: string, data: string): Promise<void> {\n await this.client.set(this.prefix + id, data, 'EX', Math.max(1, this.minutes * 60))\n }\n\n async destroy(id: string): Promise<void> {\n await this.client.del(this.prefix + id)\n }\n\n /** Redis expires keys itself. */\n async gc(): Promise<void> {}\n}\n","import { Redis } from 'ioredis'\nimport {\n ConfigRepository,\n CookieJar,\n DatabaseManager,\n Encrypter,\n HttpRequest,\n type Container,\n type SessionHandler,\n} from '@orieljs/contracts'\nimport { ArraySessionHandler } from './handlers/ArraySessionHandler'\nimport { CookieSessionHandler } from './handlers/CookieSessionHandler'\nimport { DatabaseSessionHandler } from './handlers/DatabaseSessionHandler'\nimport { FileSessionHandler } from './handlers/FileSessionHandler'\nimport { RedisSessionHandler } from './handlers/RedisSessionHandler'\nimport { Store } from './Store'\n\n/** config/session.ts (Laravel 11's keys). */\nexport interface SessionConfig {\n driver?: string | null\n lifetime?: number\n expire_on_close?: boolean\n encrypt?: boolean\n files?: string\n connection?: string | null\n table?: string\n lottery?: [number, number]\n cookie?: string\n path?: string\n domain?: string | null\n secure?: boolean | null\n http_only?: boolean\n same_site?: 'lax' | 'strict' | 'none' | null\n}\n\n/** Builds a handler for a custom driver. Called once per Store (per request scope). */\nexport type SessionHandlerFactory = (container: Container, config: SessionConfig) => SessionHandler\n\n/** An entry of config('database.redis'). */\nexport interface RedisConnectionConfig {\n url?: string\n host?: string\n port?: number\n password?: string\n username?: string\n db?: number\n lazyConnect?: boolean\n}\n\n/** An ioredis client from a `database.redis.<name>` entry: its url, else host/port/password/db, else localhost. */\nexport function makeRedisClient(config: RedisConnectionConfig = {}): Redis {\n const options: Record<string, unknown> = {}\n for (const key of ['host', 'port', 'password', 'username', 'db', 'lazyConnect'] as const) if (config[key] !== undefined) options[key] = config[key]\n return typeof config.url === 'string' && config.url !== '' ? new Redis(config.url, options) : new Redis(options)\n}\n\n/**\n * Laravel's SessionManager. A root singleton: it keeps the handlers that may be shared between requests (array,\n * file, redis) and builds a new Store for each request scope (database and cookie handlers are per Store).\n */\nexport class SessionManager {\n readonly #custom = new Map<string, SessionHandlerFactory>()\n readonly #shared = new Map<string, SessionHandler>()\n #redis: Redis | undefined\n\n constructor(private readonly app: Container) {}\n\n getSessionConfig(): SessionConfig {\n return this.app.make(ConfigRepository).get<SessionConfig>('session', {})\n }\n\n getDefaultDriver(): string | undefined {\n return this.getSessionConfig().driver ?? undefined\n }\n\n /** Register a custom driver: Session.extend('mongo', (container, config) => new MongoHandler(...)). */\n extend(driver: string, factory: SessionHandlerFactory): this {\n this.#custom.set(driver, factory)\n return this\n }\n\n /** A new Store for `container` (the request or job scope). */\n build(container: Container, driver?: string): Store {\n const config = this.getSessionConfig()\n const handler = this.handler(driver ?? config.driver ?? 'array', container)\n const encrypter = config.encrypt === true ? container.make(Encrypter) : undefined\n return new Store(config.cookie ?? 'oriel_session', handler, undefined, encrypter)\n }\n\n handler(driver: string, container: Container): SessionHandler {\n const config = this.getSessionConfig()\n const lifetime = config.lifetime ?? 120\n const custom = this.#custom.get(driver)\n if (custom !== undefined) return custom(container, config)\n switch (driver) {\n case 'array':\n return this.#share('array', () => new ArraySessionHandler(lifetime))\n case 'file':\n return this.#share('file', () => new FileSessionHandler(config.files ?? 'storage/framework/sessions', lifetime))\n case 'redis':\n return this.#share('redis', () => new RedisSessionHandler(this.redis(), lifetime))\n case 'database':\n return new DatabaseSessionHandler(\n () => container.make(DatabaseManager).connection(config.connection ?? undefined),\n config.table ?? 'sessions',\n lifetime,\n () => container,\n )\n case 'cookie':\n return new CookieSessionHandler(\n () => container.make(CookieJar),\n () => (container.bound(HttpRequest) ? container.make(HttpRequest) : undefined),\n lifetime,\n config.expire_on_close === true,\n )\n default:\n throw new Error(`Driver [${driver}] not supported.`)\n }\n }\n\n /** The redis client for config('session.connection') (an entry of config('database.redis'), default 'default'). */\n redis(): Redis {\n if (this.#redis === undefined) {\n const name = this.getSessionConfig().connection ?? 'default'\n this.#redis = makeRedisClient(this.app.make(ConfigRepository).get<RedisConnectionConfig>(`database.redis.${name}`, {}))\n }\n return this.#redis\n }\n\n /** Closes the redis connection, if one was opened. */\n async disconnect(): Promise<void> {\n await this.#redis?.quit()\n this.#redis = undefined\n }\n\n #share(driver: string, make: () => SessionHandler): SessionHandler {\n let handler = this.#shared.get(driver)\n if (handler === undefined) {\n handler = make()\n this.#shared.set(driver, handler)\n }\n return handler\n }\n}\n","import type { OrielError } from '@orieljs/contracts'\n\n/** Laravel's TokenMismatchException: rendered as 419 by the exception handler. */\nexport class TokenMismatchError extends Error implements OrielError {\n readonly kind = 'TokenMismatch' as const\n readonly status = 419\n override readonly name = 'TokenMismatchError'\n constructor(message = 'CSRF token mismatch.') {\n super(message)\n }\n}\n","import { randomInt } from 'node:crypto'\nimport { ConfigRepository, Container, Session, type HttpRequest, type Middleware, type Next } from '@orieljs/contracts'\nimport { inject } from '@orieljs/container'\nimport type { SessionConfig } from '../SessionManager'\nimport type { Store } from '../Store'\nimport { attachCookie, sessionCookie } from './cookies'\n\n/**\n * Laravel's StartSession: loads the session named by the cookie, runs the request, remembers the previous URL,\n * sends the session cookie and saves the session. Http renders errors inside the pipeline, so the \"after\" part\n * always runs and flashed errors are saved.\n */\nexport class StartSession implements Middleware {\n readonly #container = inject(Container)\n readonly #config = inject(ConfigRepository)\n\n async handle(request: HttpRequest, next: Next): Promise<Response> {\n const config = this.#config.get<SessionConfig>('session', {})\n if (config.driver === undefined || config.driver === null) return next(request)\n\n const session = this.#container.make(Session) as Session & Partial<Pick<Store, 'setId' | 'getName' | 'getHandler'>>\n session.setId?.(request.cookie(session.getName?.() ?? config.cookie ?? 'oriel_session'))\n await session.start()\n await this.#collectGarbage(session, config)\n\n let response = await next(request)\n this.#storeCurrentUrl(request, session)\n response = attachCookie(\n response,\n sessionCookie(\n config,\n {\n name: (session as Partial<Pick<Store, 'getName'>>).getName?.() ?? config.cookie ?? 'oriel_session',\n value: session.getId(),\n httpOnly: config.http_only ?? true,\n },\n request,\n ),\n )\n await session.save()\n return response\n }\n\n /** Laravel's lottery: on average lottery[0] requests out of lottery[1] clean up expired sessions. */\n async #collectGarbage(session: Partial<Pick<Store, 'getHandler'>>, config: SessionConfig): Promise<void> {\n const [chances, outOf] = config.lottery ?? [2, 100]\n if (session.getHandler !== undefined && randomInt(1, outOf + 1) <= chances) {\n await session.getHandler().gc((config.lifetime ?? 120) * 60)\n }\n }\n\n #storeCurrentUrl(request: HttpRequest, session: Session): void {\n const prefetch = request.header('purpose') === 'prefetch' || request.header('sec-purpose') === 'prefetch'\n if (request.isMethod('GET') && !request.ajax() && !prefetch) session.setPreviousUrl(request.fullUrl())\n }\n}\n","import type { Cookie, HttpRequest } from '@orieljs/contracts'\nimport type { SessionConfig } from '../SessionManager'\n\n/** A minimal Set-Cookie serializer, Session never imports Cookie. */\nfunction serialize(cookie: Cookie): string {\n const parts = [`${cookie.name}=${encodeURIComponent(cookie.value)}`]\n if (cookie.minutes > 0) {\n parts.push(`Expires=${new Date(Date.now() + cookie.minutes * 60_000).toUTCString()}`, `Max-Age=${cookie.minutes * 60}`)\n }\n parts.push(`Path=${cookie.path}`)\n if (cookie.domain !== undefined && cookie.domain !== '') parts.push(`Domain=${cookie.domain}`)\n if (cookie.secure) parts.push('Secure')\n if (cookie.httpOnly) parts.push('HttpOnly')\n parts.push(`SameSite=${cookie.sameSite.charAt(0).toUpperCase()}${cookie.sameSite.slice(1)}`)\n return parts.join('; ')\n}\n\n/** Append the cookie's Set-Cookie straight onto the response (EncryptCookies encrypts response cookies). */\nexport function attachCookie(response: Response, cookie: Cookie): Response {\n const headers = new Headers(response.headers)\n headers.append('Set-Cookie', serialize(cookie))\n return new Response(response.body, { status: response.status, statusText: response.statusText, headers })\n}\n\n/**\n * Whether a cookie should be Secure. An explicit `true`/`false` always wins; when `secure` is null/undefined\n * (the default, ruling F6), it follows Symfony's `setSecureDefault`: Secure when the request itself is HTTPS.\n */\nfunction resolveSecure(secure: boolean | null | undefined, request: HttpRequest | undefined): boolean {\n return secure ?? (request !== undefined && request.url().startsWith('https:'))\n}\n\n/** Builds the session cookie (or XSRF-TOKEN) from session config, shared by StartSession and VerifyCsrfToken. */\nexport function sessionCookie(\n config: SessionConfig,\n options: { name: string; value: string; httpOnly: boolean },\n request?: HttpRequest,\n): Cookie {\n return {\n name: options.name,\n value: options.value,\n minutes: config.expire_on_close === true ? 0 : (config.lifetime ?? 120),\n path: config.path ?? '/',\n ...(config.domain ? { domain: config.domain } : {}),\n secure: resolveSecure(config.secure, request),\n httpOnly: options.httpOnly,\n sameSite: config.same_site ?? 'lax',\n }\n}\n","import {\n Application,\n ConfigRepository,\n Container,\n Encrypter,\n Session,\n type HttpRequest,\n type Middleware,\n type Next,\n} from '@orieljs/contracts'\nimport { inject } from '@orieljs/container'\nimport { Str } from '@orieljs/support'\nimport { equals } from '../equals'\nimport { TokenMismatchError } from '../errors'\nimport type { SessionConfig } from '../SessionManager'\nimport { attachCookie, sessionCookie } from './cookies'\n\n/**\n * Laravel's VerifyCsrfToken (ValidateCsrfToken). Reads pass; writes need the session token as `_token`,\n * `X-CSRF-TOKEN` or the encrypted `X-XSRF-TOKEN` header. Paths in `except` and config('http.csrf_except') skip the\n * check. Every passing response gets the `XSRF-TOKEN` cookie (readable by JavaScript).\n */\nexport class VerifyCsrfToken implements Middleware {\n /** URIs (wildcards allowed) excluded from the check, in addition to config('http.csrf_except'). */\n protected except: string[] = []\n\n /** Whether to send the XSRF-TOKEN cookie. */\n protected addHttpCookie = true\n\n readonly #container = inject(Container)\n readonly #config = inject(ConfigRepository)\n\n async handle(request: HttpRequest, next: Next): Promise<Response> {\n if (this.isReading(request) || this.runningUnitTests() || this.inExceptArray(request) || this.tokensMatch(request)) {\n const response = await next(request)\n return this.addHttpCookie ? this.addCookieToResponse(response, request) : response\n }\n throw new TokenMismatchError()\n }\n\n protected isReading(request: HttpRequest): boolean {\n return ['HEAD', 'GET', 'OPTIONS'].includes(request.method().toUpperCase())\n }\n\n protected runningUnitTests(): boolean {\n if (!this.#container.bound(Application)) return false\n const app = this.#container.make(Application)\n return app.runningInConsole() && app.runningUnitTests()\n }\n\n protected inExceptArray(request: HttpRequest): boolean {\n const configured = this.#config.get<unknown>('http.csrf_except', [])\n const patterns = [...this.except, ...(Array.isArray(configured) ? configured.map(String) : [])]\n return patterns.some((pattern) => {\n const trimmed = pattern === '/' ? pattern : pattern.replace(/^\\/+|\\/+$/g, '')\n return Str.is(trimmed, request.fullUrl()) || request.is(trimmed)\n })\n }\n\n protected tokensMatch(request: HttpRequest): boolean {\n const sessionToken = this.#container.make(Session).token()\n const token = this.getTokenFromRequest(request)\n return typeof sessionToken === 'string' && typeof token === 'string' && token !== '' && equals(sessionToken, token)\n }\n\n protected getTokenFromRequest(request: HttpRequest): string | undefined {\n const input = request.input<unknown>('_token')\n const token = (typeof input === 'string' && input !== '' ? input : undefined) ?? request.header('X-CSRF-TOKEN')\n if (token !== undefined && token !== '') return token\n const header = request.header('X-XSRF-TOKEN')\n if (header === undefined || header === '' || !this.#container.bound(Encrypter)) return undefined\n try {\n // The XSRF-TOKEN cookie was encrypted by EncryptCookies with its name prefix (40 hex chars + '|').\n return this.#container.make(Encrypter).decrypt<string>(header, false).slice(41)\n } catch {\n return undefined\n }\n }\n\n protected addCookieToResponse(response: Response, request: HttpRequest): Response {\n const token = this.#container.make(Session).token()\n // No token (e.g. invalidate() without regenerateToken()): skip rather than queue a literal \"undefined\" value.\n if (!token) return response\n const config = this.#config.get<SessionConfig>('session', {})\n return attachCookie(\n response,\n sessionCookie(config, { name: 'XSRF-TOKEN', value: token, httpOnly: false }, request),\n )\n }\n}\n","import { timingSafeEqual } from 'node:crypto'\n\n/** Constant-time string comparison (PHP's hash_equals). */\nexport function equals(known: string, user: string): boolean {\n const a = Buffer.from(known)\n const b = Buffer.from(user)\n return a.length === b.length && timingSafeEqual(a, b)\n}\n","import type { MessageBag } from '@orieljs/contracts'\n\n/**\n * A MessageBag over one bag of the flashed validation errors (add() changes this bag, not the session). Http flashes\n * `errors: { [bag]: { field: string[] } }`; views read them with `errors().first('email')`.\n */\nexport class SessionMessageBag implements MessageBag {\n readonly #messages: Record<string, string[]>\n\n constructor(messages: Record<string, string[]> = {}) {\n this.#messages = { ...messages }\n }\n\n add(key: string, message: string): void {\n this.#messages[key] = [...this.get(key), message]\n }\n\n has(key: string): boolean {\n return this.get(key).length > 0\n }\n\n first(key?: string): string | undefined {\n return key === undefined ? this.all()[0] : this.get(key)[0]\n }\n\n get(key: string): string[] {\n const messages = Object.hasOwn(this.#messages, key) ? this.#messages[key] : undefined\n return Array.isArray(messages) ? messages.map(String) : []\n }\n\n all(): string[] {\n return Object.values(this.#messages).flatMap((messages) => (Array.isArray(messages) ? messages.map(String) : []))\n }\n\n isEmpty(): boolean {\n return this.count() === 0\n }\n\n count(): number {\n return this.all().length\n }\n\n toObject(): Record<string, string[]> {\n return Object.fromEntries(Object.keys(this.#messages).map((key) => [key, this.get(key)]))\n }\n}\n\n/** The bag named `bag` (default 'default') out of the session's flashed `errors` value. */\nexport function errorBagFrom(errors: unknown, bag = 'default'): SessionMessageBag {\n if (typeof errors !== 'object' || errors === null) return new SessionMessageBag()\n const messages = (errors as Record<string, unknown>)[bag]\n return new SessionMessageBag(typeof messages === 'object' && messages !== null ? (messages as Record<string, string[]>) : {})\n}\n","import { Application, Session } from '@orieljs/contracts'\nimport { currentContainer, inject } from '@orieljs/container'\nimport { facade } from '@orieljs/support'\nimport { SessionManager, type SessionHandlerFactory } from './SessionManager'\nimport { errorBagFrom, type SessionMessageBag } from './ViewErrorBag'\n\n/**\n * The current scope's session, or undefined where there is none: no container, no Session binding, or the\n * application itself (a console command, schedule:run, a mail view rendered outside a request). Session is scoped,\n * so resolving it on the application would throw.\n */\nfunction scopeSession(): Session | undefined {\n const container = currentContainer()\n if (container === undefined || !container.bound(Session)) return undefined\n if (container.bound(Application) && (container.make(Application) as unknown) === container) return undefined\n return container.make(Session)\n}\n\n/** The Session facade (the current request's session). `Session.extend()` registers a custom driver. */\nexport const SessionFacade = facade(Session, {\n extend: (driver: string, factory: SessionHandlerFactory): SessionManager => inject(SessionManager).extend(driver, factory),\n})\n\n/** session(): the store; session(key, default?): a value; session({ key: value }): put values. */\nexport function session(): Session\nexport function session(values: Record<string, unknown>): void\nexport function session<T = unknown>(key: string, defaultValue?: T): T\nexport function session(key?: string | Record<string, unknown>, defaultValue?: unknown): unknown {\n const store = inject(Session)\n if (key === undefined) return store\n if (typeof key === 'string') return store.get(key, defaultValue)\n store.put(key)\n return undefined\n}\n\n/** old(key?, default?): input flashed by the previous request (Laravel's old()). The default outside a request. */\nexport function old<T = unknown>(key?: string, defaultValue?: T): T {\n const store = scopeSession()\n return store === undefined ? (defaultValue as T) : store.getOldInput<T>(key, defaultValue)\n}\n\n/** csrfToken(): the session's CSRF token (Laravel's csrf_token()). */\nexport function csrfToken(): string {\n return inject(Session).token()\n}\n\n/**\n * errors(bag?): the validation errors flashed by the previous request, as a MessageBag. Empty outside a request,\n * so views rendered from a console command or a job (mail, TSX) can call it safely.\n */\nexport function errors(bag = 'default'): SessionMessageBag {\n return errorBagFrom(scopeSession()?.get('errors'), bag)\n}\n","import { Router, Session } from '@orieljs/contracts'\nimport { ServiceProvider } from '@orieljs/support'\nimport { StartSession } from './middleware/StartSession'\nimport { VerifyCsrfToken } from './middleware/VerifyCsrfToken'\nimport { SessionManager } from './SessionManager'\n\nexport class SessionServiceProvider extends ServiceProvider {\n override register(): void {\n // Laravel 11's config/session.php. The cookie name can't come from APP_NAME here (no env() in packages).\n this.mergeConfigFrom(\n {\n driver: 'database',\n lifetime: 120,\n expire_on_close: false,\n encrypt: false,\n files: this.app.storagePath('framework/sessions'),\n connection: null,\n table: 'sessions',\n lottery: [2, 100],\n cookie: 'oriel_session',\n path: '/',\n domain: null,\n secure: null,\n http_only: true,\n same_site: 'lax',\n },\n 'session',\n )\n this.app.singleton(SessionManager, (container) => new SessionManager(container))\n // At the end of the process: close the redis connection, if the manager opened one.\n this.app.onShutdown(async () => {\n if (this.app.resolved(SessionManager)) await this.app.make(SessionManager).disconnect()\n })\n this.app.scoped(Session, (container) => container.make(SessionManager).build(container))\n }\n\n override boot(): void {\n if (!this.app.bound(Router)) return\n this.app.make(Router).pushMiddlewareToGroup('web', StartSession).pushMiddlewareToGroup('web', VerifyCsrfToken)\n }\n}\n"],"mappings":"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","names":["old","session","Str","session","HttpRequest","HttpRequest","ConfigRepository","ConfigRepository","session","ConfigRepository","Container","Encrypter","Session","inject","Str","inject","Container","ConfigRepository","Str","Session","Encrypter","errors","Application","Session","inject","Session","Application","inject","Session","Session"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orieljs/session",
3
- "version": "0.1.0-alpha.6",
3
+ "version": "0.1.0-alpha.8",
4
4
  "description": "The Oriel Session component.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -27,13 +27,14 @@
27
27
  "files": [
28
28
  "dist",
29
29
  "LICENSE",
30
- "NOTICE"
30
+ "NOTICE",
31
+ "TRADEMARKS.md"
31
32
  ],
32
33
  "dependencies": {
33
34
  "ioredis": "6.0.0",
34
- "@orieljs/contracts": "0.1.0-alpha.6",
35
- "@orieljs/container": "0.1.0-alpha.6",
36
- "@orieljs/support": "0.1.0-alpha.6"
35
+ "@orieljs/contracts": "0.1.0-alpha.8",
36
+ "@orieljs/support": "0.1.0-alpha.8",
37
+ "@orieljs/container": "0.1.0-alpha.8"
37
38
  },
38
39
  "scripts": {
39
40
  "build": "tsup && node ../../../scripts/copy-license.mjs"