Skip to content

Commit d7b7d13

Browse files
committed
update schema
1 parent 8bfca71 commit d7b7d13

7 files changed

Lines changed: 257 additions & 51 deletions

File tree

CHANGELOG.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,43 @@
11
# Changelog
22

33
All notable changes to this project will be documented in this file.
4+
5+
## [0.1.0] - 2025-12-17
6+
7+
### Breaking Changes
8+
9+
- **Renamed class**: `NextrowsClient``Nextrows`
10+
- **Changed constructor signature**: Now accepts an options object instead of positional arguments
11+
```typescript
12+
// Before
13+
const client = new NextrowsClient("api-key");
14+
const client = new NextrowsClient("api-key", { timeout: 60000 });
15+
16+
// After
17+
const client = new Nextrows({ apiKey: "api-key" });
18+
const client = new Nextrows({ apiKey: "api-key", timeout: 60000 });
19+
```
20+
- **Renamed interface**: `NextrowsClientOptions``NextrowsOptions`
21+
22+
### Added
23+
24+
- **Zod schema support**: The `extract` method now accepts Zod schemas in addition to JSON Schema objects (requires Zod 3.24+)
25+
```typescript
26+
import { z } from "zod/v4";
27+
28+
const schema = z.array(z.object({
29+
name: z.string(),
30+
price: z.number()
31+
}));
32+
33+
const result = await client.extract({
34+
type: "url",
35+
data: ["https://example.com"],
36+
schema: schema,
37+
});
38+
```
39+
- Added `JsonSchema` type export for explicit JSON Schema typing
40+
41+
## [0.0.5] and earlier
42+
43+
Initial releases with basic API client functionality.

README.md

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,9 @@ bun add @wordbricks/nextrows-client
3737
## Quick Start
3838

3939
```typescript
40-
import { NextrowsClient } from "@wordbricks/nextrows-client";
40+
import { Nextrows } from "@wordbricks/nextrows-client";
4141

42-
const client = new NextrowsClient("sk-nr-your-api-key");
42+
const client = new Nextrows({ apiKey: "sk-nr-your-api-key" });
4343
```
4444

4545
## API Methods
@@ -60,6 +60,27 @@ if (result.success) {
6060
}
6161
```
6262

63+
#### Using Zod Schema
64+
65+
You can use Zod schemas to define the extraction output structure (requires Zod 3.24+):
66+
67+
```typescript
68+
import { z } from "zod/v4";
69+
70+
const productSchema = z.array(
71+
z.object({
72+
name: z.string(),
73+
price: z.number(),
74+
})
75+
);
76+
77+
const result = await client.extract({
78+
type: "url",
79+
data: ["https://example.com/products"],
80+
schema: productSchema,
81+
});
82+
```
83+
6384
### Run App
6485

6586
Run a published NextRows app and get JSON output.
@@ -96,7 +117,8 @@ if (result.success && result.data) {
96117
## Configuration
97118

98119
```typescript
99-
const client = new NextrowsClient("sk-nr-your-api-key", {
120+
const client = new Nextrows({
121+
apiKey: "sk-nr-your-api-key",
100122
baseUrl: "https://api.nextrows.com", // default
101123
timeout: 30000, // default, in milliseconds
102124
});
@@ -107,3 +129,4 @@ const client = new NextrowsClient("sk-nr-your-api-key", {
107129
- **Fully Typed**: All request and response types are exported for TypeScript support
108130
- **Simple API**: Easy-to-use methods that mirror the REST API
109131
- **Configurable**: Custom base URL and timeout options
132+
- **Zod Support**: Use Zod schemas for type-safe extraction (optional, requires Zod 3.24+)

package-lock.json

Lines changed: 22 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@wordbricks/nextrows-client",
3-
"version": "0.0.5",
3+
"version": "0.1.0",
44
"repository": {
55
"type": "git",
66
"url": "https://github.com/wordbricks/nextrows-client"
@@ -32,7 +32,16 @@
3232
"dependencies": {
3333
"axios": "^1.13.2"
3434
},
35+
"peerDependencies": {
36+
"zod": "^3.24.0"
37+
},
38+
"peerDependenciesMeta": {
39+
"zod": {
40+
"optional": true
41+
}
42+
},
3543
"devDependencies": {
44+
"zod": "^3.25.67",
3645
"@biomejs/biome": "2.3.8",
3746
"@types/node": "^25.0.1",
3847
"concurrently": "9.2.1",

src/api/extract.ts

Lines changed: 88 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type { AxiosInstance } from "axios";
2+
import type { ZodType } from "zod";
23

34
/**
45
* The type of data source to extract from.
@@ -9,20 +10,18 @@ export type ExtractType = "url" | "text";
910

1011
/**
1112
* JSON Schema definition for structured extraction output.
12-
* Must conform to JSON Schema specification.
13+
*/
14+
export interface JsonSchema {
15+
[key: string]: unknown;
16+
}
17+
18+
/**
19+
* Schema for structured extraction output.
20+
* Can be either a JSON Schema object or a Zod schema.
1321
*
1422
* @example
1523
* ```typescript
16-
* // Schema for extracting a table as 2D array
17-
* const schema: ExtractSchema = {
18-
* type: "array",
19-
* items: {
20-
* type: "array",
21-
* items: { type: "string" }
22-
* }
23-
* };
24-
*
25-
* // Schema for extracting product objects
24+
* // Using JSON Schema
2625
* const schema: ExtractSchema = {
2726
* type: "array",
2827
* items: {
@@ -33,10 +32,62 @@ export type ExtractType = "url" | "text";
3332
* }
3433
* }
3534
* };
35+
*
36+
* // Using Zod schema (requires Zod 3.24+)
37+
* import { z } from "zod/v4";
38+
*
39+
* const schema = z.array(z.object({
40+
* name: z.string(),
41+
* price: z.number()
42+
* }));
3643
* ```
3744
*/
38-
export interface ExtractSchema {
39-
[key: string]: unknown;
45+
export type ExtractSchema = JsonSchema | ZodType;
46+
47+
/**
48+
* Check if a value is a Zod schema.
49+
*/
50+
function isZodSchema(schema: ExtractSchema): schema is ZodType {
51+
return (
52+
schema !== null &&
53+
typeof schema === "object" &&
54+
"_def" in schema &&
55+
"safeParse" in schema &&
56+
typeof (schema as ZodType).safeParse === "function"
57+
);
58+
}
59+
60+
// Cache the zod module to avoid repeated dynamic imports
61+
let zodModule: { toJSONSchema?: (schema: ZodType) => JsonSchema } | null = null;
62+
63+
/**
64+
* Convert a schema to JSON Schema format.
65+
* If the schema is a Zod schema, it will be converted using Zod's toJSONSchema().
66+
*/
67+
async function convertToJsonSchema(schema: ExtractSchema): Promise<JsonSchema> {
68+
if (isZodSchema(schema)) {
69+
// Try to use cached zod module first
70+
if (zodModule?.toJSONSchema) {
71+
return zodModule.toJSONSchema(schema);
72+
}
73+
74+
// Dynamically import zod/v4 (works in both ESM and CJS environments)
75+
try {
76+
const z = await import("zod/v4");
77+
if (z && typeof z.toJSONSchema === "function") {
78+
zodModule = z;
79+
return z.toJSONSchema(schema) as JsonSchema;
80+
}
81+
} catch {
82+
// import failed, zod/v4 not available
83+
}
84+
85+
throw new Error(
86+
"Zod schema conversion requires Zod 3.24+ with zod/v4 subpath. " +
87+
"Please install Zod 3.24+ or use a JSON Schema object directly.",
88+
);
89+
}
90+
return schema;
4091
}
4192

4293
/**
@@ -69,21 +120,30 @@ export interface ExtractRequest {
69120
prompt?: string;
70121

71122
/**
72-
* Optional JSON Schema for consistent and predictable extraction results.
123+
* Optional schema for consistent and predictable extraction results.
124+
* Can be a JSON Schema object or a Zod schema (requires Zod 3.24+).
73125
* If not provided, the system will auto-generate the structure based on the data.
74126
*
75127
* @example
76-
* ```json
77-
* {
78-
* "type": "array",
79-
* "items": {
80-
* "type": "object",
81-
* "properties": {
82-
* "name": { "type": "string" },
83-
* "price": { "type": "number" }
128+
* ```typescript
129+
* // Using JSON Schema
130+
* schema: {
131+
* type: "array",
132+
* items: {
133+
* type: "object",
134+
* properties: {
135+
* name: { type: "string" },
136+
* price: { type: "number" }
84137
* }
85138
* }
86139
* }
140+
*
141+
* // Using Zod schema (requires Zod 3.24+)
142+
* import { z } from "zod/v4";
143+
* schema: z.array(z.object({
144+
* name: z.string(),
145+
* price: z.number()
146+
* }))
87147
* ```
88148
*/
89149
schema?: ExtractSchema;
@@ -151,6 +211,11 @@ export async function extract(
151211
client: AxiosInstance,
152212
request: ExtractRequest,
153213
): Promise<ExtractResponse> {
154-
const response = await client.post<ExtractResponse>("/v1/extract", request);
214+
// Convert Zod schema to JSON Schema if needed
215+
const payload = request.schema
216+
? { ...request, schema: await convertToJsonSchema(request.schema) }
217+
: request;
218+
219+
const response = await client.post<ExtractResponse>("/v1/extract", payload);
155220
return response.data;
156221
}

0 commit comments

Comments
 (0)