@rawdash/hono 0.15.0 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -154,7 +154,7 @@ In deferred mode:
154
154
  - `runSync` is **never** invoked by the trigger handler.
155
155
  - `getConfig` is optional and never called.
156
156
  - `markSyncQueued` is called exactly as in in-process mode; its return value drives the `{queued: true|false}` response.
157
- - Your external worker is responsible for calling `markSyncRunning`, `markSyncSucceeded`, and `markSyncFailed` on the same storage.
157
+ - Your external worker is responsible for calling `markSyncSucceeded` and `markSyncFailed` on the same storage. `markSyncRunning` is optional on `ServerStorage` and may be omitted by deferred-mode storages — the running transition is driven by the external runner's own aggregation, not the trigger handler.
158
158
 
159
159
  ## Running on Node
160
160
 
@@ -183,7 +183,7 @@ Handler errors translate to JSON:
183
183
 
184
184
  - [rawdash docs](https://rawdash.dev)
185
185
  - [`@rawdash/server`](https://www.npmjs.com/package/@rawdash/server) — pure handlers + engine (the package this wraps)
186
- - [`@rawdash/client`](https://www.npmjs.com/package/@rawdash/client) — typed HTTP client (speaks the same wire contract)
186
+ - [`@rawdash/sdk-client`](https://www.npmjs.com/package/@rawdash/sdk-client) — typed HTTP client (speaks the same wire contract)
187
187
  - [GitHub](https://github.com/rawdash/rawdash)
188
188
  - [Issues](https://github.com/rawdash/rawdash/issues)
189
189
 
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { DashboardConfig, ServerStorage, WidgetCache, ConnectorRegistry as ConnectorRegistry$1, SecretsResolver as SecretsResolver$1 } from '@rawdash/server';
1
+ import { DashboardConfig, ServerStorage, ConnectorLoggerFactory, WidgetCache, ConnectorRegistry as ConnectorRegistry$1, SecretsResolver as SecretsResolver$1 } from '@rawdash/server';
2
2
  import { Context, MiddlewareHandler, Hono } from 'hono';
3
3
  import { ConnectorRegistry, SecretsResolver } from '@rawdash/core';
4
4
 
@@ -48,6 +48,7 @@ type SyncRouterOptions = (HonoRouterOptions & {
48
48
  mode?: 'in-process';
49
49
  connectorRegistry: ConnectorRegistry;
50
50
  secretsResolver?: SecretsResolver;
51
+ loggerFactory?: ConnectorLoggerFactory;
51
52
  }) | {
52
53
  mode: 'deferred';
53
54
  getStorage: HonoRouterOptions['getStorage'];
@@ -123,6 +124,13 @@ interface MountEngineOptions {
123
124
  * instantiation.
124
125
  */
125
126
  secretsResolver?: SecretsResolver$1;
127
+ /**
128
+ * Build a connector logger for the runner and each connector instance.
129
+ * Called with `'runner'` for the sync-runner envelopes and with each
130
+ * connector instance name for per-connector progress logs. Defaults to
131
+ * a structured stdout logger.
132
+ */
133
+ loggerFactory?: ConnectorLoggerFactory;
126
134
  /** Set false to skip the background retention timer (e.g. on serverless). */
127
135
  startRetention?: boolean;
128
136
  }
package/dist/index.js CHANGED
@@ -60,7 +60,8 @@ function createSyncRouter(opts) {
60
60
  getStorage: () => opts.getStorage(c),
61
61
  getConfig: () => opts.getConfig(c),
62
62
  connectorRegistry: opts.connectorRegistry,
63
- secretsResolver: opts.secretsResolver
63
+ secretsResolver: opts.secretsResolver,
64
+ loggerFactory: opts.loggerFactory
64
65
  })
65
66
  );
66
67
  } catch (err) {
@@ -110,14 +111,23 @@ function createWidgetsRouter(opts) {
110
111
  });
111
112
  app.get("/:dashboardId/widgets/:widgetId", async (c) => {
112
113
  try {
113
- return c.json(
114
- await getWidget(
115
- makeEngineContext(c, opts),
116
- c.req.param("dashboardId"),
117
- c.req.param("widgetId"),
118
- opts.cache?.(c)
119
- )
114
+ const result = await getWidget(
115
+ makeEngineContext(c, opts),
116
+ c.req.param("dashboardId"),
117
+ c.req.param("widgetId"),
118
+ {
119
+ cache: opts.cache?.(c),
120
+ ifNoneMatch: c.req.header("if-none-match")
121
+ }
120
122
  );
123
+ if (result.status === "not-modified") {
124
+ c.header("ETag", result.etag);
125
+ return c.body(null, 304);
126
+ }
127
+ if (result.etag) {
128
+ c.header("ETag", result.etag);
129
+ }
130
+ return c.json(result.widget);
121
131
  } catch (err) {
122
132
  return mapError(c, err);
123
133
  }
@@ -212,7 +222,7 @@ import { InMemoryStorage, ROUTES } from "@rawdash/server";
212
222
  import { Hono as Hono5 } from "hono";
213
223
  function mountEngine(config, options) {
214
224
  const storage = options.storage ?? new InMemoryStorage();
215
- const { connectorRegistry, secretsResolver } = options;
225
+ const { connectorRegistry, secretsResolver, loggerFactory } = options;
216
226
  const getConfig = () => config;
217
227
  const getStorage = () => storage;
218
228
  const app = new Hono5();
@@ -223,7 +233,8 @@ function mountEngine(config, options) {
223
233
  getConfig,
224
234
  getStorage,
225
235
  connectorRegistry,
226
- secretsResolver
236
+ secretsResolver,
237
+ loggerFactory
227
238
  })
228
239
  );
229
240
  app.route(ROUTES.syncState, createSyncStateRouter({ getStorage }));
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/health.ts","../src/sync.ts","../src/shared.ts","../src/widgets.ts","../src/retention.ts","../src/mount.ts"],"sourcesContent":["import { getHealth } from '@rawdash/server';\nimport { Hono } from 'hono';\n\n/**\n * Liveness probe — returns `{status:'ok'}` synchronously, no storage\n * access. Mount at `/health` (or wherever your platform's probe expects).\n */\nexport function createHealthRouter(): Hono {\n const app = new Hono();\n app.get('/', (c) => c.json(getHealth()));\n return app;\n}\n","import type { ConnectorRegistry, SecretsResolver } from '@rawdash/core';\nimport { getSyncStateHandler, triggerSync } from '@rawdash/server';\nimport type { MiddlewareHandler } from 'hono';\nimport { Hono } from 'hono';\n\nimport type { HonoRouterOptions, HonoStorageRouterOptions } from './shared';\nimport { applyBefore, mapError } from './shared';\n\n/**\n * Options for `createSyncRouter`.\n *\n * `mode` defaults to `'in-process'`: the trigger handler kicks off\n * `runSync` in the background, iterating `config.connectors` and\n * instantiating each via `connectorRegistry`. In this mode both\n * `getConfig` and `connectorRegistry` are required.\n *\n * In `mode: 'deferred'`, the trigger handler only records the `queued`\n * transition; an external runner is responsible for `running →\n * succeeded/failed`. `getConfig` and `connectorRegistry` can be omitted\n * in this mode — useful when the deployment cannot materialize connector\n * implementations at request time (e.g. cloud, where the actual\n * `connector.sync(...)` call happens in a queue consumer worker).\n */\nexport type SyncRouterOptions =\n | (HonoRouterOptions & {\n mode?: 'in-process';\n connectorRegistry: ConnectorRegistry;\n secretsResolver?: SecretsResolver;\n })\n | {\n mode: 'deferred';\n getStorage: HonoRouterOptions['getStorage'];\n getConfig?: HonoRouterOptions['getConfig'];\n before?: MiddlewareHandler[];\n };\n\n/**\n * `POST /` — triggers a sync, returning immediately with\n * `{queued: true|false}`. In `mode: 'in-process'` (default) the sync\n * runs in the background; in `mode: 'deferred'` the handler only\n * persists the `queued` transition and the external runner takes it\n * from there.\n *\n * Mount at `/sync`.\n */\nexport function createSyncRouter(opts: SyncRouterOptions): Hono {\n const app = new Hono();\n applyBefore(app, opts.before);\n app.post('/', async (c) => {\n try {\n if (opts.mode === 'deferred') {\n const getConfig = opts.getConfig;\n return c.json(\n await triggerSync(\n {\n getStorage: () => opts.getStorage(c),\n getConfig: getConfig ? () => getConfig(c) : undefined,\n },\n { mode: 'deferred' },\n ),\n );\n }\n return c.json(\n await triggerSync({\n getStorage: () => opts.getStorage(c),\n getConfig: () => opts.getConfig(c),\n connectorRegistry: opts.connectorRegistry,\n secretsResolver: opts.secretsResolver,\n }),\n );\n } catch (err) {\n return mapError(c, err);\n }\n });\n return app;\n}\n\n/**\n * `GET /` — returns the current `SyncState`. Mount at `/sync/state`.\n */\nexport function createSyncStateRouter(opts: HonoStorageRouterOptions): Hono {\n const app = new Hono();\n applyBefore(app, opts.before);\n app.get('/', async (c) => {\n try {\n return c.json(\n await getSyncStateHandler({\n getConfig: () => {\n throw new Error('getConfig should not be called by sync-state');\n },\n getStorage: () => opts.getStorage(c),\n }),\n );\n } catch (err) {\n return mapError(c, err);\n }\n });\n return app;\n}\n","import type { EngineContext } from '@rawdash/server';\nimport type { DashboardConfig, ServerStorage } from '@rawdash/server';\nimport { isRawdashError } from '@rawdash/server';\nimport type { Context, MiddlewareHandler } from 'hono';\nimport { Hono } from 'hono';\n\n/**\n * Common options accepted by every `@rawdash/hono` router factory.\n *\n * `getConfig` / `getStorage` are invoked per-request with the Hono\n * `Context`, so adapters can derive the config or storage from request\n * state (e.g. a path parameter, an id attached by an auth middleware, or\n * environment bindings).\n *\n * `before` middleware runs before any handler — typically auth/scope\n * checks.\n */\nexport interface HonoRouterOptions {\n getConfig: (c: Context) => DashboardConfig | Promise<DashboardConfig>;\n getStorage: (c: Context) => ServerStorage | Promise<ServerStorage>;\n before?: MiddlewareHandler[];\n}\n\nexport interface HonoStorageRouterOptions {\n getStorage: (c: Context) => ServerStorage | Promise<ServerStorage>;\n before?: MiddlewareHandler[];\n}\n\nexport function makeEngineContext(\n c: Context,\n opts: HonoRouterOptions,\n): EngineContext {\n return {\n getConfig: () => opts.getConfig(c),\n getStorage: () => opts.getStorage(c),\n };\n}\n\nexport function applyBefore(app: Hono, before?: MiddlewareHandler[]): void {\n if (!before) {\n return;\n }\n for (const mw of before) {\n app.use('*', mw);\n }\n}\n\n/**\n * Translate a thrown error into a Hono JSON response. `RawdashError`\n * becomes a structured `{error, code}` body at the carried status; any\n * other error is re-thrown for Hono's own error handling.\n */\nexport function mapError(c: Context, err: unknown): Response {\n if (isRawdashError(err)) {\n return c.json(\n { error: err.message, code: err.code },\n err.status as Parameters<typeof c.json>[1],\n );\n }\n throw err;\n}\n","import type { WidgetCache } from '@rawdash/server';\nimport { getWidget, listWidgets } from '@rawdash/server';\nimport type { Context } from 'hono';\nimport { Hono } from 'hono';\n\nimport type { HonoRouterOptions } from './shared';\nimport { applyBefore, makeEngineContext, mapError } from './shared';\n\nexport interface HonoWidgetsRouterOptions extends HonoRouterOptions {\n /**\n * Optional per-request factory returning a `WidgetCache`. Invoked once\n * per request so the cache can be scoped to the request's tenant/auth\n * context. When omitted, widgets are resolved fresh on every request.\n */\n cache?: (c: Context) => WidgetCache;\n}\n\n/**\n * - `GET /:dashboardId/widgets` → `WidgetsListResponse`\n * - `GET /:dashboardId/widgets/:widgetId` → `CachedWidget`\n *\n * Mount at `/dashboards`.\n */\nexport function createWidgetsRouter(opts: HonoWidgetsRouterOptions): Hono {\n const app = new Hono();\n applyBefore(app, opts.before);\n\n app.get('/:dashboardId/widgets', async (c) => {\n try {\n return c.json(\n await listWidgets(\n makeEngineContext(c, opts),\n c.req.param('dashboardId'),\n opts.cache?.(c),\n ),\n );\n } catch (err) {\n return mapError(c, err);\n }\n });\n\n app.get('/:dashboardId/widgets/:widgetId', async (c) => {\n try {\n return c.json(\n await getWidget(\n makeEngineContext(c, opts),\n c.req.param('dashboardId'),\n c.req.param('widgetId'),\n opts.cache?.(c),\n ),\n );\n } catch (err) {\n return mapError(c, err);\n }\n });\n\n return app;\n}\n","import type { DashboardConfig, ServerStorage } from '@rawdash/server';\nimport {\n DEFAULT_RETENTION_INTERVAL_MS,\n hasPruningPolicy,\n runRetention,\n runRetentionOnce,\n} from '@rawdash/server';\nimport { Hono } from 'hono';\n\nimport type { HonoRouterOptions } from './shared';\nimport { applyBefore, makeEngineContext, mapError } from './shared';\n\n/**\n * `POST /retain` — runs the retention policy once. Coalesces concurrent\n * calls so multiple requests during an in-flight run share the same\n * promise.\n *\n * Mount at `/retention`.\n */\nexport function createRetentionRouter(opts: HonoRouterOptions): Hono {\n const app = new Hono();\n applyBefore(app, opts.before);\n\n let inFlight: Promise<void> | null = null;\n\n app.post('/retain', async (c) => {\n try {\n if (!inFlight) {\n const ctx = makeEngineContext(c, opts);\n inFlight = runRetentionOnce(ctx).finally(() => {\n inFlight = null;\n });\n }\n await inFlight;\n return c.json({ triggered: true });\n } catch (err) {\n console.error('retention run failed', err);\n return mapError(c, err);\n }\n });\n\n return app;\n}\n\nexport interface RetentionLoopOptions {\n getConfig: () => DashboardConfig | Promise<DashboardConfig>;\n getStorage: () => ServerStorage | Promise<ServerStorage>;\n intervalMs?: number;\n}\n\n/**\n * Start a background loop that periodically runs the retention policy.\n * Returns a `stop()` function that clears the interval.\n *\n * Only useful on long-lived runtimes (Node, Bun, Deno). In serverless\n * runtimes (Workers, Lambda) use the platform's native scheduler\n * (Cron Triggers, CloudWatch Events) to call `POST /retention/retain`.\n */\nexport function startRetentionLoop(opts: RetentionLoopOptions): () => void {\n let stopped = false;\n let inFlight: Promise<void> | null = null;\n let timer: ReturnType<typeof setInterval> | null = null;\n\n const tick = async (): Promise<void> => {\n if (inFlight || stopped) {\n return;\n }\n try {\n const config = await opts.getConfig();\n if (!config.retention || !hasPruningPolicy(config.retention)) {\n return;\n }\n const storage = await opts.getStorage();\n inFlight = runRetention(config, storage).finally(() => {\n inFlight = null;\n });\n await inFlight;\n } catch (err) {\n console.error('retention run failed', err);\n }\n };\n\n void (async () => {\n try {\n const config = await opts.getConfig();\n if (!config.retention || !hasPruningPolicy(config.retention)) {\n return;\n }\n // Re-check `stopped` after the async getConfig in case stop()\n // was called while we were awaiting it.\n if (stopped) {\n return;\n }\n const intervalMs =\n opts.intervalMs ??\n config.retention.intervalMs ??\n DEFAULT_RETENTION_INTERVAL_MS;\n const created = setInterval(() => {\n void tick();\n }, intervalMs);\n // Race with stop(): if stop() ran between the check above and\n // setInterval, clear it immediately rather than leaving a\n // lingering timer behind.\n if (stopped) {\n clearInterval(created);\n } else {\n timer = created;\n }\n } catch (err) {\n console.error('retention loop startup failed', err);\n }\n })();\n\n return () => {\n stopped = true;\n if (timer !== null) {\n clearInterval(timer);\n timer = null;\n }\n };\n}\n","import type {\n ConnectorRegistry,\n DashboardConfig,\n SecretsResolver,\n ServerStorage,\n} from '@rawdash/server';\nimport { InMemoryStorage, ROUTES } from '@rawdash/server';\nimport { Hono } from 'hono';\n\nimport { createHealthRouter } from './health';\nimport { createRetentionRouter, startRetentionLoop } from './retention';\nimport { createSyncRouter, createSyncStateRouter } from './sync';\nimport { createWidgetsRouter } from './widgets';\n\nexport interface MountEngineOptions {\n storage?: ServerStorage;\n /**\n * Registry mapping connector type id (e.g. `'github-actions'`) to the\n * connector class. Used to instantiate connector implementations on\n * demand from the declarative entries in `DashboardConfig.connectors`.\n * Required for sync and retention to function.\n */\n connectorRegistry: ConnectorRegistry;\n /**\n * Resolves `secret('NAME')` markers in connector configs. Defaults to\n * `EnvSecretsResolver` (process.env lookup) inside connector\n * instantiation.\n */\n secretsResolver?: SecretsResolver;\n /** Set false to skip the background retention timer (e.g. on serverless). */\n startRetention?: boolean;\n}\n\nexport interface MountEngineResult {\n app: Hono;\n stop(): void;\n}\n\n/**\n * Convenience wrapper for the common case: builds a Hono app with all\n * standard rawdash routes mounted at their canonical paths, backed by\n * one `DashboardConfig` and one `ServerStorage` (defaults to\n * `InMemoryStorage`).\n *\n * For deployments that need auth or that look up config / storage per\n * request, skip this and compose the router factories directly with\n * per-request `getConfig` / `getStorage` and `before` middleware.\n */\nexport function mountEngine(\n config: DashboardConfig,\n options: MountEngineOptions,\n): MountEngineResult {\n const storage: ServerStorage = options.storage ?? new InMemoryStorage();\n const { connectorRegistry, secretsResolver } = options;\n const getConfig = (): DashboardConfig => config;\n const getStorage = (): ServerStorage => storage;\n\n const app = new Hono();\n app.route('/dashboards', createWidgetsRouter({ getConfig, getStorage }));\n app.route(\n ROUTES.sync,\n createSyncRouter({\n getConfig,\n getStorage,\n connectorRegistry,\n secretsResolver,\n }),\n );\n app.route(ROUTES.syncState, createSyncStateRouter({ getStorage }));\n app.route('/retention', createRetentionRouter({ getConfig, getStorage }));\n app.route(ROUTES.health, createHealthRouter());\n\n let stopRetention: (() => void) | null = null;\n if (options.startRetention !== false) {\n stopRetention = startRetentionLoop({ getConfig, getStorage });\n }\n\n return {\n app,\n stop() {\n if (stopRetention) {\n stopRetention();\n }\n },\n };\n}\n"],"mappings":"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","names":["Hono","Hono","Hono","Hono","Hono","Hono","Hono","Hono"]}
1
+ {"version":3,"sources":["../src/health.ts","../src/sync.ts","../src/shared.ts","../src/widgets.ts","../src/retention.ts","../src/mount.ts"],"sourcesContent":["import { getHealth } from '@rawdash/server';\nimport { Hono } from 'hono';\n\n/**\n * Liveness probe — returns `{status:'ok'}` synchronously, no storage\n * access. Mount at `/health` (or wherever your platform's probe expects).\n */\nexport function createHealthRouter(): Hono {\n const app = new Hono();\n app.get('/', (c) => c.json(getHealth()));\n return app;\n}\n","import type { ConnectorRegistry, SecretsResolver } from '@rawdash/core';\nimport type { ConnectorLoggerFactory } from '@rawdash/server';\nimport { getSyncStateHandler, triggerSync } from '@rawdash/server';\nimport type { MiddlewareHandler } from 'hono';\nimport { Hono } from 'hono';\n\nimport type { HonoRouterOptions, HonoStorageRouterOptions } from './shared';\nimport { applyBefore, mapError } from './shared';\n\n/**\n * Options for `createSyncRouter`.\n *\n * `mode` defaults to `'in-process'`: the trigger handler kicks off\n * `runSync` in the background, iterating `config.connectors` and\n * instantiating each via `connectorRegistry`. In this mode both\n * `getConfig` and `connectorRegistry` are required.\n *\n * In `mode: 'deferred'`, the trigger handler only records the `queued`\n * transition; an external runner is responsible for `running →\n * succeeded/failed`. `getConfig` and `connectorRegistry` can be omitted\n * in this mode — useful when the deployment cannot materialize connector\n * implementations at request time (e.g. cloud, where the actual\n * `connector.sync(...)` call happens in a queue consumer worker).\n */\nexport type SyncRouterOptions =\n | (HonoRouterOptions & {\n mode?: 'in-process';\n connectorRegistry: ConnectorRegistry;\n secretsResolver?: SecretsResolver;\n loggerFactory?: ConnectorLoggerFactory;\n })\n | {\n mode: 'deferred';\n getStorage: HonoRouterOptions['getStorage'];\n getConfig?: HonoRouterOptions['getConfig'];\n before?: MiddlewareHandler[];\n };\n\n/**\n * `POST /` — triggers a sync, returning immediately with\n * `{queued: true|false}`. In `mode: 'in-process'` (default) the sync\n * runs in the background; in `mode: 'deferred'` the handler only\n * persists the `queued` transition and the external runner takes it\n * from there.\n *\n * Mount at `/sync`.\n */\nexport function createSyncRouter(opts: SyncRouterOptions): Hono {\n const app = new Hono();\n applyBefore(app, opts.before);\n app.post('/', async (c) => {\n try {\n if (opts.mode === 'deferred') {\n const getConfig = opts.getConfig;\n return c.json(\n await triggerSync(\n {\n getStorage: () => opts.getStorage(c),\n getConfig: getConfig ? () => getConfig(c) : undefined,\n },\n { mode: 'deferred' },\n ),\n );\n }\n return c.json(\n await triggerSync({\n getStorage: () => opts.getStorage(c),\n getConfig: () => opts.getConfig(c),\n connectorRegistry: opts.connectorRegistry,\n secretsResolver: opts.secretsResolver,\n loggerFactory: opts.loggerFactory,\n }),\n );\n } catch (err) {\n return mapError(c, err);\n }\n });\n return app;\n}\n\n/**\n * `GET /` — returns the current `SyncState`. Mount at `/sync/state`.\n */\nexport function createSyncStateRouter(opts: HonoStorageRouterOptions): Hono {\n const app = new Hono();\n applyBefore(app, opts.before);\n app.get('/', async (c) => {\n try {\n return c.json(\n await getSyncStateHandler({\n getConfig: () => {\n throw new Error('getConfig should not be called by sync-state');\n },\n getStorage: () => opts.getStorage(c),\n }),\n );\n } catch (err) {\n return mapError(c, err);\n }\n });\n return app;\n}\n","import type { EngineContext } from '@rawdash/server';\nimport type { DashboardConfig, ServerStorage } from '@rawdash/server';\nimport { isRawdashError } from '@rawdash/server';\nimport type { Context, MiddlewareHandler } from 'hono';\nimport { Hono } from 'hono';\n\n/**\n * Common options accepted by every `@rawdash/hono` router factory.\n *\n * `getConfig` / `getStorage` are invoked per-request with the Hono\n * `Context`, so adapters can derive the config or storage from request\n * state (e.g. a path parameter, an id attached by an auth middleware, or\n * environment bindings).\n *\n * `before` middleware runs before any handler — typically auth/scope\n * checks.\n */\nexport interface HonoRouterOptions {\n getConfig: (c: Context) => DashboardConfig | Promise<DashboardConfig>;\n getStorage: (c: Context) => ServerStorage | Promise<ServerStorage>;\n before?: MiddlewareHandler[];\n}\n\nexport interface HonoStorageRouterOptions {\n getStorage: (c: Context) => ServerStorage | Promise<ServerStorage>;\n before?: MiddlewareHandler[];\n}\n\nexport function makeEngineContext(\n c: Context,\n opts: HonoRouterOptions,\n): EngineContext {\n return {\n getConfig: () => opts.getConfig(c),\n getStorage: () => opts.getStorage(c),\n };\n}\n\nexport function applyBefore(app: Hono, before?: MiddlewareHandler[]): void {\n if (!before) {\n return;\n }\n for (const mw of before) {\n app.use('*', mw);\n }\n}\n\n/**\n * Translate a thrown error into a Hono JSON response. `RawdashError`\n * becomes a structured `{error, code}` body at the carried status; any\n * other error is re-thrown for Hono's own error handling.\n */\nexport function mapError(c: Context, err: unknown): Response {\n if (isRawdashError(err)) {\n return c.json(\n { error: err.message, code: err.code },\n err.status as Parameters<typeof c.json>[1],\n );\n }\n throw err;\n}\n","import type { WidgetCache } from '@rawdash/server';\nimport { getWidget, listWidgets } from '@rawdash/server';\nimport type { Context } from 'hono';\nimport { Hono } from 'hono';\n\nimport type { HonoRouterOptions } from './shared';\nimport { applyBefore, makeEngineContext, mapError } from './shared';\n\nexport interface HonoWidgetsRouterOptions extends HonoRouterOptions {\n /**\n * Optional per-request factory returning a `WidgetCache`. Invoked once\n * per request so the cache can be scoped to the request's tenant/auth\n * context. When omitted, widgets are resolved fresh on every request.\n */\n cache?: (c: Context) => WidgetCache;\n}\n\n/**\n * - `GET /:dashboardId/widgets` → `WidgetsListResponse`\n * - `GET /:dashboardId/widgets/:widgetId` → `CachedWidget`\n *\n * Mount at `/dashboards`.\n */\nexport function createWidgetsRouter(opts: HonoWidgetsRouterOptions): Hono {\n const app = new Hono();\n applyBefore(app, opts.before);\n\n app.get('/:dashboardId/widgets', async (c) => {\n try {\n return c.json(\n await listWidgets(\n makeEngineContext(c, opts),\n c.req.param('dashboardId'),\n opts.cache?.(c),\n ),\n );\n } catch (err) {\n return mapError(c, err);\n }\n });\n\n app.get('/:dashboardId/widgets/:widgetId', async (c) => {\n try {\n const result = await getWidget(\n makeEngineContext(c, opts),\n c.req.param('dashboardId'),\n c.req.param('widgetId'),\n {\n cache: opts.cache?.(c),\n ifNoneMatch: c.req.header('if-none-match'),\n },\n );\n if (result.status === 'not-modified') {\n c.header('ETag', result.etag);\n return c.body(null, 304);\n }\n if (result.etag) {\n c.header('ETag', result.etag);\n }\n return c.json(result.widget);\n } catch (err) {\n return mapError(c, err);\n }\n });\n\n return app;\n}\n","import type { DashboardConfig, ServerStorage } from '@rawdash/server';\nimport {\n DEFAULT_RETENTION_INTERVAL_MS,\n hasPruningPolicy,\n runRetention,\n runRetentionOnce,\n} from '@rawdash/server';\nimport { Hono } from 'hono';\n\nimport type { HonoRouterOptions } from './shared';\nimport { applyBefore, makeEngineContext, mapError } from './shared';\n\n/**\n * `POST /retain` — runs the retention policy once. Coalesces concurrent\n * calls so multiple requests during an in-flight run share the same\n * promise.\n *\n * Mount at `/retention`.\n */\nexport function createRetentionRouter(opts: HonoRouterOptions): Hono {\n const app = new Hono();\n applyBefore(app, opts.before);\n\n let inFlight: Promise<void> | null = null;\n\n app.post('/retain', async (c) => {\n try {\n if (!inFlight) {\n const ctx = makeEngineContext(c, opts);\n inFlight = runRetentionOnce(ctx).finally(() => {\n inFlight = null;\n });\n }\n await inFlight;\n return c.json({ triggered: true });\n } catch (err) {\n console.error('retention run failed', err);\n return mapError(c, err);\n }\n });\n\n return app;\n}\n\nexport interface RetentionLoopOptions {\n getConfig: () => DashboardConfig | Promise<DashboardConfig>;\n getStorage: () => ServerStorage | Promise<ServerStorage>;\n intervalMs?: number;\n}\n\n/**\n * Start a background loop that periodically runs the retention policy.\n * Returns a `stop()` function that clears the interval.\n *\n * Only useful on long-lived runtimes (Node, Bun, Deno). In serverless\n * runtimes (Workers, Lambda) use the platform's native scheduler\n * (Cron Triggers, CloudWatch Events) to call `POST /retention/retain`.\n */\nexport function startRetentionLoop(opts: RetentionLoopOptions): () => void {\n let stopped = false;\n let inFlight: Promise<void> | null = null;\n let timer: ReturnType<typeof setInterval> | null = null;\n\n const tick = async (): Promise<void> => {\n if (inFlight || stopped) {\n return;\n }\n try {\n const config = await opts.getConfig();\n if (!config.retention || !hasPruningPolicy(config.retention)) {\n return;\n }\n const storage = await opts.getStorage();\n inFlight = runRetention(config, storage).finally(() => {\n inFlight = null;\n });\n await inFlight;\n } catch (err) {\n console.error('retention run failed', err);\n }\n };\n\n void (async () => {\n try {\n const config = await opts.getConfig();\n if (!config.retention || !hasPruningPolicy(config.retention)) {\n return;\n }\n // Re-check `stopped` after the async getConfig in case stop()\n // was called while we were awaiting it.\n if (stopped) {\n return;\n }\n const intervalMs =\n opts.intervalMs ??\n config.retention.intervalMs ??\n DEFAULT_RETENTION_INTERVAL_MS;\n const created = setInterval(() => {\n void tick();\n }, intervalMs);\n // Race with stop(): if stop() ran between the check above and\n // setInterval, clear it immediately rather than leaving a\n // lingering timer behind.\n if (stopped) {\n clearInterval(created);\n } else {\n timer = created;\n }\n } catch (err) {\n console.error('retention loop startup failed', err);\n }\n })();\n\n return () => {\n stopped = true;\n if (timer !== null) {\n clearInterval(timer);\n timer = null;\n }\n };\n}\n","import type {\n ConnectorLoggerFactory,\n ConnectorRegistry,\n DashboardConfig,\n SecretsResolver,\n ServerStorage,\n} from '@rawdash/server';\nimport { InMemoryStorage, ROUTES } from '@rawdash/server';\nimport { Hono } from 'hono';\n\nimport { createHealthRouter } from './health';\nimport { createRetentionRouter, startRetentionLoop } from './retention';\nimport { createSyncRouter, createSyncStateRouter } from './sync';\nimport { createWidgetsRouter } from './widgets';\n\nexport interface MountEngineOptions {\n storage?: ServerStorage;\n /**\n * Registry mapping connector type id (e.g. `'github-actions'`) to the\n * connector class. Used to instantiate connector implementations on\n * demand from the declarative entries in `DashboardConfig.connectors`.\n * Required for sync and retention to function.\n */\n connectorRegistry: ConnectorRegistry;\n /**\n * Resolves `secret('NAME')` markers in connector configs. Defaults to\n * `EnvSecretsResolver` (process.env lookup) inside connector\n * instantiation.\n */\n secretsResolver?: SecretsResolver;\n /**\n * Build a connector logger for the runner and each connector instance.\n * Called with `'runner'` for the sync-runner envelopes and with each\n * connector instance name for per-connector progress logs. Defaults to\n * a structured stdout logger.\n */\n loggerFactory?: ConnectorLoggerFactory;\n /** Set false to skip the background retention timer (e.g. on serverless). */\n startRetention?: boolean;\n}\n\nexport interface MountEngineResult {\n app: Hono;\n stop(): void;\n}\n\n/**\n * Convenience wrapper for the common case: builds a Hono app with all\n * standard rawdash routes mounted at their canonical paths, backed by\n * one `DashboardConfig` and one `ServerStorage` (defaults to\n * `InMemoryStorage`).\n *\n * For deployments that need auth or that look up config / storage per\n * request, skip this and compose the router factories directly with\n * per-request `getConfig` / `getStorage` and `before` middleware.\n */\nexport function mountEngine(\n config: DashboardConfig,\n options: MountEngineOptions,\n): MountEngineResult {\n const storage: ServerStorage = options.storage ?? new InMemoryStorage();\n const { connectorRegistry, secretsResolver, loggerFactory } = options;\n const getConfig = (): DashboardConfig => config;\n const getStorage = (): ServerStorage => storage;\n\n const app = new Hono();\n app.route('/dashboards', createWidgetsRouter({ getConfig, getStorage }));\n app.route(\n ROUTES.sync,\n createSyncRouter({\n getConfig,\n getStorage,\n connectorRegistry,\n secretsResolver,\n loggerFactory,\n }),\n );\n app.route(ROUTES.syncState, createSyncStateRouter({ getStorage }));\n app.route('/retention', createRetentionRouter({ getConfig, getStorage }));\n app.route(ROUTES.health, createHealthRouter());\n\n let stopRetention: (() => void) | null = null;\n if (options.startRetention !== false) {\n stopRetention = startRetentionLoop({ getConfig, getStorage });\n }\n\n return {\n app,\n stop() {\n if (stopRetention) {\n stopRetention();\n }\n },\n };\n}\n"],"mappings":"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","names":["Hono","Hono","Hono","Hono","Hono","Hono","Hono","Hono"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rawdash/hono",
3
- "version": "0.15.0",
3
+ "version": "0.17.0",
4
4
  "description": "Hono adapter for rawdash — router factories and helpers that mount @rawdash/server handlers onto a Hono app. Runtime-agnostic (Workers, Node, Bun, Deno).",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -25,8 +25,8 @@
25
25
  "hono": "^4.0.0"
26
26
  },
27
27
  "dependencies": {
28
- "@rawdash/core": "0.15.0",
29
- "@rawdash/server": "0.15.0"
28
+ "@rawdash/core": "0.17.0",
29
+ "@rawdash/server": "0.17.0"
30
30
  },
31
31
  "devDependencies": {
32
32
  "hono": "^4.7.7",