@deepnote/database-integrations 1.0.0 → 1.1.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.js CHANGED
@@ -1,4 +1,3 @@
1
- import buildUrl from "build-url-ts";
2
1
  import { z } from "zod";
3
2
 
4
3
  //#region src/sql-integration-auth-methods.ts
@@ -39,30 +38,35 @@ function isFederatedAuthMetadata(metadata) {
39
38
 
40
39
  //#endregion
41
40
  //#region src/snowflake-integration-env-vars.ts
41
+ /**
42
+ * Build a URL with path and query parameters using native URL API
43
+ */
44
+ function buildUrl(baseUrl, options) {
45
+ const url = new URL(baseUrl.replace(/^(\w+):\/\//, "http://"));
46
+ if (options.path) url.pathname = options.path;
47
+ if (options.queryParams) {
48
+ for (const [key, value] of Object.entries(options.queryParams)) if (value !== void 0) url.searchParams.set(key, value);
49
+ }
50
+ return url.href.replace(/^http:\/\//, baseUrl.match(/^(\w+):\/\//)?.[0] || "http://");
51
+ }
42
52
  function getSnowflakeSqlAlchemyInput(metadata, params) {
43
53
  if (isFederatedAuthMetadata(metadata)) return null;
44
54
  const { username, accountName, database, authMethod } = metadata;
45
- if (authMethod === SnowflakeAuthMethods.ServiceAccountKeyPair) {
46
- const url$1 = buildUrl(`snowflake://${encodeURIComponent(username)}@${encodeURIComponent(accountName)}`, {
47
- path: database,
48
- queryParams: {
49
- ...createBaseQueryParams(metadata, params.snowflakePartnerIdentifier),
50
- authenticator: "snowflake_jwt"
51
- }
52
- });
53
- if (!url$1) throw new Error("getSnowflakeEnvVar URL must be defined");
54
- return createSqlAlchemyInputFromUrl(url$1, {
55
- privateKey: metadata.privateKey,
56
- password: metadata.privateKeyPassphrase,
57
- username: metadata.username
58
- });
59
- }
60
- const url = buildUrl(`snowflake://${encodeURIComponent(username)}:${encodeURIComponent(metadata.password)}@${encodeURIComponent(accountName)}`, {
55
+ if (authMethod === SnowflakeAuthMethods.ServiceAccountKeyPair) return createSqlAlchemyInputFromUrl(buildUrl(`snowflake://${encodeURIComponent(username)}@${encodeURIComponent(accountName)}`, {
61
56
  path: database,
62
- queryParams: { ...createBaseQueryParams(metadata, params.snowflakePartnerIdentifier) }
57
+ queryParams: {
58
+ ...createBaseQueryParams(metadata, params.snowflakePartnerIdentifier),
59
+ authenticator: "snowflake_jwt"
60
+ }
61
+ }), {
62
+ privateKey: metadata.privateKey,
63
+ password: metadata.privateKeyPassphrase,
64
+ username: metadata.username
63
65
  });
64
- if (!url) throw new Error("getSnowflakeEnvVar URL must be defined");
65
- return createSqlAlchemyInputFromUrl(url);
66
+ return createSqlAlchemyInputFromUrl(buildUrl(`snowflake://${encodeURIComponent(username)}:${encodeURIComponent(metadata.password)}@${encodeURIComponent(accountName)}`, {
67
+ path: database,
68
+ queryParams: { ...createBaseQueryParams(metadata, params.snowflakePartnerIdentifier) }
69
+ }));
66
70
  }
67
71
  function createBaseQueryParams(metadata, snowflakePartnerIdentifier) {
68
72
  return {
@@ -75,8 +79,8 @@ function createSqlAlchemyInputFromUrl(url, keyPair) {
75
79
  return {
76
80
  url,
77
81
  params: keyPair ? {
78
- snowflake_private_key: Buffer.from(keyPair.privateKey).toString("base64"),
79
- snowflake_private_key_passphrase: keyPair.password || void 0
82
+ snowflake_private_key: btoa(keyPair.privateKey),
83
+ ...keyPair.password ? { snowflake_private_key_passphrase: keyPair.password } : {}
80
84
  } : {},
81
85
  param_style: "pyformat"
82
86
  };
@@ -84,10 +88,10 @@ function createSqlAlchemyInputFromUrl(url, keyPair) {
84
88
 
85
89
  //#endregion
86
90
  //#region src/database-integration-env-vars.ts
87
- function getIntegrationListEnv(sqlIntegrations, params) {
91
+ function getEnvironmentVariablesForIntegrations(integrations, params) {
88
92
  const envVars = [];
89
93
  const errors = [];
90
- sqlIntegrations.forEach((integration) => {
94
+ integrations.forEach((integration) => {
91
95
  const namePrefix = convertToEnvironmentVariableName(integration.name);
92
96
  const envVarsForThisIntegration = Object.entries(integration.metadata).map(([key, rawValue]) => {
93
97
  const name = `${namePrefix}_${key.toUpperCase()}`;
@@ -114,11 +118,6 @@ function getIntegrationListEnv(sqlIntegrations, params) {
114
118
  errors
115
119
  };
116
120
  }
117
- const duckDbEnvVar = {
118
- url: `deepnote+duckdb:///:memory:`,
119
- params: {},
120
- param_style: "qmark"
121
- };
122
121
  function addSslOptionsToMongoConnectionString(projectRoot, connectionString, integrationId, metadata) {
123
122
  const [base, paramString] = connectionString.split("?");
124
123
  const params = new URLSearchParams(paramString);
@@ -137,7 +136,7 @@ function getEnvVarForSqlCells(integration, params) {
137
136
  const sqlAlchemyInput = getSqlAlchemyInput(integration, params);
138
137
  if (!sqlAlchemyInput) return null;
139
138
  return {
140
- name: convertToEnvironmentVariableName(getSqlEnvVarName(integration.id)),
139
+ name: getSqlEnvVarName(integration.id),
141
140
  value: JSON.stringify({
142
141
  integration_id: integration.id,
143
142
  ...sqlAlchemyInput
@@ -168,7 +167,11 @@ function getSqlAlchemyInput(integration, params) {
168
167
  case "mindsdb":
169
168
  case "mysql": return getMySqlSqlAlchemyInput(integration.id, params.projectRootDirectory, integration.metadata);
170
169
  case "materialize": return getMaterializePostgresSqlAlchemyInput(integration.id, params.projectRootDirectory, integration.metadata);
171
- case "pandas-dataframe": return { ...duckDbEnvVar };
170
+ case "pandas-dataframe": return {
171
+ url: `deepnote+duckdb:///:memory:`,
172
+ params: {},
173
+ param_style: "qmark"
174
+ };
172
175
  case "redshift": return getRedshiftSqlAlchemyInput(integration.id, params.projectRootDirectory, integration.metadata);
173
176
  case "snowflake": return getSnowflakeSqlAlchemyInput(integration.metadata, { snowflakePartnerIdentifier: params.snowflakePartnerIdentifier });
174
177
  case "spanner": return getSpannerSqlAlchemyInput(integration.metadata);
@@ -187,7 +190,7 @@ const getDatabricksSqlAlchemyInput = ({ httpPath, host, token, port, schema, cat
187
190
  } },
188
191
  param_style: "pyformat",
189
192
  ssh_options: {
190
- enabled: String(sshEnabled),
193
+ enabled: sshEnabled == null ? void 0 : String(sshEnabled),
191
194
  host: sshHost,
192
195
  port: sshPort,
193
196
  user: sshUser
@@ -195,7 +198,7 @@ const getDatabricksSqlAlchemyInput = ({ httpPath, host, token, port, schema, cat
195
198
  };
196
199
  };
197
200
  const getDremioSqlAlchemyInput = ({ port, host, token, schema, sshEnabled, sshHost, sshPort, sshUser }) => {
198
- const url = new URL(`dremio+flight://${host}:${port}${schema ? "/" + schema : ""}`);
201
+ const url = new URL(`dremio+flight://${host}:${port}${schema ? `/${schema}` : ""}`);
199
202
  url.searchParams.set("UseEncryption", "true");
200
203
  url.searchParams.set("Token", token);
201
204
  return {
@@ -203,7 +206,7 @@ const getDremioSqlAlchemyInput = ({ port, host, token, schema, sshEnabled, sshHo
203
206
  params: {},
204
207
  param_style: "pyformat",
205
208
  ssh_options: {
206
- enabled: String(sshEnabled),
209
+ enabled: sshEnabled == null ? void 0 : String(sshEnabled),
207
210
  host: sshHost,
208
211
  port: sshPort,
209
212
  user: sshUser
@@ -217,7 +220,7 @@ const getSQLServerVar = ({ user, password, host, port, database, sshEnabled, ssh
217
220
  params: {},
218
221
  param_style: "pyformat",
219
222
  ssh_options: {
220
- enabled: String(sshEnabled),
223
+ enabled: sshEnabled == null ? void 0 : String(sshEnabled),
221
224
  host: sshHost,
222
225
  port: sshPort,
223
226
  user: sshUser
@@ -243,7 +246,7 @@ const getPostgresSqlAlchemyInput = (integrationId, projectRootDirectory, { user,
243
246
  } },
244
247
  param_style: "pyformat",
245
248
  ssh_options: {
246
- enabled: String(sshEnabled),
249
+ enabled: sshEnabled == null ? void 0 : String(sshEnabled),
247
250
  host: sshHost,
248
251
  port: sshPort,
249
252
  user: sshUser
@@ -271,7 +274,7 @@ const getRedshiftSqlAlchemyInput = (integrationId, projectRootDirectory, metadat
271
274
  } },
272
275
  param_style: "pyformat",
273
276
  ssh_options: {
274
- enabled: String(metadata.sshEnabled),
277
+ enabled: metadata.sshEnabled == null ? void 0 : String(metadata.sshEnabled),
275
278
  host: metadata.sshHost,
276
279
  port: metadata.sshPort,
277
280
  user: metadata.sshUser
@@ -303,7 +306,7 @@ const getMaterializePostgresSqlAlchemyInput = (integrationId, projectRootDirecto
303
306
  } },
304
307
  param_style: "pyformat",
305
308
  ssh_options: {
306
- enabled: String(sshEnabled),
309
+ enabled: sshEnabled == null ? void 0 : String(sshEnabled),
307
310
  host: sshHost,
308
311
  port: sshPort,
309
312
  user: sshUser
@@ -356,7 +359,7 @@ const getClickHouseSqlAlchemyInput = (integrationId, projectRootDirectory, { use
356
359
  params: {},
357
360
  param_style: "pyformat",
358
361
  ssh_options: {
359
- enabled: String(sshEnabled),
362
+ enabled: sshEnabled == null ? void 0 : String(sshEnabled),
360
363
  host: sshHost,
361
364
  port: sshPort,
362
365
  user: sshUser
@@ -422,7 +425,7 @@ const getMySqlSqlAlchemyInput = (integrationId, projectRootDirectory, { user, pa
422
425
  params: { connect_args: { ssl } },
423
426
  param_style: "pyformat",
424
427
  ssh_options: {
425
- enabled: String(sshEnabled),
428
+ enabled: sshEnabled == null ? void 0 : String(sshEnabled),
426
429
  host: sshHost,
427
430
  port: sshPort,
428
431
  user: sshUser
@@ -430,13 +433,13 @@ const getMySqlSqlAlchemyInput = (integrationId, projectRootDirectory, { user, pa
430
433
  };
431
434
  };
432
435
  function getCACertificatePath({ projectRoot, integrationId, caCertificateName }) {
433
- return `${projectRoot ?? ""}/.deepnote/${integrationId}/${caCertificateName}`;
436
+ return `${projectRoot}/.deepnote/${integrationId}/${caCertificateName}`;
434
437
  }
435
438
  function convertToEnvironmentVariableName(str) {
436
439
  return (/^\d/.test(str) ? `_${str}` : str).toUpperCase().replace(/[^\w]/g, "_");
437
440
  }
438
441
  function getSqlEnvVarName(integrationId) {
439
- return `SQL_${integrationId}`;
442
+ return convertToEnvironmentVariableName(`SQL_${integrationId}`);
440
443
  }
441
444
  function assertNever(value) {
442
445
  throw new Error(`Unexpected value: ${value}`);
@@ -693,4 +696,4 @@ const databaseIntegrationTypesWithSslSupport = [
693
696
  ];
694
697
 
695
698
  //#endregion
696
- export { AwsAuthMethods, BigQueryAuthMethods, BigQueryServiceAccountParseError, DatabaseAuthMethods, SnowflakeAuthMethods, SpannerServiceAccountParseError, databaseIntegrationTypes, databaseIntegrationTypesWithSslSupport, databaseMetadataSchemasByType, getIntegrationListEnv, getSqlAlchemyInput, isFederatedAuthMetadata, isFederatedAuthMethod, sqlIntegrationTypes };
699
+ export { AwsAuthMethods, BigQueryAuthMethods, BigQueryServiceAccountParseError, DatabaseAuthMethods, SnowflakeAuthMethods, SpannerServiceAccountParseError, databaseIntegrationTypes, databaseIntegrationTypesWithSslSupport, databaseMetadataSchemasByType, getEnvironmentVariablesForIntegrations, getSqlAlchemyInput, isFederatedAuthMetadata, isFederatedAuthMethod, sqlIntegrationTypes };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deepnote/database-integrations",
3
- "version": "1.0.0",
3
+ "version": "1.1.1",
4
4
  "description": "Deepnote database integration definitions",
5
5
  "keywords": [],
6
6
  "repository": {
@@ -26,17 +26,16 @@
26
26
  "LICENSE",
27
27
  "package.json"
28
28
  ],
29
- "scripts": {
30
- "build": "tsdown --format esm --format cjs --dts",
31
- "test": "vitest",
32
- "watch": "tsdown --watch --format esm --format cjs --dts"
33
- },
34
29
  "dependencies": {
35
- "build-url-ts": "^6.1.7",
36
- "zod": "^4.1.12"
30
+ "zod": "3.25.76"
37
31
  },
38
32
  "publishConfig": {
39
33
  "access": "public",
40
34
  "registry": "https://registry.npmjs.org"
35
+ },
36
+ "scripts": {
37
+ "build": "tsdown --format esm --format cjs --dts",
38
+ "test": "vitest",
39
+ "watch": "tsdown --watch --format esm --format cjs --dts"
41
40
  }
42
- }
41
+ }