@rewritejs/sdk 1.0.0 → 1.0.1

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/index.js CHANGED
@@ -14,8 +14,33 @@ class HTTPError extends Error {
14
14
  }
15
15
  }
16
16
 
17
+ class RateLimitError extends HTTPError {
18
+ limit;
19
+ global;
20
+ retryAfter;
21
+ constructor(message, url, method, context) {
22
+ super(message, 429, url, method);
23
+ this.limit = context.limit;
24
+ this.global = context.isGlobal;
25
+ this.retryAfter = context.retryAfter;
26
+ this.name = "RateLimitError";
27
+ }
28
+ }
29
+
30
+ class RewriteError extends Error {
31
+ message;
32
+ code;
33
+ detailed;
34
+ constructor(message, code, detailed) {
35
+ super(message);
36
+ this.message = message;
37
+ this.code = code;
38
+ this.detailed = detailed;
39
+ }
40
+ }
41
+
17
42
  // node_modules/@rewritejs/rest/dist/utils.js
18
- var createURL = (route, query, baseURL = "https://api.userewrite.me") => {
43
+ var createURL = (route, query, baseURL = "https://api.rewritetoday.com") => {
19
44
  const url = `${baseURL}/v1${route}`;
20
45
  return query ? `${url}?${new URLSearchParams(query)}` : url;
21
46
  };
@@ -30,6 +55,7 @@ var backoff = (attempt) => {
30
55
  return Math.floor(exp + jitter);
31
56
  };
32
57
  var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
58
+ var RATE_LIMIT_STATUS = 429;
33
59
 
34
60
  // node_modules/@rewritejs/rest/dist/client.js
35
61
  class REST {
@@ -38,6 +64,7 @@ class REST {
38
64
  constructor(options) {
39
65
  this.options = typeof options === "string" ? { auth: options } : options;
40
66
  this.headers = {
67
+ "Content-Type": "application/json",
41
68
  ...this.options.headers,
42
69
  Authorization: `Bearer ${this.options.auth}`
43
70
  };
@@ -63,7 +90,7 @@ class REST {
63
90
  return this.fetch(route, { data, ...options, method: "PATCH" });
64
91
  }
65
92
  async fetch(route, options, attempt = 0) {
66
- const response = await this.createRequest(route, options);
93
+ const response = await this.prefetch(route, options);
67
94
  if (!response.ok)
68
95
  return this.handleError({
69
96
  route,
@@ -77,19 +104,62 @@ class REST {
77
104
  }
78
105
  async handleError({ route, method, options, attempt, response }) {
79
106
  if (!isRetryableStatus(response.status)) {
80
- const { error } = await response.json();
81
- throw new HTTPError(error, response.status, response.url, method);
107
+ const { code, error, message } = await response.json();
108
+ throw new RewriteError(message, code, error.detailed);
82
109
  }
83
- const { retry } = this.options;
110
+ const { onRateLimit, retry } = this.options;
111
+ const rateLimitContext = response.status === RATE_LIMIT_STATUS ? this.parseRateLimitContext(response) : null;
84
112
  if (attempt >= (retry?.max ?? 3))
85
- throw new HTTPError("Max retries reached", response.status, response.url, method);
113
+ throw this.buildRetryExceededError(response, method, rateLimitContext);
114
+ if (rateLimitContext && onRateLimit)
115
+ await onRateLimit(rateLimitContext);
86
116
  if (retry?.onRetry)
87
117
  await retry.onRetry({ route, attempt, options, response, method });
88
- const delay = (retry?.delay ?? backoff)(attempt);
118
+ const delay = this.resolveRetryDelay(attempt, retry, rateLimitContext);
89
119
  await sleep(delay);
90
120
  return this.fetch(route, options, attempt + 1);
91
121
  }
92
- createRequest(route, options) {
122
+ buildRetryExceededError(response, method, rateLimitContext) {
123
+ if (rateLimitContext)
124
+ return new RateLimitError("Rate limit has not been reset yet", response.url, method, rateLimitContext);
125
+ return new HTTPError("Max retries reached", response.status, response.url, method);
126
+ }
127
+ resolveRetryDelay(attempt, retry, rateLimitContext) {
128
+ const retryAfterDelay = rateLimitContext?.retryAfter ?? 0;
129
+ if (retryAfterDelay > 0)
130
+ return retryAfterDelay;
131
+ return (retry?.delay ?? backoff)(attempt);
132
+ }
133
+ parseRateLimitContext(response) {
134
+ const { headers } = response;
135
+ const xRateLimitRetryAfter = this.parseNumberHeader(headers, "X-RateLimit-Retry-After");
136
+ const retryAfter = xRateLimitRetryAfter > 0 ? xRateLimitRetryAfter : this.parseRetryAfterHeader(headers.get("Retry-After"));
137
+ return {
138
+ retryAfter,
139
+ limit: Number(headers.get("X-RateLimit-Limit")),
140
+ isGlobal: this.parseBooleanHeader(headers, "X-RateLimit-Global")
141
+ };
142
+ }
143
+ parseNumberHeader(headers, key) {
144
+ const value = headers.get(key);
145
+ if (!value)
146
+ return 0;
147
+ const parsed = Number(value);
148
+ return Number.isFinite(parsed) ? parsed : 0;
149
+ }
150
+ parseBooleanHeader(headers, key) {
151
+ return headers.get(key)?.toLowerCase() === "true";
152
+ }
153
+ parseRetryAfterHeader(header) {
154
+ if (!header)
155
+ return 0;
156
+ const seconds = Number(header);
157
+ if (Number.isFinite(seconds))
158
+ return Math.max(0, Math.ceil(seconds * 1000));
159
+ const date = Date.parse(header);
160
+ return Number.isNaN(date) ? 0 : Math.max(0, date - Date.now());
161
+ }
162
+ prefetch(route, options) {
93
163
  const timeout = options.timeout ?? this.options.timeout ?? FIVE_SECONDS_IN_MS;
94
164
  const url = createURL(route, options.query, this.options.baseURL);
95
165
  return fetch(url, {
@@ -306,7 +376,7 @@ class Rewrite {
306
376
  }
307
377
  }
308
378
  // src/version.ts
309
- var version = "1.0.0";
379
+ var version = "1.0.1";
310
380
  export {
311
381
  version,
312
382
  Rewrite
package/dist/version.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  /**
2
2
  * Current version of [@rewritejs/sdk](https://www.npmjs.com/package/@rewritejs/sdk).
3
3
  */
4
- export declare const version: "1.0.0";
4
+ export declare const version: "1.0.1";
package/package.json CHANGED
@@ -3,16 +3,16 @@
3
3
  "module": "src/index.ts",
4
4
  "type": "module",
5
5
  "private": false,
6
- "version": "1.0.0",
6
+ "version": "1.0.1",
7
7
  "devDependencies": {
8
8
  "@biomejs/biome": "^2.4.2",
9
9
  "@types/bun": "latest"
10
10
  },
11
11
  "peerDependencies": {
12
- "typescript": "^5"
12
+ "typescript": "^5.9.3"
13
13
  },
14
14
  "dependencies": {
15
- "@rewritejs/rest": "^1.0.1",
15
+ "@rewritejs/rest": "^1.0.2",
16
16
  "@rewritejs/types": "^1.0.0"
17
17
  },
18
18
  "main": "./dist/index.js",