Brendan Clement
|
9330a9b851
|
feat(nodejs): expose connectNamespace for namespace-backed connections (#3383)
### Summary
Adds a `connectNamespace(implName, properties, options?)` to the NodeJS
SDK`. Closes #3380.
### Testing
- pnpm test
- Ran smoke test
```
import { connectNamespace } from "lancedb"
import { tmpdir } from "os";
import { mkdtempSync } from "fs";
import { join } from "path";
const dir = mkdtempSync(join(tmpdir(), "lancedb-connect-namespace-smoke-"));
console.log(`Using temp dir: ${dir}\n`);
// 1. Happy path: connect via the "dir" namespace impl, create + list a table.
console.log('Connecting via connectNamespace("dir", { root })...');
const db = await connectNamespace("dir", { root: dir });
console.log(" ✓ connected:", db.display());
console.log("Creating a table and listing it...");
await db.createTable("users", [
{ id: 1, name: "alice" },
{ id: 2, name: "bob" },
]);
console.log(" ✓ tableNames ->", await db.tableNames());
const table = await db.openTable("users");
console.log(" ✓ users.countRows ->", await table.countRows());
// 2. Storage options pass-through.
console.log("\nReconnecting with storageOptions (plumbing check)...");
const dbWithOpts = await connectNamespace(
"dir",
{ root: dir },
{ storageOptions: { newTableDataStorageVersion: "stable" } },
);
console.log(" ✓ connected with storageOptions:", dbWithOpts.display());
await dbWithOpts.close();
// 3. Empty implName -> clear error.
console.log("\nCalling connectNamespace('', {}) (expect error)...");
try {
await connectNamespace("", {});
console.error(" UNEXPECTED: empty implName did not throw");
} catch (err) {
console.log(` ✓ Got expected error: ${err.message.split("\n")[0]}`);
}
// 4. Unknown impl -> error.
console.log("\nCalling connectNamespace('not-a-real-impl', {}) (expect error)...");
try {
await connectNamespace("not-a-real-impl", {});
console.error(" UNEXPECTED: unknown impl did not throw");
} catch (err) {
console.log(` ✓ Got expected error: ${err.message.split("\n")[0]}`);
}
// 5. Create a table inside a child namespace, then reconnect with a fresh
// connectNamespace call and confirm the table is reachable via that
// namespace path. (The dir+manifest impl keeps the namespace hierarchy in
// a root manifest, so "scoping" happens via namespacePath args, not by
// pointing root at a subdir.)
console.log("\nCreating a table inside a child namespace...");
const dir2 = mkdtempSync(join(tmpdir(), "lancedb-connect-namespace-smoke-"));
const writer = await connectNamespace("dir", {
root: dir2,
manifest_enabled: "true",
});
await writer.createNamespace(["analytics"]);
await writer.createTable(
"orders",
[
{ id: 1, total: 10 },
{ id: 2, total: 20 },
],
["analytics"],
);
console.log(
" ✓ writer sees tables under [analytics] ->",
await writer.tableNames(["analytics"]),
);
await writer.close();
console.log("Reconnecting and reading the table via its namespace path...");
const reader = await connectNamespace("dir", {
root: dir2,
manifest_enabled: "true",
});
console.log(
" ✓ reader tableNames(['analytics']) ->",
await reader.tableNames(["analytics"]),
);
const orders = await reader.openTable("orders", ["analytics"]);
console.log(" ✓ orders.countRows via reader ->", await orders.countRows());
await reader.close();
await db.close();
console.log("\nAll checks passed.");
```
```
Using temp dir: /var/folders/bj/hn6jv9c50y301d1nx0y8xmn00000gn/T/lancedb-connect-namespace-smoke-WByF1P
Connecting via connectNamespace("dir", { root })...
✓ connected: LanceNamespaceDatabase
Creating a table and listing it...
✓ tableNames -> [ 'users' ]
✓ users.countRows -> 2
Reconnecting with storageOptions (plumbing check)...
✓ connected with storageOptions: LanceNamespaceDatabase
Calling connectNamespace('', {}) (expect error)...
✓ Got expected error: implName must be a non-empty string
Calling connectNamespace('not-a-real-impl', {}) (expect error)...
✓ Got expected error: Invalid input, Failed to connect to namespace: Namespace { source: Unsupported { message: "Implementation 'not-a-real-impl' is not available. Supported: dir, rest" }, location: Location { file: "/Users/brendan/.cargo/git/checkouts/lance-8ddea23c38163eda/f693245/rust/lance-namespace-impls/src/connect.rs", line: 216, column: 14 } }
Creating a table inside a child namespace...
✓ writer sees tables under [analytics] -> [ 'orders' ]
Reconnecting and reading the table via its namespace path...
✓ reader tableNames(['analytics']) -> [ 'orders' ]
✓ orders.countRows via reader -> 2
All checks passed.
```
### Docs
- regenerated docs
|
2026-05-13 16:16:56 -07:00 |
|