@xata.io/client 0.0.0-beta.62e04e1 → 0.0.0-beta.645c53a

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.
Files changed (49) hide show
  1. package/.eslintrc.cjs +13 -0
  2. package/CHANGELOG.md +49 -0
  3. package/dist/api/client.d.ts +95 -0
  4. package/dist/api/client.js +236 -0
  5. package/dist/api/components.d.ts +1436 -0
  6. package/dist/api/components.js +997 -0
  7. package/dist/api/fetcher.d.ts +25 -0
  8. package/dist/api/fetcher.js +73 -0
  9. package/dist/api/index.d.ts +7 -0
  10. package/dist/api/index.js +21 -0
  11. package/dist/api/parameters.d.ts +16 -0
  12. package/dist/api/parameters.js +2 -0
  13. package/dist/api/providers.d.ts +8 -0
  14. package/dist/api/providers.js +30 -0
  15. package/dist/api/responses.d.ts +50 -0
  16. package/dist/api/responses.js +2 -0
  17. package/dist/api/schemas.d.ts +311 -0
  18. package/dist/api/schemas.js +2 -0
  19. package/dist/index.d.ts +2 -182
  20. package/dist/index.js +16 -499
  21. package/dist/schema/filters.d.ts +22 -0
  22. package/dist/schema/filters.js +25 -0
  23. package/dist/schema/index.d.ts +7 -0
  24. package/dist/schema/index.js +29 -0
  25. package/dist/schema/operators.d.ts +72 -0
  26. package/dist/schema/operators.js +91 -0
  27. package/dist/schema/pagination.d.ts +83 -0
  28. package/dist/schema/pagination.js +93 -0
  29. package/dist/schema/query.d.ts +118 -0
  30. package/dist/schema/query.js +242 -0
  31. package/dist/schema/record.d.ts +66 -0
  32. package/dist/schema/record.js +13 -0
  33. package/dist/schema/repository.d.ts +100 -0
  34. package/dist/schema/repository.js +288 -0
  35. package/dist/schema/selection.d.ts +25 -0
  36. package/dist/schema/selection.js +2 -0
  37. package/dist/{index.test.d.ts → schema/selection.spec.d.ts} +0 -0
  38. package/dist/schema/selection.spec.js +203 -0
  39. package/dist/util/lang.d.ts +5 -0
  40. package/dist/util/lang.js +22 -0
  41. package/dist/util/types.d.ts +13 -0
  42. package/dist/util/types.js +2 -0
  43. package/package.json +3 -3
  44. package/dist/index.test.js +0 -320
  45. package/dist/util/errors.d.ts +0 -3
  46. package/dist/util/errors.js +0 -9
  47. package/src/index.test.ts +0 -412
  48. package/src/index.ts +0 -667
  49. package/src/util/errors.ts +0 -6
package/src/index.ts DELETED
@@ -1,667 +0,0 @@
1
- import { errors } from './util/errors';
2
-
3
- export interface XataRecord {
4
- id: string;
5
- xata: {
6
- version: number;
7
- };
8
- read(): Promise<this>;
9
- update(data: Selectable<this>): Promise<this>;
10
- delete(): Promise<void>;
11
- }
12
-
13
- export type Queries<T> = {
14
- [key in keyof T as T[key] extends Query<infer A, infer B> ? key : never]: T[key];
15
- };
16
-
17
- export type OmitQueries<T> = {
18
- [key in keyof T as T[key] extends Query<infer A, infer B> ? never : key]: T[key];
19
- };
20
-
21
- export type OmitLinks<T> = {
22
- [key in keyof T as T[key] extends XataRecord ? never : key]: T[key];
23
- };
24
-
25
- export type OmitMethods<T> = {
26
- // eslint-disable-next-line @typescript-eslint/ban-types
27
- [key in keyof T as T[key] extends Function ? never : key]: T[key];
28
- };
29
-
30
- export type Selectable<T> = Omit<OmitQueries<OmitMethods<T>>, 'id' | 'xata'>;
31
-
32
- export type Select<T, K extends keyof T> = Pick<T, K> & Queries<T> & XataRecord;
33
-
34
- export type Include<T> = {
35
- [key in keyof T as T[key] extends XataRecord ? key : never]?: boolean | Array<keyof Selectable<T[key]>>;
36
- };
37
-
38
- type SortDirection = 'asc' | 'desc';
39
-
40
- type Operator =
41
- | '$gt'
42
- | '$lt'
43
- | '$ge'
44
- | '$le'
45
- | '$exists'
46
- | '$notExists'
47
- | '$endsWith'
48
- | '$startsWith'
49
- | '$pattern'
50
- | '$is'
51
- | '$isNot'
52
- | '$contains'
53
- | '$includes'
54
- | '$includesSubstring'
55
- | '$includesPattern'
56
- | '$includesAll';
57
-
58
- // TODO: restrict constraints depending on type?
59
- // E.g. startsWith cannot be used with numbers
60
- type Constraint<T> = { [key in Operator]?: T };
61
-
62
- type DeepConstraint<T> = T extends Record<string, any>
63
- ? {
64
- [key in keyof T]?: T[key] | DeepConstraint<T[key]>;
65
- }
66
- : Constraint<T>;
67
-
68
- type ComparableType = number | Date;
69
-
70
- export const gt = <T extends ComparableType>(value: T): Constraint<T> => ({ $gt: value });
71
- export const ge = <T extends ComparableType>(value: T): Constraint<T> => ({ $ge: value });
72
- export const gte = <T extends ComparableType>(value: T): Constraint<T> => ({ $ge: value });
73
- export const lt = <T extends ComparableType>(value: T): Constraint<T> => ({ $lt: value });
74
- export const lte = <T extends ComparableType>(value: T): Constraint<T> => ({ $le: value });
75
- export const le = <T extends ComparableType>(value: T): Constraint<T> => ({ $le: value });
76
- export const exists = (column: string): Constraint<string> => ({ $exists: column });
77
- export const notExists = (column: string): Constraint<string> => ({ $notExists: column });
78
- export const startsWith = (value: string): Constraint<string> => ({ $startsWith: value });
79
- export const endsWith = (value: string): Constraint<string> => ({ $endsWith: value });
80
- export const pattern = (value: string): Constraint<string> => ({ $pattern: value });
81
- export const is = <T>(value: T): Constraint<T> => ({ $is: value });
82
- export const isNot = <T>(value: T): Constraint<T> => ({ $isNot: value });
83
- export const contains = <T>(value: T): Constraint<T> => ({ $contains: value });
84
-
85
- // TODO: these can only be applied to columns of type "multiple"
86
- export const includes = (value: string): Constraint<string> => ({ $includes: value });
87
- export const includesSubstring = (value: string): Constraint<string> => ({ $includesSubstring: value });
88
- export const includesPattern = (value: string): Constraint<string> => ({ $includesPattern: value });
89
- export const includesAll = (value: string): Constraint<string> => ({ $includesAll: value });
90
-
91
- type FilterConstraints<T> = {
92
- [key in keyof T]?: T[key] extends Record<string, any> ? FilterConstraints<T[key]> : T[key] | DeepConstraint<T[key]>;
93
- };
94
-
95
- type CursorNavigationOptions = { first?: string } | { last?: string } | { after?: string; before?: string };
96
- type OffsetNavigationOptions = { size?: number; offset?: number };
97
- type PaginationOptions = CursorNavigationOptions & OffsetNavigationOptions;
98
-
99
- type BulkQueryOptions<T> = {
100
- page?: PaginationOptions;
101
- /** TODO: Not implemented yet
102
- filter?: FilterConstraints<T>;
103
- sort?:
104
- | {
105
- column: keyof T;
106
- direction?: SortDirection;
107
- }
108
- | keyof T;
109
- **/
110
- };
111
-
112
- type QueryOrConstraint<T, R> = Query<T, R> | Constraint<T>;
113
-
114
- type QueryMeta = { page: { cursor: string; more: boolean } };
115
-
116
- interface BasePage<T, R> {
117
- query: Query<T, R>;
118
- meta: QueryMeta;
119
- records: R[];
120
-
121
- nextPage(size?: number, offset?: number): Promise<Page<T, R>>;
122
- previousPage(size?: number, offset?: number): Promise<Page<T, R>>;
123
- firstPage(size?: number, offset?: number): Promise<Page<T, R>>;
124
- lastPage(size?: number, offset?: number): Promise<Page<T, R>>;
125
-
126
- hasNextPage(): boolean;
127
- }
128
-
129
- class Page<T, R> implements BasePage<T, R> {
130
- readonly query: Query<T, R>;
131
- readonly meta: QueryMeta;
132
- readonly records: R[];
133
-
134
- constructor(query: Query<T, R>, meta: QueryMeta, records: R[] = []) {
135
- this.query = query;
136
- this.meta = meta;
137
- this.records = records;
138
- }
139
-
140
- async nextPage(size?: number, offset?: number): Promise<Page<T, R>> {
141
- return this.query.getPaginated({ page: { size, offset, after: this.meta.page.cursor } });
142
- }
143
-
144
- async previousPage(size?: number, offset?: number): Promise<Page<T, R>> {
145
- return this.query.getPaginated({ page: { size, offset, before: this.meta.page.cursor } });
146
- }
147
-
148
- async firstPage(size?: number, offset?: number): Promise<Page<T, R>> {
149
- return this.query.getPaginated({ page: { size, offset, first: this.meta.page.cursor } });
150
- }
151
-
152
- async lastPage(size?: number, offset?: number): Promise<Page<T, R>> {
153
- return this.query.getPaginated({ page: { size, offset, last: this.meta.page.cursor } });
154
- }
155
-
156
- // TODO: We need to add something on the backend if we want a hasPreviousPage
157
- hasNextPage(): boolean {
158
- return this.meta.page.more;
159
- }
160
- }
161
-
162
- export class Query<T, R = T> implements BasePage<T, R> {
163
- table: string;
164
- repository: Repository<T>;
165
-
166
- readonly $any?: QueryOrConstraint<T, R>[];
167
- readonly $all?: QueryOrConstraint<T, R>[];
168
- readonly $not?: QueryOrConstraint<T, R>[];
169
- readonly $none?: QueryOrConstraint<T, R>[];
170
- readonly $sort?: Record<string, SortDirection>;
171
-
172
- // Cursor pagination
173
- readonly query: Query<T, R> = this;
174
- readonly meta: QueryMeta = { page: { cursor: 'start', more: true } };
175
- readonly records: R[] = [];
176
-
177
- constructor(repository: Repository<T> | null, table: string, data: Partial<Query<T, R>>, parent?: Query<T, R>) {
178
- if (repository) {
179
- this.repository = repository;
180
- } else {
181
- this.repository = this as any;
182
- }
183
- this.table = table;
184
-
185
- // For some reason Object.assign(this, parent) didn't work in this case
186
- // so doing all this manually:
187
- this.$any = parent?.$any;
188
- this.$all = parent?.$all;
189
- this.$not = parent?.$not;
190
- this.$none = parent?.$none;
191
- this.$sort = parent?.$sort;
192
-
193
- Object.assign(this, data);
194
- // These bindings are used to support deconstructing
195
- // const { any, not, filter, sort } = xata.users.query()
196
- this.any = this.any.bind(this);
197
- this.all = this.all.bind(this);
198
- this.not = this.not.bind(this);
199
- this.filter = this.filter.bind(this);
200
- this.sort = this.sort.bind(this);
201
- this.none = this.none.bind(this);
202
-
203
- Object.defineProperty(this, 'table', { enumerable: false });
204
- Object.defineProperty(this, 'repository', { enumerable: false });
205
- }
206
-
207
- any(...queries: Query<T, R>[]): Query<T, R> {
208
- return new Query<T, R>(
209
- this.repository,
210
- this.table,
211
- {
212
- $any: (this.$any || []).concat(queries)
213
- },
214
- this
215
- );
216
- }
217
-
218
- all(...queries: Query<T, R>[]): Query<T, R> {
219
- return new Query<T, R>(
220
- this.repository,
221
- this.table,
222
- {
223
- $all: (this.$all || []).concat(queries)
224
- },
225
- this
226
- );
227
- }
228
-
229
- not(...queries: Query<T, R>[]): Query<T, R> {
230
- return new Query<T, R>(
231
- this.repository,
232
- this.table,
233
- {
234
- $not: (this.$not || []).concat(queries)
235
- },
236
- this
237
- );
238
- }
239
-
240
- none(...queries: Query<T, R>[]): Query<T, R> {
241
- return new Query<T, R>(
242
- this.repository,
243
- this.table,
244
- {
245
- $none: (this.$none || []).concat(queries)
246
- },
247
- this
248
- );
249
- }
250
-
251
- filter(constraints: FilterConstraints<T>): Query<T, R>;
252
- filter<F extends keyof T>(column: F, value: FilterConstraints<T[F]> | DeepConstraint<T[F]>): Query<T, R>;
253
- filter(a: any, b?: any): Query<T, R> {
254
- if (arguments.length === 1) {
255
- const constraints = a as FilterConstraints<T>;
256
- const queries: QueryOrConstraint<T, R>[] = [];
257
- for (const [column, constraint] of Object.entries(constraints)) {
258
- queries.push({ [column]: constraint });
259
- }
260
- return new Query<T, R>(
261
- this.repository,
262
- this.table,
263
- {
264
- $all: (this.$all || []).concat(queries)
265
- },
266
- this
267
- );
268
- } else {
269
- const column = a as keyof T;
270
- const value = b as Partial<T[keyof T]> | Constraint<T[keyof T]>;
271
- return new Query<T, R>(
272
- this.repository,
273
- this.table,
274
- {
275
- $all: (this.$all || []).concat({ [column]: value })
276
- },
277
- this
278
- );
279
- }
280
- }
281
-
282
- sort<F extends keyof T>(column: F, direction: SortDirection): Query<T, R> {
283
- const sort = { ...this.$sort, [column]: direction };
284
- const q = new Query<T, R>(
285
- this.repository,
286
- this.table,
287
- {
288
- $sort: sort
289
- },
290
- this
291
- );
292
-
293
- return q;
294
- }
295
-
296
- async getPaginated(options?: BulkQueryOptions<T>): Promise<Page<T, R>> {
297
- return this.repository._runQuery(this, options);
298
- }
299
-
300
- async *[Symbol.asyncIterator](): AsyncIterableIterator<R> {
301
- for await (const [record] of this.getIterator(1)) {
302
- yield record;
303
- }
304
- }
305
-
306
- async *getIterator(chunk: number, options: Omit<BulkQueryOptions<T>, 'page'> = {}): AsyncGenerator<R[]> {
307
- let offset = 0;
308
- let end = false;
309
-
310
- while (!end) {
311
- const { records, meta } = await this.getPaginated({ ...options, page: { size: chunk, offset } });
312
- yield records;
313
-
314
- offset += chunk;
315
- end = !meta.page.more;
316
- }
317
- }
318
-
319
- async getMany(options?: BulkQueryOptions<T>): Promise<R[]> {
320
- const { records } = await this.getPaginated(options);
321
- return records;
322
- }
323
-
324
- async getOne(options: Omit<BulkQueryOptions<T>, 'page'> = {}): Promise<R | null> {
325
- const records = await this.getMany({ ...options, page: { size: 1 } });
326
- return records[0] || null;
327
- }
328
-
329
- async deleteAll(): Promise<number> {
330
- // TODO: Return number of affected rows
331
- return 0;
332
- }
333
-
334
- include(columns: Include<T>) {
335
- // TODO
336
- return this;
337
- }
338
-
339
- async nextPage(size?: number, offset?: number): Promise<Page<T, R>> {
340
- return this.firstPage(size, offset);
341
- }
342
-
343
- async previousPage(size?: number, offset?: number): Promise<Page<T, R>> {
344
- return this.firstPage(size, offset);
345
- }
346
-
347
- async firstPage(size?: number, offset?: number): Promise<Page<T, R>> {
348
- return this.getPaginated({ page: { size, offset } });
349
- }
350
-
351
- async lastPage(size?: number, offset?: number): Promise<Page<T, R>> {
352
- return this.getPaginated({ page: { size, offset, before: 'end' } });
353
- }
354
-
355
- hasNextPage(): boolean {
356
- return this.meta.page.more;
357
- }
358
- }
359
-
360
- export abstract class Repository<T> extends Query<T, Selectable<T>> {
361
- select<K extends keyof Selectable<T>>(...columns: K[]) {
362
- return new Query<T, Select<T, K>>(this.repository, this.table, {});
363
- }
364
-
365
- abstract create(object: Selectable<T>): Promise<T>;
366
-
367
- abstract createMany(objects: Selectable<T>[]): Promise<T[]>;
368
-
369
- abstract read(id: string): Promise<T | null>;
370
-
371
- abstract update(id: string, object: Partial<T>): Promise<T>;
372
-
373
- abstract delete(id: string): void;
374
-
375
- // Used by the Query object internally
376
- abstract _runQuery<R>(query: Query<T, R>, options?: BulkQueryOptions<T>): Promise<Page<T, R>>;
377
- }
378
-
379
- export class RestRepository<T> extends Repository<T> {
380
- client: BaseClient<any>;
381
- fetch: any;
382
-
383
- constructor(client: BaseClient<any>, table: string) {
384
- super(null, table, {});
385
- this.client = client;
386
-
387
- const doWeHaveFetch = typeof fetch !== 'undefined';
388
- const isInjectedFetchProblematic = !this.client.options.fetch;
389
-
390
- if (doWeHaveFetch) {
391
- this.fetch = fetch;
392
- } else if (isInjectedFetchProblematic) {
393
- throw new Error(errors.falsyFetchImplementation);
394
- } else {
395
- this.fetch = this.client.options.fetch;
396
- }
397
-
398
- Object.defineProperty(this, 'client', { enumerable: false });
399
- Object.defineProperty(this, 'fetch', { enumerable: false });
400
- Object.defineProperty(this, 'hostname', { enumerable: false });
401
- }
402
-
403
- async request<T>(method: string, path: string, body?: unknown): Promise<T | undefined> {
404
- const { databaseURL, apiKey } = this.client.options;
405
- const branch = await this.client.getBranch();
406
-
407
- const resp: Response = await this.fetch(`${databaseURL}:${branch}${path}`, {
408
- method,
409
- headers: {
410
- Accept: '*/*',
411
- 'Content-Type': 'application/json',
412
- Authorization: `Bearer ${apiKey}`
413
- },
414
- body: JSON.stringify(body)
415
- });
416
-
417
- if (!resp.ok) {
418
- try {
419
- const json = await resp.json();
420
- const message = json.message;
421
- if (typeof message === 'string') {
422
- throw new XataError(message, resp.status);
423
- }
424
- } catch (err) {
425
- if (err instanceof XataError) throw err;
426
- // Ignore errors for other reasons.
427
- // For example if the response's body cannot be parsed as JSON
428
- }
429
- throw new XataError(resp.statusText, resp.status);
430
- }
431
-
432
- if (resp.status === 204) return undefined;
433
- return resp.json();
434
- }
435
-
436
- select<K extends keyof T>(...columns: K[]) {
437
- return new Query<T, Select<T, K>>(this.repository, this.table, {});
438
- }
439
-
440
- async create(object: T): Promise<T> {
441
- const record = transformObjectLinks(object);
442
-
443
- const response = await this.request<{
444
- id: string;
445
- xata: { version: number };
446
- }>('POST', `/tables/${this.table}/data`, record);
447
- if (!response) {
448
- throw new Error("The server didn't return any data for the query");
449
- }
450
-
451
- const finalObject = await this.read(response.id);
452
- if (!finalObject) {
453
- throw new Error('The server failed to save the record');
454
- }
455
-
456
- return finalObject;
457
- }
458
-
459
- async createMany(objects: T[]): Promise<T[]> {
460
- const records = objects.map((object) => transformObjectLinks(object));
461
-
462
- const response = await this.request<{
463
- recordIDs: string[];
464
- }>('POST', `/tables/${this.table}/bulk`, { records });
465
- if (!response) {
466
- throw new Error("The server didn't return any data for the query");
467
- }
468
-
469
- // TODO: Use filer.$any() to get all the records
470
- const finalObjects = await Promise.all(response.recordIDs.map((id) => this.read(id)));
471
- if (finalObjects.some((object) => !object)) {
472
- throw new Error('The server failed to save the record');
473
- }
474
-
475
- return finalObjects as T[];
476
- }
477
-
478
- async read(id: string): Promise<T | null> {
479
- try {
480
- const response = await this.request<
481
- T & { id: string; xata: { version: number; table?: string; warnings?: string[] } }
482
- >('GET', `/tables/${this.table}/data/${id}`);
483
- if (!response) return null;
484
-
485
- return this.client.initObject(this.table, response);
486
- } catch (err) {
487
- if ((err as XataError).status === 404) return null;
488
- throw err;
489
- }
490
- }
491
-
492
- async update(id: string, object: Partial<T>): Promise<T> {
493
- const response = await this.request<{
494
- id: string;
495
- xata: { version: number };
496
- }>('PUT', `/tables/${this.table}/data/${id}`, object);
497
- if (!response) {
498
- throw new Error("The server didn't return any data for the query");
499
- }
500
-
501
- // TODO: Review this, not sure we are properly initializing the object
502
- return this.client.initObject(this.table, response);
503
- }
504
-
505
- async delete(id: string) {
506
- await this.request('DELETE', `/tables/${this.table}/data/${id}`);
507
- }
508
-
509
- async _runQuery<R>(query: Query<T, R>, options?: BulkQueryOptions<T>): Promise<Page<T, R>> {
510
- const filter = {
511
- $any: query.$any,
512
- $all: query.$all,
513
- $not: query.$not,
514
- $none: query.$none
515
- };
516
-
517
- const body = {
518
- filter: Object.values(filter).some(Boolean) ? filter : undefined,
519
- sort: query.$sort,
520
- page: options?.page
521
- };
522
-
523
- const response = await this.request<{
524
- records: object[];
525
- meta: { page: { cursor: string; more: boolean } };
526
- }>('POST', `/tables/${this.table}/query`, body);
527
- if (!response) {
528
- throw new Error("The server didn't return any data for the query");
529
- }
530
-
531
- const { meta, records: objects } = response;
532
- const records = objects.map((record) => this.client.initObject<R>(this.table, record));
533
-
534
- return new Page(query, meta, records);
535
- }
536
- }
537
-
538
- interface RepositoryFactory {
539
- createRepository<T>(client: BaseClient<any>, table: string): Repository<T>;
540
- }
541
-
542
- export class RestRespositoryFactory implements RepositoryFactory {
543
- createRepository<T>(client: BaseClient<any>, table: string): Repository<T> {
544
- return new RestRepository<T>(client, table);
545
- }
546
- }
547
-
548
- type BranchStrategyValue = string | undefined | null;
549
- type BranchStrategyBuilder = () => BranchStrategyValue | Promise<BranchStrategyValue>;
550
- type BranchStrategy = BranchStrategyValue | BranchStrategyBuilder;
551
- type BranchStrategyOption = NonNullable<BranchStrategy | BranchStrategy[]>;
552
-
553
- export type XataClientOptions = {
554
- fetch?: unknown;
555
- databaseURL: string;
556
- branch: BranchStrategyOption;
557
- apiKey: string;
558
- repositoryFactory?: RepositoryFactory;
559
- };
560
-
561
- export class BaseClient<D extends Record<string, Repository<any>>> {
562
- options: XataClientOptions;
563
- private links: Links;
564
- private branch: BranchStrategyValue;
565
- db!: D;
566
-
567
- constructor(options: XataClientOptions, links: Links) {
568
- if (!options.databaseURL || !options.apiKey || !options.branch) {
569
- throw new Error('Options databaseURL, apiKey and branch are required');
570
- }
571
-
572
- this.options = options;
573
- this.links = links;
574
- }
575
-
576
- public initObject<T>(table: string, object: object) {
577
- const o: Record<string, unknown> = {};
578
- Object.assign(o, object);
579
-
580
- const tableLinks = this.links[table] || [];
581
- for (const link of tableLinks) {
582
- const [field, linkTable] = link;
583
- const value = o[field];
584
-
585
- if (value && typeof value === 'object') {
586
- const { id } = value as any;
587
- if (Object.keys(value).find((col) => col === 'id')) {
588
- o[field] = this.initObject(linkTable, value);
589
- } else if (id) {
590
- o[field] = {
591
- id,
592
- get: () => {
593
- this.db[linkTable].read(id);
594
- }
595
- };
596
- }
597
- }
598
- }
599
-
600
- const db = this.db;
601
- o.read = function () {
602
- return db[table].read(o['id'] as string);
603
- };
604
- o.update = function (data: any) {
605
- return db[table].update(o['id'] as string, data);
606
- };
607
- o.delete = function () {
608
- return db[table].delete(o['id'] as string);
609
- };
610
-
611
- for (const prop of ['read', 'update', 'delete']) {
612
- Object.defineProperty(o, prop, { enumerable: false });
613
- }
614
-
615
- // TODO: links and rev links
616
-
617
- Object.freeze(o);
618
- return o as T;
619
- }
620
-
621
- public async getBranch(): Promise<string> {
622
- if (this.branch) return this.branch;
623
-
624
- const { branch: param } = this.options;
625
- const strategies = Array.isArray(param) ? [...param] : [param];
626
-
627
- const evaluateBranch = async (strategy: BranchStrategy) => {
628
- return isBranchStrategyBuilder(strategy) ? await strategy() : strategy;
629
- };
630
-
631
- for await (const strategy of strategies) {
632
- const branch = await evaluateBranch(strategy);
633
- if (branch) {
634
- this.branch = branch;
635
- return branch;
636
- }
637
- }
638
-
639
- throw new Error('Unable to resolve branch value');
640
- }
641
- }
642
-
643
- export class XataError extends Error {
644
- readonly status: number;
645
-
646
- constructor(message: string, status: number) {
647
- super(message);
648
- this.status = status;
649
- }
650
- }
651
-
652
- export type Links = Record<string, Array<string[]>>;
653
-
654
- const isBranchStrategyBuilder = (strategy: BranchStrategy): strategy is BranchStrategyBuilder => {
655
- return typeof strategy === 'function';
656
- };
657
-
658
- // TODO: We can find a better implementation for links
659
- const transformObjectLinks = (object: any) => {
660
- return Object.entries(object).reduce((acc, [key, value]) => {
661
- if (value && typeof value === 'object' && typeof (value as Record<string, unknown>).id === 'string') {
662
- return { ...acc, [key]: (value as XataRecord).id };
663
- }
664
-
665
- return { ...acc, [key]: value };
666
- }, {});
667
- };
@@ -1,6 +0,0 @@
1
- export const errors = {
2
- falsyFetchImplementation: `The \`fetch\` option passed to the Xata client is resolving to a falsy value and may not be correctly imported.
3
-
4
- More in the docs:
5
- ` /** @todo add a link after docs exist */
6
- };