@claryai/cli 0.1.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 (237) hide show
  1. package/LICENSE +25 -0
  2. package/README.md +197 -0
  3. package/dist/.tsbuildinfo +1 -0
  4. package/dist/ajv.d.ts +3 -0
  5. package/dist/ajv.d.ts.map +1 -0
  6. package/dist/ajv.js +13 -0
  7. package/dist/analytics/analytics.d.ts +370 -0
  8. package/dist/analytics/analytics.d.ts.map +1 -0
  9. package/dist/analytics/analytics.js +143 -0
  10. package/dist/config.d.ts +34 -0
  11. package/dist/config.d.ts.map +1 -0
  12. package/dist/config.js +134 -0
  13. package/dist/dbt/context.d.ts +14 -0
  14. package/dist/dbt/context.d.ts.map +1 -0
  15. package/dist/dbt/context.js +76 -0
  16. package/dist/dbt/context.test.d.ts +2 -0
  17. package/dist/dbt/context.test.d.ts.map +1 -0
  18. package/dist/dbt/context.test.js +152 -0
  19. package/dist/dbt/manifest.d.ts +7 -0
  20. package/dist/dbt/manifest.d.ts.map +1 -0
  21. package/dist/dbt/manifest.js +23 -0
  22. package/dist/dbt/models.d.ts +43 -0
  23. package/dist/dbt/models.d.ts.map +1 -0
  24. package/dist/dbt/models.js +256 -0
  25. package/dist/dbt/models.test.d.ts +2 -0
  26. package/dist/dbt/models.test.d.ts.map +1 -0
  27. package/dist/dbt/models.test.js +19 -0
  28. package/dist/dbt/profile.d.ts +9 -0
  29. package/dist/dbt/profile.d.ts.map +1 -0
  30. package/dist/dbt/profile.js +86 -0
  31. package/dist/dbt/profiles.test.d.ts +2 -0
  32. package/dist/dbt/profiles.test.d.ts.map +1 -0
  33. package/dist/dbt/profiles.test.js +50 -0
  34. package/dist/dbt/schema.d.ts +31 -0
  35. package/dist/dbt/schema.d.ts.map +1 -0
  36. package/dist/dbt/schema.js +49 -0
  37. package/dist/dbt/targets/Bigquery/index.d.ts +18 -0
  38. package/dist/dbt/targets/Bigquery/index.d.ts.map +1 -0
  39. package/dist/dbt/targets/Bigquery/index.js +105 -0
  40. package/dist/dbt/targets/Bigquery/oauth.d.ts +2 -0
  41. package/dist/dbt/targets/Bigquery/oauth.d.ts.map +1 -0
  42. package/dist/dbt/targets/Bigquery/oauth.js +43 -0
  43. package/dist/dbt/targets/Bigquery/serviceAccount.d.ts +35 -0
  44. package/dist/dbt/targets/Bigquery/serviceAccount.d.ts.map +1 -0
  45. package/dist/dbt/targets/Bigquery/serviceAccount.js +149 -0
  46. package/dist/dbt/targets/Databricks/oauth.d.ts +21 -0
  47. package/dist/dbt/targets/Databricks/oauth.d.ts.map +1 -0
  48. package/dist/dbt/targets/Databricks/oauth.js +184 -0
  49. package/dist/dbt/targets/athena.d.ts +21 -0
  50. package/dist/dbt/targets/athena.d.ts.map +1 -0
  51. package/dist/dbt/targets/athena.js +91 -0
  52. package/dist/dbt/targets/athena.test.d.ts +2 -0
  53. package/dist/dbt/targets/athena.test.d.ts.map +1 -0
  54. package/dist/dbt/targets/athena.test.js +60 -0
  55. package/dist/dbt/targets/clickhouse.d.ts +24 -0
  56. package/dist/dbt/targets/clickhouse.d.ts.map +1 -0
  57. package/dist/dbt/targets/clickhouse.js +90 -0
  58. package/dist/dbt/targets/databricks.d.ts +27 -0
  59. package/dist/dbt/targets/databricks.d.ts.map +1 -0
  60. package/dist/dbt/targets/databricks.js +138 -0
  61. package/dist/dbt/targets/duckdb.d.ts +16 -0
  62. package/dist/dbt/targets/duckdb.d.ts.map +1 -0
  63. package/dist/dbt/targets/duckdb.js +63 -0
  64. package/dist/dbt/targets/duckdb.test.d.ts +2 -0
  65. package/dist/dbt/targets/duckdb.test.d.ts.map +1 -0
  66. package/dist/dbt/targets/duckdb.test.js +37 -0
  67. package/dist/dbt/targets/postgres.d.ts +26 -0
  68. package/dist/dbt/targets/postgres.d.ts.map +1 -0
  69. package/dist/dbt/targets/postgres.js +142 -0
  70. package/dist/dbt/targets/redshift.d.ts +23 -0
  71. package/dist/dbt/targets/redshift.d.ts.map +1 -0
  72. package/dist/dbt/targets/redshift.js +96 -0
  73. package/dist/dbt/targets/snowflake.d.ts +4 -0
  74. package/dist/dbt/targets/snowflake.d.ts.map +1 -0
  75. package/dist/dbt/targets/snowflake.js +134 -0
  76. package/dist/dbt/targets/trino.d.ts +16 -0
  77. package/dist/dbt/targets/trino.d.ts.map +1 -0
  78. package/dist/dbt/targets/trino.js +65 -0
  79. package/dist/dbt/templating.d.ts +15 -0
  80. package/dist/dbt/templating.d.ts.map +1 -0
  81. package/dist/dbt/templating.js +50 -0
  82. package/dist/dbt/templating.test.d.ts +2 -0
  83. package/dist/dbt/templating.test.d.ts.map +1 -0
  84. package/dist/dbt/templating.test.js +51 -0
  85. package/dist/dbt/types.d.ts +17 -0
  86. package/dist/dbt/types.d.ts.map +1 -0
  87. package/dist/dbt/types.js +2 -0
  88. package/dist/dbt/validation.d.ts +9 -0
  89. package/dist/dbt/validation.d.ts.map +1 -0
  90. package/dist/dbt/validation.js +54 -0
  91. package/dist/env.d.ts +12 -0
  92. package/dist/env.d.ts.map +1 -0
  93. package/dist/env.js +40 -0
  94. package/dist/error.d.ts +2 -0
  95. package/dist/error.d.ts.map +1 -0
  96. package/dist/error.js +12 -0
  97. package/dist/globalState.d.ts +29 -0
  98. package/dist/globalState.d.ts.map +1 -0
  99. package/dist/globalState.js +67 -0
  100. package/dist/handlers/asyncQuery.d.ts +7 -0
  101. package/dist/handlers/asyncQuery.d.ts.map +1 -0
  102. package/dist/handlers/asyncQuery.js +50 -0
  103. package/dist/handlers/compile.d.ts +16 -0
  104. package/dist/handlers/compile.d.ts.map +1 -0
  105. package/dist/handlers/compile.js +277 -0
  106. package/dist/handlers/compile.test.d.ts +2 -0
  107. package/dist/handlers/compile.test.d.ts.map +1 -0
  108. package/dist/handlers/compile.test.js +201 -0
  109. package/dist/handlers/createProject.d.ts +37 -0
  110. package/dist/handlers/createProject.d.ts.map +1 -0
  111. package/dist/handlers/createProject.js +272 -0
  112. package/dist/handlers/dbt/apiClient.d.ts +14 -0
  113. package/dist/handlers/dbt/apiClient.d.ts.map +1 -0
  114. package/dist/handlers/dbt/apiClient.js +167 -0
  115. package/dist/handlers/dbt/compile.d.ts +35 -0
  116. package/dist/handlers/dbt/compile.d.ts.map +1 -0
  117. package/dist/handlers/dbt/compile.js +220 -0
  118. package/dist/handlers/dbt/getDbtProfileTargetName.d.ts +9 -0
  119. package/dist/handlers/dbt/getDbtProfileTargetName.d.ts.map +1 -0
  120. package/dist/handlers/dbt/getDbtProfileTargetName.js +44 -0
  121. package/dist/handlers/dbt/getDbtVersion.d.ts +16 -0
  122. package/dist/handlers/dbt/getDbtVersion.d.ts.map +1 -0
  123. package/dist/handlers/dbt/getDbtVersion.js +141 -0
  124. package/dist/handlers/dbt/getDbtVersion.mocks.d.ts +11 -0
  125. package/dist/handlers/dbt/getDbtVersion.mocks.d.ts.map +1 -0
  126. package/dist/handlers/dbt/getDbtVersion.mocks.js +70 -0
  127. package/dist/handlers/dbt/getDbtVersion.test.d.ts +2 -0
  128. package/dist/handlers/dbt/getDbtVersion.test.d.ts.map +1 -0
  129. package/dist/handlers/dbt/getDbtVersion.test.js +97 -0
  130. package/dist/handlers/dbt/getWarehouseClient.d.ts +24 -0
  131. package/dist/handlers/dbt/getWarehouseClient.d.ts.map +1 -0
  132. package/dist/handlers/dbt/getWarehouseClient.js +312 -0
  133. package/dist/handlers/dbt/refresh.d.ts +11 -0
  134. package/dist/handlers/dbt/refresh.d.ts.map +1 -0
  135. package/dist/handlers/dbt/refresh.js +114 -0
  136. package/dist/handlers/dbt/run.d.ts +14 -0
  137. package/dist/handlers/dbt/run.d.ts.map +1 -0
  138. package/dist/handlers/dbt/run.js +67 -0
  139. package/dist/handlers/deploy.d.ts +26 -0
  140. package/dist/handlers/deploy.d.ts.map +1 -0
  141. package/dist/handlers/deploy.js +377 -0
  142. package/dist/handlers/diagnostics.d.ts +11 -0
  143. package/dist/handlers/diagnostics.d.ts.map +1 -0
  144. package/dist/handlers/diagnostics.js +194 -0
  145. package/dist/handlers/download.d.ts +29 -0
  146. package/dist/handlers/download.d.ts.map +1 -0
  147. package/dist/handlers/download.js +955 -0
  148. package/dist/handlers/exportChartImage.d.ts +7 -0
  149. package/dist/handlers/exportChartImage.d.ts.map +1 -0
  150. package/dist/handlers/exportChartImage.js +33 -0
  151. package/dist/handlers/generate.d.ts +13 -0
  152. package/dist/handlers/generate.d.ts.map +1 -0
  153. package/dist/handlers/generate.js +159 -0
  154. package/dist/handlers/generateExposures.d.ts +8 -0
  155. package/dist/handlers/generateExposures.d.ts.map +1 -0
  156. package/dist/handlers/generateExposures.js +100 -0
  157. package/dist/handlers/getProject.d.ts +6 -0
  158. package/dist/handlers/getProject.d.ts.map +1 -0
  159. package/dist/handlers/getProject.js +43 -0
  160. package/dist/handlers/installSkills.d.ts +12 -0
  161. package/dist/handlers/installSkills.d.ts.map +1 -0
  162. package/dist/handlers/installSkills.js +321 -0
  163. package/dist/handlers/lint/ajvToSarif.d.ts +66 -0
  164. package/dist/handlers/lint/ajvToSarif.d.ts.map +1 -0
  165. package/dist/handlers/lint/ajvToSarif.js +222 -0
  166. package/dist/handlers/lint/sarifFormatter.d.ts +14 -0
  167. package/dist/handlers/lint/sarifFormatter.d.ts.map +1 -0
  168. package/dist/handlers/lint/sarifFormatter.js +111 -0
  169. package/dist/handlers/lint.d.ts +8 -0
  170. package/dist/handlers/lint.d.ts.map +1 -0
  171. package/dist/handlers/lint.js +308 -0
  172. package/dist/handlers/listProjects.d.ts +6 -0
  173. package/dist/handlers/listProjects.d.ts.map +1 -0
  174. package/dist/handlers/listProjects.js +53 -0
  175. package/dist/handlers/login/oauth.d.ts +2 -0
  176. package/dist/handlers/login/oauth.d.ts.map +1 -0
  177. package/dist/handlers/login/oauth.js +27 -0
  178. package/dist/handlers/login/pat.d.ts +2 -0
  179. package/dist/handlers/login/pat.d.ts.map +1 -0
  180. package/dist/handlers/login/pat.js +31 -0
  181. package/dist/handlers/login.d.ts +15 -0
  182. package/dist/handlers/login.d.ts.map +1 -0
  183. package/dist/handlers/login.js +239 -0
  184. package/dist/handlers/metadataFile.d.ts +9 -0
  185. package/dist/handlers/metadataFile.d.ts.map +1 -0
  186. package/dist/handlers/metadataFile.js +34 -0
  187. package/dist/handlers/oauthLogin.d.ts +6 -0
  188. package/dist/handlers/oauthLogin.d.ts.map +1 -0
  189. package/dist/handlers/oauthLogin.js +191 -0
  190. package/dist/handlers/preview.d.ts +29 -0
  191. package/dist/handlers/preview.d.ts.map +1 -0
  192. package/dist/handlers/preview.js +415 -0
  193. package/dist/handlers/renameHandler.d.ts +16 -0
  194. package/dist/handlers/renameHandler.d.ts.map +1 -0
  195. package/dist/handlers/renameHandler.js +160 -0
  196. package/dist/handlers/runChart.d.ts +10 -0
  197. package/dist/handlers/runChart.d.ts.map +1 -0
  198. package/dist/handlers/runChart.js +105 -0
  199. package/dist/handlers/selectProject.d.ts +20 -0
  200. package/dist/handlers/selectProject.d.ts.map +1 -0
  201. package/dist/handlers/selectProject.js +91 -0
  202. package/dist/handlers/setProject.d.ts +14 -0
  203. package/dist/handlers/setProject.d.ts.map +1 -0
  204. package/dist/handlers/setProject.js +131 -0
  205. package/dist/handlers/setWarehouse.d.ts +14 -0
  206. package/dist/handlers/setWarehouse.d.ts.map +1 -0
  207. package/dist/handlers/setWarehouse.js +94 -0
  208. package/dist/handlers/sql.d.ts +9 -0
  209. package/dist/handlers/sql.d.ts.map +1 -0
  210. package/dist/handlers/sql.js +89 -0
  211. package/dist/handlers/utils.d.ts +11 -0
  212. package/dist/handlers/utils.d.ts.map +1 -0
  213. package/dist/handlers/utils.js +36 -0
  214. package/dist/handlers/validate.d.ts +22 -0
  215. package/dist/handlers/validate.d.ts.map +1 -0
  216. package/dist/handlers/validate.js +201 -0
  217. package/dist/index.d.ts +3 -0
  218. package/dist/index.d.ts.map +1 -0
  219. package/dist/index.js +581 -0
  220. package/dist/lightdash/loader.d.ts +21 -0
  221. package/dist/lightdash/loader.d.ts.map +1 -0
  222. package/dist/lightdash/loader.js +122 -0
  223. package/dist/lightdash/projectType.d.ts +84 -0
  224. package/dist/lightdash/projectType.d.ts.map +1 -0
  225. package/dist/lightdash/projectType.js +75 -0
  226. package/dist/lightdash-config/index.d.ts +2 -0
  227. package/dist/lightdash-config/index.d.ts.map +1 -0
  228. package/dist/lightdash-config/index.js +41 -0
  229. package/dist/lightdash-config/lightdash-config.test.d.ts +2 -0
  230. package/dist/lightdash-config/lightdash-config.test.d.ts.map +1 -0
  231. package/dist/lightdash-config/lightdash-config.test.js +70 -0
  232. package/dist/styles.d.ts +10 -0
  233. package/dist/styles.d.ts.map +1 -0
  234. package/dist/styles.js +14 -0
  235. package/entitlements.plist +33 -0
  236. package/package.json +71 -0
  237. package/track.sh +116 -0
@@ -0,0 +1,415 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.stopPreviewHandler = exports.startPreviewHandler = exports.previewHandler = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const core = tslib_1.__importStar(require("@actions/core"));
6
+ const common_1 = require("@lightdash/common");
7
+ const chokidar_1 = tslib_1.__importDefault(require("chokidar"));
8
+ const inquirer_1 = tslib_1.__importDefault(require("inquirer"));
9
+ const path_1 = tslib_1.__importDefault(require("path"));
10
+ const unique_names_generator_1 = require("unique-names-generator");
11
+ const url_1 = require("url");
12
+ const uuid_1 = require("uuid");
13
+ const analytics_1 = require("../analytics/analytics");
14
+ const config_1 = require("../config");
15
+ const context_1 = require("../dbt/context");
16
+ const globalState_1 = tslib_1.__importDefault(require("../globalState"));
17
+ const projectType_1 = require("../lightdash/projectType");
18
+ const styles = tslib_1.__importStar(require("../styles"));
19
+ const compile_1 = require("./compile");
20
+ const createProject_1 = require("./createProject");
21
+ const apiClient_1 = require("./dbt/apiClient");
22
+ const deploy_1 = require("./deploy");
23
+ const deletePreviewProject = async (projectUuid) => {
24
+ /**
25
+ * projectUuid may be undefined here if a command fails early enough
26
+ * that a project was never created, or we were otherwise unable to
27
+ * retrieve a UUID. We know `undefined` will always fail, so we avoid
28
+ * the round-trip.
29
+ */
30
+ if (typeof projectUuid === 'undefined') {
31
+ globalState_1.default.debug('no projectUuid available to delete, may not have been ready yet - skipping');
32
+ return;
33
+ }
34
+ await (0, apiClient_1.lightdashApi)({
35
+ method: 'DELETE',
36
+ url: `/api/v1/org/projects/${projectUuid}`,
37
+ body: undefined,
38
+ });
39
+ };
40
+ const cleanupProject = async (executionId, projectUuid, previewStartTime) => {
41
+ const teardownSpinner = globalState_1.default.startSpinner(` Cleaning up`);
42
+ try {
43
+ await deletePreviewProject(projectUuid);
44
+ await analytics_1.LightdashAnalytics.track({
45
+ event: 'preview.stopped',
46
+ properties: {
47
+ executionId,
48
+ projectId: projectUuid,
49
+ durationMs: previewStartTime
50
+ ? Date.now() - previewStartTime
51
+ : 0,
52
+ },
53
+ });
54
+ teardownSpinner.succeed(` Cleaned up`);
55
+ }
56
+ catch (e) {
57
+ // console.error(styles.error(`Error during cleanup: ${getErrorMessage(e)}`));
58
+ teardownSpinner.fail(` Cleanup failed: ${(0, common_1.getErrorMessage)(e)}`);
59
+ }
60
+ };
61
+ const projectUrl = async (project) => {
62
+ const config = await (0, config_1.getConfig)();
63
+ if (config.context?.serverUrl) {
64
+ return new url_1.URL(`/projects/${project.projectUuid}/tables`, config.context.serverUrl);
65
+ }
66
+ throw new Error('Missing server url. Make sure you login before running other commands.');
67
+ };
68
+ const getPreviewProject = async (name) => {
69
+ const projects = await (0, apiClient_1.lightdashApi)({
70
+ method: 'GET',
71
+ url: `/api/v1/org/projects/`,
72
+ body: undefined,
73
+ });
74
+ return projects.find((project) => project.type === common_1.ProjectType.PREVIEW && project.name === name);
75
+ };
76
+ const previewHandler = async (options) => {
77
+ globalState_1.default.setVerbose(options.verbose);
78
+ const executionId = (0, uuid_1.v4)();
79
+ await (0, apiClient_1.checkLightdashVersion)();
80
+ // Detect project type
81
+ const absoluteProjectPath = path_1.default.resolve(options.projectDir);
82
+ const projectTypeConfig = await (0, projectType_1.detectProjectType)({
83
+ projectDir: options.projectDir,
84
+ userOptions: {
85
+ warehouseCredentials: options.warehouseCredentials,
86
+ skipDbtCompile: options.skipDbtCompile,
87
+ skipWarehouseCatalog: options.skipWarehouseCatalog,
88
+ },
89
+ });
90
+ let name = options?.name;
91
+ if (name === undefined) {
92
+ name = (0, unique_names_generator_1.uniqueNamesGenerator)({
93
+ length: 2,
94
+ separator: ' ',
95
+ dictionaries: [unique_names_generator_1.colors, unique_names_generator_1.animals],
96
+ });
97
+ }
98
+ console.error('');
99
+ const spinner = globalState_1.default.startSpinner(` Setting up preview environment`);
100
+ const previewProject = await getPreviewProject(name);
101
+ if (previewProject) {
102
+ globalState_1.default.debug(`> Preview with the same name already running`);
103
+ spinner.fail();
104
+ throw new Error('Preview with the same name already running.');
105
+ }
106
+ let project;
107
+ let hasContentCopy = false;
108
+ let contentCopyError;
109
+ let contentCopySkipReason;
110
+ const config = await (0, config_1.getConfig)();
111
+ // Validate upstream project before attempting to copy content
112
+ let upstreamProjectValid = false;
113
+ if (config.context?.project && !options.skipCopyContent) {
114
+ try {
115
+ globalState_1.default.debug(`> Validating upstream project: ${config.context.project}`);
116
+ const upstreamProject = await (0, apiClient_1.lightdashApi)({
117
+ method: 'GET',
118
+ url: `/api/v1/projects/${config.context.project}`,
119
+ body: undefined,
120
+ });
121
+ upstreamProjectValid =
122
+ upstreamProject.projectUuid === config.context.project;
123
+ if (!upstreamProjectValid) {
124
+ contentCopySkipReason = `Project UUID mismatch. Expected ${config.context.project} but got ${upstreamProject.projectUuid}`;
125
+ console.error(styles.warning(`\n\nWarning: Cannot access upstream project "${config.context.projectName || config.context.project}"\n` +
126
+ `Content will not be copied. Please run 'clary config set-project' to set a valid project.\n`));
127
+ }
128
+ }
129
+ catch (e) {
130
+ const errorMessage = e instanceof Error ? e.message : String(e);
131
+ contentCopySkipReason = `Failed to validate upstream project: ${errorMessage}`;
132
+ globalState_1.default.debug(`> Upstream project validation failed: ${errorMessage}`);
133
+ console.error(styles.warning(`\n\nWarning: Cannot access upstream project "${config.context.projectName || config.context.project}"\n` +
134
+ `Content will not be copied. Please run 'clary config set-project' to set a valid project.\n`));
135
+ }
136
+ }
137
+ if (!config.context?.project) {
138
+ contentCopySkipReason = 'No upstream project configured';
139
+ console.error(styles.warning(`\n\nDeveloper preview will be deployed without any copied content!\nPlease set a project to copy content from by running 'clary config set-project'.\n`));
140
+ }
141
+ else if (options.skipCopyContent) {
142
+ contentCopySkipReason = '--skip-copy-content flag was used';
143
+ console.error(styles.warning(`\n\nDeveloper preview will be deployed without any copied content!\n`));
144
+ }
145
+ else if (upstreamProjectValid) {
146
+ console.error(`\n${styles.success('✔')} Copying charts and dashboards from "${config.context?.projectName || 'source project'}"`);
147
+ }
148
+ try {
149
+ const results = await (0, createProject_1.createProject)({
150
+ ...options,
151
+ name,
152
+ type: common_1.ProjectType.PREVIEW,
153
+ upstreamProjectUuid: upstreamProjectValid && config.context?.project
154
+ ? config.context.project
155
+ : undefined,
156
+ copyContent: !options.skipCopyContent && upstreamProjectValid,
157
+ warehouseCredentials: projectTypeConfig.warehouseCredentials,
158
+ });
159
+ project = results?.project;
160
+ hasContentCopy = Boolean(results?.hasContentCopy);
161
+ contentCopyError = results?.contentCopyError;
162
+ }
163
+ catch (e) {
164
+ globalState_1.default.debug(`> Unable to create project: ${e}`);
165
+ spinner.fail();
166
+ throw e;
167
+ }
168
+ if (!project) {
169
+ spinner.fail('Cancel preview environment');
170
+ console.error("To create your project, you'll need to manually enter your warehouse connection details.");
171
+ const createProjectUrl = config.context?.serverUrl &&
172
+ new url_1.URL('/createProject', config.context.serverUrl);
173
+ if (createProjectUrl) {
174
+ console.error(`Fill out the project connection form here: ${createProjectUrl}`);
175
+ }
176
+ return;
177
+ }
178
+ const previewStartTime = Date.now();
179
+ await analytics_1.LightdashAnalytics.track({
180
+ event: 'preview.started',
181
+ properties: {
182
+ executionId,
183
+ projectId: project.projectUuid,
184
+ },
185
+ });
186
+ try {
187
+ const explores = await (0, compile_1.compile)(options);
188
+ await (0, deploy_1.deploy)(explores, {
189
+ ...options,
190
+ projectUuid: project.projectUuid,
191
+ });
192
+ await (0, config_1.setPreviewProject)(project.projectUuid, name);
193
+ process.on('SIGINT', async () => {
194
+ await cleanupProject(executionId, project.projectUuid, previewStartTime);
195
+ process.exit(0);
196
+ });
197
+ if (!hasContentCopy) {
198
+ let errorMessage = `\n\nDeveloper preview deployed without any copied content!`;
199
+ if (contentCopyError) {
200
+ errorMessage += `\nError: ${contentCopyError}`;
201
+ }
202
+ else if (contentCopySkipReason) {
203
+ errorMessage += `\nReason: ${contentCopySkipReason}`;
204
+ }
205
+ errorMessage += '\n';
206
+ console.error(styles.warning(errorMessage));
207
+ }
208
+ spinner.succeed(` Developer preview "${name}" ready at: ${await projectUrl(project)}\n`);
209
+ await analytics_1.LightdashAnalytics.track({
210
+ event: 'preview.completed',
211
+ properties: {
212
+ executionId,
213
+ projectId: project.projectUuid,
214
+ durationMs: Date.now() - previewStartTime,
215
+ },
216
+ });
217
+ const pressToShutdown = globalState_1.default.startSpinner(` Press [ENTER] to shutdown preview...`);
218
+ // Only set up dbt manifest file watching for dbt projects
219
+ // YAML-only projects don't have a manifest.json to watch
220
+ let watcher;
221
+ if (projectTypeConfig.type === projectType_1.CliProjectType.Dbt) {
222
+ const context = await (0, context_1.getDbtContext)({
223
+ projectDir: absoluteProjectPath,
224
+ targetPath: options.targetPath,
225
+ });
226
+ const manifestFilePath = path_1.default.join(context.targetDir, 'manifest.json');
227
+ watcher = chokidar_1.default
228
+ .watch(manifestFilePath)
229
+ .on('change', async () => {
230
+ pressToShutdown.stop();
231
+ console.error(`${styles.title('↻')} Detected changes on dbt project. Updating preview`);
232
+ watcher.unwatch(manifestFilePath);
233
+ // Deploying will change manifest.json too, so we need to stop watching the file until it is deployed
234
+ if (project) {
235
+ await (0, deploy_1.deploy)(await (0, compile_1.compile)(options), {
236
+ ...options,
237
+ projectUuid: project.projectUuid,
238
+ });
239
+ }
240
+ console.error(`${styles.success('✔')} Preview updated \n`);
241
+ pressToShutdown.start();
242
+ watcher.add(manifestFilePath);
243
+ });
244
+ }
245
+ await inquirer_1.default.prompt([
246
+ {
247
+ type: 'input',
248
+ name: 'press-enter',
249
+ prefix: styles.success('✔'),
250
+ message: ` Press [ENTER] to shutdown preview...`,
251
+ },
252
+ ]);
253
+ pressToShutdown.clear();
254
+ // Clean up watcher if it was created
255
+ if (watcher) {
256
+ await watcher.close();
257
+ }
258
+ }
259
+ catch (e) {
260
+ spinner.fail(`Error creating developer preview: ${(0, common_1.getErrorMessage)(e)}`);
261
+ await deletePreviewProject(project.projectUuid);
262
+ await (0, config_1.unsetPreviewProject)();
263
+ await analytics_1.LightdashAnalytics.track({
264
+ event: 'preview.error',
265
+ properties: {
266
+ executionId,
267
+ projectId: project.projectUuid,
268
+ error: `Error creating developer preview ${e}`,
269
+ },
270
+ });
271
+ throw e;
272
+ }
273
+ await cleanupProject(executionId, project.projectUuid, previewStartTime);
274
+ };
275
+ exports.previewHandler = previewHandler;
276
+ const startPreviewHandler = async (options) => {
277
+ globalState_1.default.setVerbose(options.verbose);
278
+ await (0, apiClient_1.checkLightdashVersion)();
279
+ const executionId = (0, uuid_1.v4)();
280
+ if (!options.name) {
281
+ console.error(styles.error(`--name argument is required`));
282
+ return;
283
+ }
284
+ // Detect project type
285
+ const projectTypeConfig = await (0, projectType_1.detectProjectType)({
286
+ projectDir: options.projectDir,
287
+ userOptions: {
288
+ warehouseCredentials: options.warehouseCredentials,
289
+ skipDbtCompile: options.skipDbtCompile,
290
+ skipWarehouseCatalog: options.skipWarehouseCatalog,
291
+ },
292
+ });
293
+ const projectName = options.name;
294
+ const config = await (0, config_1.getConfig)();
295
+ // Log current source project info if copying content
296
+ if (!options.skipCopyContent && config.context?.project) {
297
+ console.error(`\n${styles.success('Source project for content:')} ${styles.bold(config.context.projectName || config.context.project)}\n`);
298
+ }
299
+ const previewProject = await getPreviewProject(projectName);
300
+ if (previewProject) {
301
+ console.error(`\n${styles.success('Updating preview project:')} ${styles.bold(projectName)}\n`);
302
+ await (0, config_1.setPreviewProject)(previewProject.projectUuid, projectName);
303
+ await analytics_1.LightdashAnalytics.track({
304
+ event: 'start_preview.update',
305
+ properties: {
306
+ executionId,
307
+ projectId: previewProject.projectUuid,
308
+ name: options.name,
309
+ },
310
+ });
311
+ // Update
312
+ const explores = await (0, compile_1.compile)(options);
313
+ await (0, deploy_1.deploy)(explores, {
314
+ ...options,
315
+ projectUuid: previewProject.projectUuid,
316
+ });
317
+ const url = await projectUrl(previewProject);
318
+ console.error(`Project updated on ${url}`);
319
+ if (process.env.CI === 'true') {
320
+ core.setOutput('url', url.toString());
321
+ core.setOutput('project_uuid', previewProject.projectUuid);
322
+ }
323
+ }
324
+ else {
325
+ console.error(`\n${styles.success('Creating preview project:')} ${styles.bold(projectName)}\n`);
326
+ if (!config.context?.project) {
327
+ console.error(styles.warning(`\n\nDeveloper preview will be deployed without any copied content!\nPlease set a project to copy content from by running 'clary config set-project'.\n`));
328
+ }
329
+ else if (options.skipCopyContent) {
330
+ console.error(styles.warning(`\n\nDeveloper preview will be deployed without any copied content!\n`));
331
+ }
332
+ else {
333
+ console.error(`\n${styles.success('✔')} Copying charts and dashboards from "${config.context?.projectName || 'source project'}"`);
334
+ }
335
+ // Create
336
+ const results = await (0, createProject_1.createProject)({
337
+ ...options,
338
+ name: projectName,
339
+ type: common_1.ProjectType.PREVIEW,
340
+ upstreamProjectUuid: config.context?.project,
341
+ copyContent: !options.skipCopyContent,
342
+ warehouseCredentials: projectTypeConfig.warehouseCredentials,
343
+ });
344
+ const project = results?.project;
345
+ const hasContentCopy = Boolean(results?.hasContentCopy);
346
+ if (!project) {
347
+ console.error("To create your project, you'll need to manually enter your warehouse connection details.");
348
+ const createProjectUrl = config.context?.serverUrl &&
349
+ new url_1.URL('/createProject', config.context.serverUrl);
350
+ if (createProjectUrl) {
351
+ console.error(`Fill out the project connection form here: ${createProjectUrl}`);
352
+ }
353
+ return;
354
+ }
355
+ await (0, config_1.setPreviewProject)(project.projectUuid, projectName);
356
+ await analytics_1.LightdashAnalytics.track({
357
+ event: 'start_preview.create',
358
+ properties: {
359
+ executionId,
360
+ projectId: project.projectUuid,
361
+ name: options.name,
362
+ },
363
+ });
364
+ const explores = await (0, compile_1.compile)(options);
365
+ await (0, deploy_1.deploy)(explores, {
366
+ ...options,
367
+ projectUuid: project.projectUuid,
368
+ });
369
+ const url = await projectUrl(project);
370
+ if (!hasContentCopy) {
371
+ console.error(styles.warning(`\n\nDeveloper preview deployed without any copied content!\n`));
372
+ }
373
+ console.error(`New project created on ${url}`);
374
+ if (process.env.CI === 'true') {
375
+ core.setOutput('url', url.toString());
376
+ core.setOutput('project_uuid', project.projectUuid);
377
+ }
378
+ }
379
+ };
380
+ exports.startPreviewHandler = startPreviewHandler;
381
+ const stopPreviewHandler = async (options) => {
382
+ globalState_1.default.setVerbose(options.verbose);
383
+ await (0, apiClient_1.checkLightdashVersion)();
384
+ const executionId = (0, uuid_1.v4)();
385
+ if (!options.name) {
386
+ console.error(styles.error(`--name argument is required`));
387
+ return;
388
+ }
389
+ const projectName = options.name;
390
+ await (0, config_1.unsetPreviewProject)();
391
+ const previewProject = await getPreviewProject(projectName);
392
+ if (previewProject) {
393
+ await analytics_1.LightdashAnalytics.track({
394
+ event: 'stop_preview.delete',
395
+ properties: {
396
+ executionId,
397
+ projectId: previewProject.projectUuid,
398
+ name: options.name,
399
+ },
400
+ });
401
+ await deletePreviewProject(previewProject.projectUuid);
402
+ console.error(`Successfully deleted preview project named ${projectName}`);
403
+ }
404
+ else {
405
+ await analytics_1.LightdashAnalytics.track({
406
+ event: 'stop_preview.missing',
407
+ properties: {
408
+ name: options.name,
409
+ },
410
+ });
411
+ console.error(styles.error(`Could not find preview project with name ${projectName}`));
412
+ process.exit(1);
413
+ }
414
+ };
415
+ exports.stopPreviewHandler = stopPreviewHandler;
@@ -0,0 +1,16 @@
1
+ import { RenameType } from '@lightdash/common';
2
+ type RenameHandlerOptions = {
3
+ verbose: boolean;
4
+ type: RenameType;
5
+ project?: string;
6
+ model?: string;
7
+ from: string;
8
+ to: string;
9
+ dryRun: boolean;
10
+ assumeYes: boolean;
11
+ list: boolean;
12
+ validate: boolean;
13
+ };
14
+ export declare const renameHandler: (options: RenameHandlerOptions) => Promise<void>;
15
+ export {};
16
+ //# sourceMappingURL=renameHandler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"renameHandler.d.ts","sourceRoot":"","sources":["../../src/handlers/renameHandler.ts"],"names":[],"mappings":"AAAA,OAAO,EAMH,UAAU,EAEb,MAAM,mBAAmB,CAAC;AAkB3B,KAAK,oBAAoB,GAAG;IACxB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,UAAU,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,OAAO,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,EAAE,OAAO,CAAC;CACrB,CAAC;AAsCF,eAAO,MAAM,aAAa,GAAU,SAAS,oBAAoB,kBAmMhE,CAAC"}
@@ -0,0 +1,160 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.renameHandler = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const common_1 = require("@lightdash/common");
6
+ const fs_1 = tslib_1.__importDefault(require("fs"));
7
+ const inquirer_1 = tslib_1.__importDefault(require("inquirer"));
8
+ const path_1 = tslib_1.__importDefault(require("path"));
9
+ const uuid_1 = require("uuid");
10
+ const analytics_1 = require("../analytics/analytics");
11
+ const config_1 = require("../config");
12
+ const globalState_1 = tslib_1.__importDefault(require("../globalState"));
13
+ const styles = tslib_1.__importStar(require("../styles"));
14
+ const apiClient_1 = require("./dbt/apiClient");
15
+ const refresh_1 = require("./dbt/refresh");
16
+ const validate_1 = require("./validate");
17
+ const REFETCH_JOB_INTERVAL = 2000;
18
+ const waitUntilFinished = async (jobUuid) => {
19
+ const job = await (0, validate_1.getJobState)(jobUuid);
20
+ if (job.status === common_1.SchedulerJobStatus.COMPLETED) {
21
+ return job.status;
22
+ }
23
+ if (job.status === common_1.SchedulerJobStatus.ERROR) {
24
+ throw new Error(`\nRename failed: ${job.details?.error || 'unknown error'}`);
25
+ }
26
+ return (0, validate_1.delay)(REFETCH_JOB_INTERVAL).then(() => waitUntilFinished(jobUuid));
27
+ };
28
+ const listResources = (resources, type, list) => {
29
+ if (resources.length === 0)
30
+ return;
31
+ const maxList = 5;
32
+ const resourcesToShow = list ? resources : resources.slice(0, maxList);
33
+ console.info(`- ${resourcesToShow.map((r) => r.name).join('\n- ')}`);
34
+ if (!list && resources.length > maxList) {
35
+ console.info(`${styles.secondary(`...\nShowing ${maxList} of ${resources.length} ${type}, use --list to see all`)}`);
36
+ }
37
+ };
38
+ const renameHandler = async (options) => {
39
+ globalState_1.default.setVerbose(options.verbose);
40
+ await (0, apiClient_1.checkLightdashVersion)();
41
+ const executionId = (0, uuid_1.v4)();
42
+ const startTime = Date.now();
43
+ const config = await (0, config_1.getConfig)();
44
+ if (!config.context?.apiKey || !config.context.serverUrl) {
45
+ throw new common_1.AuthorizationError(`Not logged in. Run 'clary login --help'`);
46
+ }
47
+ const projectUuid = options.project ||
48
+ config.context.previewProject ||
49
+ config.context.project;
50
+ if (!projectUuid) {
51
+ throw new common_1.LightdashError({
52
+ message: 'No project selected. Run clary config set-project',
53
+ name: 'Not Found',
54
+ statusCode: 404,
55
+ data: {},
56
+ });
57
+ }
58
+ // Log current project info
59
+ if (options.project) {
60
+ console.error(`\n${styles.success('Renaming in project:')} ${projectUuid}\n`);
61
+ }
62
+ else {
63
+ globalState_1.default.logProjectInfo(config);
64
+ }
65
+ const isValidInput = (input) => /^[a-z_]+$/.test(input);
66
+ if (!isValidInput(options.from) || !isValidInput(options.to)) {
67
+ throw new Error('Invalid input: Only lowercase letters (a-z) and underscores (_) are allowed.');
68
+ }
69
+ const project = await (0, refresh_1.getProject)(projectUuid);
70
+ if (!options.assumeYes && !options.dryRun) {
71
+ const answers = await inquirer_1.default.prompt([
72
+ {
73
+ type: 'confirm',
74
+ name: 'isConfirm',
75
+ message: `This command will replace all ${styles.title(options.type)} occurrences from ${styles.title(options.from)} to ${styles.title(options.to)} in all charts and dashboards in project ${styles.title(project.name)} (${projectUuid}).\nAre you sure you want to continue? `,
76
+ },
77
+ ]);
78
+ if (!answers.isConfirm) {
79
+ console.info('Aborting rename');
80
+ return;
81
+ }
82
+ }
83
+ try {
84
+ const jobResponse = await (0, apiClient_1.lightdashApi)({
85
+ method: 'POST',
86
+ url: `/api/v1/projects/${projectUuid}/rename`,
87
+ body: JSON.stringify(options),
88
+ });
89
+ globalState_1.default.debug(`Rename job scheduled with id: ${jobResponse.jobId}`);
90
+ const status = await waitUntilFinished(jobResponse.jobId);
91
+ globalState_1.default.debug(`Rename job finished with status: ${status}`);
92
+ const job = await (0, validate_1.getJobState)(jobResponse.jobId);
93
+ const results = job.details?.results;
94
+ globalState_1.default.debug(`Updated results: ${JSON.stringify(results, null, 2)}`);
95
+ console.info(`${styles.bold('Total updated charts:')} ${results.charts.length}`);
96
+ listResources(results.charts, 'charts', options.list);
97
+ console.info(`${styles.bold('Total updated dashboards:')} ${results.dashboards.length}`);
98
+ listResources(results.dashboards, 'dashboards', options.list);
99
+ if (results.alerts.length > 0) {
100
+ console.info(`${styles.bold('Total updated alerts:')} ${results.alerts.length}`);
101
+ listResources(results.alerts, 'chart alerts', options.list);
102
+ }
103
+ if (results.dashboardSchedulers.length > 0) {
104
+ console.info(`${styles.bold('Total updated dashboard schedulers:')} ${results.dashboardSchedulers.length}`);
105
+ listResources(results.dashboardSchedulers, 'dashboard schedulers', options.list);
106
+ }
107
+ const hasResults = results.charts.length > 0 ||
108
+ results.dashboards.length > 0 ||
109
+ results.alerts.length > 0 ||
110
+ results.dashboardSchedulers.length > 0;
111
+ if (options.dryRun) {
112
+ console.info(`\n${styles.warning(`This is a test run, no changes were committed to the database, remove ${styles.bold('--dry-run')} flag to make changes`)}\n`);
113
+ }
114
+ else if (hasResults) {
115
+ const currentDate = new Date().toISOString().split('T')[0];
116
+ const filePath = path_1.default.join(__dirname, `rename ${options.from} to ${options.to} ${currentDate}.json`);
117
+ fs_1.default.writeFileSync(filePath, JSON.stringify(results, null, 2), 'utf-8');
118
+ console.info(`Rename changes saved to: ${styles.success(` ${filePath}`)}`);
119
+ }
120
+ if (options.validate && !options.dryRun) {
121
+ const validationJob = await (0, validate_1.requestValidation)(projectUuid, [], []);
122
+ const { jobId } = validationJob;
123
+ await waitUntilFinished(jobId);
124
+ const validation = await (0, validate_1.getValidation)(projectUuid, jobId);
125
+ console.info(validation);
126
+ }
127
+ await analytics_1.LightdashAnalytics.track({
128
+ event: 'rename.completed',
129
+ properties: {
130
+ executionId,
131
+ projectId: projectUuid,
132
+ renameType: options.type,
133
+ isDryRun: options.dryRun,
134
+ chartsUpdated: results.charts.length,
135
+ dashboardsUpdated: results.dashboards.length,
136
+ durationMs: Date.now() - startTime,
137
+ },
138
+ });
139
+ }
140
+ catch (e) {
141
+ await analytics_1.LightdashAnalytics.track({
142
+ event: 'rename.error',
143
+ properties: {
144
+ executionId,
145
+ error: (0, common_1.getErrorMessage)(e),
146
+ errorCategory: (0, analytics_1.categorizeError)(e),
147
+ },
148
+ });
149
+ const errorString = `${e}`;
150
+ if (errorString.includes(`Rename failed`)) {
151
+ console.error(errorString);
152
+ if (errorString.includes('was found on multiple models'))
153
+ console.info(`Use argument ${styles.bold('--model')} to specify a model to filter on`);
154
+ }
155
+ else {
156
+ console.error('Unable to rename, unexpected error:', e);
157
+ }
158
+ }
159
+ };
160
+ exports.renameHandler = renameHandler;
@@ -0,0 +1,10 @@
1
+ type RunChartOptions = {
2
+ path: string;
3
+ output?: string;
4
+ limit?: number;
5
+ pageSize?: number;
6
+ verbose?: boolean;
7
+ };
8
+ export declare const runChartHandler: (options: RunChartOptions) => Promise<void>;
9
+ export {};
10
+ //# sourceMappingURL=runChart.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runChart.d.ts","sourceRoot":"","sources":["../../src/handlers/runChart.ts"],"names":[],"mappings":"AAaA,KAAK,eAAe,GAAG;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAIF,eAAO,MAAM,eAAe,GACxB,SAAS,eAAe,KACzB,OAAO,CAAC,IAAI,CAuHd,CAAC"}