@umijs/core 4.0.0-rc.2 → 4.0.0-rc.20

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.
@@ -1,23 +1,14 @@
1
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
2
  var __importDefault = (this && this.__importDefault) || function (mod) {
12
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
4
  };
14
5
  Object.defineProperty(exports, "__esModule", { value: true });
15
6
  exports.Service = void 0;
7
+ const tapable_1 = require("@umijs/bundler-utils/compiled/tapable");
16
8
  const utils_1 = require("@umijs/utils");
17
9
  const assert_1 = __importDefault(require("assert"));
18
10
  const fs_1 = require("fs");
19
11
  const path_1 = require("path");
20
- const tapable_1 = require("../../compiled/tapable");
21
12
  const config_1 = require("../config/config");
22
13
  const constants_1 = require("../constants");
23
14
  const types_1 = require("../types");
@@ -25,7 +16,6 @@ const env_1 = require("./env");
25
16
  const path_2 = require("./path");
26
17
  const plugin_1 = require("./plugin");
27
18
  const pluginAPI_1 = require("./pluginAPI");
28
- const utils_2 = require("./utils");
29
19
  class Service {
30
20
  constructor(opts) {
31
21
  this.appData = {};
@@ -55,302 +45,352 @@ class Service {
55
45
  (0, assert_1.default)((0, fs_1.existsSync)(this.cwd), `Invalid cwd ${this.cwd}, it's not found.`);
56
46
  }
57
47
  applyPlugins(opts) {
58
- return __awaiter(this, void 0, void 0, function* () {
59
- const hooks = this.hooks[opts.key] || [];
60
- let type = opts.type;
61
- // guess type from key
62
- if (!type) {
63
- if (opts.key.startsWith('on')) {
64
- type = types_1.ApplyPluginsType.event;
48
+ const hooks = this.hooks[opts.key] || [];
49
+ let type = opts.type;
50
+ // guess type from key
51
+ if (!type) {
52
+ if (opts.key.startsWith('on')) {
53
+ type = types_1.ApplyPluginsType.event;
54
+ }
55
+ else if (opts.key.startsWith('modify')) {
56
+ type = types_1.ApplyPluginsType.modify;
57
+ }
58
+ else if (opts.key.startsWith('add')) {
59
+ type = types_1.ApplyPluginsType.add;
60
+ }
61
+ else {
62
+ throw new Error(`Invalid applyPlugins arguments, type must be supplied for key ${opts.key}.`);
63
+ }
64
+ }
65
+ switch (type) {
66
+ case types_1.ApplyPluginsType.add:
67
+ (0, assert_1.default)(!('initialValue' in opts) || Array.isArray(opts.initialValue), `applyPlugins failed, opts.initialValue must be Array if opts.type is add.`);
68
+ const tAdd = new tapable_1.AsyncSeriesWaterfallHook(['memo']);
69
+ for (const hook of hooks) {
70
+ if (!this.isPluginEnable(hook))
71
+ continue;
72
+ tAdd.tapPromise({
73
+ name: hook.plugin.key,
74
+ stage: hook.stage || 0,
75
+ before: hook.before,
76
+ }, async (memo) => {
77
+ var _a, _b;
78
+ const dateStart = new Date();
79
+ const items = await hook.fn(opts.args);
80
+ (_a = hook.plugin.time.hooks)[_b = opts.key] || (_a[_b] = []);
81
+ hook.plugin.time.hooks[opts.key].push(new Date().getTime() - dateStart.getTime());
82
+ return memo.concat(items);
83
+ });
65
84
  }
66
- else if (opts.key.startsWith('modify')) {
67
- type = types_1.ApplyPluginsType.modify;
85
+ return tAdd.promise(opts.initialValue || []);
86
+ case types_1.ApplyPluginsType.modify:
87
+ const tModify = new tapable_1.AsyncSeriesWaterfallHook(['memo']);
88
+ for (const hook of hooks) {
89
+ if (!this.isPluginEnable(hook))
90
+ continue;
91
+ tModify.tapPromise({
92
+ name: hook.plugin.key,
93
+ stage: hook.stage || 0,
94
+ before: hook.before,
95
+ }, async (memo) => {
96
+ var _a, _b;
97
+ const dateStart = new Date();
98
+ const ret = await hook.fn(memo, opts.args);
99
+ (_a = hook.plugin.time.hooks)[_b = opts.key] || (_a[_b] = []);
100
+ hook.plugin.time.hooks[opts.key].push(new Date().getTime() - dateStart.getTime());
101
+ return ret;
102
+ });
68
103
  }
69
- else if (opts.key.startsWith('add')) {
70
- type = types_1.ApplyPluginsType.add;
104
+ return tModify.promise(opts.initialValue);
105
+ case types_1.ApplyPluginsType.event:
106
+ if (opts.sync) {
107
+ const tEvent = new tapable_1.SyncWaterfallHook(['_']);
108
+ hooks.forEach((hook) => {
109
+ if (this.isPluginEnable(hook)) {
110
+ tEvent.tap({
111
+ name: hook.plugin.key,
112
+ stage: hook.stage || 0,
113
+ before: hook.before,
114
+ }, () => {
115
+ var _a, _b;
116
+ const dateStart = new Date();
117
+ hook.fn(opts.args);
118
+ (_a = hook.plugin.time.hooks)[_b = opts.key] || (_a[_b] = []);
119
+ hook.plugin.time.hooks[opts.key].push(new Date().getTime() - dateStart.getTime());
120
+ });
121
+ }
122
+ });
123
+ return tEvent.call(1);
71
124
  }
72
- else {
73
- throw new Error(`Invalid applyPlugins arguments, type must be supplied for key ${opts.key}.`);
125
+ const tEvent = new tapable_1.AsyncSeriesWaterfallHook(['_']);
126
+ for (const hook of hooks) {
127
+ if (!this.isPluginEnable(hook))
128
+ continue;
129
+ tEvent.tapPromise({
130
+ name: hook.plugin.key,
131
+ stage: hook.stage || 0,
132
+ before: hook.before,
133
+ }, async () => {
134
+ var _a, _b;
135
+ const dateStart = new Date();
136
+ await hook.fn(opts.args);
137
+ (_a = hook.plugin.time.hooks)[_b = opts.key] || (_a[_b] = []);
138
+ hook.plugin.time.hooks[opts.key].push(new Date().getTime() - dateStart.getTime());
139
+ });
74
140
  }
75
- }
76
- switch (type) {
77
- case types_1.ApplyPluginsType.add:
78
- (0, assert_1.default)(!('initialValue' in opts) || Array.isArray(opts.initialValue), `applyPlugins failed, opts.initialValue must be Array if opts.type is add.`);
79
- const tAdd = new tapable_1.AsyncSeriesWaterfallHook(['memo']);
80
- for (const hook of hooks) {
81
- if (!this.isPluginEnable(hook))
82
- continue;
83
- tAdd.tapPromise({
84
- name: hook.plugin.id,
85
- stage: hook.stage,
86
- before: hook.before,
87
- }, (memo) => __awaiter(this, void 0, void 0, function* () {
88
- const items = yield hook.fn(opts.args);
89
- return memo.concat(items);
90
- }));
91
- }
92
- return (yield tAdd.promise(opts.initialValue || []));
93
- case types_1.ApplyPluginsType.modify:
94
- const tModify = new tapable_1.AsyncSeriesWaterfallHook(['memo']);
95
- for (const hook of hooks) {
96
- if (!this.isPluginEnable(hook))
97
- continue;
98
- tModify.tapPromise({
99
- name: hook.plugin.id,
100
- stage: hook.stage,
101
- before: hook.before,
102
- }, (memo) => __awaiter(this, void 0, void 0, function* () {
103
- return yield hook.fn(memo, opts.args);
104
- }));
105
- }
106
- return (yield tModify.promise(opts.initialValue));
107
- case types_1.ApplyPluginsType.event:
108
- const tEvent = new tapable_1.AsyncSeriesWaterfallHook(['_']);
109
- for (const hook of hooks) {
110
- if (!this.isPluginEnable(hook))
111
- continue;
112
- tEvent.tapPromise({
113
- name: hook.plugin.id,
114
- stage: hook.stage || 0,
115
- before: hook.before,
116
- }, () => __awaiter(this, void 0, void 0, function* () {
117
- yield hook.fn(opts.args);
118
- }));
119
- }
120
- return (yield tEvent.promise(1));
121
- default:
122
- throw new Error(`applyPlugins failed, type is not defined or is not matched, got ${opts.type}.`);
123
- }
124
- });
141
+ return tEvent.promise(1);
142
+ default:
143
+ throw new Error(`applyPlugins failed, type is not defined or is not matched, got ${opts.type}.`);
144
+ }
125
145
  }
126
- run(opts) {
127
- return __awaiter(this, void 0, void 0, function* () {
128
- const { name, args = {} } = opts;
129
- args._ = args._ || [];
130
- // shift the command itself
131
- if (args._[0] === name)
132
- args._.shift();
133
- this.args = args;
134
- this.name = name;
135
- // loadEnv
136
- this.stage = types_1.ServiceStage.init;
137
- (0, env_1.loadEnv)({ cwd: this.cwd, envFile: '.env' });
138
- // get pkg from package.json
139
- let pkg = {};
140
- let pkgPath = '';
141
- try {
142
- pkg = require((0, path_1.join)(this.cwd, 'package.json'));
143
- pkgPath = (0, path_1.join)(this.cwd, 'package.json');
144
- }
145
- catch (_e) {
146
- // APP_ROOT
147
- if (this.cwd !== process.cwd()) {
148
- try {
149
- pkg = require((0, path_1.join)(process.cwd(), 'package.json'));
150
- pkgPath = (0, path_1.join)(process.cwd(), 'package.json');
151
- }
152
- catch (_e) { }
146
+ async run(opts) {
147
+ const { name, args = {} } = opts;
148
+ args._ = args._ || [];
149
+ // shift the command itself
150
+ if (args._[0] === name)
151
+ args._.shift();
152
+ this.args = args;
153
+ this.name = name;
154
+ // loadEnv
155
+ this.stage = types_1.ServiceStage.init;
156
+ (0, env_1.loadEnv)({ cwd: this.cwd, envFile: '.env' });
157
+ // get pkg from package.json
158
+ let pkg = {};
159
+ let pkgPath = '';
160
+ try {
161
+ pkg = require((0, path_1.join)(this.cwd, 'package.json'));
162
+ pkgPath = (0, path_1.join)(this.cwd, 'package.json');
163
+ }
164
+ catch (_e) {
165
+ // APP_ROOT
166
+ if (this.cwd !== process.cwd()) {
167
+ try {
168
+ pkg = require((0, path_1.join)(process.cwd(), 'package.json'));
169
+ pkgPath = (0, path_1.join)(process.cwd(), 'package.json');
153
170
  }
171
+ catch (_e) { }
154
172
  }
155
- this.pkg = pkg;
156
- this.pkgPath = pkgPath;
157
- // get user config
158
- const configManager = new config_1.Config({
159
- cwd: this.cwd,
160
- env: this.env,
161
- defaultConfigFiles: this.opts.defaultConfigFiles,
173
+ }
174
+ this.pkg = pkg;
175
+ this.pkgPath = pkgPath || (0, path_1.join)(this.cwd, 'package.json');
176
+ const prefix = this.opts.frameworkName || constants_1.DEFAULT_FRAMEWORK_NAME;
177
+ // get user config
178
+ const configManager = new config_1.Config({
179
+ cwd: this.cwd,
180
+ env: this.env,
181
+ defaultConfigFiles: this.opts.defaultConfigFiles,
182
+ specifiedEnv: process.env[`${prefix}_ENV`.toUpperCase()],
183
+ });
184
+ this.configManager = configManager;
185
+ this.userConfig = configManager.getUserConfig().config;
186
+ // get paths
187
+ const paths = (0, path_2.getPaths)({
188
+ cwd: this.cwd,
189
+ env: this.env,
190
+ prefix: this.opts.frameworkName || constants_1.DEFAULT_FRAMEWORK_NAME,
191
+ });
192
+ // temporary paths for use by function generateFinalConfig.
193
+ // the value of paths may be updated by plugins later
194
+ this.paths = paths;
195
+ // resolve initial presets and plugins
196
+ const { plugins, presets } = plugin_1.Plugin.getPluginsAndPresets({
197
+ cwd: this.cwd,
198
+ pkg,
199
+ plugins: [require.resolve('./generatePlugin')].concat(this.opts.plugins || []),
200
+ presets: [require.resolve('./servicePlugin')].concat(this.opts.presets || []),
201
+ userConfig: this.userConfig,
202
+ prefix,
203
+ });
204
+ // register presets and plugins
205
+ this.stage = types_1.ServiceStage.initPresets;
206
+ const presetPlugins = [];
207
+ while (presets.length) {
208
+ await this.initPreset({
209
+ preset: presets.shift(),
210
+ presets,
211
+ plugins: presetPlugins,
162
212
  });
163
- this.configManager = configManager;
164
- this.userConfig = configManager.getUserConfig().config;
165
- // get paths (move after?)
166
- // resolve initial presets and plugins
167
- const { plugins, presets } = plugin_1.Plugin.getPluginsAndPresets({
213
+ }
214
+ plugins.unshift(...presetPlugins);
215
+ this.stage = types_1.ServiceStage.initPlugins;
216
+ while (plugins.length) {
217
+ await this.initPlugin({ plugin: plugins.shift(), plugins });
218
+ }
219
+ const command = this.commands[name];
220
+ (0, assert_1.default)(command, `Invalid command ${name}, it's not registered.`);
221
+ // collect configSchemas and configDefaults
222
+ for (const id of Object.keys(this.plugins)) {
223
+ const { config, key } = this.plugins[id];
224
+ if (config.schema)
225
+ this.configSchemas[key] = config.schema;
226
+ if (config.default !== undefined) {
227
+ this.configDefaults[key] = config.default;
228
+ }
229
+ this.configOnChanges[key] = config.onChange || types_1.ConfigChangeType.reload;
230
+ }
231
+ // setup api.config from modifyConfig and modifyDefaultConfig
232
+ this.stage = types_1.ServiceStage.resolveConfig;
233
+ const { config, defaultConfig } = await this.resolveConfig();
234
+ if (this.config.outputPath) {
235
+ paths.absOutputPath = (0, path_1.isAbsolute)(this.config.outputPath)
236
+ ? this.config.outputPath
237
+ : (0, path_1.join)(this.cwd, this.config.outputPath);
238
+ }
239
+ this.paths = await this.applyPlugins({
240
+ key: 'modifyPaths',
241
+ initialValue: paths,
242
+ });
243
+ // applyPlugin collect app data
244
+ // TODO: some data is mutable
245
+ this.stage = types_1.ServiceStage.collectAppData;
246
+ this.appData = await this.applyPlugins({
247
+ key: 'modifyAppData',
248
+ initialValue: {
249
+ // base
168
250
  cwd: this.cwd,
169
251
  pkg,
170
- plugins: [require.resolve('./generatePlugin')].concat(this.opts.plugins || []),
171
- presets: [require.resolve('./servicePlugin')].concat(this.opts.presets || []),
252
+ pkgPath,
253
+ plugins,
254
+ presets,
255
+ name,
256
+ args,
257
+ // config
172
258
  userConfig: this.userConfig,
173
- prefix: this.opts.frameworkName || constants_1.DEFAULT_FRAMEWORK_NAME,
174
- });
175
- // register presets and plugins
176
- this.stage = types_1.ServiceStage.initPresets;
177
- const presetPlugins = [];
178
- while (presets.length) {
179
- yield this.initPreset({
180
- preset: presets.shift(),
181
- presets,
182
- plugins: presetPlugins,
183
- });
184
- }
185
- plugins.unshift(...presetPlugins);
186
- this.stage = types_1.ServiceStage.initPlugins;
187
- while (plugins.length) {
188
- yield this.initPlugin({ plugin: plugins.shift(), plugins });
189
- }
190
- // keyToPluginMap
191
- for (const id of Object.keys(this.plugins)) {
192
- this.keyToPluginMap[this.plugins[id].key] = this.plugins[id];
193
- }
194
- // collect configSchemas and configDefaults
195
- for (const id of Object.keys(this.plugins)) {
196
- const { config, key } = this.plugins[id];
197
- if (config.schema)
198
- this.configSchemas[key] = config.schema;
199
- if (config.default !== undefined) {
200
- this.configDefaults[key] = config.default;
201
- }
202
- this.configOnChanges[key] = config.onChange || types_1.ConfigChangeType.reload;
203
- }
204
- // setup api.config from modifyConfig and modifyDefaultConfig
205
- const paths = (0, path_2.getPaths)({
206
- cwd: this.cwd,
207
- env: this.env,
208
- prefix: this.opts.frameworkName || constants_1.DEFAULT_FRAMEWORK_NAME,
209
- });
210
- this.stage = types_1.ServiceStage.resolveConfig;
211
- const config = yield this.applyPlugins({
212
- key: 'modifyConfig',
213
- // why clone deep?
214
- // user may change the config in modifyConfig
215
- // e.g. memo.alias = xxx
216
- initialValue: utils_1.lodash.cloneDeep(configManager.getConfig({
259
+ mainConfigFile: configManager.mainConfigFile,
260
+ config,
261
+ defaultConfig: defaultConfig,
262
+ // TODO
263
+ // moduleGraph,
264
+ // routes,
265
+ // npmClient,
266
+ // nodeVersion,
267
+ // gitInfo,
268
+ // gitBranch,
269
+ // debugger info,
270
+ // devPort,
271
+ // devHost,
272
+ // env
273
+ },
274
+ });
275
+ // applyPlugin onCheck
276
+ this.stage = types_1.ServiceStage.onCheck;
277
+ await this.applyPlugins({
278
+ key: 'onCheck',
279
+ });
280
+ // applyPlugin onStart
281
+ this.stage = types_1.ServiceStage.onStart;
282
+ await this.applyPlugins({
283
+ key: 'onStart',
284
+ });
285
+ // run command
286
+ this.stage = types_1.ServiceStage.runCommand;
287
+ let ret = await command.fn({ args });
288
+ this._baconPlugins();
289
+ return ret;
290
+ }
291
+ async resolveConfig() {
292
+ // configManager and paths are not available until the init stage
293
+ (0, assert_1.default)(this.stage > types_1.ServiceStage.init, `Can't generate final config before init stage`);
294
+ const resolveMode = this.commands[this.name].configResolveMode;
295
+ const config = await this.applyPlugins({
296
+ key: 'modifyConfig',
297
+ // why clone deep?
298
+ // user may change the config in modifyConfig
299
+ // e.g. memo.alias = xxx
300
+ initialValue: utils_1.lodash.cloneDeep(resolveMode === 'strict'
301
+ ? this.configManager.getConfig({
217
302
  schemas: this.configSchemas,
218
- }).config),
219
- args: { paths },
220
- });
221
- const defaultConfig = yield this.applyPlugins({
222
- key: 'modifyDefaultConfig',
223
- initialValue: this.configDefaults,
224
- });
225
- this.config = utils_1.lodash.merge(defaultConfig, config);
226
- if (this.config.outputPath) {
227
- paths.absOutputPath = (0, path_1.join)(this.cwd, this.config.outputPath);
228
- }
229
- this.paths = yield this.applyPlugins({
230
- key: 'modifyPaths',
231
- initialValue: paths,
232
- });
233
- // applyPlugin collect app data
234
- // TODO: some data is mutable
235
- this.stage = types_1.ServiceStage.collectAppData;
236
- this.appData = yield this.applyPlugins({
237
- key: 'modifyAppData',
238
- initialValue: {
239
- // base
240
- cwd: this.cwd,
241
- pkg,
242
- pkgPath,
243
- plugins,
244
- presets,
245
- name,
246
- args,
247
- // config
248
- userConfig: this.userConfig,
249
- mainConfigFile: configManager.mainConfigFile,
250
- config,
251
- defaultConfig: defaultConfig,
252
- // TODO
253
- // moduleGraph,
254
- // routes,
255
- // npmClient,
256
- // nodeVersion,
257
- // gitInfo,
258
- // gitBranch,
259
- // debugger info,
260
- // devPort,
261
- // devHost,
262
- // env
263
- },
264
- });
265
- // applyPlugin onCheck
266
- this.stage = types_1.ServiceStage.onCheck;
267
- yield this.applyPlugins({
268
- key: 'onCheck',
269
- });
270
- // applyPlugin onStart
271
- this.stage = types_1.ServiceStage.onStart;
272
- yield this.applyPlugins({
273
- key: 'onStart',
274
- });
275
- // run command
276
- this.stage = types_1.ServiceStage.runCommand;
277
- const command = this.commands[name];
278
- (0, assert_1.default)(command, `Invalid command ${name}, it's not registered.`);
279
- return command.fn({ args });
303
+ }).config
304
+ : this.configManager.getUserConfig().config),
305
+ args: { paths: this.paths },
306
+ });
307
+ const defaultConfig = await this.applyPlugins({
308
+ key: 'modifyDefaultConfig',
309
+ initialValue: this.configDefaults,
280
310
  });
311
+ this.config = utils_1.lodash.merge(defaultConfig, config);
312
+ return { config, defaultConfig };
281
313
  }
282
- initPreset(opts) {
283
- return __awaiter(this, void 0, void 0, function* () {
284
- const { presets, plugins } = yield this.initPlugin({
285
- plugin: opts.preset,
286
- presets: opts.presets,
287
- plugins: opts.plugins,
288
- });
289
- opts.presets.unshift(...(presets || []));
290
- opts.plugins.push(...(plugins || []));
314
+ _baconPlugins() {
315
+ // TODO: prettier
316
+ if (this.args.baconPlugins) {
317
+ console.log();
318
+ for (const id of Object.keys(this.plugins)) {
319
+ const plugin = this.plugins[id];
320
+ console.log(utils_1.chalk.green('plugin'), plugin.id, plugin.time);
321
+ }
322
+ }
323
+ }
324
+ async initPreset(opts) {
325
+ const { presets, plugins } = await this.initPlugin({
326
+ plugin: opts.preset,
327
+ presets: opts.presets,
328
+ plugins: opts.plugins,
291
329
  });
330
+ opts.presets.unshift(...(presets || []));
331
+ opts.plugins.push(...(plugins || []));
292
332
  }
293
- initPlugin(opts) {
294
- var _a;
295
- return __awaiter(this, void 0, void 0, function* () {
296
- // register to this.plugins
297
- (0, assert_1.default)(!this.plugins[opts.plugin.id], `${opts.plugin.type} ${opts.plugin.id} is already registered by ${(_a = this.plugins[opts.plugin.id]) === null || _a === void 0 ? void 0 : _a.path}, ${opts.plugin.type} from ${opts.plugin.path} register failed.`);
298
- this.plugins[opts.plugin.id] = opts.plugin;
299
- // apply with PluginAPI
300
- const pluginAPI = new pluginAPI_1.PluginAPI({
301
- plugin: opts.plugin,
302
- service: this,
303
- });
304
- pluginAPI.registerPresets = pluginAPI.registerPresets.bind(pluginAPI, opts.presets || []);
305
- pluginAPI.registerPlugins = pluginAPI.registerPlugins.bind(pluginAPI, opts.plugins);
306
- const proxyPluginAPI = pluginAPI_1.PluginAPI.proxyPluginAPI({
333
+ async initPlugin(opts) {
334
+ var _a, _b;
335
+ // register to this.plugins
336
+ (0, assert_1.default)(!this.plugins[opts.plugin.id], `${opts.plugin.type} ${opts.plugin.id} is already registered by ${(_a = this.plugins[opts.plugin.id]) === null || _a === void 0 ? void 0 : _a.path}, ${opts.plugin.type} from ${opts.plugin.path} register failed.`);
337
+ this.plugins[opts.plugin.id] = opts.plugin;
338
+ // apply with PluginAPI
339
+ const pluginAPI = new pluginAPI_1.PluginAPI({
340
+ plugin: opts.plugin,
341
+ service: this,
342
+ });
343
+ pluginAPI.registerPresets = pluginAPI.registerPresets.bind(pluginAPI, opts.presets || []);
344
+ pluginAPI.registerPlugins = pluginAPI.registerPlugins.bind(pluginAPI, opts.plugins);
345
+ const proxyPluginAPI = pluginAPI_1.PluginAPI.proxyPluginAPI({
346
+ service: this,
347
+ pluginAPI,
348
+ serviceProps: [
349
+ 'appData',
350
+ 'applyPlugins',
351
+ 'args',
352
+ 'config',
353
+ 'cwd',
354
+ 'pkg',
355
+ 'pkgPath',
356
+ 'name',
357
+ 'paths',
358
+ 'userConfig',
359
+ 'env',
360
+ 'isPluginEnable',
361
+ ],
362
+ staticProps: {
363
+ ApplyPluginsType: types_1.ApplyPluginsType,
364
+ ConfigChangeType: types_1.ConfigChangeType,
365
+ EnableBy: types_1.EnableBy,
366
+ ServiceStage: types_1.ServiceStage,
307
367
  service: this,
308
- pluginAPI,
309
- serviceProps: [
310
- 'appData',
311
- 'applyPlugins',
312
- 'args',
313
- 'config',
314
- 'cwd',
315
- 'pkg',
316
- 'pkgPath',
317
- 'name',
318
- 'paths',
319
- 'userConfig',
320
- 'env',
321
- 'isPluginEnable',
322
- ],
323
- staticProps: {
324
- ApplyPluginsType: types_1.ApplyPluginsType,
325
- ConfigChangeType: types_1.ConfigChangeType,
326
- EnableBy: types_1.EnableBy,
327
- ServiceStage: types_1.ServiceStage,
328
- service: this,
329
- },
330
- });
331
- let ret = opts.plugin.apply()(proxyPluginAPI);
332
- if ((0, utils_2.isPromise)(ret)) {
333
- ret = yield ret;
334
- }
335
- if (opts.plugin.type === 'plugin') {
336
- (0, assert_1.default)(!ret, `plugin should return nothing`);
337
- }
338
- if (ret === null || ret === void 0 ? void 0 : ret.presets) {
339
- ret.presets = ret.presets.map((preset) => new plugin_1.Plugin({
340
- path: preset,
341
- type: types_1.PluginType.preset,
342
- cwd: this.cwd,
343
- }));
344
- }
345
- if (ret === null || ret === void 0 ? void 0 : ret.plugins) {
346
- ret.plugins = ret.plugins.map((plugin) => new plugin_1.Plugin({
347
- path: plugin,
348
- type: types_1.PluginType.plugin,
349
- cwd: this.cwd,
350
- }));
351
- }
352
- return ret || {};
368
+ },
353
369
  });
370
+ let dateStart = new Date();
371
+ let ret = await opts.plugin.apply()(proxyPluginAPI);
372
+ opts.plugin.time.register = new Date().getTime() - dateStart.getTime();
373
+ if (opts.plugin.type === 'plugin') {
374
+ (0, assert_1.default)(!ret, `plugin should return nothing`);
375
+ }
376
+ // key should be unique
377
+ (0, assert_1.default)(!this.keyToPluginMap[opts.plugin.key], `key ${opts.plugin.key} is already registered by ${(_b = this.keyToPluginMap[opts.plugin.key]) === null || _b === void 0 ? void 0 : _b.path}, ${opts.plugin.type} from ${opts.plugin.path} register failed.`);
378
+ this.keyToPluginMap[opts.plugin.key] = opts.plugin;
379
+ if (ret === null || ret === void 0 ? void 0 : ret.presets) {
380
+ ret.presets = ret.presets.map((preset) => new plugin_1.Plugin({
381
+ path: preset,
382
+ type: types_1.PluginType.preset,
383
+ cwd: this.cwd,
384
+ }));
385
+ }
386
+ if (ret === null || ret === void 0 ? void 0 : ret.plugins) {
387
+ ret.plugins = ret.plugins.map((plugin) => new plugin_1.Plugin({
388
+ path: plugin,
389
+ type: types_1.PluginType.plugin,
390
+ cwd: this.cwd,
391
+ }));
392
+ }
393
+ return ret || {};
354
394
  }
355
395
  isPluginEnable(hook) {
356
396
  let plugin;
@@ -369,7 +409,15 @@ class Service {
369
409
  return false;
370
410
  if (enableBy === types_1.EnableBy.config) {
371
411
  // TODO: 提供单独的命令用于启用插件
372
- return key in this.userConfig;
412
+ // this.userConfig 中如果存在,启用
413
+ // this.config 好了之后如果存在,启用
414
+ // this.config 在 modifyConfig 和 modifyDefaultConfig 之后才会 ready
415
+ // 这意味着 modifyConfig 和 modifyDefaultConfig 只能判断 api.userConfig
416
+ // 举个具体场景:
417
+ // - p1 enableBy config, p2 modifyDefaultConfig p1 = {}
418
+ // - p1 里 modifyConfig 和 modifyDefaultConfig 仅 userConfig 里有 p1 有效,其他 p2 开启时即有效
419
+ // - p2 里因为用了 modifyDefaultConfig,如果 p2 是 enableBy config,需要 userConfig 里配 p2,p2 和 p1 才有效
420
+ return key in this.userConfig || (this.config && key in this.config);
373
421
  }
374
422
  if (typeof enableBy === 'function')
375
423
  return enableBy({