@infaris/data 0.0.0-stage → 0.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 +125 -2
- package/dist/index.cjs +492 -0
- package/dist/index.d.cts +349 -0
- package/dist/index.d.ts +349 -0
- package/dist/index.js +473 -0
- package/package.json +65 -4
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
/** Common base of the SDK-specific errors. Existing error names and constructors remain supported. */
|
|
2
|
+
declare class InfarisError extends Error {
|
|
3
|
+
static [Symbol.hasInstance](value: unknown): boolean;
|
|
4
|
+
readonly code: string;
|
|
5
|
+
readonly status: number | null | undefined;
|
|
6
|
+
constructor(message: string, code?: string, status?: number | null | undefined);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/** `fetch`, or anything with its shape (tests, a fetch with retries). */
|
|
10
|
+
type FetchLike = (input: string, init?: RequestInit) => Promise<Response>;
|
|
11
|
+
/** A failed request: PostgREST's error (`code`, `message`, `details`, `hint`) or the gateway's (`invalid_key`, ...). */
|
|
12
|
+
declare class DataApiError extends InfarisError {
|
|
13
|
+
readonly code: string;
|
|
14
|
+
readonly details: string | null;
|
|
15
|
+
readonly hint: string | null;
|
|
16
|
+
readonly status: number | null;
|
|
17
|
+
constructor(input: {
|
|
18
|
+
code: string;
|
|
19
|
+
message: string;
|
|
20
|
+
details?: string | null;
|
|
21
|
+
hint?: string | null;
|
|
22
|
+
status?: number;
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
/** What every query resolves to: data or an error, never both; never throws (except `throwOnError`). */
|
|
26
|
+
type DataApiResponse<T> = {
|
|
27
|
+
data: T;
|
|
28
|
+
error: null;
|
|
29
|
+
count: number | null;
|
|
30
|
+
status: number;
|
|
31
|
+
statusText: string;
|
|
32
|
+
} | {
|
|
33
|
+
data: null;
|
|
34
|
+
error: DataApiError;
|
|
35
|
+
count: number | null;
|
|
36
|
+
status: number;
|
|
37
|
+
statusText: string;
|
|
38
|
+
};
|
|
39
|
+
/** The shape `infaris-guard hosting db types` generates. */
|
|
40
|
+
interface GenericTable {
|
|
41
|
+
Row: Record<string, unknown>;
|
|
42
|
+
Insert: Record<string, unknown>;
|
|
43
|
+
Update: Record<string, unknown>;
|
|
44
|
+
}
|
|
45
|
+
interface GenericView {
|
|
46
|
+
Row: Record<string, unknown>;
|
|
47
|
+
}
|
|
48
|
+
interface GenericFunction {
|
|
49
|
+
Args: Record<string, unknown>;
|
|
50
|
+
Returns: unknown;
|
|
51
|
+
}
|
|
52
|
+
interface GenericSchema {
|
|
53
|
+
Tables: Record<string, GenericTable>;
|
|
54
|
+
Views: Record<string, GenericView>;
|
|
55
|
+
Functions: Record<string, GenericFunction>;
|
|
56
|
+
}
|
|
57
|
+
/** Without generated types every table is a loose record. */
|
|
58
|
+
type AnyDatabase = Record<string, GenericSchema>;
|
|
59
|
+
type TableName<S extends GenericSchema> = (keyof S['Tables'] & string) | (keyof S['Views'] & string);
|
|
60
|
+
type RowOf<S extends GenericSchema, T extends string> = T extends keyof S['Tables'] ? S['Tables'][T]['Row'] : T extends keyof S['Views'] ? S['Views'][T]['Row'] : Record<string, unknown>;
|
|
61
|
+
interface ClientOptions {
|
|
62
|
+
/** The signed-in user's access token from Infaris Auth (role `authenticated`); null for anonymous calls. */
|
|
63
|
+
accessToken?: () => Promise<string | null> | string | null;
|
|
64
|
+
/** The schema `from()` uses by default (the first exposed one, normally `public`). */
|
|
65
|
+
schema?: string;
|
|
66
|
+
headers?: Record<string, string>;
|
|
67
|
+
fetch?: FetchLike;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* The result type of a PostgREST `select` string, computed at compile time from the generated `Database` type:
|
|
72
|
+
*
|
|
73
|
+
* - `*` and plain columns: `select('id, title')` is `{ id: number; title: string }`;
|
|
74
|
+
* - aliases and casts: `name:title`, `price::text` (`string`), `total:amount::int` (`number`);
|
|
75
|
+
* - JSON paths: `meta->theme` (`unknown`), `meta->>theme` (`string | null`), named after the last key;
|
|
76
|
+
* - embedded relations over foreign keys: `author:users(name)` is one object (or `null`) for a many-to-one and
|
|
77
|
+
* `orders(id, total)` an array for a one-to-many; `!inner` drops the `null`, `!hint` picks a foreign key;
|
|
78
|
+
* - spreads `...users(name)` lift the embedded columns into the row;
|
|
79
|
+
* - aggregates (with `aggregates` on): `count()`, `amount.sum()`, `amount.avg()`, `created_at.max()`.
|
|
80
|
+
*
|
|
81
|
+
* A column that does not exist becomes a string type that says so, which shows up where the value is used. Without
|
|
82
|
+
* generated types every row stays `Record<string, unknown>`.
|
|
83
|
+
*/
|
|
84
|
+
type SelectResult<S extends GenericSchema, N extends string, Q extends string> = string extends Q ? RowFor<S, N> : string extends keyof RowFor<S, N> ? Record<string, unknown> : Simplify<Fields<S, N, SplitTop<StripWs<Q>>>>;
|
|
85
|
+
type RowFor<S extends GenericSchema, N extends string> = N extends keyof S['Tables'] ? S['Tables'][N]['Row'] : N extends keyof S['Views'] ? S['Views'][N]['Row'] : Record<string, unknown>;
|
|
86
|
+
/** Readable object type in hovers. */
|
|
87
|
+
type Simplify<T> = {
|
|
88
|
+
[K in keyof T]: T[K];
|
|
89
|
+
} & {};
|
|
90
|
+
type Ws = ' ' | '\n' | '\t' | '\r';
|
|
91
|
+
/** Whitespace out, like the client does before sending (quoted names are rare in a select). */
|
|
92
|
+
type StripWs<S extends string, Out extends string = ''> = S extends `${infer C}${infer Rest}` ? StripWs<Rest, C extends Ws ? Out : `${Out}${C}`> : Out;
|
|
93
|
+
/** Splits on commas outside parentheses. */
|
|
94
|
+
type SplitTop<S extends string, Depth extends unknown[] = [], Cur extends string = '', Out extends string[] = []> = S extends `${infer C}${infer Rest}` ? C extends ',' ? Depth extends [] ? SplitTop<Rest, Depth, '', [...Out, Cur]> : SplitTop<Rest, Depth, `${Cur}${C}`, Out> : C extends '(' ? SplitTop<Rest, [...Depth, 0], `${Cur}${C}`, Out> : C extends ')' ? SplitTop<Rest, Depth extends [unknown, ...infer D] ? D : [], `${Cur}${C}`, Out> : SplitTop<Rest, Depth, `${Cur}${C}`, Out> : Cur extends '' ? Out : [...Out, Cur];
|
|
95
|
+
type UnionToIntersection<U> = (U extends unknown ? (x: U) => void : never) extends (x: infer I) => void ? I : never;
|
|
96
|
+
type Fields<S extends GenericSchema, N extends string, F extends string[]> = F extends [] ? Record<string, never> : UnionToIntersection<{
|
|
97
|
+
[I in keyof F]: F[I] extends string ? Field<S, N, F[I]> : never;
|
|
98
|
+
}[number]>;
|
|
99
|
+
/** One entry of the select list. */
|
|
100
|
+
type Field<S extends GenericSchema, N extends string, F extends string> = F extends '*' ? RowFor<S, N> : F extends `...${infer Embed}` ? Spread<S, N, Embed> : F extends `${infer Alias}:${infer Rest}` ? Rest extends `:${string}` ? Unaliased<S, N, F> : Alias extends `${string}(${string}` ? Unaliased<S, N, F> : {
|
|
101
|
+
[K in Alias]: ValueOf<S, N, Rest>;
|
|
102
|
+
} : Unaliased<S, N, F>;
|
|
103
|
+
type Unaliased<S extends GenericSchema, N extends string, F extends string> = {
|
|
104
|
+
[K in NameOf<F>]: ValueOf<S, N, F>;
|
|
105
|
+
};
|
|
106
|
+
type Aggregate = 'sum' | 'avg' | 'min' | 'max' | 'count';
|
|
107
|
+
/** `[column, function]` of an aggregate entry (`count()`, `amount.sum()`), never for an embed that holds one. */
|
|
108
|
+
type AggregateOf<F extends string> = F extends `count()${string}` ? ['', 'count'] : F extends `${infer Col}.${infer Fn extends Aggregate}()${string}` ? Col extends `${string}(${string}` ? never : [Col, Fn] : never;
|
|
109
|
+
/** The key PostgREST gives an entry without an alias. */
|
|
110
|
+
type NameOf<F extends string> = [AggregateOf<F>] extends [never] ? PlainName<F> : AggregateOf<F>[1];
|
|
111
|
+
type PlainName<F extends string> = F extends `${infer Base}::${string}` ? NameOf<Base> : F extends `${infer Rel}(${string}` ? Rel extends `${infer Name}!${string}` ? Name : Rel : F extends `${string}->${infer Path}` ? LastKey<Path> : F;
|
|
112
|
+
type LastKey<P extends string> = P extends `>${infer Rest}` ? LastKey<Rest> : P extends `${string}->${infer Rest}` ? LastKey<Rest> : P;
|
|
113
|
+
type Cast<T extends string> = T extends 'text' | 'varchar' | 'uuid' | 'date' | 'timestamp' | 'timestamptz' ? string : T extends 'int' | 'int2' | 'int4' | 'int8' | 'integer' | 'bigint' | 'smallint' | 'numeric' | 'float4' | 'float8' | 'real' ? number : T extends 'bool' | 'boolean' ? boolean : T extends 'json' | 'jsonb' ? unknown : unknown;
|
|
114
|
+
/** The value of an entry: column, cast, JSON path, aggregate or embedded relation. */
|
|
115
|
+
type ValueOf<S extends GenericSchema, N extends string, F extends string> = [AggregateOf<F>] extends [never] ? PlainValue<S, N, F> : AggregateOf<F>[1] extends 'count' | 'sum' | 'avg' ? number : ColumnValue<S, N, AggregateOf<F>[0]>;
|
|
116
|
+
type PlainValue<S extends GenericSchema, N extends string, F extends string> = F extends `${infer Rel}(${infer Inner})` ? Embedded<S, N, Rel, Inner> : F extends `${infer Base}::${infer T}` ? Base extends keyof RowFor<S, N> | `${string}->${string}` ? Cast<T> | (null extends RowFor<S, N>[Base & keyof RowFor<S, N>] ? null : never) : Missing<N, Base> : F extends `${infer Col}->${infer Path}` ? Col extends keyof RowFor<S, N> ? Path extends `${string}->>${string}` | `>${string}` ? string | null : unknown : Missing<N, Col> : ColumnValue<S, N, F>;
|
|
117
|
+
type ColumnValue<S extends GenericSchema, N extends string, C extends string> = C extends keyof RowFor<S, N> ? RowFor<S, N>[C] : Missing<N, C>;
|
|
118
|
+
/** Shows up as the value's type wherever it is used: a compile-time hint instead of a runtime surprise. */
|
|
119
|
+
type Missing<N extends string, C extends string> = `column '${C}' does not exist on '${N}'`;
|
|
120
|
+
type RelationName<R extends string> = R extends `${infer Name}!${string}` ? Name : R;
|
|
121
|
+
type RelationshipsOf<S extends GenericSchema, N extends string> = N extends keyof S['Tables'] ? S['Tables'][N] extends {
|
|
122
|
+
Relationships: infer R;
|
|
123
|
+
} ? R : [] : N extends keyof S['Views'] ? S['Views'][N] extends {
|
|
124
|
+
Relationships: infer R;
|
|
125
|
+
} ? R : [] : [];
|
|
126
|
+
/** This relation holds the foreign key to the other: many-to-one, so one object. */
|
|
127
|
+
type ManyToOne<S extends GenericSchema, N extends string, Other extends string> = RelationshipsOf<S, N> extends readonly (infer E)[] ? ([Extract<E, {
|
|
128
|
+
referencedRelation: Other;
|
|
129
|
+
}>] extends [never] ? false : true) : false;
|
|
130
|
+
type Embedded<S extends GenericSchema, N extends string, Rel extends string, Inner extends string> = RelationName<Rel> extends infer Other extends string ? Other extends keyof S['Tables'] | keyof S['Views'] ? ManyToOne<S, N, Other> extends true ? SelectResult<S, Other, Inner extends '' ? '*' : Inner> | (Rel extends `${string}!inner${string}` ? never : null) : SelectResult<S, Other, Inner extends '' ? '*' : Inner>[] : `relation '${Other}' does not exist` : never;
|
|
131
|
+
type Spread<S extends GenericSchema, N extends string, E extends string> = E extends `${infer Rel}(${infer Inner})` ? RelationName<Rel> extends infer Other extends string ? Other extends keyof S['Tables'] | keyof S['Views'] ? SelectResult<S, Other, Inner extends '' ? '*' : Inner> : Record<string, never> : never : Record<string, never>;
|
|
132
|
+
|
|
133
|
+
/** What a request needs from its client: where, with which headers, and how. */
|
|
134
|
+
interface RequestContext {
|
|
135
|
+
restUrl: string;
|
|
136
|
+
/** Builds apikey, Authorization and profile headers for one request. */
|
|
137
|
+
headers: (method: string, schema: string | null) => Promise<Record<string, string>>;
|
|
138
|
+
fetch: FetchLike;
|
|
139
|
+
schema: string | null;
|
|
140
|
+
}
|
|
141
|
+
type Count = 'exact' | 'planned' | 'estimated';
|
|
142
|
+
/**
|
|
143
|
+
* Quotes a value for PostgREST's list syntax (`in.(...)`, `cs.{...}`): reserved characters and spaces in double
|
|
144
|
+
* quotes, with `"` and `\` escaped.
|
|
145
|
+
*/
|
|
146
|
+
declare function quoteValue(value: unknown): string;
|
|
147
|
+
/** Columns of a relation; without generated types any name. */
|
|
148
|
+
type ColumnName<S extends GenericSchema, N extends string> = string extends keyof RowFor<S, N> ? string : keyof RowFor<S, N> & string;
|
|
149
|
+
/** A column, a column of an embedded table (`orders.status`) or a JSON path (`meta->>theme`). */
|
|
150
|
+
type FilterColumn<S extends GenericSchema, N extends string> = string extends ColumnName<S, N> ? string : ColumnName<S, N> | `${string}.${string}` | `${string}->${string}`;
|
|
151
|
+
/** What a filter on a column compares with: its own type (an element for an array column), anything for a path. */
|
|
152
|
+
type FilterValue<S extends GenericSchema, N extends string, K> = K extends keyof RowFor<S, N> ? NonNullable<RowFor<S, N>[K]> extends infer V ? V extends readonly (infer E)[] ? V | E : V : never : unknown;
|
|
153
|
+
type InsertOf<S extends GenericSchema, N extends string> = N extends keyof S['Tables'] ? S['Tables'][N]['Insert'] : Partial<RowFor<S, N>>;
|
|
154
|
+
type UpdateOf<S extends GenericSchema, N extends string> = N extends keyof S['Tables'] ? S['Tables'][N]['Update'] : Partial<RowFor<S, N>>;
|
|
155
|
+
type One<R> = R extends readonly (infer E)[] ? E : R;
|
|
156
|
+
/**
|
|
157
|
+
* One request to the Data API, built step by step and run when awaited: `from('todos').select('*').eq('done', false)`.
|
|
158
|
+
* Filters and modifiers map one to one onto PostgREST's query syntax; nothing runs before `await` (or `.then`). With
|
|
159
|
+
* generated types (`createClient<Database>()`), columns, filter values, inserts and the result of `select` are typed.
|
|
160
|
+
*/
|
|
161
|
+
declare class QueryBuilder<S extends GenericSchema = GenericSchema, N extends string = string, Result = RowFor<S, N>[]> implements PromiseLike<DataApiResponse<Result>> {
|
|
162
|
+
private readonly ctx;
|
|
163
|
+
private readonly path;
|
|
164
|
+
private method;
|
|
165
|
+
private readonly params;
|
|
166
|
+
private readonly prefer;
|
|
167
|
+
private body;
|
|
168
|
+
private accept;
|
|
169
|
+
private maybe;
|
|
170
|
+
private signal;
|
|
171
|
+
constructor(ctx: RequestContext, path: string);
|
|
172
|
+
private retype;
|
|
173
|
+
/** Overrides the result type when you know better (a view without types, a computed column). */
|
|
174
|
+
returns<R>(): QueryBuilder<S, N, R>;
|
|
175
|
+
/** Read rows (`GET`), or with a mutation before it, return the changed rows. `head: true` only counts. */
|
|
176
|
+
select<Q extends string = '*'>(columns?: Q, options?: {
|
|
177
|
+
count?: Count;
|
|
178
|
+
head?: boolean;
|
|
179
|
+
}): QueryBuilder<S, N, SelectResult<S, N, Q>[]>;
|
|
180
|
+
insert(values: InsertOf<S, N> | InsertOf<S, N>[], options?: {
|
|
181
|
+
count?: Count;
|
|
182
|
+
defaultToNull?: boolean;
|
|
183
|
+
}): QueryBuilder<S, N, null>;
|
|
184
|
+
/** Insert or, on a conflict with `onConflict` (default the primary key), update (or skip with `ignoreDuplicates`). */
|
|
185
|
+
upsert(values: InsertOf<S, N> | InsertOf<S, N>[], options?: {
|
|
186
|
+
onConflict?: string;
|
|
187
|
+
ignoreDuplicates?: boolean;
|
|
188
|
+
count?: Count;
|
|
189
|
+
defaultToNull?: boolean;
|
|
190
|
+
}): QueryBuilder<S, N, null>;
|
|
191
|
+
update(values: UpdateOf<S, N>, options?: {
|
|
192
|
+
count?: Count;
|
|
193
|
+
}): QueryBuilder<S, N, null>;
|
|
194
|
+
delete(options?: {
|
|
195
|
+
count?: Count;
|
|
196
|
+
}): QueryBuilder<S, N, null>;
|
|
197
|
+
/** `columns` for a bulk insert, so rows that leave a column out get its default instead of null. */
|
|
198
|
+
private columns;
|
|
199
|
+
/** Any PostgREST filter: `filter('age', 'gte', 18)`, `filter('tags', 'cs', '{a,b}')`. */
|
|
200
|
+
filter(column: FilterColumn<S, N>, operator: string, value: unknown): this;
|
|
201
|
+
eq<K extends FilterColumn<S, N>>(column: K, value: FilterValue<S, N, K>): this;
|
|
202
|
+
neq<K extends FilterColumn<S, N>>(column: K, value: FilterValue<S, N, K>): this;
|
|
203
|
+
gt<K extends FilterColumn<S, N>>(column: K, value: FilterValue<S, N, K>): this;
|
|
204
|
+
gte<K extends FilterColumn<S, N>>(column: K, value: FilterValue<S, N, K>): this;
|
|
205
|
+
lt<K extends FilterColumn<S, N>>(column: K, value: FilterValue<S, N, K>): this;
|
|
206
|
+
lte<K extends FilterColumn<S, N>>(column: K, value: FilterValue<S, N, K>): this;
|
|
207
|
+
like(column: FilterColumn<S, N>, pattern: string): this;
|
|
208
|
+
ilike(column: FilterColumn<S, N>, pattern: string): this;
|
|
209
|
+
/** `IS NULL`, `IS TRUE`, `IS FALSE`. */
|
|
210
|
+
is(column: FilterColumn<S, N>, value: null | boolean): this;
|
|
211
|
+
in<K extends FilterColumn<S, N>>(column: K, values: readonly FilterValue<S, N, K>[]): this;
|
|
212
|
+
contains(column: FilterColumn<S, N>, value: unknown): this;
|
|
213
|
+
containedBy(column: FilterColumn<S, N>, value: unknown): this;
|
|
214
|
+
overlaps(column: FilterColumn<S, N>, value: unknown): this;
|
|
215
|
+
/**
|
|
216
|
+
* Full-text search on a tsvector column (`infaris-guard hosting db search add` makes one):
|
|
217
|
+
* `textSearch('fts', 'fiets bel', { type: 'websearch', config: 'dutch' })`.
|
|
218
|
+
*/
|
|
219
|
+
textSearch(column: FilterColumn<S, N>, query: string, options?: {
|
|
220
|
+
type?: 'plain' | 'phrase' | 'websearch';
|
|
221
|
+
config?: string;
|
|
222
|
+
}): this;
|
|
223
|
+
/** Several equalities at once. */
|
|
224
|
+
match(query: {
|
|
225
|
+
[K in ColumnName<S, N>]?: FilterValue<S, N, K>;
|
|
226
|
+
}): this;
|
|
227
|
+
/** Negate a filter: `not('status', 'eq', 'done')`. */
|
|
228
|
+
not(column: FilterColumn<S, N>, operator: string, value: unknown): this;
|
|
229
|
+
/** Raw PostgREST `or`: `or('status.eq.open,priority.gt.3')`; `referencedTable` filters an embedded table. */
|
|
230
|
+
or(filters: string, options?: {
|
|
231
|
+
referencedTable?: string;
|
|
232
|
+
}): this;
|
|
233
|
+
/** Sorting; on an embedded table pass `referencedTable` and that table's column. */
|
|
234
|
+
order(column: FilterColumn<S, N>, options?: {
|
|
235
|
+
ascending?: boolean;
|
|
236
|
+
nullsFirst?: boolean;
|
|
237
|
+
}): this;
|
|
238
|
+
order(column: string, options: {
|
|
239
|
+
ascending?: boolean;
|
|
240
|
+
nullsFirst?: boolean;
|
|
241
|
+
referencedTable: string;
|
|
242
|
+
}): this;
|
|
243
|
+
limit(count: number, options?: {
|
|
244
|
+
referencedTable?: string;
|
|
245
|
+
}): this;
|
|
246
|
+
/** Rows `from` to `to`, both included, counting from 0. */
|
|
247
|
+
range(from: number, to: number, options?: {
|
|
248
|
+
referencedTable?: string;
|
|
249
|
+
}): this;
|
|
250
|
+
/** Exactly one row, else an error (PostgREST `PGRST116`). */
|
|
251
|
+
single(): QueryBuilder<S, N, One<Result>>;
|
|
252
|
+
/** One row or null; more than one is an error. */
|
|
253
|
+
maybeSingle(): QueryBuilder<S, N, One<Result> | null>;
|
|
254
|
+
abortSignal(signal: AbortSignal): this;
|
|
255
|
+
/** The url this query will call (for logging and tests; holds filter values). */
|
|
256
|
+
toUrl(): string;
|
|
257
|
+
then<A = DataApiResponse<Result>, B = never>(onfulfilled?: ((value: DataApiResponse<Result>) => A | PromiseLike<A>) | null, onrejected?: ((reason: unknown) => B | PromiseLike<B>) | null): PromiseLike<A | B>;
|
|
258
|
+
/** Throws the error instead of returning it: `const rows = await db.from('todos').select().throwOnError()`. */
|
|
259
|
+
throwOnError(): Promise<Result>;
|
|
260
|
+
private execute;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* GraphQL over the same Data API (`<url>/graphql/v1`): the same key, the same user token, so the same role, grants and
|
|
265
|
+
* row level security as REST. Typed with the documents of graphql-codegen (`client` preset, `documentMode: 'string'`):
|
|
266
|
+
* the result and the variables come from the document.
|
|
267
|
+
*/
|
|
268
|
+
/** What graphql-codegen's client preset produces (`TypedDocumentString`), and what a plain string is too. */
|
|
269
|
+
interface TypedDocument<Result = unknown, Variables = Record<string, unknown>> {
|
|
270
|
+
/** Phantom fields: only for the types. */
|
|
271
|
+
readonly __apiType?: (variables: Variables) => Result;
|
|
272
|
+
/** `persistedDocuments: true` adds the sha256 of the document. */
|
|
273
|
+
readonly __meta__?: {
|
|
274
|
+
readonly hash?: string;
|
|
275
|
+
readonly [key: string]: unknown;
|
|
276
|
+
};
|
|
277
|
+
toString(): string;
|
|
278
|
+
}
|
|
279
|
+
type ResultOf<D> = D extends TypedDocument<infer R, any> ? R : unknown;
|
|
280
|
+
type VariablesOf<D> = D extends TypedDocument<any, infer V> ? V : Record<string, unknown>;
|
|
281
|
+
interface GraphqlError {
|
|
282
|
+
message: string;
|
|
283
|
+
path?: (string | number)[];
|
|
284
|
+
/** `code`: GRAPHQL_VALIDATION_FAILED, max_depth, max_complexity, page_too_large, introspection_disabled, a Postgres code (42501) … */
|
|
285
|
+
extensions?: {
|
|
286
|
+
code?: string;
|
|
287
|
+
[key: string]: unknown;
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
interface GraphqlResponse<T> {
|
|
291
|
+
data: T | null;
|
|
292
|
+
errors: GraphqlError[] | null;
|
|
293
|
+
status: number;
|
|
294
|
+
}
|
|
295
|
+
interface GraphqlOptions {
|
|
296
|
+
operationName?: string;
|
|
297
|
+
/** Send only the hash (`documentId`) of a persisted document; the owner registered it with `hosting db graphql persist`. */
|
|
298
|
+
persisted?: boolean;
|
|
299
|
+
/** The exposed schema to query (default: the first one). */
|
|
300
|
+
schema?: string;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/** Requests in one schema: `db.schema('api').from('orders')`. */
|
|
304
|
+
declare class SchemaClient<S extends GenericSchema> {
|
|
305
|
+
private readonly base;
|
|
306
|
+
private readonly schemaName;
|
|
307
|
+
constructor(base: Omit<RequestContext, 'schema'>, schemaName: string | null);
|
|
308
|
+
/** A table or view: `select`, `insert`, `upsert`, `update`, `delete` with filters. */
|
|
309
|
+
from<T extends TableName<S>>(relation: T): QueryBuilder<S, T, RowOf<S, T>[]>;
|
|
310
|
+
from(relation: string): QueryBuilder<GenericSchema, string, Record<string, unknown>[]>;
|
|
311
|
+
/** A function under `/rpc`: `POST` with the arguments as JSON (or `get: true` for a read-only `GET`). */
|
|
312
|
+
rpc<F extends keyof S['Functions'] & string>(fn: F, args?: S['Functions'][F]['Args'], options?: {
|
|
313
|
+
get?: boolean;
|
|
314
|
+
head?: boolean;
|
|
315
|
+
count?: 'exact' | 'planned' | 'estimated';
|
|
316
|
+
}): Promise<DataApiResponse<S['Functions'][F]['Returns']>>;
|
|
317
|
+
}
|
|
318
|
+
/** The client of one Data API: `createClient(url, key)`. */
|
|
319
|
+
declare class DataClient<Database = AnyDatabase, SchemaName extends string & keyof Database = 'public' & keyof Database> extends SchemaClient<Database[SchemaName] extends GenericSchema ? Database[SchemaName] : GenericSchema> {
|
|
320
|
+
readonly url: string;
|
|
321
|
+
private readonly context;
|
|
322
|
+
constructor(url: string, key: string, options?: ClientOptions);
|
|
323
|
+
/**
|
|
324
|
+
* A GraphQL query or mutation (`<url>/graphql/v1`), with the same key and token as REST. Pass a document of
|
|
325
|
+
* graphql-codegen for typed data and variables: `const { data } = await db.graphql(TodosDocument, { first: 10 })`.
|
|
326
|
+
*/
|
|
327
|
+
graphql<D extends TypedDocument<any, any> | string>(document: D, variables?: VariablesOf<D>, options?: GraphqlOptions): Promise<GraphqlResponse<ResultOf<D>>>;
|
|
328
|
+
/** Requests in another exposed schema. */
|
|
329
|
+
schema<S extends string & keyof Database>(name: S): SchemaClient<Database[S] extends GenericSchema ? Database[S] : GenericSchema>;
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* The client of a Data API of Hosting by Infaris. In the browser use the publishable key and, for a signed-in user,
|
|
333
|
+
* their access token from Infaris Auth; on a server the secret key (it bypasses RLS).
|
|
334
|
+
*
|
|
335
|
+
* ```ts
|
|
336
|
+
* const db = createClient<Database>(process.env.NEXT_PUBLIC_INFARIS_DATA_URL!, process.env.NEXT_PUBLIC_INFARIS_AUTH_KEY!, {
|
|
337
|
+
* accessToken: () => auth.getAccessToken(),
|
|
338
|
+
* });
|
|
339
|
+
* const { data, error } = await db.from('todos').select('id, title').eq('done', false).order('id');
|
|
340
|
+
* ```
|
|
341
|
+
*/
|
|
342
|
+
declare function createClient<Database = AnyDatabase, SchemaName extends string & keyof Database = 'public' & keyof Database>(options: ClientOptions & {
|
|
343
|
+
url: string;
|
|
344
|
+
key: string;
|
|
345
|
+
}): DataClient<Database, SchemaName>;
|
|
346
|
+
/** @deprecated Use createClient({ url, key, ...options }). */
|
|
347
|
+
declare function createClient<Database = AnyDatabase, SchemaName extends string & keyof Database = 'public' & keyof Database>(url: string, key: string, options?: ClientOptions): DataClient<Database, SchemaName>;
|
|
348
|
+
|
|
349
|
+
export { type AnyDatabase, type ClientOptions, type ColumnName, DataApiError, type DataApiResponse, DataClient, type FetchLike, type FilterColumn, type FilterValue, type GenericSchema, type GenericTable, type GraphqlError, type GraphqlOptions, type GraphqlResponse, InfarisError, QueryBuilder, type ResultOf, type RowFor, type RowOf, SchemaClient, type SelectResult, type TableName, type TypedDocument, type VariablesOf, createClient, quoteValue };
|