@lightdash/cli 0.1419.1 → 0.1420.1

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.
@@ -52,9 +52,13 @@ export declare const lightdashApi: <T extends string | boolean | unknown[] | imp
52
52
  } | {
53
53
  charts: import("@lightdash/common").ChartAsCode[];
54
54
  missingIds: string[];
55
+ total: number;
56
+ offset: number;
55
57
  } | {
56
58
  dashboards: import("@lightdash/common").DashboardAsCode[];
57
59
  missingIds: string[];
60
+ total: number;
61
+ offset: number;
58
62
  } | {
59
63
  edges: import("@lightdash/common").CatalogMetricsTreeEdge[];
60
64
  } | import("@lightdash/common").MetricTotalResults | null | undefined>({ method, url, body, }: LightdashApiProps) => Promise<T>;
@@ -29,7 +29,7 @@ const parseContentFilters = (items) => {
29
29
  };
30
30
  const dumpIntoFiles = async (folder, items) => {
31
31
  const outputDir = path.join(process.cwd(), DOWNLOAD_FOLDER, folder);
32
- console.info(`Writing ${items.length} ${folder} into ${outputDir}`);
32
+ globalState_1.default.debug(`Writing ${items.length} ${folder} into ${outputDir}`);
33
33
  // Make directory
34
34
  const created = await fs_1.promises.mkdir(outputDir, { recursive: true });
35
35
  if (created)
@@ -103,45 +103,80 @@ const downloadHandler = async (options) => {
103
103
  console.info(styles.warning(`No charts filters provided, skipping`));
104
104
  }
105
105
  else {
106
- globalState_1.default.debug(`Downloading charts`);
106
+ const spinner = globalState_1.default.startSpinner(`Downloading charts`);
107
107
  const chartFilters = parseContentFilters(options.charts);
108
- const chartsAsCode = await (0, apiClient_1.lightdashApi)({
109
- method: 'GET',
110
- url: `/api/v1/projects/${projectId}/charts/code${chartFilters}`,
111
- body: undefined,
112
- });
113
- chartsAsCode.missingIds.forEach((missingId) => {
114
- console.warn(styles.warning(`No chart with id "${missingId}"`));
115
- });
116
- await dumpIntoFiles('charts', chartsAsCode.charts);
108
+ let chartsAsCode;
109
+ let offset = 0;
110
+ do {
111
+ globalState_1.default.debug(`Downloading charts with offset "${offset}" and filters "${chartFilters}"`);
112
+ const queryParams = chartFilters
113
+ ? `${chartFilters}&offset=${offset}`
114
+ : `?offset=${offset}`;
115
+ chartsAsCode = await (0, apiClient_1.lightdashApi)({
116
+ method: 'GET',
117
+ url: `/api/v1/projects/${projectId}/charts/code${queryParams}`,
118
+ body: undefined,
119
+ });
120
+ spinner.start(`Downloaded ${chartsAsCode.offset} of ${chartsAsCode.total} charts`);
121
+ chartsAsCode.missingIds.forEach((missingId) => {
122
+ console.warn(styles.warning(`\nNo chart with id "${missingId}"`));
123
+ });
124
+ await dumpIntoFiles('charts', chartsAsCode.charts);
125
+ offset = chartsAsCode.offset;
126
+ } while (chartsAsCode.offset < chartsAsCode.total);
127
+ spinner.succeed(`Downloaded ${chartsAsCode.total} charts`);
117
128
  }
118
129
  // Download dashboards
119
130
  if (hasFilters && options.dashboards.length === 0) {
120
131
  console.info(styles.warning(`No dashboards filters provided, skipping`));
121
132
  }
122
133
  else {
123
- globalState_1.default.debug(`Downloading dashboards`);
134
+ const spinner = globalState_1.default.startSpinner(`Downloading dashboards`);
124
135
  const dashboardFilters = parseContentFilters(options.dashboards);
125
- const dashboardsAsCode = await (0, apiClient_1.lightdashApi)({
126
- method: 'GET',
127
- url: `/api/v1/projects/${projectId}/dashboards/code${dashboardFilters}`,
128
- body: undefined,
129
- });
130
- dashboardsAsCode.missingIds.forEach((missingId) => {
131
- console.warn(styles.warning(`No dashboard with id "${missingId}"`));
132
- });
133
- await dumpIntoFiles('dashboards', dashboardsAsCode.dashboards);
136
+ let offset = 0;
137
+ let dashboardsAsCode;
138
+ do {
139
+ globalState_1.default.debug(`Downloading dashboards with offset "${offset}" and filters "${dashboardFilters}"`);
140
+ const queryParams = dashboardFilters
141
+ ? `${dashboardFilters}&offset=${offset}`
142
+ : `?offset=${offset}`;
143
+ dashboardsAsCode = await (0, apiClient_1.lightdashApi)({
144
+ method: 'GET',
145
+ url: `/api/v1/projects/${projectId}/dashboards/code${queryParams}`,
146
+ body: undefined,
147
+ });
148
+ dashboardsAsCode.missingIds.forEach((missingId) => {
149
+ console.warn(styles.warning(`\nNo dashboard with id "${missingId}"`));
150
+ });
151
+ spinner?.start(`Downloaded ${dashboardsAsCode.offset} of ${dashboardsAsCode.total} dashboards`);
152
+ await dumpIntoFiles('dashboards', dashboardsAsCode.dashboards);
153
+ offset = dashboardsAsCode.offset;
154
+ } while (dashboardsAsCode.offset < dashboardsAsCode.total);
155
+ spinner.succeed(`Downloaded ${dashboardsAsCode.total} dashboards`);
134
156
  }
135
157
  // TODO delete files if chart don't exist ?*/
136
158
  };
137
159
  exports.downloadHandler = downloadHandler;
160
+ const getPromoteAction = (action) => {
161
+ switch (action) {
162
+ case common_1.PromotionAction.CREATE:
163
+ return 'created';
164
+ case common_1.PromotionAction.UPDATE:
165
+ return 'updated';
166
+ case common_1.PromotionAction.DELETE:
167
+ return 'deleted';
168
+ case common_1.PromotionAction.NO_CHANGES:
169
+ return 'skipped';
170
+ default:
171
+ (0, common_1.assertUnreachable)(action, `Unknown promotion action: ${action}`);
172
+ }
173
+ return 'skipped';
174
+ };
138
175
  const storeUploadChanges = (changes, promoteChanges) => {
139
176
  const getPromoteChanges = (resource) => {
140
177
  const promotions = promoteChanges[resource];
141
178
  return promotions.reduce((acc, promoteChange) => {
142
- const action = promoteChange.action === common_1.PromotionAction.NO_CHANGES
143
- ? 'skipped'
144
- : promoteChange.action;
179
+ const action = getPromoteAction(promoteChange.action);
145
180
  const key = `${resource} ${action}`;
146
181
  acc[key] = (acc[key] ?? 0) + 1;
147
182
  return acc;
@@ -223,8 +258,21 @@ const uploadHandler = async (options) => {
223
258
  throw new Error('No project selected. Run lightdash config set-project');
224
259
  }
225
260
  let changes = {};
226
- changes = await upsertResources('charts', projectId, changes, options.force, options.charts);
227
- changes = await upsertResources('dashboards', projectId, changes, options.force, options.dashboards);
261
+ // If any filter is provided, we skip those items without filters
262
+ // eg: if a --charts filter is provided, we skip dashboards if no --dashboards filter is provided
263
+ const hasFilters = options.charts.length > 0 || options.dashboards.length > 0;
264
+ if (hasFilters && options.charts.length === 0) {
265
+ console.info(styles.warning(`No charts filters provided, skipping`));
266
+ }
267
+ else {
268
+ changes = await upsertResources('charts', projectId, changes, options.force, options.charts);
269
+ }
270
+ if (hasFilters && options.dashboards.length === 0) {
271
+ console.info(styles.warning(`No dashboard filters provided, skipping`));
272
+ }
273
+ else {
274
+ changes = await upsertResources('dashboards', projectId, changes, options.force, options.dashboards);
275
+ }
228
276
  logUploadChanges(changes);
229
277
  };
230
278
  exports.uploadHandler = uploadHandler;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lightdash/cli",
3
- "version": "0.1419.1",
3
+ "version": "0.1420.1",
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.1419.1",
15
- "@lightdash/warehouses": "^0.1419.1",
14
+ "@lightdash/common": "^0.1420.1",
15
+ "@lightdash/warehouses": "^0.1420.1",
16
16
  "@types/columnify": "^1.5.1",
17
17
  "ajv": "^8.11.0",
18
18
  "ajv-formats": "^2.1.1",