@rawdash/core 0.10.0 → 0.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +15 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -185,7 +185,21 @@ async function paginateChunked(opts) {
|
|
|
185
185
|
transientError: err
|
|
186
186
|
};
|
|
187
187
|
}
|
|
188
|
-
|
|
188
|
+
try {
|
|
189
|
+
await writeBatch(phase, items, page);
|
|
190
|
+
} catch (err) {
|
|
191
|
+
if (signal?.aborted || err instanceof Error && err.name === "AbortError") {
|
|
192
|
+
return {
|
|
193
|
+
done: false,
|
|
194
|
+
cursor: { phase, page }
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
return {
|
|
198
|
+
done: false,
|
|
199
|
+
cursor: { phase, page },
|
|
200
|
+
transientError: err
|
|
201
|
+
};
|
|
202
|
+
}
|
|
189
203
|
if (next === null) {
|
|
190
204
|
break;
|
|
191
205
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../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":["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 { 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 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\n constructor(settings: TSettings, creds?: InferCredentialInput<TCreds>) {\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 }\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 (settings: TSettings, creds?: InferCredentialInput<TCreds>): 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 ): 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 await writeBatch(phase, items, page);\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 { CachedWidget } from './engine';\nimport type { ServerStorage } from './server-storage';\n\nexport async function resolveWidget(\n id: 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 id,\n widgetId: id,\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 id,\n widgetId: id,\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":["z","z"]}
|
|
1
|
+
{"version":3,"sources":["../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":["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 { 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 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\n constructor(settings: TSettings, creds?: InferCredentialInput<TCreds>) {\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 }\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 (settings: TSettings, creds?: InferCredentialInput<TCreds>): 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 ): 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 { CachedWidget } from './engine';\nimport type { ServerStorage } from './server-storage';\n\nexport async function resolveWidget(\n id: 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 id,\n widgetId: id,\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 id,\n widgetId: id,\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":["z","z"]}
|