feat(nodejs): add JSON field helper (#4082)

## Issue

Fixes #4063

## Background

The Node.js SDK currently requires callers to know the Arrow extension
metadata needed to represent JSON fields. This makes a common LanceDB
schema type unnecessarily verbose and easy to get wrong.

## Changes

- Add `makeJsonField(name, nullable = true)` to create a UTF-8 Arrow
field with the `arrow.json` extension metadata.
- Re-export the helper from the public Node.js entry point.
- Add coverage for the default nullable behavior, explicit non-nullable
fields, and the extension metadata.
- Add the generated TypeDoc function page and public globals entry,
including a usage example.

## Implementation

The helper uses the existing Apache Arrow `Field` type and sets
`ARROW:extension:name` to `arrow.json`, matching the metadata convention
already used by LanceDB.

## Compatibility

This is an additive Node.js API. Existing schema construction and Arrow
behavior are unchanged.

## Verification

- `pnpm test -- arrow.test.ts --runInBand` — 236 tests passed.
- `pnpm exec biome ci lancedb/arrow.ts lancedb/index.ts
__test__/arrow.test.ts` — passed.
- `git diff --check` — passed.

## Not run / known limitations

- `pnpm build` and `pnpm run docs` were attempted after expanding the
checkout. Both are blocked locally by the native binding build/type
declarations: Cargo did not complete, and TypeDoc reported the missing
generated `nodejs/lancedb/native` module. The docs files were generated
from the updated TypeScript comments; full build and docs validation are
left to CI.
This commit is contained in:
mikemikimike
2026-09-15 18:01:42 -07:00
committed by GitHub
parent 3a1d3be256
commit be3215a6ae
5 changed files with 78 additions and 0 deletions
+36
View File
@@ -0,0 +1,36 @@
[**@lancedb/lancedb**](../README.md) • **Docs**
***
[@lancedb/lancedb](../globals.md) / makeJsonField
# Function: makeJsonField()
```ts
function makeJsonField(name, nullable): Field
```
Create an Arrow field backed by LanceDB's JSON extension type.
## Parameters
* **name**: `string`
The field name.
* **nullable**: `boolean` = `true`
Whether the field accepts null values.
## Returns
`Field`
## Example
```ts
import { connect, makeJsonField } from "@lancedb/lancedb";
import { Schema } from "apache-arrow";
const schema = new Schema([makeJsonField("metadata")]);
const db = await connect("/path/to/database");
await db.createTable("items", [{ metadata: '{"source":"api"}' }], { schema });
```
+1
View File
@@ -170,6 +170,7 @@
- [instrumentLanceDbMetrics](functions/instrumentLanceDbMetrics.md)
- [isBlobField](functions/isBlobField.md)
- [makeArrowTable](functions/makeArrowTable.md)
- [makeJsonField](functions/makeJsonField.md)
- [packBits](functions/packBits.md)
- [permutationBuilder](functions/permutationBuilder.md)
- [tokenize](functions/tokenize.md)
+16
View File
@@ -20,6 +20,7 @@ import {
fromTableToBuffer,
makeArrowTable,
makeEmptyTable,
makeJsonField,
} from "../lancedb/arrow";
import {
EmbeddingFunction,
@@ -28,6 +29,21 @@ import {
import { EmbeddingFunctionConfig } from "../lancedb/embedding/registry";
import { sanitizeTable } from "../lancedb/sanitize";
it("creates a nullable JSON field with the Arrow extension metadata", () => {
const field = makeJsonField("metadata");
expect(field.name).toBe("metadata");
expect(field.type).toEqual(new arrow15.Utf8());
expect(field.nullable).toBe(true);
expect(field.metadata).toEqual(
new Map([["ARROW:extension:name", "arrow.json"]]),
);
});
it("allows JSON fields to be non-nullable", () => {
expect(makeJsonField("metadata", false).nullable).toBe(false);
});
// biome-ignore lint/suspicious/noExplicitAny: skip
function sampleRecords(): Array<Record<string, any>> {
return [
+24
View File
@@ -72,6 +72,30 @@ export type FieldLike =
metadata?: Map<string, string>;
};
/**
* Create an Arrow field backed by LanceDB's JSON extension type.
*
* @param name - The field name.
* @param nullable - Whether the field accepts null values.
* @example
* ```ts
* import { connect, makeJsonField } from "@lancedb/lancedb";
* import { Schema } from "apache-arrow";
*
* const schema = new Schema([makeJsonField("metadata")]);
* const db = await connect("/path/to/database");
* await db.createTable("items", [{ metadata: '{"source":"api"}' }], { schema });
* ```
*/
export function makeJsonField(name: string, nullable = true): Field {
return new Field(
name,
new Utf8(),
nullable,
new Map([["ARROW:extension:name", "arrow.json"]]),
);
}
export type DataLike =
| import("apache-arrow").Data
| {
+1
View File
@@ -72,6 +72,7 @@ export {
export {
makeArrowTable,
makeJsonField,
MakeArrowTableOptions,
Data,
VectorColumnOptions,