feat(rstack): add plugin SPI - #336
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 623c4cba77
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
RFC: Rstack CLI plugin SPIStatus: Proposed in this PR DecisionAdd a small, general Rstack CLI plugin SPI. Rstack owns orchestration only; plugins register commands and transform native tool configurations. Domain-specific lifecycle and result processing remain in Rsbuild, Rslib, Rstest, Rslint, Rspress, Prettier, and lint-staged. This fills the missing Rstack-wide extension point. Native plugins and reporters can extend one tool, but they cannot register an Contracttype RstackPlugin = {
name: string;
setup(api: RstackPluginAPI): void | Promise<void>;
};
type RstackPluginAPI = {
readonly context: {
cwd: string;
command: string;
args: readonly string[];
configFilePath: string | null;
};
readonly logger: RstackLogger;
addCommand(command: {
name: string;
handler(args: readonly string[]): void | Promise<void>;
}): void;
modifyConfig<K extends keyof RstackConfigMap>(
kind: K,
handler: ConfigModifier<RstackConfigMap[K]>,
): void;
};
import { define } from "rstack";
import { pluginAcme } from "@acme/rstack-plugin";
define.plugins([pluginAcme()]);Nested, asynchronous, conditional, and falsy entries are supported in declaration order. Rstack performs no package scanning. Lifecycle and precedence
Rstest first applies needed Validation and compatibilityRstack rejects invalid or duplicate plugin names, invalid or duplicate commands, and attempts to replace built-ins or aliases. Plugin initialization is isolated per config load and repeats on reload. Existing projects without plugins retain current behavior. The exported SPI types follow Rstack semantic versioning. Native config values follow the versions of their respective tools, so plugin packages should declare compatible peer ranges. Non-goals
Build hooks, reporters, lint execution, and documentation lifecycle remain in native tool extension APIs. VerificationThe PR includes runtime validation, command dispatch, all seven config kinds, async ordering, reload isolation, Rstest inheritance, CLI precedence, TypeScript export resolution, and aligned English/Chinese documentation. Required formatting, type, lint, spelling, build, native build, and test checks pass locally. |
|
@chenjiahan @fi3ework, could you review this Rstack CLI plugin SPI when you have a chance? It adds a deliberately small public surface for plugin commands and typed native-tool config transforms. The short RFC is attached above, the branch is current with |
chenjiahan
left a comment
There was a problem hiding this comment.
The plugin interface seems very useful. I haven’t thought deeply about a plugin design for Rstack CLI yet.
Given that we already have Rspack plugins, Rsbuild plugins and Rspress plugins, I’d like to be especially careful when introducing another plugin system to avoid confusing our users. I’ll take a closer look at the design proposed in this PR
# Conflicts: # packages/rstack/src/rslibConfig.ts # packages/rstack/src/rspressConfig.ts
Summary
define.pluginsregistration, sequential setup, custom commands, and typed config modifiersTesting
pnpm formatpnpm checkpnpm check:spellpnpm buildpnpm --filter rstack build:nativepnpm testpnpm --dir website build