@lightdash/warehouses 2.145.0 → 2.146.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.
@@ -53,6 +53,9 @@ export declare class BigqueryWarehouseClient extends WarehouseBaseClient<CreateB
53
53
  client: BigQuery;
54
54
  constructor(credentials: CreateBigqueryCredentials);
55
55
  static isBigqueryError(error: unknown): error is BigqueryError;
56
+ private usesUserRefreshToken;
57
+ private translateGoogleOauthTokenError;
58
+ private throwIfGoogleOauthTokenError;
56
59
  /**
57
60
  * Sanitize label key and values.
58
61
  * Keys and values can contain only lowercase letters, numeric characters, underscores, and dashes. All characters must use UTF-8 encoding, and international characters are allowed.
@@ -87,6 +90,7 @@ export declare class BigqueryWarehouseClient extends WarehouseBaseClient<CreateB
87
90
  table: string;
88
91
  partitionColumn: PartitionColumn | undefined;
89
92
  }[]>;
93
+ private getAllTablesFromClient;
90
94
  getFields(tableName: string, schema: string, database?: string): Promise<WarehouseCatalog>;
91
95
  parseError(error: bigquery.IErrorProto, query?: string): WarehouseQueryError;
92
96
  executeAsyncQuery({ sql, tags, timezone }: WarehouseExecuteAsyncQueryArgs, resultsStreamCallback?: (rows: WarehouseResults['rows'], fields: WarehouseResults['fields']) => void): Promise<WarehouseExecuteAsyncQuery>;
@@ -1 +1 @@
1
- {"version":3,"file":"BigqueryWarehouseClient.d.ts","sourceRoot":"","sources":["../../src/warehouseClients/BigqueryWarehouseClient.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,QAAQ,EAKR,OAAO,EACP,gBAAgB,EAChB,kBAAkB,EAGlB,iBAAiB,EACpB,MAAM,wBAAwB,CAAC;AAChC,OAAO,QAAQ,MAAM,wCAAwC,CAAC;AAC9D,OAAO,EACH,OAAO,EAEP,eAAe,EACf,eAAe,EACf,6BAA6B,EAC7B,yBAAyB,EAGzB,MAAM,EAEN,eAAe,EAKf,mBAAmB,EACnB,gBAAgB,EAEhB,mBAAmB,EACnB,gBAAgB,EAChB,cAAc,EACd,KAAK,eAAe,EACvB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACH,gBAAgB,EAChB,0BAA0B,EAC1B,8BAA8B,EAEjC,MAAM,UAAU,CAAC;AAOlB,OAAO,mBAAmB,MAAM,uBAAuB,CAAC;AACxD,OAAO,uBAAuB,MAAM,2BAA2B,CAAC;AAKhE,oBAAY,iBAAiB;IACzB,MAAM,WAAW;IACjB,OAAO,YAAY;IACnB,KAAK,UAAU;IACf,KAAK,UAAU;IACf,KAAK,UAAU;IACf,OAAO,YAAY;IACnB,OAAO,YAAY;IACnB,IAAI,SAAS;IACb,SAAS,cAAc;IACvB,IAAI,SAAS;IACb,IAAI,SAAS;IACb,QAAQ,aAAa;IACrB,SAAS,cAAc;IACvB,OAAO,YAAY;IACnB,UAAU,eAAe;IACzB,MAAM,WAAW;IACjB,MAAM,WAAW;IACjB,KAAK,UAAU;CAClB;AAiDD,eAAO,MAAM,0BAA0B,SAC7B,MAAM,GAAG,SAAS,KACzB,eAAe,GAAG,SASpB,CAAC;AA0BF,KAAK,WAAW,GAAG;IACf,MAAM,EAAE,YAAY,EAAE,CAAC;CAC1B,CAAC;AAEF,KAAK,YAAY,GAAG,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,iBAAiB,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC;AAehF,KAAK,aAAa,GAAG;IACjB,MAAM,EAAE,QAAQ,CAAC,WAAW,EAAE,CAAC;CAClC,CAAC;AAEF,qBAAa,kBAAmB,SAAQ,uBAAuB;IAC3D,QAAQ,CAAC,IAAI,2BAA2B;IAExC,cAAc,IAAI,mBAAmB,CAEpC;IAED,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAWhD;IAED,iBAAiB,IAAI,MAAM,CAE1B;IAED,eAAe,IAAI,MAAM,CAExB;IAED,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAiBlC;IAED,eAAe,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAGlC;IAED,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAG7B;IAED,oBAAoB,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAGvC;IAED,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,gBAAgB,GAAG,MAAM,CAI5D;IAED,uBAAuB,CACnB,iBAAiB,EAAE,MAAM,EACzB,eAAe,EAAE,MAAM,GACxB,MAAM,CAGR;IAED,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAGrC;IAED,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,CAGrC;IAED,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAM1D;CACJ;AAED,qBAAa,uBAAwB,SAAQ,mBAAmB,CAAC,yBAAyB,CAAC;IACvF,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAM;IAExC,MAAM,EAAE,QAAQ,CAAC;IAEjB,YAAY,WAAW,EAAE,yBAAyB,EAyBjD;IAED,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,aAAa,CAE7D;IAED;;;;;;;;;;OAUG;IACH,MAAM,CAAC,wBAAwB,CAC3B,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAChC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAoBpC;IAED,MAAM,CAAC,qBAAqB,CAAC,QAAQ,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAAG,SAAS,oEAYtE;YAEa,SAAS;YA+BT,MAAM;YAWN,qBAAqB;YAUrB,aAAa;IAoCrB,WAAW,CACb,KAAK,EAAE,MAAM,EACb,cAAc,EAAE,CAAC,IAAI,EAAE,gBAAgB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,EAChE,OAAO,EAAE;QACL,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC;QACnB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;KACrB,GACF,OAAO,CAAC,IAAI,CAAC,CAsBf;IAED,OAAa,gBAAgB,CACzB,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,MAAM,GACd,OAAO,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAShD;IAEK,UAAU,CACZ,QAAQ,EAAE;QACN,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;KACjB,EAAE,6BAgDN;IAEK,YAAY;;;;;SA6DjB;IAEK,SAAS,CACX,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,QAAQ,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,gBAAgB,CAAC,CAmB3B;IAED,UAAU,CAAC,KAAK,EAAE,QAAQ,CAAC,WAAW,EAAE,KAAK,GAAE,MAAW,uBA+FzD;IAEK,iBAAiB,CACnB,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,8BAA8B,EACvD,qBAAqB,CAAC,EAAE,CACpB,IAAI,EAAE,gBAAgB,CAAC,MAAM,CAAC,EAC9B,MAAM,EAAE,gBAAgB,CAAC,QAAQ,CAAC,KACjC,IAAI,GACV,OAAO,CAAC,0BAA0B,CAAC,CA8DrC;YAEa,kBAAkB;IAWhC,OAAa,YAAY,CACrB,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,MAAM,EACrB,cAAc,GAAE;QACZ,WAAW,EAAE,MAAM,OAAO,CAAC,gBAAgB,CAAC,CAAC;QAC7C,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,iBAAiB,CAAC,CAAC;KASvD,GACH,OAAO,CAAC,eAAe,EAAE,CAAC,CA0B5B;IAED,OAAa,wBAAwB,CACjC,QAAQ,EAAE,eAAe,EAAE,EAC3B,YAAY,EAAE,MAAM,EACpB,qBAAqB,GAAE,CAAC,SAAS,EAAE,MAAM,KAAK;QAC1C,WAAW,EAAE,CACT,OAAO,EAAE,kBAAkB,KAC1B,OAAO,CAAC,gBAAgB,CAAC,CAAC;QAC/B,KAAK,EAAE,CAAC,OAAO,EAAE;YACb,KAAK,EAAE,MAAM,CAAC;YACd,QAAQ,EAAE,MAAM,CAAC;SACpB,KAAK,OAAO,CAAC,iBAAiB,CAAC,CAAC;KAgBpC,GACF,OAAO,CAAC,6BAA6B,CAAC,CAuFxC;IAED,OAAa,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CA0DxE;CACJ"}
1
+ {"version":3,"file":"BigqueryWarehouseClient.d.ts","sourceRoot":"","sources":["../../src/warehouseClients/BigqueryWarehouseClient.ts"],"names":[],"mappings":"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"}
@@ -179,6 +179,30 @@ class BigquerySqlBuilder extends WarehouseBaseSqlBuilder_1.default {
179
179
  }
180
180
  }
181
181
  exports.BigquerySqlBuilder = BigquerySqlBuilder;
182
+ const isRecord = (value) => typeof value === 'object' && value !== null;
183
+ const readString = (record, key) => {
184
+ const value = record[key];
185
+ return typeof value === 'string' ? value : undefined;
186
+ };
187
+ const getGoogleOauthTokenError = (error) => {
188
+ if (!isRecord(error))
189
+ return undefined;
190
+ const response = isRecord(error.response) ? error.response : undefined;
191
+ const status = response?.status ?? error.status;
192
+ if (status !== 400)
193
+ return undefined;
194
+ const data = response && isRecord(response.data) ? response.data : undefined;
195
+ if (!data)
196
+ return undefined;
197
+ const code = readString(data, 'error');
198
+ if (code === undefined)
199
+ return undefined;
200
+ return {
201
+ error: code,
202
+ errorDescription: readString(data, 'error_description'),
203
+ errorSubtype: readString(data, 'error_subtype'),
204
+ };
205
+ };
182
206
  class BigqueryWarehouseClient extends WarehouseBaseClient_1.default {
183
207
  constructor(credentials) {
184
208
  super(credentials, new BigquerySqlBuilder(credentials.startOfWeek));
@@ -205,6 +229,33 @@ class BigqueryWarehouseClient extends WarehouseBaseClient_1.default {
205
229
  static isBigqueryError(error) {
206
230
  return error !== null && typeof error === 'object' && 'errors' in error;
207
231
  }
232
+ usesUserRefreshToken() {
233
+ return (this.credentials.authenticationType !==
234
+ common_1.BigqueryAuthenticationType.ADC &&
235
+ this.credentials.keyfileContents?.type === 'authorized_user');
236
+ }
237
+ translateGoogleOauthTokenError(error) {
238
+ const tokenError = getGoogleOauthTokenError(error);
239
+ if (tokenError?.error !== 'invalid_grant') {
240
+ return undefined;
241
+ }
242
+ const details = [
243
+ tokenError.errorDescription
244
+ ? `invalid_grant: ${tokenError.errorDescription}`
245
+ : 'invalid_grant',
246
+ ...(tokenError.errorSubtype ? [tokenError.errorSubtype] : []),
247
+ ].join('; ');
248
+ if (this.usesUserRefreshToken()) {
249
+ return new common_1.BigqueryTokenError(`${common_1.BIGQUERY_TOKEN_ERROR_MESSAGE_MARKER} (${details}). Reconnect your BigQuery account in personal settings.`);
250
+ }
251
+ return new common_1.WarehouseConnectionError(`Google rejected the BigQuery credentials (${details}).`);
252
+ }
253
+ throwIfGoogleOauthTokenError(error) {
254
+ const translated = this.translateGoogleOauthTokenError(error);
255
+ if (translated) {
256
+ throw translated;
257
+ }
258
+ }
208
259
  /**
209
260
  * Sanitize label key and values.
210
261
  * Keys and values can contain only lowercase letters, numeric characters, underscores, and dashes. All characters must use UTF-8 encoding, and international characters are allowed.
@@ -319,6 +370,7 @@ class BigqueryWarehouseClient extends WarehouseBaseClient_1.default {
319
370
  await this.streamResults(job, (chunk) => streamCallback({ fields, rows: [chunk] }));
320
371
  }
321
372
  catch (e) {
373
+ this.throwIfGoogleOauthTokenError(e);
322
374
  if (BigqueryWarehouseClient.isBigqueryError(e)) {
323
375
  const responseError = e?.errors[0];
324
376
  if (responseError) {
@@ -343,6 +395,7 @@ class BigqueryWarehouseClient extends WarehouseBaseClient_1.default {
343
395
  projectId: database,
344
396
  });
345
397
  return BigqueryWarehouseClient.getTableMetadata(dataset, table).catch((e) => {
398
+ this.throwIfGoogleOauthTokenError(e);
346
399
  if (e?.code === 404) {
347
400
  return undefined;
348
401
  }
@@ -366,6 +419,15 @@ class BigqueryWarehouseClient extends WarehouseBaseClient_1.default {
366
419
  }, {});
367
420
  }
368
421
  async getAllTables() {
422
+ try {
423
+ return await this.getAllTablesFromClient();
424
+ }
425
+ catch (e) {
426
+ this.throwIfGoogleOauthTokenError(e);
427
+ throw e;
428
+ }
429
+ }
430
+ async getAllTablesFromClient() {
369
431
  const [datasets] = await this.client.getDatasets();
370
432
  const datasetTablesResponses = await Promise.all(datasets.map((d) => d.getTables()));
371
433
  const datasetMetadata = await Promise.all(datasets.map(async (dataset) => {
@@ -412,7 +474,10 @@ class BigqueryWarehouseClient extends WarehouseBaseClient_1.default {
412
474
  const dataset = new bigquery_1.Dataset(this.client, schema, {
413
475
  projectId: database,
414
476
  });
415
- const schemas = await BigqueryWarehouseClient.getTableMetadata(dataset, tableName);
477
+ const schemas = await BigqueryWarehouseClient.getTableMetadata(dataset, tableName).catch((e) => {
478
+ this.throwIfGoogleOauthTokenError(e);
479
+ throw e;
480
+ });
416
481
  return this.parseWarehouseCatalog(schemas[3].fields.map((column) => ({
417
482
  table_catalog: schemas[0],
418
483
  table_schema: schemas[1],
@@ -519,6 +584,7 @@ class BigqueryWarehouseClient extends WarehouseBaseClient_1.default {
519
584
  };
520
585
  }
521
586
  catch (e) {
587
+ this.throwIfGoogleOauthTokenError(e);
522
588
  if (BigqueryWarehouseClient.isBigqueryError(e)) {
523
589
  const responseError = e?.errors[0];
524
590
  if (responseError) {
@@ -348,3 +348,109 @@ describe('BigquerySqlBuilder temporal literals', () => {
348
348
  expect(builder.castToNaiveTimestamp(epoch)).toBe("DATETIME '1970-01-01 00:00:00'");
349
349
  });
350
350
  });
351
+ describe('BigqueryWarehouseClient Google OAuth token errors', () => {
352
+ const createGaxiosError = (data, message = data.error, status = 400) => Object.assign(new Error(message), {
353
+ status,
354
+ response: { status, data },
355
+ });
356
+ const invalidGrant = {
357
+ error: 'invalid_grant',
358
+ error_description: 'Token has been expired or revoked.',
359
+ error_subtype: 'invalid_rapt',
360
+ };
361
+ const userCredentials = {
362
+ ...BigqueryWarehouseClient_mock_1.credentials,
363
+ authenticationType: common_1.BigqueryAuthenticationType.SSO,
364
+ keyfileContents: {
365
+ type: 'authorized_user',
366
+ client_id: 'client-id',
367
+ client_secret: 'client-secret',
368
+ refresh_token: 'refresh-token',
369
+ },
370
+ };
371
+ const serviceAccountCredentials = {
372
+ ...BigqueryWarehouseClient_mock_1.credentials,
373
+ authenticationType: common_1.BigqueryAuthenticationType.PRIVATE_KEY,
374
+ keyfileContents: {
375
+ type: 'service_account',
376
+ client_email: 'robot@example.iam.gserviceaccount.com',
377
+ private_key: 'private-key',
378
+ },
379
+ };
380
+ const createWarehouseRejectingQueries = (warehouseCredentials, error) => {
381
+ const warehouse = new BigqueryWarehouseClient_1.BigqueryWarehouseClient(warehouseCredentials);
382
+ const createQueryJob = vi.fn();
383
+ vi.mocked(createQueryJob).mockRejectedValue(error);
384
+ warehouse.client.createQueryJob =
385
+ createQueryJob;
386
+ return warehouse;
387
+ };
388
+ const executeAsyncQuery = (warehouse) => warehouse.executeAsyncQuery({
389
+ sql: 'SELECT 1',
390
+ tags: {},
391
+ });
392
+ it('translates an invalid_grant rejection of a user keyfile into a BigqueryTokenError', async () => {
393
+ const warehouse = createWarehouseRejectingQueries(userCredentials, createGaxiosError(invalidGrant));
394
+ await expect(executeAsyncQuery(warehouse)).rejects.toThrow(common_1.BigqueryTokenError);
395
+ await expect(executeAsyncQuery(warehouse)).rejects.toThrow('Google rejected the BigQuery refresh token (invalid_grant: Token has been expired or revoked.; invalid_rapt). Reconnect your BigQuery account in personal settings.');
396
+ });
397
+ it('translates an invalid_grant rejection of a service account keyfile into a connection error', async () => {
398
+ const warehouse = createWarehouseRejectingQueries(serviceAccountCredentials, createGaxiosError(invalidGrant));
399
+ await expect(executeAsyncQuery(warehouse)).rejects.toThrow(common_1.WarehouseConnectionError);
400
+ await expect(executeAsyncQuery(warehouse)).rejects.not.toThrow(common_1.BigqueryTokenError);
401
+ await expect(executeAsyncQuery(warehouse)).rejects.toThrow('Google rejected the BigQuery credentials (invalid_grant: Token has been expired or revoked.; invalid_rapt).');
402
+ });
403
+ it('omits the subtype clause and falls back to invalid_grant alone', async () => {
404
+ const warehouse = createWarehouseRejectingQueries(userCredentials, createGaxiosError({ error: 'invalid_grant' }));
405
+ await expect(executeAsyncQuery(warehouse)).rejects.toThrow('Google rejected the BigQuery refresh token (invalid_grant). Reconnect your BigQuery account in personal settings.');
406
+ });
407
+ it('leaves other 400 responses untranslated', async () => {
408
+ const original = createGaxiosError({
409
+ error: 'invalid_request',
410
+ error_description: 'Missing required parameter: refresh_token',
411
+ });
412
+ const warehouse = createWarehouseRejectingQueries(userCredentials, original);
413
+ await expect(executeAsyncQuery(warehouse)).rejects.toBe(original);
414
+ });
415
+ it('detects invalid_grant from the response body, not the error message', async () => {
416
+ const warehouse = createWarehouseRejectingQueries(userCredentials, createGaxiosError(invalidGrant, 'Token has been expired or revoked.'));
417
+ await expect(executeAsyncQuery(warehouse)).rejects.toThrow(common_1.BigqueryTokenError);
418
+ });
419
+ it('leaves a bare invalid_grant error without a response untranslated', async () => {
420
+ const original = new Error('invalid_grant');
421
+ const warehouse = createWarehouseRejectingQueries(userCredentials, original);
422
+ await expect(executeAsyncQuery(warehouse)).rejects.toBe(original);
423
+ });
424
+ it('still translates structured BigQuery errors', async () => {
425
+ const warehouse = createWarehouseRejectingQueries(userCredentials, {
426
+ errors: [
427
+ {
428
+ reason: 'quotaExceeded',
429
+ message: 'Query exceeded the daily quota',
430
+ },
431
+ ],
432
+ });
433
+ await expect(executeAsyncQuery(warehouse)).rejects.toThrow(common_1.WarehouseQueryError);
434
+ await expect(executeAsyncQuery(warehouse)).rejects.toThrow('BigQuery quota exceeded. Query exceeded the daily quota');
435
+ });
436
+ it('translates an invalid_grant rejection raised while fetching table metadata', async () => {
437
+ const warehouse = new BigqueryWarehouseClient_1.BigqueryWarehouseClient(userCredentials);
438
+ const getMetadata = vi.fn();
439
+ vi.mocked(getMetadata).mockRejectedValue(createGaxiosError(invalidGrant));
440
+ bigquery_1.Dataset.prototype.table = vi.fn(() => ({ getMetadata }));
441
+ await expect(warehouse.getFields('myTable', 'mySchema', 'myDatabase')).rejects.toThrow(common_1.BigqueryTokenError);
442
+ await expect(warehouse.getCatalog(WarehouseClient_mock_1.config)).rejects.toThrow(common_1.BigqueryTokenError);
443
+ });
444
+ it('translates an invalid_grant rejection raised while listing datasets', async () => {
445
+ const warehouse = new BigqueryWarehouseClient_1.BigqueryWarehouseClient(userCredentials);
446
+ const getDatasets = vi.fn();
447
+ vi.mocked(getDatasets).mockRejectedValue(createGaxiosError(invalidGrant));
448
+ warehouse.client.getDatasets =
449
+ getDatasets;
450
+ await expect(warehouse.getAllTables()).rejects.toThrow(common_1.BigqueryTokenError);
451
+ });
452
+ it('translates an invalid_grant rejection from the connection test', async () => {
453
+ const warehouse = createWarehouseRejectingQueries(userCredentials, createGaxiosError(invalidGrant));
454
+ await expect(warehouse.test()).rejects.toThrow(common_1.BigqueryTokenError);
455
+ });
456
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lightdash/warehouses",
3
- "version": "2.145.0",
3
+ "version": "2.146.1",
4
4
  "description": "Warehouse connectors for Lightdash",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -28,7 +28,7 @@
28
28
  "snowflake-sdk": "2.3.4",
29
29
  "ssh2": "1.14.0",
30
30
  "trino-client": "0.2.9",
31
- "@lightdash/common": "2.145.0"
31
+ "@lightdash/common": "2.146.1"
32
32
  },
33
33
  "devDependencies": {
34
34
  "oxlint": "1.75.0",