@shipfox/api-integration-gitea 2.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 (119) hide show
  1. package/.turbo/turbo-build.log +2 -0
  2. package/.turbo/turbo-type$colon$emit.log +1 -0
  3. package/.turbo/turbo-type.log +1 -0
  4. package/CHANGELOG.md +96 -0
  5. package/LICENSE +21 -0
  6. package/README.md +61 -0
  7. package/dist/api/client.d.ts +58 -0
  8. package/dist/api/client.d.ts.map +1 -0
  9. package/dist/api/client.js +225 -0
  10. package/dist/api/client.js.map +1 -0
  11. package/dist/config.d.ts +11 -0
  12. package/dist/config.d.ts.map +1 -0
  13. package/dist/config.js +38 -0
  14. package/dist/config.js.map +1 -0
  15. package/dist/core/connect.d.ts +18 -0
  16. package/dist/core/connect.d.ts.map +1 -0
  17. package/dist/core/connect.js +32 -0
  18. package/dist/core/connect.js.map +1 -0
  19. package/dist/core/connection-url.d.ts +2 -0
  20. package/dist/core/connection-url.d.ts.map +1 -0
  21. package/dist/core/connection-url.js +8 -0
  22. package/dist/core/connection-url.js.map +1 -0
  23. package/dist/core/errors.d.ts +10 -0
  24. package/dist/core/errors.d.ts.map +1 -0
  25. package/dist/core/errors.js +17 -0
  26. package/dist/core/errors.js.map +1 -0
  27. package/dist/core/source-control.d.ts +14 -0
  28. package/dist/core/source-control.d.ts.map +1 -0
  29. package/dist/core/source-control.js +177 -0
  30. package/dist/core/source-control.js.map +1 -0
  31. package/dist/core/webhook.d.ts +38 -0
  32. package/dist/core/webhook.d.ts.map +1 -0
  33. package/dist/core/webhook.js +162 -0
  34. package/dist/core/webhook.js.map +1 -0
  35. package/dist/db/connections.d.ts +19 -0
  36. package/dist/db/connections.d.ts.map +1 -0
  37. package/dist/db/connections.js +42 -0
  38. package/dist/db/connections.js.map +1 -0
  39. package/dist/db/db.d.ts +191 -0
  40. package/dist/db/db.d.ts.map +1 -0
  41. package/dist/db/db.js +18 -0
  42. package/dist/db/db.js.map +1 -0
  43. package/dist/db/migrations.d.ts +2 -0
  44. package/dist/db/migrations.d.ts.map +1 -0
  45. package/dist/db/migrations.js +5 -0
  46. package/dist/db/migrations.js.map +1 -0
  47. package/dist/db/schema/common.d.ts +2 -0
  48. package/dist/db/schema/common.d.ts.map +1 -0
  49. package/dist/db/schema/common.js +4 -0
  50. package/dist/db/schema/common.js.map +1 -0
  51. package/dist/db/schema/connections.d.ts +97 -0
  52. package/dist/db/schema/connections.d.ts.map +1 -0
  53. package/dist/db/schema/connections.js +28 -0
  54. package/dist/db/schema/connections.js.map +1 -0
  55. package/dist/index.d.ts +39 -0
  56. package/dist/index.d.ts.map +1 -0
  57. package/dist/index.js +42 -0
  58. package/dist/index.js.map +1 -0
  59. package/dist/presentation/dto/integrations.d.ts +17 -0
  60. package/dist/presentation/dto/integrations.d.ts.map +1 -0
  61. package/dist/presentation/dto/integrations.js +11 -0
  62. package/dist/presentation/dto/integrations.js.map +1 -0
  63. package/dist/presentation/routes/connections.d.ts +13 -0
  64. package/dist/presentation/routes/connections.d.ts.map +1 -0
  65. package/dist/presentation/routes/connections.js +47 -0
  66. package/dist/presentation/routes/connections.js.map +1 -0
  67. package/dist/presentation/routes/errors.d.ts +2 -0
  68. package/dist/presentation/routes/errors.d.ts.map +1 -0
  69. package/dist/presentation/routes/errors.js +36 -0
  70. package/dist/presentation/routes/errors.js.map +1 -0
  71. package/dist/presentation/routes/webhooks.d.ts +11 -0
  72. package/dist/presentation/routes/webhooks.d.ts.map +1 -0
  73. package/dist/presentation/routes/webhooks.js +109 -0
  74. package/dist/presentation/routes/webhooks.js.map +1 -0
  75. package/dist/tsconfig.test.tsbuildinfo +1 -0
  76. package/drizzle/0000_initial.sql +10 -0
  77. package/drizzle/meta/0000_snapshot.json +96 -0
  78. package/drizzle/meta/_journal.json +13 -0
  79. package/drizzle.config.ts +7 -0
  80. package/package.json +66 -0
  81. package/src/api/client.test.ts +367 -0
  82. package/src/api/client.ts +364 -0
  83. package/src/config.ts +42 -0
  84. package/src/connection-external-url.test.ts +36 -0
  85. package/src/core/connect.test.ts +149 -0
  86. package/src/core/connect.ts +52 -0
  87. package/src/core/connection-url.ts +8 -0
  88. package/src/core/errors.ts +17 -0
  89. package/src/core/source-control-clone-url.test.ts +83 -0
  90. package/src/core/source-control.test.ts +349 -0
  91. package/src/core/source-control.ts +231 -0
  92. package/src/core/webhook.test.ts +396 -0
  93. package/src/core/webhook.ts +203 -0
  94. package/src/db/connections.test.ts +69 -0
  95. package/src/db/connections.ts +80 -0
  96. package/src/db/db.ts +18 -0
  97. package/src/db/migrations.ts +4 -0
  98. package/src/db/schema/common.ts +3 -0
  99. package/src/db/schema/connections.ts +32 -0
  100. package/src/index.test.ts +23 -0
  101. package/src/index.ts +83 -0
  102. package/src/presentation/dto/integrations.ts +14 -0
  103. package/src/presentation/routes/connections.test.ts +200 -0
  104. package/src/presentation/routes/connections.ts +63 -0
  105. package/src/presentation/routes/errors.ts +35 -0
  106. package/src/presentation/routes/webhooks.test.ts +188 -0
  107. package/src/presentation/routes/webhooks.ts +111 -0
  108. package/test/env.ts +11 -0
  109. package/test/factories/gitea-connection.ts +19 -0
  110. package/test/factories/index.ts +1 -0
  111. package/test/fixtures/gitea-webhook.ts +237 -0
  112. package/test/globalSetup.ts +14 -0
  113. package/test/index.ts +6 -0
  114. package/test/setup.ts +17 -0
  115. package/tsconfig.build.json +9 -0
  116. package/tsconfig.build.tsbuildinfo +1 -0
  117. package/tsconfig.json +3 -0
  118. package/tsconfig.test.json +9 -0
  119. package/vitest.config.ts +12 -0
@@ -0,0 +1,36 @@
1
+ import { ConnectionSlugConflictError } from '@shipfox/api-integration-core-dto';
2
+ import { ClientError } from '@shipfox/node-fastify';
3
+ import { GiteaIntegrationProviderError, GiteaOrgAlreadyLinkedError, GiteaOrganizationNotFoundError } from '#core/errors.js';
4
+ function providerStatus(reason) {
5
+ if (reason === 'rate-limited') return 429;
6
+ if (reason === 'timeout' || reason === 'provider-unavailable') return 503;
7
+ return 422;
8
+ }
9
+ export function giteaRouteErrorHandler(error) {
10
+ if (error instanceof GiteaOrganizationNotFoundError) {
11
+ throw new ClientError(error.message, 'gitea-organization-not-found', {
12
+ status: 404
13
+ });
14
+ }
15
+ if (error instanceof GiteaOrgAlreadyLinkedError) {
16
+ throw new ClientError(error.message, 'gitea-org-already-linked', {
17
+ status: 409
18
+ });
19
+ }
20
+ if (error instanceof ConnectionSlugConflictError) {
21
+ throw new ClientError(error.message, 'slug-conflict', {
22
+ status: 409
23
+ });
24
+ }
25
+ if (error instanceof GiteaIntegrationProviderError) {
26
+ throw new ClientError(error.message, error.reason, {
27
+ details: {
28
+ retry_after_seconds: error.retryAfterSeconds
29
+ },
30
+ status: providerStatus(error.reason)
31
+ });
32
+ }
33
+ throw error;
34
+ }
35
+
36
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/presentation/routes/errors.ts"],"sourcesContent":["import {\n ConnectionSlugConflictError,\n type IntegrationProviderErrorReason,\n} from '@shipfox/api-integration-core-dto';\nimport {ClientError} from '@shipfox/node-fastify';\nimport {\n GiteaIntegrationProviderError,\n GiteaOrgAlreadyLinkedError,\n GiteaOrganizationNotFoundError,\n} from '#core/errors.js';\n\nfunction providerStatus(reason: IntegrationProviderErrorReason): number {\n if (reason === 'rate-limited') return 429;\n if (reason === 'timeout' || reason === 'provider-unavailable') return 503;\n return 422;\n}\n\nexport function giteaRouteErrorHandler(error: unknown): never {\n if (error instanceof GiteaOrganizationNotFoundError) {\n throw new ClientError(error.message, 'gitea-organization-not-found', {status: 404});\n }\n if (error instanceof GiteaOrgAlreadyLinkedError) {\n throw new ClientError(error.message, 'gitea-org-already-linked', {status: 409});\n }\n if (error instanceof ConnectionSlugConflictError) {\n throw new ClientError(error.message, 'slug-conflict', {status: 409});\n }\n if (error instanceof GiteaIntegrationProviderError) {\n throw new ClientError(error.message, error.reason, {\n details: {retry_after_seconds: error.retryAfterSeconds},\n status: providerStatus(error.reason),\n });\n }\n throw error;\n}\n"],"names":["ConnectionSlugConflictError","ClientError","GiteaIntegrationProviderError","GiteaOrgAlreadyLinkedError","GiteaOrganizationNotFoundError","providerStatus","reason","giteaRouteErrorHandler","error","message","status","details","retry_after_seconds","retryAfterSeconds"],"mappings":"AAAA,SACEA,2BAA2B,QAEtB,oCAAoC;AAC3C,SAAQC,WAAW,QAAO,wBAAwB;AAClD,SACEC,6BAA6B,EAC7BC,0BAA0B,EAC1BC,8BAA8B,QACzB,kBAAkB;AAEzB,SAASC,eAAeC,MAAsC;IAC5D,IAAIA,WAAW,gBAAgB,OAAO;IACtC,IAAIA,WAAW,aAAaA,WAAW,wBAAwB,OAAO;IACtE,OAAO;AACT;AAEA,OAAO,SAASC,uBAAuBC,KAAc;IACnD,IAAIA,iBAAiBJ,gCAAgC;QACnD,MAAM,IAAIH,YAAYO,MAAMC,OAAO,EAAE,gCAAgC;YAACC,QAAQ;QAAG;IACnF;IACA,IAAIF,iBAAiBL,4BAA4B;QAC/C,MAAM,IAAIF,YAAYO,MAAMC,OAAO,EAAE,4BAA4B;YAACC,QAAQ;QAAG;IAC/E;IACA,IAAIF,iBAAiBR,6BAA6B;QAChD,MAAM,IAAIC,YAAYO,MAAMC,OAAO,EAAE,iBAAiB;YAACC,QAAQ;QAAG;IACpE;IACA,IAAIF,iBAAiBN,+BAA+B;QAClD,MAAM,IAAID,YAAYO,MAAMC,OAAO,EAAED,MAAMF,MAAM,EAAE;YACjDK,SAAS;gBAACC,qBAAqBJ,MAAMK,iBAAiB;YAAA;YACtDH,QAAQL,eAAeG,MAAMF,MAAM;QACrC;IACF;IACA,MAAME;AACR"}
@@ -0,0 +1,11 @@
1
+ import type { GetIntegrationConnectionByIdFn, PublishSourcePushFn, RecordDeliveryOnlyFn } from '@shipfox/api-integration-core-dto';
2
+ import { type RouteGroup } from '@shipfox/node-fastify';
3
+ import type { NodePgDatabase } from 'drizzle-orm/node-postgres';
4
+ export interface CreateGiteaWebhookRoutesOptions {
5
+ coreDb: () => NodePgDatabase<Record<string, unknown>>;
6
+ publishSourcePush: PublishSourcePushFn;
7
+ recordDeliveryOnly: RecordDeliveryOnlyFn;
8
+ getIntegrationConnectionById: GetIntegrationConnectionByIdFn;
9
+ }
10
+ export declare function createGiteaWebhookRoutes(options: CreateGiteaWebhookRoutesOptions): RouteGroup;
11
+ //# sourceMappingURL=webhooks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhooks.d.ts","sourceRoot":"","sources":["../../../src/presentation/routes/webhooks.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,8BAA8B,EAC9B,mBAAmB,EACnB,oBAAoB,EACrB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAEL,KAAK,UAAU,EAIhB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,2BAA2B,CAAC;AAY9D,MAAM,WAAW,+BAA+B;IAC9C,MAAM,EAAE,MAAM,cAAc,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACtD,iBAAiB,EAAE,mBAAmB,CAAC;IACvC,kBAAkB,EAAE,oBAAoB,CAAC;IACzC,4BAA4B,EAAE,8BAA8B,CAAC;CAC9D;AAED,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,+BAA+B,GAAG,UAAU,CA6E7F"}
@@ -0,0 +1,109 @@
1
+ import { Buffer } from 'node:buffer';
2
+ import { defineRoute, rawBodyPlugin, verifyHexHmacSignature, WEBHOOK_BODY_LIMIT } from '@shipfox/node-fastify';
3
+ import { logger } from '@shipfox/node-opentelemetry';
4
+ import { config } from '#config.js';
5
+ import { GiteaWebhookMalformedJsonError, GiteaWebhookMalformedPushPayloadError, handleGiteaWebhook } from '#core/webhook.js';
6
+ const SIGNATURE_HEADER = 'x-gitea-signature';
7
+ const EVENT_HEADER = 'x-gitea-event';
8
+ const DELIVERY_HEADER = 'x-gitea-delivery';
9
+ export function createGiteaWebhookRoutes(options) {
10
+ const pushRoute = defineRoute({
11
+ method: 'POST',
12
+ path: '/',
13
+ auth: [],
14
+ description: 'Gitea org webhook receiver.',
15
+ options: {
16
+ bodyLimit: WEBHOOK_BODY_LIMIT
17
+ },
18
+ handler: async (request, reply)=>{
19
+ const deliveryId = request.headers[DELIVERY_HEADER];
20
+ const signature = request.headers[SIGNATURE_HEADER];
21
+ const event = request.headers[EVENT_HEADER];
22
+ if (typeof deliveryId !== 'string' || !deliveryId) {
23
+ reply.code(400);
24
+ return {
25
+ error: 'missing X-Gitea-Delivery header'
26
+ };
27
+ }
28
+ if (typeof signature !== 'string' || !signature) {
29
+ reply.code(401);
30
+ return {
31
+ error: 'missing X-Gitea-Signature header'
32
+ };
33
+ }
34
+ if (typeof event !== 'string' || !event) {
35
+ reply.code(400);
36
+ return {
37
+ error: 'missing X-Gitea-Event header'
38
+ };
39
+ }
40
+ const body = request.body;
41
+ if (!Buffer.isBuffer(body)) {
42
+ reply.code(400);
43
+ return {
44
+ error: 'expected raw JSON body'
45
+ };
46
+ }
47
+ const rawBody = body.toString('utf8');
48
+ if (!verifyHexHmacSignature({
49
+ rawBody,
50
+ signature,
51
+ secret: config.GITEA_WEBHOOK_SECRET
52
+ })) {
53
+ reply.code(401);
54
+ return {
55
+ error: 'invalid signature'
56
+ };
57
+ }
58
+ try {
59
+ await options.coreDb().transaction(async (tx)=>{
60
+ await handleGiteaWebhook({
61
+ tx,
62
+ deliveryId,
63
+ event,
64
+ rawBody,
65
+ publishSourcePush: options.publishSourcePush,
66
+ recordDeliveryOnly: options.recordDeliveryOnly,
67
+ getIntegrationConnectionById: options.getIntegrationConnectionById
68
+ });
69
+ });
70
+ } catch (error) {
71
+ if (error instanceof GiteaWebhookMalformedJsonError) {
72
+ logger().warn({
73
+ deliveryId,
74
+ err: error
75
+ }, 'gitea webhook payload JSON parse failed');
76
+ reply.code(400);
77
+ return {
78
+ error: 'malformed JSON'
79
+ };
80
+ }
81
+ if (error instanceof GiteaWebhookMalformedPushPayloadError) {
82
+ logger().warn({
83
+ deliveryId,
84
+ issues: error.issues
85
+ }, 'gitea webhook push payload failed schema validation');
86
+ reply.code(400);
87
+ return {
88
+ error: 'malformed push payload'
89
+ };
90
+ }
91
+ throw error;
92
+ }
93
+ reply.code(204);
94
+ return null;
95
+ }
96
+ });
97
+ return {
98
+ prefix: '/webhooks/integrations/gitea',
99
+ auth: [],
100
+ plugins: [
101
+ rawBodyPlugin
102
+ ],
103
+ routes: [
104
+ pushRoute
105
+ ]
106
+ };
107
+ }
108
+
109
+ //# sourceMappingURL=webhooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/presentation/routes/webhooks.ts"],"sourcesContent":["import {Buffer} from 'node:buffer';\nimport type {\n GetIntegrationConnectionByIdFn,\n PublishSourcePushFn,\n RecordDeliveryOnlyFn,\n} from '@shipfox/api-integration-core-dto';\nimport {\n defineRoute,\n type RouteGroup,\n rawBodyPlugin,\n verifyHexHmacSignature,\n WEBHOOK_BODY_LIMIT,\n} from '@shipfox/node-fastify';\nimport {logger} from '@shipfox/node-opentelemetry';\nimport type {NodePgDatabase} from 'drizzle-orm/node-postgres';\nimport {config} from '#config.js';\nimport {\n GiteaWebhookMalformedJsonError,\n GiteaWebhookMalformedPushPayloadError,\n handleGiteaWebhook,\n} from '#core/webhook.js';\n\nconst SIGNATURE_HEADER = 'x-gitea-signature';\nconst EVENT_HEADER = 'x-gitea-event';\nconst DELIVERY_HEADER = 'x-gitea-delivery';\n\nexport interface CreateGiteaWebhookRoutesOptions {\n coreDb: () => NodePgDatabase<Record<string, unknown>>;\n publishSourcePush: PublishSourcePushFn;\n recordDeliveryOnly: RecordDeliveryOnlyFn;\n getIntegrationConnectionById: GetIntegrationConnectionByIdFn;\n}\n\nexport function createGiteaWebhookRoutes(options: CreateGiteaWebhookRoutesOptions): RouteGroup {\n const pushRoute = defineRoute({\n method: 'POST',\n path: '/',\n auth: [],\n description: 'Gitea org webhook receiver.',\n options: {bodyLimit: WEBHOOK_BODY_LIMIT},\n handler: async (request, reply) => {\n const deliveryId = request.headers[DELIVERY_HEADER];\n const signature = request.headers[SIGNATURE_HEADER];\n const event = request.headers[EVENT_HEADER];\n\n if (typeof deliveryId !== 'string' || !deliveryId) {\n reply.code(400);\n return {error: 'missing X-Gitea-Delivery header'};\n }\n if (typeof signature !== 'string' || !signature) {\n reply.code(401);\n return {error: 'missing X-Gitea-Signature header'};\n }\n if (typeof event !== 'string' || !event) {\n reply.code(400);\n return {error: 'missing X-Gitea-Event header'};\n }\n\n const body = request.body;\n if (!Buffer.isBuffer(body)) {\n reply.code(400);\n return {error: 'expected raw JSON body'};\n }\n const rawBody = body.toString('utf8');\n\n if (!verifyHexHmacSignature({rawBody, signature, secret: config.GITEA_WEBHOOK_SECRET})) {\n reply.code(401);\n return {error: 'invalid signature'};\n }\n\n try {\n await options.coreDb().transaction(async (tx) => {\n await handleGiteaWebhook({\n tx,\n deliveryId,\n event,\n rawBody,\n publishSourcePush: options.publishSourcePush,\n recordDeliveryOnly: options.recordDeliveryOnly,\n getIntegrationConnectionById: options.getIntegrationConnectionById,\n });\n });\n } catch (error) {\n if (error instanceof GiteaWebhookMalformedJsonError) {\n logger().warn({deliveryId, err: error}, 'gitea webhook payload JSON parse failed');\n reply.code(400);\n return {error: 'malformed JSON'};\n }\n if (error instanceof GiteaWebhookMalformedPushPayloadError) {\n logger().warn(\n {deliveryId, issues: error.issues},\n 'gitea webhook push payload failed schema validation',\n );\n reply.code(400);\n return {error: 'malformed push payload'};\n }\n throw error;\n }\n\n reply.code(204);\n return null;\n },\n });\n\n return {\n prefix: '/webhooks/integrations/gitea',\n auth: [],\n plugins: [rawBodyPlugin],\n routes: [pushRoute],\n };\n}\n"],"names":["Buffer","defineRoute","rawBodyPlugin","verifyHexHmacSignature","WEBHOOK_BODY_LIMIT","logger","config","GiteaWebhookMalformedJsonError","GiteaWebhookMalformedPushPayloadError","handleGiteaWebhook","SIGNATURE_HEADER","EVENT_HEADER","DELIVERY_HEADER","createGiteaWebhookRoutes","options","pushRoute","method","path","auth","description","bodyLimit","handler","request","reply","deliveryId","headers","signature","event","code","error","body","isBuffer","rawBody","toString","secret","GITEA_WEBHOOK_SECRET","coreDb","transaction","tx","publishSourcePush","recordDeliveryOnly","getIntegrationConnectionById","warn","err","issues","prefix","plugins","routes"],"mappings":"AAAA,SAAQA,MAAM,QAAO,cAAc;AAMnC,SACEC,WAAW,EAEXC,aAAa,EACbC,sBAAsB,EACtBC,kBAAkB,QACb,wBAAwB;AAC/B,SAAQC,MAAM,QAAO,8BAA8B;AAEnD,SAAQC,MAAM,QAAO,aAAa;AAClC,SACEC,8BAA8B,EAC9BC,qCAAqC,EACrCC,kBAAkB,QACb,mBAAmB;AAE1B,MAAMC,mBAAmB;AACzB,MAAMC,eAAe;AACrB,MAAMC,kBAAkB;AASxB,OAAO,SAASC,yBAAyBC,OAAwC;IAC/E,MAAMC,YAAYd,YAAY;QAC5Be,QAAQ;QACRC,MAAM;QACNC,MAAM,EAAE;QACRC,aAAa;QACbL,SAAS;YAACM,WAAWhB;QAAkB;QACvCiB,SAAS,OAAOC,SAASC;YACvB,MAAMC,aAAaF,QAAQG,OAAO,CAACb,gBAAgB;YACnD,MAAMc,YAAYJ,QAAQG,OAAO,CAACf,iBAAiB;YACnD,MAAMiB,QAAQL,QAAQG,OAAO,CAACd,aAAa;YAE3C,IAAI,OAAOa,eAAe,YAAY,CAACA,YAAY;gBACjDD,MAAMK,IAAI,CAAC;gBACX,OAAO;oBAACC,OAAO;gBAAiC;YAClD;YACA,IAAI,OAAOH,cAAc,YAAY,CAACA,WAAW;gBAC/CH,MAAMK,IAAI,CAAC;gBACX,OAAO;oBAACC,OAAO;gBAAkC;YACnD;YACA,IAAI,OAAOF,UAAU,YAAY,CAACA,OAAO;gBACvCJ,MAAMK,IAAI,CAAC;gBACX,OAAO;oBAACC,OAAO;gBAA8B;YAC/C;YAEA,MAAMC,OAAOR,QAAQQ,IAAI;YACzB,IAAI,CAAC9B,OAAO+B,QAAQ,CAACD,OAAO;gBAC1BP,MAAMK,IAAI,CAAC;gBACX,OAAO;oBAACC,OAAO;gBAAwB;YACzC;YACA,MAAMG,UAAUF,KAAKG,QAAQ,CAAC;YAE9B,IAAI,CAAC9B,uBAAuB;gBAAC6B;gBAASN;gBAAWQ,QAAQ5B,OAAO6B,oBAAoB;YAAA,IAAI;gBACtFZ,MAAMK,IAAI,CAAC;gBACX,OAAO;oBAACC,OAAO;gBAAmB;YACpC;YAEA,IAAI;gBACF,MAAMf,QAAQsB,MAAM,GAAGC,WAAW,CAAC,OAAOC;oBACxC,MAAM7B,mBAAmB;wBACvB6B;wBACAd;wBACAG;wBACAK;wBACAO,mBAAmBzB,QAAQyB,iBAAiB;wBAC5CC,oBAAoB1B,QAAQ0B,kBAAkB;wBAC9CC,8BAA8B3B,QAAQ2B,4BAA4B;oBACpE;gBACF;YACF,EAAE,OAAOZ,OAAO;gBACd,IAAIA,iBAAiBtB,gCAAgC;oBACnDF,SAASqC,IAAI,CAAC;wBAAClB;wBAAYmB,KAAKd;oBAAK,GAAG;oBACxCN,MAAMK,IAAI,CAAC;oBACX,OAAO;wBAACC,OAAO;oBAAgB;gBACjC;gBACA,IAAIA,iBAAiBrB,uCAAuC;oBAC1DH,SAASqC,IAAI,CACX;wBAAClB;wBAAYoB,QAAQf,MAAMe,MAAM;oBAAA,GACjC;oBAEFrB,MAAMK,IAAI,CAAC;oBACX,OAAO;wBAACC,OAAO;oBAAwB;gBACzC;gBACA,MAAMA;YACR;YAEAN,MAAMK,IAAI,CAAC;YACX,OAAO;QACT;IACF;IAEA,OAAO;QACLiB,QAAQ;QACR3B,MAAM,EAAE;QACR4B,SAAS;YAAC5C;SAAc;QACxB6C,QAAQ;YAAChC;SAAU;IACrB;AACF"}