@danceroutine/tango-adapters-next 1.11.0 → 1.11.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.
@@ -1,4 +1,2 @@
1
- /**
2
- * Domain boundary barrel: centralizes this subdomain's public contract.
3
- */
4
- export { NextAdapter, type AdaptNextOptions, type AdaptNextViewSetOptions, type NextAPIView, type NextAPIViewFactory, type NextCrudViewSet, type NextDynamicRouteContext, type NextDynamicRouteHandler, type NextRouteHandler, type NextViewSetFactory, type NextViewSetRouteHandlers, } from './NextAdapter';
1
+ import { a as NextAPIViewFactory, c as NextDynamicRouteContext, d as NextViewSetFactory, f as NextViewSetRouteHandlers, i as NextAPIView, l as NextDynamicRouteHandler, n as AdaptNextOptions, o as NextAdapter, r as AdaptNextViewSetOptions, s as NextCrudViewSet, u as NextRouteHandler } from "../index-BEw-_Qrg.js";
2
+ export { type AdaptNextOptions, type AdaptNextViewSetOptions, type NextAPIView, type NextAPIViewFactory, NextAdapter, type NextCrudViewSet, type NextDynamicRouteContext, type NextDynamicRouteHandler, type NextRouteHandler, type NextViewSetFactory, type NextViewSetRouteHandlers };
@@ -1,3 +1,2 @@
1
- import { NextAdapter } from "../adapter-Em1-1ezY.js";
2
-
3
- export { NextAdapter };
1
+ import { n as NextAdapter } from "../adapter-DStdtW--.js";
2
+ export { NextAdapter };
@@ -1,19 +1,12 @@
1
+ import { t as __exportAll } from "./chunk-D7D4PA-g.js";
1
2
  import { RequestContext } from "@danceroutine/tango-resources";
2
3
  import { HttpErrorFactory, TangoQueryParams, TangoRequest, TangoResponse, getLogger } from "@danceroutine/tango-core";
3
4
  import { FRAMEWORK_ADAPTER_BRAND, FrameworkAdapterRequestExecutor } from "@danceroutine/tango-adapters-core/adapter";
4
5
  import { InternalActionMatchKind, InternalActionScope, InternalHttpMethod } from "@danceroutine/tango-adapters-core";
5
-
6
- //#region rolldown:runtime
7
- var __defProp = Object.defineProperty;
8
- var __export = (target, all) => {
9
- for (var name in all) __defProp(target, name, {
10
- get: all[name],
11
- enumerable: true
12
- });
13
- };
14
-
15
- //#endregion
16
6
  //#region src/adapter/NextAdapter.ts
7
+ /**
8
+ * Next.js adapter that translates route handlers to Tango `RequestContext`.
9
+ */
17
10
  var NextAdapter = class {
18
11
  __tangoBrand = FRAMEWORK_ADAPTER_BRAND;
19
12
  logger = getLogger("tango.adapter.next");
@@ -104,8 +97,7 @@ var NextAdapter = class {
104
97
  return apiView.dispatch(ctx);
105
98
  }, options),
106
99
  POST: this.adapt(async (ctx) => {
107
- const detailId = this.resolveDetailId(ctx.params, paramKey);
108
- if (detailId) return this.methodNotAllowedResponse();
100
+ if (this.resolveDetailId(ctx.params, paramKey)) return this.methodNotAllowedResponse();
109
101
  return apiView.dispatch(ctx);
110
102
  }, options),
111
103
  PATCH: this.adapt(async (ctx) => {
@@ -179,20 +171,16 @@ var NextAdapter = class {
179
171
  adaptRouteHandlersFactory(factory) {
180
172
  let handlersPromise = null;
181
173
  const getHandlers = async () => {
182
- if (!handlersPromise) {
183
- const initializing = factory();
184
- handlersPromise = initializing.catch((error) => {
185
- handlersPromise = null;
186
- throw error;
187
- });
188
- }
174
+ if (!handlersPromise) handlersPromise = factory().catch((error) => {
175
+ handlersPromise = null;
176
+ throw error;
177
+ });
189
178
  return handlersPromise;
190
179
  };
191
180
  const createLazyHandler = (method) => {
192
181
  return async (request, context) => {
193
182
  try {
194
- const handlers = await getHandlers();
195
- return handlers[method](request, context);
183
+ return (await getHandlers())[method](request, context);
196
184
  } catch (error) {
197
185
  return this.internalServerError(error);
198
186
  }
@@ -220,8 +208,7 @@ var NextAdapter = class {
220
208
  return Object.fromEntries(entries);
221
209
  }
222
210
  extractDirectId(params) {
223
- const directId = params.id?.trim();
224
- return directId || null;
211
+ return params.id?.trim() || null;
225
212
  }
226
213
  extractCatchAllSegments(params, paramKey) {
227
214
  const catchAll = params[paramKey]?.trim() ?? "";
@@ -261,12 +248,10 @@ var NextAdapter = class {
261
248
  return constructorValue.getActions(viewset);
262
249
  }
263
250
  };
264
-
265
251
  //#endregion
266
252
  //#region src/adapter/index.ts
267
- var adapter_exports = {};
268
- __export(adapter_exports, { NextAdapter: () => NextAdapter });
269
-
253
+ var adapter_exports = /* @__PURE__ */ __exportAll({ NextAdapter: () => NextAdapter });
270
254
  //#endregion
271
- export { NextAdapter, adapter_exports };
272
- //# sourceMappingURL=adapter-Em1-1ezY.js.map
255
+ export { NextAdapter as n, adapter_exports as t };
256
+
257
+ //# sourceMappingURL=adapter-DStdtW--.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter-DStdtW--.js","names":[],"sources":["../src/adapter/NextAdapter.ts","../src/adapter/index.ts"],"sourcesContent":["import type { NextRequest } from 'next/server';\nimport { RequestContext } from '@danceroutine/tango-resources';\nimport {\n HttpErrorFactory,\n TangoQueryParams,\n TangoRequest,\n TangoResponse,\n getLogger,\n type JsonValue,\n} from '@danceroutine/tango-core';\nimport {\n FRAMEWORK_ADAPTER_BRAND,\n FrameworkAdapterRequestExecutor,\n type FrameworkAdapter,\n type FrameworkAdapterOptions,\n} from '@danceroutine/tango-adapters-core/adapter';\nimport {\n InternalHttpMethod,\n InternalActionScope,\n InternalActionMatchKind,\n type ActionScope,\n type HttpMethod,\n} from '@danceroutine/tango-adapters-core';\n\ntype ResolvedViewSetActionDescriptor = {\n name: string;\n scope: ActionScope;\n methods: readonly HttpMethod[];\n path: string;\n};\n\n/**\n * Next.js route handler signature produced by the adapter.\n */\nexport type NextRouteHandler = (\n request: NextRequest,\n context?: { params?: Promise<Record<string, string | string[]>> }\n) => Promise<Response>;\n\nexport type NextDynamicRouteContext = {\n params: Promise<Record<string, string | string[]>>;\n};\n\nexport type NextDynamicRouteHandler = (request: NextRequest, context: NextDynamicRouteContext) => Promise<Response>;\n\n/**\n * Adapter options for Next.js integration.\n */\nexport type AdaptNextOptions = FrameworkAdapterOptions<NextRequest>;\n\n/**\n * Minimal CRUD viewset contract used by the Next adapter route helpers.\n */\nexport interface NextCrudViewSet {\n list(ctx: RequestContext): Promise<TangoResponse>;\n create(ctx: RequestContext): Promise<TangoResponse>;\n retrieve(ctx: RequestContext, id: string): Promise<TangoResponse>;\n update(ctx: RequestContext, id: string): Promise<TangoResponse>;\n destroy(ctx: RequestContext, id: string): Promise<TangoResponse>;\n}\n\nexport interface NextAPIView {\n dispatch(ctx: RequestContext): Promise<TangoResponse>;\n}\n\nexport type NextViewSetFactory = () => NextCrudViewSet | Promise<NextCrudViewSet>;\nexport type NextAPIViewFactory = () => NextAPIView | Promise<NextAPIView>;\n\n/**\n * Options for auto-generated viewset route handlers.\n */\nexport type AdaptNextViewSetOptions = AdaptNextOptions & {\n paramKey?: string;\n};\n\n/**\n * HTTP method handlers generated from a CRUD viewset.\n */\nexport interface NextViewSetRouteHandlers {\n GET: NextDynamicRouteHandler;\n POST: NextDynamicRouteHandler;\n PATCH: NextDynamicRouteHandler;\n PUT: NextDynamicRouteHandler;\n DELETE: NextDynamicRouteHandler;\n}\n\ntype ActionMatch =\n | { kind: typeof InternalActionMatchKind.DETAIL; action: ResolvedViewSetActionDescriptor; id: string }\n | { kind: typeof InternalActionMatchKind.COLLECTION; action: ResolvedViewSetActionDescriptor }\n | { kind: typeof InternalActionMatchKind.METHOD_NOT_ALLOWED };\n\n/**\n * Next.js adapter that translates route handlers to Tango `RequestContext`.\n */\nexport class NextAdapter implements FrameworkAdapter<Response, NextRouteHandler, NextRequest> {\n readonly __tangoBrand: typeof FRAMEWORK_ADAPTER_BRAND = FRAMEWORK_ADAPTER_BRAND;\n private readonly logger = getLogger('tango.adapter.next');\n private readonly requestExecutor = new FrameworkAdapterRequestExecutor();\n /**\n * Normalize Next.js-style route search params into Tango query params.\n */\n toQueryParams(searchParams: Record<string, string | string[] | undefined>): TangoQueryParams {\n return TangoQueryParams.fromRecord(searchParams);\n }\n\n /**\n * Adapt a Tango-style handler into a Next.js route handler.\n */\n adapt(\n handler: (ctx: RequestContext, ...args: unknown[]) => Promise<TangoResponse>,\n options: AdaptNextOptions = {}\n ): NextRouteHandler {\n return this.createHandler(handler, options);\n }\n\n /**\n * Build Next route handlers that map HTTP verbs to standard CRUD viewset actions.\n */\n adaptViewSet(viewset: NextCrudViewSet, options: AdaptNextViewSetOptions = {}): NextViewSetRouteHandlers {\n const paramKey = options.paramKey ?? 'tango';\n return {\n GET: this.adapt(\n (ctx) =>\n this.dispatchViewSetAction(viewset, InternalHttpMethod.GET, ctx, paramKey, (segments, directId) => {\n if (directId) return viewset.retrieve(ctx, directId);\n if (segments.length === 0) return viewset.list(ctx);\n if (segments.length === 1) return viewset.retrieve(ctx, segments[0] as string);\n return this.notFoundResponse();\n }),\n options\n ),\n POST: this.adapt(\n (ctx) =>\n this.dispatchViewSetAction(\n viewset,\n InternalHttpMethod.POST,\n ctx,\n paramKey,\n (segments, directId) => {\n if (segments.length === 0 && !directId) return viewset.create(ctx);\n return this.methodNotAllowedResponse();\n }\n ),\n options\n ),\n PATCH: this.adapt(\n (ctx) =>\n this.dispatchViewSetAction(\n viewset,\n InternalHttpMethod.PATCH,\n ctx,\n paramKey,\n (segments, directId) => {\n const id = directId ?? segments[0];\n return id ? viewset.update(ctx, id) : this.methodNotAllowedResponse();\n }\n ),\n options\n ),\n PUT: this.adapt(\n (ctx) =>\n this.dispatchViewSetAction(viewset, InternalHttpMethod.PUT, ctx, paramKey, (segments, directId) => {\n const id = directId ?? segments[0];\n return id ? viewset.update(ctx, id) : this.methodNotAllowedResponse();\n }),\n options\n ),\n DELETE: this.adapt(\n (ctx) =>\n this.dispatchViewSetAction(\n viewset,\n InternalHttpMethod.DELETE,\n ctx,\n paramKey,\n (segments, directId) => {\n const id = directId ?? segments[0];\n return id ? viewset.destroy(ctx, id) : this.methodNotAllowedResponse();\n }\n ),\n options\n ),\n };\n }\n\n /**\n * Build Next route handlers from a lazy viewset factory and memoize initialization.\n * Initialization failures clear the memoized promise so subsequent requests can retry.\n */\n adaptViewSetFactory(factory: NextViewSetFactory, options: AdaptNextViewSetOptions = {}): NextViewSetRouteHandlers {\n return this.adaptRouteHandlersFactory(async () => {\n const viewset = await factory();\n return this.adaptViewSet(viewset, options);\n });\n }\n\n /**\n * Build Next route handlers from a lazy GenericAPIView factory and memoize initialization.\n */\n adaptGenericAPIViewFactory(\n factory: NextAPIViewFactory,\n options: AdaptNextViewSetOptions = {}\n ): NextViewSetRouteHandlers {\n return this.adaptRouteHandlersFactory(async () => {\n const apiView = await factory();\n return this.adaptGenericAPIView(apiView, options);\n });\n }\n\n /**\n * Build Next route handlers that dispatch an APIView by HTTP method.\n */\n adaptAPIView(apiView: NextAPIView, options: AdaptNextOptions = {}): NextViewSetRouteHandlers {\n return {\n GET: this.adapt((ctx) => apiView.dispatch(ctx), options),\n POST: this.adapt((ctx) => apiView.dispatch(ctx), options),\n PATCH: this.adapt((ctx) => apiView.dispatch(ctx), options),\n PUT: this.adapt((ctx) => apiView.dispatch(ctx), options),\n DELETE: this.adapt((ctx) => apiView.dispatch(ctx), options),\n };\n }\n\n /**\n * Build handlers for GenericAPIView-style collection/detail splits in catch-all routes.\n */\n adaptGenericAPIView(apiView: NextAPIView, options: AdaptNextViewSetOptions = {}): NextViewSetRouteHandlers {\n // Default catch-all param matches the Next.js [[...tango]] route convention.\n const paramKey = options.paramKey ?? 'tango';\n return {\n GET: this.adapt(async (ctx) => {\n const detailId = this.resolveDetailId(ctx.params, paramKey);\n if (!detailId) {\n return apiView.dispatch(ctx);\n }\n ctx.params.id = detailId;\n return apiView.dispatch(ctx);\n }, options),\n POST: this.adapt(async (ctx) => {\n const detailId = this.resolveDetailId(ctx.params, paramKey);\n if (detailId) {\n return this.methodNotAllowedResponse();\n }\n return apiView.dispatch(ctx);\n }, options),\n PATCH: this.adapt(async (ctx) => {\n const detailId = this.resolveDetailId(ctx.params, paramKey);\n if (!detailId) {\n return this.methodNotAllowedResponse();\n }\n ctx.params.id = detailId;\n return apiView.dispatch(ctx);\n }, options),\n PUT: this.adapt(async (ctx) => {\n const detailId = this.resolveDetailId(ctx.params, paramKey);\n if (!detailId) {\n return this.methodNotAllowedResponse();\n }\n ctx.params.id = detailId;\n return apiView.dispatch(ctx);\n }, options),\n DELETE: this.adapt(async (ctx) => {\n const detailId = this.resolveDetailId(ctx.params, paramKey);\n if (!detailId) {\n return this.methodNotAllowedResponse();\n }\n ctx.params.id = detailId;\n return apiView.dispatch(ctx);\n }, options),\n };\n }\n\n private toTangoRequest(request: NextRequest): TangoRequest {\n if (TangoRequest.isTangoRequest(request)) {\n return request;\n }\n\n // oxlint-disable-next-line eslint-js/no-restricted-syntax\n if (request instanceof Request) {\n return new TangoRequest(request);\n }\n\n return new TangoRequest(String((request as { url?: unknown }).url ?? 'http://localhost'));\n }\n\n private dispatchViewSetAction(\n viewset: NextCrudViewSet,\n method: HttpMethod,\n ctx: RequestContext,\n paramKey: string,\n fallback: (segments: string[], directId: string | null) => TangoResponse | Promise<TangoResponse>\n ): Promise<TangoResponse> {\n const segments = this.extractCatchAllSegments(ctx.params, paramKey);\n const directId = this.extractDirectId(ctx.params);\n const actionMatch = this.resolveActionMatch(viewset, method, segments);\n\n if (actionMatch?.kind === InternalActionMatchKind.METHOD_NOT_ALLOWED) {\n return Promise.resolve(this.methodNotAllowedResponse());\n }\n if (actionMatch?.kind === InternalActionMatchKind.DETAIL) {\n return this.invokeDetailAction(viewset, actionMatch.action, ctx, actionMatch.id);\n }\n if (actionMatch?.kind === InternalActionMatchKind.COLLECTION) {\n return this.invokeCollectionAction(viewset, actionMatch.action, ctx);\n }\n\n return Promise.resolve(fallback(segments, directId));\n }\n\n private invokeDetailAction(\n viewset: NextCrudViewSet,\n action: ResolvedViewSetActionDescriptor,\n ctx: RequestContext,\n id: string\n ): Promise<TangoResponse> {\n const candidate = (viewset as unknown as Record<string, unknown>)[action.name];\n if (typeof candidate !== 'function') {\n return Promise.resolve(this.notFoundResponse());\n }\n return (candidate as (this: NextCrudViewSet, ctx: RequestContext, id: string) => Promise<TangoResponse>).call(\n viewset,\n ctx,\n id\n );\n }\n\n private invokeCollectionAction(\n viewset: NextCrudViewSet,\n action: ResolvedViewSetActionDescriptor,\n ctx: RequestContext\n ): Promise<TangoResponse> {\n const candidate = (viewset as unknown as Record<string, unknown>)[action.name];\n if (typeof candidate !== 'function') {\n return Promise.resolve(this.notFoundResponse());\n }\n return (candidate as (this: NextCrudViewSet, ctx: RequestContext) => Promise<TangoResponse>).call(viewset, ctx);\n }\n\n private createHandler(\n handler: (ctx: RequestContext, ...args: unknown[]) => Promise<TangoResponse>,\n options: AdaptNextOptions\n ): NextRouteHandler {\n return async (request: NextRequest, routeContext) => {\n try {\n const user = options.getUser ? await options.getUser(request) : null;\n const rawParams = routeContext?.params ? await routeContext.params : {};\n const params = this.normalizeRouteParams(rawParams);\n\n const ctx = RequestContext.create(this.toTangoRequest(request), user);\n if (Object.keys(params).length > 0) {\n ctx.params = params;\n }\n\n const id = params?.id;\n return await this.requestExecutor\n .forHandler({ handler, ctx, id })\n .runWebResponse(request.method, options.transaction);\n } catch (error) {\n return this.internalServerError(error);\n }\n };\n }\n\n private internalServerError(error: unknown): Response {\n this.logger.error('Adapter error:', error);\n const httpError = HttpErrorFactory.toHttpError(error);\n return TangoResponse.json(httpError.body as JsonValue, { status: httpError.status }).toWebResponse();\n }\n\n private adaptRouteHandlersFactory(factory: () => Promise<NextViewSetRouteHandlers>): NextViewSetRouteHandlers {\n let handlersPromise: Promise<NextViewSetRouteHandlers> | null = null;\n\n const getHandlers = async (): Promise<NextViewSetRouteHandlers> => {\n if (!handlersPromise) {\n const initializing = factory();\n handlersPromise = initializing.catch((error) => {\n handlersPromise = null;\n throw error;\n });\n }\n return handlersPromise;\n };\n\n const createLazyHandler = (method: keyof NextViewSetRouteHandlers): NextDynamicRouteHandler => {\n return async (request, context) => {\n try {\n const handlers = await getHandlers();\n return handlers[method](request, context);\n } catch (error) {\n return this.internalServerError(error);\n }\n };\n };\n\n return {\n GET: createLazyHandler('GET'),\n POST: createLazyHandler('POST'),\n PATCH: createLazyHandler('PATCH'),\n PUT: createLazyHandler('PUT'),\n DELETE: createLazyHandler('DELETE'),\n };\n }\n\n private resolveDetailId(params: Record<string, string>, paramKey: string): string | null {\n const directId = this.extractDirectId(params);\n if (directId) {\n return directId;\n }\n const segments = this.extractCatchAllSegments(params, paramKey);\n if (segments.length !== 1) {\n return null;\n }\n return segments[0] as string;\n }\n\n private normalizeRouteParams(raw: Record<string, string | string[]>): Record<string, string> {\n const entries = Object.entries(raw).map(([key, value]) => {\n return [key, Array.isArray(value) ? value.join('/') : value];\n });\n\n return Object.fromEntries(entries);\n }\n\n private extractDirectId(params: Record<string, string>): string | null {\n const directId = params.id?.trim();\n return directId || null;\n }\n\n private extractCatchAllSegments(params: Record<string, string>, paramKey: string): string[] {\n const catchAll = params[paramKey]?.trim() ?? '';\n if (!catchAll) {\n return [];\n }\n return catchAll.split('/').filter(Boolean);\n }\n\n private methodNotAllowedResponse(): TangoResponse {\n return TangoResponse.json(\n {\n error: 'Method not allowed for this route.',\n },\n { status: 405 }\n );\n }\n\n private notFoundResponse(): TangoResponse {\n return TangoResponse.json(\n {\n error: 'Not found.',\n },\n { status: 404 }\n );\n }\n\n private resolveActionMatch(viewset: NextCrudViewSet, method: HttpMethod, segments: string[]): ActionMatch | null {\n if (segments.length === 0) {\n return null;\n }\n\n const actions = this.getViewSetActions(viewset);\n\n if (segments.length >= 2) {\n const detailPath = segments.slice(1).join('/');\n const detailMatch = actions.find(\n (action) => action.scope === InternalActionScope.DETAIL && action.path === detailPath\n );\n if (detailMatch) {\n return detailMatch.methods.includes(method)\n ? { kind: InternalActionMatchKind.DETAIL, action: detailMatch, id: segments[0] as string }\n : { kind: InternalActionMatchKind.METHOD_NOT_ALLOWED };\n }\n }\n\n if (method === InternalHttpMethod.GET && segments.length === 1) {\n return null;\n }\n\n const collectionPath = segments.join('/');\n const collectionMatch = actions.find(\n (action) => action.scope === InternalActionScope.COLLECTION && action.path === collectionPath\n );\n if (!collectionMatch) {\n return null;\n }\n return collectionMatch.methods.includes(method)\n ? { kind: InternalActionMatchKind.COLLECTION, action: collectionMatch }\n : { kind: InternalActionMatchKind.METHOD_NOT_ALLOWED };\n }\n\n private getViewSetActions(viewset: NextCrudViewSet): readonly ResolvedViewSetActionDescriptor[] {\n const constructorValue = viewset.constructor as {\n getActions?: (input: NextCrudViewSet) => readonly ResolvedViewSetActionDescriptor[];\n };\n\n if (typeof constructorValue.getActions !== 'function') {\n return [];\n }\n\n return constructorValue.getActions(viewset);\n }\n}\n","/**\n * Domain boundary barrel: centralizes this subdomain's public contract.\n */\n\nexport {\n NextAdapter,\n type AdaptNextOptions,\n type AdaptNextViewSetOptions,\n type NextAPIView,\n type NextAPIViewFactory,\n type NextCrudViewSet,\n type NextDynamicRouteContext,\n type NextDynamicRouteHandler,\n type NextRouteHandler,\n type NextViewSetFactory,\n type NextViewSetRouteHandlers,\n} from './NextAdapter';\n"],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ //#region \0rolldown/runtime.js
2
+ var __defProp = Object.defineProperty;
3
+ var __exportAll = (all, no_symbols) => {
4
+ let target = {};
5
+ for (var name in all) __defProp(target, name, {
6
+ get: all[name],
7
+ enumerable: true
8
+ });
9
+ if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
10
+ return target;
11
+ };
12
+ //#endregion
13
+ export { __exportAll as t };
@@ -0,0 +1,109 @@
1
+ import { RequestContext } from "@danceroutine/tango-resources";
2
+ import { TangoQueryParams, TangoResponse } from "@danceroutine/tango-core";
3
+ import { FRAMEWORK_ADAPTER_BRAND, FrameworkAdapter, FrameworkAdapterOptions } from "@danceroutine/tango-adapters-core/adapter";
4
+ import { NextRequest } from "next/server.js";
5
+
6
+ //#region src/adapter/NextAdapter.d.ts
7
+ /**
8
+ * Next.js route handler signature produced by the adapter.
9
+ */
10
+ type NextRouteHandler = (request: NextRequest, context?: {
11
+ params?: Promise<Record<string, string | string[]>>;
12
+ }) => Promise<Response>;
13
+ type NextDynamicRouteContext = {
14
+ params: Promise<Record<string, string | string[]>>;
15
+ };
16
+ type NextDynamicRouteHandler = (request: NextRequest, context: NextDynamicRouteContext) => Promise<Response>;
17
+ /**
18
+ * Adapter options for Next.js integration.
19
+ */
20
+ type AdaptNextOptions = FrameworkAdapterOptions<NextRequest>;
21
+ /**
22
+ * Minimal CRUD viewset contract used by the Next adapter route helpers.
23
+ */
24
+ interface NextCrudViewSet {
25
+ list(ctx: RequestContext): Promise<TangoResponse>;
26
+ create(ctx: RequestContext): Promise<TangoResponse>;
27
+ retrieve(ctx: RequestContext, id: string): Promise<TangoResponse>;
28
+ update(ctx: RequestContext, id: string): Promise<TangoResponse>;
29
+ destroy(ctx: RequestContext, id: string): Promise<TangoResponse>;
30
+ }
31
+ interface NextAPIView {
32
+ dispatch(ctx: RequestContext): Promise<TangoResponse>;
33
+ }
34
+ type NextViewSetFactory = () => NextCrudViewSet | Promise<NextCrudViewSet>;
35
+ type NextAPIViewFactory = () => NextAPIView | Promise<NextAPIView>;
36
+ /**
37
+ * Options for auto-generated viewset route handlers.
38
+ */
39
+ type AdaptNextViewSetOptions = AdaptNextOptions & {
40
+ paramKey?: string;
41
+ };
42
+ /**
43
+ * HTTP method handlers generated from a CRUD viewset.
44
+ */
45
+ interface NextViewSetRouteHandlers {
46
+ GET: NextDynamicRouteHandler;
47
+ POST: NextDynamicRouteHandler;
48
+ PATCH: NextDynamicRouteHandler;
49
+ PUT: NextDynamicRouteHandler;
50
+ DELETE: NextDynamicRouteHandler;
51
+ }
52
+ /**
53
+ * Next.js adapter that translates route handlers to Tango `RequestContext`.
54
+ */
55
+ declare class NextAdapter implements FrameworkAdapter<Response, NextRouteHandler, NextRequest> {
56
+ readonly __tangoBrand: typeof FRAMEWORK_ADAPTER_BRAND;
57
+ private readonly logger;
58
+ private readonly requestExecutor;
59
+ /**
60
+ * Normalize Next.js-style route search params into Tango query params.
61
+ */
62
+ toQueryParams(searchParams: Record<string, string | string[] | undefined>): TangoQueryParams;
63
+ /**
64
+ * Adapt a Tango-style handler into a Next.js route handler.
65
+ */
66
+ adapt(handler: (ctx: RequestContext, ...args: unknown[]) => Promise<TangoResponse>, options?: AdaptNextOptions): NextRouteHandler;
67
+ /**
68
+ * Build Next route handlers that map HTTP verbs to standard CRUD viewset actions.
69
+ */
70
+ adaptViewSet(viewset: NextCrudViewSet, options?: AdaptNextViewSetOptions): NextViewSetRouteHandlers;
71
+ /**
72
+ * Build Next route handlers from a lazy viewset factory and memoize initialization.
73
+ * Initialization failures clear the memoized promise so subsequent requests can retry.
74
+ */
75
+ adaptViewSetFactory(factory: NextViewSetFactory, options?: AdaptNextViewSetOptions): NextViewSetRouteHandlers;
76
+ /**
77
+ * Build Next route handlers from a lazy GenericAPIView factory and memoize initialization.
78
+ */
79
+ adaptGenericAPIViewFactory(factory: NextAPIViewFactory, options?: AdaptNextViewSetOptions): NextViewSetRouteHandlers;
80
+ /**
81
+ * Build Next route handlers that dispatch an APIView by HTTP method.
82
+ */
83
+ adaptAPIView(apiView: NextAPIView, options?: AdaptNextOptions): NextViewSetRouteHandlers;
84
+ /**
85
+ * Build handlers for GenericAPIView-style collection/detail splits in catch-all routes.
86
+ */
87
+ adaptGenericAPIView(apiView: NextAPIView, options?: AdaptNextViewSetOptions): NextViewSetRouteHandlers;
88
+ private toTangoRequest;
89
+ private dispatchViewSetAction;
90
+ private invokeDetailAction;
91
+ private invokeCollectionAction;
92
+ private createHandler;
93
+ private internalServerError;
94
+ private adaptRouteHandlersFactory;
95
+ private resolveDetailId;
96
+ private normalizeRouteParams;
97
+ private extractDirectId;
98
+ private extractCatchAllSegments;
99
+ private methodNotAllowedResponse;
100
+ private notFoundResponse;
101
+ private resolveActionMatch;
102
+ private getViewSetActions;
103
+ }
104
+ declare namespace index_d_exports {
105
+ export { AdaptNextOptions, AdaptNextViewSetOptions, NextAPIView, NextAPIViewFactory, NextAdapter, NextCrudViewSet, NextDynamicRouteContext, NextDynamicRouteHandler, NextRouteHandler, NextViewSetFactory, NextViewSetRouteHandlers };
106
+ }
107
+ //#endregion
108
+ export { NextAPIViewFactory as a, NextDynamicRouteContext as c, NextViewSetFactory as d, NextViewSetRouteHandlers as f, NextAPIView as i, NextDynamicRouteHandler as l, AdaptNextOptions as n, NextAdapter as o, AdaptNextViewSetOptions as r, NextCrudViewSet as s, index_d_exports as t, NextRouteHandler as u };
109
+ //# sourceMappingURL=index-BEw-_Qrg.d.ts.map
package/dist/index.d.ts CHANGED
@@ -1,6 +1,2 @@
1
- /**
2
- * Bundled exports for Django-style domain drill-down imports, plus curated
3
- * top-level symbols for TS-native ergonomic imports.
4
- */
5
- export * as adapter from './adapter/index';
6
- export { NextAdapter, type AdaptNextOptions, type AdaptNextViewSetOptions, type NextAPIView, type NextAPIViewFactory, type NextCrudViewSet, type NextDynamicRouteContext, type NextDynamicRouteHandler, type NextRouteHandler, type NextViewSetFactory, type NextViewSetRouteHandlers, } from './adapter/index';
1
+ import { a as NextAPIViewFactory, c as NextDynamicRouteContext, d as NextViewSetFactory, f as NextViewSetRouteHandlers, i as NextAPIView, l as NextDynamicRouteHandler, n as AdaptNextOptions, o as NextAdapter, r as AdaptNextViewSetOptions, s as NextCrudViewSet, t as index_d_exports, u as NextRouteHandler } from "./index-BEw-_Qrg.js";
2
+ export { type AdaptNextOptions, type AdaptNextViewSetOptions, type NextAPIView, type NextAPIViewFactory, NextAdapter, type NextCrudViewSet, type NextDynamicRouteContext, type NextDynamicRouteHandler, type NextRouteHandler, type NextViewSetFactory, type NextViewSetRouteHandlers, index_d_exports as adapter };
package/dist/index.js CHANGED
@@ -1,3 +1,2 @@
1
- import { NextAdapter, adapter_exports } from "./adapter-Em1-1ezY.js";
2
-
3
- export { NextAdapter, adapter_exports as adapter };
1
+ import { n as NextAdapter, t as adapter_exports } from "./adapter-DStdtW--.js";
2
+ export { NextAdapter, adapter_exports as adapter };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danceroutine/tango-adapters-next",
3
- "version": "1.11.0",
3
+ "version": "1.11.2",
4
4
  "description": "Next.js App Router adapter for Tango viewsets",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -32,9 +32,9 @@
32
32
  "directory": "packages/adapters/next"
33
33
  },
34
34
  "dependencies": {
35
- "@danceroutine/tango-core": "1.11.0",
36
- "@danceroutine/tango-resources": "1.11.0",
37
- "@danceroutine/tango-adapters-core": "1.11.0"
35
+ "@danceroutine/tango-resources": "1.11.2",
36
+ "@danceroutine/tango-adapters-core": "1.11.2",
37
+ "@danceroutine/tango-core": "1.11.2"
38
38
  },
39
39
  "peerDependencies": {
40
40
  "next": "^15.0.0"
@@ -42,9 +42,9 @@
42
42
  "devDependencies": {
43
43
  "@types/node": "^22.9.0",
44
44
  "next": "^15.0.3",
45
- "tsdown": "^0.4.0",
45
+ "tsdown": "^0.22.1",
46
46
  "typescript": "^5.6.3",
47
- "vitest": "^4.0.6"
47
+ "vitest": "^4.1.7"
48
48
  },
49
49
  "scripts": {
50
50
  "build": "tsdown",
@@ -1,101 +0,0 @@
1
- import type { NextRequest } from 'next/server';
2
- import { RequestContext } from '@danceroutine/tango-resources';
3
- import { TangoQueryParams, TangoResponse } from '@danceroutine/tango-core';
4
- import { FRAMEWORK_ADAPTER_BRAND, type FrameworkAdapter, type FrameworkAdapterOptions } from '@danceroutine/tango-adapters-core/adapter';
5
- /**
6
- * Next.js route handler signature produced by the adapter.
7
- */
8
- export type NextRouteHandler = (request: NextRequest, context?: {
9
- params?: Promise<Record<string, string | string[]>>;
10
- }) => Promise<Response>;
11
- export type NextDynamicRouteContext = {
12
- params: Promise<Record<string, string | string[]>>;
13
- };
14
- export type NextDynamicRouteHandler = (request: NextRequest, context: NextDynamicRouteContext) => Promise<Response>;
15
- /**
16
- * Adapter options for Next.js integration.
17
- */
18
- export type AdaptNextOptions = FrameworkAdapterOptions<NextRequest>;
19
- /**
20
- * Minimal CRUD viewset contract used by the Next adapter route helpers.
21
- */
22
- export interface NextCrudViewSet {
23
- list(ctx: RequestContext): Promise<TangoResponse>;
24
- create(ctx: RequestContext): Promise<TangoResponse>;
25
- retrieve(ctx: RequestContext, id: string): Promise<TangoResponse>;
26
- update(ctx: RequestContext, id: string): Promise<TangoResponse>;
27
- destroy(ctx: RequestContext, id: string): Promise<TangoResponse>;
28
- }
29
- export interface NextAPIView {
30
- dispatch(ctx: RequestContext): Promise<TangoResponse>;
31
- }
32
- export type NextViewSetFactory = () => NextCrudViewSet | Promise<NextCrudViewSet>;
33
- export type NextAPIViewFactory = () => NextAPIView | Promise<NextAPIView>;
34
- /**
35
- * Options for auto-generated viewset route handlers.
36
- */
37
- export type AdaptNextViewSetOptions = AdaptNextOptions & {
38
- paramKey?: string;
39
- };
40
- /**
41
- * HTTP method handlers generated from a CRUD viewset.
42
- */
43
- export interface NextViewSetRouteHandlers {
44
- GET: NextDynamicRouteHandler;
45
- POST: NextDynamicRouteHandler;
46
- PATCH: NextDynamicRouteHandler;
47
- PUT: NextDynamicRouteHandler;
48
- DELETE: NextDynamicRouteHandler;
49
- }
50
- /**
51
- * Next.js adapter that translates route handlers to Tango `RequestContext`.
52
- */
53
- export declare class NextAdapter implements FrameworkAdapter<Response, NextRouteHandler, NextRequest> {
54
- readonly __tangoBrand: typeof FRAMEWORK_ADAPTER_BRAND;
55
- private readonly logger;
56
- private readonly requestExecutor;
57
- /**
58
- * Normalize Next.js-style route search params into Tango query params.
59
- */
60
- toQueryParams(searchParams: Record<string, string | string[] | undefined>): TangoQueryParams;
61
- /**
62
- * Adapt a Tango-style handler into a Next.js route handler.
63
- */
64
- adapt(handler: (ctx: RequestContext, ...args: unknown[]) => Promise<TangoResponse>, options?: AdaptNextOptions): NextRouteHandler;
65
- /**
66
- * Build Next route handlers that map HTTP verbs to standard CRUD viewset actions.
67
- */
68
- adaptViewSet(viewset: NextCrudViewSet, options?: AdaptNextViewSetOptions): NextViewSetRouteHandlers;
69
- /**
70
- * Build Next route handlers from a lazy viewset factory and memoize initialization.
71
- * Initialization failures clear the memoized promise so subsequent requests can retry.
72
- */
73
- adaptViewSetFactory(factory: NextViewSetFactory, options?: AdaptNextViewSetOptions): NextViewSetRouteHandlers;
74
- /**
75
- * Build Next route handlers from a lazy GenericAPIView factory and memoize initialization.
76
- */
77
- adaptGenericAPIViewFactory(factory: NextAPIViewFactory, options?: AdaptNextViewSetOptions): NextViewSetRouteHandlers;
78
- /**
79
- * Build Next route handlers that dispatch an APIView by HTTP method.
80
- */
81
- adaptAPIView(apiView: NextAPIView, options?: AdaptNextOptions): NextViewSetRouteHandlers;
82
- /**
83
- * Build handlers for GenericAPIView-style collection/detail splits in catch-all routes.
84
- */
85
- adaptGenericAPIView(apiView: NextAPIView, options?: AdaptNextViewSetOptions): NextViewSetRouteHandlers;
86
- private toTangoRequest;
87
- private dispatchViewSetAction;
88
- private invokeDetailAction;
89
- private invokeCollectionAction;
90
- private createHandler;
91
- private internalServerError;
92
- private adaptRouteHandlersFactory;
93
- private resolveDetailId;
94
- private normalizeRouteParams;
95
- private extractDirectId;
96
- private extractCatchAllSegments;
97
- private methodNotAllowedResponse;
98
- private notFoundResponse;
99
- private resolveActionMatch;
100
- private getViewSetActions;
101
- }
@@ -1 +0,0 @@
1
- {"version":3,"file":"adapter-Em1-1ezY.js","names":["searchParams: Record<string, string | string[] | undefined>","handler: (ctx: RequestContext, ...args: unknown[]) => Promise<TangoResponse>","options: AdaptNextOptions","viewset: NextCrudViewSet","options: AdaptNextViewSetOptions","factory: NextViewSetFactory","factory: NextAPIViewFactory","apiView: NextAPIView","request: NextRequest","method: HttpMethod","ctx: RequestContext","paramKey: string","fallback: (segments: string[], directId: string | null) => TangoResponse | Promise<TangoResponse>","action: ResolvedViewSetActionDescriptor","id: string","error: unknown","factory: () => Promise<NextViewSetRouteHandlers>","handlersPromise: Promise<NextViewSetRouteHandlers> | null","method: keyof NextViewSetRouteHandlers","params: Record<string, string>","raw: Record<string, string | string[]>","segments: string[]"],"sources":["../src/adapter/NextAdapter.ts","../src/adapter/index.ts"],"sourcesContent":["import type { NextRequest } from 'next/server';\nimport { RequestContext } from '@danceroutine/tango-resources';\nimport {\n HttpErrorFactory,\n TangoQueryParams,\n TangoRequest,\n TangoResponse,\n getLogger,\n type JsonValue,\n} from '@danceroutine/tango-core';\nimport {\n FRAMEWORK_ADAPTER_BRAND,\n FrameworkAdapterRequestExecutor,\n type FrameworkAdapter,\n type FrameworkAdapterOptions,\n} from '@danceroutine/tango-adapters-core/adapter';\nimport {\n InternalHttpMethod,\n InternalActionScope,\n InternalActionMatchKind,\n type ActionScope,\n type HttpMethod,\n} from '@danceroutine/tango-adapters-core';\n\ntype ResolvedViewSetActionDescriptor = {\n name: string;\n scope: ActionScope;\n methods: readonly HttpMethod[];\n path: string;\n};\n\n/**\n * Next.js route handler signature produced by the adapter.\n */\nexport type NextRouteHandler = (\n request: NextRequest,\n context?: { params?: Promise<Record<string, string | string[]>> }\n) => Promise<Response>;\n\nexport type NextDynamicRouteContext = {\n params: Promise<Record<string, string | string[]>>;\n};\n\nexport type NextDynamicRouteHandler = (request: NextRequest, context: NextDynamicRouteContext) => Promise<Response>;\n\n/**\n * Adapter options for Next.js integration.\n */\nexport type AdaptNextOptions = FrameworkAdapterOptions<NextRequest>;\n\n/**\n * Minimal CRUD viewset contract used by the Next adapter route helpers.\n */\nexport interface NextCrudViewSet {\n list(ctx: RequestContext): Promise<TangoResponse>;\n create(ctx: RequestContext): Promise<TangoResponse>;\n retrieve(ctx: RequestContext, id: string): Promise<TangoResponse>;\n update(ctx: RequestContext, id: string): Promise<TangoResponse>;\n destroy(ctx: RequestContext, id: string): Promise<TangoResponse>;\n}\n\nexport interface NextAPIView {\n dispatch(ctx: RequestContext): Promise<TangoResponse>;\n}\n\nexport type NextViewSetFactory = () => NextCrudViewSet | Promise<NextCrudViewSet>;\nexport type NextAPIViewFactory = () => NextAPIView | Promise<NextAPIView>;\n\n/**\n * Options for auto-generated viewset route handlers.\n */\nexport type AdaptNextViewSetOptions = AdaptNextOptions & {\n paramKey?: string;\n};\n\n/**\n * HTTP method handlers generated from a CRUD viewset.\n */\nexport interface NextViewSetRouteHandlers {\n GET: NextDynamicRouteHandler;\n POST: NextDynamicRouteHandler;\n PATCH: NextDynamicRouteHandler;\n PUT: NextDynamicRouteHandler;\n DELETE: NextDynamicRouteHandler;\n}\n\ntype ActionMatch =\n | { kind: typeof InternalActionMatchKind.DETAIL; action: ResolvedViewSetActionDescriptor; id: string }\n | { kind: typeof InternalActionMatchKind.COLLECTION; action: ResolvedViewSetActionDescriptor }\n | { kind: typeof InternalActionMatchKind.METHOD_NOT_ALLOWED };\n\n/**\n * Next.js adapter that translates route handlers to Tango `RequestContext`.\n */\nexport class NextAdapter implements FrameworkAdapter<Response, NextRouteHandler, NextRequest> {\n readonly __tangoBrand: typeof FRAMEWORK_ADAPTER_BRAND = FRAMEWORK_ADAPTER_BRAND;\n private readonly logger = getLogger('tango.adapter.next');\n private readonly requestExecutor = new FrameworkAdapterRequestExecutor();\n /**\n * Normalize Next.js-style route search params into Tango query params.\n */\n toQueryParams(searchParams: Record<string, string | string[] | undefined>): TangoQueryParams {\n return TangoQueryParams.fromRecord(searchParams);\n }\n\n /**\n * Adapt a Tango-style handler into a Next.js route handler.\n */\n adapt(\n handler: (ctx: RequestContext, ...args: unknown[]) => Promise<TangoResponse>,\n options: AdaptNextOptions = {}\n ): NextRouteHandler {\n return this.createHandler(handler, options);\n }\n\n /**\n * Build Next route handlers that map HTTP verbs to standard CRUD viewset actions.\n */\n adaptViewSet(viewset: NextCrudViewSet, options: AdaptNextViewSetOptions = {}): NextViewSetRouteHandlers {\n const paramKey = options.paramKey ?? 'tango';\n return {\n GET: this.adapt(\n (ctx) =>\n this.dispatchViewSetAction(viewset, InternalHttpMethod.GET, ctx, paramKey, (segments, directId) => {\n if (directId) return viewset.retrieve(ctx, directId);\n if (segments.length === 0) return viewset.list(ctx);\n if (segments.length === 1) return viewset.retrieve(ctx, segments[0] as string);\n return this.notFoundResponse();\n }),\n options\n ),\n POST: this.adapt(\n (ctx) =>\n this.dispatchViewSetAction(\n viewset,\n InternalHttpMethod.POST,\n ctx,\n paramKey,\n (segments, directId) => {\n if (segments.length === 0 && !directId) return viewset.create(ctx);\n return this.methodNotAllowedResponse();\n }\n ),\n options\n ),\n PATCH: this.adapt(\n (ctx) =>\n this.dispatchViewSetAction(\n viewset,\n InternalHttpMethod.PATCH,\n ctx,\n paramKey,\n (segments, directId) => {\n const id = directId ?? segments[0];\n return id ? viewset.update(ctx, id) : this.methodNotAllowedResponse();\n }\n ),\n options\n ),\n PUT: this.adapt(\n (ctx) =>\n this.dispatchViewSetAction(viewset, InternalHttpMethod.PUT, ctx, paramKey, (segments, directId) => {\n const id = directId ?? segments[0];\n return id ? viewset.update(ctx, id) : this.methodNotAllowedResponse();\n }),\n options\n ),\n DELETE: this.adapt(\n (ctx) =>\n this.dispatchViewSetAction(\n viewset,\n InternalHttpMethod.DELETE,\n ctx,\n paramKey,\n (segments, directId) => {\n const id = directId ?? segments[0];\n return id ? viewset.destroy(ctx, id) : this.methodNotAllowedResponse();\n }\n ),\n options\n ),\n };\n }\n\n /**\n * Build Next route handlers from a lazy viewset factory and memoize initialization.\n * Initialization failures clear the memoized promise so subsequent requests can retry.\n */\n adaptViewSetFactory(factory: NextViewSetFactory, options: AdaptNextViewSetOptions = {}): NextViewSetRouteHandlers {\n return this.adaptRouteHandlersFactory(async () => {\n const viewset = await factory();\n return this.adaptViewSet(viewset, options);\n });\n }\n\n /**\n * Build Next route handlers from a lazy GenericAPIView factory and memoize initialization.\n */\n adaptGenericAPIViewFactory(\n factory: NextAPIViewFactory,\n options: AdaptNextViewSetOptions = {}\n ): NextViewSetRouteHandlers {\n return this.adaptRouteHandlersFactory(async () => {\n const apiView = await factory();\n return this.adaptGenericAPIView(apiView, options);\n });\n }\n\n /**\n * Build Next route handlers that dispatch an APIView by HTTP method.\n */\n adaptAPIView(apiView: NextAPIView, options: AdaptNextOptions = {}): NextViewSetRouteHandlers {\n return {\n GET: this.adapt((ctx) => apiView.dispatch(ctx), options),\n POST: this.adapt((ctx) => apiView.dispatch(ctx), options),\n PATCH: this.adapt((ctx) => apiView.dispatch(ctx), options),\n PUT: this.adapt((ctx) => apiView.dispatch(ctx), options),\n DELETE: this.adapt((ctx) => apiView.dispatch(ctx), options),\n };\n }\n\n /**\n * Build handlers for GenericAPIView-style collection/detail splits in catch-all routes.\n */\n adaptGenericAPIView(apiView: NextAPIView, options: AdaptNextViewSetOptions = {}): NextViewSetRouteHandlers {\n // Default catch-all param matches the Next.js [[...tango]] route convention.\n const paramKey = options.paramKey ?? 'tango';\n return {\n GET: this.adapt(async (ctx) => {\n const detailId = this.resolveDetailId(ctx.params, paramKey);\n if (!detailId) {\n return apiView.dispatch(ctx);\n }\n ctx.params.id = detailId;\n return apiView.dispatch(ctx);\n }, options),\n POST: this.adapt(async (ctx) => {\n const detailId = this.resolveDetailId(ctx.params, paramKey);\n if (detailId) {\n return this.methodNotAllowedResponse();\n }\n return apiView.dispatch(ctx);\n }, options),\n PATCH: this.adapt(async (ctx) => {\n const detailId = this.resolveDetailId(ctx.params, paramKey);\n if (!detailId) {\n return this.methodNotAllowedResponse();\n }\n ctx.params.id = detailId;\n return apiView.dispatch(ctx);\n }, options),\n PUT: this.adapt(async (ctx) => {\n const detailId = this.resolveDetailId(ctx.params, paramKey);\n if (!detailId) {\n return this.methodNotAllowedResponse();\n }\n ctx.params.id = detailId;\n return apiView.dispatch(ctx);\n }, options),\n DELETE: this.adapt(async (ctx) => {\n const detailId = this.resolveDetailId(ctx.params, paramKey);\n if (!detailId) {\n return this.methodNotAllowedResponse();\n }\n ctx.params.id = detailId;\n return apiView.dispatch(ctx);\n }, options),\n };\n }\n\n private toTangoRequest(request: NextRequest): TangoRequest {\n if (TangoRequest.isTangoRequest(request)) {\n return request;\n }\n\n // oxlint-disable-next-line eslint-js/no-restricted-syntax\n if (request instanceof Request) {\n return new TangoRequest(request);\n }\n\n return new TangoRequest(String((request as { url?: unknown }).url ?? 'http://localhost'));\n }\n\n private dispatchViewSetAction(\n viewset: NextCrudViewSet,\n method: HttpMethod,\n ctx: RequestContext,\n paramKey: string,\n fallback: (segments: string[], directId: string | null) => TangoResponse | Promise<TangoResponse>\n ): Promise<TangoResponse> {\n const segments = this.extractCatchAllSegments(ctx.params, paramKey);\n const directId = this.extractDirectId(ctx.params);\n const actionMatch = this.resolveActionMatch(viewset, method, segments);\n\n if (actionMatch?.kind === InternalActionMatchKind.METHOD_NOT_ALLOWED) {\n return Promise.resolve(this.methodNotAllowedResponse());\n }\n if (actionMatch?.kind === InternalActionMatchKind.DETAIL) {\n return this.invokeDetailAction(viewset, actionMatch.action, ctx, actionMatch.id);\n }\n if (actionMatch?.kind === InternalActionMatchKind.COLLECTION) {\n return this.invokeCollectionAction(viewset, actionMatch.action, ctx);\n }\n\n return Promise.resolve(fallback(segments, directId));\n }\n\n private invokeDetailAction(\n viewset: NextCrudViewSet,\n action: ResolvedViewSetActionDescriptor,\n ctx: RequestContext,\n id: string\n ): Promise<TangoResponse> {\n const candidate = (viewset as unknown as Record<string, unknown>)[action.name];\n if (typeof candidate !== 'function') {\n return Promise.resolve(this.notFoundResponse());\n }\n return (candidate as (this: NextCrudViewSet, ctx: RequestContext, id: string) => Promise<TangoResponse>).call(\n viewset,\n ctx,\n id\n );\n }\n\n private invokeCollectionAction(\n viewset: NextCrudViewSet,\n action: ResolvedViewSetActionDescriptor,\n ctx: RequestContext\n ): Promise<TangoResponse> {\n const candidate = (viewset as unknown as Record<string, unknown>)[action.name];\n if (typeof candidate !== 'function') {\n return Promise.resolve(this.notFoundResponse());\n }\n return (candidate as (this: NextCrudViewSet, ctx: RequestContext) => Promise<TangoResponse>).call(viewset, ctx);\n }\n\n private createHandler(\n handler: (ctx: RequestContext, ...args: unknown[]) => Promise<TangoResponse>,\n options: AdaptNextOptions\n ): NextRouteHandler {\n return async (request: NextRequest, routeContext) => {\n try {\n const user = options.getUser ? await options.getUser(request) : null;\n const rawParams = routeContext?.params ? await routeContext.params : {};\n const params = this.normalizeRouteParams(rawParams);\n\n const ctx = RequestContext.create(this.toTangoRequest(request), user);\n if (Object.keys(params).length > 0) {\n ctx.params = params;\n }\n\n const id = params?.id;\n return await this.requestExecutor\n .forHandler({ handler, ctx, id })\n .runWebResponse(request.method, options.transaction);\n } catch (error) {\n return this.internalServerError(error);\n }\n };\n }\n\n private internalServerError(error: unknown): Response {\n this.logger.error('Adapter error:', error);\n const httpError = HttpErrorFactory.toHttpError(error);\n return TangoResponse.json(httpError.body as JsonValue, { status: httpError.status }).toWebResponse();\n }\n\n private adaptRouteHandlersFactory(factory: () => Promise<NextViewSetRouteHandlers>): NextViewSetRouteHandlers {\n let handlersPromise: Promise<NextViewSetRouteHandlers> | null = null;\n\n const getHandlers = async (): Promise<NextViewSetRouteHandlers> => {\n if (!handlersPromise) {\n const initializing = factory();\n handlersPromise = initializing.catch((error) => {\n handlersPromise = null;\n throw error;\n });\n }\n return handlersPromise;\n };\n\n const createLazyHandler = (method: keyof NextViewSetRouteHandlers): NextDynamicRouteHandler => {\n return async (request, context) => {\n try {\n const handlers = await getHandlers();\n return handlers[method](request, context);\n } catch (error) {\n return this.internalServerError(error);\n }\n };\n };\n\n return {\n GET: createLazyHandler('GET'),\n POST: createLazyHandler('POST'),\n PATCH: createLazyHandler('PATCH'),\n PUT: createLazyHandler('PUT'),\n DELETE: createLazyHandler('DELETE'),\n };\n }\n\n private resolveDetailId(params: Record<string, string>, paramKey: string): string | null {\n const directId = this.extractDirectId(params);\n if (directId) {\n return directId;\n }\n const segments = this.extractCatchAllSegments(params, paramKey);\n if (segments.length !== 1) {\n return null;\n }\n return segments[0] as string;\n }\n\n private normalizeRouteParams(raw: Record<string, string | string[]>): Record<string, string> {\n const entries = Object.entries(raw).map(([key, value]) => {\n return [key, Array.isArray(value) ? value.join('/') : value];\n });\n\n return Object.fromEntries(entries);\n }\n\n private extractDirectId(params: Record<string, string>): string | null {\n const directId = params.id?.trim();\n return directId || null;\n }\n\n private extractCatchAllSegments(params: Record<string, string>, paramKey: string): string[] {\n const catchAll = params[paramKey]?.trim() ?? '';\n if (!catchAll) {\n return [];\n }\n return catchAll.split('/').filter(Boolean);\n }\n\n private methodNotAllowedResponse(): TangoResponse {\n return TangoResponse.json(\n {\n error: 'Method not allowed for this route.',\n },\n { status: 405 }\n );\n }\n\n private notFoundResponse(): TangoResponse {\n return TangoResponse.json(\n {\n error: 'Not found.',\n },\n { status: 404 }\n );\n }\n\n private resolveActionMatch(viewset: NextCrudViewSet, method: HttpMethod, segments: string[]): ActionMatch | null {\n if (segments.length === 0) {\n return null;\n }\n\n const actions = this.getViewSetActions(viewset);\n\n if (segments.length >= 2) {\n const detailPath = segments.slice(1).join('/');\n const detailMatch = actions.find(\n (action) => action.scope === InternalActionScope.DETAIL && action.path === detailPath\n );\n if (detailMatch) {\n return detailMatch.methods.includes(method)\n ? { kind: InternalActionMatchKind.DETAIL, action: detailMatch, id: segments[0] as string }\n : { kind: InternalActionMatchKind.METHOD_NOT_ALLOWED };\n }\n }\n\n if (method === InternalHttpMethod.GET && segments.length === 1) {\n return null;\n }\n\n const collectionPath = segments.join('/');\n const collectionMatch = actions.find(\n (action) => action.scope === InternalActionScope.COLLECTION && action.path === collectionPath\n );\n if (!collectionMatch) {\n return null;\n }\n return collectionMatch.methods.includes(method)\n ? { kind: InternalActionMatchKind.COLLECTION, action: collectionMatch }\n : { kind: InternalActionMatchKind.METHOD_NOT_ALLOWED };\n }\n\n private getViewSetActions(viewset: NextCrudViewSet): readonly ResolvedViewSetActionDescriptor[] {\n const constructorValue = viewset.constructor as {\n getActions?: (input: NextCrudViewSet) => readonly ResolvedViewSetActionDescriptor[];\n };\n\n if (typeof constructorValue.getActions !== 'function') {\n return [];\n }\n\n return constructorValue.getActions(viewset);\n }\n}\n","/**\n * Domain boundary barrel: centralizes this subdomain's public contract.\n */\n\nexport {\n NextAdapter,\n type AdaptNextOptions,\n type AdaptNextViewSetOptions,\n type NextAPIView,\n type NextAPIViewFactory,\n type NextCrudViewSet,\n type NextDynamicRouteContext,\n type NextDynamicRouteHandler,\n type NextRouteHandler,\n type NextViewSetFactory,\n type NextViewSetRouteHandlers,\n} from './NextAdapter';\n"],"mappings":";;;;;;;;;;;;;;;;IA8Fa,cAAN,MAAuF;CAC1F,eAAwD;CACxD,SAA0B,UAAU,qBAAqB;CACzD,kBAAmC,IAAI;;;;CAIvC,cAAcA,cAA+E;AACzF,SAAO,iBAAiB,WAAW,aAAa;CACnD;;;;CAKD,MACIC,SACAC,UAA4B,CAAE,GACd;AAChB,SAAO,KAAK,cAAc,SAAS,QAAQ;CAC9C;;;;CAKD,aAAaC,SAA0BC,UAAmC,CAAE,GAA4B;EACpG,MAAM,WAAW,QAAQ,YAAY;AACrC,SAAO;GACH,KAAK,KAAK,MACN,CAAC,QACG,KAAK,sBAAsB,SAAS,mBAAmB,KAAK,KAAK,UAAU,CAAC,UAAU,aAAa;AAC/F,QAAI,SAAU,QAAO,QAAQ,SAAS,KAAK,SAAS;AACpD,QAAI,SAAS,WAAW,EAAG,QAAO,QAAQ,KAAK,IAAI;AACnD,QAAI,SAAS,WAAW,EAAG,QAAO,QAAQ,SAAS,KAAK,SAAS,GAAa;AAC9E,WAAO,KAAK,kBAAkB;GACjC,EAAC,EACN,QACH;GACD,MAAM,KAAK,MACP,CAAC,QACG,KAAK,sBACD,SACA,mBAAmB,MACnB,KACA,UACA,CAAC,UAAU,aAAa;AACpB,QAAI,SAAS,WAAW,MAAM,SAAU,QAAO,QAAQ,OAAO,IAAI;AAClE,WAAO,KAAK,0BAA0B;GACzC,EACJ,EACL,QACH;GACD,OAAO,KAAK,MACR,CAAC,QACG,KAAK,sBACD,SACA,mBAAmB,OACnB,KACA,UACA,CAAC,UAAU,aAAa;IACpB,MAAM,KAAK,YAAY,SAAS;AAChC,WAAO,KAAK,QAAQ,OAAO,KAAK,GAAG,GAAG,KAAK,0BAA0B;GACxE,EACJ,EACL,QACH;GACD,KAAK,KAAK,MACN,CAAC,QACG,KAAK,sBAAsB,SAAS,mBAAmB,KAAK,KAAK,UAAU,CAAC,UAAU,aAAa;IAC/F,MAAM,KAAK,YAAY,SAAS;AAChC,WAAO,KAAK,QAAQ,OAAO,KAAK,GAAG,GAAG,KAAK,0BAA0B;GACxE,EAAC,EACN,QACH;GACD,QAAQ,KAAK,MACT,CAAC,QACG,KAAK,sBACD,SACA,mBAAmB,QACnB,KACA,UACA,CAAC,UAAU,aAAa;IACpB,MAAM,KAAK,YAAY,SAAS;AAChC,WAAO,KAAK,QAAQ,QAAQ,KAAK,GAAG,GAAG,KAAK,0BAA0B;GACzE,EACJ,EACL,QACH;EACJ;CACJ;;;;;CAMD,oBAAoBC,SAA6BD,UAAmC,CAAE,GAA4B;AAC9G,SAAO,KAAK,0BAA0B,YAAY;GAC9C,MAAM,UAAU,MAAM,SAAS;AAC/B,UAAO,KAAK,aAAa,SAAS,QAAQ;EAC7C,EAAC;CACL;;;;CAKD,2BACIE,SACAF,UAAmC,CAAE,GACb;AACxB,SAAO,KAAK,0BAA0B,YAAY;GAC9C,MAAM,UAAU,MAAM,SAAS;AAC/B,UAAO,KAAK,oBAAoB,SAAS,QAAQ;EACpD,EAAC;CACL;;;;CAKD,aAAaG,SAAsBL,UAA4B,CAAE,GAA4B;AACzF,SAAO;GACH,KAAK,KAAK,MAAM,CAAC,QAAQ,QAAQ,SAAS,IAAI,EAAE,QAAQ;GACxD,MAAM,KAAK,MAAM,CAAC,QAAQ,QAAQ,SAAS,IAAI,EAAE,QAAQ;GACzD,OAAO,KAAK,MAAM,CAAC,QAAQ,QAAQ,SAAS,IAAI,EAAE,QAAQ;GAC1D,KAAK,KAAK,MAAM,CAAC,QAAQ,QAAQ,SAAS,IAAI,EAAE,QAAQ;GACxD,QAAQ,KAAK,MAAM,CAAC,QAAQ,QAAQ,SAAS,IAAI,EAAE,QAAQ;EAC9D;CACJ;;;;CAKD,oBAAoBK,SAAsBH,UAAmC,CAAE,GAA4B;EAEvG,MAAM,WAAW,QAAQ,YAAY;AACrC,SAAO;GACH,KAAK,KAAK,MAAM,OAAO,QAAQ;IAC3B,MAAM,WAAW,KAAK,gBAAgB,IAAI,QAAQ,SAAS;AAC3D,SAAK,SACD,QAAO,QAAQ,SAAS,IAAI;AAEhC,QAAI,OAAO,KAAK;AAChB,WAAO,QAAQ,SAAS,IAAI;GAC/B,GAAE,QAAQ;GACX,MAAM,KAAK,MAAM,OAAO,QAAQ;IAC5B,MAAM,WAAW,KAAK,gBAAgB,IAAI,QAAQ,SAAS;AAC3D,QAAI,SACA,QAAO,KAAK,0BAA0B;AAE1C,WAAO,QAAQ,SAAS,IAAI;GAC/B,GAAE,QAAQ;GACX,OAAO,KAAK,MAAM,OAAO,QAAQ;IAC7B,MAAM,WAAW,KAAK,gBAAgB,IAAI,QAAQ,SAAS;AAC3D,SAAK,SACD,QAAO,KAAK,0BAA0B;AAE1C,QAAI,OAAO,KAAK;AAChB,WAAO,QAAQ,SAAS,IAAI;GAC/B,GAAE,QAAQ;GACX,KAAK,KAAK,MAAM,OAAO,QAAQ;IAC3B,MAAM,WAAW,KAAK,gBAAgB,IAAI,QAAQ,SAAS;AAC3D,SAAK,SACD,QAAO,KAAK,0BAA0B;AAE1C,QAAI,OAAO,KAAK;AAChB,WAAO,QAAQ,SAAS,IAAI;GAC/B,GAAE,QAAQ;GACX,QAAQ,KAAK,MAAM,OAAO,QAAQ;IAC9B,MAAM,WAAW,KAAK,gBAAgB,IAAI,QAAQ,SAAS;AAC3D,SAAK,SACD,QAAO,KAAK,0BAA0B;AAE1C,QAAI,OAAO,KAAK;AAChB,WAAO,QAAQ,SAAS,IAAI;GAC/B,GAAE,QAAQ;EACd;CACJ;CAED,eAAuBI,SAAoC;AACvD,MAAI,aAAa,eAAe,QAAQ,CACpC,QAAO;AAIX,MAAI,mBAAmB,QACnB,QAAO,IAAI,aAAa;AAG5B,SAAO,IAAI,aAAa,OAAQ,QAA8B,OAAO,mBAAmB;CAC3F;CAED,sBACIL,SACAM,QACAC,KACAC,UACAC,UACsB;EACtB,MAAM,WAAW,KAAK,wBAAwB,IAAI,QAAQ,SAAS;EACnE,MAAM,WAAW,KAAK,gBAAgB,IAAI,OAAO;EACjD,MAAM,cAAc,KAAK,mBAAmB,SAAS,QAAQ,SAAS;AAEtE,MAAI,aAAa,SAAS,wBAAwB,mBAC9C,QAAO,QAAQ,QAAQ,KAAK,0BAA0B,CAAC;AAE3D,MAAI,aAAa,SAAS,wBAAwB,OAC9C,QAAO,KAAK,mBAAmB,SAAS,YAAY,QAAQ,KAAK,YAAY,GAAG;AAEpF,MAAI,aAAa,SAAS,wBAAwB,WAC9C,QAAO,KAAK,uBAAuB,SAAS,YAAY,QAAQ,IAAI;AAGxE,SAAO,QAAQ,QAAQ,SAAS,UAAU,SAAS,CAAC;CACvD;CAED,mBACIT,SACAU,QACAH,KACAI,IACsB;EACtB,MAAM,YAAa,QAA+C,OAAO;AACzE,aAAW,cAAc,WACrB,QAAO,QAAQ,QAAQ,KAAK,kBAAkB,CAAC;AAEnD,SAAO,UAAkG,KACrG,SACA,KACA,GACH;CACJ;CAED,uBACIX,SACAU,QACAH,KACsB;EACtB,MAAM,YAAa,QAA+C,OAAO;AACzE,aAAW,cAAc,WACrB,QAAO,QAAQ,QAAQ,KAAK,kBAAkB,CAAC;AAEnD,SAAO,UAAsF,KAAK,SAAS,IAAI;CAClH;CAED,cACIT,SACAC,SACgB;AAChB,SAAO,OAAOM,SAAsB,iBAAiB;AACjD,OAAI;IACA,MAAM,OAAO,QAAQ,UAAU,MAAM,QAAQ,QAAQ,QAAQ,GAAG;IAChE,MAAM,YAAY,cAAc,SAAS,MAAM,aAAa,SAAS,CAAE;IACvE,MAAM,SAAS,KAAK,qBAAqB,UAAU;IAEnD,MAAM,MAAM,eAAe,OAAO,KAAK,eAAe,QAAQ,EAAE,KAAK;AACrE,QAAI,OAAO,KAAK,OAAO,CAAC,SAAS,EAC7B,KAAI,SAAS;IAGjB,MAAM,KAAK,QAAQ;AACnB,WAAO,MAAM,KAAK,gBACb,WAAW;KAAE;KAAS;KAAK;IAAI,EAAC,CAChC,eAAe,QAAQ,QAAQ,QAAQ,YAAY;GAC3D,SAAQ,OAAO;AACZ,WAAO,KAAK,oBAAoB,MAAM;GACzC;EACJ;CACJ;CAED,oBAA4BO,OAA0B;AAClD,OAAK,OAAO,MAAM,kBAAkB,MAAM;EAC1C,MAAM,YAAY,iBAAiB,YAAY,MAAM;AACrD,SAAO,cAAc,KAAK,UAAU,MAAmB,EAAE,QAAQ,UAAU,OAAQ,EAAC,CAAC,eAAe;CACvG;CAED,0BAAkCC,SAA4E;EAC1G,IAAIC,kBAA4D;EAEhE,MAAM,cAAc,YAA+C;AAC/D,QAAK,iBAAiB;IAClB,MAAM,eAAe,SAAS;AAC9B,sBAAkB,aAAa,MAAM,CAAC,UAAU;AAC5C,uBAAkB;AAClB,WAAM;IACT,EAAC;GACL;AACD,UAAO;EACV;EAED,MAAM,oBAAoB,CAACC,WAAoE;AAC3F,UAAO,OAAO,SAAS,YAAY;AAC/B,QAAI;KACA,MAAM,WAAW,MAAM,aAAa;AACpC,YAAO,SAAS,QAAQ,SAAS,QAAQ;IAC5C,SAAQ,OAAO;AACZ,YAAO,KAAK,oBAAoB,MAAM;IACzC;GACJ;EACJ;AAED,SAAO;GACH,KAAK,kBAAkB,MAAM;GAC7B,MAAM,kBAAkB,OAAO;GAC/B,OAAO,kBAAkB,QAAQ;GACjC,KAAK,kBAAkB,MAAM;GAC7B,QAAQ,kBAAkB,SAAS;EACtC;CACJ;CAED,gBAAwBC,QAAgCR,UAAiC;EACrF,MAAM,WAAW,KAAK,gBAAgB,OAAO;AAC7C,MAAI,SACA,QAAO;EAEX,MAAM,WAAW,KAAK,wBAAwB,QAAQ,SAAS;AAC/D,MAAI,SAAS,WAAW,EACpB,QAAO;AAEX,SAAO,SAAS;CACnB;CAED,qBAA6BS,KAAgE;EACzF,MAAM,UAAU,OAAO,QAAQ,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,MAAM,KAAK;AACtD,UAAO,CAAC,KAAK,MAAM,QAAQ,MAAM,GAAG,MAAM,KAAK,IAAI,GAAG,KAAM;EAC/D,EAAC;AAEF,SAAO,OAAO,YAAY,QAAQ;CACrC;CAED,gBAAwBD,QAA+C;EACnE,MAAM,WAAW,OAAO,IAAI,MAAM;AAClC,SAAO,YAAY;CACtB;CAED,wBAAgCA,QAAgCR,UAA4B;EACxF,MAAM,WAAW,OAAO,WAAW,MAAM,IAAI;AAC7C,OAAK,SACD,QAAO,CAAE;AAEb,SAAO,SAAS,MAAM,IAAI,CAAC,OAAO,QAAQ;CAC7C;CAED,2BAAkD;AAC9C,SAAO,cAAc,KACjB,EACI,OAAO,qCACV,GACD,EAAE,QAAQ,IAAK,EAClB;CACJ;CAED,mBAA0C;AACtC,SAAO,cAAc,KACjB,EACI,OAAO,aACV,GACD,EAAE,QAAQ,IAAK,EAClB;CACJ;CAED,mBAA2BR,SAA0BM,QAAoBY,UAAwC;AAC7G,MAAI,SAAS,WAAW,EACpB,QAAO;EAGX,MAAM,UAAU,KAAK,kBAAkB,QAAQ;AAE/C,MAAI,SAAS,UAAU,GAAG;GACtB,MAAM,aAAa,SAAS,MAAM,EAAE,CAAC,KAAK,IAAI;GAC9C,MAAM,cAAc,QAAQ,KACxB,CAAC,WAAW,OAAO,UAAU,oBAAoB,UAAU,OAAO,SAAS,WAC9E;AACD,OAAI,YACA,QAAO,YAAY,QAAQ,SAAS,OAAO,GACrC;IAAE,MAAM,wBAAwB;IAAQ,QAAQ;IAAa,IAAI,SAAS;GAAc,IACxF,EAAE,MAAM,wBAAwB,mBAAoB;EAEjE;AAED,MAAI,WAAW,mBAAmB,OAAO,SAAS,WAAW,EACzD,QAAO;EAGX,MAAM,iBAAiB,SAAS,KAAK,IAAI;EACzC,MAAM,kBAAkB,QAAQ,KAC5B,CAAC,WAAW,OAAO,UAAU,oBAAoB,cAAc,OAAO,SAAS,eAClF;AACD,OAAK,gBACD,QAAO;AAEX,SAAO,gBAAgB,QAAQ,SAAS,OAAO,GACzC;GAAE,MAAM,wBAAwB;GAAY,QAAQ;EAAiB,IACrE,EAAE,MAAM,wBAAwB,mBAAoB;CAC7D;CAED,kBAA0BlB,SAAsE;EAC5F,MAAM,mBAAmB,QAAQ;AAIjC,aAAW,iBAAiB,eAAe,WACvC,QAAO,CAAE;AAGb,SAAO,iBAAiB,WAAW,QAAQ;CAC9C;AACJ"}