@xata.io/client 0.20.2 → 0.21.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/CHANGELOG.md +26 -0
- package/dist/index.cjs +167 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +257 -36
- package/dist/index.mjs +167 -20
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
@@ -1,5 +1,6 @@
|
|
1
|
-
const defaultTrace = async (
|
1
|
+
const defaultTrace = async (name, fn, _options) => {
|
2
2
|
return await fn({
|
3
|
+
name,
|
3
4
|
setAttributes: () => {
|
4
5
|
return;
|
5
6
|
}
|
@@ -41,6 +42,18 @@ function isStringArray(value) {
|
|
41
42
|
function isNumber(value) {
|
42
43
|
return isDefined(value) && typeof value === "number";
|
43
44
|
}
|
45
|
+
function parseNumber(value) {
|
46
|
+
if (isNumber(value)) {
|
47
|
+
return value;
|
48
|
+
}
|
49
|
+
if (isString(value)) {
|
50
|
+
const parsed = Number(value);
|
51
|
+
if (!Number.isNaN(parsed)) {
|
52
|
+
return parsed;
|
53
|
+
}
|
54
|
+
}
|
55
|
+
return void 0;
|
56
|
+
}
|
44
57
|
function toBase64(value) {
|
45
58
|
try {
|
46
59
|
return btoa(value);
|
@@ -67,10 +80,13 @@ function chunk(array, chunkSize) {
|
|
67
80
|
}
|
68
81
|
return result;
|
69
82
|
}
|
83
|
+
async function timeout(ms) {
|
84
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
85
|
+
}
|
70
86
|
|
71
87
|
function getEnvironment() {
|
72
88
|
try {
|
73
|
-
if (
|
89
|
+
if (isDefined(process) && isDefined(process.env)) {
|
74
90
|
return {
|
75
91
|
apiKey: process.env.XATA_API_KEY ?? getGlobalApiKey(),
|
76
92
|
databaseURL: process.env.XATA_DATABASE_URL ?? getGlobalDatabaseURL(),
|
@@ -179,6 +195,29 @@ function getAPIKey() {
|
|
179
195
|
}
|
180
196
|
}
|
181
197
|
|
198
|
+
var __accessCheck$8 = (obj, member, msg) => {
|
199
|
+
if (!member.has(obj))
|
200
|
+
throw TypeError("Cannot " + msg);
|
201
|
+
};
|
202
|
+
var __privateGet$8 = (obj, member, getter) => {
|
203
|
+
__accessCheck$8(obj, member, "read from private field");
|
204
|
+
return getter ? getter.call(obj) : member.get(obj);
|
205
|
+
};
|
206
|
+
var __privateAdd$8 = (obj, member, value) => {
|
207
|
+
if (member.has(obj))
|
208
|
+
throw TypeError("Cannot add the same private member more than once");
|
209
|
+
member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
210
|
+
};
|
211
|
+
var __privateSet$8 = (obj, member, value, setter) => {
|
212
|
+
__accessCheck$8(obj, member, "write to private field");
|
213
|
+
setter ? setter.call(obj, value) : member.set(obj, value);
|
214
|
+
return value;
|
215
|
+
};
|
216
|
+
var __privateMethod$4 = (obj, member, method) => {
|
217
|
+
__accessCheck$8(obj, member, "access private method");
|
218
|
+
return method;
|
219
|
+
};
|
220
|
+
var _fetch, _queue, _concurrency, _enqueue, enqueue_fn;
|
182
221
|
function getFetchImplementation(userFetch) {
|
183
222
|
const globalFetch = typeof fetch !== "undefined" ? fetch : void 0;
|
184
223
|
const fetchImpl = userFetch ?? globalFetch;
|
@@ -189,8 +228,74 @@ function getFetchImplementation(userFetch) {
|
|
189
228
|
}
|
190
229
|
return fetchImpl;
|
191
230
|
}
|
231
|
+
class ApiRequestPool {
|
232
|
+
constructor(concurrency = 10) {
|
233
|
+
__privateAdd$8(this, _enqueue);
|
234
|
+
__privateAdd$8(this, _fetch, void 0);
|
235
|
+
__privateAdd$8(this, _queue, void 0);
|
236
|
+
__privateAdd$8(this, _concurrency, void 0);
|
237
|
+
__privateSet$8(this, _queue, []);
|
238
|
+
__privateSet$8(this, _concurrency, concurrency);
|
239
|
+
this.running = 0;
|
240
|
+
this.started = 0;
|
241
|
+
}
|
242
|
+
setFetch(fetch2) {
|
243
|
+
__privateSet$8(this, _fetch, fetch2);
|
244
|
+
}
|
245
|
+
getFetch() {
|
246
|
+
if (!__privateGet$8(this, _fetch)) {
|
247
|
+
throw new Error("Fetch not set");
|
248
|
+
}
|
249
|
+
return __privateGet$8(this, _fetch);
|
250
|
+
}
|
251
|
+
request(url, options) {
|
252
|
+
const start = new Date();
|
253
|
+
const fetch2 = this.getFetch();
|
254
|
+
const runRequest = async (stalled = false) => {
|
255
|
+
const response = await fetch2(url, options);
|
256
|
+
if (response.status === 429) {
|
257
|
+
const rateLimitReset = parseNumber(response.headers?.get("x-ratelimit-reset")) ?? 1;
|
258
|
+
await timeout(rateLimitReset * 1e3);
|
259
|
+
return await runRequest(true);
|
260
|
+
}
|
261
|
+
if (stalled) {
|
262
|
+
const stalledTime = new Date().getTime() - start.getTime();
|
263
|
+
console.warn(`A request to Xata hit your workspace limits, was retried and stalled for ${stalledTime}ms`);
|
264
|
+
}
|
265
|
+
return response;
|
266
|
+
};
|
267
|
+
return __privateMethod$4(this, _enqueue, enqueue_fn).call(this, async () => {
|
268
|
+
return await runRequest();
|
269
|
+
});
|
270
|
+
}
|
271
|
+
}
|
272
|
+
_fetch = new WeakMap();
|
273
|
+
_queue = new WeakMap();
|
274
|
+
_concurrency = new WeakMap();
|
275
|
+
_enqueue = new WeakSet();
|
276
|
+
enqueue_fn = function(task) {
|
277
|
+
const promise = new Promise((resolve) => __privateGet$8(this, _queue).push(resolve)).finally(() => {
|
278
|
+
this.started--;
|
279
|
+
this.running++;
|
280
|
+
}).then(() => task()).finally(() => {
|
281
|
+
this.running--;
|
282
|
+
const next = __privateGet$8(this, _queue).shift();
|
283
|
+
if (next !== void 0) {
|
284
|
+
this.started++;
|
285
|
+
next();
|
286
|
+
}
|
287
|
+
});
|
288
|
+
if (this.running + this.started < __privateGet$8(this, _concurrency)) {
|
289
|
+
const next = __privateGet$8(this, _queue).shift();
|
290
|
+
if (next !== void 0) {
|
291
|
+
this.started++;
|
292
|
+
next();
|
293
|
+
}
|
294
|
+
}
|
295
|
+
return promise;
|
296
|
+
};
|
192
297
|
|
193
|
-
const VERSION = "0.
|
298
|
+
const VERSION = "0.21.0";
|
194
299
|
|
195
300
|
class ErrorWithCause extends Error {
|
196
301
|
constructor(message, options) {
|
@@ -233,6 +338,7 @@ function getMessage(data) {
|
|
233
338
|
}
|
234
339
|
}
|
235
340
|
|
341
|
+
const pool = new ApiRequestPool();
|
236
342
|
const resolveUrl = (url, queryParams = {}, pathParams = {}) => {
|
237
343
|
const cleanQueryParams = Object.entries(queryParams).reduce((acc, [key, value]) => {
|
238
344
|
if (value === void 0 || value === null)
|
@@ -281,11 +387,13 @@ async function fetch$1({
|
|
281
387
|
signal,
|
282
388
|
clientID,
|
283
389
|
sessionID,
|
390
|
+
clientName,
|
284
391
|
fetchOptions = {}
|
285
392
|
}) {
|
286
|
-
|
393
|
+
pool.setFetch(fetchImpl);
|
394
|
+
return await trace(
|
287
395
|
`${method.toUpperCase()} ${path}`,
|
288
|
-
async ({ setAttributes }) => {
|
396
|
+
async ({ name, setAttributes }) => {
|
289
397
|
const baseUrl = buildBaseUrl({ endpoint, path, workspacesApiUrl, pathParams, apiUrl });
|
290
398
|
const fullUrl = resolveUrl(baseUrl, queryParams, pathParams);
|
291
399
|
const url = fullUrl.includes("localhost") ? fullUrl.replace(/^[^.]+\./, "http://") : fullUrl;
|
@@ -293,24 +401,26 @@ async function fetch$1({
|
|
293
401
|
[TraceAttributes.HTTP_URL]: url,
|
294
402
|
[TraceAttributes.HTTP_TARGET]: resolveUrl(path, queryParams, pathParams)
|
295
403
|
});
|
296
|
-
const
|
404
|
+
const xataAgent = compact([
|
405
|
+
["client", "TS_SDK"],
|
406
|
+
["version", VERSION],
|
407
|
+
isDefined(clientName) ? ["service", clientName] : void 0
|
408
|
+
]).map(([key, value]) => `${key}=${value}`).join("; ");
|
409
|
+
const response = await pool.request(url, {
|
297
410
|
...fetchOptions,
|
298
411
|
method: method.toUpperCase(),
|
299
412
|
body: body ? JSON.stringify(body) : void 0,
|
300
413
|
headers: {
|
301
414
|
"Content-Type": "application/json",
|
302
|
-
"User-Agent": `Xata client-ts/${VERSION}`,
|
303
415
|
"X-Xata-Client-ID": clientID ?? "",
|
304
416
|
"X-Xata-Session-ID": sessionID ?? "",
|
417
|
+
"X-Xata-Agent": xataAgent,
|
305
418
|
...headers,
|
306
419
|
...hostHeader(fullUrl),
|
307
420
|
Authorization: `Bearer ${apiKey}`
|
308
421
|
},
|
309
422
|
signal
|
310
423
|
});
|
311
|
-
if (response.status === 204) {
|
312
|
-
return {};
|
313
|
-
}
|
314
424
|
const { host, protocol } = parseUrl(response.url);
|
315
425
|
const requestId = response.headers?.get("x-request-id") ?? void 0;
|
316
426
|
setAttributes({
|
@@ -320,6 +430,12 @@ async function fetch$1({
|
|
320
430
|
[TraceAttributes.HTTP_HOST]: host,
|
321
431
|
[TraceAttributes.HTTP_SCHEME]: protocol?.replace(":", "")
|
322
432
|
});
|
433
|
+
if (response.status === 204) {
|
434
|
+
return {};
|
435
|
+
}
|
436
|
+
if (response.status === 429) {
|
437
|
+
throw new FetcherError(response.status, "Rate limit exceeded", requestId);
|
438
|
+
}
|
323
439
|
try {
|
324
440
|
const jsonResponse = await response.json();
|
325
441
|
if (response.ok) {
|
@@ -771,7 +887,8 @@ class XataApiClient {
|
|
771
887
|
workspacesApiUrl: getHostUrl(provider, "workspaces"),
|
772
888
|
fetchImpl: getFetchImplementation(options.fetch),
|
773
889
|
apiKey,
|
774
|
-
trace
|
890
|
+
trace,
|
891
|
+
clientName: options.clientName
|
775
892
|
});
|
776
893
|
}
|
777
894
|
get user() {
|
@@ -2440,7 +2557,9 @@ class RestRepository extends Query {
|
|
2440
2557
|
prefix: options.prefix,
|
2441
2558
|
highlight: options.highlight,
|
2442
2559
|
filter: options.filter,
|
2443
|
-
boosters: options.boosters
|
2560
|
+
boosters: options.boosters,
|
2561
|
+
page: options.page,
|
2562
|
+
target: options.target
|
2444
2563
|
},
|
2445
2564
|
...fetchProps
|
2446
2565
|
});
|
@@ -2758,10 +2877,10 @@ const initObject = (db, schemaTables, table, object, selectedColumns) => {
|
|
2758
2877
|
const value = result[column.name];
|
2759
2878
|
switch (column.type) {
|
2760
2879
|
case "datetime": {
|
2761
|
-
const date = value !== void 0 ? new Date(value) :
|
2762
|
-
if (date && isNaN(date.getTime())) {
|
2880
|
+
const date = value !== void 0 ? new Date(value) : null;
|
2881
|
+
if (date !== null && isNaN(date.getTime())) {
|
2763
2882
|
console.error(`Failed to parse date ${value} for field ${column.name}`);
|
2764
|
-
} else
|
2883
|
+
} else {
|
2765
2884
|
result[column.name] = date;
|
2766
2885
|
}
|
2767
2886
|
break;
|
@@ -3029,10 +3148,10 @@ _schemaTables = new WeakMap();
|
|
3029
3148
|
_search = new WeakSet();
|
3030
3149
|
search_fn = async function(query, options, getFetchProps) {
|
3031
3150
|
const fetchProps = await getFetchProps();
|
3032
|
-
const { tables, fuzziness, highlight, prefix } = options ?? {};
|
3151
|
+
const { tables, fuzziness, highlight, prefix, page } = options ?? {};
|
3033
3152
|
const { records } = await searchBranch({
|
3034
3153
|
pathParams: { workspace: "{workspaceId}", dbBranchName: "{dbBranch}", region: "{region}" },
|
3035
|
-
body: { tables, query, fuzziness, prefix, highlight },
|
3154
|
+
body: { tables, query, fuzziness, prefix, highlight, page },
|
3036
3155
|
...fetchProps
|
3037
3156
|
});
|
3038
3157
|
return records;
|
@@ -3050,6 +3169,22 @@ getSchemaTables_fn = async function(getFetchProps) {
|
|
3050
3169
|
return schema.tables;
|
3051
3170
|
};
|
3052
3171
|
|
3172
|
+
class TransactionPlugin extends XataPlugin {
|
3173
|
+
build({ getFetchProps }) {
|
3174
|
+
return {
|
3175
|
+
run: async (operations) => {
|
3176
|
+
const fetchProps = await getFetchProps();
|
3177
|
+
const response = await branchTransaction({
|
3178
|
+
pathParams: { workspace: "{workspaceId}", dbBranchName: "{dbBranch}", region: "{region}" },
|
3179
|
+
body: { operations },
|
3180
|
+
...fetchProps
|
3181
|
+
});
|
3182
|
+
return response;
|
3183
|
+
}
|
3184
|
+
};
|
3185
|
+
}
|
3186
|
+
}
|
3187
|
+
|
3053
3188
|
const isBranchStrategyBuilder = (strategy) => {
|
3054
3189
|
return typeof strategy === "function";
|
3055
3190
|
};
|
@@ -3177,8 +3312,10 @@ const buildClient = (plugins) => {
|
|
3177
3312
|
};
|
3178
3313
|
const db = new SchemaPlugin(schemaTables).build(pluginOptions);
|
3179
3314
|
const search = new SearchPlugin(db, schemaTables).build(pluginOptions);
|
3315
|
+
const transactions = new TransactionPlugin().build(pluginOptions);
|
3180
3316
|
this.db = db;
|
3181
3317
|
this.search = search;
|
3318
|
+
this.transactions = transactions;
|
3182
3319
|
for (const [key, namespace] of Object.entries(plugins ?? {})) {
|
3183
3320
|
if (namespace === void 0)
|
3184
3321
|
continue;
|
@@ -3210,6 +3347,7 @@ const buildClient = (plugins) => {
|
|
3210
3347
|
const apiKey = options?.apiKey || getAPIKey();
|
3211
3348
|
const cache = options?.cache ?? new SimpleCache({ defaultQueryTTL: 0 });
|
3212
3349
|
const trace = options?.trace ?? defaultTrace;
|
3350
|
+
const clientName = options?.clientName;
|
3213
3351
|
const branch = async () => options?.branch !== void 0 ? await __privateMethod(this, _evaluateBranch, evaluateBranch_fn).call(this, options.branch) : await getCurrentBranchName({ apiKey, databaseURL, fetchImpl: options?.fetch });
|
3214
3352
|
if (!apiKey) {
|
3215
3353
|
throw new Error("Option apiKey is required");
|
@@ -3217,8 +3355,16 @@ const buildClient = (plugins) => {
|
|
3217
3355
|
if (!databaseURL) {
|
3218
3356
|
throw new Error("Option databaseURL is required");
|
3219
3357
|
}
|
3220
|
-
return { fetch, databaseURL, apiKey, branch, cache, trace, clientID: generateUUID(), enableBrowser };
|
3221
|
-
}, _getFetchProps = new WeakSet(), getFetchProps_fn = async function({
|
3358
|
+
return { fetch, databaseURL, apiKey, branch, cache, trace, clientID: generateUUID(), enableBrowser, clientName };
|
3359
|
+
}, _getFetchProps = new WeakSet(), getFetchProps_fn = async function({
|
3360
|
+
fetch,
|
3361
|
+
apiKey,
|
3362
|
+
databaseURL,
|
3363
|
+
branch,
|
3364
|
+
trace,
|
3365
|
+
clientID,
|
3366
|
+
clientName
|
3367
|
+
}) {
|
3222
3368
|
const branchValue = await __privateMethod(this, _evaluateBranch, evaluateBranch_fn).call(this, branch);
|
3223
3369
|
if (!branchValue)
|
3224
3370
|
throw new Error("Unable to resolve branch value");
|
@@ -3232,7 +3378,8 @@ const buildClient = (plugins) => {
|
|
3232
3378
|
return databaseURL + newPath;
|
3233
3379
|
},
|
3234
3380
|
trace,
|
3235
|
-
clientID
|
3381
|
+
clientID,
|
3382
|
+
clientName
|
3236
3383
|
};
|
3237
3384
|
}, _evaluateBranch = new WeakSet(), evaluateBranch_fn = async function(param) {
|
3238
3385
|
if (__privateGet(this, _branch))
|