diff --git a/packages/headless-react/src/search-engine.test.tsx b/packages/headless-react/src/search-engine.test.tsx index 2dc1809f75b..a5e1e291ad0 100644 --- a/packages/headless-react/src/search-engine.test.tsx +++ b/packages/headless-react/src/search-engine.test.tsx @@ -1,5 +1,8 @@ -import {getSampleSearchEngineConfiguration} from '@coveo/headless'; -import {defineResultList, defineSearchBox} from '@coveo/headless/ssr'; +import { + getSampleSearchEngineConfiguration, + defineResultList, + defineSearchBox, +} from '@coveo/headless/ssr'; import {render, renderHook, screen} from '@testing-library/react'; import {PropsWithChildren} from 'react'; import {MissingEngineProviderError, defineSearchEngine} from './search-engine'; diff --git a/packages/headless-react/src/search-engine.tsx b/packages/headless-react/src/search-engine.tsx index 8f9bc14f554..8778601f397 100644 --- a/packages/headless-react/src/search-engine.tsx +++ b/packages/headless-react/src/search-engine.tsx @@ -1,5 +1,7 @@ -import {Controller, CoreEngine, SearchEngine} from '@coveo/headless'; import { + Controller, + CoreEngine, + SearchEngine, ControllerDefinitionsMap, InferControllerFromDefinition, SearchEngineDefinitionOptions, diff --git a/packages/headless-react/src/types.ts b/packages/headless-react/src/types.ts index 24f2b99cbf4..5ddbd572133 100644 --- a/packages/headless-react/src/types.ts +++ b/packages/headless-react/src/types.ts @@ -3,10 +3,8 @@ import { CoreEngine, SearchEngine, SearchEngineOptions, -} from '@coveo/headless'; -import {InferControllerFromDefinition} from '@coveo/headless/dist/definitions/app/ssr-engine/types/common'; -import { ControllerDefinitionsMap, + InferControllerFromDefinition, InferControllersMapFromDefinition, InferControllerStaticStateMapFromDefinitions, EngineDefinition, diff --git a/packages/headless/package.json b/packages/headless/package.json index 3a4a1a686d9..7e3619cdb97 100644 --- a/packages/headless/package.json +++ b/packages/headless/package.json @@ -69,12 +69,12 @@ "@microsoft/api-extractor": "7.36.4", "@microsoft/api-extractor-model": "7.27.6", "@microsoft/tsdoc": "0.14.2", - "jest-fetch-mock": "3.0.3", + "execa": "8.0.1", "jest": "29.6.4", - "ts-jest": "29.1.1", + "jest-fetch-mock": "3.0.3", "pad-stream": "^4.0.0", - "ts-node": "10.9.1", - "execa": "8.0.1" + "ts-jest": "29.1.1", + "ts-node": "10.9.1" }, "engines": { "node": ">=12" diff --git a/packages/headless/src/controllers/breadcrumb-manager/headless-breadcrumb-manager.ssr.ts b/packages/headless/src/controllers/breadcrumb-manager/headless-breadcrumb-manager.ssr.ts new file mode 100644 index 00000000000..5f73b4c6a57 --- /dev/null +++ b/packages/headless/src/controllers/breadcrumb-manager/headless-breadcrumb-manager.ssr.ts @@ -0,0 +1,18 @@ +import {SearchEngine} from '../../app/search-engine/search-engine'; +import {ControllerDefinitionWithoutProps} from '../../app/ssr-engine/types/common'; +import { + BreadcrumbManager, + buildBreadcrumbManager, +} from './headless-breadcrumb-manager'; + +export * from './headless-breadcrumb-manager'; + +/** + * @internal + */ +export const defineBreadcrumbManager = (): ControllerDefinitionWithoutProps< + SearchEngine, + BreadcrumbManager +> => ({ + build: (engine) => buildBreadcrumbManager(engine), +}); diff --git a/packages/headless/src/controllers/context/headless-context.ssr.ts b/packages/headless/src/controllers/context/headless-context.ssr.ts new file mode 100644 index 00000000000..6df6efbc675 --- /dev/null +++ b/packages/headless/src/controllers/context/headless-context.ssr.ts @@ -0,0 +1,15 @@ +import {SearchEngine} from '../../app/search-engine/search-engine'; +import {ControllerDefinitionWithoutProps} from '../../app/ssr-engine/types/common'; +import {Context, buildContext} from './headless-context'; + +export * from './headless-context'; + +/** + * @internal + */ +export const defineContext = (): ControllerDefinitionWithoutProps< + SearchEngine, + Context +> => ({ + build: (engine) => buildContext(engine), +}); diff --git a/packages/headless/src/controllers/dictionary-field-context/headless-dictionary-field-context.ssr.ts b/packages/headless/src/controllers/dictionary-field-context/headless-dictionary-field-context.ssr.ts new file mode 100644 index 00000000000..67c27bd4f78 --- /dev/null +++ b/packages/headless/src/controllers/dictionary-field-context/headless-dictionary-field-context.ssr.ts @@ -0,0 +1,19 @@ +import {SearchEngine} from '../../app/search-engine/search-engine'; +import {ControllerDefinitionWithoutProps} from '../../app/ssr-engine/types/common'; +import { + DictionaryFieldContext, + buildDictionaryFieldContext, +} from './headless-dictionary-field-context'; + +export * from './headless-dictionary-field-context'; + +/** + * @internal + */ +export const defineDictionaryFieldContext = + (): ControllerDefinitionWithoutProps< + SearchEngine, + DictionaryFieldContext + > => ({ + build: (engine) => buildDictionaryFieldContext(engine), + }); diff --git a/packages/headless/src/controllers/did-you-mean/headless-did-you-mean.ssr.ts b/packages/headless/src/controllers/did-you-mean/headless-did-you-mean.ssr.ts new file mode 100644 index 00000000000..f042e8cbe80 --- /dev/null +++ b/packages/headless/src/controllers/did-you-mean/headless-did-you-mean.ssr.ts @@ -0,0 +1,15 @@ +import {SearchEngine} from '../../app/search-engine/search-engine'; +import {ControllerDefinitionWithoutProps} from '../../app/ssr-engine/types/common'; +import {DidYouMean, buildDidYouMean} from './headless-did-you-mean'; + +export * from './headless-did-you-mean'; + +/** + * @internal + */ +export const defineDidYouMean = (): ControllerDefinitionWithoutProps< + SearchEngine, + DidYouMean +> => ({ + build: (engine) => buildDidYouMean(engine), +}); diff --git a/packages/headless/src/controllers/facet-manager/headless-facet-manager.ssr.ts b/packages/headless/src/controllers/facet-manager/headless-facet-manager.ssr.ts new file mode 100644 index 00000000000..9f67babf1fb --- /dev/null +++ b/packages/headless/src/controllers/facet-manager/headless-facet-manager.ssr.ts @@ -0,0 +1,15 @@ +import {SearchEngine} from '../../app/search-engine/search-engine'; +import {ControllerDefinitionWithoutProps} from '../../app/ssr-engine/types/common'; +import {FacetManager, buildFacetManager} from './headless-facet-manager'; + +export * from './headless-facet-manager'; + +/** + * @internal + */ +export const defineFacetManager = (): ControllerDefinitionWithoutProps< + SearchEngine, + FacetManager +> => ({ + build: (engine) => buildFacetManager(engine), +}); diff --git a/packages/headless/src/controllers/facets/automatic-facet-generator/headless-automatic-facet-generator.ssr.ts b/packages/headless/src/controllers/facets/automatic-facet-generator/headless-automatic-facet-generator.ssr.ts new file mode 100644 index 00000000000..b22482ba33a --- /dev/null +++ b/packages/headless/src/controllers/facets/automatic-facet-generator/headless-automatic-facet-generator.ssr.ts @@ -0,0 +1,18 @@ +import {SearchEngine} from '../../../app/search-engine/search-engine'; +import {ControllerDefinitionWithoutProps} from '../../../app/ssr-engine/types/common'; +import { + AutomaticFacetGenerator, + AutomaticFacetGeneratorProps, + buildAutomaticFacetGenerator, +} from './headless-automatic-facet-generator'; + +export * from './headless-automatic-facet-generator'; + +/** + * @internal + */ +export const defineAutomaticFacetGenerator = ( + props: AutomaticFacetGeneratorProps +): ControllerDefinitionWithoutProps => ({ + build: (engine) => buildAutomaticFacetGenerator(engine, props), +}); diff --git a/packages/headless/src/controllers/facets/automatic-facet/headless-automatic-facet.ssr.ts b/packages/headless/src/controllers/facets/automatic-facet/headless-automatic-facet.ssr.ts new file mode 100644 index 00000000000..11c3eeddc68 --- /dev/null +++ b/packages/headless/src/controllers/facets/automatic-facet/headless-automatic-facet.ssr.ts @@ -0,0 +1,18 @@ +import {SearchEngine} from '../../../app/search-engine/search-engine'; +import {ControllerDefinitionWithoutProps} from '../../../app/ssr-engine/types/common'; +import { + AutomaticFacet, + AutomaticFacetProps, + buildAutomaticFacet, +} from './headless-automatic-facet'; + +export * from './headless-automatic-facet'; + +/** + * @internal + */ +export const defineAutomaticFacet = ( + props: AutomaticFacetProps +): ControllerDefinitionWithoutProps => ({ + build: (engine) => buildAutomaticFacet(engine, props), +}); diff --git a/packages/headless/src/controllers/facets/category-facet/headless-category-facet.ssr.ts b/packages/headless/src/controllers/facets/category-facet/headless-category-facet.ssr.ts new file mode 100644 index 00000000000..cb9763921c1 --- /dev/null +++ b/packages/headless/src/controllers/facets/category-facet/headless-category-facet.ssr.ts @@ -0,0 +1,18 @@ +import {SearchEngine} from '../../../app/search-engine/search-engine'; +import {ControllerDefinitionWithoutProps} from '../../../app/ssr-engine/types/common'; +import { + CategoryFacet, + CategoryFacetProps, + buildCategoryFacet, +} from './headless-category-facet'; + +export * from './headless-category-facet'; + +/** + * @internal + */ +export const defineCategoryFacet = ( + props: CategoryFacetProps +): ControllerDefinitionWithoutProps => ({ + build: (engine) => buildCategoryFacet(engine, props), +}); diff --git a/packages/headless/src/controllers/facets/facet/headless-facet.ssr.ts b/packages/headless/src/controllers/facets/facet/headless-facet.ssr.ts new file mode 100644 index 00000000000..abcb88cb3e2 --- /dev/null +++ b/packages/headless/src/controllers/facets/facet/headless-facet.ssr.ts @@ -0,0 +1,14 @@ +import {SearchEngine} from '../../../app/search-engine/search-engine'; +import {ControllerDefinitionWithoutProps} from '../../../app/ssr-engine/types/common'; +import {Facet, FacetProps, buildFacet} from './headless-facet'; + +export * from './headless-facet'; + +/** + * @internal + */ +export const defineFacet = ( + props: FacetProps +): ControllerDefinitionWithoutProps => ({ + build: (engine) => buildFacet(engine, props), +}); diff --git a/packages/headless/src/controllers/facets/range-facet/date-facet/headless-date-facet.ssr.ts b/packages/headless/src/controllers/facets/range-facet/date-facet/headless-date-facet.ssr.ts new file mode 100644 index 00000000000..0a0d1818a5e --- /dev/null +++ b/packages/headless/src/controllers/facets/range-facet/date-facet/headless-date-facet.ssr.ts @@ -0,0 +1,16 @@ +import {SearchEngine} from '../../../../app/search-engine/search-engine'; +import {ControllerDefinitionWithoutProps} from '../../../../app/ssr-engine/types/common'; +import {DateFacet, DateFacetProps, buildDateFacet} from './headless-date-facet'; + +export * from './headless-date-facet'; + +export {buildDateRange} from './headless-date-facet'; + +/** + * @internal + */ +export const defineDateFacet = ( + props: DateFacetProps +): ControllerDefinitionWithoutProps => ({ + build: (engine) => buildDateFacet(engine, props), +}); diff --git a/packages/headless/src/controllers/facets/range-facet/date-facet/headless-date-filter.ssr.ts b/packages/headless/src/controllers/facets/range-facet/date-facet/headless-date-filter.ssr.ts new file mode 100644 index 00000000000..3c423cf9a5c --- /dev/null +++ b/packages/headless/src/controllers/facets/range-facet/date-facet/headless-date-filter.ssr.ts @@ -0,0 +1,18 @@ +import {SearchEngine} from '../../../../app/search-engine/search-engine'; +import {ControllerDefinitionWithoutProps} from '../../../../app/ssr-engine/types/common'; +import { + DateFilter, + DateFilterProps, + buildDateFilter, +} from './headless-date-filter'; + +export * from './headless-date-filter'; + +/** + * @internal + */ +export const defineDateFilter = ( + props: DateFilterProps +): ControllerDefinitionWithoutProps => ({ + build: (engine) => buildDateFilter(engine, props), +}); diff --git a/packages/headless/src/controllers/facets/range-facet/numeric-facet/headless-numeric-facet.ssr.ts b/packages/headless/src/controllers/facets/range-facet/numeric-facet/headless-numeric-facet.ssr.ts new file mode 100644 index 00000000000..f0120041f54 --- /dev/null +++ b/packages/headless/src/controllers/facets/range-facet/numeric-facet/headless-numeric-facet.ssr.ts @@ -0,0 +1,20 @@ +import {SearchEngine} from '../../../../app/search-engine/search-engine'; +import {ControllerDefinitionWithoutProps} from '../../../../app/ssr-engine/types/common'; +import { + NumericFacet, + NumericFacetProps, + buildNumericFacet, +} from './headless-numeric-facet'; + +export * from './headless-numeric-facet'; + +export {buildNumericRange} from './headless-numeric-facet'; + +/** + * @internal + */ +export const defineNumericFacet = ( + props: NumericFacetProps +): ControllerDefinitionWithoutProps => ({ + build: (engine) => buildNumericFacet(engine, props), +}); diff --git a/packages/headless/src/controllers/facets/range-facet/numeric-facet/headless-numeric-filter.ssr.ts b/packages/headless/src/controllers/facets/range-facet/numeric-facet/headless-numeric-filter.ssr.ts new file mode 100644 index 00000000000..c6f1d1a87c1 --- /dev/null +++ b/packages/headless/src/controllers/facets/range-facet/numeric-facet/headless-numeric-filter.ssr.ts @@ -0,0 +1,18 @@ +import {SearchEngine} from '../../../../app/search-engine/search-engine'; +import {ControllerDefinitionWithoutProps} from '../../../../app/ssr-engine/types/common'; +import { + NumericFilter, + NumericFilterProps, + buildNumericFilter, +} from './headless-numeric-filter'; + +export * from './headless-numeric-filter'; + +/** + * @internal + */ +export const defineNumericFilter = ( + props: NumericFilterProps +): ControllerDefinitionWithoutProps => ({ + build: (engine) => buildNumericFilter(engine, props), +}); diff --git a/packages/headless/src/controllers/field-suggestions/category-facet/headless-category-field-suggestions.ssr.ts b/packages/headless/src/controllers/field-suggestions/category-facet/headless-category-field-suggestions.ssr.ts new file mode 100644 index 00000000000..7e9cd4b1bff --- /dev/null +++ b/packages/headless/src/controllers/field-suggestions/category-facet/headless-category-field-suggestions.ssr.ts @@ -0,0 +1,21 @@ +import {SearchEngine} from '../../../app/search-engine/search-engine'; +import {ControllerDefinitionWithoutProps} from '../../../app/ssr-engine/types/common'; +import { + CategoryFieldSuggestions, + CategoryFieldSuggestionsProps, + buildCategoryFieldSuggestions, +} from './headless-category-field-suggestions'; + +export * from './headless-category-field-suggestions'; + +/** + * @internal + */ +export const defineCategoryFieldSuggestions = ( + props: CategoryFieldSuggestionsProps +): ControllerDefinitionWithoutProps< + SearchEngine, + CategoryFieldSuggestions +> => ({ + build: (engine) => buildCategoryFieldSuggestions(engine, props), +}); diff --git a/packages/headless/src/controllers/field-suggestions/facet/headless-field-suggestions.ssr.ts b/packages/headless/src/controllers/field-suggestions/facet/headless-field-suggestions.ssr.ts new file mode 100644 index 00000000000..2681dce80c4 --- /dev/null +++ b/packages/headless/src/controllers/field-suggestions/facet/headless-field-suggestions.ssr.ts @@ -0,0 +1,18 @@ +import {SearchEngine} from '../../../app/search-engine/search-engine'; +import {ControllerDefinitionWithoutProps} from '../../../app/ssr-engine/types/common'; +import { + FieldSuggestions, + FieldSuggestionsProps, + buildFieldSuggestions, +} from './headless-field-suggestions'; + +export * from './headless-field-suggestions'; + +/** + * @internal + */ +export const defineFieldSuggestions = ( + props: FieldSuggestionsProps +): ControllerDefinitionWithoutProps => ({ + build: (engine) => buildFieldSuggestions(engine, props), +}); diff --git a/packages/headless/src/controllers/folded-result-list/headless-folded-result-list.ssr.ts b/packages/headless/src/controllers/folded-result-list/headless-folded-result-list.ssr.ts new file mode 100644 index 00000000000..4f0bbd0973d --- /dev/null +++ b/packages/headless/src/controllers/folded-result-list/headless-folded-result-list.ssr.ts @@ -0,0 +1,18 @@ +import {SearchEngine} from '../../app/search-engine/search-engine'; +import {ControllerDefinitionWithoutProps} from '../../app/ssr-engine/types/common'; +import { + FoldedResultList, + FoldedResultListProps, + buildFoldedResultList, +} from './headless-folded-result-list'; + +export * from './headless-folded-result-list'; + +/** + * @internal + */ +export const defineFoldedResultList = ( + props?: FoldedResultListProps +): ControllerDefinitionWithoutProps => ({ + build: (engine) => buildFoldedResultList(engine, props), +}); diff --git a/packages/headless/src/controllers/history-manager/headless-history-manager.ssr.ts b/packages/headless/src/controllers/history-manager/headless-history-manager.ssr.ts new file mode 100644 index 00000000000..696e2b5952a --- /dev/null +++ b/packages/headless/src/controllers/history-manager/headless-history-manager.ssr.ts @@ -0,0 +1,15 @@ +import {SearchEngine} from '../../app/search-engine/search-engine'; +import {ControllerDefinitionWithoutProps} from '../../app/ssr-engine/types/common'; +import {HistoryManager, buildHistoryManager} from './headless-history-manager'; + +export * from './headless-history-manager'; + +/** + * @internal + */ +export const defineHistoryManager = (): ControllerDefinitionWithoutProps< + SearchEngine, + HistoryManager +> => ({ + build: (engine) => buildHistoryManager(engine), +}); diff --git a/packages/headless/src/controllers/index.ts b/packages/headless/src/controllers/index.ts index 292f0fb75cd..4120998819c 100644 --- a/packages/headless/src/controllers/index.ts +++ b/packages/headless/src/controllers/index.ts @@ -339,7 +339,7 @@ export type { SmartSnippetState, QuestionAnswerDocumentIdentifier, SmartSnippetCore, -} from './core/smart-snippet/headless-core-smart-snippet'; +} from './smart-snippet/headless-smart-snippet'; export {buildSmartSnippet} from './smart-snippet/headless-smart-snippet'; export type {InlineLink} from './smart-snippet/headless-smart-snippet-interactive-inline-links'; diff --git a/packages/headless/src/controllers/instant-results/instant-results.ssr.ts b/packages/headless/src/controllers/instant-results/instant-results.ssr.ts new file mode 100644 index 00000000000..43f5cf51b9b --- /dev/null +++ b/packages/headless/src/controllers/instant-results/instant-results.ssr.ts @@ -0,0 +1,18 @@ +import {SearchEngine} from '../../app/search-engine/search-engine'; +import {ControllerDefinitionWithoutProps} from '../../app/ssr-engine/types/common'; +import { + InstantResultProps, + InstantResults, + buildInstantResults, +} from './instant-results'; + +export * from './instant-results'; + +/** + * @internal + */ +export const defineInstantResults = ( + props: InstantResultProps +): ControllerDefinitionWithoutProps => ({ + build: (engine) => buildInstantResults(engine, props), +}); diff --git a/packages/headless/src/controllers/pager/headless-pager.ssr.ts b/packages/headless/src/controllers/pager/headless-pager.ssr.ts new file mode 100644 index 00000000000..eca92a17e98 --- /dev/null +++ b/packages/headless/src/controllers/pager/headless-pager.ssr.ts @@ -0,0 +1,14 @@ +import {SearchEngine} from '../../app/search-engine/search-engine'; +import {ControllerDefinitionWithoutProps} from '../../app/ssr-engine/types/common'; +import {Pager, PagerProps, buildPager} from './headless-pager'; + +export * from './headless-pager'; + +/** + * @internal + */ +export const definePager = ( + props?: PagerProps +): ControllerDefinitionWithoutProps => ({ + build: (engine) => buildPager(engine, props), +}); diff --git a/packages/headless/src/controllers/query-error/headless-query-error.ssr.ts b/packages/headless/src/controllers/query-error/headless-query-error.ssr.ts new file mode 100644 index 00000000000..06b833564f3 --- /dev/null +++ b/packages/headless/src/controllers/query-error/headless-query-error.ssr.ts @@ -0,0 +1,15 @@ +import {SearchEngine} from '../../app/search-engine/search-engine'; +import {ControllerDefinitionWithoutProps} from '../../app/ssr-engine/types/common'; +import {QueryError, buildQueryError} from './headless-query-error'; + +export * from './headless-query-error'; + +/** + * @internal + */ +export const defineQueryError = (): ControllerDefinitionWithoutProps< + SearchEngine, + QueryError +> => ({ + build: (engine) => buildQueryError(engine), +}); diff --git a/packages/headless/src/controllers/query-summary/headless-query-summary.ssr.ts b/packages/headless/src/controllers/query-summary/headless-query-summary.ssr.ts new file mode 100644 index 00000000000..9688cfdbbae --- /dev/null +++ b/packages/headless/src/controllers/query-summary/headless-query-summary.ssr.ts @@ -0,0 +1,15 @@ +import {SearchEngine} from '../../app/search-engine/search-engine'; +import {ControllerDefinitionWithoutProps} from '../../app/ssr-engine/types/common'; +import {QuerySummary, buildQuerySummary} from './headless-query-summary'; + +export * from './headless-query-summary'; + +/** + * @internal + */ +export const defineQuerySummary = (): ControllerDefinitionWithoutProps< + SearchEngine, + QuerySummary +> => ({ + build: (engine) => buildQuerySummary(engine), +}); diff --git a/packages/headless/src/controllers/quickview/headless-quickview.ssr.ts b/packages/headless/src/controllers/quickview/headless-quickview.ssr.ts new file mode 100644 index 00000000000..1fe9ac56144 --- /dev/null +++ b/packages/headless/src/controllers/quickview/headless-quickview.ssr.ts @@ -0,0 +1,14 @@ +import {SearchEngine} from '../../app/search-engine/search-engine'; +import {ControllerDefinitionWithoutProps} from '../../app/ssr-engine/types/common'; +import {Quickview, QuickviewProps, buildQuickview} from './headless-quickview'; + +export * from './headless-quickview'; + +/** + * @internal + */ +export const defineQuickview = ( + props: QuickviewProps +): ControllerDefinitionWithoutProps => ({ + build: (engine) => buildQuickview(engine, props), +}); diff --git a/packages/headless/src/controllers/recent-queries-list/headless-recent-queries-list.ssr.ts b/packages/headless/src/controllers/recent-queries-list/headless-recent-queries-list.ssr.ts new file mode 100644 index 00000000000..00c1d1490bb --- /dev/null +++ b/packages/headless/src/controllers/recent-queries-list/headless-recent-queries-list.ssr.ts @@ -0,0 +1,18 @@ +import {SearchEngine} from '../../app/search-engine/search-engine'; +import {ControllerDefinitionWithoutProps} from '../../app/ssr-engine/types/common'; +import { + RecentQueriesList, + RecentQueriesListProps, + buildRecentQueriesList, +} from './headless-recent-queries-list'; + +export * from './headless-recent-queries-list'; + +/** + * @internal + */ +export const defineRecentQueriesList = ( + props?: RecentQueriesListProps +): ControllerDefinitionWithoutProps => ({ + build: (engine) => buildRecentQueriesList(engine, props), +}); diff --git a/packages/headless/src/controllers/recent-results-list/headless-recent-results-list.ssr.ts b/packages/headless/src/controllers/recent-results-list/headless-recent-results-list.ssr.ts new file mode 100644 index 00000000000..34f02cae688 --- /dev/null +++ b/packages/headless/src/controllers/recent-results-list/headless-recent-results-list.ssr.ts @@ -0,0 +1,18 @@ +import {SearchEngine} from '../../app/search-engine/search-engine'; +import {ControllerDefinitionWithoutProps} from '../../app/ssr-engine/types/common'; +import { + RecentResultsList, + RecentResultsListProps, + buildRecentResultsList, +} from './headless-recent-results-list'; + +export * from './headless-recent-results-list'; + +/** + * @internal + */ +export const defineRecentResultsList = ( + props?: RecentResultsListProps +): ControllerDefinitionWithoutProps => ({ + build: (engine) => buildRecentResultsList(engine, props), +}); diff --git a/packages/headless/src/controllers/relevance-inspector/headless-relevance-inspector.ssr.ts b/packages/headless/src/controllers/relevance-inspector/headless-relevance-inspector.ssr.ts new file mode 100644 index 00000000000..6c9b20d5a3c --- /dev/null +++ b/packages/headless/src/controllers/relevance-inspector/headless-relevance-inspector.ssr.ts @@ -0,0 +1,18 @@ +import {SearchEngine} from '../../app/search-engine/search-engine'; +import {ControllerDefinitionWithoutProps} from '../../app/ssr-engine/types/common'; +import { + RelevanceInspector, + RelevanceInspectorProps, + buildRelevanceInspector, +} from './headless-relevance-inspector'; + +export * from './headless-relevance-inspector'; + +/** + * @internal + */ +export const defineRelevanceInspector = ( + props?: RelevanceInspectorProps +): ControllerDefinitionWithoutProps => ({ + build: (engine) => buildRelevanceInspector(engine, props), +}); diff --git a/packages/headless/src/controllers/result-list/headless-result-list.ssr.ts b/packages/headless/src/controllers/result-list/headless-result-list.ssr.ts index 98023ce8f08..6b26e3fbe19 100644 --- a/packages/headless/src/controllers/result-list/headless-result-list.ssr.ts +++ b/packages/headless/src/controllers/result-list/headless-result-list.ssr.ts @@ -6,12 +6,7 @@ import { buildResultList, } from './headless-result-list'; -export type { - ResultListOptions, - ResultListProps, - ResultListState, - ResultList, -} from './headless-result-list'; +export * from './headless-result-list'; /** * @internal diff --git a/packages/headless/src/controllers/results-per-page/headless-results-per-page.ssr.ts b/packages/headless/src/controllers/results-per-page/headless-results-per-page.ssr.ts new file mode 100644 index 00000000000..61c9b1422c0 --- /dev/null +++ b/packages/headless/src/controllers/results-per-page/headless-results-per-page.ssr.ts @@ -0,0 +1,18 @@ +import {SearchEngine} from '../../app/search-engine/search-engine'; +import {ControllerDefinitionWithoutProps} from '../../app/ssr-engine/types/common'; +import { + ResultsPerPage, + ResultsPerPageProps, + buildResultsPerPage, +} from './headless-results-per-page'; + +export * from './headless-results-per-page'; + +/** + * @internal + */ +export const defineResultsPerPage = ( + props?: ResultsPerPageProps +): ControllerDefinitionWithoutProps => ({ + build: (engine) => buildResultsPerPage(engine, props), +}); diff --git a/packages/headless/src/controllers/search-box/headless-search-box.ssr.ts b/packages/headless/src/controllers/search-box/headless-search-box.ssr.ts index e266eb39ed1..b3c47a39cef 100644 --- a/packages/headless/src/controllers/search-box/headless-search-box.ssr.ts +++ b/packages/headless/src/controllers/search-box/headless-search-box.ssr.ts @@ -2,12 +2,7 @@ import {SearchEngine} from '../../app/search-engine/search-engine'; import {ControllerDefinitionWithoutProps} from '../../app/ssr-engine/types/common'; import {SearchBox, SearchBoxProps, buildSearchBox} from './headless-search-box'; -export type { - SearchBoxOptions, - SearchBoxProps, - SearchBoxState, - SearchBox, -} from './headless-search-box'; +export * from './headless-search-box'; /** * @internal diff --git a/packages/headless/src/controllers/search-parameter-manager/headless-search-parameter-manager.ssr.ts b/packages/headless/src/controllers/search-parameter-manager/headless-search-parameter-manager.ssr.ts index 1afde0d027a..c8e2291e55c 100644 --- a/packages/headless/src/controllers/search-parameter-manager/headless-search-parameter-manager.ssr.ts +++ b/packages/headless/src/controllers/search-parameter-manager/headless-search-parameter-manager.ssr.ts @@ -6,11 +6,7 @@ import { buildSearchParameterManager, } from './headless-search-parameter-manager'; -export type { - SearchParameterManagerInitialState, - SearchParameterManagerState, - SearchParameterManager, -} from './headless-search-parameter-manager'; +export * from './headless-search-parameter-manager'; /** * @internal diff --git a/packages/headless/src/controllers/search-status/headless-search-status.ssr.ts b/packages/headless/src/controllers/search-status/headless-search-status.ssr.ts new file mode 100644 index 00000000000..059089ba8a2 --- /dev/null +++ b/packages/headless/src/controllers/search-status/headless-search-status.ssr.ts @@ -0,0 +1,15 @@ +import {SearchEngine} from '../../app/search-engine/search-engine'; +import {ControllerDefinitionWithoutProps} from '../../app/ssr-engine/types/common'; +import {SearchStatus, buildSearchStatus} from './headless-search-status'; + +export * from './headless-search-status'; + +/** + * @internal + */ +export const defineSearchStatus = (): ControllerDefinitionWithoutProps< + SearchEngine, + SearchStatus +> => ({ + build: (engine) => buildSearchStatus(engine), +}); diff --git a/packages/headless/src/controllers/smart-snippet-questions-list/headless-smart-snippet-questions-list.ssr.ts b/packages/headless/src/controllers/smart-snippet-questions-list/headless-smart-snippet-questions-list.ssr.ts new file mode 100644 index 00000000000..39a739b4101 --- /dev/null +++ b/packages/headless/src/controllers/smart-snippet-questions-list/headless-smart-snippet-questions-list.ssr.ts @@ -0,0 +1,21 @@ +import {SearchEngine} from '../../app/search-engine/search-engine'; +import {ControllerDefinitionWithoutProps} from '../../app/ssr-engine/types/common'; +import { + SmartSnippetQuestionsList, + SmartSnippetQuestionsListProps, + buildSmartSnippetQuestionsList, +} from './headless-smart-snippet-questions-list'; + +export * from './headless-smart-snippet-questions-list'; + +/** + * @internal + */ +export const defineSmartSnippetQuestionsList = ( + props?: SmartSnippetQuestionsListProps +): ControllerDefinitionWithoutProps< + SearchEngine, + SmartSnippetQuestionsList +> => ({ + build: (engine) => buildSmartSnippetQuestionsList(engine, props), +}); diff --git a/packages/headless/src/controllers/smart-snippet/headless-smart-snippet.ssr.ts b/packages/headless/src/controllers/smart-snippet/headless-smart-snippet.ssr.ts new file mode 100644 index 00000000000..916551ed1dd --- /dev/null +++ b/packages/headless/src/controllers/smart-snippet/headless-smart-snippet.ssr.ts @@ -0,0 +1,18 @@ +import {SearchEngine} from '../../app/search-engine/search-engine'; +import {ControllerDefinitionWithoutProps} from '../../app/ssr-engine/types/common'; +import { + SmartSnippet, + SmartSnippetProps, + buildSmartSnippet, +} from './headless-smart-snippet'; + +export * from './headless-smart-snippet'; + +/** + * @internal + */ +export const defineSmartSnippet = ( + props?: SmartSnippetProps +): ControllerDefinitionWithoutProps => ({ + build: (engine) => buildSmartSnippet(engine, props), +}); diff --git a/packages/headless/src/controllers/smart-snippet/headless-smart-snippet.ts b/packages/headless/src/controllers/smart-snippet/headless-smart-snippet.ts index 709333f52c6..6bd3a54514c 100644 --- a/packages/headless/src/controllers/smart-snippet/headless-smart-snippet.ts +++ b/packages/headless/src/controllers/smart-snippet/headless-smart-snippet.ts @@ -2,12 +2,22 @@ import {SearchEngine} from '../../app/search-engine/search-engine'; import {smartSnippetAnalyticsClient} from '../../features/question-answering/question-answering-analytics-actions'; import { SmartSnippet, + SmartSnippetCore, + SmartSnippetOptions, SmartSnippetProps, + SmartSnippetState, buildCoreSmartSnippet, } from '../core/smart-snippet/headless-core-smart-snippet'; import {buildSmartSnippetInteractiveInlineLinks} from './headless-smart-snippet-interactive-inline-links'; export type {QuestionAnswerDocumentIdentifier} from '../../api/search/search/question-answering'; +export type { + SmartSnippet, + SmartSnippetOptions, + SmartSnippetProps, + SmartSnippetState, + SmartSnippetCore, +}; /** * Creates a `SmartSnippet` controller instance. diff --git a/packages/headless/src/controllers/sort/headless-sort.ssr.ts b/packages/headless/src/controllers/sort/headless-sort.ssr.ts new file mode 100644 index 00000000000..4880a6caa4f --- /dev/null +++ b/packages/headless/src/controllers/sort/headless-sort.ssr.ts @@ -0,0 +1,14 @@ +import {SearchEngine} from '../../app/search-engine/search-engine'; +import {ControllerDefinitionWithoutProps} from '../../app/ssr-engine/types/common'; +import {Sort, SortProps, buildSort} from './headless-sort'; + +export * from './headless-sort'; + +/** + * @internal + */ +export const defineSort = ( + props?: SortProps +): ControllerDefinitionWithoutProps => ({ + build: (engine) => buildSort(engine, props), +}); diff --git a/packages/headless/src/controllers/ssr.index.ts b/packages/headless/src/controllers/ssr.index.ts new file mode 100644 index 00000000000..8b9dffc3e90 --- /dev/null +++ b/packages/headless/src/controllers/ssr.index.ts @@ -0,0 +1,391 @@ +export type {Controller, Subscribable} from './controller/headless-controller'; +export type { + RelevanceInspectorInitialState, + RelevanceInspectorProps, + RelevanceInspectorState, + RelevanceInspector, + DocumentWeights, + ExecutionReport, + ExecutionStep, + QueryExpressions, + QueryRankingExpressionWeights, + QueryRankingExpression, + ResultRankingInformation, + RankingInformation, + TermWeightReport, + SecurityIdentity, +} from './relevance-inspector/headless-relevance-inspector.ssr'; +export {defineRelevanceInspector} from './relevance-inspector/headless-relevance-inspector.ssr'; + +export type { + Context, + ContextState, + ContextValue, + ContextPayload, +} from './context/headless-context.ssr'; +export {defineContext} from './context/headless-context.ssr'; + +export type { + DictionaryFieldContext, + DictionaryFieldContextState, + DictionaryFieldContextPayload, +} from './dictionary-field-context/headless-dictionary-field-context.ssr'; +export {defineDictionaryFieldContext} from './dictionary-field-context/headless-dictionary-field-context.ssr'; + +export type { + DidYouMean, + DidYouMeanState, + QueryCorrection, + WordCorrection, +} from './did-you-mean/headless-did-you-mean.ssr'; +export {defineDidYouMean} from './did-you-mean/headless-did-you-mean.ssr'; + +export type { + CategoryFacetOptions, + CategoryFacetSearchOptions, + CategoryFacetProps, + CategoryFacetState, + CategoryFacet, + CategoryFacetValue, + CategoryFacetSearch, + CategoryFacetSearchState, + CategoryFacetSearchResult, + CoreCategoryFacet, + CoreCategoryFacetState, +} from './facets/category-facet/headless-category-facet.ssr'; +export {defineCategoryFacet} from './facets/category-facet/headless-category-facet.ssr'; + +export type { + FacetOptions, + FacetSearchOptions, + FacetProps, + FacetState, + Facet, + FacetValue, + FacetValueState, + FacetSearch, + FacetSearchState, + SpecificFacetSearchResult, + CoreFacet, + CoreFacetState, +} from './facets/facet/headless-facet.ssr'; +export {defineFacet} from './facets/facet/headless-facet.ssr'; + +export type { + DateRangeOptions, + DateRangeRequest, + DateRangeInput, + DateFacetOptions, + DateFacetProps, + DateFacetState, + DateFacet, +} from './facets/range-facet/date-facet/headless-date-facet.ssr'; +export { + buildDateRange, + defineDateFacet, +} from './facets/range-facet/date-facet/headless-date-facet.ssr'; + +export type { + NumericRangeOptions, + NumericRangeRequest, + NumericFacetOptions, + NumericFacetProps, + NumericFacetState, + NumericFacet, +} from './facets/range-facet/numeric-facet/headless-numeric-facet.ssr'; +export { + buildNumericRange, + defineNumericFacet, +} from './facets/range-facet/numeric-facet/headless-numeric-facet.ssr'; + +export type { + NumericFilter, + NumericFilterOptions, + NumericFilterProps, + NumericFilterRange, + NumericFilterState, + NumericFilterInitialState, +} from './facets/range-facet/numeric-facet/headless-numeric-filter.ssr'; +export {defineNumericFilter} from './facets/range-facet/numeric-facet/headless-numeric-filter.ssr'; + +export type { + DateFilter, + DateFilterOptions, + DateFilterProps, + DateFilterRange, + DateFilterState, + DateFilterInitialState, +} from './facets/range-facet/date-facet/headless-date-filter.ssr'; +export {defineDateFilter} from './facets/range-facet/date-facet/headless-date-filter.ssr'; + +export type { + HistoryManager, + HistoryManagerState, +} from './history-manager/headless-history-manager.ssr'; +export {defineHistoryManager} from './history-manager/headless-history-manager.ssr'; + +export type { + PagerInitialState, + PagerOptions, + PagerProps, + PagerState, + Pager, +} from './pager/headless-pager.ssr'; +export {definePager} from './pager/headless-pager.ssr'; + +export type { + QueryError, + QueryErrorState, +} from './query-error/headless-query-error.ssr'; +export {defineQueryError} from './query-error/headless-query-error.ssr'; + +export type { + QuerySummaryState, + QuerySummary, +} from './query-summary/headless-query-summary.ssr'; +export {defineQuerySummary} from './query-summary/headless-query-summary.ssr'; + +export type { + ResultListProps, + ResultListOptions, + ResultListState, + ResultList, +} from './result-list/headless-result-list.ssr'; +export {defineResultList} from './result-list/headless-result-list.ssr'; + +export type { + ResultsPerPageInitialState, + ResultsPerPageProps, + ResultsPerPageState, + ResultsPerPage, +} from './results-per-page/headless-results-per-page.ssr'; +export {defineResultsPerPage} from './results-per-page/headless-results-per-page.ssr'; + +export type { + SearchBoxOptions, + SearchBoxProps, + SearchBoxState, + SearchBox, + Suggestion, + SuggestionHighlightingOptions, + Delimiters, +} from './search-box/headless-search-box.ssr'; +export {defineSearchBox} from './search-box/headless-search-box.ssr'; + +export type { + InstantResults, + InstantResultsState, + InstantResultProps, + InstantResultOptions, +} from './instant-results/instant-results.ssr'; +export {defineInstantResults} from './instant-results/instant-results.ssr'; + +export type { + SortInitialState, + SortProps, + SortState, + Sort, +} from './sort/headless-sort.ssr'; +export {defineSort} from './sort/headless-sort.ssr'; + +export type { + StaticFilterValueOptions, + StaticFilter, + StaticFilterOptions, + StaticFilterProps, + StaticFilterState, + StaticFilterValue, + StaticFilterValueState, +} from './static-filter/headless-static-filter.ssr'; +export { + buildStaticFilterValue, + defineStaticFilter, +} from './static-filter/headless-static-filter.ssr'; + +export type { + TabInitialState, + TabOptions, + TabProps, + TabState, + Tab, +} from './tab/headless-tab.ssr'; +export {defineTab} from './tab/headless-tab.ssr'; + +export type { + FacetManagerPayload, + FacetManagerState, + FacetManager, +} from './facet-manager/headless-facet-manager.ssr'; +export {defineFacetManager} from './facet-manager/headless-facet-manager.ssr'; + +export type { + NumericFacetBreadcrumb, + FacetBreadcrumb, + DateFacetBreadcrumb, + CategoryFacetBreadcrumb, + StaticFilterBreadcrumb, + Breadcrumb, + BreadcrumbValue, + BreadcrumbManagerState, + BreadcrumbManager, + DeselectableValue, + AutomaticFacetBreadcrumb, + CoreBreadcrumbManager, + CoreBreadcrumbManagerState, +} from './breadcrumb-manager/headless-breadcrumb-manager.ssr'; +export {defineBreadcrumbManager} from './breadcrumb-manager/headless-breadcrumb-manager.ssr'; + +export type { + StandaloneSearchBoxOptions, + StandaloneSearchBoxAnalytics, + StandaloneSearchBoxProps, + StandaloneSearchBoxState, + StandaloneSearchBox, +} from './standalone-search-box/headless-standalone-search-box.ssr'; +export {defineStandaloneSearchBox} from './standalone-search-box/headless-standalone-search-box.ssr'; + +export type { + SearchParameterManagerBuildProps, + SearchParameterManagerInitialState, + SearchParameterManagerState, + SearchParameterManager, + SearchParameters, +} from './search-parameter-manager/headless-search-parameter-manager.ssr'; +export {defineSearchParameterManager} from './search-parameter-manager/headless-search-parameter-manager.ssr'; + +export type { + UrlManagerProps, + UrlManagerInitialState, + UrlManagerState, + UrlManager, +} from './url-manager/headless-url-manager.ssr'; +export {defineUrlManager} from './url-manager/headless-url-manager.ssr'; + +export type { + SearchStatus, + SearchStatusState, +} from './search-status/headless-search-status.ssr'; +export {defineSearchStatus} from './search-status/headless-search-status.ssr'; + +export type {ErrorPayload} from './controller/error-payload'; + +export type { + Quickview, + QuickviewOptions, + QuickviewProps, + QuickviewState, + CoreQuickviewState, + CoreQuickview, +} from './quickview/headless-quickview.ssr'; +export {defineQuickview} from './quickview/headless-quickview.ssr'; + +export type { + FoldingOptions, + FoldedCollection, + FoldedResult, + FoldedResultListOptions, + FoldedResultListProps, + FoldedResultList, + FoldedResultListState, +} from './folded-result-list/headless-folded-result-list.ssr'; +export {defineFoldedResultList} from './folded-result-list/headless-folded-result-list.ssr'; + +export type { + RedirectionTrigger, + RedirectionTriggerState, +} from './triggers/headless-redirection-trigger.ssr'; +export {defineRedirectionTrigger} from './triggers/headless-redirection-trigger.ssr'; + +export type { + QueryTrigger, + QueryTriggerState, +} from './triggers/headless-query-trigger.ssr'; +export {defineQueryTrigger} from './triggers/headless-query-trigger.ssr'; + +export type { + ExecuteTrigger, + ExecuteTriggerState, +} from './triggers/headless-execute-trigger.ssr'; +export {defineExecuteTrigger} from './triggers/headless-execute-trigger.ssr'; + +export type {ExecuteTriggerParams} from '../api/search/trigger'; + +export type { + NotifyTrigger, + NotifyTriggerState, +} from './triggers/headless-notify-trigger.ssr'; +export {defineNotifyTrigger} from './triggers/headless-notify-trigger.ssr'; + +export type { + SmartSnippet, + SmartSnippetOptions, + SmartSnippetProps, + SmartSnippetState, + QuestionAnswerDocumentIdentifier, + SmartSnippetCore, +} from './smart-snippet/headless-smart-snippet.ssr'; +export {defineSmartSnippet} from './smart-snippet/headless-smart-snippet.ssr'; + +export type {InlineLink} from './smart-snippet/headless-smart-snippet-interactive-inline-links'; + +export type { + SmartSnippetQuestionsList, + SmartSnippetQuestionsListOptions, + SmartSnippetQuestionsListProps, + SmartSnippetQuestionsListState, + SmartSnippetRelatedQuestion, + CoreSmartSnippetQuestionsList, + CoreSmartSnippetQuestionsListState, +} from './smart-snippet-questions-list/headless-smart-snippet-questions-list.ssr'; +export {defineSmartSnippetQuestionsList} from './smart-snippet-questions-list/headless-smart-snippet-questions-list.ssr'; + +export type { + RecentQueriesListInitialState, + RecentQueriesList, + RecentQueriesState, + RecentQueriesListProps, + RecentQueriesListOptions, +} from './recent-queries-list/headless-recent-queries-list.ssr'; +export {defineRecentQueriesList} from './recent-queries-list/headless-recent-queries-list.ssr'; + +export type { + RecentResultsListInitialState, + RecentResultsList, + RecentResultsState, + RecentResultsListProps, + RecentResultsListOptions, +} from './recent-results-list/headless-recent-results-list.ssr'; +export {defineRecentResultsList} from './recent-results-list/headless-recent-results-list.ssr'; + +export type { + FieldSuggestionsValue, + FieldSuggestionsState, + FieldSuggestions, + FieldSuggestionsOptions, + FieldSuggestionsProps, +} from './field-suggestions/facet/headless-field-suggestions.ssr'; +export {defineFieldSuggestions} from './field-suggestions/facet/headless-field-suggestions.ssr'; + +export type { + CategoryFieldSuggestionsValue, + CategoryFieldSuggestionsState, + CategoryFieldSuggestions, + CategoryFieldSuggestionsOptions, + CategoryFieldSuggestionsProps, +} from './field-suggestions/category-facet/headless-category-field-suggestions.ssr'; +export {defineCategoryFieldSuggestions} from './field-suggestions/category-facet/headless-category-field-suggestions.ssr'; + +export type { + AutomaticFacet, + AutomaticFacetProps, + AutomaticFacetState, +} from './facets/automatic-facet/headless-automatic-facet.ssr'; +export {defineAutomaticFacet} from './facets/automatic-facet/headless-automatic-facet.ssr'; + +export type { + AutomaticFacetGenerator, + AutomaticFacetGeneratorProps, + AutomaticFacetGeneratorState, + AutomaticFacetGeneratorOptions, +} from './facets/automatic-facet-generator/headless-automatic-facet-generator.ssr'; +export {defineAutomaticFacetGenerator} from './facets/automatic-facet-generator/headless-automatic-facet-generator.ssr'; diff --git a/packages/headless/src/controllers/standalone-search-box/headless-standalone-search-box.ssr.ts b/packages/headless/src/controllers/standalone-search-box/headless-standalone-search-box.ssr.ts new file mode 100644 index 00000000000..76236d25edc --- /dev/null +++ b/packages/headless/src/controllers/standalone-search-box/headless-standalone-search-box.ssr.ts @@ -0,0 +1,18 @@ +import {SearchEngine} from '../../app/search-engine/search-engine'; +import {ControllerDefinitionWithoutProps} from '../../app/ssr-engine/types/common'; +import { + StandaloneSearchBox, + StandaloneSearchBoxProps, + buildStandaloneSearchBox, +} from './headless-standalone-search-box'; + +export * from './headless-standalone-search-box'; + +/** + * @internal + */ +export const defineStandaloneSearchBox = ( + props: StandaloneSearchBoxProps +): ControllerDefinitionWithoutProps => ({ + build: (engine) => buildStandaloneSearchBox(engine, props), +}); diff --git a/packages/headless/src/controllers/static-filter/headless-static-filter.ssr.ts b/packages/headless/src/controllers/static-filter/headless-static-filter.ssr.ts new file mode 100644 index 00000000000..ab0a4c12984 --- /dev/null +++ b/packages/headless/src/controllers/static-filter/headless-static-filter.ssr.ts @@ -0,0 +1,20 @@ +import {SearchEngine} from '../../app/search-engine/search-engine'; +import {ControllerDefinitionWithoutProps} from '../../app/ssr-engine/types/common'; +import { + StaticFilter, + StaticFilterProps, + buildStaticFilter, +} from './headless-static-filter'; + +export * from './headless-static-filter'; + +export {buildStaticFilterValue} from './headless-static-filter'; + +/** + * @internal + */ +export const defineStaticFilter = ( + props: StaticFilterProps +): ControllerDefinitionWithoutProps => ({ + build: (engine) => buildStaticFilter(engine, props), +}); diff --git a/packages/headless/src/controllers/tab/headless-tab.ssr.ts b/packages/headless/src/controllers/tab/headless-tab.ssr.ts new file mode 100644 index 00000000000..bf495eda80e --- /dev/null +++ b/packages/headless/src/controllers/tab/headless-tab.ssr.ts @@ -0,0 +1,14 @@ +import {SearchEngine} from '../../app/search-engine/search-engine'; +import {ControllerDefinitionWithoutProps} from '../../app/ssr-engine/types/common'; +import {Tab, TabProps, buildTab} from './headless-tab'; + +export * from './headless-tab'; + +/** + * @internal + */ +export const defineTab = ( + props: TabProps +): ControllerDefinitionWithoutProps => ({ + build: (engine) => buildTab(engine, props), +}); diff --git a/packages/headless/src/controllers/triggers/headless-execute-trigger.ssr.ts b/packages/headless/src/controllers/triggers/headless-execute-trigger.ssr.ts new file mode 100644 index 00000000000..3edfdaa9c95 --- /dev/null +++ b/packages/headless/src/controllers/triggers/headless-execute-trigger.ssr.ts @@ -0,0 +1,15 @@ +import {SearchEngine} from '../../app/search-engine/search-engine'; +import {ControllerDefinitionWithoutProps} from '../../app/ssr-engine/types/common'; +import {ExecuteTrigger, buildExecuteTrigger} from './headless-execute-trigger'; + +export * from './headless-execute-trigger'; + +/** + * @internal + */ +export const defineExecuteTrigger = (): ControllerDefinitionWithoutProps< + SearchEngine, + ExecuteTrigger +> => ({ + build: (engine) => buildExecuteTrigger(engine), +}); diff --git a/packages/headless/src/controllers/triggers/headless-notify-trigger.ssr.ts b/packages/headless/src/controllers/triggers/headless-notify-trigger.ssr.ts new file mode 100644 index 00000000000..9f7c29bc5a7 --- /dev/null +++ b/packages/headless/src/controllers/triggers/headless-notify-trigger.ssr.ts @@ -0,0 +1,15 @@ +import {SearchEngine} from '../../app/search-engine/search-engine'; +import {ControllerDefinitionWithoutProps} from '../../app/ssr-engine/types/common'; +import {NotifyTrigger, buildNotifyTrigger} from './headless-notify-trigger'; + +export * from './headless-notify-trigger'; + +/** + * @internal + */ +export const defineNotifyTrigger = (): ControllerDefinitionWithoutProps< + SearchEngine, + NotifyTrigger +> => ({ + build: (engine) => buildNotifyTrigger(engine), +}); diff --git a/packages/headless/src/controllers/triggers/headless-query-trigger.ssr.ts b/packages/headless/src/controllers/triggers/headless-query-trigger.ssr.ts new file mode 100644 index 00000000000..205502fabda --- /dev/null +++ b/packages/headless/src/controllers/triggers/headless-query-trigger.ssr.ts @@ -0,0 +1,15 @@ +import {SearchEngine} from '../../app/search-engine/search-engine'; +import {ControllerDefinitionWithoutProps} from '../../app/ssr-engine/types/common'; +import {QueryTrigger, buildQueryTrigger} from './headless-query-trigger'; + +export * from './headless-query-trigger'; + +/** + * @internal + */ +export const defineQueryTrigger = (): ControllerDefinitionWithoutProps< + SearchEngine, + QueryTrigger +> => ({ + build: (engine) => buildQueryTrigger(engine), +}); diff --git a/packages/headless/src/controllers/triggers/headless-redirection-trigger.ssr.ts b/packages/headless/src/controllers/triggers/headless-redirection-trigger.ssr.ts new file mode 100644 index 00000000000..391b9118cb9 --- /dev/null +++ b/packages/headless/src/controllers/triggers/headless-redirection-trigger.ssr.ts @@ -0,0 +1,18 @@ +import {SearchEngine} from '../../app/search-engine/search-engine'; +import {ControllerDefinitionWithoutProps} from '../../app/ssr-engine/types/common'; +import { + RedirectionTrigger, + buildRedirectionTrigger, +} from './headless-redirection-trigger'; + +export * from './headless-redirection-trigger'; + +/** + * @internal + */ +export const defineRedirectionTrigger = (): ControllerDefinitionWithoutProps< + SearchEngine, + RedirectionTrigger +> => ({ + build: (engine) => buildRedirectionTrigger(engine), +}); diff --git a/packages/headless/src/controllers/url-manager/headless-url-manager.ssr.ts b/packages/headless/src/controllers/url-manager/headless-url-manager.ssr.ts new file mode 100644 index 00000000000..ab63685f1e4 --- /dev/null +++ b/packages/headless/src/controllers/url-manager/headless-url-manager.ssr.ts @@ -0,0 +1,18 @@ +import {SearchEngine} from '../../app/search-engine/search-engine'; +import {ControllerDefinitionWithoutProps} from '../../app/ssr-engine/types/common'; +import { + UrlManager, + UrlManagerProps, + buildUrlManager, +} from './headless-url-manager'; + +export * from './headless-url-manager'; + +/** + * @internal + */ +export const defineUrlManager = ( + props: UrlManagerProps +): ControllerDefinitionWithoutProps => ({ + build: (engine) => buildUrlManager(engine, props), +}); diff --git a/packages/headless/src/ssr.index.ts b/packages/headless/src/ssr.index.ts index ffe4693fcd6..74539d33084 100644 --- a/packages/headless/src/ssr.index.ts +++ b/packages/headless/src/ssr.index.ts @@ -4,8 +4,30 @@ polyfillCryptoNode(); // 3rd Party Libraries export type {Unsubscribe, Middleware} from '@reduxjs/toolkit'; +export {createAction, createAsyncThunk, createReducer} from '@reduxjs/toolkit'; +export type {AnalyticsClientSendEventHook} from 'coveo.analytics'; +// Main App // ⚠️ NOTE: All exported SSR types, APIs should be marked as `@internal` until MVP is complete +export type { + SearchEngine, + SearchEngineOptions, + SearchEngineConfiguration, + SearchConfigurationOptions, +} from './app/search-engine/search-engine'; +export type { + SearchEngineDefinition, + SearchEngineDefinitionOptions, +} from './app/search-engine/search-engine.ssr'; +export {defineSearchEngine} from './app/search-engine/search-engine.ssr'; +export {getSampleSearchEngineConfiguration} from './app/search-engine/search-engine'; + +export type {CoreEngine, ExternalEngineOptions} from './app/engine'; +export type { + EngineConfiguration, + AnalyticsConfiguration, + AnalyticsRuntimeEnvironment, +} from './app/engine-configuration'; export type { ControllerDefinitionWithoutProps, ControllerDefinitionWithProps, @@ -15,38 +37,122 @@ export type { InferControllerStaticStateFromDefinition, InferControllerStaticStateMapFromDefinitions, } from './app/ssr-engine/types/common'; - export type { EngineDefinition, InferStaticState, InferHydratedState, } from './app/ssr-engine/types/core-engine'; +export type {LoggerOptions} from './app/logger'; + +export type {LogLevel} from './app/logger'; +// State export type { - SearchEngineDefinition, - SearchEngineDefinitionOptions, -} from './app/search-engine/search-engine.ssr'; -export {defineSearchEngine} from './app/search-engine/search-engine.ssr'; + SearchParametersState, + SearchAppState, +} from './state/search-app-state'; + +// Controllers +export * from './controllers/ssr.index'; + +// Selectors +export { + baseFacetResponseSelector, + facetRequestSelector, + facetResponseSelector, + facetResponseSelectedValuesSelector, +} from './features/facets/facet-set/facet-set-selectors'; + +export { + currentPageSelector, + maxPageSelector, + currentPagesSelector, +} from './features/pagination/pagination-selectors'; +// Grouped Actions +export * from './features/index'; + +// Analytics Actions +export * from './features/analytics/index'; + +// Types & Helpers +export {API_DATE_FORMAT} from './api/search/date/date-format'; +export type {Result} from './api/search/search/result'; +export type {FieldDescription} from './api/search/fields/fields-response'; +export type {Raw} from './api/search/search/raw'; export type { - SearchBox, - SearchBoxOptions, - SearchBoxProps, - SearchBoxState, -} from './controllers/search-box/headless-search-box.ssr'; -export {defineSearchBox} from './controllers/search-box/headless-search-box.ssr'; + TermsToHighlight, + PhrasesToHighlight, +} from './api/search/search/stemming'; export type { - ResultList, - ResultListOptions, - ResultListProps, - ResultListState, -} from './controllers/result-list/headless-result-list.ssr'; -export {defineResultList} from './controllers/result-list/headless-result-list.ssr'; - + SortCriterion, + SortByDate, + SortByField, + SortByNoSort, + SortByQRE, + SortByRelevancy, +} from './features/sort-criteria/criteria'; +export { + SortBy, + SortOrder, + buildDateSortCriterion, + buildCriterionExpression, + buildFieldSortCriterion, + buildNoSortCriterion, + buildQueryRankingExpressionSortCriterion, + buildRelevanceSortCriterion, +} from './features/sort-criteria/criteria'; +export {parseCriterionExpression} from './features/sort-criteria/criteria-parser'; +export type {ResultTemplatesManager} from './features/result-templates/result-templates-manager'; export type { - SearchParameterManager, - SearchParameterManagerInitialState, - SearchParameterManagerBuildProps, - SearchParameterManagerState, -} from './controllers/search-parameter-manager/headless-search-parameter-manager.ssr'; -export {defineSearchParameterManager} from './controllers/search-parameter-manager/headless-search-parameter-manager.ssr'; + ResultTemplate, + ResultTemplateCondition, +} from './features/result-templates/result-templates'; +export { + platformUrl, + analyticsUrl, + getOrganizationEndpoints, +} from './api/platform-client'; +export type {PlatformEnvironment} from './utils/url-utils'; +export type { + CategoryFacetValueRequest, + CategoryFacetSortCriterion, +} from './features/facets/category-facet-set/interfaces/request'; +export type {DateRangeRequest} from './features/facets/range-facets/date-facet-set/interfaces/request'; +export type { + CategoryFacetValue, + CategoryFacetValueCommon, +} from './features/facets/category-facet-set/interfaces/response'; +export type {DateFacetValue} from './features/facets/range-facets/date-facet-set/interfaces/response'; +export type { + FacetValueRequest, + FacetSortCriterion, +} from './features/facets/facet-set/interfaces/request'; +export type {FacetResultsMustMatch} from './features/facets/facet-api/request'; +export type {NumericRangeRequest} from './features/facets/range-facets/numeric-facet-set/interfaces/request'; +export type {NumericFacetValue} from './features/facets/range-facets/numeric-facet-set/interfaces/response'; +export type {AnyFacetValueRequest} from './features/facets/generic/interfaces/generic-facet-request'; +export type { + RangeFacetSortCriterion, + RangeFacetRangeAlgorithm, +} from './features/facets/range-facets/generic/interfaces/request'; +export { + MinimumFieldsToInclude, + DefaultFieldsToInclude, + EcommerceDefaultFieldsToInclude, +} from './features/fields/fields-state'; +export {buildSearchParameterSerializer} from './features/search-parameters/search-parameter-serializer'; +export type {FunctionExecutionTrigger} from './features/triggers/triggers-state'; +export type {HighlightKeyword} from './utils/highlight'; +export {VERSION} from './utils/version'; +export type { + RelativeDate, + RelativeDatePeriod, + RelativeDateUnit, +} from './api/search/date/relative-date'; +export { + deserializeRelativeDate, + validateRelativeDate, +} from './api/search/date/relative-date'; + +export * from './utils/query-expression/query-expression'; diff --git a/packages/samples/headless-ssr/cypress/e2e/smoke.cy.ts b/packages/samples/headless-ssr/cypress/e2e/smoke.cy.ts index 3a35261e9f3..85e4a7f2bbe 100644 --- a/packages/samples/headless-ssr/cypress/e2e/smoke.cy.ts +++ b/packages/samples/headless-ssr/cypress/e2e/smoke.cy.ts @@ -1,7 +1,7 @@ import 'cypress-web-vitals'; import { ConsoleAliases, - compareWithInitialResults, + getResultTitles, numResults, spyOnConsole, waitForHydration, @@ -11,7 +11,9 @@ const numResultsMsg = `Rendered page with ${numResults} results`; const msgSelector = '#hydrated-msg'; const timestampSelector = '#timestamp'; const resultListSelector = '.result-list li'; +const searchBoxSelector = '.search-box input'; const routes = ['generic', 'react'] as const; +// Note: Thresholds might need to be adjusted as the page tested changes (e.g. more components are added etc) const vitals: Record = { generic: { thresholds: { @@ -82,10 +84,11 @@ routes.forEach((route) => { }); it('should pass the web-vitals audits', () => { - // Note: Thresholds might need to be adjusted as the page tested changes (e.g. more components are added etc) - cy.startVitalsCapture({url: route}); - compareWithInitialResults(); - cy.reportVitals(vitals[route]); + cy.vitals({ + ...vitals[route], + url: route, + firstInputSelector: '.facet-values > li:first-of-type > input', + }); }); }); @@ -103,7 +106,15 @@ routes.forEach((route) => { }); it('after submitting a query, should change search results', () => { - compareWithInitialResults(); + getResultTitles().should('have.length', numResults).as('initial-results'); + waitForHydration(); + cy.get(searchBoxSelector).focus().type('abc{enter}'); + cy.wait(1000); + cy.get('@initial-results').then((initialResults) => { + getResultTitles() + .should('have.length', numResults) + .and('not.deep.equal', initialResults); + }); }); }); }); diff --git a/packages/samples/headless-ssr/cypress/e2e/utils.ts b/packages/samples/headless-ssr/cypress/e2e/utils.ts index 82f43b82842..b7b8cea68e6 100644 --- a/packages/samples/headless-ssr/cypress/e2e/utils.ts +++ b/packages/samples/headless-ssr/cypress/e2e/utils.ts @@ -1,4 +1,3 @@ -const searchBoxSelector = '.search-box input'; export const numResults = 10; export const ConsoleAliases = { @@ -26,15 +25,3 @@ export function getResultTitles() { }) as Cypress.Chainable> ).invoke('toArray'); } - -export function compareWithInitialResults() { - getResultTitles().should('have.length', numResults).as('initial-results'); - waitForHydration(); - cy.get(searchBoxSelector).focus().type('abc{enter}'); - cy.wait(1000); - cy.get('@initial-results').then((initialResults) => { - getResultTitles() - .should('have.length', numResults) - .and('not.deep.equal', initialResults); - }); -} diff --git a/packages/samples/headless-ssr/src/app/common/facet-search.tsx b/packages/samples/headless-ssr/src/app/common/facet-search.tsx new file mode 100644 index 00000000000..3da6fc9b1c0 --- /dev/null +++ b/packages/samples/headless-ssr/src/app/common/facet-search.tsx @@ -0,0 +1,50 @@ +import { + FacetState, + Facet as FacetController, + Controller, + SpecificFacetSearchResult, +} from '@coveo/headless/ssr'; +import {FunctionComponent, useEffect, useState} from 'react'; + +interface FacetSearchProps { + query: string; + facetSearchResults: SpecificFacetSearchResult[]; + isLoading: boolean; + onUpdateQuery?(query: string): void; + onSubmit?(): void; + onToggle?(facetSearchResult: SpecificFacetSearchResult): void; +} + +export default function FacetSearchCommon({ + query, + facetSearchResults, + isLoading, + onUpdateQuery, + onSubmit, + onToggle, +}: FacetSearchProps) { + return ( + <> +
{ + e.preventDefault(); + onSubmit?.(); + }} + > + onUpdateQuery?.(e.target.value)} + /> +
+
    + {facetSearchResults.map((value) => ( +
  • + +
  • + ))} +
+ + ); +} diff --git a/packages/samples/headless-ssr/src/app/common/facet.tsx b/packages/samples/headless-ssr/src/app/common/facet.tsx new file mode 100644 index 00000000000..18d5ab75815 --- /dev/null +++ b/packages/samples/headless-ssr/src/app/common/facet.tsx @@ -0,0 +1,59 @@ +import { + FacetState, + Facet, + FacetValue, + SpecificFacetSearchResult, +} from '@coveo/headless/ssr'; +import {useEffect, useState, FunctionComponent, useMemo} from 'react'; +import FacetSearchCommon from './facet-search'; + +interface FacetProps { + title: string; + values: FacetValue[]; + facetSearchQuery: string; + facetSearchResults: SpecificFacetSearchResult[]; + isLoading: boolean; + onToggleValue?(value: FacetValue): void; + onToggleSearchResult?(facetSearchResult: SpecificFacetSearchResult): void; + onUpdateSearchQuery?(query: string): void; + onSubmitSearch?(): void; +} + +export default function FacetCommon({ + title, + values, + facetSearchQuery, + facetSearchResults, + isLoading, + onToggleValue, + onToggleSearchResult, + onUpdateSearchQuery, + onSubmitSearch, +}: FacetProps) { + return ( +
+ {title} facet + +
    + {values.map((value) => ( +
  • + onToggleValue?.(value)} + disabled={isLoading} + /> + {value.value} ({value.numberOfResults} results) +
  • + ))} +
+
+ ); +} diff --git a/packages/samples/headless-ssr/src/app/common/result-list.tsx b/packages/samples/headless-ssr/src/app/common/result-list.tsx index c0233fd50a7..72e72bda16e 100644 --- a/packages/samples/headless-ssr/src/app/common/result-list.tsx +++ b/packages/samples/headless-ssr/src/app/common/result-list.tsx @@ -1,4 +1,4 @@ -import {Result} from '@coveo/headless'; +import {Result} from '@coveo/headless/ssr'; interface ResultListCommonProps { results: Result[]; diff --git a/packages/samples/headless-ssr/src/app/common/search-box.tsx b/packages/samples/headless-ssr/src/app/common/search-box.tsx index 7cb78dcec3c..f72fd8a7d40 100644 --- a/packages/samples/headless-ssr/src/app/common/search-box.tsx +++ b/packages/samples/headless-ssr/src/app/common/search-box.tsx @@ -1,4 +1,4 @@ -import {SearchBox as SearchBoxController} from '@coveo/headless'; +import {SearchBox as SearchBoxController} from '@coveo/headless/ssr'; interface SearchBoxCommonProps { controller: Omit | undefined; diff --git a/packages/samples/headless-ssr/src/app/common/search-engine-config.ts b/packages/samples/headless-ssr/src/app/common/search-engine-config.ts index 6f1c0c2c5aa..995e15589a7 100644 --- a/packages/samples/headless-ssr/src/app/common/search-engine-config.ts +++ b/packages/samples/headless-ssr/src/app/common/search-engine-config.ts @@ -1,5 +1,10 @@ -import {getSampleSearchEngineConfiguration} from '@coveo/headless'; import { + Controller, + ControllerDefinitionsMap, + SearchEngine, + SearchEngineDefinitionOptions, + getSampleSearchEngineConfiguration, + defineFacet, defineResultList, defineSearchBox, defineSearchParameterManager, @@ -13,6 +18,9 @@ export const config = { controllers: { searchBox: defineSearchBox(), resultList: defineResultList(), + authorFacet: defineFacet({options: {facetId: 'author-1', field: 'author'}}), searchParameters: defineSearchParameterManager(), }, -}; +} satisfies SearchEngineDefinitionOptions< + ControllerDefinitionsMap +>; diff --git a/packages/samples/headless-ssr/src/app/common/search-parameters-serializer.ts b/packages/samples/headless-ssr/src/app/common/search-parameters-serializer.ts index 9e5ebbf184e..399c9e48a2b 100644 --- a/packages/samples/headless-ssr/src/app/common/search-parameters-serializer.ts +++ b/packages/samples/headless-ssr/src/app/common/search-parameters-serializer.ts @@ -1,4 +1,4 @@ -import {SearchParameters} from '@coveo/headless'; +import {SearchParameters} from '@coveo/headless/ssr'; import {ReadonlyURLSearchParams} from 'next/navigation'; export type NextJSServerSideSearchParams = Record< diff --git a/packages/samples/headless-ssr/src/app/generic/components/facet-search.tsx b/packages/samples/headless-ssr/src/app/generic/components/facet-search.tsx new file mode 100644 index 00000000000..00aa7c8e932 --- /dev/null +++ b/packages/samples/headless-ssr/src/app/generic/components/facet-search.tsx @@ -0,0 +1,53 @@ +import { + FacetState, + Facet as FacetController, + Controller, +} from '@coveo/headless/ssr'; +import {FunctionComponent, useEffect, useState} from 'react'; + +interface FacetSearchProps { + staticState: FacetState; + controller?: FacetController; +} + +export const FacetSearch: FunctionComponent = ({ + staticState, + controller, +}) => { + const [state, setState] = useState(staticState); + + useEffect( + () => controller?.subscribe?.(() => setState({...controller.state})), + [controller] + ); + + return ( + <> + { + controller.facetSearch.updateText(e.currentTarget.value); + controller.facetSearch.search(); + }) + } + /> +
    + {state.facetSearch.values.map((facetSearchValue) => ( +
  • + +
  • + ))} +
+ + ); +}; diff --git a/packages/samples/headless-ssr/src/app/generic/components/facet.tsx b/packages/samples/headless-ssr/src/app/generic/components/facet.tsx new file mode 100644 index 00000000000..24ca3532dae --- /dev/null +++ b/packages/samples/headless-ssr/src/app/generic/components/facet.tsx @@ -0,0 +1,40 @@ +import {FacetState, Facet as FacetController} from '@coveo/headless/ssr'; +import {useEffect, useState, FunctionComponent} from 'react'; +import FacetCommon from '../../common/facet'; + +interface FacetProps { + title: string; + staticState: FacetState; + controller?: FacetController; +} + +export const Facet: FunctionComponent = ({ + title, + staticState, + controller, +}) => { + const [state, setState] = useState(staticState); + + useEffect( + () => controller?.subscribe?.(() => setState({...controller.state})), + [controller] + ); + + return ( + controller.toggleSelect(value))} + onUpdateSearchQuery={ + controller && ((query) => controller.facetSearch.updateText(query)) + } + onSubmitSearch={controller && (() => controller.facetSearch.search())} + onToggleSearchResult={ + controller && ((result) => controller.facetSearch.select(result)) + } + /> + ); +}; diff --git a/packages/samples/headless-ssr/src/app/generic/components/result-list.tsx b/packages/samples/headless-ssr/src/app/generic/components/result-list.tsx index 4c8ff505eb4..c55fab7ff20 100644 --- a/packages/samples/headless-ssr/src/app/generic/components/result-list.tsx +++ b/packages/samples/headless-ssr/src/app/generic/components/result-list.tsx @@ -1,7 +1,7 @@ import { ResultList as ResultListController, ResultListState, -} from '@coveo/headless'; +} from '@coveo/headless/ssr'; import {useEffect, useState, FunctionComponent} from 'react'; import ResultListCommon from '../../common/result-list'; diff --git a/packages/samples/headless-ssr/src/app/generic/components/search-box.tsx b/packages/samples/headless-ssr/src/app/generic/components/search-box.tsx index 7484ff94a74..62b807fe435 100644 --- a/packages/samples/headless-ssr/src/app/generic/components/search-box.tsx +++ b/packages/samples/headless-ssr/src/app/generic/components/search-box.tsx @@ -1,7 +1,7 @@ import { SearchBoxState, SearchBox as SearchBoxController, -} from '@coveo/headless'; +} from '@coveo/headless/ssr'; import {useEffect, useState, FunctionComponent} from 'react'; import SearchBoxCommon from '../../common/search-box'; diff --git a/packages/samples/headless-ssr/src/app/generic/components/search-page.tsx b/packages/samples/headless-ssr/src/app/generic/components/search-page.tsx index 42036080989..678484acce9 100644 --- a/packages/samples/headless-ssr/src/app/generic/components/search-page.tsx +++ b/packages/samples/headless-ssr/src/app/generic/components/search-page.tsx @@ -8,6 +8,7 @@ import { import {useEffect, useState} from 'react'; import {HydrationMetadata} from '../../common/hydration-metadata'; import {useSyncSearchParameters} from '../hooks/search-parameters'; +import {Facet} from './facet'; import {ResultList} from './result-list'; import {SearchBox} from './search-box'; @@ -44,6 +45,11 @@ export default function SearchPage({ staticState={staticState.controllers.searchBox.state} controller={hydratedState?.controllers.searchBox} /> + { + const {state, methods} = useAuthorFacet(); + + return ( + methods.toggleSelect(value))} + onUpdateSearchQuery={ + methods && ((query) => methods.facetSearch.updateText(query)) + } + onSubmitSearch={methods && (() => methods.facetSearch.search())} + onToggleSearchResult={ + methods && ((result) => methods.facetSearch.select(result)) + } + /> + ); +};