@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.
- package/dist/handlers/download.d.ts +2 -1
- package/dist/handlers/download.js +22 -16
- package/dist/index.js +2 -0
- package/package.json +3 -3
@@ -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
|
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(
|
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(
|
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.
|
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.
|
15
|
-
"@lightdash/warehouses": "^0.
|
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",
|