@ovine/core
Version:
Build flexible admin system with json.
181 lines (180 loc) • 6.46 kB
JavaScript
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
/* eslint-disable max-classes-per-file */
import { createBrowserHistory } from 'history';
import { defaultsDeep, get, isFunction, merge, set } from 'lodash';
import { defaultEnvMode, rootRoute, storage, publicUrl } from "../constants";
import { Request } from "../utils/request";
import { setGlobal } from "../utils/store";
import { AppTheme } from "./theme";
let source = {};
const initConfig = {
// TODO: 处理某些请夸下的多实例切换,而不是全局唯一实例
request: new Request(),
theme: new AppTheme(),
styled: {
globalStyle: '',
},
env: {
default: {
mode: defaultEnvMode,
domains: {
api: 'http://site-api.com',
},
},
},
constants: {
routePrefix: publicUrl.startsWith('/') ? publicUrl : rootRoute,
toastDuration: 1200,
rootLimitFlag: '*',
enableBackTop: false,
notFound: {
route: '/404',
pagePath: '',
},
},
entry: [
{
type: 'route',
path: rootRoute,
},
],
amis: {
affixOffsetTop: 50,
},
// 异步数据容器
asyncPage: {
schema: {},
preset: {},
mock: {}, // {path: mockSource} // 页面mock来源
},
hook: {},
};
function checkAppGetter(key, value) {
switch (key) {
case 'theme':
if (!(value instanceof AppTheme)) {
throw new Error('You should register theme with AppTheme instance.');
}
break;
case 'requestFunc':
if (!(value instanceof Request)) {
throw new Error('You should register request with Request instance.');
}
break;
default:
}
}
class AppProxy {
constructor() {
const that = this;
const proxy = new Proxy(that, {
get(_, key) {
const value = key in that ? that[key] : get(source, key) || get(initConfig, key);
return value;
},
});
return proxy;
}
}
// TODO: 允许 APP 多次重复创建
class App extends AppProxy {
constructor() {
super(...arguments);
this.routePrefix = rootRoute;
}
create(appConfig) {
var _a, _b, _c;
return __awaiter(this, void 0, void 0, function* () {
this.initState();
const prevBaseUrl = get(source, 'constants.routePrefix') || rootRoute;
// 等待 beforeCreate hook执行完成
if ((_a = appConfig.hook) === null || _a === void 0 ? void 0 : _a.beforeCreate) {
yield appConfig.hook.beforeCreate.bind(this, this, appConfig)();
}
// 合并参数
source = merge(initConfig, appConfig);
this.routePrefix = this.getBaseUrl((_b = appConfig.constants) === null || _b === void 0 ? void 0 : _b.routePrefix);
set(source, 'constants.routePrefix', this.routePrefix);
if (this.checkBaseUrl(prevBaseUrl, this.routePrefix)) {
this.createRouterHistory();
}
if (source.env) {
this.setEnv(source.env);
}
if (source.request) {
this.setRequest(source.request);
}
// 等待 afterCreated hook执行完成
if ((_c = source.hook) === null || _c === void 0 ? void 0 : _c.afterCreated) {
yield source.hook.afterCreated.bind(this, this, source)();
}
});
}
createRouterHistory() {
this.routerHistory = createBrowserHistory(this.routePrefix === rootRoute
? undefined
: {
basename: this.routePrefix.slice(0, -1),
});
}
initState() {
// 非 热更新模式下,每次创建,将清除原有数据
if (!process.env.HOT) {
source = {};
this.routePrefix = rootRoute;
this.routerHistory = undefined;
}
}
getBaseUrl(urlGen) {
if (isFunction(urlGen)) {
return urlGen() || rootRoute;
}
return typeof urlGen === 'string' ? urlGen : rootRoute;
}
checkBaseUrl(prevBaseUrl, routePrefix) {
if (typeof routePrefix !== 'string' ||
routePrefix.substr(-1) !== rootRoute ||
routePrefix[0] !== rootRoute) {
throw new Error(`routePrefix: "${routePrefix}" is not allowed. The "routePrefix" must be string startWith "/" and endWith "/". eg: "/subPath/"`);
}
if (this.routerHistory && routePrefix !== prevBaseUrl) {
window.location.href = routePrefix;
}
return !this.routerHistory;
}
setEnv(value) {
const mode = process.env.ENV || defaultEnvMode;
const isMock = process.env.MOCK;
const isRelease = process.env.NODE_ENV === 'production' && get(value, `${mode}.isProd`);
const env = defaultsDeep({
isMock,
mode,
}, value[mode], {
isRelease,
}, value.default, initConfig.env.default);
set(source, 'env', env);
}
setRequest(requestIns) {
const initEnv = initConfig.env.default;
checkAppGetter('requestFunc', requestIns);
// 设置 request 环境变量
const env = source.env || initEnv;
requestIns.setConfig({
isMock: env.isMock && !env.isRelease,
domains: env.domains,
});
const requestHandle = requestIns.request.bind(requestIns);
requestHandle.getUrlByOption = requestIns.getUrlByOption.bind(requestIns);
set(source, 'request', requestHandle);
}
}
export const app = new App();
setGlobal(storage.appInstance, app);