@lightdash/cli 2.562.0 → 2.564.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 (176) hide show
  1. package/dist/.tsbuildinfo.build +1 -1
  2. package/dist/agentConnectionConnectOption.d.ts +8 -0
  3. package/dist/agentConnectionConnectOption.d.ts.map +1 -0
  4. package/dist/agentConnectionConnectOption.js +39 -0
  5. package/dist/agentConnectionOption.d.ts +3 -0
  6. package/dist/agentConnectionOption.d.ts.map +1 -0
  7. package/dist/agentConnectionOption.js +48 -0
  8. package/dist/agentConnections/agentTokenProvider.d.ts +13 -0
  9. package/dist/agentConnections/agentTokenProvider.d.ts.map +1 -0
  10. package/dist/agentConnections/agentTokenProvider.js +294 -0
  11. package/dist/agentConnections/apiUrl.d.ts +4 -0
  12. package/dist/agentConnections/apiUrl.d.ts.map +1 -0
  13. package/dist/agentConnections/apiUrl.js +37 -0
  14. package/dist/agentConnections/commandPolicy.d.ts +14 -0
  15. package/dist/agentConnections/commandPolicy.d.ts.map +1 -0
  16. package/dist/agentConnections/commandPolicy.js +108 -0
  17. package/dist/agentConnections/configLock.d.ts +12 -0
  18. package/dist/agentConnections/configLock.d.ts.map +1 -0
  19. package/dist/agentConnections/configLock.js +191 -0
  20. package/dist/agentConnections/connectInputs.d.ts +20 -0
  21. package/dist/agentConnections/connectInputs.d.ts.map +1 -0
  22. package/dist/agentConnections/connectInputs.js +49 -0
  23. package/dist/agentConnections/fixtures.d.ts +3 -0
  24. package/dist/agentConnections/fixtures.d.ts.map +1 -0
  25. package/dist/agentConnections/fixtures.js +36 -0
  26. package/dist/agentConnections/initialToken.d.ts +26 -0
  27. package/dist/agentConnections/initialToken.d.ts.map +1 -0
  28. package/dist/agentConnections/initialToken.js +93 -0
  29. package/dist/agentConnections/lifecycle.d.ts +17 -0
  30. package/dist/agentConnections/lifecycle.d.ts.map +1 -0
  31. package/dist/agentConnections/lifecycle.js +44 -0
  32. package/dist/agentConnections/personalRecovery.d.ts +27 -0
  33. package/dist/agentConnections/personalRecovery.d.ts.map +1 -0
  34. package/dist/agentConnections/personalRecovery.js +71 -0
  35. package/dist/agentConnections/projectSelection.d.ts +4 -0
  36. package/dist/agentConnections/projectSelection.d.ts.map +1 -0
  37. package/dist/agentConnections/projectSelection.js +48 -0
  38. package/dist/agentConnections/providerProcess.fixture.d.ts +2 -0
  39. package/dist/agentConnections/providerProcess.fixture.d.ts.map +1 -0
  40. package/dist/agentConnections/providerProcess.fixture.js +19 -0
  41. package/dist/agentConnections/requestPolicy.d.ts +11 -0
  42. package/dist/agentConnections/requestPolicy.d.ts.map +1 -0
  43. package/dist/agentConnections/requestPolicy.js +76 -0
  44. package/dist/agentConnections/schema.d.ts +66 -0
  45. package/dist/agentConnections/schema.d.ts.map +1 -0
  46. package/dist/agentConnections/schema.js +184 -0
  47. package/dist/agentConnections/statusResponse.d.ts +10 -0
  48. package/dist/agentConnections/statusResponse.d.ts.map +1 -0
  49. package/dist/agentConnections/statusResponse.js +146 -0
  50. package/dist/agentConnections/store.d.ts +36 -0
  51. package/dist/agentConnections/store.d.ts.map +1 -0
  52. package/dist/agentConnections/store.js +275 -0
  53. package/dist/agentConnections/warehouseStatus.d.ts +30 -0
  54. package/dist/agentConnections/warehouseStatus.d.ts.map +1 -0
  55. package/dist/agentConnections/warehouseStatus.js +184 -0
  56. package/dist/analytics/analytics.d.ts.map +1 -1
  57. package/dist/analytics/analytics.js +4 -0
  58. package/dist/config.d.ts +3 -1
  59. package/dist/config.d.ts.map +1 -1
  60. package/dist/config.js +2 -2
  61. package/dist/credentials.d.ts +27 -0
  62. package/dist/credentials.d.ts.map +1 -0
  63. package/dist/credentials.js +161 -0
  64. package/dist/dbt/models.d.ts.map +1 -1
  65. package/dist/dbt/models.js +45 -14
  66. package/dist/handlers/agentAccess.d.ts.map +1 -1
  67. package/dist/handlers/agentAccess.js +9 -1
  68. package/dist/handlers/agentConnect.d.ts.map +1 -1
  69. package/dist/handlers/agentConnect.js +2 -0
  70. package/dist/handlers/agentConnectionConnect.d.ts +5 -0
  71. package/dist/handlers/agentConnectionConnect.d.ts.map +1 -0
  72. package/dist/handlers/agentConnectionConnect.js +371 -0
  73. package/dist/handlers/agentConnectionStatus.d.ts +7 -0
  74. package/dist/handlers/agentConnectionStatus.d.ts.map +1 -0
  75. package/dist/handlers/agentConnectionStatus.js +228 -0
  76. package/dist/handlers/agentRevoke.d.ts +7 -0
  77. package/dist/handlers/agentRevoke.d.ts.map +1 -0
  78. package/dist/handlers/agentRevoke.js +144 -0
  79. package/dist/handlers/agentStatus.d.ts +4 -1
  80. package/dist/handlers/agentStatus.d.ts.map +1 -1
  81. package/dist/handlers/agentStatus.js +7 -0
  82. package/dist/handlers/apps/createApp.d.ts.map +1 -1
  83. package/dist/handlers/apps/createApp.js +2 -0
  84. package/dist/handlers/apps/preview.d.ts.map +1 -1
  85. package/dist/handlers/apps/preview.js +6 -0
  86. package/dist/handlers/apps/previewProxy.d.ts.map +1 -1
  87. package/dist/handlers/apps/previewProxy.js +2 -0
  88. package/dist/handlers/apps/validate.d.ts.map +1 -1
  89. package/dist/handlers/apps/validate.js +20 -8
  90. package/dist/handlers/compile.d.ts.map +1 -1
  91. package/dist/handlers/compile.js +3 -0
  92. package/dist/handlers/connectSnowflake.d.ts.map +1 -1
  93. package/dist/handlers/connectSnowflake.js +2 -0
  94. package/dist/handlers/createProject.d.ts.map +1 -1
  95. package/dist/handlers/createProject.js +2 -0
  96. package/dist/handlers/dbt/apiClient.d.ts +4 -2
  97. package/dist/handlers/dbt/apiClient.d.ts.map +1 -1
  98. package/dist/handlers/dbt/apiClient.js +138 -4
  99. package/dist/handlers/dbt/compile.d.ts.map +1 -1
  100. package/dist/handlers/dbt/compile.js +13 -2
  101. package/dist/handlers/dbt/getDbtProfileTargetName.d.ts.map +1 -1
  102. package/dist/handlers/dbt/getDbtProfileTargetName.js +12 -4
  103. package/dist/handlers/dbt/getDbtVersion.d.ts.map +1 -1
  104. package/dist/handlers/dbt/getDbtVersion.js +12 -4
  105. package/dist/handlers/dbt/getWarehouseClient.d.ts.map +1 -1
  106. package/dist/handlers/dbt/getWarehouseClient.js +15 -5
  107. package/dist/handlers/dbt/refresh.d.ts.map +1 -1
  108. package/dist/handlers/dbt/refresh.js +2 -0
  109. package/dist/handlers/dbt/run.d.ts.map +1 -1
  110. package/dist/handlers/dbt/run.js +10 -3
  111. package/dist/handlers/deploy.d.ts.map +1 -1
  112. package/dist/handlers/deploy.js +17 -1
  113. package/dist/handlers/diagnostics.d.ts.map +1 -1
  114. package/dist/handlers/diagnostics.js +2 -0
  115. package/dist/handlers/download.d.ts.map +1 -1
  116. package/dist/handlers/download.js +19 -5
  117. package/dist/handlers/exportChartImage.d.ts.map +1 -1
  118. package/dist/handlers/exportChartImage.js +2 -0
  119. package/dist/handlers/generateExposures.d.ts.map +1 -1
  120. package/dist/handlers/generateExposures.js +4 -1
  121. package/dist/handlers/getProject.d.ts.map +1 -1
  122. package/dist/handlers/getProject.js +25 -1
  123. package/dist/handlers/listProjects.d.ts.map +1 -1
  124. package/dist/handlers/listProjects.js +2 -0
  125. package/dist/handlers/login/connectionBrowser.d.ts +2 -0
  126. package/dist/handlers/login/connectionBrowser.d.ts.map +1 -0
  127. package/dist/handlers/login/connectionBrowser.js +22 -0
  128. package/dist/handlers/login/loopback.d.ts +15 -0
  129. package/dist/handlers/login/loopback.d.ts.map +1 -0
  130. package/dist/handlers/login/loopback.js +135 -0
  131. package/dist/handlers/login/oauth.d.ts.map +1 -1
  132. package/dist/handlers/login/oauth.js +16 -3
  133. package/dist/handlers/login/pat.d.ts.map +1 -1
  134. package/dist/handlers/login/pat.js +2 -0
  135. package/dist/handlers/login.d.ts.map +1 -1
  136. package/dist/handlers/login.js +8 -1
  137. package/dist/handlers/oauthLogin.d.ts.map +1 -1
  138. package/dist/handlers/oauthLogin.js +2 -0
  139. package/dist/handlers/ordinary/harness.mocks.d.ts +42 -0
  140. package/dist/handlers/ordinary/harness.mocks.d.ts.map +1 -0
  141. package/dist/handlers/ordinary/harness.mocks.js +180 -0
  142. package/dist/handlers/preAggregateAudit.d.ts.map +1 -1
  143. package/dist/handlers/preAggregateAudit.js +2 -0
  144. package/dist/handlers/preview.d.ts.map +1 -1
  145. package/dist/handlers/preview.js +4 -0
  146. package/dist/handlers/renameHandler.d.ts.map +1 -1
  147. package/dist/handlers/renameHandler.js +2 -0
  148. package/dist/handlers/renameProject.d.ts.map +1 -1
  149. package/dist/handlers/renameProject.js +2 -0
  150. package/dist/handlers/resolveProjectFlag.d.ts.map +1 -1
  151. package/dist/handlers/resolveProjectFlag.js +5 -0
  152. package/dist/handlers/runChart.d.ts.map +1 -1
  153. package/dist/handlers/runChart.js +7 -2
  154. package/dist/handlers/selectProject.d.ts.map +1 -1
  155. package/dist/handlers/selectProject.js +5 -0
  156. package/dist/handlers/setProject.d.ts.map +1 -1
  157. package/dist/handlers/setProject.js +5 -0
  158. package/dist/handlers/setWarehouse.d.ts.map +1 -1
  159. package/dist/handlers/setWarehouse.js +2 -0
  160. package/dist/handlers/slugUpdate.d.ts.map +1 -1
  161. package/dist/handlers/slugUpdate.js +2 -0
  162. package/dist/handlers/sourceSelection.d.ts.map +1 -1
  163. package/dist/handlers/sourceSelection.js +13 -2
  164. package/dist/handlers/sql.d.ts.map +1 -1
  165. package/dist/handlers/sql.js +7 -2
  166. package/dist/handlers/utils.d.ts +3 -0
  167. package/dist/handlers/utils.d.ts.map +1 -1
  168. package/dist/handlers/utils.js +39 -0
  169. package/dist/handlers/validate.d.ts.map +1 -1
  170. package/dist/handlers/validate.js +2 -0
  171. package/dist/handlers/warehouseCatalog.d.ts.map +1 -1
  172. package/dist/handlers/warehouseCatalog.js +7 -2
  173. package/dist/index.js +43 -3
  174. package/dist/lightdash-config/index.d.ts.map +1 -1
  175. package/dist/lightdash-config/index.js +4 -1
  176. package/package.json +3 -3
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=providerProcess.fixture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"providerProcess.fixture.d.ts","sourceRoot":"","sources":["../../src/agentConnections/providerProcess.fixture.ts"],"names":[],"mappings":""}
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const agentTokenProvider_1 = require("./agentTokenProvider");
4
+ const fixtures_1 = require("./fixtures");
5
+ const store_1 = require("./store");
6
+ const run = async () => {
7
+ const store = new store_1.AgentConnectionStore(process.argv[2]);
8
+ const slot = { ...(0, fixtures_1.slotFixture)(), instanceUrl: process.argv[3] };
9
+ const result = await new agentTokenProvider_1.AgentTokenProvider(store).getToken(slot);
10
+ process.stdout.write(JSON.stringify({
11
+ generation: result.tokens.generation,
12
+ rotated: result.tokens.accessToken === 'new-access' &&
13
+ result.tokens.refreshToken === 'new-refresh',
14
+ }));
15
+ };
16
+ void run().catch((error) => {
17
+ process.stderr.write(error.message);
18
+ process.exitCode = 1;
19
+ });
@@ -0,0 +1,11 @@
1
+ type RequestPolicy = {
2
+ method: string;
3
+ path: string;
4
+ operation: string;
5
+ safeRead: boolean;
6
+ };
7
+ export declare const REQUEST_POLICY: readonly RequestPolicy[];
8
+ export declare const isAgentRequestAllowed: (method: string, url: string) => boolean;
9
+ export declare const assertAgentRequestAllowed: (method: string, url: string) => void;
10
+ export {};
11
+ //# sourceMappingURL=requestPolicy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"requestPolicy.d.ts","sourceRoot":"","sources":["../../src/agentConnections/requestPolicy.ts"],"names":[],"mappings":"AAAA,KAAK,aAAa,GAAG;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;CACrB,CAAC;AAOF,eAAO,MAAM,cAAc,EAAE,SAAS,aAAa,EAgPlD,CAAC;AAEF,eAAO,MAAM,qBAAqB,WAAY,MAAM,OAAO,MAAM,KAAG,OAenE,CAAC;AAEF,eAAO,MAAM,yBAAyB,WAC1B,MAAM,OACT,MAAM,KACZ,IAKF,CAAC"}
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.assertAgentRequestAllowed = exports.isAgentRequestAllowed = exports.REQUEST_POLICY = void 0;
4
+ const route = (method, path, operation) => ({ method, path, operation, safeRead: method === 'GET' });
5
+ exports.REQUEST_POLICY = [
6
+ route('GET', '/api/v1/user', 'UserController.getAuthenticatedUser'),
7
+ route('GET', '/api/v1/health', 'apiV1Router GET /health'),
8
+ route('GET', '/api/v2/user/agent-connections/:grant/status', 'AgentConnectionController.getConnectionStatus'),
9
+ route('DELETE', '/api/v2/user/agent-connections/:grant', 'AgentConnectionController.revoke'),
10
+ route('GET', '/api/v2/projects/:project/ai-access/me', 'AiAccessController.getMyAccess'),
11
+ route('GET', '/api/v1/projects/:project', 'ProjectController.getProject'),
12
+ route('GET', '/api/v1/projects/:project/dbt/manifest', 'ProjectController.getMergedManifest'),
13
+ route('GET', '/api/v1/projects/:project/dbt-exposures', 'ProjectController.GetDbtExposures'),
14
+ route('GET', '/api/v1/projects/:project/explores', 'ExploreController.GetExplores'),
15
+ route('GET', '/api/v1/projects/:project/explores/:explore', 'ExploreController.GetExplore'),
16
+ route('GET', '/api/v2/projects/:project/query/:query', 'QueryController.getAsyncQueryResults'),
17
+ route('POST', '/api/v2/projects/:project/query/sql', 'QueryController.executeAsyncSqlQuery'),
18
+ route('POST', '/api/v2/projects/:project/query/metric-query', 'QueryController.executeAsyncMetricQuery'),
19
+ route('GET', '/api/v1/projects/:project/sqlRunner/fields', 'SqlRunnerController.getTableFields'),
20
+ route('GET', '/api/v1/projects/:project/sqlRunner/tables', 'SqlRunnerController.getTables'),
21
+ route('POST', '/api/v1/projects/:project/sqlRunner/refresh-catalog', 'SqlRunnerController.refreshSqlRunnerCatalog'),
22
+ route('POST', '/api/v1/projects/:project/refresh', 'ProjectController.refresh'),
23
+ route('PUT', '/api/v1/projects/:project/tags/yaml', 'ProjectController.replaceYamlTags'),
24
+ route('PUT', '/api/v2/projects/:project/parameters', 'ParametersController.replaceParameters'),
25
+ route('PUT', '/api/v2/projects/:project/defaults', 'ProjectDefaultsController.replaceProjectDefaults'),
26
+ route('PUT', '/api/v1/projects/:project/table-groups', 'ProjectController.replaceProjectTableGroups'),
27
+ route('POST', '/api/v2/projects/:project/deploy', 'DeployController.startDeploySession'),
28
+ route('POST', '/api/v2/projects/:project/deploy/:session/batch', 'DeployController.addDeployBatch'),
29
+ route('POST', '/api/v2/projects/:project/deploy/:session/finalize', 'DeployController.finalizeDeploySession'),
30
+ route('PUT', '/api/v2/projects/:project/deploy', 'DeployController.deployExplores'),
31
+ route('PUT', '/api/v1/projects/:project/explores', 'ExploreController.SetExplores'),
32
+ route('GET', '/api/v2/content', 'ContentController.listContent'),
33
+ route('GET', '/api/v1/ee/projects/:project/apps', 'AppGenerateController.listProjectApps'),
34
+ route('GET', '/api/v1/ee/projects/:project/apps/chart-types', 'AppGenerateController.listProjectChartTypes'),
35
+ route('GET', '/api/v1/ee/projects/:project/apps/:app/download', 'AppGenerateController.getAppCode'),
36
+ route('GET', '/api/v1/projects/:project/spaces', 'ProjectController.getSpacesInProject'),
37
+ route('GET', '/api/v1/projects/:project/dashboards', 'ProjectController.getDashboards'),
38
+ route('GET', '/api/v1/projects/:project/dbt-sources', 'ProjectDbtSourcesController.listProjectDbtSources'),
39
+ route('GET', '/api/v1/projects/:project/validate', 'ValidationController.get'),
40
+ route('GET', '/api/v1/projects/:project/code/charts', 'ProjectCoderController.getChartsAsCode'),
41
+ route('GET', '/api/v1/projects/:project/code/dashboards', 'ProjectCoderController.getDashboardsAsCode'),
42
+ route('GET', '/api/v1/projects/:project/code/sqlCharts', 'ProjectCoderController.getSqlChartsAsCode'),
43
+ route('GET', '/api/v1/projects/:project/code/virtualViews', 'ProjectCoderController.getVirtualViewsAsCode'),
44
+ route('GET', '/api/v1/projects/:project/code/externalConnections', 'ProjectCoderController.getExternalConnectionsAsCode'),
45
+ route('GET', '/api/v1/projects/:project/code/documents', 'ProjectCoderController.getDocumentsAsCode'),
46
+ route('GET', '/api/v1/projects/:project/code/aiAgents', 'ProjectCoderController.getAiAgentsAsCode'),
47
+ route('GET', '/api/v1/projects/:project/code/alerts', 'ProjectCoderController.getAlertsAsCode'),
48
+ route('GET', '/api/v1/projects/:project/code/googleSheets', 'ProjectCoderController.getGoogleSheetsSyncsAsCode'),
49
+ route('GET', '/api/v1/projects/:project/code/scheduledDeliveries', 'ProjectCoderController.getScheduledDeliveriesAsCode'),
50
+ route('GET', '/api/v1/projects/:project/code/homepages', 'ProjectCoderController.getHomepagesAsCode'),
51
+ route('GET', '/api/v1/projects/:project/code/spaces', 'ProjectCoderController.getCodeSpaces'),
52
+ route('GET', '/api/v1/projects/:project/code/upload-advisory', 'ProjectCoderController.getContentAsCodeUploadAdvisory'),
53
+ route('POST', '/api/v1/projects/:project/code/charts/:slug', 'ProjectCoderController.upsertChartAsCode'),
54
+ route('POST', '/api/v1/projects/:project/code/dashboards/:slug', 'ProjectCoderController.upsertDashboardAsCode'),
55
+ route('POST', '/api/v1/projects/:project/code/sqlCharts/:slug', 'ProjectCoderController.upsertSqlChartAsCode'),
56
+ route('POST', '/api/v1/projects/:project/code/virtualViews/:slug', 'ProjectCoderController.upsertVirtualViewAsCode'),
57
+ ];
58
+ const isAgentRequestAllowed = (method, url) => {
59
+ const path = url.split(/[?#]/, 1)[0];
60
+ const parts = path.split('/');
61
+ return exports.REQUEST_POLICY.some((entry) => {
62
+ if (entry.method !== method)
63
+ return false;
64
+ const pattern = entry.path.split('/');
65
+ return (parts.length === pattern.length &&
66
+ pattern.every((part, index) => part.startsWith(':')
67
+ ? parts[index].length > 0
68
+ : part === parts[index]));
69
+ });
70
+ };
71
+ exports.isAgentRequestAllowed = isAgentRequestAllowed;
72
+ const assertAgentRequestAllowed = (method, url) => {
73
+ if (!(0, exports.isAgentRequestAllowed)(method, url))
74
+ throw new Error('This request is not available with an agent connection. No request was sent.');
75
+ };
76
+ exports.assertAgentRequestAllowed = assertAgentRequestAllowed;
@@ -0,0 +1,66 @@
1
+ import { AgentCapability } from '@lightdash/common';
2
+ export type SlotKey = {
3
+ instanceUrl: string;
4
+ organizationUuid: string;
5
+ personUuid: string;
6
+ name: string;
7
+ };
8
+ export type AgentConnectionStatusReason = 'invalid_grant' | 'not_supported' | 'revoked' | 'expired' | 'agent_identity_disabled' | 'project_access' | 'person_permission' | 'agent_policy';
9
+ export type AgentConnectionSlot = SlotKey & {
10
+ clientId: 'lightdash-cli';
11
+ resource: string;
12
+ grantUuid: string;
13
+ grantRevision: number | null;
14
+ approvedAt: string;
15
+ grantExpiresAt: string;
16
+ tokens: {
17
+ accessToken: string;
18
+ accessTokenExpiresAt: string;
19
+ refreshToken: string;
20
+ refreshTokenExpiresAt: string | null;
21
+ scopes: string[];
22
+ generation: number;
23
+ lastRefreshAttemptUuid: string | null;
24
+ };
25
+ lastReported: {
26
+ checkedAt: string;
27
+ limitsStatus: 'ok' | 'invalid';
28
+ approvedProjects: {
29
+ projectUuid: string;
30
+ name: string | null;
31
+ approvedCapabilities: AgentCapability[];
32
+ }[];
33
+ effectiveProjects: {
34
+ projectUuid: string;
35
+ capabilities: {
36
+ capability: AgentCapability;
37
+ allowed: boolean;
38
+ reason: AgentConnectionStatusReason | null;
39
+ }[];
40
+ }[];
41
+ status: 'active' | 'expired' | 'revoked';
42
+ lastUsedAt: string | null;
43
+ revokedAt: string | null;
44
+ };
45
+ refreshState: {
46
+ kind: 'idle';
47
+ } | {
48
+ kind: 'in_progress';
49
+ attemptUuid: string;
50
+ startedAt: string;
51
+ } | {
52
+ kind: 'reconnect_required';
53
+ since: string;
54
+ };
55
+ revokeState: {
56
+ kind: 'none';
57
+ } | {
58
+ kind: 'unconfirmed';
59
+ attemptedAt: string;
60
+ };
61
+ };
62
+ export declare const invalidConnection: () => Error;
63
+ export declare const canonicalInstanceUrl: (input: string) => string;
64
+ export declare const slotValidator: (value: unknown) => value is AgentConnectionSlot;
65
+ export declare const validateSlot: (value: unknown, key: SlotKey) => AgentConnectionSlot;
66
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/agentConnections/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAIpD,MAAM,MAAM,OAAO,GAAG;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CAChB,CAAC;AACF,MAAM,MAAM,2BAA2B,GACjC,eAAe,GACf,eAAe,GACf,SAAS,GACT,SAAS,GACT,yBAAyB,GACzB,gBAAgB,GAChB,mBAAmB,GACnB,cAAc,CAAC;AACrB,MAAM,MAAM,mBAAmB,GAAG,OAAO,GAAG;IACxC,QAAQ,EAAE,eAAe,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE;QACJ,WAAW,EAAE,MAAM,CAAC;QACpB,oBAAoB,EAAE,MAAM,CAAC;QAC7B,YAAY,EAAE,MAAM,CAAC;QACrB,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAC;QACrC,MAAM,EAAE,MAAM,EAAE,CAAC;QACjB,UAAU,EAAE,MAAM,CAAC;QACnB,sBAAsB,EAAE,MAAM,GAAG,IAAI,CAAC;KACzC,CAAC;IACF,YAAY,EAAE;QACV,SAAS,EAAE,MAAM,CAAC;QAClB,YAAY,EAAE,IAAI,GAAG,SAAS,CAAC;QAC/B,gBAAgB,EAAE;YACd,WAAW,EAAE,MAAM,CAAC;YACpB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;YACpB,oBAAoB,EAAE,eAAe,EAAE,CAAC;SAC3C,EAAE,CAAC;QACJ,iBAAiB,EAAE;YACf,WAAW,EAAE,MAAM,CAAC;YACpB,YAAY,EAAE;gBACV,UAAU,EAAE,eAAe,CAAC;gBAC5B,OAAO,EAAE,OAAO,CAAC;gBACjB,MAAM,EAAE,2BAA2B,GAAG,IAAI,CAAC;aAC9C,EAAE,CAAC;SACP,EAAE,CAAC;QACJ,MAAM,EAAE,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC;QACzC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;QAC1B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;KAC5B,CAAC;IACF,YAAY,EACN;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,GAChB;QAAE,IAAI,EAAE,aAAa,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,GAC/D;QAAE,IAAI,EAAE,oBAAoB,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACpD,WAAW,EACL;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,GAChB;QAAE,IAAI,EAAE,aAAa,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;CACtD,CAAC;AACF,eAAO,MAAM,iBAAiB,QAAO,KAGhC,CAAC;AACN,eAAO,MAAM,oBAAoB,UAAW,MAAM,KAAG,MAmBpD,CAAC;AAsHF,eAAO,MAAM,aAAa,UAAW,OAAO,KAAG,KAAK,IAAI,mBAGvD,CAAC;AACF,eAAO,MAAM,YAAY,UACd,OAAO,OACT,OAAO,KACb,mBAuDF,CAAC"}
@@ -0,0 +1,184 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.validateSlot = exports.slotValidator = exports.canonicalInstanceUrl = exports.invalidConnection = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const common_1 = require("@lightdash/common");
6
+ const ajv_1 = tslib_1.__importDefault(require("ajv"));
7
+ const ajv_formats_1 = tslib_1.__importDefault(require("ajv-formats"));
8
+ const invalidConnection = () => new Error('Invalid agent connection data. Reconnect before using this slot.');
9
+ exports.invalidConnection = invalidConnection;
10
+ const canonicalInstanceUrl = (input) => {
11
+ try {
12
+ const url = new URL(input);
13
+ if (url.username ||
14
+ url.password ||
15
+ url.search ||
16
+ url.hash ||
17
+ (url.protocol !== 'https:' &&
18
+ !(url.protocol === 'http:' &&
19
+ ['localhost', '127.0.0.1', '[::1]'].includes(url.hostname))))
20
+ throw (0, exports.invalidConnection)();
21
+ return url.href.replace(/\/+$/, '');
22
+ }
23
+ catch {
24
+ throw (0, exports.invalidConnection)();
25
+ }
26
+ };
27
+ exports.canonicalInstanceUrl = canonicalInstanceUrl;
28
+ const text = { type: 'string', minLength: 1 };
29
+ const uuid = { type: 'string', format: 'uuid' };
30
+ const date = {
31
+ type: 'string',
32
+ format: 'date-time',
33
+ pattern: '^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$',
34
+ };
35
+ const nullable = (schema) => ({ anyOf: [schema, { type: 'null' }] });
36
+ const object = (properties) => ({
37
+ type: 'object',
38
+ properties,
39
+ required: Object.keys(properties),
40
+ });
41
+ const array = (items) => ({ type: 'array', items, uniqueItems: true });
42
+ const capability = { enum: Object.values(common_1.AgentCapability) };
43
+ const createSlotValidator = () => {
44
+ const ajv = new ajv_1.default();
45
+ (0, ajv_formats_1.default)(ajv);
46
+ return ajv.compile(object({
47
+ instanceUrl: text,
48
+ organizationUuid: uuid,
49
+ personUuid: uuid,
50
+ name: {
51
+ type: 'string',
52
+ pattern: '^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$',
53
+ },
54
+ clientId: { const: 'lightdash-cli' },
55
+ resource: text,
56
+ grantUuid: uuid,
57
+ grantRevision: nullable({ type: 'integer', minimum: 1 }),
58
+ approvedAt: date,
59
+ grantExpiresAt: date,
60
+ tokens: object({
61
+ accessToken: text,
62
+ accessTokenExpiresAt: date,
63
+ refreshToken: text,
64
+ refreshTokenExpiresAt: nullable(date),
65
+ scopes: {
66
+ ...array({
67
+ type: 'string',
68
+ pattern: '^[\\x21\\x23-\\x5B\\x5D-\\x7E]+$',
69
+ }),
70
+ minItems: 1,
71
+ },
72
+ generation: {
73
+ type: 'integer',
74
+ minimum: 1,
75
+ maximum: Number.MAX_SAFE_INTEGER,
76
+ },
77
+ lastRefreshAttemptUuid: nullable(uuid),
78
+ }),
79
+ lastReported: object({
80
+ checkedAt: date,
81
+ limitsStatus: { enum: ['ok', 'invalid'] },
82
+ approvedProjects: array(object({
83
+ projectUuid: uuid,
84
+ name: nullable({ type: 'string' }),
85
+ approvedCapabilities: array(capability),
86
+ })),
87
+ effectiveProjects: array(object({
88
+ projectUuid: uuid,
89
+ capabilities: array(object({
90
+ capability,
91
+ allowed: { type: 'boolean' },
92
+ reason: {
93
+ enum: [
94
+ null,
95
+ 'invalid_grant',
96
+ 'not_supported',
97
+ 'revoked',
98
+ 'expired',
99
+ 'agent_identity_disabled',
100
+ 'project_access',
101
+ 'person_permission',
102
+ 'agent_policy',
103
+ ],
104
+ },
105
+ })),
106
+ })),
107
+ status: { enum: ['active', 'expired', 'revoked'] },
108
+ lastUsedAt: nullable(date),
109
+ revokedAt: nullable(date),
110
+ }),
111
+ refreshState: {
112
+ oneOf: [
113
+ object({ kind: { const: 'idle' } }),
114
+ object({
115
+ kind: { const: 'in_progress' },
116
+ attemptUuid: uuid,
117
+ startedAt: date,
118
+ }),
119
+ object({
120
+ kind: { const: 'reconnect_required' },
121
+ since: date,
122
+ }),
123
+ ],
124
+ },
125
+ revokeState: {
126
+ oneOf: [
127
+ object({ kind: { const: 'none' } }),
128
+ object({
129
+ kind: { const: 'unconfirmed' },
130
+ attemptedAt: date,
131
+ }),
132
+ ],
133
+ },
134
+ }));
135
+ };
136
+ let validator = null;
137
+ const slotValidator = (value) => {
138
+ validator ??= createSlotValidator();
139
+ return validator(value);
140
+ };
141
+ exports.slotValidator = slotValidator;
142
+ const validateSlot = (value, key) => {
143
+ if (!(0, exports.slotValidator)(value))
144
+ throw (0, exports.invalidConnection)();
145
+ if (value.instanceUrl !== (0, exports.canonicalInstanceUrl)(value.instanceUrl) ||
146
+ value.resource !== value.instanceUrl ||
147
+ value.instanceUrl !== key.instanceUrl ||
148
+ value.organizationUuid !== key.organizationUuid ||
149
+ value.personUuid !== key.personUuid ||
150
+ value.name !== key.name ||
151
+ Date.parse(value.approvedAt) >= Date.parse(value.grantExpiresAt) ||
152
+ Date.parse(value.tokens.accessTokenExpiresAt) >
153
+ Date.parse(value.grantExpiresAt) ||
154
+ (value.tokens.refreshTokenExpiresAt !== null &&
155
+ Date.parse(value.tokens.refreshTokenExpiresAt) >
156
+ Date.parse(value.grantExpiresAt)))
157
+ throw (0, exports.invalidConnection)();
158
+ const approved = new Map(value.lastReported.approvedProjects.map((p) => [
159
+ p.projectUuid,
160
+ p.approvedCapabilities,
161
+ ]));
162
+ const effective = new Set(value.lastReported.effectiveProjects.map((p) => p.projectUuid));
163
+ if (approved.size !== value.lastReported.approvedProjects.length ||
164
+ effective.size !== value.lastReported.effectiveProjects.length ||
165
+ approved.size !== effective.size)
166
+ throw (0, exports.invalidConnection)();
167
+ for (const project of value.lastReported.effectiveProjects) {
168
+ const capabilities = approved.get(project.projectUuid);
169
+ if (!capabilities ||
170
+ new Set(project.capabilities.map((c) => c.capability)).size !==
171
+ project.capabilities.length ||
172
+ (value.lastReported.limitsStatus === 'ok' &&
173
+ project.capabilities.length !== capabilities.length) ||
174
+ (value.lastReported.limitsStatus === 'invalid' &&
175
+ (capabilities.length !== 0 ||
176
+ project.capabilities.some((c) => c.allowed || c.reason !== 'invalid_grant'))) ||
177
+ project.capabilities.some((c) => (value.lastReported.limitsStatus === 'ok' &&
178
+ !capabilities.includes(c.capability)) ||
179
+ c.allowed !== (c.reason === null)))
180
+ throw (0, exports.invalidConnection)();
181
+ }
182
+ return value;
183
+ };
184
+ exports.validateSlot = validateSlot;
@@ -0,0 +1,10 @@
1
+ import { type AgentConnectionSlot, type AgentConnectionStatusReason } from './schema';
2
+ export declare class ConnectionMismatchError extends Error {
3
+ constructor();
4
+ }
5
+ export declare const responseRecord: (value: unknown) => Record<string, unknown>;
6
+ export declare const publicTextIsSafe: (value: string, secrets: readonly (string | null | undefined)[], maxLength?: number) => boolean;
7
+ export declare const publicConnectionReport: (slot: AgentConnectionSlot, extraSecrets?: readonly (string | null | undefined)[]) => AgentConnectionSlot['lastReported'];
8
+ export declare const connectionResponse: (value: unknown, slot: AgentConnectionSlot, requireEffective: boolean, extraSecrets?: readonly (string | null | undefined)[]) => AgentConnectionSlot;
9
+ export declare const statusReasonMessage: (reason: AgentConnectionStatusReason | null) => string | null;
10
+ //# sourceMappingURL=statusResponse.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"statusResponse.d.ts","sourceRoot":"","sources":["../../src/agentConnections/statusResponse.ts"],"names":[],"mappings":"AACA,OAAO,EAEH,KAAK,mBAAmB,EACxB,KAAK,2BAA2B,EACnC,MAAM,UAAU,CAAC;AAElB,qBAAa,uBAAwB,SAAQ,KAAK;IAC9C,cAEC;CACJ;AACD,eAAO,MAAM,cAAc,UAAW,OAAO,KAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAIrE,CAAC;AACF,eAAO,MAAM,gBAAgB,UAClB,MAAM,WACJ,SAAS,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,EAAE,yBAEhD,OAwBF,CAAC;AACF,eAAO,MAAM,sBAAsB,SACzB,mBAAmB,iBACX,SAAS,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,EAAE,KACrD,mBAAmB,CAAC,cAAc,CA2BnC,CAAC;AACH,eAAO,MAAM,kBAAkB,UACpB,OAAO,QACR,mBAAmB,oBACP,OAAO,iBACV,SAAS,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,EAAE,KACtD,mBA0EF,CAAC;AACF,eAAO,MAAM,mBAAmB,WACpB,2BAA2B,GAAG,IAAI,KAC3C,MAAM,GAAG,IA0BX,CAAC"}
@@ -0,0 +1,146 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.statusReasonMessage = exports.connectionResponse = exports.publicConnectionReport = exports.publicTextIsSafe = exports.responseRecord = exports.ConnectionMismatchError = void 0;
4
+ const common_1 = require("@lightdash/common");
5
+ const schema_1 = require("./schema");
6
+ class ConnectionMismatchError extends Error {
7
+ constructor() {
8
+ super('The server returned a different connection.');
9
+ }
10
+ }
11
+ exports.ConnectionMismatchError = ConnectionMismatchError;
12
+ const responseRecord = (value) => {
13
+ if (typeof value !== 'object' || value === null || Array.isArray(value))
14
+ throw new Error('The server returned invalid connection data.');
15
+ return Object.fromEntries(Object.entries(value));
16
+ };
17
+ exports.responseRecord = responseRecord;
18
+ const publicTextIsSafe = (value, secrets, maxLength = 2048) => {
19
+ if (value.length > maxLength)
20
+ return false;
21
+ const containsSecret = (text) => secrets.some((secret) => secret && text.includes(secret));
22
+ let decoded = value;
23
+ while (true) {
24
+ if (containsSecret(decoded))
25
+ return false;
26
+ if (URL.canParse(decoded)) {
27
+ const url = new URL(decoded);
28
+ if (containsSecret(url.href) ||
29
+ [...url.searchParams].some(([key, item]) => containsSecret(key) || containsSecret(item)))
30
+ return false;
31
+ }
32
+ const next = decoded.replace(/(?:%[0-9a-f]{2})+/gi, (encoded) => Buffer.from(encoded.replaceAll('%', ''), 'hex').toString('utf8'));
33
+ if (next === decoded)
34
+ return true;
35
+ decoded = next;
36
+ }
37
+ };
38
+ exports.publicTextIsSafe = publicTextIsSafe;
39
+ const publicConnectionReport = (slot, extraSecrets = []) => ({
40
+ checkedAt: slot.lastReported.checkedAt,
41
+ status: slot.lastReported.status,
42
+ limitsStatus: slot.lastReported.limitsStatus,
43
+ lastUsedAt: slot.lastReported.lastUsedAt,
44
+ revokedAt: slot.lastReported.revokedAt,
45
+ approvedProjects: slot.lastReported.approvedProjects.map((project) => ({
46
+ projectUuid: project.projectUuid,
47
+ name: project.name !== null &&
48
+ !(0, exports.publicTextIsSafe)(project.name, [
49
+ slot.tokens.accessToken,
50
+ slot.tokens.refreshToken,
51
+ ...extraSecrets,
52
+ ])
53
+ ? null
54
+ : project.name,
55
+ approvedCapabilities: project.approvedCapabilities,
56
+ })),
57
+ effectiveProjects: slot.lastReported.effectiveProjects.map((project) => ({
58
+ projectUuid: project.projectUuid,
59
+ capabilities: project.capabilities.map((action) => ({
60
+ capability: action.capability,
61
+ allowed: action.allowed,
62
+ reason: action.reason,
63
+ })),
64
+ })),
65
+ });
66
+ exports.publicConnectionReport = publicConnectionReport;
67
+ const connectionResponse = (value, slot, requireEffective, extraSecrets) => {
68
+ const envelope = (0, exports.responseRecord)(value);
69
+ if (envelope.status !== 'ok')
70
+ throw new Error('The server returned invalid connection data.');
71
+ const record = (0, exports.responseRecord)(envelope.results);
72
+ if (['grantUuid', 'name', 'clientId', 'approvedAt', 'expiresAt'].some((field) => typeof record[field] !== 'string'))
73
+ throw new Error('The server returned invalid connection data.');
74
+ if (record.grantUuid !== slot.grantUuid ||
75
+ record.name !== slot.name ||
76
+ record.clientId !== slot.clientId ||
77
+ record.approvedAt !== slot.approvedAt ||
78
+ record.expiresAt !== slot.grantExpiresAt)
79
+ throw new ConnectionMismatchError();
80
+ const revokedProjects = !requireEffective && Array.isArray(record.approvedProjects)
81
+ ? record.approvedProjects.map((entry) => {
82
+ const project = (0, exports.responseRecord)(entry);
83
+ return {
84
+ projectUuid: project.projectUuid,
85
+ capabilities: Array.isArray(project.approvedCapabilities)
86
+ ? project.approvedCapabilities.map((capability) => ({
87
+ capability,
88
+ allowed: false,
89
+ reason: 'revoked',
90
+ }))
91
+ : null,
92
+ };
93
+ })
94
+ : null;
95
+ const checked = (0, schema_1.validateSlot)({
96
+ ...slot,
97
+ lastReported: {
98
+ checkedAt: new Date().toISOString(),
99
+ limitsStatus: record.limitsStatus,
100
+ approvedProjects: record.approvedProjects,
101
+ effectiveProjects: requireEffective
102
+ ? record.effectiveProjects
103
+ : revokedProjects,
104
+ status: record.status,
105
+ lastUsedAt: record.lastUsedAt,
106
+ revokedAt: record.revokedAt,
107
+ },
108
+ }, slot);
109
+ if (checked.lastReported.status === 'revoked' &&
110
+ checked.lastReported.revokedAt === null)
111
+ throw new Error('The server returned invalid revocation data.');
112
+ if (extraSecrets === undefined &&
113
+ checked.lastReported.approvedProjects.some((project) => project.name !== null &&
114
+ [slot.tokens.accessToken, slot.tokens.refreshToken].some((secret) => project.name?.includes(secret))))
115
+ throw new Error('The server returned unsafe connection data.');
116
+ return {
117
+ ...checked,
118
+ lastReported: (0, exports.publicConnectionReport)(checked, extraSecrets),
119
+ };
120
+ };
121
+ exports.connectionResponse = connectionResponse;
122
+ const statusReasonMessage = (reason) => {
123
+ switch (reason) {
124
+ case null:
125
+ return null;
126
+ case 'invalid_grant':
127
+ return 'Connection limits are invalid.';
128
+ case 'not_supported':
129
+ return 'This action is not available to agent connections.';
130
+ case 'revoked':
131
+ return 'This connection was revoked.';
132
+ case 'expired':
133
+ return 'This connection expired.';
134
+ case 'agent_identity_disabled':
135
+ return 'Agent identity is disabled.';
136
+ case 'project_access':
137
+ return 'You no longer have access to this project.';
138
+ case 'person_permission':
139
+ return 'Your role does not allow this action.';
140
+ case 'agent_policy':
141
+ return "Your organisation's agent permissions do not allow this action.";
142
+ default:
143
+ return (0, common_1.assertUnreachable)(reason, 'Unknown connection status reason');
144
+ }
145
+ };
146
+ exports.statusReasonMessage = statusReasonMessage;
@@ -0,0 +1,36 @@
1
+ import { type AgentConnectionSlot, type SlotKey } from './schema';
2
+ export declare const getAgentConnectionsFilePath: () => string;
3
+ export type RefreshJournal = {
4
+ grantUuid: string;
5
+ attemptUuid: string;
6
+ generation: number;
7
+ };
8
+ export type LockedStore = {
9
+ readSlot: (key: SlotKey) => Promise<AgentConnectionSlot | null>;
10
+ saveSlot: (slot: AgentConnectionSlot) => Promise<void>;
11
+ readJournal: (key: SlotKey) => Promise<RefreshJournal | null>;
12
+ writeJournal: (key: SlotKey, journal: RefreshJournal) => Promise<void>;
13
+ clearJournal: (key: SlotKey) => Promise<void>;
14
+ discardStaleJournal: (slot: AgentConnectionSlot) => Promise<void>;
15
+ };
16
+ export declare class AgentConnectionStore {
17
+ readonly filePath: string;
18
+ constructor(filePath?: string);
19
+ private readRoot;
20
+ readSlot(key: SlotKey): Promise<AgentConnectionSlot | null>;
21
+ private saveUnlocked;
22
+ private journalPath;
23
+ private journalIsStale;
24
+ readLifecycleSlot(key: SlotKey): Promise<AgentConnectionSlot | null>;
25
+ withLock<T>(callback: (locked: LockedStore) => Promise<T>): Promise<T>;
26
+ saveSlot(slot: AgentConnectionSlot, precondition?: (previous: AgentConnectionSlot | null) => void): Promise<{
27
+ cleanupIncomplete: boolean;
28
+ }>;
29
+ private update;
30
+ updateTokens(key: SlotKey, tokens: AgentConnectionSlot['tokens']): Promise<void>;
31
+ setRefreshState(key: SlotKey, refreshState: AgentConnectionSlot['refreshState']): Promise<void>;
32
+ setRevokeState(key: SlotKey, revokeState: AgentConnectionSlot['revokeState']): Promise<void>;
33
+ removeSlot(key: SlotKey): Promise<void>;
34
+ removeSlotIfUnchanged(slot: AgentConnectionSlot): Promise<boolean>;
35
+ }
36
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/agentConnections/store.ts"],"names":[],"mappings":"AAWA,OAAO,EAGH,KAAK,mBAAmB,EACxB,KAAK,OAAO,EACf,MAAM,UAAU,CAAC;AAElB,eAAO,MAAM,2BAA2B,QAAO,MACsB,CAAC;AA4CtE,MAAM,MAAM,cAAc,GAAG;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACtB,CAAC;AACF,MAAM,MAAM,WAAW,GAAG;IACtB,QAAQ,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAAC;IAChE,QAAQ,EAAE,CAAC,IAAI,EAAE,mBAAmB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvD,WAAW,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IAC9D,YAAY,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvE,YAAY,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9C,mBAAmB,EAAE,CAAC,IAAI,EAAE,mBAAmB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACrE,CAAC;AAEF,qBAAa,oBAAoB;aAET,QAAQ,EAAE,MAAM;IADpC,YACoB,QAAQ,GAAE,MAAsC,EAChE;YAEU,QAAQ;IAchB,QAAQ,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAIhE;YAEa,YAAY;IA+C1B,OAAO,CAAC,WAAW;YAcL,cAAc;IAkBtB,iBAAiB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAQzE;IAEK,QAAQ,CAAC,CAAC,EACZ,QAAQ,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,GAC9C,OAAO,CAAC,CAAC,CAAC,CAqDZ;IAEK,QAAQ,CACV,IAAI,EAAE,mBAAmB,EACzB,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,mBAAmB,GAAG,IAAI,KAAK,IAAI,GAC9D,OAAO,CAAC;QAAE,iBAAiB,EAAE,OAAO,CAAA;KAAE,CAAC,CAmBzC;YAEa,MAAM;IAcd,YAAY,CACd,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,mBAAmB,CAAC,QAAQ,CAAC,GACtC,OAAO,CAAC,IAAI,CAAC,CAKf;IACK,eAAe,CACjB,GAAG,EAAE,OAAO,EACZ,YAAY,EAAE,mBAAmB,CAAC,cAAc,CAAC,GAClD,OAAO,CAAC,IAAI,CAAC,CAEf;IACK,cAAc,CAChB,GAAG,EAAE,OAAO,EACZ,WAAW,EAAE,mBAAmB,CAAC,aAAa,CAAC,GAChD,OAAO,CAAC,IAAI,CAAC,CAEf;IACK,UAAU,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAS5C;IACK,qBAAqB,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,OAAO,CAAC,CAiBvE;CACJ"}