@yak-io/nextjs 0.1.0 → 0.1.2

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
@@ -161,17 +161,90 @@ Behind the scenes `@yak-io/javascript` merges every `RouteSource` into a single
161
161
  ## CLI: route manifest generator
162
162
 
163
163
  ```bash
164
- yak-nextjs generate-manifest --app-dir ./src/app --output ./yak-routes.json
164
+ yak-nextjs generate-manifest
165
165
  ```
166
166
 
167
167
  Use the CLI when you prefer to pre-compute a manifest at build time. The JSON matches the runtime manifest structure exposed by the handlers.
168
168
 
169
+ **Options:**
170
+ - `--app-dir <path>` – Path to Next.js app directory (default: `./src/app`)
171
+ - `--pages-dir <path>` – Path to Next.js pages directory (optional, scanned in addition to app-dir)
172
+ - `--output <path>` – Output file path (default: `./yak-routes-manifest.json`)
173
+
174
+ **Examples:**
175
+ ```bash
176
+ yak-nextjs generate-manifest
177
+ yak-nextjs generate-manifest --pages-dir ./src/pages
178
+ yak-nextjs generate-manifest --app-dir ./app --pages-dir ./pages
179
+ ```
180
+
181
+ ## Route Manifest for Production
182
+
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
+
185
+ To enable route scanning in production builds, generate a manifest at build time.
186
+
187
+ ### Recommended setup
188
+
189
+ Add a `prebuild` script to generate the manifest before Next.js builds:
190
+
191
+ ```json
192
+ {
193
+ "scripts": {
194
+ "prebuild": "yak-nextjs generate-manifest",
195
+ "build": "next build"
196
+ }
197
+ }
198
+ ```
199
+
200
+ This uses the defaults (`./src/app` → `./yak-routes-manifest.json`). Customize if needed:
201
+
202
+ ```json
203
+ {
204
+ "scripts": {
205
+ "prebuild": "yak-nextjs generate-manifest --app-dir ./app --output ./routes.json"
206
+ }
207
+ }
208
+ ```
209
+
210
+ > **Important:** The manifest must be in the project root (not `public/`). On Vercel and other serverless platforms, files in `public/` are served via CDN and are not available on the function's filesystem.
211
+
212
+ The handler checks these locations automatically:
213
+ 1. `./yak-routes-manifest.json`
214
+ 2. `./.next/yak-routes-manifest.json`
215
+ 3. `./public/yak-routes-manifest.json` (only works in non-serverless environments)
216
+
217
+ ### Alternative: explicit routes
218
+
219
+ If you prefer not to use filesystem scanning, provide routes explicitly:
220
+
221
+ ```ts
222
+ export const { GET, POST } = createNextYakHandler({
223
+ routes: [
224
+ { path: "/", title: "Home" },
225
+ { path: "/pricing", title: "Pricing" },
226
+ ],
227
+ });
228
+ ```
229
+
230
+ ### Loading a custom manifest location
231
+
232
+ ```ts
233
+ import { createNextYakHandler, loadRoutes } from "@yak-io/nextjs/server";
234
+
235
+ export const { GET, POST } = createNextYakHandler({
236
+ routes: loadRoutes("./custom/manifest.json"),
237
+ });
238
+ ```
239
+
169
240
  ## API surface (server)
170
241
 
171
242
  `@yak-io/nextjs/server` exports:
172
243
 
173
244
  - `scanRoutes(directory: string, options?: { directoryType?: "app" | "pages" })` – low-level filesystem scanner (useful for precomputing manifests or composing custom sources). Only captures page routes, extracting `title` and `description` from static metadata exports.
174
- - `createNextYakHandler(config)` – unified GET + POST handler (wrapping `createYakHandler`). When `routes`/`getRoutes` are omitted it auto-scans `./src/app` and `./src/pages` (override with `appDir`/`pagesDir`, and narrow results via `routeFilter?: { include?: RegExp[]; exclude?: RegExp[] }`).
245
+ - `loadRouteManifest(path?: string)` – load a pre-built JSON manifest, returns `null` if not found. Checks `./yak-routes-manifest.json`, `./.next/yak-routes-manifest.json`, and `./public/yak-routes-manifest.json` by default.
246
+ - `loadRoutes(path?: string)` – load routes from a manifest, throws with helpful error if not found.
247
+ - `createNextYakHandler(config)` – unified GET + POST handler (wrapping `createYakHandler`). When `routes`/`getRoutes` are omitted it auto-scans `./src/app` and `./src/pages` (override with `appDir`/`pagesDir`, and narrow results via `routeFilter?: { include?: RegExp[]; exclude?: RegExp[] }`). In production, automatically falls back to pre-built manifests.
175
248
  - `createNextYakConfigHandler(config)` – GET-only convenience wrapper.
176
249
  - `createNextYakToolsHandler(config)` – POST-only wrapper.
177
250
  - Re-exported types from `@yak-io/javascript/server` (RouteInfo, RouteManifest, ToolDefinition, ToolManifest, ToolExecutor, ChatConfig, RouteSourceInput, ToolSourceInput, etc.).
@@ -9,7 +9,8 @@
9
9
  * yak-nextjs generate-manifest [options]
10
10
  *
11
11
  * Options:
12
- * --app-dir <path> Path to Next.js app directory (default: ./app)
12
+ * --app-dir <path> Path to Next.js app directory (default: ./src/app)
13
+ * --pages-dir <path> Path to Next.js pages directory (optional, scanned in addition to app-dir)
13
14
  * --output <path> Output file path (default: ./yak-routes-manifest.json)
14
15
  */
15
16
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"generate-manifest.d.ts","sourceRoot":"","sources":["../../src/cli/generate-manifest.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;GAYG"}
1
+ {"version":3,"file":"generate-manifest.d.ts","sourceRoot":"","sources":["../../src/cli/generate-manifest.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;;GAaG"}
@@ -9,7 +9,8 @@
9
9
  * yak-nextjs generate-manifest [options]
10
10
  *
11
11
  * Options:
12
- * --app-dir <path> Path to Next.js app directory (default: ./app)
12
+ * --app-dir <path> Path to Next.js app directory (default: ./src/app)
13
+ * --pages-dir <path> Path to Next.js pages directory (optional, scanned in addition to app-dir)
13
14
  * --output <path> Output file path (default: ./yak-routes-manifest.json)
14
15
  */
15
16
  import * as fs from "node:fs";
@@ -141,12 +142,65 @@ function scanDirectory(dirPath, segments = []) {
141
142
  }
142
143
  return routes;
143
144
  }
145
+ /**
146
+ * File discovery helpers for legacy `pages/` directories
147
+ */
148
+ const VALID_PAGE_EXTENSIONS = new Set([".js", ".jsx", ".ts", ".tsx", ".md", ".mdx"]);
149
+ const SPECIAL_PAGE_FILENAMES = new Set(["_app", "_document", "_error", "404", "500", "middleware", "_middleware"]);
150
+ /**
151
+ * Recursively scan a pages directory for Next.js page routes
152
+ */
153
+ function scanPagesDirectory(dirPath, segments = []) {
154
+ const routes = [];
155
+ try {
156
+ const entries = fs.readdirSync(dirPath, { withFileTypes: true });
157
+ for (const entry of entries) {
158
+ const fullPath = path.join(dirPath, entry.name);
159
+ if (entry.isDirectory()) {
160
+ // Skip special directories and api routes
161
+ if (entry.name.startsWith("_") || entry.name === "api") {
162
+ continue;
163
+ }
164
+ routes.push(...scanPagesDirectory(fullPath, [...segments, entry.name]));
165
+ }
166
+ else if (entry.isFile()) {
167
+ const extension = path.extname(entry.name);
168
+ if (!VALID_PAGE_EXTENSIONS.has(extension)) {
169
+ continue;
170
+ }
171
+ const baseName = entry.name.slice(0, -extension.length);
172
+ if (!baseName || SPECIAL_PAGE_FILENAMES.has(baseName) || baseName.startsWith("_")) {
173
+ continue;
174
+ }
175
+ const routeSegments = buildPagesSegments(segments, baseName);
176
+ const metadata = extractMetadata(fullPath);
177
+ routes.push({
178
+ path: normalizeRoutePath(routeSegments),
179
+ title: metadata.title,
180
+ description: metadata.description,
181
+ });
182
+ }
183
+ }
184
+ }
185
+ catch (error) {
186
+ console.error(`Error scanning directory ${dirPath}:`, error);
187
+ }
188
+ return routes;
189
+ }
190
+ function buildPagesSegments(segments, baseName) {
191
+ const routeSegments = [...segments];
192
+ if (baseName !== "index") {
193
+ routeSegments.push(baseName);
194
+ }
195
+ return routeSegments;
196
+ }
144
197
  /**
145
198
  * Parse command-line arguments
146
199
  */
147
200
  function parseArgs() {
148
201
  const args = process.argv.slice(2);
149
- let appDir = "./app";
202
+ let appDir = "./src/app";
203
+ let pagesDir = undefined;
150
204
  let output = "./yak-routes-manifest.json";
151
205
  let help = false;
152
206
  for (let i = 0; i < args.length; i++) {
@@ -158,12 +212,16 @@ function parseArgs() {
158
212
  appDir = args[i + 1];
159
213
  i++;
160
214
  }
215
+ else if (arg === "--pages-dir" && args[i + 1]) {
216
+ pagesDir = args[i + 1];
217
+ i++;
218
+ }
161
219
  else if (arg === "--output" && args[i + 1]) {
162
220
  output = args[i + 1];
163
221
  i++;
164
222
  }
165
223
  }
166
- return { appDir, output, help };
224
+ return { appDir, pagesDir, output, help };
167
225
  }
168
226
  /**
169
227
  * Display help message
@@ -178,38 +236,62 @@ Usage:
178
236
  yak-nextjs generate-manifest [options]
179
237
 
180
238
  Options:
181
- --app-dir <path> Path to Next.js app directory (default: ./app)
239
+ --app-dir <path> Path to Next.js app directory (default: ./src/app)
240
+ --pages-dir <path> Path to Next.js pages directory (optional)
182
241
  --output <path> Output file path (default: ./yak-routes-manifest.json)
183
242
  --help, -h Show this help message
184
243
 
185
- Example:
186
- yak-nextjs generate-manifest --app-dir ./src/app --output ./public/routes.json
244
+ Examples:
245
+ yak-nextjs generate-manifest
246
+ 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
187
249
  `);
188
250
  }
189
251
  /**
190
252
  * Main entry point
191
253
  */
192
254
  function main() {
193
- const { appDir, output, help } = parseArgs();
255
+ const { appDir, pagesDir, output, help } = parseArgs();
194
256
  if (help) {
195
257
  showHelp();
196
258
  process.exit(0);
197
259
  }
198
260
  console.log("🔍 Scanning Next.js page routes...");
199
- console.log(` App directory: ${appDir}`);
261
+ const routes = [];
262
+ // Scan app directory
200
263
  const appDirPath = path.resolve(process.cwd(), appDir);
201
- if (!fs.existsSync(appDirPath)) {
202
- console.error(`❌ Error: App directory not found: ${appDirPath}`);
264
+ if (fs.existsSync(appDirPath)) {
265
+ console.log(` App directory: ${appDir}`);
266
+ routes.push(...scanDirectory(appDirPath, []));
267
+ }
268
+ else {
269
+ console.log(` App directory: ${appDir} (not found, skipping)`);
270
+ }
271
+ // Scan pages directory if provided
272
+ if (pagesDir) {
273
+ const pagesDirPath = path.resolve(process.cwd(), pagesDir);
274
+ if (fs.existsSync(pagesDirPath)) {
275
+ console.log(` Pages directory: ${pagesDir}`);
276
+ routes.push(...scanPagesDirectory(pagesDirPath, []));
277
+ }
278
+ else {
279
+ console.log(` Pages directory: ${pagesDir} (not found, skipping)`);
280
+ }
281
+ }
282
+ if (routes.length === 0) {
283
+ console.error("❌ Error: No routes found. Check your directory paths.");
203
284
  process.exit(1);
204
285
  }
205
- const routes = scanDirectory(appDirPath, []);
286
+ // Deduplicate routes by path (app router takes precedence)
287
+ const uniqueRoutes = Array.from(new Map(routes.map(r => [r.path, r])).values());
206
288
  const manifest = {
207
- routes: routes.sort((a, b) => a.path.localeCompare(b.path)),
289
+ routes: uniqueRoutes.sort((a, b) => a.path.localeCompare(b.path)),
208
290
  generated_at: new Date().toISOString(),
209
291
  };
210
292
  const outputPath = path.resolve(process.cwd(), output);
211
293
  fs.writeFileSync(outputPath, JSON.stringify(manifest, null, 2), "utf-8");
212
- console.log(`✅ Generated manifest with ${routes.length} page routes`);
294
+ console.log(`✅ Generated manifest with ${uniqueRoutes.length} page routes`);
213
295
  console.log(` Output: ${outputPath}`);
214
296
  }
215
297
  // Run the CLI
@@ -1,4 +1,22 @@
1
- import type { RouteSourceInput, ToolSourceInput, RouteInfo, ToolManifest, ToolExecutor } from "@yak-io/javascript/server";
1
+ import type { RouteSourceInput, ToolSourceInput, RouteInfo, RouteManifest, ToolManifest, ToolExecutor } from "@yak-io/javascript/server";
2
+ /**
3
+ * Load a pre-built route manifest from disk.
4
+ *
5
+ * This should be used in production environments where filesystem scanning
6
+ * is not available (e.g., Vercel serverless functions).
7
+ *
8
+ * Generate the manifest at build time using:
9
+ * yak-nextjs generate-manifest
10
+ *
11
+ * @param manifestPath - Path to the manifest JSON file (default: tries common locations)
12
+ * @returns Route manifest or null if not found
13
+ */
14
+ export declare function loadRouteManifest(manifestPath?: string): RouteManifest | null;
15
+ /**
16
+ * Load routes from a pre-built manifest.
17
+ * Throws if manifest is not found.
18
+ */
19
+ export declare function loadRoutes(manifestPath?: string): RouteInfo[];
2
20
  export type NextYakRouteFilter = {
3
21
  include?: RegExp[];
4
22
  exclude?: RegExp[];
@@ -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,YAAY,EACZ,YAAY,EACb,MAAM,2BAA2B,CAAC;AAGnC,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;AA2DD,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;AAgBnC;;;;;;;;;;;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,CAa7D;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;AA6FD,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,5 +1,63 @@
1
1
  import { createYakHandler, createYakConfigHandler, createYakToolsHandler, } from "@yak-io/javascript/server";
2
+ import * as fs from "node:fs";
3
+ import * as path from "node:path";
2
4
  import { scanRoutes } from "./scan-routes.js";
5
+ /**
6
+ * Default paths to check for pre-built route manifests.
7
+ *
8
+ * On Vercel/serverless, files in `public/` are served via CDN and NOT available
9
+ * on the function's filesystem. The manifest must be in the project root or
10
+ * another location that gets bundled with the serverless function.
11
+ */
12
+ const DEFAULT_MANIFEST_PATHS = [
13
+ "./yak-routes-manifest.json",
14
+ "./.next/yak-routes-manifest.json",
15
+ "./public/yak-routes-manifest.json", // Only works in non-serverless environments
16
+ ];
17
+ /**
18
+ * Load a pre-built route manifest from disk.
19
+ *
20
+ * This should be used in production environments where filesystem scanning
21
+ * is not available (e.g., Vercel serverless functions).
22
+ *
23
+ * Generate the manifest at build time using:
24
+ * yak-nextjs generate-manifest
25
+ *
26
+ * @param manifestPath - Path to the manifest JSON file (default: tries common locations)
27
+ * @returns Route manifest or null if not found
28
+ */
29
+ export function loadRouteManifest(manifestPath) {
30
+ const pathsToTry = manifestPath ? [manifestPath] : [...DEFAULT_MANIFEST_PATHS];
31
+ for (const relativePath of pathsToTry) {
32
+ try {
33
+ const fullPath = path.resolve(process.cwd(), relativePath);
34
+ if (fs.existsSync(fullPath)) {
35
+ const content = fs.readFileSync(fullPath, "utf-8");
36
+ return JSON.parse(content);
37
+ }
38
+ }
39
+ catch {
40
+ // Continue to next path
41
+ }
42
+ }
43
+ return null;
44
+ }
45
+ /**
46
+ * Load routes from a pre-built manifest.
47
+ * Throws if manifest is not found.
48
+ */
49
+ export function loadRoutes(manifestPath) {
50
+ const manifest = loadRouteManifest(manifestPath);
51
+ if (!manifest) {
52
+ const pathsChecked = manifestPath ? manifestPath : DEFAULT_MANIFEST_PATHS.join(", ");
53
+ throw new Error(`Route manifest not found. Checked: ${pathsChecked}\n\n` +
54
+ `In production environments (like Vercel), route scanning requires a pre-built manifest.\n` +
55
+ `Generate it at build time by adding to your build script:\n\n` +
56
+ ` yak-nextjs generate-manifest\n\n` +
57
+ `Or provide routes explicitly in your handler configuration.`);
58
+ }
59
+ return manifest.routes;
60
+ }
3
61
  /**
4
62
  * Create a unified Next.js App Router handler backed by the core primitives
5
63
  */
@@ -9,6 +67,34 @@ export function createNextYakHandler(config) {
9
67
  tools: resolveToolSources(config),
10
68
  });
11
69
  }
70
+ /**
71
+ * Attempt to scan routes from filesystem, with production-safe fallback.
72
+ *
73
+ * In development: scans the app directory directly
74
+ * In production (Vercel, etc.): falls back to pre-built manifest if directory doesn't exist
75
+ */
76
+ function tryLoadRoutes(appDir) {
77
+ const targetDir = path.resolve(process.cwd(), appDir);
78
+ // If the app directory exists, scan it directly (development mode)
79
+ if (fs.existsSync(targetDir)) {
80
+ return scanRoutes(appDir);
81
+ }
82
+ // In production, the source directory doesn't exist - try loading from manifest
83
+ const manifest = loadRouteManifest();
84
+ if (manifest) {
85
+ return manifest.routes;
86
+ }
87
+ // Neither source nor manifest available - provide helpful error
88
+ throw new Error(`App directory not found: ${targetDir}\n\n` +
89
+ `This typically happens in production (Vercel, etc.) where source files aren't deployed.\n\n` +
90
+ `Solutions:\n` +
91
+ `1. Generate a route manifest at build time:\n` +
92
+ ` Add to your build script: yak-nextjs generate-manifest\n\n` +
93
+ `2. Provide routes explicitly:\n` +
94
+ ` createNextYakHandler({ routes: [...] })\n\n` +
95
+ `3. Use getRoutes callback:\n` +
96
+ ` createNextYakHandler({ getRoutes: async () => [...] })`);
97
+ }
12
98
  function resolveRouteSources(config) {
13
99
  if (config.routes) {
14
100
  return config.routes;
@@ -16,7 +102,7 @@ function resolveRouteSources(config) {
16
102
  if (config.getRoutes) {
17
103
  return config.getRoutes;
18
104
  }
19
- return async () => applyRouteFilters(scanRoutes(config.appDir ?? "./src/app"), config.routeFilter);
105
+ return async () => applyRouteFilters(tryLoadRoutes(config.appDir ?? "./src/app"), config.routeFilter);
20
106
  }
21
107
  function applyRouteFilters(routes, filter) {
22
108
  if (!filter) {
@@ -1,6 +1,6 @@
1
1
  export { scanRoutes } from "./scan-routes.js";
2
2
  export type { ScanRoutesOptions } from "./scan-routes.js";
3
- export { createNextYakHandler, createNextYakConfigHandler, createNextYakToolsHandler, } from "./createNextYakHandler.js";
3
+ export { createNextYakHandler, createNextYakConfigHandler, createNextYakToolsHandler, loadRouteManifest, loadRoutes, } from "./createNextYakHandler.js";
4
4
  export type { NextYakHandlerConfig, NextYakConfigHandlerConfig, NextYakToolsHandlerConfig, NextYakRouteFilter, } from "./createNextYakHandler.js";
5
5
  export type { ToolExecutor, ToolCallPayload, ToolCallResult, ToolDefinition, ToolManifest, RouteInfo, RouteManifest, ChatConfig, } from "@yak-io/javascript/server";
6
6
  //# 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,GACzB,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,YAAY,EACX,YAAY,EACZ,eAAe,EACf,cAAc,EACd,cAAc,EACd,YAAY,EACZ,SAAS,EACT,aAAa,EACb,UAAU,GACV,MAAM,2BAA2B,CAAC"}
@@ -1,2 +1,2 @@
1
1
  export { scanRoutes } from "./scan-routes.js";
2
- export { createNextYakHandler, createNextYakConfigHandler, createNextYakToolsHandler, } from "./createNextYakHandler.js";
2
+ export { createNextYakHandler, createNextYakConfigHandler, createNextYakToolsHandler, loadRouteManifest, loadRoutes, } from "./createNextYakHandler.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yak-io/nextjs",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
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",
@@ -11,8 +11,7 @@
11
11
  "directory": "packages/nextjs"
12
12
  },
13
13
  "publishConfig": {
14
- "access": "public",
15
- "provenance": false
14
+ "access": "public"
16
15
  },
17
16
  "keywords": [
18
17
  "yak",