@supabase/postgrest-js 2.114.0 → 2.115.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/dist/index.cjs CHANGED
@@ -1,34 +1,5 @@
1
1
  Object.defineProperty(exports, '__esModule', { value: true });
2
2
 
3
- //#region src/types/common/common.ts
4
- /**
5
- * Default number of retry attempts.
6
- */
7
- const DEFAULT_MAX_RETRIES = 3;
8
- /**
9
- * Default exponential backoff delay function.
10
- * Delays: 1s, 2s, 4s, 8s, ... (max 30s)
11
- *
12
- * @param attemptIndex - Zero-based index of the retry attempt
13
- * @returns Delay in milliseconds before the next retry
14
- */
15
- const getRetryDelay = (attemptIndex) => Math.min(1e3 * 2 ** attemptIndex, 3e4);
16
- /**
17
- * Status codes that are safe to retry.
18
- * 520 = Cloudflare timeout/connection errors (transient)
19
- * 503 = PostgREST schema cache not yet loaded (transient, signals retry via Retry-After header)
20
- */
21
- const RETRYABLE_STATUS_CODES = [520, 503];
22
- /**
23
- * HTTP methods that are safe to retry (idempotent operations).
24
- */
25
- const RETRYABLE_METHODS = [
26
- "GET",
27
- "HEAD",
28
- "OPTIONS"
29
- ];
30
-
31
- //#endregion
32
3
  //#region src/PostgrestError.ts
33
4
  /**
34
5
  * Error format
@@ -86,6 +57,35 @@ var PostgrestError = class extends Error {
86
57
  }
87
58
  };
88
59
 
60
+ //#endregion
61
+ //#region src/types/common/common.ts
62
+ /**
63
+ * Default number of retry attempts.
64
+ */
65
+ const DEFAULT_MAX_RETRIES = 3;
66
+ /**
67
+ * Default exponential backoff delay function.
68
+ * Delays: 1s, 2s, 4s, 8s, ... (max 30s)
69
+ *
70
+ * @param attemptIndex - Zero-based index of the retry attempt
71
+ * @returns Delay in milliseconds before the next retry
72
+ */
73
+ const getRetryDelay = (attemptIndex) => Math.min(1e3 * 2 ** attemptIndex, 3e4);
74
+ /**
75
+ * Status codes that are safe to retry.
76
+ * 520 = Cloudflare timeout/connection errors (transient)
77
+ * 503 = PostgREST schema cache not yet loaded (transient, signals retry via Retry-After header)
78
+ */
79
+ const RETRYABLE_STATUS_CODES = [520, 503];
80
+ /**
81
+ * HTTP methods that are safe to retry (idempotent operations).
82
+ */
83
+ const RETRYABLE_METHODS = [
84
+ "GET",
85
+ "HEAD",
86
+ "OPTIONS"
87
+ ];
88
+
89
89
  //#endregion
90
90
  //#region \0@oxc-project+runtime@0.103.0/helpers/typeof.js
91
91
  function _typeof(o) {
@@ -153,7 +153,7 @@ function _objectSpread2(e) {
153
153
  }
154
154
 
155
155
  //#endregion
156
- //#region src/PostgrestBuilder.ts
156
+ //#region src/fetchWithRetry.ts
157
157
  /**
158
158
  * Sleep for a given number of milliseconds.
159
159
  * If an AbortSignal is provided, the sleep resolves early when the signal is aborted.
@@ -184,6 +184,56 @@ function shouldRetry(method, status, attemptCount, retryEnabled) {
184
184
  if (!RETRYABLE_STATUS_CODES.includes(status)) return false;
185
185
  return true;
186
186
  }
187
+ /**
188
+ * Perform a request with the retry policy shared by every PostgREST call.
189
+ *
190
+ * Idempotent methods (GET, HEAD, OPTIONS) are retried up to
191
+ * `DEFAULT_MAX_RETRIES` times when the fetch rejects or the server answers
192
+ * with a retryable status (503, 520). The wait honours the `Retry-After`
193
+ * header when present and backs off exponentially otherwise. Retried
194
+ * attempts carry an `X-Retry-Count` header. Aborted requests and
195
+ * non-idempotent methods are never retried: their rejection propagates
196
+ * unchanged. A response body is drained before its request is retried.
197
+ */
198
+ async function fetchWithRetry(fetchImpl, url, request, retryEnabled) {
199
+ let attemptCount = 0;
200
+ while (true) {
201
+ const headers = _objectSpread2({}, request.headers);
202
+ if (attemptCount > 0) headers["X-Retry-Count"] = String(attemptCount);
203
+ let res;
204
+ try {
205
+ res = await fetchImpl(url, {
206
+ method: request.method,
207
+ headers,
208
+ body: request.body,
209
+ signal: request.signal
210
+ });
211
+ } catch (fetchError) {
212
+ if ((fetchError === null || fetchError === void 0 ? void 0 : fetchError.name) === "AbortError" || (fetchError === null || fetchError === void 0 ? void 0 : fetchError.code) === "ABORT_ERR") throw fetchError;
213
+ if (!RETRYABLE_METHODS.includes(request.method)) throw fetchError;
214
+ if (retryEnabled && attemptCount < DEFAULT_MAX_RETRIES) {
215
+ const delay = getRetryDelay(attemptCount);
216
+ attemptCount++;
217
+ await sleep(delay, request.signal);
218
+ continue;
219
+ }
220
+ throw fetchError;
221
+ }
222
+ if (shouldRetry(request.method, res.status, attemptCount, retryEnabled)) {
223
+ var _res$headers$get, _res$headers;
224
+ const retryAfterHeader = (_res$headers$get = (_res$headers = res.headers) === null || _res$headers === void 0 ? void 0 : _res$headers.get("Retry-After")) !== null && _res$headers$get !== void 0 ? _res$headers$get : null;
225
+ const delay = retryAfterHeader !== null ? Math.max(0, parseInt(retryAfterHeader, 10) || 0) * 1e3 : getRetryDelay(attemptCount);
226
+ await res.text();
227
+ attemptCount++;
228
+ await sleep(delay, request.signal);
229
+ continue;
230
+ }
231
+ return res;
232
+ }
233
+ }
234
+
235
+ //#endregion
236
+ //#region src/PostgrestBuilder.ts
187
237
  var PostgrestBuilder = class {
188
238
  /**
189
239
  * Creates a builder configured for a specific PostgREST request.
@@ -352,43 +402,17 @@ var PostgrestBuilder = class {
352
402
  }
353
403
  const _fetch = this.fetch;
354
404
  const executeWithRetry = async () => {
355
- let attemptCount = 0;
356
- while (true) {
357
- const headers = {};
358
- _this.headers.forEach((value, key) => {
359
- headers[key] = value;
360
- });
361
- if (attemptCount > 0) headers["X-Retry-Count"] = String(attemptCount);
362
- let res$1;
363
- try {
364
- res$1 = await _fetch(_this.url.toString(), {
365
- method: _this.method,
366
- headers,
367
- body: JSON.stringify(_this.body, (_, value) => typeof value === "bigint" ? value.toString() : value),
368
- signal: _this.signal
369
- });
370
- } catch (fetchError) {
371
- if ((fetchError === null || fetchError === void 0 ? void 0 : fetchError.name) === "AbortError" || (fetchError === null || fetchError === void 0 ? void 0 : fetchError.code) === "ABORT_ERR") throw fetchError;
372
- if (!RETRYABLE_METHODS.includes(_this.method)) throw fetchError;
373
- if (_this.retryEnabled && attemptCount < DEFAULT_MAX_RETRIES) {
374
- const delay = getRetryDelay(attemptCount);
375
- attemptCount++;
376
- await sleep(delay, _this.signal);
377
- continue;
378
- }
379
- throw fetchError;
380
- }
381
- if (shouldRetry(_this.method, res$1.status, attemptCount, _this.retryEnabled)) {
382
- var _res$headers$get, _res$headers;
383
- const retryAfterHeader = (_res$headers$get = (_res$headers = res$1.headers) === null || _res$headers === void 0 ? void 0 : _res$headers.get("Retry-After")) !== null && _res$headers$get !== void 0 ? _res$headers$get : null;
384
- const delay = retryAfterHeader !== null ? Math.max(0, parseInt(retryAfterHeader, 10) || 0) * 1e3 : getRetryDelay(attemptCount);
385
- await res$1.text();
386
- attemptCount++;
387
- await sleep(delay, _this.signal);
388
- continue;
389
- }
390
- return await _this.processResponse(res$1);
391
- }
405
+ const headers = {};
406
+ _this.headers.forEach((value, key) => {
407
+ headers[key] = value;
408
+ });
409
+ const res$1 = await fetchWithRetry(_fetch, _this.url.toString(), {
410
+ method: _this.method,
411
+ headers,
412
+ body: JSON.stringify(_this.body, (_, value) => typeof value === "bigint" ? value.toString() : value),
413
+ signal: _this.signal
414
+ }, _this.retryEnabled);
415
+ return await _this.processResponse(res$1);
392
416
  };
393
417
  let res = executeWithRetry();
394
418
  if (!this.shouldThrowOnError) res = res.catch((fetchError) => {
@@ -446,7 +470,7 @@ var PostgrestBuilder = class {
446
470
  let status = res.status;
447
471
  let statusText = res.statusText;
448
472
  if (res.ok) {
449
- var _this$headers$get2, _res$headers$get2;
473
+ var _this$headers$get2, _res$headers$get;
450
474
  if (_this2.method !== "HEAD") {
451
475
  var _this$headers$get;
452
476
  const body = await res.text();
@@ -466,7 +490,7 @@ var PostgrestBuilder = class {
466
490
  }
467
491
  }
468
492
  const countHeader = (_this$headers$get2 = _this2.headers.get("Prefer")) === null || _this$headers$get2 === void 0 ? void 0 : _this$headers$get2.match(/count=(exact|planned|estimated)/);
469
- const contentRange = (_res$headers$get2 = res.headers.get("content-range")) === null || _res$headers$get2 === void 0 ? void 0 : _res$headers$get2.split("/");
493
+ const contentRange = (_res$headers$get = res.headers.get("content-range")) === null || _res$headers$get === void 0 ? void 0 : _res$headers$get.split("/");
470
494
  if (countHeader && contentRange && contentRange.length > 1) count = parseInt(contentRange[1]);
471
495
  if (_this2.isMaybeSingle && Array.isArray(data)) if (data.length > 1) {
472
496
  error = {
@@ -3563,6 +3587,54 @@ var PostgrestQueryBuilder = class {
3563
3587
  //#endregion
3564
3588
  //#region src/PostgrestClient.ts
3565
3589
  /**
3590
+ * Build the error for a failed OpenAPI request. PostgREST answers with a JSON
3591
+ * error object when it produced the failure itself; proxies and disabled
3592
+ * OpenAPI output answer with plain text or an empty body, in which case the
3593
+ * body (or, failing that, the status text) becomes the message.
3594
+ */
3595
+ function toOpenApiError(body, statusText) {
3596
+ try {
3597
+ const parsed = JSON.parse(body);
3598
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
3599
+ var _parsed$message, _parsed$details, _parsed$hint, _parsed$code;
3600
+ return new PostgrestError({
3601
+ message: String((_parsed$message = parsed.message) !== null && _parsed$message !== void 0 ? _parsed$message : body),
3602
+ details: (_parsed$details = parsed.details) !== null && _parsed$details !== void 0 ? _parsed$details : "",
3603
+ hint: (_parsed$hint = parsed.hint) !== null && _parsed$hint !== void 0 ? _parsed$hint : "",
3604
+ code: (_parsed$code = parsed.code) !== null && _parsed$code !== void 0 ? _parsed$code : ""
3605
+ });
3606
+ }
3607
+ } catch (_unused) {}
3608
+ return new PostgrestError({
3609
+ message: body || statusText,
3610
+ details: "",
3611
+ hint: "",
3612
+ code: ""
3613
+ });
3614
+ }
3615
+ /**
3616
+ * Build the response for a request that yielded no readable body: the fetch
3617
+ * itself rejected (no status is known, so it is 0), or the body stream failed
3618
+ * while being read (the response status is preserved).
3619
+ */
3620
+ function toTransportFailure(cause, status, statusText) {
3621
+ var _err$name;
3622
+ const err = cause;
3623
+ return {
3624
+ success: false,
3625
+ error: new PostgrestError({
3626
+ message: `${(_err$name = err === null || err === void 0 ? void 0 : err.name) !== null && _err$name !== void 0 ? _err$name : "FetchError"}: ${err === null || err === void 0 ? void 0 : err.message}`,
3627
+ details: "",
3628
+ hint: "",
3629
+ code: ""
3630
+ }),
3631
+ data: null,
3632
+ count: null,
3633
+ status,
3634
+ statusText
3635
+ };
3636
+ }
3637
+ /**
3566
3638
  * PostgREST client.
3567
3639
  *
3568
3640
  * @typeParam Database - Types for the schema from the [type
@@ -3671,6 +3743,73 @@ var PostgrestClient = class PostgrestClient {
3671
3743
  });
3672
3744
  }
3673
3745
  /**
3746
+ * Fetch the OpenAPI description PostgREST publishes for this client's schema.
3747
+ *
3748
+ * The document lists only the tables, views and functions the caller's role
3749
+ * holds privileges on; PostgREST applies that filtering server-side. The
3750
+ * schema is the one this client was created with, so call `.schema()` first
3751
+ * to describe a different one. Transient failures are retried according to
3752
+ * the client's `retry` option, like any other idempotent request.
3753
+ *
3754
+ * @example
3755
+ * ```ts
3756
+ * const { data, error } = await supabase.getOpenApiSpec()
3757
+ * ```
3758
+ *
3759
+ * @example Describe a schema other than the client default
3760
+ * ```ts
3761
+ * const { data, error } = await supabase.schema('billing').getOpenApiSpec()
3762
+ * ```
3763
+ *
3764
+ * @category Database
3765
+ */
3766
+ async getOpenApiSpec() {
3767
+ var _this = this;
3768
+ var _this$fetch;
3769
+ const headers = new Headers(_this.headers);
3770
+ headers.set("Accept", "application/openapi+json");
3771
+ if (_this.schemaName) headers.set("Accept-Profile", _this.schemaName);
3772
+ const requestHeaders = {};
3773
+ headers.forEach((value, key) => {
3774
+ requestHeaders[key] = value;
3775
+ });
3776
+ const fetchImpl = (_this$fetch = _this.fetch) !== null && _this$fetch !== void 0 ? _this$fetch : globalThis.fetch;
3777
+ let res;
3778
+ try {
3779
+ var _this$retry;
3780
+ res = await fetchWithRetry(fetchImpl, `${_this.url}/`, {
3781
+ method: "GET",
3782
+ headers: requestHeaders
3783
+ }, (_this$retry = _this.retry) !== null && _this$retry !== void 0 ? _this$retry : true);
3784
+ } catch (fetchError) {
3785
+ return toTransportFailure(fetchError, 0, "");
3786
+ }
3787
+ let body;
3788
+ try {
3789
+ body = await res.text();
3790
+ } catch (readError) {
3791
+ return toTransportFailure(readError, res.status, res.statusText);
3792
+ }
3793
+ if (res.ok) try {
3794
+ return {
3795
+ success: true,
3796
+ error: null,
3797
+ data: JSON.parse(body),
3798
+ count: null,
3799
+ status: res.status,
3800
+ statusText: res.statusText
3801
+ };
3802
+ } catch (_unused2) {}
3803
+ return {
3804
+ success: false,
3805
+ error: toOpenApiError(body, res.statusText),
3806
+ data: null,
3807
+ count: null,
3808
+ status: res.status,
3809
+ statusText: res.statusText
3810
+ };
3811
+ }
3812
+ /**
3674
3813
  * Perform a function call.
3675
3814
  *
3676
3815
  * @param fn - The function name to call
@@ -3836,7 +3975,7 @@ var PostgrestClient = class PostgrestClient {
3836
3975
  * ```
3837
3976
  */
3838
3977
  rpc(fn, args = {}, { head = false, get = false, count } = {}) {
3839
- var _this$fetch;
3978
+ var _this$fetch2;
3840
3979
  let method;
3841
3980
  const url = new URL(`${this.url}/rpc/${fn}`);
3842
3981
  let body;
@@ -3863,7 +4002,7 @@ var PostgrestClient = class PostgrestClient {
3863
4002
  headers,
3864
4003
  schema: this.schemaName,
3865
4004
  body,
3866
- fetch: (_this$fetch = this.fetch) !== null && _this$fetch !== void 0 ? _this$fetch : fetch,
4005
+ fetch: (_this$fetch2 = this.fetch) !== null && _this$fetch2 !== void 0 ? _this$fetch2 : fetch,
3867
4006
  urlLengthLimit: this.urlLengthLimit,
3868
4007
  retry: this.retry
3869
4008
  });