@deepnote/database-integrations 1.6.0 → 1.7.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
@@ -1,4 +1,5 @@
1
- //#region rolldown:runtime
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ //#region \0rolldown/runtime.js
2
3
  var __create = Object.create;
3
4
  var __defProp = Object.defineProperty;
4
5
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -15,19 +16,15 @@ var __copyProps = (to, from, except, desc) => {
15
16
  }
16
17
  return to;
17
18
  };
18
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
19
20
  value: mod,
20
21
  enumerable: true
21
22
  }) : target, mod));
22
-
23
23
  //#endregion
24
24
  let zod = require("zod");
25
- zod = __toESM(zod);
25
+ zod = __toESM(zod, 1);
26
26
  let yaml = require("yaml");
27
- yaml = __toESM(yaml);
28
- let __deepnote_blocks = require("@deepnote/blocks");
29
- __deepnote_blocks = __toESM(__deepnote_blocks);
30
-
27
+ let _deepnote_blocks = require("@deepnote/blocks");
31
28
  //#region src/sql-integration-auth-methods.ts
32
29
  const AwsAuthMethods = {
33
30
  AccessKeys: "access-keys",
@@ -68,7 +65,6 @@ function isFederatedAuthMethod(authMethod) {
68
65
  function isFederatedAuthMetadata(metadata) {
69
66
  return metadata.authMethod !== void 0 && isFederatedAuthMethod(metadata.authMethod);
70
67
  }
71
-
72
68
  //#endregion
73
69
  //#region src/database-integration-metadata-schemas.ts
74
70
  const athenaMetadataSchema = zod.z.object({
@@ -296,8 +292,6 @@ const pgsqlMetadataSchema = commonDatabaseSchema.extend({
296
292
  caCertificateName: zod.z.string().optional(),
297
293
  caCertificateText: zod.z.string().optional()
298
294
  });
299
- const materializeMetadataSchema = pgsqlMetadataSchema.extend({ cluster: zod.z.string() });
300
- const sqlServerMetadataSchema = commonDatabaseSchema.extend({ port: zod.z.string() });
301
295
  const databaseMetadataSchemasByType = {
302
296
  "alloydb": alloydbMetadataSchema,
303
297
  "athena": athenaMetadataSchema,
@@ -307,7 +301,7 @@ const databaseMetadataSchemasByType = {
307
301
  "databricks": databricksMetadataSchema,
308
302
  "dremio": dremioMetadataSchema,
309
303
  "mariadb": mariadbMetadataSchema,
310
- "materialize": materializeMetadataSchema,
304
+ "materialize": pgsqlMetadataSchema.extend({ cluster: zod.z.string() }),
311
305
  "mindsdb": mindsdbMetadataSchema,
312
306
  "mongodb": mongodbMetadataSchema,
313
307
  "mysql": mysqlMetadataSchema,
@@ -316,10 +310,9 @@ const databaseMetadataSchemasByType = {
316
310
  "redshift": redshiftMetadataSchema,
317
311
  "snowflake": snowflakeMetadataSchema,
318
312
  "spanner": spannerMetadataSchema,
319
- "sql-server": sqlServerMetadataSchema,
313
+ "sql-server": commonDatabaseSchema.extend({ port: zod.z.string() }),
320
314
  "trino": trinoMetadataSchema
321
315
  };
322
-
323
316
  //#endregion
324
317
  //#region src/database-integration-config.ts
325
318
  const commonIntegrationConfig = zod.default.object({
@@ -434,7 +427,6 @@ const databaseIntegrationConfigSchema = zod.default.discriminatedUnion("type", [
434
427
  federated_auth_method: zod.default.enum(["trino-oauth", "password"]).optional().nullable()
435
428
  })
436
429
  ]);
437
-
438
430
  //#endregion
439
431
  //#region src/snowflake-integration-env-vars.ts
440
432
  /**
@@ -500,7 +492,6 @@ function createSqlAlchemyInputFromUrl(url, keyPair) {
500
492
  param_style: "pyformat"
501
493
  };
502
494
  }
503
-
504
495
  //#endregion
505
496
  //#region src/database-integration-env-vars.ts
506
497
  function getEnvironmentVariablesForIntegrations(integrations, params) {
@@ -865,7 +856,6 @@ function getSqlEnvVarName(integrationId) {
865
856
  function assertNever(value) {
866
857
  throw new Error(`Unexpected value: ${value}`);
867
858
  }
868
-
869
859
  //#endregion
870
860
  //#region src/database-integration-types.ts
871
861
  const sqlIntegrationTypes = [
@@ -910,7 +900,6 @@ function isSqlIntegrationType(type) {
910
900
  function isDatabaseIntegrationTypeWithSslSupport(type) {
911
901
  return databaseIntegrationTypesWithSslSupport.includes(type);
912
902
  }
913
-
914
903
  //#endregion
915
904
  //#region src/loading/api-error.ts
916
905
  /**
@@ -924,18 +913,31 @@ var ApiError = class extends Error {
924
913
  this.statusCode = statusCode;
925
914
  }
926
915
  };
927
-
928
916
  //#endregion
929
917
  //#region src/loading/constants.ts
930
- /** Built-in integrations that don't require external configuration. */
931
- const BUILTIN_INTEGRATIONS = new Set(["deepnote-dataframe-sql", "pandas-dataframe"]);
918
+ /** Built-in integrations that don't require external configuration. Keys are canonical lowercase IDs. */
919
+ const BUILTIN_INTEGRATIONS = /* @__PURE__ */ new Set(["deepnote-dataframe-sql", "pandas-dataframe"]);
920
+ /**
921
+ * Return whether the given integration ID refers to a built-in integration.
922
+ *
923
+ * The comparison is case-insensitive: built-in IDs are stored as canonical
924
+ * lowercase strings in {@link BUILTIN_INTEGRATIONS}, and SQL block metadata may
925
+ * reference them in any casing (e.g. `Pandas-DataFrame`). This mirrors the
926
+ * case-insensitive env-var derivation in `getSqlEnvVarName`, so a built-in is
927
+ * recognized regardless of how a notebook cased its `sql_integration_id`.
928
+ *
929
+ * @param integrationId - The integration ID from SQL block metadata.
930
+ * @returns `true` when the ID matches a built-in integration regardless of casing.
931
+ */
932
+ function isBuiltinIntegration(integrationId) {
933
+ return BUILTIN_INTEGRATIONS.has(integrationId.toLowerCase());
934
+ }
932
935
  /** Default `.env` file name for storing integration secrets. */
933
936
  const DEFAULT_ENV_FILE = ".env";
934
937
  /** Default integrations file name. */
935
938
  const DEFAULT_INTEGRATIONS_FILE = ".deepnote.env.yaml";
936
939
  /** Default Deepnote API base URL. */
937
940
  const DEFAULT_API_URL = "https://api.deepnote.com";
938
-
939
941
  //#endregion
940
942
  //#region src/loading/env-var-refs.ts
941
943
  const ENV_VAR_REF_PREFIX = "env:";
@@ -944,7 +946,7 @@ function generateEnvVarName(integrationId, fieldPath) {
944
946
  }
945
947
  function parseEnvVarRef(value) {
946
948
  if (typeof value !== "string") return null;
947
- if (!value.startsWith(ENV_VAR_REF_PREFIX)) return null;
949
+ if (!value.startsWith("env:")) return null;
948
950
  const varName = value.slice(4);
949
951
  if (!varName) return null;
950
952
  return {
@@ -1007,7 +1009,6 @@ function resolveEnvVarRefsFromMap(obj, vars, currentPath) {
1007
1009
  }
1008
1010
  return obj;
1009
1011
  }
1010
-
1011
1012
  //#endregion
1012
1013
  //#region src/loading/fetch-integrations.ts
1013
1014
  /**
@@ -1038,14 +1039,17 @@ function trimTrailingSlash(url) {
1038
1039
  *
1039
1040
  * @param baseUrl - The base URL of the Deepnote API
1040
1041
  * @param token - The authentication token
1041
- * @param integrationIds - Optional list of integration IDs to fetch. When provided, only these integrations are returned.
1042
+ * @param integrationIds - Optional list of integration UUIDs to fetch. When provided, only these integrations are returned.
1042
1043
  * @returns Array of integrations from the API
1043
1044
  * @throws ApiError if the request fails
1044
1045
  */
1045
1046
  async function fetchIntegrations(baseUrl, token, integrationIds) {
1046
1047
  const endpoint = new URL(`${trimTrailingSlash(baseUrl)}/v2/integrations`);
1047
1048
  endpoint.searchParams.set("includeMetadata", "true");
1048
- if (integrationIds && integrationIds.length > 0) endpoint.searchParams.set("integrationIds", integrationIds.join(","));
1049
+ if (integrationIds && integrationIds.length > 0) {
1050
+ const normalizedIntegrationIds = new Set(integrationIds.map((id) => id.toLowerCase()));
1051
+ endpoint.searchParams.set("integrationIds", Array.from(normalizedIntegrationIds).join(","));
1052
+ }
1049
1053
  const url = endpoint.toString();
1050
1054
  const response = await fetch(url, {
1051
1055
  method: "GET",
@@ -1065,21 +1069,38 @@ async function fetchIntegrations(baseUrl, token, integrationIds) {
1065
1069
  if (!parseResult.success) throw new Error(`Invalid API response: ${parseResult.error.message}`);
1066
1070
  return parseResult.data.integrations;
1067
1071
  }
1068
-
1069
1072
  //#endregion
1070
1073
  //#region src/loading/integrations-document.ts
1071
1074
  /**
1075
+ * Error thrown when integrations YAML content cannot be parsed.
1076
+ */
1077
+ var IntegrationsYamlParseError = class extends Error {
1078
+ /** The underlying parse errors reported by the `yaml` library. */
1079
+ errors;
1080
+ constructor(errors) {
1081
+ super(`Failed to parse integrations YAML: ${errors[0]?.message ?? "unknown parse error"}`);
1082
+ this.name = "IntegrationsYamlParseError";
1083
+ this.errors = errors;
1084
+ }
1085
+ };
1086
+ /**
1072
1087
  * Parse integrations YAML content into a mutable `yaml` Document that preserves
1073
1088
  * comments and formatting. Returns `null` for empty content.
1074
1089
  *
1075
1090
  * This is the content-accepting counterpart of the Node-only `readIntegrationsDocument`.
1091
+ *
1092
+ * @throws {IntegrationsYamlParseError} If the content is not valid YAML. Malformed
1093
+ * content is rejected here rather than at serialization time, where `yaml` would
1094
+ * otherwise fail with an opaque "Document with errors cannot be stringified".
1076
1095
  */
1077
1096
  function parseIntegrationsDocument(content) {
1078
1097
  if (!content.trim()) return null;
1079
- return (0, yaml.parseDocument)(content, {
1098
+ const doc = (0, yaml.parseDocument)(content, {
1080
1099
  strict: true,
1081
1100
  version: "1.2"
1082
1101
  });
1102
+ if (doc.errors.length > 0) throw new IntegrationsYamlParseError(doc.errors);
1103
+ return doc;
1083
1104
  }
1084
1105
  /**
1085
1106
  * Serialize an integrations Document back to YAML text, preserving comments and
@@ -1088,7 +1109,6 @@ function parseIntegrationsDocument(content) {
1088
1109
  function serializeIntegrationsDocument(doc) {
1089
1110
  return doc.toString({ lineWidth: 0 });
1090
1111
  }
1091
-
1092
1112
  //#endregion
1093
1113
  //#region src/loading/integrations-file-schema.ts
1094
1114
  /**
@@ -1109,7 +1129,6 @@ function serializeIntegrationsDocument(doc) {
1109
1129
  */
1110
1130
  const baseIntegrationsFileSchema = zod.z.object({ integrations: zod.z.array(zod.z.record(zod.z.unknown())).optional().default([]) });
1111
1131
  const integrationsFileSchema = zod.z.object({ integrations: zod.z.array(databaseIntegrationConfigSchema) });
1112
-
1113
1132
  //#endregion
1114
1133
  //#region src/secret-field-paths.ts
1115
1134
  /**
@@ -1168,7 +1187,6 @@ const SECRET_PATHS = {
1168
1187
  function getSecretFieldPaths(type) {
1169
1188
  return SECRET_PATHS[type] ?? [];
1170
1189
  }
1171
-
1172
1190
  //#endregion
1173
1191
  //#region src/loading/merge-integrations.ts
1174
1192
  /**
@@ -1238,7 +1256,7 @@ function updateIntegrationMetadataMap({ metadataMap, integrationId, integrationM
1238
1256
  * @returns Record of extracted secrets (envVarName -> secretValue)
1239
1257
  */
1240
1258
  function updateIntegrationInDocument(doc, integrationMap, integration) {
1241
- const { id, name, type, metadata, federated_auth_method,...rest } = integration;
1259
+ const { id, name, type, metadata, federated_auth_method, ...rest } = integration;
1242
1260
  integrationMap.set("id", id);
1243
1261
  integrationMap.set("name", name);
1244
1262
  integrationMap.set("type", type);
@@ -1261,7 +1279,7 @@ function updateIntegrationInDocument(doc, integrationMap, integration) {
1261
1279
  */
1262
1280
  function addIntegrationToSeq(doc, integrationsSeq, integration) {
1263
1281
  const secretPaths = getSecretFieldPaths(integration.type);
1264
- const { metadata,...restIntegration } = integration;
1282
+ const { metadata, ...restIntegration } = integration;
1265
1283
  const integrationMap = doc.createNode(restIntegration);
1266
1284
  const metadataMap = doc.createNode({});
1267
1285
  const secrets = updateIntegrationMetadataMap({
@@ -1388,7 +1406,6 @@ function mergeApiIntegrationsIntoDocument(doc, apiIntegrations) {
1388
1406
  skipped
1389
1407
  };
1390
1408
  }
1391
-
1392
1409
  //#endregion
1393
1410
  //#region src/loading/merge-into-yaml.ts
1394
1411
  /**
@@ -1402,6 +1419,14 @@ function mergeApiIntegrationsIntoDocument(doc, apiIntegrations) {
1402
1419
  *
1403
1420
  * @param existingContent - Current YAML content, or `null` if the file doesn't exist yet
1404
1421
  * @param apiIntegrations - Integrations fetched from the API
1422
+ *
1423
+ * @throws {IntegrationsYamlParseError} If `existingContent` is not valid YAML (for
1424
+ * example, unresolved git merge conflict markers). Callers that want to rebuild the
1425
+ * file from scratch instead of surfacing the error can catch it and re-run with
1426
+ * `mergeApiIntegrationsIntoYaml(null, apiIntegrations)` — note this discards the
1427
+ * existing content, including any local-only integrations and comments.
1428
+ * @throws {InvalidIntegrationsTypeError} If the existing `integrations` property is
1429
+ * present but is not a list.
1405
1430
  */
1406
1431
  function mergeApiIntegrationsIntoYaml(existingContent, apiIntegrations) {
1407
1432
  const doc = (existingContent != null ? parseIntegrationsDocument(existingContent) : null) ?? createNewDocument();
@@ -1414,7 +1439,6 @@ function mergeApiIntegrationsIntoYaml(existingContent, apiIntegrations) {
1414
1439
  skipped
1415
1440
  };
1416
1441
  }
1417
-
1418
1442
  //#endregion
1419
1443
  //#region src/loading/parse-integrations.ts
1420
1444
  /**
@@ -1438,12 +1462,12 @@ function formatZodIssues(issues, pathPrefix) {
1438
1462
  *
1439
1463
  * @returns Object containing valid integrations and any validation issues
1440
1464
  */
1441
- function parseIntegrations({ yaml: yaml$1, env = {} }) {
1465
+ function parseIntegrations({ yaml, env = {} }) {
1442
1466
  const emptyIntegrations = [];
1443
1467
  const issues = [];
1444
1468
  let parsed;
1445
1469
  try {
1446
- parsed = (0, __deepnote_blocks.parseYaml)(yaml$1);
1470
+ parsed = (0, _deepnote_blocks.parseYaml)(yaml);
1447
1471
  } catch (error) {
1448
1472
  const message = error instanceof Error ? error.message : String(error);
1449
1473
  issues.push({
@@ -1503,7 +1527,6 @@ function parseIntegrations({ yaml: yaml$1, env = {} }) {
1503
1527
  issues
1504
1528
  };
1505
1529
  }
1506
-
1507
1530
  //#endregion
1508
1531
  exports.ApiError = ApiError;
1509
1532
  exports.AwsAuthMethods = AwsAuthMethods;
@@ -1516,6 +1539,7 @@ exports.DEFAULT_INTEGRATIONS_FILE = DEFAULT_INTEGRATIONS_FILE;
1516
1539
  exports.DatabaseAuthMethods = DatabaseAuthMethods;
1517
1540
  exports.ENV_VAR_REF_PREFIX = ENV_VAR_REF_PREFIX;
1518
1541
  exports.EnvVarResolutionError = EnvVarResolutionError;
1542
+ exports.IntegrationsYamlParseError = IntegrationsYamlParseError;
1519
1543
  exports.InvalidIntegrationError = InvalidIntegrationError;
1520
1544
  exports.InvalidIntegrationsTypeError = InvalidIntegrationsTypeError;
1521
1545
  exports.JSON_SCHEMA_URL = JSON_SCHEMA_URL;
@@ -1546,6 +1570,7 @@ exports.getSnowflakeFederatedAuthSqlAlchemyInput = getSnowflakeFederatedAuthSqlA
1546
1570
  exports.getSqlAlchemyInput = getSqlAlchemyInput;
1547
1571
  exports.getSqlEnvVarName = getSqlEnvVarName;
1548
1572
  exports.integrationsFileSchema = integrationsFileSchema;
1573
+ exports.isBuiltinIntegration = isBuiltinIntegration;
1549
1574
  exports.isDatabaseIntegrationType = isDatabaseIntegrationType;
1550
1575
  exports.isDatabaseIntegrationTypeWithSslSupport = isDatabaseIntegrationTypeWithSslSupport;
1551
1576
  exports.isEnvVarRef = isEnvVarRef;
@@ -1562,4 +1587,4 @@ exports.resolveEnvVarRefsFromMap = resolveEnvVarRefsFromMap;
1562
1587
  exports.serializeIntegrationsDocument = serializeIntegrationsDocument;
1563
1588
  exports.sqlIntegrationTypes = sqlIntegrationTypes;
1564
1589
  exports.updateIntegrationInDocument = updateIntegrationInDocument;
1565
- exports.updateIntegrationMetadataMap = updateIntegrationMetadataMap;
1590
+ exports.updateIntegrationMetadataMap = updateIntegrationMetadataMap;