tsense 0.0.17 → 0.1.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/dist/migrator.js CHANGED
@@ -1,61 +1,50 @@
1
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
- return new (P || (P = Promise))(function (resolve, reject) {
4
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
- step((generator = generator.apply(thisArg, _arguments || [])).next());
8
- });
9
- };
10
1
  const COMPARABLE_KEYS = ["type", "facet", "sort", "index", "optional"];
11
2
  const NESTED_TYPES = ["object", "object[]"];
12
3
  export class TSenseMigrator {
4
+ collectionName;
5
+ localFields;
6
+ defaultSortingField;
7
+ axios;
13
8
  constructor(collectionName, localFields, defaultSortingField, axios) {
14
9
  this.collectionName = collectionName;
15
10
  this.localFields = localFields;
16
11
  this.defaultSortingField = defaultSortingField;
17
12
  this.axios = axios;
18
13
  }
19
- sync() {
20
- return __awaiter(this, void 0, void 0, function* () {
21
- const exists = yield this.exists();
22
- if (!exists) {
23
- return yield this.create();
24
- }
25
- const remoteFields = yield this.getRemoteFields();
26
- const diff = this.diff(remoteFields);
27
- if (!diff.toAdd.length && !diff.toRemove.length && !diff.toModify.length) {
28
- return;
29
- }
30
- const patched = yield this.patch(diff);
31
- if (patched)
32
- return;
33
- yield this.drop();
34
- yield this.create();
35
- });
14
+ async sync() {
15
+ const exists = await this.exists();
16
+ if (!exists) {
17
+ return await this.create();
18
+ }
19
+ const remoteFields = await this.getRemoteFields();
20
+ const diff = this.diff(remoteFields);
21
+ if (!diff.toAdd.length && !diff.toRemove.length && !diff.toModify.length) {
22
+ return;
23
+ }
24
+ const patched = await this.patch(diff);
25
+ if (patched)
26
+ return;
27
+ await this.drop();
28
+ await this.create();
36
29
  }
37
- exists() {
38
- return __awaiter(this, void 0, void 0, function* () {
39
- return yield this.axios({
40
- method: "GET",
41
- url: `/collections/${this.collectionName}`,
42
- })
43
- .then(() => true)
44
- .catch((e) => {
45
- if (e.status === 404)
46
- return false;
47
- throw e;
48
- });
30
+ async exists() {
31
+ return await this.axios({
32
+ method: "GET",
33
+ url: `/collections/${this.collectionName}`,
34
+ })
35
+ .then(() => true)
36
+ .catch((e) => {
37
+ if (e.status === 404)
38
+ return false;
39
+ throw e;
49
40
  });
50
41
  }
51
- getRemoteFields() {
52
- return __awaiter(this, void 0, void 0, function* () {
53
- const { data } = yield this.axios({
54
- method: "GET",
55
- url: `/collections/${this.collectionName}`,
56
- });
57
- return data.fields;
42
+ async getRemoteFields() {
43
+ const { data } = await this.axios({
44
+ method: "GET",
45
+ url: `/collections/${this.collectionName}`,
58
46
  });
47
+ return data.fields;
59
48
  }
60
49
  diff(remote) {
61
50
  const remoteByName = new Map(remote.map((f) => [f.name, f]));
@@ -85,57 +74,50 @@ export class TSenseMigrator {
85
74
  return { toAdd, toRemove, toModify };
86
75
  }
87
76
  fieldsMatch(local, remote) {
88
- var _a, _b;
89
77
  for (const key of COMPARABLE_KEYS) {
90
- if (((_a = local[key]) !== null && _a !== void 0 ? _a : undefined) !== ((_b = remote[key]) !== null && _b !== void 0 ? _b : undefined)) {
78
+ if ((local[key] ?? undefined) !== (remote[key] ?? undefined)) {
91
79
  return false;
92
80
  }
93
81
  }
94
82
  return true;
95
83
  }
96
- patch(diff) {
97
- return __awaiter(this, void 0, void 0, function* () {
98
- const fields = [];
99
- for (const field of diff.toRemove) {
100
- fields.push({ name: field.name, drop: true });
101
- }
102
- for (const field of diff.toModify) {
103
- fields.push({ name: field.name, drop: true });
104
- fields.push(field);
105
- }
106
- for (const field of diff.toAdd) {
107
- fields.push(field);
108
- }
109
- return yield this.axios({
110
- method: "PATCH",
111
- url: `/collections/${this.collectionName}`,
112
- data: { fields },
113
- })
114
- .then(() => true)
115
- .catch(() => false);
116
- });
84
+ async patch(diff) {
85
+ const fields = [];
86
+ for (const field of diff.toRemove) {
87
+ fields.push({ name: field.name, drop: true });
88
+ }
89
+ for (const field of diff.toModify) {
90
+ fields.push({ name: field.name, drop: true });
91
+ fields.push(field);
92
+ }
93
+ for (const field of diff.toAdd) {
94
+ fields.push(field);
95
+ }
96
+ return await this.axios({
97
+ method: "PATCH",
98
+ url: `/collections/${this.collectionName}`,
99
+ data: { fields },
100
+ })
101
+ .then(() => true)
102
+ .catch(() => false);
117
103
  }
118
- create() {
119
- return __awaiter(this, void 0, void 0, function* () {
120
- const enable_nested_fields = this.localFields.some((f) => NESTED_TYPES.includes(f.type));
121
- yield this.axios({
122
- method: "POST",
123
- url: "/collections",
124
- data: {
125
- name: this.collectionName,
126
- fields: this.localFields,
127
- default_sorting_field: this.defaultSortingField,
128
- enable_nested_fields,
129
- },
130
- });
104
+ async create() {
105
+ const enable_nested_fields = this.localFields.some((f) => NESTED_TYPES.includes(f.type));
106
+ await this.axios({
107
+ method: "POST",
108
+ url: "/collections",
109
+ data: {
110
+ name: this.collectionName,
111
+ fields: this.localFields,
112
+ default_sorting_field: this.defaultSortingField,
113
+ enable_nested_fields,
114
+ },
131
115
  });
132
116
  }
133
- drop() {
134
- return __awaiter(this, void 0, void 0, function* () {
135
- yield this.axios({
136
- method: "DELETE",
137
- url: `/collections/${this.collectionName}`,
138
- });
117
+ async drop() {
118
+ await this.axios({
119
+ method: "DELETE",
120
+ url: `/collections/${this.collectionName}`,
139
121
  });
140
122
  }
141
123
  }
package/dist/tsense.js CHANGED
@@ -1,13 +1,3 @@
1
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
- return new (P || (P = Promise))(function (resolve, reject) {
4
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
- step((generator = generator.apply(thisArg, _arguments || [])).next());
8
- });
9
- };
10
- var _a;
11
1
  import redaxios from "redaxios";
12
2
  import { TSenseMigrator } from "./migrator.js";
13
3
  import { defaultTransformers } from "./transformers/defaults.js";
@@ -18,7 +8,7 @@ function chunkArray(arr, size) {
18
8
  }
19
9
  return chunks;
20
10
  }
21
- const redaxiosInstance = (_a = redaxios.default) !== null && _a !== void 0 ? _a : redaxios;
11
+ const redaxiosInstance = redaxios.default ?? redaxios;
22
12
  const arkToTsense = {
23
13
  string: "string",
24
14
  number: "float",
@@ -30,21 +20,23 @@ const arkToTsense = {
30
20
  "boolean[]": "bool[]",
31
21
  };
32
22
  export class TSense {
23
+ options;
24
+ fields = [];
25
+ axios;
26
+ synced = false;
27
+ fieldTransformers = new Map();
28
+ dataSyncConfig;
29
+ infer = undefined;
33
30
  getFields() {
34
31
  return this.fields;
35
32
  }
36
33
  constructor(options) {
37
- var _a;
38
34
  this.options = options;
39
- this.fields = [];
40
- this.synced = false;
41
- this.fieldTransformers = new Map();
42
- this.infer = undefined;
43
35
  this.axios = redaxiosInstance.create({
44
36
  baseURL: `${options.connection.protocol}://${options.connection.host}:${options.connection.port}`,
45
37
  headers: { "X-TYPESENSE-API-KEY": options.connection.apiKey },
46
38
  });
47
- this.extractFields((_a = options.transformers) !== null && _a !== void 0 ? _a : defaultTransformers);
39
+ this.extractFields(options.transformers ?? defaultTransformers);
48
40
  this.dataSyncConfig = options.dataSync;
49
41
  }
50
42
  getBaseType(expression, domain) {
@@ -65,7 +57,7 @@ export class TSense {
65
57
  return "string";
66
58
  }
67
59
  serializeDoc(doc) {
68
- const result = Object.assign({}, doc);
60
+ const result = { ...doc };
69
61
  for (const [field, transformer] of this.fieldTransformers) {
70
62
  if (result[field] != null) {
71
63
  result[field] = transformer.serialize(result[field]);
@@ -94,7 +86,7 @@ export class TSense {
94
86
  if (!isFilterObject) {
95
87
  return transformer.serialize(value);
96
88
  }
97
- const result = Object.assign({}, v);
89
+ const result = { ...v };
98
90
  if ("min" in v && v.min != null)
99
91
  result.min = transformer.serialize(v.min);
100
92
  if ("max" in v && v.max != null)
@@ -106,11 +98,10 @@ export class TSense {
106
98
  return transformer.serialize(value);
107
99
  }
108
100
  extractFields(transformers) {
109
- var _a, _b, _c, _d;
110
101
  const internal = this.options.schema;
111
102
  for (const prop of internal.structure.props) {
112
- const innerType = (_b = (_a = prop.value.branches) === null || _a === void 0 ? void 0 : _a[0]) !== null && _b !== void 0 ? _b : prop.value;
113
- const meta = ((_c = innerType.meta) !== null && _c !== void 0 ? _c : prop.value.meta);
103
+ const innerType = prop.value.branches?.[0] ?? prop.value;
104
+ const meta = (innerType.meta ?? prop.value.meta);
114
105
  const expression = String(prop.value.expression);
115
106
  const domain = prop.value.domain;
116
107
  const baseType = this.getBaseType(expression, domain);
@@ -121,38 +112,33 @@ export class TSense {
121
112
  name: prop.key,
122
113
  type: transformer.storageType,
123
114
  optional: prop.kind === "optional",
124
- facet: meta === null || meta === void 0 ? void 0 : meta.facet,
125
- sort: meta === null || meta === void 0 ? void 0 : meta.sort,
126
- index: meta === null || meta === void 0 ? void 0 : meta.index,
115
+ facet: meta?.facet,
116
+ sort: meta?.sort,
117
+ index: meta?.index,
127
118
  });
128
119
  continue;
129
120
  }
130
- const type = (_d = meta === null || meta === void 0 ? void 0 : meta.type) !== null && _d !== void 0 ? _d : this.inferType(baseType);
121
+ const type = meta?.type ?? this.inferType(baseType);
131
122
  this.fields.push({
132
123
  name: prop.key,
133
124
  type,
134
125
  optional: prop.kind === "optional",
135
- facet: meta === null || meta === void 0 ? void 0 : meta.facet,
136
- sort: meta === null || meta === void 0 ? void 0 : meta.sort,
137
- index: meta === null || meta === void 0 ? void 0 : meta.index,
126
+ facet: meta?.facet,
127
+ sort: meta?.sort,
128
+ index: meta?.index,
138
129
  });
139
130
  }
140
131
  }
141
- ensureSynced(force) {
142
- return __awaiter(this, void 0, void 0, function* () {
143
- if (!force && (this.synced || !this.options.autoSyncSchema))
144
- return;
145
- yield new TSenseMigrator(this.options.name, this.fields, this.options.defaultSortingField, this.axios).sync();
146
- this.synced = true;
147
- });
132
+ async ensureSynced(force) {
133
+ if (!force && (this.synced || !this.options.autoSyncSchema))
134
+ return;
135
+ await new TSenseMigrator(this.options.name, this.fields, this.options.defaultSortingField, this.axios).sync();
136
+ this.synced = true;
148
137
  }
149
- syncSchema() {
150
- return __awaiter(this, void 0, void 0, function* () {
151
- yield this.ensureSynced(true);
152
- });
138
+ async syncSchema() {
139
+ await this.ensureSynced(true);
153
140
  }
154
141
  buildObjectFilter(key, value) {
155
- var _a, _b;
156
142
  if (Array.isArray(value)) {
157
143
  return `(${key}:[${value.join(",")}])`;
158
144
  }
@@ -160,8 +146,8 @@ export class TSense {
160
146
  if ("not" in v) {
161
147
  return `${key}:!=${v.not}`;
162
148
  }
163
- const min = (_a = v.min) !== null && _a !== void 0 ? _a : undefined;
164
- const max = (_b = v.max) !== null && _b !== void 0 ? _b : undefined;
149
+ const min = v.min ?? undefined;
150
+ const max = v.max ?? undefined;
165
151
  if (min != null && max != null) {
166
152
  return `${key}:[${min}..${max}]`;
167
153
  }
@@ -174,7 +160,7 @@ export class TSense {
174
160
  }
175
161
  buildFilter(filter) {
176
162
  const result = [];
177
- for (const entry of Object.entries(filter !== null && filter !== void 0 ? filter : {})) {
163
+ for (const entry of Object.entries(filter ?? {})) {
178
164
  const [key, rawValue] = entry;
179
165
  if (rawValue == null)
180
166
  continue;
@@ -219,322 +205,291 @@ export class TSense {
219
205
  }
220
206
  return result.join(",");
221
207
  }
222
- create() {
223
- return __awaiter(this, void 0, void 0, function* () {
224
- const enableNested = this.fields.some((f) => f.type === "object" || f.type === "object[]");
225
- yield this.axios({
226
- method: "POST",
227
- url: "/collections",
228
- data: {
229
- name: this.options.name,
230
- fields: this.fields,
231
- default_sorting_field: this.options.defaultSortingField,
232
- enable_nested_fields: enableNested,
233
- },
234
- });
235
- return this;
208
+ async create() {
209
+ const enableNested = this.fields.some((f) => f.type === "object" || f.type === "object[]");
210
+ await this.axios({
211
+ method: "POST",
212
+ url: "/collections",
213
+ data: {
214
+ name: this.options.name,
215
+ fields: this.fields,
216
+ default_sorting_field: this.options.defaultSortingField,
217
+ enable_nested_fields: enableNested,
218
+ },
236
219
  });
220
+ return this;
237
221
  }
238
- drop() {
239
- return __awaiter(this, void 0, void 0, function* () {
240
- yield this.axios({
241
- method: "DELETE",
242
- url: `/collections/${this.options.name}`,
243
- });
222
+ async drop() {
223
+ await this.axios({
224
+ method: "DELETE",
225
+ url: `/collections/${this.options.name}`,
244
226
  });
245
227
  }
246
- get(id) {
247
- return __awaiter(this, void 0, void 0, function* () {
248
- yield this.ensureSynced();
249
- const { data } = yield this.axios({
250
- method: "GET",
251
- url: `/collections/${this.options.name}/documents/${id}`,
252
- }).catch((e) => {
253
- if (e.status === 404)
254
- return { data: null };
255
- throw e;
256
- });
257
- return data ? this.deserializeDoc(data) : null;
228
+ async get(id) {
229
+ await this.ensureSynced();
230
+ const { data } = await this.axios({
231
+ method: "GET",
232
+ url: `/collections/${this.options.name}/documents/${id}`,
233
+ }).catch((e) => {
234
+ if (e.status === 404)
235
+ return { data: null };
236
+ throw e;
258
237
  });
238
+ return data ? this.deserializeDoc(data) : null;
259
239
  }
260
- delete(id) {
261
- return __awaiter(this, void 0, void 0, function* () {
262
- yield this.ensureSynced();
263
- const { data } = yield this.axios({
264
- method: "DELETE",
265
- url: `/collections/${this.options.name}/documents/${id}`,
266
- }).catch((e) => {
267
- if (e.status === 404)
268
- return { data: null };
269
- throw e;
270
- });
271
- return data != null;
240
+ async delete(id) {
241
+ await this.ensureSynced();
242
+ const { data } = await this.axios({
243
+ method: "DELETE",
244
+ url: `/collections/${this.options.name}/documents/${id}`,
245
+ }).catch((e) => {
246
+ if (e.status === 404)
247
+ return { data: null };
248
+ throw e;
272
249
  });
250
+ return data != null;
273
251
  }
274
- deleteMany(filter) {
275
- return __awaiter(this, void 0, void 0, function* () {
276
- yield this.ensureSynced();
277
- const filterBy = this.buildFilter(filter).join("&&");
278
- if (!filterBy) {
279
- throw new Error("FILTER_REQUIRED");
280
- }
281
- const { data } = yield this.axios({
282
- method: "DELETE",
283
- url: `/collections/${this.options.name}/documents`,
284
- params: { filter_by: filterBy },
285
- });
286
- return { deleted: data.num_deleted };
252
+ async deleteMany(filter) {
253
+ await this.ensureSynced();
254
+ const filterBy = this.buildFilter(filter).join("&&");
255
+ if (!filterBy) {
256
+ throw new Error("FILTER_REQUIRED");
257
+ }
258
+ const { data } = await this.axios({
259
+ method: "DELETE",
260
+ url: `/collections/${this.options.name}/documents`,
261
+ params: { filter_by: filterBy },
287
262
  });
263
+ return { deleted: data.num_deleted };
288
264
  }
289
- update(id, data) {
290
- return __awaiter(this, void 0, void 0, function* () {
291
- yield this.ensureSynced();
292
- const serialized = this.serializeDoc(data);
293
- const { data: updated } = yield this.axios({
294
- method: "PATCH",
295
- url: `/collections/${this.options.name}/documents/${id}`,
296
- data: serialized,
297
- });
298
- return this.deserializeDoc(updated);
265
+ async update(id, data) {
266
+ await this.ensureSynced();
267
+ const serialized = this.serializeDoc(data);
268
+ const { data: updated } = await this.axios({
269
+ method: "PATCH",
270
+ url: `/collections/${this.options.name}/documents/${id}`,
271
+ data: serialized,
299
272
  });
273
+ return this.deserializeDoc(updated);
300
274
  }
301
- updateMany(filter, data) {
302
- return __awaiter(this, void 0, void 0, function* () {
303
- yield this.ensureSynced();
304
- const filterBy = this.buildFilter(filter).join("&&");
305
- if (!filterBy) {
306
- throw new Error("FILTER_REQUIRED");
307
- }
308
- const serialized = this.serializeDoc(data);
309
- const { data: result } = yield this.axios({
310
- method: "PATCH",
311
- url: `/collections/${this.options.name}/documents`,
312
- params: { filter_by: filterBy },
313
- data: serialized,
314
- });
315
- return { updated: result.num_updated };
275
+ async updateMany(filter, data) {
276
+ await this.ensureSynced();
277
+ const filterBy = this.buildFilter(filter).join("&&");
278
+ if (!filterBy) {
279
+ throw new Error("FILTER_REQUIRED");
280
+ }
281
+ const serialized = this.serializeDoc(data);
282
+ const { data: result } = await this.axios({
283
+ method: "PATCH",
284
+ url: `/collections/${this.options.name}/documents`,
285
+ params: { filter_by: filterBy },
286
+ data: serialized,
316
287
  });
288
+ return { updated: result.num_updated };
317
289
  }
318
- search(options) {
319
- return __awaiter(this, void 0, void 0, function* () {
320
- var _a, _b, _c, _d, _e, _f, _g;
321
- yield this.ensureSynced();
322
- const params = {
323
- q: (_a = options.query) !== null && _a !== void 0 ? _a : "",
324
- query_by: ((_b = options.queryBy) !== null && _b !== void 0 ? _b : [this.options.defaultSearchField]).join(","),
325
- };
326
- const sortBy = this.buildSort(options);
327
- if (sortBy)
328
- params.sort_by = sortBy;
329
- const filterBy = this.buildFilter(options.filter).join("&&");
330
- if (filterBy)
331
- params.filter_by = filterBy;
332
- if (options.page != null)
333
- params.page = options.page;
334
- if (options.limit != null)
335
- params.per_page = options.limit;
336
- const facetBy = (_c = options.facetBy) === null || _c === void 0 ? void 0 : _c.join(",");
337
- if (facetBy)
338
- params.facet_by = facetBy;
339
- if ("pick" in options && options.pick) {
340
- params.include_fields = options.pick.join(",");
290
+ async search(options) {
291
+ await this.ensureSynced();
292
+ const params = {
293
+ q: options.query ?? "",
294
+ query_by: (options.queryBy ?? [this.options.defaultSearchField]).join(","),
295
+ };
296
+ const sortBy = this.buildSort(options);
297
+ if (sortBy)
298
+ params.sort_by = sortBy;
299
+ const filterBy = this.buildFilter(options.filter).join("&&");
300
+ if (filterBy)
301
+ params.filter_by = filterBy;
302
+ if (options.page != null)
303
+ params.page = options.page;
304
+ if (options.limit != null)
305
+ params.per_page = options.limit;
306
+ const facetBy = options.facetBy?.join(",");
307
+ if (facetBy)
308
+ params.facet_by = facetBy;
309
+ if ("pick" in options && options.pick) {
310
+ params.include_fields = options.pick.join(",");
311
+ }
312
+ if ("omit" in options && options.omit) {
313
+ params.exclude_fields = options.omit.join(",");
314
+ }
315
+ const highlight = options.highlight;
316
+ const highlightEnabled = !!highlight;
317
+ let highlightOpts;
318
+ if (typeof highlight === "object") {
319
+ highlightOpts = highlight;
320
+ if (highlightOpts.fields) {
321
+ params.highlight_fields = highlightOpts.fields.join(",");
341
322
  }
342
- if ("omit" in options && options.omit) {
343
- params.exclude_fields = options.omit.join(",");
323
+ if (highlightOpts.startTag) {
324
+ params.highlight_start_tag = highlightOpts.startTag;
344
325
  }
345
- const highlight = options.highlight;
346
- const highlightEnabled = !!highlight;
347
- let highlightOpts;
348
- if (typeof highlight === "object") {
349
- highlightOpts = highlight;
350
- if (highlightOpts.fields) {
351
- params.highlight_fields = highlightOpts.fields.join(",");
352
- }
353
- if (highlightOpts.startTag) {
354
- params.highlight_start_tag = highlightOpts.startTag;
355
- }
356
- if (highlightOpts.endTag) {
357
- params.highlight_end_tag = highlightOpts.endTag;
358
- }
326
+ if (highlightOpts.endTag) {
327
+ params.highlight_end_tag = highlightOpts.endTag;
359
328
  }
360
- const { data: res } = yield this.axios({
361
- method: "GET",
362
- url: `/collections/${this.options.name}/documents/search`,
363
- params,
364
- });
365
- const data = [];
366
- const scores = [];
367
- for (const hit of (_d = res.hits) !== null && _d !== void 0 ? _d : []) {
368
- if (highlightEnabled) {
369
- const fieldsToHighlight = highlightOpts === null || highlightOpts === void 0 ? void 0 : highlightOpts.fields;
370
- for (const [key, value] of Object.entries((_e = hit.highlight) !== null && _e !== void 0 ? _e : {})) {
371
- if (!(value === null || value === void 0 ? void 0 : value.snippet))
372
- continue;
373
- if (fieldsToHighlight && !fieldsToHighlight.includes(key))
374
- continue;
375
- hit.document[key] = value.snippet;
376
- }
329
+ }
330
+ const { data: res } = await this.axios({
331
+ method: "GET",
332
+ url: `/collections/${this.options.name}/documents/search`,
333
+ params,
334
+ });
335
+ const data = [];
336
+ const scores = [];
337
+ for (const hit of res.hits ?? []) {
338
+ if (highlightEnabled) {
339
+ const fieldsToHighlight = highlightOpts?.fields;
340
+ for (const [key, value] of Object.entries(hit.highlight ?? {})) {
341
+ if (!value?.snippet)
342
+ continue;
343
+ if (fieldsToHighlight && !fieldsToHighlight.includes(key))
344
+ continue;
345
+ hit.document[key] = value.snippet;
377
346
  }
378
- const doc = this.deserializeDoc(hit.document);
379
- data.push(doc);
380
- scores.push((_f = hit.text_match) !== null && _f !== void 0 ? _f : 0);
381
347
  }
382
- const facets = {};
383
- for (const facetCount of (_g = res.facet_counts) !== null && _g !== void 0 ? _g : []) {
384
- const fieldName = facetCount.field_name;
385
- facets[fieldName] = {};
386
- for (const item of facetCount.counts) {
387
- facets[fieldName][item.value] = item.count;
388
- }
348
+ const doc = this.deserializeDoc(hit.document);
349
+ data.push(doc);
350
+ scores.push(hit.text_match ?? 0);
351
+ }
352
+ const facets = {};
353
+ for (const facetCount of res.facet_counts ?? []) {
354
+ const fieldName = facetCount.field_name;
355
+ facets[fieldName] = {};
356
+ for (const item of facetCount.counts) {
357
+ facets[fieldName][item.value] = item.count;
389
358
  }
390
- return {
391
- count: res.found,
392
- data,
393
- facets,
394
- scores,
395
- };
396
- });
359
+ }
360
+ return {
361
+ count: res.found,
362
+ data,
363
+ facets,
364
+ scores,
365
+ };
397
366
  }
398
- searchList(options) {
399
- return __awaiter(this, void 0, void 0, function* () {
400
- var _a, _b, _c, _d;
401
- yield this.ensureSynced();
402
- const limit = Math.min((_a = options.limit) !== null && _a !== void 0 ? _a : 20, 100);
403
- const field = options.sort.field;
404
- const page = options.cursor ? Number(options.cursor) : 1;
405
- const params = {
406
- q: (_b = options.query) !== null && _b !== void 0 ? _b : "",
407
- query_by: ((_c = options.queryBy) !== null && _c !== void 0 ? _c : [this.options.defaultSearchField]).join(","),
408
- per_page: limit,
409
- page,
410
- sort_by: `${field}:${options.sort.direction}`,
411
- };
412
- const filterParts = this.buildFilter(options.filter);
413
- const filterBy = filterParts.join("&&");
414
- if (filterBy)
415
- params.filter_by = filterBy;
416
- const { data: res } = yield this.axios({
417
- method: "GET",
418
- url: `/collections/${this.options.name}/documents/search`,
419
- params,
420
- });
421
- const hits = (_d = res.hits) !== null && _d !== void 0 ? _d : [];
422
- const data = [];
423
- for (const hit of hits) {
424
- const doc = this.deserializeDoc(hit.document);
425
- data.push(doc);
426
- }
427
- const hasMore = page * limit < res.found;
428
- const nextCursor = hasMore ? String(page + 1) : null;
429
- return { data, nextCursor, total: res.found };
367
+ async searchList(options) {
368
+ await this.ensureSynced();
369
+ const limit = Math.min(options.limit ?? 20, 100);
370
+ const field = options.sort.field;
371
+ const page = options.cursor ? Number(options.cursor) : 1;
372
+ const params = {
373
+ q: options.query ?? "",
374
+ query_by: (options.queryBy ?? [this.options.defaultSearchField]).join(","),
375
+ per_page: limit,
376
+ page,
377
+ sort_by: `${field}:${options.sort.direction}`,
378
+ };
379
+ const filterParts = this.buildFilter(options.filter);
380
+ const filterBy = filterParts.join("&&");
381
+ if (filterBy)
382
+ params.filter_by = filterBy;
383
+ const { data: res } = await this.axios({
384
+ method: "GET",
385
+ url: `/collections/${this.options.name}/documents/search`,
386
+ params,
430
387
  });
388
+ const hits = res.hits ?? [];
389
+ const data = [];
390
+ for (const hit of hits) {
391
+ const doc = this.deserializeDoc(hit.document);
392
+ data.push(doc);
393
+ }
394
+ const hasMore = page * limit < res.found;
395
+ const nextCursor = hasMore ? String(page + 1) : null;
396
+ return { data, nextCursor, total: res.found };
431
397
  }
432
- count(filter) {
433
- return __awaiter(this, void 0, void 0, function* () {
434
- yield this.ensureSynced();
435
- const filterBy = this.buildFilter(filter).join("&&");
436
- if (!filterBy) {
437
- const { data } = yield this.axios({
438
- method: "GET",
439
- url: `/collections/${this.options.name}`,
440
- });
441
- return data.num_documents;
442
- }
443
- const { data } = yield this.axios({
398
+ async count(filter) {
399
+ await this.ensureSynced();
400
+ const filterBy = this.buildFilter(filter).join("&&");
401
+ if (!filterBy) {
402
+ const { data } = await this.axios({
444
403
  method: "GET",
445
- url: `/collections/${this.options.name}/documents/search`,
446
- params: {
447
- q: "*",
448
- query_by: this.options.defaultSearchField,
449
- per_page: 0,
450
- filter_by: filterBy,
451
- },
404
+ url: `/collections/${this.options.name}`,
452
405
  });
453
- return data.found;
406
+ return data.num_documents;
407
+ }
408
+ const { data } = await this.axios({
409
+ method: "GET",
410
+ url: `/collections/${this.options.name}/documents/search`,
411
+ params: {
412
+ q: "*",
413
+ query_by: this.options.defaultSearchField,
414
+ per_page: 0,
415
+ filter_by: filterBy,
416
+ },
454
417
  });
418
+ return data.found;
455
419
  }
456
- upsert(docs) {
457
- return __awaiter(this, void 0, void 0, function* () {
458
- yield this.ensureSynced();
459
- const items = Array.isArray(docs) ? docs : [docs];
460
- if (!items.length)
461
- return [];
462
- if (this.options.validateOnUpsert) {
463
- for (const item of items) {
464
- this.options.schema.assert(item);
465
- }
466
- }
467
- const payload = items.map((item) => JSON.stringify(this.serializeDoc(item))).join("\n");
468
- const params = { action: "upsert" };
469
- if (this.options.batchSize) {
470
- params.batch_size = this.options.batchSize;
420
+ async upsert(docs) {
421
+ await this.ensureSynced();
422
+ const items = Array.isArray(docs) ? docs : [docs];
423
+ if (!items.length)
424
+ return [];
425
+ if (this.options.validateOnUpsert) {
426
+ for (const item of items) {
427
+ this.options.schema.assert(item);
471
428
  }
472
- const { data } = yield this.axios({
473
- method: "POST",
474
- url: `/collections/${this.options.name}/documents/import`,
475
- headers: { "Content-Type": "text/plain" },
476
- params,
477
- data: payload,
478
- });
479
- if (typeof data === "string") {
480
- return data.split("\n").map((v) => JSON.parse(v));
481
- }
482
- return [data];
429
+ }
430
+ const payload = items.map((item) => JSON.stringify(this.serializeDoc(item))).join("\n");
431
+ const params = { action: "upsert" };
432
+ if (this.options.batchSize) {
433
+ params.batch_size = this.options.batchSize;
434
+ }
435
+ const { data } = await this.axios({
436
+ method: "POST",
437
+ url: `/collections/${this.options.name}/documents/import`,
438
+ headers: { "Content-Type": "text/plain" },
439
+ params,
440
+ data: payload,
483
441
  });
442
+ if (typeof data === "string") {
443
+ return data.split("\n").map((v) => JSON.parse(v));
444
+ }
445
+ return [data];
484
446
  }
485
- syncData(options) {
486
- return __awaiter(this, void 0, void 0, function* () {
487
- var _a, _b, _c;
488
- if (!this.dataSyncConfig) {
489
- throw new Error("DATA_SYNC_NOT_CONFIGURED");
490
- }
491
- const chunkSize = (_b = (_a = options === null || options === void 0 ? void 0 : options.chunkSize) !== null && _a !== void 0 ? _a : this.dataSyncConfig.chunkSize) !== null && _b !== void 0 ? _b : 500;
492
- const ids = (_c = options === null || options === void 0 ? void 0 : options.ids) !== null && _c !== void 0 ? _c : (yield this.dataSyncConfig.getAllIds());
493
- let upserted = 0;
494
- let failed = 0;
495
- for (const chunk of chunkArray(ids, chunkSize)) {
496
- const items = yield this.dataSyncConfig.getItems(chunk);
497
- const results = yield this.upsert(items);
498
- for (const r of results) {
499
- if (r.success)
500
- upserted++;
501
- else
502
- failed++;
503
- }
504
- }
505
- let deleted = 0;
506
- if (options === null || options === void 0 ? void 0 : options.purge) {
507
- deleted = yield this.purgeOrphans(ids, chunkSize);
447
+ async syncData(options) {
448
+ if (!this.dataSyncConfig) {
449
+ throw new Error("DATA_SYNC_NOT_CONFIGURED");
450
+ }
451
+ const chunkSize = options?.chunkSize ?? this.dataSyncConfig.chunkSize ?? 500;
452
+ const ids = options?.ids ?? (await this.dataSyncConfig.getAllIds());
453
+ let upserted = 0;
454
+ let failed = 0;
455
+ for (const chunk of chunkArray(ids, chunkSize)) {
456
+ const items = await this.dataSyncConfig.getItems(chunk);
457
+ const results = await this.upsert(items);
458
+ for (const r of results) {
459
+ if (r.success)
460
+ upserted++;
461
+ else
462
+ failed++;
508
463
  }
509
- return { upserted, deleted, failed };
510
- });
464
+ }
465
+ let deleted = 0;
466
+ if (options?.purge) {
467
+ deleted = await this.purgeOrphans(ids, chunkSize);
468
+ }
469
+ return { upserted, deleted, failed };
511
470
  }
512
- purgeOrphans(validIds, chunkSize) {
513
- return __awaiter(this, void 0, void 0, function* () {
514
- const validSet = new Set(validIds);
515
- const remoteIds = yield this.exportIds();
516
- const orphans = remoteIds.filter((id) => !validSet.has(id));
517
- if (!orphans.length)
518
- return 0;
519
- let deleted = 0;
520
- for (const chunk of chunkArray(orphans, chunkSize)) {
521
- const result = yield this.deleteMany({ id: chunk });
522
- deleted += result.deleted;
523
- }
524
- return deleted;
525
- });
471
+ async purgeOrphans(validIds, chunkSize) {
472
+ const validSet = new Set(validIds);
473
+ const remoteIds = await this.exportIds();
474
+ const orphans = remoteIds.filter((id) => !validSet.has(id));
475
+ if (!orphans.length)
476
+ return 0;
477
+ let deleted = 0;
478
+ for (const chunk of chunkArray(orphans, chunkSize)) {
479
+ const result = await this.deleteMany({ id: chunk });
480
+ deleted += result.deleted;
481
+ }
482
+ return deleted;
526
483
  }
527
- exportIds() {
528
- return __awaiter(this, void 0, void 0, function* () {
529
- const { data } = yield this.axios({
530
- method: "GET",
531
- url: `/collections/${this.options.name}/documents/export`,
532
- params: { include_fields: "id" },
533
- });
534
- return data
535
- .split("\n")
536
- .filter((line) => line.length)
537
- .map((line) => JSON.parse(line).id);
484
+ async exportIds() {
485
+ const { data } = await this.axios({
486
+ method: "GET",
487
+ url: `/collections/${this.options.name}/documents/export`,
488
+ params: { include_fields: "id" },
538
489
  });
490
+ return data
491
+ .split("\n")
492
+ .filter((line) => line.length)
493
+ .map((line) => JSON.parse(line).id);
539
494
  }
540
495
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tsense",
3
- "version": "0.0.17",
3
+ "version": "0.1.0",
4
4
  "private": false,
5
5
  "description": "Opinionated, fully typed typesense client",
6
6
  "keywords": [
@@ -38,15 +38,14 @@
38
38
  },
39
39
  "devDependencies": {
40
40
  "@arethetypeswrong/cli": "^0.18.2",
41
- "@biomejs/biome": "2.1.4",
42
- "@changesets/cli": "^2.29.7",
41
+ "@changesets/cli": "^2.30.0",
43
42
  "@types/bun": "latest",
44
- "arktype": "^2.1.29",
45
- "oxfmt": "^0.28.0",
46
- "oxlint": "^1.43.0"
43
+ "@typescript/native-preview": "^7.0.0-dev.20260324.1",
44
+ "arktype": "^2.2.0",
45
+ "oxfmt": "^0.42.0",
46
+ "oxlint": "^1.57.0"
47
47
  },
48
48
  "peerDependencies": {
49
- "arktype": "^2.1.29",
50
- "typescript": "^5"
49
+ "arktype": "^2.1.29"
51
50
  }
52
51
  }