@deepnote/database-integrations 1.6.0 → 1.7.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.
- package/dist/index.cjs +64 -39
- package/dist/index.d.cts +967 -943
- package/dist/index.d.ts +967 -943
- package/dist/index.js +55 -30
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import z, { z as z$1 } from "zod";
|
|
2
2
|
import { isMap, isSeq, parseDocument } from "yaml";
|
|
3
3
|
import { parseYaml } from "@deepnote/blocks";
|
|
4
|
-
|
|
5
4
|
//#region src/sql-integration-auth-methods.ts
|
|
6
5
|
const AwsAuthMethods = {
|
|
7
6
|
AccessKeys: "access-keys",
|
|
@@ -42,7 +41,6 @@ function isFederatedAuthMethod(authMethod) {
|
|
|
42
41
|
function isFederatedAuthMetadata(metadata) {
|
|
43
42
|
return metadata.authMethod !== void 0 && isFederatedAuthMethod(metadata.authMethod);
|
|
44
43
|
}
|
|
45
|
-
|
|
46
44
|
//#endregion
|
|
47
45
|
//#region src/database-integration-metadata-schemas.ts
|
|
48
46
|
const athenaMetadataSchema = z$1.object({
|
|
@@ -270,8 +268,6 @@ const pgsqlMetadataSchema = commonDatabaseSchema.extend({
|
|
|
270
268
|
caCertificateName: z$1.string().optional(),
|
|
271
269
|
caCertificateText: z$1.string().optional()
|
|
272
270
|
});
|
|
273
|
-
const materializeMetadataSchema = pgsqlMetadataSchema.extend({ cluster: z$1.string() });
|
|
274
|
-
const sqlServerMetadataSchema = commonDatabaseSchema.extend({ port: z$1.string() });
|
|
275
271
|
const databaseMetadataSchemasByType = {
|
|
276
272
|
"alloydb": alloydbMetadataSchema,
|
|
277
273
|
"athena": athenaMetadataSchema,
|
|
@@ -281,7 +277,7 @@ const databaseMetadataSchemasByType = {
|
|
|
281
277
|
"databricks": databricksMetadataSchema,
|
|
282
278
|
"dremio": dremioMetadataSchema,
|
|
283
279
|
"mariadb": mariadbMetadataSchema,
|
|
284
|
-
"materialize":
|
|
280
|
+
"materialize": pgsqlMetadataSchema.extend({ cluster: z$1.string() }),
|
|
285
281
|
"mindsdb": mindsdbMetadataSchema,
|
|
286
282
|
"mongodb": mongodbMetadataSchema,
|
|
287
283
|
"mysql": mysqlMetadataSchema,
|
|
@@ -290,10 +286,9 @@ const databaseMetadataSchemasByType = {
|
|
|
290
286
|
"redshift": redshiftMetadataSchema,
|
|
291
287
|
"snowflake": snowflakeMetadataSchema,
|
|
292
288
|
"spanner": spannerMetadataSchema,
|
|
293
|
-
"sql-server":
|
|
289
|
+
"sql-server": commonDatabaseSchema.extend({ port: z$1.string() }),
|
|
294
290
|
"trino": trinoMetadataSchema
|
|
295
291
|
};
|
|
296
|
-
|
|
297
292
|
//#endregion
|
|
298
293
|
//#region src/database-integration-config.ts
|
|
299
294
|
const commonIntegrationConfig = z.object({
|
|
@@ -408,7 +403,6 @@ const databaseIntegrationConfigSchema = z.discriminatedUnion("type", [
|
|
|
408
403
|
federated_auth_method: z.enum(["trino-oauth", "password"]).optional().nullable()
|
|
409
404
|
})
|
|
410
405
|
]);
|
|
411
|
-
|
|
412
406
|
//#endregion
|
|
413
407
|
//#region src/snowflake-integration-env-vars.ts
|
|
414
408
|
/**
|
|
@@ -474,7 +468,6 @@ function createSqlAlchemyInputFromUrl(url, keyPair) {
|
|
|
474
468
|
param_style: "pyformat"
|
|
475
469
|
};
|
|
476
470
|
}
|
|
477
|
-
|
|
478
471
|
//#endregion
|
|
479
472
|
//#region src/database-integration-env-vars.ts
|
|
480
473
|
function getEnvironmentVariablesForIntegrations(integrations, params) {
|
|
@@ -839,7 +832,6 @@ function getSqlEnvVarName(integrationId) {
|
|
|
839
832
|
function assertNever(value) {
|
|
840
833
|
throw new Error(`Unexpected value: ${value}`);
|
|
841
834
|
}
|
|
842
|
-
|
|
843
835
|
//#endregion
|
|
844
836
|
//#region src/database-integration-types.ts
|
|
845
837
|
const sqlIntegrationTypes = [
|
|
@@ -884,7 +876,6 @@ function isSqlIntegrationType(type) {
|
|
|
884
876
|
function isDatabaseIntegrationTypeWithSslSupport(type) {
|
|
885
877
|
return databaseIntegrationTypesWithSslSupport.includes(type);
|
|
886
878
|
}
|
|
887
|
-
|
|
888
879
|
//#endregion
|
|
889
880
|
//#region src/loading/api-error.ts
|
|
890
881
|
/**
|
|
@@ -898,18 +889,31 @@ var ApiError = class extends Error {
|
|
|
898
889
|
this.statusCode = statusCode;
|
|
899
890
|
}
|
|
900
891
|
};
|
|
901
|
-
|
|
902
892
|
//#endregion
|
|
903
893
|
//#region src/loading/constants.ts
|
|
904
|
-
/** Built-in integrations that don't require external configuration. */
|
|
905
|
-
const BUILTIN_INTEGRATIONS = new Set(["deepnote-dataframe-sql", "pandas-dataframe"]);
|
|
894
|
+
/** Built-in integrations that don't require external configuration. Keys are canonical lowercase IDs. */
|
|
895
|
+
const BUILTIN_INTEGRATIONS = /* @__PURE__ */ new Set(["deepnote-dataframe-sql", "pandas-dataframe"]);
|
|
896
|
+
/**
|
|
897
|
+
* Return whether the given integration ID refers to a built-in integration.
|
|
898
|
+
*
|
|
899
|
+
* The comparison is case-insensitive: built-in IDs are stored as canonical
|
|
900
|
+
* lowercase strings in {@link BUILTIN_INTEGRATIONS}, and SQL block metadata may
|
|
901
|
+
* reference them in any casing (e.g. `Pandas-DataFrame`). This mirrors the
|
|
902
|
+
* case-insensitive env-var derivation in `getSqlEnvVarName`, so a built-in is
|
|
903
|
+
* recognized regardless of how a notebook cased its `sql_integration_id`.
|
|
904
|
+
*
|
|
905
|
+
* @param integrationId - The integration ID from SQL block metadata.
|
|
906
|
+
* @returns `true` when the ID matches a built-in integration regardless of casing.
|
|
907
|
+
*/
|
|
908
|
+
function isBuiltinIntegration(integrationId) {
|
|
909
|
+
return BUILTIN_INTEGRATIONS.has(integrationId.toLowerCase());
|
|
910
|
+
}
|
|
906
911
|
/** Default `.env` file name for storing integration secrets. */
|
|
907
912
|
const DEFAULT_ENV_FILE = ".env";
|
|
908
913
|
/** Default integrations file name. */
|
|
909
914
|
const DEFAULT_INTEGRATIONS_FILE = ".deepnote.env.yaml";
|
|
910
915
|
/** Default Deepnote API base URL. */
|
|
911
916
|
const DEFAULT_API_URL = "https://api.deepnote.com";
|
|
912
|
-
|
|
913
917
|
//#endregion
|
|
914
918
|
//#region src/loading/env-var-refs.ts
|
|
915
919
|
const ENV_VAR_REF_PREFIX = "env:";
|
|
@@ -918,7 +922,7 @@ function generateEnvVarName(integrationId, fieldPath) {
|
|
|
918
922
|
}
|
|
919
923
|
function parseEnvVarRef(value) {
|
|
920
924
|
if (typeof value !== "string") return null;
|
|
921
|
-
if (!value.startsWith(
|
|
925
|
+
if (!value.startsWith("env:")) return null;
|
|
922
926
|
const varName = value.slice(4);
|
|
923
927
|
if (!varName) return null;
|
|
924
928
|
return {
|
|
@@ -981,7 +985,6 @@ function resolveEnvVarRefsFromMap(obj, vars, currentPath) {
|
|
|
981
985
|
}
|
|
982
986
|
return obj;
|
|
983
987
|
}
|
|
984
|
-
|
|
985
988
|
//#endregion
|
|
986
989
|
//#region src/loading/fetch-integrations.ts
|
|
987
990
|
/**
|
|
@@ -1012,14 +1015,17 @@ function trimTrailingSlash(url) {
|
|
|
1012
1015
|
*
|
|
1013
1016
|
* @param baseUrl - The base URL of the Deepnote API
|
|
1014
1017
|
* @param token - The authentication token
|
|
1015
|
-
* @param integrationIds - Optional list of integration
|
|
1018
|
+
* @param integrationIds - Optional list of integration UUIDs to fetch. When provided, only these integrations are returned.
|
|
1016
1019
|
* @returns Array of integrations from the API
|
|
1017
1020
|
* @throws ApiError if the request fails
|
|
1018
1021
|
*/
|
|
1019
1022
|
async function fetchIntegrations(baseUrl, token, integrationIds) {
|
|
1020
1023
|
const endpoint = new URL(`${trimTrailingSlash(baseUrl)}/v2/integrations`);
|
|
1021
1024
|
endpoint.searchParams.set("includeMetadata", "true");
|
|
1022
|
-
if (integrationIds && integrationIds.length > 0)
|
|
1025
|
+
if (integrationIds && integrationIds.length > 0) {
|
|
1026
|
+
const normalizedIntegrationIds = new Set(integrationIds.map((id) => id.toLowerCase()));
|
|
1027
|
+
endpoint.searchParams.set("integrationIds", Array.from(normalizedIntegrationIds).join(","));
|
|
1028
|
+
}
|
|
1023
1029
|
const url = endpoint.toString();
|
|
1024
1030
|
const response = await fetch(url, {
|
|
1025
1031
|
method: "GET",
|
|
@@ -1039,21 +1045,38 @@ async function fetchIntegrations(baseUrl, token, integrationIds) {
|
|
|
1039
1045
|
if (!parseResult.success) throw new Error(`Invalid API response: ${parseResult.error.message}`);
|
|
1040
1046
|
return parseResult.data.integrations;
|
|
1041
1047
|
}
|
|
1042
|
-
|
|
1043
1048
|
//#endregion
|
|
1044
1049
|
//#region src/loading/integrations-document.ts
|
|
1045
1050
|
/**
|
|
1051
|
+
* Error thrown when integrations YAML content cannot be parsed.
|
|
1052
|
+
*/
|
|
1053
|
+
var IntegrationsYamlParseError = class extends Error {
|
|
1054
|
+
/** The underlying parse errors reported by the `yaml` library. */
|
|
1055
|
+
errors;
|
|
1056
|
+
constructor(errors) {
|
|
1057
|
+
super(`Failed to parse integrations YAML: ${errors[0]?.message ?? "unknown parse error"}`);
|
|
1058
|
+
this.name = "IntegrationsYamlParseError";
|
|
1059
|
+
this.errors = errors;
|
|
1060
|
+
}
|
|
1061
|
+
};
|
|
1062
|
+
/**
|
|
1046
1063
|
* Parse integrations YAML content into a mutable `yaml` Document that preserves
|
|
1047
1064
|
* comments and formatting. Returns `null` for empty content.
|
|
1048
1065
|
*
|
|
1049
1066
|
* This is the content-accepting counterpart of the Node-only `readIntegrationsDocument`.
|
|
1067
|
+
*
|
|
1068
|
+
* @throws {IntegrationsYamlParseError} If the content is not valid YAML. Malformed
|
|
1069
|
+
* content is rejected here rather than at serialization time, where `yaml` would
|
|
1070
|
+
* otherwise fail with an opaque "Document with errors cannot be stringified".
|
|
1050
1071
|
*/
|
|
1051
1072
|
function parseIntegrationsDocument(content) {
|
|
1052
1073
|
if (!content.trim()) return null;
|
|
1053
|
-
|
|
1074
|
+
const doc = parseDocument(content, {
|
|
1054
1075
|
strict: true,
|
|
1055
1076
|
version: "1.2"
|
|
1056
1077
|
});
|
|
1078
|
+
if (doc.errors.length > 0) throw new IntegrationsYamlParseError(doc.errors);
|
|
1079
|
+
return doc;
|
|
1057
1080
|
}
|
|
1058
1081
|
/**
|
|
1059
1082
|
* Serialize an integrations Document back to YAML text, preserving comments and
|
|
@@ -1062,7 +1085,6 @@ function parseIntegrationsDocument(content) {
|
|
|
1062
1085
|
function serializeIntegrationsDocument(doc) {
|
|
1063
1086
|
return doc.toString({ lineWidth: 0 });
|
|
1064
1087
|
}
|
|
1065
|
-
|
|
1066
1088
|
//#endregion
|
|
1067
1089
|
//#region src/loading/integrations-file-schema.ts
|
|
1068
1090
|
/**
|
|
@@ -1083,7 +1105,6 @@ function serializeIntegrationsDocument(doc) {
|
|
|
1083
1105
|
*/
|
|
1084
1106
|
const baseIntegrationsFileSchema = z$1.object({ integrations: z$1.array(z$1.record(z$1.unknown())).optional().default([]) });
|
|
1085
1107
|
const integrationsFileSchema = z$1.object({ integrations: z$1.array(databaseIntegrationConfigSchema) });
|
|
1086
|
-
|
|
1087
1108
|
//#endregion
|
|
1088
1109
|
//#region src/secret-field-paths.ts
|
|
1089
1110
|
/**
|
|
@@ -1142,7 +1163,6 @@ const SECRET_PATHS = {
|
|
|
1142
1163
|
function getSecretFieldPaths(type) {
|
|
1143
1164
|
return SECRET_PATHS[type] ?? [];
|
|
1144
1165
|
}
|
|
1145
|
-
|
|
1146
1166
|
//#endregion
|
|
1147
1167
|
//#region src/loading/merge-integrations.ts
|
|
1148
1168
|
/**
|
|
@@ -1212,7 +1232,7 @@ function updateIntegrationMetadataMap({ metadataMap, integrationId, integrationM
|
|
|
1212
1232
|
* @returns Record of extracted secrets (envVarName -> secretValue)
|
|
1213
1233
|
*/
|
|
1214
1234
|
function updateIntegrationInDocument(doc, integrationMap, integration) {
|
|
1215
|
-
const { id, name, type, metadata, federated_auth_method
|
|
1235
|
+
const { id, name, type, metadata, federated_auth_method, ...rest } = integration;
|
|
1216
1236
|
integrationMap.set("id", id);
|
|
1217
1237
|
integrationMap.set("name", name);
|
|
1218
1238
|
integrationMap.set("type", type);
|
|
@@ -1235,7 +1255,7 @@ function updateIntegrationInDocument(doc, integrationMap, integration) {
|
|
|
1235
1255
|
*/
|
|
1236
1256
|
function addIntegrationToSeq(doc, integrationsSeq, integration) {
|
|
1237
1257
|
const secretPaths = getSecretFieldPaths(integration.type);
|
|
1238
|
-
const { metadata
|
|
1258
|
+
const { metadata, ...restIntegration } = integration;
|
|
1239
1259
|
const integrationMap = doc.createNode(restIntegration);
|
|
1240
1260
|
const metadataMap = doc.createNode({});
|
|
1241
1261
|
const secrets = updateIntegrationMetadataMap({
|
|
@@ -1362,7 +1382,6 @@ function mergeApiIntegrationsIntoDocument(doc, apiIntegrations) {
|
|
|
1362
1382
|
skipped
|
|
1363
1383
|
};
|
|
1364
1384
|
}
|
|
1365
|
-
|
|
1366
1385
|
//#endregion
|
|
1367
1386
|
//#region src/loading/merge-into-yaml.ts
|
|
1368
1387
|
/**
|
|
@@ -1376,6 +1395,14 @@ function mergeApiIntegrationsIntoDocument(doc, apiIntegrations) {
|
|
|
1376
1395
|
*
|
|
1377
1396
|
* @param existingContent - Current YAML content, or `null` if the file doesn't exist yet
|
|
1378
1397
|
* @param apiIntegrations - Integrations fetched from the API
|
|
1398
|
+
*
|
|
1399
|
+
* @throws {IntegrationsYamlParseError} If `existingContent` is not valid YAML (for
|
|
1400
|
+
* example, unresolved git merge conflict markers). Callers that want to rebuild the
|
|
1401
|
+
* file from scratch instead of surfacing the error can catch it and re-run with
|
|
1402
|
+
* `mergeApiIntegrationsIntoYaml(null, apiIntegrations)` — note this discards the
|
|
1403
|
+
* existing content, including any local-only integrations and comments.
|
|
1404
|
+
* @throws {InvalidIntegrationsTypeError} If the existing `integrations` property is
|
|
1405
|
+
* present but is not a list.
|
|
1379
1406
|
*/
|
|
1380
1407
|
function mergeApiIntegrationsIntoYaml(existingContent, apiIntegrations) {
|
|
1381
1408
|
const doc = (existingContent != null ? parseIntegrationsDocument(existingContent) : null) ?? createNewDocument();
|
|
@@ -1388,7 +1415,6 @@ function mergeApiIntegrationsIntoYaml(existingContent, apiIntegrations) {
|
|
|
1388
1415
|
skipped
|
|
1389
1416
|
};
|
|
1390
1417
|
}
|
|
1391
|
-
|
|
1392
1418
|
//#endregion
|
|
1393
1419
|
//#region src/loading/parse-integrations.ts
|
|
1394
1420
|
/**
|
|
@@ -1477,6 +1503,5 @@ function parseIntegrations({ yaml, env = {} }) {
|
|
|
1477
1503
|
issues
|
|
1478
1504
|
};
|
|
1479
1505
|
}
|
|
1480
|
-
|
|
1481
1506
|
//#endregion
|
|
1482
|
-
export { ApiError, AwsAuthMethods, BUILTIN_INTEGRATIONS, BigQueryAuthMethods, BigQueryServiceAccountParseError, DEFAULT_API_URL, DEFAULT_ENV_FILE, DEFAULT_INTEGRATIONS_FILE, DatabaseAuthMethods, ENV_VAR_REF_PREFIX, EnvVarResolutionError, 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, isDatabaseIntegrationType, isDatabaseIntegrationTypeWithSslSupport, isEnvVarRef, isFederatedAuthMetadata, isFederatedAuthMethod, isSqlIntegrationType, mergeApiIntegrationsIntoDocument, mergeApiIntegrationsIntoYaml, mergeProcessedIntegrations, parseEnvVarRef, parseIntegrations, parseIntegrationsDocument, resolveEnvVarRefsFromMap, serializeIntegrationsDocument, sqlIntegrationTypes, updateIntegrationInDocument, updateIntegrationMetadataMap };
|
|
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 };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deepnote/database-integrations",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.1",
|
|
4
4
|
"description": "Deepnote database integration definitions",
|
|
5
5
|
"keywords": [],
|
|
6
6
|
"repository": {
|
|
@@ -27,17 +27,17 @@
|
|
|
27
27
|
"package.json"
|
|
28
28
|
],
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"yaml": "^2.
|
|
30
|
+
"yaml": "^2.9.0",
|
|
31
31
|
"zod": "3.25.76",
|
|
32
|
-
"@deepnote/blocks": "4.
|
|
32
|
+
"@deepnote/blocks": "4.8.1"
|
|
33
33
|
},
|
|
34
34
|
"publishConfig": {
|
|
35
35
|
"access": "public",
|
|
36
36
|
"registry": "https://registry.npmjs.org"
|
|
37
37
|
},
|
|
38
38
|
"scripts": {
|
|
39
|
-
"build": "tsdown --format esm --format cjs --dts",
|
|
39
|
+
"build": "tsdown --format esm --format cjs --dts --no-fixed-extension",
|
|
40
40
|
"test": "vitest",
|
|
41
|
-
"watch": "tsdown --watch --format esm --format cjs --dts"
|
|
41
|
+
"watch": "tsdown --watch --format esm --format cjs --dts --no-fixed-extension"
|
|
42
42
|
}
|
|
43
43
|
}
|