@xata.io/client 0.10.0 → 0.11.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/.eslintrc.cjs CHANGED
@@ -6,8 +6,7 @@ module.exports = {
6
6
  project: 'packages/client/tsconfig.json'
7
7
  },
8
8
  rules: {
9
- '@typescript-eslint/no-explicit-any': 'off',
10
- '@typescript-eslint/ban-types': 'off',
11
9
  '@typescript-eslint/no-floating-promises': 'error',
10
+ "@typescript-eslint/strict-boolean-expressions": ["error", { allowNullableString: true, allowNullableObject: true }],
12
11
  }
13
12
  };
package/CHANGELOG.md CHANGED
@@ -1,5 +1,39 @@
1
1
  # @xata.io/client
2
2
 
3
+ ## 0.11.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#322](https://github.com/xataio/client-ts/pull/322) [`bc64c28`](https://github.com/xataio/client-ts/commit/bc64c28fbfbb000c7190ac8092e2ef6a261df86f) Thanks [@SferaDev](https://github.com/SferaDev)! - Add filter support for cross-table search operations
8
+
9
+ ### Patch Changes
10
+
11
+ - [#327](https://github.com/xataio/client-ts/pull/327) [`505257c`](https://github.com/xataio/client-ts/commit/505257c0c42ca0c8beaf5c0f638037c576dcc43c) Thanks [@SferaDev](https://github.com/SferaDev)! - Allow reading multiple uids at the same time
12
+
13
+ * [#346](https://github.com/xataio/client-ts/pull/346) [`ff7e5c6`](https://github.com/xataio/client-ts/commit/ff7e5c6f211913196d8c28600d7a7675ed261688) Thanks [@SferaDev](https://github.com/SferaDev)! - Fix compat with TS 4.8
14
+
15
+ - [#345](https://github.com/xataio/client-ts/pull/345) [`bf64cb8`](https://github.com/xataio/client-ts/commit/bf64cb885d55a0271e966314384324f02ded084e) Thanks [@SferaDev](https://github.com/SferaDev)! - Fix bug with nullable record filters inferred as never
16
+
17
+ * [#334](https://github.com/xataio/client-ts/pull/334) [`ce07601`](https://github.com/xataio/client-ts/commit/ce07601e4ddf9f75e20249d479dc04a63795ca96) Thanks [@SferaDev](https://github.com/SferaDev)! - Add support for TS 4.5
18
+
19
+ - [#325](https://github.com/xataio/client-ts/pull/325) [`12f1ce3`](https://github.com/xataio/client-ts/commit/12f1ce362f6cda27dfdb3afab0800282bddc8b5e) Thanks [@SferaDev](https://github.com/SferaDev)! - Fix offset errors with operations that affect many rows
20
+
21
+ * [#345](https://github.com/xataio/client-ts/pull/345) [`a73a2a2`](https://github.com/xataio/client-ts/commit/a73a2a2014c44cf88eaef42196ba1dba9d516b4a) Thanks [@SferaDev](https://github.com/SferaDev)! - Fix issue with Filter<T> not narrowing down type on object properties
22
+
23
+ ## 0.10.2
24
+
25
+ ### Patch Changes
26
+
27
+ - [#312](https://github.com/xataio/client-ts/pull/312) [`0edf1af`](https://github.com/xataio/client-ts/commit/0edf1af2205c4761d53a02c74ddaab3168d69775) Thanks [@SferaDev](https://github.com/SferaDev)! - Add filtering to search by table
28
+
29
+ * [#312](https://github.com/xataio/client-ts/pull/312) [`66ad7cc`](https://github.com/xataio/client-ts/commit/66ad7cc0365046c5d039c37117feac04428d8373) Thanks [@SferaDev](https://github.com/SferaDev)! - Add new API method for searching in a given table
30
+
31
+ ## 0.10.1
32
+
33
+ ### Patch Changes
34
+
35
+ - [#271](https://github.com/xataio/client-ts/pull/271) [`0bb17b8`](https://github.com/xataio/client-ts/commit/0bb17b88d49f1c8be32d2d6b0b3a5918890876cb) Thanks [@SferaDev](https://github.com/SferaDev)! - Link and resolve branches from git
36
+
3
37
  ## 0.10.0
4
38
 
5
39
  ### Minor Changes
package/dist/index.cjs CHANGED
@@ -11,8 +11,11 @@ function compact(arr) {
11
11
  function isObject(value) {
12
12
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
13
13
  }
14
+ function isDefined(value) {
15
+ return value !== null && value !== void 0;
16
+ }
14
17
  function isString(value) {
15
- return value !== void 0 && value !== null && typeof value === "string";
18
+ return isDefined(value) && typeof value === "string";
16
19
  }
17
20
  function toBase64(value) {
18
21
  try {
@@ -74,7 +77,12 @@ function getFetchImplementation(userFetch) {
74
77
  return fetchImpl;
75
78
  }
76
79
 
77
- class FetcherError extends Error {
80
+ class ErrorWithCause extends Error {
81
+ constructor(message, options) {
82
+ super(message, options);
83
+ }
84
+ }
85
+ class FetcherError extends ErrorWithCause {
78
86
  constructor(status, data) {
79
87
  super(getMessage(data));
80
88
  this.status = status;
@@ -370,6 +378,11 @@ const queryTable = (variables) => fetch$1({
370
378
  method: "post",
371
379
  ...variables
372
380
  });
381
+ const searchTable = (variables) => fetch$1({
382
+ url: "/db/{dbBranchName}/tables/{tableName}/search",
383
+ method: "post",
384
+ ...variables
385
+ });
373
386
  const searchBranch = (variables) => fetch$1({
374
387
  url: "/db/{dbBranchName}/search",
375
388
  method: "post",
@@ -433,6 +446,7 @@ const operationsByTag = {
433
446
  getRecord,
434
447
  bulkInsertTableRecords,
435
448
  queryTable,
449
+ searchTable,
436
450
  searchBranch
437
451
  }
438
452
  };
@@ -888,6 +902,13 @@ class RecordsApi {
888
902
  ...this.extraProps
889
903
  });
890
904
  }
905
+ searchTable(workspace, database, branch, tableName, query) {
906
+ return operationsByTag.records.searchTable({
907
+ pathParams: { workspace, dbBranchName: `${database}:${branch}`, tableName },
908
+ body: query,
909
+ ...this.extraProps
910
+ });
911
+ }
891
912
  searchBranch(workspace, database, branch, query) {
892
913
  return operationsByTag.records.searchBranch({
893
914
  pathParams: { workspace, dbBranchName: `${database}:${branch}` },
@@ -954,6 +975,9 @@ const PAGINATION_MAX_SIZE = 200;
954
975
  const PAGINATION_DEFAULT_SIZE = 200;
955
976
  const PAGINATION_MAX_OFFSET = 800;
956
977
  const PAGINATION_DEFAULT_OFFSET = 0;
978
+ function isCursorPaginationOptions(options) {
979
+ return isDefined(options) && (isDefined(options.first) || isDefined(options.last) || isDefined(options.after) || isDefined(options.before));
980
+ }
957
981
 
958
982
  var __accessCheck$5 = (obj, member, msg) => {
959
983
  if (!member.has(obj))
@@ -975,7 +999,7 @@ var __privateSet$4 = (obj, member, value, setter) => {
975
999
  };
976
1000
  var _table$1, _repository, _data;
977
1001
  const _Query = class {
978
- constructor(repository, table, data, parent) {
1002
+ constructor(repository, table, data, rawParent) {
979
1003
  __privateAdd$5(this, _table$1, void 0);
980
1004
  __privateAdd$5(this, _repository, void 0);
981
1005
  __privateAdd$5(this, _data, { filter: {} });
@@ -987,6 +1011,7 @@ const _Query = class {
987
1011
  } else {
988
1012
  __privateSet$4(this, _repository, this);
989
1013
  }
1014
+ const parent = cleanParent(data, rawParent);
990
1015
  __privateGet$5(this, _data).filter = data.filter ?? parent?.filter ?? {};
991
1016
  __privateGet$5(this, _data).filter.$any = data.filter?.$any ?? parent?.filter?.$any;
992
1017
  __privateGet$5(this, _data).filter.$all = data.filter?.$all ?? parent?.filter?.$all;
@@ -1058,13 +1083,13 @@ const _Query = class {
1058
1083
  }
1059
1084
  async *getIterator(options = {}) {
1060
1085
  const { batchSize = 1 } = options;
1061
- let offset = 0;
1062
- let end = false;
1063
- while (!end) {
1064
- const { records, meta } = await this.getPaginated({ ...options, pagination: { size: batchSize, offset } });
1065
- yield records;
1066
- offset += batchSize;
1067
- end = !meta.page.more;
1086
+ let page = await this.getPaginated({ ...options, pagination: { size: batchSize, offset: 0 } });
1087
+ let more = page.hasNextPage();
1088
+ yield page.records;
1089
+ while (more) {
1090
+ page = await page.nextPage();
1091
+ more = page.hasNextPage();
1092
+ yield page.records;
1068
1093
  }
1069
1094
  }
1070
1095
  async getMany(options = {}) {
@@ -1081,7 +1106,7 @@ const _Query = class {
1081
1106
  }
1082
1107
  async getFirst(options = {}) {
1083
1108
  const records = await this.getMany({ ...options, pagination: { size: 1 } });
1084
- return records[0] || null;
1109
+ return records[0] ?? null;
1085
1110
  }
1086
1111
  cache(ttl) {
1087
1112
  return new _Query(__privateGet$5(this, _repository), __privateGet$5(this, _table$1), { cache: ttl }, __privateGet$5(this, _data));
@@ -1106,6 +1131,12 @@ let Query = _Query;
1106
1131
  _table$1 = new WeakMap();
1107
1132
  _repository = new WeakMap();
1108
1133
  _data = new WeakMap();
1134
+ function cleanParent(data, parent) {
1135
+ if (isCursorPaginationOptions(data.pagination)) {
1136
+ return { ...parent, sorting: void 0, filter: void 0 };
1137
+ }
1138
+ return parent;
1139
+ }
1109
1140
 
1110
1141
  function isIdentifiable(x) {
1111
1142
  return isObject(x) && isString(x?.id);
@@ -1188,6 +1219,8 @@ class RestRepository extends Query {
1188
1219
  }
1189
1220
  async create(a, b) {
1190
1221
  if (Array.isArray(a)) {
1222
+ if (a.length === 0)
1223
+ return [];
1191
1224
  const records = await __privateMethod$2(this, _bulkInsertTableRecords, bulkInsertTableRecords_fn).call(this, a);
1192
1225
  await Promise.all(records.map((record) => __privateMethod$2(this, _setCacheRecord, setCacheRecord_fn).call(this, record)));
1193
1226
  return records;
@@ -1213,27 +1246,36 @@ class RestRepository extends Query {
1213
1246
  }
1214
1247
  throw new Error("Invalid arguments for create method");
1215
1248
  }
1216
- async read(recordId) {
1217
- const cacheRecord = await __privateMethod$2(this, _getCacheRecord, getCacheRecord_fn).call(this, recordId);
1218
- if (cacheRecord)
1219
- return cacheRecord;
1220
- const fetchProps = await __privateGet$4(this, _getFetchProps).call(this);
1221
- try {
1222
- const response = await getRecord({
1223
- pathParams: { workspace: "{workspaceId}", dbBranchName: "{dbBranch}", tableName: __privateGet$4(this, _table), recordId },
1224
- ...fetchProps
1225
- });
1226
- const schema = await __privateMethod$2(this, _getSchema$1, getSchema_fn$1).call(this);
1227
- return initObject(this.db, schema, __privateGet$4(this, _table), response);
1228
- } catch (e) {
1229
- if (isObject(e) && e.status === 404) {
1230
- return null;
1249
+ async read(a) {
1250
+ if (Array.isArray(a)) {
1251
+ if (a.length === 0)
1252
+ return [];
1253
+ return this.getAll({ filter: { id: { $any: a } } });
1254
+ }
1255
+ if (isString(a)) {
1256
+ const cacheRecord = await __privateMethod$2(this, _getCacheRecord, getCacheRecord_fn).call(this, a);
1257
+ if (cacheRecord)
1258
+ return cacheRecord;
1259
+ const fetchProps = await __privateGet$4(this, _getFetchProps).call(this);
1260
+ try {
1261
+ const response = await getRecord({
1262
+ pathParams: { workspace: "{workspaceId}", dbBranchName: "{dbBranch}", tableName: __privateGet$4(this, _table), recordId: a },
1263
+ ...fetchProps
1264
+ });
1265
+ const schema = await __privateMethod$2(this, _getSchema$1, getSchema_fn$1).call(this);
1266
+ return initObject(this.db, schema, __privateGet$4(this, _table), response);
1267
+ } catch (e) {
1268
+ if (isObject(e) && e.status === 404) {
1269
+ return null;
1270
+ }
1271
+ throw e;
1231
1272
  }
1232
- throw e;
1233
1273
  }
1234
1274
  }
1235
1275
  async update(a, b) {
1236
1276
  if (Array.isArray(a)) {
1277
+ if (a.length === 0)
1278
+ return [];
1237
1279
  if (a.length > 100) {
1238
1280
  console.warn("Bulk update operation is not optimized in the Xata API yet, this request might be slow");
1239
1281
  }
@@ -1255,6 +1297,8 @@ class RestRepository extends Query {
1255
1297
  }
1256
1298
  async createOrUpdate(a, b) {
1257
1299
  if (Array.isArray(a)) {
1300
+ if (a.length === 0)
1301
+ return [];
1258
1302
  if (a.length > 100) {
1259
1303
  console.warn("Bulk update operation is not optimized in the Xata API yet, this request might be slow");
1260
1304
  }
@@ -1276,6 +1320,8 @@ class RestRepository extends Query {
1276
1320
  }
1277
1321
  async delete(a) {
1278
1322
  if (Array.isArray(a)) {
1323
+ if (a.length === 0)
1324
+ return;
1279
1325
  if (a.length > 100) {
1280
1326
  console.warn("Bulk delete operation is not optimized in the Xata API yet, this request might be slow");
1281
1327
  }
@@ -1296,9 +1342,14 @@ class RestRepository extends Query {
1296
1342
  }
1297
1343
  async search(query, options = {}) {
1298
1344
  const fetchProps = await __privateGet$4(this, _getFetchProps).call(this);
1299
- const { records } = await searchBranch({
1300
- pathParams: { workspace: "{workspaceId}", dbBranchName: "{dbBranch}" },
1301
- body: { tables: [__privateGet$4(this, _table)], query, fuzziness: options.fuzziness },
1345
+ const { records } = await searchTable({
1346
+ pathParams: { workspace: "{workspaceId}", dbBranchName: "{dbBranch}", tableName: __privateGet$4(this, _table) },
1347
+ body: {
1348
+ query,
1349
+ fuzziness: options.fuzziness,
1350
+ highlight: options.highlight,
1351
+ filter: options.filter
1352
+ },
1302
1353
  ...fetchProps
1303
1354
  });
1304
1355
  const schema = await __privateMethod$2(this, _getSchema$1, getSchema_fn$1).call(this);
@@ -1311,7 +1362,7 @@ class RestRepository extends Query {
1311
1362
  const data = query.getQueryOptions();
1312
1363
  const body = {
1313
1364
  filter: Object.values(data.filter ?? {}).some(Boolean) ? data.filter : void 0,
1314
- sort: data.sort ? buildSortFilter(data.sort) : void 0,
1365
+ sort: data.sort !== void 0 ? buildSortFilter(data.sort) : void 0,
1315
1366
  page: data.pagination,
1316
1367
  columns: data.columns
1317
1368
  };
@@ -1501,7 +1552,7 @@ const initObject = (db, schema, table, object) => {
1501
1552
  const linkTable = column.link?.table;
1502
1553
  if (!linkTable) {
1503
1554
  console.error(`Failed to parse link for field ${column.name}`);
1504
- } else if (value && isObject(value)) {
1555
+ } else if (isObject(value)) {
1505
1556
  result[column.name] = initObject(db, schema, linkTable, value);
1506
1557
  }
1507
1558
  break;
@@ -1627,7 +1678,7 @@ class SchemaPlugin extends XataPlugin {
1627
1678
  get: (_target, table) => {
1628
1679
  if (!isString(table))
1629
1680
  throw new Error("Invalid table name");
1630
- if (!__privateGet$2(this, _tables)[table]) {
1681
+ if (__privateGet$2(this, _tables)[table] === void 0) {
1631
1682
  __privateGet$2(this, _tables)[table] = new RestRepository({ db, pluginOptions, table });
1632
1683
  }
1633
1684
  return __privateGet$2(this, _tables)[table];
@@ -1699,10 +1750,10 @@ _schema = new WeakMap();
1699
1750
  _search = new WeakSet();
1700
1751
  search_fn = async function(query, options, getFetchProps) {
1701
1752
  const fetchProps = await getFetchProps();
1702
- const { tables, fuzziness } = options ?? {};
1753
+ const { tables, fuzziness, highlight } = options ?? {};
1703
1754
  const { records } = await searchBranch({
1704
1755
  pathParams: { workspace: "{workspaceId}", dbBranchName: "{dbBranch}" },
1705
- body: { tables, query, fuzziness },
1756
+ body: { tables, query, fuzziness, highlight },
1706
1757
  ...fetchProps
1707
1758
  });
1708
1759
  return records;
@@ -1730,30 +1781,39 @@ const envBranchNames = [
1730
1781
  "CF_PAGES_BRANCH",
1731
1782
  "BRANCH"
1732
1783
  ];
1733
- const defaultBranch = "main";
1734
1784
  async function getCurrentBranchName(options) {
1735
- const env = await getBranchByEnvVariable();
1736
- if (env)
1737
- return env;
1738
- const branch = await getGitBranch();
1739
- if (!branch)
1740
- return defaultBranch;
1741
- const details = await getDatabaseBranch(branch, options);
1742
- if (details)
1743
- return branch;
1744
- return defaultBranch;
1785
+ const env = getBranchByEnvVariable();
1786
+ if (env) {
1787
+ const details = await getDatabaseBranch(env, options);
1788
+ if (details)
1789
+ return env;
1790
+ console.warn(`Branch ${env} not found in Xata. Ignoring...`);
1791
+ }
1792
+ const gitBranch = await getGitBranch();
1793
+ return resolveXataBranch(gitBranch, options);
1745
1794
  }
1746
1795
  async function getCurrentBranchDetails(options) {
1747
- const env = await getBranchByEnvVariable();
1748
- if (env)
1749
- return getDatabaseBranch(env, options);
1750
- const branch = await getGitBranch();
1751
- if (!branch)
1752
- return getDatabaseBranch(defaultBranch, options);
1753
- const details = await getDatabaseBranch(branch, options);
1754
- if (details)
1755
- return details;
1756
- return getDatabaseBranch(defaultBranch, options);
1796
+ const branch = await getCurrentBranchName(options);
1797
+ return getDatabaseBranch(branch, options);
1798
+ }
1799
+ async function resolveXataBranch(gitBranch, options) {
1800
+ const databaseURL = options?.databaseURL || getDatabaseURL();
1801
+ const apiKey = options?.apiKey || getAPIKey();
1802
+ if (!databaseURL)
1803
+ throw new Error("A databaseURL was not defined. Either set the XATA_DATABASE_URL env variable or pass the argument explicitely");
1804
+ if (!apiKey)
1805
+ throw new Error("An API key was not defined. Either set the XATA_API_KEY env variable or pass the argument explicitely");
1806
+ const [protocol, , host, , dbName] = databaseURL.split("/");
1807
+ const [workspace] = host.split(".");
1808
+ const { branch } = await resolveBranch({
1809
+ apiKey,
1810
+ apiUrl: databaseURL,
1811
+ fetchImpl: getFetchImplementation(options?.fetchImpl),
1812
+ workspacesApiUrl: `${protocol}//${host}`,
1813
+ pathParams: { dbName, workspace },
1814
+ queryParams: { gitBranch, fallbackBranch: getEnvVariable("XATA_FALLBACK_BRANCH") }
1815
+ });
1816
+ return branch;
1757
1817
  }
1758
1818
  async function getDatabaseBranch(branch, options) {
1759
1819
  const databaseURL = options?.databaseURL || getDatabaseURL();
@@ -1842,7 +1902,7 @@ const buildClient = (plugins) => {
1842
1902
  this.db = db;
1843
1903
  this.search = search;
1844
1904
  for (const [key, namespace] of Object.entries(plugins ?? {})) {
1845
- if (!namespace)
1905
+ if (namespace === void 0)
1846
1906
  continue;
1847
1907
  const result = namespace.build(pluginOptions);
1848
1908
  if (result instanceof Promise) {
@@ -1859,7 +1919,7 @@ const buildClient = (plugins) => {
1859
1919
  const databaseURL = options?.databaseURL || getDatabaseURL();
1860
1920
  const apiKey = options?.apiKey || getAPIKey();
1861
1921
  const cache = options?.cache ?? new SimpleCache({ cacheRecords: false, defaultQueryTTL: 0 });
1862
- const branch = async () => options?.branch ? await __privateMethod(this, _evaluateBranch, evaluateBranch_fn).call(this, options.branch) : await getCurrentBranchName({ apiKey, databaseURL, fetchImpl: options?.fetch });
1922
+ const branch = async () => options?.branch !== void 0 ? await __privateMethod(this, _evaluateBranch, evaluateBranch_fn).call(this, options.branch) : await getCurrentBranchName({ apiKey, databaseURL, fetchImpl: options?.fetch });
1863
1923
  if (!databaseURL || !apiKey) {
1864
1924
  throw new Error("Options databaseURL and apiKey are required");
1865
1925
  }
@@ -1886,7 +1946,7 @@ const buildClient = (plugins) => {
1886
1946
  }, _evaluateBranch = new WeakSet(), evaluateBranch_fn = async function(param) {
1887
1947
  if (__privateGet(this, _branch))
1888
1948
  return __privateGet(this, _branch);
1889
- if (!param)
1949
+ if (param === void 0)
1890
1950
  return void 0;
1891
1951
  const strategies = Array.isArray(param) ? [...param] : [param];
1892
1952
  const evaluateBranch = async (strategy) => {
@@ -1983,6 +2043,7 @@ exports.insertRecord = insertRecord;
1983
2043
  exports.insertRecordWithID = insertRecordWithID;
1984
2044
  exports.inviteWorkspaceMember = inviteWorkspaceMember;
1985
2045
  exports.is = is;
2046
+ exports.isCursorPaginationOptions = isCursorPaginationOptions;
1986
2047
  exports.isIdentifiable = isIdentifiable;
1987
2048
  exports.isNot = isNot;
1988
2049
  exports.isXataRecord = isXataRecord;
@@ -1998,6 +2059,7 @@ exports.removeWorkspaceMember = removeWorkspaceMember;
1998
2059
  exports.resendWorkspaceMemberInvite = resendWorkspaceMemberInvite;
1999
2060
  exports.resolveBranch = resolveBranch;
2000
2061
  exports.searchBranch = searchBranch;
2062
+ exports.searchTable = searchTable;
2001
2063
  exports.setTableSchema = setTableSchema;
2002
2064
  exports.startsWith = startsWith;
2003
2065
  exports.updateBranchMetadata = updateBranchMetadata;