@@ -18,148 +18,7 @@ import {
1818 LegacyDuckDBIntegrationConfig ,
1919 DATAFRAME_SQL_INTEGRATION_ID
2020} from './integrationTypes' ;
21-
22- /**
23- * Converts an integration ID to the environment variable name format expected by SQL blocks.
24- * Example: 'my-postgres-db' -> 'SQL_MY_POSTGRES_DB'
25- */
26- function convertToEnvironmentVariableName ( str : string ) : string {
27- return ( / ^ \d / . test ( str ) ? `_${ str } ` : str ) . toUpperCase ( ) . replace ( / [ ^ \w ] / g, '_' ) ;
28- }
29-
30- function getSqlEnvVarName ( integrationId : string ) : string {
31- return `SQL_${ integrationId } ` ;
32- }
33-
34- /**
35- * Converts integration configuration to the JSON format expected by the SQL execution code.
36- * The format must match what deepnote_toolkit expects:
37- * {
38- * "url": "sqlalchemy_connection_url",
39- * "params": {},
40- * "param_style": "qmark" | "format" | etc.
41- * }
42- */
43- function convertIntegrationConfigToJson ( config : LegacyIntegrationConfig ) : string {
44- switch ( config . type ) {
45- case IntegrationType . DuckDB : {
46- // Internal DuckDB integration for querying dataframes
47- return JSON . stringify ( {
48- url : 'deepnote+duckdb:///:memory:' ,
49- params : { } ,
50- param_style : 'qmark'
51- } ) ;
52- }
53-
54- case IntegrationType . Postgres : {
55- // Build PostgreSQL connection URL
56- // Format: postgresql://username:password@host :port/database
57- const encodedUsername = encodeURIComponent ( config . username ) ;
58- const encodedPassword = encodeURIComponent ( config . password ) ;
59- const encodedDatabase = encodeURIComponent ( config . database ) ;
60- const url = `postgresql://${ encodedUsername } :${ encodedPassword } @${ config . host } :${ config . port } /${ encodedDatabase } ` ;
61-
62- return JSON . stringify ( {
63- url : url ,
64- params : config . ssl ? { sslmode : 'require' } : { } ,
65- param_style : 'format'
66- } ) ;
67- }
68-
69- case IntegrationType . BigQuery : {
70- // BigQuery uses a special URL format
71- return JSON . stringify ( {
72- url : 'bigquery://?user_supplied_client=true' ,
73- params : {
74- project_id : config . projectId ,
75- credentials : JSON . parse ( config . credentials )
76- } ,
77- param_style : 'format'
78- } ) ;
79- }
80-
81- case IntegrationType . Snowflake : {
82- // Build Snowflake connection URL
83- // Format depends on auth method:
84- // Username+password: snowflake://{username}:{password}@{account}/{database}?warehouse={warehouse}&role={role}&application=YourApp
85- // Service account key-pair: snowflake://{username}@{account}/{database}?warehouse={warehouse}&role={role}&authenticator=snowflake_jwt&application=YourApp
86- const encodedAccount = encodeURIComponent ( config . account ) ;
87-
88- let url : string ;
89- const params : Record < string , unknown > = { } ;
90-
91- if ( config . authMethod === null || config . authMethod === SnowflakeAuthMethods . PASSWORD ) {
92- // Username+password authentication
93- const encodedUsername = encodeURIComponent ( config . username ) ;
94- const encodedPassword = encodeURIComponent ( config . password ) ;
95- const database = config . database ? `/${ encodeURIComponent ( config . database ) } ` : '' ;
96- url = `snowflake://${ encodedUsername } :${ encodedPassword } @${ encodedAccount } ${ database } ` ;
97-
98- const queryParams = new URLSearchParams ( ) ;
99- if ( config . warehouse ) {
100- queryParams . set ( 'warehouse' , config . warehouse ) ;
101- }
102- if ( config . role ) {
103- queryParams . set ( 'role' , config . role ) ;
104- }
105- queryParams . set ( 'application' , 'Deepnote' ) ;
106-
107- const queryString = queryParams . toString ( ) ;
108- if ( queryString ) {
109- url += `?${ queryString } ` ;
110- }
111- } else {
112- // Service account key-pair authentication (the only other supported method)
113- // TypeScript needs help narrowing the type here
114- if ( config . authMethod !== SnowflakeAuthMethods . SERVICE_ACCOUNT_KEY_PAIR ) {
115- // This should never happen due to the type guard above, but TypeScript needs this
116- throw new UnsupportedIntegrationError (
117- l10n . t (
118- "Snowflake integration with auth method '{0}' is not supported in VSCode" ,
119- config . authMethod
120- )
121- ) ;
122- }
123-
124- const encodedUsername = encodeURIComponent ( config . username ) ;
125- const database = config . database ? `/${ encodeURIComponent ( config . database ) } ` : '' ;
126- url = `snowflake://${ encodedUsername } @${ encodedAccount } ${ database } ` ;
127-
128- const queryParams = new URLSearchParams ( ) ;
129- if ( config . warehouse ) {
130- queryParams . set ( 'warehouse' , config . warehouse ) ;
131- }
132- if ( config . role ) {
133- queryParams . set ( 'role' , config . role ) ;
134- }
135- queryParams . set ( 'authenticator' , 'snowflake_jwt' ) ;
136- queryParams . set ( 'application' , 'Deepnote' ) ;
137-
138- const queryString = queryParams . toString ( ) ;
139- if ( queryString ) {
140- url += `?${ queryString } ` ;
141- }
142-
143- // For key-pair auth, pass the private key and passphrase as params
144- params . snowflake_private_key = btoa ( config . privateKey ) ;
145- if ( config . privateKeyPassphrase ) {
146- params . snowflake_private_key_passphrase = config . privateKeyPassphrase ;
147- }
148- }
149-
150- return JSON . stringify ( {
151- url : url ,
152- params : params ,
153- param_style : 'pyformat'
154- } ) ;
155- }
156-
157- default :
158- throw new UnsupportedIntegrationError (
159- l10n . t ( 'Unsupported integration type: {0}' , ( config as LegacyIntegrationConfig ) . type )
160- ) ;
161- }
162- }
21+ import { getEnvironmentVariablesForIntegrations } from '@deepnote/database-integrations' ;
16322
16423/**
16524 * Provides environment variables for SQL integrations.
@@ -197,14 +56,12 @@ export class SqlIntegrationEnvironmentVariablesProvider implements ISqlIntegrati
19756 * The internal DuckDB integration is always included.
19857 */
19958 public async getEnvironmentVariables ( resource : Resource , token ?: CancellationToken ) : Promise < EnvironmentVariables > {
200- const envVars : EnvironmentVariables = { } ;
201-
20259 if ( ! resource ) {
203- return envVars ;
60+ return { } ;
20461 }
20562
20663 if ( token ?. isCancellationRequested ) {
207- return envVars ;
64+ return { } ;
20865 }
20966
21067 logger . trace ( `SqlIntegrationEnvironmentVariablesProvider: Getting env vars for resource` ) ;
@@ -213,14 +70,14 @@ export class SqlIntegrationEnvironmentVariablesProvider implements ISqlIntegrati
21370 const notebook = this . notebookEditorProvider . findAssociatedNotebookDocument ( resource ) ;
21471 if ( ! notebook ) {
21572 logger . trace ( `SqlIntegrationEnvironmentVariablesProvider: No notebook found for resource` ) ;
216- return envVars ;
73+ return { } ;
21774 }
21875
21976 // Get the project ID from the notebook metadata
22077 const projectId = notebook . metadata ?. deepnoteProjectId as string | undefined ;
22178 if ( ! projectId ) {
22279 logger . trace ( `SqlIntegrationEnvironmentVariablesProvider: No project ID found in notebook metadata` ) ;
223- return envVars ;
80+ return { } ;
22481 }
22582
22683 logger . trace ( `SqlIntegrationEnvironmentVariablesProvider: Project ID: ${ projectId } ` ) ;
@@ -229,7 +86,7 @@ export class SqlIntegrationEnvironmentVariablesProvider implements ISqlIntegrati
22986 const project = this . notebookManager . getOriginalProject ( projectId ) ;
23087 if ( ! project ) {
23188 logger . trace ( `SqlIntegrationEnvironmentVariablesProvider: No project found for ID: ${ projectId } ` ) ;
232- return envVars ;
89+ return { } ;
23390 }
23491
23592 // Get the list of integrations from the project
@@ -238,51 +95,31 @@ export class SqlIntegrationEnvironmentVariablesProvider implements ISqlIntegrati
23895 `SqlIntegrationEnvironmentVariablesProvider: Found ${ projectIntegrations . length } integrations in project`
23996 ) ;
24097
98+ const projectIntegrationConfigs = (
99+ await Promise . all (
100+ projectIntegrations . map ( ( integration ) => {
101+ return this . integrationStorage . getIntegrationConfig ( integration . id ) ;
102+ } )
103+ )
104+ ) . filter ( ( config ) => config != null ) ;
105+
241106 // Always add the internal DuckDB integration
242- const duckdbConfig : DuckDBIntegrationConfig = {
107+ projectIntegrationConfigs . push ( {
243108 id : DATAFRAME_SQL_INTEGRATION_ID ,
244109 name : 'Dataframe SQL (DuckDB)' ,
245- type : IntegrationType . DuckDB
246- } ;
247- projectIntegrations . push ( duckdbConfig ) ;
110+ type : 'pandas-dataframe' ,
111+ metadata : { }
112+ } ) ;
248113
249- // Get credentials for each project integration and add to environment variables
250- for ( const projectIntegration of projectIntegrations ) {
251- if ( token ?. isCancellationRequested ) {
252- break ;
253- }
114+ const { envVars : envVarList , errors } = getEnvironmentVariablesForIntegrations ( projectIntegrationConfigs , {
115+ projectRootDirectory : ''
116+ } ) ;
254117
255- const integrationId = projectIntegration . id ;
256-
257- try {
258- // Get the integration configuration from storage
259- const config =
260- integrationId === DATAFRAME_SQL_INTEGRATION_ID
261- ? duckdbConfig
262- : await this . integrationStorage . getIntegrationConfig ( integrationId ) ;
263- if ( ! config ) {
264- logger . debug (
265- `SqlIntegrationEnvironmentVariablesProvider: No configuration found for integration ${ integrationId } , skipping`
266- ) ;
267- continue ;
268- }
269-
270- // Convert integration config to JSON and add as environment variable
271- const envVarName = convertToEnvironmentVariableName ( getSqlEnvVarName ( config . id ) ) ;
272- const credentialsJson = convertIntegrationConfigToJson ( config ) ;
273-
274- envVars [ envVarName ] = credentialsJson ;
275- logger . debug (
276- `SqlIntegrationEnvironmentVariablesProvider: Added env var ${ envVarName } for integration ${ config . id } `
277- ) ;
278- } catch ( error ) {
279- logger . error (
280- `SqlIntegrationEnvironmentVariablesProvider: Failed to get credentials for integration ${ integrationId } ` ,
281- error
282- ) ;
283- }
284- }
118+ errors . forEach ( ( error ) => {
119+ logger . error ( `SqlIntegrationEnvironmentVariablesProvider: ${ error . message } ` ) ;
120+ } ) ;
285121
122+ const envVars : EnvironmentVariables = Object . fromEntries ( envVarList . map ( ( { name, value } ) => [ name , value ] ) ) ;
286123 logger . trace ( `SqlIntegrationEnvironmentVariablesProvider: Returning ${ Object . keys ( envVars ) . length } env vars` ) ;
287124
288125 return envVars ;
0 commit comments