@lomray/vite-ssr-boost 1.0.0-beta.2 → 1.0.0-beta.4
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.
- package/browser/entry.d.ts +8 -7
- package/browser/entry.js +1 -1
- package/browser/entry.js.map +1 -1
- package/components/with-suspense.d.ts +7 -0
- package/components/with-suspense.js +2 -0
- package/components/with-suspense.js.map +1 -0
- package/helpers/import-route.d.ts +252 -0
- package/helpers/import-route.js +2 -0
- package/helpers/import-route.js.map +1 -0
- package/helpers/vite-aliases.d.ts +6 -0
- package/helpers/vite-aliases.js +2 -0
- package/helpers/vite-aliases.js.map +1 -0
- package/interfaces/fc-route.d.ts +10 -0
- package/interfaces/fc-route.js +2 -0
- package/interfaces/fc-route.js.map +1 -0
- package/interfaces/fc.d.ts +4 -0
- package/interfaces/fc.js +2 -0
- package/interfaces/fc.js.map +1 -0
- package/interfaces/route-object.d.ts +8 -0
- package/interfaces/route-object.js +2 -0
- package/interfaces/route-object.js.map +1 -0
- package/node/entry.d.ts +6 -9
- package/node/entry.js +1 -1
- package/node/entry.js.map +1 -1
- package/node/render.d.ts +2 -2
- package/node/render.js.map +1 -1
- package/package.json +7 -3
- package/plugin.d.ts +3 -0
- package/plugin.js +1 -1
- package/plugin.js.map +1 -1
- package/plugins/make-aliases.d.ts +11 -0
- package/plugins/make-aliases.js +2 -0
- package/plugins/make-aliases.js.map +1 -0
- package/plugins/normalize-route.d.ts +10 -0
- package/plugins/normalize-route.js +2 -0
- package/plugins/normalize-route.js.map +1 -0
- package/services/prepare-server.js +1 -1
- package/services/prepare-server.js.map +1 -1
package/browser/entry.d.ts
CHANGED
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
/// <reference types="react-dom" />
|
|
2
|
+
import { Router as RemixRouter } from '@remix-run/router/dist/router';
|
|
2
3
|
import { FC, PropsWithChildren } from 'react';
|
|
3
4
|
import ReactDOM from 'react-dom/client';
|
|
4
|
-
import {
|
|
5
|
-
interface IEntryClientOptions {
|
|
6
|
-
routes: RouteObject[];
|
|
7
|
-
}
|
|
5
|
+
import { TRouteObject } from "../interfaces/route-object.js";
|
|
8
6
|
interface IAppClientProps<T = undefined> {
|
|
9
7
|
client: T;
|
|
10
8
|
}
|
|
11
9
|
interface IInitPropsParams {
|
|
12
10
|
isSSRMode: boolean;
|
|
11
|
+
router: RemixRouter;
|
|
13
12
|
}
|
|
14
13
|
type TApp<T> = FC<PropsWithChildren<IAppClientProps<T>>>;
|
|
15
|
-
|
|
14
|
+
interface IEntryClientOptions<T> {
|
|
15
|
+
init?: (params: IInitPropsParams) => Promise<T>;
|
|
16
|
+
}
|
|
16
17
|
/**
|
|
17
18
|
* Render client side application
|
|
18
19
|
*/
|
|
19
|
-
declare function entry<TAppProps>(
|
|
20
|
-
export { entry as default,
|
|
20
|
+
declare function entry<TAppProps>(App: TApp<TAppProps>, routes: TRouteObject[], { init }?: IEntryClientOptions<TAppProps>): Promise<ReactDOM.Root | void>;
|
|
21
|
+
export { entry as default, IAppClientProps, IInitPropsParams, TApp, IEntryClientOptions };
|
package/browser/entry.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import t from"react";import e from"react-dom/client";import{matchRoutes as o,createBrowserRouter as r,RouterProvider as a}from"react-router-dom";import{IS_SSR_MODE as n}from"../constants/common.js";async function c(
|
|
1
|
+
import t from"react";import e from"react-dom/client";import{matchRoutes as o,createBrowserRouter as r,RouterProvider as a}from"react-router-dom";import{IS_SSR_MODE as n}from"../constants/common.js";async function c(c,l,{init:m}={}){const i=o(l,window.location)?.filter((t=>t.route.lazy));i&&i?.length>0&&await Promise.all(i.map((async t=>{const e=await(t.route.lazy?.());Object.assign(t.route,{...e,lazy:void 0})})));const s=r(l),u=document.getElementById("root"),d=await(m?.({isSSRMode:n,router:s})),f=()=>t.createElement(c,{client:d},t.createElement(a,{router:s}));return n?e.hydrateRoot(u,t.createElement(f,null)):e.createRoot(u).render(t.createElement(f,null))}export{c as default};
|
|
2
2
|
//# sourceMappingURL=entry.js.map
|
package/browser/entry.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entry.js","sources":["../../src/browser/entry.tsx"],"sourcesContent":["import type { FC, PropsWithChildren } from 'react';\nimport React from 'react';\nimport ReactDOM from 'react-dom/client';\nimport type { RouteObject } from 'react-router-dom';\nimport { createBrowserRouter, matchRoutes, RouterProvider } from 'react-router-dom';\nimport { IS_SSR_MODE } from '@constants/common';\
|
|
1
|
+
{"version":3,"file":"entry.js","sources":["../../src/browser/entry.tsx"],"sourcesContent":["import type { Router as RemixRouter } from '@remix-run/router/dist/router';\nimport type { FC, PropsWithChildren } from 'react';\nimport React from 'react';\nimport ReactDOM from 'react-dom/client';\nimport type { RouteObject } from 'react-router-dom';\nimport { createBrowserRouter, matchRoutes, RouterProvider } from 'react-router-dom';\nimport { IS_SSR_MODE } from '@constants/common';\nimport type { TRouteObject } from '@interfaces/route-object';\n\nexport interface IAppClientProps<T = undefined> {\n client: T;\n}\n\nexport interface IInitPropsParams {\n isSSRMode: boolean;\n router: RemixRouter;\n}\n\nexport type TApp<T> = FC<PropsWithChildren<IAppClientProps<T>>>;\n\nexport interface IEntryClientOptions<T> {\n init?: (params: IInitPropsParams) => Promise<T>;\n}\n\n/**\n * Render client side application\n */\nasync function entry<TAppProps>(\n App: TApp<TAppProps>,\n routes: TRouteObject[],\n { init }: IEntryClientOptions<TAppProps> = {},\n): Promise<ReactDOM.Root | void> {\n const lazyMatches = matchRoutes(routes as RouteObject[], window.location)?.filter(\n (m) => m.route.lazy,\n );\n\n // Load the lazy matches and update the routes before creating router,\n // so we can hydrate the SSR-rendered content synchronously\n if (lazyMatches && lazyMatches?.length > 0) {\n await Promise.all(\n lazyMatches.map(async (m) => {\n const routeModule = await m.route.lazy?.();\n\n Object.assign(m.route, {\n ...routeModule,\n lazy: undefined,\n });\n }),\n );\n }\n\n const router = createBrowserRouter(routes as RouteObject[]);\n const root = document.getElementById('root') as HTMLElement;\n const appProps = (await init?.({ isSSRMode: IS_SSR_MODE, router })) as TAppProps;\n\n const AppComponent: FC = () => (\n <App client={appProps}>\n <RouterProvider router={router} />\n </App>\n );\n\n if (!IS_SSR_MODE) {\n return ReactDOM.createRoot(root).render(<AppComponent />);\n }\n\n return ReactDOM.hydrateRoot(root, <AppComponent />);\n}\n\nexport default entry;\n"],"names":["async","entry","App","routes","init","lazyMatches","matchRoutes","window","location","filter","m","route","lazy","length","Promise","all","map","routeModule","Object","assign","undefined","router","createBrowserRouter","root","document","getElementById","appProps","isSSRMode","IS_SSR_MODE","AppComponent","React","createElement","client","RouterProvider","ReactDOM","hydrateRoot","createRoot","render"],"mappings":"sMA2BAA,eAAeC,EACbC,EACAC,GACAC,KAAEA,GAAyC,CAAA,GAE3C,MAAMC,EAAcC,EAAYH,EAAyBI,OAAOC,WAAWC,QACxEC,GAAMA,EAAEC,MAAMC,OAKbP,GAAeA,GAAaQ,OAAS,SACjCC,QAAQC,IACZV,EAAYW,KAAIhB,MAAOU,IACrB,MAAMO,QAAoBP,EAAEC,MAAMC,UAElCM,OAAOC,OAAOT,EAAEC,MAAO,IAClBM,EACHL,UAAMQ,GACN,KAKR,MAAMC,EAASC,EAAoBnB,GAC7BoB,EAAOC,SAASC,eAAe,QAC/BC,QAAkBtB,IAAO,CAAEuB,UAAWC,EAAaP,YAEnDQ,EAAmB,IACvBC,EAAAC,cAAC7B,EAAG,CAAC8B,OAAQN,GACXI,EAACC,cAAAE,GAAeZ,OAAQA,KAI5B,OAAKO,EAIEM,EAASC,YAAYZ,EAAMO,EAACC,cAAAF,EAAe,OAHzCK,EAASE,WAAWb,GAAMc,OAAOP,EAAAC,cAACF,EAAY,MAIzD"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { FC } from 'react';
|
|
2
|
+
import { FCAny, FCC } from "../interfaces/fc.js";
|
|
3
|
+
/**
|
|
4
|
+
* Wrap component in suspense
|
|
5
|
+
*/
|
|
6
|
+
declare const withSuspense: <T extends Record<string, any>>(Component: FCAny<T>, Suspense: FCC<Record<string, any>>) => FC<T>;
|
|
7
|
+
export { withSuspense as default };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"with-suspense.js","sources":["../../src/components/with-suspense.tsx"],"sourcesContent":["import hoistNonReactStatics from 'hoist-non-react-statics';\nimport type { FC } from 'react';\nimport React from 'react';\nimport type { FCAny, FCC } from '@interfaces/fc';\n\n/**\n * Wrap component in suspense\n */\nconst withSuspense = <T extends Record<string, any>>(\n Component: FCAny<T>,\n Suspense: FCC<Record<string, any>>,\n): FC<T> => {\n const Element: FC<T> = (props) => (\n <Suspense>\n <Component {...props} />\n </Suspense>\n );\n\n hoistNonReactStatics(Element, Component);\n\n return Element;\n};\n\nexport default withSuspense;\n"],"names":["withSuspense","Component","Suspense","Element","props","React","createElement","hoistNonReactStatics"],"mappings":"4DAQA,MAAMA,EAAe,CACnBC,EACAC,KAEA,MAAMC,EAAkBC,GACtBC,EAAAC,cAACJ,EAAQ,KACPG,EAAAC,cAACL,EAAc,IAAAG,KAMnB,OAFAG,EAAqBJ,EAASF,GAEvBE,CAAO"}
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { IndexRouteObject, NonIndexRouteObject } from 'react-router-dom';
|
|
3
|
+
import { FCCRoute, FCRoute } from "../interfaces/fc-route.js";
|
|
4
|
+
declare enum ResultType {
|
|
5
|
+
data = "data",
|
|
6
|
+
deferred = "deferred",
|
|
7
|
+
redirect = "redirect",
|
|
8
|
+
error = "error"
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Successful result from a loader or action
|
|
12
|
+
*/
|
|
13
|
+
interface SuccessResult {
|
|
14
|
+
type: ResultType.data;
|
|
15
|
+
data: any;
|
|
16
|
+
statusCode?: number;
|
|
17
|
+
headers?: Headers;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Successful defer() result from a loader or action
|
|
21
|
+
*/
|
|
22
|
+
interface DeferredResult {
|
|
23
|
+
type: ResultType.deferred;
|
|
24
|
+
deferredData: DeferredData;
|
|
25
|
+
statusCode?: number;
|
|
26
|
+
headers?: Headers;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Redirect result from a loader or action
|
|
30
|
+
*/
|
|
31
|
+
interface RedirectResult {
|
|
32
|
+
type: ResultType.redirect;
|
|
33
|
+
status: number;
|
|
34
|
+
location: string;
|
|
35
|
+
revalidate: boolean;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Unsuccessful result from a loader or action
|
|
39
|
+
*/
|
|
40
|
+
interface ErrorResult {
|
|
41
|
+
type: ResultType.error;
|
|
42
|
+
error: any;
|
|
43
|
+
headers?: Headers;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Result from a loader or action - potentially successful or unsuccessful
|
|
47
|
+
*/
|
|
48
|
+
type DataResult = SuccessResult | DeferredResult | RedirectResult | ErrorResult;
|
|
49
|
+
type LowerCaseFormMethod = "get" | "post" | "put" | "patch" | "delete";
|
|
50
|
+
type UpperCaseFormMethod = Uppercase<LowerCaseFormMethod>;
|
|
51
|
+
/**
|
|
52
|
+
* Active navigation/fetcher form methods are exposed in lowercase on the
|
|
53
|
+
* RouterState
|
|
54
|
+
*/
|
|
55
|
+
type FormMethod = LowerCaseFormMethod;
|
|
56
|
+
/**
|
|
57
|
+
* In v7, active navigation/fetcher form methods are exposed in uppercase on the
|
|
58
|
+
* RouterState. This is to align with the normalization done via fetch().
|
|
59
|
+
*/
|
|
60
|
+
type V7_FormMethod = UpperCaseFormMethod;
|
|
61
|
+
type FormEncType = "application/x-www-form-urlencoded" | "multipart/form-data";
|
|
62
|
+
/**
|
|
63
|
+
* @private
|
|
64
|
+
* Internal interface to pass around for action submissions, not intended for
|
|
65
|
+
* external consumption
|
|
66
|
+
*/
|
|
67
|
+
interface Submission {
|
|
68
|
+
formMethod: FormMethod | V7_FormMethod;
|
|
69
|
+
formAction: string;
|
|
70
|
+
formEncType: FormEncType;
|
|
71
|
+
formData: FormData;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* @private
|
|
75
|
+
* Arguments passed to route loader/action functions. Same for now but we keep
|
|
76
|
+
* this as a private implementation detail in case they diverge in the future.
|
|
77
|
+
*/
|
|
78
|
+
interface DataFunctionArgs {
|
|
79
|
+
request: Request;
|
|
80
|
+
params: Params;
|
|
81
|
+
context?: any;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Arguments passed to loader functions
|
|
85
|
+
*/
|
|
86
|
+
interface LoaderFunctionArgs extends DataFunctionArgs {
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Arguments passed to action functions
|
|
90
|
+
*/
|
|
91
|
+
interface ActionFunctionArgs extends DataFunctionArgs {
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Loaders and actions can return anything except `undefined` (`null` is a
|
|
95
|
+
* valid return value if there is no data to return). Responses are preferred
|
|
96
|
+
* and will ease any future migration to Remix
|
|
97
|
+
*/
|
|
98
|
+
type DataFunctionValue = Response | NonNullable<unknown> | null;
|
|
99
|
+
/**
|
|
100
|
+
* Route loader function signature
|
|
101
|
+
*/
|
|
102
|
+
interface LoaderFunction {
|
|
103
|
+
(args: LoaderFunctionArgs): Promise<DataFunctionValue> | DataFunctionValue;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Route action function signature
|
|
107
|
+
*/
|
|
108
|
+
interface ActionFunction {
|
|
109
|
+
(args: ActionFunctionArgs): Promise<DataFunctionValue> | DataFunctionValue;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Route shouldRevalidate function signature. This runs after any submission
|
|
113
|
+
* (navigation or fetcher), so we flatten the navigation/fetcher submission
|
|
114
|
+
* onto the arguments. It shouldn't matter whether it came from a navigation
|
|
115
|
+
* or a fetcher, what really matters is the URLs and the formData since loaders
|
|
116
|
+
* have to re-run based on the data models that were potentially mutated.
|
|
117
|
+
*/
|
|
118
|
+
interface ShouldRevalidateFunction {
|
|
119
|
+
(args: {
|
|
120
|
+
currentUrl: URL;
|
|
121
|
+
currentParams: AgnosticDataRouteMatch["params"];
|
|
122
|
+
nextUrl: URL;
|
|
123
|
+
nextParams: AgnosticDataRouteMatch["params"];
|
|
124
|
+
formMethod?: Submission["formMethod"];
|
|
125
|
+
formAction?: Submission["formAction"];
|
|
126
|
+
formEncType?: Submission["formEncType"];
|
|
127
|
+
formData?: Submission["formData"];
|
|
128
|
+
actionResult?: DataResult;
|
|
129
|
+
defaultShouldRevalidate: boolean;
|
|
130
|
+
}): boolean;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Keys we cannot change from within a lazy() function. We spread all other keys
|
|
134
|
+
* onto the route. Either they're meaningful to the router, or they'll get
|
|
135
|
+
* ignored.
|
|
136
|
+
*/
|
|
137
|
+
type ImmutableRouteKey = "lazy" | "caseSensitive" | "path" | "id" | "index" | "children";
|
|
138
|
+
/**
|
|
139
|
+
* lazy() function to load a route definition, which can add non-matching
|
|
140
|
+
* related properties to a route
|
|
141
|
+
*/
|
|
142
|
+
interface LazyRouteFunction<R extends AgnosticRouteObject> {
|
|
143
|
+
(): Promise<Omit<R, ImmutableRouteKey>>;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Base RouteObject with common props shared by all types of routes
|
|
147
|
+
*/
|
|
148
|
+
type AgnosticBaseRouteObject = {
|
|
149
|
+
caseSensitive?: boolean;
|
|
150
|
+
path?: string;
|
|
151
|
+
id?: string;
|
|
152
|
+
loader?: LoaderFunction;
|
|
153
|
+
action?: ActionFunction;
|
|
154
|
+
hasErrorBoundary?: boolean;
|
|
155
|
+
shouldRevalidate?: ShouldRevalidateFunction;
|
|
156
|
+
handle?: any;
|
|
157
|
+
lazy?: LazyRouteFunction<AgnosticBaseRouteObject>;
|
|
158
|
+
};
|
|
159
|
+
/**
|
|
160
|
+
* Index routes must not have children
|
|
161
|
+
*/
|
|
162
|
+
type AgnosticIndexRouteObject = AgnosticBaseRouteObject & {
|
|
163
|
+
children?: undefined;
|
|
164
|
+
index: true;
|
|
165
|
+
};
|
|
166
|
+
/**
|
|
167
|
+
* Non-index routes may have children, but cannot have index
|
|
168
|
+
*/
|
|
169
|
+
type AgnosticNonIndexRouteObject = AgnosticBaseRouteObject & {
|
|
170
|
+
children?: AgnosticRouteObject[];
|
|
171
|
+
index?: false;
|
|
172
|
+
};
|
|
173
|
+
/**
|
|
174
|
+
* A route object represents a logical route, with (optionally) its child
|
|
175
|
+
* routes organized in a tree-like structure.
|
|
176
|
+
*/
|
|
177
|
+
type AgnosticRouteObject = AgnosticIndexRouteObject | AgnosticNonIndexRouteObject;
|
|
178
|
+
type AgnosticDataIndexRouteObject = AgnosticIndexRouteObject & {
|
|
179
|
+
id: string;
|
|
180
|
+
};
|
|
181
|
+
type AgnosticDataNonIndexRouteObject = AgnosticNonIndexRouteObject & {
|
|
182
|
+
children?: AgnosticDataRouteObject[];
|
|
183
|
+
id: string;
|
|
184
|
+
};
|
|
185
|
+
/**
|
|
186
|
+
* A data route object, which is just a RouteObject with a required unique ID
|
|
187
|
+
*/
|
|
188
|
+
type AgnosticDataRouteObject = AgnosticDataIndexRouteObject | AgnosticDataNonIndexRouteObject;
|
|
189
|
+
/**
|
|
190
|
+
* The parameters that were parsed from the URL path.
|
|
191
|
+
*/
|
|
192
|
+
type Params<Key extends string = string> = {
|
|
193
|
+
readonly [key in Key]: string | undefined;
|
|
194
|
+
};
|
|
195
|
+
/**
|
|
196
|
+
* A RouteMatch contains info about how a route matched a URL.
|
|
197
|
+
*/
|
|
198
|
+
interface AgnosticRouteMatch<ParamKey extends string = string, RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject> {
|
|
199
|
+
/**
|
|
200
|
+
* The names and values of dynamic parameters in the URL.
|
|
201
|
+
*/
|
|
202
|
+
params: Params<ParamKey>;
|
|
203
|
+
/**
|
|
204
|
+
* The portion of the URL pathname that was matched.
|
|
205
|
+
*/
|
|
206
|
+
pathname: string;
|
|
207
|
+
/**
|
|
208
|
+
* The portion of the URL pathname that was matched before child routes.
|
|
209
|
+
*/
|
|
210
|
+
pathnameBase: string;
|
|
211
|
+
/**
|
|
212
|
+
* The route object that was used to match.
|
|
213
|
+
*/
|
|
214
|
+
route: RouteObjectType;
|
|
215
|
+
}
|
|
216
|
+
interface AgnosticDataRouteMatch extends AgnosticRouteMatch<string, AgnosticDataRouteObject> {
|
|
217
|
+
}
|
|
218
|
+
declare class DeferredData {
|
|
219
|
+
private pendingKeysSet;
|
|
220
|
+
private controller;
|
|
221
|
+
private abortPromise;
|
|
222
|
+
private unlistenAbortSignal;
|
|
223
|
+
private subscribers;
|
|
224
|
+
data: Record<string, unknown>;
|
|
225
|
+
init?: ResponseInit;
|
|
226
|
+
deferredKeys: string[];
|
|
227
|
+
constructor(data: Record<string, unknown>, responseInit?: ResponseInit);
|
|
228
|
+
private trackPromise;
|
|
229
|
+
private onSettle;
|
|
230
|
+
private emit;
|
|
231
|
+
subscribe(fn: (aborted: boolean, settledKey?: string) => void): () => boolean;
|
|
232
|
+
cancel(): void;
|
|
233
|
+
resolveData(signal: AbortSignal): Promise<boolean>;
|
|
234
|
+
get done(): boolean;
|
|
235
|
+
get unwrappedData(): {};
|
|
236
|
+
get pendingKeys(): string[];
|
|
237
|
+
}
|
|
238
|
+
type RedirectFunction = (url: string, init?: number | ResponseInit) => Response;
|
|
239
|
+
/**
|
|
240
|
+
* A redirect response. Sets the status code and the `Location` header.
|
|
241
|
+
* Defaults to "302 Found".
|
|
242
|
+
*/
|
|
243
|
+
declare const redirect: RedirectFunction;
|
|
244
|
+
type IDynamicRoute = () => Promise<{
|
|
245
|
+
default: FCRoute | FCCRoute<any>;
|
|
246
|
+
}>;
|
|
247
|
+
type IAsyncRoute = Omit<IndexRouteObject, ImmutableRouteKey> | Omit<NonIndexRouteObject, ImmutableRouteKey>;
|
|
248
|
+
/**
|
|
249
|
+
* Import dynamic route
|
|
250
|
+
*/
|
|
251
|
+
declare const importRoute: (route: IDynamicRoute) => Promise<IAsyncRoute>;
|
|
252
|
+
export { importRoute as default, IDynamicRoute, IAsyncRoute };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import e from"../components/with-suspense.js";import{keys as o}from"../interfaces/fc-route.js";const s=async s=>{const t=(await s()).default,n={Component:t};return o.forEach((e=>{t[e]&&(n[e]=t[e])})),t.Suspense&&(n.Component=e(t,t.Suspense)),n};export{s as default};
|
|
2
|
+
//# sourceMappingURL=import-route.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"import-route.js","sources":["../../src/helpers/import-route.ts"],"sourcesContent":["import type { ImmutableRouteKey } from '@remix-run/router/utils';\nimport type { IndexRouteObject, NonIndexRouteObject } from 'react-router-dom';\nimport withSuspense from '@components/with-suspense';\nimport type { FCCRoute, FCRoute } from '@interfaces/fc-route';\nimport { keys } from '@interfaces/fc-route';\n\nexport type IDynamicRoute = () => Promise<{ default: FCRoute | FCCRoute<any> }>;\n\nexport type IAsyncRoute =\n | Omit<IndexRouteObject, ImmutableRouteKey>\n | Omit<NonIndexRouteObject, ImmutableRouteKey>;\n\n/**\n * Import dynamic route\n */\nconst importRoute = async (route: IDynamicRoute): Promise<IAsyncRoute> => {\n const Component = (await route()).default;\n const result = { Component };\n\n keys.forEach((key) => {\n if (Component[key]) {\n result[key] = Component[key];\n }\n });\n\n if (Component.Suspense) {\n result.Component = withSuspense(Component, Component.Suspense);\n }\n\n return result;\n};\n\nexport default importRoute;\n"],"names":["importRoute","async","route","Component","default","result","keys","forEach","key","Suspense","withSuspense"],"mappings":"+FAeA,MAAMA,EAAcC,MAAOC,IACzB,MAAMC,SAAmBD,KAASE,QAC5BC,EAAS,CAAEF,aAYjB,OAVAG,EAAKC,SAASC,IACRL,EAAUK,KACZH,EAAOG,GAAOL,EAAUK,GACzB,IAGCL,EAAUM,WACZJ,EAAOF,UAAYO,EAAaP,EAAWA,EAAUM,WAGhDJ,CAAM"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vite-aliases.js","sources":["../../src/helpers/vite-aliases.ts"],"sourcesContent":["import { fileURLToPath, URL } from 'node:url';\nimport type { Alias } from 'vite';\n\nconst cleanupPath = (path: string) => path.replace('./', '/').replace(/([^:]\\/)\\/+/g, '$1');\n\n/**\n * Set vite aliases\n */\nconst viteAliases = (aliases: [string, string][], root = ''): Alias[] =>\n aliases.map(([find, path]) => ({\n find,\n replacement: fileURLToPath(new URL(`${root}${cleanupPath(path)}`, import.meta.url)),\n }));\n\nexport default viteAliases;\n"],"names":["cleanupPath","path","replace","viteAliases","aliases","root","map","find","replacement","fileURLToPath","URL","url"],"mappings":"kDAGA,MAAMA,EAAeC,GAAiBA,EAAKC,QAAQ,KAAM,KAAKA,QAAQ,eAAgB,MAKhFC,EAAc,CAACC,EAA6BC,EAAO,KACvDD,EAAQE,KAAI,EAAEC,EAAMN,MAAW,CAC7BM,OACAC,YAAaC,EAAc,IAAIC,EAAI,GAAGL,IAAOL,EAAYC,iBAAqBU"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { FC, PropsWithChildren } from 'react';
|
|
2
|
+
import { RouteObject } from 'react-router/dist/lib/context';
|
|
3
|
+
declare const keys: readonly ["loader", "action", "ErrorBoundary", "errorElement"];
|
|
4
|
+
type IRouteParams = Pick<RouteObject, (typeof keys)[number]> & {
|
|
5
|
+
Suspense?: FC;
|
|
6
|
+
};
|
|
7
|
+
type FCRoute<TProps = Record<string, any>> = FC<TProps> & IRouteParams;
|
|
8
|
+
type FCCRoute<TProps = Record<string, any>> = FC<PropsWithChildren<TProps>> & IRouteParams;
|
|
9
|
+
export type { FCRoute, FCCRoute, IRouteParams };
|
|
10
|
+
export { keys };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fc-route.js","sources":["../../src/interfaces/fc-route.ts"],"sourcesContent":["import type { FC, PropsWithChildren } from 'react';\nimport type { RouteObject } from 'react-router/dist/lib/context';\n\nconst keys = ['loader', 'action', 'ErrorBoundary', 'errorElement'] as const;\n\ntype IRouteParams = Pick<RouteObject, (typeof keys)[number]> & { Suspense?: FC };\n\ntype FCRoute<TProps = Record<string, any>> = FC<TProps> & IRouteParams;\ntype FCCRoute<TProps = Record<string, any>> = FC<PropsWithChildren<TProps>> & IRouteParams;\n\nexport type { FCRoute, FCCRoute, IRouteParams };\n\nexport { keys };\n"],"names":["keys"],"mappings":"AAGM,MAAAA,EAAO,CAAC,SAAU,SAAU,gBAAiB"}
|
package/interfaces/fc.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fc.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { RouteObject } from 'react-router-dom';
|
|
2
|
+
import { IDynamicRoute } from "../helpers/import-route.js";
|
|
3
|
+
type TRouteObjectNR = Omit<RouteObject, 'lazy' | 'children'> & {
|
|
4
|
+
lazyNR?: IDynamicRoute;
|
|
5
|
+
children?: TRouteObject[];
|
|
6
|
+
};
|
|
7
|
+
type TRouteObject = RouteObject | TRouteObjectNR;
|
|
8
|
+
export { TRouteObjectNR, TRouteObject };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route-object.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
package/node/entry.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Express, Request } from 'express';
|
|
2
2
|
import { Response as ExpressResponse } from "express";
|
|
3
3
|
import { FC, PropsWithChildren } from 'react';
|
|
4
|
-
import {
|
|
4
|
+
import { TRouteObject } from "../interfaces/route-object.js";
|
|
5
5
|
import { IRenderOptions, TRender } from "./render.js";
|
|
6
6
|
import ServerConfig from "../services/server-config.js";
|
|
7
7
|
interface IInitServerRequestOut<T = Record<string, any>> {
|
|
@@ -19,22 +19,19 @@ interface IEntrypointOptions<TAppProps = Record<string, any>> {
|
|
|
19
19
|
}
|
|
20
20
|
interface IPrepareRenderOut<TAppProps = Record<string, any>> {
|
|
21
21
|
render: TRender;
|
|
22
|
-
|
|
22
|
+
init: IEntryServerOptions<TAppProps>['init'];
|
|
23
23
|
}
|
|
24
24
|
interface IAppServerProps<T = Record<string, any>> {
|
|
25
|
-
server: T
|
|
26
|
-
req: Request;
|
|
27
|
-
};
|
|
25
|
+
server: T;
|
|
28
26
|
}
|
|
29
|
-
type TApp<T> = FC<PropsWithChildren<IAppServerProps<T>>>;
|
|
27
|
+
type TApp<T> = FC<PropsWithChildren<Record<string, any> & IAppServerProps<T>>>;
|
|
30
28
|
interface IEntryServerOptions<TAppProps = Record<string, any>> {
|
|
31
|
-
|
|
32
|
-
initServer?: (params: {
|
|
29
|
+
init?: (params: {
|
|
33
30
|
config: ServerConfig;
|
|
34
31
|
}) => IEntrypointOptions<TAppProps> | Promise<IEntrypointOptions<TAppProps>>;
|
|
35
32
|
}
|
|
36
33
|
/**
|
|
37
34
|
* Render server side application
|
|
38
35
|
*/
|
|
39
|
-
declare function entry<TAppProps>(
|
|
36
|
+
declare function entry<TAppProps>(App: TApp<TAppProps>, routes: TRouteObject[], { init }?: IEntryServerOptions<TAppProps>): IPrepareRenderOut<TAppProps>;
|
|
40
37
|
export { entry as default, IInitServerRequestOut, IEntrypointOptions, IPrepareRenderOut, IAppServerProps, TApp, IEntryServerOptions };
|
package/node/entry.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{createStaticHandler as r}from"react-router-dom/server.mjs";import e from"./render.js";function
|
|
1
|
+
import{createStaticHandler as r}from"react-router-dom/server.mjs";import e from"./render.js";function n(n,t,{init:o}={}){const i=r(t);return{render:e.bind(null,{handler:i,App:n}),init:o}}export{n as default};
|
|
2
2
|
//# sourceMappingURL=entry.js.map
|
package/node/entry.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entry.js","sources":["../../src/node/entry.tsx"],"sourcesContent":["import type { Express, Request, Response as ExpressResponse } from 'express';\nimport type { FC, PropsWithChildren } from 'react';\nimport type { RouteObject } from 'react-router-dom';\nimport { createStaticHandler } from 'react-router-dom/server.mjs';\nimport type { IRenderOptions, IRenderParams, TRender } from '@node/render';\nimport render from '@node/render';\nimport type ServerConfig from '@services/server-config';\n\nexport interface IInitServerRequestOut<T = Record<string, any>> {\n appProps?: T;\n}\n\nexport interface IEntrypointOptions<TAppProps = Record<string, any>> {\n onServerCreated?: (app: Express) => Promise<void> | void;\n onRequest?: (\n req: Request,\n res: ExpressResponse,\n ) => Promise<IInitServerRequestOut<TAppProps>> | IInitServerRequestOut<TAppProps>;\n onRouterReady?: IRenderOptions<TAppProps>['onRouterReady'];\n onShellReady?: IRenderOptions<TAppProps>['onShellReady'];\n onShellError?: IRenderOptions<TAppProps>['onShellError'];\n onResponse?: IRenderOptions<TAppProps>['onResponse'];\n onError?: IRenderOptions<TAppProps>['onError'];\n getState?: IRenderOptions<TAppProps>['getState'];\n}\n\nexport interface IPrepareRenderOut<TAppProps = Record<string, any>> {\n render: TRender;\n
|
|
1
|
+
{"version":3,"file":"entry.js","sources":["../../src/node/entry.tsx"],"sourcesContent":["import type { Express, Request, Response as ExpressResponse } from 'express';\nimport type { FC, PropsWithChildren } from 'react';\nimport type { RouteObject } from 'react-router-dom';\nimport { createStaticHandler } from 'react-router-dom/server.mjs';\nimport type { TRouteObject } from '@interfaces/route-object';\nimport type { IRenderOptions, IRenderParams, TRender } from '@node/render';\nimport render from '@node/render';\nimport type ServerConfig from '@services/server-config';\n\nexport interface IInitServerRequestOut<T = Record<string, any>> {\n appProps?: T;\n}\n\nexport interface IEntrypointOptions<TAppProps = Record<string, any>> {\n onServerCreated?: (app: Express) => Promise<void> | void;\n onRequest?: (\n req: Request,\n res: ExpressResponse,\n ) => Promise<IInitServerRequestOut<TAppProps>> | IInitServerRequestOut<TAppProps>;\n onRouterReady?: IRenderOptions<TAppProps>['onRouterReady'];\n onShellReady?: IRenderOptions<TAppProps>['onShellReady'];\n onShellError?: IRenderOptions<TAppProps>['onShellError'];\n onResponse?: IRenderOptions<TAppProps>['onResponse'];\n onError?: IRenderOptions<TAppProps>['onError'];\n getState?: IRenderOptions<TAppProps>['getState'];\n}\n\nexport interface IPrepareRenderOut<TAppProps = Record<string, any>> {\n render: TRender;\n init: IEntryServerOptions<TAppProps>['init'];\n}\n\nexport interface IAppServerProps<T = Record<string, any>> {\n server: T;\n}\n\nexport type TApp<T> = FC<PropsWithChildren<Record<string, any> & IAppServerProps<T>>>;\n\nexport interface IEntryServerOptions<TAppProps = Record<string, any>> {\n init?: (params: {\n config: ServerConfig;\n }) => IEntrypointOptions<TAppProps> | Promise<IEntrypointOptions<TAppProps>>;\n}\n\n/**\n * Render server side application\n */\nfunction entry<TAppProps>(\n App: TApp<TAppProps>,\n routes: TRouteObject[],\n { init }: IEntryServerOptions<TAppProps> = {},\n): IPrepareRenderOut<TAppProps> {\n const handler = createStaticHandler(routes as RouteObject[]);\n\n return {\n render: render.bind(null, { handler, App } as IRenderParams<TAppProps>) as TRender,\n init,\n };\n}\n\nexport default entry;\n"],"names":["entry","App","routes","init","handler","createStaticHandler","render","bind"],"mappings":"6FA+CA,SAASA,EACPC,EACAC,GACAC,KAAEA,GAAyC,CAAA,GAE3C,MAAMC,EAAUC,EAAoBH,GAEpC,MAAO,CACLI,OAAQA,EAAOC,KAAK,KAAM,CAAEH,UAASH,QACrCE,OAEJ"}
|
package/node/render.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ import ServerConfig from "../services/server-config.js";
|
|
|
10
10
|
interface IRequestContext<TAppProps = Record<any, any>> {
|
|
11
11
|
req: Request;
|
|
12
12
|
res: ExpressResponse;
|
|
13
|
-
appProps: TAppProps
|
|
13
|
+
appProps: NonNullable<TAppProps>;
|
|
14
14
|
html: {
|
|
15
15
|
header: string;
|
|
16
16
|
footer: string;
|
|
@@ -31,7 +31,7 @@ interface IRenderOptions<TAppProps = Record<string, any>> {
|
|
|
31
31
|
context: IRequestContext<TAppProps>;
|
|
32
32
|
}) => Promise<IRouterReadyOut> | IRouterReadyOut;
|
|
33
33
|
onShellReady?: (params: {
|
|
34
|
-
context: IRequestContext
|
|
34
|
+
context: IRequestContext<TAppProps>;
|
|
35
35
|
}) => IShellReadyOut;
|
|
36
36
|
onShellError?: (params: {
|
|
37
37
|
context: IRequestContext<TAppProps>;
|
package/node/render.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render.js","sources":["../../src/node/render.tsx"],"sourcesContent":["import type { StaticHandler } from '@remix-run/router';\nimport chalk from 'chalk';\nimport type { Request, Response as ExpressResponse } from 'express';\nimport React from 'react';\nimport { renderToPipeableStream } from 'react-dom/server';\nimport type { StaticHandlerContext } from 'react-router-dom/server';\nimport { createStaticRouter, StaticRouterProvider } from 'react-router-dom/server.mjs';\nimport StreamError from '@constants/stream-error';\nimport type { IServerContext } from '@context/server';\nimport { ServerProvider } from '@context/server';\nimport handleResponse from '@helpers/handle-response';\nimport type { IObtainStreamErrorOut } from '@helpers/obtain-stream-error';\nimport obtainStreamError from '@helpers/obtain-stream-error';\nimport createFetchRequest from '@node/create-fetch-request';\nimport type { TApp } from '@node/entry';\nimport writeResponse from '@node/write-response';\nimport type ServerConfig from '@services/server-config';\n\nexport interface IRequestContext<TAppProps = Record<any, any>> {\n req: Request;\n res: ExpressResponse;\n appProps: TAppProps
|
|
1
|
+
{"version":3,"file":"render.js","sources":["../../src/node/render.tsx"],"sourcesContent":["import type { StaticHandler } from '@remix-run/router';\nimport chalk from 'chalk';\nimport type { Request, Response as ExpressResponse } from 'express';\nimport React from 'react';\nimport { renderToPipeableStream } from 'react-dom/server';\nimport type { StaticHandlerContext } from 'react-router-dom/server';\nimport { createStaticRouter, StaticRouterProvider } from 'react-router-dom/server.mjs';\nimport StreamError from '@constants/stream-error';\nimport type { IServerContext } from '@context/server';\nimport { ServerProvider } from '@context/server';\nimport handleResponse from '@helpers/handle-response';\nimport type { IObtainStreamErrorOut } from '@helpers/obtain-stream-error';\nimport obtainStreamError from '@helpers/obtain-stream-error';\nimport createFetchRequest from '@node/create-fetch-request';\nimport type { TApp } from '@node/entry';\nimport writeResponse from '@node/write-response';\nimport type ServerConfig from '@services/server-config';\n\nexport interface IRequestContext<TAppProps = Record<any, any>> {\n req: Request;\n res: ExpressResponse;\n appProps: NonNullable<TAppProps>;\n html: { header: string; footer: string };\n routerContext?: StaticHandlerContext;\n serverContext?: IServerContext;\n isStream?: boolean;\n didError?: StreamError;\n}\n\nexport type TRender<TAppProps = Record<any, any>> = (\n config: ServerConfig,\n context: IRequestContext<TAppProps>,\n options: IRenderOptions,\n) => Promise<void>;\n\nexport interface IRenderParams<TAppProps = Record<string, any>> {\n App: TApp<TAppProps>;\n handler: StaticHandler;\n}\n\nexport interface IRenderOptions<TAppProps = Record<string, any>> {\n appProps?: TAppProps;\n onRouterReady?: (params: {\n context: IRequestContext<TAppProps>;\n }) => Promise<IRouterReadyOut> | IRouterReadyOut;\n onShellReady?: (params: { context: IRequestContext<TAppProps> }) => IShellReadyOut;\n onShellError?: (params: {\n context: IRequestContext<TAppProps>;\n error: Error;\n }) => string | undefined | void; // return html or undefined\n onError?: (params: { context: IRequestContext<TAppProps>; error: IObtainStreamErrorOut }) => void;\n onResponse?: (params: {\n context: IRequestContext<TAppProps>;\n html: string;\n }) => string | undefined | void;\n getState?: (params: {\n context: IRequestContext<TAppProps>;\n }) => Record<string, Record<string, any>> | undefined | void;\n}\n\nexport interface IRouterReadyOut {\n isStream?: boolean;\n}\n\nexport interface IShellReadyOut {\n header?: string;\n footer?: string;\n}\n\n/**\n * Render application\n */\nasync function render(\n { App, handler }: IRenderParams, // @see entry (bind)\n config: ServerConfig,\n context: IRequestContext,\n { onRouterReady, onShellReady, onResponse, onShellError, onError, getState }: IRenderOptions,\n): Promise<void> {\n const { req, res } = context;\n const fetchRequest = createFetchRequest(req);\n\n context.routerContext = (await handler.query(fetchRequest)) as StaticHandlerContext;\n /**\n * Handle response from page loader, router context can be Response\n */\n const statusCode = handleResponse(res, context.routerContext);\n\n if (!statusCode) {\n return;\n }\n\n const { isStream = true } = (await onRouterReady?.({ context })) ?? {};\n\n context.isStream = isStream;\n context.serverContext = { response: null, isServer: true };\n\n const router = createStaticRouter(handler.dataRoutes, context.routerContext);\n const write = res.write.bind(res);\n const Logger = config.getLogger();\n let abortTimer: NodeJS.Timer | undefined = undefined;\n\n /**\n * Listen response and stream to add possibility modify html on fly\n * E.g. listen stream and append some data\n */\n res.write = (data: string | Uint8Array, ...args): boolean => {\n const isString = typeof data === 'string';\n const html = isString ? data : Buffer.from(data).toString();\n const additionalHtml = onResponse?.({ context, html });\n\n if (additionalHtml) {\n return write(\n isString ? `${additionalHtml}${data}` : Buffer.concat([Buffer.from(additionalHtml), data]),\n ...args,\n ) as boolean;\n }\n\n return write(data, ...args) as boolean;\n };\n\n const { serverContext, routerContext, appProps } = context;\n\n const { pipe, abort } = renderToPipeableStream(\n <ServerProvider context={serverContext}>\n <App server={{ ...appProps, req }}>\n <StaticRouterProvider router={router} context={routerContext} hydrate={false} />\n </App>\n </ServerProvider>,\n {\n onShellReady(): void {\n if (!isStream) {\n return;\n }\n\n writeResponse(context, {\n pipe,\n statusCode,\n onShellReady,\n getState,\n });\n },\n onAllReady(): void {\n clearTimeout(abortTimer);\n\n if (isStream) {\n return;\n }\n\n writeResponse(context, {\n pipe,\n statusCode,\n onShellReady,\n getState,\n });\n },\n onShellError(e: Error): void {\n const htmlError =\n onShellError?.({ context, error: e }) ||\n `<!doctype html><p>Something went wrong: ${e.message}</p>`;\n\n res.status(500);\n res.setHeader('content-type', 'text/html');\n res.send(htmlError);\n },\n onError(err): void {\n clearTimeout(abortTimer);\n\n const error = obtainStreamError(err);\n const { code, message } = error;\n const { didError } = context;\n\n context.didError = didError ?? code;\n\n onError?.({ context, error });\n Logger.info(chalk.red(`Stream error. Code: ${code}`));\n\n if (\n [StreamError.RenderAborted, StreamError.RenderTimeout, StreamError.RenderCancel].includes(\n code,\n )\n ) {\n Logger.info(chalk.dim(message));\n\n return;\n }\n\n Logger.error(err as string);\n },\n },\n );\n\n // Abandon and switch to client rendering if enough time passes.\n abortTimer = setTimeout(() => {\n context.didError = StreamError.RenderTimeout;\n abort();\n }, config.getParams().abortDelay);\n\n // Detect cancel request\n req.on('close', () => {\n context.didError = StreamError.RenderCancel;\n abort();\n });\n}\n\nexport default render;\n"],"names":["async","render","App","handler","config","context","onRouterReady","onShellReady","onResponse","onShellError","onError","getState","req","res","fetchRequest","createFetchRequest","routerContext","query","statusCode","handleResponse","isStream","serverContext","response","isServer","router","createStaticRouter","dataRoutes","write","bind","Logger","getLogger","abortTimer","data","args","isString","html","Buffer","from","toString","additionalHtml","concat","appProps","pipe","abort","renderToPipeableStream","React","createElement","ServerProvider","server","StaticRouterProvider","hydrate","writeResponse","onAllReady","clearTimeout","e","htmlError","error","message","status","setHeader","send","err","obtainStreamError","code","didError","info","chalk","red","StreamError","RenderAborted","RenderTimeout","RenderCancel","includes","dim","setTimeout","getParams","abortDelay","on"],"mappings":"2cAwEAA,eAAeC,GACbC,IAAEA,EAAGC,QAAEA,GACPC,EACAC,GACAC,cAAEA,EAAaC,aAAEA,EAAYC,WAAEA,EAAUC,aAAEA,EAAYC,QAAEA,EAAOC,SAAEA,IAElE,MAAMC,IAAEA,EAAGC,IAAEA,GAAQR,EACfS,EAAeC,EAAmBH,GAExCP,EAAQW,oBAAuBb,EAAQc,MAAMH,GAI7C,MAAMI,EAAaC,EAAeN,EAAKR,EAAQW,eAE/C,IAAKE,EACH,OAGF,MAAME,SAAEA,GAAW,SAAgBd,IAAgB,CAAED,cAAe,GAEpEA,EAAQe,SAAWA,EACnBf,EAAQgB,cAAgB,CAAEC,SAAU,KAAMC,UAAU,GAEpD,MAAMC,EAASC,EAAmBtB,EAAQuB,WAAYrB,EAAQW,eACxDW,EAAQd,EAAIc,MAAMC,KAAKf,GACvBgB,EAASzB,EAAO0B,YACtB,IAAIC,EAMJlB,EAAIc,MAAQ,CAACK,KAA8BC,KACzC,MAAMC,EAA2B,iBAATF,EAClBG,EAAOD,EAAWF,EAAOI,OAAOC,KAAKL,GAAMM,WAC3CC,EAAiB/B,IAAa,CAAEH,UAAS8B,SAE/C,OAAII,EACKZ,EACLO,EAAW,GAAGK,IAAiBP,IAASI,OAAOI,OAAO,CAACJ,OAAOC,KAAKE,GAAiBP,OACjFC,GAIAN,EAAMK,KAASC,EAAgB,EAGxC,MAAMZ,cAAEA,EAAaL,cAAEA,EAAayB,SAAEA,GAAapC,GAE7CqC,KAAEA,EAAIC,MAAEA,GAAUC,EACtBC,EAACC,cAAAC,EAAe,CAAA1C,QAASgB,GACvBwB,EAACC,cAAA5C,GAAI8C,OAAQ,IAAKP,EAAU7B,QAC1BiC,EAAAC,cAACG,EAAqB,CAAAzB,OAAQA,EAAQnB,QAASW,EAAekC,SAAS,MAG3E,CACE3C,eACOa,GAIL+B,EAAc9C,EAAS,CACrBqC,OACAxB,aACAX,eACAI,YAEH,EACDyC,aACEC,aAAatB,GAETX,GAIJ+B,EAAc9C,EAAS,CACrBqC,OACAxB,aACAX,eACAI,YAEH,EACDF,aAAa6C,GACX,MAAMC,EACJ9C,IAAe,CAAEJ,UAASmD,MAAOF,KACjC,2CAA2CA,EAAEG,cAE/C5C,EAAI6C,OAAO,KACX7C,EAAI8C,UAAU,eAAgB,aAC9B9C,EAAI+C,KAAKL,EACV,EACD7C,QAAQmD,GACNR,aAAatB,GAEb,MAAMyB,EAAQM,EAAkBD,IAC1BE,KAAEA,EAAIN,QAAEA,GAAYD,GACpBQ,SAAEA,GAAa3D,EAErBA,EAAQ2D,SAAWA,GAAYD,EAE/BrD,IAAU,CAAEL,UAASmD,UACrB3B,EAAOoC,KAAKC,EAAMC,IAAI,uBAAuBJ,MAG3C,CAACK,EAAYC,cAAeD,EAAYE,cAAeF,EAAYG,cAAcC,SAC/ET,GAGFlC,EAAOoC,KAAKC,EAAMO,IAAIhB,IAKxB5B,EAAO2B,MAAMK,EACd,IAKL9B,EAAa2C,YAAW,KACtBrE,EAAQ2D,SAAWI,EAAYE,cAC/B3B,GAAO,GACNvC,EAAOuE,YAAYC,YAGtBhE,EAAIiE,GAAG,SAAS,KACdxE,EAAQ2D,SAAWI,EAAYG,aAC/B5B,GAAO,GAEX"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lomray/vite-ssr-boost",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.4",
|
|
4
4
|
"description": "Vite plugin for create awesome SSR or SPA applications on React.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
@@ -36,8 +36,8 @@
|
|
|
36
36
|
"commander": "^10.0.1",
|
|
37
37
|
"compression": "^1.7.4",
|
|
38
38
|
"express": "^4.18.2",
|
|
39
|
-
"
|
|
40
|
-
"react-
|
|
39
|
+
"hjson": "^3.2.2",
|
|
40
|
+
"hoist-non-react-statics": "^3.3.2"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@commitlint/cli": "^17.6.5",
|
|
@@ -47,6 +47,8 @@
|
|
|
47
47
|
"@rollup/plugin-terser": "^0.4.3",
|
|
48
48
|
"@types/compression": "^1.7.2",
|
|
49
49
|
"@types/express": "^4.17.17",
|
|
50
|
+
"@types/hjson": "^2.4.3",
|
|
51
|
+
"@types/hoist-non-react-statics": "^3.3.1",
|
|
50
52
|
"@types/react-dom": "^18.2.5",
|
|
51
53
|
"@typescript-eslint/eslint-plugin": "^5.59.11",
|
|
52
54
|
"@zerollup/ts-transform-paths": "^1.7.18",
|
|
@@ -68,6 +70,8 @@
|
|
|
68
70
|
"typescript": "^4.9.5"
|
|
69
71
|
},
|
|
70
72
|
"peerDependencies": {
|
|
73
|
+
"react-dom": ">=18.2.0",
|
|
74
|
+
"react-router-dom": ">=6.12.1",
|
|
71
75
|
"vite": "^4.3.9"
|
|
72
76
|
},
|
|
73
77
|
"bin": {
|
package/plugin.d.ts
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { Plugin } from 'vite';
|
|
2
2
|
import { ICliContext } from "./constants/cli-context.js";
|
|
3
|
+
import { IPluginOptions as IMakeAliasesPluginOptions } from "./plugins/make-aliases.js";
|
|
3
4
|
interface IPluginOptions {
|
|
4
5
|
indexFile?: string;
|
|
5
6
|
serverFile?: string;
|
|
6
7
|
abortDelay?: number;
|
|
8
|
+
hasLazyRoutePlugin?: boolean;
|
|
9
|
+
tsconfigAliases?: boolean | IMakeAliasesPluginOptions;
|
|
7
10
|
customShortcuts?: {
|
|
8
11
|
key: string;
|
|
9
12
|
description: string;
|
package/plugin.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import e from"node:path";import
|
|
1
|
+
import e from"node:path";import i from"./constants/cli-actions.js";import o from"./constants/plugin-name.js";import n from"./plugins/make-aliases.js";import s from"./plugins/normalize-route.js";const t={indexFile:"index.html",serverFile:"server.ts",abortDelay:1e4,hasLazyRoutePlugin:!0,tsconfigAliases:!0};function a(a={}){const r=new URL(import.meta.url),l=global.viteBoostAction,p={...t,...a},m=[{name:o,enforce:"pre",pluginOptions:{...p,pluginPath:e.dirname(r.pathname),action:l,isDev:l===i.dev},config:(e,{ssrBuild:i})=>(e.define={...e.define??{},__IS_SSR__:"1"===process.env.SSR_BOOST_IS_SSR||"dev"===l},i?{...e,publicDir:!1}:e)}],{hasLazyRoutePlugin:u,tsconfigAliases:c}=p;return u&&m.push(s()),c&&m.push(n("boolean"==typeof c?void 0:c)),m}export{a as default};
|
|
2
2
|
//# sourceMappingURL=plugin.js.map
|
package/plugin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.js","sources":["../src/plugin.ts"],"sourcesContent":["import path from 'node:path';\nimport type { Plugin } from 'vite';\nimport CliActions from '@constants/cli-actions';\nimport type { ICliContext } from '@constants/cli-context';\nimport PLUGIN_NAME from '@constants/plugin-name';\n\nexport interface IPluginOptions {\n indexFile?: string; // default: index.html\n serverFile?: string; // default: server.ts\n abortDelay?: number; // How long the server waits for data before giving up. default: 10000 (10 sec)\n customShortcuts?: {\n key: string;\n description: string;\n action: (cliContext: ICliContext) => Promise<void> | void;\n isOnlyDev?: boolean;\n }[];\n}\n\nconst defaultOptions: IPluginOptions = {\n indexFile: 'index.html',\n serverFile: 'server.ts',\n abortDelay: 10000,\n};\n\n/**\n * Init insane vite ssr plugin\n * @constructor\n */\nfunction ViteSsrInsanePlugin(options: IPluginOptions = {}): Plugin[] {\n const dirInfo = new URL(import.meta.url);\n const action = global.viteBoostAction as CliActions;\n const mergedOptions: IPluginOptions = { ...defaultOptions, ...options };\n\n
|
|
1
|
+
{"version":3,"file":"plugin.js","sources":["../src/plugin.ts"],"sourcesContent":["import path from 'node:path';\nimport type { Plugin } from 'vite';\nimport CliActions from '@constants/cli-actions';\nimport type { ICliContext } from '@constants/cli-context';\nimport PLUGIN_NAME from '@constants/plugin-name';\nimport ViteMakeAliasesPlugin from '@plugins/make-aliases';\nimport type { IPluginOptions as IMakeAliasesPluginOptions } from '@plugins/make-aliases';\nimport ViteNormalizeRouterPlugin from '@plugins/normalize-route';\n\nexport interface IPluginOptions {\n indexFile?: string; // default: index.html\n serverFile?: string; // default: server.ts\n abortDelay?: number; // How long the server waits for data before giving up. default: 10000 (10 sec)\n hasLazyRoutePlugin?: boolean; // Possibility to use custom export route component @see FCRoute interface\n tsconfigAliases?: boolean | IMakeAliasesPluginOptions; // Read aliases from tsconfig\n customShortcuts?: {\n key: string;\n description: string;\n action: (cliContext: ICliContext) => Promise<void> | void;\n isOnlyDev?: boolean;\n }[];\n}\n\nconst defaultOptions: IPluginOptions = {\n indexFile: 'index.html',\n serverFile: 'server.ts',\n abortDelay: 10000,\n hasLazyRoutePlugin: true,\n tsconfigAliases: true,\n};\n\n/**\n * Init insane vite ssr plugin\n * @constructor\n */\nfunction ViteSsrInsanePlugin(options: IPluginOptions = {}): Plugin[] {\n const dirInfo = new URL(import.meta.url);\n const action = global.viteBoostAction as CliActions;\n const mergedOptions: IPluginOptions = { ...defaultOptions, ...options };\n\n const plugins: Plugin[] = [\n {\n name: PLUGIN_NAME,\n enforce: 'pre',\n // @ts-ignore save custom options\n pluginOptions: {\n ...mergedOptions,\n pluginPath: path.dirname(dirInfo.pathname),\n action,\n isDev: action === CliActions.dev,\n },\n config(config, { ssrBuild }) {\n config.define = {\n ...(config.define ?? {}),\n __IS_SSR__: process.env.SSR_BOOST_IS_SSR === '1' || action === 'dev',\n };\n\n if (!ssrBuild) {\n return config;\n }\n\n return {\n ...config,\n publicDir: false,\n };\n },\n },\n ];\n\n const { hasLazyRoutePlugin, tsconfigAliases } = mergedOptions;\n\n if (hasLazyRoutePlugin) {\n plugins.push(ViteNormalizeRouterPlugin());\n }\n\n if (tsconfigAliases) {\n plugins.push(\n ViteMakeAliasesPlugin(typeof tsconfigAliases === 'boolean' ? undefined : tsconfigAliases),\n );\n }\n\n return plugins;\n}\n\nexport default ViteSsrInsanePlugin;\n"],"names":["defaultOptions","indexFile","serverFile","abortDelay","hasLazyRoutePlugin","tsconfigAliases","ViteSsrInsanePlugin","options","dirInfo","URL","url","action","global","viteBoostAction","mergedOptions","plugins","name","PLUGIN_NAME","enforce","pluginOptions","pluginPath","path","dirname","pathname","isDev","CliActions","dev","config","ssrBuild","define","__IS_SSR__","process","env","SSR_BOOST_IS_SSR","publicDir","push","ViteNormalizeRouterPlugin","ViteMakeAliasesPlugin","undefined"],"mappings":"kMAuBA,MAAMA,EAAiC,CACrCC,UAAW,aACXC,WAAY,YACZC,WAAY,IACZC,oBAAoB,EACpBC,iBAAiB,GAOnB,SAASC,EAAoBC,EAA0B,IACrD,MAAMC,EAAU,IAAIC,gBAAgBC,KAC9BC,EAASC,OAAOC,gBAChBC,EAAgC,IAAKd,KAAmBO,GAExDQ,EAAoB,CACxB,CACEC,KAAMC,EACNC,QAAS,MAETC,cAAe,IACVL,EACHM,WAAYC,EAAKC,QAAQd,EAAQe,UACjCZ,SACAa,MAAOb,IAAWc,EAAWC,KAE/BC,OAAM,CAACA,GAAQC,SAAEA,MACfD,EAAOE,OAAS,IACVF,EAAOE,QAAU,GACrBC,WAA6C,MAAjCC,QAAQC,IAAIC,kBAAuC,QAAXtB,GAGjDiB,EAIE,IACFD,EACHO,WAAW,GALJP,MAWTvB,mBAAEA,EAAkBC,gBAAEA,GAAoBS,EAYhD,OAVIV,GACFW,EAAQoB,KAAKC,KAGX/B,GACFU,EAAQoB,KACNE,EAAiD,kBAApBhC,OAAgCiC,EAAYjC,IAItEU,CACT"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Plugin } from 'vite';
|
|
2
|
+
interface IPluginOptions {
|
|
3
|
+
root?: string;
|
|
4
|
+
tsconfig?: string;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Read tsconfig file and set vite aliases
|
|
8
|
+
* @constructor
|
|
9
|
+
*/
|
|
10
|
+
declare function ViteMakeAliasesPlugin(options?: IPluginOptions): Plugin;
|
|
11
|
+
export { ViteMakeAliasesPlugin as default, IPluginOptions };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import e from"node:fs";import o from"node:path";import s from"node:process";import r from"hjson";import t from"../constants/plugin-name.js";import n from"../helpers/vite-aliases.js";const i=`${t}-make-aliases`,a=e=>e.replace("/*","");function c(t={}){const{root:c,tsconfig:p}=t,f=c??s.cwd(),m=o.resolve(f,p??"tsconfig.json"),l=[];if(e.existsSync(m)){const o=r.parse(e.readFileSync(m,{encoding:"utf-8"})),s=o?.compilerOptions?.paths??{};Object.entries(s).forEach((([e,o])=>{l.push([a(e),a(o[0])])}))}else console.error(`${i}: tsconfig not exist in "${m}"`);return{name:i,config(e){if(l.length){const o=e.resolve??{},s=o.alias??[],r=Array.isArray(s)?s:Object.entries(s).map((([e,o])=>({find:e,replacement:o})));r.push(...n(l,`${f}/${e?.root??""}`)),e.resolve={...o,alias:r}}return e}}}export{c as default};
|
|
2
|
+
//# sourceMappingURL=make-aliases.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"make-aliases.js","sources":["../../src/plugins/make-aliases.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport process from 'node:process';\nimport Hjson from 'hjson';\nimport type { Plugin } from 'vite';\nimport PLUGIN_NAME from '@constants/plugin-name';\nimport ViteAliases from '@helpers/vite-aliases';\n\nexport interface IPluginOptions {\n root?: string; // default: cwd()\n tsconfig?: string; // default: tsconfig.json\n}\n\nconst pluginName = `${PLUGIN_NAME}-make-aliases`;\nconst cleanupAlias = (str: string): string => str.replace('/*', '');\n\n/**\n * Read tsconfig file and set vite aliases\n * @constructor\n */\nfunction ViteMakeAliasesPlugin(options: IPluginOptions = {}): Plugin {\n const { root, tsconfig } = options;\n const projectRoot = root ?? process.cwd();\n const tsconfigPath = path.resolve(projectRoot, tsconfig ?? 'tsconfig.json');\n const aliases: [string, string][] = [];\n\n if (!fs.existsSync(tsconfigPath)) {\n console.error(`${pluginName}: tsconfig not exist in \"${tsconfigPath}\"`);\n } else {\n const tsJson = Hjson.parse(fs.readFileSync(tsconfigPath, { encoding: 'utf-8' }));\n const paths: Record<string, string[]> = tsJson?.compilerOptions?.paths ?? {};\n\n Object.entries(paths).forEach(([alias, aliasPaths]) => {\n aliases.push([cleanupAlias(alias), cleanupAlias(aliasPaths[0])]);\n });\n }\n\n return {\n name: pluginName,\n config(config) {\n if (aliases.length) {\n const resolveConfig = config.resolve ?? {};\n const defaultAliases = resolveConfig.alias ?? [];\n const normalizedAliases = Array.isArray(defaultAliases)\n ? defaultAliases\n : Object.entries(defaultAliases).map(([find, val]) => ({ find, replacement: val }));\n\n normalizedAliases.push(...ViteAliases(aliases, `${projectRoot}/${config?.root ?? ''}`));\n\n config.resolve = {\n ...resolveConfig,\n alias: normalizedAliases,\n };\n }\n\n return config;\n },\n };\n}\n\nexport default ViteMakeAliasesPlugin;\n"],"names":["pluginName","PLUGIN_NAME","cleanupAlias","str","replace","ViteMakeAliasesPlugin","options","root","tsconfig","projectRoot","process","cwd","tsconfigPath","path","resolve","aliases","fs","existsSync","tsJson","Hjson","parse","readFileSync","encoding","paths","compilerOptions","Object","entries","forEach","alias","aliasPaths","push","console","error","name","config","length","resolveConfig","defaultAliases","normalizedAliases","Array","isArray","map","find","val","replacement","ViteAliases"],"mappings":"sLAaA,MAAMA,EAAa,GAAGC,iBAChBC,EAAgBC,GAAwBA,EAAIC,QAAQ,KAAM,IAMhE,SAASC,EAAsBC,EAA0B,IACvD,MAAMC,KAAEA,EAAIC,SAAEA,GAAaF,EACrBG,EAAcF,GAAQG,EAAQC,MAC9BC,EAAeC,EAAKC,QAAQL,EAAaD,GAAY,iBACrDO,EAA8B,GAEpC,GAAKC,EAAGC,WAAWL,GAEZ,CACL,MAAMM,EAASC,EAAMC,MAAMJ,EAAGK,aAAaT,EAAc,CAAEU,SAAU,WAC/DC,EAAkCL,GAAQM,iBAAiBD,OAAS,CAAA,EAE1EE,OAAOC,QAAQH,GAAOI,SAAQ,EAAEC,EAAOC,MACrCd,EAAQe,KAAK,CAAC5B,EAAa0B,GAAQ1B,EAAa2B,EAAW,KAAK,GAEnE,MARCE,QAAQC,MAAM,GAAGhC,6BAAsCY,MAUzD,MAAO,CACLqB,KAAMjC,EACNkC,OAAOA,GACL,GAAInB,EAAQoB,OAAQ,CAClB,MAAMC,EAAgBF,EAAOpB,SAAW,GAClCuB,EAAiBD,EAAcR,OAAS,GACxCU,EAAoBC,MAAMC,QAAQH,GACpCA,EACAZ,OAAOC,QAAQW,GAAgBI,KAAI,EAAEC,EAAMC,MAAU,CAAED,OAAME,YAAaD,MAE9EL,EAAkBR,QAAQe,EAAY9B,EAAS,GAAGN,KAAeyB,GAAQ3B,MAAQ,OAEjF2B,EAAOpB,QAAU,IACZsB,EACHR,MAAOU,EAEV,CAED,OAAOJ,CACR,EAEL"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Plugin } from 'vite';
|
|
2
|
+
/**
|
|
3
|
+
* Add possibility to export route components like FCRoute or FCCRoute
|
|
4
|
+
* USAGE: { path: '/', lazyNR: () => import('./pages/home') }
|
|
5
|
+
* @see FCRoute
|
|
6
|
+
* @see FCCRoute
|
|
7
|
+
* @constructor
|
|
8
|
+
*/
|
|
9
|
+
declare function ViteNormalizeRouterPlugin(): Plugin;
|
|
10
|
+
export { ViteNormalizeRouterPlugin as default };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import t from"../constants/plugin-name.js";const r=r=>`import n from '${t}/helpers/import-route';${r}`.replace(/(lazyNR)(:\s*)(\(\)\s*=>\s*import\([^)]+\))/gs,"lazy$2()=>n($3)");function s(){return{name:`${t}-normalize-route`,transform:(t,s)=>{if(/^.*\.(js|ts|tsx)$/.test(s)&&(t=>/\[.*{.*path:.*lazyNR:.+import/s.test(t))(t))return{code:r(t),map:{mappings:""}}}}}export{s as default};
|
|
2
|
+
//# sourceMappingURL=normalize-route.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize-route.js","sources":["../../src/plugins/normalize-route.ts"],"sourcesContent":["import type { Plugin } from 'vite';\nimport PLUGIN_NAME from '@constants/plugin-name';\n\n/**\n * Detect route file\n */\nconst isRoutesFile = (code: string): boolean => /\\[.*{.*path:.*lazyNR:.+import/s.test(code);\n\n/**\n * Add normalize wrapper to lazy imports\n */\nconst normalizeRoutes = (code: string): string =>\n `import n from '${PLUGIN_NAME}/helpers/import-route';${code}`.replace(\n /(lazyNR)(:\\s*)(\\(\\)\\s*=>\\s*import\\([^)]+\\))/gs,\n 'lazy$2()=>n($3)',\n );\n\n/**\n * Add possibility to export route components like FCRoute or FCCRoute\n * USAGE: { path: '/', lazyNR: () => import('./pages/home') }\n * @see FCRoute\n * @see FCCRoute\n * @constructor\n */\nfunction ViteNormalizeRouterPlugin(): Plugin {\n return {\n name: `${PLUGIN_NAME}-normalize-route`,\n transform: (code, id) => {\n if (!/^.*\\.(js|ts|tsx)$/.test(id) || !isRoutesFile(code)) {\n return;\n }\n\n return {\n code: normalizeRoutes(code),\n map: { mappings: '' },\n };\n },\n };\n}\n\nexport default ViteNormalizeRouterPlugin;\n"],"names":["normalizeRoutes","code","PLUGIN_NAME","replace","ViteNormalizeRouterPlugin","name","transform","id","test","isRoutesFile","map","mappings"],"mappings":"2CAMA,MAKMA,EAAmBC,GACvB,kBAAkBC,2BAAqCD,IAAOE,QAC5D,gDACA,mBAUJ,SAASC,IACP,MAAO,CACLC,KAAM,GAAGH,oBACTI,UAAW,CAACL,EAAMM,KAChB,GAAK,oBAAoBC,KAAKD,IAtBf,CAACN,GAA0B,iCAAiCO,KAAKP,GAsB1CQ,CAAaR,GAInD,MAAO,CACLA,KAAMD,EAAgBC,GACtBS,IAAK,CAAEC,SAAU,IAClB,EAGP"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import t from"fs";import e from"path";class r{config;entrypoint;onServerCreated;html;constructor(t){this.config=t}static init(t){return new r(t)}async loadEntrypoint(){if(this.entrypoint&&this.config.isProd)return this.entrypoint;const{root:t,isProd:r,serverFile:o}=this.config.getParams(),n=e.resolve(`${t}/${o}`);let i;i=r?(await import(n)).default:(await this.config.getVite().ssrLoadModule(n,{fixStacktrace:!0})).default;const{render:s,
|
|
1
|
+
import t from"fs";import e from"path";class r{config;entrypoint;onServerCreated;html;constructor(t){this.config=t}static init(t){return new r(t)}async loadEntrypoint(){if(this.entrypoint&&this.config.isProd)return this.entrypoint;const{root:t,isProd:r,serverFile:o}=this.config.getParams(),n=e.resolve(`${t}/${o}`);let i;i=r?(await import(n)).default:(await this.config.getVite().ssrLoadModule(n,{fixStacktrace:!0})).default;const{render:s,init:a}=i,{onServerCreated:l,onRequest:h,onRouterReady:c,onShellReady:d,onResponse:p,onShellError:f,onError:g,getState:u}=await(a?.({config:this.config}))??{};return this.entrypoint={render:s,onRequest:h,onRouterReady:c,onShellReady:d,onShellError:f,onResponse:p,onError:g,getState:u},this.onServerCreated=l,this.entrypoint}async loadHtml(r){const{isProd:o,root:n,indexFile:i}=this.config.getParams();this.html&&o||(this.html=t.readFileSync(e.resolve(`${n}/${i}`),"utf-8"));let s=this.html;return o||(s=(await this.config.getVite().transformIndexHtml(r.originalUrl,this.html)).replace(/(<script.+)(>[\s\S]+injectIntoGlobalHook.+)/,"$1async$2")),s.split("\x3c!--ssr-outlet--\x3e")}async onAppCreated(){return await this.loadEntrypoint(),await(this.onServerCreated?.(this.config.getApp())),this}}export{r as default};
|
|
2
2
|
//# sourceMappingURL=prepare-server.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prepare-server.js","sources":["../../src/services/prepare-server.ts"],"sourcesContent":["import fs from 'fs';\nimport path from 'path';\nimport type { Request } from 'express';\nimport type { IEntrypointOptions, IPrepareRenderOut } from '@node/entry';\nimport type { TRender } from '@node/render';\nimport type ServerConfig from '@services/server-config';\n\ninterface IPrepareServerEntrypointLoadOut<TAppProps = Record<string, any>> {\n render: TRender;\n onRequest?: IEntrypointOptions<TAppProps>['onRequest'];\n onRouterReady?: IEntrypointOptions<TAppProps>['onRouterReady'];\n onShellReady?: IEntrypointOptions<TAppProps>['onShellReady'];\n onShellError?: IEntrypointOptions<TAppProps>['onShellError'];\n onResponse?: IEntrypointOptions<TAppProps>['onResponse'];\n onError?: IEntrypointOptions<TAppProps>['onError'];\n getState?: IEntrypointOptions<TAppProps>['getState'];\n}\n\n/**\n * Load server entrypoint and template\n * DEV MODE: refresh entrypoint and template\n */\nclass PrepareServer {\n /**\n * Server configuration\n */\n protected readonly config: ServerConfig;\n\n /**\n * Entrypoint resolved params\n */\n protected entrypoint?: IPrepareServerEntrypointLoadOut;\n\n /**\n * Hook which calls after express server created\n */\n protected onServerCreated?: IEntrypointOptions['onServerCreated'];\n\n /**\n * Html shell\n */\n protected html: string;\n\n /**\n * @constructor\n * @protected\n */\n protected constructor(config: ServerConfig) {\n this.config = config;\n }\n\n /**\n * Init service\n */\n public static init(config: ServerConfig): PrepareServer {\n return new PrepareServer(config);\n }\n\n /**\n * Resolve and return entrypoint params\n */\n public async loadEntrypoint(): Promise<IPrepareServerEntrypointLoadOut> {\n // load server entrypoint each time only in development mode (for fast refresh)\n if (this.entrypoint && this.config.isProd) {\n return this.entrypoint;\n }\n\n const { root, isProd, serverFile } = this.config.getParams();\n const entrypointPath = path.resolve(`${root}/${serverFile}`);\n\n let resolvedEntrypoint: IPrepareRenderOut;\n\n if (!isProd) {\n resolvedEntrypoint = (\n await this.config.getVite()!.ssrLoadModule(entrypointPath, {\n fixStacktrace: true,\n })\n ).default;\n } else {\n resolvedEntrypoint = (await import(entrypointPath)).default;\n }\n\n const { render,
|
|
1
|
+
{"version":3,"file":"prepare-server.js","sources":["../../src/services/prepare-server.ts"],"sourcesContent":["import fs from 'fs';\nimport path from 'path';\nimport type { Request } from 'express';\nimport type { IEntrypointOptions, IPrepareRenderOut } from '@node/entry';\nimport type { TRender } from '@node/render';\nimport type ServerConfig from '@services/server-config';\n\ninterface IPrepareServerEntrypointLoadOut<TAppProps = Record<string, any>> {\n render: TRender;\n onRequest?: IEntrypointOptions<TAppProps>['onRequest'];\n onRouterReady?: IEntrypointOptions<TAppProps>['onRouterReady'];\n onShellReady?: IEntrypointOptions<TAppProps>['onShellReady'];\n onShellError?: IEntrypointOptions<TAppProps>['onShellError'];\n onResponse?: IEntrypointOptions<TAppProps>['onResponse'];\n onError?: IEntrypointOptions<TAppProps>['onError'];\n getState?: IEntrypointOptions<TAppProps>['getState'];\n}\n\n/**\n * Load server entrypoint and template\n * DEV MODE: refresh entrypoint and template\n */\nclass PrepareServer {\n /**\n * Server configuration\n */\n protected readonly config: ServerConfig;\n\n /**\n * Entrypoint resolved params\n */\n protected entrypoint?: IPrepareServerEntrypointLoadOut;\n\n /**\n * Hook which calls after express server created\n */\n protected onServerCreated?: IEntrypointOptions['onServerCreated'];\n\n /**\n * Html shell\n */\n protected html: string;\n\n /**\n * @constructor\n * @protected\n */\n protected constructor(config: ServerConfig) {\n this.config = config;\n }\n\n /**\n * Init service\n */\n public static init(config: ServerConfig): PrepareServer {\n return new PrepareServer(config);\n }\n\n /**\n * Resolve and return entrypoint params\n */\n public async loadEntrypoint(): Promise<IPrepareServerEntrypointLoadOut> {\n // load server entrypoint each time only in development mode (for fast refresh)\n if (this.entrypoint && this.config.isProd) {\n return this.entrypoint;\n }\n\n const { root, isProd, serverFile } = this.config.getParams();\n const entrypointPath = path.resolve(`${root}/${serverFile}`);\n\n let resolvedEntrypoint: IPrepareRenderOut;\n\n if (!isProd) {\n resolvedEntrypoint = (\n await this.config.getVite()!.ssrLoadModule(entrypointPath, {\n fixStacktrace: true,\n })\n ).default;\n } else {\n resolvedEntrypoint = (await import(entrypointPath)).default;\n }\n\n const { render, init } = resolvedEntrypoint;\n const {\n onServerCreated,\n onRequest,\n onRouterReady,\n onShellReady,\n onResponse,\n onShellError,\n onError,\n getState,\n } =\n (await init?.({\n config: this.config,\n })) ?? {};\n\n this.entrypoint = {\n render,\n onRequest,\n onRouterReady,\n onShellReady,\n onShellError,\n onResponse,\n onError,\n getState,\n };\n this.onServerCreated = onServerCreated;\n\n return this.entrypoint;\n }\n\n /**\n * Load and return html shell\n */\n public async loadHtml(req: Request): Promise<[string, string]> {\n const { isProd, root, indexFile } = this.config.getParams();\n\n if (!this.html || !isProd) {\n this.html = fs.readFileSync(path.resolve(`${root}/${indexFile}`), 'utf-8');\n }\n\n let modifiedHtml = this.html;\n\n if (!isProd) {\n // Apply Vite HTML transforms. This injects the Vite HMR client,\n // and also applies HTML transforms from Vite plugins, e.g. global\n // preambles from @vitejs/plugin-react\n modifiedHtml = (await this.config.getVite()!.transformIndexHtml(req.originalUrl, this.html))\n // Make vite script 'async'\n .replace(/(<script.+)(>[\\s\\S]+injectIntoGlobalHook.+)/, '$1async$2');\n }\n\n return modifiedHtml.split('<!--ssr-outlet-->') as [string, string];\n }\n\n /**\n * Run server created hook\n */\n public async onAppCreated(): Promise<PrepareServer> {\n await this.loadEntrypoint();\n await this.onServerCreated?.(this.config.getApp()!);\n\n return this;\n }\n}\n\nexport default PrepareServer;\n"],"names":["PrepareServer","config","entrypoint","onServerCreated","html","constructor","this","static","async","isProd","root","serverFile","getParams","entrypointPath","path","resolve","resolvedEntrypoint","import","default","getVite","ssrLoadModule","fixStacktrace","render","init","onRequest","onRouterReady","onShellReady","onResponse","onShellError","onError","getState","req","indexFile","fs","readFileSync","modifiedHtml","transformIndexHtml","originalUrl","replace","split","loadEntrypoint","getApp"],"mappings":"sCAsBA,MAAMA,EAIeC,OAKTC,WAKAC,gBAKAC,KAMVC,YAAsBJ,GACpBK,KAAKL,OAASA,CACf,CAKMM,YAAYN,GACjB,OAAO,IAAID,EAAcC,EAC1B,CAKMO,uBAEL,GAAIF,KAAKJ,YAAcI,KAAKL,OAAOQ,OACjC,OAAOH,KAAKJ,WAGd,MAAMQ,KAAEA,EAAID,OAAEA,EAAME,WAAEA,GAAeL,KAAKL,OAAOW,YAC3CC,EAAiBC,EAAKC,QAAQ,GAAGL,KAAQC,KAE/C,IAAIK,EASFA,EAPGP,SAOyBQ,OAAOJ,IAAiBK,eAL5CZ,KAAKL,OAAOkB,UAAWC,cAAcP,EAAgB,CACzDQ,eAAe,KAEjBH,QAKJ,MAAMI,OAAEA,EAAMC,KAAEA,GAASP,GACnBb,gBACJA,EAAeqB,UACfA,EAASC,cACTA,EAAaC,aACbA,EAAYC,WACZA,EAAUC,aACVA,EAAYC,QACZA,EAAOC,SACPA,SAEOP,IAAO,CACZtB,OAAQK,KAAKL,WACR,CAAA,EAcT,OAZAK,KAAKJ,WAAa,CAChBoB,SACAE,YACAC,gBACAC,eACAE,eACAD,aACAE,UACAC,YAEFxB,KAAKH,gBAAkBA,EAEhBG,KAAKJ,UACb,CAKMM,eAAeuB,GACpB,MAAMtB,OAAEA,EAAMC,KAAEA,EAAIsB,UAAEA,GAAc1B,KAAKL,OAAOW,YAE3CN,KAAKF,MAASK,IACjBH,KAAKF,KAAO6B,EAAGC,aAAapB,EAAKC,QAAQ,GAAGL,KAAQsB,KAAc,UAGpE,IAAIG,EAAe7B,KAAKF,KAWxB,OATKK,IAIH0B,SAAsB7B,KAAKL,OAAOkB,UAAWiB,mBAAmBL,EAAIM,YAAa/B,KAAKF,OAEnFkC,QAAQ,8CAA+C,cAGrDH,EAAaI,MAAM,0BAC3B,CAKM/B,qBAIL,aAHMF,KAAKkC,uBACLlC,KAAKH,kBAAkBG,KAAKL,OAAOwC,WAElCnC,IACR"}
|