@deepnote/database-integrations 2.0.0 → 2.1.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.cjs CHANGED
@@ -428,6 +428,73 @@ const databaseIntegrationConfigSchema = zod.default.discriminatedUnion("type", [
428
428
  })
429
429
  ]);
430
430
  //#endregion
431
+ //#region src/secret-field-paths.ts
432
+ /**
433
+ * All secret fields for each integration type.
434
+ * This includes all possible secret fields regardless of auth method.
435
+ *
436
+ * Note: For integrations with multiple auth methods (e.g., snowflake, bigquery),
437
+ * this includes all secret fields from all auth variants.
438
+ */
439
+ const SECRET_PATHS = {
440
+ alloydb: ["password", "caCertificateText"],
441
+ mariadb: ["password", "caCertificateText"],
442
+ materialize: ["password", "caCertificateText"],
443
+ mindsdb: ["password", "caCertificateText"],
444
+ mysql: ["password", "caCertificateText"],
445
+ pgsql: ["password", "caCertificateText"],
446
+ "sql-server": ["password"],
447
+ clickhouse: ["password", "caCertificateText"],
448
+ databricks: ["token"],
449
+ dremio: ["token"],
450
+ athena: ["secret_access_key"],
451
+ spanner: ["service_account"],
452
+ "cloud-sql": ["service_account"],
453
+ mongodb: [
454
+ "password",
455
+ "connection_string",
456
+ "rawConnectionString",
457
+ "caCertificateText"
458
+ ],
459
+ "pandas-dataframe": [],
460
+ "big-query": ["service_account", "clientSecret"],
461
+ snowflake: [
462
+ "password",
463
+ "clientSecret",
464
+ "privateKey",
465
+ "privateKeyPassphrase",
466
+ "dbtServiceToken"
467
+ ],
468
+ redshift: ["password", "caCertificateText"],
469
+ trino: [
470
+ "password",
471
+ "clientSecret",
472
+ "caCertificateText"
473
+ ]
474
+ };
475
+ /**
476
+ * Get the list of secret field paths for a given integration type.
477
+ *
478
+ * @param type - The integration type (e.g., 'pgsql', 'snowflake')
479
+ * @returns Array of field names that contain secrets
480
+ *
481
+ * @example
482
+ * getSecretFieldPaths('pgsql') // => ['password', 'caCertificateText']
483
+ * getSecretFieldPaths('snowflake') // => ['password', 'clientSecret', 'privateKey', 'privateKeyPassphrase', 'dbtServiceToken']
484
+ */
485
+ function getSecretFieldPaths(type) {
486
+ return SECRET_PATHS[type] ?? [];
487
+ }
488
+ /**
489
+ * Whether `key` is a secret field of an integration whose `metadata.authMethod` is federated.
490
+ * Such integrations authenticate each user with their own identity, so the value never needs
491
+ * to reach notebook code.
492
+ */
493
+ function isFederatedAuthSecretField(type, metadata, key) {
494
+ const { authMethod } = metadata;
495
+ return typeof authMethod === "string" && isFederatedAuthMethod(authMethod) && getSecretFieldPaths(type).includes(key);
496
+ }
497
+ //#endregion
431
498
  //#region src/snowflake-integration-env-vars.ts
432
499
  /**
433
500
  * Build a URL with path and query parameters using native URL API
@@ -500,7 +567,7 @@ function getEnvironmentVariablesForIntegrations(integrations, params) {
500
567
  integrations.forEach((integration) => {
501
568
  const namePrefix = (0, _deepnote_blocks.convertToEnvironmentVariableName)(integration.name);
502
569
  const envVarsForThisIntegration = Object.entries(integration.metadata).filter(([key]) => {
503
- return key !== "caCertificateText";
570
+ return key !== "caCertificateText" && !isFederatedAuthSecretField(integration.type, integration.metadata, key);
504
571
  }).map(([key, rawValue]) => {
505
572
  const name = `${namePrefix}_${key.toUpperCase()}`;
506
573
  const value = String(rawValue);
@@ -798,6 +865,21 @@ const getBigQuerySqlAlchemyInput = (metadata) => {
798
865
  throw new BigQueryServiceAccountParseError("Failed to parse bigquery service account, returning empty environment variable.", { cause: error instanceof Error ? error : new Error(String(error)) });
799
866
  }
800
867
  };
868
+ /**
869
+ * @returns sql alchemy input for a BigQuery integration authenticated via Google OAuth, given an
870
+ * access token minted by the caller. `user_supplied_client=true` tells the runtime to build its
871
+ * BigQuery client from `access_token` / `project` instead of a service account.
872
+ */
873
+ function getBigQueryOAuthSqlAlchemyInput(metadata, accessToken) {
874
+ return {
875
+ url: "bigquery://?user_supplied_client=true",
876
+ params: {
877
+ access_token: accessToken,
878
+ project: metadata.project
879
+ },
880
+ param_style: "pyformat"
881
+ };
882
+ }
801
883
  var SpannerServiceAccountParseError = class extends Error {
802
884
  cause;
803
885
  constructor(message, params) {
@@ -1127,64 +1209,6 @@ function serializeIntegrationsDocument(doc) {
1127
1209
  const baseIntegrationsFileSchema = zod.z.object({ integrations: zod.z.array(zod.z.record(zod.z.string(), zod.z.unknown())).optional().default([]) });
1128
1210
  const integrationsFileSchema = zod.z.object({ integrations: zod.z.array(databaseIntegrationConfigSchema) });
1129
1211
  //#endregion
1130
- //#region src/secret-field-paths.ts
1131
- /**
1132
- * All secret fields for each integration type.
1133
- * This includes all possible secret fields regardless of auth method.
1134
- *
1135
- * Note: For integrations with multiple auth methods (e.g., snowflake, bigquery),
1136
- * this includes all secret fields from all auth variants.
1137
- */
1138
- const SECRET_PATHS = {
1139
- alloydb: ["password", "caCertificateText"],
1140
- mariadb: ["password", "caCertificateText"],
1141
- materialize: ["password", "caCertificateText"],
1142
- mindsdb: ["password", "caCertificateText"],
1143
- mysql: ["password", "caCertificateText"],
1144
- pgsql: ["password", "caCertificateText"],
1145
- "sql-server": ["password"],
1146
- clickhouse: ["password", "caCertificateText"],
1147
- databricks: ["token"],
1148
- dremio: ["token"],
1149
- athena: ["secret_access_key"],
1150
- spanner: ["service_account"],
1151
- "cloud-sql": ["service_account"],
1152
- mongodb: [
1153
- "password",
1154
- "connection_string",
1155
- "rawConnectionString",
1156
- "caCertificateText"
1157
- ],
1158
- "pandas-dataframe": [],
1159
- "big-query": ["service_account", "clientSecret"],
1160
- snowflake: [
1161
- "password",
1162
- "clientSecret",
1163
- "privateKey",
1164
- "privateKeyPassphrase",
1165
- "dbtServiceToken"
1166
- ],
1167
- redshift: ["password", "caCertificateText"],
1168
- trino: [
1169
- "password",
1170
- "clientSecret",
1171
- "caCertificateText"
1172
- ]
1173
- };
1174
- /**
1175
- * Get the list of secret field paths for a given integration type.
1176
- *
1177
- * @param type - The integration type (e.g., 'pgsql', 'snowflake')
1178
- * @returns Array of field names that contain secrets
1179
- *
1180
- * @example
1181
- * getSecretFieldPaths('pgsql') // => ['password', 'caCertificateText']
1182
- * getSecretFieldPaths('snowflake') // => ['password', 'clientSecret', 'privateKey', 'privateKeyPassphrase', 'dbtServiceToken']
1183
- */
1184
- function getSecretFieldPaths(type) {
1185
- return SECRET_PATHS[type] ?? [];
1186
- }
1187
- //#endregion
1188
1212
  //#region src/loading/merge-integrations.ts
1189
1213
  /**
1190
1214
  * JSON schema URL for the integrations file.
@@ -1559,6 +1583,7 @@ exports.extractEnvVarName = extractEnvVarName;
1559
1583
  exports.federatedAuthMethods = federatedAuthMethods;
1560
1584
  exports.fetchIntegrations = fetchIntegrations;
1561
1585
  exports.generateEnvVarName = generateEnvVarName;
1586
+ exports.getBigQueryOAuthSqlAlchemyInput = getBigQueryOAuthSqlAlchemyInput;
1562
1587
  exports.getEnvironmentVariablesForIntegrations = getEnvironmentVariablesForIntegrations;
1563
1588
  exports.getOrCreateIntegrationMetadata = getOrCreateIntegrationMetadata;
1564
1589
  exports.getOrCreateIntegrationsFromDocument = getOrCreateIntegrationsFromDocument;
@@ -1573,6 +1598,7 @@ exports.isDatabaseIntegrationTypeWithSslSupport = isDatabaseIntegrationTypeWithS
1573
1598
  exports.isEnvVarRef = isEnvVarRef;
1574
1599
  exports.isFederatedAuthMetadata = isFederatedAuthMetadata;
1575
1600
  exports.isFederatedAuthMethod = isFederatedAuthMethod;
1601
+ exports.isFederatedAuthSecretField = isFederatedAuthSecretField;
1576
1602
  exports.isSqlIntegrationType = isSqlIntegrationType;
1577
1603
  exports.mergeApiIntegrationsIntoDocument = mergeApiIntegrationsIntoDocument;
1578
1604
  exports.mergeApiIntegrationsIntoYaml = mergeApiIntegrationsIntoYaml;
package/dist/index.d.cts CHANGED
@@ -842,6 +842,14 @@ declare class BigQueryServiceAccountParseError extends Error {
842
842
  cause: Error;
843
843
  });
844
844
  }
845
+ /**
846
+ * @returns sql alchemy input for a BigQuery integration authenticated via Google OAuth, given an
847
+ * access token minted by the caller. `user_supplied_client=true` tells the runtime to build its
848
+ * BigQuery client from `access_token` / `project` instead of a service account.
849
+ */
850
+ declare function getBigQueryOAuthSqlAlchemyInput(metadata: Extract<DatabaseIntegrationMetadataByType['big-query'], {
851
+ authMethod: 'google-oauth';
852
+ }>, accessToken: string): SqlAlchemyInput;
845
853
  declare class SpannerServiceAccountParseError extends Error {
846
854
  cause: Error;
847
855
  constructor(message: string, params: {
@@ -1671,6 +1679,12 @@ type MetadataKey<T extends DatabaseIntegrationType> = AllKeysOf<DatabaseIntegrat
1671
1679
  * getSecretFieldPaths('snowflake') // => ['password', 'clientSecret', 'privateKey', 'privateKeyPassphrase', 'dbtServiceToken']
1672
1680
  */
1673
1681
  declare function getSecretFieldPaths(type: DatabaseIntegrationType): readonly string[];
1682
+ /**
1683
+ * Whether `key` is a secret field of an integration whose `metadata.authMethod` is federated.
1684
+ * Such integrations authenticate each user with their own identity, so the value never needs
1685
+ * to reach notebook code.
1686
+ */
1687
+ declare function isFederatedAuthSecretField(type: DatabaseIntegrationType, metadata: Readonly<Record<string, unknown>>, key: string): boolean;
1674
1688
  //#endregion
1675
1689
  //#region src/sql-integration-auth-methods.d.ts
1676
1690
  declare const AwsAuthMethods: {
@@ -1728,4 +1742,4 @@ interface SnowflakeKeyPair {
1728
1742
  username: string;
1729
1743
  }
1730
1744
  //#endregion
1731
- export { ApiError, ApiIntegration, ApiResponse, type AwsAuthMethod, AwsAuthMethods, BUILTIN_INTEGRATIONS, BaseIntegrationsFile, type BigQueryAuthMethod, BigQueryAuthMethods, BigQueryServiceAccountParseError, ConvertApiIntegrationsResult, DEFAULT_API_URL, DEFAULT_ENV_FILE, DEFAULT_INTEGRATIONS_FILE, type DatabaseAuthMethod, DatabaseAuthMethods, type DatabaseIntegrationConfig, type DatabaseIntegrationMetadataByType, type DatabaseIntegrationType, type DatabaseIntegrationTypeWithSslSupport, ENV_VAR_REF_PREFIX, type EnvVar, EnvVarResolutionError, type FederatedAuthMethod, IntegrationsDocumentMergeResult, IntegrationsFile, IntegrationsMergeResult, IntegrationsParseResult, IntegrationsYamlDocumentMergeResult, IntegrationsYamlParseError, InvalidIntegrationError, InvalidIntegrationsTypeError, JSON_SCHEMA_URL, type MetadataKey, ParseIntegrationsInput, ParsedEnvVarRef, SCHEMA_COMMENT, SkippedApiIntegration, type SnowflakeAuthMethod, SnowflakeAuthMethods, SpannerServiceAccountParseError, type SqlAlchemyInput, type SqlIntegrationConfig, type SqlIntegrationType, type TrinoAuthMethod, TrinoAuthMethods, ValidationIssue, addIntegrationToSeq, apiIntegrationSchema, apiResponseSchema, baseIntegrationsFileSchema, convertApiIntegrations, createEnvVarRef, createNewDocument, databaseIntegrationConfigSchema, databaseIntegrationTypes, databaseIntegrationTypesWithSslSupport, databaseMetadataSchemasByType, extractEnvVarName, federatedAuthMethods, fetchIntegrations, generateEnvVarName, getEnvironmentVariablesForIntegrations, getOrCreateIntegrationMetadata, getOrCreateIntegrationsFromDocument, getSecretFieldPaths, getSnowflakeFederatedAuthSqlAlchemyInput, getSqlAlchemyInput, getSqlEnvVarName, integrationsFileSchema, isBuiltinIntegration, isDatabaseIntegrationType, isDatabaseIntegrationTypeWithSslSupport, isEnvVarRef, isFederatedAuthMetadata, isFederatedAuthMethod, isSqlIntegrationType, mergeApiIntegrationsIntoDocument, mergeApiIntegrationsIntoYaml, mergeProcessedIntegrations, parseEnvVarRef, parseIntegrations, parseIntegrationsDocument, resolveEnvVarRefsFromMap, serializeIntegrationsDocument, sqlIntegrationTypes, updateIntegrationInDocument, updateIntegrationMetadataMap };
1745
+ export { ApiError, ApiIntegration, ApiResponse, type AwsAuthMethod, AwsAuthMethods, BUILTIN_INTEGRATIONS, BaseIntegrationsFile, type BigQueryAuthMethod, BigQueryAuthMethods, BigQueryServiceAccountParseError, ConvertApiIntegrationsResult, DEFAULT_API_URL, DEFAULT_ENV_FILE, DEFAULT_INTEGRATIONS_FILE, type DatabaseAuthMethod, DatabaseAuthMethods, type DatabaseIntegrationConfig, type DatabaseIntegrationMetadataByType, type DatabaseIntegrationType, type DatabaseIntegrationTypeWithSslSupport, ENV_VAR_REF_PREFIX, type EnvVar, EnvVarResolutionError, type FederatedAuthMethod, IntegrationsDocumentMergeResult, IntegrationsFile, IntegrationsMergeResult, IntegrationsParseResult, IntegrationsYamlDocumentMergeResult, IntegrationsYamlParseError, InvalidIntegrationError, InvalidIntegrationsTypeError, JSON_SCHEMA_URL, type MetadataKey, ParseIntegrationsInput, ParsedEnvVarRef, SCHEMA_COMMENT, SkippedApiIntegration, type SnowflakeAuthMethod, SnowflakeAuthMethods, SpannerServiceAccountParseError, type SqlAlchemyInput, type SqlIntegrationConfig, type SqlIntegrationType, type TrinoAuthMethod, TrinoAuthMethods, ValidationIssue, addIntegrationToSeq, apiIntegrationSchema, apiResponseSchema, baseIntegrationsFileSchema, convertApiIntegrations, createEnvVarRef, createNewDocument, databaseIntegrationConfigSchema, databaseIntegrationTypes, databaseIntegrationTypesWithSslSupport, databaseMetadataSchemasByType, extractEnvVarName, federatedAuthMethods, fetchIntegrations, generateEnvVarName, getBigQueryOAuthSqlAlchemyInput, getEnvironmentVariablesForIntegrations, getOrCreateIntegrationMetadata, getOrCreateIntegrationsFromDocument, getSecretFieldPaths, getSnowflakeFederatedAuthSqlAlchemyInput, getSqlAlchemyInput, getSqlEnvVarName, integrationsFileSchema, isBuiltinIntegration, isDatabaseIntegrationType, isDatabaseIntegrationTypeWithSslSupport, isEnvVarRef, isFederatedAuthMetadata, isFederatedAuthMethod, isFederatedAuthSecretField, isSqlIntegrationType, mergeApiIntegrationsIntoDocument, mergeApiIntegrationsIntoYaml, mergeProcessedIntegrations, parseEnvVarRef, parseIntegrations, parseIntegrationsDocument, resolveEnvVarRefsFromMap, serializeIntegrationsDocument, sqlIntegrationTypes, updateIntegrationInDocument, updateIntegrationMetadataMap };
package/dist/index.d.ts CHANGED
@@ -842,6 +842,14 @@ declare class BigQueryServiceAccountParseError extends Error {
842
842
  cause: Error;
843
843
  });
844
844
  }
845
+ /**
846
+ * @returns sql alchemy input for a BigQuery integration authenticated via Google OAuth, given an
847
+ * access token minted by the caller. `user_supplied_client=true` tells the runtime to build its
848
+ * BigQuery client from `access_token` / `project` instead of a service account.
849
+ */
850
+ declare function getBigQueryOAuthSqlAlchemyInput(metadata: Extract<DatabaseIntegrationMetadataByType['big-query'], {
851
+ authMethod: 'google-oauth';
852
+ }>, accessToken: string): SqlAlchemyInput;
845
853
  declare class SpannerServiceAccountParseError extends Error {
846
854
  cause: Error;
847
855
  constructor(message: string, params: {
@@ -1671,6 +1679,12 @@ type MetadataKey<T extends DatabaseIntegrationType> = AllKeysOf<DatabaseIntegrat
1671
1679
  * getSecretFieldPaths('snowflake') // => ['password', 'clientSecret', 'privateKey', 'privateKeyPassphrase', 'dbtServiceToken']
1672
1680
  */
1673
1681
  declare function getSecretFieldPaths(type: DatabaseIntegrationType): readonly string[];
1682
+ /**
1683
+ * Whether `key` is a secret field of an integration whose `metadata.authMethod` is federated.
1684
+ * Such integrations authenticate each user with their own identity, so the value never needs
1685
+ * to reach notebook code.
1686
+ */
1687
+ declare function isFederatedAuthSecretField(type: DatabaseIntegrationType, metadata: Readonly<Record<string, unknown>>, key: string): boolean;
1674
1688
  //#endregion
1675
1689
  //#region src/sql-integration-auth-methods.d.ts
1676
1690
  declare const AwsAuthMethods: {
@@ -1728,4 +1742,4 @@ interface SnowflakeKeyPair {
1728
1742
  username: string;
1729
1743
  }
1730
1744
  //#endregion
1731
- export { ApiError, ApiIntegration, ApiResponse, type AwsAuthMethod, AwsAuthMethods, BUILTIN_INTEGRATIONS, BaseIntegrationsFile, type BigQueryAuthMethod, BigQueryAuthMethods, BigQueryServiceAccountParseError, ConvertApiIntegrationsResult, DEFAULT_API_URL, DEFAULT_ENV_FILE, DEFAULT_INTEGRATIONS_FILE, type DatabaseAuthMethod, DatabaseAuthMethods, type DatabaseIntegrationConfig, type DatabaseIntegrationMetadataByType, type DatabaseIntegrationType, type DatabaseIntegrationTypeWithSslSupport, ENV_VAR_REF_PREFIX, type EnvVar, EnvVarResolutionError, type FederatedAuthMethod, IntegrationsDocumentMergeResult, IntegrationsFile, IntegrationsMergeResult, IntegrationsParseResult, IntegrationsYamlDocumentMergeResult, IntegrationsYamlParseError, InvalidIntegrationError, InvalidIntegrationsTypeError, JSON_SCHEMA_URL, type MetadataKey, ParseIntegrationsInput, ParsedEnvVarRef, SCHEMA_COMMENT, SkippedApiIntegration, type SnowflakeAuthMethod, SnowflakeAuthMethods, SpannerServiceAccountParseError, type SqlAlchemyInput, type SqlIntegrationConfig, type SqlIntegrationType, type TrinoAuthMethod, TrinoAuthMethods, ValidationIssue, addIntegrationToSeq, apiIntegrationSchema, apiResponseSchema, baseIntegrationsFileSchema, convertApiIntegrations, createEnvVarRef, createNewDocument, databaseIntegrationConfigSchema, databaseIntegrationTypes, databaseIntegrationTypesWithSslSupport, databaseMetadataSchemasByType, extractEnvVarName, federatedAuthMethods, fetchIntegrations, generateEnvVarName, getEnvironmentVariablesForIntegrations, getOrCreateIntegrationMetadata, getOrCreateIntegrationsFromDocument, getSecretFieldPaths, getSnowflakeFederatedAuthSqlAlchemyInput, getSqlAlchemyInput, getSqlEnvVarName, integrationsFileSchema, isBuiltinIntegration, isDatabaseIntegrationType, isDatabaseIntegrationTypeWithSslSupport, isEnvVarRef, isFederatedAuthMetadata, isFederatedAuthMethod, isSqlIntegrationType, mergeApiIntegrationsIntoDocument, mergeApiIntegrationsIntoYaml, mergeProcessedIntegrations, parseEnvVarRef, parseIntegrations, parseIntegrationsDocument, resolveEnvVarRefsFromMap, serializeIntegrationsDocument, sqlIntegrationTypes, updateIntegrationInDocument, updateIntegrationMetadataMap };
1745
+ export { ApiError, ApiIntegration, ApiResponse, type AwsAuthMethod, AwsAuthMethods, BUILTIN_INTEGRATIONS, BaseIntegrationsFile, type BigQueryAuthMethod, BigQueryAuthMethods, BigQueryServiceAccountParseError, ConvertApiIntegrationsResult, DEFAULT_API_URL, DEFAULT_ENV_FILE, DEFAULT_INTEGRATIONS_FILE, type DatabaseAuthMethod, DatabaseAuthMethods, type DatabaseIntegrationConfig, type DatabaseIntegrationMetadataByType, type DatabaseIntegrationType, type DatabaseIntegrationTypeWithSslSupport, ENV_VAR_REF_PREFIX, type EnvVar, EnvVarResolutionError, type FederatedAuthMethod, IntegrationsDocumentMergeResult, IntegrationsFile, IntegrationsMergeResult, IntegrationsParseResult, IntegrationsYamlDocumentMergeResult, IntegrationsYamlParseError, InvalidIntegrationError, InvalidIntegrationsTypeError, JSON_SCHEMA_URL, type MetadataKey, ParseIntegrationsInput, ParsedEnvVarRef, SCHEMA_COMMENT, SkippedApiIntegration, type SnowflakeAuthMethod, SnowflakeAuthMethods, SpannerServiceAccountParseError, type SqlAlchemyInput, type SqlIntegrationConfig, type SqlIntegrationType, type TrinoAuthMethod, TrinoAuthMethods, ValidationIssue, addIntegrationToSeq, apiIntegrationSchema, apiResponseSchema, baseIntegrationsFileSchema, convertApiIntegrations, createEnvVarRef, createNewDocument, databaseIntegrationConfigSchema, databaseIntegrationTypes, databaseIntegrationTypesWithSslSupport, databaseMetadataSchemasByType, extractEnvVarName, federatedAuthMethods, fetchIntegrations, generateEnvVarName, getBigQueryOAuthSqlAlchemyInput, getEnvironmentVariablesForIntegrations, getOrCreateIntegrationMetadata, getOrCreateIntegrationsFromDocument, getSecretFieldPaths, getSnowflakeFederatedAuthSqlAlchemyInput, getSqlAlchemyInput, getSqlEnvVarName, integrationsFileSchema, isBuiltinIntegration, isDatabaseIntegrationType, isDatabaseIntegrationTypeWithSslSupport, isEnvVarRef, isFederatedAuthMetadata, isFederatedAuthMethod, isFederatedAuthSecretField, isSqlIntegrationType, mergeApiIntegrationsIntoDocument, mergeApiIntegrationsIntoYaml, mergeProcessedIntegrations, parseEnvVarRef, parseIntegrations, parseIntegrationsDocument, resolveEnvVarRefsFromMap, serializeIntegrationsDocument, sqlIntegrationTypes, updateIntegrationInDocument, updateIntegrationMetadataMap };
package/dist/index.js CHANGED
@@ -404,6 +404,73 @@ const databaseIntegrationConfigSchema = z.discriminatedUnion("type", [
404
404
  })
405
405
  ]);
406
406
  //#endregion
407
+ //#region src/secret-field-paths.ts
408
+ /**
409
+ * All secret fields for each integration type.
410
+ * This includes all possible secret fields regardless of auth method.
411
+ *
412
+ * Note: For integrations with multiple auth methods (e.g., snowflake, bigquery),
413
+ * this includes all secret fields from all auth variants.
414
+ */
415
+ const SECRET_PATHS = {
416
+ alloydb: ["password", "caCertificateText"],
417
+ mariadb: ["password", "caCertificateText"],
418
+ materialize: ["password", "caCertificateText"],
419
+ mindsdb: ["password", "caCertificateText"],
420
+ mysql: ["password", "caCertificateText"],
421
+ pgsql: ["password", "caCertificateText"],
422
+ "sql-server": ["password"],
423
+ clickhouse: ["password", "caCertificateText"],
424
+ databricks: ["token"],
425
+ dremio: ["token"],
426
+ athena: ["secret_access_key"],
427
+ spanner: ["service_account"],
428
+ "cloud-sql": ["service_account"],
429
+ mongodb: [
430
+ "password",
431
+ "connection_string",
432
+ "rawConnectionString",
433
+ "caCertificateText"
434
+ ],
435
+ "pandas-dataframe": [],
436
+ "big-query": ["service_account", "clientSecret"],
437
+ snowflake: [
438
+ "password",
439
+ "clientSecret",
440
+ "privateKey",
441
+ "privateKeyPassphrase",
442
+ "dbtServiceToken"
443
+ ],
444
+ redshift: ["password", "caCertificateText"],
445
+ trino: [
446
+ "password",
447
+ "clientSecret",
448
+ "caCertificateText"
449
+ ]
450
+ };
451
+ /**
452
+ * Get the list of secret field paths for a given integration type.
453
+ *
454
+ * @param type - The integration type (e.g., 'pgsql', 'snowflake')
455
+ * @returns Array of field names that contain secrets
456
+ *
457
+ * @example
458
+ * getSecretFieldPaths('pgsql') // => ['password', 'caCertificateText']
459
+ * getSecretFieldPaths('snowflake') // => ['password', 'clientSecret', 'privateKey', 'privateKeyPassphrase', 'dbtServiceToken']
460
+ */
461
+ function getSecretFieldPaths(type) {
462
+ return SECRET_PATHS[type] ?? [];
463
+ }
464
+ /**
465
+ * Whether `key` is a secret field of an integration whose `metadata.authMethod` is federated.
466
+ * Such integrations authenticate each user with their own identity, so the value never needs
467
+ * to reach notebook code.
468
+ */
469
+ function isFederatedAuthSecretField(type, metadata, key) {
470
+ const { authMethod } = metadata;
471
+ return typeof authMethod === "string" && isFederatedAuthMethod(authMethod) && getSecretFieldPaths(type).includes(key);
472
+ }
473
+ //#endregion
407
474
  //#region src/snowflake-integration-env-vars.ts
408
475
  /**
409
476
  * Build a URL with path and query parameters using native URL API
@@ -476,7 +543,7 @@ function getEnvironmentVariablesForIntegrations(integrations, params) {
476
543
  integrations.forEach((integration) => {
477
544
  const namePrefix = convertToEnvironmentVariableName(integration.name);
478
545
  const envVarsForThisIntegration = Object.entries(integration.metadata).filter(([key]) => {
479
- return key !== "caCertificateText";
546
+ return key !== "caCertificateText" && !isFederatedAuthSecretField(integration.type, integration.metadata, key);
480
547
  }).map(([key, rawValue]) => {
481
548
  const name = `${namePrefix}_${key.toUpperCase()}`;
482
549
  const value = String(rawValue);
@@ -774,6 +841,21 @@ const getBigQuerySqlAlchemyInput = (metadata) => {
774
841
  throw new BigQueryServiceAccountParseError("Failed to parse bigquery service account, returning empty environment variable.", { cause: error instanceof Error ? error : new Error(String(error)) });
775
842
  }
776
843
  };
844
+ /**
845
+ * @returns sql alchemy input for a BigQuery integration authenticated via Google OAuth, given an
846
+ * access token minted by the caller. `user_supplied_client=true` tells the runtime to build its
847
+ * BigQuery client from `access_token` / `project` instead of a service account.
848
+ */
849
+ function getBigQueryOAuthSqlAlchemyInput(metadata, accessToken) {
850
+ return {
851
+ url: "bigquery://?user_supplied_client=true",
852
+ params: {
853
+ access_token: accessToken,
854
+ project: metadata.project
855
+ },
856
+ param_style: "pyformat"
857
+ };
858
+ }
777
859
  var SpannerServiceAccountParseError = class extends Error {
778
860
  cause;
779
861
  constructor(message, params) {
@@ -1103,64 +1185,6 @@ function serializeIntegrationsDocument(doc) {
1103
1185
  const baseIntegrationsFileSchema = z$1.object({ integrations: z$1.array(z$1.record(z$1.string(), z$1.unknown())).optional().default([]) });
1104
1186
  const integrationsFileSchema = z$1.object({ integrations: z$1.array(databaseIntegrationConfigSchema) });
1105
1187
  //#endregion
1106
- //#region src/secret-field-paths.ts
1107
- /**
1108
- * All secret fields for each integration type.
1109
- * This includes all possible secret fields regardless of auth method.
1110
- *
1111
- * Note: For integrations with multiple auth methods (e.g., snowflake, bigquery),
1112
- * this includes all secret fields from all auth variants.
1113
- */
1114
- const SECRET_PATHS = {
1115
- alloydb: ["password", "caCertificateText"],
1116
- mariadb: ["password", "caCertificateText"],
1117
- materialize: ["password", "caCertificateText"],
1118
- mindsdb: ["password", "caCertificateText"],
1119
- mysql: ["password", "caCertificateText"],
1120
- pgsql: ["password", "caCertificateText"],
1121
- "sql-server": ["password"],
1122
- clickhouse: ["password", "caCertificateText"],
1123
- databricks: ["token"],
1124
- dremio: ["token"],
1125
- athena: ["secret_access_key"],
1126
- spanner: ["service_account"],
1127
- "cloud-sql": ["service_account"],
1128
- mongodb: [
1129
- "password",
1130
- "connection_string",
1131
- "rawConnectionString",
1132
- "caCertificateText"
1133
- ],
1134
- "pandas-dataframe": [],
1135
- "big-query": ["service_account", "clientSecret"],
1136
- snowflake: [
1137
- "password",
1138
- "clientSecret",
1139
- "privateKey",
1140
- "privateKeyPassphrase",
1141
- "dbtServiceToken"
1142
- ],
1143
- redshift: ["password", "caCertificateText"],
1144
- trino: [
1145
- "password",
1146
- "clientSecret",
1147
- "caCertificateText"
1148
- ]
1149
- };
1150
- /**
1151
- * Get the list of secret field paths for a given integration type.
1152
- *
1153
- * @param type - The integration type (e.g., 'pgsql', 'snowflake')
1154
- * @returns Array of field names that contain secrets
1155
- *
1156
- * @example
1157
- * getSecretFieldPaths('pgsql') // => ['password', 'caCertificateText']
1158
- * getSecretFieldPaths('snowflake') // => ['password', 'clientSecret', 'privateKey', 'privateKeyPassphrase', 'dbtServiceToken']
1159
- */
1160
- function getSecretFieldPaths(type) {
1161
- return SECRET_PATHS[type] ?? [];
1162
- }
1163
- //#endregion
1164
1188
  //#region src/loading/merge-integrations.ts
1165
1189
  /**
1166
1190
  * JSON schema URL for the integrations file.
@@ -1501,4 +1525,4 @@ function parseIntegrations({ yaml, env = {} }) {
1501
1525
  };
1502
1526
  }
1503
1527
  //#endregion
1504
- export { ApiError, AwsAuthMethods, BUILTIN_INTEGRATIONS, BigQueryAuthMethods, BigQueryServiceAccountParseError, DEFAULT_API_URL, DEFAULT_ENV_FILE, DEFAULT_INTEGRATIONS_FILE, DatabaseAuthMethods, ENV_VAR_REF_PREFIX, EnvVarResolutionError, IntegrationsYamlParseError, InvalidIntegrationError, InvalidIntegrationsTypeError, JSON_SCHEMA_URL, SCHEMA_COMMENT, SnowflakeAuthMethods, SpannerServiceAccountParseError, TrinoAuthMethods, addIntegrationToSeq, apiIntegrationSchema, apiResponseSchema, baseIntegrationsFileSchema, convertApiIntegrations, createEnvVarRef, createNewDocument, databaseIntegrationConfigSchema, databaseIntegrationTypes, databaseIntegrationTypesWithSslSupport, databaseMetadataSchemasByType, extractEnvVarName, federatedAuthMethods, fetchIntegrations, generateEnvVarName, getEnvironmentVariablesForIntegrations, getOrCreateIntegrationMetadata, getOrCreateIntegrationsFromDocument, getSecretFieldPaths, getSnowflakeFederatedAuthSqlAlchemyInput, getSqlAlchemyInput, getSqlEnvVarName, integrationsFileSchema, isBuiltinIntegration, isDatabaseIntegrationType, isDatabaseIntegrationTypeWithSslSupport, isEnvVarRef, isFederatedAuthMetadata, isFederatedAuthMethod, isSqlIntegrationType, mergeApiIntegrationsIntoDocument, mergeApiIntegrationsIntoYaml, mergeProcessedIntegrations, parseEnvVarRef, parseIntegrations, parseIntegrationsDocument, resolveEnvVarRefsFromMap, serializeIntegrationsDocument, sqlIntegrationTypes, updateIntegrationInDocument, updateIntegrationMetadataMap };
1528
+ export { ApiError, AwsAuthMethods, BUILTIN_INTEGRATIONS, BigQueryAuthMethods, BigQueryServiceAccountParseError, DEFAULT_API_URL, DEFAULT_ENV_FILE, DEFAULT_INTEGRATIONS_FILE, DatabaseAuthMethods, ENV_VAR_REF_PREFIX, EnvVarResolutionError, IntegrationsYamlParseError, InvalidIntegrationError, InvalidIntegrationsTypeError, JSON_SCHEMA_URL, SCHEMA_COMMENT, SnowflakeAuthMethods, SpannerServiceAccountParseError, TrinoAuthMethods, addIntegrationToSeq, apiIntegrationSchema, apiResponseSchema, baseIntegrationsFileSchema, convertApiIntegrations, createEnvVarRef, createNewDocument, databaseIntegrationConfigSchema, databaseIntegrationTypes, databaseIntegrationTypesWithSslSupport, databaseMetadataSchemasByType, extractEnvVarName, federatedAuthMethods, fetchIntegrations, generateEnvVarName, getBigQueryOAuthSqlAlchemyInput, getEnvironmentVariablesForIntegrations, getOrCreateIntegrationMetadata, getOrCreateIntegrationsFromDocument, getSecretFieldPaths, getSnowflakeFederatedAuthSqlAlchemyInput, getSqlAlchemyInput, getSqlEnvVarName, integrationsFileSchema, isBuiltinIntegration, isDatabaseIntegrationType, isDatabaseIntegrationTypeWithSslSupport, isEnvVarRef, isFederatedAuthMetadata, isFederatedAuthMethod, isFederatedAuthSecretField, isSqlIntegrationType, mergeApiIntegrationsIntoDocument, mergeApiIntegrationsIntoYaml, mergeProcessedIntegrations, parseEnvVarRef, parseIntegrations, parseIntegrationsDocument, resolveEnvVarRefsFromMap, serializeIntegrationsDocument, sqlIntegrationTypes, updateIntegrationInDocument, updateIntegrationMetadataMap };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deepnote/database-integrations",
3
- "version": "2.0.0",
3
+ "version": "2.1.0",
4
4
  "description": "Deepnote database integration definitions",
5
5
  "keywords": [],
6
6
  "repository": {