@xata.io/client 0.20.2 → 0.21.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,37 @@
1
1
  # @xata.io/client
2
2
 
3
+ ## 0.21.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [#781](https://github.com/xataio/client-ts/pull/781) [`fdfa47de`](https://github.com/xataio/client-ts/commit/fdfa47de93ec772170ff00a4341fc14434347df5) Thanks [@SferaDev](https://github.com/SferaDev)! - Send header to disable encoding
8
+
9
+ ## 0.21.0
10
+
11
+ ### Minor Changes
12
+
13
+ - [#757](https://github.com/xataio/client-ts/pull/757) [`7da604d2`](https://github.com/xataio/client-ts/commit/7da604d27990e20ecadba6122434fca563e6a8c9) Thanks [@SferaDev](https://github.com/SferaDev)! - Add promise pool for retries
14
+
15
+ ### Patch Changes
16
+
17
+ - [#764](https://github.com/xataio/client-ts/pull/764) [`b131040a`](https://github.com/xataio/client-ts/commit/b131040a2d142c4e71a2e586fbf05cd9295af9a1) Thanks [@SferaDev](https://github.com/SferaDev)! - Fix bun
18
+
19
+ - [#759](https://github.com/xataio/client-ts/pull/759) [`7ea810dc`](https://github.com/xataio/client-ts/commit/7ea810dc083ec284447e3bd27bd0465f887481e6) Thanks [@SferaDev](https://github.com/SferaDev)! - Expose new transaction API
20
+
21
+ - [#767](https://github.com/xataio/client-ts/pull/767) [`d124cbfb`](https://github.com/xataio/client-ts/commit/d124cbfb93d3d591e79bbe9e94c4b6304d825e71) Thanks [@SferaDev](https://github.com/SferaDev)! - Remove formatVersion from schema
22
+
23
+ - [#767](https://github.com/xataio/client-ts/pull/767) [`d124cbfb`](https://github.com/xataio/client-ts/commit/d124cbfb93d3d591e79bbe9e94c4b6304d825e71) Thanks [@SferaDev](https://github.com/SferaDev)! - Fix null value returning on date columns
24
+
25
+ - [#775](https://github.com/xataio/client-ts/pull/775) [`fb5ccdf9`](https://github.com/xataio/client-ts/commit/fb5ccdf9fa95c37d54fbc5d9c0bb45872c831609) Thanks [@SferaDev](https://github.com/SferaDev)! - Add missing target field to search
26
+
27
+ - [#760](https://github.com/xataio/client-ts/pull/760) [`4ae00036`](https://github.com/xataio/client-ts/commit/4ae00036b53c6c89e02a1fcfdd992f1a3c22892c) Thanks [@SferaDev](https://github.com/SferaDev)! - Add support for filters in boosters
28
+
29
+ - [#766](https://github.com/xataio/client-ts/pull/766) [`bdae6668`](https://github.com/xataio/client-ts/commit/bdae6668fb571d29f1b1068a54f6866a80d9b174) Thanks [@SferaDev](https://github.com/SferaDev)! - Remove beta for Workers
30
+
31
+ - [#771](https://github.com/xataio/client-ts/pull/771) [`9486bdcc`](https://github.com/xataio/client-ts/commit/9486bdccc0af567bc5f2e8f91592b0143c539c45) Thanks [@SferaDev](https://github.com/SferaDev)! - Add modifier for numeric booster
32
+
33
+ - [#771](https://github.com/xataio/client-ts/pull/771) [`9486bdcc`](https://github.com/xataio/client-ts/commit/9486bdccc0af567bc5f2e8f91592b0143c539c45) Thanks [@SferaDev](https://github.com/SferaDev)! - Add pagination to search
34
+
3
35
  ## 0.20.2
4
36
 
5
37
  ### Patch Changes
package/dist/index.cjs CHANGED
@@ -1,7 +1,8 @@
1
1
  'use strict';
2
2
 
3
- const defaultTrace = async (_name, fn, _options) => {
3
+ const defaultTrace = async (name, fn, _options) => {
4
4
  return await fn({
5
+ name,
5
6
  setAttributes: () => {
6
7
  return;
7
8
  }
@@ -43,6 +44,18 @@ function isStringArray(value) {
43
44
  function isNumber(value) {
44
45
  return isDefined(value) && typeof value === "number";
45
46
  }
47
+ function parseNumber(value) {
48
+ if (isNumber(value)) {
49
+ return value;
50
+ }
51
+ if (isString(value)) {
52
+ const parsed = Number(value);
53
+ if (!Number.isNaN(parsed)) {
54
+ return parsed;
55
+ }
56
+ }
57
+ return void 0;
58
+ }
46
59
  function toBase64(value) {
47
60
  try {
48
61
  return btoa(value);
@@ -69,10 +82,13 @@ function chunk(array, chunkSize) {
69
82
  }
70
83
  return result;
71
84
  }
85
+ async function timeout(ms) {
86
+ return new Promise((resolve) => setTimeout(resolve, ms));
87
+ }
72
88
 
73
89
  function getEnvironment() {
74
90
  try {
75
- if (isObject(process) && isObject(process.env)) {
91
+ if (isDefined(process) && isDefined(process.env)) {
76
92
  return {
77
93
  apiKey: process.env.XATA_API_KEY ?? getGlobalApiKey(),
78
94
  databaseURL: process.env.XATA_DATABASE_URL ?? getGlobalDatabaseURL(),
@@ -181,6 +197,29 @@ function getAPIKey() {
181
197
  }
182
198
  }
183
199
 
200
+ var __accessCheck$8 = (obj, member, msg) => {
201
+ if (!member.has(obj))
202
+ throw TypeError("Cannot " + msg);
203
+ };
204
+ var __privateGet$8 = (obj, member, getter) => {
205
+ __accessCheck$8(obj, member, "read from private field");
206
+ return getter ? getter.call(obj) : member.get(obj);
207
+ };
208
+ var __privateAdd$8 = (obj, member, value) => {
209
+ if (member.has(obj))
210
+ throw TypeError("Cannot add the same private member more than once");
211
+ member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
212
+ };
213
+ var __privateSet$8 = (obj, member, value, setter) => {
214
+ __accessCheck$8(obj, member, "write to private field");
215
+ setter ? setter.call(obj, value) : member.set(obj, value);
216
+ return value;
217
+ };
218
+ var __privateMethod$4 = (obj, member, method) => {
219
+ __accessCheck$8(obj, member, "access private method");
220
+ return method;
221
+ };
222
+ var _fetch, _queue, _concurrency, _enqueue, enqueue_fn;
184
223
  function getFetchImplementation(userFetch) {
185
224
  const globalFetch = typeof fetch !== "undefined" ? fetch : void 0;
186
225
  const fetchImpl = userFetch ?? globalFetch;
@@ -191,8 +230,74 @@ function getFetchImplementation(userFetch) {
191
230
  }
192
231
  return fetchImpl;
193
232
  }
233
+ class ApiRequestPool {
234
+ constructor(concurrency = 10) {
235
+ __privateAdd$8(this, _enqueue);
236
+ __privateAdd$8(this, _fetch, void 0);
237
+ __privateAdd$8(this, _queue, void 0);
238
+ __privateAdd$8(this, _concurrency, void 0);
239
+ __privateSet$8(this, _queue, []);
240
+ __privateSet$8(this, _concurrency, concurrency);
241
+ this.running = 0;
242
+ this.started = 0;
243
+ }
244
+ setFetch(fetch2) {
245
+ __privateSet$8(this, _fetch, fetch2);
246
+ }
247
+ getFetch() {
248
+ if (!__privateGet$8(this, _fetch)) {
249
+ throw new Error("Fetch not set");
250
+ }
251
+ return __privateGet$8(this, _fetch);
252
+ }
253
+ request(url, options) {
254
+ const start = new Date();
255
+ const fetch2 = this.getFetch();
256
+ const runRequest = async (stalled = false) => {
257
+ const response = await fetch2(url, options);
258
+ if (response.status === 429) {
259
+ const rateLimitReset = parseNumber(response.headers?.get("x-ratelimit-reset")) ?? 1;
260
+ await timeout(rateLimitReset * 1e3);
261
+ return await runRequest(true);
262
+ }
263
+ if (stalled) {
264
+ const stalledTime = new Date().getTime() - start.getTime();
265
+ console.warn(`A request to Xata hit your workspace limits, was retried and stalled for ${stalledTime}ms`);
266
+ }
267
+ return response;
268
+ };
269
+ return __privateMethod$4(this, _enqueue, enqueue_fn).call(this, async () => {
270
+ return await runRequest();
271
+ });
272
+ }
273
+ }
274
+ _fetch = new WeakMap();
275
+ _queue = new WeakMap();
276
+ _concurrency = new WeakMap();
277
+ _enqueue = new WeakSet();
278
+ enqueue_fn = function(task) {
279
+ const promise = new Promise((resolve) => __privateGet$8(this, _queue).push(resolve)).finally(() => {
280
+ this.started--;
281
+ this.running++;
282
+ }).then(() => task()).finally(() => {
283
+ this.running--;
284
+ const next = __privateGet$8(this, _queue).shift();
285
+ if (next !== void 0) {
286
+ this.started++;
287
+ next();
288
+ }
289
+ });
290
+ if (this.running + this.started < __privateGet$8(this, _concurrency)) {
291
+ const next = __privateGet$8(this, _queue).shift();
292
+ if (next !== void 0) {
293
+ this.started++;
294
+ next();
295
+ }
296
+ }
297
+ return promise;
298
+ };
194
299
 
195
- const VERSION = "0.20.2";
300
+ const VERSION = "0.21.1";
196
301
 
197
302
  class ErrorWithCause extends Error {
198
303
  constructor(message, options) {
@@ -235,6 +340,7 @@ function getMessage(data) {
235
340
  }
236
341
  }
237
342
 
343
+ const pool = new ApiRequestPool();
238
344
  const resolveUrl = (url, queryParams = {}, pathParams = {}) => {
239
345
  const cleanQueryParams = Object.entries(queryParams).reduce((acc, [key, value]) => {
240
346
  if (value === void 0 || value === null)
@@ -283,11 +389,13 @@ async function fetch$1({
283
389
  signal,
284
390
  clientID,
285
391
  sessionID,
392
+ clientName,
286
393
  fetchOptions = {}
287
394
  }) {
288
- return trace(
395
+ pool.setFetch(fetchImpl);
396
+ return await trace(
289
397
  `${method.toUpperCase()} ${path}`,
290
- async ({ setAttributes }) => {
398
+ async ({ name, setAttributes }) => {
291
399
  const baseUrl = buildBaseUrl({ endpoint, path, workspacesApiUrl, pathParams, apiUrl });
292
400
  const fullUrl = resolveUrl(baseUrl, queryParams, pathParams);
293
401
  const url = fullUrl.includes("localhost") ? fullUrl.replace(/^[^.]+\./, "http://") : fullUrl;
@@ -295,24 +403,27 @@ async function fetch$1({
295
403
  [TraceAttributes.HTTP_URL]: url,
296
404
  [TraceAttributes.HTTP_TARGET]: resolveUrl(path, queryParams, pathParams)
297
405
  });
298
- const response = await fetchImpl(url, {
406
+ const xataAgent = compact([
407
+ ["client", "TS_SDK"],
408
+ ["version", VERSION],
409
+ isDefined(clientName) ? ["service", clientName] : void 0
410
+ ]).map(([key, value]) => `${key}=${value}`).join("; ");
411
+ const response = await pool.request(url, {
299
412
  ...fetchOptions,
300
413
  method: method.toUpperCase(),
301
414
  body: body ? JSON.stringify(body) : void 0,
302
415
  headers: {
416
+ "Accept-Encoding": "identity",
303
417
  "Content-Type": "application/json",
304
- "User-Agent": `Xata client-ts/${VERSION}`,
305
418
  "X-Xata-Client-ID": clientID ?? "",
306
419
  "X-Xata-Session-ID": sessionID ?? "",
420
+ "X-Xata-Agent": xataAgent,
307
421
  ...headers,
308
422
  ...hostHeader(fullUrl),
309
423
  Authorization: `Bearer ${apiKey}`
310
424
  },
311
425
  signal
312
426
  });
313
- if (response.status === 204) {
314
- return {};
315
- }
316
427
  const { host, protocol } = parseUrl(response.url);
317
428
  const requestId = response.headers?.get("x-request-id") ?? void 0;
318
429
  setAttributes({
@@ -322,6 +433,12 @@ async function fetch$1({
322
433
  [TraceAttributes.HTTP_HOST]: host,
323
434
  [TraceAttributes.HTTP_SCHEME]: protocol?.replace(":", "")
324
435
  });
436
+ if (response.status === 204) {
437
+ return {};
438
+ }
439
+ if (response.status === 429) {
440
+ throw new FetcherError(response.status, "Rate limit exceeded", requestId);
441
+ }
325
442
  try {
326
443
  const jsonResponse = await response.json();
327
444
  if (response.ok) {
@@ -773,7 +890,8 @@ class XataApiClient {
773
890
  workspacesApiUrl: getHostUrl(provider, "workspaces"),
774
891
  fetchImpl: getFetchImplementation(options.fetch),
775
892
  apiKey,
776
- trace
893
+ trace,
894
+ clientName: options.clientName
777
895
  });
778
896
  }
779
897
  get user() {
@@ -2305,13 +2423,19 @@ class RestRepository extends Query {
2305
2423
  const result = await this.read(a, columns);
2306
2424
  return result;
2307
2425
  }
2308
- if (isString(a) && isObject(b)) {
2309
- const columns = isStringArray(c) ? c : void 0;
2310
- return __privateMethod$2(this, _updateRecordWithID, updateRecordWithID_fn).call(this, a, b, columns, { ifVersion });
2311
- }
2312
- if (isObject(a) && isString(a.id)) {
2313
- const columns = isStringArray(b) ? b : void 0;
2314
- return __privateMethod$2(this, _updateRecordWithID, updateRecordWithID_fn).call(this, a.id, { ...a, id: void 0 }, columns, { ifVersion });
2426
+ try {
2427
+ if (isString(a) && isObject(b)) {
2428
+ const columns = isStringArray(c) ? c : void 0;
2429
+ return await __privateMethod$2(this, _updateRecordWithID, updateRecordWithID_fn).call(this, a, b, columns, { ifVersion });
2430
+ }
2431
+ if (isObject(a) && isString(a.id)) {
2432
+ const columns = isStringArray(b) ? b : void 0;
2433
+ return await __privateMethod$2(this, _updateRecordWithID, updateRecordWithID_fn).call(this, a.id, { ...a, id: void 0 }, columns, { ifVersion });
2434
+ }
2435
+ } catch (error) {
2436
+ if (error.status === 422)
2437
+ return null;
2438
+ throw error;
2315
2439
  }
2316
2440
  throw new Error("Invalid arguments for update method");
2317
2441
  });
@@ -2442,7 +2566,9 @@ class RestRepository extends Query {
2442
2566
  prefix: options.prefix,
2443
2567
  highlight: options.highlight,
2444
2568
  filter: options.filter,
2445
- boosters: options.boosters
2569
+ boosters: options.boosters,
2570
+ page: options.page,
2571
+ target: options.target
2446
2572
  },
2447
2573
  ...fetchProps
2448
2574
  });
@@ -2760,10 +2886,10 @@ const initObject = (db, schemaTables, table, object, selectedColumns) => {
2760
2886
  const value = result[column.name];
2761
2887
  switch (column.type) {
2762
2888
  case "datetime": {
2763
- const date = value !== void 0 ? new Date(value) : void 0;
2764
- if (date && isNaN(date.getTime())) {
2889
+ const date = value !== void 0 ? new Date(value) : null;
2890
+ if (date !== null && isNaN(date.getTime())) {
2765
2891
  console.error(`Failed to parse date ${value} for field ${column.name}`);
2766
- } else if (date) {
2892
+ } else {
2767
2893
  result[column.name] = date;
2768
2894
  }
2769
2895
  break;
@@ -3031,10 +3157,10 @@ _schemaTables = new WeakMap();
3031
3157
  _search = new WeakSet();
3032
3158
  search_fn = async function(query, options, getFetchProps) {
3033
3159
  const fetchProps = await getFetchProps();
3034
- const { tables, fuzziness, highlight, prefix } = options ?? {};
3160
+ const { tables, fuzziness, highlight, prefix, page } = options ?? {};
3035
3161
  const { records } = await searchBranch({
3036
3162
  pathParams: { workspace: "{workspaceId}", dbBranchName: "{dbBranch}", region: "{region}" },
3037
- body: { tables, query, fuzziness, prefix, highlight },
3163
+ body: { tables, query, fuzziness, prefix, highlight, page },
3038
3164
  ...fetchProps
3039
3165
  });
3040
3166
  return records;
@@ -3052,6 +3178,22 @@ getSchemaTables_fn = async function(getFetchProps) {
3052
3178
  return schema.tables;
3053
3179
  };
3054
3180
 
3181
+ class TransactionPlugin extends XataPlugin {
3182
+ build({ getFetchProps }) {
3183
+ return {
3184
+ run: async (operations) => {
3185
+ const fetchProps = await getFetchProps();
3186
+ const response = await branchTransaction({
3187
+ pathParams: { workspace: "{workspaceId}", dbBranchName: "{dbBranch}", region: "{region}" },
3188
+ body: { operations },
3189
+ ...fetchProps
3190
+ });
3191
+ return response;
3192
+ }
3193
+ };
3194
+ }
3195
+ }
3196
+
3055
3197
  const isBranchStrategyBuilder = (strategy) => {
3056
3198
  return typeof strategy === "function";
3057
3199
  };
@@ -3179,8 +3321,10 @@ const buildClient = (plugins) => {
3179
3321
  };
3180
3322
  const db = new SchemaPlugin(schemaTables).build(pluginOptions);
3181
3323
  const search = new SearchPlugin(db, schemaTables).build(pluginOptions);
3324
+ const transactions = new TransactionPlugin().build(pluginOptions);
3182
3325
  this.db = db;
3183
3326
  this.search = search;
3327
+ this.transactions = transactions;
3184
3328
  for (const [key, namespace] of Object.entries(plugins ?? {})) {
3185
3329
  if (namespace === void 0)
3186
3330
  continue;
@@ -3212,6 +3356,7 @@ const buildClient = (plugins) => {
3212
3356
  const apiKey = options?.apiKey || getAPIKey();
3213
3357
  const cache = options?.cache ?? new SimpleCache({ defaultQueryTTL: 0 });
3214
3358
  const trace = options?.trace ?? defaultTrace;
3359
+ const clientName = options?.clientName;
3215
3360
  const branch = async () => options?.branch !== void 0 ? await __privateMethod(this, _evaluateBranch, evaluateBranch_fn).call(this, options.branch) : await getCurrentBranchName({ apiKey, databaseURL, fetchImpl: options?.fetch });
3216
3361
  if (!apiKey) {
3217
3362
  throw new Error("Option apiKey is required");
@@ -3219,8 +3364,16 @@ const buildClient = (plugins) => {
3219
3364
  if (!databaseURL) {
3220
3365
  throw new Error("Option databaseURL is required");
3221
3366
  }
3222
- return { fetch, databaseURL, apiKey, branch, cache, trace, clientID: generateUUID(), enableBrowser };
3223
- }, _getFetchProps = new WeakSet(), getFetchProps_fn = async function({ fetch, apiKey, databaseURL, branch, trace, clientID }) {
3367
+ return { fetch, databaseURL, apiKey, branch, cache, trace, clientID: generateUUID(), enableBrowser, clientName };
3368
+ }, _getFetchProps = new WeakSet(), getFetchProps_fn = async function({
3369
+ fetch,
3370
+ apiKey,
3371
+ databaseURL,
3372
+ branch,
3373
+ trace,
3374
+ clientID,
3375
+ clientName
3376
+ }) {
3224
3377
  const branchValue = await __privateMethod(this, _evaluateBranch, evaluateBranch_fn).call(this, branch);
3225
3378
  if (!branchValue)
3226
3379
  throw new Error("Unable to resolve branch value");
@@ -3234,7 +3387,8 @@ const buildClient = (plugins) => {
3234
3387
  return databaseURL + newPath;
3235
3388
  },
3236
3389
  trace,
3237
- clientID
3390
+ clientID,
3391
+ clientName
3238
3392
  };
3239
3393
  }, _evaluateBranch = new WeakSet(), evaluateBranch_fn = async function(param) {
3240
3394
  if (__privateGet(this, _branch))