@rawdash/sdk-client 0.15.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 ADDED
@@ -0,0 +1,119 @@
1
+ # @rawdash/sdk-client
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@rawdash/sdk-client)](https://www.npmjs.com/package/@rawdash/sdk-client)
4
+ [![license](https://img.shields.io/npm/l/@rawdash/sdk-client)](https://github.com/rawdash/rawdash/blob/main/LICENSE)
5
+
6
+ Framework-agnostic data sources for rawdash dashboards.
7
+
8
+ ## What it is
9
+
10
+ `@rawdash/sdk-client` provides two data source factories — `inProcess` and `http` — that let you wire up rawdash widget data in any JavaScript environment. Use `inProcess` when the rawdash engine runs in the same process as your app (e.g. a Next.js route handler), and `http` when it runs as a separate service.
11
+
12
+ Both return the same `DataSource` interface, so you can swap between them without changing the rest of your code.
13
+
14
+ ## Install
15
+
16
+ ```sh
17
+ npm install @rawdash/sdk-client
18
+ ```
19
+
20
+ ## Quick example
21
+
22
+ ```ts
23
+ import { inProcess, http } from '@rawdash/sdk-client';
24
+
25
+ // Option A — engine runs in the same process
26
+ import { engine } from './rawdash-engine';
27
+ const source = inProcess(engine);
28
+
29
+ // Option B — engine runs as a separate HTTP service
30
+ const source = http({
31
+ baseUrl: 'https://rawdash.example.com',
32
+ apiKey: process.env.RAWDASH_API_KEY,
33
+ });
34
+
35
+ // Same API either way
36
+ const widget = await source.getWidget('engineering', 'open_prs');
37
+ const widgets = await source.getWidgets('engineering');
38
+ const health = await source.getHealth(); // {status:'ok'} — liveness only
39
+ const syncState = await source.getSyncState(); // current sync progress
40
+ await source.triggerSync(); // returns immediately with {queued: boolean}
41
+
42
+ // Wait for fresh data:
43
+ // - if a sync is in-flight, waits for it to settle
44
+ // - if data is stale, triggers a sync and waits for it
45
+ // - if data is fresh, returns immediately
46
+ await source.ensureFresh(5 * 60 * 1000); // max age 5 minutes
47
+ ```
48
+
49
+ ## API
50
+
51
+ ### `inProcess(engine, options?): DataSource`
52
+
53
+ Wraps an in-process rawdash engine. Zero network overhead.
54
+
55
+ | Option | Type | Default | Description |
56
+ | -------------------- | -------- | ------- | ------------------------------------- |
57
+ | `syncTimeoutMs` | `number` | `30000` | How long `ensureFresh` waits for sync |
58
+ | `syncPollIntervalMs` | `number` | `500` | Delay between sync-state polls |
59
+
60
+ ### `http(options): DataSource`
61
+
62
+ Creates an HTTP client pointing at a rawdash server.
63
+
64
+ | Option | Type | Default | Description |
65
+ | -------------------- | -------------- | ------------------ | ------------------------------------- |
66
+ | `baseUrl` | `string` | — | Base URL of the rawdash server |
67
+ | `apiKey` | `string` | — | Bearer token for authentication |
68
+ | `timeoutMs` | `number` | `5000` | Per-request timeout in milliseconds |
69
+ | `syncTimeoutMs` | `number` | `30000` | How long `ensureFresh` waits for sync |
70
+ | `syncPollIntervalMs` | `number` | `500` | Delay between sync-state polls |
71
+ | `fetch` | `typeof fetch` | `globalThis.fetch` | Custom fetch implementation |
72
+
73
+ ### `DataSource`
74
+
75
+ ```ts
76
+ interface DataSource {
77
+ getWidget(dashboardId: string, widgetId: string): Promise<CachedWidget>;
78
+ getWidgets(dashboardId: string): Promise<CachedWidget[]>;
79
+
80
+ // Liveness probe — {status:'ok'}. No storage access.
81
+ getHealth(): Promise<HealthResponse>;
82
+
83
+ // Current sync state: idle | queued | running | succeeded | failed,
84
+ // plus queuedAt / startedAt / lastSyncAt / lastError.
85
+ getSyncState(): Promise<SyncState>;
86
+
87
+ // Triggers a sync. Returns {queued: true|false} immediately —
88
+ // the sync runs in the background.
89
+ triggerSync(): Promise<TriggerSyncResponse>;
90
+
91
+ // Waits until data is at most maxAgeMs old. Returns true if a sync
92
+ // ran, false if data was already fresh. Throws on sync failure.
93
+ ensureFresh(maxAgeMs?: number): Promise<boolean>;
94
+ }
95
+ ```
96
+
97
+ ## How `ensureFresh` works
98
+
99
+ The client polls `/sync/state` (not `/health` — see the [wire contract reference](https://www.npmjs.com/package/@rawdash/server#the-wire-contract)) and walks the state machine:
100
+
101
+ 1. Get the current `SyncState`.
102
+ 2. If `status` is `queued` or `running`, wait for it to settle. Return `true` on `succeeded`, throw on `failed`.
103
+ 3. Otherwise check `lastSyncAt`. If it's within `maxAgeMs`, return `false`.
104
+ 4. Otherwise call `POST /sync`, then poll `/sync/state` until it settles.
105
+ 5. If the server returns an unrecognized `status`, **throw immediately** — turns silent contract mismatches into fast, debuggable errors instead of 30s deadlocks.
106
+
107
+ Tune `syncTimeoutMs` for long-running connectors.
108
+
109
+ ## Links
110
+
111
+ - [rawdash docs](https://rawdash.dev)
112
+ - [`@rawdash/server`](https://www.npmjs.com/package/@rawdash/server) — wire contract reference
113
+ - [`@rawdash/hono`](https://www.npmjs.com/package/@rawdash/hono) — Hono adapter for the server side
114
+ - [GitHub](https://github.com/rawdash/rawdash)
115
+ - [Issues](https://github.com/rawdash/rawdash/issues)
116
+
117
+ ## License
118
+
119
+ Apache-2.0
@@ -0,0 +1,23 @@
1
+ import { DataSource, ServerDataSource } from '@rawdash/core';
2
+
3
+ interface HttpOptions {
4
+ baseUrl: string;
5
+ apiKey?: string;
6
+ fetch?: typeof globalThis.fetch;
7
+ timeoutMs?: number;
8
+ /** Total time to wait for an in-flight sync to finish before throwing. Defaults to 30s. */
9
+ syncTimeoutMs?: number;
10
+ /** Delay between sync-state polls. Defaults to 500ms. */
11
+ syncPollIntervalMs?: number;
12
+ }
13
+ declare function http(opts: HttpOptions): DataSource;
14
+
15
+ interface InProcessOptions {
16
+ /** Total time to wait for an in-flight sync to finish. Defaults to 30s. */
17
+ syncTimeoutMs?: number;
18
+ /** Delay between sync-state polls. Defaults to 500ms. */
19
+ syncPollIntervalMs?: number;
20
+ }
21
+ declare function inProcess(engine: ServerDataSource, options?: InProcessOptions): DataSource;
22
+
23
+ export { type HttpOptions, type InProcessOptions, http, inProcess };
package/dist/index.js ADDED
@@ -0,0 +1,235 @@
1
+ // src/http.ts
2
+ import { isSyncActive } from "@rawdash/core";
3
+ var KNOWN_SYNC_STATUSES = /* @__PURE__ */ new Set([
4
+ "idle",
5
+ "queued",
6
+ "running",
7
+ "succeeded",
8
+ "failed"
9
+ ]);
10
+ function http(opts) {
11
+ const {
12
+ baseUrl,
13
+ apiKey,
14
+ fetch: fetchFn = globalThis.fetch,
15
+ timeoutMs = 5e3,
16
+ syncTimeoutMs = 3e4,
17
+ syncPollIntervalMs = 500
18
+ } = opts;
19
+ if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
20
+ throw new Error(
21
+ `http: timeoutMs must be a finite positive number (received ${timeoutMs})`
22
+ );
23
+ }
24
+ if (!Number.isFinite(syncTimeoutMs) || syncTimeoutMs <= 0) {
25
+ throw new Error(
26
+ `http: syncTimeoutMs must be a finite positive number (received ${syncTimeoutMs})`
27
+ );
28
+ }
29
+ if (!Number.isFinite(syncPollIntervalMs) || syncPollIntervalMs <= 0) {
30
+ throw new Error(
31
+ `http: syncPollIntervalMs must be a finite positive number (received ${syncPollIntervalMs})`
32
+ );
33
+ }
34
+ const baseHeaders = apiKey ? { Authorization: `Bearer ${apiKey}` } : {};
35
+ async function fetchWithTimeout(input, init = {}) {
36
+ const controller = new AbortController();
37
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
38
+ try {
39
+ return await fetchFn(input, {
40
+ ...init,
41
+ headers: { ...baseHeaders, ...init.headers ?? {} },
42
+ signal: controller.signal
43
+ });
44
+ } finally {
45
+ clearTimeout(timer);
46
+ }
47
+ }
48
+ async function get(path, init = {}) {
49
+ const res = await fetchWithTimeout(`${baseUrl}${path}`, init);
50
+ if (!res.ok) {
51
+ throw new Error(`Rawdash API error ${res.status}: ${res.statusText}`);
52
+ }
53
+ return res.json();
54
+ }
55
+ async function getSyncState() {
56
+ const state = await get("/sync/state", { cache: "no-store" });
57
+ if (!KNOWN_SYNC_STATUSES.has(state.status)) {
58
+ throw new Error(
59
+ `Rawdash returned unrecognized sync status "${String(state.status)}" \u2014 the server is likely speaking a different protocol version.`
60
+ );
61
+ }
62
+ return state;
63
+ }
64
+ async function waitForSyncToSettle() {
65
+ const deadline = Date.now() + syncTimeoutMs;
66
+ for (; ; ) {
67
+ const state = await getSyncState();
68
+ if (!isSyncActive(state.status)) {
69
+ return state;
70
+ }
71
+ if (Date.now() >= deadline) {
72
+ throw new Error(
73
+ `Rawdash sync did not settle within ${syncTimeoutMs}ms (last status: ${state.status})`
74
+ );
75
+ }
76
+ await new Promise(
77
+ (resolve) => setTimeout(resolve, syncPollIntervalMs)
78
+ );
79
+ }
80
+ }
81
+ return {
82
+ async getWidgets(dashboardId) {
83
+ const { widgets } = await get(
84
+ `/dashboards/${encodeURIComponent(dashboardId)}/widgets`
85
+ );
86
+ return widgets;
87
+ },
88
+ getWidget(dashboardId, widgetId) {
89
+ return get(
90
+ `/dashboards/${encodeURIComponent(dashboardId)}/widgets/${encodeURIComponent(widgetId)}`
91
+ );
92
+ },
93
+ getHealth() {
94
+ return get("/health", { cache: "no-store" });
95
+ },
96
+ getSyncState,
97
+ async triggerSync() {
98
+ const res = await fetchWithTimeout(`${baseUrl}/sync`, { method: "POST" });
99
+ if (!res.ok) {
100
+ throw new Error(`Rawdash sync error ${res.status}: ${res.statusText}`);
101
+ }
102
+ return res.json();
103
+ },
104
+ async ensureFresh(maxAgeMs = 5 * 60 * 1e3) {
105
+ const state = await getSyncState();
106
+ if (isSyncActive(state.status)) {
107
+ const settled2 = await waitForSyncToSettle();
108
+ if (settled2.status === "failed") {
109
+ throw new Error(
110
+ `Rawdash sync failed: ${settled2.lastError ?? "unknown error"}`
111
+ );
112
+ }
113
+ return true;
114
+ }
115
+ const lastSyncMs = state.lastSyncAt ? new Date(state.lastSyncAt).getTime() : null;
116
+ const isFresh = lastSyncMs !== null && Date.now() - lastSyncMs < maxAgeMs;
117
+ if (isFresh) {
118
+ return false;
119
+ }
120
+ const trigger = await this.triggerSync();
121
+ if (!trigger.queued) {
122
+ const settled2 = await waitForSyncToSettle();
123
+ if (settled2.status === "failed") {
124
+ throw new Error(
125
+ `Rawdash sync failed: ${settled2.lastError ?? "unknown error"}`
126
+ );
127
+ }
128
+ return true;
129
+ }
130
+ const settled = await waitForSyncToSettle();
131
+ if (settled.status === "failed") {
132
+ throw new Error(
133
+ `Rawdash sync failed: ${settled.lastError ?? "unknown error"}`
134
+ );
135
+ }
136
+ return true;
137
+ }
138
+ };
139
+ }
140
+
141
+ // src/in-process.ts
142
+ import { isSyncActive as isSyncActive2 } from "@rawdash/core";
143
+ var KNOWN_SYNC_STATUSES2 = /* @__PURE__ */ new Set([
144
+ "idle",
145
+ "queued",
146
+ "running",
147
+ "succeeded",
148
+ "failed"
149
+ ]);
150
+ function inProcess(engine, options = {}) {
151
+ const syncTimeoutMs = options.syncTimeoutMs ?? 3e4;
152
+ const syncPollIntervalMs = options.syncPollIntervalMs ?? 500;
153
+ if (!Number.isFinite(syncTimeoutMs) || syncTimeoutMs <= 0) {
154
+ throw new Error(
155
+ `inProcess: syncTimeoutMs must be a finite positive number (received ${syncTimeoutMs})`
156
+ );
157
+ }
158
+ if (!Number.isFinite(syncPollIntervalMs) || syncPollIntervalMs <= 0) {
159
+ throw new Error(
160
+ `inProcess: syncPollIntervalMs must be a finite positive number (received ${syncPollIntervalMs})`
161
+ );
162
+ }
163
+ async function getSyncStateGuarded() {
164
+ const state = await engine.getSyncState();
165
+ if (!KNOWN_SYNC_STATUSES2.has(state.status)) {
166
+ throw new Error(
167
+ `Rawdash engine returned unrecognized sync status "${String(state.status)}"`
168
+ );
169
+ }
170
+ return state;
171
+ }
172
+ async function waitForSyncToSettle() {
173
+ const deadline = Date.now() + syncTimeoutMs;
174
+ for (; ; ) {
175
+ const state = await getSyncStateGuarded();
176
+ if (!isSyncActive2(state.status)) {
177
+ return state;
178
+ }
179
+ if (Date.now() >= deadline) {
180
+ throw new Error(
181
+ `Rawdash sync did not settle within ${syncTimeoutMs}ms (last status: ${state.status})`
182
+ );
183
+ }
184
+ await new Promise(
185
+ (resolve) => setTimeout(resolve, syncPollIntervalMs)
186
+ );
187
+ }
188
+ }
189
+ return {
190
+ getWidget: (dashboardId, widgetId) => engine.getWidget(dashboardId, widgetId),
191
+ getWidgets: (dashboardId) => engine.getWidgets(dashboardId),
192
+ getHealth: () => engine.getHealth(),
193
+ getSyncState: () => getSyncStateGuarded(),
194
+ triggerSync: () => engine.triggerSync(),
195
+ async ensureFresh(maxAgeMs = 5 * 60 * 1e3) {
196
+ const state = await getSyncStateGuarded();
197
+ if (isSyncActive2(state.status)) {
198
+ const settled2 = await waitForSyncToSettle();
199
+ if (settled2.status === "failed") {
200
+ throw new Error(
201
+ `Rawdash sync failed: ${settled2.lastError ?? "unknown error"}`
202
+ );
203
+ }
204
+ return true;
205
+ }
206
+ const lastSyncMs = state.lastSyncAt ? new Date(state.lastSyncAt).getTime() : null;
207
+ const isFresh = lastSyncMs !== null && Date.now() - lastSyncMs < maxAgeMs;
208
+ if (isFresh) {
209
+ return false;
210
+ }
211
+ const trigger = await engine.triggerSync();
212
+ if (!trigger.queued) {
213
+ const settled2 = await waitForSyncToSettle();
214
+ if (settled2.status === "failed") {
215
+ throw new Error(
216
+ `Rawdash sync failed: ${settled2.lastError ?? "unknown error"}`
217
+ );
218
+ }
219
+ return true;
220
+ }
221
+ const settled = await waitForSyncToSettle();
222
+ if (settled.status === "failed") {
223
+ throw new Error(
224
+ `Rawdash sync failed: ${settled.lastError ?? "unknown error"}`
225
+ );
226
+ }
227
+ return true;
228
+ }
229
+ };
230
+ }
231
+ export {
232
+ http,
233
+ inProcess
234
+ };
235
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/http.ts","../src/in-process.ts"],"sourcesContent":["import type {\n CachedWidget,\n DataSource,\n HealthResponse,\n SyncState,\n TriggerSyncResponse,\n WidgetsListResponse,\n} from '@rawdash/core';\nimport { isSyncActive } from '@rawdash/core';\n\nexport interface HttpOptions {\n baseUrl: string;\n apiKey?: string;\n fetch?: typeof globalThis.fetch;\n timeoutMs?: number;\n /** Total time to wait for an in-flight sync to finish before throwing. Defaults to 30s. */\n syncTimeoutMs?: number;\n /** Delay between sync-state polls. Defaults to 500ms. */\n syncPollIntervalMs?: number;\n}\n\nconst KNOWN_SYNC_STATUSES = new Set([\n 'idle',\n 'queued',\n 'running',\n 'succeeded',\n 'failed',\n]);\n\nexport function http(opts: HttpOptions): DataSource {\n const {\n baseUrl,\n apiKey,\n fetch: fetchFn = globalThis.fetch,\n timeoutMs = 5000,\n syncTimeoutMs = 30_000,\n syncPollIntervalMs = 500,\n } = opts;\n\n if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {\n throw new Error(\n `http: timeoutMs must be a finite positive number (received ${timeoutMs})`,\n );\n }\n if (!Number.isFinite(syncTimeoutMs) || syncTimeoutMs <= 0) {\n throw new Error(\n `http: syncTimeoutMs must be a finite positive number (received ${syncTimeoutMs})`,\n );\n }\n if (!Number.isFinite(syncPollIntervalMs) || syncPollIntervalMs <= 0) {\n throw new Error(\n `http: syncPollIntervalMs must be a finite positive number (received ${syncPollIntervalMs})`,\n );\n }\n\n const baseHeaders: Record<string, string> = apiKey\n ? { Authorization: `Bearer ${apiKey}` }\n : {};\n\n async function fetchWithTimeout(\n input: string,\n init: RequestInit = {},\n ): Promise<Response> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n try {\n return await fetchFn(input, {\n ...init,\n headers: { ...baseHeaders, ...(init.headers ?? {}) },\n signal: controller.signal,\n });\n } finally {\n clearTimeout(timer);\n }\n }\n\n async function get<T>(path: string, init: RequestInit = {}): Promise<T> {\n const res = await fetchWithTimeout(`${baseUrl}${path}`, init);\n if (!res.ok) {\n throw new Error(`Rawdash API error ${res.status}: ${res.statusText}`);\n }\n return res.json() as Promise<T>;\n }\n\n async function getSyncState(): Promise<SyncState> {\n const state = await get<SyncState>('/sync/state', { cache: 'no-store' });\n if (!KNOWN_SYNC_STATUSES.has(state.status)) {\n throw new Error(\n `Rawdash returned unrecognized sync status \"${String(state.status)}\" — the server is likely speaking a different protocol version.`,\n );\n }\n return state;\n }\n\n async function waitForSyncToSettle(): Promise<SyncState> {\n const deadline = Date.now() + syncTimeoutMs;\n for (;;) {\n const state = await getSyncState();\n if (!isSyncActive(state.status)) {\n return state;\n }\n if (Date.now() >= deadline) {\n throw new Error(\n `Rawdash sync did not settle within ${syncTimeoutMs}ms (last status: ${state.status})`,\n );\n }\n await new Promise<void>((resolve) =>\n setTimeout(resolve, syncPollIntervalMs),\n );\n }\n }\n\n return {\n async getWidgets(dashboardId) {\n const { widgets } = await get<WidgetsListResponse>(\n `/dashboards/${encodeURIComponent(dashboardId)}/widgets`,\n );\n return widgets;\n },\n\n getWidget(dashboardId, widgetId) {\n return get<CachedWidget>(\n `/dashboards/${encodeURIComponent(dashboardId)}/widgets/${encodeURIComponent(widgetId)}`,\n );\n },\n\n getHealth() {\n return get<HealthResponse>('/health', { cache: 'no-store' });\n },\n\n getSyncState,\n\n async triggerSync() {\n const res = await fetchWithTimeout(`${baseUrl}/sync`, { method: 'POST' });\n if (!res.ok) {\n throw new Error(`Rawdash sync error ${res.status}: ${res.statusText}`);\n }\n return res.json() as Promise<TriggerSyncResponse>;\n },\n\n async ensureFresh(maxAgeMs = 5 * 60 * 1000) {\n const state = await getSyncState();\n\n if (isSyncActive(state.status)) {\n const settled = await waitForSyncToSettle();\n if (settled.status === 'failed') {\n throw new Error(\n `Rawdash sync failed: ${settled.lastError ?? 'unknown error'}`,\n );\n }\n return true;\n }\n\n const lastSyncMs = state.lastSyncAt\n ? new Date(state.lastSyncAt).getTime()\n : null;\n const isFresh = lastSyncMs !== null && Date.now() - lastSyncMs < maxAgeMs;\n if (isFresh) {\n return false;\n }\n\n const trigger = await this.triggerSync();\n if (!trigger.queued) {\n const settled = await waitForSyncToSettle();\n if (settled.status === 'failed') {\n throw new Error(\n `Rawdash sync failed: ${settled.lastError ?? 'unknown error'}`,\n );\n }\n return true;\n }\n\n const settled = await waitForSyncToSettle();\n if (settled.status === 'failed') {\n throw new Error(\n `Rawdash sync failed: ${settled.lastError ?? 'unknown error'}`,\n );\n }\n return true;\n },\n };\n}\n","import type { DataSource, ServerDataSource, SyncState } from '@rawdash/core';\nimport { isSyncActive } from '@rawdash/core';\n\nexport interface InProcessOptions {\n /** Total time to wait for an in-flight sync to finish. Defaults to 30s. */\n syncTimeoutMs?: number;\n /** Delay between sync-state polls. Defaults to 500ms. */\n syncPollIntervalMs?: number;\n}\n\nconst KNOWN_SYNC_STATUSES = new Set([\n 'idle',\n 'queued',\n 'running',\n 'succeeded',\n 'failed',\n]);\n\nexport function inProcess(\n engine: ServerDataSource,\n options: InProcessOptions = {},\n): DataSource {\n const syncTimeoutMs = options.syncTimeoutMs ?? 30_000;\n const syncPollIntervalMs = options.syncPollIntervalMs ?? 500;\n\n if (!Number.isFinite(syncTimeoutMs) || syncTimeoutMs <= 0) {\n throw new Error(\n `inProcess: syncTimeoutMs must be a finite positive number (received ${syncTimeoutMs})`,\n );\n }\n if (!Number.isFinite(syncPollIntervalMs) || syncPollIntervalMs <= 0) {\n throw new Error(\n `inProcess: syncPollIntervalMs must be a finite positive number (received ${syncPollIntervalMs})`,\n );\n }\n\n async function getSyncStateGuarded(): Promise<SyncState> {\n const state = await engine.getSyncState();\n if (!KNOWN_SYNC_STATUSES.has(state.status)) {\n throw new Error(\n `Rawdash engine returned unrecognized sync status \"${String(state.status)}\"`,\n );\n }\n return state;\n }\n\n async function waitForSyncToSettle(): Promise<SyncState> {\n const deadline = Date.now() + syncTimeoutMs;\n for (;;) {\n const state = await getSyncStateGuarded();\n if (!isSyncActive(state.status)) {\n return state;\n }\n if (Date.now() >= deadline) {\n throw new Error(\n `Rawdash sync did not settle within ${syncTimeoutMs}ms (last status: ${state.status})`,\n );\n }\n await new Promise<void>((resolve) =>\n setTimeout(resolve, syncPollIntervalMs),\n );\n }\n }\n\n return {\n getWidget: (dashboardId, widgetId) =>\n engine.getWidget(dashboardId, widgetId),\n\n getWidgets: (dashboardId) => engine.getWidgets(dashboardId),\n\n getHealth: () => engine.getHealth(),\n\n getSyncState: () => getSyncStateGuarded(),\n\n triggerSync: () => engine.triggerSync(),\n\n async ensureFresh(maxAgeMs = 5 * 60 * 1000) {\n const state = await getSyncStateGuarded();\n\n if (isSyncActive(state.status)) {\n const settled = await waitForSyncToSettle();\n if (settled.status === 'failed') {\n throw new Error(\n `Rawdash sync failed: ${settled.lastError ?? 'unknown error'}`,\n );\n }\n return true;\n }\n\n const lastSyncMs = state.lastSyncAt\n ? new Date(state.lastSyncAt).getTime()\n : null;\n const isFresh = lastSyncMs !== null && Date.now() - lastSyncMs < maxAgeMs;\n if (isFresh) {\n return false;\n }\n\n const trigger = await engine.triggerSync();\n if (!trigger.queued) {\n const settled = await waitForSyncToSettle();\n if (settled.status === 'failed') {\n throw new Error(\n `Rawdash sync failed: ${settled.lastError ?? 'unknown error'}`,\n );\n }\n return true;\n }\n\n const settled = await waitForSyncToSettle();\n if (settled.status === 'failed') {\n throw new Error(\n `Rawdash sync failed: ${settled.lastError ?? 'unknown error'}`,\n );\n }\n return true;\n },\n };\n}\n"],"mappings":"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","names":["settled","isSyncActive","KNOWN_SYNC_STATUSES","settled"]}
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "@rawdash/sdk-client",
3
+ "version": "0.15.0",
4
+ "description": "Rawdash framework-agnostic data sources",
5
+ "license": "Apache-2.0",
6
+ "type": "module",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/rawdash/rawdash.git",
10
+ "directory": "packages/sdk-client"
11
+ },
12
+ "files": [
13
+ "dist",
14
+ "README.md",
15
+ "LICENSE"
16
+ ],
17
+ "exports": {
18
+ ".": {
19
+ "@rawdash/source": "./src/index.ts",
20
+ "types": "./dist/index.d.ts",
21
+ "import": "./dist/index.js"
22
+ }
23
+ },
24
+ "scripts": {
25
+ "build": "tsup",
26
+ "typecheck": "tsc --noEmit",
27
+ "lint": "eslint src"
28
+ },
29
+ "dependencies": {
30
+ "@rawdash/core": "workspace:*"
31
+ },
32
+ "devDependencies": {
33
+ "tsup": "^8.0.0",
34
+ "typescript": "^5.7.2"
35
+ }
36
+ }