tsense 0.0.7 → 0.0.8
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/README.md +1 -40
- package/dist/index.d.ts +4 -1
- package/dist/index.js +2 -0
- package/dist/migrator.d.ts +17 -0
- package/dist/migrator.js +141 -0
- package/dist/transformers/date.d.ts +2 -0
- package/dist/transformers/date.js +6 -0
- package/dist/transformers/defaults.d.ts +2 -0
- package/dist/transformers/defaults.js +2 -0
- package/dist/transformers/types.d.ts +7 -0
- package/dist/transformers/types.js +1 -0
- package/dist/tsense.d.ts +68 -4
- package/dist/tsense.js +152 -52
- package/dist/types.d.ts +23 -4
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -74,29 +74,6 @@ await UsersCollection.drop();
|
|
|
74
74
|
|
|
75
75
|
## API Reference
|
|
76
76
|
|
|
77
|
-
### Constructor
|
|
78
|
-
|
|
79
|
-
```typescript
|
|
80
|
-
new TSense({
|
|
81
|
-
name: string,
|
|
82
|
-
schema: Type,
|
|
83
|
-
connection: ConnectionConfig,
|
|
84
|
-
defaultSearchField?: keyof T,
|
|
85
|
-
defaultSortingField?: keyof T,
|
|
86
|
-
batchSize?: number,
|
|
87
|
-
validateOnUpsert?: boolean,
|
|
88
|
-
})
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
### ConnectionConfig
|
|
92
|
-
|
|
93
|
-
| Option | Type | Description |
|
|
94
|
-
| ---------- | --------------------- | --------------------- |
|
|
95
|
-
| `host` | `string` | Typesense server host |
|
|
96
|
-
| `port` | `number` | Typesense server port |
|
|
97
|
-
| `protocol` | `"http"` \| `"https"` | Connection protocol |
|
|
98
|
-
| `apiKey` | `string` | Typesense API key |
|
|
99
|
-
|
|
100
77
|
### Schema Configuration
|
|
101
78
|
|
|
102
79
|
Use `.configure()` to set Typesense field options:
|
|
@@ -124,22 +101,6 @@ type("string").configure({
|
|
|
124
101
|
| `upsert(docs)` | Inserts or updates documents |
|
|
125
102
|
| `search(options)` | Searches the collection |
|
|
126
103
|
|
|
127
|
-
### Search Options
|
|
128
|
-
|
|
129
|
-
| Option | Type | Description |
|
|
130
|
-
| ----------- | --------------------------------- | ------------------------ |
|
|
131
|
-
| `query` | `string` | Text search query |
|
|
132
|
-
| `queryBy` | `(keyof T)[]` | Fields to search in |
|
|
133
|
-
| `filter` | `FilterFor<T>` | Filter conditions |
|
|
134
|
-
| `sortBy` | `"field:asc\|desc"[]` | Sort order |
|
|
135
|
-
| `facetBy` | `(keyof T)[]` | Fields to facet by |
|
|
136
|
-
| `page` | `number` | Page number |
|
|
137
|
-
| `limit` | `number` | Results per page |
|
|
138
|
-
| `pick` | `(keyof T)[]` | Only return these fields |
|
|
139
|
-
| `omit` | `(keyof T)[]` | Exclude these fields |
|
|
140
|
-
| `highlight` | `boolean \| HighlightOptions<T>` | Enable highlighting |
|
|
141
|
-
|
|
142
|
-
Note: `pick` and `omit` are mutually exclusive.
|
|
143
104
|
|
|
144
105
|
### Filter Syntax
|
|
145
106
|
|
|
@@ -150,4 +111,4 @@ filter: { age: [25, 30, 35] } // IN
|
|
|
150
111
|
filter: { age: { min: 20, max: 40 } } // Range
|
|
151
112
|
filter: { name: { not: "John" } } // Not equal
|
|
152
113
|
filter: { OR: [{ age: 25 }, { age: 30 }] } // OR conditions
|
|
153
|
-
```
|
|
114
|
+
```
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
1
|
export type { TsenseFieldMeta, TsenseFieldType } from "./env.js";
|
|
2
2
|
export { TSense } from "./tsense.js";
|
|
3
|
-
export
|
|
3
|
+
export { defaultTransformers } from "./transformers/defaults.js";
|
|
4
|
+
export { DateTransformer } from "./transformers/date.js";
|
|
5
|
+
export type { FieldTransformer } from "./transformers/types.js";
|
|
6
|
+
export type { ConnectionConfig, DeleteResult, FilterFor, HighlightOptions, SearchListOptions, SearchListResult, SearchOptions, SearchResult, TsenseOptions, UpdateResult, UpsertResult, } from "./types.js";
|
package/dist/index.js
CHANGED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { AxiosInstance } from "./tsense.js";
|
|
2
|
+
import type { FieldSchema } from "./types.js";
|
|
3
|
+
export declare class TSenseMigrator {
|
|
4
|
+
private collectionName;
|
|
5
|
+
private localFields;
|
|
6
|
+
private defaultSortingField;
|
|
7
|
+
private axios;
|
|
8
|
+
constructor(collectionName: string, localFields: FieldSchema[], defaultSortingField: string | undefined, axios: AxiosInstance);
|
|
9
|
+
sync(): Promise<void>;
|
|
10
|
+
private exists;
|
|
11
|
+
private getRemoteFields;
|
|
12
|
+
private diff;
|
|
13
|
+
private fieldsMatch;
|
|
14
|
+
private patch;
|
|
15
|
+
private create;
|
|
16
|
+
private drop;
|
|
17
|
+
}
|
package/dist/migrator.js
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
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
|
+
const COMPARABLE_KEYS = ["type", "facet", "sort", "index", "optional"];
|
|
11
|
+
const NESTED_TYPES = ["object", "object[]"];
|
|
12
|
+
export class TSenseMigrator {
|
|
13
|
+
constructor(collectionName, localFields, defaultSortingField, axios) {
|
|
14
|
+
this.collectionName = collectionName;
|
|
15
|
+
this.localFields = localFields;
|
|
16
|
+
this.defaultSortingField = defaultSortingField;
|
|
17
|
+
this.axios = axios;
|
|
18
|
+
}
|
|
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
|
+
});
|
|
36
|
+
}
|
|
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
|
+
});
|
|
49
|
+
});
|
|
50
|
+
}
|
|
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;
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
diff(remote) {
|
|
61
|
+
const remoteByName = new Map(remote.map((f) => [f.name, f]));
|
|
62
|
+
const localByName = new Map(this.localFields.map((f) => [f.name, f]));
|
|
63
|
+
const toAdd = [];
|
|
64
|
+
const toRemove = [];
|
|
65
|
+
const toModify = [];
|
|
66
|
+
for (const local of this.localFields) {
|
|
67
|
+
if (local.name === "id")
|
|
68
|
+
continue;
|
|
69
|
+
const remoteField = remoteByName.get(local.name);
|
|
70
|
+
if (!remoteField) {
|
|
71
|
+
toAdd.push(local);
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
if (this.fieldsMatch(local, remoteField))
|
|
75
|
+
continue;
|
|
76
|
+
toModify.push(local);
|
|
77
|
+
}
|
|
78
|
+
for (const remoteField of remote) {
|
|
79
|
+
if (remoteField.name === "id")
|
|
80
|
+
continue;
|
|
81
|
+
if (localByName.has(remoteField.name))
|
|
82
|
+
continue;
|
|
83
|
+
toRemove.push(remoteField);
|
|
84
|
+
}
|
|
85
|
+
return { toAdd, toRemove, toModify };
|
|
86
|
+
}
|
|
87
|
+
fieldsMatch(local, remote) {
|
|
88
|
+
var _a, _b;
|
|
89
|
+
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)) {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
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
|
+
});
|
|
117
|
+
}
|
|
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
|
+
});
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
drop() {
|
|
134
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
135
|
+
yield this.axios({
|
|
136
|
+
method: "DELETE",
|
|
137
|
+
url: `/collections/${this.collectionName}`,
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { TsenseFieldType } from "../env.js";
|
|
2
|
+
export interface FieldTransformer<TJs = unknown, TStorage = unknown> {
|
|
3
|
+
match: (expression: string, domain?: string) => boolean;
|
|
4
|
+
storageType: TsenseFieldType;
|
|
5
|
+
serialize: (value: TJs) => TStorage;
|
|
6
|
+
deserialize: (value: TStorage) => TJs;
|
|
7
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/tsense.d.ts
CHANGED
|
@@ -1,15 +1,77 @@
|
|
|
1
1
|
import type { Type } from "arktype";
|
|
2
|
-
import
|
|
2
|
+
import redaxios from "redaxios";
|
|
3
|
+
import type { DeleteResult, FilterFor, SearchListOptions, SearchListResult, SearchOptions, SearchResult, TsenseOptions, UpdateResult, UpsertResult } from "./types.js";
|
|
4
|
+
declare const redaxiosInstance: {
|
|
5
|
+
<T>(urlOrConfig: string | redaxios.Options, config?: redaxios.Options | undefined, _method?: any, data?: any, _undefined?: undefined): Promise<redaxios.Response<T>>;
|
|
6
|
+
request: (<T_1 = any>(config?: redaxios.Options | undefined) => Promise<redaxios.Response<T_1>>) | (<T_2 = any>(url: string, config?: redaxios.Options | undefined) => Promise<redaxios.Response<T_2>>);
|
|
7
|
+
get<T_3 = any>(url: string, config?: redaxios.Options | undefined): Promise<redaxios.Response<T_3>>;
|
|
8
|
+
delete<T_3 = any>(url: string, config?: redaxios.Options | undefined): Promise<redaxios.Response<T_3>>;
|
|
9
|
+
head<T_3 = any>(url: string, config?: redaxios.Options | undefined): Promise<redaxios.Response<T_3>>;
|
|
10
|
+
options<T_3 = any>(url: string, config?: redaxios.Options | undefined): Promise<redaxios.Response<T_3>>;
|
|
11
|
+
post<T_4 = any>(url: string, body?: any, config?: redaxios.Options | undefined): Promise<redaxios.Response<T_4>>;
|
|
12
|
+
put<T_4 = any>(url: string, body?: any, config?: redaxios.Options | undefined): Promise<redaxios.Response<T_4>>;
|
|
13
|
+
patch<T_4 = any>(url: string, body?: any, config?: redaxios.Options | undefined): Promise<redaxios.Response<T_4>>;
|
|
14
|
+
all: {
|
|
15
|
+
<T_5>(values: Iterable<T_5 | PromiseLike<T_5>>): Promise<T_5[]>;
|
|
16
|
+
<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(values: readonly [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>, T7 | PromiseLike<T7>, T8 | PromiseLike<T8>, T9 | PromiseLike<T9>, T10 | PromiseLike<T10>]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]>;
|
|
17
|
+
<T1_1, T2_1, T3_1, T4_1, T5_1, T6_1, T7_1, T8_1, T9_1>(values: readonly [T1_1 | PromiseLike<T1_1>, T2_1 | PromiseLike<T2_1>, T3_1 | PromiseLike<T3_1>, T4_1 | PromiseLike<T4_1>, T5_1 | PromiseLike<T5_1>, T6_1 | PromiseLike<T6_1>, T7_1 | PromiseLike<T7_1>, T8_1 | PromiseLike<T8_1>, T9_1 | PromiseLike<T9_1>]): Promise<[T1_1, T2_1, T3_1, T4_1, T5_1, T6_1, T7_1, T8_1, T9_1]>;
|
|
18
|
+
<T1_2, T2_2, T3_2, T4_2, T5_2, T6_2, T7_2, T8_2>(values: readonly [T1_2 | PromiseLike<T1_2>, T2_2 | PromiseLike<T2_2>, T3_2 | PromiseLike<T3_2>, T4_2 | PromiseLike<T4_2>, T5_2 | PromiseLike<T5_2>, T6_2 | PromiseLike<T6_2>, T7_2 | PromiseLike<T7_2>, T8_2 | PromiseLike<T8_2>]): Promise<[T1_2, T2_2, T3_2, T4_2, T5_2, T6_2, T7_2, T8_2]>;
|
|
19
|
+
<T1_3, T2_3, T3_3, T4_3, T5_3, T6_3, T7_3>(values: readonly [T1_3 | PromiseLike<T1_3>, T2_3 | PromiseLike<T2_3>, T3_3 | PromiseLike<T3_3>, T4_3 | PromiseLike<T4_3>, T5_3 | PromiseLike<T5_3>, T6_3 | PromiseLike<T6_3>, T7_3 | PromiseLike<T7_3>]): Promise<[T1_3, T2_3, T3_3, T4_3, T5_3, T6_3, T7_3]>;
|
|
20
|
+
<T1_4, T2_4, T3_4, T4_4, T5_4, T6_4>(values: readonly [T1_4 | PromiseLike<T1_4>, T2_4 | PromiseLike<T2_4>, T3_4 | PromiseLike<T3_4>, T4_4 | PromiseLike<T4_4>, T5_4 | PromiseLike<T5_4>, T6_4 | PromiseLike<T6_4>]): Promise<[T1_4, T2_4, T3_4, T4_4, T5_4, T6_4]>;
|
|
21
|
+
<T1_5, T2_5, T3_5, T4_5, T5_5>(values: readonly [T1_5 | PromiseLike<T1_5>, T2_5 | PromiseLike<T2_5>, T3_5 | PromiseLike<T3_5>, T4_5 | PromiseLike<T4_5>, T5_5 | PromiseLike<T5_5>]): Promise<[T1_5, T2_5, T3_5, T4_5, T5_5]>;
|
|
22
|
+
<T1_6, T2_6, T3_6, T4_6>(values: readonly [T1_6 | PromiseLike<T1_6>, T2_6 | PromiseLike<T2_6>, T3_6 | PromiseLike<T3_6>, T4_6 | PromiseLike<T4_6>]): Promise<[T1_6, T2_6, T3_6, T4_6]>;
|
|
23
|
+
<T1_7, T2_7, T3_7>(values: readonly [T1_7 | PromiseLike<T1_7>, T2_7 | PromiseLike<T2_7>, T3_7 | PromiseLike<T3_7>]): Promise<[T1_7, T2_7, T3_7]>;
|
|
24
|
+
<T1_8, T2_8>(values: readonly [T1_8 | PromiseLike<T1_8>, T2_8 | PromiseLike<T2_8>]): Promise<[T1_8, T2_8]>;
|
|
25
|
+
<T_6>(values: readonly (T_6 | PromiseLike<T_6>)[]): Promise<T_6[]>;
|
|
26
|
+
};
|
|
27
|
+
spread<Args, R>(fn: (...args: Args[]) => R): (array: Args[]) => R;
|
|
28
|
+
CancelToken: AbortController;
|
|
29
|
+
defaults: redaxios.Options;
|
|
30
|
+
create: (defaults?: redaxios.Options | undefined) => {
|
|
31
|
+
<T>(urlOrConfig: string | redaxios.Options, config?: redaxios.Options | undefined, _method?: any, data?: any, _undefined?: undefined): Promise<redaxios.Response<T>>;
|
|
32
|
+
request: (<T_1 = any>(config?: redaxios.Options | undefined) => Promise<redaxios.Response<T_1>>) | (<T_2 = any>(url: string, config?: redaxios.Options | undefined) => Promise<redaxios.Response<T_2>>);
|
|
33
|
+
get<T_3 = any>(url: string, config?: redaxios.Options | undefined): Promise<redaxios.Response<T_3>>;
|
|
34
|
+
delete<T_3 = any>(url: string, config?: redaxios.Options | undefined): Promise<redaxios.Response<T_3>>;
|
|
35
|
+
head<T_3 = any>(url: string, config?: redaxios.Options | undefined): Promise<redaxios.Response<T_3>>;
|
|
36
|
+
options<T_3 = any>(url: string, config?: redaxios.Options | undefined): Promise<redaxios.Response<T_3>>;
|
|
37
|
+
post<T_4 = any>(url: string, body?: any, config?: redaxios.Options | undefined): Promise<redaxios.Response<T_4>>;
|
|
38
|
+
put<T_4 = any>(url: string, body?: any, config?: redaxios.Options | undefined): Promise<redaxios.Response<T_4>>;
|
|
39
|
+
patch<T_4 = any>(url: string, body?: any, config?: redaxios.Options | undefined): Promise<redaxios.Response<T_4>>;
|
|
40
|
+
all: {
|
|
41
|
+
<T_5>(values: Iterable<T_5 | PromiseLike<T_5>>): Promise<T_5[]>;
|
|
42
|
+
<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(values: readonly [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>, T7 | PromiseLike<T7>, T8 | PromiseLike<T8>, T9 | PromiseLike<T9>, T10 | PromiseLike<T10>]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]>;
|
|
43
|
+
<T1_1, T2_1, T3_1, T4_1, T5_1, T6_1, T7_1, T8_1, T9_1>(values: readonly [T1_1 | PromiseLike<T1_1>, T2_1 | PromiseLike<T2_1>, T3_1 | PromiseLike<T3_1>, T4_1 | PromiseLike<T4_1>, T5_1 | PromiseLike<T5_1>, T6_1 | PromiseLike<T6_1>, T7_1 | PromiseLike<T7_1>, T8_1 | PromiseLike<T8_1>, T9_1 | PromiseLike<T9_1>]): Promise<[T1_1, T2_1, T3_1, T4_1, T5_1, T6_1, T7_1, T8_1, T9_1]>;
|
|
44
|
+
<T1_2, T2_2, T3_2, T4_2, T5_2, T6_2, T7_2, T8_2>(values: readonly [T1_2 | PromiseLike<T1_2>, T2_2 | PromiseLike<T2_2>, T3_2 | PromiseLike<T3_2>, T4_2 | PromiseLike<T4_2>, T5_2 | PromiseLike<T5_2>, T6_2 | PromiseLike<T6_2>, T7_2 | PromiseLike<T7_2>, T8_2 | PromiseLike<T8_2>]): Promise<[T1_2, T2_2, T3_2, T4_2, T5_2, T6_2, T7_2, T8_2]>;
|
|
45
|
+
<T1_3, T2_3, T3_3, T4_3, T5_3, T6_3, T7_3>(values: readonly [T1_3 | PromiseLike<T1_3>, T2_3 | PromiseLike<T2_3>, T3_3 | PromiseLike<T3_3>, T4_3 | PromiseLike<T4_3>, T5_3 | PromiseLike<T5_3>, T6_3 | PromiseLike<T6_3>, T7_3 | PromiseLike<T7_3>]): Promise<[T1_3, T2_3, T3_3, T4_3, T5_3, T6_3, T7_3]>;
|
|
46
|
+
<T1_4, T2_4, T3_4, T4_4, T5_4, T6_4>(values: readonly [T1_4 | PromiseLike<T1_4>, T2_4 | PromiseLike<T2_4>, T3_4 | PromiseLike<T3_4>, T4_4 | PromiseLike<T4_4>, T5_4 | PromiseLike<T5_4>, T6_4 | PromiseLike<T6_4>]): Promise<[T1_4, T2_4, T3_4, T4_4, T5_4, T6_4]>;
|
|
47
|
+
<T1_5, T2_5, T3_5, T4_5, T5_5>(values: readonly [T1_5 | PromiseLike<T1_5>, T2_5 | PromiseLike<T2_5>, T3_5 | PromiseLike<T3_5>, T4_5 | PromiseLike<T4_5>, T5_5 | PromiseLike<T5_5>]): Promise<[T1_5, T2_5, T3_5, T4_5, T5_5]>;
|
|
48
|
+
<T1_6, T2_6, T3_6, T4_6>(values: readonly [T1_6 | PromiseLike<T1_6>, T2_6 | PromiseLike<T2_6>, T3_6 | PromiseLike<T3_6>, T4_6 | PromiseLike<T4_6>]): Promise<[T1_6, T2_6, T3_6, T4_6]>;
|
|
49
|
+
<T1_7, T2_7, T3_7>(values: readonly [T1_7 | PromiseLike<T1_7>, T2_7 | PromiseLike<T2_7>, T3_7 | PromiseLike<T3_7>]): Promise<[T1_7, T2_7, T3_7]>;
|
|
50
|
+
<T1_8, T2_8>(values: readonly [T1_8 | PromiseLike<T1_8>, T2_8 | PromiseLike<T2_8>]): Promise<[T1_8, T2_8]>;
|
|
51
|
+
<T_6>(values: readonly (T_6 | PromiseLike<T_6>)[]): Promise<T_6[]>;
|
|
52
|
+
};
|
|
53
|
+
spread<Args, R>(fn: (...args: Args[]) => R): (array: Args[]) => R;
|
|
54
|
+
CancelToken: AbortController;
|
|
55
|
+
defaults: redaxios.Options;
|
|
56
|
+
create: any;
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
export type AxiosInstance = ReturnType<typeof redaxiosInstance.create>;
|
|
3
60
|
export declare class TSense<T extends Type> {
|
|
4
61
|
private options;
|
|
5
62
|
private fields;
|
|
6
|
-
private
|
|
7
|
-
private
|
|
8
|
-
private
|
|
63
|
+
private axios;
|
|
64
|
+
private synced;
|
|
65
|
+
private fieldTransformers;
|
|
9
66
|
infer: T["infer"];
|
|
10
67
|
constructor(options: TsenseOptions<T>);
|
|
11
68
|
private inferType;
|
|
69
|
+
private serializeDoc;
|
|
70
|
+
private deserializeDoc;
|
|
71
|
+
private serializeFilterValue;
|
|
12
72
|
private extractFields;
|
|
73
|
+
private ensureSynced;
|
|
74
|
+
sync(): Promise<void>;
|
|
13
75
|
private buildObjectFilter;
|
|
14
76
|
private buildFilter;
|
|
15
77
|
private buildSort;
|
|
@@ -21,5 +83,7 @@ export declare class TSense<T extends Type> {
|
|
|
21
83
|
update(id: string, data: Partial<T["infer"]>): Promise<T["infer"]>;
|
|
22
84
|
updateMany(filter: FilterFor<T["infer"]>, data: Partial<T["infer"]>): Promise<UpdateResult>;
|
|
23
85
|
search(options: SearchOptions<T["infer"]>): Promise<SearchResult<T["infer"]>>;
|
|
86
|
+
searchList(options: SearchListOptions<T["infer"]>): Promise<SearchListResult<T["infer"]>>;
|
|
24
87
|
upsert(docs: T["infer"] | T["infer"][]): Promise<UpsertResult[]>;
|
|
25
88
|
}
|
|
89
|
+
export {};
|
package/dist/tsense.js
CHANGED
|
@@ -9,8 +9,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
};
|
|
10
10
|
var _a;
|
|
11
11
|
import redaxios from "redaxios";
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
import { TSenseMigrator } from "./migrator.js";
|
|
13
|
+
import { defaultTransformers } from "./transformers/defaults.js";
|
|
14
|
+
const redaxiosInstance = (_a = redaxios.default) !== null && _a !== void 0 ? _a : redaxios;
|
|
14
15
|
const arkToTsense = {
|
|
15
16
|
string: "string",
|
|
16
17
|
number: "float",
|
|
@@ -22,14 +23,17 @@ const arkToTsense = {
|
|
|
22
23
|
};
|
|
23
24
|
export class TSense {
|
|
24
25
|
constructor(options) {
|
|
26
|
+
var _a;
|
|
25
27
|
this.options = options;
|
|
26
28
|
this.fields = [];
|
|
27
|
-
this.
|
|
29
|
+
this.synced = false;
|
|
30
|
+
this.fieldTransformers = new Map();
|
|
28
31
|
this.infer = undefined;
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
32
|
+
this.axios = redaxiosInstance.create({
|
|
33
|
+
baseURL: `${options.connection.protocol}://${options.connection.host}:${options.connection.port}`,
|
|
34
|
+
headers: { "X-TYPESENSE-API-KEY": options.connection.apiKey },
|
|
35
|
+
});
|
|
36
|
+
this.extractFields((_a = options.transformers) !== null && _a !== void 0 ? _a : defaultTransformers);
|
|
33
37
|
}
|
|
34
38
|
inferType(arkType) {
|
|
35
39
|
const direct = arkToTsense[arkType];
|
|
@@ -43,20 +47,71 @@ export class TSense {
|
|
|
43
47
|
return "string";
|
|
44
48
|
return "string";
|
|
45
49
|
}
|
|
46
|
-
|
|
50
|
+
serializeDoc(doc) {
|
|
51
|
+
const result = Object.assign({}, doc);
|
|
52
|
+
for (const [field, transformer] of this.fieldTransformers) {
|
|
53
|
+
if (result[field] != null) {
|
|
54
|
+
result[field] = transformer.serialize(result[field]);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return result;
|
|
58
|
+
}
|
|
59
|
+
deserializeDoc(doc) {
|
|
60
|
+
for (const [field, transformer] of this.fieldTransformers) {
|
|
61
|
+
if (doc[field] != null) {
|
|
62
|
+
doc[field] = transformer.deserialize(doc[field]);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return doc;
|
|
66
|
+
}
|
|
67
|
+
serializeFilterValue(key, value) {
|
|
68
|
+
const transformer = this.fieldTransformers.get(key);
|
|
69
|
+
if (!transformer)
|
|
70
|
+
return value;
|
|
71
|
+
if (Array.isArray(value)) {
|
|
72
|
+
return value.map((v) => transformer.serialize(v));
|
|
73
|
+
}
|
|
74
|
+
if (typeof value === "object" && value !== null) {
|
|
75
|
+
const v = value;
|
|
76
|
+
const isFilterObject = "min" in v || "max" in v || "not" in v;
|
|
77
|
+
if (!isFilterObject) {
|
|
78
|
+
return transformer.serialize(value);
|
|
79
|
+
}
|
|
80
|
+
const result = Object.assign({}, v);
|
|
81
|
+
if ("min" in v && v.min != null)
|
|
82
|
+
result.min = transformer.serialize(v.min);
|
|
83
|
+
if ("max" in v && v.max != null)
|
|
84
|
+
result.max = transformer.serialize(v.max);
|
|
85
|
+
if ("not" in v && v.not != null)
|
|
86
|
+
result.not = transformer.serialize(v.not);
|
|
87
|
+
return result;
|
|
88
|
+
}
|
|
89
|
+
return transformer.serialize(value);
|
|
90
|
+
}
|
|
91
|
+
extractFields(transformers) {
|
|
47
92
|
var _a;
|
|
48
93
|
const internal = this.options.schema;
|
|
49
94
|
for (const prop of internal.structure.props) {
|
|
50
95
|
const meta = prop.value.meta;
|
|
51
96
|
const expression = String(prop.value.expression);
|
|
52
97
|
const domain = prop.value.domain;
|
|
53
|
-
const
|
|
54
|
-
if (
|
|
55
|
-
this.
|
|
98
|
+
const transformer = transformers.find((t) => t.match(expression, domain));
|
|
99
|
+
if (transformer) {
|
|
100
|
+
this.fieldTransformers.set(prop.key, transformer);
|
|
101
|
+
this.fields.push({
|
|
102
|
+
name: prop.key,
|
|
103
|
+
type: transformer.storageType,
|
|
104
|
+
optional: prop.kind === "optional",
|
|
105
|
+
facet: meta === null || meta === void 0 ? void 0 : meta.facet,
|
|
106
|
+
sort: meta === null || meta === void 0 ? void 0 : meta.sort,
|
|
107
|
+
index: meta === null || meta === void 0 ? void 0 : meta.index,
|
|
108
|
+
});
|
|
109
|
+
continue;
|
|
56
110
|
}
|
|
111
|
+
const type = (_a = meta === null || meta === void 0 ? void 0 : meta.type) !== null && _a !== void 0 ? _a : this.inferType(domain !== null && domain !== void 0 ? domain : expression);
|
|
57
112
|
this.fields.push({
|
|
58
113
|
name: prop.key,
|
|
59
|
-
type
|
|
114
|
+
type,
|
|
60
115
|
optional: prop.kind === "optional",
|
|
61
116
|
facet: meta === null || meta === void 0 ? void 0 : meta.facet,
|
|
62
117
|
sort: meta === null || meta === void 0 ? void 0 : meta.sort,
|
|
@@ -64,6 +119,19 @@ export class TSense {
|
|
|
64
119
|
});
|
|
65
120
|
}
|
|
66
121
|
}
|
|
122
|
+
ensureSynced(force) {
|
|
123
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
124
|
+
if (!force && (this.synced || !this.options.autoSync))
|
|
125
|
+
return;
|
|
126
|
+
yield new TSenseMigrator(this.options.name, this.fields, this.options.defaultSortingField, this.axios).sync();
|
|
127
|
+
this.synced = true;
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
sync() {
|
|
131
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
132
|
+
yield this.ensureSynced(true);
|
|
133
|
+
});
|
|
134
|
+
}
|
|
67
135
|
buildObjectFilter(key, value) {
|
|
68
136
|
var _a, _b;
|
|
69
137
|
if (Array.isArray(value)) {
|
|
@@ -88,18 +156,19 @@ export class TSense {
|
|
|
88
156
|
buildFilter(filter) {
|
|
89
157
|
const result = [];
|
|
90
158
|
for (const entry of Object.entries(filter !== null && filter !== void 0 ? filter : {})) {
|
|
91
|
-
const [key,
|
|
92
|
-
if (
|
|
159
|
+
const [key, rawValue] = entry;
|
|
160
|
+
if (rawValue == null)
|
|
93
161
|
continue;
|
|
94
162
|
if (key === "OR") {
|
|
95
163
|
const orFilter = [];
|
|
96
|
-
for (const condition of
|
|
164
|
+
for (const condition of rawValue) {
|
|
97
165
|
const inner = this.buildFilter(condition);
|
|
98
166
|
orFilter.push(`(${inner.join("||")})`);
|
|
99
167
|
}
|
|
100
168
|
result.push(`(${orFilter.join("||")})`);
|
|
101
169
|
continue;
|
|
102
170
|
}
|
|
171
|
+
const value = this.serializeFilterValue(key, rawValue);
|
|
103
172
|
switch (typeof value) {
|
|
104
173
|
case "string":
|
|
105
174
|
case "number":
|
|
@@ -133,16 +202,15 @@ export class TSense {
|
|
|
133
202
|
}
|
|
134
203
|
create() {
|
|
135
204
|
return __awaiter(this, void 0, void 0, function* () {
|
|
136
|
-
|
|
205
|
+
const enableNested = this.fields.some((f) => f.type === "object" || f.type === "object[]");
|
|
206
|
+
yield this.axios({
|
|
137
207
|
method: "POST",
|
|
138
|
-
baseURL: this.baseURL,
|
|
139
208
|
url: "/collections",
|
|
140
|
-
headers: this.headers,
|
|
141
209
|
data: {
|
|
142
210
|
name: this.options.name,
|
|
143
211
|
fields: this.fields,
|
|
144
212
|
default_sorting_field: this.options.defaultSortingField,
|
|
145
|
-
enable_nested_fields:
|
|
213
|
+
enable_nested_fields: enableNested,
|
|
146
214
|
},
|
|
147
215
|
});
|
|
148
216
|
return this;
|
|
@@ -150,36 +218,32 @@ export class TSense {
|
|
|
150
218
|
}
|
|
151
219
|
drop() {
|
|
152
220
|
return __awaiter(this, void 0, void 0, function* () {
|
|
153
|
-
yield axios({
|
|
221
|
+
yield this.axios({
|
|
154
222
|
method: "DELETE",
|
|
155
|
-
baseURL: this.baseURL,
|
|
156
223
|
url: `/collections/${this.options.name}`,
|
|
157
|
-
headers: this.headers,
|
|
158
224
|
});
|
|
159
225
|
});
|
|
160
226
|
}
|
|
161
227
|
get(id) {
|
|
162
228
|
return __awaiter(this, void 0, void 0, function* () {
|
|
163
|
-
|
|
229
|
+
yield this.ensureSynced();
|
|
230
|
+
const { data } = yield this.axios({
|
|
164
231
|
method: "GET",
|
|
165
|
-
baseURL: this.baseURL,
|
|
166
232
|
url: `/collections/${this.options.name}/documents/${id}`,
|
|
167
|
-
headers: this.headers,
|
|
168
233
|
}).catch((e) => {
|
|
169
234
|
if (e.status === 404)
|
|
170
235
|
return { data: null };
|
|
171
236
|
throw e;
|
|
172
237
|
});
|
|
173
|
-
return data;
|
|
238
|
+
return data ? this.deserializeDoc(data) : null;
|
|
174
239
|
});
|
|
175
240
|
}
|
|
176
241
|
delete(id) {
|
|
177
242
|
return __awaiter(this, void 0, void 0, function* () {
|
|
178
|
-
|
|
243
|
+
yield this.ensureSynced();
|
|
244
|
+
const { data } = yield this.axios({
|
|
179
245
|
method: "DELETE",
|
|
180
|
-
baseURL: this.baseURL,
|
|
181
246
|
url: `/collections/${this.options.name}/documents/${id}`,
|
|
182
|
-
headers: this.headers,
|
|
183
247
|
}).catch((e) => {
|
|
184
248
|
if (e.status === 404)
|
|
185
249
|
return { data: null };
|
|
@@ -190,15 +254,14 @@ export class TSense {
|
|
|
190
254
|
}
|
|
191
255
|
deleteMany(filter) {
|
|
192
256
|
return __awaiter(this, void 0, void 0, function* () {
|
|
257
|
+
yield this.ensureSynced();
|
|
193
258
|
const filterBy = this.buildFilter(filter).join("&&");
|
|
194
259
|
if (!filterBy) {
|
|
195
260
|
throw new Error("FILTER_REQUIRED");
|
|
196
261
|
}
|
|
197
|
-
const { data } = yield axios({
|
|
262
|
+
const { data } = yield this.axios({
|
|
198
263
|
method: "DELETE",
|
|
199
|
-
baseURL: this.baseURL,
|
|
200
264
|
url: `/collections/${this.options.name}/documents`,
|
|
201
|
-
headers: this.headers,
|
|
202
265
|
params: { filter_by: filterBy },
|
|
203
266
|
});
|
|
204
267
|
return { deleted: data.num_deleted };
|
|
@@ -206,29 +269,29 @@ export class TSense {
|
|
|
206
269
|
}
|
|
207
270
|
update(id, data) {
|
|
208
271
|
return __awaiter(this, void 0, void 0, function* () {
|
|
209
|
-
|
|
272
|
+
yield this.ensureSynced();
|
|
273
|
+
const serialized = this.serializeDoc(data);
|
|
274
|
+
const { data: updated } = yield this.axios({
|
|
210
275
|
method: "PATCH",
|
|
211
|
-
baseURL: this.baseURL,
|
|
212
276
|
url: `/collections/${this.options.name}/documents/${id}`,
|
|
213
|
-
|
|
214
|
-
data,
|
|
277
|
+
data: serialized,
|
|
215
278
|
});
|
|
216
|
-
return updated;
|
|
279
|
+
return this.deserializeDoc(updated);
|
|
217
280
|
});
|
|
218
281
|
}
|
|
219
282
|
updateMany(filter, data) {
|
|
220
283
|
return __awaiter(this, void 0, void 0, function* () {
|
|
284
|
+
yield this.ensureSynced();
|
|
221
285
|
const filterBy = this.buildFilter(filter).join("&&");
|
|
222
286
|
if (!filterBy) {
|
|
223
287
|
throw new Error("FILTER_REQUIRED");
|
|
224
288
|
}
|
|
225
|
-
const
|
|
289
|
+
const serialized = this.serializeDoc(data);
|
|
290
|
+
const { data: result } = yield this.axios({
|
|
226
291
|
method: "PATCH",
|
|
227
|
-
baseURL: this.baseURL,
|
|
228
292
|
url: `/collections/${this.options.name}/documents`,
|
|
229
|
-
headers: this.headers,
|
|
230
293
|
params: { filter_by: filterBy },
|
|
231
|
-
data,
|
|
294
|
+
data: serialized,
|
|
232
295
|
});
|
|
233
296
|
return { updated: result.num_updated };
|
|
234
297
|
});
|
|
@@ -236,11 +299,10 @@ export class TSense {
|
|
|
236
299
|
search(options) {
|
|
237
300
|
return __awaiter(this, void 0, void 0, function* () {
|
|
238
301
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
302
|
+
yield this.ensureSynced();
|
|
239
303
|
const params = {
|
|
240
304
|
q: (_a = options.query) !== null && _a !== void 0 ? _a : "",
|
|
241
|
-
query_by: ((_b = options.queryBy) !== null && _b !== void 0 ? _b : [
|
|
242
|
-
this.options.defaultSearchField,
|
|
243
|
-
]).join(","),
|
|
305
|
+
query_by: ((_b = options.queryBy) !== null && _b !== void 0 ? _b : [this.options.defaultSearchField]).join(","),
|
|
244
306
|
};
|
|
245
307
|
const sortBy = this.buildSort(options);
|
|
246
308
|
if (sortBy)
|
|
@@ -276,11 +338,9 @@ export class TSense {
|
|
|
276
338
|
params.highlight_end_tag = highlightOpts.endTag;
|
|
277
339
|
}
|
|
278
340
|
}
|
|
279
|
-
const { data: res } = yield axios({
|
|
341
|
+
const { data: res } = yield this.axios({
|
|
280
342
|
method: "GET",
|
|
281
|
-
baseURL: this.baseURL,
|
|
282
343
|
url: `/collections/${this.options.name}/documents/search`,
|
|
283
|
-
headers: this.headers,
|
|
284
344
|
params,
|
|
285
345
|
});
|
|
286
346
|
const data = [];
|
|
@@ -296,7 +356,8 @@ export class TSense {
|
|
|
296
356
|
hit.document[key] = value.snippet;
|
|
297
357
|
}
|
|
298
358
|
}
|
|
299
|
-
|
|
359
|
+
const doc = this.deserializeDoc(hit.document);
|
|
360
|
+
data.push(doc);
|
|
300
361
|
scores.push((_f = hit.text_match) !== null && _f !== void 0 ? _f : 0);
|
|
301
362
|
}
|
|
302
363
|
const facets = {};
|
|
@@ -315,8 +376,48 @@ export class TSense {
|
|
|
315
376
|
};
|
|
316
377
|
});
|
|
317
378
|
}
|
|
379
|
+
searchList(options) {
|
|
380
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
381
|
+
var _a, _b, _c, _d;
|
|
382
|
+
yield this.ensureSynced();
|
|
383
|
+
const limit = Math.min((_a = options.limit) !== null && _a !== void 0 ? _a : 20, 100);
|
|
384
|
+
const field = options.sort.field;
|
|
385
|
+
const params = {
|
|
386
|
+
q: (_b = options.query) !== null && _b !== void 0 ? _b : "",
|
|
387
|
+
query_by: ((_c = options.queryBy) !== null && _c !== void 0 ? _c : [this.options.defaultSearchField]).join(","),
|
|
388
|
+
per_page: limit,
|
|
389
|
+
sort_by: `${field}:${options.sort.direction}`,
|
|
390
|
+
};
|
|
391
|
+
const filterParts = this.buildFilter(options.filter);
|
|
392
|
+
if (options.cursor) {
|
|
393
|
+
const op = options.sort.direction === "asc" ? ">" : "<";
|
|
394
|
+
filterParts.push(`${field}:${op}${options.cursor}`);
|
|
395
|
+
}
|
|
396
|
+
const filterBy = filterParts.join("&&");
|
|
397
|
+
if (filterBy)
|
|
398
|
+
params.filter_by = filterBy;
|
|
399
|
+
const { data: res } = yield this.axios({
|
|
400
|
+
method: "GET",
|
|
401
|
+
url: `/collections/${this.options.name}/documents/search`,
|
|
402
|
+
params,
|
|
403
|
+
});
|
|
404
|
+
const hits = (_d = res.hits) !== null && _d !== void 0 ? _d : [];
|
|
405
|
+
const data = [];
|
|
406
|
+
for (const hit of hits) {
|
|
407
|
+
const doc = this.deserializeDoc(hit.document);
|
|
408
|
+
data.push(doc);
|
|
409
|
+
}
|
|
410
|
+
if (data.length < limit) {
|
|
411
|
+
return { data, nextCursor: null };
|
|
412
|
+
}
|
|
413
|
+
const lastHit = hits[hits.length - 1].document;
|
|
414
|
+
const nextCursor = String(lastHit[field]);
|
|
415
|
+
return { data, nextCursor };
|
|
416
|
+
});
|
|
417
|
+
}
|
|
318
418
|
upsert(docs) {
|
|
319
419
|
return __awaiter(this, void 0, void 0, function* () {
|
|
420
|
+
yield this.ensureSynced();
|
|
320
421
|
const items = Array.isArray(docs) ? docs : [docs];
|
|
321
422
|
if (!items.length)
|
|
322
423
|
return [];
|
|
@@ -325,16 +426,15 @@ export class TSense {
|
|
|
325
426
|
this.options.schema.assert(item);
|
|
326
427
|
}
|
|
327
428
|
}
|
|
328
|
-
const payload = items.map((item) => JSON.stringify(item)).join("\n");
|
|
429
|
+
const payload = items.map((item) => JSON.stringify(this.serializeDoc(item))).join("\n");
|
|
329
430
|
const params = { action: "upsert" };
|
|
330
431
|
if (this.options.batchSize) {
|
|
331
432
|
params.batch_size = this.options.batchSize;
|
|
332
433
|
}
|
|
333
|
-
const { data } = yield axios({
|
|
434
|
+
const { data } = yield this.axios({
|
|
334
435
|
method: "POST",
|
|
335
|
-
baseURL: this.baseURL,
|
|
336
436
|
url: `/collections/${this.options.name}/documents/import`,
|
|
337
|
-
headers:
|
|
437
|
+
headers: { "Content-Type": "text/plain" },
|
|
338
438
|
params,
|
|
339
439
|
data: payload,
|
|
340
440
|
});
|
package/dist/types.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Type } from "arktype";
|
|
2
|
+
import type { FieldTransformer } from "./transformers/types.js";
|
|
2
3
|
type BaseIfArray<T> = T extends (infer Q)[] ? Q : T;
|
|
3
4
|
export type FieldSchema = {
|
|
4
5
|
name: string;
|
|
@@ -41,14 +42,16 @@ export type TsenseOptions<T extends Type> = {
|
|
|
41
42
|
defaultSortingField?: keyof T["infer"];
|
|
42
43
|
batchSize?: number;
|
|
43
44
|
validateOnUpsert?: boolean;
|
|
45
|
+
autoSync?: boolean;
|
|
46
|
+
transformers?: FieldTransformer[];
|
|
44
47
|
};
|
|
45
48
|
type SingleFilter<T> = Partial<{
|
|
46
49
|
[K in keyof T]: BaseIfArray<T[K]> | NonNullable<BaseIfArray<T[K]>>[] | {
|
|
47
50
|
not?: BaseIfArray<T[K]>;
|
|
48
|
-
} | (NonNullable<T[K]> extends number ? {
|
|
49
|
-
min?:
|
|
50
|
-
max?:
|
|
51
|
-
} : never);
|
|
51
|
+
} | (NonNullable<T[K]> extends number | Date ? NonNullable<T[K]> extends infer Type ? {
|
|
52
|
+
min?: Type;
|
|
53
|
+
max?: Type;
|
|
54
|
+
} : never : never);
|
|
52
55
|
}>;
|
|
53
56
|
export type FilterFor<T> = SingleFilter<T> & {
|
|
54
57
|
OR?: FilterFor<T>[];
|
|
@@ -96,4 +99,20 @@ export type UpsertResult = {
|
|
|
96
99
|
error?: string;
|
|
97
100
|
document?: unknown;
|
|
98
101
|
};
|
|
102
|
+
type SearchListSort<T> = {
|
|
103
|
+
field: keyof T;
|
|
104
|
+
direction: "asc" | "desc";
|
|
105
|
+
};
|
|
106
|
+
export type SearchListOptions<T> = {
|
|
107
|
+
query?: string;
|
|
108
|
+
queryBy?: (keyof T)[];
|
|
109
|
+
filter?: FilterFor<T>;
|
|
110
|
+
sort: SearchListSort<T>;
|
|
111
|
+
limit?: number;
|
|
112
|
+
cursor?: string;
|
|
113
|
+
};
|
|
114
|
+
export type SearchListResult<T> = {
|
|
115
|
+
data: T[];
|
|
116
|
+
nextCursor: string | null;
|
|
117
|
+
};
|
|
99
118
|
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tsense",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.8",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Opinionated, fully typed typesense client",
|
|
6
6
|
"keywords": [
|
|
@@ -41,7 +41,9 @@
|
|
|
41
41
|
"@biomejs/biome": "2.1.4",
|
|
42
42
|
"@changesets/cli": "^2.29.7",
|
|
43
43
|
"@types/bun": "latest",
|
|
44
|
-
"arktype": "^2.1.29"
|
|
44
|
+
"arktype": "^2.1.29",
|
|
45
|
+
"oxfmt": "^0.23.0",
|
|
46
|
+
"oxlint": "^1.38.0"
|
|
45
47
|
},
|
|
46
48
|
"peerDependencies": {
|
|
47
49
|
"arktype": "^2.1.29",
|