@praxium/sdk 0.3.61 → 0.3.68

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -6,7 +6,7 @@ Official TypeScript SDK for the [Praxium](https://praxium.nl) platform API. Buil
6
6
  - [Configuration](#configuration) — Environment variables and tenant routing
7
7
  - [Available Methods](#available-methods) — All API endpoints
8
8
  - [Error Handling](#error-handling) — Typed error classes
9
- - [Next.js ISR Revalidation](#nextjs-isr-revalidation) — Webhook-based cache invalidation
9
+ - [Webhooks](#webhooks) — React to entity changes (ISR revalidation, cache busting, etc.)
10
10
  - [Contributing](#contributing) — Development commands
11
11
 
12
12
  ## Quick Start
@@ -85,20 +85,20 @@ Your website needs two environment variables to connect to the Praxium platform,
85
85
 
86
86
  | Variable | Purpose | Example |
87
87
  |----------|---------|---------|
88
- | `PRAXIUM_API_URL` | Your tenant's admin portal URL. The SDK sends API requests to this host. | `https://ijfysio.admin.praxium.nl` |
89
- | `PRAXIUM_API_KEY` | HMAC API key for authentication. Generated in the admin portal under API Profiles. The tenant slug is embedded in the key — no need to configure it separately. | `hmac_v1_ijfysio_default_17..._abc...` |
88
+ | `PRAXIUM_API_URL` | Your tenant's admin portal URL. The SDK sends API requests to this host. | `https://mypractice.admin.praxium.nl` |
89
+ | `PRAXIUM_API_KEY` | HMAC API key for authentication. Generated in the admin portal under API Profiles. The tenant slug is embedded in the key — no need to configure it separately. | `hmac_v1_mypractice_default_17..._abc...` |
90
90
 
91
91
  **Optional (only if using ISR revalidation webhooks):**
92
92
 
93
93
  | Variable | Purpose | Example |
94
94
  |----------|---------|---------|
95
- | `PRAXIUM_REVALIDATION_SECRET` | Shared secret for webhook signature verification. Only needed if your website uses ISR and you want the platform to notify your site when data changes (team, FAQ, opening hours). See [Next.js ISR Revalidation](#nextjs-isr-revalidation). | (32+ character random string) |
95
+ | `PRAXIUM_WEBHOOK_SECRET` | Shared secret for webhook signature verification. Only needed if you want the platform to notify your site when data changes (team, FAQ, opening hours). See [Webhooks](#webhooks). | (32+ character random string) |
96
96
 
97
97
  ```bash
98
98
  # .env.local
99
99
  PRAXIUM_API_URL="https://mypractice.admin.praxium.nl"
100
100
  PRAXIUM_API_KEY="hmac_v1_mypractice_default_1234567890_abcdef..."
101
- PRAXIUM_REVALIDATION_SECRET="your-webhook-secret-from-admin-portal" # optional
101
+ PRAXIUM_WEBHOOK_SECRET="your-webhook-secret-from-admin-portal" # optional
102
102
  ```
103
103
 
104
104
  > **How tenant routing works:** Each tenant has its own admin subdomain (`{slug}.admin.praxium.nl`). The platform identifies your tenant from both the hostname AND the API key's embedded slug, cross-validating them for security. You don't need to configure the tenant slug separately — it's derived from your API key automatically.
@@ -149,21 +149,39 @@ try {
149
149
  | `PraxiumRateLimitError` | 429 | Too many requests |
150
150
  | `PraxiumError` | Other | Base class for all errors |
151
151
 
152
- ## Next.js ISR Revalidation
152
+ ## Webhooks
153
153
 
154
- For websites using Next.js [ISR (Incremental Static Regeneration)](https://nextjs.org/docs/app/building-your-application/data-fetching/incremental-static-regeneration), the SDK provides a webhook handler for on-demand cache revalidation. When an admin updates data (team, FAQ, opening hours), the platform sends an HMAC-signed webhook to your revalidation endpoint. The handler verifies the signature and calls `revalidatePath()` for the affected pages.
154
+ When an admin updates data (team, FAQ, opening hours), the platform sends an HMAC-signed webhook to your registered endpoint. You can use this to react to entity changes in any way your application needs.
155
+
156
+ **Common use cases:**
157
+
158
+ | Use Case | What you do on entity change |
159
+ |----------|------------------------------|
160
+ | **ISR revalidation** | Call `revalidatePath()` to refresh cached pages |
161
+ | **Search index** | Re-index changed entities in your search engine |
162
+ | **CDN cache** | Purge cached API responses or assets |
163
+
164
+ **Prerequisites:**
165
+
166
+ 1. Register your webhook endpoint URL in the admin portal (Settings → Webhooks)
167
+ 2. Set `PRAXIUM_WEBHOOK_SECRET` to the shared secret from the admin portal
168
+
169
+ All webhook handlers include HMAC-SHA256 signature verification, timestamp-based replay protection (5-minute window), and timing-safe comparison.
170
+
171
+ ### Next.js ISR Revalidation
172
+
173
+ The SDK provides a ready-made handler for Next.js [ISR](https://nextjs.org/docs/app/building-your-application/data-fetching/incremental-static-regeneration) revalidation. It verifies the webhook signature and calls `revalidatePath()` for the affected pages.
155
174
 
156
175
  The `pathMap` is fully customizable — you define which pages to revalidate for each entity based on your website's routing structure:
157
176
 
158
177
  ```typescript
159
178
  // app/api/revalidate/route.ts
160
- import { createRevalidationHandler } from '@praxium/sdk/revalidation'
179
+ import { createRevalidationHandler } from '@praxium/sdk/webhooks'
161
180
 
162
181
  export const POST = createRevalidationHandler({
163
- secret: process.env.PRAXIUM_REVALIDATION_SECRET!,
182
+ secret: process.env.PRAXIUM_WEBHOOK_SECRET!,
164
183
  // Map platform entities to YOUR website's page paths.
165
- // These are specific to your project's routing structure
166
- // adjust the paths to match your pages.
184
+ // Adjust the paths to match your project's routing structure.
167
185
  pathMap: {
168
186
  'team': ['/nl/team', '/en/team'],
169
187
  'rates': ['/nl/tarieven', '/en/rates'],
@@ -174,12 +192,35 @@ export const POST = createRevalidationHandler({
174
192
  })
175
193
  ```
176
194
 
177
- **Prerequisites:**
195
+ Requires `next` as a peer dependency.
196
+
197
+ ### Custom Webhook Handler
178
198
 
179
- 1. Register your revalidation endpoint URL in the admin portal (Settings Webhooks)
180
- 2. Set the `PRAXIUM_REVALIDATION_SECRET` env var to match the webhook secret from the admin portal
199
+ For non-Next.js use cases or custom logic, use `processWebhook()` to verify the signature and extract the changed entity:
181
200
 
182
- The handler includes HMAC-SHA256 signature verification, timestamp-based replay protection (5-minute window), and timing-safe comparison. Requires `next` as a peer dependency.
201
+ ```typescript
202
+ // Example: invalidate a Redis cache on entity change
203
+ import { processWebhook, WEBHOOK_SIGNATURE_HEADER } from '@praxium/sdk/webhooks'
204
+
205
+ export async function POST(request: Request) {
206
+ const body = await request.text()
207
+
208
+ const result = await processWebhook({
209
+ body,
210
+ signature: request.headers.get(WEBHOOK_SIGNATURE_HEADER)!,
211
+ secret: process.env.PRAXIUM_WEBHOOK_SECRET!,
212
+ })
213
+
214
+ if (!result.valid) {
215
+ return new Response(result.error, { status: 401 })
216
+ }
217
+
218
+ // result.entity = 'team' | 'faq' | 'rates' | ...
219
+ await redis.del(`cache:${result.entity}`)
220
+
221
+ return new Response('OK')
222
+ }
223
+ ```
183
224
 
184
225
  ## Contributing
185
226
 
@@ -0,0 +1,160 @@
1
+ /**
2
+ * Praxium Webhook Utilities
3
+ *
4
+ * Process and verify webhooks sent by the Praxium platform when entity
5
+ * data changes (team, FAQ, opening hours, etc.).
6
+ *
7
+ * Two levels of abstraction:
8
+ *
9
+ * **`processWebhook()`** — Framework-agnostic. Verifies HMAC signature,
10
+ * checks timestamp freshness, parses the body, and returns the entity
11
+ * that changed. Use this with Express, Fastify, or any custom handler.
12
+ *
13
+ * **`createRevalidationHandler()`** — Next.js-specific. Wraps processWebhook
14
+ * with path resolution and `revalidatePath()` calls. Returns a ready-made
15
+ * route handler for `app/api/revalidate/route.ts`.
16
+ *
17
+ * Signature scheme (H6):
18
+ * X-Praxium-Signature: t={unix_timestamp},sha256={HMAC-SHA256(secret, timestamp.body)}
19
+ *
20
+ * Security features:
21
+ * - HMAC-SHA256 signature verification (secret never sent in body)
22
+ * - Timestamp-based replay protection (default 5-minute window)
23
+ * - Timing-safe signature comparison (prevents timing side-channel attacks)
24
+ * - Web Crypto API (platform-agnostic: Edge, Node.js, browser)
25
+ *
26
+ * @example
27
+ * // Framework-agnostic (Express, Fastify, etc.):
28
+ * import { processWebhook } from '@praxium/sdk/webhooks'
29
+ *
30
+ * const result = await processWebhook({
31
+ * body: rawBody,
32
+ * signature: req.headers['x-praxium-signature'],
33
+ * secret: process.env.PRAXIUM_WEBHOOK_SECRET!,
34
+ * })
35
+ * if (result.valid) console.log('Entity changed:', result.entity)
36
+ *
37
+ * @example
38
+ * // Next.js ISR revalidation:
39
+ * import { createRevalidationHandler } from '@praxium/sdk/webhooks'
40
+ *
41
+ * export const POST = createRevalidationHandler({
42
+ * secret: process.env.PRAXIUM_WEBHOOK_SECRET!,
43
+ * pathMap: { 'team': ['/nl/team', '/en/team'] },
44
+ * })
45
+ */
46
+ /** Header name for the HMAC signature */
47
+ declare const WEBHOOK_SIGNATURE_HEADER = "X-Praxium-Signature";
48
+ /** Input for processWebhook() */
49
+ interface ProcessWebhookInput {
50
+ /** Raw request body as string */
51
+ body: string;
52
+ /** Value of the X-Praxium-Signature header */
53
+ signature: string;
54
+ /** Shared secret for HMAC verification */
55
+ secret: string;
56
+ /** Maximum age of request timestamp in milliseconds (default: 5 minutes) */
57
+ maxTimestampAge?: number;
58
+ }
59
+ /** Successful webhook processing result */
60
+ interface WebhookSuccess {
61
+ valid: true;
62
+ /** Entity type that changed (e.g., 'team', 'rates', 'faq') */
63
+ entity: string | undefined;
64
+ }
65
+ /** Failed webhook processing result */
66
+ interface WebhookFailure {
67
+ valid: false;
68
+ /** Human-readable error description */
69
+ error: string;
70
+ }
71
+ /** Result of processWebhook() */
72
+ type WebhookResult = WebhookSuccess | WebhookFailure;
73
+ /** Configuration for createRevalidationHandler() */
74
+ interface RevalidationConfig {
75
+ /** Shared secret for HMAC signature verification */
76
+ secret: string;
77
+ /** Maximum age of request timestamp in milliseconds (default: 5 minutes) */
78
+ maxTimestampAge?: number;
79
+ /**
80
+ * Entity → full paths to revalidate (including locale prefix).
81
+ *
82
+ * Paths are specific to YOUR website's routing structure.
83
+ * When a webhook arrives with `{ entity: 'team' }`, the handler looks up
84
+ * `pathMap['team']` and calls `revalidatePath()` for each path.
85
+ *
86
+ * Unknown entities fall back to revalidating ALL registered paths.
87
+ *
88
+ * @example
89
+ * pathMap: {
90
+ * 'team': ['/nl/team', '/en/team'],
91
+ * 'rates': ['/nl/tarieven', '/en/rates'],
92
+ * 'opening-hours': ['/nl', '/en'],
93
+ * }
94
+ */
95
+ pathMap: Record<string, string[]>;
96
+ }
97
+ /**
98
+ * Process and verify a Praxium platform webhook.
99
+ *
100
+ * Verifies the HMAC-SHA256 signature, checks timestamp freshness (replay
101
+ * protection), and parses the webhook body to extract the changed entity.
102
+ *
103
+ * Use this for custom webhook handling in any framework (Express, Fastify,
104
+ * Deno, etc.). For Next.js ISR revalidation, use createRevalidationHandler()
105
+ * which wraps this with path resolution and revalidatePath() calls.
106
+ *
107
+ * @example
108
+ * ```typescript
109
+ * import { processWebhook } from '@praxium/sdk/webhooks'
110
+ *
111
+ * const result = await processWebhook({
112
+ * body: rawBody,
113
+ * signature: req.headers['x-praxium-signature'],
114
+ * secret: process.env.PRAXIUM_WEBHOOK_SECRET!,
115
+ * })
116
+ *
117
+ * if (result.valid) {
118
+ * await redis.del(`cache:${result.entity}`)
119
+ * }
120
+ * ```
121
+ */
122
+ declare function processWebhook(input: ProcessWebhookInput): Promise<WebhookResult>;
123
+ /**
124
+ * Resolve entity to revalidation paths using the pathMap.
125
+ *
126
+ * Resolution priority:
127
+ * 1. pathMap[entity] → pre-computed paths for this entity
128
+ * 2. Unknown/missing entity → deduplicated union of ALL pathMap values
129
+ */
130
+ declare function resolveRevalidationPaths(entity: string | undefined, pathMap: Record<string, string[]>): {
131
+ paths: string[];
132
+ fallback: boolean;
133
+ };
134
+ /**
135
+ * Creates a Next.js route handler that revalidates ISR pages
136
+ * when triggered by a Praxium platform webhook.
137
+ *
138
+ * Wraps processWebhook() with path resolution and revalidatePath() calls.
139
+ * Returns a Fetch API handler `(request: Request) => Promise<Response>`
140
+ * compatible with Next.js App Router route exports.
141
+ *
142
+ * @example
143
+ * ```typescript
144
+ * // app/api/revalidate/route.ts
145
+ * import { createRevalidationHandler } from '@praxium/sdk/webhooks'
146
+ *
147
+ * export const POST = createRevalidationHandler({
148
+ * secret: process.env.PRAXIUM_WEBHOOK_SECRET!,
149
+ * pathMap: {
150
+ * 'team': ['/nl/team', '/en/team'],
151
+ * 'rates': ['/nl/tarieven', '/en/rates'],
152
+ * 'faq': ['/nl/faq', '/en/faq'],
153
+ * 'opening-hours': ['/nl', '/en'],
154
+ * },
155
+ * })
156
+ * ```
157
+ */
158
+ declare function createRevalidationHandler(config: RevalidationConfig): (request: Request) => Promise<Response>;
159
+
160
+ export { type ProcessWebhookInput, type RevalidationConfig, WEBHOOK_SIGNATURE_HEADER, type WebhookFailure, type WebhookResult, type WebhookSuccess, createRevalidationHandler, processWebhook, resolveRevalidationPaths };
@@ -1,5 +1,5 @@
1
- // src/revalidation.ts
2
- var SIGNATURE_HEADER = "X-Praxium-Signature";
1
+ // src/webhooks.ts
2
+ var WEBHOOK_SIGNATURE_HEADER = "X-Praxium-Signature";
3
3
  var DEFAULT_MAX_TIMESTAMP_AGE_MS = 5 * 60 * 1e3;
4
4
  var CLOCK_SKEW_TOLERANCE_MS = 5 * 60 * 1e3;
5
5
  async function computeHmacSignature(secret, payload) {
@@ -46,6 +46,36 @@ function parseSignatureHeader(headerValue) {
46
46
  signature: signatureMatch[1]
47
47
  };
48
48
  }
49
+ async function processWebhook(input) {
50
+ const {
51
+ body,
52
+ signature: signatureHeader,
53
+ secret,
54
+ maxTimestampAge = DEFAULT_MAX_TIMESTAMP_AGE_MS
55
+ } = input;
56
+ const parsed = parseSignatureHeader(signatureHeader);
57
+ if (!parsed) {
58
+ return { valid: false, error: "Invalid signature format" };
59
+ }
60
+ const requestAgeMs = Date.now() - parsed.timestamp * 1e3;
61
+ if (requestAgeMs < -CLOCK_SKEW_TOLERANCE_MS) {
62
+ return { valid: false, error: "Request timestamp is in the future" };
63
+ }
64
+ if (requestAgeMs > maxTimestampAge) {
65
+ return { valid: false, error: "Request timestamp expired" };
66
+ }
67
+ const payload = `${parsed.timestamp}.${body}`;
68
+ const expectedSignature = await computeHmacSignature(secret, payload);
69
+ if (!isSecretValid(parsed.signature, expectedSignature)) {
70
+ return { valid: false, error: "Invalid signature" };
71
+ }
72
+ try {
73
+ const parsedBody = body ? JSON.parse(body) : {};
74
+ return { valid: true, entity: parsedBody.entity };
75
+ } catch {
76
+ return { valid: false, error: "Invalid JSON body" };
77
+ }
78
+ }
49
79
  function resolveRevalidationPaths(entity, pathMap) {
50
80
  if (entity && pathMap[entity]) {
51
81
  return { paths: pathMap[entity], fallback: false };
@@ -54,60 +84,32 @@ function resolveRevalidationPaths(entity, pathMap) {
54
84
  return { paths: allPaths, fallback: true };
55
85
  }
56
86
  function createRevalidationHandler(config) {
57
- const maxTimestampAge = config.maxTimestampAge ?? DEFAULT_MAX_TIMESTAMP_AGE_MS;
58
87
  return async (request) => {
59
- const signatureHeader = request.headers.get(SIGNATURE_HEADER);
88
+ const signatureHeader = request.headers.get(WEBHOOK_SIGNATURE_HEADER);
60
89
  if (!signatureHeader) {
61
90
  return Response.json(
62
- { error: `Missing ${SIGNATURE_HEADER} header` },
63
- { status: 401 }
64
- );
65
- }
66
- const parsed = parseSignatureHeader(signatureHeader);
67
- if (!parsed) {
68
- return Response.json(
69
- { error: "Invalid signature format" },
70
- { status: 401 }
71
- );
72
- }
73
- const requestAgeMs = Date.now() - parsed.timestamp * 1e3;
74
- if (requestAgeMs < -CLOCK_SKEW_TOLERANCE_MS) {
75
- return Response.json(
76
- { error: "Request timestamp is in the future" },
77
- { status: 401 }
78
- );
79
- }
80
- if (requestAgeMs > maxTimestampAge) {
81
- return Response.json(
82
- { error: "Request timestamp expired" },
91
+ { error: `Missing ${WEBHOOK_SIGNATURE_HEADER} header` },
83
92
  { status: 401 }
84
93
  );
85
94
  }
86
95
  const rawBody = await request.text();
87
- const payload = `${parsed.timestamp}.${rawBody}`;
88
- const expectedSignature = await computeHmacSignature(
89
- config.secret,
90
- payload
91
- );
92
- if (!isSecretValid(parsed.signature, expectedSignature)) {
93
- return Response.json(
94
- { error: "Invalid signature" },
95
- { status: 401 }
96
- );
97
- }
98
- let body;
99
- try {
100
- body = rawBody ? JSON.parse(rawBody) : {};
101
- } catch {
102
- return Response.json({ error: "Invalid JSON body" }, { status: 400 });
96
+ const result = await processWebhook({
97
+ body: rawBody,
98
+ signature: signatureHeader,
99
+ secret: config.secret,
100
+ maxTimestampAge: config.maxTimestampAge
101
+ });
102
+ if (!result.valid) {
103
+ const status = result.error === "Invalid JSON body" ? 400 : 401;
104
+ return Response.json({ error: result.error }, { status });
103
105
  }
104
106
  const { paths, fallback } = resolveRevalidationPaths(
105
- body.entity,
107
+ result.entity,
106
108
  config.pathMap
107
109
  );
108
110
  if (fallback) {
109
111
  console.warn(
110
- `[Revalidation] Unknown entity "${body.entity ?? "(none)"}" \u2014 falling back to full revalidation (${paths.length} paths)`
112
+ `[Webhook] Unknown entity "${result.entity ?? "(none)"}" \u2014 falling back to full revalidation (${paths.length} paths)`
111
113
  );
112
114
  }
113
115
  try {
@@ -125,6 +127,8 @@ function createRevalidationHandler(config) {
125
127
  };
126
128
  }
127
129
  export {
130
+ WEBHOOK_SIGNATURE_HEADER,
128
131
  createRevalidationHandler,
132
+ processWebhook,
129
133
  resolveRevalidationPaths
130
134
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@praxium/sdk",
3
- "version": "0.3.61",
3
+ "version": "0.3.68",
4
4
  "description": "Official TypeScript SDK for the Praxium platform API",
5
5
  "type": "module",
6
6
  "exports": {
@@ -8,9 +8,9 @@
8
8
  "import": "./dist/index.js",
9
9
  "types": "./dist/index.d.ts"
10
10
  },
11
- "./revalidation": {
12
- "import": "./dist/revalidation.js",
13
- "types": "./dist/revalidation.d.ts"
11
+ "./webhooks": {
12
+ "import": "./dist/webhooks.js",
13
+ "types": "./dist/webhooks.d.ts"
14
14
  }
15
15
  },
16
16
  "files": [
@@ -18,8 +18,8 @@
18
18
  ],
19
19
  "scripts": {
20
20
  "generate": "openapi-ts",
21
- "build": "tsup src/index.ts src/revalidation.ts --format esm --dts --clean --external next",
22
- "typecheck": "tsc --noEmit",
21
+ "build": "tsup",
22
+ "typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.test.json",
23
23
  "test": "vitest run",
24
24
  "test:watch": "vitest"
25
25
  },
@@ -1,95 +0,0 @@
1
- /**
2
- * ISR Revalidation Handler for Tenant Websites
3
- *
4
- * When admin updates data in the platform, a webhook triggers
5
- * revalidation on the tenant's public website. This handler
6
- * validates the HMAC signature and calls Next.js revalidatePath().
7
- *
8
- * Architecture (entity-driven, three-layer path agnosticism):
9
- * - Monolith sends { entity } — knows WHAT changed, not WHERE
10
- * - SDK looks up pathMap[entity] — pure lookup + security, path-agnostic
11
- * - Tenant website provides pathMap — owns WHERE pages live (locale-prefixed)
12
- *
13
- * Signature scheme (H6):
14
- * X-Praxium-Signature: t={unix_timestamp},sha256={HMAC-SHA256(secret, timestamp.body)}
15
- *
16
- * Security features:
17
- * - HMAC-SHA256 signature verification (secret never sent in body)
18
- * - Timestamp-based replay protection (default 5-minute window)
19
- * - Timing-safe signature comparison (prevents timing side-channel attacks)
20
- * - Web Crypto API (platform-agnostic: Edge, Node.js, browser)
21
- *
22
- * Usage in tenant website's `app/api/revalidate/route.ts`:
23
- *
24
- * ```ts
25
- * import { createRevalidationHandler } from '@praxium/sdk/revalidation'
26
- *
27
- * export const POST = createRevalidationHandler({
28
- * secret: process.env.PRAXIUM_REVALIDATION_SECRET!,
29
- * pathMap: {
30
- * 'team': ['/nl/team', '/en/team'],
31
- * 'rates': ['/nl/tarieven', '/en/rates'],
32
- * 'faq': ['/nl/faq', '/en/faq'],
33
- * 'opening-hours': ['/nl', '/en'],
34
- * 'all': ['/nl', '/en'],
35
- * },
36
- * })
37
- * ```
38
- */
39
- interface RevalidationConfig {
40
- /** Shared secret for HMAC signature verification */
41
- secret: string;
42
- /** Maximum age of request timestamp in milliseconds (default: 5 minutes) */
43
- maxTimestampAge?: number;
44
- /**
45
- * Entity → full paths to revalidate (including locale prefix).
46
- *
47
- * Paths are pre-computed by the tenant website — SDK does no path manipulation.
48
- * Each tenant configures its own paths based on its URL structure and locales.
49
- *
50
- * When a webhook arrives with `{ entity: 'team' }`, the SDK looks up
51
- * `pathMap['team']` and calls `revalidatePath()` for each path.
52
- *
53
- * Unknown entities fall back to revalidating ALL registered paths (union of
54
- * all pathMap values) with a console warning.
55
- *
56
- * @example
57
- * pathMap: {
58
- * 'team': ['/nl/team', '/en/team'],
59
- * 'rates': ['/nl/tarieven', '/en/rates'],
60
- * 'opening-hours': ['/nl', '/en'],
61
- * }
62
- */
63
- pathMap: Record<string, string[]>;
64
- }
65
- /**
66
- * Resolve entity to revalidation paths using the tenant's pathMap.
67
- *
68
- * The SDK is path-agnostic — it performs a pure lookup against the
69
- * tenant-provided pathMap. Paths are pre-computed by the tenant website
70
- * including locale prefixes (e.g., '/nl/tarieven', '/en/rates').
71
- *
72
- * Resolution priority:
73
- * 1. pathMap[entity] → pre-computed paths for this entity
74
- * 2. Unknown/missing entity → deduplicated union of ALL pathMap values
75
- * (full site revalidation as safe fallback)
76
- *
77
- * @returns paths to revalidate and whether fallback was used
78
- */
79
- declare function resolveRevalidationPaths(entity: string | undefined, pathMap: Record<string, string[]>): {
80
- paths: string[];
81
- fallback: boolean;
82
- };
83
- /**
84
- * Creates a Next.js route handler that revalidates ISR pages
85
- * when triggered by the Praxium platform webhook.
86
- *
87
- * Authentication uses HMAC-SHA256 signature verification with
88
- * timestamp-based replay protection (H6 security scheme).
89
- *
90
- * Path resolution is entity-driven: the monolith sends `{ entity }`,
91
- * the SDK looks up `pathMap[entity]` for pre-computed full paths.
92
- */
93
- declare function createRevalidationHandler(config: RevalidationConfig): (request: Request) => Promise<Response>;
94
-
95
- export { createRevalidationHandler, resolveRevalidationPaths };