@shuvi/platform-shared 1.0.0-rc.0
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/esm/shared/application.d.ts +82 -0
- package/esm/shared/application.js +87 -0
- package/esm/shared/applicationTypes.d.ts +45 -0
- package/esm/shared/applicationTypes.js +1 -0
- package/esm/shared/helper/getAppData.d.ts +20 -0
- package/esm/shared/helper/getAppData.js +26 -0
- package/esm/shared/helper/getFilesOfRoute.d.ts +10 -0
- package/esm/shared/helper/getFilesOfRoute.js +30 -0
- package/esm/shared/helper/getPageData.d.ts +1 -0
- package/esm/shared/helper/getPageData.js +13 -0
- package/esm/shared/helper/getPublicPath.d.ts +1 -0
- package/esm/shared/helper/getPublicPath.js +6 -0
- package/esm/shared/helper/index.d.ts +5 -0
- package/esm/shared/helper/index.js +5 -0
- package/esm/shared/helper/router.d.ts +4 -0
- package/esm/shared/helper/router.js +60 -0
- package/esm/shared/index.d.ts +9 -0
- package/esm/shared/index.js +10 -0
- package/esm/shared/lifecycle.d.ts +46 -0
- package/esm/shared/lifecycle.js +40 -0
- package/esm/shared/loader/index.d.ts +3 -0
- package/esm/shared/loader/index.js +3 -0
- package/esm/shared/loader/loader.d.ts +9 -0
- package/esm/shared/loader/loader.js +114 -0
- package/esm/shared/loader/loaderManager.d.ts +16 -0
- package/esm/shared/loader/loaderManager.js +49 -0
- package/esm/shared/loader/types.d.ts +73 -0
- package/esm/shared/loader/types.js +1 -0
- package/esm/shared/models/error.d.ts +13 -0
- package/esm/shared/models/error.js +32 -0
- package/esm/shared/response.d.ts +51 -0
- package/esm/shared/response.js +126 -0
- package/esm/shared/router.d.ts +1 -0
- package/esm/shared/router.js +1 -0
- package/esm/shared/routerTypes.d.ts +28 -0
- package/esm/shared/routerTypes.js +1 -0
- package/esm/shared/shuvi-singleton-runtimeConfig.d.ts +12 -0
- package/esm/shared/shuvi-singleton-runtimeConfig.js +19 -0
- package/esm/shuvi-app/application.d.ts +4 -0
- package/esm/shuvi-app/application.js +34 -0
- package/esm/shuvi-app/shared.d.ts +1 -0
- package/esm/shuvi-app/shared.js +1 -0
- package/esm/shuvi-app/shuvi-runtime-app.d.ts +14 -0
- package/esm/shuvi-app/shuvi-runtime-app.js +1 -0
- package/esm/shuvi-app/shuvi-runtime-index.d.ts +10 -0
- package/esm/shuvi-app/shuvi-runtime-index.js +9 -0
- package/lib/node/index.d.ts +2 -0
- package/lib/node/index.js +18 -0
- package/lib/node/paths.d.ts +3 -0
- package/lib/node/paths.js +12 -0
- package/lib/node/platform/index.d.ts +16 -0
- package/lib/node/platform/index.js +23 -0
- package/lib/node/platform/plugins/main/hooks.d.ts +9 -0
- package/lib/node/platform/plugins/main/hooks.js +12 -0
- package/lib/node/platform/plugins/main/index.d.ts +16 -0
- package/lib/node/platform/plugins/main/index.js +32 -0
- package/lib/node/platform/plugins/main/shuvi-app.d.ts +8 -0
- package/lib/node/platform/plugins/main/shuvi-app.js +2 -0
- package/lib/node/platform/runtimeFiles.d.ts +11 -0
- package/lib/node/platform/runtimeFiles.js +47 -0
- package/lib/node/project/file-presets/files/app/core/entry.js.d.ts +3 -0
- package/lib/node/project/file-presets/files/app/core/entry.js.js +52 -0
- package/lib/node/project/file-presets/files/app/core/error.js.d.ts +2 -0
- package/lib/node/project/file-presets/files/app/core/error.js.js +9 -0
- package/lib/node/project/file-presets/files/app/core/platform.js.d.ts +3 -0
- package/lib/node/project/file-presets/files/app/core/platform.js.js +9 -0
- package/lib/node/project/file-presets/files/app/core/polyfill.js.d.ts +3 -0
- package/lib/node/project/file-presets/files/app/core/polyfill.js.js +6 -0
- package/lib/node/project/file-presets/files/app/core/runtimeConfig.js.d.ts +3 -0
- package/lib/node/project/file-presets/files/app/core/runtimeConfig.js.js +12 -0
- package/lib/node/project/file-presets/files/app/core/setPublicRuntimeConfig.js.d.ts +2 -0
- package/lib/node/project/file-presets/files/app/core/setPublicRuntimeConfig.js.js +7 -0
- package/lib/node/project/file-presets/files/app/core/setRuntimeConfig.js.d.ts +2 -0
- package/lib/node/project/file-presets/files/app/core/setRuntimeConfig.js.js +7 -0
- package/lib/node/project/file-presets/files/app/user/app.js.d.ts +3 -0
- package/lib/node/project/file-presets/files/app/user/app.js.js +15 -0
- package/lib/node/project/file-presets/files/app/user/error.js.d.ts +3 -0
- package/lib/node/project/file-presets/files/app/user/error.js.js +15 -0
- package/lib/node/project/file-presets/index.d.ts +4 -0
- package/lib/node/project/file-presets/index.js +58 -0
- package/lib/node/project/index.d.ts +2 -0
- package/lib/node/project/index.js +7 -0
- package/lib/node/project/projectContext.d.ts +13 -0
- package/lib/node/project/projectContext.js +16 -0
- package/lib/node/route/helpers.d.ts +20 -0
- package/lib/node/route/helpers.js +199 -0
- package/lib/node/route/index.d.ts +1 -0
- package/lib/node/route/index.js +7 -0
- package/lib/node/route/route.d.ts +37 -0
- package/lib/node/route/route.js +212 -0
- package/lib/shared/application.d.ts +82 -0
- package/lib/shared/application.js +91 -0
- package/lib/shared/applicationTypes.d.ts +45 -0
- package/lib/shared/applicationTypes.js +2 -0
- package/lib/shared/helper/getAppData.d.ts +20 -0
- package/lib/shared/helper/getAppData.js +30 -0
- package/lib/shared/helper/getFilesOfRoute.d.ts +10 -0
- package/lib/shared/helper/getFilesOfRoute.js +34 -0
- package/lib/shared/helper/getPageData.d.ts +1 -0
- package/lib/shared/helper/getPageData.js +17 -0
- package/lib/shared/helper/getPublicPath.d.ts +1 -0
- package/lib/shared/helper/getPublicPath.js +10 -0
- package/lib/shared/helper/index.d.ts +5 -0
- package/lib/shared/helper/index.js +24 -0
- package/lib/shared/helper/router.d.ts +4 -0
- package/lib/shared/helper/router.js +68 -0
- package/lib/shared/index.d.ts +9 -0
- package/lib/shared/index.js +28 -0
- package/lib/shared/lifecycle.d.ts +46 -0
- package/lib/shared/lifecycle.js +45 -0
- package/lib/shared/loader/index.d.ts +3 -0
- package/lib/shared/loader/index.js +19 -0
- package/lib/shared/loader/loader.d.ts +9 -0
- package/lib/shared/loader/loader.js +122 -0
- package/lib/shared/loader/loaderManager.d.ts +16 -0
- package/lib/shared/loader/loaderManager.js +53 -0
- package/lib/shared/loader/types.d.ts +73 -0
- package/lib/shared/loader/types.js +2 -0
- package/lib/shared/models/error.d.ts +13 -0
- package/lib/shared/models/error.js +35 -0
- package/lib/shared/response.d.ts +51 -0
- package/lib/shared/response.js +134 -0
- package/lib/shared/router.d.ts +1 -0
- package/lib/shared/router.js +11 -0
- package/lib/shared/routerTypes.d.ts +28 -0
- package/lib/shared/routerTypes.js +2 -0
- package/lib/shared/shuvi-singleton-runtimeConfig.d.ts +12 -0
- package/lib/shared/shuvi-singleton-runtimeConfig.js +26 -0
- package/package.json +90 -0
- package/shuvi-app-extensions.d.ts +58 -0
- package/template/document.ejs +10 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { IRouter } from './routerTypes';
|
|
2
|
+
import { IStoreManager, IApplication, IAppContext, IApplicationOptions, IRerenderConfig } from './applicationTypes';
|
|
3
|
+
export declare class Application {
|
|
4
|
+
private _error;
|
|
5
|
+
private _router;
|
|
6
|
+
private _appComponent;
|
|
7
|
+
private _pluginManager;
|
|
8
|
+
private _context;
|
|
9
|
+
private _storeManager;
|
|
10
|
+
constructor(options: IApplicationOptions);
|
|
11
|
+
get router(): IRouter<any>;
|
|
12
|
+
get context(): IAppContext;
|
|
13
|
+
get pluginManager(): import("@shuvi/hook").HookManager<import("./lifecycle").BuiltInRuntimePluginHooks, void, import("@shuvi/runtime").CustomRuntimePluginHooks>;
|
|
14
|
+
get appComponent(): any;
|
|
15
|
+
get error(): {
|
|
16
|
+
$state: import("./applicationTypes").IErrorState;
|
|
17
|
+
$set: (state: import("@shuvi/redox").State) => void;
|
|
18
|
+
$modify: (modifier: (state: import("./applicationTypes").IErrorState) => void) => void;
|
|
19
|
+
$patch: (partState: import("@shuvi/redox").ObjectState) => void;
|
|
20
|
+
$actions: {
|
|
21
|
+
setError: (payload?: import("./applicationTypes").IError | undefined) => import("@shuvi/redox").Action<import("./applicationTypes").IError | undefined>;
|
|
22
|
+
} & {
|
|
23
|
+
error: (payload?: import("./applicationTypes").IError | undefined) => void;
|
|
24
|
+
clear: () => void;
|
|
25
|
+
} & {
|
|
26
|
+
[X: string]: never;
|
|
27
|
+
[X: number]: never;
|
|
28
|
+
[X: symbol]: never;
|
|
29
|
+
};
|
|
30
|
+
$views: import("@shuvi/redox").RedoxViews<({
|
|
31
|
+
getError(): import("./applicationTypes").IError | undefined;
|
|
32
|
+
hasError(): boolean;
|
|
33
|
+
} & ThisType<import("./applicationTypes").IErrorState & {
|
|
34
|
+
$state: import("./applicationTypes").IErrorState;
|
|
35
|
+
} & import("@shuvi/redox").RedoxViews<{
|
|
36
|
+
getError(): import("./applicationTypes").IError | undefined;
|
|
37
|
+
hasError(): boolean;
|
|
38
|
+
}> & {
|
|
39
|
+
$dep: {} & {} & {};
|
|
40
|
+
}>) | undefined>;
|
|
41
|
+
$createSelector: <TReturn>(selector: import("@shuvi/redox").ISelector<import("@shuvi/redox").Model<"error", import("./applicationTypes").IErrorState, {}, {
|
|
42
|
+
setError(_state: import("./applicationTypes").IErrorState, error?: import("./applicationTypes").IError | undefined): {
|
|
43
|
+
error: import("./applicationTypes").IError | undefined;
|
|
44
|
+
};
|
|
45
|
+
}, {
|
|
46
|
+
error(payload?: import("./applicationTypes").IError | undefined): void;
|
|
47
|
+
clear(): void;
|
|
48
|
+
}, {
|
|
49
|
+
getError(): import("./applicationTypes").IError | undefined;
|
|
50
|
+
hasError(): boolean;
|
|
51
|
+
}>, TReturn>) => (() => TReturn) & {
|
|
52
|
+
clearCache: () => void;
|
|
53
|
+
};
|
|
54
|
+
} & import("@shuvi/redox").RedoxViews<{
|
|
55
|
+
getError(): import("./applicationTypes").IError | undefined;
|
|
56
|
+
hasError(): boolean;
|
|
57
|
+
} & ThisType<import("./applicationTypes").IErrorState & {
|
|
58
|
+
$state: import("./applicationTypes").IErrorState;
|
|
59
|
+
} & import("@shuvi/redox").RedoxViews<{
|
|
60
|
+
getError(): import("./applicationTypes").IError | undefined;
|
|
61
|
+
hasError(): boolean;
|
|
62
|
+
}> & {
|
|
63
|
+
$dep: {} & {} & {};
|
|
64
|
+
}>> & {
|
|
65
|
+
setError: (payload?: import("./applicationTypes").IError | undefined) => import("@shuvi/redox").Action<import("./applicationTypes").IError | undefined>;
|
|
66
|
+
} & {
|
|
67
|
+
error: (payload?: import("./applicationTypes").IError | undefined) => void;
|
|
68
|
+
clear: () => void;
|
|
69
|
+
} & {
|
|
70
|
+
[X: string]: never;
|
|
71
|
+
[X: number]: never;
|
|
72
|
+
[X: symbol]: never;
|
|
73
|
+
};
|
|
74
|
+
init(): Promise<void>;
|
|
75
|
+
get storeManager(): IStoreManager;
|
|
76
|
+
updateComponents({ AppComponent }?: IRerenderConfig): Promise<void>;
|
|
77
|
+
dispose(): Promise<void>;
|
|
78
|
+
private _initPlugin;
|
|
79
|
+
private _initAppContext;
|
|
80
|
+
private _initAppComponent;
|
|
81
|
+
getPublicAPI(): IApplication;
|
|
82
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { getManager } from './lifecycle';
|
|
11
|
+
import { initPlugins } from './lifecycle';
|
|
12
|
+
import { redox } from '@shuvi/redox';
|
|
13
|
+
import { errorModel } from './models/error';
|
|
14
|
+
export class Application {
|
|
15
|
+
constructor(options) {
|
|
16
|
+
this._router = options.router;
|
|
17
|
+
this._context = {};
|
|
18
|
+
this._storeManager = redox({ initialState: options.initialState });
|
|
19
|
+
this._error = this._storeManager.get(errorModel);
|
|
20
|
+
this._appComponent = options.AppComponent;
|
|
21
|
+
this._pluginManager = getManager();
|
|
22
|
+
initPlugins(this._pluginManager, options.plugins || []);
|
|
23
|
+
}
|
|
24
|
+
get router() {
|
|
25
|
+
return this._router;
|
|
26
|
+
}
|
|
27
|
+
get context() {
|
|
28
|
+
return this._context;
|
|
29
|
+
}
|
|
30
|
+
get pluginManager() {
|
|
31
|
+
return this._pluginManager;
|
|
32
|
+
}
|
|
33
|
+
get appComponent() {
|
|
34
|
+
return this._appComponent;
|
|
35
|
+
}
|
|
36
|
+
get error() {
|
|
37
|
+
return this._error;
|
|
38
|
+
}
|
|
39
|
+
init() {
|
|
40
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
41
|
+
yield this._initPlugin();
|
|
42
|
+
yield this._initAppContext();
|
|
43
|
+
yield this._initAppComponent();
|
|
44
|
+
this._router.init();
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
get storeManager() {
|
|
48
|
+
return this._storeManager;
|
|
49
|
+
}
|
|
50
|
+
updateComponents({ AppComponent } = {}) {
|
|
51
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
52
|
+
if (AppComponent && AppComponent !== this._appComponent) {
|
|
53
|
+
this._appComponent = AppComponent;
|
|
54
|
+
}
|
|
55
|
+
yield this._initAppComponent();
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
dispose() {
|
|
59
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
60
|
+
yield this._pluginManager.runner.dispose();
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
_initPlugin() {
|
|
64
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
65
|
+
yield this._pluginManager.runner.init();
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
_initAppContext() {
|
|
69
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
70
|
+
this._context = (yield this._pluginManager.runner.appContext(this._context));
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
_initAppComponent() {
|
|
74
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
75
|
+
this._appComponent = yield this._pluginManager.runner.appComponent(this._appComponent, this._context);
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
getPublicAPI() {
|
|
79
|
+
return {
|
|
80
|
+
context: this._context,
|
|
81
|
+
router: this._router,
|
|
82
|
+
appComponent: this._appComponent,
|
|
83
|
+
storeManager: this._storeManager,
|
|
84
|
+
error: this._error
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import type { IncomingMessage } from 'http';
|
|
3
|
+
import { IStoreManager } from '@shuvi/redox';
|
|
4
|
+
import { CustomAppContext } from '@shuvi/runtime';
|
|
5
|
+
import { IRouter } from './routerTypes';
|
|
6
|
+
import { IPluginList } from './lifecycle';
|
|
7
|
+
export declare type IRequest = IncomingMessage & {
|
|
8
|
+
[x: string]: any;
|
|
9
|
+
};
|
|
10
|
+
export interface IAppContext extends CustomAppContext {
|
|
11
|
+
[x: string]: unknown;
|
|
12
|
+
}
|
|
13
|
+
export declare type IRerenderConfig = {
|
|
14
|
+
AppComponent?: any;
|
|
15
|
+
};
|
|
16
|
+
export type { IStoreManager };
|
|
17
|
+
export interface IError {
|
|
18
|
+
code?: number;
|
|
19
|
+
message?: string;
|
|
20
|
+
}
|
|
21
|
+
export interface IErrorState {
|
|
22
|
+
error?: IError;
|
|
23
|
+
}
|
|
24
|
+
export declare type IAppState = {
|
|
25
|
+
error?: IErrorState;
|
|
26
|
+
};
|
|
27
|
+
export interface IErrorManager {
|
|
28
|
+
getError: IError | undefined;
|
|
29
|
+
error: (err: IError) => void;
|
|
30
|
+
clear: () => void;
|
|
31
|
+
hasError: boolean;
|
|
32
|
+
}
|
|
33
|
+
export interface IApplication {
|
|
34
|
+
readonly context: IAppContext;
|
|
35
|
+
readonly router: IRouter;
|
|
36
|
+
readonly appComponent: any;
|
|
37
|
+
readonly error: IErrorManager;
|
|
38
|
+
readonly storeManager: IStoreManager;
|
|
39
|
+
}
|
|
40
|
+
export interface IApplicationOptions {
|
|
41
|
+
router: IRouter;
|
|
42
|
+
AppComponent: any;
|
|
43
|
+
initialState?: IAppState;
|
|
44
|
+
plugins?: IPluginList;
|
|
45
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/// <reference lib="dom" />
|
|
2
|
+
export declare type IData = {
|
|
3
|
+
[k: string]: string | number | boolean | undefined | null;
|
|
4
|
+
};
|
|
5
|
+
export declare type IAppData<Data = {}, appState = any> = {
|
|
6
|
+
ssr: boolean;
|
|
7
|
+
runtimeConfig?: Record<string, string>;
|
|
8
|
+
pageData?: {
|
|
9
|
+
[key: string]: any;
|
|
10
|
+
};
|
|
11
|
+
loadersData?: {
|
|
12
|
+
[x: string]: any;
|
|
13
|
+
};
|
|
14
|
+
appState?: appState;
|
|
15
|
+
filesByRoutId: Record<string, string[]>;
|
|
16
|
+
publicPath: string;
|
|
17
|
+
} & {
|
|
18
|
+
[K in keyof Data]: Data[K];
|
|
19
|
+
};
|
|
20
|
+
export declare function getAppData(): IAppData;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/// <reference lib="dom" />
|
|
2
|
+
import { CLIENT_APPDATA_ID } from '@shuvi/shared/lib/constants';
|
|
3
|
+
let appData = null;
|
|
4
|
+
export function getAppData() {
|
|
5
|
+
if (appData) {
|
|
6
|
+
return appData;
|
|
7
|
+
}
|
|
8
|
+
if (typeof window === 'undefined') {
|
|
9
|
+
return {
|
|
10
|
+
ssr: false,
|
|
11
|
+
filesByRoutId: {},
|
|
12
|
+
publicPath: ''
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
const el = document.getElementById(CLIENT_APPDATA_ID);
|
|
16
|
+
if (!el || !el.textContent) {
|
|
17
|
+
return {
|
|
18
|
+
ssr: false,
|
|
19
|
+
pageData: {},
|
|
20
|
+
loadersData: {},
|
|
21
|
+
filesByRoutId: {},
|
|
22
|
+
publicPath: ''
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
return JSON.parse(el.textContent);
|
|
26
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { IRouter, PathRecord } from '../router';
|
|
2
|
+
export declare type RouteFile = {
|
|
3
|
+
id: string;
|
|
4
|
+
url: string;
|
|
5
|
+
};
|
|
6
|
+
export declare type RouteFiles = {
|
|
7
|
+
js: RouteFile[];
|
|
8
|
+
css: RouteFile[];
|
|
9
|
+
};
|
|
10
|
+
export declare function getFilesOfRoute(router: IRouter, to: PathRecord): RouteFiles;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { getAppData } from './getAppData';
|
|
2
|
+
import { getPublicPath } from './getPublicPath';
|
|
3
|
+
export function getFilesOfRoute(router, to) {
|
|
4
|
+
const { filesByRoutId } = getAppData();
|
|
5
|
+
const publicPath = getPublicPath();
|
|
6
|
+
const js = [];
|
|
7
|
+
const css = [];
|
|
8
|
+
const targetRoute = router.match(to);
|
|
9
|
+
targetRoute.forEach(({ route: { id } }) => {
|
|
10
|
+
if (!filesByRoutId[id]) {
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
filesByRoutId[id].map(path => {
|
|
14
|
+
const file = {
|
|
15
|
+
url: `${publicPath}${path}`,
|
|
16
|
+
id
|
|
17
|
+
};
|
|
18
|
+
if (path.endsWith('.js')) {
|
|
19
|
+
js.push(file);
|
|
20
|
+
}
|
|
21
|
+
else if (path.endsWith('.css')) {
|
|
22
|
+
css.push(file);
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
return {
|
|
27
|
+
js,
|
|
28
|
+
css
|
|
29
|
+
};
|
|
30
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function getPageData<T = unknown>(key: string, defaultValue?: T): any;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { getAppData } from './getAppData';
|
|
2
|
+
const hasOwnProperty = Object.prototype.hasOwnProperty;
|
|
3
|
+
export function getPageData(key, defaultValue) {
|
|
4
|
+
if (typeof window === 'undefined') {
|
|
5
|
+
console.warn('"getPageData" should only be called on client-side');
|
|
6
|
+
return defaultValue;
|
|
7
|
+
}
|
|
8
|
+
const { pageData = {} } = getAppData();
|
|
9
|
+
if (!hasOwnProperty.call(pageData, key)) {
|
|
10
|
+
return defaultValue;
|
|
11
|
+
}
|
|
12
|
+
return pageData[key];
|
|
13
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function getPublicPath(): string;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { IRoute, IPageRouteRecord, IRouteMatch } from '../routerTypes';
|
|
2
|
+
import { Loader } from '../loader';
|
|
3
|
+
export declare function runPreload(to: IRoute<IPageRouteRecord>): Promise<void>;
|
|
4
|
+
export declare function getRouteMatchesWithInvalidLoader(to: IRoute<IPageRouteRecord>, from: IRoute<IPageRouteRecord>, loaders: Record<string, Loader>): IRouteMatch<IPageRouteRecord>[];
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import isEqual from '@shuvi/utils/lib/isEqual';
|
|
11
|
+
export function runPreload(to) {
|
|
12
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
13
|
+
const toMatches = to.matches;
|
|
14
|
+
const preloadList = [];
|
|
15
|
+
toMatches.forEach(match => {
|
|
16
|
+
var _a;
|
|
17
|
+
const preload = (_a = match.route.component) === null || _a === void 0 ? void 0 : _a.preload;
|
|
18
|
+
if (preload && typeof preload === 'function') {
|
|
19
|
+
preloadList.push(preload());
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
yield Promise.all(preloadList);
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
export function getRouteMatchesWithInvalidLoader(to, from, loaders) {
|
|
26
|
+
const toMatches = to.matches;
|
|
27
|
+
const fromMatches = from.matches;
|
|
28
|
+
let changedMatches = [];
|
|
29
|
+
/**
|
|
30
|
+
* When a navigation is triggered, loaders should run in the following situation:
|
|
31
|
+
* 1. If a route changed (new route or same dynamic route but different params), its loader and all its children's loaders should run.
|
|
32
|
+
* 2. Last nested route's loader should always run.
|
|
33
|
+
*/
|
|
34
|
+
for (let i = 0; i < toMatches.length; i++) {
|
|
35
|
+
const currentToMatch = toMatches[i];
|
|
36
|
+
const currentFromMatch = fromMatches[i];
|
|
37
|
+
// new route
|
|
38
|
+
if (currentToMatch.route.id !== (currentFromMatch === null || currentFromMatch === void 0 ? void 0 : currentFromMatch.route.id)) {
|
|
39
|
+
changedMatches.push(...toMatches.slice(i));
|
|
40
|
+
break;
|
|
41
|
+
// same route but different params
|
|
42
|
+
}
|
|
43
|
+
else if (!isEqual(currentToMatch.params, currentFromMatch === null || currentFromMatch === void 0 ? void 0 : currentFromMatch.params)) {
|
|
44
|
+
changedMatches.push(...toMatches.slice(i));
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
// last nested route (last match)
|
|
48
|
+
if (i === toMatches.length - 1) {
|
|
49
|
+
changedMatches.push(currentToMatch);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
const targets = [];
|
|
53
|
+
changedMatches.forEach(match => {
|
|
54
|
+
const id = match.route.id;
|
|
55
|
+
if (loaders[id] && typeof loaders[id] === 'function') {
|
|
56
|
+
targets.push(match);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
return targets;
|
|
60
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from './helper';
|
|
2
|
+
export * from './routerTypes';
|
|
3
|
+
export * from './router';
|
|
4
|
+
export * from './response';
|
|
5
|
+
export * from './loader';
|
|
6
|
+
export { errorModel } from './models/error';
|
|
7
|
+
export * from './applicationTypes';
|
|
8
|
+
export type { Application } from './application';
|
|
9
|
+
export { IAppModule, IPluginInstance, BuiltInRuntimePluginHooks, CustomRuntimePluginHooks, RuntimePluginHooks, createRuntimePlugin, RuntimePluginInstance } from './lifecycle';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export * from './helper';
|
|
2
|
+
export * from './routerTypes';
|
|
3
|
+
export * from './router';
|
|
4
|
+
export * from './response';
|
|
5
|
+
export * from './loader';
|
|
6
|
+
export { errorModel } from './models/error';
|
|
7
|
+
export * from './applicationTypes';
|
|
8
|
+
export {
|
|
9
|
+
// fix createRuntimePlugin is not portable end
|
|
10
|
+
createRuntimePlugin } from './lifecycle';
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { IPluginInstance, IPluginHandlers, HookMap } from '@shuvi/hook';
|
|
2
|
+
import { CustomRuntimePluginHooks } from '@shuvi/runtime';
|
|
3
|
+
import { IAppContext } from './applicationTypes';
|
|
4
|
+
export declare type AppComponent = unknown;
|
|
5
|
+
declare const init: import("@shuvi/hook").AsyncParallelHook<void, void, void>;
|
|
6
|
+
declare const appContext: import("@shuvi/hook").AsyncSeriesWaterfallHook<IAppContext, void>;
|
|
7
|
+
declare const appComponent: import("@shuvi/hook").AsyncSeriesWaterfallHook<unknown, IAppContext>;
|
|
8
|
+
declare const dispose: import("@shuvi/hook").AsyncParallelHook<void, void, void>;
|
|
9
|
+
export interface BuiltInRuntimePluginHooks extends HookMap {
|
|
10
|
+
init: typeof init;
|
|
11
|
+
appComponent: typeof appComponent;
|
|
12
|
+
appContext: typeof appContext;
|
|
13
|
+
dispose: typeof dispose;
|
|
14
|
+
}
|
|
15
|
+
export interface RuntimePluginHooks extends BuiltInRuntimePluginHooks, CustomRuntimePluginHooks {
|
|
16
|
+
}
|
|
17
|
+
export declare const getManager: () => import("@shuvi/hook").HookManager<BuiltInRuntimePluginHooks, void, CustomRuntimePluginHooks>;
|
|
18
|
+
export declare const createRuntimePlugin: (pluginHandlers: Partial<import("@shuvi/hook").IPluginHandlersFullMap<BuiltInRuntimePluginHooks & CustomRuntimePluginHooks, void>> & {
|
|
19
|
+
setup?: import("@shuvi/hook").Setup<CustomRuntimePluginHooks> | undefined;
|
|
20
|
+
}, options?: import("@shuvi/hook").PluginOptions | undefined) => IPluginInstance<BuiltInRuntimePluginHooks & CustomRuntimePluginHooks, void>;
|
|
21
|
+
export type { IPluginInstance, CustomRuntimePluginHooks };
|
|
22
|
+
export declare type PluginManager = ReturnType<typeof getManager>;
|
|
23
|
+
export declare type RuntimePluginInstance = IPluginInstance<RuntimePluginHooks, void>;
|
|
24
|
+
export declare type IRuntimePluginConstructor = IPluginHandlers<RuntimePluginHooks, void>;
|
|
25
|
+
export declare type IAppModule = {
|
|
26
|
+
init?: IRuntimePluginConstructor['init'];
|
|
27
|
+
appContext?: IRuntimePluginConstructor['appContext'];
|
|
28
|
+
appComponent?: IRuntimePluginConstructor['appComponent'];
|
|
29
|
+
dispose?: IRuntimePluginConstructor['dispose'];
|
|
30
|
+
};
|
|
31
|
+
declare type SerializedPluginOptions = string;
|
|
32
|
+
export declare type IRuntimePluginOptions = Record<string, unknown>;
|
|
33
|
+
export declare type IRuntimePluginWithOptions = (...params: any[]) => RuntimePluginInstance;
|
|
34
|
+
export declare type IRuntimePlugin = RuntimePluginInstance | IRuntimePluginWithOptions;
|
|
35
|
+
export declare type IPluginModule = {
|
|
36
|
+
plugin: IRuntimePlugin;
|
|
37
|
+
pluginOptions: IRuntimePluginOptions;
|
|
38
|
+
};
|
|
39
|
+
export declare type IPluginRecord = {
|
|
40
|
+
[name: string]: {
|
|
41
|
+
plugin: IRuntimePlugin;
|
|
42
|
+
options: SerializedPluginOptions;
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
export declare type IPluginList = [IRuntimePlugin, SerializedPluginOptions?][];
|
|
46
|
+
export declare const initPlugins: (pluginManager: PluginManager, plugins: IPluginList) => Promise<void>;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { createAsyncParallelHook, createAsyncSeriesWaterfallHook, createHookManager, isPluginInstance } from '@shuvi/hook';
|
|
11
|
+
const init = createAsyncParallelHook();
|
|
12
|
+
const appContext = createAsyncSeriesWaterfallHook();
|
|
13
|
+
const appComponent = createAsyncSeriesWaterfallHook();
|
|
14
|
+
const dispose = createAsyncParallelHook();
|
|
15
|
+
const builtinRuntimePluginHooks = {
|
|
16
|
+
init,
|
|
17
|
+
appComponent,
|
|
18
|
+
appContext,
|
|
19
|
+
dispose
|
|
20
|
+
};
|
|
21
|
+
export const getManager = () => createHookManager(builtinRuntimePluginHooks, false);
|
|
22
|
+
export const { createPlugin: createRuntimePlugin } = getManager();
|
|
23
|
+
export const initPlugins = (pluginManager, plugins) => __awaiter(void 0, void 0, void 0, function* () {
|
|
24
|
+
// clear plugin at development mode every time
|
|
25
|
+
if (process.env.NODE_ENV === 'development') {
|
|
26
|
+
pluginManager.clear();
|
|
27
|
+
}
|
|
28
|
+
for (const [plugin, options] of plugins) {
|
|
29
|
+
let parsedOptions;
|
|
30
|
+
if (options) {
|
|
31
|
+
parsedOptions = JSON.parse(options);
|
|
32
|
+
}
|
|
33
|
+
if (isPluginInstance(plugin)) {
|
|
34
|
+
pluginManager.usePlugin(plugin);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
pluginManager.usePlugin(plugin(parsedOptions));
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { IRouteMatch, IPageRouteRecord } from '../routerTypes';
|
|
2
|
+
import { Loader, LoaderContextOptions, LoaderDataRecord } from './types';
|
|
3
|
+
interface Result<T> {
|
|
4
|
+
error?: unknown;
|
|
5
|
+
result?: T;
|
|
6
|
+
}
|
|
7
|
+
export declare function runInParallerAndBail<T>(fns: Array<() => Promise<T> | T>): Promise<Result<T>[]>;
|
|
8
|
+
export declare function runLoaders(matches: IRouteMatch<IPageRouteRecord>[], loadersByRouteId: Record<string, Loader>, { isServer, query, req, getAppContext }: LoaderContextOptions): Promise<LoaderDataRecord>;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import invariant from '@shuvi/utils/lib/invariant';
|
|
11
|
+
import { json as createJson, redirect as createRedirect, response, isResponse } from '../response';
|
|
12
|
+
// todo: add unit tests
|
|
13
|
+
export function runInParallerAndBail(fns) {
|
|
14
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
15
|
+
return new Promise(resolve => {
|
|
16
|
+
const resultList = [];
|
|
17
|
+
let total = fns.length;
|
|
18
|
+
let finishedNum = 0;
|
|
19
|
+
let finished = new Map();
|
|
20
|
+
let abort = false;
|
|
21
|
+
const doResolve = () => {
|
|
22
|
+
abort = true;
|
|
23
|
+
resolve(resultList.slice());
|
|
24
|
+
};
|
|
25
|
+
const isAllFinishedBefore = (targetIndex) => {
|
|
26
|
+
for (let i = 0; i < targetIndex; i++) {
|
|
27
|
+
if (!finished.has(i)) {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return true;
|
|
32
|
+
};
|
|
33
|
+
// call loaders in parallel
|
|
34
|
+
fns.map((fn, index) => __awaiter(this, void 0, void 0, function* () {
|
|
35
|
+
let result;
|
|
36
|
+
let error;
|
|
37
|
+
try {
|
|
38
|
+
result = yield fn();
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
error = err;
|
|
42
|
+
}
|
|
43
|
+
if (abort)
|
|
44
|
+
return;
|
|
45
|
+
resultList[index] = {
|
|
46
|
+
error,
|
|
47
|
+
result
|
|
48
|
+
};
|
|
49
|
+
finishedNum += 1;
|
|
50
|
+
finished.set(index, true);
|
|
51
|
+
if (finishedNum === total) {
|
|
52
|
+
doResolve();
|
|
53
|
+
}
|
|
54
|
+
else if (finishedNum === index + 1 && isAllFinishedBefore(index)) {
|
|
55
|
+
if (error) {
|
|
56
|
+
// we can bail
|
|
57
|
+
doResolve();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}));
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
function redirectHelper(to, status = 302) {
|
|
65
|
+
throw createRedirect(to, status);
|
|
66
|
+
}
|
|
67
|
+
function errorHelper(msg, statusCode = 500) {
|
|
68
|
+
invariant(statusCode >= 400 && statusCode < 600, 'status code should be 4xx and 5xx');
|
|
69
|
+
throw response(msg, { status: statusCode });
|
|
70
|
+
}
|
|
71
|
+
export function runLoaders(matches, loadersByRouteId, { isServer, query, req, getAppContext }) {
|
|
72
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
73
|
+
if (!matches.length) {
|
|
74
|
+
return [];
|
|
75
|
+
}
|
|
76
|
+
const appContext = getAppContext();
|
|
77
|
+
const createLoader = (match) => () => __awaiter(this, void 0, void 0, function* () {
|
|
78
|
+
const loaderFn = loadersByRouteId[match.route.id];
|
|
79
|
+
let res;
|
|
80
|
+
try {
|
|
81
|
+
const value = yield loaderFn(Object.assign({ isServer, pathname: match.pathname, params: match.params, query: query, redirect: redirectHelper, error: errorHelper, appContext }, (req ? { req } : {})));
|
|
82
|
+
if (value) {
|
|
83
|
+
res = createJson(value);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
if (process.env.NODE_ENV === 'development' && !isResponse(error)) {
|
|
88
|
+
console.error(`loader function error of route "${match.route.path}"`);
|
|
89
|
+
console.error(error);
|
|
90
|
+
}
|
|
91
|
+
throw error;
|
|
92
|
+
}
|
|
93
|
+
return res;
|
|
94
|
+
});
|
|
95
|
+
// call loaders in parallel
|
|
96
|
+
const resultList = yield runInParallerAndBail(matches.map(createLoader));
|
|
97
|
+
const loaderDatas = {};
|
|
98
|
+
for (let index = 0; index < resultList.length; index++) {
|
|
99
|
+
const item = resultList[index];
|
|
100
|
+
if (item.error) {
|
|
101
|
+
throw item.error;
|
|
102
|
+
}
|
|
103
|
+
const routeId = matches[index].route.id;
|
|
104
|
+
if (item.result) {
|
|
105
|
+
loaderDatas[routeId] = item.result.data;
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
// allow return undefined
|
|
109
|
+
loaderDatas[routeId] = undefined;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return loaderDatas;
|
|
113
|
+
});
|
|
114
|
+
}
|