@mendable/firecrawl 4.11.2 → 4.11.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-GVCNL5KA.js → chunk-TLAC3APA.js} +1 -1
- package/dist/index.cjs +58 -89
- package/dist/index.js +60 -91
- package/dist/{package-LU5XQZAL.js → package-3BZQ6TAW.js} +1 -1
- package/package.json +1 -1
- package/src/__tests__/unit/v2/zodSchemaToJson.test.ts +107 -0
- package/src/utils/zodSchemaToJson.ts +67 -0
- package/src/v1/index.ts +10 -83
- package/src/v2/methods/agent.ts +2 -4
- package/src/v2/methods/extract.ts +2 -4
- package/src/v2/utils/validation.ts +7 -32
|
@@ -8,7 +8,7 @@ var require_package = __commonJS({
|
|
|
8
8
|
"package.json"(exports, module) {
|
|
9
9
|
module.exports = {
|
|
10
10
|
name: "@mendable/firecrawl-js",
|
|
11
|
-
version: "4.11.
|
|
11
|
+
version: "4.11.3",
|
|
12
12
|
description: "JavaScript SDK for Firecrawl API",
|
|
13
13
|
main: "dist/index.js",
|
|
14
14
|
types: "dist/index.d.ts",
|
package/dist/index.cjs
CHANGED
|
@@ -35,7 +35,7 @@ var require_package = __commonJS({
|
|
|
35
35
|
"package.json"(exports2, module2) {
|
|
36
36
|
module2.exports = {
|
|
37
37
|
name: "@mendable/firecrawl-js",
|
|
38
|
-
version: "4.11.
|
|
38
|
+
version: "4.11.3",
|
|
39
39
|
description: "JavaScript SDK for Firecrawl API",
|
|
40
40
|
main: "dist/index.js",
|
|
41
41
|
types: "dist/index.d.ts",
|
|
@@ -249,14 +249,54 @@ var JobTimeoutError = class extends SdkError {
|
|
|
249
249
|
}
|
|
250
250
|
};
|
|
251
251
|
|
|
252
|
-
// src/
|
|
252
|
+
// src/utils/zodSchemaToJson.ts
|
|
253
253
|
var import_zod_to_json_schema = require("zod-to-json-schema");
|
|
254
|
+
function isZodSchema(value) {
|
|
255
|
+
if (!value || typeof value !== "object") return false;
|
|
256
|
+
const schema = value;
|
|
257
|
+
const hasV3Markers = "_def" in schema && (typeof schema.safeParse === "function" || typeof schema.parse === "function");
|
|
258
|
+
const hasV4Markers = "_zod" in schema && typeof schema._zod === "object";
|
|
259
|
+
return hasV3Markers || hasV4Markers;
|
|
260
|
+
}
|
|
261
|
+
function isZodV4Schema(schema) {
|
|
262
|
+
if (!schema || typeof schema !== "object") return false;
|
|
263
|
+
return "_zod" in schema && typeof schema._zod === "object";
|
|
264
|
+
}
|
|
265
|
+
function tryZodV4Conversion(schema) {
|
|
266
|
+
if (!isZodV4Schema(schema)) return null;
|
|
267
|
+
try {
|
|
268
|
+
const zodModule = schema.constructor?.prototype?.constructor;
|
|
269
|
+
if (zodModule && typeof zodModule.toJSONSchema === "function") {
|
|
270
|
+
return zodModule.toJSONSchema(schema);
|
|
271
|
+
}
|
|
272
|
+
} catch {
|
|
273
|
+
}
|
|
274
|
+
return null;
|
|
275
|
+
}
|
|
276
|
+
function zodSchemaToJsonSchema(schema) {
|
|
277
|
+
if (!isZodSchema(schema)) {
|
|
278
|
+
return schema;
|
|
279
|
+
}
|
|
280
|
+
const v4Result = tryZodV4Conversion(schema);
|
|
281
|
+
if (v4Result) {
|
|
282
|
+
return v4Result;
|
|
283
|
+
}
|
|
284
|
+
try {
|
|
285
|
+
return (0, import_zod_to_json_schema.zodToJsonSchema)(schema);
|
|
286
|
+
} catch {
|
|
287
|
+
return schema;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
254
290
|
function looksLikeZodShape(obj) {
|
|
255
291
|
if (!obj || typeof obj !== "object" || Array.isArray(obj)) return false;
|
|
256
292
|
const values = Object.values(obj);
|
|
257
293
|
if (values.length === 0) return false;
|
|
258
|
-
return values.some(
|
|
294
|
+
return values.some(
|
|
295
|
+
(v) => v && typeof v === "object" && v._def && typeof v.safeParse === "function"
|
|
296
|
+
);
|
|
259
297
|
}
|
|
298
|
+
|
|
299
|
+
// src/v2/utils/validation.ts
|
|
260
300
|
function ensureValidFormats(formats) {
|
|
261
301
|
if (!formats) return;
|
|
262
302
|
for (const fmt of formats) {
|
|
@@ -272,12 +312,8 @@ function ensureValidFormats(formats) {
|
|
|
272
312
|
throw new Error("json format requires either 'prompt' or 'schema' (or both)");
|
|
273
313
|
}
|
|
274
314
|
const maybeSchema = j.schema;
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
try {
|
|
278
|
-
j.schema = (0, import_zod_to_json_schema.zodToJsonSchema)(maybeSchema);
|
|
279
|
-
} catch {
|
|
280
|
-
}
|
|
315
|
+
if (isZodSchema(maybeSchema)) {
|
|
316
|
+
j.schema = zodSchemaToJsonSchema(maybeSchema);
|
|
281
317
|
} else if (looksLikeZodShape(maybeSchema)) {
|
|
282
318
|
throw new Error(
|
|
283
319
|
"json format schema appears to be a Zod schema's .shape property. Pass the Zod schema directly (e.g., `schema: MySchema`) instead of `schema: MySchema.shape`. The SDK will automatically convert Zod schemas to JSON Schema format."
|
|
@@ -288,12 +324,8 @@ function ensureValidFormats(formats) {
|
|
|
288
324
|
if (fmt.type === "changeTracking") {
|
|
289
325
|
const ct = fmt;
|
|
290
326
|
const maybeSchema = ct.schema;
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
try {
|
|
294
|
-
ct.schema = (0, import_zod_to_json_schema.zodToJsonSchema)(maybeSchema);
|
|
295
|
-
} catch {
|
|
296
|
-
}
|
|
327
|
+
if (isZodSchema(maybeSchema)) {
|
|
328
|
+
ct.schema = zodSchemaToJsonSchema(maybeSchema);
|
|
297
329
|
} else if (looksLikeZodShape(maybeSchema)) {
|
|
298
330
|
throw new Error(
|
|
299
331
|
"changeTracking format schema appears to be a Zod schema's .shape property. Pass the Zod schema directly (e.g., `schema: MySchema`) instead of `schema: MySchema.shape`. The SDK will automatically convert Zod schemas to JSON Schema format."
|
|
@@ -780,15 +812,12 @@ async function batchScrape(http, urls, opts = {}) {
|
|
|
780
812
|
}
|
|
781
813
|
|
|
782
814
|
// src/v2/methods/extract.ts
|
|
783
|
-
var import_zod_to_json_schema2 = require("zod-to-json-schema");
|
|
784
815
|
function prepareExtractPayload(args) {
|
|
785
816
|
const body = {};
|
|
786
817
|
if (args.urls) body.urls = args.urls;
|
|
787
818
|
if (args.prompt != null) body.prompt = args.prompt;
|
|
788
819
|
if (args.schema != null) {
|
|
789
|
-
|
|
790
|
-
const isZod = s && (typeof s.safeParse === "function" || typeof s.parse === "function") && s._def;
|
|
791
|
-
body.schema = isZod ? (0, import_zod_to_json_schema2.zodToJsonSchema)(s) : args.schema;
|
|
820
|
+
body.schema = isZodSchema(args.schema) ? zodSchemaToJsonSchema(args.schema) : args.schema;
|
|
792
821
|
}
|
|
793
822
|
if (args.systemPrompt != null) body.systemPrompt = args.systemPrompt;
|
|
794
823
|
if (args.allowExternalLinks != null) body.allowExternalLinks = args.allowExternalLinks;
|
|
@@ -841,15 +870,12 @@ async function extract(http, args) {
|
|
|
841
870
|
}
|
|
842
871
|
|
|
843
872
|
// src/v2/methods/agent.ts
|
|
844
|
-
var import_zod_to_json_schema3 = require("zod-to-json-schema");
|
|
845
873
|
function prepareAgentPayload(args) {
|
|
846
874
|
const body = {};
|
|
847
875
|
if (args.urls) body.urls = args.urls;
|
|
848
876
|
body.prompt = args.prompt;
|
|
849
877
|
if (args.schema != null) {
|
|
850
|
-
|
|
851
|
-
const isZod = s && (typeof s.safeParse === "function" || typeof s.parse === "function") && s._def;
|
|
852
|
-
body.schema = isZod ? (0, import_zod_to_json_schema3.zodToJsonSchema)(s) : args.schema;
|
|
878
|
+
body.schema = isZodSchema(args.schema) ? zodSchemaToJsonSchema(args.schema) : args.schema;
|
|
853
879
|
}
|
|
854
880
|
if (args.integration && args.integration.trim()) body.integration = args.integration.trim();
|
|
855
881
|
if (args.maxCredits !== null && args.maxCredits !== void 0) body.maxCredits = args.maxCredits;
|
|
@@ -1437,7 +1463,6 @@ var FirecrawlClient = class {
|
|
|
1437
1463
|
// src/v1/index.ts
|
|
1438
1464
|
var import_axios3 = __toESM(require("axios"), 1);
|
|
1439
1465
|
var zt2 = require("zod");
|
|
1440
|
-
var import_zod_to_json_schema4 = require("zod-to-json-schema");
|
|
1441
1466
|
|
|
1442
1467
|
// node_modules/.pnpm/typescript-event-target@1.1.1/node_modules/typescript-event-target/dist/index.mjs
|
|
1443
1468
|
var e = class extends EventTarget {
|
|
@@ -1507,30 +1532,20 @@ var FirecrawlApp = class {
|
|
|
1507
1532
|
};
|
|
1508
1533
|
let jsonData = { url, ...params, origin: typeof params.origin === "string" && params.origin.includes("mcp") ? params.origin : `js-sdk@${this.version}` };
|
|
1509
1534
|
if (jsonData?.extract?.schema) {
|
|
1510
|
-
let schema = jsonData.extract.schema;
|
|
1511
|
-
try {
|
|
1512
|
-
schema = (0, import_zod_to_json_schema4.zodToJsonSchema)(schema);
|
|
1513
|
-
} catch (error) {
|
|
1514
|
-
}
|
|
1515
1535
|
jsonData = {
|
|
1516
1536
|
...jsonData,
|
|
1517
1537
|
extract: {
|
|
1518
1538
|
...jsonData.extract,
|
|
1519
|
-
schema
|
|
1539
|
+
schema: zodSchemaToJsonSchema(jsonData.extract.schema)
|
|
1520
1540
|
}
|
|
1521
1541
|
};
|
|
1522
1542
|
}
|
|
1523
1543
|
if (jsonData?.jsonOptions?.schema) {
|
|
1524
|
-
let schema = jsonData.jsonOptions.schema;
|
|
1525
|
-
try {
|
|
1526
|
-
schema = (0, import_zod_to_json_schema4.zodToJsonSchema)(schema);
|
|
1527
|
-
} catch (error) {
|
|
1528
|
-
}
|
|
1529
1544
|
jsonData = {
|
|
1530
1545
|
...jsonData,
|
|
1531
1546
|
jsonOptions: {
|
|
1532
1547
|
...jsonData.jsonOptions,
|
|
1533
|
-
schema
|
|
1548
|
+
schema: zodSchemaToJsonSchema(jsonData.jsonOptions.schema)
|
|
1534
1549
|
}
|
|
1535
1550
|
};
|
|
1536
1551
|
}
|
|
@@ -1584,18 +1599,13 @@ var FirecrawlApp = class {
|
|
|
1584
1599
|
scrapeOptions: params?.scrapeOptions ?? { formats: [] }
|
|
1585
1600
|
};
|
|
1586
1601
|
if (jsonData?.scrapeOptions?.extract?.schema) {
|
|
1587
|
-
let schema = jsonData.scrapeOptions.extract.schema;
|
|
1588
|
-
try {
|
|
1589
|
-
schema = (0, import_zod_to_json_schema4.zodToJsonSchema)(schema);
|
|
1590
|
-
} catch (error) {
|
|
1591
|
-
}
|
|
1592
1602
|
jsonData = {
|
|
1593
1603
|
...jsonData,
|
|
1594
1604
|
scrapeOptions: {
|
|
1595
1605
|
...jsonData.scrapeOptions,
|
|
1596
1606
|
extract: {
|
|
1597
1607
|
...jsonData.scrapeOptions.extract,
|
|
1598
|
-
schema
|
|
1608
|
+
schema: zodSchemaToJsonSchema(jsonData.scrapeOptions.extract.schema)
|
|
1599
1609
|
}
|
|
1600
1610
|
}
|
|
1601
1611
|
};
|
|
@@ -1853,30 +1863,20 @@ var FirecrawlApp = class {
|
|
|
1853
1863
|
const headers = this.prepareHeaders(idempotencyKey);
|
|
1854
1864
|
let jsonData = { urls, webhook, ignoreInvalidURLs, maxConcurrency, ...params, origin: typeof params.origin === "string" && params.origin.includes("mcp") ? params.origin : `js-sdk@${this.version}` };
|
|
1855
1865
|
if (jsonData?.extract?.schema) {
|
|
1856
|
-
let schema = jsonData.extract.schema;
|
|
1857
|
-
try {
|
|
1858
|
-
schema = (0, import_zod_to_json_schema4.zodToJsonSchema)(schema);
|
|
1859
|
-
} catch (error) {
|
|
1860
|
-
}
|
|
1861
1866
|
jsonData = {
|
|
1862
1867
|
...jsonData,
|
|
1863
1868
|
extract: {
|
|
1864
1869
|
...jsonData.extract,
|
|
1865
|
-
schema
|
|
1870
|
+
schema: zodSchemaToJsonSchema(jsonData.extract.schema)
|
|
1866
1871
|
}
|
|
1867
1872
|
};
|
|
1868
1873
|
}
|
|
1869
1874
|
if (jsonData?.jsonOptions?.schema) {
|
|
1870
|
-
let schema = jsonData.jsonOptions.schema;
|
|
1871
|
-
try {
|
|
1872
|
-
schema = (0, import_zod_to_json_schema4.zodToJsonSchema)(schema);
|
|
1873
|
-
} catch (error) {
|
|
1874
|
-
}
|
|
1875
1875
|
jsonData = {
|
|
1876
1876
|
...jsonData,
|
|
1877
1877
|
jsonOptions: {
|
|
1878
1878
|
...jsonData.jsonOptions,
|
|
1879
|
-
schema
|
|
1879
|
+
schema: zodSchemaToJsonSchema(jsonData.jsonOptions.schema)
|
|
1880
1880
|
}
|
|
1881
1881
|
};
|
|
1882
1882
|
}
|
|
@@ -2042,20 +2042,7 @@ var FirecrawlApp = class {
|
|
|
2042
2042
|
async extract(urls, params) {
|
|
2043
2043
|
const headers = this.prepareHeaders();
|
|
2044
2044
|
let jsonData = { urls, ...params };
|
|
2045
|
-
|
|
2046
|
-
try {
|
|
2047
|
-
if (!params?.schema) {
|
|
2048
|
-
jsonSchema = void 0;
|
|
2049
|
-
} else {
|
|
2050
|
-
try {
|
|
2051
|
-
jsonSchema = (0, import_zod_to_json_schema4.zodToJsonSchema)(params.schema);
|
|
2052
|
-
} catch (_) {
|
|
2053
|
-
jsonSchema = params.schema;
|
|
2054
|
-
}
|
|
2055
|
-
}
|
|
2056
|
-
} catch (error) {
|
|
2057
|
-
throw new FirecrawlError("Invalid schema. Schema must be either a valid Zod schema or JSON schema object.", 400);
|
|
2058
|
-
}
|
|
2045
|
+
const jsonSchema = params?.schema ? zodSchemaToJsonSchema(params.schema) : void 0;
|
|
2059
2046
|
try {
|
|
2060
2047
|
const response = await this.postRequest(
|
|
2061
2048
|
this.apiUrl + `/v1/extract`,
|
|
@@ -2105,21 +2092,8 @@ var FirecrawlApp = class {
|
|
|
2105
2092
|
*/
|
|
2106
2093
|
async asyncExtract(urls, params, idempotencyKey) {
|
|
2107
2094
|
const headers = this.prepareHeaders(idempotencyKey);
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
try {
|
|
2111
|
-
if (!params?.schema) {
|
|
2112
|
-
jsonSchema = void 0;
|
|
2113
|
-
} else {
|
|
2114
|
-
try {
|
|
2115
|
-
jsonSchema = (0, import_zod_to_json_schema4.zodToJsonSchema)(params.schema);
|
|
2116
|
-
} catch (_) {
|
|
2117
|
-
jsonSchema = params.schema;
|
|
2118
|
-
}
|
|
2119
|
-
}
|
|
2120
|
-
} catch (error) {
|
|
2121
|
-
throw new FirecrawlError("Invalid schema. Schema must be either a valid Zod schema or JSON schema object.", 400);
|
|
2122
|
-
}
|
|
2095
|
+
const jsonData = { urls, ...params };
|
|
2096
|
+
const jsonSchema = params?.schema ? zodSchemaToJsonSchema(params.schema) : void 0;
|
|
2123
2097
|
try {
|
|
2124
2098
|
const response = await this.postRequest(
|
|
2125
2099
|
this.apiUrl + `/v1/extract`,
|
|
@@ -2401,16 +2375,11 @@ var FirecrawlApp = class {
|
|
|
2401
2375
|
const headers = this.prepareHeaders();
|
|
2402
2376
|
let jsonData = { query, ...params, origin: typeof params.origin === "string" && params.origin.includes("mcp") ? params.origin : `js-sdk@${this.version}` };
|
|
2403
2377
|
if (jsonData?.jsonOptions?.schema) {
|
|
2404
|
-
let schema = jsonData.jsonOptions.schema;
|
|
2405
|
-
try {
|
|
2406
|
-
schema = (0, import_zod_to_json_schema4.zodToJsonSchema)(schema);
|
|
2407
|
-
} catch (error) {
|
|
2408
|
-
}
|
|
2409
2378
|
jsonData = {
|
|
2410
2379
|
...jsonData,
|
|
2411
2380
|
jsonOptions: {
|
|
2412
2381
|
...jsonData.jsonOptions,
|
|
2413
|
-
schema
|
|
2382
|
+
schema: zodSchemaToJsonSchema(jsonData.jsonOptions.schema)
|
|
2414
2383
|
}
|
|
2415
2384
|
};
|
|
2416
2385
|
}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
require_package
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-TLAC3APA.js";
|
|
4
4
|
|
|
5
5
|
// src/v2/utils/httpClient.ts
|
|
6
6
|
import axios from "axios";
|
|
@@ -130,14 +130,54 @@ var JobTimeoutError = class extends SdkError {
|
|
|
130
130
|
}
|
|
131
131
|
};
|
|
132
132
|
|
|
133
|
-
// src/
|
|
134
|
-
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
133
|
+
// src/utils/zodSchemaToJson.ts
|
|
134
|
+
import { zodToJsonSchema as zodToJsonSchemaLib } from "zod-to-json-schema";
|
|
135
|
+
function isZodSchema(value) {
|
|
136
|
+
if (!value || typeof value !== "object") return false;
|
|
137
|
+
const schema = value;
|
|
138
|
+
const hasV3Markers = "_def" in schema && (typeof schema.safeParse === "function" || typeof schema.parse === "function");
|
|
139
|
+
const hasV4Markers = "_zod" in schema && typeof schema._zod === "object";
|
|
140
|
+
return hasV3Markers || hasV4Markers;
|
|
141
|
+
}
|
|
142
|
+
function isZodV4Schema(schema) {
|
|
143
|
+
if (!schema || typeof schema !== "object") return false;
|
|
144
|
+
return "_zod" in schema && typeof schema._zod === "object";
|
|
145
|
+
}
|
|
146
|
+
function tryZodV4Conversion(schema) {
|
|
147
|
+
if (!isZodV4Schema(schema)) return null;
|
|
148
|
+
try {
|
|
149
|
+
const zodModule = schema.constructor?.prototype?.constructor;
|
|
150
|
+
if (zodModule && typeof zodModule.toJSONSchema === "function") {
|
|
151
|
+
return zodModule.toJSONSchema(schema);
|
|
152
|
+
}
|
|
153
|
+
} catch {
|
|
154
|
+
}
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
function zodSchemaToJsonSchema(schema) {
|
|
158
|
+
if (!isZodSchema(schema)) {
|
|
159
|
+
return schema;
|
|
160
|
+
}
|
|
161
|
+
const v4Result = tryZodV4Conversion(schema);
|
|
162
|
+
if (v4Result) {
|
|
163
|
+
return v4Result;
|
|
164
|
+
}
|
|
165
|
+
try {
|
|
166
|
+
return zodToJsonSchemaLib(schema);
|
|
167
|
+
} catch {
|
|
168
|
+
return schema;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
135
171
|
function looksLikeZodShape(obj) {
|
|
136
172
|
if (!obj || typeof obj !== "object" || Array.isArray(obj)) return false;
|
|
137
173
|
const values = Object.values(obj);
|
|
138
174
|
if (values.length === 0) return false;
|
|
139
|
-
return values.some(
|
|
175
|
+
return values.some(
|
|
176
|
+
(v) => v && typeof v === "object" && v._def && typeof v.safeParse === "function"
|
|
177
|
+
);
|
|
140
178
|
}
|
|
179
|
+
|
|
180
|
+
// src/v2/utils/validation.ts
|
|
141
181
|
function ensureValidFormats(formats) {
|
|
142
182
|
if (!formats) return;
|
|
143
183
|
for (const fmt of formats) {
|
|
@@ -153,12 +193,8 @@ function ensureValidFormats(formats) {
|
|
|
153
193
|
throw new Error("json format requires either 'prompt' or 'schema' (or both)");
|
|
154
194
|
}
|
|
155
195
|
const maybeSchema = j.schema;
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
try {
|
|
159
|
-
j.schema = zodToJsonSchema(maybeSchema);
|
|
160
|
-
} catch {
|
|
161
|
-
}
|
|
196
|
+
if (isZodSchema(maybeSchema)) {
|
|
197
|
+
j.schema = zodSchemaToJsonSchema(maybeSchema);
|
|
162
198
|
} else if (looksLikeZodShape(maybeSchema)) {
|
|
163
199
|
throw new Error(
|
|
164
200
|
"json format schema appears to be a Zod schema's .shape property. Pass the Zod schema directly (e.g., `schema: MySchema`) instead of `schema: MySchema.shape`. The SDK will automatically convert Zod schemas to JSON Schema format."
|
|
@@ -169,12 +205,8 @@ function ensureValidFormats(formats) {
|
|
|
169
205
|
if (fmt.type === "changeTracking") {
|
|
170
206
|
const ct = fmt;
|
|
171
207
|
const maybeSchema = ct.schema;
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
try {
|
|
175
|
-
ct.schema = zodToJsonSchema(maybeSchema);
|
|
176
|
-
} catch {
|
|
177
|
-
}
|
|
208
|
+
if (isZodSchema(maybeSchema)) {
|
|
209
|
+
ct.schema = zodSchemaToJsonSchema(maybeSchema);
|
|
178
210
|
} else if (looksLikeZodShape(maybeSchema)) {
|
|
179
211
|
throw new Error(
|
|
180
212
|
"changeTracking format schema appears to be a Zod schema's .shape property. Pass the Zod schema directly (e.g., `schema: MySchema`) instead of `schema: MySchema.shape`. The SDK will automatically convert Zod schemas to JSON Schema format."
|
|
@@ -661,15 +693,12 @@ async function batchScrape(http, urls, opts = {}) {
|
|
|
661
693
|
}
|
|
662
694
|
|
|
663
695
|
// src/v2/methods/extract.ts
|
|
664
|
-
import { zodToJsonSchema as zodToJsonSchema2 } from "zod-to-json-schema";
|
|
665
696
|
function prepareExtractPayload(args) {
|
|
666
697
|
const body = {};
|
|
667
698
|
if (args.urls) body.urls = args.urls;
|
|
668
699
|
if (args.prompt != null) body.prompt = args.prompt;
|
|
669
700
|
if (args.schema != null) {
|
|
670
|
-
|
|
671
|
-
const isZod = s && (typeof s.safeParse === "function" || typeof s.parse === "function") && s._def;
|
|
672
|
-
body.schema = isZod ? zodToJsonSchema2(s) : args.schema;
|
|
701
|
+
body.schema = isZodSchema(args.schema) ? zodSchemaToJsonSchema(args.schema) : args.schema;
|
|
673
702
|
}
|
|
674
703
|
if (args.systemPrompt != null) body.systemPrompt = args.systemPrompt;
|
|
675
704
|
if (args.allowExternalLinks != null) body.allowExternalLinks = args.allowExternalLinks;
|
|
@@ -722,15 +751,12 @@ async function extract(http, args) {
|
|
|
722
751
|
}
|
|
723
752
|
|
|
724
753
|
// src/v2/methods/agent.ts
|
|
725
|
-
import { zodToJsonSchema as zodToJsonSchema3 } from "zod-to-json-schema";
|
|
726
754
|
function prepareAgentPayload(args) {
|
|
727
755
|
const body = {};
|
|
728
756
|
if (args.urls) body.urls = args.urls;
|
|
729
757
|
body.prompt = args.prompt;
|
|
730
758
|
if (args.schema != null) {
|
|
731
|
-
|
|
732
|
-
const isZod = s && (typeof s.safeParse === "function" || typeof s.parse === "function") && s._def;
|
|
733
|
-
body.schema = isZod ? zodToJsonSchema3(s) : args.schema;
|
|
759
|
+
body.schema = isZodSchema(args.schema) ? zodSchemaToJsonSchema(args.schema) : args.schema;
|
|
734
760
|
}
|
|
735
761
|
if (args.integration && args.integration.trim()) body.integration = args.integration.trim();
|
|
736
762
|
if (args.maxCredits !== null && args.maxCredits !== void 0) body.maxCredits = args.maxCredits;
|
|
@@ -1318,7 +1344,6 @@ var FirecrawlClient = class {
|
|
|
1318
1344
|
// src/v1/index.ts
|
|
1319
1345
|
import axios2, { AxiosError } from "axios";
|
|
1320
1346
|
import "zod";
|
|
1321
|
-
import { zodToJsonSchema as zodToJsonSchema4 } from "zod-to-json-schema";
|
|
1322
1347
|
|
|
1323
1348
|
// node_modules/.pnpm/typescript-event-target@1.1.1/node_modules/typescript-event-target/dist/index.mjs
|
|
1324
1349
|
var e = class extends EventTarget {
|
|
@@ -1349,7 +1374,7 @@ var FirecrawlApp = class {
|
|
|
1349
1374
|
if (typeof process !== "undefined" && process.env && process.env.npm_package_version) {
|
|
1350
1375
|
return process.env.npm_package_version;
|
|
1351
1376
|
}
|
|
1352
|
-
const packageJson = await import("./package-
|
|
1377
|
+
const packageJson = await import("./package-3BZQ6TAW.js");
|
|
1353
1378
|
return packageJson.default.version;
|
|
1354
1379
|
} catch (error) {
|
|
1355
1380
|
const isTest = typeof process !== "undefined" && (process.env.JEST_WORKER_ID != null || false);
|
|
@@ -1388,30 +1413,20 @@ var FirecrawlApp = class {
|
|
|
1388
1413
|
};
|
|
1389
1414
|
let jsonData = { url, ...params, origin: typeof params.origin === "string" && params.origin.includes("mcp") ? params.origin : `js-sdk@${this.version}` };
|
|
1390
1415
|
if (jsonData?.extract?.schema) {
|
|
1391
|
-
let schema = jsonData.extract.schema;
|
|
1392
|
-
try {
|
|
1393
|
-
schema = zodToJsonSchema4(schema);
|
|
1394
|
-
} catch (error) {
|
|
1395
|
-
}
|
|
1396
1416
|
jsonData = {
|
|
1397
1417
|
...jsonData,
|
|
1398
1418
|
extract: {
|
|
1399
1419
|
...jsonData.extract,
|
|
1400
|
-
schema
|
|
1420
|
+
schema: zodSchemaToJsonSchema(jsonData.extract.schema)
|
|
1401
1421
|
}
|
|
1402
1422
|
};
|
|
1403
1423
|
}
|
|
1404
1424
|
if (jsonData?.jsonOptions?.schema) {
|
|
1405
|
-
let schema = jsonData.jsonOptions.schema;
|
|
1406
|
-
try {
|
|
1407
|
-
schema = zodToJsonSchema4(schema);
|
|
1408
|
-
} catch (error) {
|
|
1409
|
-
}
|
|
1410
1425
|
jsonData = {
|
|
1411
1426
|
...jsonData,
|
|
1412
1427
|
jsonOptions: {
|
|
1413
1428
|
...jsonData.jsonOptions,
|
|
1414
|
-
schema
|
|
1429
|
+
schema: zodSchemaToJsonSchema(jsonData.jsonOptions.schema)
|
|
1415
1430
|
}
|
|
1416
1431
|
};
|
|
1417
1432
|
}
|
|
@@ -1465,18 +1480,13 @@ var FirecrawlApp = class {
|
|
|
1465
1480
|
scrapeOptions: params?.scrapeOptions ?? { formats: [] }
|
|
1466
1481
|
};
|
|
1467
1482
|
if (jsonData?.scrapeOptions?.extract?.schema) {
|
|
1468
|
-
let schema = jsonData.scrapeOptions.extract.schema;
|
|
1469
|
-
try {
|
|
1470
|
-
schema = zodToJsonSchema4(schema);
|
|
1471
|
-
} catch (error) {
|
|
1472
|
-
}
|
|
1473
1483
|
jsonData = {
|
|
1474
1484
|
...jsonData,
|
|
1475
1485
|
scrapeOptions: {
|
|
1476
1486
|
...jsonData.scrapeOptions,
|
|
1477
1487
|
extract: {
|
|
1478
1488
|
...jsonData.scrapeOptions.extract,
|
|
1479
|
-
schema
|
|
1489
|
+
schema: zodSchemaToJsonSchema(jsonData.scrapeOptions.extract.schema)
|
|
1480
1490
|
}
|
|
1481
1491
|
}
|
|
1482
1492
|
};
|
|
@@ -1734,30 +1744,20 @@ var FirecrawlApp = class {
|
|
|
1734
1744
|
const headers = this.prepareHeaders(idempotencyKey);
|
|
1735
1745
|
let jsonData = { urls, webhook, ignoreInvalidURLs, maxConcurrency, ...params, origin: typeof params.origin === "string" && params.origin.includes("mcp") ? params.origin : `js-sdk@${this.version}` };
|
|
1736
1746
|
if (jsonData?.extract?.schema) {
|
|
1737
|
-
let schema = jsonData.extract.schema;
|
|
1738
|
-
try {
|
|
1739
|
-
schema = zodToJsonSchema4(schema);
|
|
1740
|
-
} catch (error) {
|
|
1741
|
-
}
|
|
1742
1747
|
jsonData = {
|
|
1743
1748
|
...jsonData,
|
|
1744
1749
|
extract: {
|
|
1745
1750
|
...jsonData.extract,
|
|
1746
|
-
schema
|
|
1751
|
+
schema: zodSchemaToJsonSchema(jsonData.extract.schema)
|
|
1747
1752
|
}
|
|
1748
1753
|
};
|
|
1749
1754
|
}
|
|
1750
1755
|
if (jsonData?.jsonOptions?.schema) {
|
|
1751
|
-
let schema = jsonData.jsonOptions.schema;
|
|
1752
|
-
try {
|
|
1753
|
-
schema = zodToJsonSchema4(schema);
|
|
1754
|
-
} catch (error) {
|
|
1755
|
-
}
|
|
1756
1756
|
jsonData = {
|
|
1757
1757
|
...jsonData,
|
|
1758
1758
|
jsonOptions: {
|
|
1759
1759
|
...jsonData.jsonOptions,
|
|
1760
|
-
schema
|
|
1760
|
+
schema: zodSchemaToJsonSchema(jsonData.jsonOptions.schema)
|
|
1761
1761
|
}
|
|
1762
1762
|
};
|
|
1763
1763
|
}
|
|
@@ -1923,20 +1923,7 @@ var FirecrawlApp = class {
|
|
|
1923
1923
|
async extract(urls, params) {
|
|
1924
1924
|
const headers = this.prepareHeaders();
|
|
1925
1925
|
let jsonData = { urls, ...params };
|
|
1926
|
-
|
|
1927
|
-
try {
|
|
1928
|
-
if (!params?.schema) {
|
|
1929
|
-
jsonSchema = void 0;
|
|
1930
|
-
} else {
|
|
1931
|
-
try {
|
|
1932
|
-
jsonSchema = zodToJsonSchema4(params.schema);
|
|
1933
|
-
} catch (_) {
|
|
1934
|
-
jsonSchema = params.schema;
|
|
1935
|
-
}
|
|
1936
|
-
}
|
|
1937
|
-
} catch (error) {
|
|
1938
|
-
throw new FirecrawlError("Invalid schema. Schema must be either a valid Zod schema or JSON schema object.", 400);
|
|
1939
|
-
}
|
|
1926
|
+
const jsonSchema = params?.schema ? zodSchemaToJsonSchema(params.schema) : void 0;
|
|
1940
1927
|
try {
|
|
1941
1928
|
const response = await this.postRequest(
|
|
1942
1929
|
this.apiUrl + `/v1/extract`,
|
|
@@ -1986,21 +1973,8 @@ var FirecrawlApp = class {
|
|
|
1986
1973
|
*/
|
|
1987
1974
|
async asyncExtract(urls, params, idempotencyKey) {
|
|
1988
1975
|
const headers = this.prepareHeaders(idempotencyKey);
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
try {
|
|
1992
|
-
if (!params?.schema) {
|
|
1993
|
-
jsonSchema = void 0;
|
|
1994
|
-
} else {
|
|
1995
|
-
try {
|
|
1996
|
-
jsonSchema = zodToJsonSchema4(params.schema);
|
|
1997
|
-
} catch (_) {
|
|
1998
|
-
jsonSchema = params.schema;
|
|
1999
|
-
}
|
|
2000
|
-
}
|
|
2001
|
-
} catch (error) {
|
|
2002
|
-
throw new FirecrawlError("Invalid schema. Schema must be either a valid Zod schema or JSON schema object.", 400);
|
|
2003
|
-
}
|
|
1976
|
+
const jsonData = { urls, ...params };
|
|
1977
|
+
const jsonSchema = params?.schema ? zodSchemaToJsonSchema(params.schema) : void 0;
|
|
2004
1978
|
try {
|
|
2005
1979
|
const response = await this.postRequest(
|
|
2006
1980
|
this.apiUrl + `/v1/extract`,
|
|
@@ -2282,16 +2256,11 @@ var FirecrawlApp = class {
|
|
|
2282
2256
|
const headers = this.prepareHeaders();
|
|
2283
2257
|
let jsonData = { query, ...params, origin: typeof params.origin === "string" && params.origin.includes("mcp") ? params.origin : `js-sdk@${this.version}` };
|
|
2284
2258
|
if (jsonData?.jsonOptions?.schema) {
|
|
2285
|
-
let schema = jsonData.jsonOptions.schema;
|
|
2286
|
-
try {
|
|
2287
|
-
schema = zodToJsonSchema4(schema);
|
|
2288
|
-
} catch (error) {
|
|
2289
|
-
}
|
|
2290
2259
|
jsonData = {
|
|
2291
2260
|
...jsonData,
|
|
2292
2261
|
jsonOptions: {
|
|
2293
2262
|
...jsonData.jsonOptions,
|
|
2294
|
-
schema
|
|
2263
|
+
schema: zodSchemaToJsonSchema(jsonData.jsonOptions.schema)
|
|
2295
2264
|
}
|
|
2296
2265
|
};
|
|
2297
2266
|
}
|
package/package.json
CHANGED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { describe, test, expect } from "@jest/globals";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import {
|
|
4
|
+
isZodSchema,
|
|
5
|
+
zodSchemaToJsonSchema,
|
|
6
|
+
looksLikeZodShape,
|
|
7
|
+
} from "../../../utils/zodSchemaToJson";
|
|
8
|
+
|
|
9
|
+
describe("zodSchemaToJson utility", () => {
|
|
10
|
+
test("isZodSchema detects Zod schemas and rejects non-Zod values", () => {
|
|
11
|
+
expect(isZodSchema(z.object({ name: z.string() }))).toBe(true);
|
|
12
|
+
expect(isZodSchema(z.string())).toBe(true);
|
|
13
|
+
expect(isZodSchema(z.number())).toBe(true);
|
|
14
|
+
expect(isZodSchema(z.array(z.string()))).toBe(true);
|
|
15
|
+
expect(isZodSchema(z.enum(["A", "B"]))).toBe(true);
|
|
16
|
+
expect(isZodSchema(z.union([z.string(), z.number()]))).toBe(true);
|
|
17
|
+
expect(isZodSchema(z.string().optional())).toBe(true);
|
|
18
|
+
expect(isZodSchema(z.string().nullable())).toBe(true);
|
|
19
|
+
|
|
20
|
+
expect(isZodSchema(null)).toBe(false);
|
|
21
|
+
expect(isZodSchema(undefined)).toBe(false);
|
|
22
|
+
expect(isZodSchema({ name: "test" })).toBe(false);
|
|
23
|
+
expect(isZodSchema({ type: "object", properties: {} })).toBe(false);
|
|
24
|
+
expect(isZodSchema("string")).toBe(false);
|
|
25
|
+
expect(isZodSchema(42)).toBe(false);
|
|
26
|
+
expect(isZodSchema([1, 2, 3])).toBe(false);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test("zodSchemaToJsonSchema converts Zod schemas to JSON Schema", () => {
|
|
30
|
+
const simpleSchema = z.object({ name: z.string() });
|
|
31
|
+
const simpleResult = zodSchemaToJsonSchema(simpleSchema) as Record<string, unknown>;
|
|
32
|
+
expect(simpleResult.type).toBe("object");
|
|
33
|
+
expect(simpleResult.properties).toBeDefined();
|
|
34
|
+
expect((simpleResult.properties as Record<string, unknown>).name).toBeDefined();
|
|
35
|
+
|
|
36
|
+
const complexSchema = z.object({
|
|
37
|
+
id: z.string().uuid(),
|
|
38
|
+
name: z.string().min(1).max(100),
|
|
39
|
+
age: z.number().min(0).max(150).optional(),
|
|
40
|
+
tags: z.array(z.string()),
|
|
41
|
+
status: z.enum(["active", "inactive"]),
|
|
42
|
+
metadata: z.object({
|
|
43
|
+
createdAt: z.string(),
|
|
44
|
+
nested: z.object({ value: z.number() }),
|
|
45
|
+
}),
|
|
46
|
+
});
|
|
47
|
+
const complexResult = zodSchemaToJsonSchema(complexSchema) as Record<string, unknown>;
|
|
48
|
+
expect(complexResult.type).toBe("object");
|
|
49
|
+
expect(complexResult.properties).toBeDefined();
|
|
50
|
+
expect(complexResult.required).toContain("id");
|
|
51
|
+
expect(complexResult.required).not.toContain("age");
|
|
52
|
+
|
|
53
|
+
const enumResult = zodSchemaToJsonSchema(z.enum(["a", "b", "c"])) as Record<string, unknown>;
|
|
54
|
+
expect(enumResult.enum).toEqual(["a", "b", "c"]);
|
|
55
|
+
|
|
56
|
+
const arrayResult = zodSchemaToJsonSchema(z.array(z.number())) as Record<string, unknown>;
|
|
57
|
+
expect(arrayResult.type).toBe("array");
|
|
58
|
+
expect(arrayResult.items).toBeDefined();
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
test("zodSchemaToJsonSchema passes through non-Zod values unchanged", () => {
|
|
62
|
+
const jsonSchema = { type: "object", properties: { name: { type: "string" } } };
|
|
63
|
+
expect(zodSchemaToJsonSchema(jsonSchema)).toEqual(jsonSchema);
|
|
64
|
+
expect(zodSchemaToJsonSchema(null)).toBe(null);
|
|
65
|
+
expect(zodSchemaToJsonSchema(undefined)).toBe(undefined);
|
|
66
|
+
expect(zodSchemaToJsonSchema("string")).toBe("string");
|
|
67
|
+
expect(zodSchemaToJsonSchema(42)).toBe(42);
|
|
68
|
+
expect(zodSchemaToJsonSchema({ foo: "bar" })).toEqual({ foo: "bar" });
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
test("looksLikeZodShape detects .shape property misuse", () => {
|
|
72
|
+
const schema = z.object({ title: z.string(), count: z.number() });
|
|
73
|
+
expect(looksLikeZodShape(schema.shape)).toBe(true);
|
|
74
|
+
expect(looksLikeZodShape(schema)).toBe(false);
|
|
75
|
+
expect(looksLikeZodShape(null)).toBe(false);
|
|
76
|
+
expect(looksLikeZodShape(undefined)).toBe(false);
|
|
77
|
+
expect(looksLikeZodShape({ name: "test" })).toBe(false);
|
|
78
|
+
expect(looksLikeZodShape({})).toBe(false);
|
|
79
|
+
expect(looksLikeZodShape([1, 2, 3])).toBe(false);
|
|
80
|
+
expect(looksLikeZodShape({ type: "object", properties: {} })).toBe(false);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
test("SDK-like usage: convert Zod schema or pass through JSON schema", () => {
|
|
84
|
+
const zodSchema = z.object({
|
|
85
|
+
name: z.string(),
|
|
86
|
+
email: z.string().email(),
|
|
87
|
+
age: z.number().min(0),
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
if (isZodSchema(zodSchema)) {
|
|
91
|
+
const result = zodSchemaToJsonSchema(zodSchema) as Record<string, unknown>;
|
|
92
|
+
expect(result.type).toBe("object");
|
|
93
|
+
expect(result.properties).toBeDefined();
|
|
94
|
+
} else {
|
|
95
|
+
throw new Error("Should detect Zod schema");
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const existingJsonSchema = {
|
|
99
|
+
type: "object" as const,
|
|
100
|
+
properties: { title: { type: "string" as const } },
|
|
101
|
+
required: ["title"] as string[],
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
expect(isZodSchema(existingJsonSchema)).toBe(false);
|
|
105
|
+
expect(zodSchemaToJsonSchema(existingJsonSchema)).toEqual(existingJsonSchema);
|
|
106
|
+
});
|
|
107
|
+
});
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { zodToJsonSchema as zodToJsonSchemaLib } from "zod-to-json-schema";
|
|
2
|
+
|
|
3
|
+
type SchemaConverter = (schema: unknown) => unknown;
|
|
4
|
+
|
|
5
|
+
export function isZodSchema(value: unknown): boolean {
|
|
6
|
+
if (!value || typeof value !== "object") return false;
|
|
7
|
+
const schema = value as Record<string, unknown>;
|
|
8
|
+
|
|
9
|
+
const hasV3Markers =
|
|
10
|
+
"_def" in schema &&
|
|
11
|
+
(typeof schema.safeParse === "function" ||
|
|
12
|
+
typeof schema.parse === "function");
|
|
13
|
+
|
|
14
|
+
const hasV4Markers = "_zod" in schema && typeof schema._zod === "object";
|
|
15
|
+
|
|
16
|
+
return hasV3Markers || hasV4Markers;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function isZodV4Schema(schema: unknown): boolean {
|
|
20
|
+
if (!schema || typeof schema !== "object") return false;
|
|
21
|
+
return "_zod" in schema && typeof (schema as Record<string, unknown>)._zod === "object";
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function tryZodV4Conversion(schema: unknown): Record<string, unknown> | null {
|
|
25
|
+
if (!isZodV4Schema(schema)) return null;
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
const zodModule = (schema as Record<string, unknown>).constructor?.prototype?.constructor;
|
|
29
|
+
if (zodModule && typeof (zodModule as Record<string, unknown>).toJSONSchema === "function") {
|
|
30
|
+
return (zodModule as { toJSONSchema: SchemaConverter }).toJSONSchema(schema) as Record<string, unknown>;
|
|
31
|
+
}
|
|
32
|
+
} catch {
|
|
33
|
+
// V4 conversion not available
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function zodSchemaToJsonSchema(schema: unknown): Record<string, unknown> | unknown {
|
|
40
|
+
if (!isZodSchema(schema)) {
|
|
41
|
+
return schema;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const v4Result = tryZodV4Conversion(schema);
|
|
45
|
+
if (v4Result) {
|
|
46
|
+
return v4Result;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
return zodToJsonSchemaLib(schema as Parameters<typeof zodToJsonSchemaLib>[0]) as Record<string, unknown>;
|
|
51
|
+
} catch {
|
|
52
|
+
return schema;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function looksLikeZodShape(obj: unknown): boolean {
|
|
57
|
+
if (!obj || typeof obj !== "object" || Array.isArray(obj)) return false;
|
|
58
|
+
const values = Object.values(obj);
|
|
59
|
+
if (values.length === 0) return false;
|
|
60
|
+
return values.some(
|
|
61
|
+
(v) =>
|
|
62
|
+
v &&
|
|
63
|
+
typeof v === "object" &&
|
|
64
|
+
(v as Record<string, unknown>)._def &&
|
|
65
|
+
typeof (v as Record<string, unknown>).safeParse === "function"
|
|
66
|
+
);
|
|
67
|
+
}
|
package/src/v1/index.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import axios, { type AxiosResponse, type AxiosRequestHeaders, AxiosError } from "axios";
|
|
2
2
|
import * as zt from "zod";
|
|
3
|
-
import {
|
|
3
|
+
import { zodSchemaToJsonSchema } from "../utils/zodSchemaToJson";
|
|
4
4
|
import { TypedEventTarget } from "typescript-event-target";
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -707,36 +707,21 @@ export default class FirecrawlApp {
|
|
|
707
707
|
} as AxiosRequestHeaders;
|
|
708
708
|
let jsonData: any = { url, ...params, origin: typeof (params as any).origin === "string" && (params as any).origin.includes("mcp") ? (params as any).origin : `js-sdk@${this.version}` };
|
|
709
709
|
if (jsonData?.extract?.schema) {
|
|
710
|
-
let schema = jsonData.extract.schema;
|
|
711
|
-
|
|
712
|
-
// Try parsing the schema as a Zod schema
|
|
713
|
-
try {
|
|
714
|
-
schema = zodToJsonSchema(schema);
|
|
715
|
-
} catch (error) {
|
|
716
|
-
|
|
717
|
-
}
|
|
718
710
|
jsonData = {
|
|
719
711
|
...jsonData,
|
|
720
712
|
extract: {
|
|
721
713
|
...jsonData.extract,
|
|
722
|
-
schema: schema,
|
|
714
|
+
schema: zodSchemaToJsonSchema(jsonData.extract.schema),
|
|
723
715
|
},
|
|
724
716
|
};
|
|
725
717
|
}
|
|
726
718
|
|
|
727
719
|
if (jsonData?.jsonOptions?.schema) {
|
|
728
|
-
let schema = jsonData.jsonOptions.schema;
|
|
729
|
-
// Try parsing the schema as a Zod schema
|
|
730
|
-
try {
|
|
731
|
-
schema = zodToJsonSchema(schema);
|
|
732
|
-
} catch (error) {
|
|
733
|
-
|
|
734
|
-
}
|
|
735
720
|
jsonData = {
|
|
736
721
|
...jsonData,
|
|
737
722
|
jsonOptions: {
|
|
738
723
|
...jsonData.jsonOptions,
|
|
739
|
-
schema: schema,
|
|
724
|
+
schema: zodSchemaToJsonSchema(jsonData.jsonOptions.schema),
|
|
740
725
|
},
|
|
741
726
|
};
|
|
742
727
|
}
|
|
@@ -793,21 +778,13 @@ export default class FirecrawlApp {
|
|
|
793
778
|
};
|
|
794
779
|
|
|
795
780
|
if (jsonData?.scrapeOptions?.extract?.schema) {
|
|
796
|
-
let schema = jsonData.scrapeOptions.extract.schema;
|
|
797
|
-
|
|
798
|
-
// Try parsing the schema as a Zod schema
|
|
799
|
-
try {
|
|
800
|
-
schema = zodToJsonSchema(schema);
|
|
801
|
-
} catch (error) {
|
|
802
|
-
|
|
803
|
-
}
|
|
804
781
|
jsonData = {
|
|
805
782
|
...jsonData,
|
|
806
783
|
scrapeOptions: {
|
|
807
784
|
...jsonData.scrapeOptions,
|
|
808
785
|
extract: {
|
|
809
786
|
...jsonData.scrapeOptions.extract,
|
|
810
|
-
schema: schema,
|
|
787
|
+
schema: zodSchemaToJsonSchema(jsonData.scrapeOptions.extract.schema),
|
|
811
788
|
},
|
|
812
789
|
},
|
|
813
790
|
};
|
|
@@ -1105,36 +1082,20 @@ export default class FirecrawlApp {
|
|
|
1105
1082
|
const headers = this.prepareHeaders(idempotencyKey);
|
|
1106
1083
|
let jsonData: any = { urls, webhook, ignoreInvalidURLs, maxConcurrency, ...params, origin: typeof (params as any).origin === "string" && (params as any).origin.includes("mcp") ? (params as any).origin : `js-sdk@${this.version}` };
|
|
1107
1084
|
if (jsonData?.extract?.schema) {
|
|
1108
|
-
let schema = jsonData.extract.schema;
|
|
1109
|
-
|
|
1110
|
-
// Try parsing the schema as a Zod schema
|
|
1111
|
-
try {
|
|
1112
|
-
schema = zodToJsonSchema(schema);
|
|
1113
|
-
} catch (error) {
|
|
1114
|
-
|
|
1115
|
-
}
|
|
1116
1085
|
jsonData = {
|
|
1117
1086
|
...jsonData,
|
|
1118
1087
|
extract: {
|
|
1119
1088
|
...jsonData.extract,
|
|
1120
|
-
schema: schema,
|
|
1089
|
+
schema: zodSchemaToJsonSchema(jsonData.extract.schema),
|
|
1121
1090
|
},
|
|
1122
1091
|
};
|
|
1123
1092
|
}
|
|
1124
1093
|
if (jsonData?.jsonOptions?.schema) {
|
|
1125
|
-
let schema = jsonData.jsonOptions.schema;
|
|
1126
|
-
|
|
1127
|
-
// Try parsing the schema as a Zod schema
|
|
1128
|
-
try {
|
|
1129
|
-
schema = zodToJsonSchema(schema);
|
|
1130
|
-
} catch (error) {
|
|
1131
|
-
|
|
1132
|
-
}
|
|
1133
1094
|
jsonData = {
|
|
1134
1095
|
...jsonData,
|
|
1135
1096
|
jsonOptions: {
|
|
1136
1097
|
...jsonData.jsonOptions,
|
|
1137
|
-
schema: schema,
|
|
1098
|
+
schema: zodSchemaToJsonSchema(jsonData.jsonOptions.schema),
|
|
1138
1099
|
},
|
|
1139
1100
|
};
|
|
1140
1101
|
}
|
|
@@ -1326,20 +1287,7 @@ export default class FirecrawlApp {
|
|
|
1326
1287
|
const headers = this.prepareHeaders();
|
|
1327
1288
|
|
|
1328
1289
|
let jsonData: { urls?: string[] } & ExtractParams<T> = { urls: urls, ...params };
|
|
1329
|
-
|
|
1330
|
-
try {
|
|
1331
|
-
if (!params?.schema) {
|
|
1332
|
-
jsonSchema = undefined;
|
|
1333
|
-
} else {
|
|
1334
|
-
try {
|
|
1335
|
-
jsonSchema = zodToJsonSchema(params.schema as zt.ZodType);
|
|
1336
|
-
} catch (_) {
|
|
1337
|
-
jsonSchema = params.schema;
|
|
1338
|
-
}
|
|
1339
|
-
}
|
|
1340
|
-
} catch (error: any) {
|
|
1341
|
-
throw new FirecrawlError("Invalid schema. Schema must be either a valid Zod schema or JSON schema object.", 400);
|
|
1342
|
-
}
|
|
1290
|
+
const jsonSchema = params?.schema ? zodSchemaToJsonSchema(params.schema) : undefined;
|
|
1343
1291
|
|
|
1344
1292
|
try {
|
|
1345
1293
|
const response: AxiosResponse = await this.postRequest(
|
|
@@ -1396,22 +1344,8 @@ export default class FirecrawlApp {
|
|
|
1396
1344
|
idempotencyKey?: string
|
|
1397
1345
|
): Promise<ExtractResponse | ErrorResponse> {
|
|
1398
1346
|
const headers = this.prepareHeaders(idempotencyKey);
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
try {
|
|
1403
|
-
if (!params?.schema) {
|
|
1404
|
-
jsonSchema = undefined;
|
|
1405
|
-
} else {
|
|
1406
|
-
try {
|
|
1407
|
-
jsonSchema = zodToJsonSchema(params.schema as zt.ZodType);
|
|
1408
|
-
} catch (_) {
|
|
1409
|
-
jsonSchema = params.schema;
|
|
1410
|
-
}
|
|
1411
|
-
}
|
|
1412
|
-
} catch (error: any) {
|
|
1413
|
-
throw new FirecrawlError("Invalid schema. Schema must be either a valid Zod schema or JSON schema object.", 400);
|
|
1414
|
-
}
|
|
1347
|
+
const jsonData: any = { urls, ...params };
|
|
1348
|
+
const jsonSchema = params?.schema ? zodSchemaToJsonSchema(params.schema) : undefined;
|
|
1415
1349
|
|
|
1416
1350
|
try {
|
|
1417
1351
|
const response: AxiosResponse = await this.postRequest(
|
|
@@ -1780,18 +1714,11 @@ export default class FirecrawlApp {
|
|
|
1780
1714
|
let jsonData: any = { query, ...params, origin: typeof (params as any).origin === "string" && (params as any).origin.includes("mcp") ? (params as any).origin : `js-sdk@${this.version}` };
|
|
1781
1715
|
|
|
1782
1716
|
if (jsonData?.jsonOptions?.schema) {
|
|
1783
|
-
let schema = jsonData.jsonOptions.schema;
|
|
1784
|
-
// Try parsing the schema as a Zod schema
|
|
1785
|
-
try {
|
|
1786
|
-
schema = zodToJsonSchema(schema);
|
|
1787
|
-
} catch (error) {
|
|
1788
|
-
// Ignore error if schema can't be parsed as Zod
|
|
1789
|
-
}
|
|
1790
1717
|
jsonData = {
|
|
1791
1718
|
...jsonData,
|
|
1792
1719
|
jsonOptions: {
|
|
1793
1720
|
...jsonData.jsonOptions,
|
|
1794
|
-
schema: schema,
|
|
1721
|
+
schema: zodSchemaToJsonSchema(jsonData.jsonOptions.schema),
|
|
1795
1722
|
},
|
|
1796
1723
|
};
|
|
1797
1724
|
}
|
package/src/v2/methods/agent.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type AgentResponse, type AgentStatusResponse, type AgentWebhookConfig } from "../types";
|
|
2
2
|
import { HttpClient } from "../utils/httpClient";
|
|
3
3
|
import { normalizeAxiosError, throwForBadResponse } from "../utils/errorHandler";
|
|
4
|
-
import {
|
|
4
|
+
import { isZodSchema, zodSchemaToJsonSchema } from "../../utils/zodSchemaToJson";
|
|
5
5
|
import type { ZodTypeAny } from "zod";
|
|
6
6
|
|
|
7
7
|
function prepareAgentPayload(args: {
|
|
@@ -18,9 +18,7 @@ function prepareAgentPayload(args: {
|
|
|
18
18
|
if (args.urls) body.urls = args.urls;
|
|
19
19
|
body.prompt = args.prompt;
|
|
20
20
|
if (args.schema != null) {
|
|
21
|
-
|
|
22
|
-
const isZod = s && (typeof s.safeParse === "function" || typeof s.parse === "function") && s._def;
|
|
23
|
-
body.schema = isZod ? zodToJsonSchema(s) : args.schema;
|
|
21
|
+
body.schema = isZodSchema(args.schema) ? zodSchemaToJsonSchema(args.schema) : args.schema;
|
|
24
22
|
}
|
|
25
23
|
if (args.integration && args.integration.trim()) body.integration = args.integration.trim();
|
|
26
24
|
if (args.maxCredits !== null && args.maxCredits !== undefined) body.maxCredits = args.maxCredits;
|
|
@@ -2,7 +2,7 @@ import { type ExtractResponse, type ScrapeOptions, type AgentOptions } from "../
|
|
|
2
2
|
import { HttpClient } from "../utils/httpClient";
|
|
3
3
|
import { ensureValidScrapeOptions } from "../utils/validation";
|
|
4
4
|
import { normalizeAxiosError, throwForBadResponse } from "../utils/errorHandler";
|
|
5
|
-
import {
|
|
5
|
+
import { isZodSchema, zodSchemaToJsonSchema } from "../../utils/zodSchemaToJson";
|
|
6
6
|
import type { ZodTypeAny } from "zod";
|
|
7
7
|
|
|
8
8
|
function prepareExtractPayload(args: {
|
|
@@ -22,9 +22,7 @@ function prepareExtractPayload(args: {
|
|
|
22
22
|
if (args.urls) body.urls = args.urls;
|
|
23
23
|
if (args.prompt != null) body.prompt = args.prompt;
|
|
24
24
|
if (args.schema != null) {
|
|
25
|
-
|
|
26
|
-
const isZod = s && (typeof s.safeParse === "function" || typeof s.parse === "function") && s._def;
|
|
27
|
-
body.schema = isZod ? zodToJsonSchema(s) : args.schema;
|
|
25
|
+
body.schema = isZodSchema(args.schema) ? zodSchemaToJsonSchema(args.schema) : args.schema;
|
|
28
26
|
}
|
|
29
27
|
if (args.systemPrompt != null) body.systemPrompt = args.systemPrompt;
|
|
30
28
|
if (args.allowExternalLinks != null) body.allowExternalLinks = args.allowExternalLinks;
|
|
@@ -1,18 +1,5 @@
|
|
|
1
1
|
import { type FormatOption, type JsonFormat, type ScrapeOptions, type ScreenshotFormat, type ChangeTrackingFormat } from "../types";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Detects if an object looks like a Zod schema's `.shape` property.
|
|
6
|
-
* When users mistakenly pass `schema.shape` instead of `schema`, the object
|
|
7
|
-
* will have Zod types as values but won't be a Zod schema itself.
|
|
8
|
-
*/
|
|
9
|
-
function looksLikeZodShape(obj: unknown): boolean {
|
|
10
|
-
if (!obj || typeof obj !== "object" || Array.isArray(obj)) return false;
|
|
11
|
-
const values = Object.values(obj);
|
|
12
|
-
if (values.length === 0) return false;
|
|
13
|
-
// Check if at least one value looks like a Zod type
|
|
14
|
-
return values.some((v: any) => v && typeof v === "object" && v._def && typeof v.safeParse === "function");
|
|
15
|
-
}
|
|
2
|
+
import { isZodSchema, zodSchemaToJsonSchema, looksLikeZodShape } from "../../utils/zodSchemaToJson";
|
|
16
3
|
|
|
17
4
|
export function ensureValidFormats(formats?: FormatOption[]): void {
|
|
18
5
|
if (!formats) return;
|
|
@@ -28,17 +15,10 @@ export function ensureValidFormats(formats?: FormatOption[]): void {
|
|
|
28
15
|
if (!j.prompt && !j.schema) {
|
|
29
16
|
throw new Error("json format requires either 'prompt' or 'schema' (or both)");
|
|
30
17
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
if (isZod) {
|
|
35
|
-
try {
|
|
36
|
-
(j as any).schema = zodToJsonSchema(maybeSchema);
|
|
37
|
-
} catch {
|
|
38
|
-
// If conversion fails, leave as-is; server-side may still handle, or request will fail explicitly
|
|
39
|
-
}
|
|
18
|
+
const maybeSchema = j.schema;
|
|
19
|
+
if (isZodSchema(maybeSchema)) {
|
|
20
|
+
(j as any).schema = zodSchemaToJsonSchema(maybeSchema);
|
|
40
21
|
} else if (looksLikeZodShape(maybeSchema)) {
|
|
41
|
-
// User likely passed schema.shape instead of the schema itself
|
|
42
22
|
throw new Error(
|
|
43
23
|
"json format schema appears to be a Zod schema's .shape property. " +
|
|
44
24
|
"Pass the Zod schema directly (e.g., `schema: MySchema`) instead of `schema: MySchema.shape`. " +
|
|
@@ -49,14 +29,9 @@ export function ensureValidFormats(formats?: FormatOption[]): void {
|
|
|
49
29
|
}
|
|
50
30
|
if ((fmt as ChangeTrackingFormat).type === "changeTracking") {
|
|
51
31
|
const ct = fmt as ChangeTrackingFormat;
|
|
52
|
-
const maybeSchema
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
try {
|
|
56
|
-
(ct as any).schema = zodToJsonSchema(maybeSchema);
|
|
57
|
-
} catch {
|
|
58
|
-
// Best-effort conversion; if it fails, leave original value
|
|
59
|
-
}
|
|
32
|
+
const maybeSchema = ct.schema;
|
|
33
|
+
if (isZodSchema(maybeSchema)) {
|
|
34
|
+
(ct as any).schema = zodSchemaToJsonSchema(maybeSchema);
|
|
60
35
|
} else if (looksLikeZodShape(maybeSchema)) {
|
|
61
36
|
throw new Error(
|
|
62
37
|
"changeTracking format schema appears to be a Zod schema's .shape property. " +
|