@deepnote/database-integrations 1.7.1 → 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 +90 -67
- package/dist/index.d.cts +201 -4718
- package/dist/index.d.ts +201 -4718
- package/dist/index.js +87 -66
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import z, { z as z$1 } from "zod";
|
|
2
|
+
import { convertToEnvironmentVariableName, parseYaml } from "@deepnote/blocks";
|
|
2
3
|
import { isMap, isSeq, parseDocument } from "yaml";
|
|
3
|
-
import { parseYaml } from "@deepnote/blocks";
|
|
4
4
|
//#region src/sql-integration-auth-methods.ts
|
|
5
5
|
const AwsAuthMethods = {
|
|
6
6
|
AccessKeys: "access-keys",
|
|
@@ -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) {
|
|
@@ -823,9 +905,6 @@ const getMySqlSqlAlchemyInput = (integrationId, projectRootDirectory, { user, pa
|
|
|
823
905
|
function getCACertificatePath({ projectRoot, integrationId, caCertificateName }) {
|
|
824
906
|
return `${projectRoot}/.deepnote/${integrationId}/${caCertificateName}`;
|
|
825
907
|
}
|
|
826
|
-
function convertToEnvironmentVariableName(str) {
|
|
827
|
-
return (/^\d/.test(str) ? `_${str}` : str).toUpperCase().replace(/[^\w]/g, "_");
|
|
828
|
-
}
|
|
829
908
|
function getSqlEnvVarName(integrationId) {
|
|
830
909
|
return convertToEnvironmentVariableName(`SQL_${integrationId}`);
|
|
831
910
|
}
|
|
@@ -994,7 +1073,7 @@ const apiIntegrationSchema = z$1.object({
|
|
|
994
1073
|
id: z$1.string(),
|
|
995
1074
|
name: z$1.string(),
|
|
996
1075
|
type: z$1.string(),
|
|
997
|
-
metadata: z$1.unknown(),
|
|
1076
|
+
metadata: z$1.unknown().optional(),
|
|
998
1077
|
is_public: z$1.boolean().nullish(),
|
|
999
1078
|
created_at: z$1.string().nullish(),
|
|
1000
1079
|
updated_at: z$1.string().nullish(),
|
|
@@ -1103,67 +1182,9 @@ function serializeIntegrationsDocument(doc) {
|
|
|
1103
1182
|
* ...
|
|
1104
1183
|
* ```
|
|
1105
1184
|
*/
|
|
1106
|
-
const baseIntegrationsFileSchema = z$1.object({ integrations: z$1.array(z$1.record(z$1.unknown())).optional().default([]) });
|
|
1185
|
+
const baseIntegrationsFileSchema = z$1.object({ integrations: z$1.array(z$1.record(z$1.string(), z$1.unknown())).optional().default([]) });
|
|
1107
1186
|
const integrationsFileSchema = z$1.object({ integrations: z$1.array(databaseIntegrationConfigSchema) });
|
|
1108
1187
|
//#endregion
|
|
1109
|
-
//#region src/secret-field-paths.ts
|
|
1110
|
-
/**
|
|
1111
|
-
* All secret fields for each integration type.
|
|
1112
|
-
* This includes all possible secret fields regardless of auth method.
|
|
1113
|
-
*
|
|
1114
|
-
* Note: For integrations with multiple auth methods (e.g., snowflake, bigquery),
|
|
1115
|
-
* this includes all secret fields from all auth variants.
|
|
1116
|
-
*/
|
|
1117
|
-
const SECRET_PATHS = {
|
|
1118
|
-
alloydb: ["password", "caCertificateText"],
|
|
1119
|
-
mariadb: ["password", "caCertificateText"],
|
|
1120
|
-
materialize: ["password", "caCertificateText"],
|
|
1121
|
-
mindsdb: ["password", "caCertificateText"],
|
|
1122
|
-
mysql: ["password", "caCertificateText"],
|
|
1123
|
-
pgsql: ["password", "caCertificateText"],
|
|
1124
|
-
"sql-server": ["password"],
|
|
1125
|
-
clickhouse: ["password", "caCertificateText"],
|
|
1126
|
-
databricks: ["token"],
|
|
1127
|
-
dremio: ["token"],
|
|
1128
|
-
athena: ["secret_access_key"],
|
|
1129
|
-
spanner: ["service_account"],
|
|
1130
|
-
"cloud-sql": ["service_account"],
|
|
1131
|
-
mongodb: [
|
|
1132
|
-
"password",
|
|
1133
|
-
"connection_string",
|
|
1134
|
-
"rawConnectionString",
|
|
1135
|
-
"caCertificateText"
|
|
1136
|
-
],
|
|
1137
|
-
"pandas-dataframe": [],
|
|
1138
|
-
"big-query": ["service_account", "clientSecret"],
|
|
1139
|
-
snowflake: [
|
|
1140
|
-
"password",
|
|
1141
|
-
"clientSecret",
|
|
1142
|
-
"privateKey",
|
|
1143
|
-
"privateKeyPassphrase",
|
|
1144
|
-
"dbtServiceToken"
|
|
1145
|
-
],
|
|
1146
|
-
redshift: ["password", "caCertificateText"],
|
|
1147
|
-
trino: [
|
|
1148
|
-
"password",
|
|
1149
|
-
"clientSecret",
|
|
1150
|
-
"caCertificateText"
|
|
1151
|
-
]
|
|
1152
|
-
};
|
|
1153
|
-
/**
|
|
1154
|
-
* Get the list of secret field paths for a given integration type.
|
|
1155
|
-
*
|
|
1156
|
-
* @param type - The integration type (e.g., 'pgsql', 'snowflake')
|
|
1157
|
-
* @returns Array of field names that contain secrets
|
|
1158
|
-
*
|
|
1159
|
-
* @example
|
|
1160
|
-
* getSecretFieldPaths('pgsql') // => ['password', 'caCertificateText']
|
|
1161
|
-
* getSecretFieldPaths('snowflake') // => ['password', 'clientSecret', 'privateKey', 'privateKeyPassphrase', 'dbtServiceToken']
|
|
1162
|
-
*/
|
|
1163
|
-
function getSecretFieldPaths(type) {
|
|
1164
|
-
return SECRET_PATHS[type] ?? [];
|
|
1165
|
-
}
|
|
1166
|
-
//#endregion
|
|
1167
1188
|
//#region src/loading/merge-integrations.ts
|
|
1168
1189
|
/**
|
|
1169
1190
|
* JSON schema URL for the integrations file.
|
|
@@ -1504,4 +1525,4 @@ function parseIntegrations({ yaml, env = {} }) {
|
|
|
1504
1525
|
};
|
|
1505
1526
|
}
|
|
1506
1527
|
//#endregion
|
|
1507
|
-
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": "1.
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "Deepnote database integration definitions",
|
|
5
5
|
"keywords": [],
|
|
6
6
|
"repository": {
|
|
@@ -28,8 +28,8 @@
|
|
|
28
28
|
],
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"yaml": "^2.9.0",
|
|
31
|
-
"zod": "
|
|
32
|
-
"@deepnote/blocks": "
|
|
31
|
+
"zod": "^4.6.7",
|
|
32
|
+
"@deepnote/blocks": "5.0.0"
|
|
33
33
|
},
|
|
34
34
|
"publishConfig": {
|
|
35
35
|
"access": "public",
|