@lightdash/cli 0.1444.1 → 0.1445.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.
- 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",
|