123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151 |
- 'use strict';
- const debug = require('debug')('egg-core:extend');
- const deprecate = require('depd')('egg');
- const path = require('path');
- const originalPrototypes = {
- request: require('koa/lib/request'),
- response: require('koa/lib/response'),
- context: require('koa/lib/context'),
- application: require('koa/lib/application'),
- };
- module.exports = {
- /**
- * mixin Agent.prototype
- * @function EggLoader#loadAgentExtend
- * @since 1.0.0
- */
- loadAgentExtend() {
- this.loadExtend('agent', this.app);
- },
- /**
- * mixin Application.prototype
- * @function EggLoader#loadApplicationExtend
- * @since 1.0.0
- */
- loadApplicationExtend() {
- this.loadExtend('application', this.app);
- },
- /**
- * mixin Request.prototype
- * @function EggLoader#loadRequestExtend
- * @since 1.0.0
- */
- loadRequestExtend() {
- this.loadExtend('request', this.app.request);
- },
- /**
- * mixin Response.prototype
- * @function EggLoader#loadResponseExtend
- * @since 1.0.0
- */
- loadResponseExtend() {
- this.loadExtend('response', this.app.response);
- },
- /**
- * mixin Context.prototype
- * @function EggLoader#loadContextExtend
- * @since 1.0.0
- */
- loadContextExtend() {
- this.loadExtend('context', this.app.context);
- },
- /**
- * mixin app.Helper.prototype
- * @function EggLoader#loadHelperExtend
- * @since 1.0.0
- */
- loadHelperExtend() {
- if (this.app && this.app.Helper) {
- this.loadExtend('helper', this.app.Helper.prototype);
- }
- },
- /**
- * Find all extend file paths by name
- * can be override in top level framework to support load `app/extends/{name}.js`
- *
- * @param {String} name - filename which may be `app/extend/{name}.js`
- * @return {Array} filepaths extend file paths
- * @private
- */
- getExtendFilePaths(name) {
- return this.getLoadUnits().map(unit => path.join(unit.path, 'app/extend', name));
- },
- /**
- * Loader app/extend/xx.js to `prototype`,
- * @function loadExtend
- * @param {String} name - filename which may be `app/extend/{name}.js`
- * @param {Object} proto - prototype that mixed
- * @since 1.0.0
- */
- loadExtend(name, proto) {
- this.timing.start(`Load extend/${name}.js`);
- // All extend files
- const filepaths = this.getExtendFilePaths(name);
- // if use mm.env and serverEnv is not unittest
- const isAddUnittest = 'EGG_MOCK_SERVER_ENV' in process.env && this.serverEnv !== 'unittest';
- for (let i = 0, l = filepaths.length; i < l; i++) {
- const filepath = filepaths[i];
- filepaths.push(filepath + `.${this.serverEnv}`);
- if (isAddUnittest) filepaths.push(filepath + '.unittest');
- }
- const mergeRecord = new Map();
- for (let filepath of filepaths) {
- filepath = this.resolveModule(filepath);
- if (!filepath) {
- continue;
- } else if (filepath.endsWith('/index.js')) {
- // TODO: remove support at next version
- deprecate(`app/extend/${name}/index.js is deprecated, use app/extend/${name}.js instead`);
- }
- const ext = this.requireFile(filepath);
- const properties = Object.getOwnPropertyNames(ext)
- .concat(Object.getOwnPropertySymbols(ext));
- for (const property of properties) {
- if (mergeRecord.has(property)) {
- debug('Property: "%s" already exists in "%s",it will be redefined by "%s"',
- property, mergeRecord.get(property), filepath);
- }
- // Copy descriptor
- let descriptor = Object.getOwnPropertyDescriptor(ext, property);
- let originalDescriptor = Object.getOwnPropertyDescriptor(proto, property);
- if (!originalDescriptor) {
- // try to get descriptor from originalPrototypes
- const originalProto = originalPrototypes[name];
- if (originalProto) {
- originalDescriptor = Object.getOwnPropertyDescriptor(originalProto, property);
- }
- }
- if (originalDescriptor) {
- // don't override descriptor
- descriptor = Object.assign({}, descriptor);
- if (!descriptor.set && originalDescriptor.set) {
- descriptor.set = originalDescriptor.set;
- }
- if (!descriptor.get && originalDescriptor.get) {
- descriptor.get = originalDescriptor.get;
- }
- }
- Object.defineProperty(proto, property, descriptor);
- mergeRecord.set(property, filepath);
- }
- debug('merge %j to %s from %s', Object.keys(ext), name, filepath);
- }
- this.timing.end(`Load extend/${name}.js`);
- },
- };
|