@rawdash/sdk-nextjs 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,104 @@
1
+ # @rawdash/sdk-nextjs
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@rawdash/sdk-nextjs)](https://www.npmjs.com/package/@rawdash/sdk-nextjs)
4
+ [![license](https://img.shields.io/npm/l/@rawdash/sdk-nextjs)](https://github.com/rawdash/rawdash/blob/main/LICENSE)
5
+
6
+ Rawdash SDK for the Next.js App Router.
7
+
8
+ ## What it is
9
+
10
+ `@rawdash/sdk-nextjs` extends `@rawdash/sdk-client` with Next.js-specific behavior: the `http` function tags widget requests with Next.js cache tags so they can be invalidated via `revalidateTag`, and `createRawdashClient` wraps a data source so `triggerSync` automatically revalidates widget data in Server Components after the sync completes.
11
+
12
+ Use this package when your rawdash server runs separately from your Next.js app. For an in-process setup (engine in the same Next.js process), use `@rawdash/sdk-client`'s `inProcess` directly.
13
+
14
+ ## Install
15
+
16
+ ```sh
17
+ npm install @rawdash/sdk-nextjs
18
+ ```
19
+
20
+ Requires Next.js 14+.
21
+
22
+ ## Quick example
23
+
24
+ ```ts
25
+ // lib/rawdash.ts
26
+ import { createRawdashClient, http } from '@rawdash/sdk-nextjs';
27
+
28
+ export const rawdash = createRawdashClient(
29
+ http({
30
+ baseUrl: process.env.RAWDASH_URL!,
31
+ apiKey: process.env.RAWDASH_API_KEY,
32
+ }),
33
+ );
34
+ ```
35
+
36
+ ```tsx
37
+ // app/dashboard/page.tsx
38
+ import { rawdash } from '@/lib/rawdash';
39
+
40
+ export default async function DashboardPage() {
41
+ const widgets = await rawdash.getWidgets('engineering');
42
+
43
+ return (
44
+ <div>
45
+ {widgets.map((w) => (
46
+ <div key={w.id}>{/* render widget */}</div>
47
+ ))}
48
+ </div>
49
+ );
50
+ }
51
+ ```
52
+
53
+ In `app/actions.ts`:
54
+
55
+ ```ts
56
+ 'use server';
57
+
58
+ import { rawdash } from '@/lib/rawdash';
59
+
60
+ export async function syncDashboard() {
61
+ // Triggers sync, polls /sync/state until it settles (succeeded or failed),
62
+ // then calls revalidateTag('rawdash') so the Server Components re-fetch
63
+ // widget data on next request. Throws on sync failure.
64
+ await rawdash.triggerSync();
65
+ }
66
+ ```
67
+
68
+ > **Don't block SSR on a sync.** `triggerSync` (and `ensureFresh`) wait for the sync to settle, which can take up to ~30s. Calling either from a Server Component would block every page render. Use them in Server Actions, cron-triggered routes, or webhooks — and let pages render against whatever's cached.
69
+
70
+ ## Switching between in-process and HTTP
71
+
72
+ ```ts
73
+ // lib/rawdash.ts
74
+ import { inProcess } from '@rawdash/sdk-client';
75
+ import { createRawdashClient } from '@rawdash/sdk-nextjs';
76
+ import { http } from '@rawdash/sdk-nextjs';
77
+
78
+ const source =
79
+ process.env.NODE_ENV === 'production'
80
+ ? http({ baseUrl: process.env.RAWDASH_URL! })
81
+ : inProcess(localEngine);
82
+
83
+ export const rawdash = createRawdashClient(source);
84
+ ```
85
+
86
+ ## API
87
+
88
+ ### `http(options): DataSource`
89
+
90
+ Next.js-aware variant of `http` from `@rawdash/sdk-client`. Adds the `'rawdash'` cache tag to all widget fetch requests so they can be invalidated with `revalidateTag('rawdash')`. Accepts the same options as `@rawdash/sdk-client`'s `http`.
91
+
92
+ ### `createRawdashClient(dataSource): DataSource`
93
+
94
+ Wraps any `DataSource` with Next.js behavior: `triggerSync` polls `/sync/state` until the sync settles (transitions to `succeeded` or `failed`), then calls `revalidateTag('rawdash')` to bust Server Component caches. Throws on `failed` or if the sync doesn't settle within 30s. `ensureFresh` is also tagged to revalidate after a sync. All other methods are passed through unchanged.
95
+
96
+ ## Links
97
+
98
+ - [rawdash docs](https://rawdash.dev)
99
+ - [GitHub](https://github.com/rawdash/rawdash)
100
+ - [Issues](https://github.com/rawdash/rawdash/issues)
101
+
102
+ ## License
103
+
104
+ Apache-2.0
@@ -0,0 +1,16 @@
1
+ import { DataSource } from '@rawdash/core';
2
+ export { ACTIVE_SYNC_STATUSES, CachedWidget, DataSource, HealthResponse, SyncState, SyncStatus, TriggerSyncResponse, WidgetSyncState, WidgetsListResponse, isSyncActive } from '@rawdash/core';
3
+ import { HttpOptions } from '@rawdash/sdk-client';
4
+ export { HttpOptions } from '@rawdash/sdk-client';
5
+
6
+ /**
7
+ * Next.js-aware variant of `http` from `@rawdash/sdk-client`.
8
+ *
9
+ * Identical to `http` but wraps the underlying fetch so that widget requests
10
+ * are tagged with the `'rawdash'` cache tag, enabling `revalidateTag`-based
11
+ * invalidation from Server Actions.
12
+ */
13
+ declare function http(opts: HttpOptions): DataSource;
14
+ declare function createRawdashClient(dataSource: DataSource): DataSource;
15
+
16
+ export { createRawdashClient, http };
package/dist/index.js ADDED
@@ -0,0 +1,72 @@
1
+ // src/index.ts
2
+ import { isSyncActive } from "@rawdash/core";
3
+ import { http as clientHttp } from "@rawdash/sdk-client";
4
+ import { revalidateTag } from "next/cache";
5
+ import { ACTIVE_SYNC_STATUSES, isSyncActive as isSyncActive2 } from "@rawdash/core";
6
+ var RAWDASH_CACHE_TAG = "rawdash";
7
+ function http(opts) {
8
+ const taggedFetch = (input, init) => {
9
+ return globalThis.fetch(
10
+ input,
11
+ {
12
+ ...init,
13
+ next: {
14
+ ...init?.next,
15
+ tags: [
16
+ ...init?.next?.tags ?? [],
17
+ RAWDASH_CACHE_TAG
18
+ ]
19
+ }
20
+ }
21
+ );
22
+ };
23
+ return clientHttp({ ...opts, fetch: taggedFetch });
24
+ }
25
+ var DEFAULT_SYNC_TIMEOUT_MS = 3e4;
26
+ var DEFAULT_SYNC_POLL_INTERVAL_MS = 500;
27
+ function createRawdashClient(dataSource) {
28
+ return {
29
+ getWidget: (dashboardId, widgetId) => dataSource.getWidget(dashboardId, widgetId),
30
+ getWidgets: (dashboardId) => dataSource.getWidgets(dashboardId),
31
+ getHealth: () => dataSource.getHealth(),
32
+ getSyncState: () => dataSource.getSyncState(),
33
+ async ensureFresh(maxAgeMs) {
34
+ const synced = await dataSource.ensureFresh(maxAgeMs);
35
+ if (synced) {
36
+ revalidateTag(RAWDASH_CACHE_TAG);
37
+ }
38
+ return synced;
39
+ },
40
+ async triggerSync() {
41
+ const result = await dataSource.triggerSync();
42
+ const deadline = Date.now() + DEFAULT_SYNC_TIMEOUT_MS;
43
+ for (; ; ) {
44
+ const state = await dataSource.getSyncState();
45
+ if (!isSyncActive(state.status)) {
46
+ if (state.status === "failed") {
47
+ throw new Error(
48
+ `Rawdash sync failed: ${state.lastError ?? "unknown error"}`
49
+ );
50
+ }
51
+ revalidateTag(RAWDASH_CACHE_TAG);
52
+ return result;
53
+ }
54
+ if (Date.now() >= deadline) {
55
+ throw new Error(
56
+ `Rawdash sync did not settle within ${DEFAULT_SYNC_TIMEOUT_MS}ms (last status: ${state.status})`
57
+ );
58
+ }
59
+ await new Promise(
60
+ (resolve) => setTimeout(resolve, DEFAULT_SYNC_POLL_INTERVAL_MS)
61
+ );
62
+ }
63
+ }
64
+ };
65
+ }
66
+ export {
67
+ ACTIVE_SYNC_STATUSES,
68
+ createRawdashClient,
69
+ http,
70
+ isSyncActive2 as isSyncActive
71
+ };
72
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { DataSource } from '@rawdash/core';\n\n/**\n * A configured Rawdash client for use in Next.js Server Components and Server\n * Actions.\n *\n * Wrap a `DataSource` (from `@rawdash/core`) with Next.js-specific\n * behaviour: `triggerSync` waits for the sync to complete, then calls\n * `revalidateTag` so Server Components re-fetch widget data.\n *\n * ```ts\n * // lib/rawdash.ts\n * import { createRawdashClient, http } from '@rawdash/sdk-nextjs';\n *\n * export const rawdash = createRawdashClient(\n * http({ baseUrl: process.env.RAWDASH_URL! }),\n * );\n * ```\n */\nimport { isSyncActive } from '@rawdash/core';\nimport { http as clientHttp } from '@rawdash/sdk-client';\nimport type { HttpOptions } from '@rawdash/sdk-client';\nimport { revalidateTag } from 'next/cache';\n\nexport type { HttpOptions } from '@rawdash/sdk-client';\n\nexport type {\n CachedWidget,\n DataSource,\n HealthResponse,\n SyncState,\n SyncStatus,\n TriggerSyncResponse,\n WidgetSyncState,\n WidgetsListResponse,\n} from '@rawdash/core';\n\nexport { ACTIVE_SYNC_STATUSES, isSyncActive } from '@rawdash/core';\n\nconst RAWDASH_CACHE_TAG = 'rawdash';\n\ntype NextFetchInit = RequestInit & {\n next?: {\n revalidate?: number | false;\n tags?: string[];\n };\n};\n\n/**\n * Next.js-aware variant of `http` from `@rawdash/sdk-client`.\n *\n * Identical to `http` but wraps the underlying fetch so that widget requests\n * are tagged with the `'rawdash'` cache tag, enabling `revalidateTag`-based\n * invalidation from Server Actions.\n */\nexport function http(opts: HttpOptions): DataSource {\n const taggedFetch: typeof globalThis.fetch = (input, init) => {\n return globalThis.fetch(\n input as RequestInfo,\n {\n ...(init as NextFetchInit),\n next: {\n ...(init as NextFetchInit | undefined)?.next,\n tags: [\n ...((init as NextFetchInit | undefined)?.next?.tags ?? []),\n RAWDASH_CACHE_TAG,\n ],\n },\n } as RequestInit,\n );\n };\n return clientHttp({ ...opts, fetch: taggedFetch });\n}\n\nconst DEFAULT_SYNC_TIMEOUT_MS = 30_000;\nconst DEFAULT_SYNC_POLL_INTERVAL_MS = 500;\n\nexport function createRawdashClient(dataSource: DataSource): DataSource {\n return {\n getWidget: (dashboardId, widgetId) =>\n dataSource.getWidget(dashboardId, widgetId),\n\n getWidgets: (dashboardId) => dataSource.getWidgets(dashboardId),\n\n getHealth: () => dataSource.getHealth(),\n\n getSyncState: () => dataSource.getSyncState(),\n\n async ensureFresh(maxAgeMs) {\n const synced = await dataSource.ensureFresh(maxAgeMs);\n if (synced) {\n revalidateTag(RAWDASH_CACHE_TAG);\n }\n return synced;\n },\n\n async triggerSync() {\n const result = await dataSource.triggerSync();\n\n const deadline = Date.now() + DEFAULT_SYNC_TIMEOUT_MS;\n for (;;) {\n const state = await dataSource.getSyncState();\n if (!isSyncActive(state.status)) {\n if (state.status === 'failed') {\n throw new Error(\n `Rawdash sync failed: ${state.lastError ?? 'unknown error'}`,\n );\n }\n revalidateTag(RAWDASH_CACHE_TAG);\n return result;\n }\n if (Date.now() >= deadline) {\n throw new Error(\n `Rawdash sync did not settle within ${DEFAULT_SYNC_TIMEOUT_MS}ms (last status: ${state.status})`,\n );\n }\n await new Promise<void>((resolve) =>\n setTimeout(resolve, DEFAULT_SYNC_POLL_INTERVAL_MS),\n );\n }\n },\n };\n}\n"],"mappings":";AAmBA,SAAS,oBAAoB;AAC7B,SAAS,QAAQ,kBAAkB;AAEnC,SAAS,qBAAqB;AAe9B,SAAS,sBAAsB,gBAAAA,qBAAoB;AAEnD,IAAM,oBAAoB;AAgBnB,SAAS,KAAK,MAA+B;AAClD,QAAM,cAAuC,CAAC,OAAO,SAAS;AAC5D,WAAO,WAAW;AAAA,MAChB;AAAA,MACA;AAAA,QACE,GAAI;AAAA,QACJ,MAAM;AAAA,UACJ,GAAI,MAAoC;AAAA,UACxC,MAAM;AAAA,YACJ,GAAK,MAAoC,MAAM,QAAQ,CAAC;AAAA,YACxD;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,SAAO,WAAW,EAAE,GAAG,MAAM,OAAO,YAAY,CAAC;AACnD;AAEA,IAAM,0BAA0B;AAChC,IAAM,gCAAgC;AAE/B,SAAS,oBAAoB,YAAoC;AACtE,SAAO;AAAA,IACL,WAAW,CAAC,aAAa,aACvB,WAAW,UAAU,aAAa,QAAQ;AAAA,IAE5C,YAAY,CAAC,gBAAgB,WAAW,WAAW,WAAW;AAAA,IAE9D,WAAW,MAAM,WAAW,UAAU;AAAA,IAEtC,cAAc,MAAM,WAAW,aAAa;AAAA,IAE5C,MAAM,YAAY,UAAU;AAC1B,YAAM,SAAS,MAAM,WAAW,YAAY,QAAQ;AACpD,UAAI,QAAQ;AACV,sBAAc,iBAAiB;AAAA,MACjC;AACA,aAAO;AAAA,IACT;AAAA,IAEA,MAAM,cAAc;AAClB,YAAM,SAAS,MAAM,WAAW,YAAY;AAE5C,YAAM,WAAW,KAAK,IAAI,IAAI;AAC9B,iBAAS;AACP,cAAM,QAAQ,MAAM,WAAW,aAAa;AAC5C,YAAI,CAAC,aAAa,MAAM,MAAM,GAAG;AAC/B,cAAI,MAAM,WAAW,UAAU;AAC7B,kBAAM,IAAI;AAAA,cACR,wBAAwB,MAAM,aAAa,eAAe;AAAA,YAC5D;AAAA,UACF;AACA,wBAAc,iBAAiB;AAC/B,iBAAO;AAAA,QACT;AACA,YAAI,KAAK,IAAI,KAAK,UAAU;AAC1B,gBAAM,IAAI;AAAA,YACR,sCAAsC,uBAAuB,oBAAoB,MAAM,MAAM;AAAA,UAC/F;AAAA,QACF;AACA,cAAM,IAAI;AAAA,UAAc,CAAC,YACvB,WAAW,SAAS,6BAA6B;AAAA,QACnD;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;","names":["isSyncActive"]}
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@rawdash/sdk-nextjs",
3
+ "version": "0.15.0",
4
+ "description": "Rawdash client SDK for Next.js App Router (Server Components and Server Actions)",
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-nextjs"
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/sdk-client": "workspace:*",
31
+ "@rawdash/core": "workspace:*"
32
+ },
33
+ "peerDependencies": {
34
+ "next": ">=14.0.0"
35
+ },
36
+ "devDependencies": {
37
+ "next": "^15.0.0",
38
+ "tsup": "^8.0.0",
39
+ "typescript": "^5.7.2"
40
+ }
41
+ }