@lightdash/cli 0.2644.1 → 0.2646.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/.tsbuildinfo +1 -1
- package/dist/config.d.ts +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +13 -1
- package/dist/handlers/download.d.ts +6 -1
- package/dist/handlers/download.d.ts.map +1 -1
- package/dist/handlers/download.js +100 -24
- package/dist/handlers/login.d.ts.map +1 -1
- package/dist/handlers/login.js +5 -2
- package/dist/handlers/metadataFile.d.ts +9 -0
- package/dist/handlers/metadataFile.d.ts.map +1 -0
- package/dist/handlers/metadataFile.js +34 -0
- package/dist/handlers/renameHandler.d.ts.map +1 -1
- package/dist/handlers/renameHandler.js +6 -1
- package/dist/handlers/setProject.d.ts +5 -1
- package/dist/handlers/setProject.d.ts.map +1 -1
- package/dist/handlers/setProject.js +51 -10
- package/dist/index.js +8 -1
- package/package.json +3 -3
package/dist/config.d.ts
CHANGED
|
@@ -24,6 +24,7 @@ export type Config = {
|
|
|
24
24
|
};
|
|
25
25
|
export declare const getConfig: () => Promise<Config>;
|
|
26
26
|
export declare const setProject: (projectUuid: string, projectName: string) => Promise<void>;
|
|
27
|
+
export declare const unsetProject: () => Promise<void>;
|
|
27
28
|
export declare const setPreviewProject: (projectUuid: string, name: string) => Promise<void>;
|
|
28
29
|
export declare const unsetPreviewProject: () => Promise<void>;
|
|
29
30
|
export declare const setDefaultUser: (userUuid: string, organizationUuid: string) => Promise<void>;
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,cAAc,QAAsC,CAAC;AAElE,MAAM,MAAM,MAAM,GAAG;IACjB,IAAI,CAAC,EAAE;QACH,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;KAC7B,CAAC;IACF,OAAO,CAAC,EAAE;QACN,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB;;;WAGG;QACH,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAC5B,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,WAAW,CAAC,EAAE,MAAM,CAAC;KACxB,CAAC;IACF,OAAO,CAAC,EAAE;QACN,qCAAqC,CAAC,EAAE,OAAO,CAAC;KACnD,CAAC;CACL,CAAC;AAgCF,eAAO,MAAM,SAAS,QAAa,OAAO,CAAC,MAAM,CAmBhD,CAAC;AAEF,eAAO,MAAM,UAAU,GAAU,aAAa,MAAM,EAAE,aAAa,MAAM,kBAUxE,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAU,aAAa,MAAM,EAAE,MAAM,MAAM,kBAUxE,CAAC;AAEF,eAAO,MAAM,mBAAmB,qBAU/B,CAAC;AAEF,eAAO,MAAM,cAAc,GACvB,UAAU,MAAM,EAChB,kBAAkB,MAAM,kBAW3B,CAAC;AAEF,eAAO,MAAM,UAAU,GAAU,SAAS,MAAM,CAAC,SAAS,CAAC,kBAM1D,CAAC;AAEF,eAAO,MAAM,SAAS,GAAU,QAAQ,MAAM,CAAC,SAAS,CAAC,kBAMxD,CAAC"}
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,cAAc,QAAsC,CAAC;AAElE,MAAM,MAAM,MAAM,GAAG;IACjB,IAAI,CAAC,EAAE;QACH,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;KAC7B,CAAC;IACF,OAAO,CAAC,EAAE;QACN,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB;;;WAGG;QACH,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAC5B,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,WAAW,CAAC,EAAE,MAAM,CAAC;KACxB,CAAC;IACF,OAAO,CAAC,EAAE;QACN,qCAAqC,CAAC,EAAE,OAAO,CAAC;KACnD,CAAC;CACL,CAAC;AAgCF,eAAO,MAAM,SAAS,QAAa,OAAO,CAAC,MAAM,CAmBhD,CAAC;AAEF,eAAO,MAAM,UAAU,GAAU,aAAa,MAAM,EAAE,aAAa,MAAM,kBAUxE,CAAC;AAEF,eAAO,MAAM,YAAY,qBAUxB,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAU,aAAa,MAAM,EAAE,MAAM,MAAM,kBAUxE,CAAC;AAEF,eAAO,MAAM,mBAAmB,qBAU/B,CAAC;AAEF,eAAO,MAAM,cAAc,GACvB,UAAU,MAAM,EAChB,kBAAkB,MAAM,kBAW3B,CAAC;AAEF,eAAO,MAAM,UAAU,GAAU,SAAS,MAAM,CAAC,SAAS,CAAC,kBAM1D,CAAC;AAEF,eAAO,MAAM,SAAS,GAAU,QAAQ,MAAM,CAAC,SAAS,CAAC,kBAMxD,CAAC"}
|
package/dist/config.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.setAnswer = exports.setContext = exports.setDefaultUser = exports.unsetPreviewProject = exports.setPreviewProject = exports.setProject = exports.getConfig = exports.configFilePath = void 0;
|
|
3
|
+
exports.setAnswer = exports.setContext = exports.setDefaultUser = exports.unsetPreviewProject = exports.setPreviewProject = exports.unsetProject = exports.setProject = exports.getConfig = exports.configFilePath = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const fs_1 = require("fs");
|
|
6
6
|
const yaml = tslib_1.__importStar(require("js-yaml"));
|
|
@@ -68,6 +68,18 @@ const setProject = async (projectUuid, projectName) => {
|
|
|
68
68
|
});
|
|
69
69
|
};
|
|
70
70
|
exports.setProject = setProject;
|
|
71
|
+
const unsetProject = async () => {
|
|
72
|
+
const config = await getRawConfig();
|
|
73
|
+
await setConfig({
|
|
74
|
+
...config,
|
|
75
|
+
context: {
|
|
76
|
+
...(config.context || {}),
|
|
77
|
+
project: undefined,
|
|
78
|
+
projectName: undefined,
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
|
+
};
|
|
82
|
+
exports.unsetProject = unsetProject;
|
|
71
83
|
const setPreviewProject = async (projectUuid, name) => {
|
|
72
84
|
const config = await getRawConfig();
|
|
73
85
|
await setConfig({
|
|
@@ -14,8 +14,13 @@ export type DownloadHandlerOptions = {
|
|
|
14
14
|
concurrency: number;
|
|
15
15
|
gzip?: boolean;
|
|
16
16
|
};
|
|
17
|
+
type MetadataEntry = {
|
|
18
|
+
slug: string;
|
|
19
|
+
type: 'charts' | 'dashboards';
|
|
20
|
+
downloadedAt: string;
|
|
21
|
+
};
|
|
17
22
|
type DownloadContentType = 'charts' | 'dashboards' | 'sqlCharts';
|
|
18
|
-
export declare const downloadContent: (ids: string[], type: DownloadContentType, projectId: string, projectName: string, customPath?: string, languageMap?: boolean, nested?: boolean) => Promise<[number, string[]]>;
|
|
23
|
+
export declare const downloadContent: (ids: string[], type: DownloadContentType, projectId: string, projectName: string, customPath?: string, languageMap?: boolean, nested?: boolean) => Promise<[number, string[], MetadataEntry[]]>;
|
|
19
24
|
export declare const downloadHandler: (options: DownloadHandlerOptions) => Promise<void>;
|
|
20
25
|
export declare const uploadHandler: (options: DownloadHandlerOptions) => Promise<void>;
|
|
21
26
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"download.d.ts","sourceRoot":"","sources":["../../src/handlers/download.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"download.d.ts","sourceRoot":"","sources":["../../src/handlers/download.ts"],"names":[],"mappings":"AA2CA,MAAM,MAAM,sBAAsB,GAAG;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,OAAO,CAAC;IACrB,eAAe,EAAE,OAAO,CAAC;IACzB,MAAM,EAAE,OAAO,CAAC;IAChB,aAAa,EAAE,OAAO,CAAC;IACvB,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AA2FF,KAAK,aAAa,GAAG;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,GAAG,YAAY,CAAC;IAC9B,YAAY,EAAE,MAAM,CAAC;CACxB,CAAC;AAyOF,KAAK,mBAAmB,GAAG,QAAQ,GAAG,YAAY,GAAG,WAAW,CAAC;AAkDjE,eAAO,MAAM,eAAe,GACxB,KAAK,MAAM,EAAE,EACb,MAAM,mBAAmB,EACzB,WAAW,MAAM,EACjB,aAAa,MAAM,EACnB,aAAa,MAAM,EACnB,cAAa,OAAe,EAC5B,SAAQ,OAAe,KACxB,OAAO,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,aAAa,EAAE,CAAC,CA+G7C,CAAC;AAEF,eAAO,MAAM,eAAe,GACxB,SAAS,sBAAsB,KAChC,OAAO,CAAC,IAAI,CAmMd,CAAC;AA4ZF,eAAO,MAAM,aAAa,GACtB,SAAS,sBAAsB,KAChC,OAAO,CAAC,IAAI,CAkJd,CAAC"}
|
|
@@ -15,6 +15,7 @@ const config_1 = require("../config");
|
|
|
15
15
|
const globalState_1 = tslib_1.__importDefault(require("../globalState"));
|
|
16
16
|
const styles = tslib_1.__importStar(require("../styles"));
|
|
17
17
|
const apiClient_1 = require("./dbt/apiClient");
|
|
18
|
+
const metadataFile_1 = require("./metadataFile");
|
|
18
19
|
const selectProject_1 = require("./selectProject");
|
|
19
20
|
const getDownloadFolder = (customPath) => {
|
|
20
21
|
if (customPath) {
|
|
@@ -71,29 +72,69 @@ const getFileExtension = (contentType) => {
|
|
|
71
72
|
const writeContent = async (contentAsCode, outputDir, languageMap) => {
|
|
72
73
|
const extension = getFileExtension(contentAsCode.type);
|
|
73
74
|
const itemPath = path.join(outputDir, `${contentAsCode.content.slug}${extension}`);
|
|
74
|
-
|
|
75
|
+
// Strip timestamps — they go to .lightdash-metadata.json instead
|
|
76
|
+
const { updatedAt, downloadedAt, ...cleanContent } = contentAsCode.content;
|
|
77
|
+
const chartYml = yaml.dump(cleanContent, {
|
|
75
78
|
quotingType: '"',
|
|
79
|
+
sortKeys: true,
|
|
76
80
|
});
|
|
77
81
|
await fs_1.promises.writeFile(itemPath, chartYml);
|
|
78
82
|
if (contentAsCode.translationMap && languageMap) {
|
|
79
83
|
const translationPath = path.join(outputDir, `${contentAsCode.content.slug}.language.map.yml`);
|
|
80
|
-
await fs_1.promises.writeFile(translationPath, yaml.dump(contentAsCode.translationMap));
|
|
84
|
+
await fs_1.promises.writeFile(translationPath, yaml.dump(contentAsCode.translationMap, { sortKeys: true }));
|
|
81
85
|
}
|
|
86
|
+
const metadataType = contentAsCode.type === 'dashboard' ? 'dashboards' : 'charts';
|
|
87
|
+
let downloadedAtString;
|
|
88
|
+
if (downloadedAt instanceof Date) {
|
|
89
|
+
downloadedAtString = downloadedAt.toISOString();
|
|
90
|
+
}
|
|
91
|
+
else if (typeof downloadedAt === 'string') {
|
|
92
|
+
downloadedAtString = downloadedAt;
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
downloadedAtString = new Date().toISOString();
|
|
96
|
+
}
|
|
97
|
+
return {
|
|
98
|
+
slug: contentAsCode.content.slug,
|
|
99
|
+
type: metadataType,
|
|
100
|
+
downloadedAt: downloadedAtString,
|
|
101
|
+
};
|
|
102
|
+
};
|
|
103
|
+
const hasUnsortedKeys = (obj) => {
|
|
104
|
+
if (typeof obj !== 'object' || obj === null || Array.isArray(obj)) {
|
|
105
|
+
if (Array.isArray(obj)) {
|
|
106
|
+
return obj.some(hasUnsortedKeys);
|
|
107
|
+
}
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
const keys = Object.keys(obj);
|
|
111
|
+
const sorted = [...keys].sort();
|
|
112
|
+
if (keys.some((key, i) => key !== sorted[i])) {
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
115
|
+
return Object.values(obj).some(hasUnsortedKeys);
|
|
82
116
|
};
|
|
83
117
|
const isLightdashContentFile = (folder, entry) => entry.isFile() &&
|
|
84
118
|
entry.parentPath &&
|
|
85
119
|
entry.parentPath.endsWith(path.sep + folder) &&
|
|
86
120
|
entry.name.endsWith('.yml') &&
|
|
87
121
|
!entry.name.endsWith('.language.map.yml');
|
|
88
|
-
const loadYamlFile = async (file) => {
|
|
122
|
+
const loadYamlFile = async (file, folder, metadata) => {
|
|
89
123
|
const filePath = path.join(file.parentPath, file.name);
|
|
90
124
|
const [fileContent, stats] = await Promise.all([
|
|
91
125
|
fs_1.promises.readFile(filePath, 'utf-8'),
|
|
92
126
|
fs_1.promises.stat(filePath),
|
|
93
127
|
]);
|
|
94
128
|
const item = yaml.load(fileContent);
|
|
95
|
-
|
|
96
|
-
|
|
129
|
+
if (hasUnsortedKeys(item)) {
|
|
130
|
+
globalState_1.default.log(styles.warning(`Warning: ${file.name} has unsorted YAML keys. Re-download to fix, or sort keys alphabetically.`));
|
|
131
|
+
}
|
|
132
|
+
const metadataSection = folder === 'dashboards' ? metadata.dashboards : metadata.charts;
|
|
133
|
+
const downloadedAtRaw = metadataSection[item.slug] ?? item.downloadedAt;
|
|
134
|
+
const downloadedAt = downloadedAtRaw
|
|
135
|
+
? new Date(downloadedAtRaw instanceof Date
|
|
136
|
+
? downloadedAtRaw.getTime()
|
|
137
|
+
: downloadedAtRaw)
|
|
97
138
|
: undefined;
|
|
98
139
|
const needsUpdating = downloadedAt &&
|
|
99
140
|
Math.abs(stats.mtime.getTime() - downloadedAt.getTime()) > 30000;
|
|
@@ -111,13 +152,14 @@ const readCodeFiles = async (folder, customPath) => {
|
|
|
111
152
|
throw new Error(`Node.js v20.12.0 or later is required for this command (current: ${process.version}).`);
|
|
112
153
|
}
|
|
113
154
|
try {
|
|
155
|
+
const metadata = await (0, metadataFile_1.readMetadataFile)(baseDir);
|
|
114
156
|
const allEntries = await fs_1.promises.readdir(baseDir, {
|
|
115
157
|
recursive: true,
|
|
116
158
|
withFileTypes: true,
|
|
117
159
|
});
|
|
118
160
|
const items = await Promise.all(allEntries
|
|
119
161
|
.filter((entry) => isLightdashContentFile(folder, entry))
|
|
120
|
-
.map((file) => loadYamlFile(file)));
|
|
162
|
+
.map((file) => loadYamlFile(file, folder, metadata)));
|
|
121
163
|
if (items.length === 0) {
|
|
122
164
|
console.error(styles.warning(`Unable to upload ${folder}, no files found in "${baseDir}". Run download command first.`));
|
|
123
165
|
}
|
|
@@ -140,16 +182,19 @@ const groupBySpace = (items) => {
|
|
|
140
182
|
};
|
|
141
183
|
const writeSpaceContent = async ({ projectName, spaceSlug, folder, contentType, contentInSpace, contentAsCode, customPath, languageMap, folderScheme, }) => {
|
|
142
184
|
const outputDir = await createDirForContent(projectName, spaceSlug, folder, customPath, folderScheme);
|
|
185
|
+
const entries = [];
|
|
143
186
|
for (const { item, index } of contentInSpace) {
|
|
144
187
|
const translationMap = 'languageMap' in contentAsCode
|
|
145
188
|
? contentAsCode.languageMap?.[index]
|
|
146
189
|
: undefined;
|
|
147
|
-
await writeContent({
|
|
190
|
+
const entry = await writeContent({
|
|
148
191
|
type: contentType,
|
|
149
192
|
content: item,
|
|
150
193
|
translationMap,
|
|
151
194
|
}, outputDir, languageMap);
|
|
195
|
+
entries.push(entry);
|
|
152
196
|
}
|
|
197
|
+
return entries;
|
|
153
198
|
};
|
|
154
199
|
const getContentTypeConfig = (type, projectId) => {
|
|
155
200
|
switch (type) {
|
|
@@ -191,6 +236,7 @@ const downloadContent = async (ids, type, projectId, projectName, customPath, la
|
|
|
191
236
|
let offset = 0;
|
|
192
237
|
let total = 0;
|
|
193
238
|
let chartSlugs = [];
|
|
239
|
+
let allMetadataEntries = [];
|
|
194
240
|
do {
|
|
195
241
|
globalState_1.default.debug(`Downloading ${config.displayName} with offset "${offset}" and filters "${contentFilters}"`);
|
|
196
242
|
const commonParams = config.supportsLanguageMap
|
|
@@ -214,7 +260,7 @@ const downloadContent = async (ids, type, projectId, projectName, customPath, la
|
|
|
214
260
|
if ('sqlCharts' in results) {
|
|
215
261
|
const sqlChartsBySpace = groupBySpace(results.sqlCharts);
|
|
216
262
|
for (const [spaceSlug, sqlChartsInSpace] of Object.entries(sqlChartsBySpace)) {
|
|
217
|
-
await writeSpaceContent({
|
|
263
|
+
const entries = await writeSpaceContent({
|
|
218
264
|
projectName,
|
|
219
265
|
spaceSlug,
|
|
220
266
|
folder: 'charts',
|
|
@@ -225,12 +271,13 @@ const downloadContent = async (ids, type, projectId, projectName, customPath, la
|
|
|
225
271
|
languageMap,
|
|
226
272
|
folderScheme,
|
|
227
273
|
});
|
|
274
|
+
allMetadataEntries = [...allMetadataEntries, ...entries];
|
|
228
275
|
}
|
|
229
276
|
}
|
|
230
277
|
else if ('dashboards' in results) {
|
|
231
278
|
const dashboardsBySpace = groupBySpace(results.dashboards);
|
|
232
279
|
for (const [spaceSlug, dashboardsInSpace] of Object.entries(dashboardsBySpace)) {
|
|
233
|
-
await writeSpaceContent({
|
|
280
|
+
const entries = await writeSpaceContent({
|
|
234
281
|
projectName,
|
|
235
282
|
spaceSlug,
|
|
236
283
|
folder: 'dashboards',
|
|
@@ -241,6 +288,7 @@ const downloadContent = async (ids, type, projectId, projectName, customPath, la
|
|
|
241
288
|
languageMap,
|
|
242
289
|
folderScheme,
|
|
243
290
|
});
|
|
291
|
+
allMetadataEntries = [...allMetadataEntries, ...entries];
|
|
244
292
|
}
|
|
245
293
|
chartSlugs = [
|
|
246
294
|
...chartSlugs,
|
|
@@ -250,7 +298,7 @@ const downloadContent = async (ids, type, projectId, projectName, customPath, la
|
|
|
250
298
|
else {
|
|
251
299
|
const chartsBySpace = groupBySpace(results.charts);
|
|
252
300
|
for (const [spaceSlug, chartsInSpace] of Object.entries(chartsBySpace)) {
|
|
253
|
-
await writeSpaceContent({
|
|
301
|
+
const entries = await writeSpaceContent({
|
|
254
302
|
projectName,
|
|
255
303
|
spaceSlug,
|
|
256
304
|
folder: 'charts',
|
|
@@ -261,12 +309,13 @@ const downloadContent = async (ids, type, projectId, projectName, customPath, la
|
|
|
261
309
|
languageMap,
|
|
262
310
|
folderScheme,
|
|
263
311
|
});
|
|
312
|
+
allMetadataEntries = [...allMetadataEntries, ...entries];
|
|
264
313
|
}
|
|
265
314
|
}
|
|
266
315
|
offset = results.offset;
|
|
267
316
|
total = results.total;
|
|
268
317
|
} while (offset < total);
|
|
269
|
-
return [total, [...new Set(chartSlugs)]];
|
|
318
|
+
return [total, [...new Set(chartSlugs)], allMetadataEntries];
|
|
270
319
|
};
|
|
271
320
|
exports.downloadContent = downloadContent;
|
|
272
321
|
const downloadHandler = async (options) => {
|
|
@@ -278,7 +327,12 @@ const downloadHandler = async (options) => {
|
|
|
278
327
|
}
|
|
279
328
|
const projectSelection = await (0, selectProject_1.selectProject)(config, options.project);
|
|
280
329
|
if (!projectSelection) {
|
|
281
|
-
throw new
|
|
330
|
+
throw new common_1.LightdashError({
|
|
331
|
+
message: 'No project selected. Run lightdash config set-project',
|
|
332
|
+
name: 'Not Found',
|
|
333
|
+
statusCode: 404,
|
|
334
|
+
data: {},
|
|
335
|
+
});
|
|
282
336
|
}
|
|
283
337
|
const projectId = projectSelection.projectUuid;
|
|
284
338
|
// Log current project info
|
|
@@ -305,20 +359,21 @@ const downloadHandler = async (options) => {
|
|
|
305
359
|
},
|
|
306
360
|
});
|
|
307
361
|
try {
|
|
308
|
-
// If any filter is provided, we skip those items without filters
|
|
309
|
-
// eg: if a --charts filter is provided, we skip dashboards if no --dashboards filter is provided
|
|
310
362
|
const hasFilters = options.charts.length > 0 || options.dashboards.length > 0;
|
|
363
|
+
let allMetadataEntries = [];
|
|
311
364
|
// Download regular charts
|
|
312
365
|
if (hasFilters && options.charts.length === 0) {
|
|
313
366
|
console.info(styles.warning(`No charts filters provided, skipping`));
|
|
314
367
|
}
|
|
315
368
|
else {
|
|
316
|
-
const [regularChartTotal] = await (0, exports.downloadContent)(options.charts, 'charts', projectId, projectName, options.path, options.languageMap, options.nested);
|
|
369
|
+
const [regularChartTotal, , regularChartMeta] = await (0, exports.downloadContent)(options.charts, 'charts', projectId, projectName, options.path, options.languageMap, options.nested);
|
|
317
370
|
spinner.succeed(`Downloaded ${regularChartTotal} charts`);
|
|
371
|
+
allMetadataEntries = [...allMetadataEntries, ...regularChartMeta];
|
|
318
372
|
// Download SQL charts
|
|
319
373
|
spinner.start(`Downloading SQL charts`);
|
|
320
|
-
const [sqlChartTotal] = await (0, exports.downloadContent)(options.charts, 'sqlCharts', projectId, projectName, options.path, options.languageMap, options.nested);
|
|
374
|
+
const [sqlChartTotal, , sqlChartMeta] = await (0, exports.downloadContent)(options.charts, 'sqlCharts', projectId, projectName, options.path, options.languageMap, options.nested);
|
|
321
375
|
spinner.succeed(`Downloaded ${sqlChartTotal} SQL charts`);
|
|
376
|
+
allMetadataEntries = [...allMetadataEntries, ...sqlChartMeta];
|
|
322
377
|
chartTotal = regularChartTotal + sqlChartTotal;
|
|
323
378
|
}
|
|
324
379
|
// Download dashboards
|
|
@@ -327,18 +382,34 @@ const downloadHandler = async (options) => {
|
|
|
327
382
|
}
|
|
328
383
|
else {
|
|
329
384
|
let chartSlugs = [];
|
|
330
|
-
|
|
385
|
+
let dashMeta;
|
|
386
|
+
[dashboardTotal, chartSlugs, dashMeta] = await (0, exports.downloadContent)(options.dashboards, 'dashboards', projectId, projectName, options.path, options.languageMap, options.nested);
|
|
387
|
+
allMetadataEntries = [...allMetadataEntries, ...dashMeta];
|
|
331
388
|
spinner.succeed(`Downloaded ${dashboardTotal} dashboards`);
|
|
332
|
-
// If any filter is provided, we download all charts linked to these dashboards
|
|
333
|
-
// We don't need to do this if we download everything (no filters)
|
|
334
389
|
if (hasFilters && chartSlugs.length > 0) {
|
|
335
390
|
spinner.start(`Downloading ${chartSlugs.length} charts linked to dashboards`);
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
391
|
+
const [regularCharts, , linkedChartMeta] = await (0, exports.downloadContent)(chartSlugs, 'charts', projectId, projectName, options.path, options.languageMap, options.nested);
|
|
392
|
+
allMetadataEntries = [
|
|
393
|
+
...allMetadataEntries,
|
|
394
|
+
...linkedChartMeta,
|
|
395
|
+
];
|
|
396
|
+
const [sqlCharts, , linkedSqlMeta] = await (0, exports.downloadContent)(chartSlugs, 'sqlCharts', projectId, projectName, options.path, options.languageMap, options.nested);
|
|
397
|
+
allMetadataEntries = [...allMetadataEntries, ...linkedSqlMeta];
|
|
339
398
|
spinner.succeed(`Downloaded ${regularCharts + sqlCharts} charts linked to dashboards`);
|
|
340
399
|
}
|
|
341
400
|
}
|
|
401
|
+
// Write metadata file with all downloadedAt timestamps
|
|
402
|
+
const metadataToWrite = {
|
|
403
|
+
version: 1,
|
|
404
|
+
charts: {},
|
|
405
|
+
dashboards: {},
|
|
406
|
+
};
|
|
407
|
+
for (const entry of allMetadataEntries) {
|
|
408
|
+
metadataToWrite[entry.type][entry.slug] = entry.downloadedAt;
|
|
409
|
+
}
|
|
410
|
+
const baseDir = getDownloadFolder(options.path);
|
|
411
|
+
await (0, metadataFile_1.writeMetadataFile)(baseDir, metadataToWrite);
|
|
412
|
+
globalState_1.default.log(styles.warning(`\nNote: ${metadataFile_1.METADATA_FILENAME} was written to ${baseDir}. Consider adding it to your .gitignore.`));
|
|
342
413
|
const end = Date.now();
|
|
343
414
|
await analytics_1.LightdashAnalytics.track({
|
|
344
415
|
event: 'download.completed',
|
|
@@ -348,7 +419,7 @@ const downloadHandler = async (options) => {
|
|
|
348
419
|
projectId,
|
|
349
420
|
chartsNum: chartTotal,
|
|
350
421
|
dashboardsNum: dashboardTotal,
|
|
351
|
-
timeToCompleted: (end - start) / 1000,
|
|
422
|
+
timeToCompleted: (end - start) / 1000,
|
|
352
423
|
},
|
|
353
424
|
});
|
|
354
425
|
}
|
|
@@ -612,7 +683,12 @@ const uploadHandler = async (options) => {
|
|
|
612
683
|
}
|
|
613
684
|
const projectSelection = await (0, selectProject_1.selectProject)(config, options.project);
|
|
614
685
|
if (!projectSelection) {
|
|
615
|
-
throw new
|
|
686
|
+
throw new common_1.LightdashError({
|
|
687
|
+
message: 'No project selected. Run lightdash config set-project',
|
|
688
|
+
name: 'Not Found',
|
|
689
|
+
statusCode: 404,
|
|
690
|
+
data: {},
|
|
691
|
+
});
|
|
616
692
|
}
|
|
617
693
|
const projectId = projectSelection.projectUuid;
|
|
618
694
|
// Log current project info
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/handlers/login.ts"],"names":[],"mappings":"AAkBA,KAAK,YAAY,GAAG;IAChB,uEAAuE;IACvE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qCAAqC;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yCAAyC;IACzC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+CAA+C;IAC/C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,OAAO,EAAE,OAAO,CAAC;CACpB,CAAC;AA4JF,eAAO,MAAM,KAAK,GACd,UAAU,MAAM,GAAG,SAAS,EAC5B,SAAS,YAAY,
|
|
1
|
+
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/handlers/login.ts"],"names":[],"mappings":"AAkBA,KAAK,YAAY,GAAG;IAChB,uEAAuE;IACvE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qCAAqC;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yCAAyC;IACzC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+CAA+C;IAC/C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,OAAO,EAAE,OAAO,CAAC;CACpB,CAAC;AA4JF,eAAO,MAAM,KAAK,GACd,UAAU,MAAM,GAAG,SAAS,EAC5B,SAAS,YAAY,kBA2JxB,CAAC"}
|
package/dist/handlers/login.js
CHANGED
|
@@ -221,11 +221,14 @@ const login = async (urlInput, options) => {
|
|
|
221
221
|
await (0, setProject_1.setFirstProject)();
|
|
222
222
|
}
|
|
223
223
|
else {
|
|
224
|
-
const
|
|
225
|
-
if (
|
|
224
|
+
const result = await (0, setProject_1.setProjectCommand)();
|
|
225
|
+
if (result === 'empty') {
|
|
226
226
|
console.error('Now you can add your first project to lightdash by doing: ');
|
|
227
227
|
console.error(`\n ${styles.bold(`⚡️ lightdash deploy --create`)}\n`);
|
|
228
228
|
}
|
|
229
|
+
else if (result === 'skipped') {
|
|
230
|
+
console.error(`\n No project selected — use ${styles.bold('lightdash config set-project')} or ${styles.bold('--project <uuid>')} when running commands.\n`);
|
|
231
|
+
}
|
|
229
232
|
}
|
|
230
233
|
}
|
|
231
234
|
catch {
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare const METADATA_FILENAME = ".lightdash-metadata.json";
|
|
2
|
+
export type LightdashMetadata = {
|
|
3
|
+
version: 1;
|
|
4
|
+
charts: Record<string, string>;
|
|
5
|
+
dashboards: Record<string, string>;
|
|
6
|
+
};
|
|
7
|
+
export declare const readMetadataFile: (baseDir: string) => Promise<LightdashMetadata>;
|
|
8
|
+
export declare const writeMetadataFile: (baseDir: string, metadata: LightdashMetadata) => Promise<void>;
|
|
9
|
+
//# sourceMappingURL=metadataFile.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadataFile.d.ts","sourceRoot":"","sources":["../../src/handlers/metadataFile.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,iBAAiB,6BAA6B,CAAC;AAE5D,MAAM,MAAM,iBAAiB,GAAG;IAC5B,OAAO,EAAE,CAAC,CAAC;IACX,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACtC,CAAC;AAQF,eAAO,MAAM,gBAAgB,GACzB,SAAS,MAAM,KAChB,OAAO,CAAC,iBAAiB,CAQ3B,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAC1B,SAAS,MAAM,EACf,UAAU,iBAAiB,KAC5B,OAAO,CAAC,IAAI,CASd,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.writeMetadataFile = exports.readMetadataFile = exports.METADATA_FILENAME = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const fs_1 = require("fs");
|
|
6
|
+
const path = tslib_1.__importStar(require("path"));
|
|
7
|
+
exports.METADATA_FILENAME = '.lightdash-metadata.json';
|
|
8
|
+
const emptyMetadata = () => ({
|
|
9
|
+
version: 1,
|
|
10
|
+
charts: {},
|
|
11
|
+
dashboards: {},
|
|
12
|
+
});
|
|
13
|
+
const readMetadataFile = async (baseDir) => {
|
|
14
|
+
const filePath = path.join(baseDir, exports.METADATA_FILENAME);
|
|
15
|
+
try {
|
|
16
|
+
const content = await fs_1.promises.readFile(filePath, 'utf-8');
|
|
17
|
+
return JSON.parse(content);
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return emptyMetadata();
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
exports.readMetadataFile = readMetadataFile;
|
|
24
|
+
const writeMetadataFile = async (baseDir, metadata) => {
|
|
25
|
+
const existing = await (0, exports.readMetadataFile)(baseDir);
|
|
26
|
+
const merged = {
|
|
27
|
+
version: 1,
|
|
28
|
+
charts: { ...existing.charts, ...metadata.charts },
|
|
29
|
+
dashboards: { ...existing.dashboards, ...metadata.dashboards },
|
|
30
|
+
};
|
|
31
|
+
const filePath = path.join(baseDir, exports.METADATA_FILENAME);
|
|
32
|
+
await fs_1.promises.writeFile(filePath, JSON.stringify(merged, null, 2));
|
|
33
|
+
};
|
|
34
|
+
exports.writeMetadataFile = writeMetadataFile;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"renameHandler.d.ts","sourceRoot":"","sources":["../../src/handlers/renameHandler.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
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"}
|
|
@@ -48,7 +48,12 @@ const renameHandler = async (options) => {
|
|
|
48
48
|
config.context.previewProject ||
|
|
49
49
|
config.context.project;
|
|
50
50
|
if (!projectUuid) {
|
|
51
|
-
throw new
|
|
51
|
+
throw new common_1.LightdashError({
|
|
52
|
+
message: 'No project selected. Run lightdash config set-project',
|
|
53
|
+
name: 'Not Found',
|
|
54
|
+
statusCode: 404,
|
|
55
|
+
data: {},
|
|
56
|
+
});
|
|
52
57
|
}
|
|
53
58
|
// Log current project info
|
|
54
59
|
if (options.project) {
|
|
@@ -3,8 +3,12 @@ type SetProjectOptions = {
|
|
|
3
3
|
name: string;
|
|
4
4
|
uuid: string;
|
|
5
5
|
};
|
|
6
|
-
export declare const setProjectCommand: (name?: string, uuid?: string) => Promise<
|
|
6
|
+
export declare const setProjectCommand: (name?: string, uuid?: string) => Promise<"selected" | "skipped" | "empty">;
|
|
7
7
|
export declare const setFirstProject: () => Promise<void>;
|
|
8
8
|
export declare const setProjectHandler: (options: SetProjectOptions) => Promise<void>;
|
|
9
|
+
export declare const unsetProjectCommand: () => Promise<void>;
|
|
10
|
+
export declare const unsetProjectHandler: (options: {
|
|
11
|
+
verbose: boolean;
|
|
12
|
+
}) => Promise<void>;
|
|
9
13
|
export {};
|
|
10
14
|
//# sourceMappingURL=setProject.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setProject.d.ts","sourceRoot":"","sources":["../../src/handlers/setProject.ts"],"names":[],"mappings":"AAQA,KAAK,iBAAiB,GAAG;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,eAAO,MAAM,iBAAiB,
|
|
1
|
+
{"version":3,"file":"setProject.d.ts","sourceRoot":"","sources":["../../src/handlers/setProject.ts"],"names":[],"mappings":"AAQA,KAAK,iBAAiB,GAAG;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAC1B,OAAO,MAAM,EACb,OAAO,MAAM,KACd,OAAO,CAAC,UAAU,GAAG,SAAS,GAAG,OAAO,CAmE1C,CAAC;AAEF,eAAO,MAAM,eAAe,qBAmB3B,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAU,SAAS,iBAAiB,kBAsBjE,CAAC;AAEF,eAAO,MAAM,mBAAmB,qBAG/B,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAAU,SAAS;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,kBAmBtE,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.setProjectHandler = exports.setFirstProject = exports.setProjectCommand = void 0;
|
|
3
|
+
exports.unsetProjectHandler = exports.unsetProjectCommand = exports.setProjectHandler = exports.setFirstProject = exports.setProjectCommand = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const inquirer_1 = tslib_1.__importDefault(require("inquirer"));
|
|
6
6
|
const url_1 = require("url");
|
|
@@ -16,7 +16,7 @@ const setProjectCommand = async (name, uuid) => {
|
|
|
16
16
|
});
|
|
17
17
|
globalState_1.default.debug(`> Set project returned response: ${JSON.stringify(projects)}`);
|
|
18
18
|
if (projects.length === 0)
|
|
19
|
-
return;
|
|
19
|
+
return 'empty';
|
|
20
20
|
let selectedProject;
|
|
21
21
|
// --uuid or --name options
|
|
22
22
|
if (uuid !== undefined || name !== undefined) {
|
|
@@ -27,16 +27,27 @@ const setProjectCommand = async (name, uuid) => {
|
|
|
27
27
|
[selectedProject] = projects;
|
|
28
28
|
}
|
|
29
29
|
else {
|
|
30
|
+
const SKIP_VALUE = '__skip__';
|
|
30
31
|
const answers = await inquirer_1.default.prompt([
|
|
31
32
|
{
|
|
32
33
|
type: 'list',
|
|
33
34
|
name: 'project',
|
|
34
|
-
choices:
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
choices: [
|
|
36
|
+
{
|
|
37
|
+
name: "Don't select a project",
|
|
38
|
+
value: SKIP_VALUE,
|
|
39
|
+
},
|
|
40
|
+
...projects.map((project) => ({
|
|
41
|
+
name: project.name,
|
|
42
|
+
value: project.projectUuid,
|
|
43
|
+
})),
|
|
44
|
+
],
|
|
38
45
|
},
|
|
39
46
|
]);
|
|
47
|
+
if (answers.project === SKIP_VALUE) {
|
|
48
|
+
await (0, config_1.unsetProject)();
|
|
49
|
+
return 'skipped';
|
|
50
|
+
}
|
|
40
51
|
selectedProject = projects.find((project) => project.projectUuid === answers.project);
|
|
41
52
|
}
|
|
42
53
|
if (selectedProject !== undefined) {
|
|
@@ -45,10 +56,9 @@ const setProjectCommand = async (name, uuid) => {
|
|
|
45
56
|
const projectUrl = config.context?.serverUrl &&
|
|
46
57
|
new url_1.URL(`/projects/${selectedProject.projectUuid}/home`, config.context.serverUrl);
|
|
47
58
|
console.error(`\n ✅️ Connected to Lightdash project: ${projectUrl || ''}\n`);
|
|
59
|
+
return 'selected';
|
|
48
60
|
}
|
|
49
|
-
|
|
50
|
-
throw new Error(`Project not found.`);
|
|
51
|
-
}
|
|
61
|
+
throw new Error(`Project not found.`);
|
|
52
62
|
};
|
|
53
63
|
exports.setProjectCommand = setProjectCommand;
|
|
54
64
|
const setFirstProject = async () => {
|
|
@@ -70,7 +80,10 @@ const setProjectHandler = async (options) => {
|
|
|
70
80
|
let success = true;
|
|
71
81
|
globalState_1.default.setVerbose(options.verbose);
|
|
72
82
|
try {
|
|
73
|
-
await (0, exports.setProjectCommand)(options.name, options.uuid);
|
|
83
|
+
const result = await (0, exports.setProjectCommand)(options.name, options.uuid);
|
|
84
|
+
if (result === 'skipped') {
|
|
85
|
+
console.error(`\n Project unset.\n`);
|
|
86
|
+
}
|
|
74
87
|
}
|
|
75
88
|
catch (e) {
|
|
76
89
|
success = false;
|
|
@@ -88,3 +101,31 @@ const setProjectHandler = async (options) => {
|
|
|
88
101
|
}
|
|
89
102
|
};
|
|
90
103
|
exports.setProjectHandler = setProjectHandler;
|
|
104
|
+
const unsetProjectCommand = async () => {
|
|
105
|
+
await (0, config_1.unsetProject)();
|
|
106
|
+
console.error(`\n Project unset.\n`);
|
|
107
|
+
};
|
|
108
|
+
exports.unsetProjectCommand = unsetProjectCommand;
|
|
109
|
+
const unsetProjectHandler = async (options) => {
|
|
110
|
+
const startTime = Date.now();
|
|
111
|
+
let success = true;
|
|
112
|
+
globalState_1.default.setVerbose(options.verbose);
|
|
113
|
+
try {
|
|
114
|
+
await (0, exports.unsetProjectCommand)();
|
|
115
|
+
}
|
|
116
|
+
catch (e) {
|
|
117
|
+
success = false;
|
|
118
|
+
throw e;
|
|
119
|
+
}
|
|
120
|
+
finally {
|
|
121
|
+
await analytics_1.LightdashAnalytics.track({
|
|
122
|
+
event: 'command.executed',
|
|
123
|
+
properties: {
|
|
124
|
+
command: 'unset-project',
|
|
125
|
+
durationMs: Date.now() - startTime,
|
|
126
|
+
success,
|
|
127
|
+
},
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
exports.unsetProjectHandler = unsetProjectHandler;
|
package/dist/index.js
CHANGED
|
@@ -111,7 +111,9 @@ ${styles.bold('Examples:')}
|
|
|
111
111
|
${styles.title('⚡')}️lightdash ${styles.bold('login')} http://localhost:3000 --email demo@lightdash.com ${styles.secondary('-- Local dev only: prompts for password securely')}
|
|
112
112
|
`)
|
|
113
113
|
.option('--token <token>', 'Login with an API access token', undefined)
|
|
114
|
-
.
|
|
114
|
+
.addOption(new commander_1.Option('--project <project uuid>', 'Select a project by UUID after login')
|
|
115
|
+
.argParser(parseProjectArgument)
|
|
116
|
+
.conflicts('skipProjectSelection'))
|
|
115
117
|
.option('--email <email>', 'Login with email and password', undefined)
|
|
116
118
|
.option('--oauth-port <port>', 'Port for the local OAuth callback server (default: random available port)', (value) => {
|
|
117
119
|
const port = parseInt(value, 10);
|
|
@@ -143,6 +145,11 @@ configProgram
|
|
|
143
145
|
.description('Show the currently selected project')
|
|
144
146
|
.option('--verbose', undefined, false)
|
|
145
147
|
.action(getProject_1.getProjectHandler);
|
|
148
|
+
configProgram
|
|
149
|
+
.command('unset-project')
|
|
150
|
+
.description('Clear the currently selected project')
|
|
151
|
+
.option('--verbose', undefined, false)
|
|
152
|
+
.action(setProject_1.unsetProjectHandler);
|
|
146
153
|
const dbtProgram = commander_1.program.command('dbt').description('Runs dbt commands');
|
|
147
154
|
dbtProgram
|
|
148
155
|
.command('run')
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lightdash/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2646.0",
|
|
4
4
|
"description": "Lightdash CLI tool",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -40,8 +40,8 @@
|
|
|
40
40
|
"unique-names-generator": "^4.7.1",
|
|
41
41
|
"uuid": "^11.0.3",
|
|
42
42
|
"yaml": "^2.7.0",
|
|
43
|
-
"@lightdash/
|
|
44
|
-
"@lightdash/
|
|
43
|
+
"@lightdash/common": "0.2646.0",
|
|
44
|
+
"@lightdash/warehouses": "0.2646.0"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@types/inquirer": "^8.2.1",
|