first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,83 @@
# cookieDetector
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
`cookieDetector` is a `LocaleDetector` that reads/writes the active
locale via a single cookie. It runs in both server and browser
environments, making it the natural persistence story for stateless
visitors who have not yet authenticated. On the server it consumes the
inbound `Cookie` header and writes a `Set-Cookie` header onto
`ctx.responseHeaders`; on the browser it goes through `document.cookie`.
The detector URL-encodes values on persist and decodes them on read so
the wire format is robust against unusual locale identifiers.
## Features
- Configurable cookie name, max-age, SameSite, and path
- Server read via `ctx.request.headers` and write via
`ctx.responseHeaders`
- Browser read/write via `document.cookie` (including `ctx.document`
injection for tests)
- URL-encoded values; safe parsing tolerates malformed segments and
decode failures
- `environment: "both"`
## Usage: Basic Example
```ts
import { cookieDetector } from "@suaveplan/react-i18n/detector/cookie/cookie";
import { createDetectorChain } from "@suaveplan/i18n/detector";
const chain = createDetectorChain([cookieDetector()]);
```
## Usage: Advanced Example
```ts
import { cookieDetector } from "@suaveplan/react-i18n/detector/cookie/cookie";
// Cross-site embed scenario: SameSite=None requires Secure on real
// browsers; the detector emits the SameSite attribute literally so the
// host server can append `Secure` via its existing cookie middleware.
const detector = cookieDetector({
name: "app_locale",
maxAgeSeconds: 60 * 60 * 24 * 30, // 30 days
sameSite: "none",
path: "/embed",
});
```
## API Reference
### `cookieDetector(options?: CookieDetectorOptions): LocaleDetector`
Returns a `LocaleDetector` with `name: "cookie"` and
`environment: "both"`. Both `detect` and `cache` are implemented.
### `CookieDetectorOptions`
| Field | Type | Default | Description |
| ------------- | ---------------------------------------- | -------------------- | ---------------------------- |
| name | `string` | `"suaveplan_locale"` | Cookie name |
| maxAgeSeconds | `number` | `31536000` | Cookie lifetime in seconds |
| sameSite | `"lax" \| "strict" \| "none"` (default `"lax"`) | `"lax"` | SameSite attribute value |
| path | `string` | `"/"` | Cookie path attribute |
## Implementation Notes
- The detector emits SameSite values capitalised (`Lax`, `Strict`,
`None`) per the cookie spec; the input option stays lower-case so
consumers don't have to remember the casing convention.
- Cookie parsing tolerates segments without an `=` (skipped) and
values that fail percent-decoding (returned raw rather than
throwing).
- The cookie writer uses `Headers.append('set-cookie', …)` so a single
response may carry multiple Set-Cookie writes from sibling
middleware.
- An empty server cookie header transparently falls through to
`document.cookie` so isomorphic test harnesses can stage a browser
scenario inside a server-shaped `DetectorContext` by supplying only
`globalThis.document`.