@rubixstudios/payload-typesense 1.1.1 → 1.1.2

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.
Files changed (102) hide show
  1. package/README.md +1 -17
  2. package/dist/components/HeadlessSearchInput.d.ts +2 -92
  3. package/dist/components/HeadlessSearchInput.d.ts.map +1 -1
  4. package/dist/components/HeadlessSearchInput.js +23 -140
  5. package/dist/components/ThemeProvider.d.ts +3 -2
  6. package/dist/components/ThemeProvider.d.ts.map +1 -1
  7. package/dist/components/ThemeProvider.js +1 -1
  8. package/dist/components/index.d.ts +5 -5
  9. package/dist/components/index.d.ts.map +1 -1
  10. package/dist/components/index.js +3 -3
  11. package/dist/components/themes/hooks.d.ts +5 -5
  12. package/dist/components/themes/hooks.d.ts.map +1 -1
  13. package/dist/components/themes/hooks.js +16 -16
  14. package/dist/components/themes/index.d.ts +4 -4
  15. package/dist/components/themes/index.js +4 -4
  16. package/dist/components/themes/themes.d.ts +1 -1
  17. package/dist/components/themes/themes.d.ts.map +1 -1
  18. package/dist/components/themes/themes.js +109 -109
  19. package/dist/components/themes/types.d.ts.map +1 -1
  20. package/dist/components/themes/utils.d.ts +1 -1
  21. package/dist/components/themes/utils.d.ts.map +1 -1
  22. package/dist/components/themes/utils.js +140 -140
  23. package/dist/endpoints/handler/createAdvancedSearch.d.ts +5 -0
  24. package/dist/endpoints/handler/createAdvancedSearch.d.ts.map +1 -0
  25. package/dist/endpoints/handler/createAdvancedSearch.js +40 -0
  26. package/dist/endpoints/handler/createCollections.d.ts +4 -0
  27. package/dist/endpoints/handler/createCollections.d.ts.map +1 -0
  28. package/dist/endpoints/handler/createCollections.js +23 -0
  29. package/dist/endpoints/handler/createSearch.d.ts +5 -0
  30. package/dist/endpoints/handler/createSearch.d.ts.map +1 -0
  31. package/dist/endpoints/handler/createSearch.js +119 -0
  32. package/dist/endpoints/handler/createSuggest.d.ts +5 -0
  33. package/dist/endpoints/handler/createSuggest.d.ts.map +1 -0
  34. package/dist/endpoints/handler/createSuggest.js +50 -0
  35. package/dist/endpoints/health.d.ts +4 -10
  36. package/dist/endpoints/health.d.ts.map +1 -1
  37. package/dist/endpoints/health.js +45 -103
  38. package/dist/endpoints/search.d.ts +4 -5
  39. package/dist/endpoints/search.d.ts.map +1 -1
  40. package/dist/endpoints/search.js +26 -355
  41. package/dist/index.d.ts +3 -3
  42. package/dist/index.d.ts.map +1 -1
  43. package/dist/index.js +6 -101
  44. package/dist/lib/cache.d.ts +6 -27
  45. package/dist/lib/cache.d.ts.map +1 -1
  46. package/dist/lib/cache.js +11 -29
  47. package/dist/lib/client.d.ts +4 -0
  48. package/dist/lib/client.d.ts.map +1 -0
  49. package/dist/lib/{typesense-client.js → client.js} +10 -18
  50. package/dist/lib/headlessSearch.d.ts +89 -0
  51. package/dist/lib/headlessSearch.d.ts.map +1 -0
  52. package/dist/lib/headlessSearch.js +2 -0
  53. package/dist/lib/hooks.d.ts +12 -3
  54. package/dist/lib/hooks.d.ts.map +1 -1
  55. package/dist/lib/hooks.js +37 -37
  56. package/dist/lib/initialization.d.ts +3 -3
  57. package/dist/lib/initialization.d.ts.map +1 -1
  58. package/dist/lib/initialization.js +36 -49
  59. package/dist/lib/schema-mapper.d.ts +17 -7
  60. package/dist/lib/schema-mapper.d.ts.map +1 -1
  61. package/dist/lib/schema-mapper.js +53 -89
  62. package/dist/lib/{config-validation.d.ts → validation.d.ts} +18 -22
  63. package/dist/lib/validation.d.ts.map +1 -0
  64. package/dist/lib/{config-validation.js → validation.js} +32 -49
  65. package/dist/{lib/types.d.ts → types.d.ts} +22 -5
  66. package/dist/types.d.ts.map +1 -0
  67. package/dist/utils/buildError.d.ts +2 -0
  68. package/dist/utils/buildError.d.ts.map +1 -0
  69. package/dist/utils/buildError.js +10 -0
  70. package/dist/utils/ensureCollection.d.ts +3 -0
  71. package/dist/utils/ensureCollection.d.ts.map +1 -0
  72. package/dist/utils/ensureCollection.js +13 -0
  73. package/dist/utils/extractText.d.ts +2 -0
  74. package/dist/utils/extractText.d.ts.map +1 -0
  75. package/dist/utils/extractText.js +20 -0
  76. package/dist/utils/getAllCollections.d.ts +9 -0
  77. package/dist/utils/getAllCollections.d.ts.map +1 -0
  78. package/dist/utils/getAllCollections.js +84 -0
  79. package/dist/utils/getCacheStats.d.ts +6 -0
  80. package/dist/utils/getCacheStats.d.ts.map +1 -0
  81. package/dist/utils/getCacheStats.js +9 -0
  82. package/dist/utils/getCollectionInfo.d.ts +3 -0
  83. package/dist/utils/getCollectionInfo.d.ts.map +1 -0
  84. package/dist/utils/getCollectionInfo.js +8 -0
  85. package/dist/utils/keyboard.d.ts +8 -0
  86. package/dist/utils/keyboard.d.ts.map +1 -0
  87. package/dist/utils/keyboard.js +41 -0
  88. package/dist/utils/testConnection.d.ts +3 -0
  89. package/dist/utils/testConnection.d.ts.map +1 -0
  90. package/dist/utils/testConnection.js +8 -0
  91. package/dist/utils/useDebounce.d.ts +2 -0
  92. package/dist/utils/useDebounce.d.ts.map +1 -0
  93. package/dist/utils/useDebounce.js +15 -0
  94. package/dist/utils/useSearch.d.ts +17 -0
  95. package/dist/utils/useSearch.d.ts.map +1 -0
  96. package/dist/utils/useSearch.js +78 -0
  97. package/package.json +12 -9
  98. package/dist/lib/config-validation.d.ts.map +0 -1
  99. package/dist/lib/types.d.ts.map +0 -1
  100. package/dist/lib/typesense-client.d.ts +0 -5
  101. package/dist/lib/typesense-client.d.ts.map +0 -1
  102. /package/dist/{lib/types.js → types.js} +0 -0
@@ -1,373 +1,44 @@
1
- import { searchCache } from "../lib/cache.js";
2
- import { getValidationErrors, validateSearchParams } from "../lib/config-validation.js";
3
- import { createDetailedHealthCheckHandler, createHealthCheckHandler } from "./health.js";
4
- // Universal search across all collections
5
- const searchAllCollections = async (typesenseClient, pluginOptions, query, options)=>{
6
- try {
7
- // Check cache first
8
- const cachedResult = searchCache.get(query, "universal", options);
9
- if (cachedResult) {
10
- // Return cached result
11
- return Response.json(cachedResult);
12
- }
13
- const enabledCollections = Object.entries(pluginOptions.collections || {}).filter(([_, config])=>config?.enabled);
14
- // Process enabled collections
15
- if (enabledCollections.length === 0) {
16
- return Response.json({
17
- error: "No collections enabled for search"
18
- }, {
19
- status: 400
20
- });
21
- }
22
- // Search all collections in parallel
23
- const searchPromises = enabledCollections.map(async ([collectionName, config])=>{
24
- try {
25
- const searchParameters = {
26
- highlight_full_fields: config?.searchFields?.join(",") || "title,content",
27
- num_typos: 0,
28
- page: options.page,
29
- per_page: Math.ceil(options.per_page / enabledCollections.length),
30
- q: query,
31
- query_by: config?.searchFields?.join(",") || "title,content",
32
- snippet_threshold: 30,
33
- typo_tokens_threshold: 1
34
- };
35
- // Search collection
36
- const results = await typesenseClient.collections(collectionName).documents().search(searchParameters);
37
- // Add collection metadata to each hit
38
- return {
39
- collection: collectionName,
40
- displayName: config?.displayName || collectionName,
41
- icon: config?.icon || "📄",
42
- ...results,
43
- hits: results.hits?.map((hit)=>({
44
- ...hit,
45
- collection: collectionName,
46
- displayName: config?.displayName || collectionName,
47
- icon: config?.icon || "📄"
48
- })) || []
49
- };
50
- } catch (_error) {
51
- // Handle search error
52
- return {
53
- collection: collectionName,
54
- displayName: config?.displayName || collectionName,
55
- error: _error instanceof Error ? _error.message : "Unknown error",
56
- found: 0,
57
- hits: [],
58
- icon: config?.icon || "📄"
59
- };
60
- }
61
- });
62
- const results = await Promise.all(searchPromises);
63
- // Combine results
64
- const combinedHits = results.flatMap((result)=>result.hits || []);
65
- const totalFound = results.reduce((sum, result)=>sum + (result.found || 0), 0);
66
- // Sort combined results by relevance (text_match score)
67
- combinedHits.sort((a, b)=>(b.text_match || 0) - (a.text_match || 0));
68
- const searchResult = {
69
- collections: results.map((r)=>({
70
- collection: r.collection,
71
- displayName: r.displayName,
72
- error: r.error,
73
- found: r.found || 0,
74
- icon: r.icon
75
- })),
76
- found: totalFound,
77
- hits: combinedHits.slice(0, options.per_page),
78
- page: options.page,
79
- request_params: {
80
- per_page: options.per_page,
81
- q: query
82
- },
83
- search_cutoff: false,
84
- search_time_ms: 0
85
- };
86
- // Cache the result
87
- searchCache.set(query, searchResult, "universal", options);
88
- return Response.json(searchResult);
89
- } catch (error) {
90
- // Handle universal search error
91
- return Response.json({
92
- details: error instanceof Error ? error.message : "Unknown error",
93
- error: "Universal search failed"
94
- }, {
95
- status: 500
96
- });
97
- }
98
- };
1
+ import { createAdvancedSearch } from './handler/createAdvancedSearch.js';
2
+ import { createCollections } from './handler/createCollections.js';
3
+ import { createSearch } from './handler/createSearch.js';
4
+ import { createSuggest } from './handler/createSuggest.js';
5
+ import { createDetailedHealthCheck, createHealthCheck } from './health.js';
99
6
  export const createSearchEndpoints = (typesenseClient, pluginOptions, lastSyncTime)=>{
100
7
  return [
101
8
  {
102
- handler: createCollectionsHandler(pluginOptions),
103
- method: "get",
104
- path: "/search/collections"
9
+ handler: createCollections(pluginOptions),
10
+ method: 'get',
11
+ path: '/search/collections'
105
12
  },
106
13
  {
107
- handler: createSuggestHandler(typesenseClient, pluginOptions),
108
- method: "get",
109
- path: "/search/:collectionName/suggest"
14
+ handler: createSuggest(typesenseClient, pluginOptions),
15
+ method: 'get',
16
+ path: '/search/:collectionName/suggest'
110
17
  },
111
18
  {
112
- handler: createSearchHandler(typesenseClient, pluginOptions),
113
- method: "get",
114
- path: "/search/:collectionName"
19
+ handler: createSearch(typesenseClient, pluginOptions),
20
+ method: 'get',
21
+ path: '/search/:collectionName'
115
22
  },
116
23
  {
117
- handler: createAdvancedSearchHandler(typesenseClient, pluginOptions),
118
- method: "post",
119
- path: "/search/:collectionName"
24
+ handler: createAdvancedSearch(typesenseClient, pluginOptions),
25
+ method: 'post',
26
+ path: '/search/:collectionName'
120
27
  },
121
28
  {
122
- handler: createSearchHandler(typesenseClient, pluginOptions),
123
- method: "get",
124
- path: "/search"
29
+ handler: createSearch(typesenseClient, pluginOptions),
30
+ method: 'get',
31
+ path: '/search'
125
32
  },
126
33
  {
127
- handler: createHealthCheckHandler(typesenseClient, pluginOptions, lastSyncTime),
128
- method: "get",
129
- path: "/search/health"
34
+ handler: createHealthCheck(typesenseClient, pluginOptions, lastSyncTime),
35
+ method: 'get',
36
+ path: '/search/health'
130
37
  },
131
38
  {
132
- handler: createDetailedHealthCheckHandler(typesenseClient, pluginOptions, lastSyncTime),
133
- method: "get",
134
- path: "/search/health/detailed"
39
+ handler: createDetailedHealthCheck(typesenseClient, pluginOptions, lastSyncTime),
40
+ method: 'get',
41
+ path: '/search/health/detailed'
135
42
  }
136
43
  ];
137
44
  };
138
- const createSearchHandler = (typesenseClient, pluginOptions)=>{
139
- return async (request)=>{
140
- try {
141
- // Extract query parameters from the request
142
- const { params, query } = request;
143
- // Extract collection name from URL path (fallback to params if available)
144
- let collectionName;
145
- let collectionNameStr;
146
- if (request.url && typeof request.url === "string") {
147
- const url = new URL(request.url);
148
- const pathParts = url.pathname.split("/");
149
- const searchIndex = pathParts.indexOf("search");
150
- if (searchIndex !== -1 && pathParts[searchIndex + 1]) {
151
- collectionName = pathParts[searchIndex + 1] || "";
152
- collectionNameStr = String(collectionName);
153
- } else {
154
- collectionName = "";
155
- collectionNameStr = "";
156
- }
157
- } else {
158
- // Fallback to params extraction
159
- const { collectionName: paramCollectionName } = params || {};
160
- collectionName = String(paramCollectionName || "");
161
- collectionNameStr = collectionName;
162
- }
163
- // Extract search parameters
164
- const q = typeof query?.q === "string" ? query.q : "";
165
- const pageParam = query?.page;
166
- const perPageParam = query?.per_page;
167
- const page = typeof pageParam === "string" || typeof pageParam === "number" ? parseInt(String(pageParam), 10) : 1;
168
- const per_page = typeof perPageParam === "string" || typeof perPageParam === "number" ? parseInt(String(perPageParam), 10) : 10;
169
- const sort_by = query?.sort_by;
170
- // Validate parsed numbers
171
- if (isNaN(page) || page < 1) {
172
- return Response.json({
173
- error: "Invalid page parameter"
174
- }, {
175
- status: 400
176
- });
177
- }
178
- if (isNaN(per_page) || per_page < 1 || per_page > 250) {
179
- return Response.json({
180
- error: "Invalid per_page parameter"
181
- }, {
182
- status: 400
183
- });
184
- }
185
- // Process search request
186
- // Validate search parameters
187
- const searchParams = {
188
- page,
189
- per_page,
190
- q,
191
- sort_by: sort_by
192
- };
193
- const validation = validateSearchParams(searchParams);
194
- if (!validation.success) {
195
- return Response.json({
196
- details: getValidationErrors(validation.errors || []),
197
- error: "Invalid search parameters"
198
- }, {
199
- status: 400
200
- });
201
- }
202
- // If no collection specified, search across all enabled collections
203
- if (!collectionName) {
204
- if (!q || q.trim() === "") {
205
- return Response.json({
206
- details: "Please provide a search query using ?q=your_search_term",
207
- error: 'Query parameter "q" is required',
208
- example: "/api/search?q=example"
209
- }, {
210
- status: 400
211
- });
212
- }
213
- const searchOptions = {
214
- filters: {},
215
- page,
216
- per_page
217
- };
218
- if (sort_by && typeof sort_by === "string") {
219
- searchOptions.sort_by = sort_by;
220
- }
221
- return await searchAllCollections(typesenseClient, pluginOptions, q, searchOptions);
222
- }
223
- // Validate collection is enabled
224
- if (!pluginOptions.collections?.[collectionNameStr]?.enabled) {
225
- return Response.json({
226
- error: "Collection not enabled for search"
227
- }, {
228
- status: 400
229
- });
230
- }
231
- if (!q) {
232
- return Response.json({
233
- error: 'Query parameter "q" is required'
234
- }, {
235
- status: 400
236
- });
237
- }
238
- const searchParameters = {
239
- highlight_full_fields: pluginOptions.collections?.[collectionNameStr]?.searchFields?.join(",") || "title,content",
240
- num_typos: 0,
241
- page: Number(page),
242
- per_page: Number(per_page),
243
- q: String(q),
244
- query_by: pluginOptions.collections?.[collectionNameStr]?.searchFields?.join(",") || "title,content",
245
- snippet_threshold: 30,
246
- typo_tokens_threshold: 1
247
- };
248
- // Add sorting
249
- if (sort_by && typeof sort_by === "string") {
250
- searchParameters.sort_by = sort_by;
251
- }
252
- // Execute Typesense search
253
- // Check cache first
254
- const cacheOptions = {
255
- collection: collectionName,
256
- page,
257
- per_page,
258
- sort_by
259
- };
260
- const cachedResult = searchCache.get(q, collectionNameStr, cacheOptions);
261
- if (cachedResult) {
262
- // Return cached result
263
- return Response.json(cachedResult);
264
- }
265
- const searchResults = await typesenseClient.collections(collectionNameStr).documents().search(searchParameters);
266
- // Process search results
267
- // Cache the result
268
- searchCache.set(q, searchResults, collectionNameStr, cacheOptions);
269
- return Response.json(searchResults);
270
- } catch (_error) {
271
- // Handle search error
272
- return Response.json({
273
- details: _error instanceof Error ? _error.message : "Unknown error",
274
- error: "Search handler failed"
275
- }, {
276
- status: 500
277
- });
278
- }
279
- };
280
- };
281
- const createAdvancedSearchHandler = (typesenseClient, pluginOptions)=>{
282
- return async (request)=>{
283
- const { params, req } = request;
284
- const { collectionName } = params || {};
285
- const collectionNameStr = String(collectionName || "");
286
- const body = await req?.json?.() || {};
287
- if (!pluginOptions.collections?.[collectionNameStr]?.enabled) {
288
- return Response.json({
289
- error: "Collection not enabled for search"
290
- }, {
291
- status: 400
292
- });
293
- }
294
- try {
295
- const searchResults = await typesenseClient.collections(collectionNameStr).documents().search(body);
296
- return Response.json(searchResults);
297
- } catch (_error) {
298
- // Handle advanced search error
299
- return Response.json({
300
- error: "Advanced search failed"
301
- }, {
302
- status: 500
303
- });
304
- }
305
- };
306
- };
307
- const createSuggestHandler = (typesenseClient, pluginOptions)=>{
308
- return async (request)=>{
309
- // Extract collection name from URL path
310
- const url = new URL(request.url);
311
- const pathParts = url.pathname.split("/");
312
- const collectionName = pathParts[pathParts.indexOf("search") + 1];
313
- const collectionNameStr = String(collectionName || "");
314
- // Extract query parameters
315
- const q = url.searchParams.get("q");
316
- const limit = url.searchParams.get("limit") || "5";
317
- if (!collectionName || !pluginOptions.collections?.[collectionNameStr]?.enabled) {
318
- return Response.json({
319
- error: "Collection not enabled for search"
320
- }, {
321
- status: 400
322
- });
323
- }
324
- if (!q) {
325
- return Response.json({
326
- error: 'Query parameter "q" is required'
327
- }, {
328
- status: 400
329
- });
330
- }
331
- try {
332
- const suggestResults = await typesenseClient.collections(collectionNameStr).documents().search({
333
- highlight_full_fields: pluginOptions.collections?.[collectionNameStr]?.searchFields?.join(",") || "title,content",
334
- per_page: Number(limit),
335
- q,
336
- query_by: pluginOptions.collections?.[collectionNameStr]?.searchFields?.join(",") || "title,content",
337
- snippet_threshold: 30
338
- });
339
- return Response.json(suggestResults);
340
- } catch (_error) {
341
- // Handle suggest error
342
- return Response.json({
343
- error: "Suggest failed"
344
- }, {
345
- status: 500
346
- });
347
- }
348
- };
349
- };
350
- const createCollectionsHandler = (pluginOptions)=>{
351
- return ()=>{
352
- try {
353
- const collections = Object.entries(pluginOptions.collections || {}).filter(([_, config])=>config?.enabled).map(([slug, config])=>({
354
- slug,
355
- displayName: config?.displayName || slug.charAt(0).toUpperCase() + slug.slice(1),
356
- facetFields: config?.facetFields || [],
357
- icon: config?.icon || "📄",
358
- searchFields: config?.searchFields || []
359
- }));
360
- return Response.json({
361
- categorized: pluginOptions.settings?.categorized || false,
362
- collections
363
- });
364
- } catch (_error) {
365
- // Handle collections error
366
- return Response.json({
367
- error: "Failed to get collections"
368
- }, {
369
- status: 500
370
- });
371
- }
372
- };
373
- };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import type { Config } from "payload";
2
- export * from "./components/index.js";
1
+ import type { Config } from 'payload';
2
+ export * from './components/index.js';
3
3
  export type TypesenseSearchConfig = {
4
4
  /**
5
5
  * Collections to index in Typesense
@@ -31,7 +31,7 @@ export type TypesenseSearchConfig = {
31
31
  nodes: Array<{
32
32
  host: string;
33
33
  port: number | string;
34
- protocol: "http" | "https";
34
+ protocol: 'http' | 'https';
35
35
  }>;
36
36
  };
37
37
  };
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAQrC,cAAc,uBAAuB,CAAA;AAErC,MAAM,MAAM,qBAAqB,GAAG;IACnC;;OAEG;IACH,WAAW,CAAC,EAAE,OAAO,CACpB,MAAM,CACL,MAAM,EACN;QACC,WAAW,CAAC,EAAE,MAAM,CAAA;QACpB,OAAO,EAAE,OAAO,CAAA;QAChB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;QACtB,IAAI,CAAC,EAAE,MAAM,CAAA;QACb,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;QACvB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;KACrB,CACD,CACD,CAAA;IAED,QAAQ,CAAC,EAAE,OAAO,CAAA;IAElB;;OAEG;IACH,QAAQ,CAAC,EAAE;QACV,QAAQ,CAAC,EAAE,OAAO,CAAA;QAClB,SAAS,CAAC,EAAE,MAAM,CAAA;QAClB,WAAW,CAAC,EAAE,OAAO,CAAA;QACrB,cAAc,CAAC,EAAE,MAAM,CAAA;KACvB,CAAA;IAED;;OAEG;IACH,SAAS,EAAE;QACV,MAAM,EAAE,MAAM,CAAA;QACd,wBAAwB,CAAC,EAAE,MAAM,CAAA;QACjC,KAAK,EAAE,KAAK,CAAC;YACZ,IAAI,EAAE,MAAM,CAAA;YACZ,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;YACrB,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAA;SAC1B,CAAC,CAAA;KACF,CAAA;CACD,CAAA;AAED,eAAO,MAAM,eAAe,GAC1B,eAAe,qBAAqB,MACpC,QAAQ,MAAM,KAAG,MAwEjB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAOrC,cAAc,uBAAuB,CAAA;AAErC,MAAM,MAAM,qBAAqB,GAAG;IAClC;;OAEG;IACH,WAAW,CAAC,EAAE,OAAO,CACnB,MAAM,CACJ,MAAM,EACN;QACE,WAAW,CAAC,EAAE,MAAM,CAAA;QACpB,OAAO,EAAE,OAAO,CAAA;QAChB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;QACtB,IAAI,CAAC,EAAE,MAAM,CAAA;QACb,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;QACvB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;KACtB,CACF,CACF,CAAA;IAED,QAAQ,CAAC,EAAE,OAAO,CAAA;IAElB;;OAEG;IACH,QAAQ,CAAC,EAAE;QACT,QAAQ,CAAC,EAAE,OAAO,CAAA;QAClB,SAAS,CAAC,EAAE,MAAM,CAAA;QAClB,WAAW,CAAC,EAAE,OAAO,CAAA;QACrB,cAAc,CAAC,EAAE,MAAM,CAAA;KACxB,CAAA;IAED;;OAEG;IACH,SAAS,EAAE;QACT,MAAM,EAAE,MAAM,CAAA;QACd,wBAAwB,CAAC,EAAE,MAAM,CAAA;QACjC,KAAK,EAAE,KAAK,CAAC;YACX,IAAI,EAAE,MAAM,CAAA;YACZ,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;YACrB,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAA;SAC3B,CAAC,CAAA;KACH,CAAA;CACF,CAAA;AAED,eAAO,MAAM,eAAe,GACzB,eAAe,qBAAqB,MACpC,QAAQ,MAAM,KAAG,MA6DjB,CAAA"}
package/dist/index.js CHANGED
@@ -1,14 +1,14 @@
1
- import { createSearchEndpoints } from "./endpoints/search.js";
2
- import { initializeTypesenseCollections } from "./lib/initialization.js";
3
- import { mapPayloadDocumentToTypesense } from "./lib/schema-mapper.js";
4
- import { createTypesenseClient } from "./lib/typesense-client.js";
5
- export * from "./components/index.js";
1
+ import { createSearchEndpoints } from './endpoints/search.js';
2
+ import { createClient } from './lib/client.js';
3
+ import { deleteDocumentFromTypesense, syncDocumentToTypesense } from './lib/hooks.js';
4
+ import { initializeTypesenseCollections } from './lib/initialization.js';
5
+ export * from './components/index.js';
6
6
  export const typesenseSearch = (pluginOptions)=>(config)=>{
7
7
  if (pluginOptions.disabled) {
8
8
  return config;
9
9
  }
10
10
  // Initialize Typesense client
11
- const typesenseClient = createTypesenseClient(pluginOptions.typesense);
11
+ const typesenseClient = createClient(pluginOptions.typesense);
12
12
  // Add search endpoints
13
13
  config.endpoints = [
14
14
  ...config.endpoints || [],
@@ -51,98 +51,3 @@ export const typesenseSearch = (pluginOptions)=>(config)=>{
51
51
  };
52
52
  return config;
53
53
  };
54
- // Helper function to create collection if it doesn't exist
55
- const createCollectionIfNotExists = async (typesenseClient, collectionSlug, config)=>{
56
- const searchableFields = config?.searchFields || [
57
- "title",
58
- "content",
59
- "description"
60
- ];
61
- const facetFields = config?.facetFields || [];
62
- // Base fields that every collection should have
63
- const baseFields = [
64
- {
65
- name: "id",
66
- type: "string"
67
- },
68
- {
69
- name: "createdAt",
70
- type: "int64"
71
- },
72
- {
73
- name: "updatedAt",
74
- type: "int64"
75
- }
76
- ];
77
- // Map searchable fields
78
- const searchFields = searchableFields.map((field)=>({
79
- name: field,
80
- type: "string",
81
- facet: facetFields.includes(field)
82
- }));
83
- // Map facet-only fields (not in searchable fields)
84
- const facetOnlyFields = facetFields.filter((field)=>!searchableFields.includes(field)).map((field)=>({
85
- name: field,
86
- type: "string",
87
- facet: true
88
- }));
89
- const schema = {
90
- name: collectionSlug,
91
- fields: [
92
- ...baseFields,
93
- ...searchFields,
94
- ...facetOnlyFields
95
- ]
96
- };
97
- await typesenseClient.collections().create(schema);
98
- // Collection created successfully
99
- };
100
- // Sync functions for hooks
101
- const syncDocumentToTypesense = async (typesenseClient, collectionSlug, doc, operation, config)=>{
102
- try {
103
- // First check if the collection exists, create it if it doesn't
104
- try {
105
- await typesenseClient.collections(collectionSlug).retrieve();
106
- } catch (collectionError) {
107
- if (collectionError.httpStatus === 404) {
108
- // Collection not found, creating it
109
- await createCollectionIfNotExists(typesenseClient, collectionSlug, config);
110
- } else {
111
- throw collectionError;
112
- }
113
- }
114
- const typesenseDoc = mapPayloadDocumentToTypesense(doc, collectionSlug, config);
115
- await typesenseClient.collections(collectionSlug).documents().upsert(typesenseDoc);
116
- // Document synced successfully
117
- } catch (error) {
118
- // Handle document sync error
119
- // Log the problematic document for debugging
120
- if (error.message.includes("validation")) {
121
- // Log problematic document details
122
- }
123
- }
124
- };
125
- const deleteDocumentFromTypesense = async (typesenseClient, collectionSlug, docId)=>{
126
- try {
127
- // First check if the collection exists
128
- try {
129
- await typesenseClient.collections(collectionSlug).retrieve();
130
- } catch (collectionError) {
131
- if (collectionError.httpStatus === 404) {
132
- // Collection not found, skipping delete
133
- return;
134
- }
135
- throw collectionError;
136
- }
137
- // Try to delete the document
138
- await typesenseClient.collections(collectionSlug).documents(docId).delete();
139
- // Document deleted successfully
140
- } catch (error) {
141
- // Handle specific error cases
142
- if (error.httpStatus === 404) {
143
- // Document not found, already deleted
144
- } else {
145
- // Handle document deletion error
146
- }
147
- }
148
- };
@@ -1,41 +1,20 @@
1
- import type { CacheOptions } from "./types.js";
2
- export declare class SearchCache<T = any> {
1
+ import { type CacheOptions } from '../types.js';
2
+ export declare class SearchCache<T = unknown> {
3
3
  private cache;
4
4
  private readonly defaultTTL;
5
5
  private readonly maxSize;
6
6
  constructor(options?: CacheOptions);
7
- /**
8
- * Generate cache key from search parameters
9
- */
10
7
  private generateKey;
11
- /**
12
- * Clear expired entries
13
- */
14
8
  cleanup(): void;
15
- /**
16
- * Clear cache entries matching pattern
17
- */
18
9
  clear(pattern?: string): void;
19
- /**
20
- * Get cached search result
21
- */
22
- get(query: string, collection?: string, params?: Record<string, any>): null | T;
23
- /**
24
- * Get cache statistics
25
- */
10
+ get(query: string, collection?: string, params?: Record<string, unknown>): null | T;
26
11
  getStats(): {
27
12
  hitRate?: number;
28
13
  maxSize: number;
29
14
  size: number;
30
15
  };
31
- /**
32
- * Check if cache has valid entry
33
- */
34
- has(query: string, collection?: string, params?: Record<string, any>): boolean;
35
- /**
36
- * Set cached search result
37
- */
38
- set(query: string, data: T, collection?: string, params?: Record<string, any>, ttl?: number): void;
16
+ has(query: string, collection?: string, params?: Record<string, unknown>): boolean;
17
+ set(query: string, data: T, collection?: string, params?: Record<string, unknown>, ttl?: number): void;
39
18
  }
40
- export declare const searchCache: SearchCache<any>;
19
+ export declare const searchCache: SearchCache<unknown>;
41
20
  //# sourceMappingURL=cache.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/lib/cache.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAc,YAAY,EAAE,MAAM,YAAY,CAAA;AAE1D,qBAAa,WAAW,CAAC,CAAC,GAAG,GAAG;IAC/B,OAAO,CAAC,KAAK,CAAmC;IAChD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAQ;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAQ;gBAEpB,OAAO,GAAE,YAAiB;IAKtC;;OAEG;IACH,OAAO,CAAC,WAAW;IAgBnB;;OAEG;IACH,OAAO,IAAI,IAAI;IASf;;OAEG;IACH,KAAK,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI;IAa7B;;OAEG;IACH,GAAG,CACF,KAAK,EAAE,MAAM,EACb,UAAU,CAAC,EAAE,MAAM,EACnB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAC1B,IAAI,GAAG,CAAC;IAiBX;;OAEG;IACH,QAAQ,IAAI;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE;IAO/D;;OAEG;IACH,GAAG,CACF,KAAK,EAAE,MAAM,EACb,UAAU,CAAC,EAAE,MAAM,EACnB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAC1B,OAAO;IAIV;;OAEG;IACH,GAAG,CACF,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,CAAC,EACP,UAAU,CAAC,EAAE,MAAM,EACnB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC5B,GAAG,CAAC,EAAE,MAAM,GACV,IAAI;CAiBP;AAGD,eAAO,MAAM,WAAW,kBAGtB,CAAA"}
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/lib/cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,YAAY,EAAE,MAAM,aAAa,CAAA;AAEhE,qBAAa,WAAW,CAAC,CAAC,GAAG,OAAO;IAClC,OAAO,CAAC,KAAK,CAAmC;IAChD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAQ;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAQ;gBAEpB,OAAO,GAAE,YAAiB;IAKtC,OAAO,CAAC,WAAW;IAmBnB,OAAO,IAAI,IAAI;IASf,KAAK,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI;IAY7B,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC;IAgBnF,QAAQ,IAAI;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE;IAO/D,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO;IAIlF,GAAG,CACD,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,CAAC,EACP,UAAU,CAAC,EAAE,MAAM,EACnB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,GAAG,CAAC,EAAE,MAAM,GACX,IAAI;CAgBR;AAED,eAAO,MAAM,WAAW,sBAGtB,CAAA"}