@rawdash/core 0.12.0 → 0.13.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 +1 -0
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -367,11 +367,11 @@ var BaseConnector = class {
|
|
|
367
367
|
constructor(settings, creds, ctx) {
|
|
368
368
|
this.settings = settings;
|
|
369
369
|
this.rawCredInput = creds;
|
|
370
|
+
this.ctx = ctx ?? {};
|
|
370
371
|
this.creds = creds ? resolveSecrets(
|
|
371
372
|
creds,
|
|
372
|
-
new EnvSecretsResolver()
|
|
373
|
+
this.ctx.secretsResolver ?? new EnvSecretsResolver()
|
|
373
374
|
) : {};
|
|
374
|
-
this.ctx = ctx ?? {};
|
|
375
375
|
}
|
|
376
376
|
request(req, opts) {
|
|
377
377
|
return request(req, {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../connector-shared/src/errors.ts","../../connector-shared/src/retry.ts","../../connector-shared/src/version.ts","../../connector-shared/src/request.ts","../../connector-shared/src/rate-limit.ts","../../connector-shared/src/pagination.ts","../src/secrets.ts","../src/connector.ts","../src/paginate-chunked.ts","../src/widget-schemas.ts","../src/config.ts","../src/retention.ts","../src/config-fields.ts","../src/compute.ts","../src/resolve-widget.ts","../src/in-memory-storage.ts","../src/wire-config.ts"],"sourcesContent":["import type { HttpResponse } from './types';\n\nexport type HttpErrorKind =\n | 'transient'\n | 'rate_limit'\n | 'auth'\n | 'upstream_bug'\n | 'client_bug';\n\nexport abstract class HttpClientError extends Error {\n abstract readonly kind: HttpErrorKind;\n readonly response?: HttpResponse;\n\n constructor(message: string, response?: HttpResponse) {\n super(message);\n this.name = new.target.name;\n this.response = response;\n }\n}\n\nexport class TransientError extends HttpClientError {\n readonly kind = 'transient' as const;\n}\n\nexport class RateLimitError extends HttpClientError {\n readonly kind = 'rate_limit' as const;\n readonly retryAfter?: Date;\n\n constructor(message: string, response?: HttpResponse, retryAfter?: Date) {\n super(message, response);\n this.retryAfter = retryAfter;\n }\n}\n\nexport class AuthError extends HttpClientError {\n readonly kind = 'auth' as const;\n}\n\nexport class UpstreamBugError extends HttpClientError {\n readonly kind = 'upstream_bug' as const;\n}\n\nexport class ClientBugError extends HttpClientError {\n readonly kind = 'client_bug' as const;\n}\n\nexport function classifyStatus(status: number): HttpErrorKind {\n if (status === 429) {\n return 'rate_limit';\n }\n if (status === 401 || status === 403) {\n return 'auth';\n }\n if (status === 408) {\n return 'transient';\n }\n if (status >= 500) {\n return 'upstream_bug';\n }\n if (status >= 400) {\n return 'client_bug';\n }\n return 'client_bug';\n}\n\nexport function errorForStatus(\n message: string,\n response: HttpResponse,\n retryAfter?: Date,\n): HttpClientError {\n const kind = classifyStatus(response.status);\n switch (kind) {\n case 'rate_limit':\n return new RateLimitError(message, response, retryAfter);\n case 'auth':\n return new AuthError(message, response);\n case 'transient':\n return new TransientError(message, response);\n case 'upstream_bug':\n return new UpstreamBugError(message, response);\n case 'client_bug':\n return new ClientBugError(message, response);\n }\n}\n","import { HttpClientError, RateLimitError, TransientError } from './errors';\n\nexport interface RetryPolicy {\n maxAttempts?: number;\n initialDelayMs?: number;\n maxDelayMs?: number;\n retryOn?: (status: number | null, err?: Error) => boolean;\n}\n\nexport const defaultRetryOn = (status: number | null, err?: Error): boolean => {\n if (err instanceof RateLimitError) {\n return true;\n }\n if (err instanceof TransientError) {\n return true;\n }\n if (status === null) {\n return err instanceof Error && !(err instanceof HttpClientError);\n }\n if (status === 408 || status === 429) {\n return true;\n }\n if (status >= 500) {\n return true;\n }\n return false;\n};\n\nexport function backoffDelayMs(\n attempt: number,\n policy: Required<Pick<RetryPolicy, 'initialDelayMs' | 'maxDelayMs'>>,\n): number {\n const base = policy.initialDelayMs * 2 ** attempt;\n const jitter = base * 0.25 * Math.random();\n return Math.min(base + jitter, policy.maxDelayMs);\n}\n\nexport function parseRetryAfter(\n headerValue: string | null,\n now: Date = new Date(),\n): Date | undefined {\n if (!headerValue) {\n return undefined;\n }\n const trimmed = headerValue.trim();\n if (/^\\d+$/.test(trimmed)) {\n return new Date(now.getTime() + Number(trimmed) * 1000);\n }\n const parsed = Date.parse(trimmed);\n if (Number.isNaN(parsed)) {\n return undefined;\n }\n return new Date(parsed);\n}\n\nexport function sleep(ms: number, signal?: AbortSignal): Promise<void> {\n if (signal?.aborted) {\n return Promise.reject(signal.reason ?? new Error('Aborted'));\n }\n return new Promise<void>((resolve, reject) => {\n const onAbort = () => {\n clearTimeout(timer);\n reject(signal!.reason ?? new Error('Aborted'));\n };\n const timer = setTimeout(() => {\n signal?.removeEventListener('abort', onAbort);\n resolve();\n }, ms);\n signal?.addEventListener('abort', onAbort, { once: true });\n });\n}\n","export const HTTP_CLIENT_VERSION = '0.0.0';\n\nexport const DEFAULT_USER_AGENT = `rawdash-connector/${HTTP_CLIENT_VERSION} (+https://rawdash.dev)`;\n","import {\n AuthError,\n ClientBugError,\n HttpClientError,\n RateLimitError,\n TransientError,\n UpstreamBugError,\n errorForStatus,\n} from './errors';\nimport { defaultRetryOn, parseRetryAfter, sleep } from './retry';\nimport type { FetchLike, HttpMethod, HttpRequest, HttpResponse } from './types';\nimport { DEFAULT_USER_AGENT } from './version';\n\nconst DEFAULT_TIMEOUT_MS = 10_000;\nconst DEFAULT_MAX_ATTEMPTS = 3;\nconst DEFAULT_INITIAL_DELAY_MS = 1000;\nconst DEFAULT_MAX_DELAY_MS = 60_000;\nconst OBSERVER_TIMEOUT_MS = 250;\n\nexport interface RequestObservation {\n url: string;\n method: HttpMethod;\n status: number;\n resource: string;\n requestId: string;\n body: unknown;\n}\n\nexport type RequestObserver = (\n event: RequestObservation,\n) => void | Promise<void>;\n\nexport interface RequestOptions {\n fetch?: FetchLike;\n observer?: RequestObserver;\n resource: string;\n requestId?: string;\n}\n\nasync function notifyObserver(\n observer: RequestObserver,\n event: RequestObservation,\n): Promise<void> {\n let result: void | Promise<void>;\n try {\n result = observer(event);\n } catch (err) {\n console.warn('[connector-shared] request observer threw:', err);\n return;\n }\n if (!(result instanceof Promise)) {\n return;\n }\n const guarded = result.catch((err) => {\n console.warn('[connector-shared] request observer rejected:', err);\n });\n let timer: ReturnType<typeof setTimeout> | undefined;\n const timeout = new Promise<void>((resolve) => {\n timer = setTimeout(resolve, OBSERVER_TIMEOUT_MS);\n });\n try {\n await Promise.race([guarded, timeout]);\n } finally {\n if (timer) {\n clearTimeout(timer);\n }\n }\n}\n\nfunction newRequestId(): string {\n const c = (globalThis as { crypto?: { randomUUID?: () => string } }).crypto;\n if (c?.randomUUID) {\n return c.randomUUID();\n }\n return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;\n}\n\nfunction mergeHeaders(\n defaults: Record<string, string>,\n overrides: Record<string, string> | undefined,\n): Record<string, string> {\n const merged: Record<string, string> = {};\n for (const [k, v] of Object.entries(defaults)) {\n merged[k.toLowerCase()] = v;\n }\n if (overrides) {\n for (const [k, v] of Object.entries(overrides)) {\n merged[k.toLowerCase()] = v;\n }\n }\n return merged;\n}\n\nfunction linkTimeoutSignal(\n parent: AbortSignal | undefined,\n timeoutMs: number,\n): { signal: AbortSignal; cancel: () => void } {\n const controller = new AbortController();\n const onParentAbort = () => {\n controller.abort(parent?.reason);\n };\n if (parent) {\n if (parent.aborted) {\n controller.abort(parent.reason);\n } else {\n parent.addEventListener('abort', onParentAbort, { once: true });\n }\n }\n const timer = setTimeout(() => {\n controller.abort(new Error(`Request timed out after ${timeoutMs}ms`));\n }, timeoutMs);\n return {\n signal: controller.signal,\n cancel: () => {\n clearTimeout(timer);\n if (parent) {\n parent.removeEventListener('abort', onParentAbort);\n }\n },\n };\n}\n\nasync function readBody(res: Response, parseJson: boolean): Promise<unknown> {\n if (res.status === 204 || res.status === 205) {\n return null;\n }\n const contentType = res.headers.get('content-type') ?? '';\n if (parseJson && contentType.includes('application/json')) {\n const text = await res.text();\n if (text.length === 0) {\n return null;\n }\n return JSON.parse(text);\n }\n return res.text();\n}\n\nexport async function request<T = unknown>(\n req: HttpRequest,\n options: RequestOptions,\n): Promise<HttpResponse<T>> {\n const fetchImpl: FetchLike = options.fetch ?? (globalThis.fetch as FetchLike);\n const retry = req.retry ?? {};\n const maxAttempts = retry.maxAttempts ?? DEFAULT_MAX_ATTEMPTS;\n const initialDelayMs = retry.initialDelayMs ?? DEFAULT_INITIAL_DELAY_MS;\n const maxDelayMs = retry.maxDelayMs ?? DEFAULT_MAX_DELAY_MS;\n const retryOn = retry.retryOn ?? defaultRetryOn;\n const timeoutMs = req.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const parseJson = req.parseJson ?? true;\n\n const headers = mergeHeaders(\n {\n 'User-Agent': DEFAULT_USER_AGENT,\n Accept: 'application/json',\n },\n req.headers,\n );\n\n let lastErr: Error | undefined;\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n req.signal?.throwIfAborted();\n\n const { signal, cancel } = linkTimeoutSignal(req.signal, timeoutMs);\n let res: Response;\n try {\n res = await fetchImpl(req.url, {\n method: req.method ?? 'GET',\n headers,\n body: req.body as RequestInit['body'],\n signal,\n });\n } catch (err) {\n cancel();\n if (req.signal?.aborted) {\n throw req.signal.reason ?? err;\n }\n const error = err instanceof Error ? err : new Error(String(err));\n lastErr = error;\n if (attempt < maxAttempts - 1 && retryOn(null, error)) {\n const delay = computeDelay(attempt, initialDelayMs, maxDelayMs);\n await sleep(delay, req.signal);\n continue;\n }\n throw new TransientError(error.message);\n }\n cancel();\n\n const body = await readBody(res, parseJson);\n const httpResponse: HttpResponse<T> = {\n status: res.status,\n headers: res.headers,\n body: body as T,\n };\n if (req.rateLimit) {\n const state = req.rateLimit.parse(res.headers);\n if (state) {\n httpResponse.rateLimitState = state;\n }\n }\n\n if (options.observer) {\n await notifyObserver(options.observer, {\n url: req.url,\n method: req.method ?? 'GET',\n status: res.status,\n resource: options.resource,\n requestId: options.requestId ?? newRequestId(),\n body,\n });\n }\n\n if (res.ok) {\n return httpResponse;\n }\n\n const retryAfter = parseRetryAfter(res.headers.get('retry-after'));\n const message = `HTTP ${res.status} ${res.statusText} for ${req.method ?? 'GET'} ${req.url}`;\n const err = errorForStatus(message, httpResponse, retryAfter);\n\n if (\n attempt < maxAttempts - 1 &&\n retryOn(res.status, err) &&\n !(err instanceof AuthError) &&\n !(err instanceof ClientBugError)\n ) {\n lastErr = err;\n let delay = computeDelay(attempt, initialDelayMs, maxDelayMs);\n if (err instanceof RateLimitError && retryAfter) {\n const wait = retryAfter.getTime() - Date.now();\n if (wait > 0) {\n delay = Math.min(wait, maxDelayMs);\n }\n }\n await sleep(delay, req.signal);\n continue;\n }\n\n throw err;\n }\n\n throw lastErr ?? new UpstreamBugError('Exhausted retry attempts');\n}\n\nfunction computeDelay(\n attempt: number,\n initialDelayMs: number,\n maxDelayMs: number,\n): number {\n const base = initialDelayMs * 2 ** attempt;\n const jitter = base * 0.25 * Math.random();\n return Math.min(base + jitter, maxDelayMs);\n}\n\nexport { HttpClientError };\n","export interface RateLimitState {\n remaining: number;\n resetAt: Date;\n}\n\nexport interface RateLimitPolicy {\n parse(headers: Headers): RateLimitState | null;\n}\n\nexport const githubRateLimit: RateLimitPolicy = {\n parse(h) {\n const remainingRaw = h.get('x-ratelimit-remaining');\n const resetRaw = h.get('x-ratelimit-reset');\n if (remainingRaw === null || resetRaw === null) {\n return null;\n }\n const remaining = Number(remainingRaw);\n const reset = Number(resetRaw);\n if (!Number.isFinite(remaining) || !Number.isFinite(reset) || reset < 0) {\n return null;\n }\n return { remaining, resetAt: new Date(reset * 1000) };\n },\n};\n\nexport const sentryRateLimit: RateLimitPolicy = {\n parse(h) {\n const concurrent = h.get('x-sentry-rate-limit-remaining');\n const reset = h.get('x-sentry-rate-limit-reset');\n if (concurrent === null || reset === null) {\n return null;\n }\n const remaining = Number(concurrent);\n const resetSec = Number(reset);\n if (\n !Number.isFinite(remaining) ||\n !Number.isFinite(resetSec) ||\n resetSec < 0\n ) {\n return null;\n }\n return { remaining, resetAt: new Date(resetSec * 1000) };\n },\n};\n\nexport const linearRateLimit: RateLimitPolicy = {\n parse(h) {\n const remainingRaw = h.get('x-ratelimit-requests-remaining');\n const resetRaw = h.get('x-ratelimit-requests-reset');\n if (remainingRaw === null) {\n return null;\n }\n const remaining = Number(remainingRaw);\n if (!Number.isFinite(remaining)) {\n return null;\n }\n let resetAt: Date;\n if (resetRaw !== null) {\n const reset = Number(resetRaw);\n if (!Number.isFinite(reset) || reset < 0) {\n return null;\n }\n resetAt = new Date(reset);\n } else {\n resetAt = new Date(Date.now() + 60_000);\n }\n return { remaining, resetAt };\n },\n};\n","import { request } from './request';\nimport type { HttpRequest } from './types';\n\nexport function parseLinkHeader(header: string | null): Record<string, string> {\n if (!header) {\n return {};\n }\n const result: Record<string, string> = {};\n for (const part of header.split(',')) {\n const match = part.match(/<([^>]+)>\\s*;\\s*rel=\"([^\"]+)\"/);\n if (match) {\n result[match[2]!] = match[1]!;\n }\n }\n return result;\n}\n\nexport async function* paginateLink<T>(\n initial: HttpRequest,\n parse: (body: unknown) => T[],\n options: { resource: string },\n): AsyncIterable<T> {\n let next: string | null = initial.url;\n while (next) {\n const res: Awaited<ReturnType<typeof request>> = await request(\n {\n ...initial,\n url: next,\n },\n { resource: options.resource },\n );\n for (const item of parse(res.body)) {\n yield item;\n }\n const links = parseLinkHeader(res.headers.get('link'));\n next = links['next'] ?? null;\n }\n}\n\nexport async function* paginateCursor<T>(\n initial: HttpRequest,\n parse: (body: unknown) => { items: T[]; nextCursor: string | null },\n buildNext: (req: HttpRequest, cursor: string) => HttpRequest,\n options: { resource: string },\n): AsyncIterable<T> {\n let req: HttpRequest = initial;\n while (true) {\n const res = await request(req, { resource: options.resource });\n const { items, nextCursor } = parse(res.body);\n for (const item of items) {\n yield item;\n }\n if (!nextCursor) {\n return;\n }\n req = buildNext(req, nextCursor);\n }\n}\n\nexport async function* paginatePage<T>(\n initial: HttpRequest,\n parse: (body: unknown) => { items: T[]; hasMore: boolean },\n buildPage: (req: HttpRequest, page: number) => HttpRequest,\n options: { resource: string },\n): AsyncIterable<T> {\n let page = 1;\n while (true) {\n const req = page === 1 ? initial : buildPage(initial, page);\n const res = await request(req, { resource: options.resource });\n const { items, hasMore } = parse(res.body);\n for (const item of items) {\n yield item;\n }\n if (!hasMore || items.length === 0) {\n return;\n }\n page++;\n }\n}\n","export type Secret = { $secret: string };\n\nexport function secret(name: string): Secret {\n if (!/^[A-Z][A-Z0-9_]*$/.test(name)) {\n throw new Error(\n `Invalid secret name \"${name}\". Must match /^[A-Z][A-Z0-9_]*$/ ` +\n `(uppercase letters, digits, underscores; must start with a letter).`,\n );\n }\n return { $secret: name };\n}\n\nexport function isSecret(value: unknown): value is Secret {\n return (\n typeof value === 'object' &&\n value !== null &&\n '$secret' in value &&\n typeof (value as Secret).$secret === 'string'\n );\n}\n\nexport interface SecretsResolver {\n resolve(name: string): string | undefined;\n}\n\nexport class EnvSecretsResolver implements SecretsResolver {\n resolve(name: string): string | undefined {\n const env = (\n globalThis as { process?: { env?: Record<string, string | undefined> } }\n ).process?.env;\n return env?.[name];\n }\n}\n\nexport function extractSecretNames(value: unknown): string[] {\n const names: string[] = [];\n const visit = (v: unknown): void => {\n if (isSecret(v)) {\n names.push(v.$secret);\n return;\n }\n if (v && typeof v === 'object') {\n if (Array.isArray(v)) {\n v.forEach(visit);\n } else {\n Object.values(v as Record<string, unknown>).forEach(visit);\n }\n }\n };\n visit(value);\n return [...new Set(names)];\n}\n\nexport function resolveSecrets<T>(obj: T, resolver: SecretsResolver): T {\n if (isSecret(obj)) {\n const name = obj.$secret;\n const value = resolver.resolve(name);\n if (value === undefined) {\n throw new Error(\n `Missing secret \"${name}\". Set it via process.env.${name} or the CLI: rawdash secrets set ${name} ...`,\n );\n }\n return value as unknown as T;\n }\n if (Array.isArray(obj)) {\n return obj.map((item) => resolveSecrets(item, resolver)) as unknown as T;\n }\n if (typeof obj === 'object' && obj !== null) {\n const result: Record<string, unknown> = {};\n for (const [key, val] of Object.entries(obj as object)) {\n Object.defineProperty(result, key, {\n value: resolveSecrets(val, resolver),\n enumerable: true,\n configurable: true,\n writable: true,\n });\n }\n return result as T;\n }\n return obj;\n}\n","import {\n type HttpRequest,\n type HttpResponse,\n type RequestObserver,\n request as sharedRequest,\n} from '@rawdash/connector-shared';\n\nimport { EnvSecretsResolver, type Secret, resolveSecrets } from './secrets';\n\nexport type JSONValue =\n | string\n | number\n | boolean\n | null\n | JSONValue[]\n | { [key: string]: JSONValue };\n\n// ---------------------------------------------------------------------------\n// Five storage shapes\n// ---------------------------------------------------------------------------\n\nexport interface Event {\n name: string;\n start_ts: number;\n end_ts: number | null;\n attributes: Record<string, JSONValue>;\n}\n\nexport interface Entity {\n type: string;\n id: string;\n attributes: Record<string, JSONValue>;\n updated_at: number;\n}\n\nexport interface MetricSample {\n name: string;\n ts: number;\n value: number;\n attributes: Record<string, JSONValue>;\n}\n\nexport interface Edge {\n from_type: string;\n from_id: string;\n kind: string;\n to_type: string;\n to_id: string;\n attributes: Record<string, JSONValue>;\n updated_at: number;\n}\n\nexport type Distribution =\n | {\n name: string;\n ts: number;\n kind: 'histogram';\n data: {\n buckets: Array<{ le: number; count: number }>;\n count: number;\n sum: number;\n };\n attributes: Record<string, JSONValue>;\n }\n | {\n name: string;\n ts: number;\n kind: 'summary';\n data: {\n quantiles: Array<{ q: number; value: number }>;\n count: number;\n sum: number;\n };\n attributes: Record<string, JSONValue>;\n };\n\n// ---------------------------------------------------------------------------\n// Storage query types\n// ---------------------------------------------------------------------------\n\nexport interface EventQuery {\n name?: string;\n start?: number;\n end?: number;\n}\n\nexport interface EntityQuery {\n type: string;\n}\n\nexport interface MetricQuery {\n name?: string;\n start?: number;\n end?: number;\n}\n\nexport interface EdgeQuery {\n fromType?: string;\n fromId?: string;\n kind?: string;\n toType?: string;\n toId?: string;\n}\n\nexport interface DistributionQuery {\n name?: string;\n start?: number;\n end?: number;\n}\n\n// ---------------------------------------------------------------------------\n// StorageHandle — write and read surface\n// ---------------------------------------------------------------------------\n\nexport interface StorageHandle {\n event(e: Event): Promise<void>;\n entity(e: Entity): Promise<void>;\n metric(m: MetricSample): Promise<void>;\n edge(e: Edge): Promise<void>;\n distribution(d: Distribution): Promise<void>;\n\n events(es: Event[], scope?: { names?: string[] }): Promise<void>;\n entities(es: Entity[], scope?: { types?: string[] }): Promise<void>;\n metrics(ms: MetricSample[], scope?: { names?: string[] }): Promise<void>;\n edges(es: Edge[], scope?: { kinds?: string[] }): Promise<void>;\n distributions(\n ds: Distribution[],\n scope?: { names?: string[] },\n ): Promise<void>;\n\n queryEvents(q: EventQuery): Promise<Event[]>;\n getEntity(type: string, id: string): Promise<Entity | null>;\n queryEntities(q: EntityQuery): Promise<Entity[]>;\n queryMetrics(q: MetricQuery): Promise<MetricSample[]>;\n traverse(q: EdgeQuery): Promise<Edge[]>;\n queryDistributions(q: DistributionQuery): Promise<Distribution[]>;\n\n // Deletes all rows in the given time-series shape whose timestamp column is\n // strictly less than `tsUnixMs`. Only covers append-only shapes (events,\n // metrics, distributions). Entities and edges are excluded because they hold\n // the latest known state per primary key — deleting by age would lose live\n // data. The right model for those shapes is \"expire when source disappears.\"\n deleteOlderThan(\n shape: 'events' | 'metrics' | 'distributions',\n tsUnixMs: number,\n ): Promise<{ rowsDeleted: number }>;\n}\n\n// ---------------------------------------------------------------------------\n// Credentials\n// ---------------------------------------------------------------------------\n\nexport interface CredentialField {\n description: string;\n auth?: 'none' | 'optional' | 'required';\n}\n\nexport type CredentialsSchema = Record<string, CredentialField>;\n\nexport type InferCredentials<TCreds extends CredentialsSchema> = {\n [K in keyof TCreds]: TCreds[K] extends { auth: 'required' }\n ? string\n : string | undefined;\n};\n\nexport type InferCredentialInput<TCreds extends CredentialsSchema> = {\n [K in keyof TCreds]: TCreds[K] extends { auth: 'required' }\n ? string | Secret\n : string | Secret | undefined;\n};\n\n// ---------------------------------------------------------------------------\n// Sync + Connector\n// ---------------------------------------------------------------------------\n\nexport interface SyncOptions {\n mode: 'full' | 'latest';\n since?: string;\n cursor?: unknown;\n}\n\nexport interface SyncResult {\n done: boolean;\n cursor?: unknown;\n transientError?: unknown;\n}\n\nexport interface Connector {\n readonly id: string;\n readonly credentials?: CredentialsSchema;\n serializeConfig(): Record<string, unknown>;\n sync(\n options: SyncOptions,\n storage: StorageHandle,\n signal?: AbortSignal,\n ): Promise<SyncResult>;\n}\n\nexport interface ConnectorContext {\n observer?: RequestObserver;\n}\n\nexport interface ConnectorRequestOptions {\n resource: string;\n requestId?: string;\n}\n\nexport interface RetryPolicy {\n maxAttempts?: number;\n initialDelayMs?: number;\n maxDelayMs?: number;\n signal?: AbortSignal;\n}\n\nexport abstract class BaseConnector<\n TSettings = unknown,\n TCreds extends CredentialsSchema = CredentialsSchema,\n> implements Connector {\n abstract readonly id: string;\n readonly credentials?: TCreds;\n\n protected settings: TSettings;\n protected creds: InferCredentials<TCreds>;\n private rawCredInput: InferCredentialInput<TCreds> | undefined;\n private ctx: ConnectorContext;\n\n constructor(\n settings: TSettings,\n creds?: InferCredentialInput<TCreds>,\n ctx?: ConnectorContext,\n ) {\n this.settings = settings;\n this.rawCredInput = creds;\n this.creds = creds\n ? (resolveSecrets(\n creds,\n new EnvSecretsResolver(),\n ) as InferCredentials<TCreds>)\n : ({} as InferCredentials<TCreds>);\n this.ctx = ctx ?? {};\n }\n\n protected request<T = unknown>(\n req: HttpRequest,\n opts: ConnectorRequestOptions,\n ): Promise<HttpResponse<T>> {\n return sharedRequest<T>(req, {\n resource: opts.resource,\n requestId: opts.requestId,\n observer: this.ctx.observer,\n });\n }\n\n protected get<T = unknown>(\n url: string,\n opts: ConnectorRequestOptions & {\n headers?: Record<string, string>;\n signal?: AbortSignal;\n rateLimit?: HttpRequest['rateLimit'];\n },\n ): Promise<HttpResponse<T>> {\n return this.request<T>(\n {\n url,\n method: 'GET',\n headers: opts.headers,\n signal: opts.signal,\n rateLimit: opts.rateLimit,\n },\n { resource: opts.resource, requestId: opts.requestId },\n );\n }\n\n protected post<T = unknown>(\n url: string,\n opts: ConnectorRequestOptions & {\n body?: HttpRequest['body'];\n headers?: Record<string, string>;\n signal?: AbortSignal;\n rateLimit?: HttpRequest['rateLimit'];\n },\n ): Promise<HttpResponse<T>> {\n return this.request<T>(\n {\n url,\n method: 'POST',\n headers: opts.headers,\n body: opts.body,\n signal: opts.signal,\n rateLimit: opts.rateLimit,\n },\n { resource: opts.resource, requestId: opts.requestId },\n );\n }\n\n serializeConfig(): Record<string, unknown> {\n const config: Record<string, unknown> = {\n ...(this.settings as Record<string, unknown>),\n };\n if (this.rawCredInput) {\n for (const [key, value] of Object.entries(\n this.rawCredInput as Record<string, unknown>,\n )) {\n if (value !== undefined) {\n config[key] = value;\n }\n }\n }\n return config;\n }\n\n protected sleep(ms: number, signal?: AbortSignal): Promise<void> {\n if (signal?.aborted) {\n return Promise.reject(signal.reason ?? new Error('Aborted'));\n }\n return new Promise<void>((resolve, reject) => {\n const onAbort = () => {\n clearTimeout(timer);\n reject(signal!.reason ?? new Error('Aborted'));\n };\n const timer = setTimeout(() => {\n signal?.removeEventListener('abort', onAbort);\n resolve();\n }, ms);\n signal?.addEventListener('abort', onAbort, { once: true });\n });\n }\n\n protected async withRetry<T>(\n fn: (\n signal?: AbortSignal,\n ) => Promise<{ status: 'done'; value: T } | { status: 'retry' }>,\n options?: RetryPolicy,\n ): Promise<T | null> {\n const {\n maxAttempts = 10,\n initialDelayMs = 1000,\n maxDelayMs = 10000,\n signal,\n } = options ?? {};\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n signal?.throwIfAborted();\n const result = await fn(signal);\n if (result.status === 'done') {\n return result.value;\n }\n if (attempt < maxAttempts - 1) {\n const delay = Math.min(initialDelayMs * 2 ** attempt, maxDelayMs);\n await this.sleep(delay, signal);\n }\n }\n\n return null;\n }\n\n abstract sync(\n options: SyncOptions,\n storage: StorageHandle,\n signal?: AbortSignal,\n ): Promise<SyncResult>;\n}\n\nexport function defineConnector<TSettings>() {\n return function <\n TCreds extends CredentialsSchema = Record<string, never>,\n >(def: {\n id: string;\n credentials?: TCreds;\n sync: (\n this: { settings: TSettings; creds: InferCredentials<TCreds> },\n options: SyncOptions,\n storage: StorageHandle,\n signal?: AbortSignal,\n ) => Promise<SyncResult>;\n }): {\n new (\n settings: TSettings,\n creds?: InferCredentialInput<TCreds>,\n ctx?: ConnectorContext,\n ): Connector;\n readonly id: string;\n readonly credentials: TCreds | undefined;\n } {\n class DynamicConnector extends BaseConnector<TSettings, TCreds> {\n static readonly id = def.id;\n static readonly credentials = def.credentials;\n\n readonly id = def.id;\n override readonly credentials = def.credentials;\n\n async sync(\n options: SyncOptions,\n storage: StorageHandle,\n signal?: AbortSignal,\n ): Promise<SyncResult> {\n return def.sync.call(\n { settings: this.settings, creds: this.creds },\n options,\n storage,\n signal,\n );\n }\n }\n\n return DynamicConnector as unknown as {\n new (\n settings: TSettings,\n creds?: InferCredentialInput<TCreds>,\n ctx?: ConnectorContext,\n ): Connector;\n readonly id: string;\n readonly credentials: TCreds | undefined;\n };\n };\n}\n","import type { SyncResult } from './connector';\n\nexport interface ChunkedSyncCursor<TPhase extends string, TPage> {\n phase: TPhase;\n page: TPage | null;\n}\n\nexport interface FetchPageResult<TPage> {\n items: unknown[];\n next: TPage | null;\n}\n\nexport interface ChunkedSyncOptions<TPhase extends string, TPage> {\n phases: readonly TPhase[];\n cursor: ChunkedSyncCursor<TPhase, TPage> | undefined;\n signal: AbortSignal | undefined;\n fetchPage: (\n phase: TPhase,\n page: TPage | null,\n signal: AbortSignal | undefined,\n ) => Promise<FetchPageResult<TPage>>;\n writeBatch: (\n phase: TPhase,\n items: unknown[],\n page: TPage | null,\n ) => Promise<void>;\n}\n\nexport async function paginateChunked<TPhase extends string, TPage>(\n opts: ChunkedSyncOptions<TPhase, TPage>,\n): Promise<SyncResult> {\n const { phases, cursor, signal, fetchPage, writeBatch } = opts;\n\n if (phases.length === 0) {\n return { done: true };\n }\n\n const resumeIdx = cursor ? phases.indexOf(cursor.phase) : -1;\n const hasKnownResumePhase = resumeIdx >= 0;\n const startIdx = hasKnownResumePhase ? resumeIdx : 0;\n\n for (let i = startIdx; i < phases.length; i++) {\n const phase = phases[i]!;\n let page: TPage | null =\n i === startIdx && hasKnownResumePhase ? cursor!.page : null;\n\n while (true) {\n if (signal?.aborted) {\n return {\n done: false,\n cursor: { phase, page } satisfies ChunkedSyncCursor<TPhase, TPage>,\n };\n }\n let items: unknown[];\n let next: TPage | null;\n try {\n ({ items, next } = await fetchPage(phase, page, signal));\n } catch (err) {\n if (\n signal?.aborted ||\n (err instanceof Error && err.name === 'AbortError')\n ) {\n return {\n done: false,\n cursor: { phase, page } satisfies ChunkedSyncCursor<TPhase, TPage>,\n };\n }\n return {\n done: false,\n cursor: { phase, page } satisfies ChunkedSyncCursor<TPhase, TPage>,\n transientError: err,\n };\n }\n try {\n await writeBatch(phase, items, page);\n } catch (err) {\n if (\n signal?.aborted ||\n (err instanceof Error && err.name === 'AbortError')\n ) {\n return {\n done: false,\n cursor: { phase, page } satisfies ChunkedSyncCursor<TPhase, TPage>,\n };\n }\n return {\n done: false,\n cursor: { phase, page } satisfies ChunkedSyncCursor<TPhase, TPage>,\n transientError: err,\n };\n }\n if (next === null) {\n break;\n }\n page = next;\n }\n }\n\n return { done: true };\n}\n","import { z } from 'zod';\n\nexport const shapeSchema = z.enum([\n 'event',\n 'entity',\n 'metric',\n 'edge',\n 'distribution',\n]);\n\nexport const aggFnSchema = z.enum([\n 'count',\n 'sum',\n 'avg',\n 'min',\n 'max',\n 'latest',\n 'first',\n]);\n\nexport const filterOperatorSchema = z.enum([\n 'eq',\n 'neq',\n 'gt',\n 'gte',\n 'lt',\n 'lte',\n 'contains',\n]);\n\nexport const filterConditionSchema = z.object({\n field: z.string(),\n op: filterOperatorSchema,\n value: z.union([z.string(), z.number(), z.boolean()]),\n});\n\nexport const filterClauseSchema = z.union([\n filterConditionSchema,\n z.object({ or: z.array(filterConditionSchema) }),\n]);\n\nexport const groupBySchema = z.object({\n field: z.string(),\n granularity: z.enum(['hour', 'day', 'week', 'month']),\n});\n\nexport const computedMetricSchema = z\n .object({\n connectorId: z.string(),\n shape: shapeSchema,\n name: z.string().optional(),\n entityType: z.string().optional(),\n field: z.string().optional(),\n fn: aggFnSchema,\n window: z.string().optional(),\n filter: z.array(filterClauseSchema).optional(),\n groupBy: groupBySchema.optional(),\n })\n .refine((m) => m.fn === 'count' || m.field !== undefined, {\n message: 'field is required unless fn is \"count\"',\n path: ['field'],\n });\n\nconst titleField = z\n .string()\n .meta({ label: 'Title', description: 'Widget title.' });\n\nexport const statWidgetSchema = z.object({\n kind: z.literal('stat'),\n title: titleField,\n metric: computedMetricSchema.meta({\n label: 'Metric',\n description: 'Computed metric definition.',\n }),\n window: z\n .string()\n .optional()\n .meta({ label: 'Window', description: \"Time window, e.g. '7d'.\" }),\n compare: z\n .enum(['none', 'previous-period'])\n .default('none')\n .meta({ label: 'Compare', description: 'Comparison mode.' }),\n});\n\nexport const statusWidgetSchema = z.object({\n kind: z.literal('status'),\n title: titleField,\n source: z.string().meta({\n label: 'Source',\n description: 'Connector or data source reference.',\n }),\n});\n\nexport const timeseriesWidgetSchema = z.object({\n kind: z.literal('timeseries'),\n title: titleField,\n metric: computedMetricSchema.meta({\n label: 'Metric',\n description: 'Computed metric definition.',\n }),\n window: z\n .string()\n .meta({ label: 'Window', description: \"Time window, e.g. '30d'.\" }),\n granularity: z\n .enum(['hour', 'day', 'week'])\n .default('day')\n .meta({ label: 'Granularity', description: 'Time bucket size.' }),\n});\n\nexport const distributionWidgetSchema = z.object({\n kind: z.literal('distribution'),\n title: titleField,\n metric: computedMetricSchema.meta({\n label: 'Metric',\n description: 'Computed metric definition.',\n }),\n window: z\n .string()\n .meta({ label: 'Window', description: \"Time window, e.g. '7d'.\" }),\n});\n\nexport const widgetSchemas = {\n stat: statWidgetSchema,\n status: statusWidgetSchema,\n timeseries: timeseriesWidgetSchema,\n distribution: distributionWidgetSchema,\n} as const;\n\nexport const widgetSchema = z.discriminatedUnion('kind', [\n statWidgetSchema,\n statusWidgetSchema,\n timeseriesWidgetSchema,\n distributionWidgetSchema,\n]);\n\nexport type WidgetKind = keyof typeof widgetSchemas;\n\nexport function getWidgetSchema(kind: WidgetKind) {\n return widgetSchemas[kind];\n}\n","import type { Connector } from './connector';\nimport type { RetentionConfig } from './retention';\nimport { getWidgetSchema, widgetSchemas } from './widget-schemas';\nimport type { WidgetKind } from './widget-schemas';\n\n// ---------------------------------------------------------------------------\n// Aggregation functions\n// ---------------------------------------------------------------------------\n\nexport type AggFn =\n | 'count'\n | 'sum'\n | 'avg'\n | 'min'\n | 'max'\n | 'latest'\n | 'first';\n\n// ---------------------------------------------------------------------------\n// Shape\n// ---------------------------------------------------------------------------\n\nexport type Shape = 'event' | 'entity' | 'metric' | 'edge' | 'distribution';\n\n// ---------------------------------------------------------------------------\n// Filters\n// ---------------------------------------------------------------------------\n\nexport type FilterOperator =\n | 'eq'\n | 'neq'\n | 'gt'\n | 'gte'\n | 'lt'\n | 'lte'\n | 'contains';\n\nexport interface FilterCondition {\n field: string;\n op: FilterOperator;\n value: string | number | boolean;\n}\n\nexport type FilterClause = FilterCondition | { or: FilterCondition[] };\n\n// ---------------------------------------------------------------------------\n// GroupBy\n// ---------------------------------------------------------------------------\n\nexport interface GroupBy {\n field: string;\n granularity: 'hour' | 'day' | 'week' | 'month';\n}\n\n// ---------------------------------------------------------------------------\n// Metric\n// ---------------------------------------------------------------------------\n\nexport interface Metric {\n connector: { id: string };\n shape: Shape;\n name?: string;\n entityType?: string;\n field?: string;\n fn: AggFn;\n window?: string;\n filter?: FilterClause[];\n groupBy?: GroupBy;\n}\n\nexport interface ComputedMetric {\n readonly connectorId: string;\n readonly shape: Shape;\n readonly name?: string;\n readonly entityType?: string;\n readonly field?: string;\n readonly fn: AggFn;\n readonly window?: string;\n readonly filter?: FilterClause[];\n readonly groupBy?: GroupBy;\n}\n\n// ---------------------------------------------------------------------------\n// Widget definition\n// ---------------------------------------------------------------------------\n\nexport interface StatWidget {\n kind: 'stat';\n title: string;\n metric: ComputedMetric;\n window?: string;\n compare?: 'none' | 'previous-period';\n}\n\nexport interface StatusWidget {\n kind: 'status';\n title: string;\n source: string;\n}\n\nexport interface TimeseriesWidget {\n kind: 'timeseries';\n title: string;\n metric: ComputedMetric;\n window: string;\n granularity?: 'hour' | 'day' | 'week';\n}\n\nexport interface DistributionWidget {\n kind: 'distribution';\n title: string;\n metric: ComputedMetric;\n window: string;\n}\n\nexport type Widget =\n | StatWidget\n | StatusWidget\n | TimeseriesWidget\n | DistributionWidget;\n\nexport type { WidgetKind };\n\n// ---------------------------------------------------------------------------\n// Dashboard config\n// ---------------------------------------------------------------------------\n\nexport interface ConfiguredConnector {\n connector: Connector;\n}\n\nexport interface Dashboard {\n widgets: Record<string, Widget>;\n}\n\nexport interface DashboardConfig {\n connectors: ConfiguredConnector[];\n dashboards: Record<string, Dashboard>;\n retention?: RetentionConfig;\n}\n\n// ---------------------------------------------------------------------------\n// defineDashboard\n// ---------------------------------------------------------------------------\n\nconst VALID_WIDGET_KINDS = new Set<string>(Object.keys(widgetSchemas));\n\nexport function defineDashboard(options: {\n widgets: Record<string, Widget>;\n}): Dashboard {\n for (const [key, widget] of Object.entries(options.widgets)) {\n if (!VALID_WIDGET_KINDS.has(widget.kind)) {\n throw new Error(\n `Widget \"${key}\": unknown kind \"${widget.kind}\". Must be one of: ${[...VALID_WIDGET_KINDS].join(', ')}`,\n );\n }\n const schema = getWidgetSchema(widget.kind as WidgetKind);\n const result = schema.safeParse(widget);\n if (!result.success) {\n throw new Error(\n `Widget \"${key}\" (kind \"${widget.kind}\"): ${result.error.issues.map((i) => i.message).join('; ')}`,\n );\n }\n }\n return { widgets: options.widgets };\n}\n\n// ---------------------------------------------------------------------------\n// defineMetric\n// ---------------------------------------------------------------------------\n\nexport function defineMetric(options: Metric): ComputedMetric {\n return {\n connectorId: options.connector.id,\n shape: options.shape,\n name: options.name,\n entityType: options.entityType,\n field: options.field,\n fn: options.fn,\n window: options.window,\n filter: options.filter,\n groupBy: options.groupBy,\n };\n}\n\n// ---------------------------------------------------------------------------\n// defineConfig\n// ---------------------------------------------------------------------------\n\nconst VALID_SHAPES = new Set<string>([\n 'event',\n 'entity',\n 'metric',\n 'edge',\n 'distribution',\n]);\nconst VALID_FNS = new Set<string>([\n 'count',\n 'sum',\n 'avg',\n 'min',\n 'max',\n 'latest',\n 'first',\n]);\n\nconst SAFE_KEY_RE = /^[a-zA-Z0-9_-]+$/;\n\nfunction validateConfig(config: DashboardConfig): void {\n if (config.retention) {\n const { maxAge, maxSize, floor, intervalMs } = config.retention;\n if (maxAge !== undefined && (!Number.isFinite(maxAge) || maxAge < 0)) {\n throw new Error('retention.maxAge must be a finite number >= 0');\n }\n if (maxSize !== undefined && (!Number.isInteger(maxSize) || maxSize < 0)) {\n throw new Error('retention.maxSize must be an integer >= 0');\n }\n if (floor !== undefined && (!Number.isInteger(floor) || floor < 0)) {\n throw new Error('retention.floor must be an integer >= 0');\n }\n if (\n intervalMs !== undefined &&\n (!Number.isFinite(intervalMs) || intervalMs <= 0)\n ) {\n throw new Error('retention.intervalMs must be a finite number > 0');\n }\n }\n\n if (\n !config.dashboards ||\n typeof config.dashboards !== 'object' ||\n Array.isArray(config.dashboards)\n ) {\n throw new Error(\n 'defineConfig: config must include a \"dashboards\" record — did you mean to migrate from the old flat \"widgets\" shape?',\n );\n }\n\n const connectorIds = new Set(config.connectors.map((e) => e.connector.id));\n\n for (const [dashboardKey, dashboard] of Object.entries(config.dashboards)) {\n if (\n !dashboard.widgets ||\n typeof dashboard.widgets !== 'object' ||\n Array.isArray(dashboard.widgets)\n ) {\n throw new Error(\n `Dashboard \"${dashboardKey}\" must define a \"widgets\" record`,\n );\n }\n\n if (!SAFE_KEY_RE.test(dashboardKey)) {\n throw new Error(\n `Dashboard key \"${dashboardKey}\" contains URL-unsafe characters; use only letters, digits, hyphens, and underscores`,\n );\n }\n\n for (const [widgetKey, widget] of Object.entries(dashboard.widgets)) {\n const ref = `Dashboard \"${dashboardKey}\", widget \"${widgetKey}\"`;\n\n if (!SAFE_KEY_RE.test(widgetKey)) {\n throw new Error(\n `${ref}: widget key contains URL-unsafe characters; use only letters, digits, hyphens, and underscores`,\n );\n }\n\n if (widget.kind === 'status') {\n continue;\n }\n\n const { connectorId, shape, fn } = widget.metric;\n\n if (!connectorIds.has(connectorId)) {\n throw new Error(\n `${ref}: connector \"${connectorId}\" is not listed in connectors`,\n );\n }\n\n if (!VALID_SHAPES.has(shape)) {\n throw new Error(`${ref}: invalid shape \"${shape}\"`);\n }\n\n if (!VALID_FNS.has(fn)) {\n throw new Error(`${ref}: invalid fn \"${fn}\"`);\n }\n }\n }\n}\n\nexport function defineConfig(config: DashboardConfig): DashboardConfig {\n validateConfig(config);\n return config;\n}\n","import type {\n Distribution,\n Event,\n MetricSample,\n StorageHandle,\n} from './connector';\n\n// ---------------------------------------------------------------------------\n// RetentionConfig\n// ---------------------------------------------------------------------------\n\nexport interface RetentionConfig {\n maxAge?: number;\n maxSize?: number;\n floor?: number;\n intervalMs?: number;\n}\n\n// ---------------------------------------------------------------------------\n// RetentionDeletionPlan — rows eligible for deletion across time-series shapes\n// ---------------------------------------------------------------------------\n\nexport interface RetentionDeletionPlan {\n events: Event[];\n metrics: MetricSample[];\n distributions: Distribution[];\n}\n\n// ---------------------------------------------------------------------------\n// selectForDeletion — pure computation\n//\n// Receives rows pre-sorted newest-first (descending by timestamp).\n// Returns the subset that should be deleted given the policy.\n//\n// Rules applied in order:\n// 1. Rows beyond maxSize are candidates.\n// 2. Rows older than maxAge milliseconds are candidates.\n// 3. Rows within the newest `floor` positions are always kept (overrides 1 & 2).\n// ---------------------------------------------------------------------------\n\nexport function selectForDeletion<T>(\n rows: T[],\n getTs: (row: T) => number,\n config: RetentionConfig,\n nowMs: number = Date.now(),\n): T[] {\n const { maxAge, maxSize, floor = 0 } = config;\n\n if (maxAge === undefined && maxSize === undefined) {\n return [];\n }\n\n const toDelete: T[] = [];\n\n for (let i = 0; i < rows.length; i++) {\n const row = rows[i]!;\n if (i < floor) {\n continue;\n }\n\n const overSize = maxSize !== undefined && i >= maxSize;\n const tooOld = maxAge !== undefined && getTs(row) < nowMs - maxAge;\n\n if (overSize || tooOld) {\n toDelete.push(row);\n }\n }\n\n return toDelete;\n}\n\n// ---------------------------------------------------------------------------\n// computeRetention — async, queries the handle and returns deletion candidates\n//\n// Only covers time-series shapes (events, metrics, distributions) since those\n// grow unboundedly via append. Entities and edges are upsert-keyed and do not\n// accumulate the same way.\n// ---------------------------------------------------------------------------\n\nexport async function computeRetention(\n handle: StorageHandle,\n config: RetentionConfig,\n nowMs: number = Date.now(),\n): Promise<RetentionDeletionPlan> {\n const [events, metrics, distributions] = await Promise.all([\n handle.queryEvents({}),\n handle.queryMetrics({}),\n handle.queryDistributions({}),\n ]);\n\n const sortedEvents = [...events].sort((a, b) => b.start_ts - a.start_ts);\n const sortedMetrics = [...metrics].sort((a, b) => b.ts - a.ts);\n const sortedDistributions = [...distributions].sort((a, b) => b.ts - a.ts);\n\n return {\n events: selectForDeletion(sortedEvents, (e) => e.start_ts, config, nowMs),\n metrics: selectForDeletion(sortedMetrics, (m) => m.ts, config, nowMs),\n distributions: selectForDeletion(\n sortedDistributions,\n (d) => d.ts,\n config,\n nowMs,\n ),\n };\n}\n","import { z } from 'zod';\n\nexport type ConfigFieldsSchema = z.ZodObject<z.ZodRawShape>;\n\nexport function defineConfigFields<T extends z.ZodRawShape>(\n schema: z.ZodObject<T>,\n): z.ZodObject<T> {\n if (!(schema instanceof z.ZodObject)) {\n throw new Error(\n `configFields must be a Zod object schema (z.object({...})). Received: ${Object.prototype.toString.call(schema)}`,\n );\n }\n return schema;\n}\n","import type { ComputedMetric } from './config';\nimport type { StorageHandle } from './connector';\n\ntype FilterClause = NonNullable<ComputedMetric['filter']>[number];\ntype FilterCondition = Exclude<FilterClause, { or: unknown[] }>;\n\nfunction matchesCondition(\n record: Record<string, unknown>,\n cond: FilterCondition,\n): boolean {\n const val = record[cond.field];\n switch (cond.op) {\n case 'eq':\n return val === cond.value;\n case 'neq':\n return val !== cond.value;\n case 'gt':\n if (typeof val !== 'number' || typeof cond.value !== 'number') {\n return false;\n }\n return val > cond.value;\n case 'gte':\n if (typeof val !== 'number' || typeof cond.value !== 'number') {\n return false;\n }\n return val >= cond.value;\n case 'lt':\n if (typeof val !== 'number' || typeof cond.value !== 'number') {\n return false;\n }\n return val < cond.value;\n case 'lte':\n if (typeof val !== 'number' || typeof cond.value !== 'number') {\n return false;\n }\n return val <= cond.value;\n case 'contains':\n return String(val).includes(String(cond.value));\n default:\n return false;\n }\n}\n\nfunction applyFilter(\n record: Record<string, unknown>,\n filter: ComputedMetric['filter'],\n): boolean {\n if (!filter) {\n return true;\n }\n for (const clause of filter) {\n if ('or' in clause) {\n if (!clause.or.some((cond) => matchesCondition(record, cond))) {\n return false;\n }\n } else {\n if (!matchesCondition(record, clause)) {\n return false;\n }\n }\n }\n return true;\n}\n\nconst WINDOW_MS: Record<string, number> = {\n h: 3_600_000,\n d: 86_400_000,\n w: 604_800_000,\n m: 2_592_000_000,\n};\n\nfunction parseWindowMs(window: string): number | null {\n const match = /^(\\d+)(h|d|w|m)$/.exec(window);\n if (!match) {\n return null;\n }\n const unitMs = WINDOW_MS[match[2]!];\n if (unitMs === undefined) {\n return null;\n }\n return parseInt(match[1]!) * unitMs;\n}\n\nfunction truncateToGranularity(ts: number, granularity: string): string {\n const d = new Date(ts);\n switch (granularity) {\n case 'hour':\n d.setUTCMinutes(0, 0, 0);\n return d.toISOString();\n case 'day':\n d.setUTCHours(0, 0, 0, 0);\n return d.toISOString().slice(0, 10);\n case 'week': {\n d.setUTCDate(d.getUTCDate() - d.getUTCDay());\n d.setUTCHours(0, 0, 0, 0);\n return d.toISOString().slice(0, 10);\n }\n case 'month':\n d.setUTCDate(1);\n d.setUTCHours(0, 0, 0, 0);\n return d.toISOString().slice(0, 7);\n default:\n return d.toISOString().slice(0, 10);\n }\n}\n\nfunction computeAgg(\n records: Record<string, unknown>[],\n field: string | undefined,\n fn: string,\n): unknown {\n if (fn === 'count') {\n return records.length;\n }\n if (field === undefined) {\n throw new Error(`computeAgg: fn \"${fn}\" requires a field`);\n }\n if (fn === 'latest') {\n return records.at(-1)?.[field] ?? null;\n }\n if (fn === 'first') {\n return records[0]?.[field] ?? null;\n }\n const values = records\n .map((r) => r[field])\n .filter((v) => v !== undefined && v !== null);\n const nonNumeric = values.find((v) => typeof v !== 'number');\n if (nonNumeric !== undefined) {\n throw new Error(\n `computeAgg: fn \"${fn}\" requires numeric values for field \"${field}\", got ${typeof nonNumeric} (${String(nonNumeric)})`,\n );\n }\n const numbers = values as number[];\n if (fn === 'sum') {\n return numbers.reduce((a, b) => a + b, 0);\n }\n if (fn === 'avg') {\n return numbers.length > 0\n ? numbers.reduce((a, b) => a + b, 0) / numbers.length\n : null;\n }\n if (fn === 'min') {\n return numbers.length > 0\n ? numbers.reduce((a, b) => (a < b ? a : b))\n : null;\n }\n if (fn === 'max') {\n return numbers.length > 0\n ? numbers.reduce((a, b) => (a > b ? a : b))\n : null;\n }\n return null;\n}\n\nfunction sortByTs(\n records: Record<string, unknown>[],\n tsField: string,\n): Record<string, unknown>[] {\n return [...records].sort((a, b) => {\n return (a[tsField] as number) - (b[tsField] as number);\n });\n}\n\nfunction computeGroupBy(\n records: Record<string, unknown>[],\n metric: ComputedMetric,\n tsField: string,\n): unknown {\n const { field, granularity } = metric.groupBy!;\n const groups = new Map<string, Record<string, unknown>[]>();\n\n for (const record of records) {\n const ts = record[field] as number | undefined;\n if (ts === undefined || typeof ts !== 'number') {\n continue;\n }\n const key = truncateToGranularity(ts, granularity);\n if (!groups.has(key)) {\n groups.set(key, []);\n }\n groups.get(key)!.push(record);\n }\n\n return [...groups.entries()]\n .map(([key, groupRecords]) => ({\n date: key,\n value: computeAgg(\n sortByTs(groupRecords, tsField),\n metric.field,\n metric.fn,\n ),\n }))\n .sort((a, b) => (a.date < b.date ? -1 : 1));\n}\n\nfunction getTimestampField(shape: string): string {\n switch (shape) {\n case 'event':\n return 'start_ts';\n case 'metric':\n case 'distribution':\n return 'ts';\n case 'entity':\n case 'edge':\n return 'updated_at';\n default:\n return 'start_ts';\n }\n}\n\nexport async function computeMetric(\n storage: StorageHandle,\n metric: ComputedMetric,\n): Promise<unknown> {\n const tsField = getTimestampField(metric.shape);\n\n const windowMs = metric.window ? parseWindowMs(metric.window) : null;\n const windowStart = windowMs !== null ? Date.now() - windowMs : undefined;\n\n let records: Record<string, unknown>[];\n\n switch (metric.shape) {\n case 'event': {\n const events = await storage.queryEvents({\n name: metric.name,\n start: windowStart,\n });\n records = events.map((e) => ({\n ...e.attributes,\n name: e.name,\n start_ts: e.start_ts,\n end_ts: e.end_ts,\n }));\n break;\n }\n\n case 'entity': {\n const type = metric.entityType ?? metric.name ?? '';\n const entities = await storage.queryEntities({ type });\n records = entities.map((e) => ({\n ...e.attributes,\n type: e.type,\n id: e.id,\n updated_at: e.updated_at,\n }));\n if (windowStart !== undefined) {\n records = records.filter((r) => (r[tsField] as number) >= windowStart);\n }\n break;\n }\n\n case 'metric': {\n const metrics = await storage.queryMetrics({\n name: metric.name,\n start: windowStart,\n });\n records = metrics.map((m) => ({\n ...m.attributes,\n name: m.name,\n ts: m.ts,\n value: m.value,\n }));\n break;\n }\n\n case 'edge': {\n const edges = await storage.traverse({ kind: metric.name });\n records = edges.map((e) => ({\n ...e.attributes,\n from_type: e.from_type,\n from_id: e.from_id,\n kind: e.kind,\n to_type: e.to_type,\n to_id: e.to_id,\n updated_at: e.updated_at,\n }));\n if (windowStart !== undefined) {\n records = records.filter((r) => (r[tsField] as number) >= windowStart);\n }\n break;\n }\n\n case 'distribution': {\n const distributions = await storage.queryDistributions({\n name: metric.name,\n start: windowStart,\n });\n records = distributions.map((d) => ({\n ...d.attributes,\n name: d.name,\n ts: d.ts,\n kind: d.kind,\n data: d.data,\n }));\n break;\n }\n\n default:\n return null;\n }\n\n const filtered = records.filter((r) => applyFilter(r, metric.filter));\n const sorted = sortByTs(filtered, tsField);\n\n if (metric.groupBy) {\n return computeGroupBy(sorted, metric, tsField);\n }\n\n return computeAgg(sorted, metric.field, metric.fn);\n}\n","import { computeMetric } from './compute';\nimport type { ConfiguredConnector, Widget } from './config';\nimport type { ServerStorage } from './server-storage';\nimport type { CachedWidget } from './wire';\n\nexport async function resolveWidget(\n widgetId: string,\n widget: Widget,\n connectors: ConfiguredConnector[] | readonly string[] | undefined,\n storage: ServerStorage,\n): Promise<CachedWidget | undefined> {\n if (widget.kind === 'status') {\n return {\n widgetId,\n connectorId: widget.source,\n data: null,\n cachedAt: null,\n };\n }\n const { connectorId } = widget.metric;\n if (\n connectors !== undefined &&\n !isAllowedConnector(connectors, connectorId)\n ) {\n return undefined;\n }\n const handle = storage.getStorageHandle(connectorId);\n const data = await computeMetric(handle, widget.metric);\n return {\n widgetId,\n connectorId,\n data,\n cachedAt: (await storage.getSyncState()).lastSyncAt,\n };\n}\n\nfunction isAllowedConnector(\n connectors: ConfiguredConnector[] | readonly string[],\n connectorId: string,\n): boolean {\n if (connectors.length === 0) {\n return false;\n }\n if (typeof connectors[0] === 'string') {\n return (connectors as readonly string[]).includes(connectorId);\n }\n return (connectors as ConfiguredConnector[]).some(\n (e) => e.connector.id === connectorId,\n );\n}\n","import type {\n Distribution,\n DistributionQuery,\n Edge,\n EdgeQuery,\n Entity,\n EntityQuery,\n Event,\n EventQuery,\n MetricQuery,\n MetricSample,\n StorageHandle,\n} from './connector';\nimport type { SyncState } from './engine';\nimport type { ServerStorage } from './server-storage';\n\nexport class InMemoryStorage implements ServerStorage {\n private eventStore = new Map<string, Event[]>();\n private entityStore = new Map<string, Map<string, Map<string, Entity>>>();\n private metricStore = new Map<string, MetricSample[]>();\n private edgeStore = new Map<string, Edge[]>();\n private distributionStore = new Map<string, Distribution[]>();\n private syncState: SyncState = {\n status: 'idle',\n lastSyncAt: null,\n lastError: null,\n };\n\n getStorageHandle(connectorId: string): StorageHandle {\n const getEntityMap = (): Map<string, Map<string, Entity>> => {\n if (!this.entityStore.has(connectorId)) {\n this.entityStore.set(connectorId, new Map());\n }\n return this.entityStore.get(connectorId)!;\n };\n\n const upsertEntities = (es: Entity[]): void => {\n const byType = getEntityMap();\n for (const e of es) {\n if (!byType.has(e.type)) {\n byType.set(e.type, new Map());\n }\n byType.get(e.type)!.set(e.id, e);\n }\n };\n\n const upsertEdges = (es: Edge[]): void => {\n const existing = this.edgeStore.get(connectorId) ?? [];\n const index = new Map<string, number>();\n for (let i = 0; i < existing.length; i++) {\n const e = existing[i]!;\n index.set(\n `${e.from_type}:${e.from_id}:${e.kind}:${e.to_type}:${e.to_id}`,\n i,\n );\n }\n for (const e of es) {\n const key = `${e.from_type}:${e.from_id}:${e.kind}:${e.to_type}:${e.to_id}`;\n const idx = index.get(key);\n if (idx !== undefined) {\n existing[idx] = e;\n } else {\n index.set(key, existing.length);\n existing.push(e);\n }\n }\n this.edgeStore.set(connectorId, existing);\n };\n\n return {\n event: async (e) => {\n if (!this.eventStore.has(connectorId)) {\n this.eventStore.set(connectorId, []);\n }\n this.eventStore.get(connectorId)!.push(e);\n },\n\n entity: async (e) => {\n upsertEntities([e]);\n },\n\n metric: async (m) => {\n if (!this.metricStore.has(connectorId)) {\n this.metricStore.set(connectorId, []);\n }\n this.metricStore.get(connectorId)!.push(m);\n },\n\n edge: async (e) => {\n upsertEdges([e]);\n },\n\n distribution: async (d) => {\n if (!this.distributionStore.has(connectorId)) {\n this.distributionStore.set(connectorId, []);\n }\n this.distributionStore.get(connectorId)!.push(d);\n },\n\n events: async (es, scope) => {\n const names = new Set(scope?.names ?? es.map((e) => e.name));\n const kept = (this.eventStore.get(connectorId) ?? []).filter(\n (e) => !names.has(e.name),\n );\n this.eventStore.set(connectorId, [...kept, ...es]);\n },\n\n entities: async (es, scope) => {\n const byType = getEntityMap();\n const types = new Set(scope?.types ?? es.map((e) => e.type));\n for (const type of types) {\n byType.set(type, new Map());\n }\n upsertEntities(es);\n },\n\n metrics: async (ms, scope) => {\n const names = new Set(scope?.names ?? ms.map((m) => m.name));\n const kept = (this.metricStore.get(connectorId) ?? []).filter(\n (m) => !names.has(m.name),\n );\n this.metricStore.set(connectorId, [...kept, ...ms]);\n },\n\n edges: async (es, scope) => {\n const kinds = new Set(scope?.kinds ?? es.map((e) => e.kind));\n const kept = (this.edgeStore.get(connectorId) ?? []).filter(\n (e) => !kinds.has(e.kind),\n );\n this.edgeStore.set(connectorId, kept);\n upsertEdges(es);\n },\n\n distributions: async (ds, scope) => {\n const names = new Set(scope?.names ?? ds.map((d) => d.name));\n const kept = (this.distributionStore.get(connectorId) ?? []).filter(\n (d) => !names.has(d.name),\n );\n this.distributionStore.set(connectorId, [...kept, ...ds]);\n },\n\n queryEvents: async (q: EventQuery) => {\n let results = this.eventStore.get(connectorId) ?? [];\n if (q.name !== undefined) {\n results = results.filter((e) => e.name === q.name);\n }\n if (q.start !== undefined) {\n results = results.filter((e) => e.start_ts >= q.start!);\n }\n if (q.end !== undefined) {\n results = results.filter((e) => e.start_ts <= q.end!);\n }\n return results;\n },\n\n getEntity: async (type: string, id: string) => {\n return getEntityMap().get(type)?.get(id) ?? null;\n },\n\n queryEntities: async (q: EntityQuery) => {\n const byType = getEntityMap().get(q.type);\n if (!byType) {\n return [];\n }\n return Array.from(byType.values());\n },\n\n queryMetrics: async (q: MetricQuery) => {\n let results = this.metricStore.get(connectorId) ?? [];\n if (q.name !== undefined) {\n results = results.filter((m) => m.name === q.name);\n }\n if (q.start !== undefined) {\n results = results.filter((m) => m.ts >= q.start!);\n }\n if (q.end !== undefined) {\n results = results.filter((m) => m.ts <= q.end!);\n }\n return results;\n },\n\n traverse: async (q: EdgeQuery) => {\n let results = this.edgeStore.get(connectorId) ?? [];\n if (q.fromType !== undefined) {\n results = results.filter((e) => e.from_type === q.fromType);\n }\n if (q.fromId !== undefined) {\n results = results.filter((e) => e.from_id === q.fromId);\n }\n if (q.kind !== undefined) {\n results = results.filter((e) => e.kind === q.kind);\n }\n if (q.toType !== undefined) {\n results = results.filter((e) => e.to_type === q.toType);\n }\n if (q.toId !== undefined) {\n results = results.filter((e) => e.to_id === q.toId);\n }\n return results;\n },\n\n queryDistributions: async (q: DistributionQuery) => {\n let results = this.distributionStore.get(connectorId) ?? [];\n if (q.name !== undefined) {\n results = results.filter((d) => d.name === q.name);\n }\n if (q.start !== undefined) {\n results = results.filter((d) => d.ts >= q.start!);\n }\n if (q.end !== undefined) {\n results = results.filter((d) => d.ts <= q.end!);\n }\n return results;\n },\n\n deleteOlderThan: async (shape, tsUnixMs) => {\n if (shape === 'events') {\n const before = this.eventStore.get(connectorId) ?? [];\n const after = before.filter((e) => e.start_ts >= tsUnixMs);\n this.eventStore.set(connectorId, after);\n return { rowsDeleted: before.length - after.length };\n } else if (shape === 'metrics') {\n const before = this.metricStore.get(connectorId) ?? [];\n const after = before.filter((m) => m.ts >= tsUnixMs);\n this.metricStore.set(connectorId, after);\n return { rowsDeleted: before.length - after.length };\n } else if (shape === 'distributions') {\n const before = this.distributionStore.get(connectorId) ?? [];\n const after = before.filter((d) => d.ts >= tsUnixMs);\n this.distributionStore.set(connectorId, after);\n return { rowsDeleted: before.length - after.length };\n } else {\n throw new Error(\n `Unsupported shape for deleteOlderThan: ${String(shape)}`,\n );\n }\n },\n };\n }\n\n async getSyncState(): Promise<SyncState> {\n return { ...this.syncState };\n }\n\n async setSyncing(): Promise<boolean> {\n if (this.syncState.status === 'syncing') {\n return false;\n }\n this.syncState = { ...this.syncState, status: 'syncing' };\n return true;\n }\n\n async setSyncSuccess(): Promise<void> {\n this.syncState = {\n status: 'idle',\n lastSyncAt: new Date().toISOString(),\n lastError: null,\n };\n }\n\n async setSyncError(error: string): Promise<void> {\n this.syncState = {\n status: 'error',\n lastSyncAt: this.syncState.lastSyncAt,\n lastError: error,\n };\n }\n}\n","import { z } from 'zod';\n\nimport type { DashboardConfig } from './config';\n\nexport const wireConnectorSchema = z.object({\n name: z.string(),\n connectorId: z.string(),\n displayName: z.string().optional(),\n config: z.record(z.string(), z.unknown()),\n syncIntervalSeconds: z.number().optional(),\n enabled: z.boolean().optional(),\n});\n\nexport const wireDashboardSchema = z.object({\n id: z.string().optional(),\n name: z.string(),\n slug: z.string(),\n config: z.record(z.string(), z.unknown()),\n});\n\nexport const wireConfigSchema = z.object({\n connectors: z.array(wireConnectorSchema).optional(),\n dashboards: z.array(wireDashboardSchema).optional(),\n});\n\nexport type WireConnector = z.infer<typeof wireConnectorSchema>;\nexport type WireDashboard = z.infer<typeof wireDashboardSchema>;\nexport type WireConfig = z.infer<typeof wireConfigSchema>;\n\nexport function toWireConfig(config: DashboardConfig): WireConfig {\n return {\n connectors: config.connectors.map(({ connector }) => ({\n name: connector.id,\n connectorId: connector.id,\n displayName: connector.id,\n config: connector.serializeConfig(),\n syncIntervalSeconds: 300,\n enabled: true,\n })),\n dashboards: Object.entries(config.dashboards).map(([id, dash]) => ({\n id,\n name: id,\n slug: id,\n config: { widgets: dash.widgets },\n })),\n };\n}\n"],"mappings":"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","names":["err","z","z"]}
|
|
1
|
+
{"version":3,"sources":["../../connector-shared/src/errors.ts","../../connector-shared/src/retry.ts","../../connector-shared/src/version.ts","../../connector-shared/src/request.ts","../../connector-shared/src/rate-limit.ts","../../connector-shared/src/pagination.ts","../src/secrets.ts","../src/connector.ts","../src/paginate-chunked.ts","../src/widget-schemas.ts","../src/config.ts","../src/retention.ts","../src/config-fields.ts","../src/compute.ts","../src/resolve-widget.ts","../src/in-memory-storage.ts","../src/wire-config.ts"],"sourcesContent":["import type { HttpResponse } from './types';\n\nexport type HttpErrorKind =\n | 'transient'\n | 'rate_limit'\n | 'auth'\n | 'upstream_bug'\n | 'client_bug';\n\nexport abstract class HttpClientError extends Error {\n abstract readonly kind: HttpErrorKind;\n readonly response?: HttpResponse;\n\n constructor(message: string, response?: HttpResponse) {\n super(message);\n this.name = new.target.name;\n this.response = response;\n }\n}\n\nexport class TransientError extends HttpClientError {\n readonly kind = 'transient' as const;\n}\n\nexport class RateLimitError extends HttpClientError {\n readonly kind = 'rate_limit' as const;\n readonly retryAfter?: Date;\n\n constructor(message: string, response?: HttpResponse, retryAfter?: Date) {\n super(message, response);\n this.retryAfter = retryAfter;\n }\n}\n\nexport class AuthError extends HttpClientError {\n readonly kind = 'auth' as const;\n}\n\nexport class UpstreamBugError extends HttpClientError {\n readonly kind = 'upstream_bug' as const;\n}\n\nexport class ClientBugError extends HttpClientError {\n readonly kind = 'client_bug' as const;\n}\n\nexport function classifyStatus(status: number): HttpErrorKind {\n if (status === 429) {\n return 'rate_limit';\n }\n if (status === 401 || status === 403) {\n return 'auth';\n }\n if (status === 408) {\n return 'transient';\n }\n if (status >= 500) {\n return 'upstream_bug';\n }\n if (status >= 400) {\n return 'client_bug';\n }\n return 'client_bug';\n}\n\nexport function errorForStatus(\n message: string,\n response: HttpResponse,\n retryAfter?: Date,\n): HttpClientError {\n const kind = classifyStatus(response.status);\n switch (kind) {\n case 'rate_limit':\n return new RateLimitError(message, response, retryAfter);\n case 'auth':\n return new AuthError(message, response);\n case 'transient':\n return new TransientError(message, response);\n case 'upstream_bug':\n return new UpstreamBugError(message, response);\n case 'client_bug':\n return new ClientBugError(message, response);\n }\n}\n","import { HttpClientError, RateLimitError, TransientError } from './errors';\n\nexport interface RetryPolicy {\n maxAttempts?: number;\n initialDelayMs?: number;\n maxDelayMs?: number;\n retryOn?: (status: number | null, err?: Error) => boolean;\n}\n\nexport const defaultRetryOn = (status: number | null, err?: Error): boolean => {\n if (err instanceof RateLimitError) {\n return true;\n }\n if (err instanceof TransientError) {\n return true;\n }\n if (status === null) {\n return err instanceof Error && !(err instanceof HttpClientError);\n }\n if (status === 408 || status === 429) {\n return true;\n }\n if (status >= 500) {\n return true;\n }\n return false;\n};\n\nexport function backoffDelayMs(\n attempt: number,\n policy: Required<Pick<RetryPolicy, 'initialDelayMs' | 'maxDelayMs'>>,\n): number {\n const base = policy.initialDelayMs * 2 ** attempt;\n const jitter = base * 0.25 * Math.random();\n return Math.min(base + jitter, policy.maxDelayMs);\n}\n\nexport function parseRetryAfter(\n headerValue: string | null,\n now: Date = new Date(),\n): Date | undefined {\n if (!headerValue) {\n return undefined;\n }\n const trimmed = headerValue.trim();\n if (/^\\d+$/.test(trimmed)) {\n return new Date(now.getTime() + Number(trimmed) * 1000);\n }\n const parsed = Date.parse(trimmed);\n if (Number.isNaN(parsed)) {\n return undefined;\n }\n return new Date(parsed);\n}\n\nexport function sleep(ms: number, signal?: AbortSignal): Promise<void> {\n if (signal?.aborted) {\n return Promise.reject(signal.reason ?? new Error('Aborted'));\n }\n return new Promise<void>((resolve, reject) => {\n const onAbort = () => {\n clearTimeout(timer);\n reject(signal!.reason ?? new Error('Aborted'));\n };\n const timer = setTimeout(() => {\n signal?.removeEventListener('abort', onAbort);\n resolve();\n }, ms);\n signal?.addEventListener('abort', onAbort, { once: true });\n });\n}\n","export const HTTP_CLIENT_VERSION = '0.0.0';\n\nexport const DEFAULT_USER_AGENT = `rawdash-connector/${HTTP_CLIENT_VERSION} (+https://rawdash.dev)`;\n","import {\n AuthError,\n ClientBugError,\n HttpClientError,\n RateLimitError,\n TransientError,\n UpstreamBugError,\n errorForStatus,\n} from './errors';\nimport { defaultRetryOn, parseRetryAfter, sleep } from './retry';\nimport type { FetchLike, HttpMethod, HttpRequest, HttpResponse } from './types';\nimport { DEFAULT_USER_AGENT } from './version';\n\nconst DEFAULT_TIMEOUT_MS = 10_000;\nconst DEFAULT_MAX_ATTEMPTS = 3;\nconst DEFAULT_INITIAL_DELAY_MS = 1000;\nconst DEFAULT_MAX_DELAY_MS = 60_000;\nconst OBSERVER_TIMEOUT_MS = 250;\n\nexport interface RequestObservation {\n url: string;\n method: HttpMethod;\n status: number;\n resource: string;\n requestId: string;\n body: unknown;\n}\n\nexport type RequestObserver = (\n event: RequestObservation,\n) => void | Promise<void>;\n\nexport interface RequestOptions {\n fetch?: FetchLike;\n observer?: RequestObserver;\n resource: string;\n requestId?: string;\n}\n\nasync function notifyObserver(\n observer: RequestObserver,\n event: RequestObservation,\n): Promise<void> {\n let result: void | Promise<void>;\n try {\n result = observer(event);\n } catch (err) {\n console.warn('[connector-shared] request observer threw:', err);\n return;\n }\n if (!(result instanceof Promise)) {\n return;\n }\n const guarded = result.catch((err) => {\n console.warn('[connector-shared] request observer rejected:', err);\n });\n let timer: ReturnType<typeof setTimeout> | undefined;\n const timeout = new Promise<void>((resolve) => {\n timer = setTimeout(resolve, OBSERVER_TIMEOUT_MS);\n });\n try {\n await Promise.race([guarded, timeout]);\n } finally {\n if (timer) {\n clearTimeout(timer);\n }\n }\n}\n\nfunction newRequestId(): string {\n const c = (globalThis as { crypto?: { randomUUID?: () => string } }).crypto;\n if (c?.randomUUID) {\n return c.randomUUID();\n }\n return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;\n}\n\nfunction mergeHeaders(\n defaults: Record<string, string>,\n overrides: Record<string, string> | undefined,\n): Record<string, string> {\n const merged: Record<string, string> = {};\n for (const [k, v] of Object.entries(defaults)) {\n merged[k.toLowerCase()] = v;\n }\n if (overrides) {\n for (const [k, v] of Object.entries(overrides)) {\n merged[k.toLowerCase()] = v;\n }\n }\n return merged;\n}\n\nfunction linkTimeoutSignal(\n parent: AbortSignal | undefined,\n timeoutMs: number,\n): { signal: AbortSignal; cancel: () => void } {\n const controller = new AbortController();\n const onParentAbort = () => {\n controller.abort(parent?.reason);\n };\n if (parent) {\n if (parent.aborted) {\n controller.abort(parent.reason);\n } else {\n parent.addEventListener('abort', onParentAbort, { once: true });\n }\n }\n const timer = setTimeout(() => {\n controller.abort(new Error(`Request timed out after ${timeoutMs}ms`));\n }, timeoutMs);\n return {\n signal: controller.signal,\n cancel: () => {\n clearTimeout(timer);\n if (parent) {\n parent.removeEventListener('abort', onParentAbort);\n }\n },\n };\n}\n\nasync function readBody(res: Response, parseJson: boolean): Promise<unknown> {\n if (res.status === 204 || res.status === 205) {\n return null;\n }\n const contentType = res.headers.get('content-type') ?? '';\n if (parseJson && contentType.includes('application/json')) {\n const text = await res.text();\n if (text.length === 0) {\n return null;\n }\n return JSON.parse(text);\n }\n return res.text();\n}\n\nexport async function request<T = unknown>(\n req: HttpRequest,\n options: RequestOptions,\n): Promise<HttpResponse<T>> {\n const fetchImpl: FetchLike = options.fetch ?? (globalThis.fetch as FetchLike);\n const retry = req.retry ?? {};\n const maxAttempts = retry.maxAttempts ?? DEFAULT_MAX_ATTEMPTS;\n const initialDelayMs = retry.initialDelayMs ?? DEFAULT_INITIAL_DELAY_MS;\n const maxDelayMs = retry.maxDelayMs ?? DEFAULT_MAX_DELAY_MS;\n const retryOn = retry.retryOn ?? defaultRetryOn;\n const timeoutMs = req.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const parseJson = req.parseJson ?? true;\n\n const headers = mergeHeaders(\n {\n 'User-Agent': DEFAULT_USER_AGENT,\n Accept: 'application/json',\n },\n req.headers,\n );\n\n let lastErr: Error | undefined;\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n req.signal?.throwIfAborted();\n\n const { signal, cancel } = linkTimeoutSignal(req.signal, timeoutMs);\n let res: Response;\n try {\n res = await fetchImpl(req.url, {\n method: req.method ?? 'GET',\n headers,\n body: req.body as RequestInit['body'],\n signal,\n });\n } catch (err) {\n cancel();\n if (req.signal?.aborted) {\n throw req.signal.reason ?? err;\n }\n const error = err instanceof Error ? err : new Error(String(err));\n lastErr = error;\n if (attempt < maxAttempts - 1 && retryOn(null, error)) {\n const delay = computeDelay(attempt, initialDelayMs, maxDelayMs);\n await sleep(delay, req.signal);\n continue;\n }\n throw new TransientError(error.message);\n }\n cancel();\n\n const body = await readBody(res, parseJson);\n const httpResponse: HttpResponse<T> = {\n status: res.status,\n headers: res.headers,\n body: body as T,\n };\n if (req.rateLimit) {\n const state = req.rateLimit.parse(res.headers);\n if (state) {\n httpResponse.rateLimitState = state;\n }\n }\n\n if (options.observer) {\n await notifyObserver(options.observer, {\n url: req.url,\n method: req.method ?? 'GET',\n status: res.status,\n resource: options.resource,\n requestId: options.requestId ?? newRequestId(),\n body,\n });\n }\n\n if (res.ok) {\n return httpResponse;\n }\n\n const retryAfter = parseRetryAfter(res.headers.get('retry-after'));\n const message = `HTTP ${res.status} ${res.statusText} for ${req.method ?? 'GET'} ${req.url}`;\n const err = errorForStatus(message, httpResponse, retryAfter);\n\n if (\n attempt < maxAttempts - 1 &&\n retryOn(res.status, err) &&\n !(err instanceof AuthError) &&\n !(err instanceof ClientBugError)\n ) {\n lastErr = err;\n let delay = computeDelay(attempt, initialDelayMs, maxDelayMs);\n if (err instanceof RateLimitError && retryAfter) {\n const wait = retryAfter.getTime() - Date.now();\n if (wait > 0) {\n delay = Math.min(wait, maxDelayMs);\n }\n }\n await sleep(delay, req.signal);\n continue;\n }\n\n throw err;\n }\n\n throw lastErr ?? new UpstreamBugError('Exhausted retry attempts');\n}\n\nfunction computeDelay(\n attempt: number,\n initialDelayMs: number,\n maxDelayMs: number,\n): number {\n const base = initialDelayMs * 2 ** attempt;\n const jitter = base * 0.25 * Math.random();\n return Math.min(base + jitter, maxDelayMs);\n}\n\nexport { HttpClientError };\n","export interface RateLimitState {\n remaining: number;\n resetAt: Date;\n}\n\nexport interface RateLimitPolicy {\n parse(headers: Headers): RateLimitState | null;\n}\n\nexport const githubRateLimit: RateLimitPolicy = {\n parse(h) {\n const remainingRaw = h.get('x-ratelimit-remaining');\n const resetRaw = h.get('x-ratelimit-reset');\n if (remainingRaw === null || resetRaw === null) {\n return null;\n }\n const remaining = Number(remainingRaw);\n const reset = Number(resetRaw);\n if (!Number.isFinite(remaining) || !Number.isFinite(reset) || reset < 0) {\n return null;\n }\n return { remaining, resetAt: new Date(reset * 1000) };\n },\n};\n\nexport const sentryRateLimit: RateLimitPolicy = {\n parse(h) {\n const concurrent = h.get('x-sentry-rate-limit-remaining');\n const reset = h.get('x-sentry-rate-limit-reset');\n if (concurrent === null || reset === null) {\n return null;\n }\n const remaining = Number(concurrent);\n const resetSec = Number(reset);\n if (\n !Number.isFinite(remaining) ||\n !Number.isFinite(resetSec) ||\n resetSec < 0\n ) {\n return null;\n }\n return { remaining, resetAt: new Date(resetSec * 1000) };\n },\n};\n\nexport const linearRateLimit: RateLimitPolicy = {\n parse(h) {\n const remainingRaw = h.get('x-ratelimit-requests-remaining');\n const resetRaw = h.get('x-ratelimit-requests-reset');\n if (remainingRaw === null) {\n return null;\n }\n const remaining = Number(remainingRaw);\n if (!Number.isFinite(remaining)) {\n return null;\n }\n let resetAt: Date;\n if (resetRaw !== null) {\n const reset = Number(resetRaw);\n if (!Number.isFinite(reset) || reset < 0) {\n return null;\n }\n resetAt = new Date(reset);\n } else {\n resetAt = new Date(Date.now() + 60_000);\n }\n return { remaining, resetAt };\n },\n};\n","import { request } from './request';\nimport type { HttpRequest } from './types';\n\nexport function parseLinkHeader(header: string | null): Record<string, string> {\n if (!header) {\n return {};\n }\n const result: Record<string, string> = {};\n for (const part of header.split(',')) {\n const match = part.match(/<([^>]+)>\\s*;\\s*rel=\"([^\"]+)\"/);\n if (match) {\n result[match[2]!] = match[1]!;\n }\n }\n return result;\n}\n\nexport async function* paginateLink<T>(\n initial: HttpRequest,\n parse: (body: unknown) => T[],\n options: { resource: string },\n): AsyncIterable<T> {\n let next: string | null = initial.url;\n while (next) {\n const res: Awaited<ReturnType<typeof request>> = await request(\n {\n ...initial,\n url: next,\n },\n { resource: options.resource },\n );\n for (const item of parse(res.body)) {\n yield item;\n }\n const links = parseLinkHeader(res.headers.get('link'));\n next = links['next'] ?? null;\n }\n}\n\nexport async function* paginateCursor<T>(\n initial: HttpRequest,\n parse: (body: unknown) => { items: T[]; nextCursor: string | null },\n buildNext: (req: HttpRequest, cursor: string) => HttpRequest,\n options: { resource: string },\n): AsyncIterable<T> {\n let req: HttpRequest = initial;\n while (true) {\n const res = await request(req, { resource: options.resource });\n const { items, nextCursor } = parse(res.body);\n for (const item of items) {\n yield item;\n }\n if (!nextCursor) {\n return;\n }\n req = buildNext(req, nextCursor);\n }\n}\n\nexport async function* paginatePage<T>(\n initial: HttpRequest,\n parse: (body: unknown) => { items: T[]; hasMore: boolean },\n buildPage: (req: HttpRequest, page: number) => HttpRequest,\n options: { resource: string },\n): AsyncIterable<T> {\n let page = 1;\n while (true) {\n const req = page === 1 ? initial : buildPage(initial, page);\n const res = await request(req, { resource: options.resource });\n const { items, hasMore } = parse(res.body);\n for (const item of items) {\n yield item;\n }\n if (!hasMore || items.length === 0) {\n return;\n }\n page++;\n }\n}\n","export type Secret = { $secret: string };\n\nexport function secret(name: string): Secret {\n if (!/^[A-Z][A-Z0-9_]*$/.test(name)) {\n throw new Error(\n `Invalid secret name \"${name}\". Must match /^[A-Z][A-Z0-9_]*$/ ` +\n `(uppercase letters, digits, underscores; must start with a letter).`,\n );\n }\n return { $secret: name };\n}\n\nexport function isSecret(value: unknown): value is Secret {\n return (\n typeof value === 'object' &&\n value !== null &&\n '$secret' in value &&\n typeof (value as Secret).$secret === 'string'\n );\n}\n\nexport interface SecretsResolver {\n resolve(name: string): string | undefined;\n}\n\nexport class EnvSecretsResolver implements SecretsResolver {\n resolve(name: string): string | undefined {\n const env = (\n globalThis as { process?: { env?: Record<string, string | undefined> } }\n ).process?.env;\n return env?.[name];\n }\n}\n\nexport function extractSecretNames(value: unknown): string[] {\n const names: string[] = [];\n const visit = (v: unknown): void => {\n if (isSecret(v)) {\n names.push(v.$secret);\n return;\n }\n if (v && typeof v === 'object') {\n if (Array.isArray(v)) {\n v.forEach(visit);\n } else {\n Object.values(v as Record<string, unknown>).forEach(visit);\n }\n }\n };\n visit(value);\n return [...new Set(names)];\n}\n\nexport function resolveSecrets<T>(obj: T, resolver: SecretsResolver): T {\n if (isSecret(obj)) {\n const name = obj.$secret;\n const value = resolver.resolve(name);\n if (value === undefined) {\n throw new Error(\n `Missing secret \"${name}\". Set it via process.env.${name} or the CLI: rawdash secrets set ${name} ...`,\n );\n }\n return value as unknown as T;\n }\n if (Array.isArray(obj)) {\n return obj.map((item) => resolveSecrets(item, resolver)) as unknown as T;\n }\n if (typeof obj === 'object' && obj !== null) {\n const result: Record<string, unknown> = {};\n for (const [key, val] of Object.entries(obj as object)) {\n Object.defineProperty(result, key, {\n value: resolveSecrets(val, resolver),\n enumerable: true,\n configurable: true,\n writable: true,\n });\n }\n return result as T;\n }\n return obj;\n}\n","import {\n type HttpRequest,\n type HttpResponse,\n type RequestObserver,\n request as sharedRequest,\n} from '@rawdash/connector-shared';\n\nimport {\n EnvSecretsResolver,\n type Secret,\n type SecretsResolver,\n resolveSecrets,\n} from './secrets';\n\nexport type JSONValue =\n | string\n | number\n | boolean\n | null\n | JSONValue[]\n | { [key: string]: JSONValue };\n\n// ---------------------------------------------------------------------------\n// Five storage shapes\n// ---------------------------------------------------------------------------\n\nexport interface Event {\n name: string;\n start_ts: number;\n end_ts: number | null;\n attributes: Record<string, JSONValue>;\n}\n\nexport interface Entity {\n type: string;\n id: string;\n attributes: Record<string, JSONValue>;\n updated_at: number;\n}\n\nexport interface MetricSample {\n name: string;\n ts: number;\n value: number;\n attributes: Record<string, JSONValue>;\n}\n\nexport interface Edge {\n from_type: string;\n from_id: string;\n kind: string;\n to_type: string;\n to_id: string;\n attributes: Record<string, JSONValue>;\n updated_at: number;\n}\n\nexport type Distribution =\n | {\n name: string;\n ts: number;\n kind: 'histogram';\n data: {\n buckets: Array<{ le: number; count: number }>;\n count: number;\n sum: number;\n };\n attributes: Record<string, JSONValue>;\n }\n | {\n name: string;\n ts: number;\n kind: 'summary';\n data: {\n quantiles: Array<{ q: number; value: number }>;\n count: number;\n sum: number;\n };\n attributes: Record<string, JSONValue>;\n };\n\n// ---------------------------------------------------------------------------\n// Storage query types\n// ---------------------------------------------------------------------------\n\nexport interface EventQuery {\n name?: string;\n start?: number;\n end?: number;\n}\n\nexport interface EntityQuery {\n type: string;\n}\n\nexport interface MetricQuery {\n name?: string;\n start?: number;\n end?: number;\n}\n\nexport interface EdgeQuery {\n fromType?: string;\n fromId?: string;\n kind?: string;\n toType?: string;\n toId?: string;\n}\n\nexport interface DistributionQuery {\n name?: string;\n start?: number;\n end?: number;\n}\n\n// ---------------------------------------------------------------------------\n// StorageHandle — write and read surface\n// ---------------------------------------------------------------------------\n\nexport interface StorageHandle {\n event(e: Event): Promise<void>;\n entity(e: Entity): Promise<void>;\n metric(m: MetricSample): Promise<void>;\n edge(e: Edge): Promise<void>;\n distribution(d: Distribution): Promise<void>;\n\n events(es: Event[], scope?: { names?: string[] }): Promise<void>;\n entities(es: Entity[], scope?: { types?: string[] }): Promise<void>;\n metrics(ms: MetricSample[], scope?: { names?: string[] }): Promise<void>;\n edges(es: Edge[], scope?: { kinds?: string[] }): Promise<void>;\n distributions(\n ds: Distribution[],\n scope?: { names?: string[] },\n ): Promise<void>;\n\n queryEvents(q: EventQuery): Promise<Event[]>;\n getEntity(type: string, id: string): Promise<Entity | null>;\n queryEntities(q: EntityQuery): Promise<Entity[]>;\n queryMetrics(q: MetricQuery): Promise<MetricSample[]>;\n traverse(q: EdgeQuery): Promise<Edge[]>;\n queryDistributions(q: DistributionQuery): Promise<Distribution[]>;\n\n // Deletes all rows in the given time-series shape whose timestamp column is\n // strictly less than `tsUnixMs`. Only covers append-only shapes (events,\n // metrics, distributions). Entities and edges are excluded because they hold\n // the latest known state per primary key — deleting by age would lose live\n // data. The right model for those shapes is \"expire when source disappears.\"\n deleteOlderThan(\n shape: 'events' | 'metrics' | 'distributions',\n tsUnixMs: number,\n ): Promise<{ rowsDeleted: number }>;\n}\n\n// ---------------------------------------------------------------------------\n// Credentials\n// ---------------------------------------------------------------------------\n\nexport interface CredentialField {\n description: string;\n auth?: 'none' | 'optional' | 'required';\n}\n\nexport type CredentialsSchema = Record<string, CredentialField>;\n\nexport type InferCredentials<TCreds extends CredentialsSchema> = {\n [K in keyof TCreds]: TCreds[K] extends { auth: 'required' }\n ? string\n : string | undefined;\n};\n\nexport type InferCredentialInput<TCreds extends CredentialsSchema> = {\n [K in keyof TCreds]: TCreds[K] extends { auth: 'required' }\n ? string | Secret\n : string | Secret | undefined;\n};\n\n// ---------------------------------------------------------------------------\n// Sync + Connector\n// ---------------------------------------------------------------------------\n\nexport interface SyncOptions {\n mode: 'full' | 'latest';\n since?: string;\n cursor?: unknown;\n}\n\nexport interface SyncResult {\n done: boolean;\n cursor?: unknown;\n transientError?: unknown;\n}\n\nexport interface Connector {\n readonly id: string;\n readonly credentials?: CredentialsSchema;\n serializeConfig(): Record<string, unknown>;\n sync(\n options: SyncOptions,\n storage: StorageHandle,\n signal?: AbortSignal,\n ): Promise<SyncResult>;\n}\n\nexport interface ConnectorContext {\n observer?: RequestObserver;\n secretsResolver?: SecretsResolver;\n}\n\nexport interface ConnectorRequestOptions {\n resource: string;\n requestId?: string;\n}\n\nexport interface RetryPolicy {\n maxAttempts?: number;\n initialDelayMs?: number;\n maxDelayMs?: number;\n signal?: AbortSignal;\n}\n\nexport abstract class BaseConnector<\n TSettings = unknown,\n TCreds extends CredentialsSchema = CredentialsSchema,\n> implements Connector {\n abstract readonly id: string;\n readonly credentials?: TCreds;\n\n protected settings: TSettings;\n protected creds: InferCredentials<TCreds>;\n private rawCredInput: InferCredentialInput<TCreds> | undefined;\n private ctx: ConnectorContext;\n\n constructor(\n settings: TSettings,\n creds?: InferCredentialInput<TCreds>,\n ctx?: ConnectorContext,\n ) {\n this.settings = settings;\n this.rawCredInput = creds;\n this.ctx = ctx ?? {};\n this.creds = creds\n ? (resolveSecrets(\n creds,\n this.ctx.secretsResolver ?? new EnvSecretsResolver(),\n ) as InferCredentials<TCreds>)\n : ({} as InferCredentials<TCreds>);\n }\n\n protected request<T = unknown>(\n req: HttpRequest,\n opts: ConnectorRequestOptions,\n ): Promise<HttpResponse<T>> {\n return sharedRequest<T>(req, {\n resource: opts.resource,\n requestId: opts.requestId,\n observer: this.ctx.observer,\n });\n }\n\n protected get<T = unknown>(\n url: string,\n opts: ConnectorRequestOptions & {\n headers?: Record<string, string>;\n signal?: AbortSignal;\n rateLimit?: HttpRequest['rateLimit'];\n },\n ): Promise<HttpResponse<T>> {\n return this.request<T>(\n {\n url,\n method: 'GET',\n headers: opts.headers,\n signal: opts.signal,\n rateLimit: opts.rateLimit,\n },\n { resource: opts.resource, requestId: opts.requestId },\n );\n }\n\n protected post<T = unknown>(\n url: string,\n opts: ConnectorRequestOptions & {\n body?: HttpRequest['body'];\n headers?: Record<string, string>;\n signal?: AbortSignal;\n rateLimit?: HttpRequest['rateLimit'];\n },\n ): Promise<HttpResponse<T>> {\n return this.request<T>(\n {\n url,\n method: 'POST',\n headers: opts.headers,\n body: opts.body,\n signal: opts.signal,\n rateLimit: opts.rateLimit,\n },\n { resource: opts.resource, requestId: opts.requestId },\n );\n }\n\n serializeConfig(): Record<string, unknown> {\n const config: Record<string, unknown> = {\n ...(this.settings as Record<string, unknown>),\n };\n if (this.rawCredInput) {\n for (const [key, value] of Object.entries(\n this.rawCredInput as Record<string, unknown>,\n )) {\n if (value !== undefined) {\n config[key] = value;\n }\n }\n }\n return config;\n }\n\n protected sleep(ms: number, signal?: AbortSignal): Promise<void> {\n if (signal?.aborted) {\n return Promise.reject(signal.reason ?? new Error('Aborted'));\n }\n return new Promise<void>((resolve, reject) => {\n const onAbort = () => {\n clearTimeout(timer);\n reject(signal!.reason ?? new Error('Aborted'));\n };\n const timer = setTimeout(() => {\n signal?.removeEventListener('abort', onAbort);\n resolve();\n }, ms);\n signal?.addEventListener('abort', onAbort, { once: true });\n });\n }\n\n protected async withRetry<T>(\n fn: (\n signal?: AbortSignal,\n ) => Promise<{ status: 'done'; value: T } | { status: 'retry' }>,\n options?: RetryPolicy,\n ): Promise<T | null> {\n const {\n maxAttempts = 10,\n initialDelayMs = 1000,\n maxDelayMs = 10000,\n signal,\n } = options ?? {};\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n signal?.throwIfAborted();\n const result = await fn(signal);\n if (result.status === 'done') {\n return result.value;\n }\n if (attempt < maxAttempts - 1) {\n const delay = Math.min(initialDelayMs * 2 ** attempt, maxDelayMs);\n await this.sleep(delay, signal);\n }\n }\n\n return null;\n }\n\n abstract sync(\n options: SyncOptions,\n storage: StorageHandle,\n signal?: AbortSignal,\n ): Promise<SyncResult>;\n}\n\nexport function defineConnector<TSettings>() {\n return function <\n TCreds extends CredentialsSchema = Record<string, never>,\n >(def: {\n id: string;\n credentials?: TCreds;\n sync: (\n this: { settings: TSettings; creds: InferCredentials<TCreds> },\n options: SyncOptions,\n storage: StorageHandle,\n signal?: AbortSignal,\n ) => Promise<SyncResult>;\n }): {\n new (\n settings: TSettings,\n creds?: InferCredentialInput<TCreds>,\n ctx?: ConnectorContext,\n ): Connector;\n readonly id: string;\n readonly credentials: TCreds | undefined;\n } {\n class DynamicConnector extends BaseConnector<TSettings, TCreds> {\n static readonly id = def.id;\n static readonly credentials = def.credentials;\n\n readonly id = def.id;\n override readonly credentials = def.credentials;\n\n async sync(\n options: SyncOptions,\n storage: StorageHandle,\n signal?: AbortSignal,\n ): Promise<SyncResult> {\n return def.sync.call(\n { settings: this.settings, creds: this.creds },\n options,\n storage,\n signal,\n );\n }\n }\n\n return DynamicConnector as unknown as {\n new (\n settings: TSettings,\n creds?: InferCredentialInput<TCreds>,\n ctx?: ConnectorContext,\n ): Connector;\n readonly id: string;\n readonly credentials: TCreds | undefined;\n };\n };\n}\n","import type { SyncResult } from './connector';\n\nexport interface ChunkedSyncCursor<TPhase extends string, TPage> {\n phase: TPhase;\n page: TPage | null;\n}\n\nexport interface FetchPageResult<TPage> {\n items: unknown[];\n next: TPage | null;\n}\n\nexport interface ChunkedSyncOptions<TPhase extends string, TPage> {\n phases: readonly TPhase[];\n cursor: ChunkedSyncCursor<TPhase, TPage> | undefined;\n signal: AbortSignal | undefined;\n fetchPage: (\n phase: TPhase,\n page: TPage | null,\n signal: AbortSignal | undefined,\n ) => Promise<FetchPageResult<TPage>>;\n writeBatch: (\n phase: TPhase,\n items: unknown[],\n page: TPage | null,\n ) => Promise<void>;\n}\n\nexport async function paginateChunked<TPhase extends string, TPage>(\n opts: ChunkedSyncOptions<TPhase, TPage>,\n): Promise<SyncResult> {\n const { phases, cursor, signal, fetchPage, writeBatch } = opts;\n\n if (phases.length === 0) {\n return { done: true };\n }\n\n const resumeIdx = cursor ? phases.indexOf(cursor.phase) : -1;\n const hasKnownResumePhase = resumeIdx >= 0;\n const startIdx = hasKnownResumePhase ? resumeIdx : 0;\n\n for (let i = startIdx; i < phases.length; i++) {\n const phase = phases[i]!;\n let page: TPage | null =\n i === startIdx && hasKnownResumePhase ? cursor!.page : null;\n\n while (true) {\n if (signal?.aborted) {\n return {\n done: false,\n cursor: { phase, page } satisfies ChunkedSyncCursor<TPhase, TPage>,\n };\n }\n let items: unknown[];\n let next: TPage | null;\n try {\n ({ items, next } = await fetchPage(phase, page, signal));\n } catch (err) {\n if (\n signal?.aborted ||\n (err instanceof Error && err.name === 'AbortError')\n ) {\n return {\n done: false,\n cursor: { phase, page } satisfies ChunkedSyncCursor<TPhase, TPage>,\n };\n }\n return {\n done: false,\n cursor: { phase, page } satisfies ChunkedSyncCursor<TPhase, TPage>,\n transientError: err,\n };\n }\n try {\n await writeBatch(phase, items, page);\n } catch (err) {\n if (\n signal?.aborted ||\n (err instanceof Error && err.name === 'AbortError')\n ) {\n return {\n done: false,\n cursor: { phase, page } satisfies ChunkedSyncCursor<TPhase, TPage>,\n };\n }\n return {\n done: false,\n cursor: { phase, page } satisfies ChunkedSyncCursor<TPhase, TPage>,\n transientError: err,\n };\n }\n if (next === null) {\n break;\n }\n page = next;\n }\n }\n\n return { done: true };\n}\n","import { z } from 'zod';\n\nexport const shapeSchema = z.enum([\n 'event',\n 'entity',\n 'metric',\n 'edge',\n 'distribution',\n]);\n\nexport const aggFnSchema = z.enum([\n 'count',\n 'sum',\n 'avg',\n 'min',\n 'max',\n 'latest',\n 'first',\n]);\n\nexport const filterOperatorSchema = z.enum([\n 'eq',\n 'neq',\n 'gt',\n 'gte',\n 'lt',\n 'lte',\n 'contains',\n]);\n\nexport const filterConditionSchema = z.object({\n field: z.string(),\n op: filterOperatorSchema,\n value: z.union([z.string(), z.number(), z.boolean()]),\n});\n\nexport const filterClauseSchema = z.union([\n filterConditionSchema,\n z.object({ or: z.array(filterConditionSchema) }),\n]);\n\nexport const groupBySchema = z.object({\n field: z.string(),\n granularity: z.enum(['hour', 'day', 'week', 'month']),\n});\n\nexport const computedMetricSchema = z\n .object({\n connectorId: z.string(),\n shape: shapeSchema,\n name: z.string().optional(),\n entityType: z.string().optional(),\n field: z.string().optional(),\n fn: aggFnSchema,\n window: z.string().optional(),\n filter: z.array(filterClauseSchema).optional(),\n groupBy: groupBySchema.optional(),\n })\n .refine((m) => m.fn === 'count' || m.field !== undefined, {\n message: 'field is required unless fn is \"count\"',\n path: ['field'],\n });\n\nconst titleField = z\n .string()\n .meta({ label: 'Title', description: 'Widget title.' });\n\nexport const statWidgetSchema = z.object({\n kind: z.literal('stat'),\n title: titleField,\n metric: computedMetricSchema.meta({\n label: 'Metric',\n description: 'Computed metric definition.',\n }),\n window: z\n .string()\n .optional()\n .meta({ label: 'Window', description: \"Time window, e.g. '7d'.\" }),\n compare: z\n .enum(['none', 'previous-period'])\n .default('none')\n .meta({ label: 'Compare', description: 'Comparison mode.' }),\n});\n\nexport const statusWidgetSchema = z.object({\n kind: z.literal('status'),\n title: titleField,\n source: z.string().meta({\n label: 'Source',\n description: 'Connector or data source reference.',\n }),\n});\n\nexport const timeseriesWidgetSchema = z.object({\n kind: z.literal('timeseries'),\n title: titleField,\n metric: computedMetricSchema.meta({\n label: 'Metric',\n description: 'Computed metric definition.',\n }),\n window: z\n .string()\n .meta({ label: 'Window', description: \"Time window, e.g. '30d'.\" }),\n granularity: z\n .enum(['hour', 'day', 'week'])\n .default('day')\n .meta({ label: 'Granularity', description: 'Time bucket size.' }),\n});\n\nexport const distributionWidgetSchema = z.object({\n kind: z.literal('distribution'),\n title: titleField,\n metric: computedMetricSchema.meta({\n label: 'Metric',\n description: 'Computed metric definition.',\n }),\n window: z\n .string()\n .meta({ label: 'Window', description: \"Time window, e.g. '7d'.\" }),\n});\n\nexport const widgetSchemas = {\n stat: statWidgetSchema,\n status: statusWidgetSchema,\n timeseries: timeseriesWidgetSchema,\n distribution: distributionWidgetSchema,\n} as const;\n\nexport const widgetSchema = z.discriminatedUnion('kind', [\n statWidgetSchema,\n statusWidgetSchema,\n timeseriesWidgetSchema,\n distributionWidgetSchema,\n]);\n\nexport type WidgetKind = keyof typeof widgetSchemas;\n\nexport function getWidgetSchema(kind: WidgetKind) {\n return widgetSchemas[kind];\n}\n","import type { Connector } from './connector';\nimport type { RetentionConfig } from './retention';\nimport { getWidgetSchema, widgetSchemas } from './widget-schemas';\nimport type { WidgetKind } from './widget-schemas';\n\n// ---------------------------------------------------------------------------\n// Aggregation functions\n// ---------------------------------------------------------------------------\n\nexport type AggFn =\n | 'count'\n | 'sum'\n | 'avg'\n | 'min'\n | 'max'\n | 'latest'\n | 'first';\n\n// ---------------------------------------------------------------------------\n// Shape\n// ---------------------------------------------------------------------------\n\nexport type Shape = 'event' | 'entity' | 'metric' | 'edge' | 'distribution';\n\n// ---------------------------------------------------------------------------\n// Filters\n// ---------------------------------------------------------------------------\n\nexport type FilterOperator =\n | 'eq'\n | 'neq'\n | 'gt'\n | 'gte'\n | 'lt'\n | 'lte'\n | 'contains';\n\nexport interface FilterCondition {\n field: string;\n op: FilterOperator;\n value: string | number | boolean;\n}\n\nexport type FilterClause = FilterCondition | { or: FilterCondition[] };\n\n// ---------------------------------------------------------------------------\n// GroupBy\n// ---------------------------------------------------------------------------\n\nexport interface GroupBy {\n field: string;\n granularity: 'hour' | 'day' | 'week' | 'month';\n}\n\n// ---------------------------------------------------------------------------\n// Metric\n// ---------------------------------------------------------------------------\n\nexport interface Metric {\n connector: { id: string };\n shape: Shape;\n name?: string;\n entityType?: string;\n field?: string;\n fn: AggFn;\n window?: string;\n filter?: FilterClause[];\n groupBy?: GroupBy;\n}\n\nexport interface ComputedMetric {\n readonly connectorId: string;\n readonly shape: Shape;\n readonly name?: string;\n readonly entityType?: string;\n readonly field?: string;\n readonly fn: AggFn;\n readonly window?: string;\n readonly filter?: FilterClause[];\n readonly groupBy?: GroupBy;\n}\n\n// ---------------------------------------------------------------------------\n// Widget definition\n// ---------------------------------------------------------------------------\n\nexport interface StatWidget {\n kind: 'stat';\n title: string;\n metric: ComputedMetric;\n window?: string;\n compare?: 'none' | 'previous-period';\n}\n\nexport interface StatusWidget {\n kind: 'status';\n title: string;\n source: string;\n}\n\nexport interface TimeseriesWidget {\n kind: 'timeseries';\n title: string;\n metric: ComputedMetric;\n window: string;\n granularity?: 'hour' | 'day' | 'week';\n}\n\nexport interface DistributionWidget {\n kind: 'distribution';\n title: string;\n metric: ComputedMetric;\n window: string;\n}\n\nexport type Widget =\n | StatWidget\n | StatusWidget\n | TimeseriesWidget\n | DistributionWidget;\n\nexport type { WidgetKind };\n\n// ---------------------------------------------------------------------------\n// Dashboard config\n// ---------------------------------------------------------------------------\n\nexport interface ConfiguredConnector {\n connector: Connector;\n}\n\nexport interface Dashboard {\n widgets: Record<string, Widget>;\n}\n\nexport interface DashboardConfig {\n connectors: ConfiguredConnector[];\n dashboards: Record<string, Dashboard>;\n retention?: RetentionConfig;\n}\n\n// ---------------------------------------------------------------------------\n// defineDashboard\n// ---------------------------------------------------------------------------\n\nconst VALID_WIDGET_KINDS = new Set<string>(Object.keys(widgetSchemas));\n\nexport function defineDashboard(options: {\n widgets: Record<string, Widget>;\n}): Dashboard {\n for (const [key, widget] of Object.entries(options.widgets)) {\n if (!VALID_WIDGET_KINDS.has(widget.kind)) {\n throw new Error(\n `Widget \"${key}\": unknown kind \"${widget.kind}\". Must be one of: ${[...VALID_WIDGET_KINDS].join(', ')}`,\n );\n }\n const schema = getWidgetSchema(widget.kind as WidgetKind);\n const result = schema.safeParse(widget);\n if (!result.success) {\n throw new Error(\n `Widget \"${key}\" (kind \"${widget.kind}\"): ${result.error.issues.map((i) => i.message).join('; ')}`,\n );\n }\n }\n return { widgets: options.widgets };\n}\n\n// ---------------------------------------------------------------------------\n// defineMetric\n// ---------------------------------------------------------------------------\n\nexport function defineMetric(options: Metric): ComputedMetric {\n return {\n connectorId: options.connector.id,\n shape: options.shape,\n name: options.name,\n entityType: options.entityType,\n field: options.field,\n fn: options.fn,\n window: options.window,\n filter: options.filter,\n groupBy: options.groupBy,\n };\n}\n\n// ---------------------------------------------------------------------------\n// defineConfig\n// ---------------------------------------------------------------------------\n\nconst VALID_SHAPES = new Set<string>([\n 'event',\n 'entity',\n 'metric',\n 'edge',\n 'distribution',\n]);\nconst VALID_FNS = new Set<string>([\n 'count',\n 'sum',\n 'avg',\n 'min',\n 'max',\n 'latest',\n 'first',\n]);\n\nconst SAFE_KEY_RE = /^[a-zA-Z0-9_-]+$/;\n\nfunction validateConfig(config: DashboardConfig): void {\n if (config.retention) {\n const { maxAge, maxSize, floor, intervalMs } = config.retention;\n if (maxAge !== undefined && (!Number.isFinite(maxAge) || maxAge < 0)) {\n throw new Error('retention.maxAge must be a finite number >= 0');\n }\n if (maxSize !== undefined && (!Number.isInteger(maxSize) || maxSize < 0)) {\n throw new Error('retention.maxSize must be an integer >= 0');\n }\n if (floor !== undefined && (!Number.isInteger(floor) || floor < 0)) {\n throw new Error('retention.floor must be an integer >= 0');\n }\n if (\n intervalMs !== undefined &&\n (!Number.isFinite(intervalMs) || intervalMs <= 0)\n ) {\n throw new Error('retention.intervalMs must be a finite number > 0');\n }\n }\n\n if (\n !config.dashboards ||\n typeof config.dashboards !== 'object' ||\n Array.isArray(config.dashboards)\n ) {\n throw new Error(\n 'defineConfig: config must include a \"dashboards\" record — did you mean to migrate from the old flat \"widgets\" shape?',\n );\n }\n\n const connectorIds = new Set(config.connectors.map((e) => e.connector.id));\n\n for (const [dashboardKey, dashboard] of Object.entries(config.dashboards)) {\n if (\n !dashboard.widgets ||\n typeof dashboard.widgets !== 'object' ||\n Array.isArray(dashboard.widgets)\n ) {\n throw new Error(\n `Dashboard \"${dashboardKey}\" must define a \"widgets\" record`,\n );\n }\n\n if (!SAFE_KEY_RE.test(dashboardKey)) {\n throw new Error(\n `Dashboard key \"${dashboardKey}\" contains URL-unsafe characters; use only letters, digits, hyphens, and underscores`,\n );\n }\n\n for (const [widgetKey, widget] of Object.entries(dashboard.widgets)) {\n const ref = `Dashboard \"${dashboardKey}\", widget \"${widgetKey}\"`;\n\n if (!SAFE_KEY_RE.test(widgetKey)) {\n throw new Error(\n `${ref}: widget key contains URL-unsafe characters; use only letters, digits, hyphens, and underscores`,\n );\n }\n\n if (widget.kind === 'status') {\n continue;\n }\n\n const { connectorId, shape, fn } = widget.metric;\n\n if (!connectorIds.has(connectorId)) {\n throw new Error(\n `${ref}: connector \"${connectorId}\" is not listed in connectors`,\n );\n }\n\n if (!VALID_SHAPES.has(shape)) {\n throw new Error(`${ref}: invalid shape \"${shape}\"`);\n }\n\n if (!VALID_FNS.has(fn)) {\n throw new Error(`${ref}: invalid fn \"${fn}\"`);\n }\n }\n }\n}\n\nexport function defineConfig(config: DashboardConfig): DashboardConfig {\n validateConfig(config);\n return config;\n}\n","import type {\n Distribution,\n Event,\n MetricSample,\n StorageHandle,\n} from './connector';\n\n// ---------------------------------------------------------------------------\n// RetentionConfig\n// ---------------------------------------------------------------------------\n\nexport interface RetentionConfig {\n maxAge?: number;\n maxSize?: number;\n floor?: number;\n intervalMs?: number;\n}\n\n// ---------------------------------------------------------------------------\n// RetentionDeletionPlan — rows eligible for deletion across time-series shapes\n// ---------------------------------------------------------------------------\n\nexport interface RetentionDeletionPlan {\n events: Event[];\n metrics: MetricSample[];\n distributions: Distribution[];\n}\n\n// ---------------------------------------------------------------------------\n// selectForDeletion — pure computation\n//\n// Receives rows pre-sorted newest-first (descending by timestamp).\n// Returns the subset that should be deleted given the policy.\n//\n// Rules applied in order:\n// 1. Rows beyond maxSize are candidates.\n// 2. Rows older than maxAge milliseconds are candidates.\n// 3. Rows within the newest `floor` positions are always kept (overrides 1 & 2).\n// ---------------------------------------------------------------------------\n\nexport function selectForDeletion<T>(\n rows: T[],\n getTs: (row: T) => number,\n config: RetentionConfig,\n nowMs: number = Date.now(),\n): T[] {\n const { maxAge, maxSize, floor = 0 } = config;\n\n if (maxAge === undefined && maxSize === undefined) {\n return [];\n }\n\n const toDelete: T[] = [];\n\n for (let i = 0; i < rows.length; i++) {\n const row = rows[i]!;\n if (i < floor) {\n continue;\n }\n\n const overSize = maxSize !== undefined && i >= maxSize;\n const tooOld = maxAge !== undefined && getTs(row) < nowMs - maxAge;\n\n if (overSize || tooOld) {\n toDelete.push(row);\n }\n }\n\n return toDelete;\n}\n\n// ---------------------------------------------------------------------------\n// computeRetention — async, queries the handle and returns deletion candidates\n//\n// Only covers time-series shapes (events, metrics, distributions) since those\n// grow unboundedly via append. Entities and edges are upsert-keyed and do not\n// accumulate the same way.\n// ---------------------------------------------------------------------------\n\nexport async function computeRetention(\n handle: StorageHandle,\n config: RetentionConfig,\n nowMs: number = Date.now(),\n): Promise<RetentionDeletionPlan> {\n const [events, metrics, distributions] = await Promise.all([\n handle.queryEvents({}),\n handle.queryMetrics({}),\n handle.queryDistributions({}),\n ]);\n\n const sortedEvents = [...events].sort((a, b) => b.start_ts - a.start_ts);\n const sortedMetrics = [...metrics].sort((a, b) => b.ts - a.ts);\n const sortedDistributions = [...distributions].sort((a, b) => b.ts - a.ts);\n\n return {\n events: selectForDeletion(sortedEvents, (e) => e.start_ts, config, nowMs),\n metrics: selectForDeletion(sortedMetrics, (m) => m.ts, config, nowMs),\n distributions: selectForDeletion(\n sortedDistributions,\n (d) => d.ts,\n config,\n nowMs,\n ),\n };\n}\n","import { z } from 'zod';\n\nexport type ConfigFieldsSchema = z.ZodObject<z.ZodRawShape>;\n\nexport function defineConfigFields<T extends z.ZodRawShape>(\n schema: z.ZodObject<T>,\n): z.ZodObject<T> {\n if (!(schema instanceof z.ZodObject)) {\n throw new Error(\n `configFields must be a Zod object schema (z.object({...})). Received: ${Object.prototype.toString.call(schema)}`,\n );\n }\n return schema;\n}\n","import type { ComputedMetric } from './config';\nimport type { StorageHandle } from './connector';\n\ntype FilterClause = NonNullable<ComputedMetric['filter']>[number];\ntype FilterCondition = Exclude<FilterClause, { or: unknown[] }>;\n\nfunction matchesCondition(\n record: Record<string, unknown>,\n cond: FilterCondition,\n): boolean {\n const val = record[cond.field];\n switch (cond.op) {\n case 'eq':\n return val === cond.value;\n case 'neq':\n return val !== cond.value;\n case 'gt':\n if (typeof val !== 'number' || typeof cond.value !== 'number') {\n return false;\n }\n return val > cond.value;\n case 'gte':\n if (typeof val !== 'number' || typeof cond.value !== 'number') {\n return false;\n }\n return val >= cond.value;\n case 'lt':\n if (typeof val !== 'number' || typeof cond.value !== 'number') {\n return false;\n }\n return val < cond.value;\n case 'lte':\n if (typeof val !== 'number' || typeof cond.value !== 'number') {\n return false;\n }\n return val <= cond.value;\n case 'contains':\n return String(val).includes(String(cond.value));\n default:\n return false;\n }\n}\n\nfunction applyFilter(\n record: Record<string, unknown>,\n filter: ComputedMetric['filter'],\n): boolean {\n if (!filter) {\n return true;\n }\n for (const clause of filter) {\n if ('or' in clause) {\n if (!clause.or.some((cond) => matchesCondition(record, cond))) {\n return false;\n }\n } else {\n if (!matchesCondition(record, clause)) {\n return false;\n }\n }\n }\n return true;\n}\n\nconst WINDOW_MS: Record<string, number> = {\n h: 3_600_000,\n d: 86_400_000,\n w: 604_800_000,\n m: 2_592_000_000,\n};\n\nfunction parseWindowMs(window: string): number | null {\n const match = /^(\\d+)(h|d|w|m)$/.exec(window);\n if (!match) {\n return null;\n }\n const unitMs = WINDOW_MS[match[2]!];\n if (unitMs === undefined) {\n return null;\n }\n return parseInt(match[1]!) * unitMs;\n}\n\nfunction truncateToGranularity(ts: number, granularity: string): string {\n const d = new Date(ts);\n switch (granularity) {\n case 'hour':\n d.setUTCMinutes(0, 0, 0);\n return d.toISOString();\n case 'day':\n d.setUTCHours(0, 0, 0, 0);\n return d.toISOString().slice(0, 10);\n case 'week': {\n d.setUTCDate(d.getUTCDate() - d.getUTCDay());\n d.setUTCHours(0, 0, 0, 0);\n return d.toISOString().slice(0, 10);\n }\n case 'month':\n d.setUTCDate(1);\n d.setUTCHours(0, 0, 0, 0);\n return d.toISOString().slice(0, 7);\n default:\n return d.toISOString().slice(0, 10);\n }\n}\n\nfunction computeAgg(\n records: Record<string, unknown>[],\n field: string | undefined,\n fn: string,\n): unknown {\n if (fn === 'count') {\n return records.length;\n }\n if (field === undefined) {\n throw new Error(`computeAgg: fn \"${fn}\" requires a field`);\n }\n if (fn === 'latest') {\n return records.at(-1)?.[field] ?? null;\n }\n if (fn === 'first') {\n return records[0]?.[field] ?? null;\n }\n const values = records\n .map((r) => r[field])\n .filter((v) => v !== undefined && v !== null);\n const nonNumeric = values.find((v) => typeof v !== 'number');\n if (nonNumeric !== undefined) {\n throw new Error(\n `computeAgg: fn \"${fn}\" requires numeric values for field \"${field}\", got ${typeof nonNumeric} (${String(nonNumeric)})`,\n );\n }\n const numbers = values as number[];\n if (fn === 'sum') {\n return numbers.reduce((a, b) => a + b, 0);\n }\n if (fn === 'avg') {\n return numbers.length > 0\n ? numbers.reduce((a, b) => a + b, 0) / numbers.length\n : null;\n }\n if (fn === 'min') {\n return numbers.length > 0\n ? numbers.reduce((a, b) => (a < b ? a : b))\n : null;\n }\n if (fn === 'max') {\n return numbers.length > 0\n ? numbers.reduce((a, b) => (a > b ? a : b))\n : null;\n }\n return null;\n}\n\nfunction sortByTs(\n records: Record<string, unknown>[],\n tsField: string,\n): Record<string, unknown>[] {\n return [...records].sort((a, b) => {\n return (a[tsField] as number) - (b[tsField] as number);\n });\n}\n\nfunction computeGroupBy(\n records: Record<string, unknown>[],\n metric: ComputedMetric,\n tsField: string,\n): unknown {\n const { field, granularity } = metric.groupBy!;\n const groups = new Map<string, Record<string, unknown>[]>();\n\n for (const record of records) {\n const ts = record[field] as number | undefined;\n if (ts === undefined || typeof ts !== 'number') {\n continue;\n }\n const key = truncateToGranularity(ts, granularity);\n if (!groups.has(key)) {\n groups.set(key, []);\n }\n groups.get(key)!.push(record);\n }\n\n return [...groups.entries()]\n .map(([key, groupRecords]) => ({\n date: key,\n value: computeAgg(\n sortByTs(groupRecords, tsField),\n metric.field,\n metric.fn,\n ),\n }))\n .sort((a, b) => (a.date < b.date ? -1 : 1));\n}\n\nfunction getTimestampField(shape: string): string {\n switch (shape) {\n case 'event':\n return 'start_ts';\n case 'metric':\n case 'distribution':\n return 'ts';\n case 'entity':\n case 'edge':\n return 'updated_at';\n default:\n return 'start_ts';\n }\n}\n\nexport async function computeMetric(\n storage: StorageHandle,\n metric: ComputedMetric,\n): Promise<unknown> {\n const tsField = getTimestampField(metric.shape);\n\n const windowMs = metric.window ? parseWindowMs(metric.window) : null;\n const windowStart = windowMs !== null ? Date.now() - windowMs : undefined;\n\n let records: Record<string, unknown>[];\n\n switch (metric.shape) {\n case 'event': {\n const events = await storage.queryEvents({\n name: metric.name,\n start: windowStart,\n });\n records = events.map((e) => ({\n ...e.attributes,\n name: e.name,\n start_ts: e.start_ts,\n end_ts: e.end_ts,\n }));\n break;\n }\n\n case 'entity': {\n const type = metric.entityType ?? metric.name ?? '';\n const entities = await storage.queryEntities({ type });\n records = entities.map((e) => ({\n ...e.attributes,\n type: e.type,\n id: e.id,\n updated_at: e.updated_at,\n }));\n if (windowStart !== undefined) {\n records = records.filter((r) => (r[tsField] as number) >= windowStart);\n }\n break;\n }\n\n case 'metric': {\n const metrics = await storage.queryMetrics({\n name: metric.name,\n start: windowStart,\n });\n records = metrics.map((m) => ({\n ...m.attributes,\n name: m.name,\n ts: m.ts,\n value: m.value,\n }));\n break;\n }\n\n case 'edge': {\n const edges = await storage.traverse({ kind: metric.name });\n records = edges.map((e) => ({\n ...e.attributes,\n from_type: e.from_type,\n from_id: e.from_id,\n kind: e.kind,\n to_type: e.to_type,\n to_id: e.to_id,\n updated_at: e.updated_at,\n }));\n if (windowStart !== undefined) {\n records = records.filter((r) => (r[tsField] as number) >= windowStart);\n }\n break;\n }\n\n case 'distribution': {\n const distributions = await storage.queryDistributions({\n name: metric.name,\n start: windowStart,\n });\n records = distributions.map((d) => ({\n ...d.attributes,\n name: d.name,\n ts: d.ts,\n kind: d.kind,\n data: d.data,\n }));\n break;\n }\n\n default:\n return null;\n }\n\n const filtered = records.filter((r) => applyFilter(r, metric.filter));\n const sorted = sortByTs(filtered, tsField);\n\n if (metric.groupBy) {\n return computeGroupBy(sorted, metric, tsField);\n }\n\n return computeAgg(sorted, metric.field, metric.fn);\n}\n","import { computeMetric } from './compute';\nimport type { ConfiguredConnector, Widget } from './config';\nimport type { ServerStorage } from './server-storage';\nimport type { CachedWidget } from './wire';\n\nexport async function resolveWidget(\n widgetId: string,\n widget: Widget,\n connectors: ConfiguredConnector[] | readonly string[] | undefined,\n storage: ServerStorage,\n): Promise<CachedWidget | undefined> {\n if (widget.kind === 'status') {\n return {\n widgetId,\n connectorId: widget.source,\n data: null,\n cachedAt: null,\n };\n }\n const { connectorId } = widget.metric;\n if (\n connectors !== undefined &&\n !isAllowedConnector(connectors, connectorId)\n ) {\n return undefined;\n }\n const handle = storage.getStorageHandle(connectorId);\n const data = await computeMetric(handle, widget.metric);\n return {\n widgetId,\n connectorId,\n data,\n cachedAt: (await storage.getSyncState()).lastSyncAt,\n };\n}\n\nfunction isAllowedConnector(\n connectors: ConfiguredConnector[] | readonly string[],\n connectorId: string,\n): boolean {\n if (connectors.length === 0) {\n return false;\n }\n if (typeof connectors[0] === 'string') {\n return (connectors as readonly string[]).includes(connectorId);\n }\n return (connectors as ConfiguredConnector[]).some(\n (e) => e.connector.id === connectorId,\n );\n}\n","import type {\n Distribution,\n DistributionQuery,\n Edge,\n EdgeQuery,\n Entity,\n EntityQuery,\n Event,\n EventQuery,\n MetricQuery,\n MetricSample,\n StorageHandle,\n} from './connector';\nimport type { SyncState } from './engine';\nimport type { ServerStorage } from './server-storage';\n\nexport class InMemoryStorage implements ServerStorage {\n private eventStore = new Map<string, Event[]>();\n private entityStore = new Map<string, Map<string, Map<string, Entity>>>();\n private metricStore = new Map<string, MetricSample[]>();\n private edgeStore = new Map<string, Edge[]>();\n private distributionStore = new Map<string, Distribution[]>();\n private syncState: SyncState = {\n status: 'idle',\n lastSyncAt: null,\n lastError: null,\n };\n\n getStorageHandle(connectorId: string): StorageHandle {\n const getEntityMap = (): Map<string, Map<string, Entity>> => {\n if (!this.entityStore.has(connectorId)) {\n this.entityStore.set(connectorId, new Map());\n }\n return this.entityStore.get(connectorId)!;\n };\n\n const upsertEntities = (es: Entity[]): void => {\n const byType = getEntityMap();\n for (const e of es) {\n if (!byType.has(e.type)) {\n byType.set(e.type, new Map());\n }\n byType.get(e.type)!.set(e.id, e);\n }\n };\n\n const upsertEdges = (es: Edge[]): void => {\n const existing = this.edgeStore.get(connectorId) ?? [];\n const index = new Map<string, number>();\n for (let i = 0; i < existing.length; i++) {\n const e = existing[i]!;\n index.set(\n `${e.from_type}:${e.from_id}:${e.kind}:${e.to_type}:${e.to_id}`,\n i,\n );\n }\n for (const e of es) {\n const key = `${e.from_type}:${e.from_id}:${e.kind}:${e.to_type}:${e.to_id}`;\n const idx = index.get(key);\n if (idx !== undefined) {\n existing[idx] = e;\n } else {\n index.set(key, existing.length);\n existing.push(e);\n }\n }\n this.edgeStore.set(connectorId, existing);\n };\n\n return {\n event: async (e) => {\n if (!this.eventStore.has(connectorId)) {\n this.eventStore.set(connectorId, []);\n }\n this.eventStore.get(connectorId)!.push(e);\n },\n\n entity: async (e) => {\n upsertEntities([e]);\n },\n\n metric: async (m) => {\n if (!this.metricStore.has(connectorId)) {\n this.metricStore.set(connectorId, []);\n }\n this.metricStore.get(connectorId)!.push(m);\n },\n\n edge: async (e) => {\n upsertEdges([e]);\n },\n\n distribution: async (d) => {\n if (!this.distributionStore.has(connectorId)) {\n this.distributionStore.set(connectorId, []);\n }\n this.distributionStore.get(connectorId)!.push(d);\n },\n\n events: async (es, scope) => {\n const names = new Set(scope?.names ?? es.map((e) => e.name));\n const kept = (this.eventStore.get(connectorId) ?? []).filter(\n (e) => !names.has(e.name),\n );\n this.eventStore.set(connectorId, [...kept, ...es]);\n },\n\n entities: async (es, scope) => {\n const byType = getEntityMap();\n const types = new Set(scope?.types ?? es.map((e) => e.type));\n for (const type of types) {\n byType.set(type, new Map());\n }\n upsertEntities(es);\n },\n\n metrics: async (ms, scope) => {\n const names = new Set(scope?.names ?? ms.map((m) => m.name));\n const kept = (this.metricStore.get(connectorId) ?? []).filter(\n (m) => !names.has(m.name),\n );\n this.metricStore.set(connectorId, [...kept, ...ms]);\n },\n\n edges: async (es, scope) => {\n const kinds = new Set(scope?.kinds ?? es.map((e) => e.kind));\n const kept = (this.edgeStore.get(connectorId) ?? []).filter(\n (e) => !kinds.has(e.kind),\n );\n this.edgeStore.set(connectorId, kept);\n upsertEdges(es);\n },\n\n distributions: async (ds, scope) => {\n const names = new Set(scope?.names ?? ds.map((d) => d.name));\n const kept = (this.distributionStore.get(connectorId) ?? []).filter(\n (d) => !names.has(d.name),\n );\n this.distributionStore.set(connectorId, [...kept, ...ds]);\n },\n\n queryEvents: async (q: EventQuery) => {\n let results = this.eventStore.get(connectorId) ?? [];\n if (q.name !== undefined) {\n results = results.filter((e) => e.name === q.name);\n }\n if (q.start !== undefined) {\n results = results.filter((e) => e.start_ts >= q.start!);\n }\n if (q.end !== undefined) {\n results = results.filter((e) => e.start_ts <= q.end!);\n }\n return results;\n },\n\n getEntity: async (type: string, id: string) => {\n return getEntityMap().get(type)?.get(id) ?? null;\n },\n\n queryEntities: async (q: EntityQuery) => {\n const byType = getEntityMap().get(q.type);\n if (!byType) {\n return [];\n }\n return Array.from(byType.values());\n },\n\n queryMetrics: async (q: MetricQuery) => {\n let results = this.metricStore.get(connectorId) ?? [];\n if (q.name !== undefined) {\n results = results.filter((m) => m.name === q.name);\n }\n if (q.start !== undefined) {\n results = results.filter((m) => m.ts >= q.start!);\n }\n if (q.end !== undefined) {\n results = results.filter((m) => m.ts <= q.end!);\n }\n return results;\n },\n\n traverse: async (q: EdgeQuery) => {\n let results = this.edgeStore.get(connectorId) ?? [];\n if (q.fromType !== undefined) {\n results = results.filter((e) => e.from_type === q.fromType);\n }\n if (q.fromId !== undefined) {\n results = results.filter((e) => e.from_id === q.fromId);\n }\n if (q.kind !== undefined) {\n results = results.filter((e) => e.kind === q.kind);\n }\n if (q.toType !== undefined) {\n results = results.filter((e) => e.to_type === q.toType);\n }\n if (q.toId !== undefined) {\n results = results.filter((e) => e.to_id === q.toId);\n }\n return results;\n },\n\n queryDistributions: async (q: DistributionQuery) => {\n let results = this.distributionStore.get(connectorId) ?? [];\n if (q.name !== undefined) {\n results = results.filter((d) => d.name === q.name);\n }\n if (q.start !== undefined) {\n results = results.filter((d) => d.ts >= q.start!);\n }\n if (q.end !== undefined) {\n results = results.filter((d) => d.ts <= q.end!);\n }\n return results;\n },\n\n deleteOlderThan: async (shape, tsUnixMs) => {\n if (shape === 'events') {\n const before = this.eventStore.get(connectorId) ?? [];\n const after = before.filter((e) => e.start_ts >= tsUnixMs);\n this.eventStore.set(connectorId, after);\n return { rowsDeleted: before.length - after.length };\n } else if (shape === 'metrics') {\n const before = this.metricStore.get(connectorId) ?? [];\n const after = before.filter((m) => m.ts >= tsUnixMs);\n this.metricStore.set(connectorId, after);\n return { rowsDeleted: before.length - after.length };\n } else if (shape === 'distributions') {\n const before = this.distributionStore.get(connectorId) ?? [];\n const after = before.filter((d) => d.ts >= tsUnixMs);\n this.distributionStore.set(connectorId, after);\n return { rowsDeleted: before.length - after.length };\n } else {\n throw new Error(\n `Unsupported shape for deleteOlderThan: ${String(shape)}`,\n );\n }\n },\n };\n }\n\n async getSyncState(): Promise<SyncState> {\n return { ...this.syncState };\n }\n\n async setSyncing(): Promise<boolean> {\n if (this.syncState.status === 'syncing') {\n return false;\n }\n this.syncState = { ...this.syncState, status: 'syncing' };\n return true;\n }\n\n async setSyncSuccess(): Promise<void> {\n this.syncState = {\n status: 'idle',\n lastSyncAt: new Date().toISOString(),\n lastError: null,\n };\n }\n\n async setSyncError(error: string): Promise<void> {\n this.syncState = {\n status: 'error',\n lastSyncAt: this.syncState.lastSyncAt,\n lastError: error,\n };\n }\n}\n","import { z } from 'zod';\n\nimport type { DashboardConfig } from './config';\n\nexport const wireConnectorSchema = z.object({\n name: z.string(),\n connectorId: z.string(),\n displayName: z.string().optional(),\n config: z.record(z.string(), z.unknown()),\n syncIntervalSeconds: z.number().optional(),\n enabled: z.boolean().optional(),\n});\n\nexport const wireDashboardSchema = z.object({\n id: z.string().optional(),\n name: z.string(),\n slug: z.string(),\n config: z.record(z.string(), z.unknown()),\n});\n\nexport const wireConfigSchema = z.object({\n connectors: z.array(wireConnectorSchema).optional(),\n dashboards: z.array(wireDashboardSchema).optional(),\n});\n\nexport type WireConnector = z.infer<typeof wireConnectorSchema>;\nexport type WireDashboard = z.infer<typeof wireDashboardSchema>;\nexport type WireConfig = z.infer<typeof wireConfigSchema>;\n\nexport function toWireConfig(config: DashboardConfig): WireConfig {\n return {\n connectors: config.connectors.map(({ connector }) => ({\n name: connector.id,\n connectorId: connector.id,\n displayName: connector.id,\n config: connector.serializeConfig(),\n syncIntervalSeconds: 300,\n enabled: true,\n })),\n dashboards: Object.entries(config.dashboards).map(([id, dash]) => ({\n id,\n name: id,\n slug: id,\n config: { widgets: dash.widgets },\n })),\n };\n}\n"],"mappings":"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","names":["err","z","z"]}
|