@@ -19,17 +19,20 @@ The integrations system enables Deepnote notebooks to connect to external data s
1919Manages persistent storage of integration configurations using VSCode's encrypted SecretStorage API.
2020
2121** Key Features:**
22+
2223- Uses VSCode's ` SecretStorage ` API for secure credential storage
2324- Storage is scoped to the user's machine (shared across all Deepnote projects)
2425- In-memory caching for performance
2526- Event-driven updates via ` onDidChangeIntegrations ` event
2627- Index-based storage for efficient retrieval
2728
2829** Storage Format:**
30+
2931- Each integration config is stored as JSON under key: ` deepnote-integrations.{integrationId} `
3032- An index is maintained at key: ` deepnote-integrations.index ` containing all integration IDs
3133
3234** Key Methods:**
35+
3336- ` getAll() ` : Retrieve all stored integration configurations
3437- ` get(integrationId) ` : Get a specific integration by ID
3538- ` save(config) ` : Save or update an integration configuration
@@ -67,18 +70,21 @@ Manages persistent storage of integration configurations using VSCode's encrypte
6770Scans Deepnote projects to discover which integrations are used in SQL blocks.
6871
6972** Detection Process:**
73+
70741 . Retrieves the Deepnote project from ` IDeepnoteNotebookManager `
71752 . Scans all notebooks in the project
72763 . Examines each code block for ` metadata.sql_integration_id `
73774 . Checks if each integration is configured (has credentials)
74785 . Returns a map of integration IDs to their status
7579
7680** Integration Status:**
81+
7782- ` Connected ` : Integration has valid credentials stored
7883- ` Disconnected ` : Integration is used but not configured
7984- ` Error ` : Integration configuration is invalid
8085
8186** Special Cases:**
87+
8288- Excludes ` deepnote-dataframe-sql ` (internal DuckDB integration)
8389- Only processes code blocks with SQL integration metadata
8490
@@ -87,6 +93,7 @@ Scans Deepnote projects to discover which integrations are used in SQL blocks.
8793Orchestrates the integration management UI and commands.
8894
8995** Responsibilities:**
96+
9097- Registers the ` deepnote.manageIntegrations ` command
9198- Updates VSCode context keys for UI visibility:
9299 - ` deepnote.hasIntegrations ` : True if any integrations are detected
@@ -95,6 +102,7 @@ Orchestrates the integration management UI and commands.
95102- Opens the integration webview with detected integrations
96103
97104** Command Flow:**
105+
981061 . User triggers command (from command palette or SQL cell status bar)
991072 . Manager detects integrations in the active notebook
1001083 . Manager opens webview with integration list
@@ -105,6 +113,7 @@ Orchestrates the integration management UI and commands.
105113Provides the webview-based UI for managing integration credentials.
106114
107115** Features:**
116+
108117- Persistent webview panel (survives defocus)
109118- Real-time integration status updates
110119- Configuration forms for each integration type
@@ -113,6 +122,7 @@ Provides the webview-based UI for managing integration credentials.
113122** Message Protocol:**
114123
115124Extension → Webview:
125+
116126``` typescript
117127// Update integration list
118128{ type : ' update' , integrations : IntegrationWithStatus [] }
@@ -125,6 +135,7 @@ Extension → Webview:
125135```
126136
127137Webview → Extension:
138+
128139``` typescript
129140// Save configuration
130141{ type : ' save' , integrationId : string , config : IntegrationConfig }
@@ -143,6 +154,7 @@ Webview → Extension:
143154Main React component that manages the webview UI state.
144155
145156** State Management:**
157+
146158- ` integrations ` : List of detected integrations with status
147159- ` selectedIntegrationId ` : Currently selected integration for configuration
148160- ` selectedConfig ` : Existing configuration being edited
@@ -152,6 +164,7 @@ Main React component that manages the webview UI state.
152164** User Flows:**
153165
154166** Configure Integration:**
167+
1551681 . User clicks "Configure" button
1561692 . Panel shows configuration form overlay
1571703 . User enters credentials
@@ -160,6 +173,7 @@ Main React component that manages the webview UI state.
1601736 . Panel shows success message and refreshes list
161174
162175** Delete Integration:**
176+
1631771 . User clicks "Reset" button
1641782 . Panel shows confirmation prompt (5 seconds)
1651793 . User clicks again to confirm
@@ -172,6 +186,7 @@ Main React component that manages the webview UI state.
172186Type-specific forms for entering integration credentials.
173187
174188** PostgreSQL Form Fields:**
189+
175190- Name (display name)
176191- Host
177192- Port (default: 5432)
@@ -181,11 +196,13 @@ Type-specific forms for entering integration credentials.
181196- SSL (checkbox)
182197
183198** BigQuery Form Fields:**
199+
184200- Name (display name)
185201- Project ID
186202- Service Account Credentials (JSON textarea)
187203
188204** Validation:**
205+
189206- All fields are required
190207- BigQuery credentials must be valid JSON
191208- Port must be a valid number
@@ -197,6 +214,7 @@ Type-specific forms for entering integration credentials.
197214Provides environment variables containing integration credentials for the Jupyter kernel.
198215
199216** Process:**
217+
2002181 . Scans the notebook for SQL cells with ` sql_integration_id ` metadata
2012192 . Retrieves credentials for each detected integration
2022203 . Converts credentials to the format expected by ` deepnote-toolkit `
@@ -211,6 +229,7 @@ Example: Integration ID `my-postgres-db` → Environment variable `SQL_MY_POSTGR
211229** Credential JSON Format:**
212230
213231PostgreSQL:
232+
214233``` json
215234{
216235 "url" : " postgresql://username:password@host:port/database" ,
@@ -220,18 +239,22 @@ PostgreSQL:
220239```
221240
222241BigQuery:
242+
223243``` json
224244{
225245 "url" : " bigquery://?user_supplied_client=true" ,
226246 "params" : {
227247 "project_id" : " my-project" ,
228- "credentials" : { /* service account JSON */ }
248+ "credentials" : {
249+ /* service account JSON */
250+ }
229251 },
230252 "param_style" : " format"
231253}
232254```
233255
234256** Integration Points:**
257+
235258- Registered as an environment variable provider in the kernel environment service
236259- Called when starting a Jupyter kernel for a Deepnote notebook
237260- Environment variables are passed to the kernel process at startup
@@ -244,6 +267,7 @@ Injects Python code into the kernel at startup to set environment variables.
244267Jupyter doesn't automatically pass all environment variables from the server process to the kernel process. This provider ensures credentials are available in the kernel's ` os.environ ` .
245268
246269** Generated Code:**
270+
247271``` python
248272try :
249273 import os
@@ -258,6 +282,7 @@ except Exception as e:
258282```
259283
260284** Execution:**
285+
261286- Registered with ` IStartupCodeProviders ` for ` JupyterNotebookView `
262287- Runs automatically when a Python kernel starts for a Deepnote notebook
263288- Priority: ` StartupCodePriority.Base ` (runs early)
@@ -270,6 +295,7 @@ except Exception as e:
270295The ` deepnote-toolkit ` Python package reads credentials from environment variables to execute SQL blocks.
271296
272297** Flow:**
298+
2732991 . Extension detects SQL blocks in notebook
2743002 . Extension retrieves credentials from secure storage
2753013 . Extension converts credentials to JSON format
@@ -282,6 +308,7 @@ The `deepnote-toolkit` Python package reads credentials from environment variabl
282308
283309** Environment Variable Lookup:**
284310When a SQL block with ` sql_integration_id: "my-postgres-db" ` is executed:
311+
2853121 . Toolkit looks for environment variable ` SQL_MY_POSTGRES_DB `
2863132 . Toolkit parses the JSON value
2873143 . Toolkit creates a SQLAlchemy connection using the ` url ` and ` params `
@@ -291,6 +318,7 @@ When a SQL block with `sql_integration_id: "my-postgres-db"` is executed:
291318## Data Flow
292319
293320### Configuration Flow
321+
294322```
295323User → IntegrationPanel (UI)
296324 → vscodeApi.postMessage({ type: 'save', config })
@@ -302,6 +330,7 @@ User → IntegrationPanel (UI)
302330```
303331
304332### Execution Flow
333+
305334```
306335User executes SQL cell
307336 → Kernel startup triggered
@@ -332,13 +361,14 @@ User executes SQL cell
332361To add a new integration type (e.g., MySQL, Snowflake):
333362
3343631 . ** Add type to ` integrationTypes.ts ` ** :
364+
335365 ``` typescript
336366 export enum IntegrationType {
337367 Postgres = ' postgres' ,
338368 BigQuery = ' bigquery' ,
339369 MySQL = ' mysql' // New type
340370 }
341-
371+
342372 export interface MySQLIntegrationConfig extends BaseIntegrationConfig {
343373 type: IntegrationType .MySQL ;
344374 host: string ;
@@ -347,11 +377,12 @@ To add a new integration type (e.g., MySQL, Snowflake):
347377 username: string ;
348378 password: string ;
349379 }
350-
380+
351381 export type IntegrationConfig = PostgresIntegrationConfig | BigQueryIntegrationConfig | MySQLIntegrationConfig ;
352382 ```
353383
3543842 . ** Add conversion logic in ` sqlIntegrationEnvironmentVariablesProvider.ts ` ** :
385+
355386 ``` typescript
356387 case IntegrationType .MySQL : {
357388 const url = ` mysql://${config .username }:${config .password }@${config .host }:${config .port }/${config .database } ` ;
@@ -370,12 +401,13 @@ To add a new integration type (e.g., MySQL, Snowflake):
370401## Testing
371402
372403Unit tests are located in:
404+
373405- ` sqlIntegrationEnvironmentVariablesProvider.unit.test.ts `
374406
375407Tests cover:
408+
376409- Environment variable generation for each integration type
377410- Multiple integrations in a single notebook
378411- Missing credentials handling
379412- Integration ID to environment variable name conversion
380413- JSON format validation
381-
0 commit comments