Skip to content

Commit

Permalink
recommendation hydration working
Browse files Browse the repository at this point in the history
  • Loading branch information
y-lakhdar committed Nov 15, 2024
1 parent e60bfe5 commit be888c8
Show file tree
Hide file tree
Showing 7 changed files with 114 additions and 54 deletions.
53 changes: 43 additions & 10 deletions packages/headless/src/app/commerce-engine/commerce-engine.ssr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,13 @@ export function defineCommerceEngine<
Parameters<FetchStaticStateFromBuildResultFunction>;
type HydrateStaticStateFromBuildResultParameters =
Parameters<HydrateStaticStateFromBuildResultFunction>;
type BuildResult = {
engine: SSRCommerceEngine;
controllers: InferControllersMapFromDefinition<
TControllerDefinitions,
SolutionType
>;
}; // TODO: check if can remove the cast

// TODO: ideally , we only want to execute that for recommendation stuff
// TODO: get rid of that here. need to be computed in the fetch static state now
Expand Down Expand Up @@ -323,13 +330,7 @@ export function defineCommerceEngine<
const buildResult = (await buildFactory(
SolutionType.recommendation,
((params || [])[0] as string[])?.length // TODO: fix that mess
)(...params)) as {
engine: SSRCommerceEngine;
controllers: InferControllersMapFromDefinition<
TControllerDefinitions,
SolutionType
>;
}; // TODO: check if can remove the cast
)(...params)) as BuildResult; // TODO: check if can remove the cast
const staticState =
await fetchStaticStateFactoryForRecommendation().fromBuildResult({
buildResult,
Expand Down Expand Up @@ -407,6 +408,40 @@ export function defineCommerceEngine<
}
);

const hydrateStaticStateFactoryForRecommendation: () => HydrateStaticStateFunction =
() =>
composeFunction(
async (...params: HydrateStaticStateParameters) => {
const buildResult = (await buildFactory(SolutionType.recommendation)(
...(params as BuildParameters)
)) as BuildResult; // TODO: check if can remove the cast
const staticState =
await hydrateStaticStateFactoryForRecommendation().fromBuildResult({
buildResult,
searchActions: params[0]!.searchActions,
});
return staticState;
},
{
fromBuildResult: async (
...params: HydrateStaticStateFromBuildResultParameters
) => {
const [
{
buildResult: {engine, controllers},
searchActions,
},
] = params;

searchActions.forEach((action) => {
engine.dispatch(action);
});
await engine.waitForRequestCompletedAction();
return {engine, controllers};
},
}
);

return {
listingEngineDefinition: {
build: buildFactory(SolutionType.listing),
Expand All @@ -423,9 +458,7 @@ export function defineCommerceEngine<
recommendationEngineDefinition: {
build: buildFactory(SolutionType.recommendation),
fetchStaticState: fetchStaticStateFactoryForRecommendation(),
hydrateStaticState: hydrateStaticStateFactory(
SolutionType.recommendation
),
hydrateStaticState: hydrateStaticStateFactoryForRecommendation(),
setNavigatorContextProvider,
} as CommerceEngineDefinition<
TControllerDefinitions,
Expand Down
15 changes: 12 additions & 3 deletions packages/headless/src/app/commerce-ssr-engine/types/core-engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,17 @@ import {
FetchStaticState,
FetchStaticStateOptions,
} from './fetch-static-state.js';
import {HydrateStaticState} from './hydrate-static-state.js';
import {
HydrateStaticState,
HydrateStaticStateOptions,
} from './hydrate-static-state.js';

export type {HydrateStaticState, FetchStaticState, FetchStaticStateOptions};
export type {
HydrateStaticState,
HydrateStaticStateOptions,
FetchStaticState,
FetchStaticStateOptions,
};
export type EngineDefinitionOptions<
TOptions extends {configuration: EngineConfiguration},
TControllers extends ControllerDefinitionsMap<
Expand Down Expand Up @@ -58,7 +66,8 @@ export interface EngineDefinition<
TEngine,
InferControllersMapFromDefinition<TControllers, TSolutionType>,
UnknownAction,
InferControllerPropsMapFromDefinitions<TControllers>
InferControllerPropsMapFromDefinitions<TControllers>,
TSolutionType
>;
/**
* Builds an engine and its controllers from an engine definition.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,6 @@ export type FetchStaticState<
TControllersStaticState extends ControllerStaticStateMap,
TControllersProps extends ControllersPropsMap,
TSolutionType extends SolutionType,
FromBuildResultFunction = FromBuildResult<
TEngine,
TControllers,
FetchStaticStateOptions,
EngineStaticState<TSearchAction, TControllersStaticState>
>,
> = TSolutionType extends SolutionType.recommendation
? {
/**
Expand All @@ -40,7 +34,12 @@ export type FetchStaticState<
controllers: Array<keyof TControllers> // TODO: make the array unique
): Promise<EngineStaticState<TSearchAction, TControllersStaticState>>;

fromBuildResult: FromBuildResultFunction;
fromBuildResult: FromBuildResult<
TEngine,
TControllers,
FetchStaticStateOptions,
EngineStaticState<TSearchAction, TControllersStaticState>
>;
}
: {
/**
Expand All @@ -55,6 +54,11 @@ export type FetchStaticState<
>
): Promise<EngineStaticState<TSearchAction, TControllersStaticState>>;

fromBuildResult: FromBuildResultFunction;
fromBuildResult: FromBuildResult<
TEngine,
TControllers,
FetchStaticStateOptions,
EngineStaticState<TSearchAction, TControllersStaticState>
>;
};
buildBaseCommerceAPIRequest;
Original file line number Diff line number Diff line change
Expand Up @@ -8,36 +8,53 @@ import {
OptionsTuple,
} from '../../ssr-engine/types/common.js';
import {FromBuildResult} from '../../ssr-engine/types/from-build-result.js';
import {SolutionType} from './common.js';

export interface HydrateStaticStateOptions<TSearchAction> {
searchActions: TSearchAction[];
}

// TODO: check if need to create one hydrate function specific for recommendations.
// - If yes, then adjust this.
// - If not, then remove and reuse the interface from ssr-engine
export type HydrateStaticState<
TEngine extends CoreEngine | CoreEngineNext,
TControllers extends ControllersMap,
TSearchAction extends UnknownAction,
TControllersProps extends ControllersPropsMap,
> = {
/**
* Creates a new engine from the snapshot of the engine created in SSR with fetchStaticState.
*
* Useful when hydrating a server-side-rendered engine.
*/
(
...params: OptionsTuple<
HydrateStaticStateOptions<TSearchAction> &
EngineDefinitionControllersPropsOption<TControllersProps>
>
): Promise<HydratedState<TEngine, TControllers>>;
TSolutionType extends SolutionType,
> = TSolutionType extends SolutionType.recommendation
? {
/**
* Creates a new engine from the snapshot of the engine created in SSR with fetchStaticState.
*
* Useful when hydrating a server-side-rendered engine.
*/
(
...params: OptionsTuple<HydrateStaticStateOptions<TSearchAction>>
): Promise<HydratedState<TEngine, TControllers>>;

fromBuildResult: FromBuildResult<
TEngine,
TControllers,
HydrateStaticStateOptions<TSearchAction>,
HydratedState<TEngine, TControllers>
>;
};
fromBuildResult: FromBuildResult<
TEngine,
TControllers,
HydrateStaticStateOptions<TSearchAction>,
HydratedState<TEngine, TControllers>
>;
}
: {
/**
* Creates a new engine from the snapshot of the engine created in SSR with fetchStaticState.
*
* Useful when hydrating a server-side-rendered engine.
*/
(
...params: OptionsTuple<
HydrateStaticStateOptions<TSearchAction> &
EngineDefinitionControllersPropsOption<TControllersProps>
>
): Promise<HydratedState<TEngine, TControllers>>;

fromBuildResult: FromBuildResult<
TEngine,
TControllers,
HydrateStaticStateOptions<TSearchAction>,
HydratedState<TEngine, TControllers>
>;
};
1 change: 1 addition & 0 deletions packages/headless/src/ssr-commerce.index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ export type {
HydrateStaticState,
FetchStaticState,
FetchStaticStateOptions,
HydrateStaticStateOptions,
} from './app/commerce-ssr-engine/types/core-engine.js';
// export type {
// FromBuildResult,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ export default async function Listing({params}: {params: {category: string}}) {

const recStaticState = await recommendationEngineDefinition.fetchStaticState([
'popularBoughtRecs',
'popularViewedRecs',
]);

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,13 @@ export default function RecommendationProvider({
);

useEffect(() => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(recommendationEngineDefinition.hydrateStaticState as any)({
searchActions: staticState.searchActions,
// controllers: { },
}).then(({engine, controllers}) => {
setHydratedState({engine, controllers});
// Refreshing recommendations in the browser after hydrating the state in the client-side
// Recommendation refresh in the server is not supported yet.
// controllers.popularBoughtRecs.refresh(); // FIXME: does not work
});
recommendationEngineDefinition
.hydrateStaticState({
searchActions: staticState.searchActions,
}) // TODO: need to pass the search actions!!!!
.then(({engine, controllers}) => {
setHydratedState({engine, controllers});
});
}, [staticState]);

if (hydratedState) {
Expand Down

0 comments on commit be888c8

Please sign in to comment.