@meeovi/layer-search 1.0.6 → 1.0.7

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 (150) hide show
  1. package/README.md +39 -5
  2. package/app/composables/bridges/searchkit-server.ts +51 -0
  3. package/app/composables/bridges/searchkit.ts +88 -0
  4. package/app/composables/index.ts +4 -1
  5. package/app/composables/module.ts +41 -0
  6. package/app/composables/utils/health.ts +13 -0
  7. package/app/plugins/search.js +1 -1
  8. package/app/utils/search/client.ts +40 -0
  9. package/dist/app/composables/adapter/meilisearch.d.ts +8 -0
  10. package/dist/app/composables/adapter/meilisearch.js +36 -0
  11. package/dist/app/composables/adapter/mock.d.ts +3 -0
  12. package/dist/app/composables/adapter/mock.js +19 -0
  13. package/dist/app/composables/adapter/opensearch.d.ts +8 -0
  14. package/dist/app/composables/adapter/opensearch.js +46 -0
  15. package/dist/app/composables/adapter/types.d.ts +12 -0
  16. package/dist/app/composables/adapter/types.js +1 -0
  17. package/dist/app/composables/bridges/instantsearch.d.ts +4 -0
  18. package/dist/app/composables/bridges/instantsearch.js +17 -0
  19. package/dist/app/composables/bridges/react.d.ts +12 -0
  20. package/dist/app/composables/bridges/react.js +34 -0
  21. package/dist/app/composables/bridges/vue.d.ts +9 -0
  22. package/dist/app/composables/bridges/vue.js +31 -0
  23. package/dist/app/composables/cli.d.ts +2 -0
  24. package/dist/app/composables/cli.js +69 -0
  25. package/dist/app/composables/config/schema.d.ts +5 -0
  26. package/dist/app/composables/config/schema.js +8 -0
  27. package/dist/app/composables/config.d.ts +7 -0
  28. package/dist/app/composables/config.js +11 -0
  29. package/dist/app/composables/core/Facets.d.ts +17 -0
  30. package/dist/app/composables/core/Facets.js +8 -0
  31. package/dist/app/composables/core/Filters.d.ts +18 -0
  32. package/dist/app/composables/core/Filters.js +11 -0
  33. package/dist/app/composables/core/Normalizers.d.ts +0 -0
  34. package/dist/app/composables/core/Normalizers.js +1 -0
  35. package/dist/app/composables/core/Pipeline.d.ts +8 -0
  36. package/dist/app/composables/core/Pipeline.js +16 -0
  37. package/dist/app/composables/core/QueryBuilder.d.ts +13 -0
  38. package/dist/app/composables/core/QueryBuilder.js +15 -0
  39. package/dist/app/composables/core/SearchContext.d.ts +18 -0
  40. package/dist/app/composables/core/SearchContext.js +38 -0
  41. package/dist/app/composables/core/SearchManager.d.ts +10 -0
  42. package/dist/app/composables/core/SearchManager.js +20 -0
  43. package/dist/app/composables/events.d.ts +11 -0
  44. package/dist/app/composables/events.js +1 -0
  45. package/dist/app/composables/index.d.ts +9 -0
  46. package/dist/app/composables/index.js +9 -0
  47. package/dist/app/composables/module.d.ts +17 -0
  48. package/dist/app/composables/module.js +39 -0
  49. package/dist/app/composables/types/api/global-search.d.ts +8 -0
  50. package/dist/app/composables/types/api/global-search.js +1 -0
  51. package/dist/app/composables/utils/normalizers.d.ts +1 -0
  52. package/dist/app/composables/utils/normalizers.js +6 -0
  53. package/dist/app/utils/search/client.d.ts +3 -0
  54. package/dist/app/utils/search/client.js +31 -0
  55. package/dist/layers/search/app/composables/adapter/meilisearch.d.ts +8 -0
  56. package/dist/layers/search/app/composables/adapter/meilisearch.js +36 -0
  57. package/dist/layers/search/app/composables/adapter/mock.d.ts +3 -0
  58. package/dist/layers/search/app/composables/adapter/mock.js +19 -0
  59. package/dist/layers/search/app/composables/adapter/opensearch.d.ts +8 -0
  60. package/dist/layers/search/app/composables/adapter/opensearch.js +46 -0
  61. package/dist/layers/search/app/composables/adapter/types.d.ts +12 -0
  62. package/dist/layers/search/app/composables/adapter/types.js +1 -0
  63. package/dist/layers/search/app/composables/bridges/instantsearch.d.ts +4 -0
  64. package/dist/layers/search/app/composables/bridges/instantsearch.js +17 -0
  65. package/dist/layers/search/app/composables/bridges/react.d.ts +12 -0
  66. package/dist/layers/search/app/composables/bridges/react.js +34 -0
  67. package/dist/layers/search/app/composables/bridges/searchkit-server.d.ts +3 -0
  68. package/dist/layers/search/app/composables/bridges/searchkit-server.js +44 -0
  69. package/dist/layers/search/app/composables/bridges/searchkit.d.ts +21 -0
  70. package/dist/layers/search/app/composables/bridges/searchkit.js +60 -0
  71. package/dist/layers/search/app/composables/bridges/vue.d.ts +9 -0
  72. package/dist/layers/search/app/composables/bridges/vue.js +31 -0
  73. package/dist/layers/search/app/composables/cli.d.ts +2 -0
  74. package/dist/layers/search/app/composables/cli.js +69 -0
  75. package/dist/layers/search/app/composables/config/schema.d.ts +5 -0
  76. package/dist/layers/search/app/composables/config/schema.js +8 -0
  77. package/dist/layers/search/app/composables/config.d.ts +7 -0
  78. package/dist/layers/search/app/composables/config.js +11 -0
  79. package/dist/layers/search/app/composables/core/Facets.d.ts +17 -0
  80. package/dist/layers/search/app/composables/core/Facets.js +8 -0
  81. package/dist/layers/search/app/composables/core/Filters.d.ts +18 -0
  82. package/dist/layers/search/app/composables/core/Filters.js +11 -0
  83. package/dist/layers/search/app/composables/core/Normalizers.d.ts +0 -0
  84. package/dist/layers/search/app/composables/core/Normalizers.js +1 -0
  85. package/dist/layers/search/app/composables/core/Pipeline.d.ts +8 -0
  86. package/dist/layers/search/app/composables/core/Pipeline.js +16 -0
  87. package/dist/layers/search/app/composables/core/QueryBuilder.d.ts +13 -0
  88. package/dist/layers/search/app/composables/core/QueryBuilder.js +15 -0
  89. package/dist/layers/search/app/composables/core/SearchContext.d.ts +18 -0
  90. package/dist/layers/search/app/composables/core/SearchContext.js +38 -0
  91. package/dist/layers/search/app/composables/core/SearchManager.d.ts +10 -0
  92. package/dist/layers/search/app/composables/core/SearchManager.js +20 -0
  93. package/dist/layers/search/app/composables/events.d.ts +11 -0
  94. package/dist/layers/search/app/composables/events.js +1 -0
  95. package/dist/layers/search/app/composables/index.d.ts +12 -0
  96. package/dist/layers/search/app/composables/index.js +12 -0
  97. package/dist/layers/search/app/composables/module.d.ts +17 -0
  98. package/dist/layers/search/app/composables/module.js +73 -0
  99. package/dist/layers/search/app/composables/types/api/global-search.d.ts +8 -0
  100. package/dist/layers/search/app/composables/types/api/global-search.js +1 -0
  101. package/dist/layers/search/app/composables/utils/health.d.ts +11 -0
  102. package/dist/layers/search/app/composables/utils/health.js +11 -0
  103. package/dist/layers/search/app/composables/utils/normalizers.d.ts +1 -0
  104. package/dist/layers/search/app/composables/utils/normalizers.js +6 -0
  105. package/dist/layers/search/app/utils/search/client.d.ts +3 -0
  106. package/dist/layers/search/app/utils/search/client.js +31 -0
  107. package/dist/layers/search/nuxt.config.d.ts +2 -0
  108. package/dist/layers/search/nuxt.config.js +7 -0
  109. package/dist/layers/search/test/runtime-adapter.spec.d.ts +1 -0
  110. package/dist/layers/search/test/runtime-adapter.spec.js +49 -0
  111. package/dist/nuxt.config.d.ts +2 -0
  112. package/dist/nuxt.config.js +7 -0
  113. package/dist/packages/core/src/adapters/auth.d.ts +9 -0
  114. package/dist/packages/core/src/adapters/auth.js +1 -0
  115. package/dist/packages/core/src/adapters/cart.d.ts +22 -0
  116. package/dist/packages/core/src/adapters/cart.js +1 -0
  117. package/dist/packages/core/src/adapters/catalog.d.ts +17 -0
  118. package/dist/packages/core/src/adapters/catalog.js +1 -0
  119. package/dist/packages/core/src/adapters/common.d.ts +9 -0
  120. package/dist/packages/core/src/adapters/common.js +1 -0
  121. package/dist/packages/core/src/adapters/lists.d.ts +17 -0
  122. package/dist/packages/core/src/adapters/lists.js +1 -0
  123. package/dist/packages/core/src/adapters/search.d.ts +21 -0
  124. package/dist/packages/core/src/adapters/search.js +1 -0
  125. package/dist/packages/core/src/plugins/defineAdapter.d.ts +2 -0
  126. package/dist/packages/core/src/plugins/defineAdapter.js +3 -0
  127. package/dist/packages/core/src/plugins/defineModule.d.ts +2 -0
  128. package/dist/packages/core/src/plugins/defineModule.js +3 -0
  129. package/dist/packages/core/src/plugins/registry.d.ts +14 -0
  130. package/dist/packages/core/src/plugins/registry.js +46 -0
  131. package/dist/packages/core/src/runtime/app.d.ts +2 -0
  132. package/dist/packages/core/src/runtime/app.js +20 -0
  133. package/dist/packages/core/src/runtime/context.d.ts +9 -0
  134. package/dist/packages/core/src/runtime/context.js +11 -0
  135. package/dist/packages/core/src/runtime/hooks.d.ts +5 -0
  136. package/dist/packages/core/src/runtime/hooks.js +18 -0
  137. package/dist/packages/core/src/runtime/lifecycle.d.ts +4 -0
  138. package/dist/packages/core/src/runtime/lifecycle.js +5 -0
  139. package/dist/packages/core/src/types/adapters.d.ts +14 -0
  140. package/dist/packages/core/src/types/adapters.js +1 -0
  141. package/dist/packages/core/src/types/app.d.ts +13 -0
  142. package/dist/packages/core/src/types/app.js +1 -0
  143. package/dist/packages/core/src/types/config.d.ts +8 -0
  144. package/dist/packages/core/src/types/config.js +1 -0
  145. package/dist/packages/core/src/types/events.d.ts +20 -0
  146. package/dist/packages/core/src/types/events.js +22 -0
  147. package/dist/packages/core/src/types/module.d.ts +15 -0
  148. package/dist/packages/core/src/types/module.js +1 -0
  149. package/package.json +9 -4
  150. package/test/runtime-adapter.spec.ts +61 -0
@@ -0,0 +1,5 @@
1
+ export interface SearchModuleConfig {
2
+ defaultProvider: 'opensearch' | 'meilisearch';
3
+ providers: Record<string, unknown>;
4
+ }
5
+ export declare function validateSearchConfig(config: SearchModuleConfig): void;
@@ -0,0 +1,8 @@
1
+ export function validateSearchConfig(config) {
2
+ if (!config.defaultProvider) {
3
+ throw new Error('[@meeovi/search] Missing defaultProvider');
4
+ }
5
+ if (!config.providers[config.defaultProvider]) {
6
+ throw new Error(`[@meeovi/search] Provider "${config.defaultProvider}" not found in config.providers`);
7
+ }
8
+ }
@@ -0,0 +1,7 @@
1
+ export interface SearchConfig {
2
+ searchProvider: string;
3
+ searchUrl?: string;
4
+ apiKey?: string;
5
+ }
6
+ export declare function setSearchConfig(newConfig: Partial<SearchConfig>): void;
7
+ export declare function getSearchConfig(): SearchConfig;
@@ -0,0 +1,11 @@
1
+ let config = {
2
+ searchProvider: 'searchkit',
3
+ searchUrl: '',
4
+ apiKey: ''
5
+ };
6
+ export function setSearchConfig(newConfig) {
7
+ config = { ...config, ...newConfig };
8
+ }
9
+ export function getSearchConfig() {
10
+ return config;
11
+ }
@@ -0,0 +1,17 @@
1
+ export declare const Facets: {
2
+ terms(field: string): {
3
+ type: string;
4
+ field: string;
5
+ };
6
+ range(field: string, ranges: {
7
+ from?: number;
8
+ to?: number;
9
+ }[]): {
10
+ type: string;
11
+ field: string;
12
+ ranges: {
13
+ from?: number;
14
+ to?: number;
15
+ }[];
16
+ };
17
+ };
@@ -0,0 +1,8 @@
1
+ export const Facets = {
2
+ terms(field) {
3
+ return { type: 'terms', field };
4
+ },
5
+ range(field, ranges) {
6
+ return { type: 'range', field, ranges };
7
+ }
8
+ };
@@ -0,0 +1,18 @@
1
+ export declare const Filters: {
2
+ term(field: string, value: string): {
3
+ type: string;
4
+ field: string;
5
+ value: string;
6
+ };
7
+ range(field: string, min?: number, max?: number): {
8
+ type: string;
9
+ field: string;
10
+ min: number | undefined;
11
+ max: number | undefined;
12
+ };
13
+ boolean(field: string, value: boolean): {
14
+ type: string;
15
+ field: string;
16
+ value: boolean;
17
+ };
18
+ };
@@ -0,0 +1,11 @@
1
+ export const Filters = {
2
+ term(field, value) {
3
+ return { type: 'term', field, value };
4
+ },
5
+ range(field, min, max) {
6
+ return { type: 'range', field, min, max };
7
+ },
8
+ boolean(field, value) {
9
+ return { type: 'boolean', field, value };
10
+ }
11
+ };
File without changes
@@ -0,0 +1 @@
1
+ "use strict";
@@ -0,0 +1,8 @@
1
+ export declare class SearchPipeline {
2
+ private before;
3
+ private after;
4
+ useBefore(fn: (query: any) => any): void;
5
+ useAfter(fn: (result: any) => any): void;
6
+ runBefore(query: any): any;
7
+ runAfter(result: any): any;
8
+ }
@@ -0,0 +1,16 @@
1
+ export class SearchPipeline {
2
+ before = [];
3
+ after = [];
4
+ useBefore(fn) {
5
+ this.before.push(fn);
6
+ }
7
+ useAfter(fn) {
8
+ this.after.push(fn);
9
+ }
10
+ runBefore(query) {
11
+ return this.before.reduce((q, fn) => fn(q), query);
12
+ }
13
+ runAfter(result) {
14
+ return this.after.reduce((r, fn) => fn(r), result);
15
+ }
16
+ }
@@ -0,0 +1,13 @@
1
+ import { SearchContext } from './SearchContext';
2
+ export interface BuiltSearchQuery {
3
+ term: string;
4
+ page: number;
5
+ pageSize: number;
6
+ sort?: string;
7
+ filters: Record<string, any>;
8
+ }
9
+ export declare class QueryBuilder {
10
+ private context;
11
+ constructor(context: SearchContext);
12
+ build(): BuiltSearchQuery;
13
+ }
@@ -0,0 +1,15 @@
1
+ export class QueryBuilder {
2
+ context;
3
+ constructor(context) {
4
+ this.context = context;
5
+ }
6
+ build() {
7
+ return {
8
+ term: this.context.state.query,
9
+ page: this.context.state.page,
10
+ pageSize: this.context.state.pageSize,
11
+ sort: this.context.state.sort,
12
+ filters: this.context.state.filters
13
+ };
14
+ }
15
+ }
@@ -0,0 +1,18 @@
1
+ export interface SearchContextState {
2
+ query: string;
3
+ page: number;
4
+ pageSize: number;
5
+ sort?: string;
6
+ filters: Record<string, any>;
7
+ }
8
+ export declare class SearchContext {
9
+ state: SearchContextState;
10
+ constructor(initial?: Partial<SearchContextState>);
11
+ setQuery(query: string): void;
12
+ setPage(page: number): void;
13
+ setPageSize(size: number): void;
14
+ setSort(sort: string | undefined): void;
15
+ setFilter(key: string, value: any): void;
16
+ removeFilter(key: string): void;
17
+ reset(): void;
18
+ }
@@ -0,0 +1,38 @@
1
+ export class SearchContext {
2
+ state;
3
+ constructor(initial) {
4
+ this.state = {
5
+ query: '',
6
+ page: 1,
7
+ pageSize: 20,
8
+ filters: {},
9
+ ...initial
10
+ };
11
+ }
12
+ setQuery(query) {
13
+ this.state.query = query;
14
+ }
15
+ setPage(page) {
16
+ this.state.page = page;
17
+ }
18
+ setPageSize(size) {
19
+ this.state.pageSize = size;
20
+ }
21
+ setSort(sort) {
22
+ this.state.sort = sort;
23
+ }
24
+ setFilter(key, value) {
25
+ this.state.filters[key] = value;
26
+ }
27
+ removeFilter(key) {
28
+ delete this.state.filters[key];
29
+ }
30
+ reset() {
31
+ this.state = {
32
+ query: '',
33
+ page: 1,
34
+ pageSize: 20,
35
+ filters: {}
36
+ };
37
+ }
38
+ }
@@ -0,0 +1,10 @@
1
+ import type { SearchAdapter } from '@meeovi/core';
2
+ import { SearchContext, type SearchContextState } from './SearchContext';
3
+ import { SearchPipeline } from './Pipeline';
4
+ export declare class SearchManager<TItem = any> {
5
+ context: SearchContext;
6
+ pipeline: SearchPipeline;
7
+ adapter: SearchAdapter<TItem>;
8
+ constructor(adapter: SearchAdapter<TItem>, initial?: Partial<SearchContextState>);
9
+ search(): Promise<any>;
10
+ }
@@ -0,0 +1,20 @@
1
+ import { SearchContext } from './SearchContext';
2
+ import { QueryBuilder } from './QueryBuilder';
3
+ import { SearchPipeline } from './Pipeline';
4
+ export class SearchManager {
5
+ context;
6
+ pipeline;
7
+ adapter;
8
+ constructor(adapter, initial) {
9
+ this.context = new SearchContext(initial);
10
+ this.pipeline = new SearchPipeline();
11
+ this.adapter = adapter;
12
+ }
13
+ async search() {
14
+ const builder = new QueryBuilder(this.context);
15
+ let query = builder.build();
16
+ query = this.pipeline.runBefore(query);
17
+ const result = await this.adapter.search(query);
18
+ return this.pipeline.runAfter(result);
19
+ }
20
+ }
@@ -0,0 +1,11 @@
1
+ declare module '@meeovi/core/dist/types/events' {
2
+ interface AlternateEventMap {
3
+ 'search:query': {
4
+ term: string;
5
+ };
6
+ 'search:results': {
7
+ term: string;
8
+ total: number;
9
+ };
10
+ }
11
+ }
@@ -0,0 +1 @@
1
+ "use strict";
@@ -0,0 +1,9 @@
1
+ export * from './module';
2
+ export * from './adapter/types';
3
+ export * from './core/SearchManager';
4
+ export * from './core/SearchContext';
5
+ export * from './core/Filters';
6
+ export * from './core/Facets';
7
+ export * from './bridges/instantsearch';
8
+ export * from './bridges/vue';
9
+ export * from './bridges/react';
@@ -0,0 +1,9 @@
1
+ export * from './module';
2
+ export * from './adapter/types';
3
+ export * from './core/SearchManager';
4
+ export * from './core/SearchContext';
5
+ export * from './core/Filters';
6
+ export * from './core/Facets';
7
+ export * from './bridges/instantsearch';
8
+ export * from './bridges/vue';
9
+ export * from './bridges/react';
@@ -0,0 +1,17 @@
1
+ import { type AlternateContext } from '@meeovi/core';
2
+ import { type SearchModuleConfig } from './config/schema';
3
+ import type { MeeoviSearchItem } from './adapter/types';
4
+ declare module '@meeovi/core' {
5
+ interface AlternateConfig {
6
+ search?: SearchModuleConfig;
7
+ }
8
+ interface AlternateContext {
9
+ searchManager?: import('./core/SearchManager').SearchManager<MeeoviSearchItem>;
10
+ }
11
+ }
12
+ declare const _default: {
13
+ id: string;
14
+ adapters: {};
15
+ setup(ctx: AlternateContext): Promise<void>;
16
+ };
17
+ export default _default;
@@ -0,0 +1,39 @@
1
+ import { defineAlternateModule, useAlternateEventBus } from '@meeovi/core';
2
+ import { validateSearchConfig } from './config/schema';
3
+ import { createOpenSearchAdapter } from './adapter/opensearch';
4
+ import { createMeilisearchAdapter } from './adapter/meilisearch';
5
+ import { SearchManager } from './core/SearchManager';
6
+ export default defineAlternateModule({
7
+ id: 'search',
8
+ adapters: {},
9
+ async setup(ctx) {
10
+ const bus = useAlternateEventBus();
11
+ const config = ctx.config.search;
12
+ if (!config)
13
+ return;
14
+ validateSearchConfig(config);
15
+ if (config.defaultProvider === 'opensearch') {
16
+ const providerConfig = config.providers.opensearch;
17
+ if (providerConfig) {
18
+ this.adapters = {
19
+ search: createOpenSearchAdapter(providerConfig)
20
+ };
21
+ }
22
+ }
23
+ if (config.defaultProvider === 'meilisearch') {
24
+ const providerConfig = config.providers.meilisearch;
25
+ if (providerConfig) {
26
+ this.adapters = {
27
+ search: createMeilisearchAdapter(providerConfig)
28
+ };
29
+ }
30
+ }
31
+ const adapter = ctx.getAdapter('search');
32
+ if (adapter) {
33
+ ctx.searchManager = new SearchManager(adapter);
34
+ }
35
+ bus.on('app:ready', () => {
36
+ console.info('[@meeovi/search] Search module initialized');
37
+ });
38
+ }
39
+ });
@@ -0,0 +1,8 @@
1
+ export interface GlobalSearchResult {
2
+ id?: string;
3
+ title?: string;
4
+ type?: string;
5
+ description?: string;
6
+ image?: string;
7
+ url?: string;
8
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export declare function normalizeOpenSearchHit(hit: any): any;
@@ -0,0 +1,6 @@
1
+ export function normalizeOpenSearchHit(hit) {
2
+ return {
3
+ id: hit._id,
4
+ ...hit._source
5
+ };
6
+ }
@@ -0,0 +1,3 @@
1
+ import type { SearchClient } from 'instantsearch.js';
2
+ export declare function getIndexName(): string;
3
+ export declare function getSearchClient(): SearchClient;
@@ -0,0 +1,31 @@
1
+ export function getIndexName() {
2
+ return (process.env.NUXT_PUBLIC_SEARCH_INDEX ||
3
+ process.env.SEARCH_INDEX ||
4
+ 'default');
5
+ }
6
+ export function getSearchClient() {
7
+ const host = process.env.NUXT_PUBLIC_SEARCHKIT_HOST || process.env.SEARCHKIT_HOST;
8
+ if (!host) {
9
+ throw new Error('Searchkit host not configured via SEARCHKIT_HOST or NUXT_PUBLIC_SEARCHKIT_HOST');
10
+ }
11
+ // Defer importing heavy searchkit/instantsearch client until runtime.
12
+ // Consumers can replace this implementation with a provider-specific client.
13
+ // Here we attempt to use @searchkit/instantsearch-client if available.
14
+ // If not present, let the import fail so the plugin can fallback.
15
+ // The actual creation API differs between versions; adjust as needed.
16
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
17
+ const createClient = require('@searchkit/instantsearch-client');
18
+ if (!createClient) {
19
+ throw new Error('@searchkit/instantsearch-client is not installed');
20
+ }
21
+ // Create a minimal client. The factory API may vary; this is a best-effort
22
+ // placeholder that should be adapted to your Searchkit configuration.
23
+ // If your Searchkit installation exposes a helper, prefer using that.
24
+ try {
25
+ return createClient({ host });
26
+ }
27
+ catch (e) {
28
+ // rethrow with context
29
+ throw new Error('Failed to create Searchkit client: ' + (e?.message || e));
30
+ }
31
+ }
@@ -0,0 +1,8 @@
1
+ import { type SearchAdapterConfig } from '@meeovi/core';
2
+ interface MeiliConfig extends SearchAdapterConfig {
3
+ host: string;
4
+ apiKey?: string;
5
+ index: string;
6
+ }
7
+ export declare function createMeilisearchAdapter(config: MeiliConfig): import("@meeovi/core").AlternateAdapter<SearchAdapterConfig>;
8
+ export {};
@@ -0,0 +1,36 @@
1
+ import { defineAlternateAdapter } from '@meeovi/core';
2
+ export function createMeilisearchAdapter(config) {
3
+ const headers = {
4
+ 'Content-Type': 'application/json'
5
+ };
6
+ if (config.apiKey) {
7
+ headers['Authorization'] = `Bearer ${config.apiKey}`;
8
+ }
9
+ const adapter = {
10
+ id: 'search:meilisearch',
11
+ type: 'search',
12
+ config,
13
+ async search(query) {
14
+ const params = new URLSearchParams({
15
+ q: query.term,
16
+ offset: String((query.page - 1) * query.pageSize),
17
+ limit: String(query.pageSize)
18
+ });
19
+ const res = await fetch(`${config.host}/indexes/${config.index}/search?${params}`, {
20
+ method: 'POST',
21
+ headers,
22
+ body: JSON.stringify({
23
+ filter: Object.entries(query.filters).map(([field, value]) => `${field} = ${value}`)
24
+ })
25
+ });
26
+ const json = await res.json();
27
+ return {
28
+ items: json.hits,
29
+ total: json.estimatedTotalHits ?? json.hits.length,
30
+ page: query.page,
31
+ pageSize: query.pageSize
32
+ };
33
+ }
34
+ };
35
+ return defineAlternateAdapter(adapter);
36
+ }
@@ -0,0 +1,3 @@
1
+ import { type SearchAdapterConfig } from '@meeovi/core';
2
+ import type { MeeoviSearchItem } from './types';
3
+ export declare function createMockSearchAdapter(items?: MeeoviSearchItem[]): import("@meeovi/core").AlternateAdapter<SearchAdapterConfig>;
@@ -0,0 +1,19 @@
1
+ import { defineAlternateAdapter } from '@meeovi/core';
2
+ export function createMockSearchAdapter(items = []) {
3
+ const cfg = { provider: 'mock' };
4
+ const adapter = {
5
+ id: 'search:mock',
6
+ type: 'search',
7
+ config: cfg,
8
+ async search(query) {
9
+ const filtered = items.filter((item) => item.title.toLowerCase().includes(query.term.toLowerCase()));
10
+ return {
11
+ items: filtered,
12
+ total: filtered.length,
13
+ page: 1,
14
+ pageSize: filtered.length
15
+ };
16
+ }
17
+ };
18
+ return defineAlternateAdapter(adapter);
19
+ }
@@ -0,0 +1,8 @@
1
+ import { type SearchAdapterConfig } from '@meeovi/core';
2
+ interface OpenSearchConfig extends SearchAdapterConfig {
3
+ endpoint: string;
4
+ index: string;
5
+ apiKey?: string;
6
+ }
7
+ export declare function createOpenSearchAdapter(config: OpenSearchConfig): import("@meeovi/core").AlternateAdapter<SearchAdapterConfig>;
8
+ export {};
@@ -0,0 +1,46 @@
1
+ import { defineAlternateAdapter } from '@meeovi/core';
2
+ import { normalizeOpenSearchHit } from '../utils/normalizers';
3
+ export function createOpenSearchAdapter(config) {
4
+ const adapter = {
5
+ id: 'search:opensearch',
6
+ type: 'search',
7
+ config,
8
+ async search(query) {
9
+ const body = {
10
+ query: {
11
+ bool: {
12
+ must: [
13
+ {
14
+ multi_match: {
15
+ query: query.term,
16
+ fields: ['title^3', 'description', 'tags']
17
+ }
18
+ }
19
+ ],
20
+ filter: Object.entries(query.filters).map(([field, value]) => ({
21
+ term: { [field]: value }
22
+ }))
23
+ }
24
+ },
25
+ from: (query.page - 1) * query.pageSize,
26
+ size: query.pageSize
27
+ };
28
+ const res = await fetch(`${config.endpoint}/${config.index}/_search`, {
29
+ method: 'POST',
30
+ headers: {
31
+ 'Content-Type': 'application/json',
32
+ ...(config.apiKey ? { Authorization: `Bearer ${config.apiKey}` } : {})
33
+ },
34
+ body: JSON.stringify(body)
35
+ });
36
+ const json = await res.json();
37
+ return {
38
+ items: json.hits.hits.map(normalizeOpenSearchHit),
39
+ total: json.hits.total.value,
40
+ page: query.page,
41
+ pageSize: query.pageSize
42
+ };
43
+ }
44
+ };
45
+ return defineAlternateAdapter(adapter);
46
+ }
@@ -0,0 +1,12 @@
1
+ import type { SearchAdapter, SearchResult } from '@meeovi/core';
2
+ import type { BuiltSearchQuery } from '../core/QueryBuilder';
3
+ export interface MeeoviSearchItem {
4
+ id: string;
5
+ title: string;
6
+ description?: string;
7
+ price?: number;
8
+ [key: string]: unknown;
9
+ }
10
+ export type MeeoviSearchAdapter = SearchAdapter<MeeoviSearchItem> & {
11
+ search(query: BuiltSearchQuery): Promise<SearchResult<MeeoviSearchItem>>;
12
+ };
@@ -0,0 +1,4 @@
1
+ import type { SearchManager } from '../core/SearchManager';
2
+ export declare function createInstantSearchBridge(manager: SearchManager): {
3
+ searchFunction(helper: any): Promise<void>;
4
+ };
@@ -0,0 +1,17 @@
1
+ export function createInstantSearchBridge(manager) {
2
+ return {
3
+ searchFunction(helper) {
4
+ manager.context.setQuery(helper.state.query || '');
5
+ manager.context.setPage(helper.state.page || 1);
6
+ // map filters if needed from helper.state
7
+ return manager.search().then((result) => {
8
+ helper.setResults({
9
+ hits: result.items,
10
+ nbHits: result.total,
11
+ page: result.page - 1,
12
+ hitsPerPage: result.pageSize
13
+ });
14
+ });
15
+ }
16
+ };
17
+ }
@@ -0,0 +1,12 @@
1
+ export declare function useReactSearch(): {
2
+ query: string;
3
+ setQuery: import("react").Dispatch<import("react").SetStateAction<string>>;
4
+ page: number;
5
+ setPage: import("react").Dispatch<import("react").SetStateAction<number>>;
6
+ pageSize: number;
7
+ setPageSize: import("react").Dispatch<import("react").SetStateAction<number>>;
8
+ results: any[];
9
+ total: number;
10
+ loading: boolean;
11
+ search: () => Promise<void>;
12
+ };
@@ -0,0 +1,34 @@
1
+ import { useState, useCallback } from 'react';
2
+ import { useAlternateContext } from '@meeovi/core';
3
+ export function useReactSearch() {
4
+ const ctx = useAlternateContext();
5
+ const manager = ctx.searchManager;
6
+ const [query, setQuery] = useState(manager.context.state.query);
7
+ const [page, setPage] = useState(manager.context.state.page);
8
+ const [pageSize, setPageSize] = useState(manager.context.state.pageSize);
9
+ const [results, setResults] = useState([]);
10
+ const [total, setTotal] = useState(0);
11
+ const [loading, setLoading] = useState(false);
12
+ const search = useCallback(async () => {
13
+ setLoading(true);
14
+ manager.context.setQuery(query);
15
+ manager.context.setPage(page);
16
+ manager.context.setPageSize(pageSize);
17
+ const res = await manager.search();
18
+ setResults(res.items);
19
+ setTotal(res.total);
20
+ setLoading(false);
21
+ }, [query, page, pageSize, manager]);
22
+ return {
23
+ query,
24
+ setQuery,
25
+ page,
26
+ setPage,
27
+ pageSize,
28
+ setPageSize,
29
+ results,
30
+ total,
31
+ loading,
32
+ search
33
+ };
34
+ }
@@ -0,0 +1,3 @@
1
+ import type { SearchManager } from '../core/SearchManager';
2
+ export declare function createSearchkitGraphQLHandler(manager: SearchManager): (req: any, res: any) => Promise<void>;
3
+ export default createSearchkitGraphQLHandler;