@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,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.getRouteMatchesWithInvalidLoader = exports.runPreload = void 0;
|
|
16
|
+
const isEqual_1 = __importDefault(require("@shuvi/utils/lib/isEqual"));
|
|
17
|
+
function runPreload(to) {
|
|
18
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
19
|
+
const toMatches = to.matches;
|
|
20
|
+
const preloadList = [];
|
|
21
|
+
toMatches.forEach(match => {
|
|
22
|
+
var _a;
|
|
23
|
+
const preload = (_a = match.route.component) === null || _a === void 0 ? void 0 : _a.preload;
|
|
24
|
+
if (preload && typeof preload === 'function') {
|
|
25
|
+
preloadList.push(preload());
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
yield Promise.all(preloadList);
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
exports.runPreload = runPreload;
|
|
32
|
+
function getRouteMatchesWithInvalidLoader(to, from, loaders) {
|
|
33
|
+
const toMatches = to.matches;
|
|
34
|
+
const fromMatches = from.matches;
|
|
35
|
+
let changedMatches = [];
|
|
36
|
+
/**
|
|
37
|
+
* When a navigation is triggered, loaders should run in the following situation:
|
|
38
|
+
* 1. If a route changed (new route or same dynamic route but different params), its loader and all its children's loaders should run.
|
|
39
|
+
* 2. Last nested route's loader should always run.
|
|
40
|
+
*/
|
|
41
|
+
for (let i = 0; i < toMatches.length; i++) {
|
|
42
|
+
const currentToMatch = toMatches[i];
|
|
43
|
+
const currentFromMatch = fromMatches[i];
|
|
44
|
+
// new route
|
|
45
|
+
if (currentToMatch.route.id !== (currentFromMatch === null || currentFromMatch === void 0 ? void 0 : currentFromMatch.route.id)) {
|
|
46
|
+
changedMatches.push(...toMatches.slice(i));
|
|
47
|
+
break;
|
|
48
|
+
// same route but different params
|
|
49
|
+
}
|
|
50
|
+
else if (!(0, isEqual_1.default)(currentToMatch.params, currentFromMatch === null || currentFromMatch === void 0 ? void 0 : currentFromMatch.params)) {
|
|
51
|
+
changedMatches.push(...toMatches.slice(i));
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
// last nested route (last match)
|
|
55
|
+
if (i === toMatches.length - 1) {
|
|
56
|
+
changedMatches.push(currentToMatch);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
const targets = [];
|
|
60
|
+
changedMatches.forEach(match => {
|
|
61
|
+
const id = match.route.id;
|
|
62
|
+
if (loaders[id] && typeof loaders[id] === 'function') {
|
|
63
|
+
targets.push(match);
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
return targets;
|
|
67
|
+
}
|
|
68
|
+
exports.getRouteMatchesWithInvalidLoader = getRouteMatchesWithInvalidLoader;
|
|
@@ -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,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.createRuntimePlugin = exports.errorModel = void 0;
|
|
18
|
+
__exportStar(require("./helper"), exports);
|
|
19
|
+
__exportStar(require("./routerTypes"), exports);
|
|
20
|
+
__exportStar(require("./router"), exports);
|
|
21
|
+
__exportStar(require("./response"), exports);
|
|
22
|
+
__exportStar(require("./loader"), exports);
|
|
23
|
+
var error_1 = require("./models/error");
|
|
24
|
+
Object.defineProperty(exports, "errorModel", { enumerable: true, get: function () { return error_1.errorModel; } });
|
|
25
|
+
__exportStar(require("./applicationTypes"), exports);
|
|
26
|
+
var lifecycle_1 = require("./lifecycle");
|
|
27
|
+
// fix createRuntimePlugin is not portable end
|
|
28
|
+
Object.defineProperty(exports, "createRuntimePlugin", { enumerable: true, get: function () { return lifecycle_1.createRuntimePlugin; } });
|
|
@@ -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,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.initPlugins = exports.createRuntimePlugin = exports.getManager = void 0;
|
|
13
|
+
const hook_1 = require("@shuvi/hook");
|
|
14
|
+
const init = (0, hook_1.createAsyncParallelHook)();
|
|
15
|
+
const appContext = (0, hook_1.createAsyncSeriesWaterfallHook)();
|
|
16
|
+
const appComponent = (0, hook_1.createAsyncSeriesWaterfallHook)();
|
|
17
|
+
const dispose = (0, hook_1.createAsyncParallelHook)();
|
|
18
|
+
const builtinRuntimePluginHooks = {
|
|
19
|
+
init,
|
|
20
|
+
appComponent,
|
|
21
|
+
appContext,
|
|
22
|
+
dispose
|
|
23
|
+
};
|
|
24
|
+
const getManager = () => (0, hook_1.createHookManager)(builtinRuntimePluginHooks, false);
|
|
25
|
+
exports.getManager = getManager;
|
|
26
|
+
exports.createRuntimePlugin = (0, exports.getManager)().createPlugin;
|
|
27
|
+
const initPlugins = (pluginManager, plugins) => __awaiter(void 0, void 0, void 0, function* () {
|
|
28
|
+
// clear plugin at development mode every time
|
|
29
|
+
if (process.env.NODE_ENV === 'development') {
|
|
30
|
+
pluginManager.clear();
|
|
31
|
+
}
|
|
32
|
+
for (const [plugin, options] of plugins) {
|
|
33
|
+
let parsedOptions;
|
|
34
|
+
if (options) {
|
|
35
|
+
parsedOptions = JSON.parse(options);
|
|
36
|
+
}
|
|
37
|
+
if ((0, hook_1.isPluginInstance)(plugin)) {
|
|
38
|
+
pluginManager.usePlugin(plugin);
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
pluginManager.usePlugin(plugin(parsedOptions));
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
exports.initPlugins = initPlugins;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./loader"), exports);
|
|
18
|
+
__exportStar(require("./loaderManager"), exports);
|
|
19
|
+
__exportStar(require("./types"), exports);
|
|
@@ -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,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.runLoaders = exports.runInParallerAndBail = void 0;
|
|
16
|
+
const invariant_1 = __importDefault(require("@shuvi/utils/lib/invariant"));
|
|
17
|
+
const response_1 = require("../response");
|
|
18
|
+
// todo: add unit tests
|
|
19
|
+
function runInParallerAndBail(fns) {
|
|
20
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
21
|
+
return new Promise(resolve => {
|
|
22
|
+
const resultList = [];
|
|
23
|
+
let total = fns.length;
|
|
24
|
+
let finishedNum = 0;
|
|
25
|
+
let finished = new Map();
|
|
26
|
+
let abort = false;
|
|
27
|
+
const doResolve = () => {
|
|
28
|
+
abort = true;
|
|
29
|
+
resolve(resultList.slice());
|
|
30
|
+
};
|
|
31
|
+
const isAllFinishedBefore = (targetIndex) => {
|
|
32
|
+
for (let i = 0; i < targetIndex; i++) {
|
|
33
|
+
if (!finished.has(i)) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return true;
|
|
38
|
+
};
|
|
39
|
+
// call loaders in parallel
|
|
40
|
+
fns.map((fn, index) => __awaiter(this, void 0, void 0, function* () {
|
|
41
|
+
let result;
|
|
42
|
+
let error;
|
|
43
|
+
try {
|
|
44
|
+
result = yield fn();
|
|
45
|
+
}
|
|
46
|
+
catch (err) {
|
|
47
|
+
error = err;
|
|
48
|
+
}
|
|
49
|
+
if (abort)
|
|
50
|
+
return;
|
|
51
|
+
resultList[index] = {
|
|
52
|
+
error,
|
|
53
|
+
result
|
|
54
|
+
};
|
|
55
|
+
finishedNum += 1;
|
|
56
|
+
finished.set(index, true);
|
|
57
|
+
if (finishedNum === total) {
|
|
58
|
+
doResolve();
|
|
59
|
+
}
|
|
60
|
+
else if (finishedNum === index + 1 && isAllFinishedBefore(index)) {
|
|
61
|
+
if (error) {
|
|
62
|
+
// we can bail
|
|
63
|
+
doResolve();
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}));
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
exports.runInParallerAndBail = runInParallerAndBail;
|
|
71
|
+
function redirectHelper(to, status = 302) {
|
|
72
|
+
throw (0, response_1.redirect)(to, status);
|
|
73
|
+
}
|
|
74
|
+
function errorHelper(msg, statusCode = 500) {
|
|
75
|
+
(0, invariant_1.default)(statusCode >= 400 && statusCode < 600, 'status code should be 4xx and 5xx');
|
|
76
|
+
throw (0, response_1.response)(msg, { status: statusCode });
|
|
77
|
+
}
|
|
78
|
+
function runLoaders(matches, loadersByRouteId, { isServer, query, req, getAppContext }) {
|
|
79
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
80
|
+
if (!matches.length) {
|
|
81
|
+
return [];
|
|
82
|
+
}
|
|
83
|
+
const appContext = getAppContext();
|
|
84
|
+
const createLoader = (match) => () => __awaiter(this, void 0, void 0, function* () {
|
|
85
|
+
const loaderFn = loadersByRouteId[match.route.id];
|
|
86
|
+
let res;
|
|
87
|
+
try {
|
|
88
|
+
const value = yield loaderFn(Object.assign({ isServer, pathname: match.pathname, params: match.params, query: query, redirect: redirectHelper, error: errorHelper, appContext }, (req ? { req } : {})));
|
|
89
|
+
if (value) {
|
|
90
|
+
res = (0, response_1.json)(value);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
if (process.env.NODE_ENV === 'development' && !(0, response_1.isResponse)(error)) {
|
|
95
|
+
console.error(`loader function error of route "${match.route.path}"`);
|
|
96
|
+
console.error(error);
|
|
97
|
+
}
|
|
98
|
+
throw error;
|
|
99
|
+
}
|
|
100
|
+
return res;
|
|
101
|
+
});
|
|
102
|
+
// call loaders in parallel
|
|
103
|
+
const resultList = yield runInParallerAndBail(matches.map(createLoader));
|
|
104
|
+
const loaderDatas = {};
|
|
105
|
+
for (let index = 0; index < resultList.length; index++) {
|
|
106
|
+
const item = resultList[index];
|
|
107
|
+
if (item.error) {
|
|
108
|
+
throw item.error;
|
|
109
|
+
}
|
|
110
|
+
const routeId = matches[index].route.id;
|
|
111
|
+
if (item.result) {
|
|
112
|
+
loaderDatas[routeId] = item.result.data;
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
// allow return undefined
|
|
116
|
+
loaderDatas[routeId] = undefined;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return loaderDatas;
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
exports.runLoaders = runLoaders;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
declare function createLoaderManager(): {
|
|
2
|
+
getAllData(): Record<string, any>;
|
|
3
|
+
getData(id: string): any;
|
|
4
|
+
setDatas(obj: Record<string, any>): void;
|
|
5
|
+
subscribe(cb: Function): () => void;
|
|
6
|
+
clearAllData(): void;
|
|
7
|
+
};
|
|
8
|
+
export declare const getLoaderManager: () => {
|
|
9
|
+
getAllData(): Record<string, any>;
|
|
10
|
+
getData(id: string): any;
|
|
11
|
+
setDatas(obj: Record<string, any>): void;
|
|
12
|
+
subscribe(cb: Function): () => void;
|
|
13
|
+
clearAllData(): void;
|
|
14
|
+
};
|
|
15
|
+
export declare type LoaderManager = ReturnType<typeof createLoaderManager>;
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getLoaderManager = void 0;
|
|
4
|
+
let loaderManager;
|
|
5
|
+
function createLoaderManager() {
|
|
6
|
+
const datas = new Map();
|
|
7
|
+
const subscribers = [];
|
|
8
|
+
return {
|
|
9
|
+
getAllData() {
|
|
10
|
+
let res = {};
|
|
11
|
+
for (const [id, data] of datas.entries()) {
|
|
12
|
+
res[id] = data;
|
|
13
|
+
}
|
|
14
|
+
return res;
|
|
15
|
+
},
|
|
16
|
+
getData(id) {
|
|
17
|
+
if (!datas.has(id)) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
return datas.get(id);
|
|
21
|
+
},
|
|
22
|
+
setDatas(obj) {
|
|
23
|
+
for (const [id, data] of Object.entries(obj)) {
|
|
24
|
+
datas.set(id, data);
|
|
25
|
+
}
|
|
26
|
+
subscribers.forEach(fn => fn());
|
|
27
|
+
},
|
|
28
|
+
// setData(id: string, data: any) {
|
|
29
|
+
// datas.set(id, data);
|
|
30
|
+
// subscribers.forEach(fn => fn());
|
|
31
|
+
// },
|
|
32
|
+
subscribe(cb) {
|
|
33
|
+
subscribers.push(cb);
|
|
34
|
+
return () => {
|
|
35
|
+
const index = subscribers.indexOf(cb);
|
|
36
|
+
if (index >= 0) {
|
|
37
|
+
subscribers.splice(index, 1);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
},
|
|
41
|
+
clearAllData() {
|
|
42
|
+
datas.clear();
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
const getLoaderManager = () => {
|
|
47
|
+
if (loaderManager) {
|
|
48
|
+
return loaderManager;
|
|
49
|
+
}
|
|
50
|
+
loaderManager = createLoaderManager();
|
|
51
|
+
return loaderManager;
|
|
52
|
+
};
|
|
53
|
+
exports.getLoaderManager = getLoaderManager;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { IURLQuery, IURLParams } from '../routerTypes';
|
|
2
|
+
import { IAppContext, IRequest } from '../applicationTypes';
|
|
3
|
+
import { Response } from '../response';
|
|
4
|
+
export interface LoaderContextOptions {
|
|
5
|
+
isServer: boolean;
|
|
6
|
+
req?: IRequest;
|
|
7
|
+
query: IURLQuery;
|
|
8
|
+
getAppContext: () => IAppContext;
|
|
9
|
+
}
|
|
10
|
+
export declare type RedirectFunction = (to: string, status?: number) => any;
|
|
11
|
+
export interface ErrorFunction {
|
|
12
|
+
(): any;
|
|
13
|
+
(msg: string): any;
|
|
14
|
+
(msg: string, statusCode?: number): any;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* route component getInitialProps params `context`
|
|
18
|
+
*/
|
|
19
|
+
export interface IRouteLoaderContext {
|
|
20
|
+
/**
|
|
21
|
+
* is running on server, if server is true, client will be false
|
|
22
|
+
*/
|
|
23
|
+
isServer: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* current url path
|
|
26
|
+
*/
|
|
27
|
+
pathname: string;
|
|
28
|
+
/**
|
|
29
|
+
* the query string of current url
|
|
30
|
+
*
|
|
31
|
+
* eg. url /x?name=xx
|
|
32
|
+
* ```ts
|
|
33
|
+
* {name:xx}
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
query: IURLQuery;
|
|
37
|
+
/**
|
|
38
|
+
* the params of current url
|
|
39
|
+
*
|
|
40
|
+
* eg. url /x?name=xx path /:lng
|
|
41
|
+
* ```ts
|
|
42
|
+
* {lng:x}
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
params: IURLParams;
|
|
46
|
+
/**
|
|
47
|
+
* redirect function
|
|
48
|
+
*
|
|
49
|
+
* ```ts
|
|
50
|
+
* redirect('/target')
|
|
51
|
+
* redirect('/target', 301)
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
redirect: RedirectFunction;
|
|
55
|
+
/**
|
|
56
|
+
* throw error if necessary
|
|
57
|
+
* ```ts
|
|
58
|
+
* error('custom error describe', 502)
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
error: ErrorFunction;
|
|
62
|
+
/**
|
|
63
|
+
* server only
|
|
64
|
+
*/
|
|
65
|
+
req?: IRequest;
|
|
66
|
+
/**
|
|
67
|
+
* Application context object, which is accessiable during the entire lifecycle of application
|
|
68
|
+
*/
|
|
69
|
+
appContext: IAppContext;
|
|
70
|
+
}
|
|
71
|
+
export declare type Loader<T extends {} = {}> = (loaderContenxt: IRouteLoaderContext) => Promise<T | void | undefined> | T | void | undefined;
|
|
72
|
+
export declare type NormalizedLoader = (loaderContenxt: IRouteLoaderContext) => Promise<Response | undefined>;
|
|
73
|
+
export declare type LoaderDataRecord = Record<string, any>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { IErrorState, IError } from '../applicationTypes';
|
|
2
|
+
export declare const errorModel: import("@shuvi/redox").Model<"error", IErrorState, {}, {
|
|
3
|
+
setError(_state: IErrorState, error?: IError): {
|
|
4
|
+
error: IError | undefined;
|
|
5
|
+
};
|
|
6
|
+
}, {
|
|
7
|
+
error(payload?: IError): void;
|
|
8
|
+
clear(): void;
|
|
9
|
+
}, {
|
|
10
|
+
getError(): IError | undefined;
|
|
11
|
+
hasError(): boolean;
|
|
12
|
+
}>;
|
|
13
|
+
export declare type ErrorModel = typeof errorModel;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.errorModel = void 0;
|
|
4
|
+
const redox_1 = require("@shuvi/redox");
|
|
5
|
+
const constants_1 = require("@shuvi/shared/lib/constants");
|
|
6
|
+
const DEFAULT_ERRORSTATE = {
|
|
7
|
+
error: undefined
|
|
8
|
+
};
|
|
9
|
+
exports.errorModel = (0, redox_1.defineModel)({
|
|
10
|
+
name: 'error',
|
|
11
|
+
state: DEFAULT_ERRORSTATE,
|
|
12
|
+
reducers: {
|
|
13
|
+
setError(_state, error) {
|
|
14
|
+
return Object.assign(Object.assign({}, _state), { error: error });
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
actions: {
|
|
18
|
+
error(payload) {
|
|
19
|
+
this.setError(payload || constants_1.SHUVI_ERROR.APP_ERROR);
|
|
20
|
+
},
|
|
21
|
+
clear() {
|
|
22
|
+
if (this.hasError) {
|
|
23
|
+
this.setError(undefined);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
views: {
|
|
28
|
+
getError() {
|
|
29
|
+
return this.error;
|
|
30
|
+
},
|
|
31
|
+
hasError() {
|
|
32
|
+
return typeof this.error !== 'undefined';
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
});
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
declare type HeaderRecord = Record<string, string>;
|
|
2
|
+
declare type HeaderArray = [string, string][];
|
|
3
|
+
export interface ResponseOptions {
|
|
4
|
+
status?: number;
|
|
5
|
+
statusText?: string;
|
|
6
|
+
headers?: HeaderRecord;
|
|
7
|
+
}
|
|
8
|
+
declare class Headers {
|
|
9
|
+
private _map;
|
|
10
|
+
constructor(init?: HeaderRecord | HeaderArray);
|
|
11
|
+
append(name: string, value: string): void;
|
|
12
|
+
delete(name: string): void;
|
|
13
|
+
get(name: string): string | null;
|
|
14
|
+
has(name: string): boolean;
|
|
15
|
+
set(name: string, value: string): void;
|
|
16
|
+
forEach(callback: (value: string, name: string, t: this) => void, thisArg?: any): void;
|
|
17
|
+
keys(): {
|
|
18
|
+
next: () => {
|
|
19
|
+
done: boolean;
|
|
20
|
+
value: any;
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
value(): {
|
|
24
|
+
next: () => {
|
|
25
|
+
done: boolean;
|
|
26
|
+
value: any;
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
entries(): {
|
|
30
|
+
next: () => {
|
|
31
|
+
done: boolean;
|
|
32
|
+
value: any;
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
export declare type ResponseType = 'text' | 'json' | 'redirect' | 'plain';
|
|
37
|
+
export interface Response {
|
|
38
|
+
readonly data: string;
|
|
39
|
+
readonly status: number;
|
|
40
|
+
readonly statusText: string;
|
|
41
|
+
readonly headers: Headers;
|
|
42
|
+
}
|
|
43
|
+
export declare const isResponse: (obj: any) => obj is Response;
|
|
44
|
+
export declare const isJson: (obj: any) => obj is Response;
|
|
45
|
+
export declare const isText: (obj: any) => obj is Response;
|
|
46
|
+
export declare const isRedirect: (obj: any) => obj is Response;
|
|
47
|
+
export declare function response(data: any, options?: ResponseOptions): Response;
|
|
48
|
+
export declare function json(data: any): Response;
|
|
49
|
+
export declare function text(data: string, options?: ResponseOptions): Response;
|
|
50
|
+
export declare function redirect(to: string, status?: number): Response;
|
|
51
|
+
export {};
|