firecrawl 0.0.28
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/.env.example +3 -0
- package/README.md +195 -0
- package/build/index.js +257 -0
- package/build_and_publish.sh +34 -0
- package/jest.config.cjs +5 -0
- package/package.json +52 -0
- package/src/__tests__/e2e_withAuth/index.test.ts +156 -0
- package/src/__tests__/fixtures/scrape.json +22 -0
- package/src/__tests__/index.test.ts +48 -0
- package/src/index.ts +411 -0
- package/tsconfig.json +111 -0
- package/types/index.d.ts +189 -0
package/.env.example
ADDED
package/README.md
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
# Firecrawl JavaScript SDK
|
|
2
|
+
|
|
3
|
+
The Firecrawl JavaScript SDK is a library that allows you to easily scrape and crawl websites, and output the data in a format ready for use with language models (LLMs). It provides a simple and intuitive interface for interacting with the Firecrawl API.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
To install the Firecrawl JavaScript SDK, you can use npm:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @mendable/firecrawl-js
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
1. Get an API key from [firecrawl.dev](https://firecrawl.dev)
|
|
16
|
+
2. Set the API key as an environment variable named `FIRECRAWL_API_KEY` or pass it as a parameter to the `FirecrawlApp` class.
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
Here's an example of how to use the SDK with error handling:
|
|
20
|
+
|
|
21
|
+
```js
|
|
22
|
+
import FirecrawlApp from '@mendable/firecrawl-js';
|
|
23
|
+
|
|
24
|
+
async function main() {
|
|
25
|
+
try {
|
|
26
|
+
// Initialize the FirecrawlApp with your API key
|
|
27
|
+
const app = new FirecrawlApp({ apiKey: "YOUR_API_KEY" });
|
|
28
|
+
|
|
29
|
+
// Scrape a single URL
|
|
30
|
+
const url = 'https://mendable.ai';
|
|
31
|
+
const scrapedData = await app.scrapeUrl(url);
|
|
32
|
+
console.log(scrapedData);
|
|
33
|
+
|
|
34
|
+
// Crawl a website
|
|
35
|
+
const crawlUrl = 'https://mendable.ai';
|
|
36
|
+
const params = {
|
|
37
|
+
crawlerOptions: {
|
|
38
|
+
excludes: ['blog/'],
|
|
39
|
+
includes: [], // leave empty for all pages
|
|
40
|
+
limit: 1000,
|
|
41
|
+
},
|
|
42
|
+
pageOptions: {
|
|
43
|
+
onlyMainContent: true
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const crawlResult = await app.crawlUrl(crawlUrl, params);
|
|
48
|
+
console.log(crawlResult);
|
|
49
|
+
|
|
50
|
+
} catch (error) {
|
|
51
|
+
console.error('An error occurred:', error.message);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
main();
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Scraping a URL
|
|
59
|
+
|
|
60
|
+
To scrape a single URL with error handling, use the `scrapeUrl` method. It takes the URL as a parameter and returns the scraped data as a dictionary.
|
|
61
|
+
|
|
62
|
+
```js
|
|
63
|
+
async function scrapeExample() {
|
|
64
|
+
try {
|
|
65
|
+
const url = 'https://example.com';
|
|
66
|
+
const scrapedData = await app.scrapeUrl(url);
|
|
67
|
+
console.log(scrapedData);
|
|
68
|
+
|
|
69
|
+
} catch (error) {
|
|
70
|
+
console.error(
|
|
71
|
+
'Error occurred while scraping:',
|
|
72
|
+
error.message
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
scrapeExample();
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Extracting structured data from a URL
|
|
81
|
+
|
|
82
|
+
With LLM extraction, you can easily extract structured data from any URL. We support zod schemas to make it easier for you too. Here is how you to use it:
|
|
83
|
+
|
|
84
|
+
```js
|
|
85
|
+
import { z } from "zod";
|
|
86
|
+
|
|
87
|
+
const zodSchema = z.object({
|
|
88
|
+
top: z
|
|
89
|
+
.array(
|
|
90
|
+
z.object({
|
|
91
|
+
title: z.string(),
|
|
92
|
+
points: z.number(),
|
|
93
|
+
by: z.string(),
|
|
94
|
+
commentsURL: z.string(),
|
|
95
|
+
})
|
|
96
|
+
)
|
|
97
|
+
.length(5)
|
|
98
|
+
.describe("Top 5 stories on Hacker News"),
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
let llmExtractionResult = await app.scrapeUrl("https://news.ycombinator.com", {
|
|
102
|
+
extractorOptions: { extractionSchema: zodSchema },
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
console.log(llmExtractionResult.data.llm_extraction);
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Search for a query
|
|
109
|
+
|
|
110
|
+
Used to search the web, get the most relevant results, scrap each page and return the markdown.
|
|
111
|
+
|
|
112
|
+
```js
|
|
113
|
+
query = 'what is mendable?'
|
|
114
|
+
searchResult = app.search(query)
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Crawling a Website
|
|
118
|
+
|
|
119
|
+
To crawl a website with error handling, use the `crawlUrl` method. It takes the starting URL and optional parameters as arguments. The `params` argument allows you to specify additional options for the crawl job, such as the maximum number of pages to crawl, allowed domains, and the output format.
|
|
120
|
+
|
|
121
|
+
```js
|
|
122
|
+
async function crawlExample() {
|
|
123
|
+
try {
|
|
124
|
+
const crawlUrl = 'https://example.com';
|
|
125
|
+
const params = {
|
|
126
|
+
crawlerOptions: {
|
|
127
|
+
excludes: ['blog/'],
|
|
128
|
+
includes: [], // leave empty for all pages
|
|
129
|
+
limit: 1000,
|
|
130
|
+
},
|
|
131
|
+
pageOptions: {
|
|
132
|
+
onlyMainContent: true
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
const waitUntilDone = true;
|
|
136
|
+
const timeout = 5;
|
|
137
|
+
const crawlResult = await app.crawlUrl(
|
|
138
|
+
crawlUrl,
|
|
139
|
+
params,
|
|
140
|
+
waitUntilDone,
|
|
141
|
+
timeout
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
console.log(crawlResult);
|
|
145
|
+
|
|
146
|
+
} catch (error) {
|
|
147
|
+
console.error(
|
|
148
|
+
'Error occurred while crawling:',
|
|
149
|
+
error.message
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
crawlExample();
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
### Checking Crawl Status
|
|
159
|
+
|
|
160
|
+
To check the status of a crawl job with error handling, use the `checkCrawlStatus` method. It takes the job ID as a parameter and returns the current status of the crawl job.
|
|
161
|
+
|
|
162
|
+
```js
|
|
163
|
+
async function checkStatusExample(jobId) {
|
|
164
|
+
try {
|
|
165
|
+
const status = await app.checkCrawlStatus(jobId);
|
|
166
|
+
console.log(status);
|
|
167
|
+
|
|
168
|
+
} catch (error) {
|
|
169
|
+
console.error(
|
|
170
|
+
'Error occurred while checking crawl status:',
|
|
171
|
+
error.message
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
// Example usage, assuming you have a jobId
|
|
176
|
+
checkStatusExample('your_job_id_here');
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## Running Locally
|
|
180
|
+
To use the SDK when running Firecrawl locally, you can change the initial Firecrawl app instance to:
|
|
181
|
+
```js
|
|
182
|
+
const app = new FirecrawlApp({ apiKey: "YOUR_API_KEY", apiUrl: "http://localhost:3002" });
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## Error Handling
|
|
186
|
+
|
|
187
|
+
The SDK handles errors returned by the Firecrawl API and raises appropriate exceptions. If an error occurs during a request, an exception will be raised with a descriptive error message. The examples above demonstrate how to handle these errors using `try/catch` blocks.
|
|
188
|
+
|
|
189
|
+
## Contributing
|
|
190
|
+
|
|
191
|
+
Contributions to the Firecrawl JavaScript SDK are welcome! If you find any issues or have suggestions for improvements, please open an issue or submit a pull request on the GitHub repository.
|
|
192
|
+
|
|
193
|
+
## License
|
|
194
|
+
|
|
195
|
+
The Firecrawl JavaScript SDK is open-source and released under the [MIT License](https://opensource.org/licenses/MIT).
|
package/build/index.js
ADDED
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import axios from "axios";
|
|
11
|
+
import { z } from "zod";
|
|
12
|
+
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
13
|
+
/**
|
|
14
|
+
* Main class for interacting with the Firecrawl API.
|
|
15
|
+
*/
|
|
16
|
+
export default class FirecrawlApp {
|
|
17
|
+
/**
|
|
18
|
+
* Initializes a new instance of the FirecrawlApp class.
|
|
19
|
+
* @param {FirecrawlAppConfig} config - Configuration options for the FirecrawlApp instance.
|
|
20
|
+
*/
|
|
21
|
+
constructor({ apiKey = null, apiUrl = null }) {
|
|
22
|
+
this.apiKey = apiKey || "";
|
|
23
|
+
this.apiUrl = apiUrl || "https://api.firecrawl.dev";
|
|
24
|
+
if (!this.apiKey) {
|
|
25
|
+
throw new Error("No API key provided");
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Scrapes a URL using the Firecrawl API.
|
|
30
|
+
* @param {string} url - The URL to scrape.
|
|
31
|
+
* @param {Params | null} params - Additional parameters for the scrape request.
|
|
32
|
+
* @returns {Promise<ScrapeResponse>} The response from the scrape operation.
|
|
33
|
+
*/
|
|
34
|
+
scrapeUrl(url, params = null) {
|
|
35
|
+
var _a;
|
|
36
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
37
|
+
const headers = {
|
|
38
|
+
"Content-Type": "application/json",
|
|
39
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
40
|
+
};
|
|
41
|
+
let jsonData = Object.assign({ url }, params);
|
|
42
|
+
if ((_a = params === null || params === void 0 ? void 0 : params.extractorOptions) === null || _a === void 0 ? void 0 : _a.extractionSchema) {
|
|
43
|
+
let schema = params.extractorOptions.extractionSchema;
|
|
44
|
+
// Check if schema is an instance of ZodSchema to correctly identify Zod schemas
|
|
45
|
+
if (schema instanceof z.ZodSchema) {
|
|
46
|
+
schema = zodToJsonSchema(schema);
|
|
47
|
+
}
|
|
48
|
+
jsonData = Object.assign(Object.assign({}, jsonData), { extractorOptions: Object.assign(Object.assign({}, params.extractorOptions), { extractionSchema: schema, mode: params.extractorOptions.mode || "llm-extraction" }) });
|
|
49
|
+
}
|
|
50
|
+
try {
|
|
51
|
+
const response = yield axios.post(this.apiUrl + "/v0/scrape", jsonData, { headers });
|
|
52
|
+
if (response.status === 200) {
|
|
53
|
+
const responseData = response.data;
|
|
54
|
+
if (responseData.success) {
|
|
55
|
+
return responseData;
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
throw new Error(`Failed to scrape URL. Error: ${responseData.error}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
this.handleError(response, "scrape URL");
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
throw new Error(error.message);
|
|
67
|
+
}
|
|
68
|
+
return { success: false, error: "Internal server error." };
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Searches for a query using the Firecrawl API.
|
|
73
|
+
* @param {string} query - The query to search for.
|
|
74
|
+
* @param {Params | null} params - Additional parameters for the search request.
|
|
75
|
+
* @returns {Promise<SearchResponse>} The response from the search operation.
|
|
76
|
+
*/
|
|
77
|
+
search(query, params = null) {
|
|
78
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
79
|
+
const headers = {
|
|
80
|
+
"Content-Type": "application/json",
|
|
81
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
82
|
+
};
|
|
83
|
+
let jsonData = { query };
|
|
84
|
+
if (params) {
|
|
85
|
+
jsonData = Object.assign(Object.assign({}, jsonData), params);
|
|
86
|
+
}
|
|
87
|
+
try {
|
|
88
|
+
const response = yield axios.post(this.apiUrl + "/v0/search", jsonData, { headers });
|
|
89
|
+
if (response.status === 200) {
|
|
90
|
+
const responseData = response.data;
|
|
91
|
+
if (responseData.success) {
|
|
92
|
+
return responseData;
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
throw new Error(`Failed to search. Error: ${responseData.error}`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
this.handleError(response, "search");
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
throw new Error(error.message);
|
|
104
|
+
}
|
|
105
|
+
return { success: false, error: "Internal server error." };
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Initiates a crawl job for a URL using the Firecrawl API.
|
|
110
|
+
* @param {string} url - The URL to crawl.
|
|
111
|
+
* @param {Params | null} params - Additional parameters for the crawl request.
|
|
112
|
+
* @param {boolean} waitUntilDone - Whether to wait for the crawl job to complete.
|
|
113
|
+
* @param {number} pollInterval - Time in seconds for job status checks.
|
|
114
|
+
* @param {string} idempotencyKey - Optional idempotency key for the request.
|
|
115
|
+
* @returns {Promise<CrawlResponse | any>} The response from the crawl operation.
|
|
116
|
+
*/
|
|
117
|
+
crawlUrl(url, params = null, waitUntilDone = true, pollInterval = 2, idempotencyKey) {
|
|
118
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
119
|
+
const headers = this.prepareHeaders(idempotencyKey);
|
|
120
|
+
let jsonData = { url };
|
|
121
|
+
if (params) {
|
|
122
|
+
jsonData = Object.assign(Object.assign({}, jsonData), params);
|
|
123
|
+
}
|
|
124
|
+
try {
|
|
125
|
+
const response = yield this.postRequest(this.apiUrl + "/v0/crawl", jsonData, headers);
|
|
126
|
+
if (response.status === 200) {
|
|
127
|
+
const jobId = response.data.jobId;
|
|
128
|
+
if (waitUntilDone) {
|
|
129
|
+
return this.monitorJobStatus(jobId, headers, pollInterval);
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
return { success: true, jobId };
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
this.handleError(response, "start crawl job");
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
console.log(error);
|
|
141
|
+
throw new Error(error.message);
|
|
142
|
+
}
|
|
143
|
+
return { success: false, error: "Internal server error." };
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Checks the status of a crawl job using the Firecrawl API.
|
|
148
|
+
* @param {string} jobId - The job ID of the crawl operation.
|
|
149
|
+
* @returns {Promise<JobStatusResponse>} The response containing the job status.
|
|
150
|
+
*/
|
|
151
|
+
checkCrawlStatus(jobId) {
|
|
152
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
153
|
+
const headers = this.prepareHeaders();
|
|
154
|
+
try {
|
|
155
|
+
const response = yield this.getRequest(this.apiUrl + `/v0/crawl/status/${jobId}`, headers);
|
|
156
|
+
if (response.status === 200) {
|
|
157
|
+
return {
|
|
158
|
+
success: true,
|
|
159
|
+
status: response.data.status,
|
|
160
|
+
data: response.data.data,
|
|
161
|
+
partial_data: !response.data.data
|
|
162
|
+
? response.data.partial_data
|
|
163
|
+
: undefined,
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
this.handleError(response, "check crawl status");
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
catch (error) {
|
|
171
|
+
throw new Error(error.message);
|
|
172
|
+
}
|
|
173
|
+
return {
|
|
174
|
+
success: false,
|
|
175
|
+
status: "unknown",
|
|
176
|
+
error: "Internal server error.",
|
|
177
|
+
};
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Prepares the headers for an API request.
|
|
182
|
+
* @returns {AxiosRequestHeaders} The prepared headers.
|
|
183
|
+
*/
|
|
184
|
+
prepareHeaders(idempotencyKey) {
|
|
185
|
+
return Object.assign({ "Content-Type": "application/json", Authorization: `Bearer ${this.apiKey}` }, (idempotencyKey ? { "x-idempotency-key": idempotencyKey } : {}));
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Sends a POST request to the specified URL.
|
|
189
|
+
* @param {string} url - The URL to send the request to.
|
|
190
|
+
* @param {Params} data - The data to send in the request.
|
|
191
|
+
* @param {AxiosRequestHeaders} headers - The headers for the request.
|
|
192
|
+
* @returns {Promise<AxiosResponse>} The response from the POST request.
|
|
193
|
+
*/
|
|
194
|
+
postRequest(url, data, headers) {
|
|
195
|
+
return axios.post(url, data, { headers });
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Sends a GET request to the specified URL.
|
|
199
|
+
* @param {string} url - The URL to send the request to.
|
|
200
|
+
* @param {AxiosRequestHeaders} headers - The headers for the request.
|
|
201
|
+
* @returns {Promise<AxiosResponse>} The response from the GET request.
|
|
202
|
+
*/
|
|
203
|
+
getRequest(url, headers) {
|
|
204
|
+
return axios.get(url, { headers });
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Monitors the status of a crawl job until completion or failure.
|
|
208
|
+
* @param {string} jobId - The job ID of the crawl operation.
|
|
209
|
+
* @param {AxiosRequestHeaders} headers - The headers for the request.
|
|
210
|
+
* @param {number} timeout - Timeout in seconds for job status checks.
|
|
211
|
+
* @returns {Promise<any>} The final job status or data.
|
|
212
|
+
*/
|
|
213
|
+
monitorJobStatus(jobId, headers, checkInterval) {
|
|
214
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
215
|
+
while (true) {
|
|
216
|
+
const statusResponse = yield this.getRequest(this.apiUrl + `/v0/crawl/status/${jobId}`, headers);
|
|
217
|
+
if (statusResponse.status === 200) {
|
|
218
|
+
const statusData = statusResponse.data;
|
|
219
|
+
if (statusData.status === "completed") {
|
|
220
|
+
if ("data" in statusData) {
|
|
221
|
+
return statusData.data;
|
|
222
|
+
}
|
|
223
|
+
else {
|
|
224
|
+
throw new Error("Crawl job completed but no data was returned");
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
else if (["active", "paused", "pending", "queued"].includes(statusData.status)) {
|
|
228
|
+
if (checkInterval < 2) {
|
|
229
|
+
checkInterval = 2;
|
|
230
|
+
}
|
|
231
|
+
yield new Promise((resolve) => setTimeout(resolve, checkInterval * 1000)); // Wait for the specified timeout before checking again
|
|
232
|
+
}
|
|
233
|
+
else {
|
|
234
|
+
throw new Error(`Crawl job failed or was stopped. Status: ${statusData.status}`);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
this.handleError(statusResponse, "check crawl status");
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Handles errors from API responses.
|
|
245
|
+
* @param {AxiosResponse} response - The response from the API.
|
|
246
|
+
* @param {string} action - The action being performed when the error occurred.
|
|
247
|
+
*/
|
|
248
|
+
handleError(response, action) {
|
|
249
|
+
if ([402, 408, 409, 500].includes(response.status)) {
|
|
250
|
+
const errorMessage = response.data.error || "Unknown error occurred";
|
|
251
|
+
throw new Error(`Failed to ${action}. Status code: ${response.status}. Error: ${errorMessage}`);
|
|
252
|
+
}
|
|
253
|
+
else {
|
|
254
|
+
throw new Error(`Unexpected error occurred while trying to ${action}. Status code: ${response.status}`);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
function build_and_publish {
|
|
4
|
+
PACKAGE_NAME=$1
|
|
5
|
+
|
|
6
|
+
# Replace placeholder with the package name in package.json
|
|
7
|
+
sed -i '' "s/\"name\": \"PLACEHOLDER_NAME\"/\"name\": \"$PACKAGE_NAME\"/" package.json
|
|
8
|
+
|
|
9
|
+
# Debug: show modified state
|
|
10
|
+
echo "Modified package.json for $PACKAGE_NAME:"
|
|
11
|
+
cat package.json
|
|
12
|
+
|
|
13
|
+
# Publish the package using npm
|
|
14
|
+
npm publish
|
|
15
|
+
|
|
16
|
+
# Check if publish was successful
|
|
17
|
+
if [ $? -ne 0 ]; then
|
|
18
|
+
echo "Publish failed for $PACKAGE_NAME"
|
|
19
|
+
exit 1
|
|
20
|
+
fi
|
|
21
|
+
|
|
22
|
+
# Revert the changes to the original placeholder in package.json
|
|
23
|
+
sed -i '' "s/\"name\": \"$PACKAGE_NAME\"/\"name\": \"PLACEHOLDER_NAME\"/" package.json
|
|
24
|
+
|
|
25
|
+
# Debug: show reverted state
|
|
26
|
+
echo "Reverted package.json to placeholder:"
|
|
27
|
+
cat package.json
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
# Build and publish the first package to npm
|
|
31
|
+
build_and_publish "@mendable/firecrawl-js"
|
|
32
|
+
|
|
33
|
+
# Build and publish the second package to npm
|
|
34
|
+
build_and_publish "firecrawl"
|
package/jest.config.cjs
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "firecrawl",
|
|
3
|
+
"version": "0.0.28",
|
|
4
|
+
"description": "JavaScript SDK for Firecrawl API",
|
|
5
|
+
"main": "build/index.js",
|
|
6
|
+
"types": "types/index.d.ts",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"scripts": {
|
|
9
|
+
"build": "tsc",
|
|
10
|
+
"build-and-publish": "npm run build && npm publish --access public",
|
|
11
|
+
"publish-beta": "npm run build && npm publish --access public --tag beta",
|
|
12
|
+
"test": "jest src/__tests__/**/*.test.ts"
|
|
13
|
+
},
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "git+https://github.com/mendableai/firecrawl.git"
|
|
17
|
+
},
|
|
18
|
+
"author": "Mendable.ai",
|
|
19
|
+
"license": "MIT",
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"axios": "^1.6.8",
|
|
22
|
+
"dotenv": "^16.4.5",
|
|
23
|
+
"uuid": "^9.0.1",
|
|
24
|
+
"zod": "^3.23.8",
|
|
25
|
+
"zod-to-json-schema": "^3.23.0"
|
|
26
|
+
},
|
|
27
|
+
"bugs": {
|
|
28
|
+
"url": "https://github.com/mendableai/firecrawl/issues"
|
|
29
|
+
},
|
|
30
|
+
"homepage": "https://github.com/mendableai/firecrawl#readme",
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@jest/globals": "^29.7.0",
|
|
33
|
+
"@types/axios": "^0.14.0",
|
|
34
|
+
"@types/dotenv": "^8.2.0",
|
|
35
|
+
"@types/jest": "^29.5.12",
|
|
36
|
+
"@types/mocha": "^10.0.6",
|
|
37
|
+
"@types/node": "^20.12.12",
|
|
38
|
+
"@types/uuid": "^9.0.8",
|
|
39
|
+
"jest": "^29.7.0",
|
|
40
|
+
"ts-jest": "^29.1.2",
|
|
41
|
+
"typescript": "^5.4.5"
|
|
42
|
+
},
|
|
43
|
+
"keywords": [
|
|
44
|
+
"firecrawl",
|
|
45
|
+
"mendable",
|
|
46
|
+
"crawler",
|
|
47
|
+
"web",
|
|
48
|
+
"scraper",
|
|
49
|
+
"api",
|
|
50
|
+
"sdk"
|
|
51
|
+
]
|
|
52
|
+
}
|