@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 +104 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +72 -0
- package/dist/index.js.map +1 -0
- package/package.json +41 -0
package/README.md
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# @rawdash/sdk-nextjs
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@rawdash/sdk-nextjs)
|
|
4
|
+
[](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
|
package/dist/index.d.ts
ADDED
|
@@ -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
|
+
}
|