Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Plugin system #1933

Draft
wants to merge 21 commits into
base: v1.x-2022-07
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
30 changes: 29 additions & 1 deletion packages/hydrogen/src/config.ts
@@ -1,4 +1,13 @@
import type {InlineHydrogenConfig} from './types.js';
import type {HydrogenRequest} from './foundation/HydrogenRequest/HydrogenRequest.server.js';
import type {HydrogenResponse} from './foundation/HydrogenResponse/HydrogenResponse.server.js';
import type {Logger} from './utilities/log/log.js';
import type {SessionStorageAdapter} from './foundation/session/session-types.js';
import type {
InlineHydrogenConfig,
HydrogenPlugin,
HydrogenPluginOptions,
ResolvedHydrogenConfig,
} from './types.js';

export const defineConfig = (params: InlineHydrogenConfig) => params;

Expand All @@ -9,3 +18,22 @@ export {PerformanceMetricsServerAnalyticsConnector} from './foundation/Analytics

export {CookieSessionStorage} from './foundation/CookieSessionStorage/CookieSessionStorage.js';
export {MemorySessionStorage} from './foundation/MemorySessionStorage/MemorySessionStorage.js';

export const definePlugin =
<T extends HydrogenPluginOptions>(pluginFn: (opt: T) => HydrogenPlugin) =>
(options: T) =>
pluginFn(options);

export type HandleMiddlewareParams = {
request: HydrogenRequest;
response: HydrogenResponse;
session: SessionStorageAdapter;
log: Logger;
hydrogenConfig: ResolvedHydrogenConfig;
};

export const defineMiddleware = (
middleware: (
middlewareParams: HandleMiddlewareParams
) => void | Response | Promise<void | Response>
) => middleware;
58 changes: 37 additions & 21 deletions packages/hydrogen/src/entry-server.tsx
Expand Up @@ -14,7 +14,6 @@ import type {
RunSsrParams,
RunRscParams,
ResolvedHydrogenConfig,
ResolvedHydrogenRoutes,
RequestHandler,
} from './types.js';
import type {RequestHandlerOptions} from './shared-types.js';
Expand All @@ -27,11 +26,7 @@ import {
} from './foundation/ServerRequestProvider/index.js';
import type {ServerResponse} from 'http';
import type {PassThrough as PassThroughType} from 'stream';
import {
getApiRouteFromURL,
renderApiRoute,
getApiRoutes,
} from './utilities/apiRoutes.js';
import {getApiRouteFromURL, renderApiRoute} from './utilities/apiRoutes.js';
import {ServerPropsProvider} from './foundation/ServerPropsProvider/index.js';
import {isBotUA} from './utilities/bot-ua.js';
import {getCache, setCache} from './foundation/runtime.js';
Expand All @@ -57,6 +52,7 @@ import {
} from './foundation/Cache/cache.js';
import {CacheShort, NO_STORE} from './foundation/Cache/strategies/index.js';
import {getBuiltInRoute} from './foundation/BuiltInRoutes/BuiltInRoutes.js';
import {findRouteMatches, mergeRouteSets} from './utilities/routes.js';

declare global {
// This is provided by a Vite plugin
Expand All @@ -83,14 +79,14 @@ export const renderHydrogen = (App: any) => {
'virtual__hydrogen.config.ts'
);

const {default: hydrogenRoutes} = await import(
const allRoutes = await import(
// @ts-ignore
'virtual__hydrogen-routes.server.jsx'
);

const hydrogenConfig: ResolvedHydrogenConfig = {
...inlineHydrogenConfig,
routes: hydrogenRoutes,
routes: mergeRouteSets(allRoutes),
};

request.ctx.hydrogenConfig = hydrogenConfig;
Expand Down Expand Up @@ -127,7 +123,6 @@ export const renderHydrogen = (App: any) => {
{
resource: builtInRouteResource,
params: {},
hasServerComponent: false,
},
hydrogenConfig,
{
Expand Down Expand Up @@ -224,21 +219,47 @@ async function processRequest(
revalidate = false
) {
const {dev, nonce, indexTemplate, streamableResponse: nodeResponse} = options;

const log = getLoggerWithContext(request);

const {default: runMiddlewares} = await import(
// @ts-ignore
'virtual__hydrogen-middleware.ts'
);

const maybeResponse = await runMiddlewares(hydrogenConfig, {
request,
response,
session: sessionApi,
log,
});

if (maybeResponse instanceof Response) {
return maybeResponse;
}

const isRSCRequest = request.isRscRequest();
const apiRoute = !isRSCRequest && getApiRoute(url, hydrogenConfig.routes);
const decodedPathname = decodeURIComponent(
new URL(request.normalizedUrl).pathname
);
const matchedRoutes = findRouteMatches(
hydrogenConfig.routes,
decodedPathname
);

// These matched routes are used later in <FileRoutes> component
request.ctx.matchedRoutes = matchedRoutes;

const apiRoute =
!isRSCRequest && getApiRouteFromURL(matchedRoutes, request.method);

// The API Route might have a default export, making it also a server component
// If it does, only render the API route if the request method is GET
if (apiRoute && (!apiRoute.hasServerComponent || request.method !== 'GET')) {
if (apiRoute) {
const apiResponse = await renderApiRoute(
request,
apiRoute,
hydrogenConfig,
{
session: sessionApi,
}
{session: sessionApi}
);

return apiResponse instanceof Request
Expand All @@ -253,7 +274,7 @@ async function processRequest(
const state: Record<string, any> = isRSCRequest
? parseJSON(decodeURIComponent(url.searchParams.get('state') || '{}'))
: {
pathname: decodeURIComponent(url.pathname),
pathname: decodedPathname,
search: decodeURIComponent(url.search),
};

Expand Down Expand Up @@ -305,11 +326,6 @@ async function getTemplate(
return template;
}

function getApiRoute(url: URL, routes: ResolvedHydrogenRoutes) {
const apiRoutes = getApiRoutes(routes);
return getApiRouteFromURL(url, apiRoutes);
}

function assembleHtml({
ssrHtml,
rscPayload,
Expand Down
Expand Up @@ -73,6 +73,8 @@ function publishEvent(eventname: string, payload: any) {
subs[key](payload);
});
}

pushToServer({body: JSON.stringify(payload)}, eventname);
}

function subscribe(
Expand Down Expand Up @@ -111,6 +113,11 @@ function pushToServer(init?: RequestInit, searchParam?: string) {
},
init
)
).catch((error) =>
console.warn(
`Could not emit Hydrogen Event "${searchParam}" to the server.`,
error
)
);
}

Expand Down