@dnax/core 0.52.2 → 0.52.4

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/app/ctrl.ts CHANGED
@@ -16,6 +16,7 @@ const actions = [
16
16
  "upload",
17
17
  "batch",
18
18
  "count",
19
+ "search",
19
20
  ];
20
21
 
21
22
  function getAction(action: string) {
package/app/hono.ts CHANGED
@@ -14,6 +14,7 @@ import { consola } from "consola";
14
14
  import { cors } from "hono/cors";
15
15
  import { asyncLocalStorage, sessionStorage } from "../lib/asyncLocalStorage";
16
16
  import { localSession } from "../lib/session";
17
+ import { crypt } from "../lib/crypto";
17
18
  import {
18
19
  cleanPath,
19
20
  ContextError,
@@ -40,6 +41,7 @@ import { ipRestriction } from "hono/ip-restriction";
40
41
  import { logger } from "hono/logger";
41
42
  import { csrf } from "hono/csrf";
42
43
  import { v4 } from "uuid";
44
+ import type { SearchParams } from "meilisearch";
43
45
  const cache = bentoCache.namespace("DNAX_API");
44
46
  const app = new Hono();
45
47
  const API_PATH = "/api";
@@ -498,24 +500,66 @@ function HonoInstance(): typeof app {
498
500
  if (action == "count") {
499
501
  response = await rest.count(collection, body?.params || {});
500
502
  }
503
+
504
+ if (action == "search") {
505
+ let searchOption = {
506
+ term: body?.params?.term as string,
507
+ options: body?.params?.searchOptions as SearchParams,
508
+ };
509
+
510
+ if (col?.hooks?.beforeSearch) {
511
+ await col?.hooks?.beforeSearch({
512
+ io: Cfg.io,
513
+ data: body,
514
+ c: c,
515
+ rest: rest,
516
+ action: "search",
517
+ session: sessionStorage(),
518
+ error: fn.error,
519
+ search: searchOption,
520
+ });
521
+ }
522
+
523
+ response = await rest.search(
524
+ collection,
525
+ searchOption.term,
526
+ searchOption.options || {}
527
+ );
528
+
529
+ if (col?.hooks?.afterSearch) {
530
+ await col?.hooks?.afterSearch({
531
+ io: Cfg.io,
532
+ data: body,
533
+ c: c,
534
+ rest: rest,
535
+ action: "search",
536
+ session: sessionStorage(),
537
+ error: fn.error,
538
+ search: searchOption,
539
+ result: response,
540
+ });
541
+ }
542
+ }
501
543
  // find
502
544
  if (action == "find") {
503
545
  if (col?.cache?.enabled && useCache) {
504
- let keyCache = bentoKey({
505
- data: body,
506
- query: c.req.query,
546
+ let keyCache = crypt.AES.generateKey({
547
+ body: body,
548
+ query: c?.req?.query,
507
549
  });
508
550
 
509
551
  // if customCache
510
- if (col?.cache?.customCache) {
511
- let fetchFromCache = await col?.cache?.customCache({
552
+ if (col?.cache?.fetch) {
553
+ let fetchFromCache = await col?.cache?.fetch({
554
+ key: keyCache,
512
555
  action: action,
556
+ params: body?.params,
513
557
  rest: rest,
514
558
  session: sessionStorage(),
559
+ state: col?.cache?.state || {},
515
560
  c: c,
516
561
  });
517
-
518
- if (!fetchFromCache.isStale) {
562
+ if (!fetchFromCache?.isStale) {
519
563
  response = fetchFromCache.data;
520
564
  } else {
521
565
  response = await rest.find(collection, body?.params || {}, {
@@ -523,28 +567,6 @@ function HonoInstance(): typeof app {
523
567
  });
524
568
  }
525
569
  }
526
- // if not customCache
527
- if (!col?.cache?.customCache) {
528
- let responseFromCache = await cache.get({
529
- key: keyCache,
530
- });
531
- if (responseFromCache) {
532
- response = responseFromCache;
533
- } else {
534
- response = await rest.find(collection, body?.params || {}, {
535
- withMeta: body?.withMeta || false,
536
- });
537
- await cache.set({
538
- key: keyCache,
539
- value: response,
540
- ttl: col?.cache?.ttl || "1m",
541
- });
542
- }
543
-
544
- /* response = await rest.find(collection, body?.params || {}, {
545
- withMeta: body?.withMeta || false,
546
- }); */
547
- }
548
570
  } else {
549
571
  response = await rest.find(collection, body?.params || {}, {
550
572
  withMeta: body?.withMeta || false,
@@ -659,6 +681,9 @@ function HonoInstance(): typeof app {
659
681
  } else {
660
682
  response = omit(response, privateFields);
661
683
  }
684
+ if (response.hits) {
685
+ response.hits = omit(response.hits, privateFields);
686
+ }
662
687
  }
663
688
 
664
689
  // hidden is function
@@ -680,6 +705,9 @@ function HonoInstance(): typeof app {
680
705
  privateFields.push("password");
681
706
  privateFields = [...new Set(privateFields)];
682
707
  response.data = omit(response.data, privateFields);
708
+ if (response?.hits) {
709
+ response.hits = omit(response.hits, privateFields);
710
+ }
683
711
  } catch (e) {}
684
712
  } else {
685
713
  privateFields = await col?.api?.fields?.hidden({
@@ -690,6 +718,10 @@ function HonoInstance(): typeof app {
690
718
  });
691
719
  privateFields.push("password");
692
720
  privateFields = [...new Set(privateFields)];
721
+
722
+ if (response?.hits) {
723
+ response.hits = omit(response?.hits, privateFields);
724
+ }
693
725
  response = omit(response, privateFields);
694
726
  }
695
727
  }
@@ -703,6 +735,14 @@ function HonoInstance(): typeof app {
703
735
  response.meta = response.meta || {};
704
736
  }
705
737
 
738
+ if (response?.hits && col?.privateFields?.length) {
739
+ response = omit(response, col?.privateFields);
740
+ }
741
+
742
+ if (response?.data && col?.privateFields?.length) {
743
+ response = omit(response, col?.privateFields);
744
+ }
745
+
706
746
  return c.json(response);
707
747
  } catch (err: any) {
708
748
  if (Cfg?.debug) console.log(err?.message | err);
@@ -13,7 +13,8 @@ async function connectToMongo(t: Tenant) {
13
13
  await client
14
14
  .connect()
15
15
  .then((e) => {
16
- //consola.log(`[${t.id}] : Connected to db ✅`.green);
16
+ console.log("\n");
17
+ consola.success(`DB connected : [${t.id}] ✅`.green);
17
18
  t.database.isConnected = true;
18
19
  t.database.client = client;
19
20
  t.database.db = client.db();
@@ -8,6 +8,8 @@ import { ChangeStream, ClientSession, MongoClient, ObjectId } from "mongodb";
8
8
  import { contextError, fn, toJson, dotJson, getEntryBykeys } from "../../utils";
9
9
  import v, { type Schema } from "joi";
10
10
  import type { Context } from "hono";
11
+ import { MeiliSearch } from "../../lib/meilisearch";
12
+ import type { SearchParams } from "meilisearch";
11
13
 
12
14
  import type {
13
15
  findOneParam,
@@ -93,6 +95,9 @@ class useRest {
93
95
  $skip?: number;
94
96
  }) => Promise<Array<any>>;
95
97
  };
98
+ meilisearch: {
99
+ client: InstanceType<typeof MeiliSearch>;
100
+ };
96
101
 
97
102
  constructor(options: options) {
98
103
  this.#c = options?.c;
@@ -102,7 +107,9 @@ class useRest {
102
107
  this.#tenant = getTenant(this.#tenant_id);
103
108
  this.#useHook = options?.useHook ?? true;
104
109
  this.db = this.#tenant.database.db;
105
-
110
+ this.meilisearch = {
111
+ client: this.#tenant.searchEngine?.meilisearch?.client!,
112
+ };
106
113
  this.activity = {
107
114
  save: async (activityInput) => {
108
115
  return await restActivity.save(this.#tenant, activityInput);
@@ -383,6 +390,28 @@ class useRest {
383
390
  sessionStorage()?.get()?.state?.by ||
384
391
  null,
385
392
  });
393
+
394
+ try {
395
+ col?.cache?.watch({
396
+ action: "insertOne",
397
+ c: this.#c,
398
+ session: sessionStorage(),
399
+ rest: this,
400
+ state: col?.cache?.state || {},
401
+ result: toJson(data),
402
+ });
403
+ } catch (err) {}
404
+
405
+ // meilisearch engine
406
+ if (
407
+ this.#tenant?.searchEngine?.meilisearch?.enabled &&
408
+ col?.searchEngine?.meilisearch?.dispatchAction == "auto"
409
+ ) {
410
+ this.meilisearch.client
411
+ .index(col?.searchEngine?.meilisearch?.index)
412
+ .addDocuments([toJson(data)])
413
+ .catch();
414
+ }
386
415
  return resolve(toJson(data));
387
416
  } catch (err) {
388
417
  return reject(err);
@@ -503,7 +532,25 @@ class useRest {
503
532
  sessionStorage()?.get().state?.by ||
504
533
  null,
505
534
  });
506
-
535
+ try {
536
+ col?.cache?.watch({
537
+ action: "insertMany",
538
+ c: this.#c,
539
+ session: sessionStorage(),
540
+ rest: this,
541
+ state: col?.cache?.state || {},
542
+ result: toJson(data),
543
+ });
544
+ } catch (err) {}
545
+ if (
546
+ this.#tenant?.searchEngine?.meilisearch?.enabled &&
547
+ col?.searchEngine?.meilisearch?.dispatchAction == "auto"
548
+ ) {
549
+ this.meilisearch.client
550
+ .index(col?.searchEngine?.meilisearch?.index)
551
+ .addDocuments(toJson(data))
552
+ .catch();
553
+ }
507
554
  return resolve(toJson(data));
508
555
  } catch (err) {
509
556
  reject(err);
@@ -1104,7 +1151,26 @@ class useRest {
1104
1151
  sessionStorage().get().state?.by ||
1105
1152
  null,
1106
1153
  });
1107
- return resolve(result.doc);
1154
+ try {
1155
+ col?.cache?.watch({
1156
+ action: "insertMany",
1157
+ c: this.#c,
1158
+ session: sessionStorage(),
1159
+ rest: this,
1160
+ state: col?.cache?.state || {},
1161
+ result: toJson(result?.doc || {}),
1162
+ });
1163
+ } catch (err) {}
1164
+ if (
1165
+ this.#tenant?.searchEngine?.meilisearch?.enabled &&
1166
+ col?.searchEngine?.meilisearch?.dispatchAction == "auto"
1167
+ ) {
1168
+ this.meilisearch.client
1169
+ .index(col?.searchEngine?.meilisearch?.index)
1170
+ .updateDocuments([{ ...toJson(result?.doc || {}) }])
1171
+ .catch();
1172
+ }
1173
+ return resolve(toJson(result?.doc || {}));
1108
1174
  } catch (err) {
1109
1175
  return reject(err);
1110
1176
  }
@@ -1174,6 +1240,18 @@ class useRest {
1174
1240
  allowDiskUse: true,
1175
1241
  })
1176
1242
  .toArray();
1243
+
1244
+ if (
1245
+ this.#tenant?.searchEngine?.meilisearch?.enabled &&
1246
+ col?.searchEngine?.meilisearch?.dispatchAction == "auto"
1247
+ ) {
1248
+ this.meilisearch.client
1249
+ .index(col?.searchEngine?.meilisearch?.index)
1250
+ .updateDocuments(result.docs)
1251
+ .catch();
1252
+ }
1253
+ ``;
1254
+
1177
1255
  return resolve({
1178
1256
  docs: result.docs,
1179
1257
  matchedCount: up_?.matchedCount || 0,
@@ -1245,7 +1323,19 @@ class useRest {
1245
1323
  session: this.#session ? this.#session : undefined,
1246
1324
  }
1247
1325
  );
1248
-
1326
+ if (
1327
+ this.#tenant?.searchEngine?.meilisearch?.enabled &&
1328
+ col?.searchEngine?.meilisearch?.dispatchAction == "auto"
1329
+ ) {
1330
+ this.meilisearch.client
1331
+ .index(col?.searchEngine?.meilisearch?.index)
1332
+ .updateDocuments([
1333
+ {
1334
+ ...toJson(result.doc || {}),
1335
+ },
1336
+ ])
1337
+ .catch();
1338
+ }
1249
1339
  return resolve(result.doc);
1250
1340
  } catch (err) {
1251
1341
  return reject(err);
@@ -1253,6 +1343,44 @@ class useRest {
1253
1343
  });
1254
1344
  }
1255
1345
 
1346
+ async search(
1347
+ collection: string,
1348
+ term: string,
1349
+ searchOptions: SearchParams
1350
+ ): Promise<{
1351
+ hits: Array<object>;
1352
+ limit: number;
1353
+ offset: number;
1354
+ total: number;
1355
+ processingTimeMs: number;
1356
+ facetDistribution?: object;
1357
+ facetsStats?: object;
1358
+ estimatedTotalHits?: number;
1359
+ totalHits?: number;
1360
+ hitsPerPage?: number;
1361
+ page?: number;
1362
+ }> {
1363
+ return new Promise(async (resolve, reject) => {
1364
+ try {
1365
+ let index = getCollection(collection, this.#tenant_id)?.searchEngine
1366
+ ?.meilisearch?.index!;
1367
+
1368
+ if (!index)
1369
+ return reject({
1370
+ code: 400,
1371
+ message: "Search engine Index required",
1372
+ });
1373
+
1374
+ let result = this.meilisearch.client.index(index).search(term, {
1375
+ ...searchOptions,
1376
+ });
1377
+ resolve(result);
1378
+ } catch (err) {
1379
+ return reject(err);
1380
+ }
1381
+ });
1382
+ }
1383
+
1256
1384
  async updateMany(
1257
1385
  collection: string,
1258
1386
  ids: Array<string>,
@@ -1418,6 +1546,25 @@ class useRest {
1418
1546
  sessionStorage().get().state?.by ||
1419
1547
  null,
1420
1548
  });
1549
+ try {
1550
+ col?.cache?.watch({
1551
+ action: "updateMany",
1552
+ c: this.#c,
1553
+ session: sessionStorage(),
1554
+ rest: this,
1555
+ state: col?.cache?.state || {},
1556
+ result: toJson(result?.docs || []),
1557
+ });
1558
+ } catch (err) {}
1559
+ if (
1560
+ this.#tenant?.searchEngine?.meilisearch?.enabled &&
1561
+ col?.searchEngine?.meilisearch?.dispatchAction == "auto"
1562
+ ) {
1563
+ this.meilisearch.client
1564
+ .index(col?.searchEngine?.meilisearch?.index)
1565
+ .updateDocuments(result.docs)
1566
+ .catch();
1567
+ }
1421
1568
  return resolve(result.docs);
1422
1569
  } else {
1423
1570
  throw new contextError("List of id required", 400);
@@ -1533,6 +1680,25 @@ class useRest {
1533
1680
  sessionStorage().get().state?.by ||
1534
1681
  null,
1535
1682
  });
1683
+ try {
1684
+ col?.cache?.watch({
1685
+ action: "deleteOne",
1686
+ c: this.#c,
1687
+ session: sessionStorage(),
1688
+ rest: this,
1689
+ state: col?.cache?.state || {},
1690
+ result: toJson(doc || {}),
1691
+ });
1692
+ } catch (err) {}
1693
+ if (
1694
+ this.#tenant.searchEngine.meilisearch.enabled &&
1695
+ col?.searchEngine?.meilisearch?.dispatchAction == "auto"
1696
+ ) {
1697
+ this.meilisearch.client
1698
+ .index(col?.searchEngine?.meilisearch?.index)
1699
+ .deleteDocument(id)
1700
+ .catch();
1701
+ }
1536
1702
  return resolve(doc);
1537
1703
  } catch (err) {
1538
1704
  return resolve(err);
@@ -1648,7 +1814,25 @@ class useRest {
1648
1814
  sessionStorage().get().state?.by ||
1649
1815
  null,
1650
1816
  });
1651
-
1817
+ try {
1818
+ col?.cache?.watch({
1819
+ action: "deleteMany",
1820
+ c: this.#c,
1821
+ session: sessionStorage(),
1822
+ rest: this,
1823
+ state: col?.cache?.state || {},
1824
+ result: deletedIds || [],
1825
+ });
1826
+ } catch (err) {}
1827
+ if (
1828
+ this.#tenant.searchEngine.meilisearch.enabled &&
1829
+ col?.searchEngine?.meilisearch?.dispatchAction == "auto"
1830
+ ) {
1831
+ this.meilisearch.client
1832
+ .index(col?.searchEngine?.meilisearch?.index)
1833
+ .deleteDocuments(deletedIds)
1834
+ .catch();
1835
+ }
1652
1836
  return resolve(deletedIds);
1653
1837
  } catch (err) {
1654
1838
  return reject(err);
package/lib/collection.ts CHANGED
@@ -70,20 +70,82 @@ async function syncCollectionDatabase() {
70
70
  const collections: Collection[] | undefined = Cfg.collections?.filter(
71
71
  (cn) => cn.tenant_id == t.id
72
72
  );
73
-
74
73
  if (collections?.length) {
74
+ // searchEngine Section
75
+ if (t?.searchEngine?.meilisearch?.enabled) {
76
+ let allIndex_ = await t?.searchEngine?.meilisearch?.client
77
+ ?.getIndexes()
78
+ .then((e) => e.results)
79
+ .catch((err) => []);
80
+
81
+ for await (let c of collections) {
82
+ if (c?.searchEngine?.meilisearch?.index) {
83
+ if (c?.searchEngine?.meilisearch?.dispatchAction) {
84
+ c.searchEngine.meilisearch.dispatchAction = "auto";
85
+ }
86
+
87
+ let indexExist = allIndex_?.find(
88
+ (index) => index?.uid == c?.searchEngine?.meilisearch?.index
89
+ );
90
+ if (!indexExist) {
91
+ await t.searchEngine.meilisearch.client
92
+ ?.createIndex(c?.searchEngine?.meilisearch?.index, {
93
+ primaryKey:
94
+ c?.searchEngine?.meilisearch?.primaryKey || "_id",
95
+ })
96
+ .catch((err) => {
97
+ //consola.error(err?.message);
98
+ });
99
+ }
100
+
101
+ let attributes = await t?.searchEngine?.meilisearch?.client
102
+ ?.index(c?.searchEngine?.meilisearch?.index)
103
+ .getFilterableAttributes()
104
+ .catch();
105
+
106
+ if (
107
+ c?.searchEngine?.meilisearch?.filterableAttributes?.length
108
+ ) {
109
+ let s = false;
110
+ if (
111
+ !deepEqual(
112
+ attributes,
113
+ c?.searchEngine?.meilisearch?.filterableAttributes
114
+ )
115
+ ) {
116
+ await t?.searchEngine?.meilisearch?.client
117
+ ?.index(c?.searchEngine?.meilisearch?.index)
118
+ .updateFilterableAttributes(
119
+ c?.searchEngine?.meilisearch?.filterableAttributes
120
+ )
121
+ .catch();
122
+ }
123
+ }
124
+ }
125
+ }
126
+ }
127
+ // DatabaseSection
75
128
  for await (let c of collections) {
76
129
  // boucle sur les collections
77
130
  //console.log(c?.slug,c.init)
78
131
  if (c?.init && typeof c?.init == "function") {
79
132
  await c?.init({
80
133
  rest: new useRest({
81
- tenant_id: t.id,
134
+ tenant_id: t?.id,
82
135
  }),
83
136
  collection: c?.slug,
84
137
  });
85
138
  }
86
139
 
140
+ if (c?.cache?.enabled && c?.cache?.init) {
141
+ c?.cache?.init({
142
+ rest: new useRest({
143
+ tenant_id: t.id,
144
+ }),
145
+ state: c?.cache?.state || {},
146
+ });
147
+ }
148
+
87
149
  let collectionExist = collectionsInDatabase?.find(
88
150
  (col) => col?.name == c.slug
89
151
  );
package/lib/crypto.ts CHANGED
@@ -1,5 +1,4 @@
1
- import crypto from "node:crypto";
2
-
1
+ import cr from "node:crypto";
3
2
  class AES {
4
3
  #key;
5
4
  constructor(
@@ -10,16 +9,21 @@ class AES {
10
9
  }
11
10
  ) {
12
11
  // Crée une clé de 256 bits (32 octets) en utilisant un hachage SHA-256 de la clé secrète fournie
13
- this.#key = crypto.createHash("sha256").update(options.secretKey).digest();
12
+ this.#key = cr.createHash("sha256").update(options.secretKey).digest();
13
+ }
14
+
15
+ static generateKey(data: any) {
16
+ const stringData = typeof data === "string" ? data : JSON.stringify(data);
17
+ return cr.createHash("sha256").update(stringData).digest("hex");
14
18
  }
15
19
 
16
20
  // Fonction de chiffrement
17
21
  encrypt(data: string | object) {
18
22
  let dataEncoding = JSON.stringify(data);
19
- const iv = crypto.randomBytes(12); // Génère un IV de 12 octets pour AES-GCM
23
+ const iv = cr.randomBytes(12); // Génère un IV de 12 octets pour AES-GCM
20
24
 
21
25
  // Crée un objet de chiffrement avec AES-256-GCM, la clé et l'IV
22
- const cipher = crypto.createCipheriv("aes-256-gcm", this.#key, iv);
26
+ const cipher = cr.createCipheriv("aes-256-gcm", this.#key, iv);
23
27
 
24
28
  // Chiffre le message et convertit le texte chiffré en hexadécimal
25
29
  let encrypted = cipher.update(dataEncoding, "utf8", "hex");
@@ -42,7 +46,7 @@ class AES {
42
46
  const ciphertext = encryptedData.slice(56); // Extrait les données chiffrées
43
47
  */
44
48
  // Crée un objet de déchiffrement avec AES-256-GCM, la clé et l'IV
45
- const decipher = crypto.createDecipheriv(
49
+ const decipher = cr.createDecipheriv(
46
50
  "aes-256-gcm",
47
51
  this.#key,
48
52
  Buffer.from(iv, "hex")
@@ -65,4 +69,6 @@ const crypt = {
65
69
  AES,
66
70
  };
67
71
 
68
- export { crypt };
72
+ const crypto = crypt;
73
+
74
+ export { crypt, crypto };
package/lib/index.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { loadAllCollections, syncCollectionDatabase } from "./collection";
2
+ import { syncMeilisearchClientOnTenant } from "./meilisearch";
2
3
  import { connectTenantsDatabase } from "../driver";
3
4
  import { loadEndpoints } from "./endpoint";
4
5
  import { loadServices } from "./service";
@@ -9,6 +10,7 @@ import { loadAutoRoutes } from "./routes";
9
10
  import { initScript } from "../lib/scripts";
10
11
  import { syncAdapterFileSystem } from "./media";
11
12
  import { runGenTypes } from "../types/gen";
13
+
12
14
  // load all ressource
13
15
  async function init(cf = { app: null }) {
14
16
  await loadSocket();
@@ -23,6 +25,9 @@ async function init(cf = { app: null }) {
23
25
  // sync all collections database ( Indexes)
24
26
  syncCollectionDatabase();
25
27
 
28
+ // sync
29
+ syncMeilisearchClientOnTenant();
30
+
26
31
  // load Service
27
32
  loadServices();
28
33
 
@@ -0,0 +1,25 @@
1
+ import { MeiliSearch } from "meilisearch";
2
+ import { Cfg } from "../../config";
3
+ function getClient(config: {
4
+ host: string;
5
+ apiKey?: string;
6
+ }): InstanceType<typeof MeiliSearch> {
7
+ const client = new MeiliSearch({
8
+ host: config?.host,
9
+ apiKey: config?.apiKey,
10
+ });
11
+ return client;
12
+ }
13
+
14
+ async function syncMeilisearchClientOnTenant() {
15
+ for await (let t of Cfg.tenants) {
16
+ if (t?.searchEngine?.meilisearch?.enabled) {
17
+ t.searchEngine.meilisearch.client = getClient({
18
+ host: t.searchEngine.meilisearch.host,
19
+ apiKey: t.searchEngine.meilisearch.apiKey,
20
+ });
21
+ }
22
+ }
23
+ }
24
+
25
+ export { MeiliSearch, getClient, syncMeilisearchClientOnTenant };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dnax/core",
3
- "version": "0.52.2",
3
+ "version": "0.52.4",
4
4
  "module": "index.ts",
5
5
  "type": "module",
6
6
  "bin": {
@@ -41,6 +41,7 @@
41
41
  "joi": "17.13.3",
42
42
  "json-joy": "16.8.0",
43
43
  "jsonwebtoken": "^9.0.2",
44
+ "meilisearch": "^0.50.0",
44
45
  "mime-types": "^2.1.35",
45
46
  "mingo": "^6.5.0",
46
47
  "moment": "^2.30.1",
package/types/index.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import type { AnySchema } from "joi";
2
2
  import { Cron } from "croner";
3
- import { updateParams } from "./../driver/mongo/@types";
4
- import * as v from "valibot";
3
+ //import type{ updateParams } from "./../driver/mongo/@types";
4
+ //import * as v from "valibot";
5
5
  import type { Db, MongoClient } from "mongodb";
6
6
 
7
7
  import { useRest } from "../driver/mongo/rest";
@@ -19,6 +19,7 @@ import type {
19
19
  } from "../driver/mongo/@types";
20
20
  import type { RouterRoute } from "hono/types";
21
21
  import type { MongoClientOptions } from "mongodb";
22
+ import type { SearchParams } from "meilisearch";
22
23
  export type Socket = {
23
24
  enabled: boolean;
24
25
  exec: (ctx: { rest: useRest; io: socketIoType }) => void;
@@ -29,8 +30,17 @@ export type Tenant = {
29
30
  name?: string;
30
31
  enabled?: boolean;
31
32
  dir: string;
33
+ searchEngine?: {
34
+ meilisearch?: {
35
+ enabled?: boolean;
36
+ host: string;
37
+ apiKey: string;
38
+
39
+ client?: InstanceType<typeof import("meilisearch").MeiliSearch>;
40
+ };
41
+ };
32
42
  database: {
33
- driver: "mongodb";
43
+ driver?: "mongodb";
34
44
  /**
35
45
  * Connection URI string to connect
36
46
  */
@@ -54,7 +64,8 @@ export type Actions =
54
64
  | "deleteMany"
55
65
  | "authCollection"
56
66
  | "aggregate"
57
- | "upload";
67
+ | "upload"
68
+ | "search";
58
69
 
59
70
  type omitWhenType = "insertOne" | "insertMany" | "updateOne" | "updateMany";
60
71
 
@@ -197,6 +208,10 @@ export type sessionCtx = {
197
208
  };
198
209
 
199
210
  export type hooksCtx = (ctx: {
211
+ search?: {
212
+ term: string;
213
+ options: SearchParams;
214
+ };
200
215
  filter?: any;
201
216
  result?: any | null | object | undefined;
202
217
  driver?: "mongodb" | "postgres";
@@ -244,7 +259,7 @@ export type ctxApi = {
244
259
  rest: useRest;
245
260
  data?: any;
246
261
  session?: sessionCtx;
247
- io?: Io;
262
+ io?: socketIoType;
248
263
  params?: findParam;
249
264
  id?: string;
250
265
  ids?: string[];
@@ -288,20 +303,62 @@ export type Collection = {
288
303
  findOne?: (ctx: ctxApi) => object;
289
304
  count?: (ctx: ctxApi) => number;
290
305
  };
306
+ searchEngine?: {
307
+ meilisearch: {
308
+ /**
309
+ * unique name of the index on meilisearch
310
+ */
311
+ index: string;
312
+ primaryKey?: string;
313
+ /**
314
+ * default value :auto
315
+ */
316
+ dispatchAction: "auto" | "manual";
317
+ filterableAttributes?: Array<string>;
318
+ };
319
+ };
291
320
  /**
292
321
  * Cache available for action 'find' | 'findOne'
293
322
  */
294
323
  cache?: {
295
324
  enabled?: boolean;
296
- ttl: string;
297
- triggerEvents: ["find", "findOne"];
298
- /**
299
- * Overwrite cache bahavior
300
- * @param ctx
301
- * @returns <any>
302
- */
303
- customCache?: (ctx: {
304
- action: "find" | "findOne";
325
+ state?: {
326
+ [key: string]: any;
327
+ };
328
+ init?: (ctx: {
329
+ rest: InstanceType<typeof useRest>;
330
+ state: {
331
+ [key: string]: any;
332
+ };
333
+ }) => void;
334
+ watch: (ctx: {
335
+ action:
336
+ | "insertOne"
337
+ | "insertMany"
338
+ | "updateOne"
339
+ | "updateMany"
340
+ | "deleteOne"
341
+ | "deleteMany"
342
+ | "findOneAndUpdate";
343
+ rest: InstanceType<typeof useRest>;
344
+ c?: Context;
345
+ session?: sessionCtx;
346
+ result: any;
347
+ state: {
348
+ [key: string]: any;
349
+ };
350
+ }) => void;
351
+ fetch?: (ctx: {
352
+ state: {
353
+ [key: string]: any;
354
+ };
355
+ body: {
356
+ params: findParam;
357
+ pipeline: Array<object>;
358
+ withMeta: boolean;
359
+ };
360
+ key: string;
361
+ action: "find" | "aggregate";
305
362
  rest: InstanceType<typeof useRest>;
306
363
  c: Context;
307
364
  session: sessionCtx;
@@ -340,6 +397,8 @@ export type Collection = {
340
397
  afterCount?: hooksCtx;
341
398
  beforeUpload?: hooksCtx;
342
399
  afterUpload?: hooksCtx;
400
+ beforeSearch?: hooksCtx;
401
+ afterSearch?: hooksCtx;
343
402
  };
344
403
  access?: {
345
404
  "*"?: accessCtx;
@@ -357,9 +416,11 @@ export type Collection = {
357
416
  aggregate?: accessCtx;
358
417
  upload?: accessCtx;
359
418
  count?: accessCtx;
419
+ search?: accessCtx;
360
420
  };
361
421
  tenant_id?: string;
362
422
  slug: string;
423
+ privateFields?: string[];
363
424
  timestamps?: boolean;
364
425
  description?: string;
365
426
  fields?: Field[];
@@ -542,7 +603,8 @@ export type Q = {
542
603
  | "execService"
543
604
  | "batch"
544
605
  | "count"
545
- | "execToolkit";
606
+ | "execToolkit"
607
+ | "search";
546
608
  };
547
609
 
548
610
  export type routeOption = {