@rawdash/server 0.29.0 → 0.29.2

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 CHANGED
@@ -1,4 +1,4 @@
1
- import { DashboardConfig, ServerStorage, ConnectorLogger, ConnectorRegistry, SecretsResolver, Widget, CachedWidget, HealthResponse, SyncState, WidgetsListResponse, TriggerSyncResponse, RetentionConfig } from '@rawdash/core';
1
+ import { DashboardConfig, ServerStorage, ConnectorLogger, ConnectorRegistry, SecretsResolver, Widget, CachedWidget, HealthResponse, SyncState, WidgetsListResponse, TriggerSyncResponse, RetentionDeletionPlan, RetentionConfig } from '@rawdash/core';
2
2
  export { ACTIVE_SYNC_STATUSES, CachedWidget, ConfiguredConnector, ConnectorClass, ConnectorHealth, ConnectorRegistry, DashboardConfig, HealthResponse, InMemoryStorage, SecretsResolver, ServerStorage, SyncState, SyncStatus, TriggerSyncResponse, Widget, WidgetStatus, WidgetSyncState, WidgetsListResponse, computeMetric, instantiateConnector, isSyncActive } from '@rawdash/core';
3
3
 
4
4
  interface EngineContext {
@@ -87,6 +87,20 @@ declare function runRetentionOnce(ctx: EngineContext): Promise<void>;
87
87
 
88
88
  declare const DEFAULT_RETENTION_INTERVAL_MS: number;
89
89
  declare function hasPruningPolicy(config: RetentionConfig): boolean;
90
+ /**
91
+ * Applies a `RetentionDeletionPlan` via targeted, identity-keyed deletes and
92
+ * returns the number of rows actually deleted.
93
+ *
94
+ * Rows are matched by identity tuple, and `attributes` is compared by its exact
95
+ * serialization (`JSON.stringify`) as written by the storage adapter — not by
96
+ * deep equality. Pass the plan produced by `computeRetention` (whose rows are
97
+ * read straight from storage) so the serialization byte-matches; a hand-built
98
+ * plan whose `attributes` keys are in a different order will not match and those
99
+ * rows will survive.
100
+ */
101
+ declare function applyRetention(storage: ServerStorage, connectorId: string, plan: RetentionDeletionPlan): Promise<{
102
+ rowsDeleted: number;
103
+ }>;
90
104
  declare function runRetention(config: DashboardConfig, storage: ServerStorage): Promise<void>;
91
105
 
92
106
  interface EngineOptions {
@@ -104,4 +118,4 @@ interface Engine {
104
118
  }
105
119
  declare function createEngine(config: DashboardConfig, options?: EngineOptions): Engine;
106
120
 
107
- export { type ConnectorLoggerFactory, DEFAULT_RETENTION_INTERVAL_MS, type DeferredTriggerSyncContext, type Engine, type EngineContext, type EngineOptions, FULL_SYNC_MAX_CHUNKS, FULL_SYNC_TIMEOUT_MS, type GetWidgetOptions, type GetWidgetResult, type InProcessTriggerSyncContext, ROUTES, RawdashError, type RunSyncOptions, type TriggerSyncContext, type TriggerSyncMode, type TriggerSyncOptions, type WidgetCache, type WidgetCacheKey, createEngine, getHealth, getSyncStateHandler, getWidget, hasPruningPolicy, isRawdashError, listWidgets, runRetention, runRetentionOnce, runSync, triggerSync };
121
+ export { type ConnectorLoggerFactory, DEFAULT_RETENTION_INTERVAL_MS, type DeferredTriggerSyncContext, type Engine, type EngineContext, type EngineOptions, FULL_SYNC_MAX_CHUNKS, FULL_SYNC_TIMEOUT_MS, type GetWidgetOptions, type GetWidgetResult, type InProcessTriggerSyncContext, ROUTES, RawdashError, type RunSyncOptions, type TriggerSyncContext, type TriggerSyncMode, type TriggerSyncOptions, type WidgetCache, type WidgetCacheKey, applyRetention, createEngine, getHealth, getSyncStateHandler, getWidget, hasPruningPolicy, isRawdashError, listWidgets, runRetention, runRetentionOnce, runSync, triggerSync };
package/dist/index.js CHANGED
@@ -40,6 +40,19 @@ var DEFAULT_RETENTION_INTERVAL_MS = 60 * 60 * 1e3;
40
40
  function hasPruningPolicy(config) {
41
41
  return config.maxAge !== void 0 || config.maxSize !== void 0;
42
42
  }
43
+ async function applyRetention(storage, connectorId, plan) {
44
+ const total = plan.events.length + plan.metrics.length + plan.distributions.length + plan.entities.length;
45
+ if (total === 0) {
46
+ return { rowsDeleted: 0 };
47
+ }
48
+ const handle = storage.getStorageHandle(connectorId);
49
+ if (!handle.deleteByIdentity) {
50
+ throw new Error(
51
+ "applyRetention requires a storage adapter that implements deleteByIdentity"
52
+ );
53
+ }
54
+ return handle.deleteByIdentity(plan);
55
+ }
43
56
  async function runRetention(config, storage) {
44
57
  const retentionConfig = config.retention;
45
58
  if (!retentionConfig || !hasPruningPolicy(retentionConfig)) {
@@ -546,6 +559,7 @@ export {
546
559
  InMemoryStorage2 as InMemoryStorage,
547
560
  ROUTES,
548
561
  RawdashError,
562
+ applyRetention,
549
563
  computeMetric,
550
564
  createEngine,
551
565
  getHealth,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/errors.ts","../src/routes.ts","../src/handlers.ts","../src/retention.ts","../src/sync.ts","../src/engine.ts","../src/compute.ts","../src/storage.ts","../src/index.ts"],"sourcesContent":["export class RawdashError extends Error {\n constructor(\n readonly status: number,\n readonly code: string,\n message: string,\n ) {\n super(message);\n this.name = 'RawdashError';\n }\n}\n\nexport function isRawdashError(err: unknown): err is RawdashError {\n return err instanceof RawdashError;\n}\n","export const ROUTES = {\n health: '/health',\n syncState: '/sync/state',\n sync: '/sync',\n configValidate: '/config/validate',\n retention: '/retention/retain',\n widgets: {\n list: (dashboardId: string): string =>\n `/dashboards/${encodeURIComponent(dashboardId)}/widgets`,\n single: (dashboardId: string, widgetId: string): string =>\n `/dashboards/${encodeURIComponent(dashboardId)}/widgets/${encodeURIComponent(widgetId)}`,\n },\n} as const;\n","import type {\n CachedWidget,\n ConnectorRegistry,\n HealthResponse,\n SecretsResolver,\n SyncState,\n TriggerSyncResponse,\n Widget,\n WidgetsListResponse,\n} from '@rawdash/core';\nimport {\n computeWidgetEtag,\n isSyncActive,\n resolveWidget,\n widgetConnectorIds,\n} from '@rawdash/core';\nimport type { DashboardConfig, ServerStorage } from '@rawdash/core';\n\nimport type { EngineContext } from './context';\nimport { RawdashError } from './errors';\nimport { runRetention } from './retention';\nimport { type ConnectorLoggerFactory, runSync } from './sync';\nimport type { WidgetCache } from './widget-cache';\n\nasync function cacheGetSafe(\n cache: WidgetCache,\n dashboardId: string,\n widgetId: string,\n widget: Widget,\n): Promise<CachedWidget | undefined> {\n try {\n return await cache.get({ dashboardId, widgetId, widget });\n } catch (err) {\n console.warn('Rawdash widget cache get failed', err);\n return undefined;\n }\n}\n\nasync function cacheSetSafe(\n cache: WidgetCache,\n dashboardId: string,\n widgetId: string,\n widget: Widget,\n value: CachedWidget,\n): Promise<void> {\n try {\n await cache.set({ dashboardId, widgetId, widget }, value);\n } catch (err) {\n console.warn('Rawdash widget cache set failed', err);\n }\n}\n\nasync function resolveWithCache(\n dashboardId: string,\n widgetId: string,\n widget: Widget,\n connectorNames: readonly string[],\n storage: ServerStorage,\n cache: WidgetCache | undefined,\n): Promise<CachedWidget | undefined> {\n if (cache) {\n const hit = await cacheGetSafe(cache, dashboardId, widgetId, widget);\n if (hit) {\n return hit;\n }\n }\n const fresh = await resolveWidget(\n dashboardId,\n widgetId,\n widget,\n connectorNames,\n storage,\n );\n if (fresh && cache) {\n await cacheSetSafe(cache, dashboardId, widgetId, widget, fresh);\n }\n return fresh;\n}\n\nexport interface DeferredTriggerSyncContext {\n getConfig?: () => DashboardConfig | Promise<DashboardConfig>;\n getStorage: () => ServerStorage | Promise<ServerStorage>;\n}\n\nexport interface InProcessTriggerSyncContext {\n getConfig: () => DashboardConfig | Promise<DashboardConfig>;\n getStorage: () => ServerStorage | Promise<ServerStorage>;\n connectorRegistry: ConnectorRegistry;\n secretsResolver?: SecretsResolver;\n loggerFactory?: ConnectorLoggerFactory;\n}\n\nexport type TriggerSyncContext = DeferredTriggerSyncContext;\n\nexport type TriggerSyncMode = 'in-process' | 'deferred';\n\nexport interface TriggerSyncOptions {\n mode?: TriggerSyncMode;\n}\n\nexport function getHealth(): HealthResponse {\n return { status: 'ok' };\n}\n\nexport async function getSyncStateHandler(\n ctx: EngineContext,\n): Promise<SyncState> {\n const storage = await ctx.getStorage();\n return storage.getSyncState();\n}\n\nexport function triggerSync(\n ctx: InProcessTriggerSyncContext,\n opts?: { mode?: 'in-process' },\n): Promise<TriggerSyncResponse>;\nexport function triggerSync(\n ctx: DeferredTriggerSyncContext,\n opts: { mode: 'deferred' },\n): Promise<TriggerSyncResponse>;\nexport async function triggerSync(\n ctx: InProcessTriggerSyncContext | DeferredTriggerSyncContext,\n opts: TriggerSyncOptions = {},\n): Promise<TriggerSyncResponse> {\n const mode: TriggerSyncMode = opts.mode ?? 'in-process';\n const storage = await ctx.getStorage();\n const state = await storage.getSyncState();\n if (isSyncActive(state.status)) {\n return { queued: false };\n }\n let config: DashboardConfig | undefined;\n if (mode === 'in-process') {\n if (!ctx.getConfig) {\n throw new Error(\n 'triggerSync: getConfig is required when mode is \"in-process\"',\n );\n }\n config = await ctx.getConfig();\n }\n const queued = await storage.markSyncQueued();\n if (!queued) {\n return { queued: false };\n }\n if (mode === 'deferred') {\n return { queued: true };\n }\n const inProcessCtx = ctx as InProcessTriggerSyncContext;\n void runSync(config!, storage, {\n connectorRegistry: inProcessCtx.connectorRegistry,\n secretsResolver: inProcessCtx.secretsResolver,\n loggerFactory: inProcessCtx.loggerFactory,\n }).catch((err) => {\n console.error('Rawdash sync failed', err);\n });\n return { queued: true };\n}\n\nexport async function listWidgets(\n ctx: EngineContext,\n dashboardId: string,\n cache?: WidgetCache,\n): Promise<WidgetsListResponse> {\n const config = await ctx.getConfig();\n const dashboard = config.dashboards[dashboardId];\n if (!dashboard) {\n throw new RawdashError(404, 'DASHBOARD_NOT_FOUND', 'Dashboard not found');\n }\n const storage = await ctx.getStorage();\n const connectorNames = config.connectors.map((c) => c.name);\n const entries = Object.entries(dashboard.widgets);\n const resolved = await Promise.all(\n entries.map(([key, widget]) =>\n resolveWithCache(\n dashboardId,\n key,\n widget,\n connectorNames,\n storage,\n cache,\n ),\n ),\n );\n const widgets = resolved.filter((w): w is CachedWidget => w !== undefined);\n return { widgets };\n}\n\nexport interface GetWidgetOptions {\n cache?: WidgetCache;\n ifNoneMatch?: string;\n}\n\nexport type GetWidgetResult =\n | { status: 'ok'; etag: string | undefined; widget: CachedWidget }\n | { status: 'not-modified'; etag: string };\n\nexport async function getWidget(\n ctx: EngineContext,\n dashboardId: string,\n widgetId: string,\n opts: GetWidgetOptions = {},\n): Promise<GetWidgetResult> {\n const { cache, ifNoneMatch } = opts;\n const config = await ctx.getConfig();\n const dashboard = config.dashboards[dashboardId];\n if (!dashboard) {\n throw new RawdashError(404, 'DASHBOARD_NOT_FOUND', 'Dashboard not found');\n }\n const widget = dashboard.widgets[widgetId];\n if (!widget) {\n throw new RawdashError(404, 'WIDGET_NOT_FOUND', 'Widget not found');\n }\n const storage = await ctx.getStorage();\n const connectorNames = config.connectors.map((c) => c.name);\n const connectorIds = widgetConnectorIds(widget);\n if (!connectorIds.some((id) => connectorNames.includes(id))) {\n throw new RawdashError(404, 'WIDGET_NOT_FOUND', 'Widget not found');\n }\n\n if (ifNoneMatch) {\n const healths = await Promise.all(\n connectorIds.map((id) => storage.getHealth(id)),\n );\n const lastSyncAt = healths.reduce<string | null>((newest, health) => {\n if (!health?.lastSyncAt) {\n return newest;\n }\n if (newest === null || health.lastSyncAt > newest) {\n return health.lastSyncAt;\n }\n return newest;\n }, null);\n if (lastSyncAt) {\n const probeEtag = computeWidgetEtag(lastSyncAt, widget);\n if (probeEtag === ifNoneMatch) {\n return { status: 'not-modified', etag: probeEtag };\n }\n }\n }\n\n const result = await resolveWithCache(\n dashboardId,\n widgetId,\n widget,\n connectorNames,\n storage,\n cache,\n );\n if (!result) {\n throw new RawdashError(404, 'WIDGET_NOT_FOUND', 'Widget not found');\n }\n const etag = result.cachedAt\n ? computeWidgetEtag(result.cachedAt, widget)\n : undefined;\n return { status: 'ok', etag, widget: result };\n}\n\nexport async function runRetentionOnce(ctx: EngineContext): Promise<void> {\n const config = await ctx.getConfig();\n const storage = await ctx.getStorage();\n await runRetention(config, storage);\n}\n","import type {\n DashboardConfig,\n RetentionConfig,\n ServerStorage,\n} from '@rawdash/core';\nimport { selectForDeletion } from '@rawdash/core';\n\nexport const DEFAULT_RETENTION_INTERVAL_MS = 60 * 60 * 1000;\n\nexport function hasPruningPolicy(config: RetentionConfig): boolean {\n return config.maxAge !== undefined || config.maxSize !== undefined;\n}\n\nexport async function runRetention(\n config: DashboardConfig,\n storage: ServerStorage,\n): Promise<void> {\n const retentionConfig = config.retention;\n if (!retentionConfig || !hasPruningPolicy(retentionConfig)) {\n return;\n }\n\n const nowMs = Date.now();\n\n const results = await Promise.allSettled(\n config.connectors.map(async (entry) => {\n const handle = storage.getStorageHandle(entry.name);\n\n const [events, metrics, distributions] = await Promise.all([\n handle.queryEvents({}),\n handle.queryMetrics({}),\n handle.queryDistributions({}),\n ]);\n\n await applyRetentionToShape(\n events,\n (e) => e.start_ts,\n retentionConfig,\n nowMs,\n (survivors, names) => handle.events(survivors, { names }),\n );\n\n await applyRetentionToShape(\n metrics,\n (m) => m.ts,\n retentionConfig,\n nowMs,\n (survivors, names) => handle.metrics(survivors, { names }),\n );\n\n await applyRetentionToShape(\n distributions,\n (d) => d.ts,\n retentionConfig,\n nowMs,\n (survivors, names) => handle.distributions(survivors, { names }),\n );\n }),\n );\n\n const failures = results.filter(\n (r): r is PromiseRejectedResult => r.status === 'rejected',\n );\n if (failures.length > 0) {\n throw new Error(\n `Retention failed for ${failures.length} connector(s): ${failures.map((f) => String(f.reason)).join('; ')}`,\n );\n }\n}\n\nasync function applyRetentionToShape<T extends { name: string }>(\n rows: T[],\n getTs: (row: T) => number,\n config: RetentionConfig,\n nowMs: number,\n writeSurvivors: (survivors: T[], names: string[]) => Promise<void>,\n): Promise<void> {\n if (rows.length === 0) {\n return;\n }\n\n const sorted = [...rows].sort((a, b) => getTs(b) - getTs(a));\n const toDeleteSet = new Set(selectForDeletion(sorted, getTs, config, nowMs));\n\n if (toDeleteSet.size === 0) {\n return;\n }\n\n const survivors = sorted.filter((r) => !toDeleteSet.has(r));\n const allNames = [...new Set(rows.map((r) => r.name))];\n\n await writeSurvivors(survivors, allNames);\n}\n","import type {\n ConnectorLogger,\n ConnectorRegistry,\n DashboardConfig,\n SecretsResolver,\n ServerStorage,\n} from '@rawdash/core';\nimport {\n computeConnectorBackfill,\n createDefaultConnectorLogger,\n fetchSpecsForConnector,\n instantiateConnector,\n planSync,\n} from '@rawdash/core';\n\nexport const FULL_SYNC_TIMEOUT_MS = 300_000;\nexport const FULL_SYNC_MAX_CHUNKS = 1_000;\nexport const BACKFILL_BUFFER_MS = 86_400_000;\n\nexport type ConnectorLoggerFactory = (scope: string) => ConnectorLogger;\n\nexport interface RunSyncOptions {\n connectorRegistry: ConnectorRegistry;\n secretsResolver?: SecretsResolver;\n loggerFactory?: ConnectorLoggerFactory;\n}\n\nexport async function runSync(\n config: DashboardConfig,\n storage: ServerStorage,\n options: RunSyncOptions,\n): Promise<void> {\n await storage.markSyncQueued();\n if (typeof storage.markSyncRunning === 'function') {\n const acquired = await storage.markSyncRunning();\n if (!acquired) {\n return;\n }\n }\n const errors: string[] = [];\n const backfill = computeConnectorBackfill(config);\n const now = Date.now();\n const nowDate = new Date(now);\n const connectorStateSupported =\n typeof storage.getConnectorSyncState === 'function' &&\n typeof storage.markConnectorSyncSucceeded === 'function';\n const rawLoggerFactory: ConnectorLoggerFactory =\n options.loggerFactory ??\n ((scope) => createDefaultConnectorLogger({ scope }));\n const safeLogger = (scope: string): ConnectorLogger => {\n let inner: ConnectorLogger;\n try {\n inner = rawLoggerFactory(scope);\n } catch (err) {\n console.warn(\n `[runner] loggerFactory threw for scope=${scope}; falling back to default`,\n err,\n );\n inner = createDefaultConnectorLogger({ scope });\n }\n return {\n info(event, fields) {\n try {\n inner.info(event, fields);\n } catch (err) {\n console.warn(\n `[runner] logger.info threw for scope=${scope} event=${event}`,\n err,\n );\n }\n },\n warn(event, fields) {\n try {\n inner.warn(event, fields);\n } catch (err) {\n console.warn(\n `[runner] logger.warn threw for scope=${scope} event=${event}`,\n err,\n );\n }\n },\n };\n };\n const runnerLogger = safeLogger('runner');\n await Promise.allSettled(\n config.connectors.map(async (entry) => {\n if (entry.enabled === false) {\n return;\n }\n const scope = backfill.get(entry.name);\n if (!scope) {\n return;\n }\n const controller = new AbortController();\n const handle = storage.getStorageHandle(entry.name, {\n signal: controller.signal,\n });\n const connectorLogger = safeLogger(entry.name);\n const syncStart = Date.now();\n let timer: ReturnType<typeof setTimeout> | undefined;\n let status: 'succeeded' | 'failed' = 'succeeded';\n let failureReason: string | undefined;\n try {\n const connector = instantiateConnector(\n entry,\n options.connectorRegistry,\n options.secretsResolver,\n connectorLogger,\n );\n const timeoutPromise = new Promise<never>((_resolve, reject) => {\n timer = setTimeout(() => {\n controller.abort();\n const err = new Error(\n `${entry.name} timed out after ${FULL_SYNC_TIMEOUT_MS}ms`,\n );\n err.name = 'AbortError';\n reject(err);\n }, FULL_SYNC_TIMEOUT_MS);\n });\n\n const resources: ReadonlySet<string> = new Set(scope.keys());\n const fetchSpecs = fetchSpecsForConnector(config, entry.name);\n\n let maxWindowMs: number | undefined;\n for (const [, { specs }] of scope.entries()) {\n for (const { requiredWindowMs } of specs) {\n if (requiredWindowMs === undefined) {\n continue;\n }\n if (maxWindowMs === undefined || requiredWindowMs > maxWindowMs) {\n maxWindowMs = requiredWindowMs;\n }\n }\n }\n const connectorState = connectorStateSupported\n ? await storage.getConnectorSyncState!(entry.name)\n : null;\n const plan = planSync({\n lastSyncAt: connectorState?.lastSyncAt\n ? new Date(connectorState.lastSyncAt)\n : null,\n lastBackfillAt: connectorState?.lastBackfillAt\n ? new Date(connectorState.lastBackfillAt)\n : null,\n fetchSpecs,\n now: nowDate,\n });\n const windowedSince =\n maxWindowMs !== undefined\n ? new Date(now - maxWindowMs - BACKFILL_BUFFER_MS).toISOString()\n : undefined;\n const mode = plan.mode;\n const since = mode === 'full' ? windowedSince : plan.options.since;\n\n runnerLogger.info('sync started', {\n connector: entry.name,\n resources: Array.from(resources),\n mode,\n since,\n });\n\n let cursor: unknown = undefined;\n let chunks = 0;\n while (true) {\n chunks += 1;\n if (chunks > FULL_SYNC_MAX_CHUNKS) {\n controller.abort();\n throw new Error(\n `${entry.name} exceeded ${FULL_SYNC_MAX_CHUNKS} sync chunks without completing`,\n );\n }\n const syncPromise = connector.sync(\n { mode, since, cursor, resources, fetchSpecs },\n handle,\n controller.signal,\n );\n const result = await Promise.race([syncPromise, timeoutPromise]);\n if (result.done) {\n break;\n }\n cursor = result.cursor;\n }\n\n if (connectorStateSupported) {\n await storage.markConnectorSyncSucceeded!(entry.name, {\n backfillDue: plan.backfillDue,\n });\n }\n } catch (err) {\n status = 'failed';\n if (err instanceof Error && err.name === 'AbortError') {\n failureReason = `${entry.name} timed out after ${FULL_SYNC_TIMEOUT_MS}ms`;\n } else {\n failureReason = err instanceof Error ? err.message : String(err);\n }\n errors.push(failureReason);\n } finally {\n if (timer !== undefined) {\n clearTimeout(timer);\n }\n runnerLogger.info('sync settled', {\n connector: entry.name,\n status,\n duration_ms: Date.now() - syncStart,\n error: failureReason,\n });\n }\n }),\n );\n if (errors.length > 0) {\n await storage.markSyncFailed(errors.join('; '));\n } else {\n await storage.markSyncSucceeded();\n }\n}\n","import type {\n CachedWidget,\n ConnectorRegistry,\n DashboardConfig,\n HealthResponse,\n ResourcesByConnectorId,\n SecretsResolver,\n ServerStorage,\n SyncState,\n TriggerSyncResponse,\n} from '@rawdash/core';\nimport {\n InMemoryStorage,\n isSyncActive,\n resolveWidget,\n resourcesByConnectorIdFromRegistry,\n} from '@rawdash/core';\n\nimport { type ConnectorLoggerFactory, runSync } from './sync';\n\nexport interface EngineOptions {\n storage?: ServerStorage;\n connectorRegistry?: ConnectorRegistry;\n secretsResolver?: SecretsResolver;\n loggerFactory?: ConnectorLoggerFactory;\n}\n\nexport interface Engine {\n getWidget(\n dashboardId: string,\n widgetId: string,\n ): Promise<CachedWidget | undefined>;\n getWidgets(dashboardId: string): Promise<CachedWidget[]>;\n getHealth(): Promise<HealthResponse>;\n getSyncState(): Promise<SyncState>;\n triggerSync(): Promise<TriggerSyncResponse>;\n}\n\nexport function createEngine(\n config: DashboardConfig,\n options: EngineOptions = {},\n): Engine {\n const storage: ServerStorage = options.storage ?? new InMemoryStorage();\n const connectorNames = config.connectors.map((c) => c.name);\n const resourcesByConnectorId: ResourcesByConnectorId | undefined = (() => {\n if (!options.connectorRegistry) {\n return undefined;\n }\n const byTypeId = resourcesByConnectorIdFromRegistry(\n options.connectorRegistry,\n );\n return Object.fromEntries(\n config.connectors.flatMap(({ name, connectorId }) => {\n const defs = byTypeId[connectorId];\n return defs ? ([[name, defs]] as const) : [];\n }),\n );\n })();\n\n return {\n async getWidget(dashboardId, widgetId) {\n const dashboard = config.dashboards[dashboardId];\n if (!dashboard) {\n return undefined;\n }\n const widget = dashboard.widgets[widgetId];\n if (!widget) {\n return undefined;\n }\n return resolveWidget(\n dashboardId,\n widgetId,\n widget,\n connectorNames,\n storage,\n resourcesByConnectorId,\n );\n },\n\n async getWidgets(dashboardId) {\n const dashboard = config.dashboards[dashboardId];\n if (!dashboard) {\n return [];\n }\n const entries = Object.entries(dashboard.widgets);\n const resolved = await Promise.all(\n entries.map(([key, widget]) =>\n resolveWidget(\n dashboardId,\n key,\n widget,\n connectorNames,\n storage,\n resourcesByConnectorId,\n ),\n ),\n );\n return resolved.filter((w): w is CachedWidget => w !== undefined);\n },\n\n async getHealth() {\n return { status: 'ok' };\n },\n\n async getSyncState() {\n return storage.getSyncState();\n },\n\n async triggerSync() {\n if (!options.connectorRegistry) {\n throw new Error(\n 'createEngine: connectorRegistry is required to triggerSync',\n );\n }\n const state = await storage.getSyncState();\n if (isSyncActive(state.status)) {\n return { queued: false };\n }\n const queued = await storage.markSyncQueued();\n if (!queued) {\n return { queued: false };\n }\n void runSync(config, storage, {\n connectorRegistry: options.connectorRegistry,\n secretsResolver: options.secretsResolver,\n loggerFactory: options.loggerFactory,\n }).catch((error) => {\n console.error('Rawdash sync failed', error);\n });\n return { queued: true };\n },\n };\n}\n","export { computeMetric, computeMetricWithStatus } from '@rawdash/core';\nexport type { MetricComputation } from '@rawdash/core';\n","export { InMemoryStorage } from '@rawdash/core';\n","export type { EngineContext } from './context';\nexport { RawdashError, isRawdashError } from './errors';\nexport { ROUTES } from './routes';\nexport {\n getHealth,\n getSyncStateHandler,\n getWidget,\n listWidgets,\n runRetentionOnce,\n triggerSync,\n} from './handlers';\nexport type {\n DeferredTriggerSyncContext,\n GetWidgetOptions,\n GetWidgetResult,\n InProcessTriggerSyncContext,\n TriggerSyncContext,\n TriggerSyncMode,\n TriggerSyncOptions,\n} from './handlers';\nexport type { WidgetCache, WidgetCacheKey } from './widget-cache';\nexport { runSync, FULL_SYNC_TIMEOUT_MS, FULL_SYNC_MAX_CHUNKS } from './sync';\nexport type { ConnectorLoggerFactory, RunSyncOptions } from './sync';\nexport {\n runRetention,\n hasPruningPolicy,\n DEFAULT_RETENTION_INTERVAL_MS,\n} from './retention';\nexport { createEngine } from './engine';\nexport type { Engine, EngineOptions } from './engine';\nexport { computeMetric } from './compute';\nexport { InMemoryStorage } from './storage';\nexport type {\n CachedWidget,\n ConfiguredConnector,\n ConnectorHealth,\n DashboardConfig,\n HealthResponse,\n ServerStorage,\n SyncState,\n SyncStatus,\n TriggerSyncResponse,\n Widget,\n WidgetStatus,\n WidgetSyncState,\n WidgetsListResponse,\n} from './types';\nexport { isSyncActive, ACTIVE_SYNC_STATUSES } from '@rawdash/core';\nexport { instantiateConnector } from '@rawdash/core';\nexport type {\n ConnectorClass,\n ConnectorRegistry,\n SecretsResolver,\n} from '@rawdash/core';\n"],"mappings":"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","names":["isSyncActive","resolveWidget","resolveWidget","isSyncActive","InMemoryStorage","isSyncActive","instantiateConnector"]}
1
+ {"version":3,"sources":["../src/errors.ts","../src/routes.ts","../src/handlers.ts","../src/retention.ts","../src/sync.ts","../src/engine.ts","../src/compute.ts","../src/storage.ts","../src/index.ts"],"sourcesContent":["export class RawdashError extends Error {\n constructor(\n readonly status: number,\n readonly code: string,\n message: string,\n ) {\n super(message);\n this.name = 'RawdashError';\n }\n}\n\nexport function isRawdashError(err: unknown): err is RawdashError {\n return err instanceof RawdashError;\n}\n","export const ROUTES = {\n health: '/health',\n syncState: '/sync/state',\n sync: '/sync',\n configValidate: '/config/validate',\n retention: '/retention/retain',\n widgets: {\n list: (dashboardId: string): string =>\n `/dashboards/${encodeURIComponent(dashboardId)}/widgets`,\n single: (dashboardId: string, widgetId: string): string =>\n `/dashboards/${encodeURIComponent(dashboardId)}/widgets/${encodeURIComponent(widgetId)}`,\n },\n} as const;\n","import type {\n CachedWidget,\n ConnectorRegistry,\n HealthResponse,\n SecretsResolver,\n SyncState,\n TriggerSyncResponse,\n Widget,\n WidgetsListResponse,\n} from '@rawdash/core';\nimport {\n computeWidgetEtag,\n isSyncActive,\n resolveWidget,\n widgetConnectorIds,\n} from '@rawdash/core';\nimport type { DashboardConfig, ServerStorage } from '@rawdash/core';\n\nimport type { EngineContext } from './context';\nimport { RawdashError } from './errors';\nimport { runRetention } from './retention';\nimport { type ConnectorLoggerFactory, runSync } from './sync';\nimport type { WidgetCache } from './widget-cache';\n\nasync function cacheGetSafe(\n cache: WidgetCache,\n dashboardId: string,\n widgetId: string,\n widget: Widget,\n): Promise<CachedWidget | undefined> {\n try {\n return await cache.get({ dashboardId, widgetId, widget });\n } catch (err) {\n console.warn('Rawdash widget cache get failed', err);\n return undefined;\n }\n}\n\nasync function cacheSetSafe(\n cache: WidgetCache,\n dashboardId: string,\n widgetId: string,\n widget: Widget,\n value: CachedWidget,\n): Promise<void> {\n try {\n await cache.set({ dashboardId, widgetId, widget }, value);\n } catch (err) {\n console.warn('Rawdash widget cache set failed', err);\n }\n}\n\nasync function resolveWithCache(\n dashboardId: string,\n widgetId: string,\n widget: Widget,\n connectorNames: readonly string[],\n storage: ServerStorage,\n cache: WidgetCache | undefined,\n): Promise<CachedWidget | undefined> {\n if (cache) {\n const hit = await cacheGetSafe(cache, dashboardId, widgetId, widget);\n if (hit) {\n return hit;\n }\n }\n const fresh = await resolveWidget(\n dashboardId,\n widgetId,\n widget,\n connectorNames,\n storage,\n );\n if (fresh && cache) {\n await cacheSetSafe(cache, dashboardId, widgetId, widget, fresh);\n }\n return fresh;\n}\n\nexport interface DeferredTriggerSyncContext {\n getConfig?: () => DashboardConfig | Promise<DashboardConfig>;\n getStorage: () => ServerStorage | Promise<ServerStorage>;\n}\n\nexport interface InProcessTriggerSyncContext {\n getConfig: () => DashboardConfig | Promise<DashboardConfig>;\n getStorage: () => ServerStorage | Promise<ServerStorage>;\n connectorRegistry: ConnectorRegistry;\n secretsResolver?: SecretsResolver;\n loggerFactory?: ConnectorLoggerFactory;\n}\n\nexport type TriggerSyncContext = DeferredTriggerSyncContext;\n\nexport type TriggerSyncMode = 'in-process' | 'deferred';\n\nexport interface TriggerSyncOptions {\n mode?: TriggerSyncMode;\n}\n\nexport function getHealth(): HealthResponse {\n return { status: 'ok' };\n}\n\nexport async function getSyncStateHandler(\n ctx: EngineContext,\n): Promise<SyncState> {\n const storage = await ctx.getStorage();\n return storage.getSyncState();\n}\n\nexport function triggerSync(\n ctx: InProcessTriggerSyncContext,\n opts?: { mode?: 'in-process' },\n): Promise<TriggerSyncResponse>;\nexport function triggerSync(\n ctx: DeferredTriggerSyncContext,\n opts: { mode: 'deferred' },\n): Promise<TriggerSyncResponse>;\nexport async function triggerSync(\n ctx: InProcessTriggerSyncContext | DeferredTriggerSyncContext,\n opts: TriggerSyncOptions = {},\n): Promise<TriggerSyncResponse> {\n const mode: TriggerSyncMode = opts.mode ?? 'in-process';\n const storage = await ctx.getStorage();\n const state = await storage.getSyncState();\n if (isSyncActive(state.status)) {\n return { queued: false };\n }\n let config: DashboardConfig | undefined;\n if (mode === 'in-process') {\n if (!ctx.getConfig) {\n throw new Error(\n 'triggerSync: getConfig is required when mode is \"in-process\"',\n );\n }\n config = await ctx.getConfig();\n }\n const queued = await storage.markSyncQueued();\n if (!queued) {\n return { queued: false };\n }\n if (mode === 'deferred') {\n return { queued: true };\n }\n const inProcessCtx = ctx as InProcessTriggerSyncContext;\n void runSync(config!, storage, {\n connectorRegistry: inProcessCtx.connectorRegistry,\n secretsResolver: inProcessCtx.secretsResolver,\n loggerFactory: inProcessCtx.loggerFactory,\n }).catch((err) => {\n console.error('Rawdash sync failed', err);\n });\n return { queued: true };\n}\n\nexport async function listWidgets(\n ctx: EngineContext,\n dashboardId: string,\n cache?: WidgetCache,\n): Promise<WidgetsListResponse> {\n const config = await ctx.getConfig();\n const dashboard = config.dashboards[dashboardId];\n if (!dashboard) {\n throw new RawdashError(404, 'DASHBOARD_NOT_FOUND', 'Dashboard not found');\n }\n const storage = await ctx.getStorage();\n const connectorNames = config.connectors.map((c) => c.name);\n const entries = Object.entries(dashboard.widgets);\n const resolved = await Promise.all(\n entries.map(([key, widget]) =>\n resolveWithCache(\n dashboardId,\n key,\n widget,\n connectorNames,\n storage,\n cache,\n ),\n ),\n );\n const widgets = resolved.filter((w): w is CachedWidget => w !== undefined);\n return { widgets };\n}\n\nexport interface GetWidgetOptions {\n cache?: WidgetCache;\n ifNoneMatch?: string;\n}\n\nexport type GetWidgetResult =\n | { status: 'ok'; etag: string | undefined; widget: CachedWidget }\n | { status: 'not-modified'; etag: string };\n\nexport async function getWidget(\n ctx: EngineContext,\n dashboardId: string,\n widgetId: string,\n opts: GetWidgetOptions = {},\n): Promise<GetWidgetResult> {\n const { cache, ifNoneMatch } = opts;\n const config = await ctx.getConfig();\n const dashboard = config.dashboards[dashboardId];\n if (!dashboard) {\n throw new RawdashError(404, 'DASHBOARD_NOT_FOUND', 'Dashboard not found');\n }\n const widget = dashboard.widgets[widgetId];\n if (!widget) {\n throw new RawdashError(404, 'WIDGET_NOT_FOUND', 'Widget not found');\n }\n const storage = await ctx.getStorage();\n const connectorNames = config.connectors.map((c) => c.name);\n const connectorIds = widgetConnectorIds(widget);\n if (!connectorIds.some((id) => connectorNames.includes(id))) {\n throw new RawdashError(404, 'WIDGET_NOT_FOUND', 'Widget not found');\n }\n\n if (ifNoneMatch) {\n const healths = await Promise.all(\n connectorIds.map((id) => storage.getHealth(id)),\n );\n const lastSyncAt = healths.reduce<string | null>((newest, health) => {\n if (!health?.lastSyncAt) {\n return newest;\n }\n if (newest === null || health.lastSyncAt > newest) {\n return health.lastSyncAt;\n }\n return newest;\n }, null);\n if (lastSyncAt) {\n const probeEtag = computeWidgetEtag(lastSyncAt, widget);\n if (probeEtag === ifNoneMatch) {\n return { status: 'not-modified', etag: probeEtag };\n }\n }\n }\n\n const result = await resolveWithCache(\n dashboardId,\n widgetId,\n widget,\n connectorNames,\n storage,\n cache,\n );\n if (!result) {\n throw new RawdashError(404, 'WIDGET_NOT_FOUND', 'Widget not found');\n }\n const etag = result.cachedAt\n ? computeWidgetEtag(result.cachedAt, widget)\n : undefined;\n return { status: 'ok', etag, widget: result };\n}\n\nexport async function runRetentionOnce(ctx: EngineContext): Promise<void> {\n const config = await ctx.getConfig();\n const storage = await ctx.getStorage();\n await runRetention(config, storage);\n}\n","import type {\n DashboardConfig,\n RetentionConfig,\n RetentionDeletionPlan,\n ServerStorage,\n} from '@rawdash/core';\nimport { selectForDeletion } from '@rawdash/core';\n\nexport const DEFAULT_RETENTION_INTERVAL_MS = 60 * 60 * 1000;\n\nexport function hasPruningPolicy(config: RetentionConfig): boolean {\n return config.maxAge !== undefined || config.maxSize !== undefined;\n}\n\n/**\n * Applies a `RetentionDeletionPlan` via targeted, identity-keyed deletes and\n * returns the number of rows actually deleted.\n *\n * Rows are matched by identity tuple, and `attributes` is compared by its exact\n * serialization (`JSON.stringify`) as written by the storage adapter — not by\n * deep equality. Pass the plan produced by `computeRetention` (whose rows are\n * read straight from storage) so the serialization byte-matches; a hand-built\n * plan whose `attributes` keys are in a different order will not match and those\n * rows will survive.\n */\nexport async function applyRetention(\n storage: ServerStorage,\n connectorId: string,\n plan: RetentionDeletionPlan,\n): Promise<{ rowsDeleted: number }> {\n const total =\n plan.events.length +\n plan.metrics.length +\n plan.distributions.length +\n plan.entities.length;\n if (total === 0) {\n return { rowsDeleted: 0 };\n }\n\n const handle = storage.getStorageHandle(connectorId);\n if (!handle.deleteByIdentity) {\n throw new Error(\n 'applyRetention requires a storage adapter that implements deleteByIdentity',\n );\n }\n\n return handle.deleteByIdentity(plan);\n}\n\nexport async function runRetention(\n config: DashboardConfig,\n storage: ServerStorage,\n): Promise<void> {\n const retentionConfig = config.retention;\n if (!retentionConfig || !hasPruningPolicy(retentionConfig)) {\n return;\n }\n\n const nowMs = Date.now();\n\n const results = await Promise.allSettled(\n config.connectors.map(async (entry) => {\n const handle = storage.getStorageHandle(entry.name);\n\n const [events, metrics, distributions] = await Promise.all([\n handle.queryEvents({}),\n handle.queryMetrics({}),\n handle.queryDistributions({}),\n ]);\n\n await applyRetentionToShape(\n events,\n (e) => e.start_ts,\n retentionConfig,\n nowMs,\n (survivors, names) => handle.events(survivors, { names }),\n );\n\n await applyRetentionToShape(\n metrics,\n (m) => m.ts,\n retentionConfig,\n nowMs,\n (survivors, names) => handle.metrics(survivors, { names }),\n );\n\n await applyRetentionToShape(\n distributions,\n (d) => d.ts,\n retentionConfig,\n nowMs,\n (survivors, names) => handle.distributions(survivors, { names }),\n );\n }),\n );\n\n const failures = results.filter(\n (r): r is PromiseRejectedResult => r.status === 'rejected',\n );\n if (failures.length > 0) {\n throw new Error(\n `Retention failed for ${failures.length} connector(s): ${failures.map((f) => String(f.reason)).join('; ')}`,\n );\n }\n}\n\nasync function applyRetentionToShape<T extends { name: string }>(\n rows: T[],\n getTs: (row: T) => number,\n config: RetentionConfig,\n nowMs: number,\n writeSurvivors: (survivors: T[], names: string[]) => Promise<void>,\n): Promise<void> {\n if (rows.length === 0) {\n return;\n }\n\n const sorted = [...rows].sort((a, b) => getTs(b) - getTs(a));\n const toDeleteSet = new Set(selectForDeletion(sorted, getTs, config, nowMs));\n\n if (toDeleteSet.size === 0) {\n return;\n }\n\n const survivors = sorted.filter((r) => !toDeleteSet.has(r));\n const allNames = [...new Set(rows.map((r) => r.name))];\n\n await writeSurvivors(survivors, allNames);\n}\n","import type {\n ConnectorLogger,\n ConnectorRegistry,\n DashboardConfig,\n SecretsResolver,\n ServerStorage,\n} from '@rawdash/core';\nimport {\n computeConnectorBackfill,\n createDefaultConnectorLogger,\n fetchSpecsForConnector,\n instantiateConnector,\n planSync,\n} from '@rawdash/core';\n\nexport const FULL_SYNC_TIMEOUT_MS = 300_000;\nexport const FULL_SYNC_MAX_CHUNKS = 1_000;\nexport const BACKFILL_BUFFER_MS = 86_400_000;\n\nexport type ConnectorLoggerFactory = (scope: string) => ConnectorLogger;\n\nexport interface RunSyncOptions {\n connectorRegistry: ConnectorRegistry;\n secretsResolver?: SecretsResolver;\n loggerFactory?: ConnectorLoggerFactory;\n}\n\nexport async function runSync(\n config: DashboardConfig,\n storage: ServerStorage,\n options: RunSyncOptions,\n): Promise<void> {\n await storage.markSyncQueued();\n if (typeof storage.markSyncRunning === 'function') {\n const acquired = await storage.markSyncRunning();\n if (!acquired) {\n return;\n }\n }\n const errors: string[] = [];\n const backfill = computeConnectorBackfill(config);\n const now = Date.now();\n const nowDate = new Date(now);\n const connectorStateSupported =\n typeof storage.getConnectorSyncState === 'function' &&\n typeof storage.markConnectorSyncSucceeded === 'function';\n const rawLoggerFactory: ConnectorLoggerFactory =\n options.loggerFactory ??\n ((scope) => createDefaultConnectorLogger({ scope }));\n const safeLogger = (scope: string): ConnectorLogger => {\n let inner: ConnectorLogger;\n try {\n inner = rawLoggerFactory(scope);\n } catch (err) {\n console.warn(\n `[runner] loggerFactory threw for scope=${scope}; falling back to default`,\n err,\n );\n inner = createDefaultConnectorLogger({ scope });\n }\n return {\n info(event, fields) {\n try {\n inner.info(event, fields);\n } catch (err) {\n console.warn(\n `[runner] logger.info threw for scope=${scope} event=${event}`,\n err,\n );\n }\n },\n warn(event, fields) {\n try {\n inner.warn(event, fields);\n } catch (err) {\n console.warn(\n `[runner] logger.warn threw for scope=${scope} event=${event}`,\n err,\n );\n }\n },\n };\n };\n const runnerLogger = safeLogger('runner');\n await Promise.allSettled(\n config.connectors.map(async (entry) => {\n if (entry.enabled === false) {\n return;\n }\n const scope = backfill.get(entry.name);\n if (!scope) {\n return;\n }\n const controller = new AbortController();\n const handle = storage.getStorageHandle(entry.name, {\n signal: controller.signal,\n });\n const connectorLogger = safeLogger(entry.name);\n const syncStart = Date.now();\n let timer: ReturnType<typeof setTimeout> | undefined;\n let status: 'succeeded' | 'failed' = 'succeeded';\n let failureReason: string | undefined;\n try {\n const connector = instantiateConnector(\n entry,\n options.connectorRegistry,\n options.secretsResolver,\n connectorLogger,\n );\n const timeoutPromise = new Promise<never>((_resolve, reject) => {\n timer = setTimeout(() => {\n controller.abort();\n const err = new Error(\n `${entry.name} timed out after ${FULL_SYNC_TIMEOUT_MS}ms`,\n );\n err.name = 'AbortError';\n reject(err);\n }, FULL_SYNC_TIMEOUT_MS);\n });\n\n const resources: ReadonlySet<string> = new Set(scope.keys());\n const fetchSpecs = fetchSpecsForConnector(config, entry.name);\n\n let maxWindowMs: number | undefined;\n for (const [, { specs }] of scope.entries()) {\n for (const { requiredWindowMs } of specs) {\n if (requiredWindowMs === undefined) {\n continue;\n }\n if (maxWindowMs === undefined || requiredWindowMs > maxWindowMs) {\n maxWindowMs = requiredWindowMs;\n }\n }\n }\n const connectorState = connectorStateSupported\n ? await storage.getConnectorSyncState!(entry.name)\n : null;\n const plan = planSync({\n lastSyncAt: connectorState?.lastSyncAt\n ? new Date(connectorState.lastSyncAt)\n : null,\n lastBackfillAt: connectorState?.lastBackfillAt\n ? new Date(connectorState.lastBackfillAt)\n : null,\n fetchSpecs,\n now: nowDate,\n });\n const windowedSince =\n maxWindowMs !== undefined\n ? new Date(now - maxWindowMs - BACKFILL_BUFFER_MS).toISOString()\n : undefined;\n const mode = plan.mode;\n const since = mode === 'full' ? windowedSince : plan.options.since;\n\n runnerLogger.info('sync started', {\n connector: entry.name,\n resources: Array.from(resources),\n mode,\n since,\n });\n\n let cursor: unknown = undefined;\n let chunks = 0;\n while (true) {\n chunks += 1;\n if (chunks > FULL_SYNC_MAX_CHUNKS) {\n controller.abort();\n throw new Error(\n `${entry.name} exceeded ${FULL_SYNC_MAX_CHUNKS} sync chunks without completing`,\n );\n }\n const syncPromise = connector.sync(\n { mode, since, cursor, resources, fetchSpecs },\n handle,\n controller.signal,\n );\n const result = await Promise.race([syncPromise, timeoutPromise]);\n if (result.done) {\n break;\n }\n cursor = result.cursor;\n }\n\n if (connectorStateSupported) {\n await storage.markConnectorSyncSucceeded!(entry.name, {\n backfillDue: plan.backfillDue,\n });\n }\n } catch (err) {\n status = 'failed';\n if (err instanceof Error && err.name === 'AbortError') {\n failureReason = `${entry.name} timed out after ${FULL_SYNC_TIMEOUT_MS}ms`;\n } else {\n failureReason = err instanceof Error ? err.message : String(err);\n }\n errors.push(failureReason);\n } finally {\n if (timer !== undefined) {\n clearTimeout(timer);\n }\n runnerLogger.info('sync settled', {\n connector: entry.name,\n status,\n duration_ms: Date.now() - syncStart,\n error: failureReason,\n });\n }\n }),\n );\n if (errors.length > 0) {\n await storage.markSyncFailed(errors.join('; '));\n } else {\n await storage.markSyncSucceeded();\n }\n}\n","import type {\n CachedWidget,\n ConnectorRegistry,\n DashboardConfig,\n HealthResponse,\n ResourcesByConnectorId,\n SecretsResolver,\n ServerStorage,\n SyncState,\n TriggerSyncResponse,\n} from '@rawdash/core';\nimport {\n InMemoryStorage,\n isSyncActive,\n resolveWidget,\n resourcesByConnectorIdFromRegistry,\n} from '@rawdash/core';\n\nimport { type ConnectorLoggerFactory, runSync } from './sync';\n\nexport interface EngineOptions {\n storage?: ServerStorage;\n connectorRegistry?: ConnectorRegistry;\n secretsResolver?: SecretsResolver;\n loggerFactory?: ConnectorLoggerFactory;\n}\n\nexport interface Engine {\n getWidget(\n dashboardId: string,\n widgetId: string,\n ): Promise<CachedWidget | undefined>;\n getWidgets(dashboardId: string): Promise<CachedWidget[]>;\n getHealth(): Promise<HealthResponse>;\n getSyncState(): Promise<SyncState>;\n triggerSync(): Promise<TriggerSyncResponse>;\n}\n\nexport function createEngine(\n config: DashboardConfig,\n options: EngineOptions = {},\n): Engine {\n const storage: ServerStorage = options.storage ?? new InMemoryStorage();\n const connectorNames = config.connectors.map((c) => c.name);\n const resourcesByConnectorId: ResourcesByConnectorId | undefined = (() => {\n if (!options.connectorRegistry) {\n return undefined;\n }\n const byTypeId = resourcesByConnectorIdFromRegistry(\n options.connectorRegistry,\n );\n return Object.fromEntries(\n config.connectors.flatMap(({ name, connectorId }) => {\n const defs = byTypeId[connectorId];\n return defs ? ([[name, defs]] as const) : [];\n }),\n );\n })();\n\n return {\n async getWidget(dashboardId, widgetId) {\n const dashboard = config.dashboards[dashboardId];\n if (!dashboard) {\n return undefined;\n }\n const widget = dashboard.widgets[widgetId];\n if (!widget) {\n return undefined;\n }\n return resolveWidget(\n dashboardId,\n widgetId,\n widget,\n connectorNames,\n storage,\n resourcesByConnectorId,\n );\n },\n\n async getWidgets(dashboardId) {\n const dashboard = config.dashboards[dashboardId];\n if (!dashboard) {\n return [];\n }\n const entries = Object.entries(dashboard.widgets);\n const resolved = await Promise.all(\n entries.map(([key, widget]) =>\n resolveWidget(\n dashboardId,\n key,\n widget,\n connectorNames,\n storage,\n resourcesByConnectorId,\n ),\n ),\n );\n return resolved.filter((w): w is CachedWidget => w !== undefined);\n },\n\n async getHealth() {\n return { status: 'ok' };\n },\n\n async getSyncState() {\n return storage.getSyncState();\n },\n\n async triggerSync() {\n if (!options.connectorRegistry) {\n throw new Error(\n 'createEngine: connectorRegistry is required to triggerSync',\n );\n }\n const state = await storage.getSyncState();\n if (isSyncActive(state.status)) {\n return { queued: false };\n }\n const queued = await storage.markSyncQueued();\n if (!queued) {\n return { queued: false };\n }\n void runSync(config, storage, {\n connectorRegistry: options.connectorRegistry,\n secretsResolver: options.secretsResolver,\n loggerFactory: options.loggerFactory,\n }).catch((error) => {\n console.error('Rawdash sync failed', error);\n });\n return { queued: true };\n },\n };\n}\n","export { computeMetric, computeMetricWithStatus } from '@rawdash/core';\nexport type { MetricComputation } from '@rawdash/core';\n","export { InMemoryStorage } from '@rawdash/core';\n","export type { EngineContext } from './context';\nexport { RawdashError, isRawdashError } from './errors';\nexport { ROUTES } from './routes';\nexport {\n getHealth,\n getSyncStateHandler,\n getWidget,\n listWidgets,\n runRetentionOnce,\n triggerSync,\n} from './handlers';\nexport type {\n DeferredTriggerSyncContext,\n GetWidgetOptions,\n GetWidgetResult,\n InProcessTriggerSyncContext,\n TriggerSyncContext,\n TriggerSyncMode,\n TriggerSyncOptions,\n} from './handlers';\nexport type { WidgetCache, WidgetCacheKey } from './widget-cache';\nexport { runSync, FULL_SYNC_TIMEOUT_MS, FULL_SYNC_MAX_CHUNKS } from './sync';\nexport type { ConnectorLoggerFactory, RunSyncOptions } from './sync';\nexport {\n runRetention,\n applyRetention,\n hasPruningPolicy,\n DEFAULT_RETENTION_INTERVAL_MS,\n} from './retention';\nexport { createEngine } from './engine';\nexport type { Engine, EngineOptions } from './engine';\nexport { computeMetric } from './compute';\nexport { InMemoryStorage } from './storage';\nexport type {\n CachedWidget,\n ConfiguredConnector,\n ConnectorHealth,\n DashboardConfig,\n HealthResponse,\n ServerStorage,\n SyncState,\n SyncStatus,\n TriggerSyncResponse,\n Widget,\n WidgetStatus,\n WidgetSyncState,\n WidgetsListResponse,\n} from './types';\nexport { isSyncActive, ACTIVE_SYNC_STATUSES } from '@rawdash/core';\nexport { instantiateConnector } from '@rawdash/core';\nexport type {\n ConnectorClass,\n ConnectorRegistry,\n SecretsResolver,\n} from '@rawdash/core';\n"],"mappings":";AAAO,IAAM,eAAN,cAA2B,MAAM;AAAA,EACtC,YACW,QACA,MACT,SACA;AACA,UAAM,OAAO;AAJJ;AACA;AAIT,SAAK,OAAO;AAAA,EACd;AAAA,EANW;AAAA,EACA;AAMb;AAEO,SAAS,eAAe,KAAmC;AAChE,SAAO,eAAe;AACxB;;;ACbO,IAAM,SAAS;AAAA,EACpB,QAAQ;AAAA,EACR,WAAW;AAAA,EACX,MAAM;AAAA,EACN,gBAAgB;AAAA,EAChB,WAAW;AAAA,EACX,SAAS;AAAA,IACP,MAAM,CAAC,gBACL,eAAe,mBAAmB,WAAW,CAAC;AAAA,IAChD,QAAQ,CAAC,aAAqB,aAC5B,eAAe,mBAAmB,WAAW,CAAC,YAAY,mBAAmB,QAAQ,CAAC;AAAA,EAC1F;AACF;;;ACFA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;;;ACTP,SAAS,yBAAyB;AAE3B,IAAM,gCAAgC,KAAK,KAAK;AAEhD,SAAS,iBAAiB,QAAkC;AACjE,SAAO,OAAO,WAAW,UAAa,OAAO,YAAY;AAC3D;AAaA,eAAsB,eACpB,SACA,aACA,MACkC;AAClC,QAAM,QACJ,KAAK,OAAO,SACZ,KAAK,QAAQ,SACb,KAAK,cAAc,SACnB,KAAK,SAAS;AAChB,MAAI,UAAU,GAAG;AACf,WAAO,EAAE,aAAa,EAAE;AAAA,EAC1B;AAEA,QAAM,SAAS,QAAQ,iBAAiB,WAAW;AACnD,MAAI,CAAC,OAAO,kBAAkB;AAC5B,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,SAAO,OAAO,iBAAiB,IAAI;AACrC;AAEA,eAAsB,aACpB,QACA,SACe;AACf,QAAM,kBAAkB,OAAO;AAC/B,MAAI,CAAC,mBAAmB,CAAC,iBAAiB,eAAe,GAAG;AAC1D;AAAA,EACF;AAEA,QAAM,QAAQ,KAAK,IAAI;AAEvB,QAAM,UAAU,MAAM,QAAQ;AAAA,IAC5B,OAAO,WAAW,IAAI,OAAO,UAAU;AACrC,YAAM,SAAS,QAAQ,iBAAiB,MAAM,IAAI;AAElD,YAAM,CAAC,QAAQ,SAAS,aAAa,IAAI,MAAM,QAAQ,IAAI;AAAA,QACzD,OAAO,YAAY,CAAC,CAAC;AAAA,QACrB,OAAO,aAAa,CAAC,CAAC;AAAA,QACtB,OAAO,mBAAmB,CAAC,CAAC;AAAA,MAC9B,CAAC;AAED,YAAM;AAAA,QACJ;AAAA,QACA,CAAC,MAAM,EAAE;AAAA,QACT;AAAA,QACA;AAAA,QACA,CAAC,WAAW,UAAU,OAAO,OAAO,WAAW,EAAE,MAAM,CAAC;AAAA,MAC1D;AAEA,YAAM;AAAA,QACJ;AAAA,QACA,CAAC,MAAM,EAAE;AAAA,QACT;AAAA,QACA;AAAA,QACA,CAAC,WAAW,UAAU,OAAO,QAAQ,WAAW,EAAE,MAAM,CAAC;AAAA,MAC3D;AAEA,YAAM;AAAA,QACJ;AAAA,QACA,CAAC,MAAM,EAAE;AAAA,QACT;AAAA,QACA;AAAA,QACA,CAAC,WAAW,UAAU,OAAO,cAAc,WAAW,EAAE,MAAM,CAAC;AAAA,MACjE;AAAA,IACF,CAAC;AAAA,EACH;AAEA,QAAM,WAAW,QAAQ;AAAA,IACvB,CAAC,MAAkC,EAAE,WAAW;AAAA,EAClD;AACA,MAAI,SAAS,SAAS,GAAG;AACvB,UAAM,IAAI;AAAA,MACR,wBAAwB,SAAS,MAAM,kBAAkB,SAAS,IAAI,CAAC,MAAM,OAAO,EAAE,MAAM,CAAC,EAAE,KAAK,IAAI,CAAC;AAAA,IAC3G;AAAA,EACF;AACF;AAEA,eAAe,sBACb,MACA,OACA,QACA,OACA,gBACe;AACf,MAAI,KAAK,WAAW,GAAG;AACrB;AAAA,EACF;AAEA,QAAM,SAAS,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,GAAG,MAAM,MAAM,CAAC,IAAI,MAAM,CAAC,CAAC;AAC3D,QAAM,cAAc,IAAI,IAAI,kBAAkB,QAAQ,OAAO,QAAQ,KAAK,CAAC;AAE3E,MAAI,YAAY,SAAS,GAAG;AAC1B;AAAA,EACF;AAEA,QAAM,YAAY,OAAO,OAAO,CAAC,MAAM,CAAC,YAAY,IAAI,CAAC,CAAC;AAC1D,QAAM,WAAW,CAAC,GAAG,IAAI,IAAI,KAAK,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;AAErD,QAAM,eAAe,WAAW,QAAQ;AAC1C;;;ACzHA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEA,IAAM,uBAAuB;AAC7B,IAAM,uBAAuB;AAC7B,IAAM,qBAAqB;AAUlC,eAAsB,QACpB,QACA,SACA,SACe;AACf,QAAM,QAAQ,eAAe;AAC7B,MAAI,OAAO,QAAQ,oBAAoB,YAAY;AACjD,UAAM,WAAW,MAAM,QAAQ,gBAAgB;AAC/C,QAAI,CAAC,UAAU;AACb;AAAA,IACF;AAAA,EACF;AACA,QAAM,SAAmB,CAAC;AAC1B,QAAM,WAAW,yBAAyB,MAAM;AAChD,QAAM,MAAM,KAAK,IAAI;AACrB,QAAM,UAAU,IAAI,KAAK,GAAG;AAC5B,QAAM,0BACJ,OAAO,QAAQ,0BAA0B,cACzC,OAAO,QAAQ,+BAA+B;AAChD,QAAM,mBACJ,QAAQ,kBACP,CAAC,UAAU,6BAA6B,EAAE,MAAM,CAAC;AACpD,QAAM,aAAa,CAAC,UAAmC;AACrD,QAAI;AACJ,QAAI;AACF,cAAQ,iBAAiB,KAAK;AAAA,IAChC,SAAS,KAAK;AACZ,cAAQ;AAAA,QACN,0CAA0C,KAAK;AAAA,QAC/C;AAAA,MACF;AACA,cAAQ,6BAA6B,EAAE,MAAM,CAAC;AAAA,IAChD;AACA,WAAO;AAAA,MACL,KAAK,OAAO,QAAQ;AAClB,YAAI;AACF,gBAAM,KAAK,OAAO,MAAM;AAAA,QAC1B,SAAS,KAAK;AACZ,kBAAQ;AAAA,YACN,wCAAwC,KAAK,UAAU,KAAK;AAAA,YAC5D;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,MACA,KAAK,OAAO,QAAQ;AAClB,YAAI;AACF,gBAAM,KAAK,OAAO,MAAM;AAAA,QAC1B,SAAS,KAAK;AACZ,kBAAQ;AAAA,YACN,wCAAwC,KAAK,UAAU,KAAK;AAAA,YAC5D;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,QAAM,eAAe,WAAW,QAAQ;AACxC,QAAM,QAAQ;AAAA,IACZ,OAAO,WAAW,IAAI,OAAO,UAAU;AACrC,UAAI,MAAM,YAAY,OAAO;AAC3B;AAAA,MACF;AACA,YAAM,QAAQ,SAAS,IAAI,MAAM,IAAI;AACrC,UAAI,CAAC,OAAO;AACV;AAAA,MACF;AACA,YAAM,aAAa,IAAI,gBAAgB;AACvC,YAAM,SAAS,QAAQ,iBAAiB,MAAM,MAAM;AAAA,QAClD,QAAQ,WAAW;AAAA,MACrB,CAAC;AACD,YAAM,kBAAkB,WAAW,MAAM,IAAI;AAC7C,YAAM,YAAY,KAAK,IAAI;AAC3B,UAAI;AACJ,UAAI,SAAiC;AACrC,UAAI;AACJ,UAAI;AACF,cAAM,YAAY;AAAA,UAChB;AAAA,UACA,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR;AAAA,QACF;AACA,cAAM,iBAAiB,IAAI,QAAe,CAAC,UAAU,WAAW;AAC9D,kBAAQ,WAAW,MAAM;AACvB,uBAAW,MAAM;AACjB,kBAAM,MAAM,IAAI;AAAA,cACd,GAAG,MAAM,IAAI,oBAAoB,oBAAoB;AAAA,YACvD;AACA,gBAAI,OAAO;AACX,mBAAO,GAAG;AAAA,UACZ,GAAG,oBAAoB;AAAA,QACzB,CAAC;AAED,cAAM,YAAiC,IAAI,IAAI,MAAM,KAAK,CAAC;AAC3D,cAAM,aAAa,uBAAuB,QAAQ,MAAM,IAAI;AAE5D,YAAI;AACJ,mBAAW,CAAC,EAAE,EAAE,MAAM,CAAC,KAAK,MAAM,QAAQ,GAAG;AAC3C,qBAAW,EAAE,iBAAiB,KAAK,OAAO;AACxC,gBAAI,qBAAqB,QAAW;AAClC;AAAA,YACF;AACA,gBAAI,gBAAgB,UAAa,mBAAmB,aAAa;AAC/D,4BAAc;AAAA,YAChB;AAAA,UACF;AAAA,QACF;AACA,cAAM,iBAAiB,0BACnB,MAAM,QAAQ,sBAAuB,MAAM,IAAI,IAC/C;AACJ,cAAM,OAAO,SAAS;AAAA,UACpB,YAAY,gBAAgB,aACxB,IAAI,KAAK,eAAe,UAAU,IAClC;AAAA,UACJ,gBAAgB,gBAAgB,iBAC5B,IAAI,KAAK,eAAe,cAAc,IACtC;AAAA,UACJ;AAAA,UACA,KAAK;AAAA,QACP,CAAC;AACD,cAAM,gBACJ,gBAAgB,SACZ,IAAI,KAAK,MAAM,cAAc,kBAAkB,EAAE,YAAY,IAC7D;AACN,cAAM,OAAO,KAAK;AAClB,cAAM,QAAQ,SAAS,SAAS,gBAAgB,KAAK,QAAQ;AAE7D,qBAAa,KAAK,gBAAgB;AAAA,UAChC,WAAW,MAAM;AAAA,UACjB,WAAW,MAAM,KAAK,SAAS;AAAA,UAC/B;AAAA,UACA;AAAA,QACF,CAAC;AAED,YAAI,SAAkB;AACtB,YAAI,SAAS;AACb,eAAO,MAAM;AACX,oBAAU;AACV,cAAI,SAAS,sBAAsB;AACjC,uBAAW,MAAM;AACjB,kBAAM,IAAI;AAAA,cACR,GAAG,MAAM,IAAI,aAAa,oBAAoB;AAAA,YAChD;AAAA,UACF;AACA,gBAAM,cAAc,UAAU;AAAA,YAC5B,EAAE,MAAM,OAAO,QAAQ,WAAW,WAAW;AAAA,YAC7C;AAAA,YACA,WAAW;AAAA,UACb;AACA,gBAAM,SAAS,MAAM,QAAQ,KAAK,CAAC,aAAa,cAAc,CAAC;AAC/D,cAAI,OAAO,MAAM;AACf;AAAA,UACF;AACA,mBAAS,OAAO;AAAA,QAClB;AAEA,YAAI,yBAAyB;AAC3B,gBAAM,QAAQ,2BAA4B,MAAM,MAAM;AAAA,YACpD,aAAa,KAAK;AAAA,UACpB,CAAC;AAAA,QACH;AAAA,MACF,SAAS,KAAK;AACZ,iBAAS;AACT,YAAI,eAAe,SAAS,IAAI,SAAS,cAAc;AACrD,0BAAgB,GAAG,MAAM,IAAI,oBAAoB,oBAAoB;AAAA,QACvE,OAAO;AACL,0BAAgB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,QACjE;AACA,eAAO,KAAK,aAAa;AAAA,MAC3B,UAAE;AACA,YAAI,UAAU,QAAW;AACvB,uBAAa,KAAK;AAAA,QACpB;AACA,qBAAa,KAAK,gBAAgB;AAAA,UAChC,WAAW,MAAM;AAAA,UACjB;AAAA,UACA,aAAa,KAAK,IAAI,IAAI;AAAA,UAC1B,OAAO;AAAA,QACT,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AAAA,EACH;AACA,MAAI,OAAO,SAAS,GAAG;AACrB,UAAM,QAAQ,eAAe,OAAO,KAAK,IAAI,CAAC;AAAA,EAChD,OAAO;AACL,UAAM,QAAQ,kBAAkB;AAAA,EAClC;AACF;;;AF9LA,eAAe,aACb,OACA,aACA,UACA,QACmC;AACnC,MAAI;AACF,WAAO,MAAM,MAAM,IAAI,EAAE,aAAa,UAAU,OAAO,CAAC;AAAA,EAC1D,SAAS,KAAK;AACZ,YAAQ,KAAK,mCAAmC,GAAG;AACnD,WAAO;AAAA,EACT;AACF;AAEA,eAAe,aACb,OACA,aACA,UACA,QACA,OACe;AACf,MAAI;AACF,UAAM,MAAM,IAAI,EAAE,aAAa,UAAU,OAAO,GAAG,KAAK;AAAA,EAC1D,SAAS,KAAK;AACZ,YAAQ,KAAK,mCAAmC,GAAG;AAAA,EACrD;AACF;AAEA,eAAe,iBACb,aACA,UACA,QACA,gBACA,SACA,OACmC;AACnC,MAAI,OAAO;AACT,UAAM,MAAM,MAAM,aAAa,OAAO,aAAa,UAAU,MAAM;AACnE,QAAI,KAAK;AACP,aAAO;AAAA,IACT;AAAA,EACF;AACA,QAAM,QAAQ,MAAM;AAAA,IAClB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,MAAI,SAAS,OAAO;AAClB,UAAM,aAAa,OAAO,aAAa,UAAU,QAAQ,KAAK;AAAA,EAChE;AACA,SAAO;AACT;AAuBO,SAAS,YAA4B;AAC1C,SAAO,EAAE,QAAQ,KAAK;AACxB;AAEA,eAAsB,oBACpB,KACoB;AACpB,QAAM,UAAU,MAAM,IAAI,WAAW;AACrC,SAAO,QAAQ,aAAa;AAC9B;AAUA,eAAsB,YACpB,KACA,OAA2B,CAAC,GACE;AAC9B,QAAM,OAAwB,KAAK,QAAQ;AAC3C,QAAM,UAAU,MAAM,IAAI,WAAW;AACrC,QAAM,QAAQ,MAAM,QAAQ,aAAa;AACzC,MAAI,aAAa,MAAM,MAAM,GAAG;AAC9B,WAAO,EAAE,QAAQ,MAAM;AAAA,EACzB;AACA,MAAI;AACJ,MAAI,SAAS,cAAc;AACzB,QAAI,CAAC,IAAI,WAAW;AAClB,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AACA,aAAS,MAAM,IAAI,UAAU;AAAA,EAC/B;AACA,QAAM,SAAS,MAAM,QAAQ,eAAe;AAC5C,MAAI,CAAC,QAAQ;AACX,WAAO,EAAE,QAAQ,MAAM;AAAA,EACzB;AACA,MAAI,SAAS,YAAY;AACvB,WAAO,EAAE,QAAQ,KAAK;AAAA,EACxB;AACA,QAAM,eAAe;AACrB,OAAK,QAAQ,QAAS,SAAS;AAAA,IAC7B,mBAAmB,aAAa;AAAA,IAChC,iBAAiB,aAAa;AAAA,IAC9B,eAAe,aAAa;AAAA,EAC9B,CAAC,EAAE,MAAM,CAAC,QAAQ;AAChB,YAAQ,MAAM,uBAAuB,GAAG;AAAA,EAC1C,CAAC;AACD,SAAO,EAAE,QAAQ,KAAK;AACxB;AAEA,eAAsB,YACpB,KACA,aACA,OAC8B;AAC9B,QAAM,SAAS,MAAM,IAAI,UAAU;AACnC,QAAM,YAAY,OAAO,WAAW,WAAW;AAC/C,MAAI,CAAC,WAAW;AACd,UAAM,IAAI,aAAa,KAAK,uBAAuB,qBAAqB;AAAA,EAC1E;AACA,QAAM,UAAU,MAAM,IAAI,WAAW;AACrC,QAAM,iBAAiB,OAAO,WAAW,IAAI,CAAC,MAAM,EAAE,IAAI;AAC1D,QAAM,UAAU,OAAO,QAAQ,UAAU,OAAO;AAChD,QAAM,WAAW,MAAM,QAAQ;AAAA,IAC7B,QAAQ;AAAA,MAAI,CAAC,CAAC,KAAK,MAAM,MACvB;AAAA,QACE;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,QAAM,UAAU,SAAS,OAAO,CAAC,MAAyB,MAAM,MAAS;AACzE,SAAO,EAAE,QAAQ;AACnB;AAWA,eAAsB,UACpB,KACA,aACA,UACA,OAAyB,CAAC,GACA;AAC1B,QAAM,EAAE,OAAO,YAAY,IAAI;AAC/B,QAAM,SAAS,MAAM,IAAI,UAAU;AACnC,QAAM,YAAY,OAAO,WAAW,WAAW;AAC/C,MAAI,CAAC,WAAW;AACd,UAAM,IAAI,aAAa,KAAK,uBAAuB,qBAAqB;AAAA,EAC1E;AACA,QAAM,SAAS,UAAU,QAAQ,QAAQ;AACzC,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,aAAa,KAAK,oBAAoB,kBAAkB;AAAA,EACpE;AACA,QAAM,UAAU,MAAM,IAAI,WAAW;AACrC,QAAM,iBAAiB,OAAO,WAAW,IAAI,CAAC,MAAM,EAAE,IAAI;AAC1D,QAAM,eAAe,mBAAmB,MAAM;AAC9C,MAAI,CAAC,aAAa,KAAK,CAAC,OAAO,eAAe,SAAS,EAAE,CAAC,GAAG;AAC3D,UAAM,IAAI,aAAa,KAAK,oBAAoB,kBAAkB;AAAA,EACpE;AAEA,MAAI,aAAa;AACf,UAAM,UAAU,MAAM,QAAQ;AAAA,MAC5B,aAAa,IAAI,CAAC,OAAO,QAAQ,UAAU,EAAE,CAAC;AAAA,IAChD;AACA,UAAM,aAAa,QAAQ,OAAsB,CAAC,QAAQ,WAAW;AACnE,UAAI,CAAC,QAAQ,YAAY;AACvB,eAAO;AAAA,MACT;AACA,UAAI,WAAW,QAAQ,OAAO,aAAa,QAAQ;AACjD,eAAO,OAAO;AAAA,MAChB;AACA,aAAO;AAAA,IACT,GAAG,IAAI;AACP,QAAI,YAAY;AACd,YAAM,YAAY,kBAAkB,YAAY,MAAM;AACtD,UAAI,cAAc,aAAa;AAC7B,eAAO,EAAE,QAAQ,gBAAgB,MAAM,UAAU;AAAA,MACnD;AAAA,IACF;AAAA,EACF;AAEA,QAAM,SAAS,MAAM;AAAA,IACnB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,aAAa,KAAK,oBAAoB,kBAAkB;AAAA,EACpE;AACA,QAAM,OAAO,OAAO,WAChB,kBAAkB,OAAO,UAAU,MAAM,IACzC;AACJ,SAAO,EAAE,QAAQ,MAAM,MAAM,QAAQ,OAAO;AAC9C;AAEA,eAAsB,iBAAiB,KAAmC;AACxE,QAAM,SAAS,MAAM,IAAI,UAAU;AACnC,QAAM,UAAU,MAAM,IAAI,WAAW;AACrC,QAAM,aAAa,QAAQ,OAAO;AACpC;;;AGxPA;AAAA,EACE;AAAA,EACA,gBAAAA;AAAA,EACA,iBAAAC;AAAA,EACA;AAAA,OACK;AAsBA,SAAS,aACd,QACA,UAAyB,CAAC,GAClB;AACR,QAAM,UAAyB,QAAQ,WAAW,IAAI,gBAAgB;AACtE,QAAM,iBAAiB,OAAO,WAAW,IAAI,CAAC,MAAM,EAAE,IAAI;AAC1D,QAAM,0BAA8D,MAAM;AACxE,QAAI,CAAC,QAAQ,mBAAmB;AAC9B,aAAO;AAAA,IACT;AACA,UAAM,WAAW;AAAA,MACf,QAAQ;AAAA,IACV;AACA,WAAO,OAAO;AAAA,MACZ,OAAO,WAAW,QAAQ,CAAC,EAAE,MAAM,YAAY,MAAM;AACnD,cAAM,OAAO,SAAS,WAAW;AACjC,eAAO,OAAQ,CAAC,CAAC,MAAM,IAAI,CAAC,IAAc,CAAC;AAAA,MAC7C,CAAC;AAAA,IACH;AAAA,EACF,GAAG;AAEH,SAAO;AAAA,IACL,MAAM,UAAU,aAAa,UAAU;AACrC,YAAM,YAAY,OAAO,WAAW,WAAW;AAC/C,UAAI,CAAC,WAAW;AACd,eAAO;AAAA,MACT;AACA,YAAM,SAAS,UAAU,QAAQ,QAAQ;AACzC,UAAI,CAAC,QAAQ;AACX,eAAO;AAAA,MACT;AACA,aAAOC;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,IAEA,MAAM,WAAW,aAAa;AAC5B,YAAM,YAAY,OAAO,WAAW,WAAW;AAC/C,UAAI,CAAC,WAAW;AACd,eAAO,CAAC;AAAA,MACV;AACA,YAAM,UAAU,OAAO,QAAQ,UAAU,OAAO;AAChD,YAAM,WAAW,MAAM,QAAQ;AAAA,QAC7B,QAAQ;AAAA,UAAI,CAAC,CAAC,KAAK,MAAM,MACvBA;AAAA,YACE;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAAA,MACF;AACA,aAAO,SAAS,OAAO,CAAC,MAAyB,MAAM,MAAS;AAAA,IAClE;AAAA,IAEA,MAAM,YAAY;AAChB,aAAO,EAAE,QAAQ,KAAK;AAAA,IACxB;AAAA,IAEA,MAAM,eAAe;AACnB,aAAO,QAAQ,aAAa;AAAA,IAC9B;AAAA,IAEA,MAAM,cAAc;AAClB,UAAI,CAAC,QAAQ,mBAAmB;AAC9B,cAAM,IAAI;AAAA,UACR;AAAA,QACF;AAAA,MACF;AACA,YAAM,QAAQ,MAAM,QAAQ,aAAa;AACzC,UAAIC,cAAa,MAAM,MAAM,GAAG;AAC9B,eAAO,EAAE,QAAQ,MAAM;AAAA,MACzB;AACA,YAAM,SAAS,MAAM,QAAQ,eAAe;AAC5C,UAAI,CAAC,QAAQ;AACX,eAAO,EAAE,QAAQ,MAAM;AAAA,MACzB;AACA,WAAK,QAAQ,QAAQ,SAAS;AAAA,QAC5B,mBAAmB,QAAQ;AAAA,QAC3B,iBAAiB,QAAQ;AAAA,QACzB,eAAe,QAAQ;AAAA,MACzB,CAAC,EAAE,MAAM,CAAC,UAAU;AAClB,gBAAQ,MAAM,uBAAuB,KAAK;AAAA,MAC5C,CAAC;AACD,aAAO,EAAE,QAAQ,KAAK;AAAA,IACxB;AAAA,EACF;AACF;;;ACpIA,SAAS,eAAe,+BAA+B;;;ACAvD,SAAS,mBAAAC,wBAAuB;;;ACgDhC,SAAS,gBAAAC,eAAc,4BAA4B;AACnD,SAAS,wBAAAC,6BAA4B;","names":["isSyncActive","resolveWidget","resolveWidget","isSyncActive","InMemoryStorage","isSyncActive","instantiateConnector"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rawdash/server",
3
- "version": "0.29.0",
3
+ "version": "0.29.2",
4
4
  "description": "Framework-agnostic rawdash request handlers, engine, and wire contract. Wrap with @rawdash/hono (or another adapter) to serve over HTTP.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -22,7 +22,7 @@
22
22
  }
23
23
  },
24
24
  "dependencies": {
25
- "@rawdash/core": "0.29.0"
25
+ "@rawdash/core": "0.29.2"
26
26
  },
27
27
  "devDependencies": {
28
28
  "tsup": "^8.0.0",