@camunda/ccma-api 3.0.0 → 4.0.0
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/dist/index.d.ts +12 -8
- package/dist/index.js +4 -0
- package/dist/index.js.map +2 -2
- package/dist/services/accounts/approvals.m2m.service.d.ts +157 -0
- package/dist/services/accounts/approvals.m2m.service.js +226 -0
- package/dist/services/accounts/approvals.m2m.service.js.map +2 -2
- package/dist/services/accounts/hdp.service.d.ts +16 -3
- package/dist/services/accounts/hdp.service.js +45 -2
- package/dist/services/accounts/hdp.service.js.map +2 -2
- package/dist/services/accounts/orgs.service.d.ts +17 -1
- package/dist/services/accounts/orgs.service.js +33 -0
- package/dist/services/accounts/orgs.service.js.map +2 -2
- package/dist/services/console/console.approvals.m2m.service.d.ts +12 -1
- package/dist/services/console/console.approvals.m2m.service.js +31 -0
- package/dist/services/console/console.approvals.m2m.service.js.map +2 -2
- package/dist/services/control/control.approvals.service.d.ts +276 -0
- package/dist/services/control/control.approvals.service.js +155 -0
- package/dist/services/control/control.approvals.service.js.map +2 -2
- package/dist/services/control/control.dashboards.service.d.ts +76 -0
- package/dist/services/control/control.dashboards.service.js +180 -0
- package/dist/services/control/control.dashboards.service.js.map +7 -0
- package/dist/services/control/control.dashboards.service.spec.d.ts +1 -0
- package/dist/services/control/control.feature-flags.service.d.ts +53 -0
- package/dist/services/control/control.feature-flags.service.js +123 -0
- package/dist/services/control/control.feature-flags.service.js.map +7 -0
- package/dist/services/control/control.feature-flags.service.spec.d.ts +1 -0
- package/dist/services/control/control.platform.service.d.ts +14 -0
- package/dist/services/control/control.platform.service.js +27 -0
- package/dist/services/control/control.platform.service.js.map +2 -2
- package/dist/services/control/control.platform.service.spec.d.ts +1 -0
- package/dist/services/external/external.accounts.service.d.ts +2 -2
- package/dist/services/external/external.accounts.service.js.map +2 -2
- package/dist/services/github/github.service.d.ts +20 -0
- package/dist/services/github/github.service.js +50 -1
- package/dist/services/github/github.service.js.map +2 -2
- package/dist/services/openrouter/openrouter.service.d.ts +35 -0
- package/dist/services/openrouter/openrouter.service.js +45 -0
- package/dist/services/openrouter/openrouter.service.js.map +2 -2
- package/dist/services/slack/slack-blockkit.service.d.ts +7 -0
- package/dist/services/slack/slack-blockkit.service.js +1 -0
- package/dist/services/slack/slack-blockkit.service.js.map +2 -2
- package/dist/utils/environments.js +3 -4
- package/dist/utils/environments.js.map +2 -2
- package/dist/utils/sse.d.ts +1 -0
- package/dist/utils/sse.js +7 -0
- package/dist/utils/sse.js.map +2 -2
- package/package.json +2 -2
package/dist/utils/sse.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/utils/sse.ts"],
|
|
4
|
-
"sourcesContent": ["/*\n * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH\n * under one or more contributor license agreements. Licensed under a commercial license.\n * You may not use this file except in compliance with the commercial license.\n */\n\nimport type { RequestBaseParamsConfig } from '../types/general.types.js'\n\n/**\n * Dependency-free Server-Sent Events client built on `fetch` + `ReadableStream`.\n *\n * Why not the native `EventSource`? It cannot send an `Authorization` header,\n * which every Camunda stream requires. This helper reuses the same\n * `config.auth.getToken()` contract as `request()`, so it always sends a fresh\n * bearer token \u2014 including on every reconnect, which is how token rotation is\n * handled (no separate refresh timer needed on the consumer side).\n *\n * It is isomorphic (browser + Node 22+), auto-reconnects with exponential\n * backoff + full jitter, honours `Last-Event-ID`, and aborts+reconnects when\n * the stream goes silent past `heartbeatTimeoutMs` (comment/keep-alive frames\n * count as activity, so a well-behaved server keeps the connection pinned).\n */\n\nexport type SseConnectionState =\n | 'connecting'\n | 'open'\n | 'reconnecting'\n | 'closed'\n\nexport interface SseMessage {\n /** Concatenated `data:` lines (newline-joined), excluding the trailing newline. */\n data: string\n /** The `event:` field, if the server set one. */\n event?: string\n /** The `id:` field, if the server set one. Echoed back as `Last-Event-ID`. */\n id?: string\n}\n\nexport interface SseConnectionOptions {\n /** Absolute URL of the event stream. */\n url: string\n /** Reuses `auth.getToken` (called per (re)connect) and `logger`. */\n config: RequestBaseParamsConfig\n /** Called for each complete, non-empty SSE event (comment-only frames excluded). */\n onMessage: (message: SseMessage) => void\n /** Observability hook for connection lifecycle transitions. */\n onStateChange?: (state: SseConnectionState) => void\n /**\n * Abort + reconnect when no bytes (including comments / keep-alives) arrive\n * for this long. Default 120_000 ms.\n */\n heartbeatTimeoutMs?: number\n /** Backoff tuning. Defaults: base 1_000 ms, max 30_000 ms, full jitter. */\n reconnect?: {\n baseDelayMs?: number\n maxDelayMs?: number\n }\n}\n\nexport interface SseConnection {\n /** Idempotent. Aborts any in-flight fetch, cancels timers, emits no further events. */\n close: () => void\n /** Current lifecycle state. */\n readonly state: SseConnectionState\n}\n\nconst DEFAULT_HEARTBEAT_TIMEOUT_MS = 120_000\nconst DEFAULT_BASE_DELAY_MS = 1_000\nconst DEFAULT_MAX_DELAY_MS = 30_000\n\n/**\n * Incrementally parses a `text/event-stream` byte stream into complete events.\n * Events are separated by a blank line; `data:` lines accumulate; `event:`/`id:`\n * set the corresponding fields; lines starting with `:` are comments (ignored,\n * but still count as stream activity for the heartbeat).\n */\nclass SseParser {\n private buffer = ''\n private dataLines: string[] = []\n private eventName: string | undefined\n private lastEventId: string | undefined\n\n constructor(\n private readonly onMessage: (message: SseMessage) => void,\n /** Seed used to resume: exposed back so the connection can send Last-Event-ID. */\n lastEventId: string | undefined,\n ) {\n this.lastEventId = lastEventId\n }\n\n getLastEventId(): string | undefined {\n return this.lastEventId\n }\n\n /** Feed a decoded text chunk. Returns nothing; dispatches via `onMessage`. */\n push(chunk: string): void {\n this.buffer += chunk\n // Normalize CRLF / CR to LF so line splitting is uniform.\n this.buffer = this.buffer.replace(/\\r\\n?/g, '\\n')\n\n let newlineIndex = this.buffer.indexOf('\\n')\n while (newlineIndex !== -1) {\n const line = this.buffer.slice(0, newlineIndex)\n this.buffer = this.buffer.slice(newlineIndex + 1)\n this.handleLine(line)\n newlineIndex = this.buffer.indexOf('\\n')\n }\n }\n\n private handleLine(line: string): void {\n // Blank line: dispatch the accumulated event.\n if (line === '') {\n this.dispatch()\n return\n }\n\n // Comment line (keep-alive) \u2014 ignored.\n if (line.startsWith(':')) {\n return\n }\n\n const colonIndex = line.indexOf(':')\n const field = colonIndex === -1 ? line : line.slice(0, colonIndex)\n let value = colonIndex === -1 ? '' : line.slice(colonIndex + 1)\n // A single leading space after the colon is stripped, per the spec.\n if (value.startsWith(' ')) {\n value = value.slice(1)\n }\n\n switch (field) {\n case 'data':\n this.dataLines.push(value)\n break\n case 'event':\n this.eventName = value\n break\n case 'id':\n // Per spec, an id containing NUL is ignored; otherwise it updates the\n // last-event-id used on reconnect.\n if (!value.includes('\\u0000')) {\n this.lastEventId = value\n }\n break\n // `retry:` and unknown fields are intentionally ignored.\n default:\n break\n }\n }\n\n private dispatch(): void {\n if (this.dataLines.length === 0 && this.eventName === undefined) {\n // Nothing to dispatch (e.g. stray blank line).\n this.reset()\n return\n }\n\n this.onMessage({\n data: this.dataLines.join('\\n'),\n event: this.eventName,\n id: this.lastEventId,\n })\n this.reset()\n }\n\n private reset(): void {\n this.dataLines = []\n this.eventName = undefined\n }\n}\n\nfunction computeBackoff(\n attempt: number,\n baseDelayMs: number,\n maxDelayMs: number,\n): number {\n const exponential = Math.min(maxDelayMs, baseDelayMs * 2 ** attempt)\n // Full jitter: pick uniformly in [0, exponential].\n return Math.floor(Math.random() * exponential)\n}\n\nexport function connectSse(options: SseConnectionOptions): SseConnection {\n const heartbeatTimeoutMs =\n options.heartbeatTimeoutMs ?? DEFAULT_HEARTBEAT_TIMEOUT_MS\n const baseDelayMs = options.reconnect?.baseDelayMs ?? DEFAULT_BASE_DELAY_MS\n const maxDelayMs = options.reconnect?.maxDelayMs ?? DEFAULT_MAX_DELAY_MS\n const logger = options.config.logger\n\n let state: SseConnectionState = 'connecting'\n let closed = false\n let attempt = 0\n let lastEventId: string | undefined\n let controller: AbortController | undefined\n let heartbeatTimer: ReturnType<typeof setTimeout> | undefined\n let reconnectTimer: ReturnType<typeof setTimeout> | undefined\n // Once we've seen a 401/403 we allow exactly one immediate fresh-token retry\n // before falling back to normal backoff, so a transient auth blip self-heals\n // without hammering the token endpoint.\n let authRetryUsed = false\n\n const setState = (next: SseConnectionState): void => {\n if (state === next || closed) {\n return\n }\n state = next\n try {\n options.onStateChange?.(next)\n } catch (error) {\n logger?.debug('connectSse onStateChange callback threw', { error })\n }\n }\n\n const clearHeartbeat = (): void => {\n if (heartbeatTimer !== undefined) {\n clearTimeout(heartbeatTimer)\n heartbeatTimer = undefined\n }\n }\n\n const armHeartbeat = (): void => {\n clearHeartbeat()\n heartbeatTimer = setTimeout(() => {\n logger?.debug('connectSse heartbeat timeout, reconnecting', {\n url: options.url,\n })\n // Abort the current fetch; the read loop's catch schedules the reconnect.\n controller?.abort()\n }, heartbeatTimeoutMs)\n }\n\n const scheduleReconnect = (): void => {\n if (closed) {\n return\n }\n // Guard against stacking timers: multiple error paths (heartbeat abort +\n // stream end, etc.) can each call scheduleReconnect before the pending\n // timer fires. Without this, overlapping timers spawn concurrent run()\n // loops (and concurrent fetches).\n if (reconnectTimer !== undefined) {\n return\n }\n setState('reconnecting')\n const delay = computeBackoff(attempt, baseDelayMs, maxDelayMs)\n attempt += 1\n reconnectTimer = setTimeout(() => {\n reconnectTimer = undefined\n void run()\n }, delay)\n }\n\n const run = async (): Promise<void> => {\n if (closed) {\n return\n }\n\n controller = new AbortController()\n\n let token: string | undefined\n try {\n token = options.config.auth\n ? await options.config.auth.getToken()\n : undefined\n } catch (error) {\n logger?.debug('connectSse failed to get token', { error })\n scheduleReconnect()\n return\n }\n\n if (closed) {\n return\n }\n\n const headers: Record<string, string> = {\n accept: 'text/event-stream',\n }\n // Correlation headers (traceparent, x-cc-session-id) so the SSE connection\n // is traceable and grouped into the session, mirroring request(). A\n // throwing getDynamicHeaders is swallowed \u2014 the stream still connects.\n if (options.config.getDynamicHeaders) {\n try {\n Object.assign(headers, options.config.getDynamicHeaders())\n } catch (error) {\n logger?.debug('connectSse getDynamicHeaders threw', { error })\n }\n }\n if (token) {\n headers.authorization = `Bearer ${token}`\n }\n if (lastEventId !== undefined) {\n headers['last-event-id'] = lastEventId\n }\n\n const parser = new SseParser(options.onMessage, lastEventId)\n\n try {\n const response = await fetch(options.url, {\n method: 'GET',\n headers,\n signal: controller.signal,\n ...(options.config.proxyAgent ?? {}),\n })\n\n if (!response.ok) {\n // Auth blip: retry once immediately with a freshly minted token before\n // falling back to backoff.\n if (\n (response.status === 401 || response.status === 403) &&\n !authRetryUsed\n ) {\n authRetryUsed = true\n logger?.debug(\n 'connectSse auth error, retrying once with fresh token',\n {\n status: response.status,\n },\n )\n setState('reconnecting')\n void run()\n return\n }\n logger?.debug('connectSse non-ok response', { status: response.status })\n scheduleReconnect()\n return\n }\n\n if (!response.body) {\n logger?.debug('connectSse response has no body')\n scheduleReconnect()\n return\n }\n\n // Connected successfully: reset backoff + auth-retry budget.\n attempt = 0\n authRetryUsed = false\n setState('open')\n armHeartbeat()\n\n const reader = response.body.getReader()\n const decoder = new TextDecoder()\n\n while (!closed) {\n const { done, value } = await reader.read()\n if (done) {\n break\n }\n // Any bytes (incl. comments) count as liveness.\n armHeartbeat()\n parser.push(decoder.decode(value, { stream: true }))\n lastEventId = parser.getLastEventId()\n }\n\n // Stream ended cleanly (server closed): reconnect unless we're closing.\n if (!closed) {\n scheduleReconnect()\n }\n } catch (error) {\n if (closed) {\n return\n }\n // AbortError from close() is handled by the `closed` guard above; an\n // AbortError from the heartbeat means we intentionally dropped a silent\n // connection and should reconnect.\n logger?.debug('connectSse stream error, reconnecting', { error })\n scheduleReconnect()\n } finally {\n clearHeartbeat()\n }\n }\n\n const close = (): void => {\n if (closed) {\n return\n }\n closed = true\n clearHeartbeat()\n if (reconnectTimer !== undefined) {\n clearTimeout(reconnectTimer)\n reconnectTimer = undefined\n }\n controller?.abort()\n setStateClosed()\n }\n\n // `setState` short-circuits once `closed` is true, so set the terminal state\n // through a dedicated path.\n function setStateClosed(): void {\n state = 'closed'\n try {\n options.onStateChange?.('closed')\n } catch (error) {\n logger?.debug('connectSse onStateChange callback threw', { error })\n }\n }\n\n void run()\n\n return {\n close,\n get state() {\n return state\n },\n }\n}\n"],
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["/*\n * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH\n * under one or more contributor license agreements. Licensed under a commercial license.\n * You may not use this file except in compliance with the commercial license.\n */\n\nimport type { RequestBaseParamsConfig } from '../types/general.types.js'\n\n/**\n * Dependency-free Server-Sent Events client built on `fetch` + `ReadableStream`.\n *\n * Why not the native `EventSource`? It cannot send an `Authorization` header,\n * which every Camunda stream requires. This helper reuses the same\n * `config.auth.getToken()` contract as `request()`, so it always sends a fresh\n * bearer token \u2014 including on every reconnect, which is how token rotation is\n * handled (no separate refresh timer needed on the consumer side).\n *\n * It is isomorphic (browser + Node 22+), auto-reconnects with exponential\n * backoff + full jitter, honours `Last-Event-ID`, and aborts+reconnects when\n * the stream goes silent past `heartbeatTimeoutMs` (comment/keep-alive frames\n * count as activity, so a well-behaved server keeps the connection pinned).\n * A `204` answer ends the connection for good, as the SSE standard asks.\n */\n\nexport type SseConnectionState =\n | 'connecting'\n | 'open'\n | 'reconnecting'\n | 'closed'\n\nexport interface SseMessage {\n /** Concatenated `data:` lines (newline-joined), excluding the trailing newline. */\n data: string\n /** The `event:` field, if the server set one. */\n event?: string\n /** The `id:` field, if the server set one. Echoed back as `Last-Event-ID`. */\n id?: string\n}\n\nexport interface SseConnectionOptions {\n /** Absolute URL of the event stream. */\n url: string\n /** Reuses `auth.getToken` (called per (re)connect) and `logger`. */\n config: RequestBaseParamsConfig\n /** Called for each complete, non-empty SSE event (comment-only frames excluded). */\n onMessage: (message: SseMessage) => void\n /** Observability hook for connection lifecycle transitions. */\n onStateChange?: (state: SseConnectionState) => void\n /**\n * Abort + reconnect when no bytes (including comments / keep-alives) arrive\n * for this long. Default 120_000 ms.\n */\n heartbeatTimeoutMs?: number\n /** Backoff tuning. Defaults: base 1_000 ms, max 30_000 ms, full jitter. */\n reconnect?: {\n baseDelayMs?: number\n maxDelayMs?: number\n }\n}\n\nexport interface SseConnection {\n /** Idempotent. Aborts any in-flight fetch, cancels timers, emits no further events. */\n close: () => void\n /** Current lifecycle state. */\n readonly state: SseConnectionState\n}\n\nconst DEFAULT_HEARTBEAT_TIMEOUT_MS = 120_000\nconst DEFAULT_BASE_DELAY_MS = 1_000\nconst DEFAULT_MAX_DELAY_MS = 30_000\n\n/**\n * Incrementally parses a `text/event-stream` byte stream into complete events.\n * Events are separated by a blank line; `data:` lines accumulate; `event:`/`id:`\n * set the corresponding fields; lines starting with `:` are comments (ignored,\n * but still count as stream activity for the heartbeat).\n */\nclass SseParser {\n private buffer = ''\n private dataLines: string[] = []\n private eventName: string | undefined\n private lastEventId: string | undefined\n\n constructor(\n private readonly onMessage: (message: SseMessage) => void,\n /** Seed used to resume: exposed back so the connection can send Last-Event-ID. */\n lastEventId: string | undefined,\n ) {\n this.lastEventId = lastEventId\n }\n\n getLastEventId(): string | undefined {\n return this.lastEventId\n }\n\n /** Feed a decoded text chunk. Returns nothing; dispatches via `onMessage`. */\n push(chunk: string): void {\n this.buffer += chunk\n // Normalize CRLF / CR to LF so line splitting is uniform.\n this.buffer = this.buffer.replace(/\\r\\n?/g, '\\n')\n\n let newlineIndex = this.buffer.indexOf('\\n')\n while (newlineIndex !== -1) {\n const line = this.buffer.slice(0, newlineIndex)\n this.buffer = this.buffer.slice(newlineIndex + 1)\n this.handleLine(line)\n newlineIndex = this.buffer.indexOf('\\n')\n }\n }\n\n private handleLine(line: string): void {\n // Blank line: dispatch the accumulated event.\n if (line === '') {\n this.dispatch()\n return\n }\n\n // Comment line (keep-alive) \u2014 ignored.\n if (line.startsWith(':')) {\n return\n }\n\n const colonIndex = line.indexOf(':')\n const field = colonIndex === -1 ? line : line.slice(0, colonIndex)\n let value = colonIndex === -1 ? '' : line.slice(colonIndex + 1)\n // A single leading space after the colon is stripped, per the spec.\n if (value.startsWith(' ')) {\n value = value.slice(1)\n }\n\n switch (field) {\n case 'data':\n this.dataLines.push(value)\n break\n case 'event':\n this.eventName = value\n break\n case 'id':\n // Per spec, an id containing NUL is ignored; otherwise it updates the\n // last-event-id used on reconnect.\n if (!value.includes('\\u0000')) {\n this.lastEventId = value\n }\n break\n // `retry:` and unknown fields are intentionally ignored.\n default:\n break\n }\n }\n\n private dispatch(): void {\n if (this.dataLines.length === 0 && this.eventName === undefined) {\n // Nothing to dispatch (e.g. stray blank line).\n this.reset()\n return\n }\n\n this.onMessage({\n data: this.dataLines.join('\\n'),\n event: this.eventName,\n id: this.lastEventId,\n })\n this.reset()\n }\n\n private reset(): void {\n this.dataLines = []\n this.eventName = undefined\n }\n}\n\nfunction computeBackoff(\n attempt: number,\n baseDelayMs: number,\n maxDelayMs: number,\n): number {\n const exponential = Math.min(maxDelayMs, baseDelayMs * 2 ** attempt)\n // Full jitter: pick uniformly in [0, exponential].\n return Math.floor(Math.random() * exponential)\n}\n\nexport function connectSse(options: SseConnectionOptions): SseConnection {\n const heartbeatTimeoutMs =\n options.heartbeatTimeoutMs ?? DEFAULT_HEARTBEAT_TIMEOUT_MS\n const baseDelayMs = options.reconnect?.baseDelayMs ?? DEFAULT_BASE_DELAY_MS\n const maxDelayMs = options.reconnect?.maxDelayMs ?? DEFAULT_MAX_DELAY_MS\n const logger = options.config.logger\n\n let state: SseConnectionState = 'connecting'\n let closed = false\n let attempt = 0\n let lastEventId: string | undefined\n let controller: AbortController | undefined\n let heartbeatTimer: ReturnType<typeof setTimeout> | undefined\n let reconnectTimer: ReturnType<typeof setTimeout> | undefined\n // Once we've seen a 401/403 we allow exactly one immediate fresh-token retry\n // before falling back to normal backoff, so a transient auth blip self-heals\n // without hammering the token endpoint.\n let authRetryUsed = false\n\n const setState = (next: SseConnectionState): void => {\n if (state === next || closed) {\n return\n }\n state = next\n try {\n options.onStateChange?.(next)\n } catch (error) {\n logger?.debug('connectSse onStateChange callback threw', { error })\n }\n }\n\n const clearHeartbeat = (): void => {\n if (heartbeatTimer !== undefined) {\n clearTimeout(heartbeatTimer)\n heartbeatTimer = undefined\n }\n }\n\n const armHeartbeat = (): void => {\n clearHeartbeat()\n heartbeatTimer = setTimeout(() => {\n logger?.debug('connectSse heartbeat timeout, reconnecting', {\n url: options.url,\n })\n // Abort the current fetch; the read loop's catch schedules the reconnect.\n controller?.abort()\n }, heartbeatTimeoutMs)\n }\n\n const scheduleReconnect = (): void => {\n if (closed) {\n return\n }\n // Guard against stacking timers: multiple error paths (heartbeat abort +\n // stream end, etc.) can each call scheduleReconnect before the pending\n // timer fires. Without this, overlapping timers spawn concurrent run()\n // loops (and concurrent fetches).\n if (reconnectTimer !== undefined) {\n return\n }\n setState('reconnecting')\n const delay = computeBackoff(attempt, baseDelayMs, maxDelayMs)\n attempt += 1\n reconnectTimer = setTimeout(() => {\n reconnectTimer = undefined\n void run()\n }, delay)\n }\n\n const run = async (): Promise<void> => {\n if (closed) {\n return\n }\n\n controller = new AbortController()\n\n let token: string | undefined\n try {\n token = options.config.auth\n ? await options.config.auth.getToken()\n : undefined\n } catch (error) {\n logger?.debug('connectSse failed to get token', { error })\n scheduleReconnect()\n return\n }\n\n if (closed) {\n return\n }\n\n const headers: Record<string, string> = {\n accept: 'text/event-stream',\n }\n // Correlation headers (traceparent, x-cc-session-id) so the SSE connection\n // is traceable and grouped into the session, mirroring request(). A\n // throwing getDynamicHeaders is swallowed \u2014 the stream still connects.\n if (options.config.getDynamicHeaders) {\n try {\n Object.assign(headers, options.config.getDynamicHeaders())\n } catch (error) {\n logger?.debug('connectSse getDynamicHeaders threw', { error })\n }\n }\n if (token) {\n headers.authorization = `Bearer ${token}`\n }\n if (lastEventId !== undefined) {\n headers['last-event-id'] = lastEventId\n }\n\n const parser = new SseParser(options.onMessage, lastEventId)\n\n try {\n const response = await fetch(options.url, {\n method: 'GET',\n headers,\n signal: controller.signal,\n ...(options.config.proxyAgent ?? {}),\n })\n\n if (!response.ok) {\n // Auth blip: retry once immediately with a freshly minted token before\n // falling back to backoff.\n if (\n (response.status === 401 || response.status === 403) &&\n !authRetryUsed\n ) {\n authRetryUsed = true\n logger?.debug(\n 'connectSse auth error, retrying once with fresh token',\n {\n status: response.status,\n },\n )\n setState('reconnecting')\n void run()\n return\n }\n logger?.debug('connectSse non-ok response', { status: response.status })\n scheduleReconnect()\n return\n }\n\n // Per the SSE standard, a 204 means the server wants no stream for this\n // client. Reconnecting would only repeat the request.\n if (response.status === 204) {\n logger?.debug('connectSse got 204, the server wants no stream', {\n url: options.url,\n })\n close()\n return\n }\n\n if (!response.body) {\n logger?.debug('connectSse response has no body')\n scheduleReconnect()\n return\n }\n\n // Connected successfully: reset backoff + auth-retry budget.\n attempt = 0\n authRetryUsed = false\n setState('open')\n armHeartbeat()\n\n const reader = response.body.getReader()\n const decoder = new TextDecoder()\n\n while (!closed) {\n const { done, value } = await reader.read()\n if (done) {\n break\n }\n // Any bytes (incl. comments) count as liveness.\n armHeartbeat()\n parser.push(decoder.decode(value, { stream: true }))\n lastEventId = parser.getLastEventId()\n }\n\n // Stream ended cleanly (server closed): reconnect unless we're closing.\n if (!closed) {\n scheduleReconnect()\n }\n } catch (error) {\n if (closed) {\n return\n }\n // AbortError from close() is handled by the `closed` guard above; an\n // AbortError from the heartbeat means we intentionally dropped a silent\n // connection and should reconnect.\n logger?.debug('connectSse stream error, reconnecting', { error })\n scheduleReconnect()\n } finally {\n clearHeartbeat()\n }\n }\n\n const close = (): void => {\n if (closed) {\n return\n }\n closed = true\n clearHeartbeat()\n if (reconnectTimer !== undefined) {\n clearTimeout(reconnectTimer)\n reconnectTimer = undefined\n }\n controller?.abort()\n setStateClosed()\n }\n\n // `setState` short-circuits once `closed` is true, so set the terminal state\n // through a dedicated path.\n function setStateClosed(): void {\n state = 'closed'\n try {\n options.onStateChange?.('closed')\n } catch (error) {\n logger?.debug('connectSse onStateChange callback threw', { error })\n }\n }\n\n void run()\n\n return {\n close,\n get state() {\n return state\n },\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camunda/ccma-api",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"description": "Centralized API service layer for Camunda Cloud Management Apps",
|
|
5
5
|
"bugs": {
|
|
6
6
|
"url": "https://github.com/camunda/camunda-cloud-management-apps/issues"
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
}
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@camunda/ccma-shared-types": "
|
|
44
|
+
"@camunda/ccma-shared-types": "6.0.0"
|
|
45
45
|
},
|
|
46
46
|
"scripts": {
|
|
47
47
|
"build": "node esbuild.mjs && tsc --emitDeclarationOnly --outDir dist",
|