@xata.io/client 0.13.0 → 0.13.3

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.d.ts CHANGED
@@ -6,6 +6,9 @@ declare type FetchImpl = (url: string, init?: {
6
6
  ok: boolean;
7
7
  status: number;
8
8
  json(): Promise<any>;
9
+ headers?: {
10
+ get(name: string): string | null;
11
+ };
9
12
  }>;
10
13
  declare type WorkspaceApiUrlBuilder = (path: string, pathParams: Record<string, string>) => string;
11
14
  declare type FetcherExtraProps = {
@@ -2798,7 +2801,7 @@ declare class DatabaseApi {
2798
2801
  getGitBranchesMapping(workspace: WorkspaceID, dbName: DBName): Promise<ListGitBranchesResponse>;
2799
2802
  addGitBranchesEntry(workspace: WorkspaceID, dbName: DBName, body: AddGitBranchesEntryRequestBody): Promise<AddGitBranchesEntryResponse>;
2800
2803
  removeGitBranchesEntry(workspace: WorkspaceID, dbName: DBName, gitBranch: string): Promise<void>;
2801
- resolveBranch(workspace: WorkspaceID, dbName: DBName, gitBranch: string): Promise<ResolveBranchResponse>;
2804
+ resolveBranch(workspace: WorkspaceID, dbName: DBName, gitBranch?: string, fallbackBranch?: string): Promise<ResolveBranchResponse>;
2802
2805
  }
2803
2806
  declare class BranchApi {
2804
2807
  private extraProps;
@@ -2867,25 +2870,24 @@ declare type SelectableColumn<O, RecursivePath extends any[] = []> = '*' | 'id'
2867
2870
  declare type SelectedPick<O extends XataRecord, Key extends SelectableColumn<O>[]> = XataRecord & UnionToIntersection<Values<{
2868
2871
  [K in Key[number]]: NestedValueAtColumn<O, K> & XataRecord;
2869
2872
  }>>;
2870
- declare type ValueAtColumn<O, P extends SelectableColumn<O>> = P extends '*' ? Values<O> : P extends 'id' ? string : P extends keyof O ? O[P] : P extends `${infer K}.${infer V}` ? K extends keyof O ? Values<RemoveNullable<O[K]> extends Record<string, any> ? V extends SelectableColumn<RemoveNullable<O[K]>> ? {
2871
- V: ValueAtColumn<RemoveNullable<O[K]>, V>;
2872
- } : never : O[K]> : never : never;
2873
+ declare type ValueAtColumn<O, P extends SelectableColumn<O>> = P extends '*' ? Values<O> : P extends 'id' ? string : P extends keyof O ? O[P] : P extends `${infer K}.${infer V}` ? K extends keyof O ? Values<NonNullable<O[K]> extends infer Item ? Item extends Record<string, any> ? V extends SelectableColumn<Item> ? {
2874
+ V: ValueAtColumn<Item, V>;
2875
+ } : never : O[K] : never> : never : never;
2873
2876
  declare type MAX_RECURSION = 5;
2874
2877
  declare type NestedColumns<O, RecursivePath extends any[]> = RecursivePath['length'] extends MAX_RECURSION ? never : If<IsObject<O>, Values<{
2875
- [K in DataProps<O>]: If<IsArray<RemoveNullable<O[K]>>, K, // If the property is an array, we stop recursion. We don't support object arrays yet
2876
- If<IsObject<RemoveNullable<O[K]>>, RemoveNullable<O[K]> extends XataRecord ? SelectableColumn<RemoveNullable<O[K]>, [...RecursivePath, O[K]]> extends infer Column ? Column extends string ? K | `${K}.${Column}` : never : never : `${K}.${StringKeys<RemoveNullable<O[K]>> | '*'}`, // This allows usage of objects that are not links
2877
- K>>;
2878
+ [K in DataProps<O>]: NonNullable<O[K]> extends infer Item ? If<IsArray<Item>, K, // If the property is an array, we stop recursion. We don't support object arrays yet
2879
+ If<IsObject<Item>, Item extends XataRecord ? SelectableColumn<Item, [...RecursivePath, Item]> extends infer Column ? Column extends string ? K | `${K}.${Column}` : never : never : Item extends Date ? K : `${K}.${StringKeys<Item> | '*'}`, // This allows usage of objects that are not links
2880
+ K>> : never;
2878
2881
  }>, never>;
2879
2882
  declare type DataProps<O> = Exclude<StringKeys<O>, StringKeys<XataRecord>>;
2880
2883
  declare type NestedValueAtColumn<O, Key extends SelectableColumn<O>> = Key extends `${infer N}.${infer M}` ? N extends DataProps<O> ? {
2881
- [K in N]: M extends SelectableColumn<RemoveNullable<O[K]>> ? RemoveNullable<O[K]> extends XataRecord ? ForwardNullable<O[K], NestedValueAtColumn<RemoveNullable<O[K]>, M> & XataRecord> : ForwardNullable<O[K], NestedValueAtColumn<RemoveNullable<O[K]>, M>> : unknown;
2884
+ [K in N]: M extends SelectableColumn<NonNullable<O[K]>> ? NonNullable<O[K]> extends XataRecord ? ForwardNullable<O[K], NestedValueAtColumn<NonNullable<O[K]>, M> & XataRecord> : ForwardNullable<O[K], NestedValueAtColumn<NonNullable<O[K]>, M>> : unknown;
2882
2885
  } : unknown : Key extends DataProps<O> ? {
2883
- [K in Key]: RemoveNullable<O[K]> extends XataRecord ? ForwardNullable<O[K], SelectedPick<RemoveNullable<O[K]>, ['*']>> : O[K];
2886
+ [K in Key]: NonNullable<O[K]> extends XataRecord ? ForwardNullable<O[K], SelectedPick<NonNullable<O[K]>, ['*']>> : O[K];
2884
2887
  } : Key extends '*' ? {
2885
- [K in StringKeys<O>]: RemoveNullable<O[K]> extends XataRecord ? ForwardNullable<O[K], Link<RemoveNullable<O[K]>>> : O[K];
2888
+ [K in StringKeys<O>]: NonNullable<O[K]> extends XataRecord ? ForwardNullable<O[K], Link<NonNullable<O[K]>>> : O[K];
2886
2889
  } : unknown;
2887
- declare type RemoveNullable<T> = T extends null | undefined ? never : T;
2888
- declare type ForwardNullable<T, R> = T extends RemoveNullable<T> ? R : R | null;
2890
+ declare type ForwardNullable<T, R> = T extends NonNullable<T> ? R : R | null;
2889
2891
 
2890
2892
  /**
2891
2893
  * Represents an identifiable record from the database.
@@ -2950,9 +2952,9 @@ declare function isXataRecord(x: any): x is XataRecord & Record<string, unknown>
2950
2952
  declare type EditableData<O extends BaseData> = {
2951
2953
  [K in keyof O]: O[K] extends XataRecord ? {
2952
2954
  id: string;
2953
- } : NonNullable<O[K]> extends XataRecord ? {
2955
+ } | string : NonNullable<O[K]> extends XataRecord ? {
2954
2956
  id: string;
2955
- } | null | undefined : O[K];
2957
+ } | string | null | undefined : O[K];
2956
2958
  };
2957
2959
 
2958
2960
  /**
@@ -3380,6 +3382,7 @@ declare function isCursorPaginationOptions(options: Record<string, unknown> | un
3380
3382
  declare class RecordArray<Result extends XataRecord> extends Array<Result> {
3381
3383
  #private;
3382
3384
  constructor(page: Paginable<any, Result>, overrideRecords?: Result[]);
3385
+ static parseConstructorParams(...args: any[]): any[];
3383
3386
  /**
3384
3387
  * Retrieve next page of records
3385
3388
  *
@@ -3440,6 +3443,18 @@ declare abstract class Repository<Data extends BaseData, Record extends XataReco
3440
3443
  * @returns The persisted records for the given ids (if a record could not be found it is not returned).
3441
3444
  */
3442
3445
  abstract read(ids: string[]): Promise<Array<Readonly<SelectedPick<Record, ['*']>>>>;
3446
+ /**
3447
+ * Queries a single record from the table by the id in the object.
3448
+ * @param object Object containing the id of the record.
3449
+ * @returns The persisted record for the given id or null if the record could not be found.
3450
+ */
3451
+ abstract read(object: Identifiable): Promise<Readonly<SelectedPick<Record, ['*']> | null>>;
3452
+ /**
3453
+ * Queries multiple records from the table by the ids in the objects.
3454
+ * @param objects Array of objects containing the ids of the records.
3455
+ * @returns The persisted records for the given ids (if a record could not be found it is not returned).
3456
+ */
3457
+ abstract read(objects: Identifiable[]): Promise<Array<Readonly<SelectedPick<Record, ['*']>>>>;
3443
3458
  /**
3444
3459
  * Partially update a single record.
3445
3460
  * @param object An object with its id and the columns to be updated.
@@ -3531,6 +3546,8 @@ declare class RestRepository<Data extends BaseData, Record extends XataRecord =
3531
3546
  create(objects: EditableData<Data>[]): Promise<SelectedPick<Record, ['*']>[]>;
3532
3547
  read(recordId: string): Promise<SelectedPick<Record, ['*']> | null>;
3533
3548
  read(recordIds: string[]): Promise<Array<Readonly<SelectedPick<Record, ['*']>>>>;
3549
+ read(object: Identifiable): Promise<SelectedPick<Record, ['*']> | null>;
3550
+ read(objects: Identifiable[]): Promise<Array<Readonly<SelectedPick<Record, ['*']>>>>;
3534
3551
  update(object: Partial<EditableData<Data>> & Identifiable): Promise<SelectedPick<Record, ['*']>>;
3535
3552
  update(recordId: string, object: Partial<EditableData<Data>>): Promise<SelectedPick<Record, ['*']>>;
3536
3553
  update(objects: Array<Partial<EditableData<Data>> & Identifiable>): Promise<SelectedPick<Record, ['*']>[]>;
package/dist/index.mjs CHANGED
@@ -17,7 +17,8 @@ function toBase64(value) {
17
17
  try {
18
18
  return btoa(value);
19
19
  } catch (err) {
20
- return Buffer.from(value).toString("base64");
20
+ const buf = Buffer;
21
+ return buf.from(value).toString("base64");
21
22
  }
22
23
  }
23
24
 
@@ -73,21 +74,28 @@ function getFetchImplementation(userFetch) {
73
74
  return fetchImpl;
74
75
  }
75
76
 
77
+ const VERSION = "0.13.3";
78
+
76
79
  class ErrorWithCause extends Error {
77
80
  constructor(message, options) {
78
81
  super(message, options);
79
82
  }
80
83
  }
81
84
  class FetcherError extends ErrorWithCause {
82
- constructor(status, data) {
85
+ constructor(status, data, requestId) {
83
86
  super(getMessage(data));
84
87
  this.status = status;
85
88
  this.errors = isBulkError(data) ? data.errors : void 0;
89
+ this.requestId = requestId;
86
90
  if (data instanceof Error) {
87
91
  this.stack = data.stack;
88
92
  this.cause = data.cause;
89
93
  }
90
94
  }
95
+ toString() {
96
+ const error = super.toString();
97
+ return `[${this.status}] (${this.requestId ?? "Unknown"}): ${error}`;
98
+ }
91
99
  }
92
100
  function isBulkError(error) {
93
101
  return isObject(error) && Array.isArray(error.errors);
@@ -110,7 +118,12 @@ function getMessage(data) {
110
118
  }
111
119
 
112
120
  const resolveUrl = (url, queryParams = {}, pathParams = {}) => {
113
- const query = new URLSearchParams(queryParams).toString();
121
+ const cleanQueryParams = Object.entries(queryParams).reduce((acc, [key, value]) => {
122
+ if (value === void 0 || value === null)
123
+ return acc;
124
+ return { ...acc, [key]: value };
125
+ }, {});
126
+ const query = new URLSearchParams(cleanQueryParams).toString();
114
127
  const queryString = query.length > 0 ? `?${query}` : "";
115
128
  return url.replace(/\{\w*\}/g, (key) => pathParams[key.slice(1, -1)]) + queryString;
116
129
  };
@@ -150,6 +163,7 @@ async function fetch$1({
150
163
  body: body ? JSON.stringify(body) : void 0,
151
164
  headers: {
152
165
  "Content-Type": "application/json",
166
+ "User-Agent": `Xata client-ts/${VERSION}`,
153
167
  ...headers,
154
168
  ...hostHeader(fullUrl),
155
169
  Authorization: `Bearer ${apiKey}`
@@ -158,14 +172,15 @@ async function fetch$1({
158
172
  if (response.status === 204) {
159
173
  return {};
160
174
  }
175
+ const requestId = response.headers?.get("x-request-id") ?? void 0;
161
176
  try {
162
177
  const jsonResponse = await response.json();
163
178
  if (response.ok) {
164
179
  return jsonResponse;
165
180
  }
166
- throw new FetcherError(response.status, jsonResponse);
181
+ throw new FetcherError(response.status, jsonResponse, requestId);
167
182
  } catch (error) {
168
- throw new FetcherError(response.status, error);
183
+ throw new FetcherError(response.status, error, requestId);
169
184
  }
170
185
  }
171
186
 
@@ -689,10 +704,10 @@ class DatabaseApi {
689
704
  ...this.extraProps
690
705
  });
691
706
  }
692
- resolveBranch(workspace, dbName, gitBranch) {
707
+ resolveBranch(workspace, dbName, gitBranch, fallbackBranch) {
693
708
  return operationsByTag.database.resolveBranch({
694
709
  pathParams: { workspace, dbName },
695
- queryParams: { gitBranch },
710
+ queryParams: { gitBranch, fallbackBranch },
696
711
  ...this.extraProps
697
712
  });
698
713
  }
@@ -976,10 +991,20 @@ function isCursorPaginationOptions(options) {
976
991
  }
977
992
  const _RecordArray = class extends Array {
978
993
  constructor(page, overrideRecords) {
979
- super(...overrideRecords ?? page.records);
994
+ super(..._RecordArray.parseConstructorParams(page, overrideRecords));
980
995
  __privateAdd$6(this, _page, void 0);
981
996
  __privateSet$5(this, _page, page);
982
997
  }
998
+ static parseConstructorParams(...args) {
999
+ if (args.length === 1 && typeof args[0] === "number") {
1000
+ return new Array(args[0]);
1001
+ }
1002
+ if (args.length <= 2 && isObject(args[0]?.meta) && Array.isArray(args[1] ?? [])) {
1003
+ const result = args[1] ?? args[0].records ?? [];
1004
+ return new Array(...result);
1005
+ }
1006
+ return new Array(...args);
1007
+ }
983
1008
  async nextPage(size, offset) {
984
1009
  const newPage = await __privateGet$6(this, _page).nextPage(size, offset);
985
1010
  return new _RecordArray(newPage);
@@ -1250,9 +1275,29 @@ class RestRepository extends Query {
1250
1275
  if (Array.isArray(a)) {
1251
1276
  if (a.length === 0)
1252
1277
  return [];
1253
- const records = await __privateMethod$2(this, _bulkInsertTableRecords, bulkInsertTableRecords_fn).call(this, a);
1254
- await Promise.all(records.map((record) => __privateMethod$2(this, _setCacheRecord, setCacheRecord_fn).call(this, record)));
1255
- return records;
1278
+ const [itemsWithoutIds, itemsWithIds, order] = a.reduce(([accWithoutIds, accWithIds, accOrder], item) => {
1279
+ const condition = isString(item.id);
1280
+ accOrder.push(condition);
1281
+ if (condition) {
1282
+ accWithIds.push(item);
1283
+ } else {
1284
+ accWithoutIds.push(item);
1285
+ }
1286
+ return [accWithoutIds, accWithIds, accOrder];
1287
+ }, [[], [], []]);
1288
+ const recordsWithoutId = await __privateMethod$2(this, _bulkInsertTableRecords, bulkInsertTableRecords_fn).call(this, itemsWithoutIds);
1289
+ await Promise.all(recordsWithoutId.map((record) => __privateMethod$2(this, _setCacheRecord, setCacheRecord_fn).call(this, record)));
1290
+ if (itemsWithIds.length > 100) {
1291
+ console.warn("Bulk create operation with id is not optimized in the Xata API yet, this request might be slow");
1292
+ }
1293
+ const recordsWithId = await Promise.all(itemsWithIds.map((object) => this.create(object)));
1294
+ return order.map((condition) => {
1295
+ if (condition) {
1296
+ return recordsWithId.shift();
1297
+ } else {
1298
+ return recordsWithoutId.shift();
1299
+ }
1300
+ }).filter((record) => !!record);
1256
1301
  }
1257
1302
  if (isString(a) && isObject(b)) {
1258
1303
  if (a === "")
@@ -1279,16 +1324,18 @@ class RestRepository extends Query {
1279
1324
  if (Array.isArray(a)) {
1280
1325
  if (a.length === 0)
1281
1326
  return [];
1282
- return this.getAll({ filter: { id: { $any: a } } });
1327
+ const ids = a.map((item) => isString(item) ? item : item.id).filter((id2) => isString(id2));
1328
+ return this.getAll({ filter: { id: { $any: ids } } });
1283
1329
  }
1284
- if (isString(a)) {
1285
- const cacheRecord = await __privateMethod$2(this, _getCacheRecord, getCacheRecord_fn).call(this, a);
1330
+ const id = isString(a) ? a : a.id;
1331
+ if (isString(id)) {
1332
+ const cacheRecord = await __privateMethod$2(this, _getCacheRecord, getCacheRecord_fn).call(this, id);
1286
1333
  if (cacheRecord)
1287
1334
  return cacheRecord;
1288
1335
  const fetchProps = await __privateGet$4(this, _getFetchProps).call(this);
1289
1336
  try {
1290
1337
  const response = await getRecord({
1291
- pathParams: { workspace: "{workspaceId}", dbBranchName: "{dbBranch}", tableName: __privateGet$4(this, _table), recordId: a },
1338
+ pathParams: { workspace: "{workspaceId}", dbBranchName: "{dbBranch}", tableName: __privateGet$4(this, _table), recordId: id },
1292
1339
  ...fetchProps
1293
1340
  });
1294
1341
  const schema = await __privateMethod$2(this, _getSchema$1, getSchema_fn$1).call(this);
@@ -1460,7 +1507,7 @@ bulkInsertTableRecords_fn = async function(objects) {
1460
1507
  body: { records },
1461
1508
  ...fetchProps
1462
1509
  });
1463
- const finalObjects = await this.any(...response.recordIDs.map((id) => this.filter("id", id))).getAll();
1510
+ const finalObjects = await this.read(response.recordIDs);
1464
1511
  if (finalObjects.length !== objects.length) {
1465
1512
  throw new Error("The server failed to save some records");
1466
1513
  }
@@ -1864,10 +1911,7 @@ async function getDatabaseBranch(branch, options) {
1864
1911
  apiUrl: databaseURL,
1865
1912
  fetchImpl: getFetchImplementation(options?.fetchImpl),
1866
1913
  workspacesApiUrl: `${protocol}//${host}`,
1867
- pathParams: {
1868
- dbBranchName,
1869
- workspace
1870
- }
1914
+ pathParams: { dbBranchName, workspace }
1871
1915
  });
1872
1916
  } catch (err) {
1873
1917
  if (isObject(err) && err.status === 404)