@fengmk2 感谢大佬回复,下面是我的一个现状还原和实现的过程:
在项目配置文件中添加一个symbol指向的自定义配置(SYMBOL_PERMISSION):
// config/config.local.ts
import { EggAppConfig, PowerPartial } from 'egg';
import { SYMBOL_PERMISSION } from '../utils/constants'; // export const SYMBOL_PERMISSION = Symbol('Middleware#permission');
export default (appInfo) => {
const config: PowerPartial<EggAppConfig> = {};
config.security = {
csrf: {
enable: false,
ignoreJSON: true,
},
domainWhiteList: ['*']
};
const bizConfig = {
permission: {
enable: true,
whitelist: ['simpul']
},
// 自定义配置
[SYMBOL_PERMISSION]: {
permission: {
msg: 'local',
author: 'simpul'
}
}
};
return {
...config,
...bizConfig,
};
};
期望在我自己实现的中间件permission中访问到对应配置项,但是结果返回undefined:
// app/middleware/permission.ts
import { Context } from 'egg';
import { SYMBOL_PERMISSION } from '../../utils/constants';
export default function permission(): any {
return async (ctx: Context, next: () => Promise<any>) => {
const config = ctx.app.config.permission;
console.log((ctx.app.config as any)[SYMBOL_PERMISSION]);// 这里ctx.app.config丢失SYMBOL_PERMISSION属性, 返回undefined
if (config?.enable) {
if (!config.whitelist.includes(ctx.user.nick)) {
// 没有权限
ctx.status = 403;
ctx.body = {
code: 403,
message: 'You do not have permission',
};
return;
}
}
return await next();
};
}
发现需要补充extend2模块拷贝symbol的能力,这里我参考了lodash模块深拷贝的实现改了下源码:
// node_modules/extend2/index.js
'use strict';
var hasOwn = Object.prototype.hasOwnProperty;
var toStr = Object.prototype.toString;
var propertyIsEnumerable = Object.prototype.propertyIsEnumerable;
var nativeGetSymbols = Object.getOwnPropertySymbols;
var isPlainObject = function isPlainObject(obj) {
if (!obj || toStr.call(obj) !== '[object Object]') {
return false;
}
var hasOwnConstructor = hasOwn.call(obj, 'constructor');
var hasIsPrototypeOf = obj.constructor && obj.constructor.prototype && hasOwn.call(obj.constructor.prototype, 'isPrototypeOf');
// Not own constructor property must be Object
if (obj.constructor && !hasOwnConstructor && !hasIsPrototypeOf) {
return false;
}
// Own properties are enumerated firstly, so to speed up,
// if last one is own, then all properties are own.
var key;
for (key in obj) { /**/ }
return typeof key === 'undefined' || hasOwn.call(obj, key);
};
var getSymbols = function getSymbols(object) {
if (object == null) {
return [];
}
object = Object(object);
return nativeGetSymbols(object).filter((symbol) => propertyIsEnumerable.call(object, symbol))
}
var handleCopy = function handleCopy(target, options, name, deep) {
var src, copy, clone;
src = target[name];
copy = options[name];
// Prevent never-ending loop
if (target === copy) return;
// Recurse if we're merging plain objects
if (deep && copy && isPlainObject(copy)) {
clone = src && isPlainObject(src) ? src : {};
// Never move original objects, clone them
target[name] = extend(deep, clone, copy);
// Don't bring in undefined values
} else if (typeof copy !== 'undefined') {
target[name] = copy;
}
};
var extend = function extend() {
var options, name;
var target = arguments[0];
var i = 1;
var length = arguments.length;
var deep = false;
// Handle a deep copy situation
if (typeof target === 'boolean') {
deep = target;
target = arguments[1] || {};
// skip the boolean and the target
i = 2;
} else if ((typeof target !== 'object' && typeof target !== 'function') || target == null) {
target = {};
}
for (; i < length; ++i) {
options = arguments[i];
// Only deal with non-null/undefined values
if (options == null) continue;
// Extend the base object
for (name in options) {
if (name === '__proto__') continue;
handleCopy(target, options, name, deep);
}
// handle symbol
var symbols = getSymbols(options);
for (const symbol of symbols) {
handleCopy(target, options, symbol, deep);
}
}
// Return the modified object
return target;
};
module.exports = extend;
然后再次访问就发现可以拿到配置项了:
console.log((ctx.app.config as any)[SYMBOL_PERMISSION]); // { permission: { msg: 'local', author: 'simpul' } }