@lightdash/common 0.1470.0 → 0.1472.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/index.d.ts CHANGED
@@ -130,6 +130,7 @@ export * from './types/userAttributes';
130
130
  export * from './types/userWarehouseCredentials';
131
131
  export * from './types/validation';
132
132
  export * from './types/warehouse';
133
+ export * from './utils/accessors';
133
134
  export * from './utils/additionalMetrics';
134
135
  export * from './utils/api';
135
136
  export { default as assertUnreachable } from './utils/assertUnreachable';
package/dist/index.js CHANGED
@@ -97,6 +97,7 @@ tslib_1.__exportStar(require("./types/userAttributes"), exports);
97
97
  tslib_1.__exportStar(require("./types/userWarehouseCredentials"), exports);
98
98
  tslib_1.__exportStar(require("./types/validation"), exports);
99
99
  tslib_1.__exportStar(require("./types/warehouse"), exports);
100
+ tslib_1.__exportStar(require("./utils/accessors"), exports);
100
101
  tslib_1.__exportStar(require("./utils/additionalMetrics"), exports);
101
102
  tslib_1.__exportStar(require("./utils/api"), exports);
102
103
  var assertUnreachable_1 = require("./utils/assertUnreachable");
@@ -340,14 +341,13 @@ const getDateGroupLabel = (axisItem) => {
340
341
  };
341
342
  exports.getDateGroupLabel = getDateGroupLabel;
342
343
  const getAxisName = ({ isAxisTheSameForAllSeries, selectedAxisIndex, axisReference, axisIndex, axisName, series, itemsMap, }) => {
343
- const defaultItem = itemsMap
344
- ? itemsMap[(series || [])[0]?.encode[axisReference].field]
345
- : undefined;
344
+ const itemIndex = (series || [])[0]?.encode[axisReference].field;
345
+ const defaultItem = itemsMap && itemIndex ? itemsMap[itemIndex] : undefined;
346
346
  const dateGroupName = defaultItem
347
347
  ? (0, exports.getDateGroupLabel)(defaultItem)
348
348
  : undefined;
349
349
  const fallbackSeriesName = series && series.length === 1
350
- ? series[0].name ||
350
+ ? series[0]?.name ||
351
351
  (defaultItem && (0, item_1.getItemLabelWithoutTableName)(defaultItem))
352
352
  : undefined;
353
353
  return !isAxisTheSameForAllSeries || selectedAxisIndex === axisIndex
@@ -4,7 +4,9 @@ exports.pivotResultsAsCsv = exports.pivotQueryResults = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const isNumber_1 = tslib_1.__importDefault(require("lodash/isNumber"));
6
6
  const last_1 = tslib_1.__importDefault(require("lodash/last"));
7
+ const errors_1 = require("../types/errors");
7
8
  const field_1 = require("../types/field");
9
+ const accessors_1 = require("../utils/accessors");
8
10
  const formatting_1 = require("../utils/formatting");
9
11
  const isRecursiveRecord = (value) => typeof value === 'object' && value !== null;
10
12
  const create2DArray = (rows, columns, value = null) => Array.from({ length: rows }, () => Array.from({ length: columns }, () => value));
@@ -19,6 +21,9 @@ const setIndexByKey = (obj, keys, value) => {
19
21
  return false;
20
22
  }
21
23
  const [key, ...rest] = keys;
24
+ if (key === undefined) {
25
+ throw new errors_1.UnexpectedIndexError(`setIndexByKey: Cannot get key from keys ${keys.length}`);
26
+ }
22
27
  if (rest.length === 0) {
23
28
  if (obj[key] === undefined) {
24
29
  // eslint-disable-next-line no-param-reassign
@@ -42,6 +47,9 @@ const getIndexByKey = (obj, keys) => {
42
47
  throw new Error('Cannot get key from empty keys array');
43
48
  }
44
49
  const [key, ...rest] = keys;
50
+ if (key === undefined) {
51
+ throw new errors_1.UnexpectedServerError(`getIndexByKey: Cannot get key from keys ${keys.length}`);
52
+ }
45
53
  if (rest.length === 0) {
46
54
  const value = obj[key];
47
55
  if (typeof value !== 'number') {
@@ -79,8 +87,11 @@ const getAllIndices = (obj) => Object.values(obj).reduce((acc, value) => {
79
87
  }, []);
80
88
  const getAllIndicesByKey = (obj, keys) => {
81
89
  const [key, ...rest] = keys;
90
+ if (key === undefined) {
91
+ throw new errors_1.UnexpectedIndexError('Cannot set key on undefined');
92
+ }
82
93
  if (rest.length === 0) {
83
- const value = obj[key];
94
+ const value = (0, accessors_1.getObjectValue)(obj, key);
84
95
  if ((0, isNumber_1.default)(value)) {
85
96
  return [value];
86
97
  }
@@ -119,7 +130,10 @@ const getColSpanByKey = (currentColumnPosition, obj, keys) => {
119
130
  const combinedRetrofit = (data, getField, getFieldLabel) => {
120
131
  const indexValues = data.indexValues.length ? data.indexValues : [[]];
121
132
  const baseIdInfo = (0, last_1.default)(data.headerValues);
122
- const uniqueIdsForDataValueColumns = Array(data.headerValues[0].length);
133
+ if (data.headerValues[0] === undefined) {
134
+ throw new errors_1.UnexpectedIndexError('combinedRetrofit: Cannot get header values');
135
+ }
136
+ const uniqueIdsForDataValueColumns = Array((0, accessors_1.getArrayValue)(data.headerValues, 0).length);
123
137
  data.headerValues.forEach((headerRow) => {
124
138
  headerRow.forEach((headerColValue, colIndex) => {
125
139
  uniqueIdsForDataValueColumns[colIndex] = `${(uniqueIdsForDataValueColumns[colIndex] ?? '') +
@@ -170,12 +184,13 @@ const combinedRetrofit = (data, getField, getFieldLabel) => {
170
184
  columnType: 'indexValue',
171
185
  };
172
186
  });
173
- const remappedDataValues = data.dataValues[rowIndex].map((dataValue, colIndex) => {
187
+ const remappedDataValues = (0, accessors_1.getArrayValue)(data.dataValues, rowIndex).map((dataValue, colIndex) => {
174
188
  const baseIdInfoForCol = baseIdInfo
175
189
  ? baseIdInfo[colIndex]
176
190
  : undefined;
177
191
  const baseId = baseIdInfoForCol?.fieldId;
178
- const id = uniqueIdsForDataValueColumns[colIndex] + colIndex;
192
+ const id = (0, accessors_1.getArrayValue)(uniqueIdsForDataValueColumns, colIndex) +
193
+ colIndex;
179
194
  return {
180
195
  baseId,
181
196
  fieldId: id,
@@ -286,19 +301,19 @@ const pivotQueryResults = ({ pivotConfig, metricQuery, rows, options, getField,
286
301
  for (let nRow = 0; nRow < N_ROWS; nRow += 1) {
287
302
  const row = rows[nRow];
288
303
  for (let nMetric = 0; nMetric < metrics.length; nMetric += 1) {
289
- const metric = metrics[nMetric];
290
304
  const indexRowValues = indexDimensions
291
305
  .map((fieldId) => ({
292
306
  type: 'value',
293
307
  fieldId,
294
- value: row[fieldId].value,
308
+ value: (0, accessors_1.getObjectValue)(row, fieldId).value,
295
309
  colSpan: 1,
296
310
  }))
297
311
  .concat(pivotConfig.metricsAsRows
298
312
  ? [
299
313
  {
300
314
  type: 'label',
301
- fieldId: metric.fieldId,
315
+ fieldId: (0, accessors_1.getArrayValue)(metrics, nMetric)
316
+ .fieldId,
302
317
  },
303
318
  ]
304
319
  : []);
@@ -306,7 +321,7 @@ const pivotQueryResults = ({ pivotConfig, metricQuery, rows, options, getField,
306
321
  .map((fieldId) => ({
307
322
  type: 'value',
308
323
  fieldId,
309
- value: row[fieldId].value,
324
+ value: (0, accessors_1.getObjectValue)(row, fieldId).value,
310
325
  colSpan: 1,
311
326
  }))
312
327
  .concat(pivotConfig.metricsAsRows
@@ -314,7 +329,8 @@ const pivotQueryResults = ({ pivotConfig, metricQuery, rows, options, getField,
314
329
  : [
315
330
  {
316
331
  type: 'label',
317
- fieldId: metric.fieldId,
332
+ fieldId: (0, accessors_1.getArrayValue)(metrics, nMetric)
333
+ .fieldId,
318
334
  },
319
335
  ]);
320
336
  // Write the index values
@@ -333,7 +349,7 @@ const pivotQueryResults = ({ pivotConfig, metricQuery, rows, options, getField,
333
349
  }
334
350
  }
335
351
  const headerValues = headerValuesT[0]?.map((_, colIndex) => headerValuesT.map((row, rowIndex) => {
336
- const cell = row[colIndex];
352
+ const cell = (0, accessors_1.getArrayValue)(row, colIndex);
337
353
  if (cell.type === 'label') {
338
354
  return cell;
339
355
  }
@@ -363,7 +379,7 @@ const pivotQueryResults = ({ pivotConfig, metricQuery, rows, options, getField,
363
379
  const row = rows[nRow];
364
380
  for (let nMetric = 0; nMetric < metrics.length; nMetric += 1) {
365
381
  const metric = metrics[nMetric];
366
- const { value } = row[metric.fieldId];
382
+ const { value } = row?.[metric.fieldId] ?? {};
367
383
  const rowKeys = [
368
384
  ...indexDimensions.map((d) => row[d].value.raw),
369
385
  ...(pivotConfig.metricsAsRows ? [metric.fieldId] : []),
@@ -57,6 +57,11 @@ export declare class UnexpectedServerError extends LightdashError {
57
57
  [key: string]: AnyType;
58
58
  });
59
59
  }
60
+ export declare class UnexpectedIndexError extends LightdashError {
61
+ constructor(message?: string, data?: {
62
+ [key: string]: AnyType;
63
+ });
64
+ }
60
65
  export declare class UnexpectedGitError extends LightdashError {
61
66
  constructor(message?: string, data?: {
62
67
  [key: string]: AnyType;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getErrorMessage = exports.UnexpectedGoogleSheetsError = exports.SlackInstallationNotFoundError = exports.KnexPaginationError = exports.NotEnoughResults = exports.MissingConfigError = exports.AlreadyExistsError = exports.AlreadyProcessingError = exports.SmptError = exports.WarehouseQueryError = exports.WarehouseConnectionError = exports.InvalidUser = exports.NotFoundError = exports.DbtError = exports.FieldReferenceError = exports.CompileError = exports.ParseError = exports.UnexpectedDatabaseError = exports.UnexpectedGitError = exports.UnexpectedServerError = exports.MissingWarehouseCredentialsError = exports.MissingCatalogEntryError = exports.NonCompiledModelError = exports.ParameterError = exports.ExpiredError = exports.NotExistsError = exports.AuthorizationError = exports.DeactivatedAccountError = exports.ForbiddenError = exports.LightdashError = void 0;
3
+ exports.getErrorMessage = exports.UnexpectedGoogleSheetsError = exports.SlackInstallationNotFoundError = exports.KnexPaginationError = exports.NotEnoughResults = exports.MissingConfigError = exports.AlreadyExistsError = exports.AlreadyProcessingError = exports.SmptError = exports.WarehouseQueryError = exports.WarehouseConnectionError = exports.InvalidUser = exports.NotFoundError = exports.DbtError = exports.FieldReferenceError = exports.CompileError = exports.ParseError = exports.UnexpectedDatabaseError = exports.UnexpectedGitError = exports.UnexpectedIndexError = exports.UnexpectedServerError = exports.MissingWarehouseCredentialsError = exports.MissingCatalogEntryError = exports.NonCompiledModelError = exports.ParameterError = exports.ExpiredError = exports.NotExistsError = exports.AuthorizationError = exports.DeactivatedAccountError = exports.ForbiddenError = exports.LightdashError = void 0;
4
4
  class LightdashError extends Error {
5
5
  constructor({ message, name, statusCode, data }) {
6
6
  super(message);
@@ -120,6 +120,17 @@ class UnexpectedServerError extends LightdashError {
120
120
  }
121
121
  }
122
122
  exports.UnexpectedServerError = UnexpectedServerError;
123
+ class UnexpectedIndexError extends LightdashError {
124
+ constructor(message = 'Invalid index in array.', data = {}) {
125
+ super({
126
+ message,
127
+ name: 'UnexpectedIndexError',
128
+ statusCode: 500,
129
+ data,
130
+ });
131
+ }
132
+ }
133
+ exports.UnexpectedIndexError = UnexpectedIndexError;
123
134
  class UnexpectedGitError extends LightdashError {
124
135
  constructor(message = 'Unexpected error in Git adapter', data = {}) {
125
136
  super({
@@ -174,6 +174,7 @@ export interface DbtCloudIDEProjectConfig extends DbtProjectConfigBase {
174
174
  api_key: string;
175
175
  environment_id: string;
176
176
  discovery_api_endpoint?: string;
177
+ tags?: string[];
177
178
  }
178
179
  export interface DbtGithubProjectConfig extends DbtProjectCompilerBase {
179
180
  type: DbtProjectType.GITHUB;
@@ -0,0 +1,2 @@
1
+ export declare const getArrayValue: <T>(obj: ArrayLike<T> | undefined, key: number, errorMessage?: string) => T;
2
+ export declare const getObjectValue: <T>(obj: Record<string | number, T> | undefined, key: string | number, errorMessage?: string) => T;
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getObjectValue = exports.getArrayValue = void 0;
4
+ const errors_1 = require("../types/errors");
5
+ const getArrayValue = (obj, key, errorMessage) => {
6
+ if (obj === undefined) {
7
+ throw new errors_1.UnexpectedIndexError(errorMessage || `Cannot get key "${key}" value from empty array`);
8
+ }
9
+ const value = obj[key];
10
+ if (value === undefined) {
11
+ console.trace();
12
+ throw new errors_1.UnexpectedIndexError(errorMessage || `Cannot get key "${key}" value from array`);
13
+ }
14
+ return value;
15
+ };
16
+ exports.getArrayValue = getArrayValue;
17
+ const getObjectValue = (obj, key, errorMessage) => {
18
+ if (obj === undefined) {
19
+ throw new errors_1.UnexpectedIndexError(errorMessage || `Cannot get key "${key}" value from empty object`);
20
+ }
21
+ const value = obj[key];
22
+ if (value === undefined) {
23
+ console.trace();
24
+ throw new errors_1.UnexpectedIndexError(errorMessage || `Cannot get key "${key}" value from object`);
25
+ }
26
+ return value;
27
+ };
28
+ exports.getObjectValue = getObjectValue;
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.isValidTimezone = exports.isValidFrequency = exports.getHumanReadableCronExpression = exports.getTimezoneLabel = exports.formatMinutesOffset = exports.getTzMinutesOffset = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const cronstrue_1 = tslib_1.__importDefault(require("cronstrue"));
6
+ const accessors_1 = require("./accessors");
6
7
  function getTzMinutesOffset(oldTz, newTz) {
7
8
  const date = new Date();
8
9
  const oldFormattedString = date.toLocaleString('en-US', {
@@ -48,7 +49,8 @@ function getHumanReadableCronExpression(cronExpression, timezone) {
48
49
  const valueWithTimezone = value
49
50
  .replaceAll(' PM', ` PM (UTC ${offsetString})`)
50
51
  .replaceAll(' AM', ` AM (UTC ${offsetString})`);
51
- return valueWithTimezone[0].toLowerCase() + valueWithTimezone.slice(1);
52
+ return ((0, accessors_1.getArrayValue)(valueWithTimezone, 0).toLowerCase() +
53
+ valueWithTimezone.slice(1));
52
54
  }
53
55
  exports.getHumanReadableCronExpression = getHumanReadableCronExpression;
54
56
  function isValidFrequency(cronExpression) {
@@ -62,6 +64,9 @@ function isValidFrequency(cronExpression) {
62
64
  return false;
63
65
  }
64
66
  const [minutePart] = cronParts;
67
+ if (minutePart === undefined) {
68
+ return false;
69
+ }
65
70
  if (minutePart.includes('/') ||
66
71
  minutePart.includes(',') ||
67
72
  minutePart.includes('-')) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lightdash/common",
3
- "version": "0.1470.0",
3
+ "version": "0.1472.0",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "files": [