@eminuckan/spine 0.3.0 → 0.3.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.
Files changed (87) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +116 -98
  3. package/SECURITY.md +5 -15
  4. package/dist/access/index.mjs +2 -0
  5. package/dist/{access-CGrsDMwu.js → access-BHy1v5sr.mjs} +6 -8
  6. package/dist/access-BHy1v5sr.mjs.map +1 -0
  7. package/dist/api-client/index.mjs +3 -0
  8. package/dist/api-client/server.mjs +4 -0
  9. package/dist/{api-client-CgZUMukO.js → api-client-CB7XZaMg.mjs} +8 -10
  10. package/dist/api-client-CB7XZaMg.mjs.map +1 -0
  11. package/dist/auth/auth.server.d.ts +1 -0
  12. package/dist/auth/auth.server.d.ts.map +1 -1
  13. package/dist/auth/index.mjs +1 -0
  14. package/dist/auth/route-protection.server.d.ts.map +1 -1
  15. package/dist/auth/server.mjs +3 -0
  16. package/dist/{identity-C5un-xAs.js → identity/index.mjs} +24 -21
  17. package/dist/identity/index.mjs.map +1 -0
  18. package/dist/{server-Dxsww9v9.js → identity/server.mjs} +7 -8
  19. package/dist/identity/server.mjs.map +1 -0
  20. package/dist/{index.js → index.mjs} +11 -13
  21. package/dist/{logging-DviiAkLx.js → logging/index.mjs} +22 -24
  22. package/dist/logging/index.mjs.map +1 -0
  23. package/dist/{permission-service-CvGpwI0d.js → permission-service-DUyKomU3.mjs} +6 -10
  24. package/dist/permission-service-DUyKomU3.mjs.map +1 -0
  25. package/dist/permissions/index.mjs +3 -0
  26. package/dist/{permissions-_n1hIG7Q.js → permissions-C5dTP9y4.mjs} +23 -15
  27. package/dist/permissions-C5dTP9y4.mjs.map +1 -0
  28. package/dist/query-client/index.mjs +2 -0
  29. package/dist/{query-client-Bh3TyB8W.js → query-client-_xB300gc.mjs} +49 -15
  30. package/dist/query-client-_xB300gc.mjs.map +1 -0
  31. package/dist/react-router/{index.js → index.mjs} +11 -13
  32. package/dist/react-router/server.mjs +17 -0
  33. package/dist/{redis-session-storage.server-v2VcpFsQ.js → redis-session-storage.server-DGgQcJ9B.mjs} +30 -42
  34. package/dist/redis-session-storage.server-DGgQcJ9B.mjs.map +1 -0
  35. package/dist/{server-C96NMFBy.js → server-ByScGRXA.mjs} +39 -36
  36. package/dist/server-ByScGRXA.mjs.map +1 -0
  37. package/dist/{auth.server-D5oiz9aF.js → server-CqX2yCa4.mjs} +388 -119
  38. package/dist/server-CqX2yCa4.mjs.map +1 -0
  39. package/dist/server.mjs +90 -0
  40. package/dist/server.mjs.map +1 -0
  41. package/dist/signalr/index.mjs +2 -0
  42. package/dist/{signalr-k-70VHKo.js → signalr-C-TA8nEE.mjs} +11 -6
  43. package/dist/signalr-C-TA8nEE.mjs.map +1 -0
  44. package/dist/{tenant-DfLemb6n.js → tenant/index.mjs} +19 -12
  45. package/dist/tenant/index.mjs.map +1 -0
  46. package/dist/{server-Ca-3DJf2.js → tenant/server.mjs} +12 -12
  47. package/dist/tenant/server.mjs.map +1 -0
  48. package/dist/{types-BaaE6wjY.js → types-DqCXinAk.mjs} +3 -3
  49. package/dist/types-DqCXinAk.mjs.map +1 -0
  50. package/docs/codex-for-oss-application.md +14 -2
  51. package/package.json +14 -2
  52. package/dist/access/index.js +0 -4
  53. package/dist/access-CGrsDMwu.js.map +0 -1
  54. package/dist/api-client/index.js +0 -5
  55. package/dist/api-client/server.js +0 -6
  56. package/dist/api-client-CgZUMukO.js.map +0 -1
  57. package/dist/auth/index.js +0 -0
  58. package/dist/auth/server.js +0 -6
  59. package/dist/auth.server-D5oiz9aF.js.map +0 -1
  60. package/dist/auth.server-lC94lmlx.js +0 -5
  61. package/dist/identity/index.js +0 -3
  62. package/dist/identity/server.js +0 -5
  63. package/dist/identity-C5un-xAs.js.map +0 -1
  64. package/dist/logging/index.js +0 -3
  65. package/dist/logging-DviiAkLx.js.map +0 -1
  66. package/dist/permission-service-CvGpwI0d.js.map +0 -1
  67. package/dist/permissions/index.js +0 -4
  68. package/dist/permissions-_n1hIG7Q.js.map +0 -1
  69. package/dist/query-client/index.js +0 -3
  70. package/dist/query-client-Bh3TyB8W.js.map +0 -1
  71. package/dist/react-router/server.js +0 -20
  72. package/dist/redis-session-storage.server-v2VcpFsQ.js.map +0 -1
  73. package/dist/server-B6PCxc-T.js +0 -304
  74. package/dist/server-B6PCxc-T.js.map +0 -1
  75. package/dist/server-C96NMFBy.js.map +0 -1
  76. package/dist/server-Ca-3DJf2.js.map +0 -1
  77. package/dist/server-Dxsww9v9.js.map +0 -1
  78. package/dist/server-hGrElJMG.js +0 -78
  79. package/dist/server-hGrElJMG.js.map +0 -1
  80. package/dist/server.js +0 -20
  81. package/dist/signalr/index.js +0 -3
  82. package/dist/signalr-k-70VHKo.js.map +0 -1
  83. package/dist/src-B9rDUgSb.js +0 -0
  84. package/dist/tenant/index.js +0 -3
  85. package/dist/tenant/server.js +0 -5
  86. package/dist/tenant-DfLemb6n.js.map +0 -1
  87. package/dist/types-BaaE6wjY.js.map +0 -1
@@ -1,7 +1,6 @@
1
- import { isApiClientError } from "./types-BaaE6wjY.js";
2
- import { calculateBackoffDelay, fetchWithTimeout, isRetryableError } from "./api-client-CgZUMukO.js";
1
+ import { t as isApiClientError } from "./types-DqCXinAk.mjs";
2
+ import { i as isRetryableError, r as fetchWithTimeout, t as calculateBackoffDelay } from "./api-client-CB7XZaMg.mjs";
3
3
  import { AsyncLocalStorage } from "node:async_hooks";
4
-
5
4
  //#region src/api-client/api-config.server.ts
6
5
  /**
7
6
  * Base URL Configuration
@@ -128,15 +127,24 @@ function createAPIConfigFactory(getAccessToken, getCurrentTenant, logger, factor
128
127
  getAPIBaseURL
129
128
  };
130
129
  }
131
-
132
130
  //#endregion
133
131
  //#region src/api-client/fetch-client.server.ts
134
- const refreshPromiseMap = new Map();
135
- const responseRequestMeta = new WeakMap();
132
+ /**
133
+ * Fetch-native API client setup for generated OpenAPI clients.
134
+ *
135
+ * This module preserves the shared request behaviors we need around fetch:
136
+ * - request ID enrichment
137
+ * - serialized token refresh on 401
138
+ * - retry with exponential backoff
139
+ * - ProblemDetails-aware error shaping
140
+ *
141
+ * It gives downstream apps a single fetch-native entry point for generated clients.
142
+ */
143
+ const refreshPromiseMap = /* @__PURE__ */ new Map();
144
+ const responseRequestMeta = /* @__PURE__ */ new WeakMap();
136
145
  const rawResponseStore = new AsyncLocalStorage();
137
146
  function getSessionKeyFromRequest(request) {
138
- const cookie = request.headers.get("cookie") || "";
139
- return `session:${cookie.slice(0, 50)}`;
147
+ return `session:${(request.headers.get("cookie") || "").slice(0, 50)}`;
140
148
  }
141
149
  function getOrCreateRefreshPromise(sessionKey, refreshFn, logger) {
142
150
  const existingPromise = refreshPromiseMap.get(sessionKey);
@@ -167,7 +175,7 @@ function cloneInit(init) {
167
175
  };
168
176
  }
169
177
  function createTimeoutFetch(timeout) {
170
- if (!timeout) return void 0;
178
+ if (!timeout) return;
171
179
  return (input, init) => fetchWithTimeout(input, {
172
180
  ...init,
173
181
  timeout
@@ -182,13 +190,12 @@ async function parseResponseBody(response) {
182
190
  if (contentType.includes("application/json") || contentType.includes("+json")) try {
183
191
  return await clone.json();
184
192
  } catch {
185
- return void 0;
193
+ return;
186
194
  }
187
195
  try {
188
- const text = await clone.text();
189
- return text || void 0;
196
+ return await clone.text() || void 0;
190
197
  } catch {
191
- return void 0;
198
+ return;
192
199
  }
193
200
  }
194
201
  function createClientError(params) {
@@ -204,9 +211,8 @@ function createClientError(params) {
204
211
  return error;
205
212
  }
206
213
  async function toAPIResponse(rawResponse, resolvedData) {
207
- const data = resolvedData === void 0 ? await parseResponseBody(rawResponse) : resolvedData;
208
214
  return {
209
- data,
215
+ data: resolvedData === void 0 ? await parseResponseBody(rawResponse) : resolvedData,
210
216
  status: rawResponse.status,
211
217
  statusText: rawResponse.statusText,
212
218
  headers: headersToRecord(rawResponse.headers),
@@ -240,10 +246,10 @@ function isRetryableFetchError(error) {
240
246
  async function maybeRetryResponse(context, retryConfig, logger) {
241
247
  const init = cloneInit(context.init);
242
248
  const meta = ensureRequestMeta(init);
243
- if (context.response.status === 401 || context.response.status === 409) return void 0;
244
- if (!isRetryableError(context.response)) return void 0;
249
+ if (context.response.status === 401 || context.response.status === 409) return;
250
+ if (!isRetryableError(context.response)) return;
245
251
  const retryCount = meta.retryCount ?? 0;
246
- if (retryCount >= retryConfig.maxRetries) return void 0;
252
+ if (retryCount >= retryConfig.maxRetries) return;
247
253
  meta.retryCount = retryCount + 1;
248
254
  const delay = calculateBackoffDelay(meta.retryCount, retryConfig.baseDelay, retryConfig.maxDelay);
249
255
  logger?.info?.("Retrying request", {
@@ -261,7 +267,7 @@ async function maybeRetryError(context, retryConfig, logger) {
261
267
  const init = cloneInit(context.init);
262
268
  const meta = ensureRequestMeta(init);
263
269
  const retryCount = meta.retryCount ?? 0;
264
- if (!isRetryableFetchError(context.error) || retryCount >= retryConfig.maxRetries) return void 0;
270
+ if (!isRetryableFetchError(context.error) || retryCount >= retryConfig.maxRetries) return;
265
271
  meta.retryCount = retryCount + 1;
266
272
  const delay = calculateBackoffDelay(meta.retryCount, retryConfig.baseDelay, retryConfig.maxDelay);
267
273
  logger?.info?.("Retrying request after fetch failure", {
@@ -352,7 +358,6 @@ function createFetchMiddleware(request, options = {}) {
352
358
  async onError(context) {
353
359
  const retryResponse = await maybeRetryError(context, normalizedRetryConfig, logger);
354
360
  if (retryResponse) return retryResponse;
355
- return void 0;
356
361
  }
357
362
  }];
358
363
  }
@@ -378,12 +383,12 @@ function instrumentRawMethods(client) {
378
383
  }
379
384
  function wrapClient(client) {
380
385
  instrumentRawMethods(client);
381
- const methodCache = new Map();
386
+ const methodCache = /* @__PURE__ */ new Map();
382
387
  return new Proxy(client, { get(target, prop, receiver) {
383
388
  const value = Reflect.get(target, prop, receiver);
384
389
  if (typeof prop !== "string" || typeof value !== "function" || prop.endsWith("Raw")) return typeof value === "function" ? value.bind(target) : value;
385
390
  if (methodCache.has(prop)) return methodCache.get(prop);
386
- const wrapped = async (...args) => rawResponseStore.run(new Map(), async () => {
391
+ const wrapped = async (...args) => rawResponseStore.run(/* @__PURE__ */ new Map(), async () => {
387
392
  try {
388
393
  const resolvedData = await value.apply(target, args);
389
394
  const rawResponse = rawResponseStore.getStore()?.get(`${prop}Raw`);
@@ -403,28 +408,26 @@ function wrapClient(client) {
403
408
  } });
404
409
  }
405
410
  async function createApiClient(request, ClientClass, createAPIConfig, ConfigurationClass, options = {}) {
406
- const { requireTenant, includeAuth, tenantId, customHeaders, credentials,...fetchOptions } = options;
411
+ const { requireTenant, includeAuth, tenantId, customHeaders, credentials, ...fetchOptions } = options;
407
412
  const config = await createAPIConfig(request, {
408
413
  requireTenant,
409
414
  includeAuth,
410
415
  tenantId,
411
416
  customHeaders
412
417
  });
413
- const configuration = new ConfigurationClass({
414
- basePath: config.basePath,
415
- accessToken: config.accessToken,
416
- headers: config.headers,
417
- credentials: credentials ?? config.credentials,
418
- middleware: createFetchMiddleware(request, fetchOptions),
419
- fetchApi: createTimeoutFetch(config.baseOptions?.timeout)
420
- });
421
- const client = new ClientClass(configuration);
422
418
  return {
423
- client: wrapClient(client),
419
+ client: wrapClient(new ClientClass(new ConfigurationClass({
420
+ basePath: config.basePath,
421
+ accessToken: config.accessToken,
422
+ headers: config.headers,
423
+ credentials: credentials ?? config.credentials,
424
+ middleware: createFetchMiddleware(request, fetchOptions),
425
+ fetchApi: createTimeoutFetch(config.baseOptions?.timeout)
426
+ }))),
424
427
  tenantId: config.tenantId
425
428
  };
426
429
  }
427
-
428
430
  //#endregion
429
- export { createAPIConfigFactory, createApiClient, createFetchMiddleware };
430
- //# sourceMappingURL=server-C96NMFBy.js.map
431
+ export { createFetchMiddleware as n, createAPIConfigFactory as r, createApiClient as t };
432
+
433
+ //# sourceMappingURL=server-ByScGRXA.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-ByScGRXA.mjs","names":[],"sources":["../src/api-client/api-config.server.ts","../src/api-client/fetch-client.server.ts"],"sourcesContent":["/**\n * API Configuration Server Module\n *\n * Centralized configuration for all API clients,\n * automatically handling authentication tokens and tenant context.\n */\n\nimport type { APIConfig, CreateAPIConfigOptions, GetAccessTokenFn, GetCurrentTenantFn, APILogger } from './types';\n\n/**\n * Base URL Configuration\n * Single unified base URL for all API operations\n */\nconst DEFAULT_API_BASE_URL = process.env.API_BASE_URL || '';\n\n/**\n * Default Headers\n * Applied to all API requests\n */\nconst DEFAULT_HEADERS: Record<string, string> = {\n Accept: 'application/json, application/problem+json',\n 'Content-Type': 'application/json',\n};\n\n/**\n * API Config Factory Options\n */\nexport interface APIConfigFactoryOptions {\n /**\n * Base URL for API requests\n */\n baseURL?: string;\n /**\n * Default headers applied to all requests\n */\n defaultHeaders?: Record<string, string>;\n /**\n * User agent string\n */\n userAgent?: string;\n /**\n * Default timeout in milliseconds\n */\n timeout?: number;\n /**\n * Header name used for bearer-style auth. Set to null when buildHeaders owns auth.\n * @default 'Authorization'\n */\n authHeaderName?: string | null;\n /**\n * Build an auth header value from the resolved access token.\n * @default token => `Bearer ${token}`\n */\n authHeaderValue?: (accessToken: string) => string;\n /**\n * Header name used for tenant context. Set to null when buildHeaders owns tenancy.\n * @default 'X-Tenant-Id'\n */\n tenantHeaderName?: string | null;\n /**\n * Final app-specific header hook. Returned headers are merged last.\n */\n buildHeaders?: (context: APIHeaderStrategyContext) => Record<string, string>;\n}\n\nexport interface APIHeaderStrategyContext {\n request: Request;\n options: CreateAPIConfigOptions;\n accessToken?: string;\n tenantId: string | null;\n includeAuth: boolean;\n requireTenant: boolean;\n}\n\n/**\n * Create API Config Factory\n *\n * Creates a factory function that generates API configurations\n * with the provided auth and tenant resolvers.\n */\nexport function createAPIConfigFactory(\n getAccessToken: GetAccessTokenFn,\n getCurrentTenant: GetCurrentTenantFn,\n logger?: APILogger,\n factoryOptions: APIConfigFactoryOptions = {}\n) {\n const {\n baseURL = DEFAULT_API_BASE_URL,\n defaultHeaders = DEFAULT_HEADERS,\n userAgent = 'Spine/1.0',\n timeout = 30000,\n authHeaderName = 'Authorization',\n authHeaderValue = (token: string) => `Bearer ${token}`,\n tenantHeaderName = 'X-Tenant-Id',\n buildHeaders,\n } = factoryOptions;\n\n /**\n * Resolve tenant ID from request or options\n */\n async function resolveTenantId(\n request: Request,\n options: CreateAPIConfigOptions\n ): Promise<string | null> {\n // Use explicit tenant ID if provided\n if (options.tenantId) {\n logger?.debug?.('Using explicit tenant ID', { tenantId: options.tenantId });\n return options.tenantId;\n }\n\n // Resolve from current tenant context\n try {\n const tenantId = await getCurrentTenant(request);\n if (tenantId) {\n logger?.debug?.('Resolved tenant from context', { tenantId });\n }\n return tenantId;\n } catch (error) {\n logger?.warn?.('Failed to resolve current tenant', error instanceof Error ? error : undefined);\n return null;\n }\n }\n\n /**\n * Creates unified API configuration for all services.\n *\n * This function automatically:\n * - Adds authentication token using the configured auth header strategy\n * - Injects tenant context using the configured tenant header strategy\n * - Configures base URL from options or environment\n * - Applies default headers\n *\n * @param request - The incoming request object\n * @param options - Configuration options\n * @returns API configuration object\n * @throws Error if required authentication or tenant context is missing\n *\n * @example\n * `\typescript\n * // Standard usage with auth and tenant\n * const config = await createAPIConfig(request);\n * const api = new IdentityApi(config);\n *\n * // Without tenant requirement\n * const config = await createAPIConfig(request, { requireTenant: false });\n *\n * // With explicit tenant override\n * const config = await createAPIConfig(request, { tenantId: 'specific-tenant-id' });\n * `\n */\n async function createAPIConfig(\n request: Request,\n options: CreateAPIConfigOptions = {}\n ): Promise<APIConfig> {\n const {\n requireTenant = true,\n includeAuth = true,\n customHeaders = {},\n } = options;\n\n // Start with default headers\n const headers: Record<string, string> = {\n ...defaultHeaders,\n 'User-Agent': userAgent,\n ...customHeaders,\n };\n\n let accessToken: string | undefined;\n\n // Add authentication if required\n if (includeAuth) {\n const token = await getAccessToken(request);\n if (!token) {\n logger?.error?.('No access token available for API request');\n throw new Error('No access token available');\n }\n\n accessToken = token;\n if (authHeaderName) {\n headers[authHeaderName] = authHeaderValue(token);\n }\n logger?.debug?.('Added authorization header to API config');\n }\n\n // Resolve tenant context\n const tenantId = await resolveTenantId(request, options);\n\n // Add tenant header if required\n if (requireTenant) {\n if (!tenantId) {\n logger?.error?.('Tenant context required but not available');\n throw new Error('Tenant context is required for this operation');\n }\n\n if (tenantHeaderName) {\n headers[tenantHeaderName] = tenantId;\n }\n logger?.debug?.('Added tenant context header', { tenantId });\n }\n\n if (buildHeaders) {\n Object.assign(headers, buildHeaders({\n request,\n options,\n accessToken,\n tenantId,\n includeAuth,\n requireTenant,\n }));\n }\n\n logger?.debug?.('API config created', {\n basePath: baseURL,\n hasAuth: includeAuth,\n hasTenant: !!tenantId,\n requireTenant,\n });\n\n return {\n basePath: baseURL,\n accessToken,\n headers,\n tenantId: tenantId || '',\n baseOptions: {\n timeout,\n },\n };\n }\n\n /**\n * Get the configured API base URL\n */\n function getAPIBaseURL(): string {\n return baseURL;\n }\n\n return {\n createAPIConfig,\n getAPIBaseURL,\n };\n}\n\nexport type APIConfigFactory = ReturnType<typeof createAPIConfigFactory>;\n","/**\n * Fetch-native API client setup for generated OpenAPI clients.\n *\n * This module preserves the shared request behaviors we need around fetch:\n * - request ID enrichment\n * - serialized token refresh on 401\n * - retry with exponential backoff\n * - ProblemDetails-aware error shaping\n *\n * It gives downstream apps a single fetch-native entry point for generated clients.\n */\n\nimport { AsyncLocalStorage } from 'node:async_hooks';\nimport type {\n APIClientError,\n APIConfig,\n APIResponse,\n APILogger,\n CreateAPIConfigOptions,\n EnhancedAPIClient,\n FetchErrorContext,\n FetchMiddleware,\n FetchResponseContext,\n ProblemDetails,\n RetryConfig,\n TokenRefreshFn,\n TokenRefreshResult,\n} from './types';\nimport { isApiClientError } from './types';\nimport { calculateBackoffDelay, fetchWithTimeout, isRetryableError } from './retry-handler';\n\ntype RuntimeApiResponse<T> = {\n raw: Response;\n value(): Promise<T>;\n};\n\ntype GeneratedFetchClient = object;\n\ntype SpineRequestInit = RequestInit & {\n __spineMeta?: {\n requestId?: string;\n retryCount?: number;\n refreshed?: boolean;\n };\n};\n\ntype ResponseRequestMeta = {\n url: string;\n method: string;\n headers: Record<string, string>;\n};\n\nconst refreshPromiseMap = new Map<string, Promise<TokenRefreshResult>>();\nconst responseRequestMeta = new WeakMap<Response, ResponseRequestMeta>();\nconst rawResponseStore = new AsyncLocalStorage<Map<string, RuntimeApiResponse<unknown>>>();\n\nfunction getSessionKeyFromRequest(request: Request): string {\n const cookie = request.headers.get('cookie') || '';\n return `session:${cookie.slice(0, 50)}`;\n}\n\nfunction getOrCreateRefreshPromise(\n sessionKey: string,\n refreshFn: () => Promise<TokenRefreshResult>,\n logger?: APILogger\n): Promise<TokenRefreshResult> {\n const existingPromise = refreshPromiseMap.get(sessionKey);\n if (existingPromise) {\n logger?.info?.('Token refresh already in progress, waiting for existing refresh');\n return existingPromise;\n }\n\n logger?.info?.('Starting new token refresh');\n\n const refreshPromise = refreshFn().finally(() => {\n refreshPromiseMap.delete(sessionKey);\n });\n\n refreshPromiseMap.set(sessionKey, refreshPromise);\n return refreshPromise;\n}\n\nfunction ensureRequestMeta(init: SpineRequestInit): NonNullable<SpineRequestInit['__spineMeta']> {\n if (!init.__spineMeta) {\n init.__spineMeta = {};\n }\n\n return init.__spineMeta;\n}\n\nfunction headersToRecord(headersInit?: HeadersInit): Record<string, string> {\n return Object.fromEntries(new Headers(headersInit).entries());\n}\n\nfunction cloneInit(init: RequestInit): SpineRequestInit {\n const source = init as SpineRequestInit;\n\n return {\n ...source,\n headers: headersToRecord(source.headers),\n __spineMeta: source.__spineMeta ? { ...source.__spineMeta } : undefined,\n };\n}\n\nfunction createTimeoutFetch(timeout?: number): typeof fetch | undefined {\n if (!timeout) {\n return undefined;\n }\n\n return (input, init) => fetchWithTimeout(input, { ...init, timeout });\n}\n\nfunction isProblemDetails(value: unknown): value is ProblemDetails {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'title' in value &&\n 'status' in value &&\n 'detail' in value\n );\n}\n\nasync function parseResponseBody(response: Response): Promise<unknown> {\n const clone = response.clone();\n const contentType = clone.headers.get('content-type') || '';\n\n if (contentType.includes('application/json') || contentType.includes('+json')) {\n try {\n return await clone.json();\n } catch {\n return undefined;\n }\n }\n\n try {\n const text = await clone.text();\n return text || undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction createClientError<T = unknown>(params: {\n message: string;\n response?: APIResponse<T>;\n config?: ResponseRequestMeta;\n problemDetails?: ProblemDetails;\n shouldLogout?: boolean;\n originalError?: unknown;\n cause?: unknown;\n}): APIClientError<T> {\n const error = new Error(params.message) as APIClientError<T>;\n\n error.name = 'APIClientError';\n error.isApiClientError = true;\n error.response = params.response;\n error.config = params.config;\n error.problemDetails = params.problemDetails;\n error.shouldLogout = params.shouldLogout;\n error.originalError = params.originalError;\n error.cause = params.cause;\n\n return error;\n}\n\nasync function toAPIResponse<T>(\n rawResponse: Response,\n resolvedData?: T\n): Promise<APIResponse<T>> {\n const data = resolvedData === undefined ? ((await parseResponseBody(rawResponse)) as T) : resolvedData;\n\n return {\n data,\n status: rawResponse.status,\n statusText: rawResponse.statusText,\n headers: headersToRecord(rawResponse.headers),\n raw: rawResponse,\n };\n}\n\nasync function normalizeClientError(error: unknown): Promise<APIClientError> {\n if (isApiClientError(error)) {\n return error;\n }\n\n if (error && typeof error === 'object' && 'response' in error && (error as { response?: unknown }).response instanceof Response) {\n const response = (error as { response: Response }).response;\n const responseData = await parseResponseBody(response);\n const problemDetails = isProblemDetails(responseData) ? responseData : undefined;\n\n return createClientError({\n message:\n problemDetails?.detail ||\n problemDetails?.title ||\n response.statusText ||\n 'API request failed',\n response: await toAPIResponse(response, responseData),\n config: responseRequestMeta.get(response),\n problemDetails,\n cause: error,\n });\n }\n\n return createClientError({\n message: error instanceof Error ? error.message : 'API request failed',\n cause: error,\n });\n}\n\nfunction isRetryableFetchError(error: unknown): boolean {\n if (isRetryableError(error)) {\n return true;\n }\n\n if (error && typeof error === 'object' && 'cause' in error) {\n return isRetryableError((error as { cause?: unknown }).cause);\n }\n\n return false;\n}\n\nasync function maybeRetryResponse(\n context: FetchResponseContext,\n retryConfig: Required<Pick<RetryConfig, 'maxRetries' | 'baseDelay' | 'maxDelay'>>,\n logger?: APILogger\n): Promise<Response | undefined> {\n const init = cloneInit(context.init);\n const meta = ensureRequestMeta(init);\n\n if (context.response.status === 401 || context.response.status === 409) {\n return undefined;\n }\n\n if (!isRetryableError(context.response)) {\n return undefined;\n }\n\n const retryCount = meta.retryCount ?? 0;\n if (retryCount >= retryConfig.maxRetries) {\n return undefined;\n }\n\n meta.retryCount = retryCount + 1;\n\n const delay = calculateBackoffDelay(meta.retryCount, retryConfig.baseDelay, retryConfig.maxDelay);\n logger?.info?.('Retrying request', {\n url: context.url,\n method: (init.method ?? 'GET').toUpperCase(),\n attempt: meta.retryCount,\n maxRetries: retryConfig.maxRetries,\n delay,\n status: context.response.status,\n });\n\n await new Promise((resolve) => setTimeout(resolve, delay));\n\n return context.fetch(context.url, init);\n}\n\nasync function maybeRetryError(\n context: FetchErrorContext,\n retryConfig: Required<Pick<RetryConfig, 'maxRetries' | 'baseDelay' | 'maxDelay'>>,\n logger?: APILogger\n): Promise<Response | undefined> {\n const init = cloneInit(context.init);\n const meta = ensureRequestMeta(init);\n const retryCount = meta.retryCount ?? 0;\n\n if (!isRetryableFetchError(context.error) || retryCount >= retryConfig.maxRetries) {\n return undefined;\n }\n\n meta.retryCount = retryCount + 1;\n\n const delay = calculateBackoffDelay(meta.retryCount, retryConfig.baseDelay, retryConfig.maxDelay);\n logger?.info?.('Retrying request after fetch failure', {\n url: context.url,\n method: (init.method ?? 'GET').toUpperCase(),\n attempt: meta.retryCount,\n maxRetries: retryConfig.maxRetries,\n delay,\n });\n\n await new Promise((resolve) => setTimeout(resolve, delay));\n\n return context.fetch(context.url, init);\n}\n\nexport interface FetchSetupOptions {\n logger?: APILogger;\n attemptTokenRefresh?: TokenRefreshFn;\n retryConfig?: RetryConfig;\n addRequestId?: boolean;\n}\n\nexport function createFetchMiddleware(\n request: Request,\n options: FetchSetupOptions = {}\n): FetchMiddleware[] {\n const {\n logger,\n attemptTokenRefresh,\n retryConfig = {},\n addRequestId = true,\n } = options;\n\n const normalizedRetryConfig = {\n maxRetries: retryConfig.maxRetries ?? 3,\n baseDelay: retryConfig.baseDelay ?? 1000,\n maxDelay: retryConfig.maxDelay ?? 10000,\n };\n\n return [\n {\n async pre(context) {\n const init = cloneInit(context.init);\n const meta = ensureRequestMeta(init);\n const headers = new Headers(init.headers);\n\n if (addRequestId) {\n const requestId = headers.get('X-Request-Id') || crypto.randomUUID();\n headers.set('X-Request-Id', requestId);\n meta.requestId = requestId;\n }\n\n init.headers = headersToRecord(headers);\n\n logger?.debug?.('API request initiated', {\n method: (init.method ?? 'GET').toUpperCase(),\n url: context.url,\n requestId: meta.requestId,\n });\n\n return {\n url: context.url,\n init,\n };\n },\n\n async post(context) {\n const init = cloneInit(context.init);\n const meta = ensureRequestMeta(init);\n\n responseRequestMeta.set(context.response, {\n url: context.url,\n method: (init.method ?? 'GET').toUpperCase(),\n headers: headersToRecord(init.headers),\n });\n\n if (context.response.status === 401 && attemptTokenRefresh && !meta.refreshed) {\n meta.refreshed = true;\n\n logger?.info?.('Received 401 from backend, attempting token refresh', {\n url: context.url,\n method: (init.method ?? 'GET').toUpperCase(),\n });\n\n const refreshResult = await getOrCreateRefreshPromise(\n getSessionKeyFromRequest(request),\n () => attemptTokenRefresh(request),\n logger\n );\n\n if (refreshResult.success && refreshResult.newAccessToken) {\n const headers = new Headers(init.headers);\n headers.set('Authorization', `Bearer ${refreshResult.newAccessToken}`);\n init.headers = headersToRecord(headers);\n\n logger?.info?.('Token refresh successful, retrying original request');\n\n return context.fetch(context.url, init);\n }\n\n if (refreshResult.shouldLogout) {\n throw createClientError({\n message: 'REFRESH_TOKEN_EXPIRED',\n response: await toAPIResponse(context.response),\n config: responseRequestMeta.get(context.response),\n shouldLogout: true,\n originalError: refreshResult,\n cause: refreshResult,\n });\n }\n }\n\n const retryResponse = await maybeRetryResponse(context, normalizedRetryConfig, logger);\n if (retryResponse) {\n return retryResponse;\n }\n\n if (context.response.status >= 400) {\n const responseData = await parseResponseBody(context.response);\n const problemDetails = isProblemDetails(responseData) ? responseData : undefined;\n\n logger?.error?.('API error response received', undefined, {\n url: context.url,\n method: (init.method ?? 'GET').toUpperCase(),\n status: context.response.status,\n code: problemDetails?.title,\n detail: problemDetails?.detail,\n traceId: problemDetails?.traceId,\n });\n }\n\n return context.response;\n },\n\n async onError(context) {\n const retryResponse = await maybeRetryError(context, normalizedRetryConfig, logger);\n if (retryResponse) {\n return retryResponse;\n }\n\n return undefined;\n },\n },\n ];\n}\n\nexport interface CreateApiClientOptions extends FetchSetupOptions, CreateAPIConfigOptions {\n credentials?: RequestCredentials;\n}\n\nfunction instrumentRawMethods<T extends GeneratedFetchClient>(client: T): void {\n if ((client as { __spineRawMethodsInstrumented?: boolean }).__spineRawMethodsInstrumented) {\n return;\n }\n\n const prototype = Object.getPrototypeOf(client) as Record<string, unknown>;\n\n for (const key of Object.getOwnPropertyNames(prototype)) {\n if (!key.endsWith('Raw')) {\n continue;\n }\n\n const original = prototype[key];\n if (typeof original !== 'function') {\n continue;\n }\n\n Object.defineProperty(client, key, {\n configurable: true,\n enumerable: false,\n writable: true,\n value: async (...args: unknown[]) => {\n const result = await (original as (...innerArgs: unknown[]) => Promise<RuntimeApiResponse<unknown>>).apply(client, args);\n rawResponseStore.getStore()?.set(key, result);\n return result;\n },\n });\n }\n\n (client as { __spineRawMethodsInstrumented?: boolean }).__spineRawMethodsInstrumented = true;\n}\n\nfunction wrapClient<T extends GeneratedFetchClient>(client: T): EnhancedAPIClient<T> {\n instrumentRawMethods(client);\n\n const methodCache = new Map<PropertyKey, unknown>();\n\n return new Proxy(client, {\n get(target, prop, receiver) {\n const value = Reflect.get(target, prop, receiver);\n\n if (typeof prop !== 'string' || typeof value !== 'function' || prop.endsWith('Raw')) {\n return typeof value === 'function' ? value.bind(target) : value;\n }\n\n if (methodCache.has(prop)) {\n return methodCache.get(prop);\n }\n\n const wrapped = async (...args: unknown[]) =>\n rawResponseStore.run(new Map(), async () => {\n try {\n const resolvedData = await (value as (...innerArgs: unknown[]) => Promise<unknown>).apply(target, args);\n const rawResponse = rawResponseStore.getStore()?.get(`${prop}Raw`);\n\n if (rawResponse) {\n return toAPIResponse(rawResponse.raw, resolvedData);\n }\n\n return {\n data: resolvedData,\n status: 200,\n statusText: 'OK',\n headers: {},\n };\n } catch (error) {\n throw await normalizeClientError(error);\n }\n });\n\n methodCache.set(prop, wrapped);\n return wrapped;\n },\n }) as EnhancedAPIClient<T>;\n}\n\nexport async function createApiClient<T extends GeneratedFetchClient>(\n request: Request,\n ClientClass: new (configuration?: unknown) => T,\n createAPIConfig: (request: Request, options?: CreateAPIConfigOptions) => Promise<APIConfig>,\n ConfigurationClass: new (params?: Record<string, unknown>) => unknown,\n options: CreateApiClientOptions = {}\n): Promise<{ client: EnhancedAPIClient<T>; tenantId: string }> {\n const {\n requireTenant,\n includeAuth,\n tenantId,\n customHeaders,\n credentials,\n ...fetchOptions\n } = options;\n\n const config = await createAPIConfig(request, {\n requireTenant,\n includeAuth,\n tenantId,\n customHeaders,\n });\n\n const configuration = new ConfigurationClass({\n basePath: config.basePath,\n accessToken: config.accessToken,\n headers: config.headers,\n credentials: credentials ?? config.credentials,\n middleware: createFetchMiddleware(request, fetchOptions),\n fetchApi: createTimeoutFetch(config.baseOptions?.timeout),\n });\n\n const client = new ClientClass(configuration);\n\n return {\n client: wrapClient(client),\n tenantId: config.tenantId,\n };\n}\n"],"mappings":";;;;;;;;AAaA,MAAM,uBAAuB,QAAQ,IAAI,gBAAgB;;;;;AAMzD,MAAM,kBAA0C;CAC9C,QAAQ;CACR,gBAAgB;AAClB;;;;;;;AA0DA,SAAgB,uBACd,gBACA,kBACA,QACA,iBAA0C,CAAC,GAC3C;CACA,MAAM,EACJ,UAAU,sBACV,iBAAiB,iBACjB,YAAY,aACZ,UAAU,KACV,iBAAiB,iBACjB,mBAAmB,UAAkB,UAAU,SAC/C,mBAAmB,eACnB,iBACE;;;;CAKJ,eAAe,gBACb,SACA,SACwB;EAExB,IAAI,QAAQ,UAAU;GACpB,QAAQ,QAAQ,4BAA4B,EAAE,UAAU,QAAQ,SAAS,CAAC;GAC1E,OAAO,QAAQ;EACjB;EAGA,IAAI;GACF,MAAM,WAAW,MAAM,iBAAiB,OAAO;GAC/C,IAAI,UACF,QAAQ,QAAQ,gCAAgC,EAAE,SAAS,CAAC;GAE9D,OAAO;EACT,SAAS,OAAO;GACd,QAAQ,OAAO,oCAAoC,iBAAiB,QAAQ,QAAQ,KAAA,CAAS;GAC7F,OAAO;EACT;CACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6BA,eAAe,gBACb,SACA,UAAkC,CAAC,GACf;EACpB,MAAM,EACJ,gBAAgB,MAChB,cAAc,MACd,gBAAgB,CAAC,MACf;EAGJ,MAAM,UAAkC;GACtC,GAAG;GACH,cAAc;GACd,GAAG;EACL;EAEA,IAAI;EAGJ,IAAI,aAAa;GACf,MAAM,QAAQ,MAAM,eAAe,OAAO;GAC1C,IAAI,CAAC,OAAO;IACV,QAAQ,QAAQ,2CAA2C;IAC3D,MAAM,IAAI,MAAM,2BAA2B;GAC7C;GAEA,cAAc;GACd,IAAI,gBACF,QAAQ,kBAAkB,gBAAgB,KAAK;GAEjD,QAAQ,QAAQ,0CAA0C;EAC5D;EAGA,MAAM,WAAW,MAAM,gBAAgB,SAAS,OAAO;EAGvD,IAAI,eAAe;GACjB,IAAI,CAAC,UAAU;IACb,QAAQ,QAAQ,2CAA2C;IAC3D,MAAM,IAAI,MAAM,+CAA+C;GACjE;GAEA,IAAI,kBACF,QAAQ,oBAAoB;GAE9B,QAAQ,QAAQ,+BAA+B,EAAE,SAAS,CAAC;EAC7D;EAEA,IAAI,cACF,OAAO,OAAO,SAAS,aAAa;GAClC;GACA;GACA;GACA;GACA;GACA;EACF,CAAC,CAAC;EAGJ,QAAQ,QAAQ,sBAAsB;GACpC,UAAU;GACV,SAAS;GACT,WAAW,CAAC,CAAC;GACb;EACF,CAAC;EAED,OAAO;GACL,UAAU;GACV;GACA;GACA,UAAU,YAAY;GACtB,aAAa,EACX,QACF;EACF;CACF;;;;CAKA,SAAS,gBAAwB;EAC/B,OAAO;CACT;CAEA,OAAO;EACL;EACA;CACF;AACF;;;;;;;;;;;;;;AC5LA,MAAM,oCAAoB,IAAI,IAAyC;AACvE,MAAM,sCAAsB,IAAI,QAAuC;AACvE,MAAM,mBAAmB,IAAI,kBAA4D;AAEzF,SAAS,yBAAyB,SAA0B;CAE1D,OAAO,YADQ,QAAQ,QAAQ,IAAI,QAAQ,KAAK,GAAA,CACvB,MAAM,GAAG,EAAE;AACtC;AAEA,SAAS,0BACP,YACA,WACA,QAC6B;CAC7B,MAAM,kBAAkB,kBAAkB,IAAI,UAAU;CACxD,IAAI,iBAAiB;EACnB,QAAQ,OAAO,iEAAiE;EAChF,OAAO;CACT;CAEA,QAAQ,OAAO,4BAA4B;CAE3C,MAAM,iBAAiB,UAAU,CAAC,CAAC,cAAc;EAC/C,kBAAkB,OAAO,UAAU;CACrC,CAAC;CAED,kBAAkB,IAAI,YAAY,cAAc;CAChD,OAAO;AACT;AAEA,SAAS,kBAAkB,MAAsE;CAC/F,IAAI,CAAC,KAAK,aACR,KAAK,cAAc,CAAC;CAGtB,OAAO,KAAK;AACd;AAEA,SAAS,gBAAgB,aAAmD;CAC1E,OAAO,OAAO,YAAY,IAAI,QAAQ,WAAW,CAAC,CAAC,QAAQ,CAAC;AAC9D;AAEA,SAAS,UAAU,MAAqC;CACtD,MAAM,SAAS;CAEf,OAAO;EACL,GAAG;EACH,SAAS,gBAAgB,OAAO,OAAO;EACvC,aAAa,OAAO,cAAc,EAAE,GAAG,OAAO,YAAY,IAAI,KAAA;CAChE;AACF;AAEA,SAAS,mBAAmB,SAA4C;CACtE,IAAI,CAAC,SACH;CAGF,QAAQ,OAAO,SAAS,iBAAiB,OAAO;EAAE,GAAG;EAAM;CAAQ,CAAC;AACtE;AAEA,SAAS,iBAAiB,OAAyC;CACjE,OACE,OAAO,UAAU,YACjB,UAAU,QACV,WAAW,SACX,YAAY,SACZ,YAAY;AAEhB;AAEA,eAAe,kBAAkB,UAAsC;CACrE,MAAM,QAAQ,SAAS,MAAM;CAC7B,MAAM,cAAc,MAAM,QAAQ,IAAI,cAAc,KAAK;CAEzD,IAAI,YAAY,SAAS,kBAAkB,KAAK,YAAY,SAAS,OAAO,GAC1E,IAAI;EACF,OAAO,MAAM,MAAM,KAAK;CAC1B,QAAQ;EACN;CACF;CAGF,IAAI;EAEF,OAAO,MADY,MAAM,KAAK,KACf,KAAA;CACjB,QAAQ;EACN;CACF;AACF;AAEA,SAAS,kBAA+B,QAQlB;CACpB,MAAM,QAAQ,IAAI,MAAM,OAAO,OAAO;CAEtC,MAAM,OAAO;CACb,MAAM,mBAAmB;CACzB,MAAM,WAAW,OAAO;CACxB,MAAM,SAAS,OAAO;CACtB,MAAM,iBAAiB,OAAO;CAC9B,MAAM,eAAe,OAAO;CAC5B,MAAM,gBAAgB,OAAO;CAC7B,MAAM,QAAQ,OAAO;CAErB,OAAO;AACT;AAEA,eAAe,cACb,aACA,cACyB;CAGzB,OAAO;EACL,MAHW,iBAAiB,KAAA,IAAc,MAAM,kBAAkB,WAAW,IAAW;EAIxF,QAAQ,YAAY;EACpB,YAAY,YAAY;EACxB,SAAS,gBAAgB,YAAY,OAAO;EAC5C,KAAK;CACP;AACF;AAEA,eAAe,qBAAqB,OAAyC;CAC3E,IAAI,iBAAiB,KAAK,GACxB,OAAO;CAGT,IAAI,SAAS,OAAO,UAAU,YAAY,cAAc,SAAU,MAAiC,oBAAoB,UAAU;EAC/H,MAAM,WAAY,MAAiC;EACnD,MAAM,eAAe,MAAM,kBAAkB,QAAQ;EACrD,MAAM,iBAAiB,iBAAiB,YAAY,IAAI,eAAe,KAAA;EAEvE,OAAO,kBAAkB;GACvB,SACE,gBAAgB,UAChB,gBAAgB,SAChB,SAAS,cACT;GACF,UAAU,MAAM,cAAc,UAAU,YAAY;GACpD,QAAQ,oBAAoB,IAAI,QAAQ;GACxC;GACA,OAAO;EACT,CAAC;CACH;CAEA,OAAO,kBAAkB;EACvB,SAAS,iBAAiB,QAAQ,MAAM,UAAU;EAClD,OAAO;CACT,CAAC;AACH;AAEA,SAAS,sBAAsB,OAAyB;CACtD,IAAI,iBAAiB,KAAK,GACxB,OAAO;CAGT,IAAI,SAAS,OAAO,UAAU,YAAY,WAAW,OACnD,OAAO,iBAAkB,MAA8B,KAAK;CAG9D,OAAO;AACT;AAEA,eAAe,mBACb,SACA,aACA,QAC+B;CAC/B,MAAM,OAAO,UAAU,QAAQ,IAAI;CACnC,MAAM,OAAO,kBAAkB,IAAI;CAEnC,IAAI,QAAQ,SAAS,WAAW,OAAO,QAAQ,SAAS,WAAW,KACjE;CAGF,IAAI,CAAC,iBAAiB,QAAQ,QAAQ,GACpC;CAGF,MAAM,aAAa,KAAK,cAAc;CACtC,IAAI,cAAc,YAAY,YAC5B;CAGF,KAAK,aAAa,aAAa;CAE/B,MAAM,QAAQ,sBAAsB,KAAK,YAAY,YAAY,WAAW,YAAY,QAAQ;CAChG,QAAQ,OAAO,oBAAoB;EACjC,KAAK,QAAQ;EACb,SAAS,KAAK,UAAU,MAAA,CAAO,YAAY;EAC3C,SAAS,KAAK;EACd,YAAY,YAAY;EACxB;EACA,QAAQ,QAAQ,SAAS;CAC3B,CAAC;CAED,MAAM,IAAI,SAAS,YAAY,WAAW,SAAS,KAAK,CAAC;CAEzD,OAAO,QAAQ,MAAM,QAAQ,KAAK,IAAI;AACxC;AAEA,eAAe,gBACb,SACA,aACA,QAC+B;CAC/B,MAAM,OAAO,UAAU,QAAQ,IAAI;CACnC,MAAM,OAAO,kBAAkB,IAAI;CACnC,MAAM,aAAa,KAAK,cAAc;CAEtC,IAAI,CAAC,sBAAsB,QAAQ,KAAK,KAAK,cAAc,YAAY,YACrE;CAGF,KAAK,aAAa,aAAa;CAE/B,MAAM,QAAQ,sBAAsB,KAAK,YAAY,YAAY,WAAW,YAAY,QAAQ;CAChG,QAAQ,OAAO,wCAAwC;EACrD,KAAK,QAAQ;EACb,SAAS,KAAK,UAAU,MAAA,CAAO,YAAY;EAC3C,SAAS,KAAK;EACd,YAAY,YAAY;EACxB;CACF,CAAC;CAED,MAAM,IAAI,SAAS,YAAY,WAAW,SAAS,KAAK,CAAC;CAEzD,OAAO,QAAQ,MAAM,QAAQ,KAAK,IAAI;AACxC;AASA,SAAgB,sBACd,SACA,UAA6B,CAAC,GACX;CACnB,MAAM,EACJ,QACA,qBACA,cAAc,CAAC,GACf,eAAe,SACb;CAEJ,MAAM,wBAAwB;EAC5B,YAAY,YAAY,cAAc;EACtC,WAAW,YAAY,aAAa;EACpC,UAAU,YAAY,YAAY;CACpC;CAEA,OAAO,CACL;EACE,MAAM,IAAI,SAAS;GACjB,MAAM,OAAO,UAAU,QAAQ,IAAI;GACnC,MAAM,OAAO,kBAAkB,IAAI;GACnC,MAAM,UAAU,IAAI,QAAQ,KAAK,OAAO;GAExC,IAAI,cAAc;IAChB,MAAM,YAAY,QAAQ,IAAI,cAAc,KAAK,OAAO,WAAW;IACnE,QAAQ,IAAI,gBAAgB,SAAS;IACrC,KAAK,YAAY;GACnB;GAEA,KAAK,UAAU,gBAAgB,OAAO;GAEtC,QAAQ,QAAQ,yBAAyB;IACvC,SAAS,KAAK,UAAU,MAAA,CAAO,YAAY;IAC3C,KAAK,QAAQ;IACb,WAAW,KAAK;GAClB,CAAC;GAED,OAAO;IACL,KAAK,QAAQ;IACb;GACF;EACF;EAEA,MAAM,KAAK,SAAS;GAClB,MAAM,OAAO,UAAU,QAAQ,IAAI;GACnC,MAAM,OAAO,kBAAkB,IAAI;GAEnC,oBAAoB,IAAI,QAAQ,UAAU;IACxC,KAAK,QAAQ;IACb,SAAS,KAAK,UAAU,MAAA,CAAO,YAAY;IAC3C,SAAS,gBAAgB,KAAK,OAAO;GACvC,CAAC;GAED,IAAI,QAAQ,SAAS,WAAW,OAAO,uBAAuB,CAAC,KAAK,WAAW;IAC7E,KAAK,YAAY;IAEjB,QAAQ,OAAO,uDAAuD;KACpE,KAAK,QAAQ;KACb,SAAS,KAAK,UAAU,MAAA,CAAO,YAAY;IAC7C,CAAC;IAED,MAAM,gBAAgB,MAAM,0BAC1B,yBAAyB,OAAO,SAC1B,oBAAoB,OAAO,GACjC,MACF;IAEA,IAAI,cAAc,WAAW,cAAc,gBAAgB;KACzD,MAAM,UAAU,IAAI,QAAQ,KAAK,OAAO;KACxC,QAAQ,IAAI,iBAAiB,UAAU,cAAc,gBAAgB;KACrE,KAAK,UAAU,gBAAgB,OAAO;KAEtC,QAAQ,OAAO,qDAAqD;KAEpE,OAAO,QAAQ,MAAM,QAAQ,KAAK,IAAI;IACxC;IAEA,IAAI,cAAc,cAChB,MAAM,kBAAkB;KACtB,SAAS;KACT,UAAU,MAAM,cAAc,QAAQ,QAAQ;KAC9C,QAAQ,oBAAoB,IAAI,QAAQ,QAAQ;KAChD,cAAc;KACd,eAAe;KACf,OAAO;IACT,CAAC;GAEL;GAEA,MAAM,gBAAgB,MAAM,mBAAmB,SAAS,uBAAuB,MAAM;GACrF,IAAI,eACF,OAAO;GAGT,IAAI,QAAQ,SAAS,UAAU,KAAK;IAClC,MAAM,eAAe,MAAM,kBAAkB,QAAQ,QAAQ;IAC7D,MAAM,iBAAiB,iBAAiB,YAAY,IAAI,eAAe,KAAA;IAEvE,QAAQ,QAAQ,+BAA+B,KAAA,GAAW;KACxD,KAAK,QAAQ;KACb,SAAS,KAAK,UAAU,MAAA,CAAO,YAAY;KAC3C,QAAQ,QAAQ,SAAS;KACzB,MAAM,gBAAgB;KACtB,QAAQ,gBAAgB;KACxB,SAAS,gBAAgB;IAC3B,CAAC;GACH;GAEA,OAAO,QAAQ;EACjB;EAEA,MAAM,QAAQ,SAAS;GACrB,MAAM,gBAAgB,MAAM,gBAAgB,SAAS,uBAAuB,MAAM;GAClF,IAAI,eACF,OAAO;EAIX;CACF,CACF;AACF;AAMA,SAAS,qBAAqD,QAAiB;CAC7E,IAAK,OAAuD,+BAC1D;CAGF,MAAM,YAAY,OAAO,eAAe,MAAM;CAE9C,KAAK,MAAM,OAAO,OAAO,oBAAoB,SAAS,GAAG;EACvD,IAAI,CAAC,IAAI,SAAS,KAAK,GACrB;EAGF,MAAM,WAAW,UAAU;EAC3B,IAAI,OAAO,aAAa,YACtB;EAGF,OAAO,eAAe,QAAQ,KAAK;GACjC,cAAc;GACd,YAAY;GACZ,UAAU;GACV,OAAO,OAAO,GAAG,SAAoB;IACnC,MAAM,SAAS,MAAO,SAA+E,MAAM,QAAQ,IAAI;IACvH,iBAAiB,SAAS,CAAC,EAAE,IAAI,KAAK,MAAM;IAC5C,OAAO;GACT;EACF,CAAC;CACH;CAEA,OAAwD,gCAAgC;AAC1F;AAEA,SAAS,WAA2C,QAAiC;CACnF,qBAAqB,MAAM;CAE3B,MAAM,8BAAc,IAAI,IAA0B;CAElD,OAAO,IAAI,MAAM,QAAQ,EACvB,IAAI,QAAQ,MAAM,UAAU;EAC1B,MAAM,QAAQ,QAAQ,IAAI,QAAQ,MAAM,QAAQ;EAEhD,IAAI,OAAO,SAAS,YAAY,OAAO,UAAU,cAAc,KAAK,SAAS,KAAK,GAChF,OAAO,OAAO,UAAU,aAAa,MAAM,KAAK,MAAM,IAAI;EAG5D,IAAI,YAAY,IAAI,IAAI,GACtB,OAAO,YAAY,IAAI,IAAI;EAG7B,MAAM,UAAU,OAAO,GAAG,SACxB,iBAAiB,oBAAI,IAAI,IAAI,GAAG,YAAY;GAC1C,IAAI;IACF,MAAM,eAAe,MAAO,MAAwD,MAAM,QAAQ,IAAI;IACtG,MAAM,cAAc,iBAAiB,SAAS,CAAC,EAAE,IAAI,GAAG,KAAK,IAAI;IAEjE,IAAI,aACF,OAAO,cAAc,YAAY,KAAK,YAAY;IAGpD,OAAO;KACL,MAAM;KACN,QAAQ;KACR,YAAY;KACZ,SAAS,CAAC;IACZ;GACF,SAAS,OAAO;IACd,MAAM,MAAM,qBAAqB,KAAK;GACxC;EACF,CAAC;EAEH,YAAY,IAAI,MAAM,OAAO;EAC7B,OAAO;CACT,EACF,CAAC;AACH;AAEA,eAAsB,gBACpB,SACA,aACA,iBACA,oBACA,UAAkC,CAAC,GAC0B;CAC7D,MAAM,EACJ,eACA,aACA,UACA,eACA,aACA,GAAG,iBACD;CAEJ,MAAM,SAAS,MAAM,gBAAgB,SAAS;EAC5C;EACA;EACA;EACA;CACF,CAAC;CAaD,OAAO;EACL,QAAQ,WAAW,IAHF,YAAY,IATL,mBAAmB;GAC3C,UAAU,OAAO;GACjB,aAAa,OAAO;GACpB,SAAS,OAAO;GAChB,aAAa,eAAe,OAAO;GACnC,YAAY,sBAAsB,SAAS,YAAY;GACvD,UAAU,mBAAmB,OAAO,aAAa,OAAO;EAC1D,CAE2C,CAGjB,CAAC;EACzB,UAAU,OAAO;CACnB;AACF"}