@danceroutine/tango-core 0.1.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +82 -0
  3. package/dist/{TangoError-NPkVPfuH.js → TangoError-DdQVQNZU.js} +5 -1
  4. package/dist/TangoError-DdQVQNZU.js.map +1 -0
  5. package/dist/errors/AuthenticationError.d.ts +6 -1
  6. package/dist/errors/ConflictError.d.ts +6 -1
  7. package/dist/errors/NotFoundError.d.ts +6 -1
  8. package/dist/errors/PermissionDenied.d.ts +6 -1
  9. package/dist/errors/TangoError.d.ts +13 -1
  10. package/dist/errors/ValidationError.d.ts +5 -1
  11. package/dist/errors/factories/HttpErrorFactory.d.ts +20 -11
  12. package/dist/errors/factories/index.d.ts +1 -1
  13. package/dist/errors/index.d.ts +2 -2
  14. package/dist/errors/index.js +4 -4
  15. package/dist/{errors-CzSQXdgI.js → errors-_tWsmNyZ.js} +81 -34
  16. package/dist/errors-_tWsmNyZ.js.map +1 -0
  17. package/dist/http/TangoBody.d.ts +43 -18
  18. package/dist/http/TangoHeaders.d.ts +10 -5
  19. package/dist/http/TangoQueryParams.d.ts +69 -0
  20. package/dist/http/TangoRequest.d.ts +82 -0
  21. package/dist/http/TangoResponse.d.ts +184 -49
  22. package/dist/http/index.d.ts +2 -1
  23. package/dist/http/index.js +4 -4
  24. package/dist/{http-DOLwwAYt.js → http-D20MQa6p.js} +675 -295
  25. package/dist/http-D20MQa6p.js.map +1 -0
  26. package/dist/index.d.ts +9 -7
  27. package/dist/index.js +7 -6
  28. package/dist/logging/ConsoleLogger.d.ts +15 -0
  29. package/dist/logging/Logger.d.ts +13 -0
  30. package/dist/logging/getLogger.d.ts +23 -0
  31. package/dist/logging/index.d.ts +3 -0
  32. package/dist/logging/index.js +3 -0
  33. package/dist/logging-BWeD4HOO.js +48 -0
  34. package/dist/logging-BWeD4HOO.js.map +1 -0
  35. package/dist/runtime/binary/isArrayBuffer.d.ts +3 -0
  36. package/dist/runtime/binary/isBlob.d.ts +3 -0
  37. package/dist/runtime/binary/isUint8Array.d.ts +3 -0
  38. package/dist/runtime/date/isDate.d.ts +3 -0
  39. package/dist/runtime/error/isError.d.ts +3 -0
  40. package/dist/runtime/index.d.ts +1 -1
  41. package/dist/runtime/index.js +2 -2
  42. package/dist/runtime/object/index.d.ts +1 -0
  43. package/dist/runtime/object/isNil.d.ts +4 -0
  44. package/dist/runtime/object/isObject.d.ts +3 -0
  45. package/dist/runtime/web/isFile.d.ts +3 -0
  46. package/dist/runtime/web/isFormData.d.ts +3 -0
  47. package/dist/runtime/web/isReadableStream.d.ts +3 -0
  48. package/dist/runtime/web/isURLSearchParams.d.ts +3 -0
  49. package/dist/{runtime-DPpCYEe_.js → runtime-B8KkgD3R.js} +14 -4
  50. package/dist/runtime-B8KkgD3R.js.map +1 -0
  51. package/dist/sql/SqlDialect.d.ts +5 -0
  52. package/dist/sql/SqlIdentifierRole.d.ts +13 -0
  53. package/dist/sql/SqlSafetyEngine.d.ts +50 -0
  54. package/dist/sql/TrustedSqlFragment.d.ts +5 -0
  55. package/dist/sql/ValidatedSqlIdentifier.d.ts +7 -0
  56. package/dist/sql/index.d.ts +13 -0
  57. package/dist/sql/index.js +3 -0
  58. package/dist/sql/isTrustedSqlFragment.d.ts +5 -0
  59. package/dist/sql/quoteSqlIdentifier.d.ts +6 -0
  60. package/dist/sql/trustedSql.d.ts +5 -0
  61. package/dist/sql/validateSqlIdentifier.d.ts +6 -0
  62. package/dist/sql-D3frkfy-.js +116 -0
  63. package/dist/sql-D3frkfy-.js.map +1 -0
  64. package/package.json +65 -54
  65. package/dist/TangoError-NPkVPfuH.js.map +0 -1
  66. package/dist/errors/factories/HttpErrorFactory.js +0 -91
  67. package/dist/errors-CzSQXdgI.js.map +0 -1
  68. package/dist/http/TangoHeaders.js +0 -396
  69. package/dist/http/TangoResponse.js +0 -556
  70. package/dist/http-DOLwwAYt.js.map +0 -1
  71. package/dist/result/Err.d.ts +0 -21
  72. package/dist/result/Ok.d.ts +0 -21
  73. package/dist/result/Result.d.ts +0 -33
  74. package/dist/result/index.d.ts +0 -8
  75. package/dist/result/index.js +0 -3
  76. package/dist/result-CBqw9Hlg.js +0 -82
  77. package/dist/result-CBqw9Hlg.js.map +0 -1
  78. package/dist/runtime-DPpCYEe_.js.map +0 -1
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Pedro Del Moral Lopez
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,82 @@
1
+ # @danceroutine/tango-core
2
+
3
+ `@danceroutine/tango-core` contains Tango's low-level HTTP, error, logging, and runtime primitives.
4
+
5
+ This package exists so that the rest of Tango can rely on one shared vocabulary for common server-side concerns. It is also useful outside Tango when you want fetch-compatible request and response helpers, application error types that map cleanly to HTTP, logger wiring, and runtime guards for common boundary checks. Keeping those concerns in one package makes the higher-level packages easier to understand because they do not each need their own local version of the same foundational ideas.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ pnpm add @danceroutine/tango-core
11
+ ```
12
+
13
+ ## What lives here
14
+
15
+ The package groups together four kinds of primitives:
16
+
17
+ - HTTP types such as `TangoRequest`, `TangoResponse`, `TangoHeaders`, `TangoBody`, and `TangoQueryParams`
18
+ - application error types such as `ValidationError`, `NotFoundError`, `PermissionDenied`, `AuthenticationError`, and `ConflictError`
19
+ - logger utilities such as `ConsoleLogger`, `getLogger`, and `setLoggerFactory`
20
+ - runtime guards for common server-side values
21
+
22
+ These are the pieces other Tango packages build on when they need to describe a request, return a response, raise a domain error, narrow an unknown runtime value, or normalize query input.
23
+
24
+ ## Quick start
25
+
26
+ ```ts
27
+ import { NotFoundError, TangoResponse, HttpErrorFactory } from '@danceroutine/tango-core';
28
+
29
+ export async function getPost(id: string): Promise<Response> {
30
+ const post = null;
31
+
32
+ if (!post) {
33
+ const error = HttpErrorFactory.toHttpError(new NotFoundError(`Post ${id} not found`));
34
+ return TangoResponse.problem(error.body, { status: error.status });
35
+ }
36
+
37
+ return TangoResponse.json({ id, title: 'Hello' });
38
+ }
39
+ ```
40
+
41
+ The error type expresses application intent, the HTTP mapping stays consistent, and the response helper keeps the endpoint code direct.
42
+
43
+ ## Import style
44
+
45
+ Most projects will use curated root imports:
46
+
47
+ ```ts
48
+ import { TangoResponse, ValidationError, getLogger } from '@danceroutine/tango-core';
49
+ ```
50
+
51
+ If you are used to Django-style domain drill-down imports, the package also exposes namespace imports and subpaths that keep related primitives grouped together:
52
+
53
+ ```ts
54
+ import '@danceroutine/tango-core/errors';
55
+ import '@danceroutine/tango-core/http';
56
+ import '@danceroutine/tango-core/logging';
57
+ import '@danceroutine/tango-core/runtime';
58
+ ```
59
+
60
+ Available subpaths include `http`, `errors`, `logging`, and `runtime`.
61
+
62
+ ## Documentation
63
+
64
+ - Official documentation: <https://tangowebframework.dev>
65
+ - Architecture topic: <https://tangowebframework.dev/topics/architecture>
66
+ - Resources API reference: <https://tangowebframework.dev/reference/resources-api>
67
+
68
+ ## Development
69
+
70
+ ```bash
71
+ pnpm --filter @danceroutine/tango-core build
72
+ pnpm --filter @danceroutine/tango-core typecheck
73
+ pnpm --filter @danceroutine/tango-core test
74
+ ```
75
+
76
+ For the wider contributor workflow, use:
77
+
78
+ - <https://tangowebframework.dev/contributing>
79
+
80
+ ## License
81
+
82
+ MIT
@@ -2,12 +2,15 @@
2
2
  //#region src/errors/TangoError.ts
3
3
  var TangoError = class extends Error {
4
4
  __tangoErrorBrand = "tango.error";
5
+ /** Runtime guard for Tango-branded errors. */
5
6
  static isTangoError(err) {
6
7
  return !!err && err.__tangoErrorBrand === "tango.error";
7
8
  }
9
+ /** Runtime guard for plain problem-details objects. */
8
10
  static isProblemDetails(err) {
9
11
  return !!err && typeof err === "object" && err !== null && "code" in err && typeof err.code === "string" && "message" in err && typeof err.message === "string";
10
12
  }
13
+ /** Convert this error to wire-level envelope format. */
11
14
  toErrorEnvelope() {
12
15
  return { error: {
13
16
  code: this.getErrorName(),
@@ -15,6 +18,7 @@ var TangoError = class extends Error {
15
18
  details: this.getDetails()
16
19
  } };
17
20
  }
21
+ /** Convert this error to legacy `HttpError` shape. */
18
22
  toHttpError() {
19
23
  return {
20
24
  status: this.status,
@@ -28,4 +32,4 @@ var TangoError = class extends Error {
28
32
 
29
33
  //#endregion
30
34
  export { TangoError };
31
- //# sourceMappingURL=TangoError-NPkVPfuH.js.map
35
+ //# sourceMappingURL=TangoError-DdQVQNZU.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TangoError-DdQVQNZU.js","names":["err: unknown"],"sources":["../src/errors/TangoError.ts"],"sourcesContent":["import type { HttpError } from './HttpError';\n\n/** Structured error detail payload for API responses. */\nexport type ErrorDetails = Record<string, string[]> | null | undefined;\n\n/** Canonical error payload shape used by Tango HTTP error responses. */\nexport type ProblemDetails<TDetails extends ErrorDetails = null> = {\n code: string;\n message: string;\n details?: TDetails;\n fields?: Record<string, string[]>;\n};\n\n/** Envelope shape for serialized error responses. */\nexport type ErrorEnvelope<TDetails extends ErrorDetails = null> = {\n error: ProblemDetails<TDetails>;\n};\n\n/**\n * Base branded framework error.\n *\n * Subclasses provide HTTP status, stable code, and structured details.\n */\nexport abstract class TangoError extends Error {\n // String brand avoids instanceof and survives cross-package boundaries.\n readonly __tangoErrorBrand = 'tango.error' as const;\n abstract status: number;\n\n protected abstract getDetails(): ErrorDetails;\n\n protected abstract getErrorName(): string;\n\n /** Runtime guard for Tango-branded errors. */\n static isTangoError(err: unknown): err is TangoError {\n return !!err && (err as { __tangoErrorBrand?: string }).__tangoErrorBrand === 'tango.error';\n }\n\n /** Runtime guard for plain problem-details objects. */\n static isProblemDetails(err: unknown): err is ProblemDetails {\n return (\n !!err &&\n typeof err === 'object' &&\n err !== null &&\n 'code' in err &&\n typeof (err as { code: unknown }).code === 'string' &&\n 'message' in err &&\n typeof (err as { message: unknown }).message === 'string'\n );\n }\n\n /** Convert this error to wire-level envelope format. */\n toErrorEnvelope(): ErrorEnvelope<ErrorDetails> {\n return {\n error: {\n code: this.getErrorName(),\n message: this.message,\n details: this.getDetails(),\n },\n };\n }\n\n /** Convert this error to legacy `HttpError` shape. */\n toHttpError(): HttpError {\n return {\n status: this.status,\n body: {\n error: this.message,\n details: this.getDetails(),\n },\n };\n }\n}\n"],"mappings":";;IAuBsB,aAAf,cAAkC,MAAM;CAE3C,oBAA6B;;CAQ7B,OAAO,aAAaA,KAAiC;AACjD,WAAS,OAAQ,IAAuC,sBAAsB;CACjF;;CAGD,OAAO,iBAAiBA,KAAqC;AACzD,WACM,cACK,QAAQ,YACf,QAAQ,QACR,UAAU,cACF,IAA0B,SAAS,YAC3C,aAAa,cACL,IAA6B,YAAY;CAExD;;CAGD,kBAA+C;AAC3C,SAAO,EACH,OAAO;GACH,MAAM,KAAK,cAAc;GACzB,SAAS,KAAK;GACd,SAAS,KAAK,YAAY;EAC7B,EACJ;CACJ;;CAGD,cAAyB;AACrB,SAAO;GACH,QAAQ,KAAK;GACb,MAAM;IACF,OAAO,KAAK;IACZ,SAAS,KAAK,YAAY;GAC7B;EACJ;CACJ;AACJ"}
@@ -1,10 +1,15 @@
1
1
  import { TangoError, type ErrorDetails } from './TangoError';
2
+ /** Error for missing/invalid authentication (HTTP 401). */
2
3
  export declare class AuthenticationError extends TangoError {
3
4
  static readonly BRAND: "tango.error.authentication";
4
5
  readonly __tangoBrand: typeof AuthenticationError.BRAND;
5
6
  status: number;
6
- static isAuthenticationError(value: unknown): value is AuthenticationError;
7
+ /** Create an authentication error with optional custom message. */
7
8
  constructor(message?: string);
9
+ /**
10
+ * Narrow an unknown value to `AuthenticationError`.
11
+ */
12
+ static isAuthenticationError(value: unknown): value is AuthenticationError;
8
13
  protected getErrorName(): string;
9
14
  protected getDetails(): ErrorDetails;
10
15
  }
@@ -1,10 +1,15 @@
1
1
  import { TangoError, type ErrorDetails } from './TangoError';
2
+ /** Error for conflicting resource state (HTTP 409). */
2
3
  export declare class ConflictError extends TangoError {
3
4
  static readonly BRAND: "tango.error.conflict";
4
5
  readonly __tangoBrand: typeof ConflictError.BRAND;
5
6
  status: number;
6
- static isConflictError(value: unknown): value is ConflictError;
7
+ /** Create a conflict error with optional custom message. */
7
8
  constructor(message?: string);
9
+ /**
10
+ * Narrow an unknown value to `ConflictError`.
11
+ */
12
+ static isConflictError(value: unknown): value is ConflictError;
8
13
  protected getErrorName(): string;
9
14
  protected getDetails(): ErrorDetails;
10
15
  }
@@ -1,10 +1,15 @@
1
1
  import { TangoError, type ErrorDetails } from './TangoError';
2
+ /** Error for missing resources (HTTP 404). */
2
3
  export declare class NotFoundError extends TangoError {
3
4
  static readonly BRAND: "tango.error.not_found";
4
5
  readonly __tangoBrand: typeof NotFoundError.BRAND;
5
6
  status: number;
6
- static isNotFoundError(value: unknown): value is NotFoundError;
7
+ /** Create a not-found error with optional custom message. */
7
8
  constructor(message?: string);
9
+ /**
10
+ * Narrow an unknown value to `NotFoundError`.
11
+ */
12
+ static isNotFoundError(value: unknown): value is NotFoundError;
8
13
  protected getErrorName(): string;
9
14
  protected getDetails(): ErrorDetails;
10
15
  }
@@ -1,10 +1,15 @@
1
1
  import { TangoError, type ErrorDetails } from './TangoError';
2
+ /** Error for authorization failures (HTTP 403). */
2
3
  export declare class PermissionDenied extends TangoError {
3
4
  static readonly BRAND: "tango.error.permission_denied";
4
5
  readonly __tangoBrand: typeof PermissionDenied.BRAND;
5
6
  status: number;
6
- static isPermissionDenied(value: unknown): value is PermissionDenied;
7
+ /** Create a permission-denied error with optional custom message. */
7
8
  constructor(message?: string);
9
+ /**
10
+ * Narrow an unknown value to `PermissionDenied`.
11
+ */
12
+ static isPermissionDenied(value: unknown): value is PermissionDenied;
8
13
  protected getErrorName(): string;
9
14
  protected getDetails(): ErrorDetails;
10
15
  }
@@ -1,21 +1,33 @@
1
1
  import type { HttpError } from './HttpError';
2
+ /** Structured error detail payload for API responses. */
2
3
  export type ErrorDetails = Record<string, string[]> | null | undefined;
4
+ /** Canonical error payload shape used by Tango HTTP error responses. */
3
5
  export type ProblemDetails<TDetails extends ErrorDetails = null> = {
4
6
  code: string;
5
7
  message: string;
6
8
  details?: TDetails;
7
9
  fields?: Record<string, string[]>;
8
10
  };
11
+ /** Envelope shape for serialized error responses. */
9
12
  export type ErrorEnvelope<TDetails extends ErrorDetails = null> = {
10
13
  error: ProblemDetails<TDetails>;
11
14
  };
15
+ /**
16
+ * Base branded framework error.
17
+ *
18
+ * Subclasses provide HTTP status, stable code, and structured details.
19
+ */
12
20
  export declare abstract class TangoError extends Error {
13
- readonly __tangoErrorBrand: 'tango.error';
21
+ readonly __tangoErrorBrand: "tango.error";
14
22
  abstract status: number;
15
23
  protected abstract getDetails(): ErrorDetails;
16
24
  protected abstract getErrorName(): string;
25
+ /** Runtime guard for Tango-branded errors. */
17
26
  static isTangoError(err: unknown): err is TangoError;
27
+ /** Runtime guard for plain problem-details objects. */
18
28
  static isProblemDetails(err: unknown): err is ProblemDetails;
29
+ /** Convert this error to wire-level envelope format. */
19
30
  toErrorEnvelope(): ErrorEnvelope<ErrorDetails>;
31
+ /** Convert this error to legacy `HttpError` shape. */
20
32
  toHttpError(): HttpError;
21
33
  }
@@ -1,9 +1,13 @@
1
1
  import { TangoError, type ErrorDetails } from './TangoError';
2
+ /** Error for request validation failures (HTTP 400). */
2
3
  export declare class ValidationError extends TangoError {
3
4
  details?: ErrorDetails;
4
- readonly __tangoValidationErrorBrand: 'tango.error.validation';
5
+ readonly __tangoValidationErrorBrand: "tango.error.validation";
5
6
  status: number;
6
7
  constructor(message: string, details?: ErrorDetails);
8
+ /**
9
+ * Narrow an unknown value to `ValidationError`, including common legacy shapes.
10
+ */
7
11
  static isValidationError(err: unknown): err is ValidationError;
8
12
  protected getErrorName(): string;
9
13
  protected getDetails(): ErrorDetails;
@@ -25,6 +25,9 @@ export interface HttpErrorFactoryConfig {
25
25
  * status: 400,
26
26
  * body: { error: 'Validation failed', details: err.flatten().fieldErrors },
27
27
  * }));
28
+ *
29
+ * // Quick one-shot conversion with dev defaults
30
+ * const httpError = HttpErrorFactory.toHttpError(new NotFoundError('missing'));
28
31
  * ```
29
32
  */
30
33
  export declare class HttpErrorFactory {
@@ -33,18 +36,24 @@ export declare class HttpErrorFactory {
33
36
  private handlers;
34
37
  private exposeErrors;
35
38
  constructor(config?: HttpErrorFactoryConfig);
39
+ /**
40
+ * Narrow an unknown value to `HttpErrorFactory`.
41
+ */
36
42
  static isHttpErrorFactory(value: unknown): value is HttpErrorFactory;
37
- registerHandler<T extends Error>(errorClass: new (...args: unknown[]) => T, handler: (error: T) => HttpError): this;
43
+ /**
44
+ * Convert an unknown error into an `HttpError` using dev-friendly defaults.
45
+ * Shorthand for `new HttpErrorFactory().create(error)`.
46
+ */
47
+ static toHttpError(error: unknown): HttpError;
48
+ private static isZodLikeValidationError;
49
+ private static zodLikeErrorDetails;
50
+ /**
51
+ * Register a custom mapper for an application or third-party error type.
52
+ */
53
+ registerHandler<T extends Error>(errorClass: new (...args: any[]) => T, handler: (error: T) => HttpError): this;
54
+ /**
55
+ * Convert an unknown error into the normalized HTTP error shape Tango uses.
56
+ */
38
57
  create(error: unknown): HttpError;
39
58
  private isErrorClassInstance;
40
59
  }
41
- /**
42
- * Default factory instance with dev-friendly defaults (exposes error messages).
43
- * Use this directly or create a custom HttpErrorFactory for production.
44
- */
45
- export declare const defaultHttpErrorFactory: HttpErrorFactory;
46
- /**
47
- * Convenience function that converts unknown errors to an HttpError
48
- * using the default factory instance.
49
- */
50
- export declare function toHttpError(error: unknown): HttpError;
@@ -1,4 +1,4 @@
1
1
  /**
2
2
  * Domain boundary barrel: centralizes this subdomain's public contract.
3
3
  */
4
- export { HttpErrorFactory, defaultHttpErrorFactory, toHttpError, type HttpErrorFactoryConfig, } from './HttpErrorFactory';
4
+ export { HttpErrorFactory, type HttpErrorFactoryConfig } from './HttpErrorFactory';
@@ -9,6 +9,6 @@ import { ValidationError } from './ValidationError';
9
9
  import { NotFoundError } from './NotFoundError';
10
10
  import { PermissionDenied } from './PermissionDenied';
11
11
  import { AuthenticationError } from './AuthenticationError';
12
- import { HttpErrorFactory, defaultHttpErrorFactory, toHttpError, type HttpErrorFactoryConfig } from './factories/HttpErrorFactory';
13
- export { AuthenticationError, ConflictError, HttpErrorFactory, NotFoundError, PermissionDenied, TangoError, ValidationError, factories, defaultHttpErrorFactory, toHttpError, };
12
+ import { HttpErrorFactory, type HttpErrorFactoryConfig } from './factories/HttpErrorFactory';
13
+ export { AuthenticationError, ConflictError, HttpErrorFactory, NotFoundError, PermissionDenied, TangoError, ValidationError, factories, };
14
14
  export type { ErrorDetails, ErrorEnvelope, HttpError, HttpErrorFactoryConfig, ProblemDetails };
@@ -1,5 +1,5 @@
1
- import { TangoError } from "../TangoError-NPkVPfuH.js";
2
- import "../runtime-DPpCYEe_.js";
3
- import { AuthenticationError, ConflictError, HttpErrorFactory, NotFoundError, PermissionDenied, ValidationError, defaultHttpErrorFactory, factories_exports, toHttpError } from "../errors-CzSQXdgI.js";
1
+ import { TangoError } from "../TangoError-DdQVQNZU.js";
2
+ import "../runtime-B8KkgD3R.js";
3
+ import { AuthenticationError, ConflictError, HttpErrorFactory, NotFoundError, PermissionDenied, ValidationError, factories_exports } from "../errors-_tWsmNyZ.js";
4
4
 
5
- export { AuthenticationError, ConflictError, HttpErrorFactory, NotFoundError, PermissionDenied, TangoError, ValidationError, defaultHttpErrorFactory, factories_exports as factories, toHttpError };
5
+ export { AuthenticationError, ConflictError, HttpErrorFactory, NotFoundError, PermissionDenied, TangoError, ValidationError, factories_exports as factories };
@@ -1,6 +1,6 @@
1
1
  import { __export } from "./chunk-BkvOhyD0.js";
2
- import { TangoError } from "./TangoError-NPkVPfuH.js";
3
- import { isError, isObject } from "./runtime-DPpCYEe_.js";
2
+ import { TangoError } from "./TangoError-DdQVQNZU.js";
3
+ import { isError, isObject } from "./runtime-B8KkgD3R.js";
4
4
 
5
5
  //#region src/errors/factories/HttpErrorFactory.ts
6
6
  var HttpErrorFactory = class HttpErrorFactory {
@@ -11,15 +11,52 @@ var HttpErrorFactory = class HttpErrorFactory {
11
11
  constructor(config = {}) {
12
12
  this.exposeErrors = config.exposeErrors ?? true;
13
13
  }
14
+ /**
15
+ * Narrow an unknown value to `HttpErrorFactory`.
16
+ */
14
17
  static isHttpErrorFactory(value) {
15
18
  return typeof value === "object" && value !== null && value.__tangoBrand === HttpErrorFactory.BRAND;
16
19
  }
20
+ /**
21
+ * Convert an unknown error into an `HttpError` using dev-friendly defaults.
22
+ * Shorthand for `new HttpErrorFactory().create(error)`.
23
+ */
24
+ static toHttpError(error) {
25
+ return new HttpErrorFactory().create(error);
26
+ }
27
+ static isZodLikeValidationError(error) {
28
+ return isError(error) && isObject(error) && Array.isArray(error.issues) && error.name === "ZodError";
29
+ }
30
+ static zodLikeErrorDetails(error) {
31
+ const details = {};
32
+ for (const issue of error.issues) {
33
+ const key = Array.isArray(issue.path) && issue.path.length > 0 ? String(issue.path.join(".")) : "_schema";
34
+ const message = typeof issue.message === "string" ? issue.message : "Invalid value";
35
+ const existing = details[key];
36
+ if (existing) existing.push(message);
37
+ else details[key] = [message];
38
+ }
39
+ return details;
40
+ }
41
+ /**
42
+ * Register a custom mapper for an application or third-party error type.
43
+ */
17
44
  registerHandler(errorClass, handler) {
18
45
  this.handlers.set(errorClass, handler);
19
46
  return this;
20
47
  }
48
+ /**
49
+ * Convert an unknown error into the normalized HTTP error shape Tango uses.
50
+ */
21
51
  create(error) {
22
52
  if (TangoError.isTangoError(error)) return error.toHttpError();
53
+ if (HttpErrorFactory.isZodLikeValidationError(error)) return {
54
+ status: 400,
55
+ body: {
56
+ error: error.message || "Validation failed",
57
+ details: HttpErrorFactory.zodLikeErrorDetails(error)
58
+ }
59
+ };
23
60
  for (const [ErrorClass, handler] of this.handlers) if (this.isErrorClassInstance(error, ErrorClass)) return handler(error);
24
61
  if (isError(error)) return {
25
62
  status: 500,
@@ -37,28 +74,21 @@ var HttpErrorFactory = class HttpErrorFactory {
37
74
  };
38
75
  }
39
76
  isErrorClassInstance(error, ErrorClass) {
40
- if (!isObject(error)) return false;
41
- let proto = Object.getPrototypeOf(error);
42
- while (proto) {
43
- if (proto === ErrorClass.prototype) return true;
44
- proto = Object.getPrototypeOf(proto);
45
- }
77
+ if (!isError(error)) return false;
78
+ const expectedBrand = ErrorClass.BRAND;
79
+ if (typeof expectedBrand === "string" && isObject(error) && error.__tangoBrand === expectedBrand) return true;
80
+ const constructorName = error.constructor?.name;
81
+ if (typeof constructorName === "string" && constructorName === ErrorClass.name) return true;
82
+ const errorName = error.name;
83
+ if (typeof errorName === "string" && errorName === ErrorClass.name) return true;
46
84
  return false;
47
85
  }
48
86
  };
49
- const defaultHttpErrorFactory = new HttpErrorFactory();
50
- function toHttpError(error) {
51
- return defaultHttpErrorFactory.create(error);
52
- }
53
87
 
54
88
  //#endregion
55
89
  //#region src/errors/factories/index.ts
56
90
  var factories_exports = {};
57
- __export(factories_exports, {
58
- HttpErrorFactory: () => HttpErrorFactory,
59
- defaultHttpErrorFactory: () => defaultHttpErrorFactory,
60
- toHttpError: () => toHttpError
61
- });
91
+ __export(factories_exports, { HttpErrorFactory: () => HttpErrorFactory });
62
92
 
63
93
  //#endregion
64
94
  //#region src/errors/ConflictError.ts
@@ -66,14 +96,18 @@ var ConflictError = class ConflictError extends TangoError {
66
96
  static BRAND = "tango.error.conflict";
67
97
  __tangoBrand = ConflictError.BRAND;
68
98
  status = 409;
69
- static isConflictError(value) {
70
- return typeof value === "object" && value !== null && value.__tangoBrand === ConflictError.BRAND;
71
- }
99
+ /** Create a conflict error with optional custom message. */
72
100
  constructor(message = "Resource conflict") {
73
101
  super(message);
74
102
  this.name = "ConflictError";
75
103
  Object.setPrototypeOf(this, ConflictError.prototype);
76
104
  }
105
+ /**
106
+ * Narrow an unknown value to `ConflictError`.
107
+ */
108
+ static isConflictError(value) {
109
+ return typeof value === "object" && value !== null && value.__tangoBrand === ConflictError.BRAND;
110
+ }
77
111
  getErrorName() {
78
112
  return "conflict";
79
113
  }
@@ -93,6 +127,9 @@ var ValidationError = class ValidationError extends TangoError {
93
127
  this.name = "ValidationError";
94
128
  Object.setPrototypeOf(this, ValidationError.prototype);
95
129
  }
130
+ /**
131
+ * Narrow an unknown value to `ValidationError`, including common legacy shapes.
132
+ */
96
133
  static isValidationError(err) {
97
134
  return !!err && typeof err === "object" && err.__tangoValidationErrorBrand === "tango.error.validation" || typeof err === "object" && err !== null && "fields" in err && typeof err.fields === "object";
98
135
  }
@@ -110,14 +147,18 @@ var NotFoundError = class NotFoundError extends TangoError {
110
147
  static BRAND = "tango.error.not_found";
111
148
  __tangoBrand = NotFoundError.BRAND;
112
149
  status = 404;
113
- static isNotFoundError(value) {
114
- return typeof value === "object" && value !== null && value.__tangoBrand === NotFoundError.BRAND;
115
- }
150
+ /** Create a not-found error with optional custom message. */
116
151
  constructor(message = "Resource not found") {
117
152
  super(message);
118
153
  this.name = "NotFoundError";
119
154
  Object.setPrototypeOf(this, NotFoundError.prototype);
120
155
  }
156
+ /**
157
+ * Narrow an unknown value to `NotFoundError`.
158
+ */
159
+ static isNotFoundError(value) {
160
+ return typeof value === "object" && value !== null && value.__tangoBrand === NotFoundError.BRAND;
161
+ }
121
162
  getErrorName() {
122
163
  return "not_found";
123
164
  }
@@ -132,14 +173,18 @@ var PermissionDenied = class PermissionDenied extends TangoError {
132
173
  static BRAND = "tango.error.permission_denied";
133
174
  __tangoBrand = PermissionDenied.BRAND;
134
175
  status = 403;
135
- static isPermissionDenied(value) {
136
- return typeof value === "object" && value !== null && value.__tangoBrand === PermissionDenied.BRAND;
137
- }
176
+ /** Create a permission-denied error with optional custom message. */
138
177
  constructor(message = "Permission denied") {
139
178
  super(message);
140
179
  this.name = "PermissionDenied";
141
180
  Object.setPrototypeOf(this, PermissionDenied.prototype);
142
181
  }
182
+ /**
183
+ * Narrow an unknown value to `PermissionDenied`.
184
+ */
185
+ static isPermissionDenied(value) {
186
+ return typeof value === "object" && value !== null && value.__tangoBrand === PermissionDenied.BRAND;
187
+ }
143
188
  getErrorName() {
144
189
  return "permission_denied";
145
190
  }
@@ -154,14 +199,18 @@ var AuthenticationError = class AuthenticationError extends TangoError {
154
199
  static BRAND = "tango.error.authentication";
155
200
  __tangoBrand = AuthenticationError.BRAND;
156
201
  status = 401;
157
- static isAuthenticationError(value) {
158
- return typeof value === "object" && value !== null && value.__tangoBrand === AuthenticationError.BRAND;
159
- }
202
+ /** Create an authentication error with optional custom message. */
160
203
  constructor(message = "Authentication required") {
161
204
  super(message);
162
205
  this.name = "AuthenticationError";
163
206
  Object.setPrototypeOf(this, AuthenticationError.prototype);
164
207
  }
208
+ /**
209
+ * Narrow an unknown value to `AuthenticationError`.
210
+ */
211
+ static isAuthenticationError(value) {
212
+ return typeof value === "object" && value !== null && value.__tangoBrand === AuthenticationError.BRAND;
213
+ }
165
214
  getErrorName() {
166
215
  return "authentication_error";
167
216
  }
@@ -181,11 +230,9 @@ __export(errors_exports, {
181
230
  PermissionDenied: () => PermissionDenied,
182
231
  TangoError: () => TangoError,
183
232
  ValidationError: () => ValidationError,
184
- defaultHttpErrorFactory: () => defaultHttpErrorFactory,
185
- factories: () => factories_exports,
186
- toHttpError: () => toHttpError
233
+ factories: () => factories_exports
187
234
  });
188
235
 
189
236
  //#endregion
190
- export { AuthenticationError, ConflictError, HttpErrorFactory, NotFoundError, PermissionDenied, ValidationError, defaultHttpErrorFactory, errors_exports, factories_exports, toHttpError };
191
- //# sourceMappingURL=errors-CzSQXdgI.js.map
237
+ export { AuthenticationError, ConflictError, HttpErrorFactory, NotFoundError, PermissionDenied, ValidationError, errors_exports, factories_exports };
238
+ //# sourceMappingURL=errors-_tWsmNyZ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors-_tWsmNyZ.js","names":["config: HttpErrorFactoryConfig","value: unknown","error: unknown","error: ZodLikeError","details: Record<string, string[]>","errorClass: new (...args: any[]) => T","handler: (error: T) => HttpError","ErrorClass: new (...args: any[]) => Error","message: string","value: unknown","message: string","details?: ErrorDetails","err: unknown","message: string","value: unknown","message: string","value: unknown","message: string","value: unknown"],"sources":["../src/errors/factories/HttpErrorFactory.ts","../src/errors/factories/index.ts","../src/errors/ConflictError.ts","../src/errors/ValidationError.ts","../src/errors/NotFoundError.ts","../src/errors/PermissionDenied.ts","../src/errors/AuthenticationError.ts","../src/errors/index.ts"],"sourcesContent":["import { TangoError } from '../TangoError';\nimport type { HttpError } from '../HttpError';\nimport { isError, isObject } from '../../runtime/index';\n\nexport interface HttpErrorFactoryConfig {\n /**\n * When true, raw error messages are included in HTTP responses.\n * When false, generic messages are returned for non-TangoError exceptions.\n * Defaults to true (dev-friendly). Set to false in production.\n */\n exposeErrors?: boolean;\n}\n\ntype ZodLikeIssue = {\n path?: unknown[];\n message?: unknown;\n};\n\ntype ZodLikeError = Error & {\n issues: ZodLikeIssue[];\n};\n\n/**\n * Converts errors into structured HTTP error responses.\n * Supports TangoError subclasses out of the box, and custom error handlers\n * can be registered for third-party or application-specific error types.\n *\n * @example\n * ```typescript\n * // Development (default) — exposes real error messages\n * const devFactory = new HttpErrorFactory();\n *\n * // Production — hides internal error details\n * const prodFactory = new HttpErrorFactory({ exposeErrors: false });\n *\n * // Register a custom handler for a third-party error\n * prodFactory.registerHandler(ZodError, (err) => ({\n * status: 400,\n * body: { error: 'Validation failed', details: err.flatten().fieldErrors },\n * }));\n *\n * // Quick one-shot conversion with dev defaults\n * const httpError = HttpErrorFactory.toHttpError(new NotFoundError('missing'));\n * ```\n */\nexport class HttpErrorFactory {\n static readonly BRAND = 'tango.error_factory.http' as const;\n readonly __tangoBrand: typeof HttpErrorFactory.BRAND = HttpErrorFactory.BRAND;\n\n // oxlint-disable-next-line typescript/no-explicit-any\n private handlers = new Map<new (...args: any[]) => Error, (error: Error) => HttpError>();\n private exposeErrors: boolean;\n\n constructor(config: HttpErrorFactoryConfig = {}) {\n this.exposeErrors = config.exposeErrors ?? true;\n }\n\n /**\n * Narrow an unknown value to `HttpErrorFactory`.\n */\n static isHttpErrorFactory(value: unknown): value is HttpErrorFactory {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as { __tangoBrand?: unknown }).__tangoBrand === HttpErrorFactory.BRAND\n );\n }\n\n /**\n * Convert an unknown error into an `HttpError` using dev-friendly defaults.\n * Shorthand for `new HttpErrorFactory().create(error)`.\n */\n static toHttpError(error: unknown): HttpError {\n return new HttpErrorFactory().create(error);\n }\n\n private static isZodLikeValidationError(error: unknown): error is ZodLikeError {\n return (\n isError(error) &&\n isObject(error) &&\n Array.isArray((error as { issues?: unknown }).issues) &&\n (error as { name?: unknown }).name === 'ZodError'\n );\n }\n\n private static zodLikeErrorDetails(error: ZodLikeError): Record<string, string[]> {\n const details: Record<string, string[]> = {};\n\n for (const issue of error.issues) {\n const key = Array.isArray(issue.path) && issue.path.length > 0 ? String(issue.path.join('.')) : '_schema';\n const message = typeof issue.message === 'string' ? issue.message : 'Invalid value';\n\n const existing = details[key];\n if (existing) {\n existing.push(message);\n } else {\n details[key] = [message];\n }\n }\n\n return details;\n }\n\n /**\n * Register a custom mapper for an application or third-party error type.\n */\n\n // oxlint-disable-next-line typescript/no-explicit-any\n registerHandler<T extends Error>(errorClass: new (...args: any[]) => T, handler: (error: T) => HttpError): this {\n this.handlers.set(errorClass, handler as (error: Error) => HttpError);\n return this;\n }\n\n /**\n * Convert an unknown error into the normalized HTTP error shape Tango uses.\n */\n create(error: unknown): HttpError {\n if (TangoError.isTangoError(error)) {\n return error.toHttpError();\n }\n\n if (HttpErrorFactory.isZodLikeValidationError(error)) {\n return {\n status: 400,\n body: {\n error: error.message || 'Validation failed',\n details: HttpErrorFactory.zodLikeErrorDetails(error),\n },\n };\n }\n\n for (const [ErrorClass, handler] of this.handlers) {\n if (this.isErrorClassInstance(error, ErrorClass)) {\n return handler(error);\n }\n }\n\n if (isError(error)) {\n return {\n status: 500,\n body: {\n error: this.exposeErrors ? error.message : 'Internal Server Error',\n details: null,\n },\n };\n }\n\n return {\n status: 500,\n body: {\n error: 'Unknown error occurred',\n details: null,\n },\n };\n }\n\n // oxlint-disable-next-line typescript/no-explicit-any\n private isErrorClassInstance(error: unknown, ErrorClass: new (...args: any[]) => Error): error is Error {\n if (!isError(error)) {\n return false;\n }\n\n const expectedBrand = (ErrorClass as { BRAND?: unknown }).BRAND;\n if (\n typeof expectedBrand === 'string' &&\n isObject(error) &&\n (error as { __tangoBrand?: unknown }).__tangoBrand === expectedBrand\n ) {\n return true;\n }\n\n const constructorName = (error as { constructor?: { name?: unknown } }).constructor?.name;\n if (typeof constructorName === 'string' && constructorName === ErrorClass.name) {\n return true;\n }\n\n const errorName = (error as { name?: unknown }).name;\n if (typeof errorName === 'string' && errorName === ErrorClass.name) {\n return true;\n }\n\n return false;\n }\n}\n","/**\n * Domain boundary barrel: centralizes this subdomain's public contract.\n */\n\nexport { HttpErrorFactory, type HttpErrorFactoryConfig } from './HttpErrorFactory';\n","import { TangoError, type ErrorDetails } from './TangoError';\n\n/** Error for conflicting resource state (HTTP 409). */\nexport class ConflictError extends TangoError {\n static readonly BRAND = 'tango.error.conflict' as const;\n readonly __tangoBrand: typeof ConflictError.BRAND = ConflictError.BRAND;\n status = 409;\n\n /** Create a conflict error with optional custom message. */\n constructor(message: string = 'Resource conflict') {\n super(message);\n this.name = 'ConflictError';\n Object.setPrototypeOf(this, ConflictError.prototype);\n }\n\n /**\n * Narrow an unknown value to `ConflictError`.\n */\n static isConflictError(value: unknown): value is ConflictError {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as { __tangoBrand?: unknown }).__tangoBrand === ConflictError.BRAND\n );\n }\n\n protected override getErrorName(): string {\n return 'conflict';\n }\n\n protected override getDetails(): ErrorDetails {\n return undefined;\n }\n}\n","import { TangoError, type ErrorDetails } from './TangoError';\n\n/** Error for request validation failures (HTTP 400). */\nexport class ValidationError extends TangoError {\n readonly __tangoValidationErrorBrand = 'tango.error.validation' as const;\n status = 400;\n\n constructor(\n message: string,\n public details?: ErrorDetails\n ) {\n super(message);\n this.name = 'ValidationError';\n Object.setPrototypeOf(this, ValidationError.prototype);\n }\n\n /**\n * Narrow an unknown value to `ValidationError`, including common legacy shapes.\n */\n static isValidationError(err: unknown): err is ValidationError {\n return (\n (!!err &&\n typeof err === 'object' &&\n (err as { __tangoValidationErrorBrand?: string }).__tangoValidationErrorBrand ===\n 'tango.error.validation') ||\n (typeof err === 'object' &&\n err !== null &&\n 'fields' in err &&\n typeof (err as { fields: unknown }).fields === 'object')\n );\n }\n\n protected override getErrorName(): string {\n return 'ValidationError';\n }\n\n protected override getDetails(): ErrorDetails {\n return this.details;\n }\n}\n","import { TangoError, type ErrorDetails } from './TangoError';\n\n/** Error for missing resources (HTTP 404). */\nexport class NotFoundError extends TangoError {\n static readonly BRAND = 'tango.error.not_found' as const;\n readonly __tangoBrand: typeof NotFoundError.BRAND = NotFoundError.BRAND;\n status = 404;\n\n /** Create a not-found error with optional custom message. */\n constructor(message: string = 'Resource not found') {\n super(message);\n this.name = 'NotFoundError';\n Object.setPrototypeOf(this, NotFoundError.prototype);\n }\n\n /**\n * Narrow an unknown value to `NotFoundError`.\n */\n static isNotFoundError(value: unknown): value is NotFoundError {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as { __tangoBrand?: unknown }).__tangoBrand === NotFoundError.BRAND\n );\n }\n\n protected override getErrorName(): string {\n return 'not_found';\n }\n\n protected override getDetails(): ErrorDetails {\n return undefined;\n }\n}\n","import { TangoError, type ErrorDetails } from './TangoError';\n\n/** Error for authorization failures (HTTP 403). */\nexport class PermissionDenied extends TangoError {\n static readonly BRAND = 'tango.error.permission_denied' as const;\n readonly __tangoBrand: typeof PermissionDenied.BRAND = PermissionDenied.BRAND;\n status = 403;\n\n /** Create a permission-denied error with optional custom message. */\n constructor(message: string = 'Permission denied') {\n super(message);\n this.name = 'PermissionDenied';\n Object.setPrototypeOf(this, PermissionDenied.prototype);\n }\n\n /**\n * Narrow an unknown value to `PermissionDenied`.\n */\n static isPermissionDenied(value: unknown): value is PermissionDenied {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as { __tangoBrand?: unknown }).__tangoBrand === PermissionDenied.BRAND\n );\n }\n\n protected override getErrorName(): string {\n return 'permission_denied';\n }\n\n protected override getDetails(): ErrorDetails {\n return undefined;\n }\n}\n","import { TangoError, type ErrorDetails } from './TangoError';\n\n/** Error for missing/invalid authentication (HTTP 401). */\nexport class AuthenticationError extends TangoError {\n static readonly BRAND = 'tango.error.authentication' as const;\n readonly __tangoBrand: typeof AuthenticationError.BRAND = AuthenticationError.BRAND;\n status = 401;\n\n /** Create an authentication error with optional custom message. */\n constructor(message: string = 'Authentication required') {\n super(message);\n this.name = 'AuthenticationError';\n Object.setPrototypeOf(this, AuthenticationError.prototype);\n }\n\n /**\n * Narrow an unknown value to `AuthenticationError`.\n */\n static isAuthenticationError(value: unknown): value is AuthenticationError {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as { __tangoBrand?: unknown }).__tangoBrand === AuthenticationError.BRAND\n );\n }\n\n protected override getErrorName(): string {\n return 'authentication_error';\n }\n\n protected override getDetails(): ErrorDetails {\n return undefined;\n }\n}\n","/**\n * Domain boundary barrel: centralizes this subdomain's public contract.\n */\n\nimport type { HttpError } from './HttpError';\nimport * as factories from './factories/index';\nimport { TangoError, type ErrorDetails, type ErrorEnvelope, type ProblemDetails } from './TangoError';\nimport { ConflictError } from './ConflictError';\nimport { ValidationError } from './ValidationError';\nimport { NotFoundError } from './NotFoundError';\nimport { PermissionDenied } from './PermissionDenied';\nimport { AuthenticationError } from './AuthenticationError';\nimport { HttpErrorFactory, type HttpErrorFactoryConfig } from './factories/HttpErrorFactory';\n\nexport {\n AuthenticationError,\n ConflictError,\n HttpErrorFactory,\n NotFoundError,\n PermissionDenied,\n TangoError,\n ValidationError,\n factories,\n};\n\nexport type { ErrorDetails, ErrorEnvelope, HttpError, HttpErrorFactoryConfig, ProblemDetails };\n"],"mappings":";;;;;IA6Ca,mBAAN,MAAM,iBAAiB;CAC1B,OAAgB,QAAQ;CACxB,eAAuD,iBAAiB;CAGxE,WAAmB,IAAI;CACvB;CAEA,YAAYA,SAAiC,CAAE,GAAE;AAC7C,OAAK,eAAe,OAAO,gBAAgB;CAC9C;;;;CAKD,OAAO,mBAAmBC,OAA2C;AACjE,gBACW,UAAU,YACjB,UAAU,QACT,MAAqC,iBAAiB,iBAAiB;CAE/E;;;;;CAMD,OAAO,YAAYC,OAA2B;AAC1C,SAAO,IAAI,mBAAmB,OAAO,MAAM;CAC9C;CAED,OAAe,yBAAyBA,OAAuC;AAC3E,SACI,QAAQ,MAAM,IACd,SAAS,MAAM,IACf,MAAM,QAAS,MAA+B,OAAO,IACpD,MAA6B,SAAS;CAE9C;CAED,OAAe,oBAAoBC,OAA+C;EAC9E,MAAMC,UAAoC,CAAE;AAE5C,OAAK,MAAM,SAAS,MAAM,QAAQ;GAC9B,MAAM,MAAM,MAAM,QAAQ,MAAM,KAAK,IAAI,MAAM,KAAK,SAAS,IAAI,OAAO,MAAM,KAAK,KAAK,IAAI,CAAC,GAAG;GAChG,MAAM,iBAAiB,MAAM,YAAY,WAAW,MAAM,UAAU;GAEpE,MAAM,WAAW,QAAQ;AACzB,OAAI,SACA,UAAS,KAAK,QAAQ;IAEtB,SAAQ,OAAO,CAAC,OAAQ;EAE/B;AAED,SAAO;CACV;;;;CAOD,gBAAiCC,YAAuCC,SAAwC;AAC5G,OAAK,SAAS,IAAI,YAAY,QAAuC;AACrE,SAAO;CACV;;;;CAKD,OAAOJ,OAA2B;AAC9B,MAAI,WAAW,aAAa,MAAM,CAC9B,QAAO,MAAM,aAAa;AAG9B,MAAI,iBAAiB,yBAAyB,MAAM,CAChD,QAAO;GACH,QAAQ;GACR,MAAM;IACF,OAAO,MAAM,WAAW;IACxB,SAAS,iBAAiB,oBAAoB,MAAM;GACvD;EACJ;AAGL,OAAK,MAAM,CAAC,YAAY,QAAQ,IAAI,KAAK,SACrC,KAAI,KAAK,qBAAqB,OAAO,WAAW,CAC5C,QAAO,QAAQ,MAAM;AAI7B,MAAI,QAAQ,MAAM,CACd,QAAO;GACH,QAAQ;GACR,MAAM;IACF,OAAO,KAAK,eAAe,MAAM,UAAU;IAC3C,SAAS;GACZ;EACJ;AAGL,SAAO;GACH,QAAQ;GACR,MAAM;IACF,OAAO;IACP,SAAS;GACZ;EACJ;CACJ;CAGD,qBAA6BA,OAAgBK,YAA2D;AACpG,OAAK,QAAQ,MAAM,CACf,QAAO;EAGX,MAAM,gBAAiB,WAAmC;AAC1D,aACW,kBAAkB,YACzB,SAAS,MAAM,IACd,MAAqC,iBAAiB,cAEvD,QAAO;EAGX,MAAM,kBAAmB,MAA+C,aAAa;AACrF,aAAW,oBAAoB,YAAY,oBAAoB,WAAW,KACtE,QAAO;EAGX,MAAM,YAAa,MAA6B;AAChD,aAAW,cAAc,YAAY,cAAc,WAAW,KAC1D,QAAO;AAGX,SAAO;CACV;AACJ;;;;;;;;;ICpLY,gBAAN,MAAM,sBAAsB,WAAW;CAC1C,OAAgB,QAAQ;CACxB,eAAoD,cAAc;CAClE,SAAS;;CAGT,YAAYC,UAAkB,qBAAqB;AAC/C,QAAM,QAAQ;AACd,OAAK,OAAO;AACZ,SAAO,eAAe,MAAM,cAAc,UAAU;CACvD;;;;CAKD,OAAO,gBAAgBC,OAAwC;AAC3D,gBACW,UAAU,YACjB,UAAU,QACT,MAAqC,iBAAiB,cAAc;CAE5E;CAED,eAA0C;AACtC,SAAO;CACV;CAED,aAA8C;AAC1C,SAAO;CACV;AACJ;;;;IC9BY,kBAAN,MAAM,wBAAwB,WAAW;CAC5C,8BAAuC;CACvC,SAAS;CAET,YACIC,SACOC,SACT;AACE,QAAM,QAAQ;AAAA,OAFP,UAAA;AAGP,OAAK,OAAO;AACZ,SAAO,eAAe,MAAM,gBAAgB,UAAU;CACzD;;;;CAKD,OAAO,kBAAkBC,KAAsC;AAC3D,WACO,cACQ,QAAQ,YACd,IAAiD,gCAC9C,mCACA,QAAQ,YACZ,QAAQ,QACR,YAAY,cACJ,IAA4B,WAAW;CAE1D;CAED,eAA0C;AACtC,SAAO;CACV;CAED,aAA8C;AAC1C,SAAO,KAAK;CACf;AACJ;;;;ICpCY,gBAAN,MAAM,sBAAsB,WAAW;CAC1C,OAAgB,QAAQ;CACxB,eAAoD,cAAc;CAClE,SAAS;;CAGT,YAAYC,UAAkB,sBAAsB;AAChD,QAAM,QAAQ;AACd,OAAK,OAAO;AACZ,SAAO,eAAe,MAAM,cAAc,UAAU;CACvD;;;;CAKD,OAAO,gBAAgBC,OAAwC;AAC3D,gBACW,UAAU,YACjB,UAAU,QACT,MAAqC,iBAAiB,cAAc;CAE5E;CAED,eAA0C;AACtC,SAAO;CACV;CAED,aAA8C;AAC1C,SAAO;CACV;AACJ;;;;IC9BY,mBAAN,MAAM,yBAAyB,WAAW;CAC7C,OAAgB,QAAQ;CACxB,eAAuD,iBAAiB;CACxE,SAAS;;CAGT,YAAYC,UAAkB,qBAAqB;AAC/C,QAAM,QAAQ;AACd,OAAK,OAAO;AACZ,SAAO,eAAe,MAAM,iBAAiB,UAAU;CAC1D;;;;CAKD,OAAO,mBAAmBC,OAA2C;AACjE,gBACW,UAAU,YACjB,UAAU,QACT,MAAqC,iBAAiB,iBAAiB;CAE/E;CAED,eAA0C;AACtC,SAAO;CACV;CAED,aAA8C;AAC1C,SAAO;CACV;AACJ;;;;IC9BY,sBAAN,MAAM,4BAA4B,WAAW;CAChD,OAAgB,QAAQ;CACxB,eAA0D,oBAAoB;CAC9E,SAAS;;CAGT,YAAYC,UAAkB,2BAA2B;AACrD,QAAM,QAAQ;AACd,OAAK,OAAO;AACZ,SAAO,eAAe,MAAM,oBAAoB,UAAU;CAC7D;;;;CAKD,OAAO,sBAAsBC,OAA8C;AACvE,gBACW,UAAU,YACjB,UAAU,QACT,MAAqC,iBAAiB,oBAAoB;CAElF;CAED,eAA0C;AACtC,SAAO;CACV;CAED,aAA8C;AAC1C,SAAO;CACV;AACJ"}