Skip to content

[SEA-NodeJS] (2/8) napi-rs binding consumer — TS loader + build script#380

Merged
msrathore-db merged 11 commits into
mainfrom
msrathore/sea-napi-binding
Jun 1, 2026
Merged

[SEA-NodeJS] (2/8) napi-rs binding consumer — TS loader + build script#380
msrathore-db merged 11 commits into
mainfrom
msrathore/sea-napi-binding

Conversation

@msrathore-db
Copy link
Copy Markdown
Contributor

@msrathore-db msrathore-db commented May 16, 2026

Stack

Linear stack of 8 PRs landing the M0 + M1 Phase 1 SEA NodeJS work. Merge in order from base ↑ to tip. The tip branch (msrathore/sea-auth-u2m, PR #383) is the single snapshot containing everything in flight — point your test or benchmark harness at it for an end-to-end check.

Pos PR Branch Scope
1/8 #378 sea-abstraction IBackend / ISessionBackend / IOperationBackend interfaces
2/8 #380 sea-napi-binding TS loader + build script for the kernel-provided .node artifact
3/8 #377 sea-errors-logging Kernel ErrorCode → JS error-class mapping (M0 minimum)
4/8 #379 sea-auth PAT auth via useSEA: true
5/8 #382 sea-execution executeStatement + openSession (sessionConfig, initialCatalog/Schema)
6/8 #381 sea-results CloudFetch + Inline Arrow result fetching
7/8 #384 sea-operation cancel / close / finished lifecycle + INTERVAL parity + napi-relocation acceptance (absorbed sea-integration content)
8/8 #383 sea-auth-u2m ← TIP M1 Phase 1 OAuth M2M + U2M (5 review rounds, ZERO HIGH at close)

Companion kernel stack (databricks/databricks-sql-kernel): 8 PRs — root #26 (async-public-api) → #27#25#29#28#30#24#23 (tip).

Policy: new PRs always stack on the current tip. No sibling/parallel topology. No force-pushes on existing PRs unless absolutely necessary; if a PR's content is wrong, add a fix-up commit on top of the stack tip rather than rewriting history.


This PR is position 2/8.

Summary

Thin TypeScript loader for the napi-rs binding (SeaNativeLoader), generated native/sea/index.d.ts, and the build:native npm script that compiles against the kernel workspace's napi/ sub-crate.

Companion kernel PR

The Rust napi crate itself lives in the kernel repo — see databricks/databricks-sql-kernel#25 (Database / Connection / Statement / ResultStream classes) and its skeleton predecessor #27.

Downstream fixes / reviewer note

Test plan

  • npm run build:native produces native/sea/index.linux-x64-gnu.node
  • ✅ Loader correctly require()s the platform-specific binary

Draft until you give the go for review.

Tracking

Co-authored-by: Isaac

@github-actions
Copy link
Copy Markdown

Thanks for your contribution! To satisfy the DCO policy in our contributing guide every commit message must include a sign-off message. One or more of your commits is missing this message. You can reword previous commit messages with an interactive rebase (git rebase -i main).

@msrathore-db msrathore-db force-pushed the msrathore/sea-napi-binding branch from 84d0860 to 20231c8 Compare May 17, 2026 13:22
@msrathore-db msrathore-db changed the base branch from main to msrathore/sea-abstraction May 17, 2026 13:22
@github-actions
Copy link
Copy Markdown

Thanks for your contribution! To satisfy the DCO policy in our contributing guide every commit message must include a sign-off message. One or more of your commits is missing this message. You can reword previous commit messages with an interactive rebase (git rebase -i main).

@github-actions
Copy link
Copy Markdown

Thanks for your contribution! To satisfy the DCO policy in our contributing guide every commit message must include a sign-off message. One or more of your commits is missing this message. You can reword previous commit messages with an interactive rebase (git rebase -i main).

msrathore-db added a commit that referenced this pull request May 24, 2026
Addresses PR #380 review findings C1, C2 (partial), C3, H1, H2, H3,
H4, H5, H6, H7, H8 (runtime guard), H9, M1, M2, M3, M4 (linguist),
M5, M6, M7, M8, L1, L2, L4.

- C1 lint: drop `.js` ext from native/sea require so eslint
  import/extensions passes; gitignore the auto-generated index.js
  and *.node artifacts; prettier-ignore the napi-rs auto-generated
  index.d.ts / index.js.
- C2 publish: whitelist native/sea/index.{js,d.ts} in .npmignore;
  declare @databricks/sea-native-linux-x64-gnu in optionalDependencies.
  The kernel-side package-name rename (drop the linux-x64-gnu
  prefix) is tracked separately as a cross-PR ask.
- C3 test wiring: move tests/native/version.test.ts ->
  tests/unit/sea/, tests/native/e2e-smoke.test.ts -> tests/e2e/sea/;
  both now picked up by the existing mocharc globs and run via the
  existing `npm test` / `npm run e2e` jobs.
- H1 noise drop: version.test.ts now asserts one meaningful semver
  check; three tautological assertions removed.
- H2 + H3 + H7 lazy load: rewrite SeaNativeLoader.ts on the
  lib/utils/lz4.ts pattern. Lazy require behind getSeaNative();
  capability-detection helper tryGetSeaNative(); structured error
  messages that classify MODULE_NOT_FOUND vs ERR_DLOPEN_FAILED and
  include platform/arch/Node-version + install hint.
- H4 supply chain: pin @napi-rs/cli to 2.18.4 in devDependencies;
  build:native switches to `npx --no-install` so the pinned local
  install is used (no per-build network fetch).
- H5 path: switch build:native default kernel path to the canonical
  `../../databricks-sql-kernel/napi-binding` (the worktree-specific
  `-sea-WT` suffix is gone).
- H6 CI safety: e2e suite hard-fails when CI=true and any required
  env var is missing; dev machines still skip.
- H8 runtime guard: loader throws a structured error on Node <18
  instead of attempting a dlopen that would fail mysteriously.
  Driver's engines.node stays >=14 — Thrift consumers on older
  Node continue to work.
- H9 + M1 + M2 types: tsconfig adds a `@sea-native` path alias to
  native/sea/index.d.ts; loader imports the real Connection /
  Statement / ConnectionOptions / ExecuteOptions / ArrowBatch /
  ArrowSchema types and re-exports them. Tests use the re-exported
  types — the inline-shape duplication across three files collapses.
- M3 README: rewrite native/sea/README.md to match kernel reality.
  The napi crate is a standalone Cargo workspace (not a pyo3
  sibling); explain the tls-rustls choice that the standalone
  workspace exists to enable.
- M4 drift detection: mark native/sea/index.d.ts as
  linguist-generated in .gitattributes so GitHub collapses it in
  diffs and excludes from blame/language stats.
- M5 artifacts: gitignore native/sea/index.js, index.node,
  index.*.node.
- M6 + M7 e2e coverage: decode the IPC payload via apache-arrow's
  tableFromIPC and assert numRows + cell value (not just shape);
  add drain-past-null idempotence and schema-before-fetch
  coverage.
- L1 build scripts: collapse build:native + build:native:debug
  into one script taking BUILD_PROFILE (defaults to --release).
- L2 / L4 / M8: drop the version() alias and the "Round 2+ will…"
  comment debt; the loader now actually delivers the value the
  prior JSDoc was only promising.

Verified on this branch: npm run lint clean (0 errors); npm run
prettier clean for PR-owned files (3 unrelated pre-existing
warnings on PR #378 territory); tsc --project tsconfig.build.json
clean; mocha on tests/unit/sea passes (4/4); mocha on
tests/e2e/sea passes against a live pecotesting warehouse (2/2,
IPC decode confirms SELECT 1 returns 1).
@github-actions
Copy link
Copy Markdown

Thanks for your contribution! To satisfy the DCO policy in our contributing guide every commit message must include a sign-off message. One or more of your commits is missing this message. You can reword previous commit messages with an interactive rebase (git rebase -i main).

msrathore-db added a commit that referenced this pull request May 24, 2026
Addresses PR #380 review findings C1, C2 (partial), C3, H1, H2, H3,
H4, H5, H6, H7, H8 (runtime guard), H9, M1, M2, M3, M4 (linguist),
M5, M6, M7, M8, L1, L2, L4.

- C1 lint: drop `.js` ext from native/sea require so eslint
  import/extensions passes; gitignore the auto-generated index.js
  and *.node artifacts; prettier-ignore the napi-rs auto-generated
  index.d.ts / index.js.
- C2 publish: whitelist native/sea/index.{js,d.ts} in .npmignore;
  declare @databricks/sea-native-linux-x64-gnu in optionalDependencies.
  The kernel-side package-name rename (drop the linux-x64-gnu
  prefix) is tracked separately as a cross-PR ask.
- C3 test wiring: move tests/native/version.test.ts ->
  tests/unit/sea/, tests/native/e2e-smoke.test.ts -> tests/e2e/sea/;
  both now picked up by the existing mocharc globs and run via the
  existing `npm test` / `npm run e2e` jobs.
- H1 noise drop: version.test.ts now asserts one meaningful semver
  check; three tautological assertions removed.
- H2 + H3 + H7 lazy load: rewrite SeaNativeLoader.ts on the
  lib/utils/lz4.ts pattern. Lazy require behind getSeaNative();
  capability-detection helper tryGetSeaNative(); structured error
  messages that classify MODULE_NOT_FOUND vs ERR_DLOPEN_FAILED and
  include platform/arch/Node-version + install hint.
- H4 supply chain: pin @napi-rs/cli to 2.18.4 in devDependencies;
  build:native switches to `npx --no-install` so the pinned local
  install is used (no per-build network fetch).
- H5 path: switch build:native default kernel path to the canonical
  `../../databricks-sql-kernel/napi-binding` (the worktree-specific
  `-sea-WT` suffix is gone).
- H6 CI safety: e2e suite hard-fails when CI=true and any required
  env var is missing; dev machines still skip.
- H8 runtime guard: loader throws a structured error on Node <18
  instead of attempting a dlopen that would fail mysteriously.
  Driver's engines.node stays >=14 — Thrift consumers on older
  Node continue to work.
- H9 + M1 + M2 types: tsconfig adds a `@sea-native` path alias to
  native/sea/index.d.ts; loader imports the real Connection /
  Statement / ConnectionOptions / ExecuteOptions / ArrowBatch /
  ArrowSchema types and re-exports them. Tests use the re-exported
  types — the inline-shape duplication across three files collapses.
- M3 README: rewrite native/sea/README.md to match kernel reality.
  The napi crate is a standalone Cargo workspace (not a pyo3
  sibling); explain the tls-rustls choice that the standalone
  workspace exists to enable.
- M4 drift detection: mark native/sea/index.d.ts as
  linguist-generated in .gitattributes so GitHub collapses it in
  diffs and excludes from blame/language stats.
- M5 artifacts: gitignore native/sea/index.js, index.node,
  index.*.node.
- M6 + M7 e2e coverage: decode the IPC payload via apache-arrow's
  tableFromIPC and assert numRows + cell value (not just shape);
  add drain-past-null idempotence and schema-before-fetch
  coverage.
- L1 build scripts: collapse build:native + build:native:debug
  into one script taking BUILD_PROFILE (defaults to --release).
- L2 / L4 / M8: drop the version() alias and the "Round 2+ will…"
  comment debt; the loader now actually delivers the value the
  prior JSDoc was only promising.

Verified on this branch: npm run lint clean (0 errors); npm run
prettier clean for PR-owned files (3 unrelated pre-existing
warnings on PR #378 territory); tsc --project tsconfig.build.json
clean; mocha on tests/unit/sea passes (4/4); mocha on
tests/e2e/sea passes against a live pecotesting warehouse (2/2,
IPC decode confirms SELECT 1 returns 1).

Signed-off-by: Madhavendra Rathore <madhavendra.rathore@databricks.com>
@msrathore-db msrathore-db force-pushed the msrathore/sea-napi-binding branch from 6b70ce4 to 548a14b Compare May 24, 2026 23:23
Comment thread .npmignore
# selects the per-platform `.node` artifact from `@databricks/sea-native-*`
# optionalDependencies (populated when the kernel CI publishes them);
# the .d.ts is the consumer-facing type contract.
!native/sea/index.js
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

High — release-engineering landmine that crashes every consumer the moment PR 3/8+ wires SEA in.

Verified at HEAD 548a14b8:

  • git ls-tree native/sea/ shows ONLY README.md and index.d.ts — no index.js.
  • .gitignore:17 ignores native/sea/index.js (it's regenerated by npm run build:native).
  • .npmignore:10 allow-lists !native/sea/index.js to ship in the tarball.
  • package.json scripts has no prepack or prepublishOnly hook that runs build:native.
  • The loader at lib/sea/SeaNativeLoader.ts:82 does require('../../native/sea') — Node's resolver looks for index.js in that directory.

Result: any npm publish from a workspace that didn't manually run npm run build:native first ships a tarball missing the napi-rs router. Consumers get MODULE_NOT_FOUND with a misleading hint that tells them to install the optional dep (which is already installed) instead of pointing at the missing router shim.

PR #380 doesn't crash anything today because nothing calls getSeaNative(). The moment PR 3/8 wires SeaBackend.connect() to the loader, every install bricks.

  • Suggested fix: either (a) commit native/sea/index.js (analogous to the committed index.d.ts — the file is small and stable), or (b) add a prepack script that runs build:native gated on DATABRICKS_RELEASE_BUILD=1, with an explicit [ -f native/sea/index.js ] || (echo "Missing native router; run npm run build:native first" && exit 1) assertion that fails the pack if it's still missing.

Found by: security, ops, maintainability, devils-advocate (4 reviewers).


Posted by code-review-squad · /full-review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed in 3216019 (C1). Committed the napi-rs router native/sea/index.js (un-ignored, analogous to the committed index.d.ts) and added a prepack assertion that hard-fails the pack if the router is missing:

"prepack": "test -f native/sea/index.js || { echo 'ERROR: native/sea/index.js (napi-rs router) is missing …' >&2; exit 1; }"

Companion kernel fix databricks-sql-kernel#93 corrects the base package name so the router’s require paths resolve. A publish can no longer ship a tarball missing the router.

Comment thread tsconfig.json Outdated
"forceConsistentCasingInFileNames": true
"forceConsistentCasingInFileNames": true,
"baseUrl": "./",
"paths": {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Medium — published declaration files reference an unresolvable module specifier.

Verified: tsconfig.build.json extends tsconfig.json, so the paths: { "@sea-native": ["./native/sea/index.d.ts"] } mapping propagates into the production build. TypeScript does NOT rewrite path-aliased specifiers in emitted declarations.

When this loader is re-exported from the public surface (which is the goal in PR 3/8+), every downstream TS consumer of @databricks/sql will see import type { ... } from '@sea-native' in the .d.ts and fail type-check with "Cannot find module '@sea-native'".

Today it doesn't break anything because (a) only import type is used in lib/sea/SeaNativeLoader.ts:26 (erased at runtime) and (b) the loader isn't re-exported from lib/index.ts. But the bug is already in the published surface waiting to be triggered.

  • Suggested fix: Drop the paths mapping and use a relative import type { … } from '../../native/sea'. The alias is used by exactly one file — it buys nothing.

Found by: architecture, language, agent-compat, devils-advocate (4 reviewers).


Posted by code-review-squad · /full-review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed in 3216019 (C2). Dropped the @sea-native paths alias entirely (0 sea-native refs left in tsconfig.json); SeaNativeLoader.ts uses a relative import(../../native/sea). No unresolvable specifier leaks into the emitted .d.ts.

Comment thread lib/sea/SeaNativeLoader.ts Outdated

function loadFailureHint(err: NodeJS.ErrnoException): string {
const platform = `${process.platform}-${process.arch}`;
const installHint = `Install the matching optional dependency (e.g. @databricks/sea-native-${platform}).`;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Medium — every customer who hits this error is sent on a wild-goose chase.

Verified: line 55 builds platform = '${process.platform}-${process.arch}'. On linux/x64 that produces linux-x64; on darwin/arm64 it produces darwin-arm64. The error message then says:

Install the matching optional dependency (e.g. @databricks/sea-native-linux-x64).

But the actual published package (per package.json:95) is @databricks/sea-native-linux-x64-**gnu**. The hint's recommended npm install will 404.

Same issue cross-platform:

  • linux/x64 → suggests @databricks/sea-native-linux-x64; actual is -linux-x64-gnu or -linux-x64-musl

  • linux/arm64 → suggests @databricks/sea-native-linux-arm64; actual is -linux-arm64-gnu

  • win32/x64 → suggests @databricks/sea-native-win32-x64; actual is -win32-x64-msvc

  • Suggested fix: either compute the napi-rs triple correctly (mirror the router's platform→triple table — easier said than done) or drop the package-name example: "Install the matching @databricks/sea-native-* optional dependency for your platform; see the README for the supported triple list."

Found by: ops, agent-compat.


Posted by code-review-squad · /full-review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed in 3216019 (C3). The error hint no longer names a specific (404-ing) package — it points at the README’s supported-triple list instead (// 404. Point at the READMEs supported-triple list instead.).

Comment thread package.json Outdated
"optionalDependencies": {
"lz4": "^0.6.5"
"lz4": "^0.6.5",
"@databricks/sea-native-linux-x64-gnu": "0.1.0"
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Medium — by far the highest-consensus finding; 7 reviewers flagged it.

Only @databricks/sea-native-linux-x64-gnu: 0.1.0 is in optionalDependencies. macOS-arm64, macOS-x64, linux-arm64-gnu, linux-x64-musl (Alpine), win32-x64-msvc, etc. all have zero installable binding.

Three coupled consequences:

  1. Silent degradation — on every non-linux-x64-gnu platform, the loader will hit MODULE_NOT_FOUND. Users may not realize they're stuck on Thrift.
  2. Misleading hint (see M2) — the loader tells them to install a package that doesn't exist.
  3. Supply-chain squat risk — the unlisted names (@databricks/sea-native-darwin-arm64, …-darwin-x64, etc.) are not on the npm registry. Confirm @databricks org scope is locked to Databricks publishers, OR pre-register empty placeholder packages now, so an external party can't typosquat @databricks/sea-native-darwin-arm64 before Databricks does and have it autoload via the napi-rs router for darwin-arm64 consumers.
  • Suggested fix: Decide between two coherent models:
    • (a) Intentional M0 scope — explicitly document "M0 = linux-x64-gnu only; other platforms continue using Thrift exclusively" in the README and update the loader's error message to match.
    • (b) Multi-platform support — list all planned triples in optionalDependencies (npm tolerates missing optionalDeps on the registry — they skip silently with a warning).

Whichever you pick, address the supply-chain squat question separately (lock the scope or pre-register placeholders).

Found by: security, ops, devils-advocate, performance, architecture, agent-compat, language (7 reviewers).


Posted by code-review-squad · /full-review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed in 3216019 (C4) via model (a) — intentional M0 scope. native/sea/README.md now has a “Supported platforms (M0)” section documenting that M0 publishes a single triple (linux-x64-gnu); other platforms stay on Thrift. Added an npm scope-lock / placeholder note for the supply-chain-squat concern. Multi-platform (model b) is post-M0.

Comment thread lib/sea/SeaNativeLoader.ts Outdated
export type Connection = NativeConnection;
export type Statement = NativeStatement;

export interface SeaNativeBinding {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Medium — single-source-of-truth violation.

Lines 39-44 declare:

export interface SeaNativeBinding {
  version(): string;
  openSession(options: ConnectionOptions): Promise<NativeConnection>;
  Connection: typeof NativeConnection;
  Statement: typeof NativeStatement;
}

This is a manual subset of what native/sea/index.d.ts already declares. When the kernel adds a new free function (e.g. cancelStatement, future async APIs), the .d.ts regenerates but this interface stays stale until someone notices. The unchecked cast at line 82 (require('../../native/sea') as SeaNativeBinding) hides the drift.

  • Suggested fix: derive the type from the generated module instead of redeclaring it:
import type * as SeaNative from '../../native/sea';
export type SeaNativeBinding = typeof SeaNative;

Then the cast at line 82 stays automatically correct, and the README's claim that "the .d.ts is the contract" is enforced by the type system.

Found by: architecture.


Posted by code-review-squad · /full-review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed in 3216019 (C5). SeaNativeBinding is now derived from the generated module — export type SeaNativeBinding = typeof import(../../native/sea) — so it can’t drift from the .d.ts, and the defaultRequire() cast stays correct automatically.

Comment thread lib/sea/SeaNativeLoader.ts Outdated
return `SEA native binding failed to load on platform ${platform} / Node ${process.version}: ${err.message}`;
}

let cached: SeaNativeBinding | null | undefined;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Medium — turns every SeaBackend unit test into an integration test once SEA is wired in.

cached and cachedError are module-level let bindings (lines 65-66). getSeaNative() / tryGetSeaNative() are free functions that close over them. There's no constructor, no DI seam, no exported reset hook.

Consequence for PR 3/8: when SeaBackend.connect() stops throwing NOT_IMPLEMENTED and starts calling getSeaNative(), any unit test that touches SeaBackend will require a real .node to be loadable on the test machine — otherwise it skips. sinon.stub(SeaNativeLoader, 'getSeaNative') works once per file but the cached value persists across files in the same mocha run. Order-dependence is baked in.

The lz4 pattern this is "mirroring" gets away with module-state because the existing codebase wraps it (e.g., Lz4Util and adapters at the call sites accept the resolved module). Here SeaNativeLoader IS the wrapper, and the wrapper has no seam.

  • Suggested fix: expose the loader as a class with an injectable seam:
export class SeaNativeLoader {
  constructor(private readonly load: () => SeaNativeBinding = defaultRequire) {}
  get(): SeaNativeBinding { /* ... */ }
  tryGet(): SeaNativeBinding | undefined { /* ... */ }
}

Then SeaBackend takes loader: SeaNativeLoader via constructor (matches the existing IClientContext pattern in lib/DBSQLClient.ts). Keep getSeaNative() as a thin convenience over a process-global default instance.

Much cheaper to change now (0 callers) than after PRs 3–8 land.

Found by: architecture, devils-advocate, maintainability adjacent (3 reviewers).


Posted by code-review-squad · /full-review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed in 3216019 (C6). SeaNativeLoader is now a class with an injectable load seam (constructor(load = defaultRequire)); getSeaNative()/tryGetSeaNative() are thin wrappers over a process-global default instance. The new tests/unit/sea/loader.test.ts exercises it via the injected seam with no real .node required, so wiring SEA into SeaBackend won’t turn its unit tests into integration tests.

Comment thread lib/sea/SeaNativeLoader.ts Outdated
ArrowBatch,
ArrowSchema,
} from '@sea-native';

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Medium — name collisions will surface as IDE autocomplete ambiguity and silent field-shape bugs once SEA is wired in.

Lines 34-37 re-export:

export type { ConnectionOptions, ExecuteOptions, ArrowBatch, ArrowSchema };
export type Connection = NativeConnection;
export type Statement = NativeStatement;

Collisions with existing public types:

  • ConnectionOptions (SEA: hostName/httpPath/token) vs ConnectionOptions from lib/contracts/IDBSQLClient.ts (Thrift: host/path/token + AuthOptions union). The token field is shared → silent shape-mismatch bugs when an IDE auto-imports the wrong one.
  • ArrowBatch (SEA: {ipcBytes: Buffer}) vs ArrowBatch from lib/result/utils.ts (Thrift: {batches: Buffer[]; rowCount: number}).

With 0 callers today this is harmless. The moment SEA is wired into DBSQLClient and these types are imported anywhere outside lib/sea/, the bare names become ambiguous in autocomplete and in code review.

  • Suggested fix: rename the SEA-side exports now, before any production consumer imports them:
export type { ConnectionOptions as SeaConnectionOptions, ExecuteOptions as SeaExecuteOptions, ArrowBatch as SeaArrowBatch, ArrowSchema as SeaArrowSchema };
export type SeaConnection = NativeConnection;
export type SeaStatement = NativeStatement;

The kernel-generated .d.ts can keep the napi-rs default names (it's the kernel's contract). The TS-side wrapper is where disambiguation should happen, and doing it before any consumer imports the bare names is a one-way door.

Found by: agent-compat, architecture, devils-advocate, language, maintainability (5 reviewers).


Posted by code-review-squad · /full-review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed in 3216019 (C7). The TS-side re-exports are renamed SeaConnectionOptions / SeaExecuteOptions / SeaArrowBatch / SeaArrowSchema / SeaConnection / SeaStatement. The kernel-generated .d.ts keeps the napi-rs default names. Done now, before any production consumer imports the bare names.


describe('SEA native binding — smoke test', function smoke() {
const binding = tryGetSeaNative();
if (binding === undefined) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Medium — coverage gap that masks broken-binding regressions.

Two coupled problems:

  1. tests/unit/sea/version.test.ts:20-30 — silent skip when tryGetSeaNative() returns undefined. No CI escalation. On a linux-x64-gnu CI runner where the optional dep should install, a silently broken @databricks/sea-native-linux-x64-gnu would produce a green build. Compare to tests/e2e/sea/e2e-smoke.test.ts:55-62, which DOES fail loud in CI when env vars are missing — but applies the same logic only to env vars, not to the binding.

  2. Line 33 — the only assertion is expect(binding.version()).to.match(/^\d+\.\d+\.\d+$/). No shape-check on binding.openSession, binding.Connection, binding.Statement. If the kernel renames any of these, the test still passes — green.

  • Suggested fixes:
    • Mirror the CI fail-loud logic from the e2e test: on a runner whose triple is supposed to have a published .node (e.g., process.env.CI === 'true' and process.platform === 'linux' && process.arch === 'x64'), treat binding === undefined as a hard failure.
    • Add shape checks inside tryLoad() (lib/sea/SeaNativeLoader.ts:82 — verify typeof binding.openSession === 'function', binding.Connection exists, binding.Statement exists) so kernel-side shape drift is caught.
    • Add a tests/unit/sea/loader.test.ts with proxyquire covering the loadFailureHint branches (MODULE_NOT_FOUND, ERR_DLOPEN_FAILED, generic), the Node-version gate, and caching. Pure logic tests; run everywhere regardless of binding availability.

Found by: test, devils-advocate, ops, agent-compat.


Posted by code-review-squad · /full-review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed in 3216019 (C8). version.test.ts now fails loud on a linux-x64 CI runner (where the optional dep should install) instead of silently skipping, and adds shape checks for openSession/Connection/Statement. New tests/unit/sea/loader.test.ts covers the hint branches, the Node-version gate, the shape check, and caching — all via the injected seam, so they run everywhere regardless of binding availability.

Comment thread lib/sea/SeaNativeLoader.ts Outdated

function tryLoad(): SeaNativeBinding | undefined {
const nodeMajor = detectNodeMajor();
if (Number.isFinite(nodeMajor) && nodeMajor < MIN_NODE_MAJOR) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Low — defensive guard works backwards.

if (Number.isFinite(nodeMajor) && nodeMajor < MIN_NODE_MAJOR) evaluates to false when nodeMajor === NaN, so the load proceeds. The intent reads "fail closed if we can't tell what Node we're on" but the code does the opposite.

In practice process.version is always parseable, so the practical risk is near-zero. But it's the kind of guard that future runtime quirks will surface.

Suggested fix:

if (!Number.isFinite(nodeMajor) || nodeMajor < MIN_NODE_MAJOR) {
  // ...
}

Posted by code-review-squad · /full-review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 3216019 (C9). The guard now fails closed: if (!Number.isFinite(nodeMajor) || nodeMajor < MIN_NODE_MAJOR) — NaN (unparseable version) now also blocks the load.

Comment thread native/sea/index.d.ts Outdated
executeStatement(sql: string, options: ExecuteOptions): Promise<Statement>
/**
* Explicit close. Marks the connection wrapper as closed so
* subsequent calls on this `Connection` return `InvalidArg`, then
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Low — agent-friendliness / signal-to-noise.

The docstring on Connection.close discusses tracing::EnteredSpan, !Send futures, napi-rs's execute_tokio_future glue rejects non-Send futures, etc. This is excellent for a Rust reviewer but counterproductive for JS consumers — an LLM agent answering "why doesn't connection.close() await?" will paste the Rust paragraph into a JS issue/Slack where it has no context.

When the kernel fixes this (via cloned span or similar), the .d.ts is regenerated and the now-stale Rust rationale silently disappears — any agent that scraped it for caching is now serving wrong advice.

  • Suggested fix: in the Rust source, move the kernel-internal reasoning into a Rust comment (// SAFETY: style) and keep the #[napi] JSDoc terse and behavior-focused:

Returns immediately after marking the wrapper closed. The server-side close runs in the background; failures are not surfaced to JS. Use Statement.close() (which awaits) if you need to observe close errors per-statement.

Same lens applies to the class-level docs on Connection and StatementArc<Mutex<Option<...>>>, result_stream_mut, ExecutedStatementHandle are all Rust-side concerns the JS audience doesn't need.


Posted by code-review-squad · /full-review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Partially addressed (C10). index.d.ts was regenerated from merged kernel main, which terser’d most of the Rust-internal prose. The remaining Rust phrasing lives in this generated file, so the real fix is to terse the #[napi] JSDoc in the kernel Rust source rather than hand-edit here — raising that on the kernel side. Not blocking M0.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 1, 2026

Thanks for your contribution! To satisfy the DCO policy in our contributing guide every commit message must include a sign-off message. One or more of your commits is missing this message. You can reword previous commit messages with an interactive rebase (git rebase -i main).

msrathore-db added a commit that referenced this pull request Jun 1, 2026
Addresses PR #380 review findings C1, C2 (partial), C3, H1, H2, H3,
H4, H5, H6, H7, H8 (runtime guard), H9, M1, M2, M3, M4 (linguist),
M5, M6, M7, M8, L1, L2, L4.

- C1 lint: drop `.js` ext from native/sea require so eslint
  import/extensions passes; gitignore the auto-generated index.js
  and *.node artifacts; prettier-ignore the napi-rs auto-generated
  index.d.ts / index.js.
- C2 publish: whitelist native/sea/index.{js,d.ts} in .npmignore;
  declare @databricks/sea-native-linux-x64-gnu in optionalDependencies.
  The kernel-side package-name rename (drop the linux-x64-gnu
  prefix) is tracked separately as a cross-PR ask.
- C3 test wiring: move tests/native/version.test.ts ->
  tests/unit/sea/, tests/native/e2e-smoke.test.ts -> tests/e2e/sea/;
  both now picked up by the existing mocharc globs and run via the
  existing `npm test` / `npm run e2e` jobs.
- H1 noise drop: version.test.ts now asserts one meaningful semver
  check; three tautological assertions removed.
- H2 + H3 + H7 lazy load: rewrite SeaNativeLoader.ts on the
  lib/utils/lz4.ts pattern. Lazy require behind getSeaNative();
  capability-detection helper tryGetSeaNative(); structured error
  messages that classify MODULE_NOT_FOUND vs ERR_DLOPEN_FAILED and
  include platform/arch/Node-version + install hint.
- H4 supply chain: pin @napi-rs/cli to 2.18.4 in devDependencies;
  build:native switches to `npx --no-install` so the pinned local
  install is used (no per-build network fetch).
- H5 path: switch build:native default kernel path to the canonical
  `../../databricks-sql-kernel/napi-binding` (the worktree-specific
  `-sea-WT` suffix is gone).
- H6 CI safety: e2e suite hard-fails when CI=true and any required
  env var is missing; dev machines still skip.
- H8 runtime guard: loader throws a structured error on Node <18
  instead of attempting a dlopen that would fail mysteriously.
  Driver's engines.node stays >=14 — Thrift consumers on older
  Node continue to work.
- H9 + M1 + M2 types: tsconfig adds a `@sea-native` path alias to
  native/sea/index.d.ts; loader imports the real Connection /
  Statement / ConnectionOptions / ExecuteOptions / ArrowBatch /
  ArrowSchema types and re-exports them. Tests use the re-exported
  types — the inline-shape duplication across three files collapses.
- M3 README: rewrite native/sea/README.md to match kernel reality.
  The napi crate is a standalone Cargo workspace (not a pyo3
  sibling); explain the tls-rustls choice that the standalone
  workspace exists to enable.
- M4 drift detection: mark native/sea/index.d.ts as
  linguist-generated in .gitattributes so GitHub collapses it in
  diffs and excludes from blame/language stats.
- M5 artifacts: gitignore native/sea/index.js, index.node,
  index.*.node.
- M6 + M7 e2e coverage: decode the IPC payload via apache-arrow's
  tableFromIPC and assert numRows + cell value (not just shape);
  add drain-past-null idempotence and schema-before-fetch
  coverage.
- L1 build scripts: collapse build:native + build:native:debug
  into one script taking BUILD_PROFILE (defaults to --release).
- L2 / L4 / M8: drop the version() alias and the "Round 2+ will…"
  comment debt; the loader now actually delivers the value the
  prior JSDoc was only promising.

Verified on this branch: npm run lint clean (0 errors); npm run
prettier clean for PR-owned files (3 unrelated pre-existing
warnings on PR #378 territory); tsc --project tsconfig.build.json
clean; mocha on tests/unit/sea passes (4/4); mocha on
tests/e2e/sea passes against a live pecotesting warehouse (2/2,
IPC decode confirms SELECT 1 returns 1).

Signed-off-by: Madhavendra Rathore <madhavendra.rathore@databricks.com>
msrathore-db added a commit that referenced this pull request Jun 1, 2026
…DI seam, packaging, tests

Rebuilds native/sea against the merged kernel main (binding renamed
@databricks/sea-native -> @databricks/sql-kernel via kernel #82) and
addresses the /full-review findings on PR #380:

- C1: commit the napi-rs router (native/sea/index.js, un-ignored) + a
  prepack assertion so the publish tarball can never ship without it.
  Companion kernel fix (databricks-sql-kernel#93) corrects the base
  package name so the router require paths resolve.
- C2: drop the @sea-native tsconfig path alias; use a relative import
  so no unresolvable specifier leaks into the emitted .d.ts.
- C3/C11: error hints no longer name a 404-ing package; dlopen hint now
  includes the underlying dlerror string + concrete remediation.
- C4: document M0 = linux-x64-gnu-only scope + npm scope-lock note.
- C5: SeaNativeBinding = typeof import('../../native/sea') (no drift).
- C6: SeaNativeLoader is now a class with an injectable load seam;
  getSeaNative/tryGetSeaNative are thin process-global wrappers.
- C7: re-exports renamed Sea* to avoid colliding with Thrift types.
- C8: version.test.ts fails loud on the linux-x64 CI runner + shape
  checks; new loader.test.ts covers the hint branches, Node gate,
  shape check, and caching via the injected seam.
- C9: Node-version guard fails closed (NaN or < floor).
- C13: e2e smoke uses the shared tests/e2e/utils/config.ts creds.
- C10/C12 are resolved upstream in merged kernel main / deferred to M1.

index.d.ts regenerated from merged main: ExecuteOptions dropped
(catalog/schema/sessionConf are session-level on openSession),
close() awaits DeleteSession, schema() is sync, sessionId/statementId
getters added.

Verified: 11 unit tests; e2e SELECT 1 against a live warehouse, direct
and through mitmproxy (SEA REST: POST /sql/sessions -> POST
/sql/statements -> DELETE /sql/sessions/<id>).

Co-authored-by: Isaac
@msrathore-db msrathore-db changed the base branch from msrathore/sea-abstraction to main June 1, 2026 05:22
@msrathore-db msrathore-db force-pushed the msrathore/sea-napi-binding branch from 33b75b8 to 715a6f4 Compare June 1, 2026 05:22
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 1, 2026

Thanks for your contribution! To satisfy the DCO policy in our contributing guide every commit message must include a sign-off message. One or more of your commits is missing this message. You can reword previous commit messages with an interactive rebase (git rebase -i main).

1 similar comment
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 1, 2026

Thanks for your contribution! To satisfy the DCO policy in our contributing guide every commit message must include a sign-off message. One or more of your commits is missing this message. You can reword previous commit messages with an interactive rebase (git rebase -i main).

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 1, 2026

Thanks for your contribution! To satisfy the DCO policy in our contributing guide every commit message must include a sign-off message. One or more of your commits is missing this message. You can reword previous commit messages with an interactive rebase (git rebase -i main).

Creates the napi-rs binding skeleton: Cargo.toml + lib.rs + module
stubs for database/connection/statement/result/error/logger. Captures
napi-rs tokio Handle via OnceCell in runtime.rs. Single working
#[napi] fn version() proves the binding loads + executes end-to-end
in Node.

Depends on krn-async-public-api branch (path dep on kernel).

Round 2 will add open/execute/fetch methods.

Signed-off-by: Madhavendra Rathore <madhavendra.rathore@databricks.com>
…wired

Adds real async methods on the opaque wrappers backing M0:
- openSession (free function) with PAT → kernel Session
- Connection::execute_statement → kernel ExecutedStatement
- Statement::fetch_next_batch / schema / cancel / close → kernel ResultStream
- Arrow batches returned as IPC bytes (per Layer 2 design)
- Error mapping preserves kernel ErrorCode + SQLSTATE for TS layer
- All entry points wrapped in catch_unwind

End-to-end smoke test against pecotesting passes.
No new dependencies beyond arrow-{ipc,array,schema} + futures.
Uses kernel async public API (no block_on).

Co-authored-by: Isaac
Signed-off-by: Madhavendra Rathore <madhavendra.rathore@databricks.com>
…indings

Round 1 scaffold declared tracing + tracing-subscriber as deps but
never used them. Removed. Logger bridge will re-add in round 3.

Other findings from 6b3affd-2026-05-15.md reviewed:
- Finding 2 (Database::Drop unreachable in Round 1b) — obsoleted by
  Round 2 (40d0b57): database.rs no longer declares a Database struct
  or Drop impl; it is now an `open_session` free function.
- Finding 3 (empty Connection::Drop) — obsoleted by Round 2: the Drop
  impl now spawns a real fire-and-forget close on the captured tokio
  handle.

Co-authored-by: Isaac
Signed-off-by: Madhavendra Rathore <madhavendra.rathore@databricks.com>
Per D-006 architectural decision (Python team's workspace pattern):
all language bindings (PyO3, napi-rs) now live as workspace siblings
in the kernel repo at databricks-sql-kernel/{pyo3,napi}/.

What this commit removes from the nodejs repo:
- native/sea/Cargo.toml (path dep relocated; package now at
  databricks-sql-kernel/napi/Cargo.toml with path = "..")
- native/sea/build.rs
- native/sea/src/* (lib, runtime, database, connection, statement,
  result, error, logger, util — all 9 files)
- native/sea/package.json (the @databricks/sea-native-linux-x64-gnu
  sub-package moves to the kernel workspace too)
- native/sea/index.js (regenerated artifact)

What stays in nodejs:
- native/sea/index.d.ts — TS declarations consumed by lib/sea/ adapter
- native/sea/README.md (new) — explains the move; points readers at
  databricks-sql-kernel/napi/

What's updated:
- package.json: `build:native` and `build:native:debug` scripts now
  delegate to the kernel workspace via $DATABRICKS_SQL_KERNEL_REPO
  (defaults to ../../databricks-sql-kernel-sea-WT/napi-binding for the
  local dev worktree layout). Build copies index.node + index.d.ts
  back into native/sea/ for the loader to find.

Why workspace co-location:
- Arrow version pinning lockstep — no silent IPC version drift
- path = ".." (clean) vs ../../../../databricks-sql-kernel-sea-WT/...
- Single CI: cargo build --workspace covers kernel + pyo3 + napi
- Kernel API changes that break either binding caught at PR-review time
- Future cgo binding for Go SEA slots in as another workspace member

This branch (sea-napi-binding) is now a thin consumer of the kernel
napi crate. The actual Rust code lives at krn-napi-binding HEAD on
the kernel repo (commit debe3d7).

Signed-off-by: Madhavendra Rathore <madhavendra.rathore@databricks.com>
…generated

Signed-off-by: Madhavendra Rathore <madhavendra.rathore@databricks.com>
Addresses PR #380 review findings C1, C2 (partial), C3, H1, H2, H3,
H4, H5, H6, H7, H8 (runtime guard), H9, M1, M2, M3, M4 (linguist),
M5, M6, M7, M8, L1, L2, L4.

- C1 lint: drop `.js` ext from native/sea require so eslint
  import/extensions passes; gitignore the auto-generated index.js
  and *.node artifacts; prettier-ignore the napi-rs auto-generated
  index.d.ts / index.js.
- C2 publish: whitelist native/sea/index.{js,d.ts} in .npmignore;
  declare @databricks/sea-native-linux-x64-gnu in optionalDependencies.
  The kernel-side package-name rename (drop the linux-x64-gnu
  prefix) is tracked separately as a cross-PR ask.
- C3 test wiring: move tests/native/version.test.ts ->
  tests/unit/sea/, tests/native/e2e-smoke.test.ts -> tests/e2e/sea/;
  both now picked up by the existing mocharc globs and run via the
  existing `npm test` / `npm run e2e` jobs.
- H1 noise drop: version.test.ts now asserts one meaningful semver
  check; three tautological assertions removed.
- H2 + H3 + H7 lazy load: rewrite SeaNativeLoader.ts on the
  lib/utils/lz4.ts pattern. Lazy require behind getSeaNative();
  capability-detection helper tryGetSeaNative(); structured error
  messages that classify MODULE_NOT_FOUND vs ERR_DLOPEN_FAILED and
  include platform/arch/Node-version + install hint.
- H4 supply chain: pin @napi-rs/cli to 2.18.4 in devDependencies;
  build:native switches to `npx --no-install` so the pinned local
  install is used (no per-build network fetch).
- H5 path: switch build:native default kernel path to the canonical
  `../../databricks-sql-kernel/napi-binding` (the worktree-specific
  `-sea-WT` suffix is gone).
- H6 CI safety: e2e suite hard-fails when CI=true and any required
  env var is missing; dev machines still skip.
- H8 runtime guard: loader throws a structured error on Node <18
  instead of attempting a dlopen that would fail mysteriously.
  Driver's engines.node stays >=14 — Thrift consumers on older
  Node continue to work.
- H9 + M1 + M2 types: tsconfig adds a `@sea-native` path alias to
  native/sea/index.d.ts; loader imports the real Connection /
  Statement / ConnectionOptions / ExecuteOptions / ArrowBatch /
  ArrowSchema types and re-exports them. Tests use the re-exported
  types — the inline-shape duplication across three files collapses.
- M3 README: rewrite native/sea/README.md to match kernel reality.
  The napi crate is a standalone Cargo workspace (not a pyo3
  sibling); explain the tls-rustls choice that the standalone
  workspace exists to enable.
- M4 drift detection: mark native/sea/index.d.ts as
  linguist-generated in .gitattributes so GitHub collapses it in
  diffs and excludes from blame/language stats.
- M5 artifacts: gitignore native/sea/index.js, index.node,
  index.*.node.
- M6 + M7 e2e coverage: decode the IPC payload via apache-arrow's
  tableFromIPC and assert numRows + cell value (not just shape);
  add drain-past-null idempotence and schema-before-fetch
  coverage.
- L1 build scripts: collapse build:native + build:native:debug
  into one script taking BUILD_PROFILE (defaults to --release).
- L2 / L4 / M8: drop the version() alias and the "Round 2+ will…"
  comment debt; the loader now actually delivers the value the
  prior JSDoc was only promising.

Verified on this branch: npm run lint clean (0 errors); npm run
prettier clean for PR-owned files (3 unrelated pre-existing
warnings on PR #378 territory); tsc --project tsconfig.build.json
clean; mocha on tests/unit/sea passes (4/4); mocha on
tests/e2e/sea passes against a live pecotesting warehouse (2/2,
IPC decode confirms SELECT 1 returns 1).

Signed-off-by: Madhavendra Rathore <madhavendra.rathore@databricks.com>
…DI seam, packaging, tests

Rebuilds native/sea against the merged kernel main (binding renamed
@databricks/sea-native -> @databricks/sql-kernel via kernel #82) and
addresses the /full-review findings on PR #380:

- C1: commit the napi-rs router (native/sea/index.js, un-ignored) + a
  prepack assertion so the publish tarball can never ship without it.
  Companion kernel fix (databricks-sql-kernel#93) corrects the base
  package name so the router require paths resolve.
- C2: drop the @sea-native tsconfig path alias; use a relative import
  so no unresolvable specifier leaks into the emitted .d.ts.
- C3/C11: error hints no longer name a 404-ing package; dlopen hint now
  includes the underlying dlerror string + concrete remediation.
- C4: document M0 = linux-x64-gnu-only scope + npm scope-lock note.
- C5: SeaNativeBinding = typeof import('../../native/sea') (no drift).
- C6: SeaNativeLoader is now a class with an injectable load seam;
  getSeaNative/tryGetSeaNative are thin process-global wrappers.
- C7: re-exports renamed Sea* to avoid colliding with Thrift types.
- C8: version.test.ts fails loud on the linux-x64 CI runner + shape
  checks; new loader.test.ts covers the hint branches, Node gate,
  shape check, and caching via the injected seam.
- C9: Node-version guard fails closed (NaN or < floor).
- C13: e2e smoke uses the shared tests/e2e/utils/config.ts creds.
- C10/C12 are resolved upstream in merged kernel main / deferred to M1.

index.d.ts regenerated from merged main: ExecuteOptions dropped
(catalog/schema/sessionConf are session-level on openSession),
close() awaits DeleteSession, schema() is sync, sessionId/statementId
getters added.

Verified: 11 unit tests; e2e SELECT 1 against a live warehouse, direct
and through mitmproxy (SEA REST: POST /sql/sessions -> POST
/sql/statements -> DELETE /sql/sessions/<id>).

Co-authored-by: Isaac
Signed-off-by: Madhavendra Rathore <madhavendra.rathore@databricks.com>
…until binding ships

CI was red on every job at `npm ci` (EUSAGE: "Missing @napi-rs/cli@2.18.4
from lock file") — package.json added @napi-rs/cli (build:native devDep) and
the @databricks/sql-kernel-linux-x64-gnu optional dep, but package-lock.json
was never regenerated. Updated the lock (the unpublished optional dep is
recorded as optional, so `npm ci` tolerates/skips it).

Also: the version smoke test fail-louded when the binding was absent on a
linux-x64 CI runner, assuming the optional dep installs there. It doesn't yet
— the @databricks/sql-kernel-* packages aren't published and the standard CI
doesn't run build:native — so the fail-loud was spurious. Gate it behind
SEA_NATIVE_EXPECTED=1 (set once a CI step provisions the binding); default to
skip. The e2e smoke test already skips when the binding is absent.

Co-authored-by: Isaac
Signed-off-by: Madhavendra Rathore <madhavendra.rathore@databricks.com>
`@databricks/sql-kernel-linux-x64-gnu@0.1.0` is not published yet, so the
lockfile recorded it with no resolved version and `npm ci` rejected the
mismatch ("lock file's @databricks/sql-kernel-linux-x64-gnu@undefined does
not satisfy @0.1.0") — npm ci does NOT silently skip a pinned-but-
unresolvable optional dependency. Remove it from optionalDependencies until
the per-triple binding packages are actually published; the loader already
handles an absent binding (and version.test skips unless SEA_NATIVE_EXPECTED
is set). Re-add the optional deps once the `@databricks/sql-kernel-*`
packages ship.

Co-authored-by: Isaac
Signed-off-by: Madhavendra Rathore <madhavendra.rathore@databricks.com>
The unit-test matrix spans Node 14–20, but SeaNativeLoader's version gate
read the live `process.version` before the injected `load` seam ran. On the
14 and 16 runners every "successful load" / "load-failure hints" / "shape
check" test hit `requires Node >=18` instead of the path it asserted (7
failures per job). Make Node-major detection a second injectable ctor seam
(default = live process.version), inject a supported major in the load-path
tests, and inject the version-under-test in the gate's own tests (no more
mutating process.version). Tests now pass identically on every matrix Node.

Co-authored-by: Isaac
Signed-off-by: Madhavendra Rathore <madhavendra.rathore@databricks.com>
Two CI failures, both unrelated to driver behavior:

1. unit-test/lint/e2e intermittently failed at `npm ci` with ECONNRESET
   fetching @napi-rs/cli@2.18.4 from the internal npm proxy (cold-cache
   matrix jobs; the warm-cache node-14 job kept passing). @napi-rs/cli is
   only used by `build:native`, which CI never runs. Move it from
   devDependencies to optionalDependencies — matching the existing lz4
   pattern — so a proxy hiccup is a non-fatal skip instead of failing the
   whole install. `build:native`'s `npx --no-install` still resolves it on
   dev machines where the optional install succeeds.

2. prettier flagged loader.test.ts: the two-arg `new SeaNativeLoader(cb, fn)`
   calls needed multi-line formatting. Ran prettier --write.

Co-authored-by: Isaac
Signed-off-by: Madhavendra Rathore <madhavendra.rathore@databricks.com>
@msrathore-db msrathore-db merged commit 334db7c into main Jun 1, 2026
8 checks passed
msrathore-db added a commit that referenced this pull request Jun 1, 2026
#380 (napi binding) and #378 (backend abstraction) are squash-merged on
main, and main's abstraction evolved past this branch's early fork (neutral
IOperationBackendWaitOptions, hasResultSet() method, isClosed seam,
dataProvider, telemetry mappers, relocated wireSynthesis). Resolution:

- Facade / abstraction / thrift / test-stubs -> main (authoritative, evolved):
  DBSQLOperation, DBSQLSession, DBSQLClient, IOperationBackend,
  ThriftOperationBackend, createOperationForTest, createSessionForTest.
- SeaBackend -> branch (real impl; main only had the NOT_IMPLEMENTED stub).
- native/sea/* -> branch (full kernel binding surface the SEA code needs).
- Loader files (SeaNativeLoader, loader.test, version.test) -> main (final
  CI fixes: injectable node-version seam, prettier, version gating).
- package.json optionalDeps -> main (lz4 + @napi-rs/cli optional; dropped
  the unpublished sql-kernel pin); @napi-rs/cli removed from devDeps.

SEA implementers still need conformance to main's neutral abstraction
(follow-up commit).

Co-authored-by: Isaac
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