@lightdash/cli 0.1444.1 → 0.1445.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -3,7 +3,8 @@ export type DownloadHandlerOptions = {
3
3
  charts: string[];
4
4
  dashboards: string[];
5
5
  force: boolean;
6
+ path?: string;
6
7
  };
7
- export declare const downloadContent: (ids: string[], type: 'charts' | 'dashboards', projectId: string) => Promise<[number, string[]]>;
8
+ export declare const downloadContent: (ids: string[], type: 'charts' | 'dashboards', projectId: string, customPath?: string) => Promise<[number, string[]]>;
8
9
  export declare const downloadHandler: (options: DownloadHandlerOptions) => Promise<void>;
9
10
  export declare const uploadHandler: (options: DownloadHandlerOptions) => Promise<void>;
@@ -13,7 +13,14 @@ const config_1 = require("../config");
13
13
  const globalState_1 = tslib_1.__importDefault(require("../globalState"));
14
14
  const styles = tslib_1.__importStar(require("../styles"));
15
15
  const apiClient_1 = require("./dbt/apiClient");
16
- const DOWNLOAD_FOLDER = 'lightdash';
16
+ const getDownloadFolder = (customPath) => {
17
+ if (customPath) {
18
+ return path.isAbsolute(customPath)
19
+ ? customPath
20
+ : path.join(process.cwd(), customPath);
21
+ }
22
+ return path.join(process.cwd(), 'lightdash');
23
+ };
17
24
  /*
18
25
  This function is used to parse the content filters.
19
26
  It can be slugs, uuids or urls
@@ -28,8 +35,8 @@ const parseContentFilters = (items) => {
28
35
  });
29
36
  return `?${new URLSearchParams(parsedItems.map((item) => ['ids', item])).toString()}`;
30
37
  };
31
- const dumpIntoFiles = async (folder, items) => {
32
- const outputDir = path.join(process.cwd(), DOWNLOAD_FOLDER, folder);
38
+ const dumpIntoFiles = async (folder, items, customPath) => {
39
+ const outputDir = path.join(getDownloadFolder(customPath), folder);
33
40
  globalState_1.default.debug(`Writing ${items.length} ${folder} into ${outputDir}`);
34
41
  // Make directory
35
42
  const created = await fs_1.promises.mkdir(outputDir, { recursive: true });
@@ -43,8 +50,8 @@ const dumpIntoFiles = async (folder, items) => {
43
50
  await fs_1.promises.writeFile(itemPath, chartYml);
44
51
  }
45
52
  };
46
- const readCodeFiles = async (folder) => {
47
- const inputDir = path.join(process.cwd(), DOWNLOAD_FOLDER, folder);
53
+ const readCodeFiles = async (folder, customPath) => {
54
+ const inputDir = path.join(getDownloadFolder(customPath), folder);
48
55
  console.info(`Reading ${folder} from ${inputDir}`);
49
56
  const items = [];
50
57
  try {
@@ -88,7 +95,7 @@ const readCodeFiles = async (folder) => {
88
95
  return items;
89
96
  };
90
97
  const downloadContent = async (ids, // slug, uuid or url
91
- type, projectId) => {
98
+ type, projectId, customPath) => {
92
99
  const spinner = globalState_1.default.getActiveSpinner();
93
100
  const contentFilters = parseContentFilters(ids);
94
101
  let contentAsCode;
@@ -109,7 +116,7 @@ type, projectId) => {
109
116
  console.warn(styles.warning(`\nNo chart with id "${missingId}"`));
110
117
  });
111
118
  if ('dashboards' in contentAsCode) {
112
- await dumpIntoFiles('dashboards', contentAsCode.dashboards);
119
+ await dumpIntoFiles('dashboards', contentAsCode.dashboards, customPath);
113
120
  // Extract chart slugs from dashboards
114
121
  chartSlugs = contentAsCode.dashboards.reduce((acc, dashboard) => {
115
122
  const slugs = dashboard.tiles.map((chart) => 'chartSlug' in chart.properties
@@ -122,7 +129,7 @@ type, projectId) => {
122
129
  }, chartSlugs);
123
130
  }
124
131
  else {
125
- await dumpIntoFiles('charts', contentAsCode.charts);
132
+ await dumpIntoFiles('charts', contentAsCode.charts, customPath);
126
133
  }
127
134
  offset = contentAsCode.offset;
128
135
  } while (contentAsCode.offset < contentAsCode.total);
@@ -162,7 +169,7 @@ const downloadHandler = async (options) => {
162
169
  }
163
170
  else {
164
171
  const spinner = globalState_1.default.startSpinner(`Downloading charts`);
165
- [chartTotal] = await (0, exports.downloadContent)(options.charts, 'charts', projectId);
172
+ [chartTotal] = await (0, exports.downloadContent)(options.charts, 'charts', projectId, options.path);
166
173
  spinner.succeed(`Downloaded ${chartTotal} charts`);
167
174
  }
168
175
  // Download dashboards
@@ -172,13 +179,13 @@ const downloadHandler = async (options) => {
172
179
  else {
173
180
  const spinner = globalState_1.default.startSpinner(`Downloading dashboards`);
174
181
  let chartSlugs = [];
175
- [dashboardTotal, chartSlugs] = await (0, exports.downloadContent)(options.dashboards, 'dashboards', projectId);
182
+ [dashboardTotal, chartSlugs] = await (0, exports.downloadContent)(options.dashboards, 'dashboards', projectId, options.path);
176
183
  spinner.succeed(`Downloaded ${dashboardTotal} dashboards`);
177
184
  // If any filter is provided, we download all charts for these dashboard
178
185
  // We don't need to do this if we download everything (no filters)
179
186
  if (hasFilters) {
180
187
  spinner.start(`Downloading ${chartSlugs.length} charts linked to dashboards`);
181
- const [totalCharts] = await (0, exports.downloadContent)(chartSlugs, 'charts', projectId);
188
+ const [totalCharts] = await (0, exports.downloadContent)(chartSlugs, 'charts', projectId, options.path);
182
189
  spinner.succeed(`Downloaded ${totalCharts} charts linked to dashboards`);
183
190
  }
184
191
  }
@@ -207,7 +214,6 @@ const downloadHandler = async (options) => {
207
214
  },
208
215
  });
209
216
  }
210
- // TODO delete files if chart don't exist ?*/
211
217
  };
212
218
  exports.downloadHandler = downloadHandler;
213
219
  const getPromoteAction = (action) => {
@@ -255,9 +261,9 @@ const logUploadChanges = (changes) => {
255
261
  *
256
262
  * @param slugs if slugs are provided, we only force upsert the charts/dashboards that match the slugs, if slugs are empty, we upload files that were locally updated
257
263
  */
258
- const upsertResources = async (type, projectId, changes, force, slugs) => {
264
+ const upsertResources = async (type, projectId, changes, force, slugs, customPath) => {
259
265
  const config = await (0, config_1.getConfig)();
260
- const items = await readCodeFiles(type);
266
+ const items = await readCodeFiles(type, customPath);
261
267
  console.info(`Found ${items.length} ${type} files`);
262
268
  const hasFilter = slugs.length > 0;
263
269
  const filteredItems = hasFilter
@@ -342,7 +348,7 @@ const uploadHandler = async (options) => {
342
348
  console.info(styles.warning(`No charts filters provided, skipping`));
343
349
  }
344
350
  else {
345
- const { changes: chartChanges, total } = await upsertResources('charts', projectId, changes, options.force, options.charts);
351
+ const { changes: chartChanges, total } = await upsertResources('charts', projectId, changes, options.force, options.charts, options.path);
346
352
  changes = chartChanges;
347
353
  chartTotal = total;
348
354
  }
@@ -350,7 +356,7 @@ const uploadHandler = async (options) => {
350
356
  console.info(styles.warning(`No dashboard filters provided, skipping`));
351
357
  }
352
358
  else {
353
- const { changes: dashboardChanges, total } = await upsertResources('dashboards', projectId, changes, options.force, options.dashboards);
359
+ const { changes: dashboardChanges, total } = await upsertResources('dashboards', projectId, changes, options.force, options.dashboards, options.path);
354
360
  changes = dashboardChanges;
355
361
  dashboardTotal = total;
356
362
  }
package/dist/index.js CHANGED
@@ -198,6 +198,7 @@ commander_1.program
198
198
  .option('--verbose', undefined, false)
199
199
  .option('-c, --charts <charts...>', 'specify chart slugs, uuids, or urls to download', [])
200
200
  .option('-d, --dashboards <dashboards...>', 'specify dashboard slugs, uuids or urls to download', [])
201
+ .option('-p, --path <path>', 'specify a custom path to download charts and dashboards', undefined)
201
202
  .action(download_1.downloadHandler);
202
203
  commander_1.program
203
204
  .command('upload')
@@ -206,6 +207,7 @@ commander_1.program
206
207
  .option('-c, --charts <charts...>', 'specify chart slugs to force upload', [])
207
208
  .option('-d, --dashboards <dashboards...>', 'specify dashboard slugs to force upload', [])
208
209
  .option('--force', 'Force upload even if local files have not changed, use this when you want to upload files to a new project', false)
210
+ .option('-p, --path <path>', 'specify a custom path to upload charts and dashboards from', undefined)
209
211
  .action(download_1.uploadHandler);
210
212
  commander_1.program
211
213
  .command('deploy')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lightdash/cli",
3
- "version": "0.1444.1",
3
+ "version": "0.1445.0",
4
4
  "license": "MIT",
5
5
  "bin": {
6
6
  "lightdash": "dist/index.js"
@@ -11,8 +11,8 @@
11
11
  ],
12
12
  "dependencies": {
13
13
  "@actions/core": "^1.11.1",
14
- "@lightdash/common": "^0.1444.1",
15
- "@lightdash/warehouses": "^0.1444.1",
14
+ "@lightdash/common": "^0.1445.0",
15
+ "@lightdash/warehouses": "^0.1445.0",
16
16
  "@types/columnify": "^1.5.1",
17
17
  "ajv": "^8.11.0",
18
18
  "ajv-formats": "^2.1.1",