Plugin API 
WinJS's core lies in its plugin mechanism. Based on WinJS's plugin mechanism, you can gain the ability to extend your project's compile-time and runtime capabilities. The following lists all the plugin APIs we provide for you to help you write plugins freely.
Before using the WinJS plugin API, we recommend you first read the Plugins section to understand the mechanisms and principles of WinJS plugins, which will help you better use the plugin APIs.
For easy reference, the following content is sorted alphabetically.
Core APIs 
Methods defined in service and PluginAPI.
applyPlugins 
api.applyPlugins({ key: string, type? : api.ApplyPluginsType, initialValue? : any, args? : any })Gets the data from the execution of hooks registered by register(). This is an asynchronous function, so it returns a Promise. For examples and detailed explanations of this method, see the register API.
describe 
api.describe({ key? : string, config? : { default, schema, onChange }, enableBy? })Executed during the plugin registration stage (initPresets or initPlugins stage), used to describe the plugin or plugin set's key, configuration information, and enablement method.
keyis the key name for this plugin's configuration in the configconfig.defaultis the default value of the plugin configuration. When the user hasn't configured the key in the configuration, the default configuration will take effect.config.schemais used to declare the configuration type, based on joi. This is required if you want users to configure it, otherwise user configuration will be invalidconfig.onChangeis the handling mechanism when configuration is modified in dev mode. The default value isapi.ConfigChangeType.reload, which means the dev process will restart when the configuration item is modified in dev mode. You can also change it toapi.ConfigChangeType.regenerateTmpFiles, which means only temporary files will be regenerated. You can also pass in a method to customize the handling mechanism.enableByis the plugin enablement method. The default isapi.EnableBy.register, which means registration enablement, i.e., the plugin will be enabled as long as it's registered. Can be changed toapi.EnableBy.config, which means configuration enablement, the plugin is only enabled when the plugin's configuration item is configured. You can also customize a method that returns a boolean value (true for enabled) to determine its enablement timing, which is usually used to implement dynamic enabling.
e.g.
api.describe({
  key: 'foo',
  config: {
    schema(joi) {
      return joi.string();
    },
    onChange: api.ConfigChangeType.regenerateTmpFiles,
  },
  enableBy: api.EnableBy.config,
})In this example, the plugin's key is foo, so the key name in the configuration is foo, the configuration type is string, when the foo configuration changes, dev will only regenerate temporary files. This plugin will only be enabled after the user configures foo.
isPluginEnable 
api.isPluginEnable(key:string)Determines whether a plugin is enabled. The parameter passed in is the plugin's key.
register 
api.register({ key: string, fn, before? : string, stage? : number })Registers hooks for use by api.applyPlugins.
keyis the category name of the registered hook. You can useregistermultiple times to register hooks to the samekey, and they will be executed in sequence. Thiskeyis also the samekeyused when usingapplyPluginsto collect hooks data. Note: this key has no relationship with the plugin's key.fnis the hook definition, which can be synchronous or asynchronous (just return a Promise)stageis used to adjust execution order, default is 0. Set to -1 or less will execute earlier, set to 1 or more will execute later.beforeis also used to adjust execution order, the value passed in is the name of the registered hook. Note: the name of the hook registered byregisteris the id of the WinJS plugin it belongs to. For more usage of stage and before, refer to tapable
The writing of fn needs to be determined in combination with the type parameter of the applyPlugins that will be used:
api.ApplyPluginsType.addapplyPluginswill concatenate their return values into an array according to hook order. At this time,fnneeds to have a return value, andfnwill receive theargsparameter ofapplyPluginsas its own parameter. TheinitialValueofapplyPluginsmust be an array, with a default value of empty array. Whenkeystarts with'add'and notypeis explicitly declared,applyPluginswill execute according to this type by default.api.ApplyPluginsType.modifyapplyPluginswill sequentially modify theinitialValuereceived byapplyPluginsaccording to hook order, soinitialValueis required at this time. At this time,fnneeds to receive amemoas its first parameter, and will take theargsparameter ofapplyPluginsas its second parameter.memois the result of the previous series of hooks modifyinginitialValue, andfnneeds to return the modifiedmemo. Whenkeystarts with'modify'and notypeis explicitly declared,applyPluginswill execute according to this type by default.api.ApplyPluginsType.eventapplyPluginswill execute sequentially according to hook order. At this time, there's no need to pass ininitialValue.fndoesn't need to have a return value, and will take theargsparameter ofapplyPluginsas its own parameter. Whenkeystarts with'on'and notypeis explicitly declared,applyPluginswill execute according to this type by default.
e.g.1 add type
api.register({
  key: 'addFoo',
  // synchronous
  fn: (args) => args
});
api.register({
  key: 'addFoo',
  // asynchronous
  fn: async (args) => args * 2
})
api.applyPlugins({
  key: 'addFoo',
  // key is add type, no need to explicitly declare as api.ApplyPluginsType.add
  args: 1
}).then((data) => {
  console.log(data); // [1,2]
})e.g.2 modify type
api.register({
  key: 'foo',
  fn: (memo, args) => ({ ...memo, a: args })
})
api.register({
  key: 'foo',
  fn: (memo) => ({ ...memo, b: 2 })
})
api.applyPlugins({
  key: 'foo',
  type: api.ApplyPluginsType.modify,
  // initialValue is required
  initialValue: {
    a: 0,
    b: 0
  },
  args: 1
}).then((data) => {
  console.log(data); // { a: 1, b: 2 }
});registerCommand 
api.registerCommand({
  name: string,
  description? : string,
  options? : string,
  details? : string,
  fn,
  alias? : string | string[]
  resolveConfigMode? : 'strict' | 'loose'
})Registers a command.
aliasis an alias, such as the aliasgfor generate- The parameter of 
fnis{ args }, args format is the same as yargs parsing result. Note that the command itself in_has been removed, for example, when executingwin generate page foo,args._is['page','foo'] - The 
resolveConfigModeparameter controls the configuration parsing method when executing commands. Instrictmode, it strictly validates the WinJS project's configuration file content, and interrupts command execution if there's illegal content; inloosemode, it doesn't perform configuration file validation checks. 
registerMethod 
api.registerMethod({ name: string, fn? })Register a method named 'name' on the api.
- When 
fnis passed, execute thefn - When 
fnis not passed,registerMethodwill usenameas thekeyforapi.registerand curry it asfn. In this case, it's equivalent to registering a shortcut forregister, making it convenient to register hooks. 
Note:
- It's generally not recommended to register additional methods since they won't have TypeScript hints. Using 
api.register()directly is a safer approach. 
e.g.1
api.registerMethod({
  name: foo,
  // with fn
  fn: (args) => {
    console.log(args);
  }
})
api.foo('hello, win!'); // hello, win!In this example, we register a foo method on the api that logs the parameter to the console.
e.g.2
import api from './api';
api.registerMethod({
  name: 'addFoo'
  // without fn
})
api.addFoo(args => args);
api.addFoo(args => args * 2);
api.applyPlugins({
  key: 'addFoo',
  args: 1
}).then((data) => {
  console.log(data); // [ 1, 2 ]
});In this example, we don't pass fn to api.registerMethod. At this point, we're essentially registering a "registrar" on the api: addFoo. Each call to this method is equivalent to calling register({ key: 'addFoo', fn }). Therefore, when we use api.applyPlugins (since our method is of the add type, we don't need to explicitly declare its type), we can get the values from the hooks we just registered.
registerPresets 
api.registerPresets(presets
:
string[]
)Register plugin presets, the parameter is an array of paths. This API must be executed in the initPresets stage, meaning it can only be used in presets to register other presets.
e.g.
api.registerPresets([
  './preset',
  require.resolve('./preset_foo')
])registerPlugins 
api.registerPlugins(plugins
:
string[]
)Register plugins, the parameter is an array of paths. This API must be executed in the initPresets and initPlugins stages.
e.g.
api.registerPlugins([
  './plugin',
  require.resolve('./plugin_foo')
])Note: Only plugin paths are allowed to be passed.
registerGenerator 
Register micro-generators for quickly generating template code.
Example:
import { GeneratorType } from '@winner-fed/core';
import { logger } from '@winner-fed/utils';
import { join } from 'path';
import { writeFileSync } from 'fs';
api.registerGenerator({
  key: 'editorconfig',
  name: 'Create .editorconfig',
  description: 'Setup editorconfig config',
  type: GeneratorType.generate,
  fn: () => {
    const configFilePath = join(api.cwd, '.editorconfig')
    if (existsSync(configFilePath)) {
      logger.info(`The .editorconfig file already exists.`)
      return
    }
    writeFileSync(
      configFilePath,
      `
# 🎨 http://editorconfig.org
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
`.trimStart(),
      'utf-8'
    )
    logger.info(`Generate .editorconfig file successful.`)
  }
})skipPlugins 
api.skipPlugins(keys
:
string[]
)Declare which plugins need to be disabled, the parameter is an array of plugin keys.
Extension Methods 
Methods extended through api.registerMethod(), their purpose is to register hooks for use, so they all need to receive a fn. Most of these methods are named in the pattern of add-, modify-, on-, which correspond to the three types of api.ApplyPluginsType. Different types receive different fn parameters, see the register section for details.
Note: All fn mentioned below can be synchronous or asynchronous (just return a Promise). All fn can be replaced by:
{
  fn,
  name?: string,
  before?: string | string[],
  stage: number,
}For the purpose of each parameter, see tapable.
addBeforeBabelPlugins 
Add additional Babel plugins. The passed fn requires no parameters and should return a Babel plugin or an array of plugins.
api.addBeforeBabelPlugins(() => {
  // Return a Babel plugin (example from Babel official website)
  return () => {
    visitor: {
      Identifier(path)
      {
        const name = path.node.name;
        path.node.name = name.split("").reverse().join("");
      }
    }
  }
})addBeforeBabelPresets 
Add additional Babel presets. The passed fn requires no parameters and should return a Babel preset or an array of presets.
api.addBeforeBabelPresets(() => {
  // Return a Babel preset
  return () => {
    return {
      plugins: ["Babel_Plugin_A", "Babel_Plugin_B"]
    }
  }
})addBeforeMiddlewares 
Add middleware before webpack-dev-middleware. The passed fn requires no parameters and should return an express middleware or an array of middlewares.
api.addBeforeMiddlewares(() => {
  return (req, res, next) => {
    if (false) {
      res.end('end');
    }
    next();
  }
})addEntryCode 
Add code at the end of the entry file (after render). The passed fn requires no parameters and should return a string or an array of strings.
api.addEntryCode(() => `console.log('I am after render!')`);addEntryCodeAhead 
Add code at the beginning of the entry file (before render, after imports). The passed fn requires no parameters and should return a string or an array of strings.
api.addEntryCodeAhead(() => `console.log('I am before render!')`)addEntryImports 
Add import statements to the entry file (at the end of imports). The passed fn requires no parameters and should return a {source: string, specifier?: string} object or an array of such objects.
api.addEntryImports(() => ({
  source: '/modulePath/xxx.js',
  specifier: 'moduleName'
}))addEntryImportsAhead 
Add import statements to the entry file (at the beginning of imports). The passed fn requires no parameters and should return a {source: string, specifier?: string} object or an array of such objects.
api.addEntryImportsAhead(() => ({
  source: 'anyPackage'
}))addExtraBabelPlugins 
Add additional Babel plugins. The passed fn requires no parameters and should return a Babel plugin or an array of plugins.
addExtraBabelPresets 
Add additional Babel presets. The passed fn requires no parameters and should return a Babel preset or an array of presets.
addHTMLHeadScripts 
Add Script tags to the HTML <head> element. The passed fn requires no parameters and should return a string (the code to be added) or { async?: boolean, charset?: string, crossOrigin?: string | null, defer?: boolean, src?: string, type?: string, content?: string } or an array of them.
api.addHTMLHeadScripts(() => `console.log('I am in HTML-head')`)addHTMLLinks 
Add Link tags to HTML. The passed fn requires no parameters and returns an object or an array of objects with the following interface:
{
  as?: string,
  crossOrigin: string | null,
  disabled?: boolean,
  href?: string,
  hreflang?: string,
  imageSizes?: string,
  imageSrcset?: string,
  integrity?: string,
  media?: string,
  referrerPolicy?: string,
  rel?: string,
  rev?: string,
  target?: string,
  type?: string
}addHTMLMetas 
Add Meta tags to HTML. The passed fn requires no parameters and returns an object or an array of objects with the following interface:
{
  content?: string,
  'http-equiv'?: string,
  name?: string,
  scheme?: string
}For example,
api.addHTMLMetas(() => [
  {
    'http-equiv': 'Cache-Control',
    'content': 'no-store, no-cache, must-revalidate'
  },
  {
    'http-equiv': 'Pragma',
    'content': 'no-cache'
  },
  {
    'http-equiv': 'Expires',
    'content': '0'
  }
]);addHTMLScripts 
Add Script tags to the HTML footer. The passed fn requires no parameters and returns an object with the same interface as addHTMLHeadScripts.
addHTMLStyles 
Add Style tags to HTML. The passed fn requires no parameters and returns a string (the code inside the style tag) or { type?: string, content?: string }, or an array of them.
addLayouts 
Add global layout components. The passed fn requires no parameters and returns { id?: string, file: string }.
addMiddlewares 
Add middleware after the route middleware. The passed fn requires no parameters and returns express middleware.
addPolyfillImports 
Add polyfill imports to be executed at the very beginning of the entire application. The passed fn requires no parameters and returns { source: string, specifier?: string }.
addPrepareBuildPlugins 
addRuntimePlugin 
Add runtime plugins. The passed fn requires no parameters and returns a string representing the plugin path.
addRuntimePluginKey 
Add runtime plugin keys. The passed fn requires no parameters and returns a string representing the plugin path.
addTmpGenerateWatcherPaths 
Add watch paths that will regenerate temporary files when changed. The passed fn requires no parameters and returns a string representing the path to watch.
addOnDemandDeps 
Add on-demand dependencies that will be checked for installation when the project starts:
  api.addOnDemandDeps(() => [{ name: '@swc/core', version: '^1.0.0', dev: true }])chainWebpack 
Modify webpack configuration through webpack-chain. Pass in a fn that doesn't need to return a value. It will receive two parameters:
memocorresponds to webpack-chain's configargs: { webpack, env }whereargs.webpackis the webpack instance andargs.envrepresents the current runtime environment.
e.g.
api.chainWebpack((memo, { webpack, env }) => {
  // set alias
  memo.resolve.alias.set('a', 'path/to/a');
  // Delete progress bar plugin
  memo.plugins.delete('progress');
})modifyAppData 
Modify app metadata. The passed fn receives appData and returns it.
api.modifyAppData((memo) => {
  memo.foo = 'foo';
  return memo;
})modifyBundlerChain 
modifyBundlerChain is used to call rspack-chain to modify Rspack configuration. rspack-chain is a utility library for configuring Rspack. It provides a chainable API that makes configuring Rspack more flexible. By using rspack-chain, you can more conveniently modify and extend Rspack configuration without directly manipulating complex configuration objects.
You can refer to Configure Rspack.
- Type:
 
type ModifyBundlerChainUtils = {
  environment: EnvironmentContext;
  env: NodeEnv;
  isDev: boolean;
  isProd: boolean;
  target: RsbuildTarget;
  isServer: boolean;
  isWebWorker: boolean;
  CHAIN_ID: ChainIdentifier;
  HtmlPlugin: typeof import('html-rspack-plugin');
  bundler: {
    BannerPlugin: rspack.BannerPlugin;
    DefinePlugin: rspack.DefinePlugin;
    IgnorePlugin: rspack.IgnorePlugin;
    ProvidePlugin: rspack.ProvidePlugin;
    HotModuleReplacementPlugin: rspack.HotModuleReplacementPlugin;
  };
};
function ModifyBundlerChain(
  callback: (
    chain: RspackChain,
    utils: ModifyBundlerChainUtils,
  ) => Promise<void> | void,
): void;- Example:
 
import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer';
api.modifyBundlerChain((chain, utils) => {
  if (utils.env === 'development') {
    chain.devtool('eval');
  }
  
  chain.plugin('bundle-analyze').use(BundleAnalyzerPlugin);
});modifyConfig 
Modify configuration. Compared to user configuration, this is the final configuration passed to WinJS. The passed fn receives config as the first parameter and returns it. Additionally, fn can receive { paths } as the second parameter. paths contains various paths of WinJS.
api.modifyConfig((memo, { paths }) => {
  memo.alias = {
    ...memo.alias,
    '@': paths.absSrcPath
  }
  return memo;
})modifyDefaultConfig 
Modify default configuration. The passed fn receives config and returns it.
modifyHTML 
Modify HTML based on cheerio's AST. The passed fn receives cheerioAPI and returns it. Additionally, fn can receive { path } as its second parameter, which represents the route path.
api.modifyHTML(($, { path }) => {
  $('h2').addClass('welcome');
  return $;
})modifyHTMLFavicon 
Modify the HTML favicon path. The passed fn receives the original favicon path (string type) and returns it.
modifyPaths 
Modify paths, such as absOutputPath and absTmpPath. The passed fn receives paths and returns it.
The paths interface is as follows:
paths:{
  cwd?: string;
  absSrcPath?: string;
  absPagesPath?: string;
  absTmpPath?: string;
  absNodeModulesPath?: string;
  absOutputPath?: string;
}modifyRendererPath 
Modify renderer path. The passed fn receives the original path (string type) and returns it.
modifyServerRendererPath 
Modify server renderer path. The passed fn receives the original path (string type) and returns it.
modifyRoutes 
Modify routes. The passed fn receives an id-route map and returns it. The route interface is as follows:
interface IRoute {
  path: string;
  file?: string;
  id: string;
  parentId?: string;
  
  [key: string]: any;
}e.g.
api.modifyRoutes((memo) => {
  Object.keys(memo).forEach((id) => {
    const route = memo[id];
    if (route.path === '/') {
      route.path = '/redirect'
    }
  });
  return memo;
})modifyRsbuildConfig 
Modify the configuration options passed to Rsbuild. You can directly modify the passed config object or return a new object to replace the passed object.
You can refer to Configure Rsbuild.
- Type:
 
import { RsbuildConfig, Rspack, rspack } from '@rsbuild/core';
export enum Env {
  development = 'development',
  production = 'production',
}
function ModifyRsbuildConfig(
  callback: (
    config: RsbuildConfig,
    args: {
      env: Env;
      rspack: typeof rspack
    },
  ) => MaybePromise<RsbuildConfig | void>,
): void;- Example: Set a default value for a configuration option:
 
api.modifyRsbuildConfig((config) => {
  config.html ||= {};
  config.html.title = 'My Default Title';
  
  return config;
});modifyRspackConfig 
Modify the final Rspack configuration. You can directly modify the passed config object or return a new object to replace the passed object.
You can refer to Configure Rspack.
- Type:
 
type ModifyRspackConfigUtils = {
  environment: EnvironmentContext;
  env: NodeEnv;
  isDev: boolean;
  isProd: boolean;
  target: RsbuildTarget;
  isServer: boolean;
  isWebWorker: boolean;
  rspack: Rspack;
};
function ModifyRspackConfig(
  callback: (
    config: RspackConfig,
    utils: ModifyRspackConfigUtils,
  ) => Promise<RspackConfig | void> | RspackConfig | void,
): void;- Example:
 
api.modifyRspackConfig((config, utils) => {
  if (utils.env === 'development') {
    config.devtool = 'eval-cheap-source-map';
  }
});modifyTSConfig 
Modify the content of the tsconfig file in the temporary directory.
api.modifyTSConfig((memo) => {
  memo.compilerOptions.paths['foo'] = ['bar'];
  return memo;
});modifyViteConfig 
Modify the final Vite configuration. The passed fn receives Vite's Config object as the first parameter and returns it. Additionally, fn can receive { env } as the second parameter to get the current environment.
api.modifyViteConfig((memo, { env }) => {
  if (env === 'development') {
    // do something
  }
  return memo;
})modifyWebpackConfig 
Modify the final webpack configuration. The passed fn receives webpack's Config object as the first parameter and returns it. Additionally, fn can receive { webpack, env } as the second parameter, where webpack is the webpack instance and env represents the current environment.
api.modifyWebpackConfig((memo, { webpack, env }) => {
  // do something
  
  return memo;
})onBeforeCompiler 
After generate, before webpack / vite / rsbuild compiler. The passed fn receives no parameters.
onBeforeMiddleware 
Provides the ability to execute custom middleware before all other middleware is executed internally by the server. This can be used to define custom handlers, for example:
api.onBeforeMiddleware(({ app }) => {
  app.get('/some/path', function (req, res) {
    res.json({ custom: 'response' });
  });
});onBuildComplete 
When build is complete. The passed fn receives { isFirstCompile: boolean, stats, time: number, err?: Error } as parameters.
onBuildHtmlComplete 
After build is complete and HTML construction is finished. The passed fn receives parameters with the following interface:
args: {
  htmlFiles?: Array<{ path: string, content: string }>
}- path: HTML file path
 - content: HTML file content
 
For example:
htmlFiles: [
  {
    path: 'index.html',
    content: '<!DOCTYPE html><html lang="zh-CN"><head>\n' +
      '<meta charset="utf-8">\n' +
      '<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">\n' +
      '<meta http-equiv="X-UA-Compatible" content="ie=edge">\n' +
      '<meta name="renderer" content="webkit">\n' +
      '<meta name="mobile-web-app-capable" content="yes">\n' +
      '<meta name="apple-mobile-web-app-status-bar-style" content="black">\n' +
      '<meta name="telephone=no" content="format-detection">\n' +
      '<meta name="email=no" content="format-detection">\n' +
      '<style>\n' +
      '  html,\n' +
      '  body,\n' +
      '  #root {\n' +
      '      height: 100%;\n' +
      '      margin: 0;\n' +
      '      padding: 0;\n' +
      '  }</style>\n' +
      '</head>\n' +
      '<body>\n' +
      '\n' +
      '  <div id="root">\n' +
      '<div style="\n' +
      '          display: flex;\n' +
      '          flex-direction: column;\n' +
      '          align-items: center;\n' +
      '          justify-content: center;\n' +
      '          height: 100%;\n' +
      '          min-height: 362px;\n' +
      '        ">\n' +
      '    <div class="loading-title">\n' +
      '      Loading resources\n' +
      '    </div>\n' +
      '    <div class="loading-sub-title">\n' +
      '      Initial resource loading may take some time, please wait patiently\n' +
      '    </div>\n' +
      '</div>\n' +
      '</div>\n' +
      '\n' +
      '<script src="/win.js"></script>\n' +
      '\n' +
      '</body></html>'
  }
]onCheck 
During check, executed before onStart. The passed fn receives no parameters.
onCheckCode 
When checking code. The passed fn receives parameters with the following interface:
args: {
  file: string;
  code: string;
  isFromTmp: boolean;
  imports: {
    source: string;
    loc: any;
    default: string;
    namespace: string;
    kind: babelImportKind;
    specifiers: Record<string, { name: string; kind: babelImportKind }>;
  }[];
  exports: any[];
  cjsExports: string[];
}onCheckConfig 
When checking config. The passed fn receives { config, userConfig } as parameters, which represent the actual configuration and user configuration respectively.
onCheckPkgJSON 
When checking package.json. The passed fn receives {origin?, current} as parameters. Both types are package.json objects.
onDevCompileDone 
When dev is complete. The passed fn receives parameters with the following interface:
args: {
  isFirstCompile: boolean;
  stats: any;
  time: number;
}onGenerateFiles 
When generating temporary files, frequently triggered as files change, with caching. The passed fn receives parameters with the following interface:
args: {
  isFirstTime?: boolean;
  files?: {
    event: string;
    path: string;
  } | null;
}onPatchRoute 
Match a single route, can modify the route and patch it.
onPkgJSONChanged 
When package.json changes. The passed fn receives {origin?, current} as parameters. Both types are package.json objects.
onPrepareBuildSuccess 
onStart 
When starting. The passed fn receives no parameters.
writeTmpFile 
The type parameter type for api.writeTmpFile().
- content: The text content to write. If there is content, templates will not be used.
 - context: Template context.
 - noPluginDir: Whether to use the plugin name as the directory.
 - path: The path of the file to write.
 - tpl: Use template string, will be used if there is no template path.
 - tplPath: The path of the template file to use.
 
Properties 
Properties that can be directly accessed from the api, some of which come from the service.
appData 
args 
Command line arguments with the command itself removed.
e.g.
$ win dev --foo, args is{ _:[], foo: true }$ win g page index --typescript --less, args is{ _: [ 'page', 'index''], typescript: true, less: true }
config 
The final configuration (depending on when you access it, it may be the current collected final configuration).
cwd 
Current path.
env 
i.e., process.env.NODE_ENV which can be development, production, or test.
logger 
Plugin logger object containing { log, info, debug, error, warn, profile }, all of which are methods. api.logger.profile can be used for performance timing recording.
api.logger.profile('barId');
setTimeout(() => {
  api.logger.profile('barId');
})
// profile - barId Completed in 6254msname 
The name of the current command, for example $ win dev, name would be dev.
paths 
Project-related paths:
absNodeModulesPath, absolute path to node_modules directoryabsOutputPath, output path, defaults to ./distabsPagesPath, absolute path to pages directoryabsSrcPath, absolute path to src directory. Note that the src directory is optional; if there is no src directory, absSrcPath is equivalent to cwdabsTmpPath, absolute path to temporary directorycwd, current path
Note: Cannot be obtained during the registration phase. Therefore, it cannot be accessed directly in plugins and must be used in hooks.
pkg 
The current project's package.json object.
pkgPath 
The absolute path to the current project's package.json.
plugin 
The current plugin object.
typePlugin type, either preset or pluginpathPlugin pathidPlugin idkeyPlugin keyconfigPlugin configurationenableByPlugin enablement method
Note: The plugin object used during the registration phase is the object before you describe.
service 
WinJS's Service instance. Usually not needed unless you know why.
userConfig 
User configuration read from .winrc or config/config, without any processing by defaultConfig or plugins. Can be used during the registration phase.
ApplyPluginsType 
The type parameter type for api.applyPlugins(). Contains:
- add
 - modify
 - event
 
ConfigChangeType 
The type for config.onChange provided to api.describe(), currently includes two types:
- restart, restart the dev process, is the default value
 - regenerateTmpFiles, regenerate temporary files
 
EnableBy 
Plugin enablement methods, includes three types:
- register
 - config
 
ServiceStage 
WinJS service runtime stages. Has the following stages:
- uninitialized
 - init
 - initPresets
 - initPlugins
 - resolveConfig
 - collectAppData
 - onCheck
 - onStart
 - runCommand
 
