Skip to content

Commit 41bff72

Browse files
Copilothotlong
andcommitted
fix(cli): address code review feedback for plugin command robustness
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
1 parent 23104ec commit 41bff72

1 file changed

Lines changed: 21 additions & 10 deletions

File tree

packages/cli/src/commands/plugin.ts

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,13 @@ function addPluginToConfig(configPath: string, packageName: string): void {
6363
let content = readConfigText(configPath);
6464

6565
// Derive a variable name from the package name
66-
// e.g. "@objectstack/plugin-auth" → "pluginAuth"
66+
// e.g. "@objectstack/plugin-auth" → "authPlugin"
6767
const shortName = packageName
6868
.replace(/^@[^/]+\//, '') // strip scope
69-
.replace(/^plugin-/, ''); // strip "plugin-" prefix
70-
const varName = shortName.replace(/-([a-z])/g, (_, c) => c.toUpperCase()) + 'Plugin';
69+
.replace(/^plugin-/, '') // strip "plugin-" prefix
70+
.replace(/-+/g, '-') // collapse consecutive hyphens
71+
.replace(/^-|-$/g, ''); // trim leading/trailing hyphens
72+
const varName = shortName.replace(/-([a-z])/g, (_, c: string) => c.toUpperCase()) + 'Plugin';
7173

7274
// 1. Add import
7375
const importLine = `import ${varName} from '${packageName}';\n`;
@@ -90,12 +92,17 @@ function addPluginToConfig(configPath: string, packageName: string): void {
9092
content = importLine + '\n' + content;
9193
}
9294

93-
// 2. Add to plugins array
95+
// 2. Add to plugins array (target only the first plugins: [ within defineStack)
9496
if (/plugins\s*:\s*\[/.test(content)) {
95-
// plugins array exists — append to it
97+
// plugins array exists — append to it (first occurrence only)
98+
let replaced = false;
9699
content = content.replace(
97100
/(plugins\s*:\s*\[)/,
98-
`$1\n ${varName},`
101+
(match) => {
102+
if (replaced) return match;
103+
replaced = true;
104+
return `${match}\n ${varName},`;
105+
}
99106
);
100107
} else {
101108
// No plugins array — add one before the closing of defineStack({...})
@@ -117,16 +124,20 @@ function addPluginToConfig(configPath: string, packageName: string): void {
117124
function removePluginFromConfig(configPath: string, pluginName: string): void {
118125
let content = readConfigText(configPath);
119126

120-
// Remove the import line that references this plugin (by package name or variable)
121-
const importRegex = new RegExp(`^import .+['"]${escapeRegex(pluginName)}['"].*$\\n?`, 'gm');
127+
// Remove the import line that references this plugin (exact package name match)
128+
const importRegex = new RegExp(`^import .+['"]${escapeRegex(pluginName)}['"]\\s*;?\\s*$\\n?`, 'gm');
122129
const hadImport = importRegex.test(content);
130+
// Reset regex lastIndex after test()
131+
importRegex.lastIndex = 0;
123132
content = content.replace(importRegex, '');
124133

125134
// Also try to remove by a derived variable name
126135
const shortName = pluginName
127136
.replace(/^@[^/]+\//, '')
128-
.replace(/^plugin-/, '');
129-
const varName = shortName.replace(/-([a-z])/g, (_, c) => c.toUpperCase()) + 'Plugin';
137+
.replace(/^plugin-/, '')
138+
.replace(/-+/g, '-')
139+
.replace(/^-|-$/g, '');
140+
const varName = shortName.replace(/-([a-z])/g, (_, c: string) => c.toUpperCase()) + 'Plugin';
130141

131142
// Remove import by variable name if it wasn't caught above
132143
if (!hadImport) {

0 commit comments

Comments
 (0)