Skip to content

feat(@deepnote/database-integrations): extract reusable integration loading#394

Merged
tkislan merged 13 commits into
mainfrom
tk/extract-integrations-loading-library
Jun 16, 2026
Merged

feat(@deepnote/database-integrations): extract reusable integration loading#394
tkislan merged 13 commits into
mainfrom
tk/extract-integrations-loading-library

Conversation

@tkislan

@tkislan tkislan commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

What & why

Extracts the browser-safe integration loading logic out of @deepnote/cli into @deepnote/database-integrations, so the CLI and the VS Code extension can parse, fetch, and write integrations the same way. The extension already depends on @deepnote/database-integrations (it consumes getEnvironmentVariablesForIntegrations), so this is the natural home for the shared logic.

The split is along the Node boundary: everything pure (works in the browser and Node) moves into the package, while the thin Node fs / process.env wrappers and the CLI's fetch-and-merge orchestration stay in the CLI. The package root keeps no node: imports, so the extension can import it directly (feeding it strings it reads via workspace.fs) without any Node-only entry point.

What moved into @deepnote/database-integrations

New src/loading/ directory, re-exported from the package root (export * from './loading'):

  • parseIntegrations({ yaml, env }) — parse the integrations YAML and resolve env: references against a supplied map
  • resolveEnvVarRefsFromMap + the env: ref helpers (parseEnvVarRef, createEnvVarRef, isEnvVarRef, extractEnvVarName, generateEnvVarName, EnvVarResolutionError)
  • fetchIntegrations + the API response schemas (apiIntegrationSchema, apiResponseSchema)
  • convertApiIntegrations, mergeApiIntegrationsIntoDocument, the comment-preserving YAML document builders, and the merge-result types
  • mergeApiIntegrationsIntoYaml — string-in / string-out write-back convenience
  • parseIntegrationsDocument / serializeIntegrationsDocument
  • integrationsFileSchema, ValidationIssue, ApiError (moved from the CLI's utils/api.ts), and constants (BUILTIN_INTEGRATIONS, DEFAULT_ENV_FILE, DEFAULT_INTEGRATIONS_FILE, DEFAULT_API_URL)

The package gains @deepnote/blocks (workspace) and yaml as dependencies, and reuses @deepnote/blocks' strict parseYaml for exact behavior parity (browser-safe, no dependency cycle).

What stays in @deepnote/cli

The Node-specific glue, now thin wrappers over the extracted functions:

  • parseIntegrationsFile / getDefaultIntegrationsFilePath — read the file from disk (decoding via @deepnote/blocks' decodeUtf8NoBom), overlay .env + process.env, then delegate to parseIntegrations
  • resolveEnvVarRefs(obj) — wraps resolveEnvVarRefsFromMap(obj, process.env)
  • fetchAndMergeApiIntegrations — the CLI's orchestration over fetchIntegrations + convertApiIntegrations
  • .env read/write (utils/dotenv.ts), still backed by the dotenv package — keeping dotenv's eager node:fs require out of the package root

The now-removed integrations/index.ts barrel's consumers (run, validate, integrations, add/edit-integration, collect-integrations, analysis, …) import from @deepnote/database-integrations directly. The run command and overall CLI behavior are unchanged.

Tests

Pure-logic suites moved into the package alongside the code (env-var-refs, fetch-integrations, merge-integrations). The CLI keeps the tests for its remaining Node wrappers (parse-integrations file reader, dotenv, the env-var-refs wrapper).

Notable decisions

  • .env parsing stays in the CLI via dotenv, so the package root stays browser-safe.
  • Merge results are split into distinct types — IntegrationsMergeResult (secrets + stats) → IntegrationsDocumentMergeResult (adds skipped: SkippedApiIntegration[]) → IntegrationsYamlDocumentMergeResult — so callers can surface invalid/unsupported integrations that were skipped.
  • No /node subpath and no version bump (stays 1.4.3): because the path/process.env wrappers stay in the CLI, the package root is browser-safe by construction and a separate Node entry point proved unnecessary.

Verification

  • pnpm -r run build — all 7 packages build ✓
  • Tests for the affected packages (@deepnote/database-integrations + @deepnote/cli): 1200 passed / 79 files ✓
  • pnpm run typecheck (root tsc -p tsconfig.json + per-package tsc --noEmit) ✓
  • biome check . — no errors ✓
  • Browser-safety: built root bundle (dist/index.js + dist/index.cjs) has no node: / fs / path / os / process imports ✓

Not included

VS Code extension wiring (/workspace/vscode-deepnote) is intentionally out of scope; it can consume the new @deepnote/database-integrations exports as a follow-up.

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • New Features
    • Enhanced integrations pull to provide detailed reporting for skipped, invalid, and unsupported integrations, including names, types, IDs, and specific issues.
    • Extended integrations file parsing to support an optional envFilePath for resolving env: references from a dotenv file, with process environment values taking precedence.
  • Bug Fixes
    • Improved consistency when integrations files are empty or can’t be read, returning clear issue output.

…oading

Move the integration loading pipeline (YAML parsing, .env secret
resolution, cloud-pull/fetch, and comment-preserving YAML/.env write-back)
out of @deepnote/cli into @deepnote/database-integrations so the CLI and
the VS Code extension can load and store integrations the same way.

- Root export is browser-safe; Node fs/process.env wrappers live behind a
  new @deepnote/database-integrations/node subpath. File-touching functions
  are split into a content-accepting core (parseIntegrations, parseDotEnv,
  parseIntegrationsDocument, ...) plus thin path wrappers
  (parseIntegrationsFile, readDotEnv/updateDotEnv, ...).
- @deepnote/cli integration modules become thin re-export shims; the `run`
  command and CLI behavior are unchanged. Integration tests moved into the
  package.
- Reuse @deepnote/blocks' strict parseYaml/decodeUtf8NoBom for parity.
- Reimplement .env parsing (no dotenv dependency) to keep the root
  browser-safe, since dotenv eagerly requires node:fs.
- MergeResult now reports skipped (invalid/unsupported) integrations so
  callers can surface them.

Bumps @deepnote/database-integrations to 1.5.0.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
@codecov

codecov Bot commented Jun 6, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 94.11765% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 83.94%. Comparing base (71172e2) to head (97562d8).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
...tabase-integrations/src/loading/merge-into-yaml.ts 0.00% 6 Missing ⚠️
...-integrations/src/loading/integrations-document.ts 83.33% 1 Missing ⚠️
...ase-integrations/src/loading/parse-integrations.ts 97.56% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #394      +/-   ##
==========================================
- Coverage   83.95%   83.94%   -0.02%     
==========================================
  Files         146      151       +5     
  Lines        8029     8047      +18     
  Branches     2168     2236      +68     
==========================================
+ Hits         6741     6755      +14     
- Misses       1287     1291       +4     
  Partials        1        1              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

tkislan and others added 10 commits June 9, 2026 08:11
…tabase-integrations directly

Drop the backward-compat re-export shims left behind by the integration
loading extraction and have every CLI consumer import from
@deepnote/database-integrations (browser-safe root) or its /node subpath
directly.

- Delete the 9 re-export shims (constants, utils/{api,dotenv,env-var-refs},
  integrations/{fetch-integrations,inject-integration-env-vars,
  integrations-file-schemas,merge-integrations,parse-integrations}) and the
  integrations barrel
- Remove the re-export blocks from commands/integrations.ts and validate.ts
- Repoint all consumers, dynamic import() calls, and the generate-json-schemas
  script
- Retarget vitest mocks to the package root and /node specifiers

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
…for environment variable resolution

- Updated the environment variable resolution logic to prioritize real environment variables over those defined in the .env file.
- Enhanced documentation comments for clarity on the environment variable resolution process.
- Added tests to verify that environment variables from the .env file are correctly resolved and that process.env can override these values.
Move the Node fs/process.env wrappers out of
@deepnote/database-integrations/node back into the CLI, leaving the package
as a single browser-safe entry point. The VS Code extension will provide its
own filesystem wrappers around the same browser-safe core.

- readDotEnv/updateDotEnv -> cli src/utils/dotenv.ts, using the dotenv
  library directly (drops the custom parseDotEnv reimplementation)
- resolveEnvVarRefs -> cli src/utils/env-var-refs.ts
- parseIntegrationsFile/getDefaultIntegrationsFilePath ->
  cli src/integrations/parse-integrations.ts
- readIntegrationsDocument/writeIntegrationsFile ->
  cli src/integrations/integrations-document.ts
- injectIntegrationEnvVars ->
  cli src/integrations/inject-integration-env-vars.ts

Remove the ./node export, the dotenv dependency, and the second tsdown
entry from @deepnote/database-integrations.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Restore the non-extracted CLI code to its original main location and content,
so the diff reflects only code extracted into @deepnote/database-integrations
(plus CLI imports updated to consume it), not incidental code movement.

- utils/dotenv.ts: restored verbatim from main (not extracted)
- integrations/inject-integration-env-vars.ts: back to main content
- utils/env-var-refs.ts + .test.ts: keep only resolveEnvVarRefs in place,
  importing the extracted resolveEnvVarRefsFromMap from the library
- readIntegrationsDocument/writeIntegrationsFile stay in commands/integrations.ts;
  drop the interim integrations-document.ts module
- run.test.ts / merge-integrations.test.ts: re-point only the extracted symbols
  to the library, keep CLI-local mocks/imports as on main

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
- Extracted the DEEPNOTE_TOKEN_ENV constant into a new constants.ts file for better organization.
- Updated all relevant imports across CLI and command files to reference the new location of DEEPNOTE_TOKEN_ENV.
- Cleaned up imports in integrations and run command files to remove direct imports from @deepnote/database-integrations.

This change enhances code maintainability and clarity by centralizing the environment variable definition.
Keep API fetch orchestration in the CLI where logging and machine-output
handling live; the library continues to export fetchIntegrations and
convertApiIntegrations as the shared primitives.

Co-authored-by: Cursor <[email protected]>
Separate skipped integrations from the base merge result so
mergeProcessedIntegrations no longer returns a dummy empty array,
and rename result types for clarity.

Co-authored-by: Cursor <[email protected]>
…ata helper

The parameter only existed for a CLI error log removed during the
integration loading extraction.

Co-authored-by: Cursor <[email protected]>
@tkislan tkislan marked this pull request as ready for review June 11, 2026 05:58
@tkislan tkislan requested a review from a team as a code owner June 11, 2026 05:58
@tkislan tkislan requested review from dinohamzic and m1so June 11, 2026 13:45
@tkislan

tkislan commented Jun 16, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@tkislan

tkislan commented Jun 16, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

A new loading submodule in packages/database-integrations consolidates constants (BUILTIN_INTEGRATIONS, DEFAULT_*), env-var reference utilities, YAML document helpers, ValidationIssue, integration parsing, and updated merge logic with skipped-integration tracking. The CLI removes parallel implementations and imports from the package instead. parseIntegrationsFile gains an optional envFilePath for dotenv-based env resolution.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • deepnote/deepnote#403: Extends CLI integrations add/edit command wiring to support the cloud-sql integration type alongside the refactored imports from @deepnote/database-integrations.
🚥 Pre-merge checks | ✅ 4 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 65.22% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Updates Docs ⚠️ Warning The PR adds significant new loading/parsing functionality to @deepnote/database-integrations (parseIntegrations, fetchIntegrations, mergeApiIntegrations, env-var refs) but the package README was no... Update packages/database-integrations/README.md to document the new loading module APIs: parseIntegrations, fetchIntegrations, mergeApiIntegrationsIntoYaml, resolveEnvVarRefsFromMap, and related types/constants.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the primary change: extracting reusable integration loading functionality from the CLI into the database-integrations package.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

@tkislan

tkislan commented Jun 16, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai approve
this is a simple PR, just moving the code around into a different package
your estimate of 60 minutes is completely unjustified and wrong

@coderabbitai

coderabbitai Bot commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

@tkislan Fair point — code movement, not new logic. Approving.

(ᵔ ᵕ ᵔ)⌐■-■

✅ Action performed

Comments resolved and changes approved.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/cli/src/commands/integrations.ts (1)

152-154: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Preserved-count math should exclude skipped API integrations.

preservedCount currently subtracts all fetched integrations, including skipped invalid/unsupported ones, so the summary can undercount preserved local-only entries.

Suggested fix
-  const preservedCount = finalCount - fetchedIntegrations.length
+  const mergedFetchedCount = fetchedIntegrations.length - skipped.length
+  const preservedCount = finalCount - mergedFetchedCount
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/cli/src/commands/integrations.ts` around lines 152 - 154, The
preservedCount calculation in the integrations command is incorrectly including
skipped invalid or unsupported API integrations in the subtraction. Fix the
calculation by subtracting only the actually-processed/valid integrations from
finalCount instead of subtracting the entire fetchedIntegrations.length. You
should track how many integrations were successfully processed (excluding those
that were skipped due to being invalid or unsupported) and use that count in the
preservedCount calculation to accurately reflect how many local-only
integrations were preserved.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/cli/src/integrations/parse-integrations.test.ts`:
- Around line 468-478: Import dedent from 'ts-dedent' at the top of the file if
not already present. Then, wrap the multiline YAML template string literals
passed to writeFile at lines 468 and 498 with the dedent function call, changing
from backtick strings directly to dedent`` template strings. This ensures
consistent formatting and removes unnecessary indentation from the YAML content
blocks, following the established pattern used elsewhere in the codebase.

In `@packages/cli/src/integrations/parse-integrations.ts`:
- Around line 52-54: Wrap the readDotEnv function call (line 53) in a try-catch
block to handle permission denied, parse failures, and other file I/O errors. In
the catch block, return a structured issues result that aligns with the existing
error handling pattern used for integrations file failures, rather than allowing
these errors to propagate uncaught. This ensures consistent error handling
across both the envFilePath and integrations file paths.

---

Outside diff comments:
In `@packages/cli/src/commands/integrations.ts`:
- Around line 152-154: The preservedCount calculation in the integrations
command is incorrectly including skipped invalid or unsupported API integrations
in the subtraction. Fix the calculation by subtracting only the
actually-processed/valid integrations from finalCount instead of subtracting the
entire fetchedIntegrations.length. You should track how many integrations were
successfully processed (excluding those that were skipped due to being invalid
or unsupported) and use that count in the preservedCount calculation to
accurately reflect how many local-only integrations were preserved.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 644f4708-aa38-4f45-9073-bad5c8ecf584

📥 Commits

Reviewing files that changed from the base of the PR and between 71172e2 and 97562d8.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (35)
  • packages/cli/scripts/generate-json-schemas.ts
  • packages/cli/src/cli.ts
  • packages/cli/src/commands/integrations.test.ts
  • packages/cli/src/commands/integrations.ts
  • packages/cli/src/commands/integrations/add-integration.ts
  • packages/cli/src/commands/integrations/edit-integration.ts
  • packages/cli/src/commands/lint.test.ts
  • packages/cli/src/commands/run.test.ts
  • packages/cli/src/commands/run.ts
  • packages/cli/src/commands/validate.ts
  • packages/cli/src/constants.ts
  • packages/cli/src/integrations/collect-integrations.ts
  • packages/cli/src/integrations/fetch-and-merge-integrations.ts
  • packages/cli/src/integrations/index.ts
  • packages/cli/src/integrations/parse-integrations.test.ts
  • packages/cli/src/integrations/parse-integrations.ts
  • packages/cli/src/utils/analysis.ts
  • packages/cli/src/utils/env-var-refs.test.ts
  • packages/cli/src/utils/env-var-refs.ts
  • packages/database-integrations/package.json
  • packages/database-integrations/src/index.ts
  • packages/database-integrations/src/loading/api-error.ts
  • packages/database-integrations/src/loading/constants.ts
  • packages/database-integrations/src/loading/env-var-refs.test.ts
  • packages/database-integrations/src/loading/env-var-refs.ts
  • packages/database-integrations/src/loading/fetch-integrations.test.ts
  • packages/database-integrations/src/loading/fetch-integrations.ts
  • packages/database-integrations/src/loading/index.ts
  • packages/database-integrations/src/loading/integrations-document.ts
  • packages/database-integrations/src/loading/integrations-file-schema.ts
  • packages/database-integrations/src/loading/merge-integrations.test.ts
  • packages/database-integrations/src/loading/merge-integrations.ts
  • packages/database-integrations/src/loading/merge-into-yaml.ts
  • packages/database-integrations/src/loading/parse-integrations.ts
  • packages/database-integrations/src/loading/validation-issue.ts
💤 Files with no reviewable changes (2)
  • packages/cli/src/constants.ts
  • packages/cli/src/integrations/index.ts

Comment thread packages/cli/src/integrations/parse-integrations.test.ts
Comment thread packages/cli/src/integrations/parse-integrations.ts
@tkislan tkislan merged commit 2954ed6 into main Jun 16, 2026
21 checks passed
@tkislan tkislan deleted the tk/extract-integrations-loading-library branch June 16, 2026 10:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants