wellmarked 1.1.0
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/LICENSE +21 -0
- package/README.md +233 -0
- package/dist/cjs/client.cjs +332 -0
- package/dist/cjs/client.d.ts +173 -0
- package/dist/cjs/errors.cjs +143 -0
- package/dist/cjs/errors.d.ts +66 -0
- package/dist/cjs/index.cjs +31 -0
- package/dist/cjs/index.d.ts +15 -0
- package/dist/cjs/models.cjs +166 -0
- package/dist/cjs/models.d.ts +141 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/version.cjs +4 -0
- package/dist/cjs/version.d.ts +1 -0
- package/dist/esm/client.d.ts +173 -0
- package/dist/esm/client.js +330 -0
- package/dist/esm/errors.d.ts +66 -0
- package/dist/esm/errors.js +130 -0
- package/dist/esm/index.d.ts +15 -0
- package/dist/esm/index.js +15 -0
- package/dist/esm/models.d.ts +141 -0
- package/dist/esm/models.js +154 -0
- package/dist/esm/version.d.ts +1 -0
- package/dist/esm/version.js +1 -0
- package/dist/types/client.d.ts +173 -0
- package/dist/types/errors.d.ts +66 -0
- package/dist/types/index.d.ts +15 -0
- package/dist/types/models.d.ts +141 -0
- package/dist/types/version.d.ts +1 -0
- package/package.json +73 -0
- package/src/client.ts +463 -0
- package/src/errors.ts +162 -0
- package/src/index.ts +45 -0
- package/src/models.ts +311 -0
- package/src/version.ts +1 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Exception hierarchy for the WellMarked SDK.
|
|
3
|
+
*
|
|
4
|
+
* Every HTTP error returned by the API is translated into a typed error
|
|
5
|
+
* whose class corresponds to the HTTP status and whose `code` matches the
|
|
6
|
+
* `error.code` field in the response body. Catch `WellMarkedError` for
|
|
7
|
+
* anything raised by the SDK; catch a more specific subclass when you want
|
|
8
|
+
* to handle one failure mode.
|
|
9
|
+
*/
|
|
10
|
+
export interface WellMarkedErrorOptions {
|
|
11
|
+
code?: string | undefined;
|
|
12
|
+
statusCode?: number | undefined;
|
|
13
|
+
retryAfter?: number | undefined;
|
|
14
|
+
requestId?: string | undefined;
|
|
15
|
+
cause?: unknown;
|
|
16
|
+
}
|
|
17
|
+
export declare class WellMarkedError extends Error {
|
|
18
|
+
readonly code: string | undefined;
|
|
19
|
+
readonly statusCode: number | undefined;
|
|
20
|
+
readonly retryAfter: number | undefined;
|
|
21
|
+
readonly requestId: string | undefined;
|
|
22
|
+
constructor(message: string, options?: WellMarkedErrorOptions);
|
|
23
|
+
}
|
|
24
|
+
/** Raised when the SDK couldn't reach the API (DNS, TCP, TLS, timeout). */
|
|
25
|
+
export declare class APIConnectionError extends WellMarkedError {
|
|
26
|
+
constructor(message: string, options?: WellMarkedErrorOptions);
|
|
27
|
+
}
|
|
28
|
+
/** Raised for any non-2xx response from the API. */
|
|
29
|
+
export declare class APIStatusError extends WellMarkedError {
|
|
30
|
+
constructor(message: string, options?: WellMarkedErrorOptions);
|
|
31
|
+
}
|
|
32
|
+
/** 401 — missing or invalid API key. */
|
|
33
|
+
export declare class AuthenticationError extends APIStatusError {
|
|
34
|
+
constructor(message: string, options?: WellMarkedErrorOptions);
|
|
35
|
+
}
|
|
36
|
+
/** 403 — account inactive, plan does not allow this operation, or job belongs to another user. */
|
|
37
|
+
export declare class PermissionDeniedError extends APIStatusError {
|
|
38
|
+
constructor(message: string, options?: WellMarkedErrorOptions);
|
|
39
|
+
}
|
|
40
|
+
/** 404 — job not found or expired past the 6-hour retention window. */
|
|
41
|
+
export declare class NotFoundError extends APIStatusError {
|
|
42
|
+
constructor(message: string, options?: WellMarkedErrorOptions);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* 422 — request was syntactically valid but couldn't be fulfilled.
|
|
46
|
+
*
|
|
47
|
+
* Common `code` values:
|
|
48
|
+
* - `no_content` — could not identify main content on the page
|
|
49
|
+
* - `target_timeout` — the target URL timed out
|
|
50
|
+
* - `js_rendering_disabled` — `renderJs=true` but the server has it off
|
|
51
|
+
* - `bulk_cap_exceeded` — more URLs than the plan allows per request
|
|
52
|
+
* - `crawl_depth_exceeded` — requested depth above the plan cap
|
|
53
|
+
*/
|
|
54
|
+
export declare class UnprocessableEntityError extends APIStatusError {
|
|
55
|
+
constructor(message: string, options?: WellMarkedErrorOptions);
|
|
56
|
+
}
|
|
57
|
+
/** 429 — monthly plan limit reached. `retryAfter` is the number of seconds until reset. */
|
|
58
|
+
export declare class RateLimitError extends APIStatusError {
|
|
59
|
+
constructor(message: string, options?: WellMarkedErrorOptions);
|
|
60
|
+
}
|
|
61
|
+
/** 5xx — something went wrong on the API side. */
|
|
62
|
+
export declare class InternalServerError extends APIStatusError {
|
|
63
|
+
constructor(message: string, options?: WellMarkedErrorOptions);
|
|
64
|
+
}
|
|
65
|
+
/** Build the right error subclass for a given HTTP status + JSON body. */
|
|
66
|
+
export declare function fromResponse(statusCode: number, body: unknown, requestId?: string): APIStatusError;
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Exception hierarchy for the WellMarked SDK.
|
|
3
|
+
*
|
|
4
|
+
* Every HTTP error returned by the API is translated into a typed error
|
|
5
|
+
* whose class corresponds to the HTTP status and whose `code` matches the
|
|
6
|
+
* `error.code` field in the response body. Catch `WellMarkedError` for
|
|
7
|
+
* anything raised by the SDK; catch a more specific subclass when you want
|
|
8
|
+
* to handle one failure mode.
|
|
9
|
+
*/
|
|
10
|
+
export class WellMarkedError extends Error {
|
|
11
|
+
constructor(message, options = {}) {
|
|
12
|
+
super(message);
|
|
13
|
+
this.name = "WellMarkedError";
|
|
14
|
+
this.code = options.code;
|
|
15
|
+
this.statusCode = options.statusCode;
|
|
16
|
+
this.retryAfter = options.retryAfter;
|
|
17
|
+
this.requestId = options.requestId;
|
|
18
|
+
if (options.cause !== undefined) {
|
|
19
|
+
this.cause = options.cause;
|
|
20
|
+
}
|
|
21
|
+
// Maintain proper prototype chain when transpiled to ES5.
|
|
22
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/** Raised when the SDK couldn't reach the API (DNS, TCP, TLS, timeout). */
|
|
26
|
+
export class APIConnectionError extends WellMarkedError {
|
|
27
|
+
constructor(message, options = {}) {
|
|
28
|
+
super(message, options);
|
|
29
|
+
this.name = "APIConnectionError";
|
|
30
|
+
Object.setPrototypeOf(this, APIConnectionError.prototype);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/** Raised for any non-2xx response from the API. */
|
|
34
|
+
export class APIStatusError extends WellMarkedError {
|
|
35
|
+
constructor(message, options = {}) {
|
|
36
|
+
super(message, options);
|
|
37
|
+
this.name = "APIStatusError";
|
|
38
|
+
Object.setPrototypeOf(this, APIStatusError.prototype);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/** 401 — missing or invalid API key. */
|
|
42
|
+
export class AuthenticationError extends APIStatusError {
|
|
43
|
+
constructor(message, options = {}) {
|
|
44
|
+
super(message, options);
|
|
45
|
+
this.name = "AuthenticationError";
|
|
46
|
+
Object.setPrototypeOf(this, AuthenticationError.prototype);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/** 403 — account inactive, plan does not allow this operation, or job belongs to another user. */
|
|
50
|
+
export class PermissionDeniedError extends APIStatusError {
|
|
51
|
+
constructor(message, options = {}) {
|
|
52
|
+
super(message, options);
|
|
53
|
+
this.name = "PermissionDeniedError";
|
|
54
|
+
Object.setPrototypeOf(this, PermissionDeniedError.prototype);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/** 404 — job not found or expired past the 6-hour retention window. */
|
|
58
|
+
export class NotFoundError extends APIStatusError {
|
|
59
|
+
constructor(message, options = {}) {
|
|
60
|
+
super(message, options);
|
|
61
|
+
this.name = "NotFoundError";
|
|
62
|
+
Object.setPrototypeOf(this, NotFoundError.prototype);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* 422 — request was syntactically valid but couldn't be fulfilled.
|
|
67
|
+
*
|
|
68
|
+
* Common `code` values:
|
|
69
|
+
* - `no_content` — could not identify main content on the page
|
|
70
|
+
* - `target_timeout` — the target URL timed out
|
|
71
|
+
* - `js_rendering_disabled` — `renderJs=true` but the server has it off
|
|
72
|
+
* - `bulk_cap_exceeded` — more URLs than the plan allows per request
|
|
73
|
+
* - `crawl_depth_exceeded` — requested depth above the plan cap
|
|
74
|
+
*/
|
|
75
|
+
export class UnprocessableEntityError extends APIStatusError {
|
|
76
|
+
constructor(message, options = {}) {
|
|
77
|
+
super(message, options);
|
|
78
|
+
this.name = "UnprocessableEntityError";
|
|
79
|
+
Object.setPrototypeOf(this, UnprocessableEntityError.prototype);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/** 429 — monthly plan limit reached. `retryAfter` is the number of seconds until reset. */
|
|
83
|
+
export class RateLimitError extends APIStatusError {
|
|
84
|
+
constructor(message, options = {}) {
|
|
85
|
+
super(message, options);
|
|
86
|
+
this.name = "RateLimitError";
|
|
87
|
+
Object.setPrototypeOf(this, RateLimitError.prototype);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/** 5xx — something went wrong on the API side. */
|
|
91
|
+
export class InternalServerError extends APIStatusError {
|
|
92
|
+
constructor(message, options = {}) {
|
|
93
|
+
super(message, options);
|
|
94
|
+
this.name = "InternalServerError";
|
|
95
|
+
Object.setPrototypeOf(this, InternalServerError.prototype);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
const STATUS_TO_EXC = {
|
|
99
|
+
401: AuthenticationError,
|
|
100
|
+
403: PermissionDeniedError,
|
|
101
|
+
404: NotFoundError,
|
|
102
|
+
422: UnprocessableEntityError,
|
|
103
|
+
429: RateLimitError,
|
|
104
|
+
};
|
|
105
|
+
/** Build the right error subclass for a given HTTP status + JSON body. */
|
|
106
|
+
export function fromResponse(statusCode, body, requestId) {
|
|
107
|
+
let code;
|
|
108
|
+
let message = `HTTP ${statusCode}`;
|
|
109
|
+
let retryAfter;
|
|
110
|
+
if (body && typeof body === "object" && "error" in body) {
|
|
111
|
+
const err = body.error;
|
|
112
|
+
if (err && typeof err === "object") {
|
|
113
|
+
const e = err;
|
|
114
|
+
if (typeof e.code === "string")
|
|
115
|
+
code = e.code;
|
|
116
|
+
if (typeof e.message === "string")
|
|
117
|
+
message = e.message;
|
|
118
|
+
if (typeof e.retry_after === "number")
|
|
119
|
+
retryAfter = e.retry_after;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
let Ctor;
|
|
123
|
+
if (statusCode >= 500) {
|
|
124
|
+
Ctor = InternalServerError;
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
Ctor = STATUS_TO_EXC[statusCode] ?? APIStatusError;
|
|
128
|
+
}
|
|
129
|
+
return new Ctor(message, { code, statusCode, retryAfter, requestId });
|
|
130
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Official JavaScript/TypeScript SDK for the WellMarked API.
|
|
3
|
+
*
|
|
4
|
+
* import { WellMarked } from "wellmarked";
|
|
5
|
+
*
|
|
6
|
+
* const wm = new WellMarked({ apiKey: "wm_..." });
|
|
7
|
+
* const result = await wm.extract("https://example.com/article");
|
|
8
|
+
* console.log(result.markdown);
|
|
9
|
+
*
|
|
10
|
+
* See https://wellmarked.io/docs for the full API reference.
|
|
11
|
+
*/
|
|
12
|
+
export { VERSION } from "./version.js";
|
|
13
|
+
export { WellMarked, type WellMarkedOptions, type ExtractOptions, type BulkOptions, type CrawlOptions, type WaitForJobOptions, } from "./client.js";
|
|
14
|
+
export { type BulkItem, type BulkJob, type CrawlItem, type CrawlJob, type ExtractionMeta, type ExtractResult, type JobStatus, type RotatedKey, type TruncatedReason, type Usage, isBulkJob, isCrawlJob, } from "./models.js";
|
|
15
|
+
export { APIConnectionError, APIStatusError, AuthenticationError, InternalServerError, NotFoundError, PermissionDeniedError, RateLimitError, UnprocessableEntityError, WellMarkedError, } from "./errors.js";
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Official JavaScript/TypeScript SDK for the WellMarked API.
|
|
3
|
+
*
|
|
4
|
+
* import { WellMarked } from "wellmarked";
|
|
5
|
+
*
|
|
6
|
+
* const wm = new WellMarked({ apiKey: "wm_..." });
|
|
7
|
+
* const result = await wm.extract("https://example.com/article");
|
|
8
|
+
* console.log(result.markdown);
|
|
9
|
+
*
|
|
10
|
+
* See https://wellmarked.io/docs for the full API reference.
|
|
11
|
+
*/
|
|
12
|
+
export { VERSION } from "./version.js";
|
|
13
|
+
export { WellMarked, } from "./client.js";
|
|
14
|
+
export { isBulkJob, isCrawlJob, } from "./models.js";
|
|
15
|
+
export { APIConnectionError, APIStatusError, AuthenticationError, InternalServerError, NotFoundError, PermissionDeniedError, RateLimitError, UnprocessableEntityError, WellMarkedError, } from "./errors.js";
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed response objects returned by the WellMarked SDK.
|
|
3
|
+
*
|
|
4
|
+
* These mirror the JSON shapes documented at https://api.wellmarked.io/docs.
|
|
5
|
+
*
|
|
6
|
+
* Response objects carry only the body fields documented in the API
|
|
7
|
+
* reference — they do not surface HTTP headers. Quota state lives on the
|
|
8
|
+
* account, so use `WellMarked.getUsage()` to read it.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Per-article metadata returned with each extraction.
|
|
12
|
+
*
|
|
13
|
+
* `date` is the article's published date as a string (often `null` — not
|
|
14
|
+
* every page publishes one). `retrievedAt` is the timestamp at which
|
|
15
|
+
* WellMarked actually fetched the page, populated on every successful
|
|
16
|
+
* extraction. The two fields are independent.
|
|
17
|
+
*/
|
|
18
|
+
export interface ExtractionMeta {
|
|
19
|
+
url: string;
|
|
20
|
+
title: string | null;
|
|
21
|
+
author: string | null;
|
|
22
|
+
date: string | null;
|
|
23
|
+
retrievedAt: Date | null;
|
|
24
|
+
}
|
|
25
|
+
export declare function extractionMetaFromDict(data: Record<string, unknown>): ExtractionMeta;
|
|
26
|
+
/** Result of `POST /extract`. */
|
|
27
|
+
export interface ExtractResult {
|
|
28
|
+
markdown: string;
|
|
29
|
+
metadata: ExtractionMeta;
|
|
30
|
+
requestId: string;
|
|
31
|
+
}
|
|
32
|
+
export declare function extractResultFromResponse(body: Record<string, unknown>): ExtractResult;
|
|
33
|
+
/**
|
|
34
|
+
* One entry in a bulk job's `results` list.
|
|
35
|
+
*
|
|
36
|
+
* On success, `markdown` and `metadata` are populated and `error` is null.
|
|
37
|
+
* On a per-URL failure, `markdown`/`metadata` are null and `error` carries
|
|
38
|
+
* an API error code (e.g. `target_timeout`).
|
|
39
|
+
*/
|
|
40
|
+
export interface BulkItem {
|
|
41
|
+
url: string;
|
|
42
|
+
markdown: string | null;
|
|
43
|
+
metadata: ExtractionMeta | null;
|
|
44
|
+
error: string | null;
|
|
45
|
+
/** True when the item completed successfully (no error + has markdown). */
|
|
46
|
+
readonly ok: boolean;
|
|
47
|
+
}
|
|
48
|
+
export declare function bulkItemFromDict(data: Record<string, unknown>): BulkItem;
|
|
49
|
+
/** "queued" | "processing" | "done" */
|
|
50
|
+
export type JobStatus = "queued" | "processing" | "done";
|
|
51
|
+
/**
|
|
52
|
+
* Status of a bulk extraction job.
|
|
53
|
+
*
|
|
54
|
+
* Returned from both `POST /bulk` and `GET /bulk/{jobId}`. Also one of the
|
|
55
|
+
* two possible return types from the polymorphic `WellMarked.getJob` and
|
|
56
|
+
* `WellMarked.waitForJob` — use the `kind` discriminator (or a type guard)
|
|
57
|
+
* to distinguish from `CrawlJob` if you need to read crawl-specific fields.
|
|
58
|
+
*/
|
|
59
|
+
export interface BulkJob {
|
|
60
|
+
readonly kind: "bulk";
|
|
61
|
+
jobId: string;
|
|
62
|
+
status: JobStatus;
|
|
63
|
+
total: number;
|
|
64
|
+
completed: number;
|
|
65
|
+
results: BulkItem[];
|
|
66
|
+
createdAt: Date | null;
|
|
67
|
+
finishedAt: Date | null;
|
|
68
|
+
/** True when `status === "done"`. */
|
|
69
|
+
readonly done: boolean;
|
|
70
|
+
}
|
|
71
|
+
export declare function bulkJobFromResponse(body: Record<string, unknown>): BulkJob;
|
|
72
|
+
/**
|
|
73
|
+
* One page in a crawl job's `results` list.
|
|
74
|
+
*
|
|
75
|
+
* Shape mirrors `BulkItem` with an added `depth` field showing how far
|
|
76
|
+
* from the root URL this page sits in the BFS.
|
|
77
|
+
*/
|
|
78
|
+
export interface CrawlItem {
|
|
79
|
+
url: string;
|
|
80
|
+
depth: number;
|
|
81
|
+
markdown: string | null;
|
|
82
|
+
metadata: ExtractionMeta | null;
|
|
83
|
+
error: string | null;
|
|
84
|
+
/** True when the page completed successfully (no error + has markdown). */
|
|
85
|
+
readonly ok: boolean;
|
|
86
|
+
}
|
|
87
|
+
export declare function crawlItemFromDict(data: Record<string, unknown>): CrawlItem;
|
|
88
|
+
export type TruncatedReason = "page_cap_reached" | "quota_exhausted";
|
|
89
|
+
/**
|
|
90
|
+
* Status of a crawl job. Returned from `POST /crawl` and `GET /crawl/{jobId}`.
|
|
91
|
+
*
|
|
92
|
+
* Two crawl-only fields:
|
|
93
|
+
* - `truncated` — true when the crawl stopped before exhausting
|
|
94
|
+
* the frontier (depth/page cap or quota).
|
|
95
|
+
* - `truncatedReason` — `"page_cap_reached"` | `"quota_exhausted"` |
|
|
96
|
+
* `null`.
|
|
97
|
+
*/
|
|
98
|
+
export interface CrawlJob {
|
|
99
|
+
readonly kind: "crawl";
|
|
100
|
+
jobId: string;
|
|
101
|
+
status: JobStatus;
|
|
102
|
+
total: number;
|
|
103
|
+
completed: number;
|
|
104
|
+
results: CrawlItem[];
|
|
105
|
+
truncated: boolean;
|
|
106
|
+
truncatedReason: TruncatedReason | null;
|
|
107
|
+
createdAt: Date | null;
|
|
108
|
+
finishedAt: Date | null;
|
|
109
|
+
/** True when `status === "done"`. */
|
|
110
|
+
readonly done: boolean;
|
|
111
|
+
}
|
|
112
|
+
export declare function crawlJobFromResponse(body: Record<string, unknown>): CrawlJob;
|
|
113
|
+
/**
|
|
114
|
+
* Result of `GET /usage` — current-period quota state.
|
|
115
|
+
*
|
|
116
|
+
* This is the source of truth for rate-limit / quota information. The SDK
|
|
117
|
+
* does not surface `X-RateLimit-*` headers on extract/bulk responses;
|
|
118
|
+
* call `WellMarked.getUsage()` instead.
|
|
119
|
+
*/
|
|
120
|
+
export interface Usage {
|
|
121
|
+
plan: string;
|
|
122
|
+
period: string;
|
|
123
|
+
used: number;
|
|
124
|
+
limit: number;
|
|
125
|
+
remaining: number;
|
|
126
|
+
}
|
|
127
|
+
export declare function usageFromResponse(body: Record<string, unknown>): Usage;
|
|
128
|
+
/**
|
|
129
|
+
* Result of `POST /keys/rotate`.
|
|
130
|
+
*
|
|
131
|
+
* `apiKey` is the new raw key — store it before discarding this object,
|
|
132
|
+
* there is no recovery flow. The previous key is invalidated the moment
|
|
133
|
+
* the rotation call returns 200.
|
|
134
|
+
*/
|
|
135
|
+
export interface RotatedKey {
|
|
136
|
+
apiKey: string;
|
|
137
|
+
rotatedAt: Date | null;
|
|
138
|
+
}
|
|
139
|
+
export declare function rotatedKeyFromResponse(body: Record<string, unknown>): RotatedKey;
|
|
140
|
+
export declare function isBulkJob(job: BulkJob | CrawlJob): job is BulkJob;
|
|
141
|
+
export declare function isCrawlJob(job: BulkJob | CrawlJob): job is CrawlJob;
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed response objects returned by the WellMarked SDK.
|
|
3
|
+
*
|
|
4
|
+
* These mirror the JSON shapes documented at https://api.wellmarked.io/docs.
|
|
5
|
+
*
|
|
6
|
+
* Response objects carry only the body fields documented in the API
|
|
7
|
+
* reference — they do not surface HTTP headers. Quota state lives on the
|
|
8
|
+
* account, so use `WellMarked.getUsage()` to read it.
|
|
9
|
+
*/
|
|
10
|
+
function parseDate(value) {
|
|
11
|
+
if (value === null || value === undefined)
|
|
12
|
+
return null;
|
|
13
|
+
if (value instanceof Date)
|
|
14
|
+
return value;
|
|
15
|
+
if (typeof value !== "string")
|
|
16
|
+
return null;
|
|
17
|
+
const d = new Date(value);
|
|
18
|
+
return Number.isNaN(d.getTime()) ? null : d;
|
|
19
|
+
}
|
|
20
|
+
export function extractionMetaFromDict(data) {
|
|
21
|
+
return {
|
|
22
|
+
url: typeof data.url === "string" ? data.url : "",
|
|
23
|
+
title: typeof data.title === "string" ? data.title : null,
|
|
24
|
+
author: typeof data.author === "string" ? data.author : null,
|
|
25
|
+
date: typeof data.date === "string" ? data.date : null,
|
|
26
|
+
retrievedAt: parseDate(data.retrieved_at),
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export function extractResultFromResponse(body) {
|
|
30
|
+
const rawMeta = body.metadata && typeof body.metadata === "object"
|
|
31
|
+
? body.metadata
|
|
32
|
+
: {};
|
|
33
|
+
return {
|
|
34
|
+
markdown: typeof body.markdown === "string" ? body.markdown : "",
|
|
35
|
+
metadata: extractionMetaFromDict(rawMeta),
|
|
36
|
+
requestId: typeof body.request_id === "string" ? body.request_id : "",
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
export function bulkItemFromDict(data) {
|
|
40
|
+
const rawMeta = data.metadata;
|
|
41
|
+
const url = typeof data.url === "string" ? data.url : "";
|
|
42
|
+
const markdown = typeof data.markdown === "string" ? data.markdown : null;
|
|
43
|
+
const error = typeof data.error === "string" ? data.error : null;
|
|
44
|
+
const metadata = rawMeta && typeof rawMeta === "object"
|
|
45
|
+
? extractionMetaFromDict(rawMeta)
|
|
46
|
+
: null;
|
|
47
|
+
return {
|
|
48
|
+
url,
|
|
49
|
+
markdown,
|
|
50
|
+
metadata,
|
|
51
|
+
error,
|
|
52
|
+
get ok() {
|
|
53
|
+
return error === null && markdown !== null;
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
export function bulkJobFromResponse(body) {
|
|
58
|
+
const rawResults = Array.isArray(body.results) ? body.results : [];
|
|
59
|
+
const status = typeof body.status === "string" ? body.status : "queued";
|
|
60
|
+
const jobId = typeof body.job_id === "string" ? body.job_id : "";
|
|
61
|
+
const total = typeof body.total === "number" ? body.total : 0;
|
|
62
|
+
const completed = typeof body.completed === "number" ? body.completed : 0;
|
|
63
|
+
const createdAt = parseDate(body.created_at);
|
|
64
|
+
const finishedAt = parseDate(body.finished_at);
|
|
65
|
+
const results = rawResults
|
|
66
|
+
.filter((r) => r !== null && typeof r === "object")
|
|
67
|
+
.map(bulkItemFromDict);
|
|
68
|
+
return {
|
|
69
|
+
kind: "bulk",
|
|
70
|
+
jobId,
|
|
71
|
+
status,
|
|
72
|
+
total,
|
|
73
|
+
completed,
|
|
74
|
+
results,
|
|
75
|
+
createdAt,
|
|
76
|
+
finishedAt,
|
|
77
|
+
get done() {
|
|
78
|
+
return status === "done";
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
export function crawlItemFromDict(data) {
|
|
83
|
+
const rawMeta = data.metadata;
|
|
84
|
+
const url = typeof data.url === "string" ? data.url : "";
|
|
85
|
+
const depth = typeof data.depth === "number" ? data.depth : 0;
|
|
86
|
+
const markdown = typeof data.markdown === "string" ? data.markdown : null;
|
|
87
|
+
const error = typeof data.error === "string" ? data.error : null;
|
|
88
|
+
const metadata = rawMeta && typeof rawMeta === "object"
|
|
89
|
+
? extractionMetaFromDict(rawMeta)
|
|
90
|
+
: null;
|
|
91
|
+
return {
|
|
92
|
+
url,
|
|
93
|
+
depth,
|
|
94
|
+
markdown,
|
|
95
|
+
metadata,
|
|
96
|
+
error,
|
|
97
|
+
get ok() {
|
|
98
|
+
return error === null && markdown !== null;
|
|
99
|
+
},
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
export function crawlJobFromResponse(body) {
|
|
103
|
+
const rawResults = Array.isArray(body.results) ? body.results : [];
|
|
104
|
+
const status = typeof body.status === "string" ? body.status : "queued";
|
|
105
|
+
const jobId = typeof body.job_id === "string" ? body.job_id : "";
|
|
106
|
+
const total = typeof body.total === "number" ? body.total : 0;
|
|
107
|
+
const completed = typeof body.completed === "number" ? body.completed : 0;
|
|
108
|
+
const createdAt = parseDate(body.created_at);
|
|
109
|
+
const finishedAt = parseDate(body.finished_at);
|
|
110
|
+
const truncated = body.truncated === true;
|
|
111
|
+
const truncatedReason = typeof body.truncated_reason === "string"
|
|
112
|
+
? body.truncated_reason
|
|
113
|
+
: null;
|
|
114
|
+
const results = rawResults
|
|
115
|
+
.filter((r) => r !== null && typeof r === "object")
|
|
116
|
+
.map(crawlItemFromDict);
|
|
117
|
+
return {
|
|
118
|
+
kind: "crawl",
|
|
119
|
+
jobId,
|
|
120
|
+
status,
|
|
121
|
+
total,
|
|
122
|
+
completed,
|
|
123
|
+
results,
|
|
124
|
+
truncated,
|
|
125
|
+
truncatedReason,
|
|
126
|
+
createdAt,
|
|
127
|
+
finishedAt,
|
|
128
|
+
get done() {
|
|
129
|
+
return status === "done";
|
|
130
|
+
},
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
export function usageFromResponse(body) {
|
|
134
|
+
return {
|
|
135
|
+
plan: typeof body.plan === "string" ? body.plan : "",
|
|
136
|
+
period: typeof body.period === "string" ? body.period : "",
|
|
137
|
+
used: typeof body.used === "number" ? body.used : 0,
|
|
138
|
+
limit: typeof body.limit === "number" ? body.limit : 0,
|
|
139
|
+
remaining: typeof body.remaining === "number" ? body.remaining : 0,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
export function rotatedKeyFromResponse(body) {
|
|
143
|
+
return {
|
|
144
|
+
apiKey: typeof body.api_key === "string" ? body.api_key : "",
|
|
145
|
+
rotatedAt: parseDate(body.rotated_at),
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
// ── Type guards ──────────────────────────────────────────────────────────────
|
|
149
|
+
export function isBulkJob(job) {
|
|
150
|
+
return job.kind === "bulk";
|
|
151
|
+
}
|
|
152
|
+
export function isCrawlJob(job) {
|
|
153
|
+
return job.kind === "crawl";
|
|
154
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const VERSION = "1.0.0";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const VERSION = "1.0.0";
|