@tern-secure/nextjs 5.2.0-canary.v20250919131424 → 5.2.0-canary.v20250926170202

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.
Files changed (66) hide show
  1. package/dist/cjs/app-router/admin/api/endpoints/abstract.js.map +1 -1
  2. package/dist/cjs/app-router/admin/{claude-authenticateRequestProcessor.js → c-authenticateRequestProcessor.js} +22 -7
  3. package/dist/cjs/app-router/admin/c-authenticateRequestProcessor.js.map +1 -0
  4. package/dist/cjs/app-router/admin/endpointRouter.js +10 -11
  5. package/dist/cjs/app-router/admin/endpointRouter.js.map +1 -1
  6. package/dist/cjs/app-router/admin/fnValidators.js +10 -24
  7. package/dist/cjs/app-router/admin/fnValidators.js.map +1 -1
  8. package/dist/cjs/app-router/admin/index.js +0 -5
  9. package/dist/cjs/app-router/admin/index.js.map +1 -1
  10. package/dist/cjs/app-router/admin/sessionHandlers.js +83 -123
  11. package/dist/cjs/app-router/admin/sessionHandlers.js.map +1 -1
  12. package/dist/cjs/app-router/admin/ternsecureNextjsHandler.js +21 -34
  13. package/dist/cjs/app-router/admin/ternsecureNextjsHandler.js.map +1 -1
  14. package/dist/cjs/app-router/admin/types.js +83 -5
  15. package/dist/cjs/app-router/admin/types.js.map +1 -1
  16. package/dist/cjs/server/constant.js +4 -1
  17. package/dist/cjs/server/constant.js.map +1 -1
  18. package/dist/cjs/server/ternSecureEdgeMiddleware.js +1 -11
  19. package/dist/cjs/server/ternSecureEdgeMiddleware.js.map +1 -1
  20. package/dist/esm/app-router/admin/api/endpoints/abstract.js.map +1 -1
  21. package/dist/esm/app-router/admin/{claude-authenticateRequestProcessor.js → c-authenticateRequestProcessor.js} +19 -4
  22. package/dist/esm/app-router/admin/c-authenticateRequestProcessor.js.map +1 -0
  23. package/dist/esm/app-router/admin/endpointRouter.js +11 -12
  24. package/dist/esm/app-router/admin/endpointRouter.js.map +1 -1
  25. package/dist/esm/app-router/admin/fnValidators.js +10 -23
  26. package/dist/esm/app-router/admin/fnValidators.js.map +1 -1
  27. package/dist/esm/app-router/admin/index.js +0 -3
  28. package/dist/esm/app-router/admin/index.js.map +1 -1
  29. package/dist/esm/app-router/admin/sessionHandlers.js +82 -110
  30. package/dist/esm/app-router/admin/sessionHandlers.js.map +1 -1
  31. package/dist/esm/app-router/admin/ternsecureNextjsHandler.js +22 -35
  32. package/dist/esm/app-router/admin/ternsecureNextjsHandler.js.map +1 -1
  33. package/dist/esm/app-router/admin/types.js +80 -4
  34. package/dist/esm/app-router/admin/types.js.map +1 -1
  35. package/dist/esm/server/constant.js +3 -1
  36. package/dist/esm/server/constant.js.map +1 -1
  37. package/dist/esm/server/ternSecureEdgeMiddleware.js +2 -12
  38. package/dist/esm/server/ternSecureEdgeMiddleware.js.map +1 -1
  39. package/dist/types/app-router/admin/api/endpoints/abstract.d.ts +6 -4
  40. package/dist/types/app-router/admin/api/endpoints/abstract.d.ts.map +1 -1
  41. package/dist/types/app-router/admin/{claude-authenticateRequestProcessor.d.ts → c-authenticateRequestProcessor.d.ts} +13 -5
  42. package/dist/types/app-router/admin/c-authenticateRequestProcessor.d.ts.map +1 -0
  43. package/dist/types/app-router/admin/endpointRouter.d.ts +7 -4
  44. package/dist/types/app-router/admin/endpointRouter.d.ts.map +1 -1
  45. package/dist/types/app-router/admin/fnValidators.d.ts +2 -11
  46. package/dist/types/app-router/admin/fnValidators.d.ts.map +1 -1
  47. package/dist/types/app-router/admin/index.d.ts +1 -3
  48. package/dist/types/app-router/admin/index.d.ts.map +1 -1
  49. package/dist/types/app-router/admin/sessionHandlers.d.ts +3 -24
  50. package/dist/types/app-router/admin/sessionHandlers.d.ts.map +1 -1
  51. package/dist/types/app-router/admin/ternsecureNextjsHandler.d.ts.map +1 -1
  52. package/dist/types/app-router/admin/types.d.ts +40 -64
  53. package/dist/types/app-router/admin/types.d.ts.map +1 -1
  54. package/dist/types/server/constant.d.ts +2 -1
  55. package/dist/types/server/constant.d.ts.map +1 -1
  56. package/dist/types/server/ternSecureEdgeMiddleware.d.ts.map +1 -1
  57. package/package.json +5 -5
  58. package/dist/cjs/app-router/admin/claude-authenticateRequestProcessor.js.map +0 -1
  59. package/dist/cjs/app-router/admin/handlerUtils.js +0 -63
  60. package/dist/cjs/app-router/admin/handlerUtils.js.map +0 -1
  61. package/dist/esm/app-router/admin/claude-authenticateRequestProcessor.js.map +0 -1
  62. package/dist/esm/app-router/admin/handlerUtils.js +0 -38
  63. package/dist/esm/app-router/admin/handlerUtils.js.map +0 -1
  64. package/dist/types/app-router/admin/claude-authenticateRequestProcessor.d.ts.map +0 -1
  65. package/dist/types/app-router/admin/handlerUtils.d.ts +0 -19
  66. package/dist/types/app-router/admin/handlerUtils.d.ts.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/app-router/admin/endpointRouter.ts"],"sourcesContent":["import type { EndpointHandler} from './api/endpoints/abstract';\nimport type { HandlerContext } from './handlerUtils';\nimport { createApiErrorResponse } from './responses';\nimport { SessionEndpointHandler } from './sessionHandlers';\nimport type { AuthEndpoint, TernSecureInternalHandlerConfig } from './types';\n\nclass SessionsHandler implements EndpointHandler {\n canHandle(endpoint: AuthEndpoint): boolean {\n return endpoint === 'sessions';\n }\n\n async handle(\n handlerContext: HandlerContext,\n config: TernSecureInternalHandlerConfig,\n ): Promise<Response> {\n const { request, subEndpoint, method } = handlerContext;\n return await SessionEndpointHandler.handle(request, method, subEndpoint, config);\n }\n}\n\nclass UsersHandler implements EndpointHandler {\n canHandle(endpoint: AuthEndpoint): boolean {\n return endpoint === 'users';\n }\n\n handle(\n _handlerContext: HandlerContext,\n _config: TernSecureInternalHandlerConfig,\n ): Promise<Response> {\n return Promise.resolve(\n createApiErrorResponse('ENDPOINT_NOT_IMPLEMENTED', 'Users endpoint not implemented', 501),\n );\n }\n}\n\nexport class EndpointRouter {\n private static readonly handlers: EndpointHandler[] = [\n new SessionsHandler(),\n new UsersHandler(),\n ];\n\n static async route(\n handlerContext: HandlerContext,\n config: TernSecureInternalHandlerConfig,\n ): Promise<Response> {\n const { endpoint } = handlerContext;\n\n const handler = this.handlers.find(h => h.canHandle(endpoint));\n\n if (!handler) {\n return createApiErrorResponse('ENDPOINT_NOT_FOUND', 'Endpoint not found', 404);\n }\n\n return handler.handle(handlerContext, config);\n }\n\n static addHandler(handler: EndpointHandler): void {\n this.handlers.push(handler);\n }\n\n static removeHandler(predicate: (handler: EndpointHandler) => boolean): void {\n const index = this.handlers.findIndex(predicate);\n if (index > -1) {\n this.handlers.splice(index, 1);\n }\n }\n}"],"mappings":"AAEA,SAAS,8BAA8B;AACvC,SAAS,8BAA8B;AAGvC,MAAM,gBAA2C;AAAA,EAC/C,UAAU,UAAiC;AACzC,WAAO,aAAa;AAAA,EACtB;AAAA,EAEA,MAAM,OACJ,gBACA,QACmB;AACnB,UAAM,EAAE,SAAS,aAAa,OAAO,IAAI;AACzC,WAAO,MAAM,uBAAuB,OAAO,SAAS,QAAQ,aAAa,MAAM;AAAA,EACjF;AACF;AAEA,MAAM,aAAwC;AAAA,EAC5C,UAAU,UAAiC;AACzC,WAAO,aAAa;AAAA,EACtB;AAAA,EAEA,OACE,iBACA,SACmB;AACnB,WAAO,QAAQ;AAAA,MACb,uBAAuB,4BAA4B,kCAAkC,GAAG;AAAA,IAC1F;AAAA,EACF;AACF;AAEO,MAAM,eAAe;AAAA,EAC1B,OAAwB,WAA8B;AAAA,IACpD,IAAI,gBAAgB;AAAA,IACpB,IAAI,aAAa;AAAA,EACnB;AAAA,EAEA,aAAa,MACX,gBACA,QACmB;AACnB,UAAM,EAAE,SAAS,IAAI;AAErB,UAAM,UAAU,KAAK,SAAS,KAAK,OAAK,EAAE,UAAU,QAAQ,CAAC;AAE7D,QAAI,CAAC,SAAS;AACZ,aAAO,uBAAuB,sBAAsB,sBAAsB,GAAG;AAAA,IAC/E;AAEA,WAAO,QAAQ,OAAO,gBAAgB,MAAM;AAAA,EAC9C;AAAA,EAEA,OAAO,WAAW,SAAgC;AAChD,SAAK,SAAS,KAAK,OAAO;AAAA,EAC5B;AAAA,EAEA,OAAO,cAAc,WAAwD;AAC3E,UAAM,QAAQ,KAAK,SAAS,UAAU,SAAS;AAC/C,QAAI,QAAQ,IAAI;AACd,WAAK,SAAS,OAAO,OAAO,CAAC;AAAA,IAC/B;AAAA,EACF;AACF;","names":[]}
1
+ {"version":3,"sources":["../../../../src/app-router/admin/endpointRouter.ts"],"sourcesContent":["import type { RequestProcessorContext } from './c-authenticateRequestProcessor';\nimport { createApiErrorResponse } from './responses';\nimport { sessionEndpointHandler } from './sessionHandlers';\nimport type { AuthEndpoint, TernSecureHandlerOptions } from './types';\n\nexport interface EndpointHandler {\n canHandle(endpoint: AuthEndpoint): boolean;\n handle(context: RequestProcessorContext, config: TernSecureHandlerOptions): Promise<Response>;\n}\n\nclass SessionsHandler implements EndpointHandler {\n canHandle(endpoint: AuthEndpoint): boolean {\n return endpoint === 'sessions';\n }\n\n async handle(\n context: RequestProcessorContext,\n config: TernSecureHandlerOptions,\n ): Promise<Response> {\n return await sessionEndpointHandler(context, config);\n }\n}\n\nclass UsersHandler implements EndpointHandler {\n canHandle(endpoint: AuthEndpoint): boolean {\n return endpoint === 'users';\n }\n\n handle(_context: RequestProcessorContext, _config: TernSecureHandlerOptions): Promise<Response> {\n return Promise.resolve(\n createApiErrorResponse('ENDPOINT_NOT_IMPLEMENTED', 'Users endpoint not implemented', 501),\n );\n }\n}\n\nexport class EndpointRouter {\n private static readonly handlers: EndpointHandler[] = [new SessionsHandler(), new UsersHandler()];\n\n static async route(\n context: RequestProcessorContext,\n config: TernSecureHandlerOptions,\n ): Promise<Response> {\n const { endpoint } = context;\n\n if (!endpoint) {\n return createApiErrorResponse('ENDPOINT_REQUIRED', 'Endpoint is required', 400);\n }\n\n const handler = this.handlers.find(h => h.canHandle(endpoint));\n\n if (!handler) {\n return createApiErrorResponse('ENDPOINT_NOT_FOUND', 'Endpoint not found', 404);\n }\n\n return handler.handle(context, config);\n }\n\n static addHandler(handler: EndpointHandler): void {\n this.handlers.push(handler);\n }\n\n static removeHandler(predicate: (handler: EndpointHandler) => boolean): void {\n const index = this.handlers.findIndex(predicate);\n if (index > -1) {\n this.handlers.splice(index, 1);\n }\n }\n}\n"],"mappings":"AACA,SAAS,8BAA8B;AACvC,SAAS,8BAA8B;AAQvC,MAAM,gBAA2C;AAAA,EAC/C,UAAU,UAAiC;AACzC,WAAO,aAAa;AAAA,EACtB;AAAA,EAEA,MAAM,OACJ,SACA,QACmB;AACnB,WAAO,MAAM,uBAAuB,SAAS,MAAM;AAAA,EACrD;AACF;AAEA,MAAM,aAAwC;AAAA,EAC5C,UAAU,UAAiC;AACzC,WAAO,aAAa;AAAA,EACtB;AAAA,EAEA,OAAO,UAAmC,SAAsD;AAC9F,WAAO,QAAQ;AAAA,MACb,uBAAuB,4BAA4B,kCAAkC,GAAG;AAAA,IAC1F;AAAA,EACF;AACF;AAEO,MAAM,eAAe;AAAA,EAC1B,OAAwB,WAA8B,CAAC,IAAI,gBAAgB,GAAG,IAAI,aAAa,CAAC;AAAA,EAEhG,aAAa,MACX,SACA,QACmB;AACnB,UAAM,EAAE,SAAS,IAAI;AAErB,QAAI,CAAC,UAAU;AACb,aAAO,uBAAuB,qBAAqB,wBAAwB,GAAG;AAAA,IAChF;AAEA,UAAM,UAAU,KAAK,SAAS,KAAK,OAAK,EAAE,UAAU,QAAQ,CAAC;AAE7D,QAAI,CAAC,SAAS;AACZ,aAAO,uBAAuB,sBAAsB,sBAAsB,GAAG;AAAA,IAC/E;AAEA,WAAO,QAAQ,OAAO,SAAS,MAAM;AAAA,EACvC;AAAA,EAEA,OAAO,WAAW,SAAgC;AAChD,SAAK,SAAS,KAAK,OAAO;AAAA,EAC5B;AAAA,EAEA,OAAO,cAAc,WAAwD;AAC3E,UAAM,QAAQ,KAAK,SAAS,UAAU,SAAS;AAC/C,QAAI,QAAQ,IAAI;AACd,WAAK,SAAS,OAAO,OAAO,CAAC;AAAA,IAC/B;AAAA,EACF;AACF;","names":[]}
@@ -1,20 +1,8 @@
1
1
  import { cookies } from "next/headers";
2
2
  import { createApiErrorResponse } from "./responses";
3
- function createRequestContext(request) {
4
- const url = new URL(request.url);
5
- const pathSegments = url.pathname.split("/").filter(Boolean);
6
- return {
7
- request,
8
- origin: request.headers.get("origin"),
9
- host: request.headers.get("host"),
10
- referer: request.headers.get("referer"),
11
- userAgent: request.headers.get("user-agent") || "",
12
- method: request.method,
13
- pathSegments
14
- };
15
- }
16
3
  function createValidators(context) {
17
- const { request, origin, host, referer, userAgent, method, pathSegments } = context;
4
+ const { origin, host, referrer, userAgent, method, pathSegments } = context;
5
+ const request = context.request;
18
6
  async function validateCors(corsOptions) {
19
7
  if (corsOptions.skipSameOrigin) {
20
8
  if (!origin || host && origin.includes(host)) {
@@ -69,13 +57,13 @@ function createValidators(context) {
69
57
  }
70
58
  function validateCsrf(securityOptions) {
71
59
  if (securityOptions.requireCSRF && origin && host && !origin.includes(host)) {
72
- const hasCSRFHeader = request.headers.get("x-requested-with") === "XMLHttpRequest";
73
- const hasValidReferer = referer && host && referer.includes(host);
60
+ const hasCSRFHeader = context.request.headers.get("x-requested-with") === "XMLHttpRequest";
61
+ const hasValidReferer = referrer && host && referrer.includes(host);
74
62
  if (!hasCSRFHeader && !hasValidReferer) {
75
- const isAllowedReferer = securityOptions.allowedReferers?.some(
76
- (allowedRef) => referer?.includes(allowedRef)
63
+ const isAllowedReferrer = securityOptions.allowedReferers?.some(
64
+ (allowedRef) => referrer?.includes(allowedRef)
77
65
  );
78
- if (!isAllowedReferer) {
66
+ if (!isAllowedReferrer) {
79
67
  return createApiErrorResponse("CSRF_PROTECTION", "Access denied", 403);
80
68
  }
81
69
  }
@@ -85,7 +73,7 @@ function createValidators(context) {
85
73
  function validateRequiredHeaders(securityOptions) {
86
74
  if (securityOptions.requiredHeaders) {
87
75
  for (const [headerName, expectedValue] of Object.entries(securityOptions.requiredHeaders)) {
88
- const actualValue = request.headers.get(headerName);
76
+ const actualValue = context.request.headers.get(headerName);
89
77
  if (actualValue !== expectedValue) {
90
78
  return createApiErrorResponse(
91
79
  "INVALID_HEADERS",
@@ -100,7 +88,7 @@ function createValidators(context) {
100
88
  function validateUserAgent(securityOptions) {
101
89
  if (securityOptions.userAgent?.block?.length) {
102
90
  const isBlocked = securityOptions.userAgent.block.some(
103
- (blocked) => userAgent.toLowerCase().includes(blocked.toLowerCase())
91
+ (blocked) => context.request.headers.get("user-agent")?.toLowerCase().includes(blocked.toLowerCase())
104
92
  );
105
93
  if (isBlocked) {
106
94
  return createApiErrorResponse("USER_AGENT_BLOCKED", "Access denied", 403);
@@ -108,7 +96,7 @@ function createValidators(context) {
108
96
  }
109
97
  if (securityOptions.userAgent?.allow?.length) {
110
98
  const isAllowed = securityOptions.userAgent.allow.some(
111
- (allowed) => userAgent.toLowerCase().includes(allowed.toLowerCase())
99
+ (allowed) => request.headers.get("user-agent")?.toLowerCase().includes(allowed.toLowerCase())
112
100
  );
113
101
  if (!isAllowed) {
114
102
  return createApiErrorResponse("USER_AGENT_NOT_ALLOWED", "Access denied", 403);
@@ -265,7 +253,6 @@ function createValidators(context) {
265
253
  };
266
254
  }
267
255
  export {
268
- createRequestContext,
269
256
  createValidators
270
257
  };
271
258
  //# sourceMappingURL=fnValidators.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/app-router/admin/fnValidators.ts"],"sourcesContent":["import { cookies } from 'next/headers';\n\nimport { createApiErrorResponse } from './responses';\nimport type {\n AuthEndpoint,\n ComprehensiveValidationResult,\n CorsOptions,\n EndpointConfig,\n SecurityOptions,\n SessionSubEndpoint,\n ValidationConfig,\n} from './types';\n//import type { RequestProcessorContext } from './claude-authenticateRequestProcessor';\n\nexport interface RequestContext {\n request: Request;\n origin: string | null;\n host: string | null;\n referer: string | null;\n userAgent: string;\n method: string;\n pathSegments: string[];\n}\n\nexport function createRequestContext(request: Request): RequestContext {\n const url = new URL(request.url);\n const pathSegments = url.pathname.split('/').filter(Boolean);\n\n return {\n request,\n origin: request.headers.get('origin'),\n host: request.headers.get('host'),\n referer: request.headers.get('referer'),\n userAgent: request.headers.get('user-agent') || '',\n method: request.method,\n pathSegments,\n };\n}\n\n/**\n * Main validators factory function\n * Returns an object containing all validator functions and utilities\n */\nexport function createValidators(context: RequestContext) {\n const { request, origin, host, referer, userAgent, method, pathSegments } = context;\n\n async function validateCors(corsOptions: CorsOptions): Promise<Response | null> {\n if (corsOptions.skipSameOrigin) {\n if (!origin || (host && origin.includes(host))) {\n return null;\n }\n }\n\n if (corsOptions.allowedOrigins !== '*') {\n const isAllowed = corsOptions.allowedOrigins.some(allowedOrigin => {\n if (allowedOrigin.startsWith('*')) {\n const domain = allowedOrigin.slice(1);\n return origin?.endsWith(domain);\n }\n return origin === allowedOrigin;\n });\n\n if (!isAllowed) {\n return createApiErrorResponse('CORS_ORIGIN_NOT_ALLOWED', 'Origin not allowed', 403);\n }\n }\n\n return null;\n }\n\n function createCorsOptionsResponse(corsOptions: CorsOptions): Response {\n const response = new Response(null, { status: 204 });\n\n if (corsOptions.allowedOrigins === '*') {\n response.headers.set('Access-Control-Allow-Origin', '*');\n } else {\n response.headers.set('Access-Control-Allow-Origin', corsOptions.allowedOrigins.join(','));\n }\n\n response.headers.set(\n 'Access-Control-Allow-Methods',\n corsOptions.allowedMethods?.join(',') || 'GET,POST',\n );\n response.headers.set(\n 'Access-Control-Allow-Headers',\n corsOptions.allowedHeaders?.join(',') || 'Content-Type,Authorization',\n );\n\n if (corsOptions.allowCredentials) {\n response.headers.set('Access-Control-Allow-Credentials', 'true');\n }\n\n if (corsOptions.maxAge) {\n response.headers.set('Access-Control-Max-Age', corsOptions.maxAge.toString());\n }\n\n return response;\n }\n\n async function validateSecurity(securityOptions: SecurityOptions): Promise<Response | null> {\n const csrfResult = validateCsrf(securityOptions);\n if (csrfResult) return csrfResult;\n\n const headersResult = validateRequiredHeaders(securityOptions);\n if (headersResult) return headersResult;\n\n const userAgentResult = validateUserAgent(securityOptions);\n if (userAgentResult) return userAgentResult;\n\n return null;\n }\n\n function validateCsrf(securityOptions: SecurityOptions): Response | null {\n if (securityOptions.requireCSRF && origin && host && !origin.includes(host)) {\n const hasCSRFHeader = request.headers.get('x-requested-with') === 'XMLHttpRequest';\n const hasValidReferer = referer && host && referer.includes(host);\n\n if (!hasCSRFHeader && !hasValidReferer) {\n const isAllowedReferer = securityOptions.allowedReferers?.some((allowedRef: string) =>\n referer?.includes(allowedRef),\n );\n\n if (!isAllowedReferer) {\n return createApiErrorResponse('CSRF_PROTECTION', 'Access denied', 403);\n }\n }\n }\n return null;\n }\n\n function validateRequiredHeaders(securityOptions: SecurityOptions): Response | null {\n if (securityOptions.requiredHeaders) {\n for (const [headerName, expectedValue] of Object.entries(securityOptions.requiredHeaders)) {\n const actualValue = request.headers.get(headerName);\n if (actualValue !== expectedValue) {\n return createApiErrorResponse(\n 'INVALID_HEADERS',\n 'Required header missing or invalid',\n 400,\n );\n }\n }\n }\n return null;\n }\n\n function validateUserAgent(securityOptions: SecurityOptions): Response | null {\n if (securityOptions.userAgent?.block?.length) {\n const isBlocked = securityOptions.userAgent.block.some((blocked: string) =>\n userAgent.toLowerCase().includes(blocked.toLowerCase()),\n );\n\n if (isBlocked) {\n return createApiErrorResponse('USER_AGENT_BLOCKED', 'Access denied', 403);\n }\n }\n\n if (securityOptions.userAgent?.allow?.length) {\n const isAllowed = securityOptions.userAgent.allow.some((allowed: string) =>\n userAgent.toLowerCase().includes(allowed.toLowerCase()),\n );\n\n if (!isAllowed) {\n return createApiErrorResponse('USER_AGENT_NOT_ALLOWED', 'Access denied', 403);\n }\n }\n\n return null;\n }\n\n function validateCsrfToken(\n csrfToken: string,\n csrfCookieValue: string | undefined,\n ): Response | null {\n if (!csrfToken) {\n return createApiErrorResponse('INVALID_CSRF_TOKEN', 'CSRF token is required', 400);\n }\n\n if (!csrfCookieValue) {\n return createApiErrorResponse('CSRF_COOKIE_MISSING', 'CSRF token cookie not found', 403);\n }\n\n if (csrfToken !== csrfCookieValue) {\n return createApiErrorResponse('CSRF_TOKEN_MISMATCH', 'CSRF token mismatch', 403);\n }\n\n return null;\n }\n\n function validatePathStructure(): Response | null {\n if (pathSegments.length < 3) {\n return createApiErrorResponse(\n 'INVALID_ROUTE',\n 'Invalid route structure. Expected: /api/auth/{endpoint}',\n 404,\n );\n }\n return null;\n }\n\n function validateEndpoint(\n _endpoint: AuthEndpoint,\n endpointConfig: EndpointConfig,\n ): Response | null {\n if (!endpointConfig || !endpointConfig.enabled) {\n return createApiErrorResponse('ENDPOINT_NOT_FOUND', 'Endpoint not found', 404);\n }\n\n if (method !== 'OPTIONS' && !endpointConfig.methods.includes(method as any)) {\n return createApiErrorResponse('METHOD_NOT_ALLOWED', 'Method not allowed', 405);\n }\n\n return null;\n }\n\n function validateSubEndpoint(\n subEndpoint: SessionSubEndpoint | undefined,\n subEndpointConfig: any,\n ): Response | null {\n if (!subEndpoint) {\n return createApiErrorResponse('SUB_ENDPOINT_REQUIRED', 'Session sub-endpoint required', 400);\n }\n\n if (!subEndpointConfig || !subEndpointConfig.enabled) {\n return createApiErrorResponse('ENDPOINT_NOT_FOUND', 'Endpoint not found', 404);\n }\n\n if (!subEndpointConfig.methods?.includes(method as any)) {\n return createApiErrorResponse('METHOD_NOT_ALLOWED', 'Method not allowed', 405);\n }\n\n return null;\n }\n\n async function validateSessionRequest(): Promise<{\n body: any;\n idToken?: string;\n csrfToken?: string;\n error?: Response;\n }> {\n try {\n const body = await request.json();\n return { body, idToken: body.idToken, csrfToken: body.csrfToken };\n } catch (error) {\n return {\n body: null,\n error: createApiErrorResponse('INVALID_REQUEST_FORMAT', 'Invalid request format', 400),\n };\n }\n }\n\n function validateIdToken(idToken: string | undefined): Response | null {\n if (!idToken) {\n return createApiErrorResponse(\n 'INVALID_TOKEN',\n 'ID token is required for creating session',\n 400,\n );\n }\n return null;\n }\n\n /**\n * Main validation orchestrator function\n * Runs all configured validations in the correct order\n */\n async function validateRequest(config: ValidationConfig): Promise<ComprehensiveValidationResult> {\n if (method === 'OPTIONS' && config.cors) {\n return {\n isValid: true,\n corsResponse: createCorsOptionsResponse(config.cors),\n };\n }\n const pathError = validatePathStructure();\n if (pathError) {\n return { isValid: false, error: pathError };\n }\n\n if (config.cors) {\n const corsError = await validateCors(config.cors);\n if (corsError) {\n return { isValid: false, error: corsError };\n }\n }\n\n if (config.security) {\n const securityError = await validateSecurity(config.security);\n if (securityError) {\n return { isValid: false, error: securityError };\n }\n }\n\n if (config.endpoint) {\n const endpointError = validateEndpoint(config.endpoint.name, config.endpoint.config);\n if (endpointError) {\n return { isValid: false, error: endpointError };\n }\n }\n\n if (config.subEndpoint) {\n const subEndpointError = validateSubEndpoint(\n config.subEndpoint.name,\n config.subEndpoint.config,\n );\n if (subEndpointError) {\n return { isValid: false, error: subEndpointError };\n }\n }\n\n let sessionData;\n if (method === 'POST' && (config.requireIdToken || config.requireCsrfToken)) {\n const sessionResult = await validateSessionRequest();\n if (sessionResult.error) {\n return { isValid: false, error: sessionResult.error };\n }\n\n sessionData = sessionResult;\n\n if (config.requireIdToken) {\n const idTokenError = validateIdToken(sessionData.idToken);\n if (idTokenError) {\n return { isValid: false, error: idTokenError };\n }\n }\n\n if (config.requireCsrfToken && sessionData.csrfToken) {\n const cookieStore = await cookies();\n const csrfCookieValue = cookieStore.get('csrfToken')?.value;\n const csrfError = validateCsrfToken(sessionData.csrfToken, csrfCookieValue);\n if (csrfError) {\n return { isValid: false, error: csrfError };\n }\n }\n }\n\n return {\n isValid: true,\n sessionData,\n };\n }\n\n /**\n * Convenience function for quick validation setup\n */\n function createValidationConfig(overrides: Partial<ValidationConfig> = {}): ValidationConfig {\n return {\n ...overrides,\n };\n }\n\n return {\n createValidationConfig,\n\n validateRequest,\n\n validateCors,\n validateSecurity,\n validatePathStructure,\n validateEndpoint,\n validateSubEndpoint,\n validateSessionRequest,\n validateIdToken,\n validateCsrfToken,\n\n createCorsOptionsResponse,\n };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../src/app-router/admin/fnValidators.ts"],"sourcesContent":["import { cookies } from 'next/headers';\n\nimport type { RequestProcessorContext } from './c-authenticateRequestProcessor';\nimport { createApiErrorResponse } from './responses';\nimport type {\n AuthEndpoint,\n ComprehensiveValidationResult,\n CorsOptions,\n EndpointConfig,\n SecurityOptions,\n SessionSubEndpoint,\n ValidationConfig,\n} from './types';\n\n/**\n * Main validators factory function\n * Returns an object containing all validator functions and utilities\n */\nexport function createValidators(context: RequestProcessorContext) {\n const { origin, host, referrer, userAgent, method, pathSegments } = context;\n const request = context.request;\n\n async function validateCors(corsOptions: CorsOptions): Promise<Response | null> {\n if (corsOptions.skipSameOrigin) {\n if (!origin || (host && origin.includes(host))) {\n return null;\n }\n }\n\n if (corsOptions.allowedOrigins !== '*') {\n const isAllowed = corsOptions.allowedOrigins.some(allowedOrigin => {\n if (allowedOrigin.startsWith('*')) {\n const domain = allowedOrigin.slice(1);\n return origin?.endsWith(domain);\n }\n return origin === allowedOrigin;\n });\n\n if (!isAllowed) {\n return createApiErrorResponse('CORS_ORIGIN_NOT_ALLOWED', 'Origin not allowed', 403);\n }\n }\n\n return null;\n }\n\n function createCorsOptionsResponse(corsOptions: CorsOptions): Response {\n const response = new Response(null, { status: 204 });\n\n if (corsOptions.allowedOrigins === '*') {\n response.headers.set('Access-Control-Allow-Origin', '*');\n } else {\n response.headers.set('Access-Control-Allow-Origin', corsOptions.allowedOrigins.join(','));\n }\n\n response.headers.set(\n 'Access-Control-Allow-Methods',\n corsOptions.allowedMethods?.join(',') || 'GET,POST',\n );\n response.headers.set(\n 'Access-Control-Allow-Headers',\n corsOptions.allowedHeaders?.join(',') || 'Content-Type,Authorization',\n );\n\n if (corsOptions.allowCredentials) {\n response.headers.set('Access-Control-Allow-Credentials', 'true');\n }\n\n if (corsOptions.maxAge) {\n response.headers.set('Access-Control-Max-Age', corsOptions.maxAge.toString());\n }\n\n return response;\n }\n\n async function validateSecurity(securityOptions: SecurityOptions): Promise<Response | null> {\n const csrfResult = validateCsrf(securityOptions);\n if (csrfResult) return csrfResult;\n\n const headersResult = validateRequiredHeaders(securityOptions);\n if (headersResult) return headersResult;\n\n const userAgentResult = validateUserAgent(securityOptions);\n if (userAgentResult) return userAgentResult;\n\n return null;\n }\n\n function validateCsrf(securityOptions: SecurityOptions): Response | null {\n if (securityOptions.requireCSRF && origin && host && !origin.includes(host)) {\n const hasCSRFHeader = context.request.headers.get('x-requested-with') === 'XMLHttpRequest';\n const hasValidReferer = referrer && host && referrer.includes(host);\n\n if (!hasCSRFHeader && !hasValidReferer) {\n const isAllowedReferrer = securityOptions.allowedReferers?.some((allowedRef: string) =>\n referrer?.includes(allowedRef),\n );\n\n if (!isAllowedReferrer) {\n return createApiErrorResponse('CSRF_PROTECTION', 'Access denied', 403);\n }\n }\n }\n return null;\n }\n\n function validateRequiredHeaders(securityOptions: SecurityOptions): Response | null {\n if (securityOptions.requiredHeaders) {\n for (const [headerName, expectedValue] of Object.entries(securityOptions.requiredHeaders)) {\n const actualValue = context.request.headers.get(headerName);\n if (actualValue !== expectedValue) {\n return createApiErrorResponse(\n 'INVALID_HEADERS',\n 'Required header missing or invalid',\n 400,\n );\n }\n }\n }\n return null;\n }\n\n function validateUserAgent(securityOptions: SecurityOptions): Response | null {\n if (securityOptions.userAgent?.block?.length) {\n const isBlocked = securityOptions.userAgent.block.some((blocked: string) =>\n context.request.headers.get('user-agent')?.toLowerCase().includes(blocked.toLowerCase()),\n );\n\n if (isBlocked) {\n return createApiErrorResponse('USER_AGENT_BLOCKED', 'Access denied', 403);\n }\n }\n\n if (securityOptions.userAgent?.allow?.length) {\n const isAllowed = securityOptions.userAgent.allow.some((allowed: string) =>\n request.headers.get('user-agent')?.toLowerCase().includes(allowed.toLowerCase()),\n );\n\n if (!isAllowed) {\n return createApiErrorResponse('USER_AGENT_NOT_ALLOWED', 'Access denied', 403);\n }\n }\n\n return null;\n }\n\n function validateCsrfToken(\n csrfToken: string,\n csrfCookieValue: string | undefined,\n ): Response | null {\n if (!csrfToken) {\n return createApiErrorResponse('INVALID_CSRF_TOKEN', 'CSRF token is required', 400);\n }\n\n if (!csrfCookieValue) {\n return createApiErrorResponse('CSRF_COOKIE_MISSING', 'CSRF token cookie not found', 403);\n }\n\n if (csrfToken !== csrfCookieValue) {\n return createApiErrorResponse('CSRF_TOKEN_MISMATCH', 'CSRF token mismatch', 403);\n }\n\n return null;\n }\n\n function validatePathStructure(): Response | null {\n if (pathSegments.length < 3) {\n return createApiErrorResponse(\n 'INVALID_ROUTE',\n 'Invalid route structure. Expected: /api/auth/{endpoint}',\n 404,\n );\n }\n return null;\n }\n\n function validateEndpoint(\n _endpoint: AuthEndpoint,\n endpointConfig: EndpointConfig,\n ): Response | null {\n if (!endpointConfig || !endpointConfig.enabled) {\n return createApiErrorResponse('ENDPOINT_NOT_FOUND', 'Endpoint not found', 404);\n }\n\n if (method !== 'OPTIONS' && !endpointConfig.methods.includes(method as any)) {\n return createApiErrorResponse('METHOD_NOT_ALLOWED', 'Method not allowed', 405);\n }\n\n return null;\n }\n\n function validateSubEndpoint(\n subEndpoint: SessionSubEndpoint | undefined,\n subEndpointConfig: any,\n ): Response | null {\n if (!subEndpoint) {\n return createApiErrorResponse('SUB_ENDPOINT_REQUIRED', 'Session sub-endpoint required', 400);\n }\n\n if (!subEndpointConfig || !subEndpointConfig.enabled) {\n return createApiErrorResponse('ENDPOINT_NOT_FOUND', 'Endpoint not found', 404);\n }\n\n if (!subEndpointConfig.methods?.includes(method as any)) {\n return createApiErrorResponse('METHOD_NOT_ALLOWED', 'Method not allowed', 405);\n }\n\n return null;\n }\n\n async function validateSessionRequest(): Promise<{\n body: any;\n idToken?: string;\n csrfToken?: string;\n error?: Response;\n }> {\n try {\n const body = await request.json();\n return { body, idToken: body.idToken, csrfToken: body.csrfToken };\n } catch (error) {\n return {\n body: null,\n error: createApiErrorResponse('INVALID_REQUEST_FORMAT', 'Invalid request format', 400),\n };\n }\n }\n\n function validateIdToken(idToken: string | undefined): Response | null {\n if (!idToken) {\n return createApiErrorResponse(\n 'INVALID_TOKEN',\n 'ID token is required for creating session',\n 400,\n );\n }\n return null;\n }\n\n /**\n * Main validation orchestrator function\n * Runs all configured validations in the correct order\n */\n async function validateRequest(config: ValidationConfig): Promise<ComprehensiveValidationResult> {\n if (method === 'OPTIONS' && config.cors) {\n return {\n isValid: true,\n corsResponse: createCorsOptionsResponse(config.cors),\n };\n }\n const pathError = validatePathStructure();\n if (pathError) {\n return { isValid: false, error: pathError };\n }\n\n if (config.cors) {\n const corsError = await validateCors(config.cors);\n if (corsError) {\n return { isValid: false, error: corsError };\n }\n }\n\n if (config.security) {\n const securityError = await validateSecurity(config.security);\n if (securityError) {\n return { isValid: false, error: securityError };\n }\n }\n\n if (config.endpoint) {\n const endpointError = validateEndpoint(config.endpoint.name, config.endpoint.config);\n if (endpointError) {\n return { isValid: false, error: endpointError };\n }\n }\n\n if (config.subEndpoint) {\n const subEndpointError = validateSubEndpoint(\n config.subEndpoint.name,\n config.subEndpoint.config,\n );\n if (subEndpointError) {\n return { isValid: false, error: subEndpointError };\n }\n }\n\n let sessionData;\n if (method === 'POST' && (config.requireIdToken || config.requireCsrfToken)) {\n const sessionResult = await validateSessionRequest();\n if (sessionResult.error) {\n return { isValid: false, error: sessionResult.error };\n }\n\n sessionData = sessionResult;\n\n if (config.requireIdToken) {\n const idTokenError = validateIdToken(sessionData.idToken);\n if (idTokenError) {\n return { isValid: false, error: idTokenError };\n }\n }\n\n if (config.requireCsrfToken && sessionData.csrfToken) {\n const cookieStore = await cookies();\n const csrfCookieValue = cookieStore.get('csrfToken')?.value;\n const csrfError = validateCsrfToken(sessionData.csrfToken, csrfCookieValue);\n if (csrfError) {\n return { isValid: false, error: csrfError };\n }\n }\n }\n\n return {\n isValid: true,\n sessionData,\n };\n }\n\n /**\n * Convenience function for quick validation setup\n */\n function createValidationConfig(overrides: Partial<ValidationConfig> = {}): ValidationConfig {\n return {\n ...overrides,\n };\n }\n\n return {\n createValidationConfig,\n\n validateRequest,\n\n validateCors,\n validateSecurity,\n validatePathStructure,\n validateEndpoint,\n validateSubEndpoint,\n validateSessionRequest,\n validateIdToken,\n validateCsrfToken,\n\n createCorsOptionsResponse,\n };\n}\n"],"mappings":"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","names":[]}
@@ -8,11 +8,8 @@ import {
8
8
  setNextServerToken
9
9
  } from "./actions";
10
10
  import { EndpointRouter } from "./endpointRouter";
11
- import { RequestContextBuilder, ValidationPipeline } from "./handlerUtils";
12
11
  export {
13
12
  EndpointRouter,
14
- RequestContextBuilder,
15
- ValidationPipeline,
16
13
  clearNextSessionCookie,
17
14
  clearSessionCookieServer,
18
15
  createNextSessionCookie,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/app-router/admin/index.ts"],"sourcesContent":["export { createTernSecureNextJsHandler } from './ternsecureNextjsHandler'\n\nexport {\n clearSessionCookieServer,\n clearNextSessionCookie,\n createSessionCookieServer,\n createNextSessionCookie,\n setNextServerSession,\n setNextServerToken\n} from './actions'\n\nexport { EndpointRouter } from './endpointRouter'\nexport { RequestContextBuilder, ValidationPipeline } from './handlerUtils'\nexport type { HandlerContext } from './handlerUtils'\n\nexport type { TernSecureHandlerOptions, TernSecureInternalHandlerConfig } from './types'"],"mappings":"AAAA,SAAS,qCAAqC;AAE9C;AAAA,EACI;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACG;AAEP,SAAS,sBAAsB;AAC/B,SAAS,uBAAuB,0BAA0B;","names":[]}
1
+ {"version":3,"sources":["../../../../src/app-router/admin/index.ts"],"sourcesContent":["export { createTernSecureNextJsHandler } from './ternsecureNextjsHandler'\n\nexport {\n clearSessionCookieServer,\n clearNextSessionCookie,\n createSessionCookieServer,\n createNextSessionCookie,\n setNextServerSession,\n setNextServerToken\n} from './actions'\n\nexport { EndpointRouter } from './endpointRouter'\n\nexport type { TernSecureHandlerOptions } from './types'"],"mappings":"AAAA,SAAS,qCAAqC;AAE9C;AAAA,EACI;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACG;AAEP,SAAS,sBAAsB;","names":[]}
@@ -2,132 +2,104 @@ import { clearSessionCookie, createSessionCookie } from "@tern-secure/backend/ad
2
2
  import { ternDecodeJwtUnguarded } from "@tern-secure/backend/jwt";
3
3
  import { cookies } from "next/headers";
4
4
  import { NextCookieStore } from "../../utils/NextCookieAdapter";
5
+ import { createValidators } from "./fnValidators";
5
6
  import { createApiErrorResponse, HttpResponseHelper, SessionResponseHelper } from "./responses";
6
- import { CsrfValidator, RequestValidator } from "./validators";
7
- class SessionGetHandler {
8
- static async handle(subEndpoint, _config) {
9
- switch (subEndpoint) {
10
- case "verify":
11
- return this.handleVerify();
12
- default:
13
- return HttpResponseHelper.createNotFoundResponse();
14
- }
7
+ async function sessionEndpointHandler(context, options) {
8
+ const { subEndpoint, method } = context;
9
+ const validators = createValidators(context);
10
+ const {
11
+ validateSubEndpoint,
12
+ validateSecurity,
13
+ validateSessionRequest,
14
+ validateCsrfToken,
15
+ validateIdToken
16
+ } = validators;
17
+ if (!subEndpoint) {
18
+ return createApiErrorResponse("SUB_ENDPOINT_REQUIRED", "Session sub-endpoint required", 400);
15
19
  }
16
- static async handleVerify() {
17
- try {
18
- const cookieStore = await cookies();
19
- const sessionCookie = cookieStore.get("_session_cookie")?.value;
20
- if (!sessionCookie) {
21
- return SessionResponseHelper.createUnauthorizedResponse();
22
- }
23
- const { data: decodedSession, errors } = ternDecodeJwtUnguarded(sessionCookie);
24
- if (errors) {
20
+ const sessionsConfig = options.endpoints?.sessions;
21
+ const subEndpointConfig = sessionsConfig?.subEndpoints?.[subEndpoint];
22
+ validateSubEndpoint(subEndpoint, subEndpointConfig);
23
+ if (subEndpointConfig?.security) {
24
+ await validateSecurity(subEndpointConfig.security);
25
+ }
26
+ const SessionGetHandler = async (subEndpoint2) => {
27
+ const handleSessionVerify = async () => {
28
+ try {
29
+ const cookieStore = await cookies();
30
+ const sessionCookie = cookieStore.get("_session_cookie")?.value;
31
+ if (!sessionCookie) {
32
+ return SessionResponseHelper.createUnauthorizedResponse();
33
+ }
34
+ const { data: decodedSession, errors } = ternDecodeJwtUnguarded(sessionCookie);
35
+ if (errors) {
36
+ return SessionResponseHelper.createUnauthorizedResponse();
37
+ }
38
+ return SessionResponseHelper.createVerificationResponse(decodedSession);
39
+ } catch (error) {
25
40
  return SessionResponseHelper.createUnauthorizedResponse();
26
41
  }
27
- return SessionResponseHelper.createVerificationResponse(decodedSession);
28
- } catch (error) {
29
- return SessionResponseHelper.createUnauthorizedResponse();
42
+ };
43
+ switch (subEndpoint2) {
44
+ case "verify":
45
+ return handleSessionVerify();
46
+ default:
47
+ return HttpResponseHelper.createNotFoundResponse();
30
48
  }
31
- }
32
- }
33
- class SessionPostHandler {
34
- static async handle(request, subEndpoint, _config) {
49
+ };
50
+ const SessionPostHandler = async (subEndpoint2) => {
35
51
  const cookieStore = new NextCookieStore();
36
- const { idToken, csrfToken, error } = await RequestValidator.validateSessionRequest(request);
52
+ const { idToken, csrfToken, error } = await validateSessionRequest();
37
53
  if (error) return error;
38
54
  const csrfCookieValue = await cookieStore.get("_session_terncf");
39
- const csrfValidationError = CsrfValidator.validate(csrfToken || "", csrfCookieValue.value);
40
- if (csrfValidationError) return csrfValidationError;
41
- const options = {
42
- tenantId: _config.tenantId
55
+ validateCsrfToken(csrfToken || "", csrfCookieValue.value);
56
+ const handleCreateSession = async (cookieStore2, idToken2) => {
57
+ try {
58
+ const res = await createSessionCookie(idToken2, cookieStore2, options);
59
+ return SessionResponseHelper.createSessionCreationResponse(res);
60
+ } catch (error2) {
61
+ return createApiErrorResponse("SESSION_CREATION_FAILED", "Session creation failed", 500);
62
+ }
43
63
  };
44
- switch (subEndpoint) {
45
- case "createsession":
46
- return this.handleCreateSession(options, idToken, cookieStore);
64
+ const handleRefreshSession = async (cookieStore2, idToken2) => {
65
+ try {
66
+ const decodedSession = ternDecodeJwtUnguarded(idToken2);
67
+ if (decodedSession.errors) {
68
+ return createApiErrorResponse("INVALID_SESSION", "Invalid session for refresh", 401);
69
+ }
70
+ const refreshRes = await createSessionCookie(idToken2, cookieStore2, options);
71
+ return SessionResponseHelper.createRefreshResponse(refreshRes);
72
+ } catch (error2) {
73
+ return createApiErrorResponse("REFRESH_FAILED", "Session refresh failed", 500);
74
+ }
75
+ };
76
+ const handleRevokeSession = async (cookieStore2) => {
77
+ const res = await clearSessionCookie(cookieStore2);
78
+ return SessionResponseHelper.createRevokeResponse(res);
79
+ };
80
+ switch (subEndpoint2) {
81
+ case "createsession": {
82
+ validateIdToken(idToken);
83
+ return handleCreateSession(cookieStore, idToken);
84
+ }
47
85
  case "refresh":
48
- return this.handleRefreshSession(cookieStore);
86
+ return handleRefreshSession(cookieStore, idToken);
49
87
  case "revoke":
50
- return this.handleRevokeSession(cookieStore);
88
+ return handleRevokeSession(cookieStore);
51
89
  default:
52
90
  return HttpResponseHelper.createSubEndpointNotSupportedResponse();
53
91
  }
54
- }
55
- static async handleCreateSession(options, idToken, cookieStore) {
56
- const validationError = RequestValidator.validateIdToken(idToken);
57
- if (validationError) return validationError;
58
- if (!idToken) {
59
- return createApiErrorResponse("ID_TOKEN_REQUIRED", "ID token is required", 400);
60
- }
61
- try {
62
- const res = await createSessionCookie(idToken, cookieStore, options);
63
- return SessionResponseHelper.createSessionCreationResponse(res);
64
- } catch (error) {
65
- return createApiErrorResponse("SESSION_CREATION_FAILED", "Session creation failed", 500);
66
- }
67
- }
68
- static async handleRefreshSession(cookieStore) {
69
- const currentSessionCookie = await cookieStore.get("__session");
70
- if (!currentSessionCookie) {
71
- return createApiErrorResponse("NO_SESSION", "No session to refresh", 401);
72
- }
73
- try {
74
- const decodedSession = ternDecodeJwtUnguarded(currentSessionCookie.value || "");
75
- if (decodedSession.errors) {
76
- return createApiErrorResponse("INVALID_SESSION", "Invalid session for refresh", 401);
77
- }
78
- const refreshRes = await createSessionCookie(
79
- decodedSession.data?.payload?.sub || "",
80
- cookieStore
81
- );
82
- return SessionResponseHelper.createRefreshResponse(refreshRes);
83
- } catch (error) {
84
- return createApiErrorResponse("REFRESH_FAILED", "Session refresh failed", 500);
85
- }
86
- }
87
- static async handleRevokeSession(cookieStore) {
88
- const res = await clearSessionCookie(cookieStore);
89
- return SessionResponseHelper.createRevokeResponse(res);
90
- }
91
- }
92
- class SessionEndpointHandler {
93
- static async handle(request, method, subEndpoint, config) {
94
- const sessionsConfig = config.endpoints.sessions;
95
- if (!subEndpoint) {
96
- return createApiErrorResponse("SUB_ENDPOINT_REQUIRED", "Session sub-endpoint required", 400);
97
- }
98
- const subEndpointConfig = sessionsConfig?.subEndpoints?.[subEndpoint];
99
- const subEndpointValidation = this.validateSubEndpoint(subEndpoint, subEndpointConfig, method);
100
- if (subEndpointValidation) return subEndpointValidation;
101
- if (subEndpointConfig?.security) {
102
- const { SecurityValidator } = await import("./validators.js");
103
- const securityResult = await SecurityValidator.validate(request, subEndpointConfig.security);
104
- if (securityResult) return securityResult;
105
- }
106
- switch (method) {
107
- case "GET":
108
- return SessionGetHandler.handle(subEndpoint, config);
109
- case "POST":
110
- return SessionPostHandler.handle(request, subEndpoint, config);
111
- default:
112
- return HttpResponseHelper.createMethodNotAllowedResponse();
113
- }
114
- }
115
- static validateSubEndpoint(subEndpoint, subEndpointConfig, method) {
116
- if (!subEndpoint) {
117
- return createApiErrorResponse("SUB_ENDPOINT_REQUIRED", "Session sub-endpoint required", 400);
118
- }
119
- if (!subEndpointConfig || !subEndpointConfig.enabled) {
120
- return createApiErrorResponse("ENDPOINT_NOT_FOUND", "Endpoint not found", 404);
121
- }
122
- if (!subEndpointConfig.methods?.includes(method)) {
123
- return createApiErrorResponse("METHOD_NOT_ALLOWED", "Method not allowed", 405);
124
- }
125
- return null;
92
+ };
93
+ switch (method) {
94
+ case "GET":
95
+ return SessionGetHandler(subEndpoint);
96
+ case "POST":
97
+ return SessionPostHandler(subEndpoint);
98
+ default:
99
+ return HttpResponseHelper.createMethodNotAllowedResponse();
126
100
  }
127
101
  }
128
102
  export {
129
- SessionEndpointHandler,
130
- SessionGetHandler,
131
- SessionPostHandler
103
+ sessionEndpointHandler
132
104
  };
133
105
  //# sourceMappingURL=sessionHandlers.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/app-router/admin/sessionHandlers.ts"],"sourcesContent":["import type { RequestOptions } from '@tern-secure/backend';\nimport { clearSessionCookie, createSessionCookie } from '@tern-secure/backend/admin';\nimport { ternDecodeJwtUnguarded} from '@tern-secure/backend/jwt';\nimport { cookies } from 'next/headers';\n\nimport { NextCookieStore } from '../../utils/NextCookieAdapter';\nimport { createApiErrorResponse, HttpResponseHelper, SessionResponseHelper } from './responses';\nimport type {\n SessionSubEndpoint,\n TernSecureHandlerOptions,\n TernSecureInternalHandlerConfig,\n} from './types';\nimport { CsrfValidator, RequestValidator } from './validators';\n\n/**\n * Session GET request handlers\n */\nexport class SessionGetHandler {\n static async handle(\n subEndpoint: SessionSubEndpoint,\n _config: Required<TernSecureHandlerOptions>,\n ): Promise<Response> {\n switch (subEndpoint) {\n case 'verify':\n return this.handleVerify();\n default:\n return HttpResponseHelper.createNotFoundResponse();\n }\n }\n\n private static async handleVerify(): Promise<Response> {\n try {\n const cookieStore = await cookies();\n const sessionCookie = cookieStore.get('_session_cookie')?.value;\n if (!sessionCookie) {\n return SessionResponseHelper.createUnauthorizedResponse();\n }\n\n const { data: decodedSession, errors } = ternDecodeJwtUnguarded(sessionCookie);\n if (errors) {\n return SessionResponseHelper.createUnauthorizedResponse();\n }\n\n return SessionResponseHelper.createVerificationResponse(decodedSession);\n } catch (error) {\n return SessionResponseHelper.createUnauthorizedResponse();\n }\n }\n}\n\n/**\n * Session POST request handlers\n */\nexport class SessionPostHandler {\n static async handle(\n request: Request,\n subEndpoint: SessionSubEndpoint,\n _config: TernSecureInternalHandlerConfig,\n ): Promise<Response> {\n const cookieStore = new NextCookieStore();\n\n const { idToken, csrfToken, error } = await RequestValidator.validateSessionRequest(request);\n if (error) return error;\n\n const csrfCookieValue = await cookieStore.get('_session_terncf');\n const csrfValidationError = CsrfValidator.validate(csrfToken || '', csrfCookieValue.value);\n if (csrfValidationError) return csrfValidationError;\n\n const options = {\n tenantId: _config.tenantId,\n };\n\n switch (subEndpoint) {\n case 'createsession':\n return this.handleCreateSession(options, idToken, cookieStore);\n case 'refresh':\n return this.handleRefreshSession(cookieStore);\n case 'revoke':\n return this.handleRevokeSession(cookieStore);\n default:\n return HttpResponseHelper.createSubEndpointNotSupportedResponse();\n }\n }\n\n private static async handleCreateSession(\n options: RequestOptions,\n idToken: string | undefined,\n cookieStore: NextCookieStore,\n ): Promise<Response> {\n const validationError = RequestValidator.validateIdToken(idToken);\n if (validationError) return validationError;\n if (!idToken) {\n return createApiErrorResponse('ID_TOKEN_REQUIRED', 'ID token is required', 400);\n }\n\n try {\n const res = await createSessionCookie(idToken, cookieStore, options);\n return SessionResponseHelper.createSessionCreationResponse(res);\n } catch (error) {\n return createApiErrorResponse('SESSION_CREATION_FAILED', 'Session creation failed', 500);\n }\n }\n\n private static async handleRefreshSession(\n cookieStore: NextCookieStore,\n ): Promise<Response> {\n const currentSessionCookie = await cookieStore.get('__session');\n if (!currentSessionCookie) {\n return createApiErrorResponse('NO_SESSION', 'No session to refresh', 401);\n }\n\n try {\n const decodedSession = ternDecodeJwtUnguarded(currentSessionCookie.value || '');\n if (decodedSession.errors) {\n return createApiErrorResponse('INVALID_SESSION', 'Invalid session for refresh', 401);\n }\n\n const refreshRes = await createSessionCookie(\n decodedSession.data?.payload?.sub || '',\n cookieStore,\n );\n\n return SessionResponseHelper.createRefreshResponse(refreshRes);\n } catch (error) {\n return createApiErrorResponse('REFRESH_FAILED', 'Session refresh failed', 500);\n }\n }\n\n private static async handleRevokeSession(cookieStore: NextCookieStore): Promise<Response> {\n const res = await clearSessionCookie(cookieStore);\n return SessionResponseHelper.createRevokeResponse(res);\n }\n}\n\n/**\n * Main session endpoint orchestrator\n */\nexport class SessionEndpointHandler {\n static async handle(\n request: Request,\n method: string,\n subEndpoint: SessionSubEndpoint | undefined,\n config: Required<TernSecureHandlerOptions>,\n ): Promise<Response> {\n const sessionsConfig = config.endpoints.sessions;\n\n if (!subEndpoint) {\n return createApiErrorResponse('SUB_ENDPOINT_REQUIRED', 'Session sub-endpoint required', 400);\n }\n\n const subEndpointConfig = sessionsConfig?.subEndpoints?.[subEndpoint];\n\n const subEndpointValidation = this.validateSubEndpoint(subEndpoint, subEndpointConfig, method);\n if (subEndpointValidation) return subEndpointValidation;\n\n if (subEndpointConfig?.security) {\n const { SecurityValidator } = await import('./validators.js');\n const securityResult = await SecurityValidator.validate(request, subEndpointConfig.security);\n if (securityResult) return securityResult;\n }\n\n switch (method) {\n case 'GET':\n return SessionGetHandler.handle(subEndpoint, config);\n case 'POST':\n return SessionPostHandler.handle(request, subEndpoint, config);\n default:\n return HttpResponseHelper.createMethodNotAllowedResponse();\n }\n }\n\n private static validateSubEndpoint(\n subEndpoint: SessionSubEndpoint | undefined,\n subEndpointConfig: any,\n method: string,\n ): Response | null {\n if (!subEndpoint) {\n return createApiErrorResponse('SUB_ENDPOINT_REQUIRED', 'Session sub-endpoint required', 400);\n }\n\n if (!subEndpointConfig || !subEndpointConfig.enabled) {\n return createApiErrorResponse('ENDPOINT_NOT_FOUND', 'Endpoint not found', 404);\n }\n\n if (!subEndpointConfig.methods?.includes(method as any)) {\n return createApiErrorResponse('METHOD_NOT_ALLOWED', 'Method not allowed', 405);\n }\n\n return null;\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../src/app-router/admin/sessionHandlers.ts"],"sourcesContent":["import { clearSessionCookie, createSessionCookie } from '@tern-secure/backend/admin';\nimport { ternDecodeJwtUnguarded } from '@tern-secure/backend/jwt';\nimport { cookies } from 'next/headers';\n\nimport { NextCookieStore } from '../../utils/NextCookieAdapter';\nimport { type RequestProcessorContext } from './c-authenticateRequestProcessor';\nimport { createValidators } from './fnValidators';\nimport { createApiErrorResponse, HttpResponseHelper, SessionResponseHelper } from './responses';\nimport type { SessionSubEndpoint, TernSecureHandlerOptions } from './types';\n\nexport async function sessionEndpointHandler(\n context: RequestProcessorContext,\n options: TernSecureHandlerOptions,\n): Promise<Response> {\n const { subEndpoint, method } = context;\n \n const validators = createValidators(context);\n\n const {\n validateSubEndpoint,\n validateSecurity,\n validateSessionRequest,\n validateCsrfToken,\n validateIdToken,\n } = validators;\n\n if (!subEndpoint) {\n return createApiErrorResponse('SUB_ENDPOINT_REQUIRED', 'Session sub-endpoint required', 400);\n }\n\n const sessionsConfig = options.endpoints?.sessions;\n const subEndpointConfig = sessionsConfig?.subEndpoints?.[subEndpoint];\n\n validateSubEndpoint(subEndpoint, subEndpointConfig);\n\n if (subEndpointConfig?.security) {\n await validateSecurity(subEndpointConfig.security);\n }\n\n const SessionGetHandler = async (subEndpoint: SessionSubEndpoint): Promise<Response> => {\n const handleSessionVerify = async (): Promise<Response> => {\n try {\n const cookieStore = await cookies();\n const sessionCookie = cookieStore.get('_session_cookie')?.value;\n if (!sessionCookie) {\n return SessionResponseHelper.createUnauthorizedResponse();\n }\n\n const { data: decodedSession, errors } = ternDecodeJwtUnguarded(sessionCookie);\n if (errors) {\n return SessionResponseHelper.createUnauthorizedResponse();\n }\n\n return SessionResponseHelper.createVerificationResponse(decodedSession);\n } catch (error) {\n return SessionResponseHelper.createUnauthorizedResponse();\n }\n };\n\n switch (subEndpoint) {\n case 'verify':\n return handleSessionVerify();\n default:\n return HttpResponseHelper.createNotFoundResponse();\n }\n };\n\n const SessionPostHandler = async (subEndpoint: SessionSubEndpoint): Promise<Response> => {\n const cookieStore = new NextCookieStore();\n\n const { idToken, csrfToken, error } = await validateSessionRequest();\n if (error) return error;\n\n const csrfCookieValue = await cookieStore.get('_session_terncf');\n validateCsrfToken(csrfToken || '', csrfCookieValue.value);\n\n const handleCreateSession = async (\n cookieStore: NextCookieStore,\n idToken: string,\n ): Promise<Response> => {\n try {\n const res = await createSessionCookie(idToken, cookieStore, options);\n return SessionResponseHelper.createSessionCreationResponse(res);\n } catch (error) {\n return createApiErrorResponse('SESSION_CREATION_FAILED', 'Session creation failed', 500);\n }\n };\n\n const handleRefreshSession = async (\n cookieStore: NextCookieStore,\n idToken: string,\n ): Promise<Response> => {\n try {\n const decodedSession = ternDecodeJwtUnguarded(idToken);\n if (decodedSession.errors) {\n return createApiErrorResponse('INVALID_SESSION', 'Invalid session for refresh', 401);\n }\n\n const refreshRes = await createSessionCookie(idToken, cookieStore, options);\n return SessionResponseHelper.createRefreshResponse(refreshRes);\n } catch (error) {\n return createApiErrorResponse('REFRESH_FAILED', 'Session refresh failed', 500);\n }\n };\n\n const handleRevokeSession = async (cookieStore: NextCookieStore): Promise<Response> => {\n const res = await clearSessionCookie(cookieStore);\n return SessionResponseHelper.createRevokeResponse(res);\n };\n\n switch (subEndpoint) {\n case 'createsession': {\n validateIdToken(idToken);\n //eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return handleCreateSession(cookieStore, idToken!);\n }\n\n case 'refresh':\n //eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return handleRefreshSession(cookieStore, idToken!);\n\n case 'revoke':\n return handleRevokeSession(cookieStore);\n\n default:\n return HttpResponseHelper.createSubEndpointNotSupportedResponse();\n }\n };\n\n switch (method) {\n case 'GET':\n return SessionGetHandler(subEndpoint);\n\n case 'POST':\n return SessionPostHandler(subEndpoint);\n\n default:\n return HttpResponseHelper.createMethodNotAllowedResponse();\n }\n}\n"],"mappings":"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","names":["subEndpoint","cookieStore","idToken","error"]}
@@ -1,49 +1,36 @@
1
+ import { createTernSecureRequest } from "@tern-secure/backend";
2
+ import { createRequestProcessor } from "./c-authenticateRequestProcessor";
1
3
  import { TENANT_ID } from "./constants";
2
4
  import { EndpointRouter } from "./endpointRouter";
3
- import { createRequestContext } from "./fnValidators";
4
- import { RequestContextBuilder, ValidationPipeline } from "./handlerUtils";
5
+ import { createValidators } from "./fnValidators";
5
6
  import { createApiErrorResponse } from "./responses";
6
7
  import { DEFAULT_HANDLER_OPTIONS } from "./types";
7
8
  import { ConfigUtils } from "./utils";
8
- class HandlerConfigFactory {
9
- static create(options) {
10
- const baseConfig = ConfigUtils.mergeWithDefaults(
11
- DEFAULT_HANDLER_OPTIONS,
12
- options
13
- );
14
- return {
15
- ...baseConfig,
16
- tenantId: TENANT_ID
17
- };
18
- }
9
+ function createHandlerConfig(options) {
10
+ const baseConfig = ConfigUtils.mergeWithDefaults(
11
+ DEFAULT_HANDLER_OPTIONS,
12
+ options
13
+ );
14
+ return {
15
+ ...baseConfig,
16
+ tenantId: TENANT_ID
17
+ };
19
18
  }
20
- class TernSecureRequestHandler {
21
- config;
22
- constructor(config) {
23
- this.config = config;
24
- }
25
- async handle(request) {
26
- const handlerContext = RequestContextBuilder.create(request);
27
- const validationContext = createRequestContext(request);
19
+ function createTernSecureNextJsHandler(options) {
20
+ const config = createHandlerConfig(options);
21
+ const handler = async (request) => {
28
22
  try {
29
- const validationResult = await this.executeValidation(validationContext);
30
- if (validationResult) {
31
- return validationResult;
23
+ const context = createRequestProcessor(createTernSecureRequest(request), options);
24
+ const { validateSecurity } = createValidators(context);
25
+ await validateSecurity(options.security || {});
26
+ if (!context.endpoint) {
27
+ return createApiErrorResponse("ENDPOINT_REQUIRED", "Endpoint is required", 400);
32
28
  }
33
- return await EndpointRouter.route(handlerContext, this.config);
29
+ return await EndpointRouter.route(context, config);
34
30
  } catch (error) {
35
31
  return createApiErrorResponse("INTERNAL_SERVER_ERROR", "Internal server error", 500);
36
32
  }
37
- }
38
- async executeValidation(validationContext) {
39
- const validationPipeline = new ValidationPipeline(this.config, validationContext);
40
- return validationPipeline.execute();
41
- }
42
- }
43
- function createTernSecureNextJsHandler(options) {
44
- const config = HandlerConfigFactory.create(options);
45
- const requestHandler = new TernSecureRequestHandler(config);
46
- const handler = async (request) => await requestHandler.handle(request);
33
+ };
47
34
  return {
48
35
  GET: handler,
49
36
  POST: handler
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/app-router/admin/ternsecureNextjsHandler.ts"],"sourcesContent":["\nimport { TENANT_ID } from './constants';\nimport { EndpointRouter } from './endpointRouter';\nimport { createRequestContext } from './fnValidators';\nimport { RequestContextBuilder, ValidationPipeline } from './handlerUtils';\nimport { createApiErrorResponse } from './responses';\nimport type { TernSecureHandlerOptions, TernSecureInternalHandlerConfig } from './types';\nimport { DEFAULT_HANDLER_OPTIONS } from './types';\nimport { ConfigUtils } from './utils';\n\nclass HandlerConfigFactory {\n static create(options?: TernSecureHandlerOptions): TernSecureInternalHandlerConfig {\n const baseConfig: Required<TernSecureHandlerOptions> = ConfigUtils.mergeWithDefaults(\n DEFAULT_HANDLER_OPTIONS,\n options,\n );\n\n return {\n ...baseConfig,\n tenantId: TENANT_ID,\n };\n }\n}\n\nclass TernSecureRequestHandler {\n private readonly config: TernSecureInternalHandlerConfig;\n\n constructor(config: TernSecureInternalHandlerConfig) {\n this.config = config;\n }\n\n async handle(request: Request): Promise<Response> {\n const handlerContext = RequestContextBuilder.create(request);\n const validationContext = createRequestContext(request);\n\n try {\n const validationResult = await this.executeValidation(validationContext);\n if (validationResult) {\n return validationResult;\n }\n\n return await EndpointRouter.route(handlerContext, this.config);\n } catch (error) {\n return createApiErrorResponse('INTERNAL_SERVER_ERROR', 'Internal server error', 500);\n }\n }\n\n private async executeValidation(validationContext: any): Promise<Response | null> {\n const validationPipeline = new ValidationPipeline(this.config, validationContext);\n return validationPipeline.execute();\n }\n}\n\nexport function createTernSecureNextJsHandler(options: TernSecureHandlerOptions) {\n const config = HandlerConfigFactory.create(options);\n const requestHandler = new TernSecureRequestHandler(config);\n\n const handler = async (request: Request) => await requestHandler.handle(request);\n\n //const handler = async (request: Request): Promise<Response> => {\n // const context = await createRequestProcessor(createTernSecureRequest(request), options);\n // const { validateCors, validateSecurity } = createValidators(context);\n // await validateCors(options.cors || '');\n // await validateSecurity(options.security || {});\n //};\n\n return {\n GET: handler,\n POST: handler,\n } as const;\n}\n"],"mappings":"AACA,SAAS,iBAAiB;AAC1B,SAAS,sBAAsB;AAC/B,SAAS,4BAA4B;AACrC,SAAS,uBAAuB,0BAA0B;AAC1D,SAAS,8BAA8B;AAEvC,SAAS,+BAA+B;AACxC,SAAS,mBAAmB;AAE5B,MAAM,qBAAqB;AAAA,EACzB,OAAO,OAAO,SAAqE;AACjF,UAAM,aAAiD,YAAY;AAAA,MACjE;AAAA,MACA;AAAA,IACF;AAEA,WAAO;AAAA,MACL,GAAG;AAAA,MACH,UAAU;AAAA,IACZ;AAAA,EACF;AACF;AAEA,MAAM,yBAAyB;AAAA,EACZ;AAAA,EAEjB,YAAY,QAAyC;AACnD,SAAK,SAAS;AAAA,EAChB;AAAA,EAEA,MAAM,OAAO,SAAqC;AAChD,UAAM,iBAAiB,sBAAsB,OAAO,OAAO;AAC3D,UAAM,oBAAoB,qBAAqB,OAAO;AAEtD,QAAI;AACF,YAAM,mBAAmB,MAAM,KAAK,kBAAkB,iBAAiB;AACvE,UAAI,kBAAkB;AACpB,eAAO;AAAA,MACT;AAEA,aAAO,MAAM,eAAe,MAAM,gBAAgB,KAAK,MAAM;AAAA,IAC/D,SAAS,OAAO;AACd,aAAO,uBAAuB,yBAAyB,yBAAyB,GAAG;AAAA,IACrF;AAAA,EACF;AAAA,EAEA,MAAc,kBAAkB,mBAAkD;AAChF,UAAM,qBAAqB,IAAI,mBAAmB,KAAK,QAAQ,iBAAiB;AAChF,WAAO,mBAAmB,QAAQ;AAAA,EACpC;AACF;AAEO,SAAS,8BAA8B,SAAmC;AAC/E,QAAM,SAAS,qBAAqB,OAAO,OAAO;AAClD,QAAM,iBAAiB,IAAI,yBAAyB,MAAM;AAE1D,QAAM,UAAU,OAAO,YAAqB,MAAM,eAAe,OAAO,OAAO;AAS/E,SAAO;AAAA,IACL,KAAK;AAAA,IACL,MAAM;AAAA,EACR;AACF;","names":[]}
1
+ {"version":3,"sources":["../../../../src/app-router/admin/ternsecureNextjsHandler.ts"],"sourcesContent":["import { createTernSecureRequest } from '@tern-secure/backend';\n\nimport { createRequestProcessor } from './c-authenticateRequestProcessor';\nimport { TENANT_ID } from './constants';\nimport { EndpointRouter } from './endpointRouter';\nimport { createValidators } from './fnValidators';\nimport { createApiErrorResponse } from './responses';\nimport type { TernSecureHandlerOptions } from './types';\nimport { DEFAULT_HANDLER_OPTIONS } from './types';\nimport { ConfigUtils } from './utils';\n\nfunction createHandlerConfig(options?: TernSecureHandlerOptions): TernSecureHandlerOptions {\n const baseConfig: Required<TernSecureHandlerOptions> = ConfigUtils.mergeWithDefaults(\n DEFAULT_HANDLER_OPTIONS,\n options,\n );\n\n return {\n ...baseConfig,\n tenantId: TENANT_ID,\n };\n}\n\nexport function createTernSecureNextJsHandler(options: TernSecureHandlerOptions) {\n const config = createHandlerConfig(options);\n\n const handler = async (request: Request): Promise<Response> => {\n try {\n const context = createRequestProcessor(createTernSecureRequest(request), options);\n\n const { validateSecurity } = createValidators(context);\n await validateSecurity(options.security || {});\n\n if (!context.endpoint) {\n return createApiErrorResponse('ENDPOINT_REQUIRED', 'Endpoint is required', 400);\n }\n\n return await EndpointRouter.route(context, config);\n } catch (error) {\n return createApiErrorResponse('INTERNAL_SERVER_ERROR', 'Internal server error', 500);\n }\n };\n\n return {\n GET: handler,\n POST: handler,\n } as const;\n}\n"],"mappings":"AAAA,SAAS,+BAA+B;AAExC,SAAS,8BAA8B;AACvC,SAAS,iBAAiB;AAC1B,SAAS,sBAAsB;AAC/B,SAAS,wBAAwB;AACjC,SAAS,8BAA8B;AAEvC,SAAS,+BAA+B;AACxC,SAAS,mBAAmB;AAE5B,SAAS,oBAAoB,SAA8D;AACzF,QAAM,aAAiD,YAAY;AAAA,IACjE;AAAA,IACA;AAAA,EACF;AAEA,SAAO;AAAA,IACL,GAAG;AAAA,IACH,UAAU;AAAA,EACZ;AACF;AAEO,SAAS,8BAA8B,SAAmC;AAC/E,QAAM,SAAS,oBAAoB,OAAO;AAE1C,QAAM,UAAU,OAAO,YAAwC;AAC7D,QAAI;AACF,YAAM,UAAU,uBAAuB,wBAAwB,OAAO,GAAG,OAAO;AAEhF,YAAM,EAAE,iBAAiB,IAAI,iBAAiB,OAAO;AACrD,YAAM,iBAAiB,QAAQ,YAAY,CAAC,CAAC;AAE7C,UAAI,CAAC,QAAQ,UAAU;AACrB,eAAO,uBAAuB,qBAAqB,wBAAwB,GAAG;AAAA,MAChF;AAEA,aAAO,MAAM,eAAe,MAAM,SAAS,MAAM;AAAA,IACnD,SAAS,OAAO;AACd,aAAO,uBAAuB,yBAAyB,yBAAyB,GAAG;AAAA,IACrF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,KAAK;AAAA,IACL,MAAM;AAAA,EACR;AACF;","names":[]}