@craftainer/crud-sdk 0.8.0 → 0.8.1
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/README.md +15 -1
- package/dist/cache/index.mjs +1 -1
- package/dist/{client-CzbFW5YG.mjs → client-DikBkRMm.mjs} +7 -214
- package/dist/client-DikBkRMm.mjs.map +1 -0
- package/dist/codegen/cli.mjs +32 -16
- package/dist/codegen/cli.mjs.map +1 -1
- package/dist/errors-ZdOt0_zk.mjs +232 -0
- package/dist/errors-ZdOt0_zk.mjs.map +1 -0
- package/dist/{events-Dfz-rzC8.mjs → events-swCOTQOS.mjs} +27 -8
- package/dist/{events-Dfz-rzC8.mjs.map → events-swCOTQOS.mjs.map} +1 -1
- package/dist/index.mjs +2 -1
- package/dist/tanstack/index.mjs +1 -1
- package/package.json +1 -1
- package/dist/client-CzbFW5YG.mjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"events-Dfz-rzC8.mjs","names":[],"sources":["../src/cache/policy.ts","../src/reset-once.ts","../node_modules/.pnpm/eventsource-parser@4.1.2/node_modules/eventsource-parser/dist/errors.js","../node_modules/.pnpm/eventsource-parser@4.1.2/node_modules/eventsource-parser/dist/parse.js","../src/events.ts"],"sourcesContent":["/** Per-resource cache policy, defaulted from the manifest `cache` hints. */\n\n/**\n * How one resource is cached. Times are seconds. `maxAge` and\n * `staleWhileRevalidate` only take effect while the resource's SSE stream is\n * running; without it every read revalidates. `statsTtl` bounds the staleness\n * of `stats`/`predict` on its own, as the server caches those bodies for the\n * same time. `revalidateOnly` means no fresh window and no\n * stale-while-revalidate.\n */\nexport interface CachePolicy {\n readonly enabled: boolean;\n readonly maxAge: number;\n readonly statsTtl: number;\n readonly staleWhileRevalidate: number;\n readonly etag: boolean;\n readonly revalidateOnly: boolean;\n}\n\n/** The manifest resource members a policy reads (I1); everything else is ignored. */\nexport interface ManifestCacheHints {\n readonly cache?: {\n readonly max_age?: unknown;\n readonly stats_ttl?: unknown;\n readonly stale_while_revalidate?: unknown;\n readonly etag?: unknown;\n readonly revalidate_only?: unknown;\n } | null;\n}\n\nfunction seconds(value: unknown): number {\n return typeof value === \"number\" && Number.isFinite(value)\n ? Math.max(value, 0)\n : 0;\n}\n\n/** Build a policy from a manifest resource object; `overrides` win over the hints. */\nexport function cachePolicyFromManifest(\n resource: ManifestCacheHints,\n overrides: Partial<CachePolicy> = {},\n): CachePolicy {\n const hints = resource.cache ?? {};\n return {\n enabled: overrides.enabled ?? true,\n maxAge: overrides.maxAge ?? seconds(hints.max_age),\n statsTtl: overrides.statsTtl ?? seconds(hints.stats_ttl),\n staleWhileRevalidate:\n overrides.staleWhileRevalidate ?? seconds(hints.stale_while_revalidate),\n etag: overrides.etag ?? hints.etag !== false,\n revalidateOnly: overrides.revalidateOnly ?? hints.revalidate_only === true,\n };\n}\n\n/**\n * The policy to use under TanStack Query: its `staleTime` decides freshness,\n * so the SDK cache only revalidates (ETag/304) unless told otherwise.\n */\nexport function tanstackCachePolicy(\n resource: ManifestCacheHints,\n overrides: Partial<CachePolicy> = {},\n): CachePolicy {\n return cachePolicyFromManifest(resource, {\n revalidateOnly: true,\n ...overrides,\n });\n}\n","/**\n * \"Reset once per target per connection\" (ADR 0002). A subscriber that is told\n * about a connection runs its reset through here; a second subscriber with the\n * same target (the same cache, or the same QueryClient, and resource) on the\n * same connection joins the first one's reset instead of running another.\n */\nimport type { EventConnection } from \"./events.ts\";\n\nconst ledger = new WeakMap<\n EventConnection,\n WeakMap<object, Map<string, Promise<void>>>\n>();\n\n/**\n * Runs `reset` unless `owner`/`key` was already reset on `connection`; resolves\n * when that reset is done, whoever started it. A failed reset is forgotten so\n * a later subscriber can retry.\n */\nexport function resetOnce(\n connection: EventConnection,\n owner: object,\n key: string,\n reset: () => Promise<void> | void,\n): Promise<void> {\n let owners = ledger.get(connection);\n if (owners === undefined) {\n owners = new WeakMap();\n ledger.set(connection, owners);\n }\n let keys = owners.get(owner);\n if (keys === undefined) {\n keys = new Map();\n owners.set(owner, keys);\n }\n const done = keys.get(key);\n if (done !== undefined) {\n return done;\n }\n const started = (async (): Promise<void> => {\n await reset();\n })();\n keys.set(key, started);\n const forget = keys;\n started.catch(() => {\n forget.delete(key);\n });\n return started;\n}\n","/**\n * Error thrown when encountering an issue during parsing.\n *\n * @public\n */\nexport class ParseError extends Error {\n constructor(message, options) {\n super(message);\n this.name = 'ParseError';\n this.type = options.type;\n this.field = options.field;\n this.value = options.value;\n this.line = options.line;\n }\n}\n//# sourceMappingURL=errors.js.map","/**\n * EventSource/Server-Sent Events parser\n * @see https://html.spec.whatwg.org/multipage/server-sent-events.html\n */\nimport { ParseError } from './errors.js';\n// ASCII codes used in the hot parsing paths.\nconst LF = 10;\nconst CR = 13;\nconst SPACE = 32;\nconst MAX_FIELD_PREFIX_LENGTH = 6;\n/**\n * Creates a new EventSource parser.\n *\n * @param config - Parser configuration. Accepts callbacks (see {@link ParserCallbacks})\n * and options like `maxBufferSize` (see {@link ParserConfig}).\n *\n * @returns A new EventSource parser, with `feed` and `reset` methods.\n * @public\n */\nexport function createParser(config) {\n if (typeof config === 'function') {\n throw new TypeError('`config` must be an object, got a function instead. Did you mean `createParser({onEvent: fn})`?');\n }\n const { maxBufferSize, onComment, onError, onEvent, onId, onRetry } = config;\n // Trailing bytes from prior `feed()` calls that did not yet form a complete line.\n // Stored as an array of fragments and only joined when a line terminator arrives.\n // Concatenating per-feed (`prefix + chunk`) is O(N²) when a single SSE line spans\n // many chunks (e.g. a large `data:` payload streamed in tiny slices, or an MCP-style\n // server that emits one giant content block). Buffering as fragments + joining once\n // makes the same workload linear.\n const pendingFragments = [];\n // Running total of `pendingFragments` lengths, kept in sync with the array so the\n // `maxBufferSize` check doesn't have to walk the fragment list on every feed.\n let pendingFragmentsLength = 0;\n // Empty or partial leading BOM; undefined once the BOM check is complete.\n let bomPrefix = '';\n let id;\n let data = '';\n let dataLines = 0;\n let eventType;\n // Set after a `maxBufferSize` overflow. Once tripped, `feed()` throws until\n // `reset()` is called — see the comment on `maxBufferSize` in `ParserConfig`.\n let terminated = false;\n let skippingLine = false;\n // Set when a line (parsed or discarded) was terminated by a trailing `\\r` at the very\n // end of a chunk. That `\\r` is ambiguous: it may be a bare-CR terminator or the first\n // half of a `\\r\\n` whose `\\n` lands in the next chunk. The line itself is complete\n // either way, but we must remember to swallow a single leading `\\n` from the next\n // chunk so the pair is treated as one terminator rather than a blank line (which\n // would dispatch an event prematurely).\n let skipNextLineFeed = false;\n /**\n * Feeds a chunk of the SSE stream to the parser. Any trailing bytes that do\n * not yet form a complete line are held back and prepended to the next chunk,\n * so callers can pass arbitrary slices of the stream without worrying about\n * line boundaries.\n *\n * Per the SSE spec, one leading UTF-8 BOM is stripped before parsing,\n * even when split across chunks. This handles both the raw 3-byte form (0xEF 0xBB\n * 0xBF) and a single decoded U+FEFF, so a leading BOM is ignored regardless of\n * how the caller decoded the bytes.\n *\n * @see https://html.spec.whatwg.org/multipage/server-sent-events.html#parsing-an-event-stream\n */\n function feed(chunk) {\n if (terminated) {\n throw new Error('Cannot feed parser: it was terminated after exceeding the configured max buffer size. Call `reset()` to resume parsing.');\n }\n if (bomPrefix !== undefined) {\n chunk = bomPrefix + chunk;\n // Wait only while the input could still be a raw BOM. Empty chunks must\n // not finish the check, and a mismatched prefix must remain ordinary input.\n if (chunk === '' || chunk === '\\xEF' || chunk === '\\xEF\\xBB') {\n bomPrefix = chunk;\n return;\n }\n bomPrefix = undefined;\n // Strip exactly one leading BOM, in decoded or raw byte-valued form.\n chunk = chunk.replace(/^(?:\\uFEFF|\\xEF\\xBB\\xBF)/, '');\n }\n // Rare resume states from a prior chunk boundary: a pending `\\r\\n` split or a\n // line being discarded. Single combined check keeps the hot path to one branch;\n // the actual handling lives out-of-line in `resumeAfterSkip`.\n if (skippingLine || skipNextLineFeed) {\n chunk = resumeAfterSkip(chunk);\n if (!chunk) {\n return;\n }\n }\n // Hot path: no buffered prefix from a prior partial line. Hand the chunk\n // straight to `processLines`, exactly like the original implementation.\n // Zero new work in the common case (every chunk ends with `\\n\\n`).\n if (!pendingFragments.length) {\n const trailing = processLines(chunk);\n if (trailing !== '') {\n storeTrailing(trailing);\n }\n checkForBufferOverflow();\n return;\n }\n // We have a buffered prefix. If this chunk also has no terminator, append\n // to the buffer without concatenating — that's the O(N²) trap we're\n // avoiding (large single `data:` payload split across many tiny chunks).\n if (chunk.indexOf('\\n') === -1 && chunk.indexOf('\\r') === -1) {\n if (pendingFragmentsLength < MAX_FIELD_PREFIX_LENGTH) {\n const head = pendingFragments.join('') +\n chunk.slice(0, MAX_FIELD_PREFIX_LENGTH - pendingFragmentsLength);\n if (!shouldBufferTrailing(head)) {\n pendingFragments.length = 0;\n pendingFragmentsLength = 0;\n skippingLine = true;\n return;\n }\n }\n pendingFragments.push(chunk);\n pendingFragmentsLength += chunk.length;\n checkForBufferOverflow();\n return;\n }\n // Terminator arrived. Join the accumulated fragments + this chunk once,\n // process, and buffer any new trailing partial line.\n pendingFragments.push(chunk);\n const input = pendingFragments.join('');\n pendingFragments.length = 0;\n pendingFragmentsLength = 0;\n storeTrailing(processLines(input));\n checkForBufferOverflow();\n }\n // Out-of-line handler for the rare post-boundary states. `skipNextLineFeed` means a\n // line (parsed or discarded) ended with a trailing `\\r` at the previous chunk boundary,\n // so a single leading `\\n` must be swallowed to consume a split `\\r\\n` as one terminator.\n // `skippingLine` means we are discarding an invalid line until its terminator arrives.\n // The two states are mutually exclusive. Returns the remaining chunk to parse ('' if\n // this chunk was fully consumed).\n function resumeAfterSkip(chunk) {\n if (chunk.length === 0) {\n return chunk;\n }\n if (skipNextLineFeed) {\n skipNextLineFeed = false;\n return chunk.charCodeAt(0) === LF ? chunk.slice(1) : chunk;\n }\n const crIndex = chunk.indexOf('\\r');\n const lfIndex = chunk.indexOf('\\n');\n const lineEnd = crIndex === -1 ? lfIndex : lfIndex === -1 ? crIndex : crIndex < lfIndex ? crIndex : lfIndex;\n if (lineEnd === -1) {\n return '';\n }\n // Trailing `\\r` at the very end of the chunk: defer the CRLF/CR decision to the\n // next chunk (see `skipNextLineFeed`) rather than greedily consuming just the `\\r`.\n if (lineEnd === chunk.length - 1 && chunk.charCodeAt(lineEnd) === CR) {\n skippingLine = false;\n skipNextLineFeed = true;\n return '';\n }\n skippingLine = false;\n return chunk.slice(lineEnd + (chunk.charCodeAt(lineEnd) === CR && chunk.charCodeAt(lineEnd + 1) === LF ? 2 : 1));\n }\n function storeTrailing(trailing) {\n if (!trailing)\n return;\n // A trailing that ends with `\\r` is not a partial line: the `\\r` terminates it,\n // and only the CRLF-vs-CR ambiguity remains (the matching `\\n` may start the next\n // chunk). Parse the completed line now — buffering it could grow unbounded through\n // the no-terminator append path, and discarding it would eat the terminator and\n // make skip mode swallow the next line.\n if (trailing.charCodeAt(trailing.length - 1) === CR) {\n parseLine(trailing, 0, trailing.length - 1);\n if (checkForBufferOverflow())\n return;\n skipNextLineFeed = true;\n return;\n }\n if (shouldBufferTrailing(trailing)) {\n pendingFragments.push(trailing);\n pendingFragmentsLength = trailing.length;\n return;\n }\n skippingLine = true;\n }\n function shouldBufferTrailing(trailing) {\n const firstCharCode = trailing.charCodeAt(0);\n return ((firstCharCode === 58 && !!onComment) ||\n (firstCharCode === 100 && isPotentialField(trailing, 'data')) ||\n (firstCharCode === 101 && isPotentialField(trailing, 'event')) ||\n (firstCharCode === 105 && isPotentialField(trailing, 'id')) ||\n (firstCharCode === 114 && isPotentialField(trailing, 'retry')));\n }\n // Returns true when parsing must stop for the current chunk (the parser was already\n // terminated or has just overflowed), and false when processing can continue.\n function checkForBufferOverflow() {\n if (terminated)\n return true;\n if (maxBufferSize === undefined)\n return false;\n if (pendingFragmentsLength + data.length <= maxBufferSize)\n return false;\n terminated = true;\n pendingFragments.length = 0;\n pendingFragmentsLength = 0;\n id = undefined;\n data = '';\n dataLines = 0;\n eventType = undefined;\n skippingLine = false;\n skipNextLineFeed = false;\n onError === null || onError === void 0 ? void 0 : onError(new ParseError(`Buffered data exceeded max buffer size of ${maxBufferSize} characters`, {\n type: 'max-buffer-size-exceeded',\n }));\n return true;\n }\n /**\n * Splits `chunk` into SSE lines and dispatches each to the appropriate handler.\n * Returns any trailing bytes that did not terminate with a line break, so the\n * caller can prepend them to the next chunk.\n *\n * The SSE spec permits three line terminators: `\\n`, `\\r`, and `\\r\\n`. Real-world\n * streams almost always use plain `\\n`, so we take a fast path when no `\\r` is\n * present in the chunk. The slow path is spec-correct but does more work per line.\n */\n function processLines(chunk) {\n let searchIndex = 0;\n // Fast path: LF-only chunk (the common case for typical SSE servers).\n // We can scan forward with a single `indexOf('\\n')` per line and inline\n // the hot-path branches for `data:` and `event:` without the CR bookkeeping\n // the slow path needs.\n if (chunk.indexOf('\\r') === -1) {\n let lfIndex = chunk.indexOf('\\n', searchIndex);\n while (lfIndex !== -1) {\n // Blank line: end-of-event marker. Dispatch the accumulated event (if any)\n // and reset the buffered fields. This is hoisted out of `parseLine` because\n // it's the single most common line shape after `data:` lines.\n if (searchIndex === lfIndex) {\n if (id !== undefined) {\n onId === null || onId === void 0 ? void 0 : onId(id);\n }\n if (dataLines > 0) {\n onEvent === null || onEvent === void 0 ? void 0 : onEvent({ id, event: eventType, data });\n }\n id = undefined;\n data = '';\n dataLines = 0;\n eventType = undefined;\n searchIndex = lfIndex + 1;\n lfIndex = chunk.indexOf('\\n', searchIndex);\n continue;\n }\n const firstCharCode = chunk.charCodeAt(searchIndex);\n if (isDataPrefix(chunk, searchIndex, firstCharCode)) {\n // `data:` line — append the value to the event's data buffer.\n // 'data:'.length === 5, 'data: '.length === 6\n const valueStart = chunk.charCodeAt(searchIndex + 5) === SPACE ? searchIndex + 6 : searchIndex + 5;\n const value = chunk.slice(valueStart, lfIndex);\n // Fast path within a fast path: if this is the first data line AND the\n // next char is another LF (i.e. `data:foo\\n\\n`), dispatch immediately\n // without ever writing to the `data` buffer. This is the shape of a\n // typical single-line SSE event (ChatGPT-style streams, etc.) and is\n // hot enough to be worth the duplication.\n if (dataLines === 0 && chunk.charCodeAt(lfIndex + 1) === LF) {\n if (id !== undefined) {\n onId === null || onId === void 0 ? void 0 : onId(id);\n }\n onEvent === null || onEvent === void 0 ? void 0 : onEvent({ id, event: eventType, data: value });\n id = undefined;\n data = '';\n eventType = undefined;\n searchIndex = lfIndex + 2;\n lfIndex = chunk.indexOf('\\n', searchIndex);\n continue;\n }\n // Multi-line data: concatenate with newline separator per spec.\n data = dataLines === 0 ? value : `${data}\\n${value}`;\n dataLines++;\n }\n else if (isEventPrefix(chunk, searchIndex, firstCharCode)) {\n // `event:` line — set the event type for the next dispatch. Per spec,\n // an empty value resets `event type` to its default (undefined here).\n // 'event:'.length === 6, 'event: '.length === 7\n eventType =\n chunk.slice(chunk.charCodeAt(searchIndex + 6) === SPACE ? searchIndex + 7 : searchIndex + 6, lfIndex) || undefined;\n }\n else {\n // Everything else: `id:`, `retry:`, comment lines (`:` prefix), unknown\n // fields, or malformed lines. These are rarer and go through the full\n // per-line parser, which handles the SSE field grammar in detail.\n parseLine(chunk, searchIndex, lfIndex);\n }\n if (checkForBufferOverflow())\n return '';\n searchIndex = lfIndex + 1;\n lfIndex = chunk.indexOf('\\n', searchIndex);\n }\n return chunk.slice(searchIndex);\n }\n // Slow path: the chunk contains at least one `\\r`, so lines may be terminated\n // by `\\r`, `\\n`, or `\\r\\n`. We locate the next terminator by looking at both\n // the nearest `\\r` and `\\n` and picking whichever comes first.\n while (searchIndex < chunk.length) {\n const crIndex = chunk.indexOf('\\r', searchIndex);\n const lfIndex = chunk.indexOf('\\n', searchIndex);\n let lineEnd = -1;\n if (crIndex !== -1 && lfIndex !== -1) {\n lineEnd = crIndex < lfIndex ? crIndex : lfIndex;\n }\n else if (crIndex !== -1) {\n // A trailing `\\r` at the very end of the chunk is ambiguous: it could be\n // a bare-CR terminator, or the first half of a `\\r\\n` whose `\\n` arrives\n // in the next chunk. Defer until we see more input.\n if (crIndex === chunk.length - 1) {\n lineEnd = -1;\n }\n else {\n lineEnd = crIndex;\n }\n }\n else if (lfIndex !== -1) {\n lineEnd = lfIndex;\n }\n if (lineEnd === -1) {\n break;\n }\n parseLine(chunk, searchIndex, lineEnd);\n if (checkForBufferOverflow())\n return '';\n searchIndex = lineEnd + 1;\n // If we just consumed a `\\r` and the next char is `\\n`, skip it so the\n // pair is treated as a single terminator rather than an empty line.\n if (chunk.charCodeAt(searchIndex - 1) === CR && chunk.charCodeAt(searchIndex) === LF) {\n searchIndex++;\n }\n }\n return chunk.slice(searchIndex);\n }\n function parseLine(chunk, start, end) {\n if (start === end) {\n dispatchEvent();\n return;\n }\n const firstCharCode = chunk.charCodeAt(start);\n if (isDataPrefix(chunk, start, firstCharCode)) {\n // 'data:'.length === 5, 'data: '.length === 6\n const valueStart = chunk.charCodeAt(start + 5) === SPACE ? start + 6 : start + 5;\n const value = chunk.slice(valueStart, end);\n data = dataLines === 0 ? value : `${data}\\n${value}`;\n dataLines++;\n return;\n }\n if (isEventPrefix(chunk, start, firstCharCode)) {\n // 'event:'.length === 6, 'event: '.length === 7\n eventType =\n chunk.slice(chunk.charCodeAt(start + 6) === SPACE ? start + 7 : start + 6, end) || undefined;\n return;\n }\n // Fast path for \"id:\" — 'i' = 105, 'd' = 100, ':' = 58\n if (firstCharCode === 105 &&\n chunk.charCodeAt(start + 1) === 100 &&\n chunk.charCodeAt(start + 2) === 58) {\n // 'id:'.length === 3, 'id: '.length === 4\n const value = chunk.slice(chunk.charCodeAt(start + 3) === SPACE ? start + 4 : start + 3, end);\n // If the field value does not contain U+0000 NULL, then set the `ID` buffer to\n // the field value. Otherwise, ignore the field.\n if (!value.includes('\\0'))\n id = value;\n return;\n }\n // Comment line — ':' = 58\n if (firstCharCode === 58) {\n if (onComment) {\n const line = chunk.slice(start, end);\n // skip ':' (+1), or ': ' (+2) when a space follows\n onComment(line.slice(chunk.charCodeAt(start + 1) === SPACE ? 2 : 1));\n }\n return;\n }\n const line = chunk.slice(start, end);\n const fieldSeparatorIndex = line.indexOf(':');\n if (fieldSeparatorIndex === -1) {\n processField(line, '', line);\n return;\n }\n const field = line.slice(0, fieldSeparatorIndex);\n // skip ':' (+1), or ': ' (+2) when a space follows\n const offset = line.charCodeAt(fieldSeparatorIndex + 1) === SPACE ? 2 : 1;\n const value = line.slice(fieldSeparatorIndex + offset);\n processField(field, value, line);\n }\n function processField(field, value, line) {\n // Field names must be compared literally, with no case folding performed.\n switch (field) {\n case 'event':\n // Set the `event type` buffer to field value\n eventType = value || undefined;\n break;\n case 'data':\n data = dataLines === 0 ? value : `${data}\\n${value}`;\n dataLines++;\n break;\n case 'id':\n // If the field value does not contain U+0000 NULL, then set the `ID` buffer to\n // the field value. Otherwise, ignore the field.\n if (!value.includes('\\0'))\n id = value;\n break;\n case 'retry':\n // If the field value consists of only ASCII digits, then interpret the field value as an\n // integer in base ten, and set the event stream's reconnection time to that integer.\n // Otherwise, ignore the field.\n if (/^\\d+$/.test(value)) {\n onRetry === null || onRetry === void 0 ? void 0 : onRetry(parseInt(value, 10));\n }\n else {\n onError === null || onError === void 0 ? void 0 : onError(new ParseError(`Invalid \\`retry\\` value: \"${value}\"`, {\n type: 'invalid-retry',\n value,\n line,\n }));\n }\n break;\n default:\n // Otherwise, the field is ignored.\n onError === null || onError === void 0 ? void 0 : onError(new ParseError(`Unknown field \"${field.length > 20 ? `${field.slice(0, 20)}…` : field}\"`, { type: 'unknown-field', field, value, line }));\n break;\n }\n }\n function dispatchEvent() {\n if (id !== undefined) {\n onId === null || onId === void 0 ? void 0 : onId(id);\n }\n if (dataLines > 0) {\n onEvent === null || onEvent === void 0 ? void 0 : onEvent({\n id,\n event: eventType,\n data,\n });\n }\n id = undefined;\n data = '';\n dataLines = 0;\n eventType = undefined;\n }\n function reset(options = {}) {\n if (options.consume && pendingFragments.length > 0) {\n const incompleteLine = pendingFragments.join('');\n parseLine(incompleteLine, 0, incompleteLine.length);\n }\n bomPrefix = '';\n id = undefined;\n data = '';\n dataLines = 0;\n eventType = undefined;\n pendingFragments.length = 0;\n pendingFragmentsLength = 0;\n terminated = false;\n skippingLine = false;\n skipNextLineFeed = false;\n }\n return { feed, reset };\n}\n/**\n * Checks if `chunk` starts with the literal `data:` at index `i`.\n *\n * Equivalent to `chunk.startsWith('data:', i)`, but benchmarks show this\n * hand-unrolled char-code comparison is ~20% faster on common event types.\n * The caller passes `firstCharCode` (the code at `i`) so it can be reused\n * across prefix checks.\n *\n * ASCII: 'd' = 100, 'a' = 97, 't' = 116, 'a' = 97, ':' = 58\n */\nfunction isDataPrefix(chunk, i, firstCharCode) {\n return (firstCharCode === 100 &&\n chunk.charCodeAt(i + 1) === 97 &&\n chunk.charCodeAt(i + 2) === 116 &&\n chunk.charCodeAt(i + 3) === 97 &&\n chunk.charCodeAt(i + 4) === 58);\n}\n/**\n * Checks if `chunk` starts with the literal `event:` at index `i`.\n *\n * See {@link isDataPrefix} for why this is hand-unrolled rather than using\n * `String.prototype.startsWith`.\n *\n * ASCII: 'e' = 101, 'v' = 118, 'e' = 101, 'n' = 110, 't' = 116, ':' = 58\n */\nfunction isEventPrefix(chunk, i, firstCharCode) {\n return (firstCharCode === 101 &&\n chunk.charCodeAt(i + 1) === 118 &&\n chunk.charCodeAt(i + 2) === 101 &&\n chunk.charCodeAt(i + 3) === 110 &&\n chunk.charCodeAt(i + 4) === 116 &&\n chunk.charCodeAt(i + 5) === 58);\n}\nfunction isPotentialField(line, field) {\n let i = 1;\n while (i < line.length && i < field.length) {\n if (line.charCodeAt(i) !== field.charCodeAt(i)) {\n return false;\n }\n i++;\n }\n return line.length <= field.length || line.charCodeAt(field.length) === 58;\n}\n//# sourceMappingURL=parse.js.map","/**\n * SSE subscriber that turns `GET {base_path}/events` into callbacks.\n *\n * One connection per (fetch, url), reference-counted and fanned out to every\n * subscriber. The caller passes an already authenticated `fetch`: this is\n * fetch streaming, not `EventSource`, because `EventSource` cannot send an\n * Authorization header. Frames carry no `event:` name: the first has\n * `id: 0` and `{\"subscriber_id\": ...}`; later ones are record events. A\n * reconnect passes `?{resume_param}=<subscriber_id>` explicitly (never\n * `Last-Event-ID`, which the server would read as a subscriber id) when the\n * stream replays, and always tells subscribers to reset, so the gap is\n * covered even without replay. A stream silent for three keep-alive\n * intervals is dead and is reconnected with exponential backoff and jitter.\n * Events invalidate; they never apply snapshots.\n *\n * A hub is shared by every subscriber of the same (fetch, url) and the first\n * subscriber's options win: the keep-alive, resume parameter, replay mode and\n * resource label of later subscribers are ignored. In development\n * (`process.env.NODE_ENV !== \"production\"`) a later subscriber whose options\n * differ gets a `console.warn` naming the URL and the fields.\n *\n * Every connection has an identity (an opaque {@link EventConnection}) that\n * the hub passes to `onReset` (for the connect reset) and to `onStatus(true)`.\n * A subscriber that joins an already connected hub, or during the handshake's\n * reset fan-out, gets no connect reset; it sees `onStatus(true)` with a\n * connection it was never reset for and resets itself (see `invalidateOnEvents`\n * and `bridgeEvents`).\n */\nimport { createParser } from \"eventsource-parser\";\nimport type { EventSourceMessage } from \"eventsource-parser\";\nimport type { CrudEvent, MaybePromise } from \"./interfaces.ts\";\n\n/** The manifest's `capabilities.events` object (I1), plain. */\nexport interface EventsConfig {\n /** The server's event label, not the manifest name. */\n readonly resource: string;\n readonly path?: string;\n readonly resume_param?: string;\n /** `persistent` resumes by subscriber id; anything else (`none`) does not. A plain string, as on the wire. */\n readonly replay?: string;\n readonly keepalive_seconds?: number;\n}\n\n/** Opaque identity of one connection of a hub; a new one per connect. */\nexport type EventConnection = object;\n\n/**\n * What a subscriber wants to hear. A handler that throws must not kill the\n * stream, so errors are swallowed; handlers run one after another, in order.\n */\nexport interface EventHandlers {\n onEvent(event: CrudEvent): MaybePromise<void>;\n /**\n * After every connect (the first included), and for an event with no usable\n * record id: clear the resource. `connection` is set for the connect reset\n * only, and is the same object `onStatus(true)` then receives.\n */\n onReset?(connection?: EventConnection): MaybePromise<void>;\n /**\n * `true` when the stream is connected, `false` on any loss, exit or\n * unsubscribe. `connection` identifies the connection when `connected`.\n * A subscriber that joined after the connect reset gets `true` without\n * having been sent `onReset` for that connection.\n */\n onStatus?(\n connected: boolean,\n connection?: EventConnection,\n ): MaybePromise<void>;\n}\n\n/** A shared event stream: `subscribe` returns the (idempotent) unsubscribe. */\nexport interface EventHub {\n subscribe(handlers: EventHandlers): () => void;\n}\n\nexport interface EventHubOptions {\n /** Authenticated; shared hubs are keyed by this function and `url`. */\n readonly fetch: typeof fetch;\n /** Absolute URL of the events endpoint. */\n readonly url: string;\n /**\n * Used only by the first subscriber of a hub (first wins): a later\n * subscriber's differing `resource`, `resume_param`, `replay` or\n * `keepalive_seconds` is ignored, with a development `console.warn`.\n */\n readonly events: EventsConfig;\n /** Jitter source in `[0, 1)`; defaults to `Math.random`. */\n readonly random?: () => number;\n}\n\nexport interface SubscribeEventsOptions extends EventHubOptions, EventHandlers {\n /** Aborting unsubscribes. */\n readonly signal?: AbortSignal;\n}\n\nconst BACKOFF_START_MS = 1000;\nconst BACKOFF_MAX_MS = 30_000;\nconst DEFAULT_KEEPALIVE_S = 15;\nconst DEAD_AFTER_KEEPALIVES = 3;\n/** `setTimeout` clamps a longer delay to 1 ms, which would declare the stream dead at once. */\nconst MAX_TIMER_MS = 2 ** 31 - 1;\nconst ACTIONS: ReadonlySet<unknown> = new Set([\n \"create\",\n \"update\",\n \"delete\",\n \"restore\",\n]);\n\n/**\n * The keep-alive interval in seconds. Zero, negative and non-finite values\n * are invalid and treated as unset, so the default applies (as the WHATWG SSE\n * spec ignores an invalid `retry` value instead of acting on it); otherwise a\n * dead-stream deadline of 0 would reconnect forever.\n */\nfunction keepaliveSeconds(events: EventsConfig): number {\n const value = events.keepalive_seconds;\n return value !== undefined && Number.isFinite(value) && value > 0\n ? value\n : DEFAULT_KEEPALIVE_S;\n}\n\n/** The `events` fields that change what a hub does, with defaults applied. */\nfunction hubSettings(events: EventsConfig): Record<string, unknown> {\n return {\n resource: events.resource,\n resume_param: events.resume_param ?? \"subscriber_id\",\n replay: events.replay,\n keepalive_seconds: keepaliveSeconds(events),\n };\n}\n\n/** `process.env.NODE_ENV` is replaced by bundlers; without it (no `process`) assume development. */\nfunction inDevelopment(): boolean {\n try {\n return process.env.NODE_ENV !== \"production\";\n } catch {\n return true;\n }\n}\n\n/** Warns, in development, that a later subscriber's options differ from the hub's. */\nfunction warnOnDifferingOptions(\n hub: EventHubOptions,\n later: EventHubOptions,\n): void {\n if (!inDevelopment()) {\n return;\n }\n const first = hubSettings(hub.events);\n const next = hubSettings(later.events);\n const differing = Object.keys(first).filter(\n (key) => first[key] !== next[key],\n );\n if (differing.length > 0) {\n console.warn(\n `crud-sdk: the event hub for ${hub.url} was opened with other events options; ` +\n `the first subscriber's win and these are ignored: ${differing.join(\", \")}`,\n );\n }\n}\n\nconst registry = new WeakMap<typeof fetch, Map<string, Hub>>();\n\nfunction sleep(ms: number, signal: AbortSignal): Promise<void> {\n return new Promise((resolve) => {\n if (signal.aborted) {\n resolve();\n return;\n }\n const done = (): void => {\n clearTimeout(timer);\n signal.removeEventListener(\"abort\", done);\n resolve();\n };\n const timer = setTimeout(done, ms);\n signal.addEventListener(\"abort\", done, { once: true });\n });\n}\n\nclass Hub {\n private readonly handlers = new Set<EventHandlers>();\n private readonly options: EventHubOptions;\n private readonly onEmpty: () => void;\n private controller: AbortController | undefined;\n private connected = false;\n private connection: EventConnection | undefined;\n private subscriberId: string | undefined;\n private attempt = 0;\n\n constructor(options: EventHubOptions, onEmpty: () => void) {\n this.options = options;\n this.onEmpty = onEmpty;\n }\n\n subscribe(handlers: EventHandlers, requested: EventHubOptions): () => void {\n if (this.handlers.size > 0) {\n warnOnDifferingOptions(this.options, requested);\n }\n // The same object may subscribe twice; give each subscription its own identity.\n const entry: EventHandlers = {\n onEvent: (event) => handlers.onEvent(event),\n onReset: (connection) => handlers.onReset?.(connection),\n onStatus: (connected, connection) =>\n handlers.onStatus?.(connected, connection),\n };\n this.handlers.add(entry);\n if (this.controller === undefined) {\n this.controller = new AbortController();\n void this.run(this.controller.signal);\n } else if (this.connected) {\n void this.guard(() => entry.onStatus?.(true, this.connection));\n }\n return () => {\n if (!this.handlers.delete(entry)) {\n return;\n }\n void this.guard(() => entry.onStatus?.(false));\n if (this.handlers.size === 0) {\n // Abort the live stream instead of waiting for the next frame.\n this.controller?.abort();\n this.controller = undefined;\n this.onEmpty();\n }\n };\n }\n\n private async guard(\n call: () => MaybePromise<void> | undefined,\n ): Promise<void> {\n try {\n await call();\n } catch {\n // A failing subscriber must not take the stream down.\n }\n }\n\n private async fan(\n call: (handlers: EventHandlers) => MaybePromise<void> | undefined,\n ): Promise<void> {\n // A snapshot, so a subscriber added during dispatch waits for the next\n // one; one removed meanwhile (its unsubscribe already ran) is skipped.\n for (const handlers of Array.from(this.handlers)) {\n if (this.handlers.has(handlers)) {\n await this.guard(() => call(handlers));\n }\n }\n }\n\n private async setConnected(\n connected: boolean,\n connection?: EventConnection,\n ): Promise<void> {\n if (this.connected === connected) {\n return;\n }\n this.connected = connected;\n this.connection = connected ? connection : undefined;\n await this.fan((handlers) => handlers.onStatus?.(connected, connection));\n }\n\n private backoff(): number {\n const base = Math.min(BACKOFF_START_MS * 2 ** this.attempt, BACKOFF_MAX_MS);\n this.attempt += 1;\n const jitter = (this.options.random ?? Math.random)();\n return Math.min(base * (1 + 0.5 * jitter), BACKOFF_MAX_MS);\n }\n\n /** Connect, read and reconnect until aborted. */\n private async run(signal: AbortSignal): Promise<void> {\n try {\n while (!signal.aborted) {\n try {\n await this.readOnce(signal);\n } catch {\n // Lost, refused or dead: reconnect below.\n }\n await this.setConnected(false);\n await sleep(this.backoff(), signal);\n }\n } finally {\n // On any exit, tell the subscribers so the freshness gate closes.\n await this.setConnected(false);\n }\n }\n\n private resumeUrl(): string {\n const { url, events } = this.options;\n if (events.replay !== \"persistent\" || this.subscriberId === undefined) {\n return url;\n }\n const param = events.resume_param ?? \"subscriber_id\";\n const separator = url.includes(\"?\") ? \"&\" : \"?\";\n return `${url}${separator}${encodeURIComponent(param)}=${encodeURIComponent(this.subscriberId)}`;\n }\n\n private async readOnce(signal: AbortSignal): Promise<void> {\n const deadMs = Math.min(\n keepaliveSeconds(this.options.events) * DEAD_AFTER_KEEPALIVES * 1000,\n MAX_TIMER_MS,\n );\n const conn = new AbortController();\n const abortConn = (): void => {\n conn.abort();\n };\n signal.addEventListener(\"abort\", abortConn, { once: true });\n let timer: ReturnType<typeof setTimeout> | undefined;\n const arm = (): void => {\n clearTimeout(timer);\n timer = setTimeout(abortConn, deadMs);\n };\n try {\n arm();\n const response = await this.options.fetch(this.resumeUrl(), {\n headers: { accept: \"text/event-stream\" },\n signal: conn.signal,\n });\n if (!response.ok || response.body === null) {\n throw new Error(`event stream refused: HTTP ${response.status}`);\n }\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n const pending: EventSourceMessage[] = [];\n const parser = createParser({\n onEvent: (message) => {\n pending.push(message);\n },\n });\n for (;;) {\n const { done, value } = await reader.read();\n if (done) {\n return;\n }\n parser.feed(decoder.decode(value, { stream: true }));\n // Any byte, keep-alive comments included, proves the stream is alive.\n // Handlers may be slow and nothing is read meanwhile, so the timer is\n // paused while they run and restarts once they are done.\n clearTimeout(timer);\n for (const message of pending.splice(0)) {\n await this.handle(message);\n }\n arm();\n }\n } finally {\n clearTimeout(timer);\n signal.removeEventListener(\"abort\", abortConn);\n conn.abort(); // release the connection on every way out\n }\n }\n\n private async handle(message: EventSourceMessage): Promise<void> {\n let data: unknown;\n try {\n data = JSON.parse(message.data);\n } catch {\n return;\n }\n if (typeof data !== \"object\" || data === null || Array.isArray(data)) {\n return;\n }\n const record = data as Record<string, unknown>;\n if (\"subscriber_id\" in record) {\n this.subscriberId = String(record[\"subscriber_id\"]);\n this.attempt = 0;\n // Every connect, the first included: entries stored before this stream\n // (an earlier page session, a persisted store) may predate server changes.\n // A subscriber that joins while this fans out is not in it; it gets\n // `onStatus(true)` with this connection and resets itself.\n const connection: EventConnection = {};\n const present = new Set(this.handlers);\n await this.fan((handlers) => handlers.onReset?.(connection));\n if (this.connected) {\n // A repeated handshake on a live stream: whoever joined during the\n // fan-out was told about the old connection only.\n this.connection = connection;\n for (const handlers of Array.from(this.handlers)) {\n if (!present.has(handlers)) {\n await this.guard(() => handlers.onStatus?.(true, connection));\n }\n }\n } else {\n await this.setConnected(true, connection);\n }\n return;\n }\n if (record[\"resource\"] !== this.options.events.resource) {\n return;\n }\n const action = record[\"action\"];\n const recordId = record[\"record_id\"];\n if (!ACTIONS.has(action) || !Number.isInteger(recordId)) {\n await this.fan((handlers) => handlers.onReset?.());\n return;\n }\n const snapshot = record[\"snapshot\"];\n const event: CrudEvent = {\n resource: String(record[\"resource\"]),\n recordId: recordId as number,\n action: action as CrudEvent[\"action\"],\n snapshot:\n typeof snapshot === \"object\" && snapshot !== null\n ? (snapshot as Record<string, unknown>)\n : {},\n timestamp: String(record[\"timestamp\"] ?? \"\"),\n };\n await this.fan((handlers) => handlers.onEvent(event));\n }\n}\n\n/**\n * The shared hub for `(fetch, url)`: the first subscriber opens the stream,\n * the last one aborts it. A later subscribe after that opens a fresh one.\n *\n * The first subscriber's `events` options win while the hub lives. A later\n * subscriber whose `resource`, `resume_param`, `replay` or `keepalive_seconds`\n * differ is served by the same stream with the first's values, and in\n * development (`process.env.NODE_ENV !== \"production\"`) gets a `console.warn`\n * naming the URL and the differing fields.\n */\nexport function getEventHub(options: EventHubOptions): EventHub {\n return {\n subscribe(handlers) {\n let hubs = registry.get(options.fetch);\n if (hubs === undefined) {\n hubs = new Map();\n registry.set(options.fetch, hubs);\n }\n const byUrl = hubs;\n let hub = byUrl.get(options.url);\n if (hub === undefined) {\n hub = new Hub(options, () => {\n byUrl.delete(options.url);\n });\n byUrl.set(options.url, hub);\n }\n return hub.subscribe(handlers, options);\n },\n };\n}\n\n/**\n * Subscribe to one resource's event stream. Returns the unsubscribe; the\n * last unsubscribe aborts the stream. `signal` aborting unsubscribes too.\n */\nexport function subscribeEvents(options: SubscribeEventsOptions): () => void {\n const { signal } = options;\n if (signal?.aborted === true) {\n return () => undefined;\n }\n const unsubscribe = getEventHub(options).subscribe(options);\n signal?.addEventListener(\"abort\", unsubscribe, { once: true });\n return () => {\n signal?.removeEventListener(\"abort\", unsubscribe);\n unsubscribe();\n };\n}\n"],"ignoreList":[2,3],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"events-swCOTQOS.mjs","names":[],"sources":["../src/cache/policy.ts","../src/reset-once.ts","../node_modules/.pnpm/eventsource-parser@4.1.2/node_modules/eventsource-parser/dist/errors.js","../node_modules/.pnpm/eventsource-parser@4.1.2/node_modules/eventsource-parser/dist/parse.js","../src/events.ts"],"sourcesContent":["/** Per-resource cache policy, defaulted from the manifest `cache` hints. */\n\n/**\n * How one resource is cached. Times are seconds. `maxAge` and\n * `staleWhileRevalidate` only take effect while the resource's SSE stream is\n * running; without it every read revalidates. `statsTtl` bounds the staleness\n * of `stats`/`predict` on its own, as the server caches those bodies for the\n * same time. `revalidateOnly` means no fresh window and no\n * stale-while-revalidate.\n */\nexport interface CachePolicy {\n readonly enabled: boolean;\n readonly maxAge: number;\n readonly statsTtl: number;\n readonly staleWhileRevalidate: number;\n readonly etag: boolean;\n readonly revalidateOnly: boolean;\n}\n\n/** The manifest resource members a policy reads (I1); everything else is ignored. */\nexport interface ManifestCacheHints {\n readonly cache?: {\n readonly max_age?: unknown;\n readonly stats_ttl?: unknown;\n readonly stale_while_revalidate?: unknown;\n readonly etag?: unknown;\n readonly revalidate_only?: unknown;\n } | null;\n}\n\nfunction seconds(value: unknown): number {\n return typeof value === \"number\" && Number.isFinite(value)\n ? Math.max(value, 0)\n : 0;\n}\n\n/** Build a policy from a manifest resource object; `overrides` win over the hints. */\nexport function cachePolicyFromManifest(\n resource: ManifestCacheHints,\n overrides: Partial<CachePolicy> = {},\n): CachePolicy {\n const hints = resource.cache ?? {};\n return {\n enabled: overrides.enabled ?? true,\n maxAge: overrides.maxAge ?? seconds(hints.max_age),\n statsTtl: overrides.statsTtl ?? seconds(hints.stats_ttl),\n staleWhileRevalidate:\n overrides.staleWhileRevalidate ?? seconds(hints.stale_while_revalidate),\n etag: overrides.etag ?? hints.etag !== false,\n revalidateOnly: overrides.revalidateOnly ?? hints.revalidate_only === true,\n };\n}\n\n/**\n * The policy to use under TanStack Query: its `staleTime` decides freshness,\n * so the SDK cache only revalidates (ETag/304) unless told otherwise.\n */\nexport function tanstackCachePolicy(\n resource: ManifestCacheHints,\n overrides: Partial<CachePolicy> = {},\n): CachePolicy {\n return cachePolicyFromManifest(resource, {\n revalidateOnly: true,\n ...overrides,\n });\n}\n","/**\n * \"Reset once per target per connection\" (ADR 0002). A subscriber that is told\n * about a connection runs its reset through here; a second subscriber with the\n * same target (the same cache, or the same QueryClient, and resource) on the\n * same connection joins the first one's reset instead of running another.\n */\nimport type { EventConnection } from \"./events.ts\";\n\nconst ledger = new WeakMap<\n EventConnection,\n WeakMap<object, Map<string, Promise<void>>>\n>();\n\n/**\n * Runs `reset` unless `owner`/`key` was already reset on `connection`; resolves\n * when that reset is done, whoever started it. A failed reset is forgotten so\n * a later subscriber can retry.\n */\nexport function resetOnce(\n connection: EventConnection,\n owner: object,\n key: string,\n reset: () => Promise<void> | void,\n): Promise<void> {\n let owners = ledger.get(connection);\n if (owners === undefined) {\n owners = new WeakMap();\n ledger.set(connection, owners);\n }\n let keys = owners.get(owner);\n if (keys === undefined) {\n keys = new Map();\n owners.set(owner, keys);\n }\n const done = keys.get(key);\n if (done !== undefined) {\n return done;\n }\n const started = (async (): Promise<void> => {\n await reset();\n })();\n keys.set(key, started);\n const forget = keys;\n started.catch(() => {\n forget.delete(key);\n });\n return started;\n}\n","/**\n * Error thrown when encountering an issue during parsing.\n *\n * @public\n */\nexport class ParseError extends Error {\n constructor(message, options) {\n super(message);\n this.name = 'ParseError';\n this.type = options.type;\n this.field = options.field;\n this.value = options.value;\n this.line = options.line;\n }\n}\n//# sourceMappingURL=errors.js.map","/**\n * EventSource/Server-Sent Events parser\n * @see https://html.spec.whatwg.org/multipage/server-sent-events.html\n */\nimport { ParseError } from './errors.js';\n// ASCII codes used in the hot parsing paths.\nconst LF = 10;\nconst CR = 13;\nconst SPACE = 32;\nconst MAX_FIELD_PREFIX_LENGTH = 6;\n/**\n * Creates a new EventSource parser.\n *\n * @param config - Parser configuration. Accepts callbacks (see {@link ParserCallbacks})\n * and options like `maxBufferSize` (see {@link ParserConfig}).\n *\n * @returns A new EventSource parser, with `feed` and `reset` methods.\n * @public\n */\nexport function createParser(config) {\n if (typeof config === 'function') {\n throw new TypeError('`config` must be an object, got a function instead. Did you mean `createParser({onEvent: fn})`?');\n }\n const { maxBufferSize, onComment, onError, onEvent, onId, onRetry } = config;\n // Trailing bytes from prior `feed()` calls that did not yet form a complete line.\n // Stored as an array of fragments and only joined when a line terminator arrives.\n // Concatenating per-feed (`prefix + chunk`) is O(N²) when a single SSE line spans\n // many chunks (e.g. a large `data:` payload streamed in tiny slices, or an MCP-style\n // server that emits one giant content block). Buffering as fragments + joining once\n // makes the same workload linear.\n const pendingFragments = [];\n // Running total of `pendingFragments` lengths, kept in sync with the array so the\n // `maxBufferSize` check doesn't have to walk the fragment list on every feed.\n let pendingFragmentsLength = 0;\n // Empty or partial leading BOM; undefined once the BOM check is complete.\n let bomPrefix = '';\n let id;\n let data = '';\n let dataLines = 0;\n let eventType;\n // Set after a `maxBufferSize` overflow. Once tripped, `feed()` throws until\n // `reset()` is called — see the comment on `maxBufferSize` in `ParserConfig`.\n let terminated = false;\n let skippingLine = false;\n // Set when a line (parsed or discarded) was terminated by a trailing `\\r` at the very\n // end of a chunk. That `\\r` is ambiguous: it may be a bare-CR terminator or the first\n // half of a `\\r\\n` whose `\\n` lands in the next chunk. The line itself is complete\n // either way, but we must remember to swallow a single leading `\\n` from the next\n // chunk so the pair is treated as one terminator rather than a blank line (which\n // would dispatch an event prematurely).\n let skipNextLineFeed = false;\n /**\n * Feeds a chunk of the SSE stream to the parser. Any trailing bytes that do\n * not yet form a complete line are held back and prepended to the next chunk,\n * so callers can pass arbitrary slices of the stream without worrying about\n * line boundaries.\n *\n * Per the SSE spec, one leading UTF-8 BOM is stripped before parsing,\n * even when split across chunks. This handles both the raw 3-byte form (0xEF 0xBB\n * 0xBF) and a single decoded U+FEFF, so a leading BOM is ignored regardless of\n * how the caller decoded the bytes.\n *\n * @see https://html.spec.whatwg.org/multipage/server-sent-events.html#parsing-an-event-stream\n */\n function feed(chunk) {\n if (terminated) {\n throw new Error('Cannot feed parser: it was terminated after exceeding the configured max buffer size. Call `reset()` to resume parsing.');\n }\n if (bomPrefix !== undefined) {\n chunk = bomPrefix + chunk;\n // Wait only while the input could still be a raw BOM. Empty chunks must\n // not finish the check, and a mismatched prefix must remain ordinary input.\n if (chunk === '' || chunk === '\\xEF' || chunk === '\\xEF\\xBB') {\n bomPrefix = chunk;\n return;\n }\n bomPrefix = undefined;\n // Strip exactly one leading BOM, in decoded or raw byte-valued form.\n chunk = chunk.replace(/^(?:\\uFEFF|\\xEF\\xBB\\xBF)/, '');\n }\n // Rare resume states from a prior chunk boundary: a pending `\\r\\n` split or a\n // line being discarded. Single combined check keeps the hot path to one branch;\n // the actual handling lives out-of-line in `resumeAfterSkip`.\n if (skippingLine || skipNextLineFeed) {\n chunk = resumeAfterSkip(chunk);\n if (!chunk) {\n return;\n }\n }\n // Hot path: no buffered prefix from a prior partial line. Hand the chunk\n // straight to `processLines`, exactly like the original implementation.\n // Zero new work in the common case (every chunk ends with `\\n\\n`).\n if (!pendingFragments.length) {\n const trailing = processLines(chunk);\n if (trailing !== '') {\n storeTrailing(trailing);\n }\n checkForBufferOverflow();\n return;\n }\n // We have a buffered prefix. If this chunk also has no terminator, append\n // to the buffer without concatenating — that's the O(N²) trap we're\n // avoiding (large single `data:` payload split across many tiny chunks).\n if (chunk.indexOf('\\n') === -1 && chunk.indexOf('\\r') === -1) {\n if (pendingFragmentsLength < MAX_FIELD_PREFIX_LENGTH) {\n const head = pendingFragments.join('') +\n chunk.slice(0, MAX_FIELD_PREFIX_LENGTH - pendingFragmentsLength);\n if (!shouldBufferTrailing(head)) {\n pendingFragments.length = 0;\n pendingFragmentsLength = 0;\n skippingLine = true;\n return;\n }\n }\n pendingFragments.push(chunk);\n pendingFragmentsLength += chunk.length;\n checkForBufferOverflow();\n return;\n }\n // Terminator arrived. Join the accumulated fragments + this chunk once,\n // process, and buffer any new trailing partial line.\n pendingFragments.push(chunk);\n const input = pendingFragments.join('');\n pendingFragments.length = 0;\n pendingFragmentsLength = 0;\n storeTrailing(processLines(input));\n checkForBufferOverflow();\n }\n // Out-of-line handler for the rare post-boundary states. `skipNextLineFeed` means a\n // line (parsed or discarded) ended with a trailing `\\r` at the previous chunk boundary,\n // so a single leading `\\n` must be swallowed to consume a split `\\r\\n` as one terminator.\n // `skippingLine` means we are discarding an invalid line until its terminator arrives.\n // The two states are mutually exclusive. Returns the remaining chunk to parse ('' if\n // this chunk was fully consumed).\n function resumeAfterSkip(chunk) {\n if (chunk.length === 0) {\n return chunk;\n }\n if (skipNextLineFeed) {\n skipNextLineFeed = false;\n return chunk.charCodeAt(0) === LF ? chunk.slice(1) : chunk;\n }\n const crIndex = chunk.indexOf('\\r');\n const lfIndex = chunk.indexOf('\\n');\n const lineEnd = crIndex === -1 ? lfIndex : lfIndex === -1 ? crIndex : crIndex < lfIndex ? crIndex : lfIndex;\n if (lineEnd === -1) {\n return '';\n }\n // Trailing `\\r` at the very end of the chunk: defer the CRLF/CR decision to the\n // next chunk (see `skipNextLineFeed`) rather than greedily consuming just the `\\r`.\n if (lineEnd === chunk.length - 1 && chunk.charCodeAt(lineEnd) === CR) {\n skippingLine = false;\n skipNextLineFeed = true;\n return '';\n }\n skippingLine = false;\n return chunk.slice(lineEnd + (chunk.charCodeAt(lineEnd) === CR && chunk.charCodeAt(lineEnd + 1) === LF ? 2 : 1));\n }\n function storeTrailing(trailing) {\n if (!trailing)\n return;\n // A trailing that ends with `\\r` is not a partial line: the `\\r` terminates it,\n // and only the CRLF-vs-CR ambiguity remains (the matching `\\n` may start the next\n // chunk). Parse the completed line now — buffering it could grow unbounded through\n // the no-terminator append path, and discarding it would eat the terminator and\n // make skip mode swallow the next line.\n if (trailing.charCodeAt(trailing.length - 1) === CR) {\n parseLine(trailing, 0, trailing.length - 1);\n if (checkForBufferOverflow())\n return;\n skipNextLineFeed = true;\n return;\n }\n if (shouldBufferTrailing(trailing)) {\n pendingFragments.push(trailing);\n pendingFragmentsLength = trailing.length;\n return;\n }\n skippingLine = true;\n }\n function shouldBufferTrailing(trailing) {\n const firstCharCode = trailing.charCodeAt(0);\n return ((firstCharCode === 58 && !!onComment) ||\n (firstCharCode === 100 && isPotentialField(trailing, 'data')) ||\n (firstCharCode === 101 && isPotentialField(trailing, 'event')) ||\n (firstCharCode === 105 && isPotentialField(trailing, 'id')) ||\n (firstCharCode === 114 && isPotentialField(trailing, 'retry')));\n }\n // Returns true when parsing must stop for the current chunk (the parser was already\n // terminated or has just overflowed), and false when processing can continue.\n function checkForBufferOverflow() {\n if (terminated)\n return true;\n if (maxBufferSize === undefined)\n return false;\n if (pendingFragmentsLength + data.length <= maxBufferSize)\n return false;\n terminated = true;\n pendingFragments.length = 0;\n pendingFragmentsLength = 0;\n id = undefined;\n data = '';\n dataLines = 0;\n eventType = undefined;\n skippingLine = false;\n skipNextLineFeed = false;\n onError === null || onError === void 0 ? void 0 : onError(new ParseError(`Buffered data exceeded max buffer size of ${maxBufferSize} characters`, {\n type: 'max-buffer-size-exceeded',\n }));\n return true;\n }\n /**\n * Splits `chunk` into SSE lines and dispatches each to the appropriate handler.\n * Returns any trailing bytes that did not terminate with a line break, so the\n * caller can prepend them to the next chunk.\n *\n * The SSE spec permits three line terminators: `\\n`, `\\r`, and `\\r\\n`. Real-world\n * streams almost always use plain `\\n`, so we take a fast path when no `\\r` is\n * present in the chunk. The slow path is spec-correct but does more work per line.\n */\n function processLines(chunk) {\n let searchIndex = 0;\n // Fast path: LF-only chunk (the common case for typical SSE servers).\n // We can scan forward with a single `indexOf('\\n')` per line and inline\n // the hot-path branches for `data:` and `event:` without the CR bookkeeping\n // the slow path needs.\n if (chunk.indexOf('\\r') === -1) {\n let lfIndex = chunk.indexOf('\\n', searchIndex);\n while (lfIndex !== -1) {\n // Blank line: end-of-event marker. Dispatch the accumulated event (if any)\n // and reset the buffered fields. This is hoisted out of `parseLine` because\n // it's the single most common line shape after `data:` lines.\n if (searchIndex === lfIndex) {\n if (id !== undefined) {\n onId === null || onId === void 0 ? void 0 : onId(id);\n }\n if (dataLines > 0) {\n onEvent === null || onEvent === void 0 ? void 0 : onEvent({ id, event: eventType, data });\n }\n id = undefined;\n data = '';\n dataLines = 0;\n eventType = undefined;\n searchIndex = lfIndex + 1;\n lfIndex = chunk.indexOf('\\n', searchIndex);\n continue;\n }\n const firstCharCode = chunk.charCodeAt(searchIndex);\n if (isDataPrefix(chunk, searchIndex, firstCharCode)) {\n // `data:` line — append the value to the event's data buffer.\n // 'data:'.length === 5, 'data: '.length === 6\n const valueStart = chunk.charCodeAt(searchIndex + 5) === SPACE ? searchIndex + 6 : searchIndex + 5;\n const value = chunk.slice(valueStart, lfIndex);\n // Fast path within a fast path: if this is the first data line AND the\n // next char is another LF (i.e. `data:foo\\n\\n`), dispatch immediately\n // without ever writing to the `data` buffer. This is the shape of a\n // typical single-line SSE event (ChatGPT-style streams, etc.) and is\n // hot enough to be worth the duplication.\n if (dataLines === 0 && chunk.charCodeAt(lfIndex + 1) === LF) {\n if (id !== undefined) {\n onId === null || onId === void 0 ? void 0 : onId(id);\n }\n onEvent === null || onEvent === void 0 ? void 0 : onEvent({ id, event: eventType, data: value });\n id = undefined;\n data = '';\n eventType = undefined;\n searchIndex = lfIndex + 2;\n lfIndex = chunk.indexOf('\\n', searchIndex);\n continue;\n }\n // Multi-line data: concatenate with newline separator per spec.\n data = dataLines === 0 ? value : `${data}\\n${value}`;\n dataLines++;\n }\n else if (isEventPrefix(chunk, searchIndex, firstCharCode)) {\n // `event:` line — set the event type for the next dispatch. Per spec,\n // an empty value resets `event type` to its default (undefined here).\n // 'event:'.length === 6, 'event: '.length === 7\n eventType =\n chunk.slice(chunk.charCodeAt(searchIndex + 6) === SPACE ? searchIndex + 7 : searchIndex + 6, lfIndex) || undefined;\n }\n else {\n // Everything else: `id:`, `retry:`, comment lines (`:` prefix), unknown\n // fields, or malformed lines. These are rarer and go through the full\n // per-line parser, which handles the SSE field grammar in detail.\n parseLine(chunk, searchIndex, lfIndex);\n }\n if (checkForBufferOverflow())\n return '';\n searchIndex = lfIndex + 1;\n lfIndex = chunk.indexOf('\\n', searchIndex);\n }\n return chunk.slice(searchIndex);\n }\n // Slow path: the chunk contains at least one `\\r`, so lines may be terminated\n // by `\\r`, `\\n`, or `\\r\\n`. We locate the next terminator by looking at both\n // the nearest `\\r` and `\\n` and picking whichever comes first.\n while (searchIndex < chunk.length) {\n const crIndex = chunk.indexOf('\\r', searchIndex);\n const lfIndex = chunk.indexOf('\\n', searchIndex);\n let lineEnd = -1;\n if (crIndex !== -1 && lfIndex !== -1) {\n lineEnd = crIndex < lfIndex ? crIndex : lfIndex;\n }\n else if (crIndex !== -1) {\n // A trailing `\\r` at the very end of the chunk is ambiguous: it could be\n // a bare-CR terminator, or the first half of a `\\r\\n` whose `\\n` arrives\n // in the next chunk. Defer until we see more input.\n if (crIndex === chunk.length - 1) {\n lineEnd = -1;\n }\n else {\n lineEnd = crIndex;\n }\n }\n else if (lfIndex !== -1) {\n lineEnd = lfIndex;\n }\n if (lineEnd === -1) {\n break;\n }\n parseLine(chunk, searchIndex, lineEnd);\n if (checkForBufferOverflow())\n return '';\n searchIndex = lineEnd + 1;\n // If we just consumed a `\\r` and the next char is `\\n`, skip it so the\n // pair is treated as a single terminator rather than an empty line.\n if (chunk.charCodeAt(searchIndex - 1) === CR && chunk.charCodeAt(searchIndex) === LF) {\n searchIndex++;\n }\n }\n return chunk.slice(searchIndex);\n }\n function parseLine(chunk, start, end) {\n if (start === end) {\n dispatchEvent();\n return;\n }\n const firstCharCode = chunk.charCodeAt(start);\n if (isDataPrefix(chunk, start, firstCharCode)) {\n // 'data:'.length === 5, 'data: '.length === 6\n const valueStart = chunk.charCodeAt(start + 5) === SPACE ? start + 6 : start + 5;\n const value = chunk.slice(valueStart, end);\n data = dataLines === 0 ? value : `${data}\\n${value}`;\n dataLines++;\n return;\n }\n if (isEventPrefix(chunk, start, firstCharCode)) {\n // 'event:'.length === 6, 'event: '.length === 7\n eventType =\n chunk.slice(chunk.charCodeAt(start + 6) === SPACE ? start + 7 : start + 6, end) || undefined;\n return;\n }\n // Fast path for \"id:\" — 'i' = 105, 'd' = 100, ':' = 58\n if (firstCharCode === 105 &&\n chunk.charCodeAt(start + 1) === 100 &&\n chunk.charCodeAt(start + 2) === 58) {\n // 'id:'.length === 3, 'id: '.length === 4\n const value = chunk.slice(chunk.charCodeAt(start + 3) === SPACE ? start + 4 : start + 3, end);\n // If the field value does not contain U+0000 NULL, then set the `ID` buffer to\n // the field value. Otherwise, ignore the field.\n if (!value.includes('\\0'))\n id = value;\n return;\n }\n // Comment line — ':' = 58\n if (firstCharCode === 58) {\n if (onComment) {\n const line = chunk.slice(start, end);\n // skip ':' (+1), or ': ' (+2) when a space follows\n onComment(line.slice(chunk.charCodeAt(start + 1) === SPACE ? 2 : 1));\n }\n return;\n }\n const line = chunk.slice(start, end);\n const fieldSeparatorIndex = line.indexOf(':');\n if (fieldSeparatorIndex === -1) {\n processField(line, '', line);\n return;\n }\n const field = line.slice(0, fieldSeparatorIndex);\n // skip ':' (+1), or ': ' (+2) when a space follows\n const offset = line.charCodeAt(fieldSeparatorIndex + 1) === SPACE ? 2 : 1;\n const value = line.slice(fieldSeparatorIndex + offset);\n processField(field, value, line);\n }\n function processField(field, value, line) {\n // Field names must be compared literally, with no case folding performed.\n switch (field) {\n case 'event':\n // Set the `event type` buffer to field value\n eventType = value || undefined;\n break;\n case 'data':\n data = dataLines === 0 ? value : `${data}\\n${value}`;\n dataLines++;\n break;\n case 'id':\n // If the field value does not contain U+0000 NULL, then set the `ID` buffer to\n // the field value. Otherwise, ignore the field.\n if (!value.includes('\\0'))\n id = value;\n break;\n case 'retry':\n // If the field value consists of only ASCII digits, then interpret the field value as an\n // integer in base ten, and set the event stream's reconnection time to that integer.\n // Otherwise, ignore the field.\n if (/^\\d+$/.test(value)) {\n onRetry === null || onRetry === void 0 ? void 0 : onRetry(parseInt(value, 10));\n }\n else {\n onError === null || onError === void 0 ? void 0 : onError(new ParseError(`Invalid \\`retry\\` value: \"${value}\"`, {\n type: 'invalid-retry',\n value,\n line,\n }));\n }\n break;\n default:\n // Otherwise, the field is ignored.\n onError === null || onError === void 0 ? void 0 : onError(new ParseError(`Unknown field \"${field.length > 20 ? `${field.slice(0, 20)}…` : field}\"`, { type: 'unknown-field', field, value, line }));\n break;\n }\n }\n function dispatchEvent() {\n if (id !== undefined) {\n onId === null || onId === void 0 ? void 0 : onId(id);\n }\n if (dataLines > 0) {\n onEvent === null || onEvent === void 0 ? void 0 : onEvent({\n id,\n event: eventType,\n data,\n });\n }\n id = undefined;\n data = '';\n dataLines = 0;\n eventType = undefined;\n }\n function reset(options = {}) {\n if (options.consume && pendingFragments.length > 0) {\n const incompleteLine = pendingFragments.join('');\n parseLine(incompleteLine, 0, incompleteLine.length);\n }\n bomPrefix = '';\n id = undefined;\n data = '';\n dataLines = 0;\n eventType = undefined;\n pendingFragments.length = 0;\n pendingFragmentsLength = 0;\n terminated = false;\n skippingLine = false;\n skipNextLineFeed = false;\n }\n return { feed, reset };\n}\n/**\n * Checks if `chunk` starts with the literal `data:` at index `i`.\n *\n * Equivalent to `chunk.startsWith('data:', i)`, but benchmarks show this\n * hand-unrolled char-code comparison is ~20% faster on common event types.\n * The caller passes `firstCharCode` (the code at `i`) so it can be reused\n * across prefix checks.\n *\n * ASCII: 'd' = 100, 'a' = 97, 't' = 116, 'a' = 97, ':' = 58\n */\nfunction isDataPrefix(chunk, i, firstCharCode) {\n return (firstCharCode === 100 &&\n chunk.charCodeAt(i + 1) === 97 &&\n chunk.charCodeAt(i + 2) === 116 &&\n chunk.charCodeAt(i + 3) === 97 &&\n chunk.charCodeAt(i + 4) === 58);\n}\n/**\n * Checks if `chunk` starts with the literal `event:` at index `i`.\n *\n * See {@link isDataPrefix} for why this is hand-unrolled rather than using\n * `String.prototype.startsWith`.\n *\n * ASCII: 'e' = 101, 'v' = 118, 'e' = 101, 'n' = 110, 't' = 116, ':' = 58\n */\nfunction isEventPrefix(chunk, i, firstCharCode) {\n return (firstCharCode === 101 &&\n chunk.charCodeAt(i + 1) === 118 &&\n chunk.charCodeAt(i + 2) === 101 &&\n chunk.charCodeAt(i + 3) === 110 &&\n chunk.charCodeAt(i + 4) === 116 &&\n chunk.charCodeAt(i + 5) === 58);\n}\nfunction isPotentialField(line, field) {\n let i = 1;\n while (i < line.length && i < field.length) {\n if (line.charCodeAt(i) !== field.charCodeAt(i)) {\n return false;\n }\n i++;\n }\n return line.length <= field.length || line.charCodeAt(field.length) === 58;\n}\n//# sourceMappingURL=parse.js.map","/**\n * SSE subscriber that turns `GET {base_path}/events` into callbacks.\n *\n * One connection per (fetch, url), reference-counted and fanned out to every\n * subscriber. The caller passes an already authenticated `fetch`: this is\n * fetch streaming, not `EventSource`, because `EventSource` cannot send an\n * Authorization header. Frames carry no `event:` name: the first has\n * `id: 0` and `{\"subscriber_id\": ...}`; later ones are record events. A\n * reconnect passes `?{resume_param}=<subscriber_id>` explicitly (never\n * `Last-Event-ID`, which the server would read as a subscriber id) when the\n * stream replays, and always tells subscribers to reset, so the gap is\n * covered even without replay. A stream silent for three keep-alive\n * intervals is dead and is reconnected with exponential backoff and jitter.\n * Events invalidate; they never apply snapshots.\n *\n * A hub is shared by every subscriber of the same (fetch, url) and the first\n * subscriber's options win: the keep-alive, resume parameter, replay mode and\n * resource label of later subscribers are ignored. In development\n * (`process.env.NODE_ENV !== \"production\"`) a later subscriber whose options\n * differ gets a `console.warn` naming the URL and the fields.\n *\n * Every connection has an identity (an opaque {@link EventConnection}) that\n * the hub passes to `onReset` (for the connect reset) and to `onStatus(true)`.\n * A subscriber that joins an already connected hub, or during the handshake's\n * reset fan-out, gets no connect reset; it sees `onStatus(true)` with a\n * connection it was never reset for and resets itself (see `invalidateOnEvents`\n * and `bridgeEvents`).\n */\nimport { createParser } from \"eventsource-parser\";\nimport type { EventSourceMessage } from \"eventsource-parser\";\nimport { describeUrl } from \"./errors.ts\";\nimport type { CrudEvent, MaybePromise } from \"./interfaces.ts\";\n\n/** The manifest's `capabilities.events` object (I1), plain. */\nexport interface EventsConfig {\n /** The server's event label, not the manifest name. */\n readonly resource: string;\n readonly path?: string;\n readonly resume_param?: string;\n /** `persistent` resumes by subscriber id; anything else (`none`) does not. A plain string, as on the wire. */\n readonly replay?: string;\n readonly keepalive_seconds?: number;\n}\n\n/** Opaque identity of one connection of a hub; a new one per connect. */\nexport type EventConnection = object;\n\n/**\n * What a subscriber wants to hear. A handler that throws must not kill the\n * stream, so errors are swallowed; handlers run one after another, in order.\n */\nexport interface EventHandlers {\n onEvent(event: CrudEvent): MaybePromise<void>;\n /**\n * After every connect (the first included), and for an event with no usable\n * record id: clear the resource. `connection` is set for the connect reset\n * only, and is the same object `onStatus(true)` then receives.\n */\n onReset?(connection?: EventConnection): MaybePromise<void>;\n /**\n * `true` when the stream is connected, `false` on any loss, exit or\n * unsubscribe. `connection` identifies the connection when `connected`.\n * A subscriber that joined after the connect reset gets `true` without\n * having been sent `onReset` for that connection.\n */\n onStatus?(\n connected: boolean,\n connection?: EventConnection,\n ): MaybePromise<void>;\n}\n\n/** A shared event stream: `subscribe` returns the (idempotent) unsubscribe. */\nexport interface EventHub {\n subscribe(handlers: EventHandlers): () => void;\n}\n\nexport interface EventHubOptions {\n /** Authenticated; shared hubs are keyed by this function and `url`. */\n readonly fetch: typeof fetch;\n /** Absolute URL of the events endpoint. */\n readonly url: string;\n /**\n * Used only by the first subscriber of a hub (first wins): a later\n * subscriber's differing `resource`, `resume_param`, `replay` or\n * `keepalive_seconds` is ignored, with a development `console.warn`.\n */\n readonly events: EventsConfig;\n /** Jitter source in `[0, 1)`; defaults to `Math.random`. */\n readonly random?: () => number;\n}\n\nexport interface SubscribeEventsOptions extends EventHubOptions, EventHandlers {\n /** Aborting unsubscribes. */\n readonly signal?: AbortSignal;\n}\n\nconst BACKOFF_START_MS = 1000;\nconst BACKOFF_MAX_MS = 30_000;\nconst DEFAULT_KEEPALIVE_S = 15;\nconst DEAD_AFTER_KEEPALIVES = 3;\n/** Cap on the SSE parser's buffered characters (one unterminated line or event); past it the stream is dropped. */\nconst MAX_BUFFER_CHARS = 1024 * 1024;\n/** `setTimeout` clamps a longer delay to 1 ms, which would declare the stream dead at once. */\nconst MAX_TIMER_MS = 2 ** 31 - 1;\nconst ACTIONS: ReadonlySet<unknown> = new Set([\n \"create\",\n \"update\",\n \"delete\",\n \"restore\",\n]);\n\n/**\n * The keep-alive interval in seconds. Zero, negative and non-finite values\n * are invalid and treated as unset, so the default applies (as the WHATWG SSE\n * spec ignores an invalid `retry` value instead of acting on it); otherwise a\n * dead-stream deadline of 0 would reconnect forever.\n */\nfunction keepaliveSeconds(events: EventsConfig): number {\n const value = events.keepalive_seconds;\n return value !== undefined && Number.isFinite(value) && value > 0\n ? value\n : DEFAULT_KEEPALIVE_S;\n}\n\n/** The `events` fields that change what a hub does, with defaults applied. */\nfunction hubSettings(events: EventsConfig): Record<string, unknown> {\n return {\n resource: events.resource,\n resume_param: events.resume_param ?? \"subscriber_id\",\n replay: events.replay,\n keepalive_seconds: keepaliveSeconds(events),\n };\n}\n\n/** `process.env.NODE_ENV` is replaced by bundlers; without it (no `process`) assume development. */\nfunction inDevelopment(): boolean {\n try {\n return process.env.NODE_ENV !== \"production\";\n } catch {\n return true;\n }\n}\n\n/** Warns, in development, that a later subscriber's options differ from the hub's. */\nfunction warnOnDifferingOptions(\n hub: EventHubOptions,\n later: EventHubOptions,\n): void {\n if (!inDevelopment()) {\n return;\n }\n const first = hubSettings(hub.events);\n const next = hubSettings(later.events);\n const differing = Object.keys(first).filter(\n (key) => first[key] !== next[key],\n );\n if (differing.length > 0) {\n console.warn(\n `crud-sdk: the event hub for ${describeUrl(hub.url)} was opened with other events options; ` +\n `the first subscriber's win and these are ignored: ${differing.join(\", \")}`,\n );\n }\n}\n\nconst registry = new WeakMap<typeof fetch, Map<string, Hub>>();\n\nfunction sleep(ms: number, signal: AbortSignal): Promise<void> {\n return new Promise((resolve) => {\n if (signal.aborted) {\n resolve();\n return;\n }\n const done = (): void => {\n clearTimeout(timer);\n signal.removeEventListener(\"abort\", done);\n resolve();\n };\n const timer = setTimeout(done, ms);\n signal.addEventListener(\"abort\", done, { once: true });\n });\n}\n\nclass Hub {\n private readonly handlers = new Set<EventHandlers>();\n private readonly options: EventHubOptions;\n private readonly onEmpty: () => void;\n private controller: AbortController | undefined;\n private connected = false;\n private connection: EventConnection | undefined;\n private subscriberId: string | undefined;\n private attempt = 0;\n\n constructor(options: EventHubOptions, onEmpty: () => void) {\n this.options = options;\n this.onEmpty = onEmpty;\n }\n\n subscribe(handlers: EventHandlers, requested: EventHubOptions): () => void {\n if (this.handlers.size > 0) {\n warnOnDifferingOptions(this.options, requested);\n }\n // The same object may subscribe twice; give each subscription its own identity.\n const entry: EventHandlers = {\n onEvent: (event) => handlers.onEvent(event),\n onReset: (connection) => handlers.onReset?.(connection),\n onStatus: (connected, connection) =>\n handlers.onStatus?.(connected, connection),\n };\n this.handlers.add(entry);\n if (this.controller === undefined) {\n this.controller = new AbortController();\n void this.run(this.controller.signal);\n } else if (this.connected) {\n void this.guard(() => entry.onStatus?.(true, this.connection));\n }\n return () => {\n if (!this.handlers.delete(entry)) {\n return;\n }\n void this.guard(() => entry.onStatus?.(false));\n if (this.handlers.size === 0) {\n // Abort the live stream instead of waiting for the next frame.\n this.controller?.abort();\n this.controller = undefined;\n this.onEmpty();\n }\n };\n }\n\n private async guard(\n call: () => MaybePromise<void> | undefined,\n ): Promise<void> {\n try {\n await call();\n } catch {\n // A failing subscriber must not take the stream down.\n }\n }\n\n private async fan(\n call: (handlers: EventHandlers) => MaybePromise<void> | undefined,\n ): Promise<void> {\n // A snapshot, so a subscriber added during dispatch waits for the next\n // one; one removed meanwhile (its unsubscribe already ran) is skipped.\n for (const handlers of Array.from(this.handlers)) {\n if (this.handlers.has(handlers)) {\n await this.guard(() => call(handlers));\n }\n }\n }\n\n private async setConnected(\n connected: boolean,\n connection?: EventConnection,\n ): Promise<void> {\n if (this.connected === connected) {\n return;\n }\n this.connected = connected;\n this.connection = connected ? connection : undefined;\n await this.fan((handlers) => handlers.onStatus?.(connected, connection));\n }\n\n private backoff(): number {\n const base = Math.min(BACKOFF_START_MS * 2 ** this.attempt, BACKOFF_MAX_MS);\n this.attempt += 1;\n const jitter = (this.options.random ?? Math.random)();\n return Math.min(base * (1 + 0.5 * jitter), BACKOFF_MAX_MS);\n }\n\n /** Connect, read and reconnect until aborted. */\n private async run(signal: AbortSignal): Promise<void> {\n try {\n while (!signal.aborted) {\n try {\n await this.readOnce(signal);\n } catch {\n // Lost, refused or dead: reconnect below.\n }\n await this.setConnected(false);\n await sleep(this.backoff(), signal);\n }\n } finally {\n // On any exit, tell the subscribers so the freshness gate closes.\n await this.setConnected(false);\n }\n }\n\n private resumeUrl(): string {\n const { url, events } = this.options;\n if (events.replay !== \"persistent\" || this.subscriberId === undefined) {\n return url;\n }\n const param = events.resume_param ?? \"subscriber_id\";\n const separator = url.includes(\"?\") ? \"&\" : \"?\";\n return `${url}${separator}${encodeURIComponent(param)}=${encodeURIComponent(this.subscriberId)}`;\n }\n\n private async readOnce(signal: AbortSignal): Promise<void> {\n const deadMs = Math.min(\n keepaliveSeconds(this.options.events) * DEAD_AFTER_KEEPALIVES * 1000,\n MAX_TIMER_MS,\n );\n const conn = new AbortController();\n const abortConn = (): void => {\n conn.abort();\n };\n signal.addEventListener(\"abort\", abortConn, { once: true });\n let timer: ReturnType<typeof setTimeout> | undefined;\n const arm = (): void => {\n clearTimeout(timer);\n timer = setTimeout(abortConn, deadMs);\n };\n try {\n arm();\n const response = await this.options.fetch(this.resumeUrl(), {\n headers: { accept: \"text/event-stream\" },\n signal: conn.signal,\n });\n if (!response.ok || response.body === null) {\n throw new Error(`event stream refused: HTTP ${response.status}`);\n }\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n const pending: EventSourceMessage[] = [];\n let overflow = false;\n const parser = createParser({\n maxBufferSize: MAX_BUFFER_CHARS,\n onEvent: (message) => {\n pending.push(message);\n },\n onError: (error) => {\n overflow ||= error.type === \"max-buffer-size-exceeded\";\n },\n });\n // Rejects when the connection is aborted (dead-stream timer included),\n // so a handler that never settles cannot hold the reader loop.\n const closed = new Promise<never>((_resolve, reject) => {\n conn.signal.addEventListener(\n \"abort\",\n () => {\n reject(new Error(\"event stream closed\"));\n },\n { once: true },\n );\n });\n closed.catch(() => undefined);\n for (;;) {\n const { done, value } = await reader.read();\n if (done) {\n return;\n }\n // Any byte, keep-alive comments included, proves the stream is alive.\n // The timer keeps running while handlers do, and each message gets a\n // fresh `deadMs` for its handler: a hung handler ends the connection\n // like a silent stream (the hub reconnects, closing the freshness gate\n // meanwhile), while a batch of slow-but-finishing handlers does not.\n // Reconnects are paced by the backoff and by `deadMs` per attempt.\n arm();\n parser.feed(decoder.decode(value, { stream: true }));\n for (const message of pending.splice(0)) {\n arm();\n await Promise.race([this.handle(message), closed]);\n }\n if (overflow) {\n // Events parsed before the oversized one were handled above.\n throw new Error(\"event stream line or event too large\");\n }\n }\n } finally {\n clearTimeout(timer);\n signal.removeEventListener(\"abort\", abortConn);\n conn.abort(); // release the connection on every way out\n }\n }\n\n private async handle(message: EventSourceMessage): Promise<void> {\n let data: unknown;\n try {\n data = JSON.parse(message.data);\n } catch {\n return;\n }\n if (typeof data !== \"object\" || data === null || Array.isArray(data)) {\n return;\n }\n const record = data as Record<string, unknown>;\n if (\"subscriber_id\" in record) {\n this.subscriberId = String(record[\"subscriber_id\"]);\n this.attempt = 0;\n // Every connect, the first included: entries stored before this stream\n // (an earlier page session, a persisted store) may predate server changes.\n // A subscriber that joins while this fans out is not in it; it gets\n // `onStatus(true)` with this connection and resets itself.\n const connection: EventConnection = {};\n const present = new Set(this.handlers);\n await this.fan((handlers) => handlers.onReset?.(connection));\n if (this.connected) {\n // A repeated handshake on a live stream: whoever joined during the\n // fan-out was told about the old connection only.\n this.connection = connection;\n for (const handlers of Array.from(this.handlers)) {\n if (!present.has(handlers)) {\n await this.guard(() => handlers.onStatus?.(true, connection));\n }\n }\n } else {\n await this.setConnected(true, connection);\n }\n return;\n }\n if (record[\"resource\"] !== this.options.events.resource) {\n return;\n }\n const action = record[\"action\"];\n const recordId = record[\"record_id\"];\n if (!ACTIONS.has(action) || !Number.isInteger(recordId)) {\n await this.fan((handlers) => handlers.onReset?.());\n return;\n }\n const snapshot = record[\"snapshot\"];\n const event: CrudEvent = {\n resource: String(record[\"resource\"]),\n recordId: recordId as number,\n action: action as CrudEvent[\"action\"],\n snapshot:\n typeof snapshot === \"object\" && snapshot !== null\n ? (snapshot as Record<string, unknown>)\n : {},\n timestamp: String(record[\"timestamp\"] ?? \"\"),\n };\n await this.fan((handlers) => handlers.onEvent(event));\n }\n}\n\n/**\n * The shared hub for `(fetch, url)`: the first subscriber opens the stream,\n * the last one aborts it. A later subscribe after that opens a fresh one.\n *\n * The first subscriber's `events` options win while the hub lives. A later\n * subscriber whose `resource`, `resume_param`, `replay` or `keepalive_seconds`\n * differ is served by the same stream with the first's values, and in\n * development (`process.env.NODE_ENV !== \"production\"`) gets a `console.warn`\n * naming the URL and the differing fields.\n */\nexport function getEventHub(options: EventHubOptions): EventHub {\n return {\n subscribe(handlers) {\n let hubs = registry.get(options.fetch);\n if (hubs === undefined) {\n hubs = new Map();\n registry.set(options.fetch, hubs);\n }\n const byUrl = hubs;\n let hub = byUrl.get(options.url);\n if (hub === undefined) {\n hub = new Hub(options, () => {\n byUrl.delete(options.url);\n });\n byUrl.set(options.url, hub);\n }\n return hub.subscribe(handlers, options);\n },\n };\n}\n\n/**\n * Subscribe to one resource's event stream. Returns the unsubscribe; the\n * last unsubscribe aborts the stream. `signal` aborting unsubscribes too.\n */\nexport function subscribeEvents(options: SubscribeEventsOptions): () => void {\n const { signal } = options;\n if (signal?.aborted === true) {\n return () => undefined;\n }\n const unsubscribe = getEventHub(options).subscribe(options);\n signal?.addEventListener(\"abort\", unsubscribe, { once: true });\n return () => {\n signal?.removeEventListener(\"abort\", unsubscribe);\n unsubscribe();\n };\n}\n"],"ignoreList":[2,3],"mappings":"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"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a as encodeParams, c as CATALOG_PATH, d as loadManifest, f as manifestUrlFromCatalog, i as buildQuery, l as PROFILE, m as composeMiddleware, n as ResourceClient, o as formatScalar, p as parseManifest, r as createClient, s as quote, t as CrudClient, u as findResource } from "./client-DikBkRMm.mjs";
|
|
2
2
|
import { i as staticToken, n as cacheScope, t as ANON } from "./auth-C5__H0Ln.mjs";
|
|
3
|
+
import { _ as Unauthorized, a as CrudError, c as InvalidQueryError, d as NotFound, f as PreconditionFailed, g as ServerError, h as ResponseError, i as ConnectionFailed, l as Locked, m as RateLimited, n as CapabilityError, o as Forbidden, p as ProblemError, r as ClientError, s as InsecureTransportError, t as BadRequest, u as ManifestError, v as UnknownResourceError, x as problemFromResponse, y as ValidationFailed } from "./errors-ZdOt0_zk.mjs";
|
|
3
4
|
export { ANON, BadRequest, CATALOG_PATH, CapabilityError, ClientError, ConnectionFailed, CrudClient, CrudError, Forbidden, InsecureTransportError, InvalidQueryError, Locked, ManifestError, NotFound, PROFILE, PreconditionFailed, ProblemError, RateLimited, ResourceClient, ResponseError, ServerError, Unauthorized, UnknownResourceError, ValidationFailed, buildQuery, cacheScope, composeMiddleware, createClient, encodeParams, findResource, formatScalar, loadManifest, manifestUrlFromCatalog, parseManifest, problemFromResponse, quote, staticToken };
|
package/dist/tanstack/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as tanstackCachePolicy, n as subscribeEvents, r as resetOnce, t as getEventHub } from "../events-
|
|
1
|
+
import { a as tanstackCachePolicy, n as subscribeEvents, r as resetOnce, t as getEventHub } from "../events-swCOTQOS.mjs";
|
|
2
2
|
//#region src/tanstack/adapter.ts
|
|
3
3
|
/**
|
|
4
4
|
* A query is the client's `ListOptions`, `StatsOptions` or `PredictOptions`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@craftainer/crud-sdk",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.1",
|
|
4
4
|
"description": "Typed fetch client for craftainer CRUD APIs: manifest-driven resources, query builder, problem-details errors, opt-in cache with SSE invalidation and TanStack Query helpers.",
|
|
5
5
|
"license": "GPL-3.0-only",
|
|
6
6
|
"repository": {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"client-CzbFW5YG.mjs","names":["isObject","tokenScope"],"sources":["../src/interfaces.ts","../src/errors.ts","../src/manifest.ts","../src/query.ts","../src/client.ts"],"sourcesContent":["/**\n * Contracts shared by the client core (TS1) and the cache layer (TS2).\n * Fixed in TS0 (plan interface I3): change them only through the plan.\n */\n\n/** A value or a promise of it. */\nexport type MaybePromise<T> = T | Promise<T>;\n\n/** What a request does, as classified by the client. */\nexport type Op =\n | \"manifest\"\n | \"list\"\n | \"record\"\n | \"filters\"\n | \"stats\"\n | \"predict\"\n | \"revisions\"\n | \"create\"\n | \"update\"\n | \"delete\"\n | \"bulk_update\"\n | \"bulk_delete\"\n | \"clone\"\n | \"draft\"\n | \"publish\"\n | \"restore\"\n | \"events\";\n\n/**\n * One stored `200` response. Times are epoch milliseconds (`Date.now()`).\n * Structured-clone safe, so IndexedDB can store it as is.\n */\nexport interface CacheEntry {\n readonly status: number;\n readonly headers: ReadonlyArray<readonly [string, string]>;\n /** JSON text; the SDK only caches JSON. */\n readonly body: string;\n readonly storedAt: number;\n /** `<= storedAt` means \"always revalidate\". */\n readonly freshUntil: number;\n /** End of the stale-while-revalidate window (`>= freshUntil`). */\n readonly staleUntil: number;\n readonly etag?: string;\n}\n\n/**\n * Cache backend. Keys are opaque, slash-separated strings built by\n * `./cache`'s `cacheKey`\n * (`v1/{resource}/{kind}/{subject}/{apiVersion}/{scope}/{query}`, with `_`\n * when there is no apiVersion).\n * `ttlMs` is how long the backend may keep the entry (undefined = backend\n * default); freshness lives in `CacheEntry`. `clear(prefix)` removes every\n * key starting with `prefix`; `clear()` removes everything the store owns.\n * Methods may be sync or async. They must not reject for a missing key\n * (`get` resolves `undefined`), and a failing backend must not fail the\n * request: the cache layer swallows store errors and treats them as a miss.\n */\nexport interface CacheStore {\n get(key: string): MaybePromise<CacheEntry | undefined>;\n set(key: string, entry: CacheEntry, ttlMs?: number): MaybePromise<void>;\n delete(key: string): MaybePromise<void>;\n clear(prefix?: string): MaybePromise<void>;\n}\n\n/**\n * What the client knows about a request that a bare `Request` does not. The\n * client builds it for every call; middleware read it, so they never parse\n * URLs or read Authorization.\n */\nexport interface RequestContext {\n /** The request about to be sent; replace it by passing a new context to `next`. */\n readonly request: Request;\n /** Manifest name; `undefined` for the manifest document itself. */\n readonly resource: string | undefined;\n readonly op: Op;\n /** The record the request targets, when it targets one. */\n readonly recordId: number | undefined;\n /**\n * \"anon\", or the first 32 hex characters of the SHA-256 of the\n * Authorization credential actually sent.\n */\n readonly scope: string;\n /**\n * Set by the client only when `createClient({ cacheScope })` is used: the\n * caller scope the cache keys by (opaque and key-safe, internally\n * namespaced; it equals `scope`). When absent the cache derives the scope\n * from the Authorization header. A middleware that builds a new context must\n * carry it through (`{ ...ctx, request }`), or the cache falls back to the\n * header scope.\n */\n readonly cacheScope?: string;\n /**\n * The resource's `api_version` from the manifest, or `null` when it has\n * none. Part of the cache key, so versions never share entries (the cache\n * layer renders `null` as `_`).\n */\n readonly apiVersion: string | null;\n readonly signal: AbortSignal | undefined;\n}\n\n/** Calls the next middleware, or the network when none is left. */\nexport type Next = (ctx: RequestContext) => Promise<Response>;\n\n/**\n * Onion middleware. In `chain = [a, b]`, `a` is outermost: the request runs\n * a -> b -> fetch and the response returns fetch -> b -> a. A middleware may\n * replace `ctx.request` (pass `{ ...ctx, request }` to `next`), return\n * without calling `next` (short-circuit, e.g. a fresh cache hit), or replace\n * the response (e.g. a `304` rebuilt from the cache). It must not consume\n * `response.body` unless it returns a different `Response`; use\n * `response.clone()` to read it.\n */\nexport type Middleware = (ctx: RequestContext, next: Next) => Promise<Response>;\n\n/**\n * Returns the bearer token, or `null`/`undefined` for an anonymous call.\n * `refresh: true` is passed once after a `401`, to force a new token.\n */\nexport type TokenProvider = (opts: {\n readonly refresh: boolean;\n}) => MaybePromise<string | null | undefined>;\n\n/** One record-mutation event from `GET {basePath}/events` (the server's event envelope). */\nexport interface CrudEvent {\n /** The server's event label (e.g. \"hero\"), not the manifest name. */\n readonly resource: string;\n readonly recordId: number;\n readonly action: \"create\" | \"update\" | \"delete\" | \"restore\";\n /** The read view of the record after the change. */\n readonly snapshot: Readonly<Record<string, unknown>>;\n /** ISO 8601, UTC. */\n readonly timestamp: string;\n}\n\n/**\n * Folds `chain` (outermost first) around `terminal`, usually the network\n * `fetch`, into one `Next`. Each middleware's `next` is the rest of the\n * chain; an empty chain is `terminal`. A throwing middleware yields a\n * rejected promise.\n */\nexport function composeMiddleware(\n chain: readonly Middleware[],\n terminal: Next,\n): Next {\n const dispatch = async (\n index: number,\n ctx: RequestContext,\n ): Promise<Response> => {\n const middleware = chain[index];\n if (middleware === undefined) {\n return terminal(ctx);\n }\n return middleware(ctx, (next) => dispatch(index + 1, next));\n };\n return (ctx) => dispatch(0, ctx);\n}\n","/**\n * Error hierarchy: client-side errors and RFC 9457 problem details (ADR-0004).\n * Mirrors the Python SDK class for class.\n */\n\n/** Base class of every error this package throws on purpose. */\nexport class CrudError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = new.target.name;\n }\n}\n\n/** The call was refused before any request was sent. */\nexport class ClientError extends CrudError {}\n\n/** The resource does not support the operation (manifest capability or path missing). */\nexport class CapabilityError extends ClientError {}\n\n/** A filter, sort or paging argument is not valid for the resource. */\nexport class InvalidQueryError extends ClientError {}\n\n/**\n * A request carrying an `Authorization` header was about to go over plain\n * `http:` to a non-loopback host. Nothing was sent. Use `https:`, or opt in\n * with `allowInsecureHttp`.\n */\nexport class InsecureTransportError extends ClientError {}\n\n/** The discovery document or the manifest is missing, unusable or of an unknown version. */\nexport class ManifestError extends ClientError {}\n\n/** The manifest lists no such resource for this caller. */\nexport class UnknownResourceError extends ClientError {}\n\n/** A successful response whose body is not the JSON the client expects; `cause` holds the parse error. */\nexport class ResponseError extends CrudError {}\n\n/** The request never produced a response; `cause` holds the transport error. */\nexport class ConnectionFailed extends CrudError {}\n\n/** One normalized validation error (`422`). */\nexport interface ProblemDetail {\n readonly loc: readonly (string | number)[];\n readonly msg: string;\n readonly type: string;\n}\n\n/** Members of a {@link ProblemError}. */\nexport interface ProblemInit {\n readonly status: number;\n readonly title: string;\n readonly detail?: string | undefined;\n readonly type?: string | undefined;\n readonly instance?: string | undefined;\n readonly errors?: readonly ProblemDetail[] | undefined;\n readonly headers?: Headers | undefined;\n readonly response?: Response | undefined;\n}\n\nconst NO_TYPE = \"about:blank\";\n\n/** An error response, as RFC 9457 problem details. */\nexport class ProblemError extends CrudError {\n readonly status: number;\n readonly title: string;\n readonly detail: string | undefined;\n readonly type: string;\n readonly instance: string | undefined;\n readonly errors: readonly ProblemDetail[];\n readonly headers: Headers;\n readonly response: Response | undefined;\n\n constructor(init: ProblemInit) {\n const errors = init.errors ?? [];\n let message = `${init.status} ${init.title}`;\n if (init.detail) {\n message += `: ${init.detail}`;\n } else if (errors.length > 0) {\n message += `: ${errors.map((e) => `${e.loc.join(\".\")}: ${e.msg}`).join(\"; \")}`;\n }\n super(message);\n this.status = init.status;\n this.title = init.title;\n this.detail = init.detail;\n this.type = init.type ?? NO_TYPE;\n this.instance = init.instance;\n this.errors = errors;\n this.headers = init.headers ?? new Headers();\n this.response = init.response;\n }\n}\n\n/** 400. */\nexport class BadRequest extends ProblemError {}\n\n/** 401; `wwwAuthenticate` keeps the challenge. */\nexport class Unauthorized extends ProblemError {\n get wwwAuthenticate(): string | undefined {\n return this.headers.get(\"www-authenticate\") ?? undefined;\n }\n}\n\n/** 403. */\nexport class Forbidden extends ProblemError {}\n\n/** 404. */\nexport class NotFound extends ProblemError {}\n\n/** 412: a stale `If-Match`. */\nexport class PreconditionFailed extends ProblemError {}\n\n/** 422; `errors` holds normalized `{loc, msg, type}` entries. */\nexport class ValidationFailed extends ProblemError {}\n\n/** 423. */\nexport class Locked extends ProblemError {}\n\n/** 429; `retryAfter` is the `Retry-After` header in seconds, when it is a number. */\nexport class RateLimited extends ProblemError {\n get retryAfter(): number | undefined {\n const raw = this.headers.get(\"retry-after\");\n if (raw === null || raw.trim() === \"\") {\n return undefined;\n }\n const seconds = Number(raw);\n return Number.isFinite(seconds) && seconds >= 0 ? seconds : undefined;\n }\n}\n\n/** 5xx. */\nexport class ServerError extends ProblemError {}\n\nconst BY_STATUS: ReadonlyMap<number, typeof ProblemError> = new Map([\n [400, BadRequest],\n [401, Unauthorized],\n [403, Forbidden],\n [404, NotFound],\n [412, PreconditionFailed],\n [422, ValidationFailed],\n [423, Locked],\n [429, RateLimited],\n]);\n\n// Python's `http.HTTPStatus` phrases, so both SDKs synthesize the same title.\nconst PHRASES: ReadonlyMap<number, string> = new Map([\n [100, \"Continue\"],\n [101, \"Switching Protocols\"],\n [102, \"Processing\"],\n [103, \"Early Hints\"],\n [200, \"OK\"],\n [201, \"Created\"],\n [202, \"Accepted\"],\n [203, \"Non-Authoritative Information\"],\n [204, \"No Content\"],\n [205, \"Reset Content\"],\n [206, \"Partial Content\"],\n [207, \"Multi-Status\"],\n [208, \"Already Reported\"],\n [226, \"IM Used\"],\n [300, \"Multiple Choices\"],\n [301, \"Moved Permanently\"],\n [302, \"Found\"],\n [303, \"See Other\"],\n [304, \"Not Modified\"],\n [305, \"Use Proxy\"],\n [307, \"Temporary Redirect\"],\n [308, \"Permanent Redirect\"],\n [400, \"Bad Request\"],\n [401, \"Unauthorized\"],\n [402, \"Payment Required\"],\n [403, \"Forbidden\"],\n [404, \"Not Found\"],\n [405, \"Method Not Allowed\"],\n [406, \"Not Acceptable\"],\n [407, \"Proxy Authentication Required\"],\n [408, \"Request Timeout\"],\n [409, \"Conflict\"],\n [410, \"Gone\"],\n [411, \"Length Required\"],\n [412, \"Precondition Failed\"],\n [413, \"Content Too Large\"],\n [414, \"URI Too Long\"],\n [415, \"Unsupported Media Type\"],\n [416, \"Range Not Satisfiable\"],\n [417, \"Expectation Failed\"],\n [418, \"I'm a Teapot\"],\n [421, \"Misdirected Request\"],\n [422, \"Unprocessable Content\"],\n [423, \"Locked\"],\n [424, \"Failed Dependency\"],\n [425, \"Too Early\"],\n [426, \"Upgrade Required\"],\n [428, \"Precondition Required\"],\n [429, \"Too Many Requests\"],\n [431, \"Request Header Fields Too Large\"],\n [451, \"Unavailable For Legal Reasons\"],\n [500, \"Internal Server Error\"],\n [501, \"Not Implemented\"],\n [502, \"Bad Gateway\"],\n [503, \"Service Unavailable\"],\n [504, \"Gateway Timeout\"],\n [505, \"HTTP Version Not Supported\"],\n [506, \"Variant Also Negotiates\"],\n [507, \"Insufficient Storage\"],\n [508, \"Loop Detected\"],\n [510, \"Not Extended\"],\n [511, \"Network Authentication Required\"],\n]);\n\ntype Obj = Record<string, unknown>;\n\nconst isObject = (value: unknown): value is Obj =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nfunction normalizeErrors(items: readonly unknown[]): ProblemDetail[] {\n return items.map((item) => {\n if (isObject(item)) {\n return {\n loc: Array.isArray(item[\"loc\"])\n ? (item[\"loc\"] as (string | number)[])\n : [],\n msg: String(item[\"msg\"] ?? \"\"),\n type: String(item[\"type\"] ?? \"\"),\n };\n }\n return { loc: [], msg: String(item), type: \"\" };\n });\n}\n\n/**\n * Builds the matching `ProblemError` subclass from an error response. A body\n * that is not a JSON object yields a synthesized problem from the status\n * phrase. Reads a clone, so `response.body` stays readable.\n */\nexport async function problemFromResponse(\n response: Response,\n): Promise<ProblemError> {\n const status = response.status;\n const phrase = PHRASES.get(status) ?? \"Error\";\n let parsed: unknown;\n try {\n parsed = JSON.parse(await response.clone().text());\n } catch {\n parsed = undefined;\n }\n const body: Obj = isObject(parsed) ? parsed : {};\n const rawDetail = body[\"detail\"];\n const rawErrors = Array.isArray(rawDetail) ? rawDetail : body[\"errors\"];\n const Cls =\n BY_STATUS.get(status) ?? (status >= 500 ? ServerError : ProblemError);\n const instance = body[\"instance\"];\n return new Cls({\n status,\n title: String(body[\"title\"] || phrase),\n detail: typeof rawDetail === \"string\" ? rawDetail : undefined,\n type: String(body[\"type\"] || NO_TYPE),\n instance: typeof instance === \"string\" ? instance : undefined,\n errors: Array.isArray(rawErrors) ? normalizeErrors(rawErrors) : [],\n headers: response.headers,\n response,\n });\n}\n","/**\n * Typed models of the CRUD manifest (v1) and discovery via the api-catalog.\n * Members keep their wire names (`skip_param`, `max_age`, ...). Members this\n * version does not know are ignored, as the manifest spec requires.\n */\nimport { ManifestError } from \"./errors.ts\";\n\nexport const PROFILE = \"https://craftainer.github.io/schemas/crud-manifest/v1\";\nexport const CATALOG_PATH = \"/.well-known/api-catalog\";\n\n/** A JSON object. */\nexport type JsonObject = Record<string, unknown>;\n\n/** One filterable and sortable field. */\nexport interface FieldSpec {\n readonly name: string;\n readonly value_type: string;\n readonly filter_ops: readonly string[];\n readonly sortable: boolean;\n readonly choices: readonly string[] | null;\n readonly numeric: boolean;\n readonly categorical: boolean;\n readonly read_only: boolean;\n readonly required: boolean;\n}\n\n/** Offset paging parameters and bounds. */\nexport interface Pagination {\n readonly style: string;\n readonly skip_param: string;\n readonly limit_param: string;\n readonly sort_param: string;\n readonly default_limit: number;\n readonly max_limit: number;\n readonly total: boolean;\n}\n\n/** The SSE stream of a resource. */\nexport interface EventsSpec {\n readonly transport: string;\n readonly path: string;\n /** The server-side event label (not the manifest name). */\n readonly resource: string;\n readonly resume_param: string;\n readonly replay: string;\n readonly keepalive_seconds: number;\n readonly actions: readonly string[];\n}\n\n/** What the resource supports. */\nexport interface Capabilities {\n readonly bulk_update: boolean;\n readonly bulk_delete: boolean;\n readonly clone: boolean;\n readonly draft_publish: boolean;\n readonly archive_restore: boolean;\n readonly revisions: boolean;\n readonly events: EventsSpec | null;\n readonly stats: boolean;\n readonly predict: boolean;\n readonly conditional_requests: boolean;\n readonly owner_scoped: boolean;\n readonly schedulable: boolean;\n}\n\n/** Authentication scheme and roles. */\nexport interface AuthSpec {\n readonly scheme: string;\n readonly oidc_discovery_url: string | null;\n readonly public_read: boolean;\n readonly read_roles: readonly string[];\n readonly write_roles: readonly string[];\n readonly delete_roles: readonly string[];\n}\n\n/** The manifest `cache` hints of a resource. */\nexport interface CacheHints {\n readonly etag: boolean;\n readonly max_age: number;\n readonly stats_ttl: number | null;\n readonly stale_while_revalidate: number;\n readonly list_etag: string | null;\n readonly record_etag: string | null;\n readonly revalidate_only: boolean;\n}\n\n/** JSON Schemas of the record views (plain objects). */\nexport interface Schemas {\n readonly read: JsonObject;\n readonly create: JsonObject;\n readonly update: JsonObject;\n readonly draft: JsonObject | null;\n}\n\n/** One resource (`name` + `api_version`). */\nexport interface Resource {\n readonly name: string;\n readonly title: string;\n readonly api_version: string;\n readonly base_path: string;\n readonly formats: Readonly<Record<string, string>>;\n readonly id_field: string;\n readonly schemas: Schemas;\n readonly fields: readonly FieldSpec[];\n readonly pagination: Pagination;\n readonly capabilities: Capabilities;\n readonly paths: Readonly<Record<string, string>>;\n readonly bulk: { readonly max_matched: number };\n readonly auth: AuthSpec;\n readonly cache: CacheHints;\n}\n\n/** The manifest document, as filtered to the caller. */\nexport interface Manifest {\n readonly manifest_version: string;\n readonly service: { readonly name: string; readonly version: string };\n readonly resources: readonly Resource[];\n}\n\nconst isObject = (value: unknown): value is JsonObject =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nfunction bad(where: string, key: string, what: string): never {\n throw new ManifestError(`${where}.${key}: ${what}`);\n}\n\nfunction str(obj: JsonObject, key: string, where: string): string {\n const value = obj[key];\n return typeof value === \"string\"\n ? value\n : bad(where, key, \"missing or not a string\");\n}\n\nfunction bool(obj: JsonObject, key: string, where: string): boolean {\n const value = obj[key];\n return typeof value === \"boolean\"\n ? value\n : bad(where, key, \"missing or not a boolean\");\n}\n\nfunction num(obj: JsonObject, key: string, where: string): number {\n const value = obj[key];\n return typeof value === \"number\" && Number.isFinite(value)\n ? value\n : bad(where, key, \"missing or not a number\");\n}\n\nfunction int(obj: JsonObject, key: string, where: string): number {\n const value = num(obj, key, where);\n return Number.isInteger(value) ? value : bad(where, key, \"not an integer\");\n}\n\nfunction obj(parent: JsonObject, key: string, where: string): JsonObject {\n const value = parent[key];\n return isObject(value) ? value : bad(where, key, \"missing or not an object\");\n}\n\nfunction list(\n parent: JsonObject,\n key: string,\n where: string,\n): readonly unknown[] {\n const value = parent[key];\n return Array.isArray(value)\n ? value\n : bad(where, key, \"missing or not a list\");\n}\n\nfunction strs(\n parent: JsonObject,\n key: string,\n where: string,\n): readonly string[] {\n const items = list(parent, key, where);\n return items.every((item) => typeof item === \"string\")\n ? (items as readonly string[])\n : bad(where, key, \"expected a list of strings\");\n}\n\n/** A member that may be absent or `null`. */\nfunction opt<T>(\n parent: JsonObject,\n key: string,\n where: string,\n read: (parent: JsonObject, key: string, where: string) => T,\n): T | null {\n return parent[key] === undefined || parent[key] === null\n ? null\n : read(parent, key, where);\n}\n\nfunction stringMap(\n parent: JsonObject,\n key: string,\n where: string,\n): Record<string, string> {\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(obj(parent, key, where))) {\n if (typeof v === \"string\") {\n out[k] = v;\n }\n }\n return out;\n}\n\nfunction objects(parent: JsonObject, key: string, where: string): JsonObject[] {\n return list(parent, key, where).map((item, i) =>\n isObject(item) ? item : bad(`${where}.${key}`, `[${i}]`, \"not an object\"),\n );\n}\n\nfunction parseField(o: JsonObject, w: string): FieldSpec {\n return {\n name: str(o, \"name\", w),\n value_type: str(o, \"value_type\", w),\n filter_ops: strs(o, \"filter_ops\", w),\n sortable: bool(o, \"sortable\", w),\n choices: opt(o, \"choices\", w, strs),\n numeric: bool(o, \"numeric\", w),\n categorical: bool(o, \"categorical\", w),\n read_only: bool(o, \"read_only\", w),\n required: bool(o, \"required\", w),\n };\n}\n\nfunction parseEvents(o: JsonObject, w: string): EventsSpec {\n return {\n transport: str(o, \"transport\", w),\n path: str(o, \"path\", w),\n resource: str(o, \"resource\", w),\n resume_param: str(o, \"resume_param\", w),\n replay: str(o, \"replay\", w),\n keepalive_seconds: num(o, \"keepalive_seconds\", w),\n actions: strs(o, \"actions\", w),\n };\n}\n\nfunction parseCapabilities(o: JsonObject, w: string): Capabilities {\n return {\n bulk_update: bool(o, \"bulk_update\", w),\n bulk_delete: bool(o, \"bulk_delete\", w),\n clone: bool(o, \"clone\", w),\n draft_publish: bool(o, \"draft_publish\", w),\n archive_restore: bool(o, \"archive_restore\", w),\n revisions: bool(o, \"revisions\", w),\n events: opt(o, \"events\", w, (p, k, ww) =>\n parseEvents(obj(p, k, ww), `${ww}.${k}`),\n ),\n stats: bool(o, \"stats\", w),\n predict: bool(o, \"predict\", w),\n conditional_requests: bool(o, \"conditional_requests\", w),\n owner_scoped: bool(o, \"owner_scoped\", w),\n schedulable: bool(o, \"schedulable\", w),\n };\n}\n\nfunction parseResource(o: JsonObject, w: string): Resource {\n const schemas = obj(o, \"schemas\", w);\n const pagination = obj(o, \"pagination\", w);\n const auth = obj(o, \"auth\", w);\n const cache = obj(o, \"cache\", w);\n const sw = `${w}.schemas`;\n return {\n name: str(o, \"name\", w),\n title: str(o, \"title\", w),\n api_version: str(o, \"api_version\", w),\n base_path: str(o, \"base_path\", w),\n formats: stringMap(o, \"formats\", w),\n id_field: str(o, \"id_field\", w),\n schemas: {\n read: obj(schemas, \"read\", sw),\n create: obj(schemas, \"create\", sw),\n update: obj(schemas, \"update\", sw),\n draft: opt(schemas, \"draft\", sw, obj),\n },\n fields: objects(o, \"fields\", w).map((f, i) =>\n parseField(f, `${w}.fields[${i}]`),\n ),\n pagination: {\n style: str(pagination, \"style\", w),\n skip_param: str(pagination, \"skip_param\", w),\n limit_param: str(pagination, \"limit_param\", w),\n sort_param: str(pagination, \"sort_param\", w),\n default_limit: int(pagination, \"default_limit\", w),\n max_limit: int(pagination, \"max_limit\", w),\n total: bool(pagination, \"total\", w),\n },\n capabilities: parseCapabilities(\n obj(o, \"capabilities\", w),\n `${w}.capabilities`,\n ),\n paths: stringMap(o, \"paths\", w),\n bulk: { max_matched: int(obj(o, \"bulk\", w), \"max_matched\", `${w}.bulk`) },\n auth: {\n scheme: str(auth, \"scheme\", w),\n oidc_discovery_url: opt(auth, \"oidc_discovery_url\", w, str),\n public_read: bool(auth, \"public_read\", w),\n read_roles: strs(auth, \"read_roles\", w),\n write_roles: strs(auth, \"write_roles\", w),\n delete_roles: strs(auth, \"delete_roles\", w),\n },\n cache: {\n etag: bool(cache, \"etag\", w),\n max_age: int(cache, \"max_age\", w),\n stats_ttl: opt(cache, \"stats_ttl\", w, int),\n stale_while_revalidate: int(cache, \"stale_while_revalidate\", w),\n list_etag: opt(cache, \"list_etag\", w, str),\n record_etag: opt(cache, \"record_etag\", w, str),\n revalidate_only: bool(cache, \"revalidate_only\", w),\n },\n };\n}\n\n/** Parses a manifest document; unknown members are ignored, unknown versions refused. */\nexport function parseManifest(document: unknown): Manifest {\n if (!isObject(document)) {\n throw new ManifestError(\"the manifest is not a JSON object\");\n }\n const version = str(document, \"manifest_version\", \"manifest\");\n if (version !== \"1\") {\n throw new ManifestError(`unsupported manifest_version \"${version}\"`);\n }\n const service = obj(document, \"service\", \"manifest\");\n return {\n manifest_version: version,\n service: {\n name: str(service, \"name\", \"manifest.service\"),\n version: str(service, \"version\", \"manifest.service\"),\n },\n resources: objects(document, \"resources\", \"manifest\").map((r, i) =>\n parseResource(r, `resources[${i}]`),\n ),\n };\n}\n\n/**\n * The resource called `name`: the one with `apiVersion` when given, else the\n * highest `api_version` (`v2` beats `v1`); `undefined` when there is none.\n */\nexport function findResource(\n manifest: Manifest,\n name: string,\n apiVersion?: string,\n): Resource | undefined {\n // The manifest spec's `v<N>`; anything else (`v2beta`, `x5`, `next`) ranks lowest.\n const rank = (r: Resource): number =>\n Number(/^v(\\d+)$/.exec(r.api_version)?.[1] ?? 0);\n let best: Resource | undefined;\n for (const r of manifest.resources) {\n if (\n r.name === name &&\n (apiVersion === undefined || r.api_version === apiVersion)\n ) {\n if (best === undefined || rank(r) > rank(best)) {\n best = r;\n }\n }\n }\n return best;\n}\n\n/** The absolute manifest URL: the first `describedby` link with the manifest profile. */\nexport function manifestUrlFromCatalog(\n linkset: unknown,\n catalogUrl: string,\n): string {\n const entries = isObject(linkset) ? linkset[\"linkset\"] : undefined;\n for (const entry of Array.isArray(entries) ? entries : []) {\n const links = isObject(entry) ? entry[\"describedby\"] : undefined;\n for (const link of Array.isArray(links) ? links : []) {\n if (\n isObject(link) &&\n link[\"profile\"] === PROFILE &&\n typeof link[\"href\"] === \"string\"\n ) {\n const url = new URL(link[\"href\"], catalogUrl);\n if (url.origin !== new URL(catalogUrl).origin) {\n // The client sends its bearer token to this URL: stay on the server's origin.\n throw new ManifestError(\n `the api-catalog points at another origin (${url.origin}); pass manifestUrl to use it`,\n );\n }\n return url.href;\n }\n }\n }\n throw new ManifestError(\n `the api-catalog has no describedby link with profile ${PROFILE}`,\n );\n}\n\n/** Fetches a JSON document; `catalog` marks the api-catalog request (kept out of the manifest cache). */\nexport type GetJson = (url: string, catalog: boolean) => Promise<unknown>;\n\n/**\n * Loads and parses the manifest, via api-catalog discovery from `baseUrl` or\n * a direct `manifestUrl`.\n */\nexport async function loadManifest(\n getJson: GetJson,\n baseUrl: string,\n manifestUrl?: string,\n): Promise<Manifest> {\n let url = manifestUrl;\n if (url === undefined) {\n const catalogUrl = new URL(CATALOG_PATH, baseUrl).href;\n url = manifestUrlFromCatalog(await getJson(catalogUrl, true), catalogUrl);\n }\n return parseManifest(await getJson(url, false));\n}\n","/**\n * Query-string builder with `crud_query` semantics, validated against the\n * manifest fields. Produces the same bytes as the Python SDK.\n */\nimport { InvalidQueryError } from \"./errors.ts\";\nimport type { FieldSpec } from \"./manifest.ts\";\n\nconst MAX_REGEX_LENGTH = 200;\n\n/** The part of a manifest field the builder needs. */\nexport type QueryField = Pick<\n FieldSpec,\n \"name\" | \"value_type\" | \"filter_ops\" | \"sortable\" | \"choices\"\n>;\n\n/** Filter arguments: `field` (equality, emitted bare) or `field__op` -> value. */\nexport type Filters = Readonly<Record<string, unknown>>;\n\n/** `\"name,-other\"` or `[\"name\", \"-other\"]`. */\nexport type Sort = string | readonly string[];\n\n/** Everything {@link buildQuery} takes beside the fields. */\nexport interface QueryParams {\n readonly recordId?: number | undefined;\n readonly filters?: Filters | undefined;\n readonly sort?: Sort | undefined;\n readonly skip?: number | undefined;\n readonly limit?: number | undefined;\n readonly maxLimit?: number | undefined;\n readonly skipParam?: string | undefined;\n readonly limitParam?: string | undefined;\n readonly sortParam?: string | undefined;\n readonly includeArchived?: boolean | undefined;\n /**\n * Only rows with `archived_at` set (list only; implies `include_archived`).\n * Emitted only when `true`; combining `true` with `includeArchived: false`\n * throws `InvalidQueryError`, as the server answers 422.\n */\n readonly onlyArchived?: boolean | undefined;\n readonly includeUnpublished?: boolean | undefined;\n}\n\n/** Percent-encodes everything but the RFC 3986 unreserved characters `A-Za-z0-9-._~`. */\nexport function quote(text: string): string {\n return encodeURIComponent(text).replace(\n /[!'()*]/g,\n (c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`,\n );\n}\n\n/**\n * {@link quote} for caller input: a lone surrogate (an emoji cut in half)\n * cannot be UTF-8 encoded, which is an invalid argument, not a `URIError`.\n */\nfunction encode(text: string): string {\n try {\n return quote(text);\n } catch (error) {\n // `encodeURIComponent` throws only `URIError`.\n throw new InvalidQueryError(\n \"a query value is not well-formed Unicode (lone surrogate)\",\n { cause: error },\n );\n }\n}\n\n/** Joins already-stringified pairs, encoding keys and values. */\nexport function encodeParams(\n pairs: readonly (readonly [string, string])[],\n): string {\n return pairs.map(([k, v]) => `${encode(k)}=${encode(v)}`).join(\"&\");\n}\n\nfunction formatDatetime(value: Date): string | undefined {\n if (Number.isNaN(value.getTime())) {\n return undefined;\n }\n const iso = value.toISOString();\n if (iso.length !== 24) {\n return undefined; // expanded years (outside 0000-9999)\n }\n const millis = iso.slice(20, 23).replace(/0+$/, \"\");\n return millis === \"\"\n ? `${iso.slice(0, 19)}Z`\n : `${iso.slice(0, 19)}.${millis}Z`;\n}\n\nfunction formatDate(value: string): string | undefined {\n if (!/^\\d{4}-\\d{2}-\\d{2}$/.test(value)) {\n return undefined;\n }\n const parsed = new Date(`${value}T00:00:00Z`);\n return Number.isNaN(parsed.getTime()) ||\n parsed.toISOString().slice(0, 10) !== value\n ? undefined\n : value;\n}\n\nfunction scalarText(kind: string, value: unknown): string | undefined {\n switch (kind) {\n case \"integer\":\n return typeof value === \"number\" && Number.isSafeInteger(value)\n ? String(value)\n : undefined;\n case \"number\":\n return typeof value === \"number\" && Number.isFinite(value)\n ? String(value)\n : undefined;\n case \"boolean\":\n return typeof value === \"boolean\" ? String(value) : undefined;\n case \"date\":\n return typeof value === \"string\" ? formatDate(value) : undefined;\n case \"datetime\":\n return value instanceof Date ? formatDatetime(value) : undefined;\n default:\n return typeof value === \"string\" ? value : undefined;\n }\n}\n\n/**\n * Wire form of one value for `field`; throws `InvalidQueryError` on a type\n * mismatch. Dates are `YYYY-MM-DD` strings, datetimes `Date`s (UTC, with\n * millisecond precision, trailing zeros trimmed).\n */\nexport function formatScalar(field: QueryField, value: unknown): string {\n const text = scalarText(field.value_type, value);\n if (text === undefined) {\n throw new InvalidQueryError(\n `field \"${field.name}\" (${field.value_type}) cannot take ${String(value)}`,\n );\n }\n if (\n field.value_type === \"enum\" &&\n field.choices !== null &&\n !field.choices.includes(text)\n ) {\n throw new InvalidQueryError(\n `field \"${field.name}\" accepts only ${JSON.stringify(field.choices)}, not \"${text}\"`,\n );\n }\n return text;\n}\n\nfunction filterPair(\n field: QueryField,\n op: string,\n value: unknown,\n): [string, string] {\n const key = op === \"eq\" ? field.name : `${field.name}__${op}`;\n if (op === \"in\") {\n if (!Array.isArray(value) || value.length === 0) {\n throw new InvalidQueryError(`\"${key}\" takes a non-empty array`);\n }\n const parts = value.map((item: unknown) => formatScalar(field, item));\n if (parts.some((part) => part.includes(\",\"))) {\n throw new InvalidQueryError(\n `\"${key}\": a value contains a comma, which separates the list`,\n );\n }\n return [key, parts.map((part) => encode(part)).join(\",\")];\n }\n const text = formatScalar(field, value);\n if (op === \"regex\" && [...text].length > MAX_REGEX_LENGTH) {\n throw new InvalidQueryError(\n `\"${key}\": a regex is limited to ${MAX_REGEX_LENGTH} characters`,\n );\n }\n return [key, encode(text)];\n}\n\nconst compare = (a: string, b: string): number => (a < b ? -1 : a > b ? 1 : 0);\n\nfunction filterPairs(\n fields: ReadonlyMap<string, QueryField>,\n filters: Filters,\n): [string, string][] {\n const parsed = new Map<\n string,\n { name: string; op: string; pair: [string, string] }\n >();\n for (const [rawKey, value] of Object.entries(filters)) {\n const at = rawKey.lastIndexOf(\"__\");\n const name = at < 0 ? rawKey : rawKey.slice(0, at);\n const op = at < 0 ? \"eq\" : rawKey.slice(at + 2);\n const field = fields.get(name);\n if (field === undefined) {\n throw new InvalidQueryError(`unknown filter field \"${name}\"`);\n }\n if (!field.filter_ops.includes(op)) {\n throw new InvalidQueryError(\n `field \"${name}\" does not support the \"${op}\" operator`,\n );\n }\n if (name === \"id\" && op === \"eq\") {\n throw new InvalidQueryError(\n \"filter on id with recordId, not an equality filter\",\n );\n }\n const id = `${name}\\u0000${op}`;\n if (parsed.has(id)) {\n throw new InvalidQueryError(`filter \"${name}\" \"${op}\" given twice`);\n }\n parsed.set(id, { name, op, pair: filterPair(field, op, value) });\n }\n return [...parsed.values()]\n .sort((a, b) => compare(a.name, b.name) || compare(a.op, b.op))\n .map((entry) => entry.pair);\n}\n\nfunction sortValue(\n fields: ReadonlyMap<string, QueryField>,\n sort: Sort,\n): string {\n const parts = typeof sort === \"string\" ? sort.split(\",\") : sort;\n const out = parts.map((part) => {\n const name = part.startsWith(\"-\") ? part.slice(1) : part;\n const field = fields.get(name);\n if (field === undefined || !field.sortable) {\n throw new InvalidQueryError(`cannot sort by \"${name}\"`);\n }\n return encode(part);\n });\n if (out.length === 0) {\n throw new InvalidQueryError(\"sort is empty\");\n }\n return out.join(\",\");\n}\n\nfunction intArg(name: string, value: unknown, minimum: number): string {\n if (\n typeof value !== \"number\" ||\n !Number.isSafeInteger(value) ||\n value < minimum\n ) {\n throw new InvalidQueryError(`${name} must be an integer >= ${minimum}`);\n }\n return String(value);\n}\n\n/**\n * The query string (no leading `?`) for a list, get or bulk call. Order of\n * parameters: `id`, filters sorted by (field, operator), sort, skip, limit,\n * `include_archived`, `only_archived`, `include_unpublished`. The sort/skip/limit names are\n * `sortParam`/`skipParam`/`limitParam` (the manifest's `pagination`); the\n * `id` parameter is always `id`. Flags are emitted whenever they are not\n * `undefined`, except `only_archived`, which is emitted only when `true`\n * (absent means false; it is a reserved key, not a filter).\n */\nexport function buildQuery(\n fields: readonly QueryField[],\n params: QueryParams = {},\n): string {\n if (params.onlyArchived === true && params.includeArchived === false) {\n throw new InvalidQueryError(\n \"onlyArchived cannot be combined with includeArchived: false\",\n );\n }\n const byName = new Map(fields.map((f) => [f.name, f]));\n const parts: string[] = [];\n if (params.recordId !== undefined) {\n parts.push(`id=${intArg(\"recordId\", params.recordId, 0)}`);\n }\n for (const [key, value] of filterPairs(byName, params.filters ?? {})) {\n parts.push(`${encode(key)}=${value}`); // values arrive encoded; `in` keeps its commas\n }\n if (params.sort !== undefined) {\n parts.push(\n `${encode(params.sortParam ?? \"sort\")}=${sortValue(byName, params.sort)}`,\n );\n }\n if (params.skip !== undefined) {\n parts.push(\n `${encode(params.skipParam ?? \"skip\")}=${intArg(\"skip\", params.skip, 0)}`,\n );\n }\n if (params.limit !== undefined) {\n const text = intArg(\"limit\", params.limit, 1);\n if (params.maxLimit !== undefined && params.limit > params.maxLimit) {\n throw new InvalidQueryError(\n `limit ${params.limit} exceeds the server maximum ${params.maxLimit}`,\n );\n }\n parts.push(`${encode(params.limitParam ?? \"limit\")}=${text}`);\n }\n if (params.includeArchived !== undefined) {\n parts.push(`include_archived=${params.includeArchived}`);\n }\n if (params.onlyArchived === true) {\n parts.push(\"only_archived=true\");\n }\n if (params.includeUnpublished !== undefined) {\n parts.push(`include_unpublished=${params.includeUnpublished}`);\n }\n return parts.join(\"&\");\n}\n","/** Fetch client: manifest-driven resource handles over a middleware chain. */\nimport { cacheScope as tokenScope, isInsecureRemote } from \"./auth.ts\";\nimport {\n CapabilityError,\n ClientError,\n ConnectionFailed,\n InsecureTransportError,\n InvalidQueryError,\n ManifestError,\n ResponseError,\n UnknownResourceError,\n problemFromResponse,\n} from \"./errors.ts\";\nimport { composeMiddleware } from \"./interfaces.ts\";\nimport type { Middleware, Op, TokenProvider } from \"./interfaces.ts\";\nimport { findResource, loadManifest } from \"./manifest.ts\";\nimport type { JsonObject, Manifest, Resource } from \"./manifest.ts\";\nimport { buildQuery, encodeParams } from \"./query.ts\";\nimport type { Filters, QueryParams, Sort } from \"./query.ts\";\n\n/** Per-call options. */\nexport interface RequestOptions {\n readonly signal?: AbortSignal | undefined;\n}\n\n/**\n * Options of `list` and `iterAll`. `onlyArchived: true` returns only archived\n * rows (it implies `includeArchived`; with `includeArchived: false` the call\n * throws `InvalidQueryError` before any request). Non-archivable resources\n * ignore it.\n */\nexport interface ListOptions extends RequestOptions {\n readonly filters?: Filters | undefined;\n readonly sort?: Sort | undefined;\n readonly skip?: number | undefined;\n readonly limit?: number | undefined;\n readonly includeArchived?: boolean | undefined;\n readonly onlyArchived?: boolean | undefined;\n readonly includeUnpublished?: boolean | undefined;\n}\n\n/** Options of `update` and `delete`: `ifMatch` is an ETag (`412` when stale). */\nexport interface WriteOptions extends RequestOptions {\n readonly ifMatch?: string | undefined;\n}\n\n/** Options of `deleteMany`. */\nexport interface DeleteManyOptions extends RequestOptions {\n readonly includeUnpublished?: boolean | undefined;\n}\n\n/** Options of `stats`. There is no `onlyArchived` (the server rejects it on `/stats`). */\nexport interface StatsOptions extends RequestOptions {\n readonly bucket?: string | undefined;\n readonly includeArchived?: boolean | undefined;\n readonly includeUnpublished?: boolean | undefined;\n}\n\n/** Options of `predict`. */\nexport interface PredictOptions extends RequestOptions {\n readonly field?: string | undefined;\n readonly periods?: number | undefined;\n readonly bucket?: string | undefined;\n}\n\n/** Options of `restore`: exactly one of `id` and `filters`. */\nexport interface RestoreOptions extends RequestOptions {\n readonly id?: number | undefined;\n readonly filters?: Filters | undefined;\n}\n\n/** The result of a bulk call. */\nexport interface BulkResult {\n readonly matched: number;\n readonly ids: readonly number[];\n}\n\nexport interface Call {\n readonly method: \"GET\" | \"POST\" | \"PATCH\" | \"DELETE\";\n readonly url: string;\n readonly op: Op;\n readonly resource: string | undefined;\n readonly recordId: number | undefined;\n readonly apiVersion: string | null;\n readonly json?: unknown;\n readonly headers?: Readonly<Record<string, string>>;\n}\n\n/** What a {@link ResourceClient} needs from its client. */\nexport interface Transport {\n json(call: Call, signal: AbortSignal | undefined): Promise<unknown>;\n none(call: Call, signal: AbortSignal | undefined): Promise<void>;\n}\n\n/**\n * The origins of `allowedOrigins`, normalised (`https://a.example:443` and\n * `https://a.example` are one). Anything that is not an http(s) origin is a\n * configuration error.\n */\nfunction normalizeOrigins(origins: readonly string[]): ReadonlySet<string> {\n const out = new Set<string>();\n for (const value of origins) {\n let origin: string | undefined;\n try {\n const url = new URL(value);\n origin =\n (url.protocol === \"http:\" || url.protocol === \"https:\") &&\n url.origin !== \"null\"\n ? url.origin\n : undefined;\n } catch {\n origin = undefined;\n }\n if (origin === undefined) {\n throw new ClientError(\n `allowedOrigins entry \"${value}\" is not an http(s) origin`,\n );\n }\n out.add(origin);\n }\n return out;\n}\n\n/** Builds the requests of one resource. */\nclass Plan {\n readonly #baseUrl: string;\n readonly #origins: ReadonlySet<string>;\n readonly resource: Resource;\n\n constructor(\n baseUrl: string,\n resource: Resource,\n allowedOrigins: ReadonlySet<string>,\n ) {\n this.#baseUrl = baseUrl;\n this.#origins = new Set([...allowedOrigins, new URL(baseUrl).origin]);\n this.resource = resource;\n }\n\n /**\n * Resolves a manifest-supplied path against `baseUrl`. The client sends its\n * bearer token there, so a path that leaves baseUrl's origin (an absolute\n * URL or a protocol-relative `//host`) is refused unless the client lists\n * that origin in `allowedOrigins`.\n */\n #url(path: string): string {\n const url = new URL(path, this.#baseUrl);\n if (!this.#origins.has(url.origin)) {\n throw new ManifestError(\n `resource \"${this.resource.name}\": the manifest path \"${path}\" points at another origin (${url.origin}), ` +\n \"where the token would follow; pass allowedOrigins to the client to allow it\",\n );\n }\n return url.href;\n }\n\n #call(\n method: Call[\"method\"],\n op: Op,\n path: string,\n query = \"\",\n extra: {\n recordId?: number | undefined;\n json?: unknown;\n ifMatch?: string | undefined;\n } = {},\n ): Call {\n const url = this.#url(path) + (query === \"\" ? \"\" : `?${query}`);\n return {\n method,\n url,\n op,\n resource: this.resource.name,\n recordId: extra.recordId,\n apiVersion: this.resource.api_version,\n ...(extra.json === undefined ? {} : { json: extra.json }),\n ...(extra.ifMatch === undefined\n ? {}\n : { headers: { \"If-Match\": extra.ifMatch } }),\n };\n }\n\n #query(params: QueryParams = {}): string {\n const paging = this.resource.pagination;\n return buildQuery(this.resource.fields, {\n maxLimit: paging.max_limit,\n skipParam: paging.skip_param,\n limitParam: paging.limit_param,\n sortParam: paging.sort_param,\n ...params,\n });\n }\n\n #subPath(key: string, supported: boolean): string {\n const path = this.resource.paths[key];\n if (!supported || path === undefined) {\n throw new CapabilityError(\n `resource \"${this.resource.name}\" does not support ${key}`,\n );\n }\n return path;\n }\n\n #need(supported: boolean, what: string): void {\n if (!supported) {\n throw new CapabilityError(\n `resource \"${this.resource.name}\" does not support ${what}`,\n );\n }\n }\n\n #bulkFilters(\n filters: Filters,\n includeUnpublished?: boolean | undefined,\n ): string {\n if (Object.keys(filters).length === 0) {\n throw new InvalidQueryError(\"a bulk operation needs at least one filter\");\n }\n return this.#query({ filters, includeUnpublished });\n }\n\n get #base(): string {\n return this.resource.base_path;\n }\n\n eventsUrl(): string {\n const events = this.resource.capabilities.events;\n if (events === null) {\n throw new CapabilityError(\n `resource \"${this.resource.name}\" does not support events`,\n );\n }\n return this.#url(events.path);\n }\n\n list(o: ListOptions): Call {\n const query = this.#query({\n filters: o.filters,\n sort: o.sort,\n skip: o.skip,\n limit: o.limit,\n includeArchived: o.includeArchived,\n onlyArchived: o.onlyArchived,\n includeUnpublished: o.includeUnpublished,\n });\n return this.#call(\"GET\", \"list\", this.#base, query);\n }\n\n get(id: number): Call {\n return this.#call(\n \"GET\",\n \"record\",\n this.#base,\n this.#query({ recordId: id }),\n {\n recordId: id,\n },\n );\n }\n\n create(data: unknown): Call {\n return this.#call(\"POST\", \"create\", this.#base, \"\", { json: data });\n }\n\n update(id: number, data: unknown, ifMatch: string | undefined): Call {\n return this.#call(\n \"PATCH\",\n \"update\",\n this.#base,\n this.#query({ recordId: id }),\n {\n recordId: id,\n json: data,\n ifMatch,\n },\n );\n }\n\n updateMany(filters: Filters, data: unknown): Call {\n this.#need(this.resource.capabilities.bulk_update, \"bulk_update\");\n return this.#call(\n \"PATCH\",\n \"bulk_update\",\n this.#base,\n this.#bulkFilters(filters),\n {\n json: data,\n },\n );\n }\n\n delete(id: number, ifMatch: string | undefined): Call {\n return this.#call(\n \"DELETE\",\n \"delete\",\n this.#base,\n this.#query({ recordId: id }),\n {\n recordId: id,\n ifMatch,\n },\n );\n }\n\n deleteMany(filters: Filters, includeUnpublished?: boolean | undefined): Call {\n this.#need(this.resource.capabilities.bulk_delete, \"bulk_delete\");\n return this.#call(\n \"DELETE\",\n \"bulk_delete\",\n this.#base,\n this.#bulkFilters(filters, includeUnpublished),\n );\n }\n\n restore(id: number | undefined, filters: Filters | undefined): Call {\n const path = this.#subPath(\n \"restore\",\n this.resource.capabilities.archive_restore,\n );\n if ((id === undefined) === (filters === undefined)) {\n throw new InvalidQueryError(\n \"restore takes exactly one of id and filters\",\n );\n }\n const query =\n filters === undefined\n ? this.#query({ recordId: id })\n : this.#bulkFilters(filters);\n return this.#call(\"POST\", \"restore\", path, query, { recordId: id });\n }\n\n stats(o: StatsOptions): Call {\n const path = this.#subPath(\"stats\", this.resource.capabilities.stats);\n const pairs: [string, string][] =\n o.bucket === undefined ? [] : [[\"bucket\", o.bucket]];\n if (o.includeArchived !== undefined) {\n pairs.push([\"include_archived\", String(o.includeArchived)]);\n }\n if (o.includeUnpublished !== undefined) {\n pairs.push([\"include_unpublished\", String(o.includeUnpublished)]);\n }\n return this.#call(\"GET\", \"stats\", path, encodeParams(pairs));\n }\n\n predict(o: PredictOptions): Call {\n const path = this.#subPath(\"predict\", this.resource.capabilities.predict);\n const pairs: [string, string][] = [];\n if (o.field !== undefined) {\n const spec = this.resource.fields.find((f) => f.name === o.field);\n if (spec === undefined || !spec.numeric) {\n throw new InvalidQueryError(\n `cannot predict \"${o.field}\": not a numeric field`,\n );\n }\n pairs.push([\"field\", o.field]);\n }\n if (o.periods !== undefined) {\n if (!Number.isSafeInteger(o.periods) || o.periods < 1) {\n throw new InvalidQueryError(\"periods must be an integer >= 1\");\n }\n pairs.push([\"periods\", String(o.periods)]);\n }\n if (o.bucket !== undefined) {\n pairs.push([\"bucket\", o.bucket]);\n }\n return this.#call(\"GET\", \"predict\", path, encodeParams(pairs));\n }\n\n clone(id: number): Call {\n const path = this.#subPath(\"clone\", this.resource.capabilities.clone);\n return this.#call(\"POST\", \"clone\", path, this.#query({ recordId: id }), {\n recordId: id,\n });\n }\n\n draft(data: unknown): Call {\n const path = this.#subPath(\n \"draft\",\n this.resource.capabilities.draft_publish,\n );\n return this.#call(\"POST\", \"draft\", path, \"\", { json: data });\n }\n\n publish(id: number): Call {\n const path = this.#subPath(\n \"publish\",\n this.resource.capabilities.draft_publish,\n );\n return this.#call(\"POST\", \"publish\", path, this.#query({ recordId: id }), {\n recordId: id,\n });\n }\n\n filters(): Call {\n return this.#call(\"GET\", \"filters\", this.#subPath(\"filters\", true));\n }\n\n revisions(id: number): Call {\n const path = this.#subPath(\n \"revisions\",\n this.resource.capabilities.revisions,\n );\n return this.#call(\"GET\", \"revisions\", path, this.#query({ recordId: id }), {\n recordId: id,\n });\n }\n}\n\n/**\n * Operations on one resource. The type parameters are the record views;\n * `crud-sdk-codegen` writes interfaces to pass for them (they are not\n * checked against the manifest at runtime).\n */\nexport class ResourceClient<\n Read extends object = JsonObject,\n Create extends object = JsonObject,\n Update extends object = JsonObject,\n> {\n /** The manifest entry this handle is bound to. */\n readonly resource: Resource;\n readonly #plan: Plan;\n readonly #transport: Transport;\n\n /** Use `CrudClient.resource`. */\n constructor(\n baseUrl: string,\n resource: Resource,\n transport: Transport,\n allowedOrigins: readonly string[] = [],\n ) {\n this.resource = resource;\n this.#plan = new Plan(baseUrl, resource, normalizeOrigins(allowedOrigins));\n this.#transport = transport;\n }\n\n async #one<T>(call: Call, options: RequestOptions): Promise<T> {\n const body = await this.#transport.json(call, options.signal);\n if (typeof body !== \"object\" || body === null || Array.isArray(body)) {\n throw new ResponseError(\n `${call.method} ${call.url}: expected a JSON object, got ${shapeOf(body)}`,\n );\n }\n return body as T;\n }\n\n async #many<T>(call: Call, options: RequestOptions): Promise<T[]> {\n const body = await this.#transport.json(call, options.signal);\n if (!Array.isArray(body)) {\n throw new ResponseError(\n `${call.method} ${call.url}: expected a JSON array, got ${shapeOf(body)}`,\n );\n }\n return body as T[];\n }\n\n /** One page of records. */\n async list(options: ListOptions = {}): Promise<Read[]> {\n return this.#many(this.#plan.list(options), options);\n }\n\n /** Every record, paging with `skip += limit` until a page shorter than `limit`. */\n async *iterAll(\n options: ListOptions = {},\n ): AsyncGenerator<Read, void, undefined> {\n const { default_limit: fallback, max_limit: cap } =\n this.resource.pagination;\n const size = options.limit ?? Math.min(fallback, cap);\n let skip = options.skip ?? 0;\n for (;;) {\n const page = await this.list({ ...options, skip, limit: size });\n yield* page;\n if (page.length < size) {\n return;\n }\n skip += size;\n }\n }\n\n /** One record. */\n async get(id: number, options: RequestOptions = {}): Promise<Read> {\n return this.#one(this.#plan.get(id), options);\n }\n\n /** Creates a record. */\n async create(data: Create, options: RequestOptions = {}): Promise<Read> {\n return this.#one(this.#plan.create(data), options);\n }\n\n /** Patches one record; `ifMatch` is an ETag (`412` when stale). */\n async update(\n id: number,\n data: Update,\n options: WriteOptions = {},\n ): Promise<Read> {\n return this.#one(this.#plan.update(id, data, options.ifMatch), options);\n }\n\n /** Patches every record matching `filters`. */\n async updateMany(\n filters: Filters,\n data: Update,\n options: RequestOptions = {},\n ): Promise<BulkResult> {\n return this.#one(this.#plan.updateMany(filters, data), options);\n }\n\n /** Deletes one record; `ifMatch` as for `update`. */\n async delete(id: number, options: WriteOptions = {}): Promise<void> {\n await this.#transport.none(\n this.#plan.delete(id, options.ifMatch),\n options.signal,\n );\n }\n\n /**\n * Deletes every record matching `filters`. `includeUnpublished: false`\n * leaves not-yet/no-longer-published rows alone; it is sent only when\n * given (needs a server with the BD1 bulk-delete support, older ones ignore it).\n */\n async deleteMany(\n filters: Filters,\n options: DeleteManyOptions = {},\n ): Promise<BulkResult> {\n return this.#one(\n this.#plan.deleteMany(filters, options.includeUnpublished),\n options,\n );\n }\n\n /** Restores archived records, by `id` or by `filters`. */\n async restore(options: RestoreOptions): Promise<BulkResult> {\n return this.#one(this.#plan.restore(options.id, options.filters), options);\n }\n\n /** Aggregates over the resource. */\n async stats(options: StatsOptions = {}): Promise<JsonObject> {\n return this.#one(this.#plan.stats(options), options);\n }\n\n /** A forecast. */\n async predict(options: PredictOptions = {}): Promise<JsonObject> {\n return this.#one(this.#plan.predict(options), options);\n }\n\n /** Copies a record; returns the copy. */\n async clone(id: number, options: RequestOptions = {}): Promise<Read> {\n return this.#one(this.#plan.clone(id), options);\n }\n\n /** Creates a draft (needs `draft_publish`). */\n async createDraft(data: Create, options: RequestOptions = {}): Promise<Read> {\n return this.#one(this.#plan.draft(data), options);\n }\n\n /** Publishes a draft (needs `draft_publish`). */\n async publish(id: number, options: RequestOptions = {}): Promise<Read> {\n return this.#one(this.#plan.publish(id), options);\n }\n\n /** The server's filter metadata (`kind` instead of `value_type`). */\n async filters(options: RequestOptions = {}): Promise<JsonObject[]> {\n return this.#many(this.#plan.filters(), options);\n }\n\n /** Revisions of one record, newest first. */\n async revisions(\n id: number,\n options: RequestOptions = {},\n ): Promise<JsonObject[]> {\n return this.#many(this.#plan.revisions(id), options);\n }\n\n /** Absolute URL of the resource's SSE stream. */\n eventsUrl(): string {\n return this.#plan.eventsUrl();\n }\n}\n\n/** Options of {@link createClient}. */\nexport interface ClientOptions {\n /** The server origin (or any URL on it). */\n readonly baseUrl: string;\n /** The network `fetch`; defaults to `globalThis.fetch`. */\n readonly fetch?: typeof fetch | undefined;\n /** Returns the bearer token; called again with `refresh: true` once after a `401`. */\n readonly tokenProvider?: TokenProvider | undefined;\n /**\n * The cache scope of the caller, for sessions that carry no bearer token\n * (a cookie session behind a BFF). A string, or a function (sync or async)\n * evaluated per request (and reused across that request's 401 retry), plus\n * once per `scope()` call; return the same value for the same caller (for example the OIDC `sub`). It must be non-empty. When given it\n * REPLACES the token-hash / `\"anon\"` scope, even if a `tokenProvider` is also\n * set (the token still authenticates; it no longer selects the scope), and\n * the `./cache` middleware keys by it instead of the Authorization header.\n * Change what it returns on login or logout and nothing cached for the\n * previous caller is visible.\n */\n readonly cacheScope?: string | (() => string | Promise<string>) | undefined;\n /**\n * Passed to every `fetch` as `RequestInit.credentials` (`\"same-origin\"`\n * sends the session cookie to a same-origin `baseUrl`). Default: the\n * platform's (`\"same-origin\"`). `\"include\"` over plain `http:` to a\n * non-loopback host is refused with {@link InsecureTransportError}.\n */\n readonly credentials?: NonNullable<RequestInit[\"credentials\"]> | undefined;\n /**\n * Called (and awaited) on each final `401` response, after the\n * `tokenProvider` refresh retry (if any) has failed to help; manifest and\n * discovery requests included. A client call that makes several requests\n * can fire it more than once, so make it idempotent (for example a\n * navigation). It gets a clone of the response, so its body may be read.\n * The call still rejects with `Unauthorized` afterwards; if the callback\n * throws, its error is the `Unauthorized`'s `cause` (or, when the problem\n * already has a `cause`, a non-enumerable `onUnauthorizedError` property).\n * Typical use: navigate to the login page.\n */\n readonly onUnauthorized?:\n ((response: Response) => void | Promise<void>) | undefined;\n /** Outermost first; see `composeMiddleware`. */\n readonly middleware?: readonly Middleware[] | undefined;\n /** Skips api-catalog discovery. */\n readonly manifestUrl?: string | undefined;\n /**\n * Stable identity of this client in TanStack query keys. Defaults to\n * `baseUrl`; set it when two clients share a `baseUrl` but must not share\n * cached data, and keep it constant across reloads of a persisted cache.\n */\n readonly id?: string | undefined;\n /**\n * Exact origins (`https://files.example`) that manifest-supplied\n * `base_path`, `paths.*` and `events.path` may resolve to besides\n * `baseUrl`'s own. By default such a URL (absolute or protocol-relative) is\n * refused with a `ManifestError`, because the token would follow it. For\n * split-origin deployments only.\n */\n readonly allowedOrigins?: readonly string[] | undefined;\n /**\n * Allow sending an `Authorization` header (the bearer token), or cookies\n * (`credentials: \"include\"`), over plain `http:` to a\n * host that is not loopback. Default `false`: such a request is refused\n * with {@link InsecureTransportError} before it is sent.\n * Loopback (`localhost`, `*.localhost`, `127.0.0.0/8`, `[::1]`) and\n * anonymous requests without credentials are always allowed. Opt in only for a trusted\n * network, as the token is readable on the wire.\n */\n readonly allowInsecureHttp?: boolean | undefined;\n}\n\nfunction shapeOf(body: unknown): string {\n if (body === undefined) {\n return \"no body\";\n }\n return body === null\n ? \"null\"\n : Array.isArray(body)\n ? \"an array\"\n : typeof body;\n}\n\n/** Discovers the manifest and hands out {@link ResourceClient}s. */\nexport class CrudClient {\n readonly baseUrl: string;\n /** Stable identity in TanStack query keys (`ClientOptions.id`, else `baseUrl`). */\n readonly id: string;\n readonly #fetch: typeof fetch | undefined;\n readonly #tokenProvider: TokenProvider | undefined;\n readonly #cacheScope: ClientOptions[\"cacheScope\"];\n readonly #credentials: NonNullable<RequestInit[\"credentials\"]> | undefined;\n readonly #onUnauthorized: ClientOptions[\"onUnauthorized\"];\n readonly #middleware: Middleware[];\n readonly #manifestUrl: string | undefined;\n readonly #allowedOrigins: readonly string[];\n readonly #allowInsecureHttp: boolean;\n readonly #manifests = new Map<string, Promise<Manifest>>();\n /** The newest `refresh: true` load per scope, until it settles. */\n readonly #refreshes = new Map<string, Promise<Manifest>>();\n readonly #transport: Transport;\n\n constructor(options: ClientOptions) {\n this.baseUrl = options.baseUrl;\n this.id = options.id ?? options.baseUrl;\n this.#fetch = options.fetch;\n this.#tokenProvider = options.tokenProvider;\n this.#cacheScope = options.cacheScope;\n this.#credentials = options.credentials;\n this.#onUnauthorized = options.onUnauthorized;\n this.#middleware = [...(options.middleware ?? [])];\n this.#manifestUrl = options.manifestUrl;\n this.#allowedOrigins = [...(options.allowedOrigins ?? [])];\n this.#allowInsecureHttp = options.allowInsecureHttp ?? false;\n normalizeOrigins(this.#allowedOrigins); // fail at createClient, not at the first call\n this.#transport = {\n json: async (call, signal) => {\n const response = await this.#send(call, signal);\n if (response.status === 204) {\n return undefined;\n }\n try {\n return (await response.json()) as unknown;\n } catch (error) {\n throw new ResponseError(\n `${call.method} ${call.url}: the ${response.status} response body is not valid JSON`,\n { cause: error },\n );\n }\n },\n none: async (call, signal) => {\n await (await this.#send(call, signal)).body?.cancel();\n },\n };\n }\n\n /** Adds middleware after the existing ones (innermost); it sees every later request. */\n use(middleware: Middleware): this {\n this.#middleware.push(middleware);\n return this;\n }\n\n async #token(refresh: boolean): Promise<string | null> {\n // An empty token sends no header, so it is anonymous for the scope too.\n return (await this.#tokenProvider?.({ refresh })) || null;\n }\n\n /** The current bearer token, or `null` when anonymous. */\n token(refresh = false): Promise<string | null> {\n return this.#token(refresh);\n }\n\n /**\n * The `cacheScope` option, evaluated once, validated and namespaced\n * (`s:` + the percent-encoded value, so it can never equal `anon` or a token\n * hash and adds no key segments); `undefined` when the option is not used.\n * The prefix is internal.\n */\n async #explicitScope(): Promise<string | undefined> {\n if (this.#cacheScope === undefined) {\n return undefined;\n }\n const value: unknown =\n typeof this.#cacheScope === \"function\"\n ? await this.#cacheScope()\n : this.#cacheScope;\n if (typeof value !== \"string\" || value === \"\") {\n throw new ClientError(\"cacheScope must resolve to a non-empty string\");\n }\n return `s:${encodeURIComponent(value)}`;\n }\n\n /**\n * The cache scope of the current caller: the `cacheScope` option (opaque,\n * namespaced; the `tokenProvider` is not called), else `\"anon\"` or a hash of\n * the token.\n */\n async scope(): Promise<string> {\n return (\n (await this.#explicitScope()) ?? tokenScope(await this.#token(false))\n );\n }\n\n /** The `{ client, scope }` namespace the `./tanstack` key factory takes. */\n async namespace(): Promise<{\n readonly client: string;\n readonly scope: string;\n }> {\n return { client: this.id, scope: await this.scope() };\n }\n\n async #dispatch(\n call: Call,\n token: string | null,\n explicit: string | undefined,\n signal: AbortSignal | undefined,\n ): Promise<Response> {\n const headers = new Headers({\n Accept: \"application/json\",\n ...call.headers,\n });\n if (token !== null) {\n headers.set(\"Authorization\", `Bearer ${token}`);\n }\n const init: RequestInit = {\n method: call.method,\n headers,\n signal: signal ?? null,\n ...(this.#credentials === undefined\n ? {}\n : { credentials: this.#credentials }),\n };\n if (call.json !== undefined) {\n headers.set(\"Content-Type\", \"application/json\");\n init.body = JSON.stringify(call.json);\n }\n const request = new Request(call.url, init);\n const terminal = async (ctx: {\n readonly request: Request;\n }): Promise<Response> => {\n // Judged on the request as it is sent, so a middleware that rewrites the\n // URL or sets its own Authorization is covered too.\n if (\n !this.#allowInsecureHttp &&\n (ctx.request.headers.has(\"Authorization\") ||\n this.#credentials === \"include\") &&\n isInsecureRemote(ctx.request.url)\n ) {\n throw new InsecureTransportError(\n `refusing to send credentials (an Authorization header or cookies) over plain http to ${new URL(ctx.request.url).origin}; ` +\n \"use https, or pass allowInsecureHttp: true to createClient to allow it\",\n );\n }\n try {\n return await (this.#fetch ?? globalThis.fetch)(ctx.request);\n } catch (error) {\n if (ctx.request.signal.aborted) {\n throw error;\n }\n throw new ConnectionFailed(\n error instanceof Error ? error.message : String(error),\n {\n cause: error,\n },\n );\n }\n };\n return composeMiddleware(\n this.#middleware,\n terminal,\n )({\n request,\n resource: call.resource,\n op: call.op,\n recordId: call.recordId,\n scope: explicit ?? (await tokenScope(token)),\n ...(explicit === undefined ? {} : { cacheScope: explicit }),\n apiVersion: call.apiVersion,\n signal,\n });\n }\n\n /** Sends `call`, retrying once with a refreshed token after a `401`; throws on `>= 400`. */\n async #send(call: Call, signal: AbortSignal | undefined): Promise<Response> {\n const explicit = await this.#explicitScope(); // once per call, reused on the retry\n const token = await this.#token(false);\n let response = await this.#dispatch(call, token, explicit, signal);\n if (response.status === 401 && this.#tokenProvider !== undefined) {\n const fresh = await this.#token(true);\n if (fresh !== null && fresh !== token) {\n await response.body?.cancel();\n response = await this.#dispatch(call, fresh, explicit, signal);\n }\n }\n let callbackError: unknown;\n let callbackFailed = false;\n if (response.status === 401 && this.#onUnauthorized !== undefined) {\n try {\n await this.#onUnauthorized(response.clone());\n } catch (error) {\n callbackFailed = true;\n callbackError = error;\n }\n }\n if (response.status >= 400) {\n const problem = await problemFromResponse(response);\n if (callbackFailed) {\n if (problem.cause === undefined) {\n problem.cause = callbackError;\n } else {\n // Keep the cause the problem already has; expose the callback's error here.\n Object.defineProperty(problem, \"onUnauthorizedError\", {\n value: callbackError,\n enumerable: false,\n configurable: true,\n writable: true,\n });\n }\n }\n throw problem;\n }\n return response;\n }\n\n async #getJson(url: string, catalog: boolean): Promise<unknown> {\n const call: Call = {\n method: \"GET\",\n url,\n op: \"manifest\",\n resource: undefined,\n recordId: undefined,\n apiVersion: null,\n // The catalog shares the \"manifest\" op; no-store keeps it out of the manifest cache entry.\n ...(catalog ? { headers: { \"Cache-Control\": \"no-store\" } } : {}),\n };\n const response = await this.#send(call, undefined);\n try {\n return (await response.json()) as unknown;\n } catch (error) {\n throw new ManifestError(`${url} is not JSON`, { cause: error });\n }\n }\n\n /** The manifest for this caller, loaded once per caller scope (`refresh: true` reloads). */\n async manifest(\n options: { readonly refresh?: boolean } = {},\n ): Promise<Manifest> {\n const scope = await this.scope(); // the manifest is filtered per caller\n const current = this.#manifests.get(scope);\n if (current !== undefined && options.refresh !== true) {\n return current;\n }\n const started = loadManifest(\n (url, catalog) => this.#getJson(url, catalog),\n this.baseUrl,\n this.#manifestUrl,\n );\n if (current === undefined) {\n this.#manifests.clear(); // rotated tokens must not pile up manifests\n this.#manifests.set(scope, started);\n started.catch(() => {\n if (this.#manifests.get(scope) === started) {\n this.#manifests.delete(scope);\n }\n });\n } else {\n // A refresh replaces the cached manifest only once it loaded, and only\n // if no newer refresh was started: a failed one rejects here and leaves\n // the last good manifest to everyone else.\n this.#refreshes.set(scope, started);\n const settle = (loaded?: Manifest): void => {\n if (this.#refreshes.get(scope) === started) {\n this.#refreshes.delete(scope);\n // Not for a scope the rotation eviction already dropped.\n if (\n loaded !== undefined &&\n (this.#manifests.has(scope) || this.#manifests.size === 0)\n ) {\n this.#manifests.set(scope, Promise.resolve(loaded));\n }\n }\n };\n started.then(settle, () => {\n settle();\n });\n }\n return started;\n }\n\n /** A handle for `name` (the highest `api_version` unless given). */\n async resource<\n Read extends object = JsonObject,\n Create extends object = JsonObject,\n Update extends object = JsonObject,\n >(\n name: string,\n apiVersion?: string,\n ): Promise<ResourceClient<Read, Create, Update>> {\n const resource = findResource(await this.manifest(), name, apiVersion);\n if (resource === undefined) {\n throw new UnknownResourceError(\n `the manifest has no resource \"${name}\"${apiVersion === undefined ? \"\" : ` ${apiVersion}`} for this caller`,\n );\n }\n return new ResourceClient<Read, Create, Update>(\n this.baseUrl,\n resource,\n this.#transport,\n this.#allowedOrigins,\n );\n }\n}\n\n/** Creates a client; the manifest loads on first use. */\nexport function createClient(options: ClientOptions): CrudClient {\n return new CrudClient(options);\n}\n"],"mappings":"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"}
|