@modern-js/plugin-v2 0.0.0-next-20241113090110

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.
Files changed (91) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +26 -0
  3. package/dist/cjs/cli/api.js +107 -0
  4. package/dist/cjs/cli/context.js +75 -0
  5. package/dist/cjs/cli/hooks.js +65 -0
  6. package/dist/cjs/cli/index.js +43 -0
  7. package/dist/cjs/cli/run/config/createLoadedConfig.js +99 -0
  8. package/dist/cjs/cli/run/config/createResolvedConfig.js +40 -0
  9. package/dist/cjs/cli/run/config/loadConfig.js +117 -0
  10. package/dist/cjs/cli/run/create.js +125 -0
  11. package/dist/cjs/cli/run/index.js +29 -0
  12. package/dist/cjs/cli/run/run.js +58 -0
  13. package/dist/cjs/cli/run/types.js +16 -0
  14. package/dist/cjs/cli/run/utils/checkIsDuplicationPlugin.js +45 -0
  15. package/dist/cjs/cli/run/utils/commander.js +50 -0
  16. package/dist/cjs/cli/run/utils/createFileWatcher.js +114 -0
  17. package/dist/cjs/cli/run/utils/initAppDir.js +49 -0
  18. package/dist/cjs/cli/run/utils/loadEnv.js +53 -0
  19. package/dist/cjs/cli/run/utils/mergeConfig.js +62 -0
  20. package/dist/cjs/hooks.js +69 -0
  21. package/dist/cjs/index.js +38 -0
  22. package/dist/cjs/manager.js +141 -0
  23. package/dist/cjs/types/cli/api.js +16 -0
  24. package/dist/cjs/types/cli/context.js +16 -0
  25. package/dist/cjs/types/cli/hooks.js +16 -0
  26. package/dist/cjs/types/cli/index.js +16 -0
  27. package/dist/cjs/types/cli/plugin.js +16 -0
  28. package/dist/cjs/types/hooks.js +16 -0
  29. package/dist/cjs/types/index.js +24 -0
  30. package/dist/cjs/types/plugin.js +16 -0
  31. package/dist/cjs/types/utils.js +16 -0
  32. package/dist/esm/index.js +1499 -0
  33. package/dist/esm-node/cli/api.js +83 -0
  34. package/dist/esm-node/cli/context.js +40 -0
  35. package/dist/esm-node/cli/hooks.js +41 -0
  36. package/dist/esm-node/cli/index.js +14 -0
  37. package/dist/esm-node/cli/run/config/createLoadedConfig.js +74 -0
  38. package/dist/esm-node/cli/run/config/createResolvedConfig.js +16 -0
  39. package/dist/esm-node/cli/run/config/loadConfig.js +80 -0
  40. package/dist/esm-node/cli/run/create.js +101 -0
  41. package/dist/esm-node/cli/run/index.js +5 -0
  42. package/dist/esm-node/cli/run/run.js +34 -0
  43. package/dist/esm-node/cli/run/types.js +0 -0
  44. package/dist/esm-node/cli/run/utils/checkIsDuplicationPlugin.js +21 -0
  45. package/dist/esm-node/cli/run/utils/commander.js +24 -0
  46. package/dist/esm-node/cli/run/utils/createFileWatcher.js +80 -0
  47. package/dist/esm-node/cli/run/utils/initAppDir.js +15 -0
  48. package/dist/esm-node/cli/run/utils/loadEnv.js +19 -0
  49. package/dist/esm-node/cli/run/utils/mergeConfig.js +38 -0
  50. package/dist/esm-node/hooks.js +44 -0
  51. package/dist/esm-node/index.js +9 -0
  52. package/dist/esm-node/manager.js +117 -0
  53. package/dist/esm-node/types/cli/api.js +0 -0
  54. package/dist/esm-node/types/cli/context.js +0 -0
  55. package/dist/esm-node/types/cli/hooks.js +0 -0
  56. package/dist/esm-node/types/cli/index.js +0 -0
  57. package/dist/esm-node/types/cli/plugin.js +0 -0
  58. package/dist/esm-node/types/hooks.js +0 -0
  59. package/dist/esm-node/types/index.js +2 -0
  60. package/dist/esm-node/types/plugin.js +0 -0
  61. package/dist/esm-node/types/utils.js +0 -0
  62. package/dist/types/cli/api.d.ts +7 -0
  63. package/dist/types/cli/context.d.ts +18 -0
  64. package/dist/types/cli/hooks.d.ts +39 -0
  65. package/dist/types/cli/index.d.ts +6 -0
  66. package/dist/types/cli/run/config/createLoadedConfig.d.ts +6 -0
  67. package/dist/types/cli/run/config/createResolvedConfig.d.ts +3 -0
  68. package/dist/types/cli/run/config/loadConfig.d.ts +25 -0
  69. package/dist/types/cli/run/create.d.ts +7 -0
  70. package/dist/types/cli/run/index.d.ts +6 -0
  71. package/dist/types/cli/run/run.d.ts +2 -0
  72. package/dist/types/cli/run/types.d.ts +29 -0
  73. package/dist/types/cli/run/utils/checkIsDuplicationPlugin.d.ts +1 -0
  74. package/dist/types/cli/run/utils/commander.d.ts +5 -0
  75. package/dist/types/cli/run/utils/createFileWatcher.d.ts +2 -0
  76. package/dist/types/cli/run/utils/initAppDir.d.ts +1 -0
  77. package/dist/types/cli/run/utils/loadEnv.d.ts +1 -0
  78. package/dist/types/cli/run/utils/mergeConfig.d.ts +2 -0
  79. package/dist/types/hooks.d.ts +3 -0
  80. package/dist/types/index.d.ts +4 -0
  81. package/dist/types/manager.d.ts +2 -0
  82. package/dist/types/types/cli/api.d.ts +42 -0
  83. package/dist/types/types/cli/context.d.ts +40 -0
  84. package/dist/types/types/cli/hooks.d.ts +41 -0
  85. package/dist/types/types/cli/index.d.ts +3 -0
  86. package/dist/types/types/cli/plugin.d.ts +6 -0
  87. package/dist/types/types/hooks.d.ts +10 -0
  88. package/dist/types/types/index.d.ts +3 -0
  89. package/dist/types/types/plugin.d.ts +40 -0
  90. package/dist/types/types/utils.d.ts +5 -0
  91. package/package.json +85 -0
@@ -0,0 +1,38 @@
1
+ import { ensureArray, isOverriddenConfigKey } from "@modern-js/utils";
2
+ import { isFunction, mergeWith } from "@modern-js/utils/lodash";
3
+ const mergeConfig = (configs) => mergeWith({}, ...configs, (target, source, key) => {
4
+ if (key === "designSystem" || key === "tailwindcss" && typeof source === "object") {
5
+ return mergeWith({}, target !== null && target !== void 0 ? target : {}, source !== null && source !== void 0 ? source : {});
6
+ }
7
+ if (isOverriddenConfigKey(key)) {
8
+ return source !== null && source !== void 0 ? source : target;
9
+ }
10
+ if (Array.isArray(target) || Array.isArray(source)) {
11
+ if (target === void 0) {
12
+ return source;
13
+ }
14
+ if (source === void 0) {
15
+ return target;
16
+ }
17
+ return [
18
+ ...ensureArray(target),
19
+ ...ensureArray(source)
20
+ ];
21
+ }
22
+ if (isFunction(target) || isFunction(source)) {
23
+ if (source === void 0) {
24
+ return target;
25
+ }
26
+ if (target === void 0) {
27
+ return source;
28
+ }
29
+ return [
30
+ target,
31
+ source
32
+ ];
33
+ }
34
+ return void 0;
35
+ });
36
+ export {
37
+ mergeConfig
38
+ };
@@ -0,0 +1,44 @@
1
+ function createAsyncHook() {
2
+ const callbacks = [];
3
+ const tap = (cb) => {
4
+ callbacks.push(cb);
5
+ };
6
+ const call = async (...params) => {
7
+ for (const callback of callbacks) {
8
+ const result = await callback(...params);
9
+ if (result !== void 0) {
10
+ params[0] = result;
11
+ }
12
+ }
13
+ return params[0] || [];
14
+ };
15
+ return {
16
+ tap,
17
+ call
18
+ };
19
+ }
20
+ function createCollectAsyncHook() {
21
+ const callbacks = [];
22
+ const tap = (cb) => {
23
+ callbacks.push(cb);
24
+ };
25
+ const call = async (...params) => {
26
+ const results = [];
27
+ for (const callback of callbacks) {
28
+ const result = await callback(...params);
29
+ if (result !== void 0) {
30
+ params[0] = result;
31
+ results.push(result);
32
+ }
33
+ }
34
+ return results;
35
+ };
36
+ return {
37
+ tap,
38
+ call
39
+ };
40
+ }
41
+ export {
42
+ createAsyncHook,
43
+ createCollectAsyncHook
44
+ };
@@ -0,0 +1,9 @@
1
+ import { createPluginManager } from "./manager";
2
+ import { createAsyncHook, createCollectAsyncHook } from "./hooks";
3
+ export * from "./cli";
4
+ export * from "./types";
5
+ export {
6
+ createAsyncHook,
7
+ createCollectAsyncHook,
8
+ createPluginManager
9
+ };
@@ -0,0 +1,117 @@
1
+ import { createDebugger, isFunction, logger } from "@modern-js/utils";
2
+ const debug = createDebugger("plugin-v2");
3
+ function validatePlugin(plugin) {
4
+ const type = typeof plugin;
5
+ if (type !== "object" || plugin === null) {
6
+ throw new Error(`Expect CLI Plugin instance to be an object, but got ${type}.`);
7
+ }
8
+ if (isFunction(plugin.setup)) {
9
+ return;
10
+ }
11
+ throw new Error(`Expect CLI Plugin plugin.setup to be a function, but got ${type}.`);
12
+ }
13
+ function createPluginManager() {
14
+ const plugins = /* @__PURE__ */ new Map();
15
+ const dependencies = /* @__PURE__ */ new Map();
16
+ const addDependency = (plugin, dependency, type) => {
17
+ if (!dependencies.has(dependency)) {
18
+ dependencies.set(dependency, {
19
+ pre: /* @__PURE__ */ new Map(),
20
+ post: /* @__PURE__ */ new Map()
21
+ });
22
+ }
23
+ if (type === "pre") {
24
+ dependencies.get(plugin).pre.set(dependency, {
25
+ name: dependency,
26
+ isUse: false
27
+ });
28
+ } else if (type === "post") {
29
+ dependencies.get(plugin).post.set(dependency, {
30
+ name: dependency
31
+ });
32
+ } else if (type === "use") {
33
+ if (!dependencies.get(plugin).post.has(dependency)) {
34
+ dependencies.get(plugin).pre.set(dependency, {
35
+ name: dependency,
36
+ isUse: true
37
+ });
38
+ }
39
+ }
40
+ };
41
+ const addPlugin = (newPlugin) => {
42
+ if (!newPlugin) {
43
+ return;
44
+ }
45
+ validatePlugin(newPlugin);
46
+ const { name, usePlugins = [], pre = [], post = [] } = newPlugin;
47
+ if (plugins.has(name)) {
48
+ logger.warn(`Plugin ${name} already exists.`);
49
+ return;
50
+ }
51
+ plugins.set(name, newPlugin);
52
+ dependencies.set(name, {
53
+ pre: /* @__PURE__ */ new Map(),
54
+ post: /* @__PURE__ */ new Map()
55
+ });
56
+ pre.forEach((dep) => {
57
+ addDependency(name, dep, "pre");
58
+ });
59
+ post.forEach((dep) => {
60
+ addDependency(name, dep, "post");
61
+ });
62
+ usePlugins.forEach((plugin) => {
63
+ if (!plugins.has(plugin.name)) {
64
+ addPlugin(plugin);
65
+ }
66
+ addDependency(name, plugin.name, "use");
67
+ });
68
+ };
69
+ const addPlugins = (newPlugins) => {
70
+ for (const newPlugin of newPlugins) {
71
+ addPlugin(newPlugin);
72
+ }
73
+ };
74
+ const getPlugins = () => {
75
+ const visited = /* @__PURE__ */ new Set();
76
+ const temp = /* @__PURE__ */ new Set();
77
+ let result = [];
78
+ const visit = (name) => {
79
+ if (temp.has(name)) {
80
+ throw new Error(`Circular dependency detected: ${name}`);
81
+ }
82
+ if (!visited.has(name)) {
83
+ temp.add(name);
84
+ const { pre } = dependencies.get(name);
85
+ Array.from(pre.values()).filter((dep) => !dep.isUse).forEach((dep) => visit(dep.name));
86
+ Array.from(pre.values()).filter((dep) => dep.isUse).forEach((dep) => visit(dep.name));
87
+ temp.delete(name);
88
+ visited.add(name);
89
+ result.push(plugins.get(name));
90
+ }
91
+ };
92
+ plugins.forEach((_, name) => {
93
+ const { post } = dependencies.get(name);
94
+ post.forEach((dep) => {
95
+ if (!dependencies.get(dep.name).pre.has(name)) {
96
+ dependencies.get(dep.name).pre.set(name, {
97
+ name,
98
+ isUse: false
99
+ });
100
+ }
101
+ });
102
+ });
103
+ plugins.forEach((_, name) => {
104
+ visit(name);
105
+ });
106
+ result = result.filter((result2) => result2);
107
+ debug("CLI Plugins:", result.map((p) => p.name));
108
+ return result;
109
+ };
110
+ return {
111
+ getPlugins,
112
+ addPlugins
113
+ };
114
+ }
115
+ export {
116
+ createPluginManager
117
+ };
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1,2 @@
1
+ export * from "./cli";
2
+ export * from "./hooks";
File without changes
File without changes
@@ -0,0 +1,7 @@
1
+ import type { CLIPluginAPI } from '../types/cli/api';
2
+ import type { InternalContext } from '../types/cli/context';
3
+ import type { PluginManager } from '../types/plugin';
4
+ export declare function initPluginAPI<Config, NormalizedConfig, ExtendsHooksKey extends string>({ context, }: {
5
+ context: InternalContext<Config, NormalizedConfig, ExtendsHooksKey>;
6
+ pluginManager: PluginManager;
7
+ }): CLIPluginAPI<Config, NormalizedConfig>;
@@ -0,0 +1,18 @@
1
+ import type { AppContext, InternalContext } from '../types/cli/context';
2
+ import type { CLIPlugin } from '../types/cli/plugin';
3
+ interface ContextParams<Config, NormalizedConfig> {
4
+ appContext: AppContext<Config, NormalizedConfig>;
5
+ config: Config;
6
+ normalizedConfig: NormalizedConfig;
7
+ }
8
+ export declare function initAppContext<Config, NormalizedConfig>(params: {
9
+ packageName: string;
10
+ configFile: string;
11
+ command: string;
12
+ appDirectory: string;
13
+ plugins: CLIPlugin<Config, NormalizedConfig>[];
14
+ srcDir?: string;
15
+ distDir?: string;
16
+ }): AppContext<Config, NormalizedConfig>;
17
+ export declare function createContext<Config, NormalizedConfig, ExtendsHooksKey extends string>({ appContext, config, normalizedConfig, }: ContextParams<Config, NormalizedConfig>): Promise<InternalContext<Config, NormalizedConfig, ExtendsHooksKey>>;
18
+ export {};
@@ -0,0 +1,39 @@
1
+ import type { ModifyBundlerChainFn, ModifyRsbuildConfigFn, ModifyRspackConfigFn, ModifyWebpackChainFn, ModifyWebpackConfigFn, OnAfterBuildFn, OnAfterCreateCompilerFn, OnBeforeBuildFn, OnBeforeCreateCompilerFn } from '@rsbuild/core';
2
+ import type { AddCommandFn, AddWatchFilesFn, ConfigFn, ModifyConfigFn, ModifyHtmlPartialsFn, ModifyResolvedConfigFn, OnAfterDeployFn, OnAfterDevFn, OnBeforeDeployFn, OnBeforeDevFn, OnBeforeExitFn, OnBeforeRestartFn, OnFileChangedFn, OnPrepareFn } from '../types/cli/hooks';
3
+ import type { DeepPartial } from '../types/utils';
4
+ export declare function initHooks<Config, NormalizedConfig>(): {
5
+ /**
6
+ * add config for this cli plugin
7
+ */
8
+ config: import("..").CollectAsyncHook<ConfigFn<DeepPartial<Config>>>;
9
+ /**
10
+ * @private
11
+ * modify config for this cli plugin
12
+ */
13
+ modifyConfig: import("..").AsyncHook<ModifyConfigFn<Config>>;
14
+ /**
15
+ * modify final config
16
+ */
17
+ modifyResolvedConfig: import("..").AsyncHook<ModifyResolvedConfigFn<NormalizedConfig>>;
18
+ modifyRsbuildConfig: import("..").AsyncHook<ModifyRsbuildConfigFn>;
19
+ modifyBundlerChain: import("..").AsyncHook<ModifyBundlerChainFn>;
20
+ modifyRspackConfig: import("..").AsyncHook<ModifyRspackConfigFn>;
21
+ modifyWebpackChain: import("..").AsyncHook<ModifyWebpackChainFn>;
22
+ modifyWebpackConfig: import("..").AsyncHook<ModifyWebpackConfigFn>;
23
+ modifyHtmlPartials: import("..").AsyncHook<ModifyHtmlPartialsFn>;
24
+ addCommand: import("..").AsyncHook<AddCommandFn>;
25
+ addWatchFiles: import("..").CollectAsyncHook<AddWatchFilesFn>;
26
+ onPrepare: import("..").AsyncHook<OnPrepareFn>;
27
+ onFileChanged: import("..").AsyncHook<OnFileChangedFn>;
28
+ onBeforeRestart: import("..").AsyncHook<OnBeforeRestartFn>;
29
+ onBeforeCreateCompiler: import("..").AsyncHook<OnBeforeCreateCompilerFn>;
30
+ onAfterCreateCompiler: import("..").AsyncHook<OnAfterCreateCompilerFn>;
31
+ onBeforeBuild: import("..").AsyncHook<OnBeforeBuildFn>;
32
+ onAfterBuild: import("..").AsyncHook<OnAfterBuildFn>;
33
+ onBeforeDev: import("..").AsyncHook<OnBeforeDevFn>;
34
+ onAfterDev: import("..").AsyncHook<OnAfterDevFn>;
35
+ onBeforeDeploy: import("..").AsyncHook<OnBeforeDeployFn>;
36
+ onAfterDeploy: import("..").AsyncHook<OnAfterDeployFn>;
37
+ onBeforeExit: import("..").AsyncHook<OnBeforeExitFn>;
38
+ };
39
+ export type Hooks<Config, NormalizedConfig> = ReturnType<typeof initHooks<Config, NormalizedConfig>>;
@@ -0,0 +1,6 @@
1
+ export { initPluginAPI } from './api';
2
+ export { initAppContext } from './context';
3
+ export { initHooks } from './hooks';
4
+ export { cli } from './run';
5
+ export { initAppDir } from './run/utils/initAppDir';
6
+ export { createLoadedConfig } from '../cli/run/config/createLoadedConfig';
@@ -0,0 +1,6 @@
1
+ import type { LoadedConfig } from '../types';
2
+ /**
3
+ * Assign the pkg config into the user config.
4
+ */
5
+ export declare function assignPkgConfig<T>(userConfig: T, pkgConfig: T): {} & T;
6
+ export declare function createLoadedConfig<T>(appDirectory: string, configFilePath: string, packageJsonConfig?: string, loadedConfig?: T): Promise<LoadedConfig<T>>;
@@ -0,0 +1,3 @@
1
+ import type { DeepPartial } from '../../../types/utils';
2
+ import type { LoadedConfig } from '../types';
3
+ export declare const createResolveConfig: <Config, NormalizedConfig>(loaded: LoadedConfig<Config>, configs: DeepPartial<Config>[]) => Promise<NormalizedConfig>;
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Get user config from package.json.
3
+ * @param appDirectory - App root directory.
4
+ * @returns modernConfig or undefined
5
+ */
6
+ export declare const getPackageConfig: <T>(appDirectory: string, packageJsonConfig: string) => T | undefined;
7
+ export declare const getConfigFilePath: (appDirectory: string, configFilePath: string) => string;
8
+ /**
9
+ *
10
+ * @param targetDir target dir
11
+ * @param overtime Unit of second
12
+ */
13
+ export declare const clearFilesOverTime: (targetDir: string, overtime: number) => Promise<void>;
14
+ /**
15
+ * Parse and load user config file, support extensions like .ts, mjs, js, ejs.
16
+ * @param appDirectory - App root directory, from which start search user config file.
17
+ * @param configFile - Specific absolute config file path.
18
+ * @returns Object contain config file path, user config object and dependency files used by config file.
19
+ */
20
+ export declare const loadConfig: <T>(appDirectory: string, configFile: string, packageJsonConfig?: string, loadedConfig?: T) => Promise<{
21
+ packageName: string;
22
+ configFile: string;
23
+ config?: T;
24
+ pkgConfig?: T;
25
+ }>;
@@ -0,0 +1,7 @@
1
+ import type { CLIRunOptions } from './types';
2
+ export declare const createCli: <Config, NormalizedConfig, ExtendsHooksKey extends string>() => {
3
+ init: (options: CLIRunOptions<Config>) => Promise<{
4
+ appContext: import("../..").InternalContext<Config, NormalizedConfig, ExtendsHooksKey>;
5
+ }>;
6
+ run: (options: CLIRunOptions<Config>) => Promise<void>;
7
+ };
@@ -0,0 +1,6 @@
1
+ export declare const cli: {
2
+ init: (options: import("./types").CLIRunOptions<unknown>) => Promise<{
3
+ appContext: import("../..").InternalContext<unknown, unknown, string>;
4
+ }>;
5
+ run: (options: import("./types").CLIRunOptions<unknown>) => Promise<void>;
6
+ };
@@ -0,0 +1,2 @@
1
+ import type { CLIOptions } from './types';
2
+ export declare const run: <Config>(options: CLIOptions<Config>) => Promise<void>;
@@ -0,0 +1,29 @@
1
+ import type { Plugin } from '../../types/plugin';
2
+ export interface CLIOptions<Config> {
3
+ cwd?: string;
4
+ version?: string;
5
+ metaName?: string;
6
+ /**
7
+ * The initial log message when CLI started
8
+ */
9
+ initialLog?: string;
10
+ configFile: string;
11
+ /**
12
+ * @deprecated
13
+ * `package.json` config field, will be removed in the future, expect use configFile instead
14
+ */
15
+ packageJsonConfig?: string;
16
+ loadedConfig?: Config;
17
+ internalPlugins?: Plugin[];
18
+ handleSetupResult?: (params: any, api: Record<string, any>) => Promise<void> | void;
19
+ }
20
+ export type LoadedConfig<T> = {
21
+ packageName: string;
22
+ configFile: string;
23
+ config: T;
24
+ pkgConfig?: T;
25
+ jsConfig?: T;
26
+ };
27
+ export interface CLIRunOptions<Config> extends CLIOptions<Config> {
28
+ command: string;
29
+ }
@@ -0,0 +1 @@
1
+ export declare function checkIsDuplicationPlugin(plugins: (string | undefined)[], autoLoadPlugin?: boolean): void;
@@ -0,0 +1,5 @@
1
+ import { type Command, program } from '@modern-js/utils';
2
+ export declare const setProgramVersion: (version?: string) => void;
3
+ export declare function initCommandsMap(): void;
4
+ export type { Command };
5
+ export { program };
@@ -0,0 +1,2 @@
1
+ import type { InternalContext } from '../../../types';
2
+ export declare const createFileWatcher: <Config, NormalizedConfig, ExtendsHooksKey extends string>(appContext: InternalContext<Config, NormalizedConfig, ExtendsHooksKey>) => Promise<import("@modern-js/utils").FSWatcher | undefined>;
@@ -0,0 +1 @@
1
+ export declare const initAppDir: (currentDir?: string) => Promise<string>;
@@ -0,0 +1 @@
1
+ export declare const loadEnv: (appDirectory: string, mode?: string) => void;
@@ -0,0 +1,2 @@
1
+ import type { DeepPartial } from '../../../types/utils';
2
+ export declare const mergeConfig: <Config, NormalizedConfig>(configs: Array<DeepPartial<Config>>) => NormalizedConfig;
@@ -0,0 +1,3 @@
1
+ import type { AsyncHook, CollectAsyncHook } from './types/hooks';
2
+ export declare function createAsyncHook<Callback extends (...args: any[]) => any>(): AsyncHook<Callback>;
3
+ export declare function createCollectAsyncHook<Callback extends (...args: any[]) => any>(): CollectAsyncHook<Callback>;
@@ -0,0 +1,4 @@
1
+ export { createPluginManager } from './manager';
2
+ export { createAsyncHook, createCollectAsyncHook } from './hooks';
3
+ export * from './cli';
4
+ export * from './types';
@@ -0,0 +1,2 @@
1
+ import type { PluginManager } from './types/plugin';
2
+ export declare function createPluginManager(): PluginManager;
@@ -0,0 +1,42 @@
1
+ import type { ModifyBundlerChainFn, ModifyRsbuildConfigFn, ModifyRspackConfigFn, ModifyWebpackChainFn, ModifyWebpackConfigFn, OnAfterBuildFn, OnAfterCreateCompilerFn, OnBeforeBuildFn, OnBeforeCreateCompilerFn } from '@rsbuild/core';
2
+ import type { Hooks } from '../../cli/hooks';
3
+ import type { PluginHook, PluginHookTap } from '../hooks';
4
+ import type { DeepPartial } from '../utils';
5
+ import type { AppContext } from './context';
6
+ import type { AddCommandFn, AddWatchFilesFn, ConfigFn, ModifyConfigFn, ModifyHtmlPartialsFn, ModifyResolvedConfigFn, OnAfterDeployFn, OnAfterDevFn, OnBeforeDeployFn, OnBeforeDevFn, OnBeforeExitFn, OnBeforeRestartFn, OnFileChangedFn, OnPrepareFn } from './hooks';
7
+ /**
8
+ * Define a generic CLI plugin API that provider can extend as needed.
9
+ */
10
+ export type CLIPluginAPI<Config, NormalizedConfig> = Readonly<{
11
+ getAppContext: () => Readonly<AppContext<Config, NormalizedConfig>>;
12
+ getConfig: () => Readonly<Config>;
13
+ getNormalizedConfig: () => Readonly<NormalizedConfig>;
14
+ getHooks: () => Readonly<Hooks<Config, NormalizedConfig> & Record<string, PluginHook<(...args: any[]) => any>>>;
15
+ updateAppContext: (appContext: DeepPartial<AppContext<Config, NormalizedConfig>>) => void;
16
+ config: PluginHookTap<ConfigFn<DeepPartial<Config>>>;
17
+ modifyConfig: PluginHookTap<ModifyConfigFn<Config>>;
18
+ modifyResolvedConfig: PluginHookTap<ModifyResolvedConfigFn<NormalizedConfig>>;
19
+ modifyRsbuildConfig: PluginHookTap<ModifyRsbuildConfigFn>;
20
+ modifyBundlerChain: PluginHookTap<ModifyBundlerChainFn>;
21
+ /** Only works when bundler is Rspack */
22
+ modifyRspackConfig: PluginHookTap<ModifyRspackConfigFn>;
23
+ /** Only works when bundler is Webpack */
24
+ modifyWebpackChain: PluginHookTap<ModifyWebpackChainFn>;
25
+ /** Only works when bundler is Webpack */
26
+ modifyWebpackConfig: PluginHookTap<ModifyWebpackConfigFn>;
27
+ modifyHtmlPartials: PluginHookTap<ModifyHtmlPartialsFn>;
28
+ addCommand: PluginHookTap<AddCommandFn>;
29
+ onPrepare: PluginHookTap<OnPrepareFn>;
30
+ onWatchFiles: PluginHookTap<AddWatchFilesFn>;
31
+ onFileChanged: PluginHookTap<OnFileChangedFn>;
32
+ onBeforeRestart: PluginHookTap<OnBeforeRestartFn>;
33
+ onBeforeCreateCompiler: PluginHookTap<OnBeforeCreateCompilerFn>;
34
+ onAfterCreateCompiler: PluginHookTap<OnAfterCreateCompilerFn>;
35
+ onBeforeBuild: PluginHookTap<OnBeforeBuildFn>;
36
+ onAfterBuild: PluginHookTap<OnAfterBuildFn>;
37
+ onBeforeDev: PluginHookTap<OnBeforeDevFn>;
38
+ onAfterDev: PluginHookTap<OnAfterDevFn>;
39
+ onBeforeDeploy: PluginHookTap<OnBeforeDeployFn>;
40
+ onAfterDeploy: PluginHookTap<OnAfterDeployFn>;
41
+ onBeforeExit: PluginHookTap<OnBeforeExitFn>;
42
+ }>;
@@ -0,0 +1,40 @@
1
+ import type { ServerRoute } from '@modern-js/types';
2
+ import type { UniBuilderInstance, UniBuilderWebpackInstance } from '@modern-js/uni-builder';
3
+ import type { Hooks } from '../../cli/hooks';
4
+ import type { AsyncHook } from '../hooks';
5
+ import type { CLIPluginAPI } from './api';
6
+ import type { CLIPlugin } from './plugin';
7
+ export interface Entrypoint {
8
+ name: string;
9
+ entry: string;
10
+ }
11
+ /** The public context */
12
+ export type AppContext<Config, NormalizedConfig> = {
13
+ packageName: string;
14
+ configFile: string;
15
+ command: string;
16
+ isProd: boolean;
17
+ appDirectory: string;
18
+ srcDirectory?: string;
19
+ distDirectory?: string;
20
+ nodeModulesDirectory?: string;
21
+ plugins: CLIPlugin<Config, NormalizedConfig>[];
22
+ bundlerType?: 'webpack' | 'rspack' | 'esbuild';
23
+ builder?: UniBuilderInstance | UniBuilderWebpackInstance;
24
+ port?: number;
25
+ host?: string;
26
+ ip?: string;
27
+ serverRoutes?: ServerRoute[];
28
+ };
29
+ /** The inner context. */
30
+ export type InternalContext<Config, NormalizedConfig, ExtendsHooksKey extends string> = AppContext<Config, NormalizedConfig> & {
31
+ /** All hooks. */
32
+ hooks: Hooks<Config, NormalizedConfig> & Record<ExtendsHooksKey, AsyncHook<(...args: any[]) => any>>;
33
+ /** All plugin registry hooks */
34
+ extendsHooks: Record<ExtendsHooksKey, AsyncHook<(...args: any[]) => any>>;
35
+ /** Current App config. */
36
+ config: Readonly<Config>;
37
+ /** The normalized Rsbuild config. */
38
+ normalizedConfig?: NormalizedConfig;
39
+ pluginAPI?: CLIPluginAPI<Config, NormalizedConfig> & Record<string, (...args: any[]) => any>;
40
+ };
@@ -0,0 +1,41 @@
1
+ import type { Command } from '@modern-js/utils/commander';
2
+ import type { TransformFunction } from '../plugin';
3
+ import type { Entrypoint } from './context';
4
+ export type ConfigFn<Config> = () => Config;
5
+ export type ModifyConfigFn<Config> = TransformFunction<Config>;
6
+ export type ModifyResolvedConfigFn<NormalizedConfig> = TransformFunction<NormalizedConfig>;
7
+ type IPartialMethod = (...script: string[]) => void;
8
+ export interface PartialMethod {
9
+ append: IPartialMethod;
10
+ prepend: IPartialMethod;
11
+ }
12
+ export type ModifyHtmlPartialsFn = (params: {
13
+ entrypoint: Entrypoint;
14
+ partials: {
15
+ top: PartialMethod;
16
+ head: PartialMethod;
17
+ body: PartialMethod;
18
+ };
19
+ }) => Promise<void> | void;
20
+ export type AddCommandFn = (params: {
21
+ program: Command;
22
+ }) => void;
23
+ export type OnPrepareFn = () => Promise<void> | void;
24
+ export type AddWatchFilesFn = () => Array<string> | {
25
+ files: string[];
26
+ isPrivate: boolean;
27
+ };
28
+ export type OnFileChangedFn = (params: {
29
+ filename: string;
30
+ eventType: 'add' | 'change' | 'unlink';
31
+ isPrivate: boolean;
32
+ }) => void;
33
+ export type OnBeforeRestartFn = () => Promise<void> | void;
34
+ export type OnBeforeDevFn = () => Promise<void> | void;
35
+ export type OnAfterDevFn = (params: {
36
+ isFirstCompile: boolean;
37
+ }) => Promise<void> | void;
38
+ export type OnBeforeDeployFn = () => Promise<void> | void;
39
+ export type OnAfterDeployFn = () => Promise<void> | void;
40
+ export type OnBeforeExitFn = () => void;
41
+ export {};
@@ -0,0 +1,3 @@
1
+ export type { CLIPluginAPI } from './api';
2
+ export type { AppContext, InternalContext, Entrypoint } from './context';
3
+ export type { CLIPlugin } from './plugin';
@@ -0,0 +1,6 @@
1
+ import type { Plugin } from '../plugin';
2
+ import type { CLIPluginAPI } from './api';
3
+ /**
4
+ * The type of the CLI plugin object.
5
+ */
6
+ export type CLIPlugin<Config, NormalizedConfig> = Plugin<CLIPluginAPI<Config, NormalizedConfig>>;
@@ -0,0 +1,10 @@
1
+ export type AsyncHook<Callback extends (...args: any[]) => any> = {
2
+ tap: (cb: Callback) => void;
3
+ call: (...args: Parameters<Callback>) => Promise<Parameters<Callback>>;
4
+ };
5
+ export type CollectAsyncHook<Callback extends (...args: any[]) => any> = {
6
+ tap: (cb: Callback) => void;
7
+ call: (...args: Parameters<Callback>) => Promise<ReturnType<Callback>[]>;
8
+ };
9
+ export type PluginHook<Callback extends (...args: any[]) => any> = AsyncHook<Callback> | CollectAsyncHook<Callback>;
10
+ export type PluginHookTap<T extends (...args: any[]) => any> = (options: T) => void;
@@ -0,0 +1,3 @@
1
+ export type { Plugin, PluginManager, TransformFunction, } from './plugin';
2
+ export * from './cli';
3
+ export * from './hooks';
@@ -0,0 +1,40 @@
1
+ import type { PluginHook } from './hooks';
2
+ import type { Falsy } from './utils';
3
+ import type { MaybePromise } from './utils';
4
+ export type TransformFunction<T> = (arg: T) => T | Promise<T>;
5
+ export type Plugin<PluginAPI = {}, Context = {}> = {
6
+ /**
7
+ * The name of the plugin, a unique identifier.
8
+ */
9
+ name: string;
10
+ /**
11
+ * The plugins that this plugin depends on.
12
+ */
13
+ usePlugins?: Plugin<PluginAPI, Context>[];
14
+ /**
15
+ * The plugins add new hooks to the plugin manager.
16
+ */
17
+ registryHooks?: Record<string, PluginHook<(...args: any[]) => any>>;
18
+ /**
19
+ * The plugins add new apis to the plugin manager.
20
+ */
21
+ registryApi?: (context: Context, updateAppContext: (context: Context) => void) => Record<string, (...args: any[]) => any>;
22
+ /**
23
+ * The setup function of the plugin, which can be an async function.
24
+ * This function is called once when the plugin is initialized.
25
+ * @param api provides the context info, utility functions and lifecycle hooks.
26
+ */
27
+ setup: (api: PluginAPI) => MaybePromise<void>;
28
+ /**
29
+ * Declare the names of pre-plugins, which will be executed before the current plugin.
30
+ */
31
+ pre?: string[];
32
+ /**
33
+ * Declare the names of post-plugins, which will be executed after the current plugin.
34
+ */
35
+ post?: string[];
36
+ };
37
+ export type PluginManager = {
38
+ getPlugins: () => Plugin[];
39
+ addPlugins: (plugins: Array<Plugin | Falsy>) => void;
40
+ };
@@ -0,0 +1,5 @@
1
+ export type Falsy = false | null | undefined;
2
+ export type MaybePromise<T> = T | Promise<T>;
3
+ export type DeepPartial<T> = {
4
+ [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
5
+ };