mm-share-lib 0.0.4 → 0.0.5
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.js +25 -25
- package/.prettierrc +3 -3
- package/README.md +73 -73
- package/dist/src/exception/bad-request-error.exception.d.ts +4 -0
- package/dist/src/exception/bad-request-error.exception.js +12 -0
- package/dist/src/exception/bad-request-error.exception.js.map +1 -0
- package/dist/src/exception/base.exception.d.ts +21 -0
- package/dist/src/exception/base.exception.js +16 -0
- package/dist/src/exception/base.exception.js.map +1 -0
- package/dist/src/exception/conflict-error.exception.d.ts +4 -0
- package/dist/src/exception/conflict-error.exception.js +12 -0
- package/dist/src/exception/conflict-error.exception.js.map +1 -0
- package/dist/src/exception/forbidden-error.exception.d.ts +4 -0
- package/dist/src/exception/forbidden-error.exception.js +12 -0
- package/dist/src/exception/forbidden-error.exception.js.map +1 -0
- package/dist/src/exception/index.d.ts +7 -0
- package/dist/src/exception/index.js +23 -0
- package/dist/src/exception/index.js.map +1 -1
- package/dist/src/exception/internal-server-error.exception.d.ts +4 -0
- package/dist/src/exception/internal-server-error.exception.js +12 -0
- package/dist/src/exception/internal-server-error.exception.js.map +1 -0
- package/dist/src/exception/not-found-error.exception.d.ts +4 -0
- package/dist/src/exception/not-found-error.exception.js +12 -0
- package/dist/src/exception/not-found-error.exception.js.map +1 -0
- package/dist/src/exception/unauthorized-error.exception.d.ts +4 -0
- package/dist/src/exception/unauthorized-error.exception.js +12 -0
- package/dist/src/exception/unauthorized-error.exception.js.map +1 -0
- package/dist/src/filter/http-exception.filter.d.ts +4 -0
- package/dist/src/filter/http-exception.filter.js +27 -0
- package/dist/src/filter/http-exception.filter.js.map +1 -0
- package/dist/src/filter/index.d.ts +1 -0
- package/dist/src/filter/index.js +18 -0
- package/dist/src/filter/index.js.map +1 -0
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.js +2 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/setup/index.d.ts +1 -0
- package/dist/src/setup/index.js +18 -0
- package/dist/src/setup/index.js.map +1 -0
- package/dist/src/setup/microservice.setup.d.ts +2 -0
- package/dist/src/setup/microservice.setup.js +25 -0
- package/dist/src/setup/microservice.setup.js.map +1 -0
- package/dist/src/setup/swagger.setup.d.ts +0 -0
- package/dist/src/setup/swagger.setup.js +1 -0
- package/dist/src/setup/swagger.setup.js.map +1 -0
- package/dist/src/util/app.utils.d.ts +4 -0
- package/dist/src/util/app.utils.js +21 -0
- package/dist/src/util/app.utils.js.map +1 -0
- package/dist/src/util/index.d.ts +1 -0
- package/dist/src/util/index.js +1 -0
- package/dist/src/util/index.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/index.ts +1 -1
- package/nest-cli.json +8 -8
- package/package.json +82 -81
- package/src/constant/entity-state.constant.ts +4 -4
- package/src/constant/index.ts +1 -1
- package/src/dto/base-filter.dto.ts +4 -4
- package/src/dto/index.ts +2 -2
- package/src/dto/pagination.dto.ts +4 -4
- package/src/exception/bad-request-error.exception.spec.ts +24 -0
- package/src/exception/bad-request-error.exception.ts +8 -0
- package/src/exception/base.exception.ts +36 -0
- package/src/exception/conflict-error.exception.spec.ts +23 -0
- package/src/exception/conflict-error.exception.ts +8 -0
- package/src/exception/forbidden-error.exception.spec.ts +23 -0
- package/src/exception/forbidden-error.exception.ts +8 -0
- package/src/exception/index.ts +7 -0
- package/src/exception/internal-server-error.exception.spec.ts +23 -0
- package/src/exception/internal-server-error.exception.ts +12 -0
- package/src/exception/not-found-error.exception.spec.ts +23 -0
- package/src/exception/not-found-error.exception.ts +8 -0
- package/src/exception/unauthorized-error.exception.spec.ts +23 -0
- package/src/exception/unauthorized-error.exception.ts +12 -0
- package/src/filter/http-exception.filter.ts +23 -0
- package/src/filter/index.ts +1 -0
- package/src/generic/entity/entity.generic.ts +34 -34
- package/src/generic/entity/index.ts +1 -1
- package/src/generic/index.ts +2 -2
- package/src/generic/service/index.ts +1 -1
- package/src/generic/service/service.generic.ts +112 -112
- package/src/index.ts +2 -0
- package/src/lib/index.ts +1 -1
- package/src/lib/search-engine/document/base.document.ts +2 -2
- package/src/lib/search-engine/index.ts +1 -1
- package/src/lib/search-engine/interface/index.ts +1 -1
- package/src/lib/search-engine/interface/search-document.interface.ts +5 -5
- package/src/lib/search-engine/interface/transform-service.interface.ts +10 -10
- package/src/lib/search-engine/typesense/index.ts +3 -3
- package/src/lib/search-engine/typesense/metadata/index.ts +1 -1
- package/src/lib/search-engine/typesense/metadata/schema.metadata.ts +13 -13
- package/src/lib/search-engine/typesense/metadata/typesense.metadata-registry.ts +28 -28
- package/src/lib/search-engine/typesense/service/client.service.ts +258 -258
- package/src/lib/search-engine/typesense/typesense-module.interface.ts +36 -36
- package/src/lib/search-engine/typesense/typesense.constants.ts +1 -1
- package/src/lib/search-engine/typesense/typesense.module.test.ts +94 -94
- package/src/lib/search-engine/typesense/typesense.module.ts +76 -76
- package/src/lib/search-engine/typesense/typesense.providers.ts +42 -42
- package/src/response/index.ts +1 -1
- package/src/response/pagination.response.ts +37 -37
- package/src/setup/index.ts +1 -0
- package/src/setup/microservice.setup.ts +29 -0
- package/src/setup/swagger.setup.ts +0 -0
- package/src/util/app.utils.ts +18 -0
- package/src/util/date.util.spec.ts +49 -49
- package/src/util/date.util.ts +10 -10
- package/src/util/generator.util.spec.ts +79 -79
- package/src/util/generator.util.ts +34 -34
- package/src/util/index.ts +3 -2
- package/test/app.e2e-spec.ts +24 -24
- package/test/jest-e2e.json +9 -9
- package/tsconfig.build.json +4 -4
- package/tsconfig.json +21 -21
@@ -1,258 +1,258 @@
|
|
1
|
-
import { Client } from 'typesense';
|
2
|
-
import { Logger, Type } from '@nestjs/common';
|
3
|
-
import { plainToClass } from 'class-transformer';
|
4
|
-
import { CollectionCreateSchema } from 'typesense/lib/Typesense/Collections';
|
5
|
-
import {
|
6
|
-
SearchParams,
|
7
|
-
SearchOptions,
|
8
|
-
SearchResponse,
|
9
|
-
DeleteResponse,
|
10
|
-
ImportResponse,
|
11
|
-
} from 'typesense/lib/Typesense/Documents';
|
12
|
-
import { BaseDocument } from '../../document';
|
13
|
-
import { SearchDocumentService } from '../../interface';
|
14
|
-
import { EntityGeneric } from '../../../../generic';
|
15
|
-
import { PaginationResponse } from '../../../../response';
|
16
|
-
|
17
|
-
export abstract class ClientService<
|
18
|
-
Document extends BaseDocument,
|
19
|
-
Entity extends EntityGeneric,
|
20
|
-
> implements SearchDocumentService<Document>
|
21
|
-
{
|
22
|
-
protected readonly entity: Type<Entity>;
|
23
|
-
protected abstract cache_s: number;
|
24
|
-
protected readonly skipCheckSchema: boolean = false;
|
25
|
-
constructor(
|
26
|
-
protected readonly client: Client,
|
27
|
-
protected readonly schema: CollectionCreateSchema,
|
28
|
-
protected readonly prefix: string,
|
29
|
-
) {
|
30
|
-
if (!this.skipCheckSchema && schema != null) {
|
31
|
-
this.ensureCollection();
|
32
|
-
}
|
33
|
-
}
|
34
|
-
|
35
|
-
// searchDocument(searchParameters: SearchParams, options: SearchOptions) {
|
36
|
-
// const {
|
37
|
-
// per_page = 25,
|
38
|
-
// filter_by,
|
39
|
-
// archived = false,
|
40
|
-
// } = { ...searchParameters };
|
41
|
-
// searchParameters.per_page = per_page;
|
42
|
-
// return this.client.collections(this?.schema?.name || this.prefix).documents().search(searchParameters, options);
|
43
|
-
// }
|
44
|
-
|
45
|
-
async searchDocument(
|
46
|
-
searchParameters: SearchParams,
|
47
|
-
options: SearchOptions,
|
48
|
-
): Promise<SearchResponse<any>> {
|
49
|
-
try {
|
50
|
-
const { includeIds = [], per_page = 25 } = { ...searchParameters };
|
51
|
-
// TODO: should be support with include/exclude ids.
|
52
|
-
const includeDocuments = [];
|
53
|
-
if (includeIds.length > 0) {
|
54
|
-
const includeOpts = {
|
55
|
-
...searchParameters,
|
56
|
-
filter_by: `id:=[${includeIds.join(', ')}]`,
|
57
|
-
};
|
58
|
-
const includeDocs = await this.client
|
59
|
-
.collections(this?.schema?.name || this.prefix)
|
60
|
-
.documents()
|
61
|
-
.search(includeOpts, options);
|
62
|
-
if (includeDocs?.hits?.length > 0) {
|
63
|
-
const names = includeDocs.hits.map(
|
64
|
-
(data: Record<string, any>) => data.document.name,
|
65
|
-
);
|
66
|
-
searchParameters.filter_by =
|
67
|
-
searchParameters.filter_by == null
|
68
|
-
? `name:!=[${names.join(', ')}]`
|
69
|
-
: `${searchParameters.filter_by} && name:!=[${names.join(', ')}]`;
|
70
|
-
searchParameters.per_page = per_page - names.length;
|
71
|
-
}
|
72
|
-
includeDocuments.push(...includeDocs?.hits);
|
73
|
-
}
|
74
|
-
const documents = await this.client
|
75
|
-
.collections(this?.schema?.name || this.prefix)
|
76
|
-
.documents()
|
77
|
-
.search(searchParameters, options);
|
78
|
-
if (includeDocuments.length > 0) {
|
79
|
-
documents.hits.push(...includeDocuments);
|
80
|
-
documents.request_params.per_page = per_page;
|
81
|
-
}
|
82
|
-
return documents;
|
83
|
-
} catch (error) {
|
84
|
-
return null;
|
85
|
-
}
|
86
|
-
}
|
87
|
-
|
88
|
-
getAllRawDocs = async (
|
89
|
-
searchParameters: SearchParams,
|
90
|
-
options: SearchOptions,
|
91
|
-
) => {
|
92
|
-
searchParameters.per_page = searchParameters.per_page ?? 250;
|
93
|
-
options.cacheSearchResultsForSeconds = 1;
|
94
|
-
const response = await this.searchDocument(searchParameters, options);
|
95
|
-
const { hits = [], found = 0, page = 1 } = response;
|
96
|
-
let documents = hits;
|
97
|
-
const hasNext = hits.length * page < found;
|
98
|
-
if (hasNext) {
|
99
|
-
searchParameters.page = page + 1;
|
100
|
-
documents = await this.getAllRawDocs(searchParameters, options);
|
101
|
-
}
|
102
|
-
return documents;
|
103
|
-
};
|
104
|
-
|
105
|
-
async importIndex(data: Document[]): Promise<ImportResponse[]> {
|
106
|
-
if (data.length > 0) {
|
107
|
-
try {
|
108
|
-
return this.client
|
109
|
-
.collections(this?.schema?.name || this.prefix)
|
110
|
-
.documents()
|
111
|
-
.import(data, { action: 'upsert' });
|
112
|
-
} catch (error) {
|
113
|
-
console.log(error);
|
114
|
-
}
|
115
|
-
}
|
116
|
-
}
|
117
|
-
|
118
|
-
async deleteOutOfDate(data: string[] | number[], key: string): Promise<any> {
|
119
|
-
if (data?.length > 0) {
|
120
|
-
const deleteParameters = {
|
121
|
-
filter_by: `${key}:!=[${data.join(', ')}]`,
|
122
|
-
};
|
123
|
-
return await this.client
|
124
|
-
.collections(this?.schema?.name || this.prefix)
|
125
|
-
.documents()
|
126
|
-
.delete(deleteParameters);
|
127
|
-
}
|
128
|
-
}
|
129
|
-
|
130
|
-
async insertIndex(data: Document): Promise<any> {
|
131
|
-
return this.client
|
132
|
-
.collections(this?.schema?.name || this.prefix)
|
133
|
-
.documents()
|
134
|
-
.create(data, { action: 'upsert' });
|
135
|
-
}
|
136
|
-
|
137
|
-
async updateIndex(data: Document): Promise<any> {
|
138
|
-
return this.client
|
139
|
-
.collections(this?.schema?.name || this.prefix)
|
140
|
-
.documents()
|
141
|
-
.upsert(data, { action: 'upsert' });
|
142
|
-
}
|
143
|
-
|
144
|
-
updateDocumentById = async (data: Document) => {
|
145
|
-
if (data?.id) {
|
146
|
-
const exist = await this.client
|
147
|
-
.collections(this?.schema?.name || this.prefix)
|
148
|
-
.documents(data.id)
|
149
|
-
.retrieve();
|
150
|
-
if (exist) {
|
151
|
-
return this.client
|
152
|
-
.collections(this?.schema?.name || this.prefix)
|
153
|
-
.documents(data.id)
|
154
|
-
.update(data);
|
155
|
-
}
|
156
|
-
}
|
157
|
-
};
|
158
|
-
|
159
|
-
async upsertOrDeleteIndex(datas: Document) {
|
160
|
-
throw new Error('Method is not implement.');
|
161
|
-
}
|
162
|
-
|
163
|
-
async deleteIndex(data: Document): Promise<DeleteResponse> {
|
164
|
-
return this.client
|
165
|
-
.collections(this?.schema?.name || this.prefix)
|
166
|
-
.documents()
|
167
|
-
.delete({ filter_by: `id: ${data.id}` });
|
168
|
-
}
|
169
|
-
|
170
|
-
async deleteBatchIndex(ids: string[]): Promise<DeleteResponse> {
|
171
|
-
return this.client
|
172
|
-
.collections(this?.schema?.name || this.prefix)
|
173
|
-
.documents()
|
174
|
-
.delete({ filter_by: `id: [${ids.join(',')}]` });
|
175
|
-
}
|
176
|
-
|
177
|
-
async deleteIndexByKeyValue(
|
178
|
-
key = 'id',
|
179
|
-
value: number,
|
180
|
-
): Promise<DeleteResponse> {
|
181
|
-
return this.client
|
182
|
-
.collections(this?.schema?.name || this.prefix)
|
183
|
-
.documents()
|
184
|
-
.delete({ filter_by: `${key}:=${value}` });
|
185
|
-
}
|
186
|
-
|
187
|
-
transforms = (
|
188
|
-
searchResponse: SearchResponse<Record<string, unknown>>,
|
189
|
-
): Entity[] => {
|
190
|
-
const entities: Entity[] = [];
|
191
|
-
const { hits = [] } = { ...searchResponse };
|
192
|
-
for (const hit of hits) {
|
193
|
-
const document = hit?.document;
|
194
|
-
if (document) {
|
195
|
-
const entity = plainToClass(this.entity, document);
|
196
|
-
entity.id = Number(document.id);
|
197
|
-
entities.push(entity);
|
198
|
-
}
|
199
|
-
}
|
200
|
-
return entities;
|
201
|
-
};
|
202
|
-
|
203
|
-
transform = (
|
204
|
-
searchResponse: SearchResponse<Record<string, unknown>>,
|
205
|
-
): Entity => {
|
206
|
-
let entity: Entity = null;
|
207
|
-
const { hits = [] } = { ...searchResponse };
|
208
|
-
for (const hit of hits) {
|
209
|
-
const document = hit?.document;
|
210
|
-
if (document) {
|
211
|
-
entity = plainToClass(this.entity, document);
|
212
|
-
entity.id = Number(document.id);
|
213
|
-
}
|
214
|
-
break;
|
215
|
-
}
|
216
|
-
return entity;
|
217
|
-
};
|
218
|
-
|
219
|
-
responseList = (
|
220
|
-
searchResponse: SearchResponse<Record<string, unknown>>,
|
221
|
-
offset = 0,
|
222
|
-
): PaginationResponse<Entity> => {
|
223
|
-
const entities: Entity[] = [];
|
224
|
-
const {
|
225
|
-
hits = [],
|
226
|
-
found = 0,
|
227
|
-
page = 1,
|
228
|
-
request_params,
|
229
|
-
} = { ...searchResponse };
|
230
|
-
for (const hit of hits) {
|
231
|
-
const document = hit?.document;
|
232
|
-
if (document) {
|
233
|
-
const entity = plainToClass(this.entity, document);
|
234
|
-
entity.id = Number(document.id);
|
235
|
-
entities.push(entity);
|
236
|
-
}
|
237
|
-
}
|
238
|
-
|
239
|
-
const limit = request_params?.per_page;
|
240
|
-
|
241
|
-
// offset = offset ?? (page - 1) * limit;
|
242
|
-
|
243
|
-
return new PaginationResponse(entities, found, limit, offset);
|
244
|
-
};
|
245
|
-
|
246
|
-
private ensureCollection = async (): Promise<void> => {
|
247
|
-
this.checkSchemaName();
|
248
|
-
const exists = await this.client.collections(this.schema.name).exists();
|
249
|
-
if (!exists) {
|
250
|
-
await this.client.collections().create(this.schema);
|
251
|
-
}
|
252
|
-
};
|
253
|
-
|
254
|
-
private checkSchemaName = (): void => {
|
255
|
-
const schemaName = this.schema.name.replace(/.*?\_/gi, '');
|
256
|
-
this.schema.name = `${this.prefix}_${schemaName}`;
|
257
|
-
};
|
258
|
-
}
|
1
|
+
import { Client } from 'typesense';
|
2
|
+
import { Logger, Type } from '@nestjs/common';
|
3
|
+
import { plainToClass } from 'class-transformer';
|
4
|
+
import { CollectionCreateSchema } from 'typesense/lib/Typesense/Collections';
|
5
|
+
import {
|
6
|
+
SearchParams,
|
7
|
+
SearchOptions,
|
8
|
+
SearchResponse,
|
9
|
+
DeleteResponse,
|
10
|
+
ImportResponse,
|
11
|
+
} from 'typesense/lib/Typesense/Documents';
|
12
|
+
import { BaseDocument } from '../../document';
|
13
|
+
import { SearchDocumentService } from '../../interface';
|
14
|
+
import { EntityGeneric } from '../../../../generic';
|
15
|
+
import { PaginationResponse } from '../../../../response';
|
16
|
+
|
17
|
+
export abstract class ClientService<
|
18
|
+
Document extends BaseDocument,
|
19
|
+
Entity extends EntityGeneric,
|
20
|
+
> implements SearchDocumentService<Document>
|
21
|
+
{
|
22
|
+
protected readonly entity: Type<Entity>;
|
23
|
+
protected abstract cache_s: number;
|
24
|
+
protected readonly skipCheckSchema: boolean = false;
|
25
|
+
constructor(
|
26
|
+
protected readonly client: Client,
|
27
|
+
protected readonly schema: CollectionCreateSchema,
|
28
|
+
protected readonly prefix: string,
|
29
|
+
) {
|
30
|
+
if (!this.skipCheckSchema && schema != null) {
|
31
|
+
this.ensureCollection();
|
32
|
+
}
|
33
|
+
}
|
34
|
+
|
35
|
+
// searchDocument(searchParameters: SearchParams, options: SearchOptions) {
|
36
|
+
// const {
|
37
|
+
// per_page = 25,
|
38
|
+
// filter_by,
|
39
|
+
// archived = false,
|
40
|
+
// } = { ...searchParameters };
|
41
|
+
// searchParameters.per_page = per_page;
|
42
|
+
// return this.client.collections(this?.schema?.name || this.prefix).documents().search(searchParameters, options);
|
43
|
+
// }
|
44
|
+
|
45
|
+
async searchDocument(
|
46
|
+
searchParameters: SearchParams,
|
47
|
+
options: SearchOptions,
|
48
|
+
): Promise<SearchResponse<any>> {
|
49
|
+
try {
|
50
|
+
const { includeIds = [], per_page = 25 } = { ...searchParameters };
|
51
|
+
// TODO: should be support with include/exclude ids.
|
52
|
+
const includeDocuments = [];
|
53
|
+
if (includeIds.length > 0) {
|
54
|
+
const includeOpts = {
|
55
|
+
...searchParameters,
|
56
|
+
filter_by: `id:=[${includeIds.join(', ')}]`,
|
57
|
+
};
|
58
|
+
const includeDocs = await this.client
|
59
|
+
.collections(this?.schema?.name || this.prefix)
|
60
|
+
.documents()
|
61
|
+
.search(includeOpts, options);
|
62
|
+
if (includeDocs?.hits?.length > 0) {
|
63
|
+
const names = includeDocs.hits.map(
|
64
|
+
(data: Record<string, any>) => data.document.name,
|
65
|
+
);
|
66
|
+
searchParameters.filter_by =
|
67
|
+
searchParameters.filter_by == null
|
68
|
+
? `name:!=[${names.join(', ')}]`
|
69
|
+
: `${searchParameters.filter_by} && name:!=[${names.join(', ')}]`;
|
70
|
+
searchParameters.per_page = per_page - names.length;
|
71
|
+
}
|
72
|
+
includeDocuments.push(...includeDocs?.hits);
|
73
|
+
}
|
74
|
+
const documents = await this.client
|
75
|
+
.collections(this?.schema?.name || this.prefix)
|
76
|
+
.documents()
|
77
|
+
.search(searchParameters, options);
|
78
|
+
if (includeDocuments.length > 0) {
|
79
|
+
documents.hits.push(...includeDocuments);
|
80
|
+
documents.request_params.per_page = per_page;
|
81
|
+
}
|
82
|
+
return documents;
|
83
|
+
} catch (error) {
|
84
|
+
return null;
|
85
|
+
}
|
86
|
+
}
|
87
|
+
|
88
|
+
getAllRawDocs = async (
|
89
|
+
searchParameters: SearchParams,
|
90
|
+
options: SearchOptions,
|
91
|
+
) => {
|
92
|
+
searchParameters.per_page = searchParameters.per_page ?? 250;
|
93
|
+
options.cacheSearchResultsForSeconds = 1;
|
94
|
+
const response = await this.searchDocument(searchParameters, options);
|
95
|
+
const { hits = [], found = 0, page = 1 } = response;
|
96
|
+
let documents = hits;
|
97
|
+
const hasNext = hits.length * page < found;
|
98
|
+
if (hasNext) {
|
99
|
+
searchParameters.page = page + 1;
|
100
|
+
documents = await this.getAllRawDocs(searchParameters, options);
|
101
|
+
}
|
102
|
+
return documents;
|
103
|
+
};
|
104
|
+
|
105
|
+
async importIndex(data: Document[]): Promise<ImportResponse[]> {
|
106
|
+
if (data.length > 0) {
|
107
|
+
try {
|
108
|
+
return this.client
|
109
|
+
.collections(this?.schema?.name || this.prefix)
|
110
|
+
.documents()
|
111
|
+
.import(data, { action: 'upsert' });
|
112
|
+
} catch (error) {
|
113
|
+
console.log(error);
|
114
|
+
}
|
115
|
+
}
|
116
|
+
}
|
117
|
+
|
118
|
+
async deleteOutOfDate(data: string[] | number[], key: string): Promise<any> {
|
119
|
+
if (data?.length > 0) {
|
120
|
+
const deleteParameters = {
|
121
|
+
filter_by: `${key}:!=[${data.join(', ')}]`,
|
122
|
+
};
|
123
|
+
return await this.client
|
124
|
+
.collections(this?.schema?.name || this.prefix)
|
125
|
+
.documents()
|
126
|
+
.delete(deleteParameters);
|
127
|
+
}
|
128
|
+
}
|
129
|
+
|
130
|
+
async insertIndex(data: Document): Promise<any> {
|
131
|
+
return this.client
|
132
|
+
.collections(this?.schema?.name || this.prefix)
|
133
|
+
.documents()
|
134
|
+
.create(data, { action: 'upsert' });
|
135
|
+
}
|
136
|
+
|
137
|
+
async updateIndex(data: Document): Promise<any> {
|
138
|
+
return this.client
|
139
|
+
.collections(this?.schema?.name || this.prefix)
|
140
|
+
.documents()
|
141
|
+
.upsert(data, { action: 'upsert' });
|
142
|
+
}
|
143
|
+
|
144
|
+
updateDocumentById = async (data: Document) => {
|
145
|
+
if (data?.id) {
|
146
|
+
const exist = await this.client
|
147
|
+
.collections(this?.schema?.name || this.prefix)
|
148
|
+
.documents(data.id)
|
149
|
+
.retrieve();
|
150
|
+
if (exist) {
|
151
|
+
return this.client
|
152
|
+
.collections(this?.schema?.name || this.prefix)
|
153
|
+
.documents(data.id)
|
154
|
+
.update(data);
|
155
|
+
}
|
156
|
+
}
|
157
|
+
};
|
158
|
+
|
159
|
+
async upsertOrDeleteIndex(datas: Document) {
|
160
|
+
throw new Error('Method is not implement.');
|
161
|
+
}
|
162
|
+
|
163
|
+
async deleteIndex(data: Document): Promise<DeleteResponse> {
|
164
|
+
return this.client
|
165
|
+
.collections(this?.schema?.name || this.prefix)
|
166
|
+
.documents()
|
167
|
+
.delete({ filter_by: `id: ${data.id}` });
|
168
|
+
}
|
169
|
+
|
170
|
+
async deleteBatchIndex(ids: string[]): Promise<DeleteResponse> {
|
171
|
+
return this.client
|
172
|
+
.collections(this?.schema?.name || this.prefix)
|
173
|
+
.documents()
|
174
|
+
.delete({ filter_by: `id: [${ids.join(',')}]` });
|
175
|
+
}
|
176
|
+
|
177
|
+
async deleteIndexByKeyValue(
|
178
|
+
key = 'id',
|
179
|
+
value: number,
|
180
|
+
): Promise<DeleteResponse> {
|
181
|
+
return this.client
|
182
|
+
.collections(this?.schema?.name || this.prefix)
|
183
|
+
.documents()
|
184
|
+
.delete({ filter_by: `${key}:=${value}` });
|
185
|
+
}
|
186
|
+
|
187
|
+
transforms = (
|
188
|
+
searchResponse: SearchResponse<Record<string, unknown>>,
|
189
|
+
): Entity[] => {
|
190
|
+
const entities: Entity[] = [];
|
191
|
+
const { hits = [] } = { ...searchResponse };
|
192
|
+
for (const hit of hits) {
|
193
|
+
const document = hit?.document;
|
194
|
+
if (document) {
|
195
|
+
const entity = plainToClass(this.entity, document);
|
196
|
+
entity.id = Number(document.id);
|
197
|
+
entities.push(entity);
|
198
|
+
}
|
199
|
+
}
|
200
|
+
return entities;
|
201
|
+
};
|
202
|
+
|
203
|
+
transform = (
|
204
|
+
searchResponse: SearchResponse<Record<string, unknown>>,
|
205
|
+
): Entity => {
|
206
|
+
let entity: Entity = null;
|
207
|
+
const { hits = [] } = { ...searchResponse };
|
208
|
+
for (const hit of hits) {
|
209
|
+
const document = hit?.document;
|
210
|
+
if (document) {
|
211
|
+
entity = plainToClass(this.entity, document);
|
212
|
+
entity.id = Number(document.id);
|
213
|
+
}
|
214
|
+
break;
|
215
|
+
}
|
216
|
+
return entity;
|
217
|
+
};
|
218
|
+
|
219
|
+
responseList = (
|
220
|
+
searchResponse: SearchResponse<Record<string, unknown>>,
|
221
|
+
offset = 0,
|
222
|
+
): PaginationResponse<Entity> => {
|
223
|
+
const entities: Entity[] = [];
|
224
|
+
const {
|
225
|
+
hits = [],
|
226
|
+
found = 0,
|
227
|
+
page = 1,
|
228
|
+
request_params,
|
229
|
+
} = { ...searchResponse };
|
230
|
+
for (const hit of hits) {
|
231
|
+
const document = hit?.document;
|
232
|
+
if (document) {
|
233
|
+
const entity = plainToClass(this.entity, document);
|
234
|
+
entity.id = Number(document.id);
|
235
|
+
entities.push(entity);
|
236
|
+
}
|
237
|
+
}
|
238
|
+
|
239
|
+
const limit = request_params?.per_page;
|
240
|
+
|
241
|
+
// offset = offset ?? (page - 1) * limit;
|
242
|
+
|
243
|
+
return new PaginationResponse(entities, found, limit, offset);
|
244
|
+
};
|
245
|
+
|
246
|
+
private ensureCollection = async (): Promise<void> => {
|
247
|
+
this.checkSchemaName();
|
248
|
+
const exists = await this.client.collections(this.schema.name).exists();
|
249
|
+
if (!exists) {
|
250
|
+
await this.client.collections().create(this.schema);
|
251
|
+
}
|
252
|
+
};
|
253
|
+
|
254
|
+
private checkSchemaName = (): void => {
|
255
|
+
const schemaName = this.schema.name.replace(/.*?\_/gi, '');
|
256
|
+
this.schema.name = `${this.prefix}_${schemaName}`;
|
257
|
+
};
|
258
|
+
}
|
@@ -1,36 +1,36 @@
|
|
1
|
-
import { ModuleMetadata, Type } from '@nestjs/common/interfaces';
|
2
|
-
import { LogLevelDesc } from 'loglevel';
|
3
|
-
|
4
|
-
export interface TypesenseNodeOptions {
|
5
|
-
host: string;
|
6
|
-
port: number;
|
7
|
-
protocol: string;
|
8
|
-
path?: string;
|
9
|
-
url?: string;
|
10
|
-
}
|
11
|
-
|
12
|
-
export interface TypesenseModuleOptions {
|
13
|
-
nodes?: Array<TypesenseNodeOptions>;
|
14
|
-
numRetries?: number;
|
15
|
-
apiKey?: string;
|
16
|
-
connectionTimeoutSeconds?: number;
|
17
|
-
retryIntervalSeconds?: number;
|
18
|
-
healthcheckIntervalSeconds?: number;
|
19
|
-
logLevel?: LogLevelDesc;
|
20
|
-
}
|
21
|
-
|
22
|
-
export interface TypesenseOptionsFactory {
|
23
|
-
createTypesenseOptions():
|
24
|
-
| Promise<TypesenseModuleOptions>
|
25
|
-
| TypesenseModuleOptions;
|
26
|
-
}
|
27
|
-
|
28
|
-
export interface TypesenseModuleAsyncOptions
|
29
|
-
extends Pick<ModuleMetadata, 'imports'> {
|
30
|
-
useExisting?: Type<TypesenseOptionsFactory>;
|
31
|
-
useClass?: Type<TypesenseOptionsFactory>;
|
32
|
-
useFactory?: (
|
33
|
-
...args: any[]
|
34
|
-
) => Promise<TypesenseModuleOptions> | TypesenseModuleOptions;
|
35
|
-
inject?: any[];
|
36
|
-
}
|
1
|
+
import { ModuleMetadata, Type } from '@nestjs/common/interfaces';
|
2
|
+
import { LogLevelDesc } from 'loglevel';
|
3
|
+
|
4
|
+
export interface TypesenseNodeOptions {
|
5
|
+
host: string;
|
6
|
+
port: number;
|
7
|
+
protocol: string;
|
8
|
+
path?: string;
|
9
|
+
url?: string;
|
10
|
+
}
|
11
|
+
|
12
|
+
export interface TypesenseModuleOptions {
|
13
|
+
nodes?: Array<TypesenseNodeOptions>;
|
14
|
+
numRetries?: number;
|
15
|
+
apiKey?: string;
|
16
|
+
connectionTimeoutSeconds?: number;
|
17
|
+
retryIntervalSeconds?: number;
|
18
|
+
healthcheckIntervalSeconds?: number;
|
19
|
+
logLevel?: LogLevelDesc;
|
20
|
+
}
|
21
|
+
|
22
|
+
export interface TypesenseOptionsFactory {
|
23
|
+
createTypesenseOptions():
|
24
|
+
| Promise<TypesenseModuleOptions>
|
25
|
+
| TypesenseModuleOptions;
|
26
|
+
}
|
27
|
+
|
28
|
+
export interface TypesenseModuleAsyncOptions
|
29
|
+
extends Pick<ModuleMetadata, 'imports'> {
|
30
|
+
useExisting?: Type<TypesenseOptionsFactory>;
|
31
|
+
useClass?: Type<TypesenseOptionsFactory>;
|
32
|
+
useFactory?: (
|
33
|
+
...args: any[]
|
34
|
+
) => Promise<TypesenseModuleOptions> | TypesenseModuleOptions;
|
35
|
+
inject?: any[];
|
36
|
+
}
|
@@ -1 +1 @@
|
|
1
|
-
export const TYPESENSE_MODULE_OPTIONS = 'TYPESENSE_MODULE_OPTIONS';
|
1
|
+
export const TYPESENSE_MODULE_OPTIONS = 'TYPESENSE_MODULE_OPTIONS';
|