@riverbankcms/sdk 0.7.0 → 0.7.3
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 +229 -0
- package/dist/cli/index.js +42 -95
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/init-docs/content/agents-section.md +50 -0
- package/dist/cli/init-docs/content/cli-reference.md +574 -0
- package/dist/cli/init-docs/content/content-management.md +384 -0
- package/dist/cli/init-docs/content/context-brand.md +125 -0
- package/dist/cli/init-docs/content/context-brief.md +77 -0
- package/dist/cli/init-docs/content/context-knowledge.md +111 -0
- package/dist/cli/init-docs/content/getting-started.md +130 -0
- package/dist/cli/init-docs/content/site-workflows-readme.md +96 -0
- package/dist/cli/init-docs/content/workflow-add-block.md +228 -0
- package/dist/cli/init-docs/content/workflow-create-page.md +193 -0
- package/dist/cli/init-docs/content/workflow-publish.md +280 -0
- package/dist/client/bookings.d.mts +2 -0
- package/dist/client/bookings.d.ts +2 -0
- package/dist/client/bookings.js +2956 -104
- package/dist/client/bookings.js.map +1 -1
- package/dist/client/bookings.mjs +2929 -70
- package/dist/client/bookings.mjs.map +1 -1
- package/dist/client/client.d.mts +2 -2
- package/dist/client/client.d.ts +2 -2
- package/dist/client/client.js +602 -68
- package/dist/client/client.js.map +1 -1
- package/dist/client/client.mjs +602 -68
- package/dist/client/client.mjs.map +1 -1
- package/dist/client/hooks.d.mts +2 -2
- package/dist/client/hooks.d.ts +2 -2
- package/dist/client/rendering/client.js +3070 -259
- package/dist/client/rendering/client.js.map +1 -1
- package/dist/client/rendering/client.mjs +3212 -395
- package/dist/client/rendering/client.mjs.map +1 -1
- package/dist/client/spam-protection.d.mts +55 -0
- package/dist/client/spam-protection.d.ts +55 -0
- package/dist/client/spam-protection.js +2915 -0
- package/dist/client/spam-protection.js.map +1 -0
- package/dist/client/spam-protection.mjs +2893 -0
- package/dist/client/spam-protection.mjs.map +1 -0
- package/dist/client/{usePage-BiOReg0_.d.ts → usePage-BYmJCCm1.d.ts} +132 -11
- package/dist/client/{usePage-BXjk8BhD.d.mts → usePage-DZtrWajy.d.mts} +132 -11
- package/dist/server/{Layout-wBtJLTVX.d.ts → Layout-Yluyb6sK.d.ts} +1 -1
- package/dist/server/{Layout-B7cvis7r.d.mts → Layout-qWLdVm5-.d.mts} +1 -1
- package/dist/server/chunk-2IZ6S225.js +122 -0
- package/dist/server/chunk-2IZ6S225.js.map +1 -0
- package/dist/server/chunk-4CV4JOE5.js +27 -0
- package/dist/server/chunk-4CV4JOE5.js.map +1 -0
- package/dist/server/chunk-5LRR64Y6.mjs +72 -0
- package/dist/server/chunk-5LRR64Y6.mjs.map +1 -0
- package/dist/server/chunk-NBTRDLCM.js +72 -0
- package/dist/server/chunk-NBTRDLCM.js.map +1 -0
- package/dist/server/chunk-NFEGQTCC.mjs +27 -0
- package/dist/server/{chunk-7FIJSGHU.mjs → chunk-NFQLH5IA.mjs} +856 -74
- package/dist/server/chunk-NFQLH5IA.mjs.map +1 -0
- package/dist/server/chunk-PPHZV6YD.mjs +122 -0
- package/dist/server/chunk-PPHZV6YD.mjs.map +1 -0
- package/dist/server/{chunk-P7UVAMK6.js → chunk-VLXTNB2C.js} +866 -84
- package/dist/server/chunk-VLXTNB2C.js.map +1 -0
- package/dist/server/{components-CMMwDXTW.d.mts → components-DNHfSCML.d.mts} +3 -3
- package/dist/server/{components-CICSJyp_.d.ts → components-Di5ME6He.d.ts} +3 -3
- package/dist/server/components.d.mts +5 -5
- package/dist/server/components.d.ts +5 -5
- package/dist/server/components.js +1 -1
- package/dist/server/components.mjs +1 -1
- package/dist/server/config-validation.js +1 -1
- package/dist/server/config-validation.mjs +1 -1
- package/dist/server/config.js +1 -1
- package/dist/server/config.mjs +1 -1
- package/dist/server/data.d.mts +2 -2
- package/dist/server/data.d.ts +2 -2
- package/dist/server/data.js +1 -1
- package/dist/server/data.mjs +1 -1
- package/dist/server/env.d.mts +109 -0
- package/dist/server/env.d.ts +109 -0
- package/dist/server/env.js +14 -0
- package/dist/server/env.js.map +1 -0
- package/dist/server/env.mjs +14 -0
- package/dist/server/{index-DI_qlYx3.d.mts → index--Oyunk_B.d.mts} +2 -2
- package/dist/server/{index-BTwWvSBu.d.ts → index-C9Ra8dza.d.ts} +2 -2
- package/dist/server/{index-Bucs6UqG.d.mts → index-Clm3skz_.d.mts} +1 -1
- package/dist/server/{index-Cp7tJuRt.d.ts → index-DLvNddi-.d.ts} +1 -1
- package/dist/server/index.d.mts +216 -5
- package/dist/server/index.d.ts +216 -5
- package/dist/server/index.js +301 -4
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +301 -4
- package/dist/server/index.mjs.map +1 -1
- package/dist/server/{loadContent-DmgpFcFC.d.ts → loadContent-D7LQwI0o.d.ts} +3 -3
- package/dist/server/{loadContent-C-YYUKQa.d.mts → loadContent-DVfuBLiZ.d.mts} +3 -3
- package/dist/server/{loadPage-IDGVDFBB.js → loadPage-AXNAERDS.js} +2 -2
- package/dist/server/{loadPage-IDGVDFBB.js.map → loadPage-AXNAERDS.js.map} +1 -1
- package/dist/server/{loadPage-DP3nrHBi.d.ts → loadPage-BmYJCe_V.d.ts} +2 -2
- package/dist/server/{loadPage-B8mQUUSo.d.mts → loadPage-BucnLHmE.d.mts} +2 -2
- package/dist/server/{loadPage-DNQTTRHL.mjs → loadPage-XR7ORQ2E.mjs} +2 -2
- package/dist/server/loadPage-XR7ORQ2E.mjs.map +1 -0
- package/dist/server/metadata.d.mts +4 -4
- package/dist/server/metadata.d.ts +4 -4
- package/dist/server/metadata.js +1 -1
- package/dist/server/metadata.mjs +1 -1
- package/dist/server/navigation.d.mts +2 -2
- package/dist/server/navigation.d.ts +2 -2
- package/dist/server/navigation.js +1 -1
- package/dist/server/navigation.mjs +1 -1
- package/dist/server/next/revalidate.d.mts +66 -0
- package/dist/server/next/revalidate.d.ts +66 -0
- package/dist/server/next/revalidate.js +60 -0
- package/dist/server/next/revalidate.js.map +1 -0
- package/dist/server/next/revalidate.mjs +60 -0
- package/dist/server/next/revalidate.mjs.map +1 -0
- package/dist/server/next/tags.d.mts +81 -0
- package/dist/server/next/tags.d.ts +81 -0
- package/dist/server/next/tags.js +36 -0
- package/dist/server/next/tags.js.map +1 -0
- package/dist/server/next/tags.mjs +36 -0
- package/dist/server/next/tags.mjs.map +1 -0
- package/dist/server/next.d.mts +164 -6
- package/dist/server/next.d.ts +164 -6
- package/dist/server/next.js +79 -11
- package/dist/server/next.js.map +1 -1
- package/dist/server/next.mjs +76 -8
- package/dist/server/next.mjs.map +1 -1
- package/dist/server/rendering/server.d.mts +4 -4
- package/dist/server/rendering/server.d.ts +4 -4
- package/dist/server/rendering/server.js +1 -1
- package/dist/server/rendering/server.mjs +1 -1
- package/dist/server/rendering.d.mts +7 -7
- package/dist/server/rendering.d.ts +7 -7
- package/dist/server/rendering.js +3 -3
- package/dist/server/rendering.js.map +1 -1
- package/dist/server/rendering.mjs +4 -4
- package/dist/server/routing.d.mts +3 -3
- package/dist/server/routing.d.ts +3 -3
- package/dist/server/routing.js +2 -2
- package/dist/server/routing.mjs +2 -2
- package/dist/server/server.d.mts +5 -5
- package/dist/server/server.d.ts +5 -5
- package/dist/server/server.js +5 -5
- package/dist/server/server.js.map +1 -1
- package/dist/server/server.mjs +5 -5
- package/dist/server/theme-bridge.js +1 -1
- package/dist/server/theme-bridge.mjs +1 -1
- package/dist/server/theme.js +1 -1
- package/dist/server/theme.mjs +1 -1
- package/dist/server/{types-BvcJU7zk.d.ts → types-BRQyLrQU.d.ts} +132 -11
- package/dist/server/{types-Dsu9wsUh.d.mts → types-BSV6Vc-P.d.mts} +2 -2
- package/dist/server/{types-1cLz0vnq.d.mts → types-C-LShyIg.d.mts} +132 -11
- package/dist/server/{types-CVykEqXN.d.ts → types-Dt98DeYa.d.ts} +2 -2
- package/dist/server/webhooks.d.mts +81 -0
- package/dist/server/webhooks.d.ts +81 -0
- package/dist/server/webhooks.js +12 -0
- package/dist/server/webhooks.js.map +1 -0
- package/dist/server/webhooks.mjs +12 -0
- package/dist/server/webhooks.mjs.map +1 -0
- package/package.json +29 -3
- package/dist/client/resolver-BhueZVxZ.d.mts +0 -61
- package/dist/client/resolver-BhueZVxZ.d.ts +0 -61
- package/dist/client/usePage--fGlyrgj.d.mts +0 -6439
- package/dist/client/usePage-BBcFCxOU.d.ts +0 -6297
- package/dist/client/usePage-BC8Q2E3t.d.mts +0 -6431
- package/dist/client/usePage-BTPnCuWC.d.mts +0 -6511
- package/dist/client/usePage-BafOS9UT.d.mts +0 -6512
- package/dist/client/usePage-BcjWPXvh.d.mts +0 -6388
- package/dist/client/usePage-Bnx-kA6x.d.mts +0 -6670
- package/dist/client/usePage-BvKAa3Zw.d.mts +0 -366
- package/dist/client/usePage-BvKAa3Zw.d.ts +0 -366
- package/dist/client/usePage-BydHcMYB.d.mts +0 -6297
- package/dist/client/usePage-C3ZKNwY7.d.mts +0 -6393
- package/dist/client/usePage-CE7X5NcN.d.ts +0 -6439
- package/dist/client/usePage-CHEybPMD.d.ts +0 -6429
- package/dist/client/usePage-CrKw1H6Y.d.ts +0 -6338
- package/dist/client/usePage-CyYpOJud.d.ts +0 -6388
- package/dist/client/usePage-D4fxZbRR.d.mts +0 -6429
- package/dist/client/usePage-DMI8ImsU.d.mts +0 -6338
- package/dist/client/usePage-DoPI6b8V.d.ts +0 -6511
- package/dist/client/usePage-DpRNZUtP.d.ts +0 -6431
- package/dist/client/usePage-QNWArrVO.d.ts +0 -6670
- package/dist/client/usePage-fBgPB6Oq.d.ts +0 -6512
- package/dist/client/usePage-gpVaeWDy.d.ts +0 -6393
- package/dist/server/chunk-7FIJSGHU.mjs.map +0 -1
- package/dist/server/chunk-BJTO5JO5.mjs +0 -11
- package/dist/server/chunk-DGUM43GV.js +0 -11
- package/dist/server/chunk-DGUM43GV.js.map +0 -1
- package/dist/server/chunk-P7UVAMK6.js.map +0 -1
- /package/dist/server/{chunk-BJTO5JO5.mjs.map → chunk-NFEGQTCC.mjs.map} +0 -0
- /package/dist/server/{loadPage-DNQTTRHL.mjs.map → env.mjs.map} +0 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { WebhookPayload } from '../webhooks.js';
|
|
2
|
+
import 'zod';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Next.js revalidation handler for webhook-based cache invalidation
|
|
6
|
+
*
|
|
7
|
+
* This module provides a pre-built API route handler for processing
|
|
8
|
+
* CMS webhooks and revalidating Next.js cache entries.
|
|
9
|
+
*
|
|
10
|
+
* @example One-line setup in consumer site
|
|
11
|
+
* ```ts
|
|
12
|
+
* // app/api/revalidate/route.ts
|
|
13
|
+
* import { createRevalidateHandler } from '@riverbankcms/sdk/next/revalidate';
|
|
14
|
+
* export const POST = createRevalidateHandler();
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* @example With custom options
|
|
18
|
+
* ```ts
|
|
19
|
+
* // app/api/revalidate/route.ts
|
|
20
|
+
* import { createRevalidateHandler } from '@riverbankcms/sdk/next/revalidate';
|
|
21
|
+
*
|
|
22
|
+
* export const POST = createRevalidateHandler({
|
|
23
|
+
* onRevalidate: (payload, items) => {
|
|
24
|
+
* console.log(`Revalidated ${items.length} items for ${payload.event}`);
|
|
25
|
+
* },
|
|
26
|
+
* });
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Options for the revalidation handler.
|
|
32
|
+
*/
|
|
33
|
+
interface RevalidateHandlerOptions {
|
|
34
|
+
/**
|
|
35
|
+
* Override the webhook secret. Defaults to RIVERBANK_WEBHOOK_SECRET env var.
|
|
36
|
+
*/
|
|
37
|
+
secret?: string;
|
|
38
|
+
/**
|
|
39
|
+
* Callback called after successful revalidation.
|
|
40
|
+
* Useful for logging or analytics.
|
|
41
|
+
*/
|
|
42
|
+
onRevalidate?: (payload: WebhookPayload, revalidatedItems: string[]) => void;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Create a Next.js API route handler for webhook revalidation.
|
|
46
|
+
*
|
|
47
|
+
* The handler:
|
|
48
|
+
* 1. Verifies the webhook signature using HMAC-SHA256
|
|
49
|
+
* 2. Calls `revalidateTag()` for each tag in the payload
|
|
50
|
+
* 3. Calls `revalidatePath()` if a path is included in the data
|
|
51
|
+
* 4. Returns a JSON response with the revalidation results
|
|
52
|
+
*
|
|
53
|
+
* @param options - Configuration options
|
|
54
|
+
* @returns A Next.js Route Handler function
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```ts
|
|
58
|
+
* // app/api/revalidate/route.ts
|
|
59
|
+
* import { createRevalidateHandler } from '@riverbankcms/sdk/next/revalidate';
|
|
60
|
+
*
|
|
61
|
+
* export const POST = createRevalidateHandler();
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
declare function createRevalidateHandler(options?: RevalidateHandlerOptions): (request: Request) => Promise<Response>;
|
|
65
|
+
|
|
66
|
+
export { type RevalidateHandlerOptions, createRevalidateHandler };
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
var _chunkNBTRDLCMjs = require('../chunk-NBTRDLCM.js');
|
|
5
|
+
require('../chunk-4CV4JOE5.js');
|
|
6
|
+
|
|
7
|
+
// src/next/revalidate.ts
|
|
8
|
+
var _cache = require('next/cache');
|
|
9
|
+
function createRevalidateHandler(options = {}) {
|
|
10
|
+
return async function handleRevalidateRequest(request) {
|
|
11
|
+
const secret = _nullishCoalesce(options.secret, () => ( process.env.RIVERBANK_WEBHOOK_SECRET));
|
|
12
|
+
if (!secret) {
|
|
13
|
+
console.error("[Riverbank] RIVERBANK_WEBHOOK_SECRET not configured");
|
|
14
|
+
return Response.json(
|
|
15
|
+
{ error: "Webhook secret not configured" },
|
|
16
|
+
{ status: 500 }
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
const body = await request.text();
|
|
20
|
+
const signature = request.headers.get("x-riverbank-signature");
|
|
21
|
+
if (!signature || !_chunkNBTRDLCMjs.verifyWebhookSignature.call(void 0, body, signature, secret)) {
|
|
22
|
+
return Response.json({ error: "Invalid signature" }, { status: 401 });
|
|
23
|
+
}
|
|
24
|
+
const parseResult = _chunkNBTRDLCMjs.parseWebhookPayload.call(void 0, body);
|
|
25
|
+
if (!parseResult.success) {
|
|
26
|
+
return Response.json({ error: parseResult.error }, { status: 400 });
|
|
27
|
+
}
|
|
28
|
+
const payload = parseResult.payload;
|
|
29
|
+
const revalidated = [];
|
|
30
|
+
if (_optionalChain([payload, 'access', _ => _.tags, 'optionalAccess', _2 => _2.length])) {
|
|
31
|
+
for (const tag of payload.tags) {
|
|
32
|
+
_cache.revalidateTag.call(void 0, tag);
|
|
33
|
+
revalidated.push(`tag:${tag}`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
const path = typeof _optionalChain([payload, 'access', _3 => _3.data, 'optionalAccess', _4 => _4.path]) === "string" ? payload.data.path : void 0;
|
|
37
|
+
if (path) {
|
|
38
|
+
_cache.revalidatePath.call(void 0, path);
|
|
39
|
+
revalidated.push(`path:${path}`);
|
|
40
|
+
}
|
|
41
|
+
if (revalidated.length > 0) {
|
|
42
|
+
console.log(
|
|
43
|
+
`[Riverbank] Revalidated: ${revalidated.join(", ")} (event: ${payload.event})`
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
if (options.onRevalidate) {
|
|
47
|
+
options.onRevalidate(payload, revalidated);
|
|
48
|
+
}
|
|
49
|
+
return Response.json({
|
|
50
|
+
revalidated: true,
|
|
51
|
+
items: revalidated,
|
|
52
|
+
event: payload.event,
|
|
53
|
+
timestamp: Date.now()
|
|
54
|
+
});
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
exports.createRevalidateHandler = createRevalidateHandler;
|
|
60
|
+
//# sourceMappingURL=revalidate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/will/Projects/Business/cms/builder/packages/sdk/dist/server/next/revalidate.js","../../../src/next/revalidate.ts"],"names":[],"mappings":"AAAA;AACE;AACA;AACF,uDAA6B;AAC7B,gCAA6B;AAC7B;AACA;ACoBA,mCAA8C;AA2CvC,SAAS,uBAAA,CACd,QAAA,EAAoC,CAAC,CAAA,EACI;AACzC,EAAA,OAAO,MAAA,SAAe,uBAAA,CAAwB,OAAA,EAAqC;AAEjF,IAAA,MAAM,OAAA,mBAAS,OAAA,CAAQ,MAAA,UAAU,OAAA,CAAQ,GAAA,CAAI,0BAAA;AAE7C,IAAA,GAAA,CAAI,CAAC,MAAA,EAAQ;AACX,MAAA,OAAA,CAAQ,KAAA,CAAM,qDAAqD,CAAA;AACnE,MAAA,OAAO,QAAA,CAAS,IAAA;AAAA,QACd,EAAE,KAAA,EAAO,gCAAgC,CAAA;AAAA,QACzC,EAAE,MAAA,EAAQ,IAAI;AAAA,MAChB,CAAA;AAAA,IACF;AAGA,IAAA,MAAM,KAAA,EAAO,MAAM,OAAA,CAAQ,IAAA,CAAK,CAAA;AAChC,IAAA,MAAM,UAAA,EAAY,OAAA,CAAQ,OAAA,CAAQ,GAAA,CAAI,uBAAuB,CAAA;AAG7D,IAAA,GAAA,CAAI,CAAC,UAAA,GAAa,CAAC,qDAAA,IAAuB,EAAM,SAAA,EAAW,MAAM,CAAA,EAAG;AAClE,MAAA,OAAO,QAAA,CAAS,IAAA,CAAK,EAAE,KAAA,EAAO,oBAAoB,CAAA,EAAG,EAAE,MAAA,EAAQ,IAAI,CAAC,CAAA;AAAA,IACtE;AAGA,IAAA,MAAM,YAAA,EAAc,kDAAA,IAAwB,CAAA;AAC5C,IAAA,GAAA,CAAI,CAAC,WAAA,CAAY,OAAA,EAAS;AACxB,MAAA,OAAO,QAAA,CAAS,IAAA,CAAK,EAAE,KAAA,EAAO,WAAA,CAAY,MAAM,CAAA,EAAG,EAAE,MAAA,EAAQ,IAAI,CAAC,CAAA;AAAA,IACpE;AACA,IAAA,MAAM,QAAA,EAAU,WAAA,CAAY,OAAA;AAC5B,IAAA,MAAM,YAAA,EAAwB,CAAC,CAAA;AAG/B,IAAA,GAAA,iBAAI,OAAA,mBAAQ,IAAA,6BAAM,QAAA,EAAQ;AACxB,MAAA,IAAA,CAAA,MAAW,IAAA,GAAO,OAAA,CAAQ,IAAA,EAAM;AAC9B,QAAA,kCAAA,GAAiB,CAAA;AACjB,QAAA,WAAA,CAAY,IAAA,CAAK,CAAA,IAAA,EAAO,GAAG,CAAA,CAAA;AAC7B,MAAA;AACF,IAAA;AAG4B,IAAA;AAClB,IAAA;AACW,MAAA;AACU,MAAA;AAC/B,IAAA;AAG4B,IAAA;AAClB,MAAA;AACsB,QAAA;AAC9B,MAAA;AACF,IAAA;AAG0B,IAAA;AACM,MAAA;AAChC,IAAA;AAEqB,IAAA;AACN,MAAA;AACN,MAAA;AACQ,MAAA;AACK,MAAA;AACrB,IAAA;AACH,EAAA;AACF;AD/EoC;AACA;AACA","file":"/Users/will/Projects/Business/cms/builder/packages/sdk/dist/server/next/revalidate.js","sourcesContent":[null,"/**\n * Next.js revalidation handler for webhook-based cache invalidation\n *\n * This module provides a pre-built API route handler for processing\n * CMS webhooks and revalidating Next.js cache entries.\n *\n * @example One-line setup in consumer site\n * ```ts\n * // app/api/revalidate/route.ts\n * import { createRevalidateHandler } from '@riverbankcms/sdk/next/revalidate';\n * export const POST = createRevalidateHandler();\n * ```\n *\n * @example With custom options\n * ```ts\n * // app/api/revalidate/route.ts\n * import { createRevalidateHandler } from '@riverbankcms/sdk/next/revalidate';\n *\n * export const POST = createRevalidateHandler({\n * onRevalidate: (payload, items) => {\n * console.log(`Revalidated ${items.length} items for ${payload.event}`);\n * },\n * });\n * ```\n */\n\nimport { revalidateTag, revalidatePath } from 'next/cache';\nimport {\n verifyWebhookSignature,\n parseWebhookPayload,\n type WebhookPayload,\n} from '../webhooks/verify';\n\n/**\n * Options for the revalidation handler.\n */\nexport interface RevalidateHandlerOptions {\n /**\n * Override the webhook secret. Defaults to RIVERBANK_WEBHOOK_SECRET env var.\n */\n secret?: string;\n\n /**\n * Callback called after successful revalidation.\n * Useful for logging or analytics.\n */\n onRevalidate?: (payload: WebhookPayload, revalidatedItems: string[]) => void;\n}\n\n/**\n * Create a Next.js API route handler for webhook revalidation.\n *\n * The handler:\n * 1. Verifies the webhook signature using HMAC-SHA256\n * 2. Calls `revalidateTag()` for each tag in the payload\n * 3. Calls `revalidatePath()` if a path is included in the data\n * 4. Returns a JSON response with the revalidation results\n *\n * @param options - Configuration options\n * @returns A Next.js Route Handler function\n *\n * @example\n * ```ts\n * // app/api/revalidate/route.ts\n * import { createRevalidateHandler } from '@riverbankcms/sdk/next/revalidate';\n *\n * export const POST = createRevalidateHandler();\n * ```\n */\nexport function createRevalidateHandler(\n options: RevalidateHandlerOptions = {}\n): (request: Request) => Promise<Response> {\n return async function handleRevalidateRequest(request: Request): Promise<Response> {\n // Get webhook secret\n const secret = options.secret ?? process.env.RIVERBANK_WEBHOOK_SECRET;\n\n if (!secret) {\n console.error('[Riverbank] RIVERBANK_WEBHOOK_SECRET not configured');\n return Response.json(\n { error: 'Webhook secret not configured' },\n { status: 500 }\n );\n }\n\n // Read request body\n const body = await request.text();\n const signature = request.headers.get('x-riverbank-signature');\n\n // Verify signature\n if (!signature || !verifyWebhookSignature(body, signature, secret)) {\n return Response.json({ error: 'Invalid signature' }, { status: 401 });\n }\n\n // Parse and validate payload\n const parseResult = parseWebhookPayload(body);\n if (!parseResult.success) {\n return Response.json({ error: parseResult.error }, { status: 400 });\n }\n const payload = parseResult.payload;\n const revalidated: string[] = [];\n\n // Tag-based revalidation (preferred)\n if (payload.tags?.length) {\n for (const tag of payload.tags) {\n revalidateTag(tag);\n revalidated.push(`tag:${tag}`);\n }\n }\n\n // Path-based fallback (from data.path if present)\n const path = typeof payload.data?.path === 'string' ? payload.data.path : undefined;\n if (path) {\n revalidatePath(path);\n revalidated.push(`path:${path}`);\n }\n\n // Log revalidation\n if (revalidated.length > 0) {\n console.log(\n `[Riverbank] Revalidated: ${revalidated.join(', ')} (event: ${payload.event})`\n );\n }\n\n // Call optional callback\n if (options.onRevalidate) {\n options.onRevalidate(payload, revalidated);\n }\n\n return Response.json({\n revalidated: true,\n items: revalidated,\n event: payload.event,\n timestamp: Date.now(),\n });\n };\n}\n"]}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import {
|
|
2
|
+
parseWebhookPayload,
|
|
3
|
+
verifyWebhookSignature
|
|
4
|
+
} from "../chunk-5LRR64Y6.mjs";
|
|
5
|
+
import "../chunk-NFEGQTCC.mjs";
|
|
6
|
+
|
|
7
|
+
// src/next/revalidate.ts
|
|
8
|
+
import { revalidateTag, revalidatePath } from "next/cache";
|
|
9
|
+
function createRevalidateHandler(options = {}) {
|
|
10
|
+
return async function handleRevalidateRequest(request) {
|
|
11
|
+
const secret = options.secret ?? process.env.RIVERBANK_WEBHOOK_SECRET;
|
|
12
|
+
if (!secret) {
|
|
13
|
+
console.error("[Riverbank] RIVERBANK_WEBHOOK_SECRET not configured");
|
|
14
|
+
return Response.json(
|
|
15
|
+
{ error: "Webhook secret not configured" },
|
|
16
|
+
{ status: 500 }
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
const body = await request.text();
|
|
20
|
+
const signature = request.headers.get("x-riverbank-signature");
|
|
21
|
+
if (!signature || !verifyWebhookSignature(body, signature, secret)) {
|
|
22
|
+
return Response.json({ error: "Invalid signature" }, { status: 401 });
|
|
23
|
+
}
|
|
24
|
+
const parseResult = parseWebhookPayload(body);
|
|
25
|
+
if (!parseResult.success) {
|
|
26
|
+
return Response.json({ error: parseResult.error }, { status: 400 });
|
|
27
|
+
}
|
|
28
|
+
const payload = parseResult.payload;
|
|
29
|
+
const revalidated = [];
|
|
30
|
+
if (payload.tags?.length) {
|
|
31
|
+
for (const tag of payload.tags) {
|
|
32
|
+
revalidateTag(tag);
|
|
33
|
+
revalidated.push(`tag:${tag}`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
const path = typeof payload.data?.path === "string" ? payload.data.path : void 0;
|
|
37
|
+
if (path) {
|
|
38
|
+
revalidatePath(path);
|
|
39
|
+
revalidated.push(`path:${path}`);
|
|
40
|
+
}
|
|
41
|
+
if (revalidated.length > 0) {
|
|
42
|
+
console.log(
|
|
43
|
+
`[Riverbank] Revalidated: ${revalidated.join(", ")} (event: ${payload.event})`
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
if (options.onRevalidate) {
|
|
47
|
+
options.onRevalidate(payload, revalidated);
|
|
48
|
+
}
|
|
49
|
+
return Response.json({
|
|
50
|
+
revalidated: true,
|
|
51
|
+
items: revalidated,
|
|
52
|
+
event: payload.event,
|
|
53
|
+
timestamp: Date.now()
|
|
54
|
+
});
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
export {
|
|
58
|
+
createRevalidateHandler
|
|
59
|
+
};
|
|
60
|
+
//# sourceMappingURL=revalidate.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/next/revalidate.ts"],"sourcesContent":["/**\n * Next.js revalidation handler for webhook-based cache invalidation\n *\n * This module provides a pre-built API route handler for processing\n * CMS webhooks and revalidating Next.js cache entries.\n *\n * @example One-line setup in consumer site\n * ```ts\n * // app/api/revalidate/route.ts\n * import { createRevalidateHandler } from '@riverbankcms/sdk/next/revalidate';\n * export const POST = createRevalidateHandler();\n * ```\n *\n * @example With custom options\n * ```ts\n * // app/api/revalidate/route.ts\n * import { createRevalidateHandler } from '@riverbankcms/sdk/next/revalidate';\n *\n * export const POST = createRevalidateHandler({\n * onRevalidate: (payload, items) => {\n * console.log(`Revalidated ${items.length} items for ${payload.event}`);\n * },\n * });\n * ```\n */\n\nimport { revalidateTag, revalidatePath } from 'next/cache';\nimport {\n verifyWebhookSignature,\n parseWebhookPayload,\n type WebhookPayload,\n} from '../webhooks/verify';\n\n/**\n * Options for the revalidation handler.\n */\nexport interface RevalidateHandlerOptions {\n /**\n * Override the webhook secret. Defaults to RIVERBANK_WEBHOOK_SECRET env var.\n */\n secret?: string;\n\n /**\n * Callback called after successful revalidation.\n * Useful for logging or analytics.\n */\n onRevalidate?: (payload: WebhookPayload, revalidatedItems: string[]) => void;\n}\n\n/**\n * Create a Next.js API route handler for webhook revalidation.\n *\n * The handler:\n * 1. Verifies the webhook signature using HMAC-SHA256\n * 2. Calls `revalidateTag()` for each tag in the payload\n * 3. Calls `revalidatePath()` if a path is included in the data\n * 4. Returns a JSON response with the revalidation results\n *\n * @param options - Configuration options\n * @returns A Next.js Route Handler function\n *\n * @example\n * ```ts\n * // app/api/revalidate/route.ts\n * import { createRevalidateHandler } from '@riverbankcms/sdk/next/revalidate';\n *\n * export const POST = createRevalidateHandler();\n * ```\n */\nexport function createRevalidateHandler(\n options: RevalidateHandlerOptions = {}\n): (request: Request) => Promise<Response> {\n return async function handleRevalidateRequest(request: Request): Promise<Response> {\n // Get webhook secret\n const secret = options.secret ?? process.env.RIVERBANK_WEBHOOK_SECRET;\n\n if (!secret) {\n console.error('[Riverbank] RIVERBANK_WEBHOOK_SECRET not configured');\n return Response.json(\n { error: 'Webhook secret not configured' },\n { status: 500 }\n );\n }\n\n // Read request body\n const body = await request.text();\n const signature = request.headers.get('x-riverbank-signature');\n\n // Verify signature\n if (!signature || !verifyWebhookSignature(body, signature, secret)) {\n return Response.json({ error: 'Invalid signature' }, { status: 401 });\n }\n\n // Parse and validate payload\n const parseResult = parseWebhookPayload(body);\n if (!parseResult.success) {\n return Response.json({ error: parseResult.error }, { status: 400 });\n }\n const payload = parseResult.payload;\n const revalidated: string[] = [];\n\n // Tag-based revalidation (preferred)\n if (payload.tags?.length) {\n for (const tag of payload.tags) {\n revalidateTag(tag);\n revalidated.push(`tag:${tag}`);\n }\n }\n\n // Path-based fallback (from data.path if present)\n const path = typeof payload.data?.path === 'string' ? payload.data.path : undefined;\n if (path) {\n revalidatePath(path);\n revalidated.push(`path:${path}`);\n }\n\n // Log revalidation\n if (revalidated.length > 0) {\n console.log(\n `[Riverbank] Revalidated: ${revalidated.join(', ')} (event: ${payload.event})`\n );\n }\n\n // Call optional callback\n if (options.onRevalidate) {\n options.onRevalidate(payload, revalidated);\n }\n\n return Response.json({\n revalidated: true,\n items: revalidated,\n event: payload.event,\n timestamp: Date.now(),\n });\n };\n}\n"],"mappings":";;;;;;;AA0BA,SAAS,eAAe,sBAAsB;AA2CvC,SAAS,wBACd,UAAoC,CAAC,GACI;AACzC,SAAO,eAAe,wBAAwB,SAAqC;AAEjF,UAAM,SAAS,QAAQ,UAAU,QAAQ,IAAI;AAE7C,QAAI,CAAC,QAAQ;AACX,cAAQ,MAAM,qDAAqD;AACnE,aAAO,SAAS;AAAA,QACd,EAAE,OAAO,gCAAgC;AAAA,QACzC,EAAE,QAAQ,IAAI;AAAA,MAChB;AAAA,IACF;AAGA,UAAM,OAAO,MAAM,QAAQ,KAAK;AAChC,UAAM,YAAY,QAAQ,QAAQ,IAAI,uBAAuB;AAG7D,QAAI,CAAC,aAAa,CAAC,uBAAuB,MAAM,WAAW,MAAM,GAAG;AAClE,aAAO,SAAS,KAAK,EAAE,OAAO,oBAAoB,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,IACtE;AAGA,UAAM,cAAc,oBAAoB,IAAI;AAC5C,QAAI,CAAC,YAAY,SAAS;AACxB,aAAO,SAAS,KAAK,EAAE,OAAO,YAAY,MAAM,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,IACpE;AACA,UAAM,UAAU,YAAY;AAC5B,UAAM,cAAwB,CAAC;AAG/B,QAAI,QAAQ,MAAM,QAAQ;AACxB,iBAAW,OAAO,QAAQ,MAAM;AAC9B,sBAAc,GAAG;AACjB,oBAAY,KAAK,OAAO,GAAG,EAAE;AAAA,MAC/B;AAAA,IACF;AAGA,UAAM,OAAO,OAAO,QAAQ,MAAM,SAAS,WAAW,QAAQ,KAAK,OAAO;AAC1E,QAAI,MAAM;AACR,qBAAe,IAAI;AACnB,kBAAY,KAAK,QAAQ,IAAI,EAAE;AAAA,IACjC;AAGA,QAAI,YAAY,SAAS,GAAG;AAC1B,cAAQ;AAAA,QACN,4BAA4B,YAAY,KAAK,IAAI,CAAC,YAAY,QAAQ,KAAK;AAAA,MAC7E;AAAA,IACF;AAGA,QAAI,QAAQ,cAAc;AACxB,cAAQ,aAAa,SAAS,WAAW;AAAA,IAC3C;AAEA,WAAO,SAAS,KAAK;AAAA,MACnB,aAAa;AAAA,MACb,OAAO;AAAA,MACP,OAAO,QAAQ;AAAA,MACf,WAAW,KAAK,IAAI;AAAA,IACtB,CAAC;AAAA,EACH;AACF;","names":[]}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tag generation helpers for Next.js cache invalidation
|
|
3
|
+
*
|
|
4
|
+
* These helpers generate consistent cache tags for use with Next.js
|
|
5
|
+
* `unstable_cache` and `revalidateTag` APIs.
|
|
6
|
+
*
|
|
7
|
+
* Tag naming convention:
|
|
8
|
+
* - `riverbank` - Global tag that invalidates ALL Riverbank data
|
|
9
|
+
* - `riverbank:<resource>` - Collection tag (e.g., `riverbank:pages`)
|
|
10
|
+
* - `riverbank:<resource>:<id>` - Specific resource tag (e.g., `riverbank:page:page-123`)
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```tsx
|
|
14
|
+
* // Consumer site: lib/cms-fetchers.ts
|
|
15
|
+
* import { unstable_cache } from 'next/cache';
|
|
16
|
+
* import { loadPage } from '@riverbankcms/sdk';
|
|
17
|
+
* import { getPageTags } from '@riverbankcms/sdk/next/tags';
|
|
18
|
+
*
|
|
19
|
+
* export const getCachedPage = unstable_cache(
|
|
20
|
+
* async (path: string) => loadPage({ client, siteId, path }),
|
|
21
|
+
* ['riverbank-page'],
|
|
22
|
+
* { tags: getPageTags(), revalidate: 300 }
|
|
23
|
+
* );
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
/**
|
|
27
|
+
* Global tag that invalidates ALL Riverbank data.
|
|
28
|
+
* Revalidating this tag will refresh everything.
|
|
29
|
+
*
|
|
30
|
+
* NOTE: This constant is also defined in apps/dashboard/src/lib/webhooks/dispatch.ts.
|
|
31
|
+
* If you change this value, update both locations.
|
|
32
|
+
*/
|
|
33
|
+
declare const RIVERBANK_GLOBAL_TAG = "riverbank";
|
|
34
|
+
/**
|
|
35
|
+
* Generate tags for site-level data (settings, theme).
|
|
36
|
+
*
|
|
37
|
+
* @returns Array of tags: ['riverbank', 'riverbank:site']
|
|
38
|
+
*/
|
|
39
|
+
declare function getSiteTags(): string[];
|
|
40
|
+
/**
|
|
41
|
+
* Generate tags for page data.
|
|
42
|
+
*
|
|
43
|
+
* @param pageId - Optional specific page ID to include
|
|
44
|
+
* @returns Array of tags including global, pages collection, and optionally page-specific
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```ts
|
|
48
|
+
* getPageTags() // ['riverbank', 'riverbank:pages']
|
|
49
|
+
* getPageTags('page-123') // ['riverbank', 'riverbank:pages', 'riverbank:page:page-123']
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
declare function getPageTags(pageId?: string): string[];
|
|
53
|
+
/**
|
|
54
|
+
* Generate tags for content entries.
|
|
55
|
+
*
|
|
56
|
+
* @param contentTypeSlug - The content type slug (e.g., 'blog-post', 'event')
|
|
57
|
+
* @param entryId - Optional specific entry ID to include
|
|
58
|
+
* @returns Array of tags including global, content-type, and optionally entry-specific
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```ts
|
|
62
|
+
* getEntryTags('blog-post') // ['riverbank', 'riverbank:content-type:blog-post']
|
|
63
|
+
* getEntryTags('blog-post', 'entry-456') // ['riverbank', 'riverbank:content-type:blog-post', 'riverbank:entry:entry-456']
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
declare function getEntryTags(contentTypeSlug: string, entryId?: string): string[];
|
|
67
|
+
/**
|
|
68
|
+
* Generate tags for navigation menus.
|
|
69
|
+
*
|
|
70
|
+
* @param menuKey - Optional specific menu key to include
|
|
71
|
+
* @returns Array of tags including global, navigation collection, and optionally menu-specific
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* ```ts
|
|
75
|
+
* getNavigationTags() // ['riverbank', 'riverbank:navigation']
|
|
76
|
+
* getNavigationTags('main') // ['riverbank', 'riverbank:navigation', 'riverbank:navigation:main']
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
declare function getNavigationTags(menuKey?: string): string[];
|
|
80
|
+
|
|
81
|
+
export { RIVERBANK_GLOBAL_TAG, getEntryTags, getNavigationTags, getPageTags, getSiteTags };
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tag generation helpers for Next.js cache invalidation
|
|
3
|
+
*
|
|
4
|
+
* These helpers generate consistent cache tags for use with Next.js
|
|
5
|
+
* `unstable_cache` and `revalidateTag` APIs.
|
|
6
|
+
*
|
|
7
|
+
* Tag naming convention:
|
|
8
|
+
* - `riverbank` - Global tag that invalidates ALL Riverbank data
|
|
9
|
+
* - `riverbank:<resource>` - Collection tag (e.g., `riverbank:pages`)
|
|
10
|
+
* - `riverbank:<resource>:<id>` - Specific resource tag (e.g., `riverbank:page:page-123`)
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```tsx
|
|
14
|
+
* // Consumer site: lib/cms-fetchers.ts
|
|
15
|
+
* import { unstable_cache } from 'next/cache';
|
|
16
|
+
* import { loadPage } from '@riverbankcms/sdk';
|
|
17
|
+
* import { getPageTags } from '@riverbankcms/sdk/next/tags';
|
|
18
|
+
*
|
|
19
|
+
* export const getCachedPage = unstable_cache(
|
|
20
|
+
* async (path: string) => loadPage({ client, siteId, path }),
|
|
21
|
+
* ['riverbank-page'],
|
|
22
|
+
* { tags: getPageTags(), revalidate: 300 }
|
|
23
|
+
* );
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
/**
|
|
27
|
+
* Global tag that invalidates ALL Riverbank data.
|
|
28
|
+
* Revalidating this tag will refresh everything.
|
|
29
|
+
*
|
|
30
|
+
* NOTE: This constant is also defined in apps/dashboard/src/lib/webhooks/dispatch.ts.
|
|
31
|
+
* If you change this value, update both locations.
|
|
32
|
+
*/
|
|
33
|
+
declare const RIVERBANK_GLOBAL_TAG = "riverbank";
|
|
34
|
+
/**
|
|
35
|
+
* Generate tags for site-level data (settings, theme).
|
|
36
|
+
*
|
|
37
|
+
* @returns Array of tags: ['riverbank', 'riverbank:site']
|
|
38
|
+
*/
|
|
39
|
+
declare function getSiteTags(): string[];
|
|
40
|
+
/**
|
|
41
|
+
* Generate tags for page data.
|
|
42
|
+
*
|
|
43
|
+
* @param pageId - Optional specific page ID to include
|
|
44
|
+
* @returns Array of tags including global, pages collection, and optionally page-specific
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```ts
|
|
48
|
+
* getPageTags() // ['riverbank', 'riverbank:pages']
|
|
49
|
+
* getPageTags('page-123') // ['riverbank', 'riverbank:pages', 'riverbank:page:page-123']
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
declare function getPageTags(pageId?: string): string[];
|
|
53
|
+
/**
|
|
54
|
+
* Generate tags for content entries.
|
|
55
|
+
*
|
|
56
|
+
* @param contentTypeSlug - The content type slug (e.g., 'blog-post', 'event')
|
|
57
|
+
* @param entryId - Optional specific entry ID to include
|
|
58
|
+
* @returns Array of tags including global, content-type, and optionally entry-specific
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```ts
|
|
62
|
+
* getEntryTags('blog-post') // ['riverbank', 'riverbank:content-type:blog-post']
|
|
63
|
+
* getEntryTags('blog-post', 'entry-456') // ['riverbank', 'riverbank:content-type:blog-post', 'riverbank:entry:entry-456']
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
declare function getEntryTags(contentTypeSlug: string, entryId?: string): string[];
|
|
67
|
+
/**
|
|
68
|
+
* Generate tags for navigation menus.
|
|
69
|
+
*
|
|
70
|
+
* @param menuKey - Optional specific menu key to include
|
|
71
|
+
* @returns Array of tags including global, navigation collection, and optionally menu-specific
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* ```ts
|
|
75
|
+
* getNavigationTags() // ['riverbank', 'riverbank:navigation']
|
|
76
|
+
* getNavigationTags('main') // ['riverbank', 'riverbank:navigation', 'riverbank:navigation:main']
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
declare function getNavigationTags(menuKey?: string): string[];
|
|
80
|
+
|
|
81
|
+
export { RIVERBANK_GLOBAL_TAG, getEntryTags, getNavigationTags, getPageTags, getSiteTags };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});require('../chunk-4CV4JOE5.js');
|
|
2
|
+
|
|
3
|
+
// src/next/tags.ts
|
|
4
|
+
var RIVERBANK_GLOBAL_TAG = "riverbank";
|
|
5
|
+
function getSiteTags() {
|
|
6
|
+
return [RIVERBANK_GLOBAL_TAG, "riverbank:site"];
|
|
7
|
+
}
|
|
8
|
+
function getPageTags(pageId) {
|
|
9
|
+
const tags = [RIVERBANK_GLOBAL_TAG, "riverbank:pages"];
|
|
10
|
+
if (pageId) {
|
|
11
|
+
tags.push(`riverbank:page:${pageId}`);
|
|
12
|
+
}
|
|
13
|
+
return tags;
|
|
14
|
+
}
|
|
15
|
+
function getEntryTags(contentTypeSlug, entryId) {
|
|
16
|
+
const tags = [RIVERBANK_GLOBAL_TAG, `riverbank:content-type:${contentTypeSlug}`];
|
|
17
|
+
if (entryId) {
|
|
18
|
+
tags.push(`riverbank:entry:${entryId}`);
|
|
19
|
+
}
|
|
20
|
+
return tags;
|
|
21
|
+
}
|
|
22
|
+
function getNavigationTags(menuKey) {
|
|
23
|
+
const tags = [RIVERBANK_GLOBAL_TAG, "riverbank:navigation"];
|
|
24
|
+
if (menuKey) {
|
|
25
|
+
tags.push(`riverbank:navigation:${menuKey}`);
|
|
26
|
+
}
|
|
27
|
+
return tags;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
exports.RIVERBANK_GLOBAL_TAG = RIVERBANK_GLOBAL_TAG; exports.getEntryTags = getEntryTags; exports.getNavigationTags = getNavigationTags; exports.getPageTags = getPageTags; exports.getSiteTags = getSiteTags;
|
|
36
|
+
//# sourceMappingURL=tags.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/will/Projects/Business/cms/builder/packages/sdk/dist/server/next/tags.js","../../../src/next/tags.ts"],"names":[],"mappings":"AAAA,yGAA6B;AAC7B;AACA;AC+BO,IAAM,qBAAA,EAAuB,WAAA;AAO7B,SAAS,WAAA,CAAA,EAAwB;AACtC,EAAA,OAAO,CAAC,oBAAA,EAAsB,gBAAgB,CAAA;AAChD;AAcO,SAAS,WAAA,CAAY,MAAA,EAA2B;AACrD,EAAA,MAAM,KAAA,EAAO,CAAC,oBAAA,EAAsB,iBAAiB,CAAA;AACrD,EAAA,GAAA,CAAI,MAAA,EAAQ;AACV,IAAA,IAAA,CAAK,IAAA,CAAK,CAAA,eAAA,EAAkB,MAAM,CAAA,CAAA;AACpC,EAAA;AACO,EAAA;AACT;AAesD;AAChB,EAAA;AACvB,EAAA;AACkB,IAAA;AAC/B,EAAA;AACO,EAAA;AACT;AAc8D;AACxB,EAAA;AACvB,EAAA;AACuB,IAAA;AACpC,EAAA;AACO,EAAA;AACT;AD3EuC;AACA;AACA;AACA;AACA;AACA;AACA","file":"/Users/will/Projects/Business/cms/builder/packages/sdk/dist/server/next/tags.js","sourcesContent":[null,"/**\n * Tag generation helpers for Next.js cache invalidation\n *\n * These helpers generate consistent cache tags for use with Next.js\n * `unstable_cache` and `revalidateTag` APIs.\n *\n * Tag naming convention:\n * - `riverbank` - Global tag that invalidates ALL Riverbank data\n * - `riverbank:<resource>` - Collection tag (e.g., `riverbank:pages`)\n * - `riverbank:<resource>:<id>` - Specific resource tag (e.g., `riverbank:page:page-123`)\n *\n * @example\n * ```tsx\n * // Consumer site: lib/cms-fetchers.ts\n * import { unstable_cache } from 'next/cache';\n * import { loadPage } from '@riverbankcms/sdk';\n * import { getPageTags } from '@riverbankcms/sdk/next/tags';\n *\n * export const getCachedPage = unstable_cache(\n * async (path: string) => loadPage({ client, siteId, path }),\n * ['riverbank-page'],\n * { tags: getPageTags(), revalidate: 300 }\n * );\n * ```\n */\n\n/**\n * Global tag that invalidates ALL Riverbank data.\n * Revalidating this tag will refresh everything.\n *\n * NOTE: This constant is also defined in apps/dashboard/src/lib/webhooks/dispatch.ts.\n * If you change this value, update both locations.\n */\nexport const RIVERBANK_GLOBAL_TAG = 'riverbank';\n\n/**\n * Generate tags for site-level data (settings, theme).\n *\n * @returns Array of tags: ['riverbank', 'riverbank:site']\n */\nexport function getSiteTags(): string[] {\n return [RIVERBANK_GLOBAL_TAG, 'riverbank:site'];\n}\n\n/**\n * Generate tags for page data.\n *\n * @param pageId - Optional specific page ID to include\n * @returns Array of tags including global, pages collection, and optionally page-specific\n *\n * @example\n * ```ts\n * getPageTags() // ['riverbank', 'riverbank:pages']\n * getPageTags('page-123') // ['riverbank', 'riverbank:pages', 'riverbank:page:page-123']\n * ```\n */\nexport function getPageTags(pageId?: string): string[] {\n const tags = [RIVERBANK_GLOBAL_TAG, 'riverbank:pages'];\n if (pageId) {\n tags.push(`riverbank:page:${pageId}`);\n }\n return tags;\n}\n\n/**\n * Generate tags for content entries.\n *\n * @param contentTypeSlug - The content type slug (e.g., 'blog-post', 'event')\n * @param entryId - Optional specific entry ID to include\n * @returns Array of tags including global, content-type, and optionally entry-specific\n *\n * @example\n * ```ts\n * getEntryTags('blog-post') // ['riverbank', 'riverbank:content-type:blog-post']\n * getEntryTags('blog-post', 'entry-456') // ['riverbank', 'riverbank:content-type:blog-post', 'riverbank:entry:entry-456']\n * ```\n */\nexport function getEntryTags(contentTypeSlug: string, entryId?: string): string[] {\n const tags = [RIVERBANK_GLOBAL_TAG, `riverbank:content-type:${contentTypeSlug}`];\n if (entryId) {\n tags.push(`riverbank:entry:${entryId}`);\n }\n return tags;\n}\n\n/**\n * Generate tags for navigation menus.\n *\n * @param menuKey - Optional specific menu key to include\n * @returns Array of tags including global, navigation collection, and optionally menu-specific\n *\n * @example\n * ```ts\n * getNavigationTags() // ['riverbank', 'riverbank:navigation']\n * getNavigationTags('main') // ['riverbank', 'riverbank:navigation', 'riverbank:navigation:main']\n * ```\n */\nexport function getNavigationTags(menuKey?: string): string[] {\n const tags = [RIVERBANK_GLOBAL_TAG, 'riverbank:navigation'];\n if (menuKey) {\n tags.push(`riverbank:navigation:${menuKey}`);\n }\n return tags;\n}\n"]}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import "../chunk-NFEGQTCC.mjs";
|
|
2
|
+
|
|
3
|
+
// src/next/tags.ts
|
|
4
|
+
var RIVERBANK_GLOBAL_TAG = "riverbank";
|
|
5
|
+
function getSiteTags() {
|
|
6
|
+
return [RIVERBANK_GLOBAL_TAG, "riverbank:site"];
|
|
7
|
+
}
|
|
8
|
+
function getPageTags(pageId) {
|
|
9
|
+
const tags = [RIVERBANK_GLOBAL_TAG, "riverbank:pages"];
|
|
10
|
+
if (pageId) {
|
|
11
|
+
tags.push(`riverbank:page:${pageId}`);
|
|
12
|
+
}
|
|
13
|
+
return tags;
|
|
14
|
+
}
|
|
15
|
+
function getEntryTags(contentTypeSlug, entryId) {
|
|
16
|
+
const tags = [RIVERBANK_GLOBAL_TAG, `riverbank:content-type:${contentTypeSlug}`];
|
|
17
|
+
if (entryId) {
|
|
18
|
+
tags.push(`riverbank:entry:${entryId}`);
|
|
19
|
+
}
|
|
20
|
+
return tags;
|
|
21
|
+
}
|
|
22
|
+
function getNavigationTags(menuKey) {
|
|
23
|
+
const tags = [RIVERBANK_GLOBAL_TAG, "riverbank:navigation"];
|
|
24
|
+
if (menuKey) {
|
|
25
|
+
tags.push(`riverbank:navigation:${menuKey}`);
|
|
26
|
+
}
|
|
27
|
+
return tags;
|
|
28
|
+
}
|
|
29
|
+
export {
|
|
30
|
+
RIVERBANK_GLOBAL_TAG,
|
|
31
|
+
getEntryTags,
|
|
32
|
+
getNavigationTags,
|
|
33
|
+
getPageTags,
|
|
34
|
+
getSiteTags
|
|
35
|
+
};
|
|
36
|
+
//# sourceMappingURL=tags.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/next/tags.ts"],"sourcesContent":["/**\n * Tag generation helpers for Next.js cache invalidation\n *\n * These helpers generate consistent cache tags for use with Next.js\n * `unstable_cache` and `revalidateTag` APIs.\n *\n * Tag naming convention:\n * - `riverbank` - Global tag that invalidates ALL Riverbank data\n * - `riverbank:<resource>` - Collection tag (e.g., `riverbank:pages`)\n * - `riverbank:<resource>:<id>` - Specific resource tag (e.g., `riverbank:page:page-123`)\n *\n * @example\n * ```tsx\n * // Consumer site: lib/cms-fetchers.ts\n * import { unstable_cache } from 'next/cache';\n * import { loadPage } from '@riverbankcms/sdk';\n * import { getPageTags } from '@riverbankcms/sdk/next/tags';\n *\n * export const getCachedPage = unstable_cache(\n * async (path: string) => loadPage({ client, siteId, path }),\n * ['riverbank-page'],\n * { tags: getPageTags(), revalidate: 300 }\n * );\n * ```\n */\n\n/**\n * Global tag that invalidates ALL Riverbank data.\n * Revalidating this tag will refresh everything.\n *\n * NOTE: This constant is also defined in apps/dashboard/src/lib/webhooks/dispatch.ts.\n * If you change this value, update both locations.\n */\nexport const RIVERBANK_GLOBAL_TAG = 'riverbank';\n\n/**\n * Generate tags for site-level data (settings, theme).\n *\n * @returns Array of tags: ['riverbank', 'riverbank:site']\n */\nexport function getSiteTags(): string[] {\n return [RIVERBANK_GLOBAL_TAG, 'riverbank:site'];\n}\n\n/**\n * Generate tags for page data.\n *\n * @param pageId - Optional specific page ID to include\n * @returns Array of tags including global, pages collection, and optionally page-specific\n *\n * @example\n * ```ts\n * getPageTags() // ['riverbank', 'riverbank:pages']\n * getPageTags('page-123') // ['riverbank', 'riverbank:pages', 'riverbank:page:page-123']\n * ```\n */\nexport function getPageTags(pageId?: string): string[] {\n const tags = [RIVERBANK_GLOBAL_TAG, 'riverbank:pages'];\n if (pageId) {\n tags.push(`riverbank:page:${pageId}`);\n }\n return tags;\n}\n\n/**\n * Generate tags for content entries.\n *\n * @param contentTypeSlug - The content type slug (e.g., 'blog-post', 'event')\n * @param entryId - Optional specific entry ID to include\n * @returns Array of tags including global, content-type, and optionally entry-specific\n *\n * @example\n * ```ts\n * getEntryTags('blog-post') // ['riverbank', 'riverbank:content-type:blog-post']\n * getEntryTags('blog-post', 'entry-456') // ['riverbank', 'riverbank:content-type:blog-post', 'riverbank:entry:entry-456']\n * ```\n */\nexport function getEntryTags(contentTypeSlug: string, entryId?: string): string[] {\n const tags = [RIVERBANK_GLOBAL_TAG, `riverbank:content-type:${contentTypeSlug}`];\n if (entryId) {\n tags.push(`riverbank:entry:${entryId}`);\n }\n return tags;\n}\n\n/**\n * Generate tags for navigation menus.\n *\n * @param menuKey - Optional specific menu key to include\n * @returns Array of tags including global, navigation collection, and optionally menu-specific\n *\n * @example\n * ```ts\n * getNavigationTags() // ['riverbank', 'riverbank:navigation']\n * getNavigationTags('main') // ['riverbank', 'riverbank:navigation', 'riverbank:navigation:main']\n * ```\n */\nexport function getNavigationTags(menuKey?: string): string[] {\n const tags = [RIVERBANK_GLOBAL_TAG, 'riverbank:navigation'];\n if (menuKey) {\n tags.push(`riverbank:navigation:${menuKey}`);\n }\n return tags;\n}\n"],"mappings":";;;AAiCO,IAAM,uBAAuB;AAO7B,SAAS,cAAwB;AACtC,SAAO,CAAC,sBAAsB,gBAAgB;AAChD;AAcO,SAAS,YAAY,QAA2B;AACrD,QAAM,OAAO,CAAC,sBAAsB,iBAAiB;AACrD,MAAI,QAAQ;AACV,SAAK,KAAK,kBAAkB,MAAM,EAAE;AAAA,EACtC;AACA,SAAO;AACT;AAeO,SAAS,aAAa,iBAAyB,SAA4B;AAChF,QAAM,OAAO,CAAC,sBAAsB,0BAA0B,eAAe,EAAE;AAC/E,MAAI,SAAS;AACX,SAAK,KAAK,mBAAmB,OAAO,EAAE;AAAA,EACxC;AACA,SAAO;AACT;AAcO,SAAS,kBAAkB,SAA4B;AAC5D,QAAM,OAAO,CAAC,sBAAsB,sBAAsB;AAC1D,MAAI,SAAS;AACX,SAAK,KAAK,wBAAwB,OAAO,EAAE;AAAA,EAC7C;AACA,SAAO;AACT;","names":[]}
|
package/dist/server/next.d.mts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { ReactNode, ComponentType } from 'react';
|
|
2
|
-
import { R as RiverbankClient } from './types-
|
|
2
|
+
import { R as RiverbankClient } from './types-C-LShyIg.mjs';
|
|
3
3
|
import { R as RiverbankSiteConfig } from './types-BjgZt8xJ.mjs';
|
|
4
|
-
import { B as BlockOverrides } from './loadPage-
|
|
4
|
+
import { B as BlockOverrides } from './loadPage-BucnLHmE.mjs';
|
|
5
5
|
import './schema-Z6-afHJG.mjs';
|
|
6
|
-
import { M as Metadata } from './index
|
|
7
|
-
import { b as LoadContentResult } from './loadContent-
|
|
8
|
-
import './types-
|
|
6
|
+
import { M as Metadata } from './index--Oyunk_B.mjs';
|
|
7
|
+
import { b as LoadContentResult } from './loadContent-DVfuBLiZ.mjs';
|
|
8
|
+
import './types-BSV6Vc-P.mjs';
|
|
9
9
|
import '@riverbankcms/ai';
|
|
10
10
|
import 'zod';
|
|
11
11
|
import './link-DjxLyC82.mjs';
|
|
@@ -271,4 +271,162 @@ interface CreateCatchAllPageResult {
|
|
|
271
271
|
*/
|
|
272
272
|
declare function createCatchAllPage(options: CreateCatchAllPageOptions): CreateCatchAllPageResult;
|
|
273
273
|
|
|
274
|
-
|
|
274
|
+
/**
|
|
275
|
+
* Static params generation for Next.js SSG
|
|
276
|
+
*
|
|
277
|
+
* Provides helpers for generating static params from published CMS routes.
|
|
278
|
+
*
|
|
279
|
+
* @example
|
|
280
|
+
* ```tsx
|
|
281
|
+
* // app/[[...slug]]/page.tsx
|
|
282
|
+
* import { generateAllStaticParams } from '@riverbankcms/sdk/next';
|
|
283
|
+
*
|
|
284
|
+
* export { generateAllStaticParams as generateStaticParams };
|
|
285
|
+
* ```
|
|
286
|
+
*/
|
|
287
|
+
/**
|
|
288
|
+
* Environment variable validation result
|
|
289
|
+
*/
|
|
290
|
+
type StaticParamsEnvResult = {
|
|
291
|
+
valid: true;
|
|
292
|
+
config: {
|
|
293
|
+
apiKey: string;
|
|
294
|
+
siteId: string;
|
|
295
|
+
baseUrl: string;
|
|
296
|
+
};
|
|
297
|
+
} | {
|
|
298
|
+
valid: false;
|
|
299
|
+
missingVars: string[];
|
|
300
|
+
};
|
|
301
|
+
/**
|
|
302
|
+
* Validate that all required environment variables are set.
|
|
303
|
+
*
|
|
304
|
+
* Required env vars:
|
|
305
|
+
* - RIVERBANK_API_KEY: API key for published content
|
|
306
|
+
* - RIVERBANK_SITE_ID: Site ID
|
|
307
|
+
* - NEXT_PUBLIC_DASHBOARD_URL: Dashboard API URL
|
|
308
|
+
*
|
|
309
|
+
* @returns Validation result with config or missing vars
|
|
310
|
+
*/
|
|
311
|
+
declare function validateStaticParamsEnv(): StaticParamsEnvResult;
|
|
312
|
+
/**
|
|
313
|
+
* Convert a route path to a Next.js slug array.
|
|
314
|
+
*
|
|
315
|
+
* @param path - The route path (e.g., '/about', '/blog/post')
|
|
316
|
+
* @returns The slug array for Next.js catch-all route
|
|
317
|
+
*
|
|
318
|
+
* @example
|
|
319
|
+
* ```ts
|
|
320
|
+
* pathToSlugArray('/') // []
|
|
321
|
+
* pathToSlugArray('/about') // ['about']
|
|
322
|
+
* pathToSlugArray('/blog/post') // ['blog', 'post']
|
|
323
|
+
* ```
|
|
324
|
+
*/
|
|
325
|
+
declare function pathToSlugArray(path: string): string[];
|
|
326
|
+
/**
|
|
327
|
+
* Generate static params for all published routes.
|
|
328
|
+
*
|
|
329
|
+
* This function fetches all published routes from the CMS and converts them
|
|
330
|
+
* to the static params format expected by Next.js catch-all routes.
|
|
331
|
+
*
|
|
332
|
+
* Requires environment variables:
|
|
333
|
+
* - RIVERBANK_API_KEY: API key for published content
|
|
334
|
+
* - RIVERBANK_SITE_ID: Site ID
|
|
335
|
+
* - NEXT_PUBLIC_DASHBOARD_URL: Dashboard API URL
|
|
336
|
+
*
|
|
337
|
+
* @throws Error if required env vars are missing (prevents silent empty SSG in CI)
|
|
338
|
+
* @returns Array of static params objects for Next.js
|
|
339
|
+
*
|
|
340
|
+
* @example
|
|
341
|
+
* ```tsx
|
|
342
|
+
* // app/[[...slug]]/page.tsx
|
|
343
|
+
* import { generateAllStaticParams } from '@riverbankcms/sdk/next';
|
|
344
|
+
*
|
|
345
|
+
* export { generateAllStaticParams as generateStaticParams };
|
|
346
|
+
*
|
|
347
|
+
* // Or with custom logic:
|
|
348
|
+
* export async function generateStaticParams() {
|
|
349
|
+
* const params = await generateAllStaticParams();
|
|
350
|
+
* // Filter or modify params as needed
|
|
351
|
+
* return params.filter(p => !p.slug.includes('private'));
|
|
352
|
+
* }
|
|
353
|
+
* ```
|
|
354
|
+
*/
|
|
355
|
+
declare function generateAllStaticParams(): Promise<{
|
|
356
|
+
slug: string[];
|
|
357
|
+
}[]>;
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* Next.js integration helpers for Riverbank CMS SDK.
|
|
361
|
+
*
|
|
362
|
+
* Provides opinionated factories for common Next.js patterns, reducing
|
|
363
|
+
* boilerplate while maintaining full customizability through escape hatches.
|
|
364
|
+
*
|
|
365
|
+
* @example Basic catch-all page
|
|
366
|
+
* ```tsx
|
|
367
|
+
* // src/app/[[...slug]]/page.tsx
|
|
368
|
+
* import { createCatchAllPage } from '@riverbankcms/sdk/next';
|
|
369
|
+
* import { getRiverbankClient } from '@/lib/builder-client';
|
|
370
|
+
* import config from '@/riverbank.config';
|
|
371
|
+
*
|
|
372
|
+
* const { Page, generateMetadata } = createCatchAllPage({
|
|
373
|
+
* getClient: getRiverbankClient,
|
|
374
|
+
* config,
|
|
375
|
+
* });
|
|
376
|
+
*
|
|
377
|
+
* export default Page;
|
|
378
|
+
* export { generateMetadata };
|
|
379
|
+
* ```
|
|
380
|
+
*
|
|
381
|
+
* @example With customization
|
|
382
|
+
* ```tsx
|
|
383
|
+
* const { Page, generateMetadata } = createCatchAllPage({
|
|
384
|
+
* getClient,
|
|
385
|
+
* config,
|
|
386
|
+
* blockOverrides: { hero: MyCustomHero },
|
|
387
|
+
* beforeRender: async () => {
|
|
388
|
+
* if (process.env.MAINTENANCE_MODE === 'true') {
|
|
389
|
+
* return <MaintenancePage />;
|
|
390
|
+
* }
|
|
391
|
+
* return null;
|
|
392
|
+
* },
|
|
393
|
+
* });
|
|
394
|
+
* ```
|
|
395
|
+
*
|
|
396
|
+
* @packageDocumentation
|
|
397
|
+
*/
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* ISR revalidation duration in seconds for production mode.
|
|
401
|
+
* 5 minutes provides a good balance between freshness and performance.
|
|
402
|
+
*/
|
|
403
|
+
declare const ISR_REVALIDATE_SECONDS = 300;
|
|
404
|
+
interface ISRConfig {
|
|
405
|
+
/**
|
|
406
|
+
* Revalidation interval in seconds.
|
|
407
|
+
* - 0: Dynamic rendering (no caching) - used in preview mode
|
|
408
|
+
* - 300: 5 minute ISR - used in production mode
|
|
409
|
+
*/
|
|
410
|
+
revalidate: number | false;
|
|
411
|
+
/**
|
|
412
|
+
* Whether the current environment is in preview mode.
|
|
413
|
+
* Useful for conditional rendering or data fetching behavior.
|
|
414
|
+
*/
|
|
415
|
+
isPreview: boolean;
|
|
416
|
+
}
|
|
417
|
+
/**
|
|
418
|
+
* Get ISR configuration based on the current environment.
|
|
419
|
+
*
|
|
420
|
+
* @example
|
|
421
|
+
* ```tsx
|
|
422
|
+
* // app/[[...slug]]/page.tsx
|
|
423
|
+
* import { getISRConfig } from '@riverbankcms/sdk/next';
|
|
424
|
+
*
|
|
425
|
+
* export const revalidate = getISRConfig().revalidate;
|
|
426
|
+
* ```
|
|
427
|
+
*
|
|
428
|
+
* @returns ISR configuration with revalidate interval and preview flag
|
|
429
|
+
*/
|
|
430
|
+
declare function getISRConfig(): ISRConfig;
|
|
431
|
+
|
|
432
|
+
export { type CatchAllContext, type CatchAllPageProps, type CreateCatchAllPageOptions, type CreateCatchAllPageResult, type ISRConfig, ISR_REVALIDATE_SECONDS, type StaticParamsEnvResult, createCatchAllPage, generateAllStaticParams, getISRConfig, pathToSlugArray, validateStaticParamsEnv };
|