@yak-io/nextjs 0.1.4 → 0.1.6

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,18 +164,18 @@ 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
@@ -184,7 +184,7 @@ During local development, routes are scanned directly from the filesystem—no s
184
184
 
185
185
  ### Recommended setup
186
186
 
187
- 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:
188
188
 
189
189
  ```json
190
190
  {
@@ -195,9 +195,35 @@ Add a `prebuild` script to generate the manifest before Next.js builds:
195
195
  }
196
196
  ```
197
197
 
198
- That's it! The manifest is generated to `./src/yak-routes-manifest.json` and automatically bundled with your serverless function. No code changes needed in your API route.
198
+ 2. Use the route manifest adapter in your handler:
199
199
 
200
- The manifest is placed in `./src/` so that Next.js file tracing includes it in the serverless bundle, making it available at runtime on platforms like Vercel.
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
+ ```
223
+
224
+ Pattern matching:
225
+ - Exact match: `"/pricing"` matches only `/pricing`
226
+ - Prefix match: `"/docs/*"` matches `/docs`, `/docs/getting-started`, etc.
201
227
 
202
228
  ### Alternative: explicit routes
203
229
 
@@ -201,8 +201,8 @@ function parseArgs() {
201
201
  const args = process.argv.slice(2);
202
202
  let appDir = "./src/app";
203
203
  let pagesDir = undefined;
204
- // Default to ./src/ so the file is included in Next.js serverless bundle via file tracing
205
- let output = "./src/yak-routes-manifest.json";
204
+ // Default to ./src/yak.routes.ts - TypeScript module that gets bundled
205
+ let output = "./src/yak.routes.ts";
206
206
  let help = false;
207
207
  for (let i = 0; i < args.length; i++) {
208
208
  const arg = args[i];
@@ -231,7 +231,7 @@ function showHelp() {
231
231
  console.log(`
232
232
  Yak Next.js Route Manifest Generator
233
233
 
234
- 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.
235
235
 
236
236
  Usage:
237
237
  yak-nextjs generate-manifest [options]
@@ -239,16 +239,36 @@ Usage:
239
239
  Options:
240
240
  --app-dir <path> Path to Next.js app directory (default: ./src/app)
241
241
  --pages-dir <path> Path to Next.js pages directory (optional)
242
- --output <path> Output file path (default: ./src/yak-routes-manifest.json)
242
+ --output <path> Output file path (default: ./src/yak.routes.ts)
243
243
  --help, -h Show this help message
244
244
 
245
245
  Examples:
246
246
  yak-nextjs generate-manifest
247
247
  yak-nextjs generate-manifest --app-dir ./app
248
- yak-nextjs generate-manifest --pages-dir ./src/pages
249
- yak-nextjs generate-manifest --app-dir ./app --pages-dir ./pages
248
+ yak-nextjs generate-manifest --output ./src/generated/yak.routes.ts
250
249
  `);
251
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
+ }
252
272
  /**
253
273
  * Main entry point
254
274
  */
@@ -285,15 +305,17 @@ function main() {
285
305
  process.exit(1);
286
306
  }
287
307
  // Deduplicate routes by path (app router takes precedence)
288
- const uniqueRoutes = Array.from(new Map(routes.map(r => [r.path, r])).values());
289
- const manifest = {
290
- routes: uniqueRoutes.sort((a, b) => a.path.localeCompare(b.path)),
291
- generated_at: new Date().toISOString(),
292
- };
308
+ const uniqueRoutes = Array.from(new Map(routes.map(r => [r.path, r])).values()).sort((a, b) => a.path.localeCompare(b.path));
293
309
  const outputPath = path.resolve(process.cwd(), output);
294
- // Write JSON manifest
295
- fs.writeFileSync(outputPath, JSON.stringify(manifest, null, 2), "utf-8");
296
- 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`);
297
319
  console.log(` Output: ${outputPath}`);
298
320
  }
299
321
  // Run the CLI
@@ -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.4",
3
+ "version": "0.1.6",
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",
@@ -30,23 +30,38 @@
30
30
  "LICENSE"
31
31
  ],
32
32
  "sideEffects": false,
33
+ "main": "./dist/index.client.js",
34
+ "module": "./dist/index.client.js",
35
+ "types": "./dist/index.client.d.ts",
33
36
  "exports": {
34
37
  "./client": {
35
38
  "types": "./dist/index.client.d.ts",
36
- "import": "./dist/index.client.js"
39
+ "import": "./dist/index.client.js",
40
+ "default": "./dist/index.client.js"
37
41
  },
38
42
  "./server": {
39
43
  "types": "./dist/index.server.d.ts",
40
- "import": "./dist/index.server.js"
44
+ "import": "./dist/index.server.js",
45
+ "default": "./dist/index.server.js"
41
46
  },
42
47
  "./package.json": "./package.json"
43
48
  },
49
+ "typesVersions": {
50
+ "*": {
51
+ "client": [
52
+ "./dist/index.client.d.ts"
53
+ ],
54
+ "server": [
55
+ "./dist/index.server.d.ts"
56
+ ]
57
+ }
58
+ },
44
59
  "bin": {
45
60
  "yak-nextjs": "./dist/cli/generate-manifest.js"
46
61
  },
47
62
  "dependencies": {
48
- "@yak-io/javascript": "0.1.0",
49
- "@yak-io/react": "0.1.0"
63
+ "@yak-io/javascript": "0.1.1",
64
+ "@yak-io/react": "0.1.1"
50
65
  },
51
66
  "peerDependencies": {
52
67
  "next": "^14.0.0 || ^15.0.0",