@yak-io/nextjs 0.1.3 → 0.1.5

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
@@ -164,29 +164,27 @@ Behind the scenes `@yak-io/javascript` merges every `RouteSource` into a single
164
164
  yak-nextjs generate-manifest
165
165
  ```
166
166
 
167
- Use the CLI to pre-compute a manifest at build time. The JSON matches the runtime manifest structure exposed by the handlers.
167
+ Use the CLI to generate a TypeScript module with your routes at build time.
168
168
 
169
169
  **Options:**
170
170
  - `--app-dir <path>` – Path to Next.js app directory (default: `./src/app`)
171
171
  - `--pages-dir <path>` – Path to Next.js pages directory (optional, scanned in addition to app-dir)
172
- - `--output <path>` – Output file path (default: `./public/yak-routes-manifest.json`)
172
+ - `--output <path>` – Output file path (default: `./src/yak.routes.ts`)
173
173
 
174
174
  **Examples:**
175
175
  ```bash
176
176
  yak-nextjs generate-manifest
177
177
  yak-nextjs generate-manifest --pages-dir ./src/pages
178
- yak-nextjs generate-manifest --app-dir ./app --pages-dir ./pages
178
+ yak-nextjs generate-manifest --app-dir ./app --output ./src/generated/routes.ts
179
179
  ```
180
180
 
181
181
  ## Route Manifest for Production
182
182
 
183
183
  During local development, routes are scanned directly from the filesystem—no setup needed. However, when you build your Next.js app for production, only the compiled `.next` output is included. Source files like `./src/app` are not present at runtime.
184
184
 
185
- To enable route scanning in production builds, generate a manifest at build time.
186
-
187
185
  ### Recommended setup
188
186
 
189
- Add a `prebuild` script to generate the manifest before Next.js builds:
187
+ 1. Add a `prebuild` script to generate the manifest before Next.js builds:
190
188
 
191
189
  ```json
192
190
  {
@@ -197,9 +195,35 @@ Add a `prebuild` script to generate the manifest before Next.js builds:
197
195
  }
198
196
  ```
199
197
 
200
- That's it! The manifest is generated to `./public/yak-routes-manifest.json` and the handler automatically fetches it at runtime on serverless platforms like Vercel. No code changes needed.
198
+ 2. Use the route manifest adapter in your handler:
199
+
200
+ ```ts
201
+ // app/api/yak/[...yak]/route.ts
202
+ import { createNextYakHandler, createRouteManifestAdapter } from "@yak-io/nextjs/server";
203
+ import { routes } from "@/yak.routes";
204
+
205
+ export const { GET, POST } = createNextYakHandler({
206
+ routes: createRouteManifestAdapter({ routes }),
207
+ });
208
+ ```
209
+
210
+ The generated TypeScript module is imported directly, ensuring it's bundled with your serverless function automatically.
211
+
212
+ ### Route filtering
213
+
214
+ Use `allowedRoutes` and `disallowedRoutes` to control which routes are exposed (similar to tRPC adapter):
215
+
216
+ ```ts
217
+ createRouteManifestAdapter({
218
+ routes,
219
+ allowedRoutes: ["/docs/*", "/pricing", "/"],
220
+ disallowedRoutes: ["/docs/internal/*"],
221
+ })
222
+ ```
201
223
 
202
- The handler automatically detects the deployment environment (Vercel via `VERCEL_URL`, Netlify via `URL`, or custom `NEXT_PUBLIC_BASE_URL`) and fetches the manifest from the public folder.
224
+ Pattern matching:
225
+ - Exact match: `"/pricing"` matches only `/pricing`
226
+ - Prefix match: `"/docs/*"` matches `/docs`, `/docs/getting-started`, etc.
203
227
 
204
228
  ### Alternative: explicit routes
205
229
 
@@ -11,7 +11,7 @@
11
11
  * Options:
12
12
  * --app-dir <path> Path to Next.js app directory (default: ./src/app)
13
13
  * --pages-dir <path> Path to Next.js pages directory (optional, scanned in addition to app-dir)
14
- * --output <path> Output file path (default: ./public/yak-routes-manifest.json)
14
+ * --output <path> Output file path (default: ./src/yak-routes-manifest.json)
15
15
  */
16
16
  export {};
17
17
  //# sourceMappingURL=generate-manifest.d.ts.map
@@ -11,7 +11,7 @@
11
11
  * Options:
12
12
  * --app-dir <path> Path to Next.js app directory (default: ./src/app)
13
13
  * --pages-dir <path> Path to Next.js pages directory (optional, scanned in addition to app-dir)
14
- * --output <path> Output file path (default: ./public/yak-routes-manifest.json)
14
+ * --output <path> Output file path (default: ./src/yak-routes-manifest.json)
15
15
  */
16
16
  import * as fs from "node:fs";
17
17
  import * as path from "node:path";
@@ -201,7 +201,8 @@ function parseArgs() {
201
201
  const args = process.argv.slice(2);
202
202
  let appDir = "./src/app";
203
203
  let pagesDir = undefined;
204
- let output = "./public/yak-routes-manifest.json";
204
+ // Default to ./src/yak.routes.ts - TypeScript module that gets bundled
205
+ let output = "./src/yak.routes.ts";
205
206
  let help = false;
206
207
  for (let i = 0; i < args.length; i++) {
207
208
  const arg = args[i];
@@ -230,7 +231,7 @@ function showHelp() {
230
231
  console.log(`
231
232
  Yak Next.js Route Manifest Generator
232
233
 
233
- Scans a Next.js app directory and generates a manifest of all available page routes.
234
+ Scans a Next.js app directory and generates a TypeScript module with route definitions.
234
235
 
235
236
  Usage:
236
237
  yak-nextjs generate-manifest [options]
@@ -238,16 +239,36 @@ Usage:
238
239
  Options:
239
240
  --app-dir <path> Path to Next.js app directory (default: ./src/app)
240
241
  --pages-dir <path> Path to Next.js pages directory (optional)
241
- --output <path> Output file path (default: ./public/yak-routes-manifest.json)
242
+ --output <path> Output file path (default: ./src/yak.routes.ts)
242
243
  --help, -h Show this help message
243
244
 
244
245
  Examples:
245
246
  yak-nextjs generate-manifest
246
247
  yak-nextjs generate-manifest --app-dir ./app
247
- yak-nextjs generate-manifest --pages-dir ./src/pages
248
- yak-nextjs generate-manifest --app-dir ./app --pages-dir ./pages
248
+ yak-nextjs generate-manifest --output ./src/generated/yak.routes.ts
249
249
  `);
250
250
  }
251
+ /**
252
+ * Generate TypeScript module content
253
+ */
254
+ function generateTypeScriptModule(routes) {
255
+ const routesJson = JSON.stringify(routes, null, 2);
256
+ return `/**
257
+ * Auto-generated by yak-nextjs generate-manifest
258
+ * DO NOT EDIT - This file is regenerated at build time
259
+ *
260
+ * Generated: ${new Date().toISOString()}
261
+ */
262
+
263
+ import type { RouteInfo } from "@yak-io/nextjs/server";
264
+
265
+ /**
266
+ * All scanned routes from your Next.js application.
267
+ * Use with createRouteManifestAdapter for filtering options.
268
+ */
269
+ export const routes: RouteInfo[] = ${routesJson} as const;
270
+ `;
271
+ }
251
272
  /**
252
273
  * Main entry point
253
274
  */
@@ -284,15 +305,17 @@ function main() {
284
305
  process.exit(1);
285
306
  }
286
307
  // Deduplicate routes by path (app router takes precedence)
287
- const uniqueRoutes = Array.from(new Map(routes.map(r => [r.path, r])).values());
288
- const manifest = {
289
- routes: uniqueRoutes.sort((a, b) => a.path.localeCompare(b.path)),
290
- generated_at: new Date().toISOString(),
291
- };
308
+ const uniqueRoutes = Array.from(new Map(routes.map(r => [r.path, r])).values()).sort((a, b) => a.path.localeCompare(b.path));
292
309
  const outputPath = path.resolve(process.cwd(), output);
293
- // Write JSON manifest
294
- fs.writeFileSync(outputPath, JSON.stringify(manifest, null, 2), "utf-8");
295
- console.log(`✅ Generated manifest with ${uniqueRoutes.length} page routes`);
310
+ // Ensure output directory exists
311
+ const outputDir = path.dirname(outputPath);
312
+ if (!fs.existsSync(outputDir)) {
313
+ fs.mkdirSync(outputDir, { recursive: true });
314
+ }
315
+ // Write TypeScript module
316
+ const content = generateTypeScriptModule(uniqueRoutes);
317
+ fs.writeFileSync(outputPath, content, "utf-8");
318
+ console.log(`✅ Generated route manifest with ${uniqueRoutes.length} routes`);
296
319
  console.log(` Output: ${outputPath}`);
297
320
  }
298
321
  // Run the CLI
@@ -3,6 +3,7 @@ import type { RouteSourceInput, ToolSourceInput, RouteInfo, RouteManifest, ToolM
3
3
  * Load a pre-built route manifest from disk (JSON file).
4
4
  *
5
5
  * This works in traditional Node.js deployments where the filesystem is available.
6
+ * For Vercel serverless, the manifest must be imported directly in your route file.
6
7
  *
7
8
  * Generate the manifest at build time using:
8
9
  * yak-nextjs generate-manifest
@@ -1 +1 @@
1
- {"version":3,"file":"createNextYakHandler.d.ts","sourceRoot":"","sources":["../../src/server/createNextYakHandler.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACV,gBAAgB,EAChB,eAAe,EACf,SAAS,EACT,aAAa,EACb,YAAY,EACZ,YAAY,EACb,MAAM,2BAA2B,CAAC;AAiBnC;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAgB7E;AAgED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,EAAE,CAe7D;AAED,MAAM,MAAM,kBAAkB,GAAG;IAC/B,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;IACvC,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC,YAAY,CAAC,CAAC;IACvC,WAAW,CAAC,EAAE,YAAY,CAAC;CAC5B,CAAC;AAEF;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,oBAAoB;;;EAKhE;AAmGD,MAAM,MAAM,0BAA0B,GAAG;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;IACvC,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC,YAAY,CAAC,CAAC;CACxC,CAAC;AAEF,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,0BAA0B,wCAK5E;AAED,MAAM,MAAM,yBAAyB,GAAG;IACtC,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC,YAAY,CAAC,CAAC;IACvC,WAAW,EAAE,YAAY,CAAC;CAC3B,CAAC;AAEF,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,yBAAyB,uCAW1E"}
1
+ {"version":3,"file":"createNextYakHandler.d.ts","sourceRoot":"","sources":["../../src/server/createNextYakHandler.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACV,gBAAgB,EAChB,eAAe,EACf,SAAS,EACT,aAAa,EACb,YAAY,EACZ,YAAY,EACb,MAAM,2BAA2B,CAAC;AAkBnC;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAgB7E;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,EAAE,CAe7D;AAED,MAAM,MAAM,kBAAkB,GAAG;IAC/B,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;IACvC,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC,YAAY,CAAC,CAAC;IACvC,WAAW,CAAC,EAAE,YAAY,CAAC;CAC5B,CAAC;AAEF;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,oBAAoB;;;EAKhE;AA0FD,MAAM,MAAM,0BAA0B,GAAG;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;IACvC,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC,YAAY,CAAC,CAAC;CACxC,CAAC;AAEF,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,0BAA0B,wCAK5E;AAED,MAAM,MAAM,yBAAyB,GAAG;IACtC,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC,YAAY,CAAC,CAAC;IACvC,WAAW,EAAE,YAAY,CAAC;CAC3B,CAAC;AAEF,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,yBAAyB,uCAW1E"}
@@ -5,19 +5,22 @@ import { scanRoutes } from "./scan-routes.js";
5
5
  /**
6
6
  * Default paths to check for pre-built route manifests (JSON files).
7
7
  * These are read via fs.readFileSync at runtime.
8
+ *
9
+ * Priority:
10
+ * 1. ./src/yak-routes-manifest.json - Default output, bundled by Next.js file tracing
11
+ * 2. ./yak-routes-manifest.json - Root fallback
12
+ * 3. ./public/yak-routes-manifest.json - Legacy location (doesn't work on Vercel serverless)
8
13
  */
9
14
  const DEFAULT_MANIFEST_PATHS = [
10
- "./public/yak-routes-manifest.json",
15
+ "./src/yak-routes-manifest.json",
11
16
  "./yak-routes-manifest.json",
17
+ "./public/yak-routes-manifest.json",
12
18
  ];
13
- /**
14
- * Public URL path where the manifest is served from (when in public/).
15
- */
16
- const PUBLIC_MANIFEST_URL = "/yak-routes-manifest.json";
17
19
  /**
18
20
  * Load a pre-built route manifest from disk (JSON file).
19
21
  *
20
22
  * This works in traditional Node.js deployments where the filesystem is available.
23
+ * For Vercel serverless, the manifest must be imported directly in your route file.
21
24
  *
22
25
  * Generate the manifest at build time using:
23
26
  * yak-nextjs generate-manifest
@@ -41,59 +44,6 @@ export function loadRouteManifest(manifestPath) {
41
44
  }
42
45
  return null;
43
46
  }
44
- /**
45
- * Fetch the route manifest from the public URL.
46
- * Used in serverless environments where filesystem access is not available.
47
- */
48
- async function fetchRouteManifest() {
49
- // Try to determine the base URL for fetching
50
- const baseUrl = getBaseUrl();
51
- if (!baseUrl) {
52
- return null;
53
- }
54
- try {
55
- const url = new URL(PUBLIC_MANIFEST_URL, baseUrl);
56
- const response = await fetch(url.toString(), {
57
- headers: { "Accept": "application/json" },
58
- cache: "no-store",
59
- });
60
- if (!response.ok) {
61
- return null;
62
- }
63
- const manifest = await response.json();
64
- if (manifest?.routes) {
65
- return manifest;
66
- }
67
- }
68
- catch {
69
- // Fetch failed
70
- }
71
- return null;
72
- }
73
- /**
74
- * Get the base URL for the current deployment.
75
- * Supports Vercel, Netlify, and custom configurations.
76
- */
77
- function getBaseUrl() {
78
- // Vercel provides VERCEL_URL (without protocol)
79
- if (process.env.VERCEL_URL) {
80
- const protocol = process.env.VERCEL_ENV === "development" ? "http" : "https";
81
- return `${protocol}://${process.env.VERCEL_URL}`;
82
- }
83
- // Netlify provides URL
84
- if (process.env.URL) {
85
- return process.env.URL;
86
- }
87
- // Custom base URL
88
- if (process.env.NEXT_PUBLIC_BASE_URL) {
89
- return process.env.NEXT_PUBLIC_BASE_URL;
90
- }
91
- // For local development
92
- if (process.env.NODE_ENV === "development") {
93
- return "http://localhost:3000";
94
- }
95
- return null;
96
- }
97
47
  /**
98
48
  * Load routes from a pre-built manifest.
99
49
  * Throws if manifest is not found.
@@ -138,22 +88,14 @@ async function tryLoadRoutes(appDir) {
138
88
  if (manifest) {
139
89
  return manifest.routes;
140
90
  }
141
- // Try fetching from public URL (works on Vercel/serverless)
142
- const fetchedManifest = await fetchRouteManifest();
143
- if (fetchedManifest) {
144
- return fetchedManifest.routes;
145
- }
146
91
  // Neither source nor manifest available - provide helpful error
147
- throw new Error(`App directory not found: ${targetDir}\n\n` +
148
- `This typically happens in production (Vercel, etc.) where source files aren't deployed.\n\n` +
149
- `Solutions:\n` +
150
- `1. Generate a route manifest at build time (recommended):\n` +
151
- ` Add to package.json: "prebuild": "yak-nextjs generate-manifest"\n` +
152
- ` The manifest will be placed in public/ and automatically loaded.\n\n` +
153
- `2. Provide routes explicitly:\n` +
154
- ` createNextYakHandler({ routes: [{ path: "/", title: "Home" }, ...] })\n\n` +
155
- `3. Use getRoutes callback:\n` +
156
- ` createNextYakHandler({ getRoutes: async () => [...] })`);
92
+ throw new Error(`Route manifest not found.\n\n` +
93
+ `Generate the manifest at build time by adding to package.json:\n` +
94
+ ` "prebuild": "yak-nextjs generate-manifest"\n\n` +
95
+ `The manifest will be created at ./src/yak-routes-manifest.json and automatically\n` +
96
+ `bundled with your serverless function.\n\n` +
97
+ `Alternatively, provide routes explicitly:\n` +
98
+ ` createNextYakHandler({ routes: [{ path: "/", title: "Home" }] })`);
157
99
  }
158
100
  function resolveRouteSources(config) {
159
101
  if (config.routes) {
@@ -2,5 +2,7 @@ export { scanRoutes } from "./scan-routes.js";
2
2
  export type { ScanRoutesOptions } from "./scan-routes.js";
3
3
  export { createNextYakHandler, createNextYakConfigHandler, createNextYakToolsHandler, loadRouteManifest, loadRoutes, } from "./createNextYakHandler.js";
4
4
  export type { NextYakHandlerConfig, NextYakConfigHandlerConfig, NextYakToolsHandlerConfig, NextYakRouteFilter, } from "./createNextYakHandler.js";
5
+ export { createRouteManifestAdapter } from "./route-manifest-adapter.js";
6
+ export type { RouteManifestAdapterConfig } from "./route-manifest-adapter.js";
5
7
  export type { ToolExecutor, ToolCallPayload, ToolCallResult, ToolDefinition, ToolManifest, RouteInfo, RouteManifest, ChatConfig, } from "@yak-io/javascript/server";
6
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,YAAY,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAE1D,OAAO,EACN,oBAAoB,EACpB,0BAA0B,EAC1B,yBAAyB,EACzB,iBAAiB,EACjB,UAAU,GACV,MAAM,2BAA2B,CAAC;AACnC,YAAY,EACX,oBAAoB,EACpB,0BAA0B,EAC1B,yBAAyB,EACzB,kBAAkB,GAClB,MAAM,2BAA2B,CAAC;AAEnC,YAAY,EACX,YAAY,EACZ,eAAe,EACf,cAAc,EACd,cAAc,EACd,YAAY,EACZ,SAAS,EACT,aAAa,EACb,UAAU,GACV,MAAM,2BAA2B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,YAAY,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAE1D,OAAO,EACN,oBAAoB,EACpB,0BAA0B,EAC1B,yBAAyB,EACzB,iBAAiB,EACjB,UAAU,GACV,MAAM,2BAA2B,CAAC;AACnC,YAAY,EACX,oBAAoB,EACpB,0BAA0B,EAC1B,yBAAyB,EACzB,kBAAkB,GAClB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAC;AACzE,YAAY,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAC;AAE9E,YAAY,EACX,YAAY,EACZ,eAAe,EACf,cAAc,EACd,cAAc,EACd,YAAY,EACZ,SAAS,EACT,aAAa,EACb,UAAU,GACV,MAAM,2BAA2B,CAAC"}
@@ -1,2 +1,3 @@
1
1
  export { scanRoutes } from "./scan-routes.js";
2
2
  export { createNextYakHandler, createNextYakConfigHandler, createNextYakToolsHandler, loadRouteManifest, loadRoutes, } from "./createNextYakHandler.js";
3
+ export { createRouteManifestAdapter } from "./route-manifest-adapter.js";
@@ -0,0 +1,73 @@
1
+ import type { RouteInfo, RouteSource } from "@yak-io/javascript/server";
2
+ /**
3
+ * Configuration for creating a route manifest adapter
4
+ */
5
+ export type RouteManifestAdapterConfig = {
6
+ /**
7
+ * The routes from the generated manifest.
8
+ * Import from the generated file: `import { routes } from "@/yak.routes"`
9
+ */
10
+ routes: RouteInfo[];
11
+ /**
12
+ * Optional ID for this route source (default: "manifest")
13
+ */
14
+ id?: string;
15
+ /**
16
+ * List of allowed route paths, e.g. ["/", "/docs", "/pricing"].
17
+ * Supports exact matches and prefix patterns ending with `*`.
18
+ * If provided, only these routes will be included.
19
+ * If omitted, all routes are allowed by default.
20
+ *
21
+ * @example
22
+ * ```ts
23
+ * allowedRoutes: ["/docs/*", "/pricing", "/"]
24
+ * ```
25
+ */
26
+ allowedRoutes?: string[];
27
+ /**
28
+ * List of disallowed route paths, e.g. ["/admin/*", "/internal/*"].
29
+ * Supports exact matches and prefix patterns ending with `*`.
30
+ * These routes will be excluded even if they would otherwise be allowed.
31
+ * Applied after allowedRoutes filtering.
32
+ *
33
+ * @example
34
+ * ```ts
35
+ * disallowedRoutes: ["/admin/*", "/settings/billing"]
36
+ * ```
37
+ */
38
+ disallowedRoutes?: string[];
39
+ };
40
+ /**
41
+ * Create a route source adapter from an imported route manifest.
42
+ *
43
+ * This adapter allows you to use generated route manifests with optional
44
+ * filtering to control which routes are exposed to the chatbot.
45
+ *
46
+ * @example Basic usage - all routes
47
+ * ```ts
48
+ * import { createNextYakHandler } from "@yak-io/nextjs/server";
49
+ * import { createRouteManifestAdapter } from "@yak-io/nextjs/server";
50
+ * import { routes } from "@/yak.routes";
51
+ *
52
+ * export const { GET, POST } = createNextYakHandler({
53
+ * routes: createRouteManifestAdapter({ routes }),
54
+ * });
55
+ * ```
56
+ *
57
+ * @example With filtering
58
+ * ```ts
59
+ * import { createNextYakHandler } from "@yak-io/nextjs/server";
60
+ * import { createRouteManifestAdapter } from "@yak-io/nextjs/server";
61
+ * import { routes } from "@/yak.routes";
62
+ *
63
+ * export const { GET, POST } = createNextYakHandler({
64
+ * routes: createRouteManifestAdapter({
65
+ * routes,
66
+ * allowedRoutes: ["/docs/*", "/pricing", "/"],
67
+ * disallowedRoutes: ["/docs/internal/*"],
68
+ * }),
69
+ * });
70
+ * ```
71
+ */
72
+ export declare function createRouteManifestAdapter(config: RouteManifestAdapterConfig): RouteSource;
73
+ //# sourceMappingURL=route-manifest-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route-manifest-adapter.d.ts","sourceRoot":"","sources":["../../src/server/route-manifest-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAExE;;GAEG;AACH,MAAM,MAAM,0BAA0B,GAAG;IACvC;;;OAGG;IACH,MAAM,EAAE,SAAS,EAAE,CAAC;IAEpB;;OAEG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;IAEZ;;;;;;;;;;OAUG;IACH,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IAEzB;;;;;;;;;;OAUG;IACH,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC7B,CAAC;AAiDF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,0BAA0B,GACjC,WAAW,CASb"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Check if a route path matches a pattern.
3
+ * Supports exact matches and prefix patterns ending with `*`.
4
+ */
5
+ function matchesPattern(pattern, routePath) {
6
+ if (pattern.endsWith("/*")) {
7
+ const prefix = pattern.slice(0, -1); // Remove the *
8
+ return routePath === prefix.slice(0, -1) || routePath.startsWith(prefix);
9
+ }
10
+ return pattern === routePath;
11
+ }
12
+ /**
13
+ * Filter routes based on allowed and disallowed patterns.
14
+ */
15
+ function filterRoutes(routes, allowedRoutes, disallowedRoutes) {
16
+ return routes.filter((route) => {
17
+ const path = route.path;
18
+ // If allowedRoutes is set, route must match at least one pattern
19
+ if (allowedRoutes && allowedRoutes.length > 0) {
20
+ const isAllowed = allowedRoutes.some((pattern) => matchesPattern(pattern, path));
21
+ if (!isAllowed) {
22
+ return false;
23
+ }
24
+ }
25
+ // If disallowedRoutes is set, route must not match any pattern
26
+ if (disallowedRoutes && disallowedRoutes.length > 0) {
27
+ const isDisallowed = disallowedRoutes.some((pattern) => matchesPattern(pattern, path));
28
+ if (isDisallowed) {
29
+ return false;
30
+ }
31
+ }
32
+ return true;
33
+ });
34
+ }
35
+ /**
36
+ * Create a route source adapter from an imported route manifest.
37
+ *
38
+ * This adapter allows you to use generated route manifests with optional
39
+ * filtering to control which routes are exposed to the chatbot.
40
+ *
41
+ * @example Basic usage - all routes
42
+ * ```ts
43
+ * import { createNextYakHandler } from "@yak-io/nextjs/server";
44
+ * import { createRouteManifestAdapter } from "@yak-io/nextjs/server";
45
+ * import { routes } from "@/yak.routes";
46
+ *
47
+ * export const { GET, POST } = createNextYakHandler({
48
+ * routes: createRouteManifestAdapter({ routes }),
49
+ * });
50
+ * ```
51
+ *
52
+ * @example With filtering
53
+ * ```ts
54
+ * import { createNextYakHandler } from "@yak-io/nextjs/server";
55
+ * import { createRouteManifestAdapter } from "@yak-io/nextjs/server";
56
+ * import { routes } from "@/yak.routes";
57
+ *
58
+ * export const { GET, POST } = createNextYakHandler({
59
+ * routes: createRouteManifestAdapter({
60
+ * routes,
61
+ * allowedRoutes: ["/docs/*", "/pricing", "/"],
62
+ * disallowedRoutes: ["/docs/internal/*"],
63
+ * }),
64
+ * });
65
+ * ```
66
+ */
67
+ export function createRouteManifestAdapter(config) {
68
+ const { routes, id = "manifest", allowedRoutes, disallowedRoutes } = config;
69
+ return {
70
+ id,
71
+ getRoutes: async () => {
72
+ return filterRoutes(routes, allowedRoutes, disallowedRoutes);
73
+ },
74
+ };
75
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yak-io/nextjs",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "Next.js SDK for embedding yak chatbot with route manifest generation",
5
5
  "type": "module",
6
6
  "license": "SEE LICENSE IN LICENSE",