@agntcms/next 0.2.1 → 0.3.0

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/dist/config.cjs CHANGED
@@ -80,10 +80,17 @@ function defineConfig(config) {
80
80
  }
81
81
 
82
82
  // src/config/withagntcms.ts
83
+ var DEV_PAGE_EXTENSIONS = ["dev.ts", "dev.tsx", "ts", "tsx", "js", "jsx"];
84
+ var PROD_PAGE_EXTENSIONS = ["ts", "tsx", "js", "jsx"];
83
85
  function withagntcms(nextConfig) {
86
+ const isProd = process.env.NODE_ENV === "production";
87
+ const defaultPageExtensions = isProd ? PROD_PAGE_EXTENSIONS : DEV_PAGE_EXTENSIONS;
88
+ const userPageExtensions = nextConfig.pageExtensions;
89
+ const pageExtensions = Array.isArray(userPageExtensions) ? userPageExtensions : [...defaultPageExtensions];
84
90
  return {
85
91
  ...nextConfig,
86
- output: "standalone"
92
+ output: "standalone",
93
+ pageExtensions
87
94
  };
88
95
  }
89
96
 
package/dist/config.d.cts CHANGED
@@ -102,11 +102,18 @@ declare function defineConfig(config: AgentCmsConfig): ResolvedConfig;
102
102
  * Sets `output: 'standalone'` so the production Docker build
103
103
  * (which copies `.next/standalone/`) works out of the box.
104
104
  *
105
+ * Also injects a `pageExtensions` default: in dev we accept `.dev.ts` /
106
+ * `.dev.tsx` so dev-only routes (preview, admin, MCP) can be named
107
+ * `route.dev.ts` and excluded from the production build automatically.
108
+ * If the user already provided `pageExtensions`, theirs wins — the
109
+ * convention is opt-in.
110
+ *
105
111
  * In future versions this may also configure webpack aliases,
106
112
  * image optimization domains, or framework-level middleware.
107
113
  */
108
114
  declare function withagntcms<T extends Record<string, unknown>>(nextConfig: T): T & {
109
115
  output: 'standalone';
116
+ pageExtensions: string[];
110
117
  };
111
118
 
112
119
  export { type AgentCmsConfig, AnyFormDefinition, type PageTemplate, type ResolvedConfig, type SubmissionRateLimit, SubmissionStorageAdapter, defineConfig, withagntcms };
package/dist/config.d.ts CHANGED
@@ -102,11 +102,18 @@ declare function defineConfig(config: AgentCmsConfig): ResolvedConfig;
102
102
  * Sets `output: 'standalone'` so the production Docker build
103
103
  * (which copies `.next/standalone/`) works out of the box.
104
104
  *
105
+ * Also injects a `pageExtensions` default: in dev we accept `.dev.ts` /
106
+ * `.dev.tsx` so dev-only routes (preview, admin, MCP) can be named
107
+ * `route.dev.ts` and excluded from the production build automatically.
108
+ * If the user already provided `pageExtensions`, theirs wins — the
109
+ * convention is opt-in.
110
+ *
105
111
  * In future versions this may also configure webpack aliases,
106
112
  * image optimization domains, or framework-level middleware.
107
113
  */
108
114
  declare function withagntcms<T extends Record<string, unknown>>(nextConfig: T): T & {
109
115
  output: 'standalone';
116
+ pageExtensions: string[];
110
117
  };
111
118
 
112
119
  export { type AgentCmsConfig, AnyFormDefinition, type PageTemplate, type ResolvedConfig, type SubmissionRateLimit, SubmissionStorageAdapter, defineConfig, withagntcms };
package/dist/config.mjs CHANGED
@@ -35,10 +35,17 @@ function defineConfig(config) {
35
35
  }
36
36
 
37
37
  // src/config/withagntcms.ts
38
+ var DEV_PAGE_EXTENSIONS = ["dev.ts", "dev.tsx", "ts", "tsx", "js", "jsx"];
39
+ var PROD_PAGE_EXTENSIONS = ["ts", "tsx", "js", "jsx"];
38
40
  function withagntcms(nextConfig) {
41
+ const isProd = process.env.NODE_ENV === "production";
42
+ const defaultPageExtensions = isProd ? PROD_PAGE_EXTENSIONS : DEV_PAGE_EXTENSIONS;
43
+ const userPageExtensions = nextConfig.pageExtensions;
44
+ const pageExtensions = Array.isArray(userPageExtensions) ? userPageExtensions : [...defaultPageExtensions];
39
45
  return {
40
46
  ...nextConfig,
41
- output: "standalone"
47
+ output: "standalone",
48
+ pageExtensions
42
49
  };
43
50
  }
44
51
 
package/dist/handlers.cjs CHANGED
@@ -45,7 +45,8 @@ __export(handlers_exports, {
45
45
  createPreviewTokenStore: () => createPreviewTokenStore,
46
46
  createSubmitFormHandler: () => createSubmitFormHandler,
47
47
  createTaskStore: () => createTaskStore,
48
- createTemplateHandler: () => createTemplateHandler
48
+ createTemplateHandler: () => createTemplateHandler,
49
+ createagntcmsRouteHandler: () => createagntcmsRouteHandler
49
50
  });
50
51
  module.exports = __toCommonJS(handlers_exports);
51
52
 
@@ -2502,6 +2503,84 @@ function createFormsDeleteHandler() {
2502
2503
  };
2503
2504
  }
2504
2505
 
2506
+ // src/handlers/dispatcher.ts
2507
+ function buildRouteTable(h) {
2508
+ const table = /* @__PURE__ */ new Map();
2509
+ table.set("assets", { GET: h.assets.list });
2510
+ table.set("assets/upload", { POST: h.assets.upload });
2511
+ table.set("events", { GET: async (req) => h.events.GET(req) });
2512
+ table.set("mcp", { POST: h.mcp.POST });
2513
+ table.set("draft/save", { POST: h.draft.save });
2514
+ table.set("draft/list", { GET: h.draft.list });
2515
+ table.set("draft/publish", { POST: h.draft.publish });
2516
+ table.set("draft/reorder", { POST: h.draft.reorder });
2517
+ table.set("draft/discard", { POST: h.draft.discard });
2518
+ table.set("page/list", { GET: h.page.list });
2519
+ table.set("page/read", { GET: h.page.read });
2520
+ table.set("page/delete", { POST: h.page.deletePage });
2521
+ table.set("page/unpublish", { POST: h.page.unpublish });
2522
+ table.set("page/history", { GET: h.page.listHistory });
2523
+ table.set("page/rollback", { POST: h.page.rollback });
2524
+ table.set("page/rename", { POST: h.page.rename });
2525
+ table.set("page/duplicate", { POST: h.page.duplicate });
2526
+ table.set("global/list", { GET: h.global.list });
2527
+ table.set("global/read", { GET: h.global.read });
2528
+ table.set("global/save", { POST: h.global.save });
2529
+ table.set("global/delete", { DELETE: h.global.delete });
2530
+ table.set("global/history", { GET: h.global.listHistory });
2531
+ table.set("global/rollback", { POST: h.global.rollback });
2532
+ table.set("preview/enter", { POST: async (req) => h.preview.enter(req), GET: async (req) => h.preview.enterWithToken(req) });
2533
+ table.set("preview/exit", { POST: async (req) => h.preview.exit(req) });
2534
+ table.set("preview/issue", { POST: h.preview.issueToken });
2535
+ table.set("template/list", { GET: h.template.list });
2536
+ table.set("forms/list", { GET: h.formsList });
2537
+ table.set("forms/read", { GET: h.formsRead });
2538
+ table.set("forms/delete", { POST: h.formsDelete });
2539
+ return table;
2540
+ }
2541
+ function createagntcmsRouteHandler(opts) {
2542
+ const handlers = {
2543
+ assets: createAssetsHandler(opts.assets),
2544
+ draft: createDraftHandler(opts.draft),
2545
+ page: createPageHandler(opts.page),
2546
+ global: createGlobalHandler(opts.global),
2547
+ // `preview` deps are optional; pass undefined explicitly so the
2548
+ // factory's `deps?` parameter sees `undefined` rather than `{}` (the
2549
+ // factory branches on `deps?.tokenStore` and `deps?.cookieName`).
2550
+ preview: createPreviewHandler(opts.preview),
2551
+ events: createEventsHandler(opts.events),
2552
+ mcp: createMcpHandler(opts.mcp),
2553
+ template: createTemplateHandler(opts.template),
2554
+ formsList: createFormsListHandler(opts.formsList),
2555
+ formsRead: createFormsReadHandler(opts.formsRead),
2556
+ formsDelete: createFormsDeleteHandler()
2557
+ };
2558
+ const table = buildRouteTable(handlers);
2559
+ const dispatch = async (method, req, ctx) => {
2560
+ const { path: path6 } = await ctx.params;
2561
+ if (!path6 || path6.length === 0) {
2562
+ return new Response(null, { status: 404 });
2563
+ }
2564
+ const key = path6.join("/");
2565
+ const entry = table.get(key);
2566
+ if (!entry) {
2567
+ return new Response(null, { status: 404 });
2568
+ }
2569
+ const handler = entry[method];
2570
+ if (!handler) {
2571
+ const allowed = Object.keys(entry).join(", ");
2572
+ return new Response(null, { status: 405, headers: { Allow: allowed } });
2573
+ }
2574
+ return await handler(req);
2575
+ };
2576
+ return {
2577
+ GET: (req, ctx) => dispatch("GET", req, ctx),
2578
+ POST: (req, ctx) => dispatch("POST", req, ctx),
2579
+ PUT: (req, ctx) => dispatch("PUT", req, ctx),
2580
+ DELETE: (req, ctx) => dispatch("DELETE", req, ctx)
2581
+ };
2582
+ }
2583
+
2505
2584
  // src/handlers.ts
2506
2585
  installDefaultAdapterFactories();
2507
2586
  // Annotate the CommonJS export names for ESM import in node:
@@ -2521,5 +2600,6 @@ installDefaultAdapterFactories();
2521
2600
  createPreviewTokenStore,
2522
2601
  createSubmitFormHandler,
2523
2602
  createTaskStore,
2524
- createTemplateHandler
2603
+ createTemplateHandler,
2604
+ createagntcmsRouteHandler
2525
2605
  });
@@ -327,4 +327,68 @@ declare function createFormsReadHandler(deps: FormsReadHandlerDeps): (req: Reque
327
327
 
328
328
  declare function createFormsDeleteHandler(): (_req: Request) => Promise<Response>;
329
329
 
330
- export { type AgentBridge, type AgentBridgeStatus, AgentUnreachableError, type AssetsHandler, type AssetsHandlerDeps, type CreateAgentBridgeOptions, type DraftHandler, type DraftHandlerDeps, type EventsHandler, type EventsHandlerDeps, type FormsListAdapterInfo, type FormsListHandlerDeps, type FormsReadHandlerDeps, type GlobalHandler, type GlobalHandlerDeps, type McpHandler, type McpHandlerDeps, type PageHandler, type PageHandlerDeps, type PreviewHandler, type PreviewHandlerDeps, type PreviewToken, type PreviewTokenStore, type PreviewTokenStoreOptions, type SubmitHandlerDeps, type Task, type TaskEvent, type TaskId, type TaskSnapshot, type TaskState, type TaskStore, type TemplateHandler, type TemplateHandlerDeps, createAgentBridge, createAssetsHandler, createDraftHandler, createEventsHandler, createFormsDeleteHandler, createFormsListHandler, createFormsReadHandler, createGlobalHandler, createMcpHandler, createPageHandler, createPreviewHandler, createPreviewTokenStore, createSubmitFormHandler, createTaskStore, createTemplateHandler };
330
+ /**
331
+ * Dependencies for every endpoint the dispatcher serves. Grouped by
332
+ * underlying handler factory so the template wiring mirrors the v0.2
333
+ * `_shared.ts` shape one-to-one (each frozen route file passed the same
334
+ * `deps` object to its factory; the dispatcher merges them at the top).
335
+ *
336
+ * `preview` is optional because `createPreviewHandler` has all-optional
337
+ * deps (cookie name and token store both have defaults / null fallbacks).
338
+ * Everything else is required: omitting a slice would break a real
339
+ * endpoint at runtime, and a typed signature catches that at compile time.
340
+ */
341
+ interface agntcmsRouteHandlerOptions {
342
+ readonly assets: AssetsHandlerDeps;
343
+ readonly draft: DraftHandlerDeps;
344
+ readonly page: PageHandlerDeps;
345
+ readonly global: GlobalHandlerDeps;
346
+ readonly preview?: PreviewHandlerDeps;
347
+ readonly events: EventsHandlerDeps;
348
+ readonly mcp: McpHandlerDeps;
349
+ readonly template: TemplateHandlerDeps;
350
+ readonly formsList: FormsListHandlerDeps;
351
+ readonly formsRead: FormsReadHandlerDeps;
352
+ }
353
+ /** HTTP methods the dispatcher routes. */
354
+ type DispatcherMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';
355
+ /**
356
+ * Shape Next.js 15 passes as the second argument to a catch-all route's
357
+ * method handlers. `params.path` is a Promise resolving to the path
358
+ * segments after `/api/agntcms/` — for `assets/upload` it resolves to
359
+ * `['assets', 'upload']`.
360
+ */
361
+ interface agntcmsRouteContext {
362
+ readonly params: Promise<{
363
+ readonly path: readonly string[];
364
+ }>;
365
+ }
366
+ interface agntcmsRouteHandler {
367
+ readonly GET: (req: Request, ctx: agntcmsRouteContext) => Promise<Response>;
368
+ readonly POST: (req: Request, ctx: agntcmsRouteContext) => Promise<Response>;
369
+ readonly PUT: (req: Request, ctx: agntcmsRouteContext) => Promise<Response>;
370
+ readonly DELETE: (req: Request, ctx: agntcmsRouteContext) => Promise<Response>;
371
+ }
372
+ /**
373
+ * Create the agntcms catch-all route handler for Next.js.
374
+ *
375
+ * Usage in the template's frozen `app/api/agntcms/[...path]/route.ts`:
376
+ *
377
+ * ```ts
378
+ * import { createagntcmsRouteHandler } from '@agntcms/next/handlers'
379
+ * import { contentAdapter, assetAdapter, runtime, taskStore, bridge, ... } from '../_shared'
380
+ *
381
+ * export const { GET, POST, PUT, DELETE } = createagntcmsRouteHandler({
382
+ * assets: { assetAdapter },
383
+ * draft: { contentAdapter, runtime },
384
+ * // ... etc
385
+ * })
386
+ * ```
387
+ *
388
+ * The returned object also exports `PUT` even though no current endpoint
389
+ * uses it. Exporting all four method symbols keeps the template's
390
+ * frozen `route.ts` shape stable as new endpoints are added.
391
+ */
392
+ declare function createagntcmsRouteHandler(opts: agntcmsRouteHandlerOptions): agntcmsRouteHandler;
393
+
394
+ export { type AgentBridge, type AgentBridgeStatus, AgentUnreachableError, type AssetsHandler, type AssetsHandlerDeps, type CreateAgentBridgeOptions, type DispatcherMethod, type DraftHandler, type DraftHandlerDeps, type EventsHandler, type EventsHandlerDeps, type FormsListAdapterInfo, type FormsListHandlerDeps, type FormsReadHandlerDeps, type GlobalHandler, type GlobalHandlerDeps, type McpHandler, type McpHandlerDeps, type PageHandler, type PageHandlerDeps, type PreviewHandler, type PreviewHandlerDeps, type PreviewToken, type PreviewTokenStore, type PreviewTokenStoreOptions, type SubmitHandlerDeps, type Task, type TaskEvent, type TaskId, type TaskSnapshot, type TaskState, type TaskStore, type TemplateHandler, type TemplateHandlerDeps, type agntcmsRouteContext, type agntcmsRouteHandler, type agntcmsRouteHandlerOptions, createAgentBridge, createAssetsHandler, createDraftHandler, createEventsHandler, createFormsDeleteHandler, createFormsListHandler, createFormsReadHandler, createGlobalHandler, createMcpHandler, createPageHandler, createPreviewHandler, createPreviewTokenStore, createSubmitFormHandler, createTaskStore, createTemplateHandler, createagntcmsRouteHandler };
@@ -327,4 +327,68 @@ declare function createFormsReadHandler(deps: FormsReadHandlerDeps): (req: Reque
327
327
 
328
328
  declare function createFormsDeleteHandler(): (_req: Request) => Promise<Response>;
329
329
 
330
- export { type AgentBridge, type AgentBridgeStatus, AgentUnreachableError, type AssetsHandler, type AssetsHandlerDeps, type CreateAgentBridgeOptions, type DraftHandler, type DraftHandlerDeps, type EventsHandler, type EventsHandlerDeps, type FormsListAdapterInfo, type FormsListHandlerDeps, type FormsReadHandlerDeps, type GlobalHandler, type GlobalHandlerDeps, type McpHandler, type McpHandlerDeps, type PageHandler, type PageHandlerDeps, type PreviewHandler, type PreviewHandlerDeps, type PreviewToken, type PreviewTokenStore, type PreviewTokenStoreOptions, type SubmitHandlerDeps, type Task, type TaskEvent, type TaskId, type TaskSnapshot, type TaskState, type TaskStore, type TemplateHandler, type TemplateHandlerDeps, createAgentBridge, createAssetsHandler, createDraftHandler, createEventsHandler, createFormsDeleteHandler, createFormsListHandler, createFormsReadHandler, createGlobalHandler, createMcpHandler, createPageHandler, createPreviewHandler, createPreviewTokenStore, createSubmitFormHandler, createTaskStore, createTemplateHandler };
330
+ /**
331
+ * Dependencies for every endpoint the dispatcher serves. Grouped by
332
+ * underlying handler factory so the template wiring mirrors the v0.2
333
+ * `_shared.ts` shape one-to-one (each frozen route file passed the same
334
+ * `deps` object to its factory; the dispatcher merges them at the top).
335
+ *
336
+ * `preview` is optional because `createPreviewHandler` has all-optional
337
+ * deps (cookie name and token store both have defaults / null fallbacks).
338
+ * Everything else is required: omitting a slice would break a real
339
+ * endpoint at runtime, and a typed signature catches that at compile time.
340
+ */
341
+ interface agntcmsRouteHandlerOptions {
342
+ readonly assets: AssetsHandlerDeps;
343
+ readonly draft: DraftHandlerDeps;
344
+ readonly page: PageHandlerDeps;
345
+ readonly global: GlobalHandlerDeps;
346
+ readonly preview?: PreviewHandlerDeps;
347
+ readonly events: EventsHandlerDeps;
348
+ readonly mcp: McpHandlerDeps;
349
+ readonly template: TemplateHandlerDeps;
350
+ readonly formsList: FormsListHandlerDeps;
351
+ readonly formsRead: FormsReadHandlerDeps;
352
+ }
353
+ /** HTTP methods the dispatcher routes. */
354
+ type DispatcherMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';
355
+ /**
356
+ * Shape Next.js 15 passes as the second argument to a catch-all route's
357
+ * method handlers. `params.path` is a Promise resolving to the path
358
+ * segments after `/api/agntcms/` — for `assets/upload` it resolves to
359
+ * `['assets', 'upload']`.
360
+ */
361
+ interface agntcmsRouteContext {
362
+ readonly params: Promise<{
363
+ readonly path: readonly string[];
364
+ }>;
365
+ }
366
+ interface agntcmsRouteHandler {
367
+ readonly GET: (req: Request, ctx: agntcmsRouteContext) => Promise<Response>;
368
+ readonly POST: (req: Request, ctx: agntcmsRouteContext) => Promise<Response>;
369
+ readonly PUT: (req: Request, ctx: agntcmsRouteContext) => Promise<Response>;
370
+ readonly DELETE: (req: Request, ctx: agntcmsRouteContext) => Promise<Response>;
371
+ }
372
+ /**
373
+ * Create the agntcms catch-all route handler for Next.js.
374
+ *
375
+ * Usage in the template's frozen `app/api/agntcms/[...path]/route.ts`:
376
+ *
377
+ * ```ts
378
+ * import { createagntcmsRouteHandler } from '@agntcms/next/handlers'
379
+ * import { contentAdapter, assetAdapter, runtime, taskStore, bridge, ... } from '../_shared'
380
+ *
381
+ * export const { GET, POST, PUT, DELETE } = createagntcmsRouteHandler({
382
+ * assets: { assetAdapter },
383
+ * draft: { contentAdapter, runtime },
384
+ * // ... etc
385
+ * })
386
+ * ```
387
+ *
388
+ * The returned object also exports `PUT` even though no current endpoint
389
+ * uses it. Exporting all four method symbols keeps the template's
390
+ * frozen `route.ts` shape stable as new endpoints are added.
391
+ */
392
+ declare function createagntcmsRouteHandler(opts: agntcmsRouteHandlerOptions): agntcmsRouteHandler;
393
+
394
+ export { type AgentBridge, type AgentBridgeStatus, AgentUnreachableError, type AssetsHandler, type AssetsHandlerDeps, type CreateAgentBridgeOptions, type DispatcherMethod, type DraftHandler, type DraftHandlerDeps, type EventsHandler, type EventsHandlerDeps, type FormsListAdapterInfo, type FormsListHandlerDeps, type FormsReadHandlerDeps, type GlobalHandler, type GlobalHandlerDeps, type McpHandler, type McpHandlerDeps, type PageHandler, type PageHandlerDeps, type PreviewHandler, type PreviewHandlerDeps, type PreviewToken, type PreviewTokenStore, type PreviewTokenStoreOptions, type SubmitHandlerDeps, type Task, type TaskEvent, type TaskId, type TaskSnapshot, type TaskState, type TaskStore, type TemplateHandler, type TemplateHandlerDeps, type agntcmsRouteContext, type agntcmsRouteHandler, type agntcmsRouteHandlerOptions, createAgentBridge, createAssetsHandler, createDraftHandler, createEventsHandler, createFormsDeleteHandler, createFormsListHandler, createFormsReadHandler, createGlobalHandler, createMcpHandler, createPageHandler, createPreviewHandler, createPreviewTokenStore, createSubmitFormHandler, createTaskStore, createTemplateHandler, createagntcmsRouteHandler };
package/dist/handlers.mjs CHANGED
@@ -2451,6 +2451,84 @@ function createFormsDeleteHandler() {
2451
2451
  };
2452
2452
  }
2453
2453
 
2454
+ // src/handlers/dispatcher.ts
2455
+ function buildRouteTable(h) {
2456
+ const table = /* @__PURE__ */ new Map();
2457
+ table.set("assets", { GET: h.assets.list });
2458
+ table.set("assets/upload", { POST: h.assets.upload });
2459
+ table.set("events", { GET: async (req) => h.events.GET(req) });
2460
+ table.set("mcp", { POST: h.mcp.POST });
2461
+ table.set("draft/save", { POST: h.draft.save });
2462
+ table.set("draft/list", { GET: h.draft.list });
2463
+ table.set("draft/publish", { POST: h.draft.publish });
2464
+ table.set("draft/reorder", { POST: h.draft.reorder });
2465
+ table.set("draft/discard", { POST: h.draft.discard });
2466
+ table.set("page/list", { GET: h.page.list });
2467
+ table.set("page/read", { GET: h.page.read });
2468
+ table.set("page/delete", { POST: h.page.deletePage });
2469
+ table.set("page/unpublish", { POST: h.page.unpublish });
2470
+ table.set("page/history", { GET: h.page.listHistory });
2471
+ table.set("page/rollback", { POST: h.page.rollback });
2472
+ table.set("page/rename", { POST: h.page.rename });
2473
+ table.set("page/duplicate", { POST: h.page.duplicate });
2474
+ table.set("global/list", { GET: h.global.list });
2475
+ table.set("global/read", { GET: h.global.read });
2476
+ table.set("global/save", { POST: h.global.save });
2477
+ table.set("global/delete", { DELETE: h.global.delete });
2478
+ table.set("global/history", { GET: h.global.listHistory });
2479
+ table.set("global/rollback", { POST: h.global.rollback });
2480
+ table.set("preview/enter", { POST: async (req) => h.preview.enter(req), GET: async (req) => h.preview.enterWithToken(req) });
2481
+ table.set("preview/exit", { POST: async (req) => h.preview.exit(req) });
2482
+ table.set("preview/issue", { POST: h.preview.issueToken });
2483
+ table.set("template/list", { GET: h.template.list });
2484
+ table.set("forms/list", { GET: h.formsList });
2485
+ table.set("forms/read", { GET: h.formsRead });
2486
+ table.set("forms/delete", { POST: h.formsDelete });
2487
+ return table;
2488
+ }
2489
+ function createagntcmsRouteHandler(opts) {
2490
+ const handlers = {
2491
+ assets: createAssetsHandler(opts.assets),
2492
+ draft: createDraftHandler(opts.draft),
2493
+ page: createPageHandler(opts.page),
2494
+ global: createGlobalHandler(opts.global),
2495
+ // `preview` deps are optional; pass undefined explicitly so the
2496
+ // factory's `deps?` parameter sees `undefined` rather than `{}` (the
2497
+ // factory branches on `deps?.tokenStore` and `deps?.cookieName`).
2498
+ preview: createPreviewHandler(opts.preview),
2499
+ events: createEventsHandler(opts.events),
2500
+ mcp: createMcpHandler(opts.mcp),
2501
+ template: createTemplateHandler(opts.template),
2502
+ formsList: createFormsListHandler(opts.formsList),
2503
+ formsRead: createFormsReadHandler(opts.formsRead),
2504
+ formsDelete: createFormsDeleteHandler()
2505
+ };
2506
+ const table = buildRouteTable(handlers);
2507
+ const dispatch = async (method, req, ctx) => {
2508
+ const { path: path6 } = await ctx.params;
2509
+ if (!path6 || path6.length === 0) {
2510
+ return new Response(null, { status: 404 });
2511
+ }
2512
+ const key = path6.join("/");
2513
+ const entry = table.get(key);
2514
+ if (!entry) {
2515
+ return new Response(null, { status: 404 });
2516
+ }
2517
+ const handler = entry[method];
2518
+ if (!handler) {
2519
+ const allowed = Object.keys(entry).join(", ");
2520
+ return new Response(null, { status: 405, headers: { Allow: allowed } });
2521
+ }
2522
+ return await handler(req);
2523
+ };
2524
+ return {
2525
+ GET: (req, ctx) => dispatch("GET", req, ctx),
2526
+ POST: (req, ctx) => dispatch("POST", req, ctx),
2527
+ PUT: (req, ctx) => dispatch("PUT", req, ctx),
2528
+ DELETE: (req, ctx) => dispatch("DELETE", req, ctx)
2529
+ };
2530
+ }
2531
+
2454
2532
  // src/handlers.ts
2455
2533
  installDefaultAdapterFactories();
2456
2534
  export {
@@ -2469,5 +2547,6 @@ export {
2469
2547
  createPreviewTokenStore,
2470
2548
  createSubmitFormHandler,
2471
2549
  createTaskStore,
2472
- createTemplateHandler
2550
+ createTemplateHandler,
2551
+ createagntcmsRouteHandler
2473
2552
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agntcms/next",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "agntcms runtime for Next.js: domain model, storage adapters, React components",
5
5
  "type": "module",
6
6
  "private": false,