ts-api-core
Version:
Nodejs api framework core
906 lines • 36.7 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.IocContainer = exports.config = exports.ConfigScope = exports.injectWrapper = exports.inject = exports.InjectClassParam = exports.Route = exports.Wrapper = exports.Service = exports.Provide = exports.BaseClass = exports.TSDesignType = exports.ScopeEnum = exports.BaseProvider = void 0;
const crypto = require("crypto");
const request_context_1 = require("../context/request.context");
const glob_1 = require("./glob");
const path_1 = require("path");
/** 基于此类的 `ScopeEnum.Request` 型自动注入对象,在释放时会触发 `onFree` 事件 */
class BaseProvider {
}
exports.BaseProvider = BaseProvider;
/** 作用域 */
var ScopeEnum;
(function (ScopeEnum) {
/** 单例,全局唯一(进程级别) */
ScopeEnum[ScopeEnum["Singleton"] = 0] = "Singleton";
/** **默认**,请求 (Context) 作用域, Context 生命周期上唯一,Context 释放时立即销毁 (如果实例化时没有指定 Context,则和 `Prototype` 一样 ) */
ScopeEnum[ScopeEnum["Request"] = 1] = "Request";
/** 原型作用域,每次调用都会重复创建一个新的对象 */
ScopeEnum[ScopeEnum["Prototype"] = 2] = "Prototype";
})(ScopeEnum = exports.ScopeEnum || (exports.ScopeEnum = {}));
/** TS 设计期类型信息 */
class TSDesignType {
constructor() {
this.isBaseType = true;
}
}
exports.TSDesignType = TSDesignType;
const FUNCTION_INJECT_KEY = 'ioc:function_inject_key';
const STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/gm;
const ToString = Function.prototype.toString;
/** 基类标识,主要功能是留下构造函数参数信息 */
function BaseClass() {
return function (target) { };
}
exports.BaseClass = BaseClass;
/**
* 提供者标识, 在 Service、Model 类型上使用, 如果实现自动注入,构造函数应无参数或只有Context参数
* @param identifier 标识符,如果不指定,默认为类名
* @param scope 作用域, 默认为 `ScopeEnum.Request`
*/
function Provide(identifier, scope) {
return function (target) {
IocContainer.bind(target, identifier, scope !== null && scope !== void 0 ? scope : ScopeEnum.Request);
};
}
exports.Provide = Provide;
/**
* 标识 Service 提供者
* @param identifier 标识符,如果不指定,默认为类名
* @param scope 作用域, 默认为 `ScopeEnum.Request`
*/
exports.Service = Provide;
/**
* 标识 Wrapper 提供者
* @param identifier 标识符,如果不指定,默认为类名
* @param scope 作用域, 默认为 `ScopeEnum.Request`
*/
exports.Wrapper = Provide;
class RouteConfigData {
}
/** 路由配置 */
RouteConfigData.routeConfigMap = new Map();
/**
* 路由配置标识装饰器
* @param baseUrl 基础路径,使用 "/" 开头
* @param logPackage 是否输出 api 日志
* @returns
*/
function Route(baseUrl = '', logPackage) {
return function (target) {
RouteConfigData.routeConfigMap.set(target.name, { basePath: baseUrl, logPackage });
};
}
exports.Route = Route;
/** 注入Class参数 */
class InjectClassParam {
}
exports.InjectClassParam = InjectClassParam;
/**
* 自动注入装饰器,支持构造器和属性注入,支持注入对象和函数(参考 `injectWrapper`)
* @param identifier 标识符,如果不指定,默认为参数名称
* @param options 可选,注入选项设置。用于指定实例化参数等信息
* @returns
*/
function inject(identifier, options) {
return function (target, targetKey, index) {
var _a, _b, _c;
if (typeof index === 'number') {
// 构造器注入
let key = identifier;
if (!key) {
const args = IocContainer.getParamNames(target);
if (target.length === args.length && index < target.length) {
key = args[index];
}
}
else if (key.includes('@') && !key.includes(":")) {
const args = IocContainer.getParamNames(target);
if (target.length === args.length && index < target.length) {
key = `${key}:${args[index]}`;
}
}
if (key) {
const data = new InjectData(key, 0);
data.target = target;
data.targetKey = targetKey;
data.index = index;
data.args = options === null || options === void 0 ? void 0 : options.args;
data.must = (_a = options === null || options === void 0 ? void 0 : options.must) !== null && _a !== void 0 ? _a : true;
data.errMsg = options === null || options === void 0 ? void 0 : options.errMsg;
IocContainer._saveInjectData(data);
}
}
else {
// 属性注入
let key = identifier;
if (!key) {
const type = IocContainer.getPropertyType(target, targetKey);
if (!type.isBaseType &&
IocContainer.isClass(type.origin) &&
IocContainer.isProvide(type.origin)) {
key = (_b = IocContainer.getProviderUUId(type.origin)) !== null && _b !== void 0 ? _b : IocContainer.getProviderId(type.origin);
}
if (!key) {
key = targetKey;
}
}
if (key.includes('@') && !key.includes(':')) {
key = `${key}:${targetKey}`;
}
if (key) {
const data = new InjectData(key, 1);
data.target = target;
data.targetKey = targetKey;
data.args = options === null || options === void 0 ? void 0 : options.args;
data.must = (_c = options === null || options === void 0 ? void 0 : options.must) !== null && _c !== void 0 ? _c : true;
data.errMsg = options === null || options === void 0 ? void 0 : options.errMsg;
IocContainer._saveInjectData(data);
}
}
};
}
exports.inject = inject;
/**
* 自动注入函数 Wrapper
*/
function injectWrapper(wrapperInfo) {
for (const info of wrapperInfo) {
Object.defineProperty(info.provider, FUNCTION_INJECT_KEY, {
value: info,
writable: false,
});
IocContainer.bindInjectWrapper(info.provider, info.id);
}
}
exports.injectWrapper = injectWrapper;
/** 配置信息来源 */
var ConfigScope;
(function (ConfigScope) {
ConfigScope[ConfigScope["app"] = 0] = "app";
ConfigScope[ConfigScope["config"] = 1] = "config";
ConfigScope[ConfigScope["server"] = 2] = "server";
ConfigScope[ConfigScope["context"] = 3] = "context";
})(ConfigScope = exports.ConfigScope || (exports.ConfigScope = {}));
/**
* 自动配置信息注入装饰器, 只支持属性注入
* @param path 配置信息的名称完整路径,默认使用字段名称,不区分大小写
* @param scope 配置信息来源, 默认 `ConfigScope.config`。如果是数组,则以先后顺序作为优先级获取
* @param defaultValue 默认值
* @description Path 示例:"ossConfig"、"ossConfig.region"、"apiBaseUrl"
* @returns
*/
function config(path, scope, defaultValue) {
return function (target, targetKey) {
const data = new InjectConfigItem();
data.path = path;
data.scope = scope;
data.defaultValue = defaultValue;
data.target = target;
data.targetKey = targetKey;
IocContainer._saveConfigInjectData(data);
};
}
exports.config = config;
class InjectConfigItem {
}
class ContainerItem {
}
class InjectData {
/**
*
* @param identifier 标识符
* @param type 类型:0 构造器,1 属性, 2 非注入的占位参数
*/
constructor(identifier, type) {
this.identifier = identifier;
this.type = type;
}
}
const DEFAULT_PATTERN = ['**/**.ts', '**/**.tsx', '**/**.js'];
const DEFAULT_IGNORE_PATTERN = [
'**/**.d.ts',
'**/logs/**',
'**/run/**',
'**/doc/**',
'**/public/**',
'**/app/view/**',
'**/app/views/**',
'**/app/extend/**',
'**/node_modules/**',
'**/**.test.ts',
'**/**.test.js',
'**/__test__/**',
];
/**
* IOC 控制反转容器
*/
class IocContainer {
/** 获取类型定义数据 */
static getDefinition(identifier) {
var _a, _b;
if (typeof identifier === 'string') {
const id = identifier.length === 32 ? (_a = this.provideUuidMap.get(identifier)) !== null && _a !== void 0 ? _a : identifier : identifier;
const key = id.toLowerCase();
return [this.findImplementClass(key, identifier), key];
}
else {
const id = (_b = this.provideMap.get(identifier.name)) !== null && _b !== void 0 ? _b : identifier.name;
const key = id.toLowerCase();
return [this.findImplementClass(key, id), key];
}
}
/**
* 获取接口实现类
* @param identifier 标识符
* @param context 上下文对象
* @param args 可选,实例化实现类的参数列表,需要视具休的实现类实例化参数而定
* @returns
*/
static get(identifier, context, ...args) {
let [item, key] = this.getDefinition(identifier);
return this.getData(item, key, context, ...args);
}
/**
* 获取配置信息
* @param path 配置信息的名称完整路径,默认使用字段名称,不区分大小写
* @param scope 配置信息来源, 默认 `ConfigScope.config`。如果是数组,则以先后顺序作为优先级获取
* @param defaultValue 默认值
* @param context 上下文对象
*/
static getConfig(path, scope, context, defaultValue) {
var _a, _b, _c;
const nodes = path.split('.');
if (nodes.length === 0) {
return defaultValue;
}
const scopes = Array.isArray(scope) ? scope : [scope !== null && scope !== void 0 ? scope : ConfigScope.config];
if ((context === null || context === void 0 ? void 0 : context.config) && scopes.length === 1 && scopes[0] === ConfigScope.config) {
// 存在上下文对象时,优先取上下文中的配置信息
scopes.unshift(ConfigScope.context);
}
for (const scope of scopes) {
let data = undefined;
if (scope === ConfigScope.server && context) {
data = (_a = context.server) === null || _a === void 0 ? void 0 : _a.options;
if (data !== undefined) {
data = this.getConfigData(nodes, data);
}
if (data === undefined) {
// 服务本身没有取成功时,且只有一个默认的全局服务配置时,从全局配置取
const _config = (_b = this.config) === null || _b === void 0 ? void 0 : _b.server;
if (_config) {
if (Array.isArray(_config)) {
if (_config.length === 1) {
data = this.getConfigData(nodes, _config[0]);
}
}
else {
data = this.getConfigData(nodes, _config);
}
}
}
}
else {
data = scope === ConfigScope.config
? (_c = this.config) === null || _c === void 0 ? void 0 : _c.config
: (scope === ConfigScope.app ? this.config : context === null || context === void 0 ? void 0 : context.config);
if (data !== undefined) {
data = this.getConfigData(nodes, data);
}
}
if (data !== undefined) {
return data;
}
}
return defaultValue;
}
static getData(item, key, context, ...args) {
if (item) {
const functionInject = item.classType[FUNCTION_INJECT_KEY];
if (functionInject) {
return context ? functionInject.provider(context, ...args) : undefined;
}
else {
return this.getObject(item, key, context, ...args);
}
}
else {
return this.injectObjectList.get(key);
}
}
static getObject(item, key, context, ...args) {
let map;
let instance = undefined;
switch (item.scope) {
case ScopeEnum.Request:
if (context) {
map = IocContainer.contextContainer.get(context);
if (!map) {
map = new Map();
IocContainer.contextContainer.set(context, map);
instance = this.createObject(context, item, ...args);
map.set(key, instance);
}
else {
instance = map.get(key);
}
}
break;
case ScopeEnum.Singleton:
instance = IocContainer.singletonList.get(key);
break;
}
if (instance) {
return instance;
}
instance = this.createObject(context, item, ...args);
if (item.scope === ScopeEnum.Singleton && IocContainer.singletonList.has(key)) {
IocContainer.singletonList.set(key, instance);
}
return instance;
}
/** 释放上下文容器 */
static destroy(context) {
if (context) {
const map = IocContainer.contextContainer.get(context);
if (map === undefined) {
return;
}
IocContainer.contextContainer.delete(context);
map.forEach((item, key) => {
if (item instanceof BaseProvider) {
try {
item.onFree();
}
catch (e) {
context.logE(e.message);
}
}
});
map.clear();
}
}
/** 实例化对象 */
static createObject(context, definition, ...args) {
let constructorArgs = undefined;
if (args && Array.isArray(args) && args.length > 0) {
// 设置了参数时,如果参数是一个 ClassType、Context 或 InjectClassParam,则自动注入对应类型的参数
constructorArgs = [];
args.forEach((v) => {
if (v === undefined || v === null) {
constructorArgs === null || constructorArgs === void 0 ? void 0 : constructorArgs.push(v);
return;
}
if (this.isContext(v)) {
if (context instanceof v) {
constructorArgs === null || constructorArgs === void 0 ? void 0 : constructorArgs.push(context);
}
else {
constructorArgs === null || constructorArgs === void 0 ? void 0 : constructorArgs.push(undefined);
}
}
else if (this.isClass(v)) {
if (constructorArgs) {
const [item, key] = this.getDefinition(v);
constructorArgs.push(this.getData(item, key, context));
}
}
else if (v instanceof InjectClassParam || (this.isClass(v.type))) {
const [item, key] = this.getDefinition(v.type);
constructorArgs === null || constructorArgs === void 0 ? void 0 : constructorArgs.push(v.args
? this.getData(item, key, context, ...v.args)
: this.getData(item, key, context));
}
else {
constructorArgs === null || constructorArgs === void 0 ? void 0 : constructorArgs.push(v);
}
});
}
else {
if (!this.compareAndSetCreateStatus(definition.uuid)) {
// 循环创建
throw Error(`注入对象 ${definition.classType.name} 时存在循环异常`);
}
try {
constructorArgs = this.getClassConstructorArgs(context, definition.classType, definition);
if (context && (constructorArgs === undefined || constructorArgs.length === 0)) {
// 获取参数类型列表,如果存在 context 时,将参数中的 context 设置为当前 context
const paramTypes = this.getParamTypes(definition.classType);
if (paramTypes) {
constructorArgs = [];
paramTypes.forEach((v) => {
if (this.isContext(v)) {
constructorArgs === null || constructorArgs === void 0 ? void 0 : constructorArgs.push(context);
}
else {
constructorArgs === null || constructorArgs === void 0 ? void 0 : constructorArgs.push(undefined);
}
});
}
}
}
finally {
this.creating.delete(definition.uuid);
}
}
const instance = constructorArgs === undefined || constructorArgs.length === 0
? new definition.classType()
: new definition.classType(...constructorArgs);
this.resolveInject(context, instance, definition.classType);
return instance;
}
static getInstanceInjectCache(instance) {
if (instance.__injectObjs === undefined) {
instance.__injectObjs = new Map();
}
return instance.__injectObjs;
}
/**
* 注入属性
* @param instance 对象实例
*/
static resolveInject(context, instance, target) {
const injectList = this.getClassInject(target);
if (injectList.length === 0) {
this.resolveInjectConfigFiled(context, instance, target);
return;
}
for (const item of injectList) {
Object.defineProperty(instance, item.targetKey, {
get: () => {
var _a;
const map = IocContainer.getInstanceInjectCache(instance);
const result = map.get(item.targetKey);
if (result) {
return result;
}
const data = item.args === undefined
? IocContainer.get(item.identifier, context !== null && context !== void 0 ? context : instance.context)
: IocContainer.get(item.identifier, context !== null && context !== void 0 ? context : instance.context, ...item.args);
if (data === undefined || data === null) {
if (item.must) {
throw Error((_a = item.errMsg) !== null && _a !== void 0 ? _a : `参数 ${item.targetKey} 自动注入失败`);
}
}
map.set(item.targetKey, data);
return data;
}
});
}
this.resolveInjectConfigFiled(context, instance, target);
}
/**
* 注入配置属性
* @param instance 对象实例
*/
static resolveInjectConfigFiled(context, instance, target) {
let cls = target;
do {
const data = this.injectConfigIdMap.get(cls.name);
data === null || data === void 0 ? void 0 : data.forEach((v) => {
Object.defineProperty(instance, v.targetKey, {
get: () => {
var _a;
const map = IocContainer.getInstanceInjectCache(instance);
const result = map.get(v.targetKey);
if (result) {
return result;
}
const value = this.getConfig((_a = v.path) !== null && _a !== void 0 ? _a : v.targetKey, v.scope, context, v.defaultValue);
map.set(v.targetKey, value);
return value;
}
});
});
cls = cls.prototype.__proto__.constructor;
} while (cls !== null && cls.name !== 'Object');
}
static getConfigData(nodes, srcData) {
let data = srcData;
for (const v of nodes) {
const keys = new Map();
Object.keys(data).forEach((v) => {
keys.set(v.toLowerCase(), v);
});
const key = keys.get(v.toLowerCase());
data = key ? data[key] : undefined;
if (data === undefined) {
break;
}
}
return data;
}
/** 生成一个匿名对象的类类型, 使用 `new` 的时候,返回这个对象本身 */
static getUnknowClassType(obj, className) {
class UnknowClass {
constructor(...args) {
return obj;
}
}
const v = UnknowClass;
if (className) {
Object.defineProperty(v, 'name', {
value: className,
writable: false
});
}
return v;
}
/** 获取指定类的构造参数 */
static getClassConstructorArgs(context, target, definition) {
const injectArgs = definition ? definition.constructorArgs : this.getConstructorInject(target);
if (injectArgs.length === 0) {
return undefined;
}
let result = [];
injectArgs.forEach((v, idx) => {
if (v.type === 2) {
// 自动注入 context
if (context && this.isContext(v.target)) {
result.push(context);
}
else if (v.identifier) {
// 尝试通过 id 注入
let [item, key] = this.getDefinition(v.identifier);
if (item) {
if (this.isFunction(item.classType)) {
result.push(this.getData(item, key, context));
}
else if (item.classType === v.target || item.classType instanceof v.target) {
const data = v.args == undefined
? this.getObject(item, key, context)
: this.getObject(item, key, context, v.args);
result.push(data);
}
else {
result.push(undefined);
}
}
else {
result.push(this.injectObjectList.get(key));
}
}
else {
result.push(undefined);
}
}
else {
const value = v.args === undefined
? this.get(v.identifier, context)
: this.get(v.identifier, context, ...v.args);
result.push(value);
}
});
return result;
}
/** 获取构造函数需要注入的参数列表 */
static getConstructorInject(target) {
const injectArgs = this.getInjectList(target.name, 0);
if (injectArgs.length === 0) {
return injectArgs;
}
const paramTypes = this.getParamTypes(target);
if (paramTypes && injectArgs.length !== paramTypes.length) {
let result = [];
let map = {};
injectArgs.forEach((v) => {
if (v.index !== undefined) {
map[v.index] = v;
}
});
const names = this.getParamNames(target);
paramTypes.forEach((v, idx) => {
const injectData = map[idx];
if (injectData) {
result.push(injectData);
}
else {
const argsItem = new InjectData(names[idx], 2);
argsItem.index = idx;
argsItem.target = v;
result.push(argsItem);
}
});
return result;
}
else {
return injectArgs;
}
}
/** 获取类需要注入的参数列表 */
static getClassInject(target) {
const cacheList = this.injectClsMap.get(target.name);
if (cacheList) {
return cacheList;
}
let result = [];
let cls = target;
do {
const data = this.getInjectList(cls.name, 1);
result.push(...data);
cls = cls.prototype.__proto__.constructor;
} while (cls !== null && cls.name !== 'Object');
this.injectClsMap.set(target.name, result);
return result;
}
/**
* 获取指定类的注入数据列表
* @param className 类名称
* @param type 注入数据类型 0 构造函数 1 属性
* @returns
*/
static getInjectList(className, type) {
const ids = IocContainer.injectIdMap.get(className);
let result = [];
if (ids && ids.length > 0) {
ids.forEach((v) => {
const value = IocContainer.injectMap.get(className + "." + v.toLowerCase());
if (value && value.type === type) {
result.push(value);
}
});
}
return result;
}
static compareAndSetCreateStatus(id) {
if (!this.creating.has(id) ||
!this.creating.get(id)) {
this.creating.set(id, true);
return true;
}
else {
return false;
}
}
/**
* 绑定对象定义
* @param identifier 标识名称, 不区分大小写
* @param scope 作用域
* @param module 实现类
*/
static bind(module, identifier, scope = ScopeEnum.Request) {
const key = (identifier !== null && identifier !== void 0 ? identifier : module.name).toLowerCase();
if (scope === ScopeEnum.Singleton) {
IocContainer.singletonList.set(key, undefined);
}
const uuid = this.generateRandomId();
const constructorArgs = this.getConstructorInject(module);
this.provideMap.set(module.name, key);
this.provideUuidMap.set(uuid, key);
this.container.set(key, { classType: module, scope, uuid, constructorArgs });
}
/**
* 绑定动态 Wrapper 函数定义
* @param identifier 标识名称, 不区分大小写
* @param provider 实现函数
* @description `
* export function xxx(context: RequestContext): any {
* return () => { return data; }
* }`
*/
static bindInjectWrapper(provider, identifier) {
if (!identifier) {
return;
}
const key = identifier.toLowerCase();
const uuid = this.generateRandomId();
this.provideUuidMap.set(uuid, key);
this.container.set(key, { classType: provider, scope: ScopeEnum.Prototype, uuid, constructorArgs: [] });
}
/** 注入已有对象 */
static registerObject(identifier, obj) {
this.injectObjectList.set(identifier.toLowerCase(), obj);
}
static _saveInjectData(data) {
const className = data.type === 0 ? data.target.name : data.target.constructor.name;
let ids = this.injectIdMap.get(className);
if (!ids) {
ids = [];
this.injectIdMap.set(className, ids);
}
ids.push(data.identifier);
IocContainer.injectMap.set(className + "." + data.identifier.toLowerCase(), data);
}
static _saveConfigInjectData(data) {
const className = data.target.constructor.name;
let ids = this.injectConfigIdMap.get(className);
if (!ids) {
ids = [];
this.injectConfigIdMap.set(className, ids);
}
ids.push(data);
}
/** 查找接口名称的实现类 */
static findImplementClass(key, implementName) {
let definition = IocContainer.container.get(key);
if (!definition && /:/.test(key)) {
let identifier = key.replace(/^.*?:/, '');
definition = IocContainer.container.get(identifier);
}
if (definition) {
return definition;
}
// eslint-disable-next-line no-console
console.warn(`没有找到 ${implementName} 的实现类`);
return undefined;
}
static getParamTypes(classType) {
let result = undefined;
let cls = classType;
do {
result = cls.name === 'BaseObject' ? [request_context_1.RequestContext] : Reflect.getMetadata('design:paramtypes', cls);
if (result === undefined) {
cls = cls.prototype.__proto__.constructor;
}
} while (result === undefined && cls !== null && cls.name !== 'Object');
return result;
}
static getParamNames(func) {
const fnStr = func.toString().replace(STRIP_COMMENTS, '');
let result = fnStr
.slice(fnStr.indexOf('(') + 1, fnStr.indexOf(')'))
.split(',')
.map(content => {
return content.trim().replace(/\s?=.*$/, '');
});
if (result.length === 1 && result[0] === '') {
result = [];
}
return result;
}
static isNullOrUndefined(value) {
return value === undefined || value === null;
}
static transformTypeFromTSDesign(designFn) {
if (this.isNullOrUndefined(designFn)) {
return { name: 'undefined', isBaseType: true, origin: designFn };
}
switch (designFn.name) {
case 'String':
return { name: 'string', isBaseType: true, origin: designFn };
case 'Number':
return { name: 'number', isBaseType: true, origin: designFn };
case 'Boolean':
return { name: 'boolean', isBaseType: true, origin: designFn };
case 'Symbol':
return { name: 'symbol', isBaseType: true, origin: designFn };
case 'Object':
return { name: 'object', isBaseType: true, origin: designFn };
case 'Function':
return { name: 'function', isBaseType: true, origin: designFn };
default:
return { name: designFn.name, isBaseType: false, origin: designFn };
}
}
static getPropertyType(target, propertyKey) {
return this.transformTypeFromTSDesign(Reflect.getMetadata('design:type', target, propertyKey));
}
static fnBody(fn) {
return ToString.call(fn)
.replace(/^[^{]*{\s*/, '')
.replace(/\s*}[^}]*$/, '');
}
static isContext(fn) {
if (fn === request_context_1.RequestContext) {
return true;
}
if (typeof fn !== 'function') {
return false;
}
return fn.prototype instanceof request_context_1.RequestContext;
}
static isClass(fn) {
if (typeof fn !== 'function') {
return false;
}
if (/^class[\s{]/.test(ToString.call(fn))) {
return true;
}
// babel.js classCallCheck() & inlined
const body = this.fnBody(fn);
return (/classCallCheck\(/.test(body) ||
/TypeError\("Cannot call a class as a function"\)/.test(body));
}
static isFunction(value) {
return typeof value === 'function';
}
static isObject(value) {
return value !== null && typeof value === 'object';
}
static isProvide(target) {
return this.provideMap.has(target.name);
}
static isTypeScriptEnvironment() {
const TS_MODE_PROCESS_FLAG = process.env.MIDWAY_TS_MODE;
if ('false' === TS_MODE_PROCESS_FLAG) {
return false;
}
// eslint-disable-next-line node/no-deprecated-api
return TS_MODE_PROCESS_FLAG === 'true' || !!require.extensions['.ts'];
}
static isRouteConfig(target) {
return RouteConfigData.routeConfigMap.has(target.name);
}
static getRouteConfig(target) {
return RouteConfigData.routeConfigMap.get(target.name);
}
static getProviderUUId(module) {
const key = this.provideMap.get(module.name);
const data = key ? this.container.get(key) : undefined;
return data ? data.uuid : undefined;
}
static getProviderId(module) {
const key = this.provideMap.get(module.name);
const data = key ? this.container.get(key) : undefined;
return data ? key : String(module.name).toLowerCase();
}
static generateRandomId() {
return crypto.randomBytes(16).toString('hex');
}
/** 获取项目自动加载时的根目录 */
static getBaseDir(devPath, distPath) {
const appDir = process.cwd();
if (this.isTypeScriptEnvironment()) {
return (0, path_1.join)(appDir, devPath !== null && devPath !== void 0 ? devPath : 'src');
}
else {
return (0, path_1.join)(appDir, distPath !== null && distPath !== void 0 ? distPath : 'dist');
}
}
/** 自动扫描,加载模块 */
static loadDirectory(opts, onBindClass) {
var _a;
if (!opts.baseDir) {
opts.baseDir = this.getBaseDir();
}
const baseDir = (_a = opts.baseDir) !== null && _a !== void 0 ? _a : '';
const loadDirs = Array.isArray(opts.loadDir) ? opts.loadDir : [opts.loadDir];
console.log(`scanning "${baseDir}"`);
for (const dir of loadDirs) {
const _dir = (0, path_1.join)(baseDir, dir);
const fileResults = (0, glob_1.run)(DEFAULT_PATTERN.concat(opts.pattern || []), {
cwd: _dir,
ignore: DEFAULT_IGNORE_PATTERN.concat(opts.ignore || []),
});
for (const file of fileResults) {
console.log(`load "${file}"`);
const exports = require(file);
if (onBindClass) {
if (this.isClass(exports) || this.isFunction(exports)) {
onBindClass(exports, file);
}
else {
for (const m in exports) {
const module = exports[m];
if (this.isClass(module) || this.isFunction(module)) {
onBindClass(module, file);
}
}
}
}
}
}
}
}
exports.IocContainer = IocContainer;
/** 全局容器 */
IocContainer.container = new Map();
IocContainer.provideMap = new Map();
IocContainer.provideUuidMap = new Map();
/** 单例列表 */
IocContainer.singletonList = new Map();
/** 手动注册的对象或函数 */
IocContainer.injectObjectList = new Map();
/** Context容器 */
IocContainer.contextContainer = new Map();
/** 注入映射 */
IocContainer.injectMap = new Map();
IocContainer.injectIdMap = new Map();
/** 配置注入映射 */
IocContainer.injectConfigIdMap = new Map();
/** 缓存类型需要注入的属性列表 */
IocContainer.injectClsMap = new Map();
IocContainer.creating = new Map();
//# sourceMappingURL=ioc.decorator.js.map