@supabase/postgrest-js 2.114.0 → 2.115.0-canary.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 +210 -71
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +44 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +44 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +210 -71
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/PostgrestBuilder.ts +27 -125
- package/src/PostgrestClient.ts +137 -0
- package/src/fetchWithRetry.ts +141 -0
- package/src/index.ts +1 -0
- package/src/types/types.ts +22 -0
- package/src/version.ts +1 -1
package/package.json
CHANGED
package/src/PostgrestBuilder.ts
CHANGED
|
@@ -5,66 +5,11 @@ import type {
|
|
|
5
5
|
MergePartialResult,
|
|
6
6
|
IsValidResultOverride,
|
|
7
7
|
} from './types/types'
|
|
8
|
-
import {
|
|
9
|
-
ClientServerOptions,
|
|
10
|
-
Fetch,
|
|
11
|
-
DEFAULT_MAX_RETRIES,
|
|
12
|
-
getRetryDelay,
|
|
13
|
-
RETRYABLE_STATUS_CODES,
|
|
14
|
-
RETRYABLE_METHODS,
|
|
15
|
-
} from './types/common/common'
|
|
8
|
+
import { ClientServerOptions, Fetch } from './types/common/common'
|
|
16
9
|
import PostgrestError from './PostgrestError'
|
|
10
|
+
import { fetchWithRetry } from './fetchWithRetry'
|
|
17
11
|
import { ContainsNull } from './select-query-parser/types'
|
|
18
12
|
|
|
19
|
-
/**
|
|
20
|
-
* Sleep for a given number of milliseconds.
|
|
21
|
-
* If an AbortSignal is provided, the sleep resolves early when the signal is aborted.
|
|
22
|
-
*/
|
|
23
|
-
function sleep(ms: number, signal?: AbortSignal): Promise<void> {
|
|
24
|
-
return new Promise((resolve) => {
|
|
25
|
-
if (signal?.aborted) {
|
|
26
|
-
resolve()
|
|
27
|
-
return
|
|
28
|
-
}
|
|
29
|
-
const id = setTimeout(() => {
|
|
30
|
-
signal?.removeEventListener('abort', onAbort)
|
|
31
|
-
resolve()
|
|
32
|
-
}, ms)
|
|
33
|
-
function onAbort() {
|
|
34
|
-
clearTimeout(id)
|
|
35
|
-
resolve()
|
|
36
|
-
}
|
|
37
|
-
signal?.addEventListener('abort', onAbort)
|
|
38
|
-
})
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Check if a request should be retried based on method and status code.
|
|
43
|
-
*/
|
|
44
|
-
function shouldRetry(
|
|
45
|
-
method: string,
|
|
46
|
-
status: number,
|
|
47
|
-
attemptCount: number,
|
|
48
|
-
retryEnabled: boolean
|
|
49
|
-
): boolean {
|
|
50
|
-
// Don't retry if retries are disabled or we've exhausted attempts
|
|
51
|
-
if (!retryEnabled || attemptCount >= DEFAULT_MAX_RETRIES) {
|
|
52
|
-
return false
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// Only retry idempotent methods (GET, HEAD, OPTIONS)
|
|
56
|
-
if (!RETRYABLE_METHODS.includes(method as (typeof RETRYABLE_METHODS)[number])) {
|
|
57
|
-
return false
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// Only retry on specific status codes (520 - Cloudflare errors)
|
|
61
|
-
if (!RETRYABLE_STATUS_CODES.includes(status as (typeof RETRYABLE_STATUS_CODES)[number])) {
|
|
62
|
-
return false
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
return true
|
|
66
|
-
}
|
|
67
|
-
|
|
68
13
|
export default abstract class PostgrestBuilder<
|
|
69
14
|
ClientOptions extends ClientServerOptions,
|
|
70
15
|
Result,
|
|
@@ -314,75 +259,32 @@ export default abstract class PostgrestBuilder<
|
|
|
314
259
|
status: number
|
|
315
260
|
statusText: string
|
|
316
261
|
}> => {
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
this.headers.forEach((value, key) => {
|
|
327
|
-
headers[key] = value
|
|
328
|
-
})
|
|
329
|
-
if (attemptCount > 0) {
|
|
330
|
-
headers['X-Retry-Count'] = String(attemptCount)
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
// Only wrap the fetch call itself — processResponse errors must never trigger retries
|
|
334
|
-
let res: Response
|
|
335
|
-
try {
|
|
336
|
-
res = await _fetch(this.url.toString(), {
|
|
337
|
-
method: this.method,
|
|
338
|
-
headers,
|
|
339
|
-
body: JSON.stringify(this.body, (_, value) =>
|
|
340
|
-
typeof value === 'bigint' ? value.toString() : value
|
|
341
|
-
),
|
|
342
|
-
signal: this.signal,
|
|
343
|
-
})
|
|
344
|
-
// JS allows throwing any value, and serverless or realm-crossing fetch
|
|
345
|
-
// implementations can reject with non-Error objects. `instanceof Error`
|
|
346
|
-
// is too narrow here; narrow at the use site with optional chaining.
|
|
347
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
348
|
-
} catch (fetchError: any) {
|
|
349
|
-
// Never retry aborted requests
|
|
350
|
-
if (fetchError?.name === 'AbortError' || fetchError?.code === 'ABORT_ERR') {
|
|
351
|
-
throw fetchError
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
// Don't retry network errors for non-idempotent methods
|
|
355
|
-
if (!RETRYABLE_METHODS.includes(this.method as (typeof RETRYABLE_METHODS)[number])) {
|
|
356
|
-
throw fetchError
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
// Check if we should retry network errors
|
|
360
|
-
if (this.retryEnabled && attemptCount < DEFAULT_MAX_RETRIES) {
|
|
361
|
-
const delay = getRetryDelay(attemptCount)
|
|
362
|
-
attemptCount++
|
|
363
|
-
await sleep(delay, this.signal)
|
|
364
|
-
continue
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
// Exhausted retries or retries disabled, throw the last error
|
|
368
|
-
throw fetchError
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
// Check if we should retry this HTTP response
|
|
372
|
-
if (shouldRetry(this.method, res.status, attemptCount, this.retryEnabled)) {
|
|
373
|
-
const retryAfterHeader = res.headers?.get('Retry-After') ?? null
|
|
374
|
-
const delay =
|
|
375
|
-
retryAfterHeader !== null
|
|
376
|
-
? Math.max(0, parseInt(retryAfterHeader, 10) || 0) * 1000
|
|
377
|
-
: getRetryDelay(attemptCount)
|
|
378
|
-
await res.text()
|
|
379
|
-
attemptCount++
|
|
380
|
-
await sleep(delay, this.signal)
|
|
381
|
-
continue
|
|
382
|
-
}
|
|
262
|
+
// Serialize headers as a plain object rather than a Headers instance.
|
|
263
|
+
// React Native's XHR-based fetch silently drops headers (notably Content-Type)
|
|
264
|
+
// when given a Headers instance, causing PGRST202 on parameter-less RPC calls.
|
|
265
|
+
// See supabase/supabase-js#1562 and facebook/react-native#33933.
|
|
266
|
+
// All sibling packages (auth-js, storage-js, functions-js) already pass plain objects.
|
|
267
|
+
const headers: Record<string, string> = {}
|
|
268
|
+
this.headers.forEach((value, key) => {
|
|
269
|
+
headers[key] = value
|
|
270
|
+
})
|
|
383
271
|
|
|
384
|
-
|
|
385
|
-
|
|
272
|
+
// Only the fetch itself is retried — processResponse errors must never trigger retries
|
|
273
|
+
const res = await fetchWithRetry(
|
|
274
|
+
_fetch,
|
|
275
|
+
this.url.toString(),
|
|
276
|
+
{
|
|
277
|
+
method: this.method,
|
|
278
|
+
headers,
|
|
279
|
+
body: JSON.stringify(this.body, (_, value) =>
|
|
280
|
+
typeof value === 'bigint' ? value.toString() : value
|
|
281
|
+
),
|
|
282
|
+
signal: this.signal,
|
|
283
|
+
},
|
|
284
|
+
this.retryEnabled
|
|
285
|
+
)
|
|
286
|
+
|
|
287
|
+
return await this.processResponse(res)
|
|
386
288
|
}
|
|
387
289
|
|
|
388
290
|
let res = executeWithRetry()
|
package/src/PostgrestClient.ts
CHANGED
|
@@ -2,6 +2,62 @@ import PostgrestQueryBuilder from './PostgrestQueryBuilder'
|
|
|
2
2
|
import PostgrestFilterBuilder from './PostgrestFilterBuilder'
|
|
3
3
|
import { Fetch, GenericSchema, ClientServerOptions } from './types/common/common'
|
|
4
4
|
import { GetRpcFunctionFilterBuilderByArgs } from './types/common/rpc'
|
|
5
|
+
import PostgrestError from './PostgrestError'
|
|
6
|
+
import { fetchWithRetry } from './fetchWithRetry'
|
|
7
|
+
import {
|
|
8
|
+
PostgrestOpenApiSpec,
|
|
9
|
+
PostgrestResponseFailure,
|
|
10
|
+
PostgrestSingleResponse,
|
|
11
|
+
} from './types/types'
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Build the error for a failed OpenAPI request. PostgREST answers with a JSON
|
|
15
|
+
* error object when it produced the failure itself; proxies and disabled
|
|
16
|
+
* OpenAPI output answer with plain text or an empty body, in which case the
|
|
17
|
+
* body (or, failing that, the status text) becomes the message.
|
|
18
|
+
*/
|
|
19
|
+
function toOpenApiError(body: string, statusText: string): PostgrestError {
|
|
20
|
+
try {
|
|
21
|
+
const parsed = JSON.parse(body)
|
|
22
|
+
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
|
|
23
|
+
return new PostgrestError({
|
|
24
|
+
message: String(parsed.message ?? body),
|
|
25
|
+
details: parsed.details ?? '',
|
|
26
|
+
hint: parsed.hint ?? '',
|
|
27
|
+
code: parsed.code ?? '',
|
|
28
|
+
})
|
|
29
|
+
}
|
|
30
|
+
} catch {
|
|
31
|
+
// Not JSON; fall through to the plain-text message.
|
|
32
|
+
}
|
|
33
|
+
return new PostgrestError({ message: body || statusText, details: '', hint: '', code: '' })
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Build the response for a request that yielded no readable body: the fetch
|
|
38
|
+
* itself rejected (no status is known, so it is 0), or the body stream failed
|
|
39
|
+
* while being read (the response status is preserved).
|
|
40
|
+
*/
|
|
41
|
+
function toTransportFailure(
|
|
42
|
+
cause: unknown,
|
|
43
|
+
status: number,
|
|
44
|
+
statusText: string
|
|
45
|
+
): PostgrestResponseFailure {
|
|
46
|
+
const err = cause as { name?: string; message?: string } | null | undefined
|
|
47
|
+
return {
|
|
48
|
+
success: false,
|
|
49
|
+
error: new PostgrestError({
|
|
50
|
+
message: `${err?.name ?? 'FetchError'}: ${err?.message}`,
|
|
51
|
+
details: '',
|
|
52
|
+
hint: '',
|
|
53
|
+
code: '',
|
|
54
|
+
}),
|
|
55
|
+
data: null,
|
|
56
|
+
count: null,
|
|
57
|
+
status,
|
|
58
|
+
statusText,
|
|
59
|
+
}
|
|
60
|
+
}
|
|
5
61
|
|
|
6
62
|
/**
|
|
7
63
|
* PostgREST client.
|
|
@@ -203,6 +259,87 @@ export default class PostgrestClient<
|
|
|
203
259
|
})
|
|
204
260
|
}
|
|
205
261
|
|
|
262
|
+
/**
|
|
263
|
+
* Fetch the OpenAPI description PostgREST publishes for this client's schema.
|
|
264
|
+
*
|
|
265
|
+
* The document lists only the tables, views and functions the caller's role
|
|
266
|
+
* holds privileges on; PostgREST applies that filtering server-side. The
|
|
267
|
+
* schema is the one this client was created with, so call `.schema()` first
|
|
268
|
+
* to describe a different one. Transient failures are retried according to
|
|
269
|
+
* the client's `retry` option, like any other idempotent request.
|
|
270
|
+
*
|
|
271
|
+
* @example
|
|
272
|
+
* ```ts
|
|
273
|
+
* const { data, error } = await supabase.getOpenApiSpec()
|
|
274
|
+
* ```
|
|
275
|
+
*
|
|
276
|
+
* @example Describe a schema other than the client default
|
|
277
|
+
* ```ts
|
|
278
|
+
* const { data, error } = await supabase.schema('billing').getOpenApiSpec()
|
|
279
|
+
* ```
|
|
280
|
+
*
|
|
281
|
+
* @category Database
|
|
282
|
+
*/
|
|
283
|
+
async getOpenApiSpec(): Promise<PostgrestSingleResponse<PostgrestOpenApiSpec>> {
|
|
284
|
+
const headers = new Headers(this.headers)
|
|
285
|
+
headers.set('Accept', 'application/openapi+json')
|
|
286
|
+
if (this.schemaName) {
|
|
287
|
+
headers.set('Accept-Profile', this.schemaName)
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// Headers reach the fetch implementation as a plain object, as in
|
|
291
|
+
// PostgrestBuilder: React Native's XHR-based fetch drops headers that are
|
|
292
|
+
// supplied as a Headers instance.
|
|
293
|
+
const requestHeaders: Record<string, string> = {}
|
|
294
|
+
headers.forEach((value, key) => {
|
|
295
|
+
requestHeaders[key] = value
|
|
296
|
+
})
|
|
297
|
+
|
|
298
|
+
const fetchImpl = this.fetch ?? globalThis.fetch
|
|
299
|
+
let res: Response
|
|
300
|
+
try {
|
|
301
|
+
res = await fetchWithRetry(
|
|
302
|
+
fetchImpl,
|
|
303
|
+
`${this.url}/`,
|
|
304
|
+
{ method: 'GET', headers: requestHeaders },
|
|
305
|
+
this.retry ?? true
|
|
306
|
+
)
|
|
307
|
+
} catch (fetchError) {
|
|
308
|
+
return toTransportFailure(fetchError, 0, '')
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
let body: string
|
|
312
|
+
try {
|
|
313
|
+
body = await res.text()
|
|
314
|
+
} catch (readError) {
|
|
315
|
+
return toTransportFailure(readError, res.status, res.statusText)
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
if (res.ok) {
|
|
319
|
+
try {
|
|
320
|
+
return {
|
|
321
|
+
success: true,
|
|
322
|
+
error: null,
|
|
323
|
+
data: JSON.parse(body) as PostgrestOpenApiSpec,
|
|
324
|
+
count: null,
|
|
325
|
+
status: res.status,
|
|
326
|
+
statusText: res.statusText,
|
|
327
|
+
}
|
|
328
|
+
} catch {
|
|
329
|
+
// A 2xx status does not guarantee a JSON body; report it like a failure.
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
return {
|
|
334
|
+
success: false,
|
|
335
|
+
error: toOpenApiError(body, res.statusText),
|
|
336
|
+
data: null,
|
|
337
|
+
count: null,
|
|
338
|
+
status: res.status,
|
|
339
|
+
statusText: res.statusText,
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
206
343
|
/**
|
|
207
344
|
* Perform a function call.
|
|
208
345
|
*
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DEFAULT_MAX_RETRIES,
|
|
3
|
+
Fetch,
|
|
4
|
+
getRetryDelay,
|
|
5
|
+
RETRYABLE_METHODS,
|
|
6
|
+
RETRYABLE_STATUS_CODES,
|
|
7
|
+
} from './types/common/common'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Sleep for a given number of milliseconds.
|
|
11
|
+
* If an AbortSignal is provided, the sleep resolves early when the signal is aborted.
|
|
12
|
+
*/
|
|
13
|
+
function sleep(ms: number, signal?: AbortSignal): Promise<void> {
|
|
14
|
+
return new Promise((resolve) => {
|
|
15
|
+
if (signal?.aborted) {
|
|
16
|
+
resolve()
|
|
17
|
+
return
|
|
18
|
+
}
|
|
19
|
+
const id = setTimeout(() => {
|
|
20
|
+
signal?.removeEventListener('abort', onAbort)
|
|
21
|
+
resolve()
|
|
22
|
+
}, ms)
|
|
23
|
+
function onAbort() {
|
|
24
|
+
clearTimeout(id)
|
|
25
|
+
resolve()
|
|
26
|
+
}
|
|
27
|
+
signal?.addEventListener('abort', onAbort)
|
|
28
|
+
})
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Check if a request should be retried based on method and status code.
|
|
33
|
+
*/
|
|
34
|
+
function shouldRetry(
|
|
35
|
+
method: string,
|
|
36
|
+
status: number,
|
|
37
|
+
attemptCount: number,
|
|
38
|
+
retryEnabled: boolean
|
|
39
|
+
): boolean {
|
|
40
|
+
// Don't retry if retries are disabled or we've exhausted attempts
|
|
41
|
+
if (!retryEnabled || attemptCount >= DEFAULT_MAX_RETRIES) {
|
|
42
|
+
return false
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Only retry idempotent methods (GET, HEAD, OPTIONS)
|
|
46
|
+
if (!RETRYABLE_METHODS.includes(method as (typeof RETRYABLE_METHODS)[number])) {
|
|
47
|
+
return false
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Only retry on specific status codes (520 - Cloudflare errors)
|
|
51
|
+
if (!RETRYABLE_STATUS_CODES.includes(status as (typeof RETRYABLE_STATUS_CODES)[number])) {
|
|
52
|
+
return false
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return true
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface RetryableRequest {
|
|
59
|
+
method: string
|
|
60
|
+
/** Plain object, never a Headers instance: React Native's XHR-based fetch drops the latter. */
|
|
61
|
+
headers: Record<string, string>
|
|
62
|
+
body?: string
|
|
63
|
+
signal?: AbortSignal
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Perform a request with the retry policy shared by every PostgREST call.
|
|
68
|
+
*
|
|
69
|
+
* Idempotent methods (GET, HEAD, OPTIONS) are retried up to
|
|
70
|
+
* `DEFAULT_MAX_RETRIES` times when the fetch rejects or the server answers
|
|
71
|
+
* with a retryable status (503, 520). The wait honours the `Retry-After`
|
|
72
|
+
* header when present and backs off exponentially otherwise. Retried
|
|
73
|
+
* attempts carry an `X-Retry-Count` header. Aborted requests and
|
|
74
|
+
* non-idempotent methods are never retried: their rejection propagates
|
|
75
|
+
* unchanged. A response body is drained before its request is retried.
|
|
76
|
+
*/
|
|
77
|
+
export async function fetchWithRetry(
|
|
78
|
+
fetchImpl: Fetch,
|
|
79
|
+
url: string,
|
|
80
|
+
request: RetryableRequest,
|
|
81
|
+
retryEnabled: boolean
|
|
82
|
+
): Promise<Response> {
|
|
83
|
+
let attemptCount = 0
|
|
84
|
+
|
|
85
|
+
while (true) {
|
|
86
|
+
const headers: Record<string, string> = { ...request.headers }
|
|
87
|
+
if (attemptCount > 0) {
|
|
88
|
+
headers['X-Retry-Count'] = String(attemptCount)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
let res: Response
|
|
92
|
+
try {
|
|
93
|
+
res = await fetchImpl(url, {
|
|
94
|
+
method: request.method,
|
|
95
|
+
headers,
|
|
96
|
+
body: request.body,
|
|
97
|
+
signal: request.signal,
|
|
98
|
+
})
|
|
99
|
+
// JS allows throwing any value, and serverless or realm-crossing fetch
|
|
100
|
+
// implementations can reject with non-Error objects. `instanceof Error`
|
|
101
|
+
// is too narrow here; narrow at the use site with optional chaining.
|
|
102
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
103
|
+
} catch (fetchError: any) {
|
|
104
|
+
// Never retry aborted requests
|
|
105
|
+
if (fetchError?.name === 'AbortError' || fetchError?.code === 'ABORT_ERR') {
|
|
106
|
+
throw fetchError
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Don't retry network errors for non-idempotent methods
|
|
110
|
+
if (!RETRYABLE_METHODS.includes(request.method as (typeof RETRYABLE_METHODS)[number])) {
|
|
111
|
+
throw fetchError
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Check if we should retry network errors
|
|
115
|
+
if (retryEnabled && attemptCount < DEFAULT_MAX_RETRIES) {
|
|
116
|
+
const delay = getRetryDelay(attemptCount)
|
|
117
|
+
attemptCount++
|
|
118
|
+
await sleep(delay, request.signal)
|
|
119
|
+
continue
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Exhausted retries or retries disabled, throw the last error
|
|
123
|
+
throw fetchError
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Check if we should retry this HTTP response
|
|
127
|
+
if (shouldRetry(request.method, res.status, attemptCount, retryEnabled)) {
|
|
128
|
+
const retryAfterHeader = res.headers?.get('Retry-After') ?? null
|
|
129
|
+
const delay =
|
|
130
|
+
retryAfterHeader !== null
|
|
131
|
+
? Math.max(0, parseInt(retryAfterHeader, 10) || 0) * 1000
|
|
132
|
+
: getRetryDelay(attemptCount)
|
|
133
|
+
await res.text()
|
|
134
|
+
attemptCount++
|
|
135
|
+
await sleep(delay, request.signal)
|
|
136
|
+
continue
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return res
|
|
140
|
+
}
|
|
141
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -27,6 +27,7 @@ export type {
|
|
|
27
27
|
PostgrestResponseSuccess,
|
|
28
28
|
PostgrestSingleResponse,
|
|
29
29
|
PostgrestMaybeSingleResponse,
|
|
30
|
+
PostgrestOpenApiSpec,
|
|
30
31
|
} from './types/types'
|
|
31
32
|
export type { ClientServerOptions as PostgrestClientOptions } from './types/common/common'
|
|
32
33
|
// https://github.com/supabase/postgrest-js/issues/551
|
package/src/types/types.ts
CHANGED
|
@@ -40,6 +40,28 @@ export type PostgrestSingleResponse<T> = PostgrestResponseSuccess<T> | Postgrest
|
|
|
40
40
|
export type PostgrestMaybeSingleResponse<T> = PostgrestSingleResponse<T | null>
|
|
41
41
|
export type PostgrestResponse<T> = PostgrestSingleResponse<T[]>
|
|
42
42
|
|
|
43
|
+
/**
|
|
44
|
+
* OpenAPI description served by PostgREST at the REST root (`GET /`).
|
|
45
|
+
*
|
|
46
|
+
* PostgREST emits OpenAPI 2.0 (Swagger), so the version lives in `swagger`.
|
|
47
|
+
* OpenAPI 2.0 requires only `swagger`, `info` and `paths`; a PostgREST
|
|
48
|
+
* `db-root-spec` override may leave out any other field. Only the top level
|
|
49
|
+
* is typed here; the contents of `paths`, `definitions` and `parameters`
|
|
50
|
+
* follow the OpenAPI 2.0 specification and vary with the PostgREST version.
|
|
51
|
+
*
|
|
52
|
+
* {@link https://docs.postgrest.org/en/stable/references/api/openapi.html}
|
|
53
|
+
*/
|
|
54
|
+
export interface PostgrestOpenApiSpec {
|
|
55
|
+
swagger: string
|
|
56
|
+
info: Record<string, unknown>
|
|
57
|
+
host?: string
|
|
58
|
+
basePath?: string
|
|
59
|
+
paths: Record<string, Record<string, unknown>>
|
|
60
|
+
definitions?: Record<string, Record<string, unknown>>
|
|
61
|
+
parameters?: Record<string, Record<string, unknown>>
|
|
62
|
+
[key: string]: unknown
|
|
63
|
+
}
|
|
64
|
+
|
|
43
65
|
export type DatabaseWithOptions<Database, Options extends ClientServerOptions> = {
|
|
44
66
|
db: Database
|
|
45
67
|
options: Options
|
package/src/version.ts
CHANGED
|
@@ -4,4 +4,4 @@
|
|
|
4
4
|
// - Debugging and support (identifying which version is running)
|
|
5
5
|
// - Telemetry and logging (version reporting in errors/analytics)
|
|
6
6
|
// - Ensuring build artifacts match the published package version
|
|
7
|
-
export const version = '2.
|
|
7
|
+
export const version = '2.115.0-canary.0'
|