aicm 0.14.3 → 0.14.5
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.
- package/dist/cli.js +4 -1
- package/dist/commands/install.d.ts +5 -1
- package/dist/commands/install.js +24 -13
- package/package.json +3 -3
- package/dist/api_v2.d.ts +0 -9
- package/dist/api_v2.js +0 -12
- package/dist/bin/aicm_v2.d.ts +0 -2
- package/dist/bin/aicm_v2.js +0 -8
- package/dist/cli_v2.d.ts +0 -2
- package/dist/cli_v2.js +0 -94
- package/dist/commands/install/install-package.d.ts +0 -53
- package/dist/commands/install/install-package.js +0 -122
- package/dist/commands/install/install-single-package.d.ts +0 -53
- package/dist/commands/install/install-single-package.js +0 -139
- package/dist/commands/install/install-workspaces.d.ts +0 -9
- package/dist/commands/install/install-workspaces.js +0 -172
- package/dist/commands/install_new.d.ts +0 -17
- package/dist/commands/install_new.js +0 -457
- package/dist/commands/install_v2.d.ts +0 -52
- package/dist/commands/install_v2.js +0 -505
- package/dist/commands/install_/327/2242.d.ts +0 -59
- package/dist/commands/install_/327/2242.js +0 -546
- package/dist/commands/workspaces/discovery.d.ts +0 -7
- package/dist/commands/workspaces/discovery.js +0 -50
- package/dist/commands/workspaces/workspaces-install.d.ts +0 -9
- package/dist/commands/workspaces/workspaces-install.js +0 -48
- package/dist/index.d.ts +0 -2
- package/dist/index.js +0 -76
- package/dist/types/index.d.ts +0 -64
- package/dist/types/index.js +0 -2
- package/dist/utils/config_new.d.ts +0 -64
- package/dist/utils/config_new.js +0 -228
- package/dist/utils/config_v2.d.ts +0 -64
- package/dist/utils/config_v2.js +0 -250
- package/dist/utils/glob-handler.d.ts +0 -35
- package/dist/utils/glob-handler.js +0 -125
- package/dist/utils/mcp-writer.d.ts +0 -14
- package/dist/utils/mcp-writer.js +0 -69
- package/dist/utils/mdc-parser.d.ts +0 -9
- package/dist/utils/mdc-parser.js +0 -59
- package/dist/utils/rule-collector.d.ts +0 -33
- package/dist/utils/rule-collector.js +0 -169
- package/dist/utils/rule-detector.d.ts +0 -4
- package/dist/utils/rule-detector.js +0 -31
- package/dist/utils/rule-status.d.ts +0 -8
- package/dist/utils/rule-status.js +0 -53
- package/dist/utils/rule-writer.d.ts +0 -6
- package/dist/utils/rule-writer.js +0 -118
|
@@ -1,546 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.installPackage = installPackage;
|
|
7
|
-
exports.install = install;
|
|
8
|
-
exports.installCommand = installCommand;
|
|
9
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
10
|
-
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
11
|
-
const node_path_1 = __importDefault(require("node:path"));
|
|
12
|
-
const child_process_1 = require("child_process");
|
|
13
|
-
const ci_info_1 = require("ci-info");
|
|
14
|
-
const config_new_1 = require("../utils/config_new");
|
|
15
|
-
const working_directory_1 = require("../utils/working-directory");
|
|
16
|
-
/**
|
|
17
|
-
* Checks if the current environment is a CI environment
|
|
18
|
-
* This function respects any explicit settings in process.env.CI
|
|
19
|
-
*/
|
|
20
|
-
function isInCIEnvironment() {
|
|
21
|
-
// Explicit environment variable settings take precedence
|
|
22
|
-
if (process.env.CI === "true")
|
|
23
|
-
return true;
|
|
24
|
-
if (process.env.CI === "false")
|
|
25
|
-
return false;
|
|
26
|
-
// Fall back to ci-info's detection
|
|
27
|
-
return ci_info_1.isCI;
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Get the IDE-specific rule installation paths
|
|
31
|
-
*/
|
|
32
|
-
function getIdePaths() {
|
|
33
|
-
const projectDir = process.cwd();
|
|
34
|
-
return {
|
|
35
|
-
cursor: node_path_1.default.join(projectDir, ".cursor", "rules", "aicm"),
|
|
36
|
-
windsurf: node_path_1.default.join(projectDir, ".aicm"),
|
|
37
|
-
codex: node_path_1.default.join(projectDir, ".aicm"),
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Write rules to Cursor's rules directory
|
|
42
|
-
*/
|
|
43
|
-
function writeCursorRules(rules, cursorRulesDir) {
|
|
44
|
-
fs_extra_1.default.emptyDirSync(cursorRulesDir);
|
|
45
|
-
for (const rule of rules) {
|
|
46
|
-
let rulePath;
|
|
47
|
-
// Parse rule name into path segments using platform-specific path separator
|
|
48
|
-
const ruleNameParts = rule.name.split(/[/\\]/).filter(Boolean);
|
|
49
|
-
if (rule.presetName) {
|
|
50
|
-
// For rules from presets, create a namespaced directory structure
|
|
51
|
-
const namespace = extractNamespaceFromPresetPath(rule.presetName);
|
|
52
|
-
// Path will be: cursorRulesDir/namespace/rule-name.mdc
|
|
53
|
-
rulePath = node_path_1.default.join(cursorRulesDir, ...namespace, ...ruleNameParts);
|
|
54
|
-
}
|
|
55
|
-
else {
|
|
56
|
-
// For local rules, maintain the original flat structure
|
|
57
|
-
rulePath = node_path_1.default.join(cursorRulesDir, ...ruleNameParts);
|
|
58
|
-
}
|
|
59
|
-
const ruleFile = rulePath + ".mdc";
|
|
60
|
-
fs_extra_1.default.ensureDirSync(node_path_1.default.dirname(ruleFile));
|
|
61
|
-
fs_extra_1.default.writeFileSync(ruleFile, rule.content);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
/**
|
|
65
|
-
* Extract a normalized namespace from a preset path
|
|
66
|
-
*/
|
|
67
|
-
function extractNamespaceFromPresetPath(presetPath) {
|
|
68
|
-
// Special case: npm package names always use forward slashes, regardless of platform
|
|
69
|
-
if (presetPath.startsWith("@")) {
|
|
70
|
-
// For scoped packages like @scope/package/subdir, create nested directories
|
|
71
|
-
return presetPath.split("/");
|
|
72
|
-
}
|
|
73
|
-
// Handle both Unix and Windows style path separators
|
|
74
|
-
const parts = presetPath.split(/[/\\]/);
|
|
75
|
-
return parts.filter((part) => part.length > 0); // Filter out empty segments
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* Generate rules file content for Windsurf/Codex
|
|
79
|
-
*/
|
|
80
|
-
function generateRulesFileContent(ruleFiles) {
|
|
81
|
-
const alwaysApplyRules = [];
|
|
82
|
-
const optInRules = [];
|
|
83
|
-
for (const rule of ruleFiles) {
|
|
84
|
-
// Parse frontmatter to determine rule type
|
|
85
|
-
const frontmatterMatch = rule.content.match(/^---\n([\s\S]*?)\n---/);
|
|
86
|
-
let alwaysApply = false;
|
|
87
|
-
if (frontmatterMatch) {
|
|
88
|
-
try {
|
|
89
|
-
const frontmatter = frontmatterMatch[1];
|
|
90
|
-
// Simple YAML parsing for alwaysApply field
|
|
91
|
-
const alwaysApplyMatch = frontmatter.match(/alwaysApply:\s*(true|false)/);
|
|
92
|
-
if (alwaysApplyMatch) {
|
|
93
|
-
alwaysApply = alwaysApplyMatch[1] === "true";
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
catch (_a) {
|
|
97
|
-
// If parsing fails, default to false
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
if (alwaysApply) {
|
|
101
|
-
alwaysApplyRules.push(`- ${rule.path}`);
|
|
102
|
-
}
|
|
103
|
-
else {
|
|
104
|
-
optInRules.push(`- ${rule.path}`);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
let content = "<!-- AICM:BEGIN -->\n";
|
|
108
|
-
content +=
|
|
109
|
-
"<!-- WARNING: Everything between these markers will be overwritten during installation -->\n\n";
|
|
110
|
-
if (alwaysApplyRules.length > 0) {
|
|
111
|
-
content +=
|
|
112
|
-
"The following rules always apply to all files in the project:\n";
|
|
113
|
-
content += alwaysApplyRules.join("\n") + "\n\n";
|
|
114
|
-
}
|
|
115
|
-
if (optInRules.length > 0) {
|
|
116
|
-
content +=
|
|
117
|
-
"The following rules are available for the AI to include when needed:\n";
|
|
118
|
-
content += optInRules.join("\n") + "\n\n";
|
|
119
|
-
}
|
|
120
|
-
content += "<!-- AICM:END -->";
|
|
121
|
-
return content;
|
|
122
|
-
}
|
|
123
|
-
/**
|
|
124
|
-
* Write rules file content to a file, preserving existing content outside markers
|
|
125
|
-
*/
|
|
126
|
-
function writeRulesFile(rulesContent, rulesFilePath) {
|
|
127
|
-
const RULES_BEGIN = "<!-- AICM:BEGIN -->";
|
|
128
|
-
const RULES_END = "<!-- AICM:END -->";
|
|
129
|
-
let fileContent;
|
|
130
|
-
// Check if file exists
|
|
131
|
-
if (fs_extra_1.default.existsSync(rulesFilePath)) {
|
|
132
|
-
const existingContent = fs_extra_1.default.readFileSync(rulesFilePath, "utf8");
|
|
133
|
-
// Check if our markers exist
|
|
134
|
-
if (existingContent.includes(RULES_BEGIN) &&
|
|
135
|
-
existingContent.includes(RULES_END)) {
|
|
136
|
-
// Replace content between markers
|
|
137
|
-
const beforeMarker = existingContent.split(RULES_BEGIN)[0];
|
|
138
|
-
const afterMarker = existingContent.split(RULES_END)[1];
|
|
139
|
-
fileContent = beforeMarker + rulesContent + afterMarker;
|
|
140
|
-
}
|
|
141
|
-
else {
|
|
142
|
-
// Preserve the existing content and append markers
|
|
143
|
-
let separator = "";
|
|
144
|
-
if (!existingContent.endsWith("\n")) {
|
|
145
|
-
separator += "\n";
|
|
146
|
-
}
|
|
147
|
-
if (!existingContent.endsWith("\n\n")) {
|
|
148
|
-
separator += "\n";
|
|
149
|
-
}
|
|
150
|
-
fileContent = existingContent + separator + rulesContent;
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
else {
|
|
154
|
-
// Create new file with markers and content
|
|
155
|
-
fileContent = rulesContent;
|
|
156
|
-
}
|
|
157
|
-
fs_extra_1.default.writeFileSync(rulesFilePath, fileContent);
|
|
158
|
-
}
|
|
159
|
-
/**
|
|
160
|
-
* Write rules to a shared directory and update the given rules file
|
|
161
|
-
*/
|
|
162
|
-
function writeRulesForFile(rules, ruleDir, rulesFile) {
|
|
163
|
-
fs_extra_1.default.emptyDirSync(ruleDir);
|
|
164
|
-
const ruleFiles = rules.map((rule) => {
|
|
165
|
-
let rulePath;
|
|
166
|
-
// Parse rule name into path segments using platform-specific path separator
|
|
167
|
-
const ruleNameParts = rule.name.split(/[/\\]/).filter(Boolean);
|
|
168
|
-
if (rule.presetName) {
|
|
169
|
-
// For rules from presets, create a namespaced directory structure
|
|
170
|
-
const namespace = extractNamespaceFromPresetPath(rule.presetName);
|
|
171
|
-
// Path will be: ruleDir/namespace/rule-name.md
|
|
172
|
-
rulePath = node_path_1.default.join(ruleDir, ...namespace, ...ruleNameParts);
|
|
173
|
-
}
|
|
174
|
-
else {
|
|
175
|
-
// For local rules, maintain the original flat structure
|
|
176
|
-
rulePath = node_path_1.default.join(ruleDir, ...ruleNameParts);
|
|
177
|
-
}
|
|
178
|
-
const physicalRulePath = rulePath + ".md";
|
|
179
|
-
fs_extra_1.default.ensureDirSync(node_path_1.default.dirname(physicalRulePath));
|
|
180
|
-
fs_extra_1.default.writeFileSync(physicalRulePath, rule.content);
|
|
181
|
-
const relativeRuleDir = node_path_1.default.basename(ruleDir); // Gets '.aicm'
|
|
182
|
-
// For the rules file, maintain the same structure
|
|
183
|
-
let windsurfPath;
|
|
184
|
-
if (rule.presetName) {
|
|
185
|
-
const namespace = extractNamespaceFromPresetPath(rule.presetName);
|
|
186
|
-
windsurfPath =
|
|
187
|
-
node_path_1.default.join(relativeRuleDir, ...namespace, ...ruleNameParts) + ".md";
|
|
188
|
-
}
|
|
189
|
-
else {
|
|
190
|
-
windsurfPath = node_path_1.default.join(relativeRuleDir, ...ruleNameParts) + ".md";
|
|
191
|
-
}
|
|
192
|
-
// Normalize to POSIX style for cross-platform compatibility
|
|
193
|
-
const windsurfPathPosix = windsurfPath.replace(/\\/g, "/");
|
|
194
|
-
return {
|
|
195
|
-
name: rule.name,
|
|
196
|
-
path: windsurfPathPosix,
|
|
197
|
-
content: rule.content,
|
|
198
|
-
};
|
|
199
|
-
});
|
|
200
|
-
const rulesContent = generateRulesFileContent(ruleFiles);
|
|
201
|
-
writeRulesFile(rulesContent, node_path_1.default.join(process.cwd(), rulesFile));
|
|
202
|
-
}
|
|
203
|
-
/**
|
|
204
|
-
* Write all collected rules to their respective IDE targets
|
|
205
|
-
*/
|
|
206
|
-
function writeRulesToTargets(rules, targets) {
|
|
207
|
-
const idePaths = getIdePaths();
|
|
208
|
-
for (const target of targets) {
|
|
209
|
-
switch (target) {
|
|
210
|
-
case "cursor":
|
|
211
|
-
if (rules.length > 0) {
|
|
212
|
-
writeCursorRules(rules, idePaths.cursor);
|
|
213
|
-
}
|
|
214
|
-
break;
|
|
215
|
-
case "windsurf":
|
|
216
|
-
if (rules.length > 0) {
|
|
217
|
-
writeRulesForFile(rules, idePaths.windsurf, ".windsurfrules");
|
|
218
|
-
}
|
|
219
|
-
break;
|
|
220
|
-
case "codex":
|
|
221
|
-
if (rules.length > 0) {
|
|
222
|
-
writeRulesForFile(rules, idePaths.codex, "AGENTS.md");
|
|
223
|
-
}
|
|
224
|
-
break;
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
/**
|
|
229
|
-
* Write MCP servers configuration to IDE targets
|
|
230
|
-
*/
|
|
231
|
-
function writeMcpServersToTargets(mcpServers, targets, cwd) {
|
|
232
|
-
if (!mcpServers || Object.keys(mcpServers).length === 0)
|
|
233
|
-
return;
|
|
234
|
-
for (const target of targets) {
|
|
235
|
-
if (target === "cursor") {
|
|
236
|
-
const mcpPath = node_path_1.default.join(cwd, ".cursor", "mcp.json");
|
|
237
|
-
writeMcpServersToFile(mcpServers, mcpPath);
|
|
238
|
-
}
|
|
239
|
-
// Windsurf and Codex do not support project mcpServers, so skip
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
/**
|
|
243
|
-
* Write MCP servers configuration to a specific file
|
|
244
|
-
*/
|
|
245
|
-
function writeMcpServersToFile(mcpServers, mcpPath) {
|
|
246
|
-
var _a;
|
|
247
|
-
fs_extra_1.default.ensureDirSync(node_path_1.default.dirname(mcpPath));
|
|
248
|
-
const existingConfig = fs_extra_1.default.existsSync(mcpPath)
|
|
249
|
-
? fs_extra_1.default.readJsonSync(mcpPath)
|
|
250
|
-
: {};
|
|
251
|
-
const existingMcpServers = (_a = existingConfig === null || existingConfig === void 0 ? void 0 : existingConfig.mcpServers) !== null && _a !== void 0 ? _a : {};
|
|
252
|
-
// Filter out any existing aicm-managed servers (with aicm: true)
|
|
253
|
-
// This removes stale aicm servers that are no longer in the configuration
|
|
254
|
-
const userMcpServers = {};
|
|
255
|
-
for (const [key, value] of Object.entries(existingMcpServers)) {
|
|
256
|
-
if (typeof value === "object" && value !== null && value.aicm !== true) {
|
|
257
|
-
userMcpServers[key] = value;
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
// Mark new aicm servers as managed and filter out canceled servers
|
|
261
|
-
const aicmMcpServers = {};
|
|
262
|
-
for (const [key, value] of Object.entries(mcpServers)) {
|
|
263
|
-
if (value !== false) {
|
|
264
|
-
aicmMcpServers[key] = {
|
|
265
|
-
...value,
|
|
266
|
-
aicm: true,
|
|
267
|
-
};
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
// Merge user servers with aicm servers (aicm servers override user servers with same key)
|
|
271
|
-
const mergedMcpServers = {
|
|
272
|
-
...userMcpServers,
|
|
273
|
-
...aicmMcpServers,
|
|
274
|
-
};
|
|
275
|
-
const mergedConfig = {
|
|
276
|
-
...existingConfig,
|
|
277
|
-
mcpServers: mergedMcpServers,
|
|
278
|
-
};
|
|
279
|
-
fs_extra_1.default.writeJsonSync(mcpPath, mergedConfig, { spaces: 2 });
|
|
280
|
-
}
|
|
281
|
-
/**
|
|
282
|
-
* Discover all packages with aicm configurations using git ls-files
|
|
283
|
-
*/
|
|
284
|
-
function findAicmFiles(rootDir) {
|
|
285
|
-
try {
|
|
286
|
-
const output = (0, child_process_1.execSync)("git ls-files --cached --others --exclude-standard aicm.json **/aicm.json", {
|
|
287
|
-
cwd: rootDir,
|
|
288
|
-
encoding: "utf8",
|
|
289
|
-
});
|
|
290
|
-
return output
|
|
291
|
-
.trim()
|
|
292
|
-
.split("\n")
|
|
293
|
-
.filter(Boolean)
|
|
294
|
-
.map((file) => node_path_1.default.resolve(rootDir, file));
|
|
295
|
-
}
|
|
296
|
-
catch (_a) {
|
|
297
|
-
// Fallback to manual search if git is not available
|
|
298
|
-
return [];
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
/**
|
|
302
|
-
* Discover all packages with aicm configurations
|
|
303
|
-
*/
|
|
304
|
-
async function discoverPackagesWithAicm(rootDir) {
|
|
305
|
-
const aicmFiles = findAicmFiles(rootDir);
|
|
306
|
-
const packages = [];
|
|
307
|
-
for (const aicmFile of aicmFiles) {
|
|
308
|
-
const packageDir = node_path_1.default.dirname(aicmFile);
|
|
309
|
-
const relativePath = node_path_1.default.relative(rootDir, packageDir);
|
|
310
|
-
// Normalize to forward slashes for cross-platform compatibility
|
|
311
|
-
const normalizedRelativePath = relativePath.replace(/\\/g, "/");
|
|
312
|
-
const config = await (0, config_new_1.loadConfig)(packageDir);
|
|
313
|
-
if (config) {
|
|
314
|
-
packages.push({
|
|
315
|
-
relativePath: normalizedRelativePath || ".",
|
|
316
|
-
absolutePath: packageDir,
|
|
317
|
-
config,
|
|
318
|
-
});
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
// Sort packages by relativePath for deterministic order
|
|
322
|
-
return packages.sort((a, b) => a.relativePath.localeCompare(b.relativePath));
|
|
323
|
-
}
|
|
324
|
-
/**
|
|
325
|
-
* Install rules for a single package (used within workspaces and standalone installs)
|
|
326
|
-
*/
|
|
327
|
-
async function installPackage(options = {}) {
|
|
328
|
-
const cwd = options.cwd || process.cwd();
|
|
329
|
-
return (0, working_directory_1.withWorkingDirectory)(cwd, async () => {
|
|
330
|
-
let resolvedConfig;
|
|
331
|
-
if (options.config) {
|
|
332
|
-
resolvedConfig = options.config;
|
|
333
|
-
}
|
|
334
|
-
else {
|
|
335
|
-
resolvedConfig = await (0, config_new_1.loadConfig)(cwd);
|
|
336
|
-
}
|
|
337
|
-
if (!resolvedConfig) {
|
|
338
|
-
return {
|
|
339
|
-
success: false,
|
|
340
|
-
error: "Configuration file not found",
|
|
341
|
-
installedRuleCount: 0,
|
|
342
|
-
packagesCount: 0,
|
|
343
|
-
};
|
|
344
|
-
}
|
|
345
|
-
const { config, rules, mcpServers } = resolvedConfig;
|
|
346
|
-
// Check if rules are defined (either directly or through presets)
|
|
347
|
-
if (!rules || rules.length === 0) {
|
|
348
|
-
// If there are no presets defined either, show a message
|
|
349
|
-
if (!config.presets || config.presets.length === 0) {
|
|
350
|
-
return {
|
|
351
|
-
success: false,
|
|
352
|
-
error: "No rules defined in configuration",
|
|
353
|
-
installedRuleCount: 0,
|
|
354
|
-
packagesCount: 0,
|
|
355
|
-
};
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
try {
|
|
359
|
-
// Write rules to targets
|
|
360
|
-
writeRulesToTargets(rules, config.targets);
|
|
361
|
-
// Write MCP servers
|
|
362
|
-
if (mcpServers && Object.keys(mcpServers).length > 0) {
|
|
363
|
-
writeMcpServersToTargets(mcpServers, config.targets, cwd);
|
|
364
|
-
}
|
|
365
|
-
return {
|
|
366
|
-
success: true,
|
|
367
|
-
installedRuleCount: rules.length,
|
|
368
|
-
packagesCount: 1,
|
|
369
|
-
};
|
|
370
|
-
}
|
|
371
|
-
catch (error) {
|
|
372
|
-
const errorMessage = `Error during installation: ${error instanceof Error ? error.message : String(error)}`;
|
|
373
|
-
return {
|
|
374
|
-
success: false,
|
|
375
|
-
error: errorMessage,
|
|
376
|
-
errorStack: error instanceof Error ? error.stack : undefined,
|
|
377
|
-
installedRuleCount: 0,
|
|
378
|
-
packagesCount: 0,
|
|
379
|
-
};
|
|
380
|
-
}
|
|
381
|
-
});
|
|
382
|
-
}
|
|
383
|
-
/**
|
|
384
|
-
* Install aicm configurations for all packages in a workspace
|
|
385
|
-
*/
|
|
386
|
-
async function installWorkspacesPackages(packages, options = {}) {
|
|
387
|
-
const results = [];
|
|
388
|
-
let totalRuleCount = 0;
|
|
389
|
-
// Install packages sequentially for now (can be parallelized later)
|
|
390
|
-
for (const pkg of packages) {
|
|
391
|
-
const packagePath = pkg.absolutePath;
|
|
392
|
-
try {
|
|
393
|
-
const result = await installPackage({
|
|
394
|
-
...options,
|
|
395
|
-
cwd: packagePath,
|
|
396
|
-
config: pkg.config,
|
|
397
|
-
});
|
|
398
|
-
totalRuleCount += result.installedRuleCount;
|
|
399
|
-
results.push({
|
|
400
|
-
path: pkg.relativePath,
|
|
401
|
-
success: result.success,
|
|
402
|
-
error: result.error,
|
|
403
|
-
errorStack: result.errorStack,
|
|
404
|
-
installedRuleCount: result.installedRuleCount,
|
|
405
|
-
});
|
|
406
|
-
}
|
|
407
|
-
catch (error) {
|
|
408
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
409
|
-
results.push({
|
|
410
|
-
path: pkg.relativePath,
|
|
411
|
-
success: false,
|
|
412
|
-
error: errorMessage,
|
|
413
|
-
errorStack: error instanceof Error ? error.stack : undefined,
|
|
414
|
-
installedRuleCount: 0,
|
|
415
|
-
});
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
const failedPackages = results.filter((r) => !r.success);
|
|
419
|
-
return {
|
|
420
|
-
success: failedPackages.length === 0,
|
|
421
|
-
packages: results,
|
|
422
|
-
totalRuleCount,
|
|
423
|
-
};
|
|
424
|
-
}
|
|
425
|
-
/**
|
|
426
|
-
* Install rules across multiple packages in a workspace
|
|
427
|
-
*/
|
|
428
|
-
async function installWorkspaces(cwd, installOnCI, verbose = false) {
|
|
429
|
-
return (0, working_directory_1.withWorkingDirectory)(cwd, async () => {
|
|
430
|
-
if (verbose) {
|
|
431
|
-
console.log(chalk_1.default.blue("🔍 Discovering packages..."));
|
|
432
|
-
}
|
|
433
|
-
const allPackages = await discoverPackagesWithAicm(cwd);
|
|
434
|
-
const packages = allPackages.filter((pkg) => {
|
|
435
|
-
const isRoot = pkg.relativePath === ".";
|
|
436
|
-
if (!isRoot)
|
|
437
|
-
return true;
|
|
438
|
-
// For root directories, only keep if it has rules or presets
|
|
439
|
-
const hasRules = pkg.config.rules && pkg.config.rules.length > 0;
|
|
440
|
-
const hasPresets = pkg.config.config.presets && pkg.config.config.presets.length > 0;
|
|
441
|
-
return hasRules || hasPresets;
|
|
442
|
-
});
|
|
443
|
-
if (packages.length === 0) {
|
|
444
|
-
return {
|
|
445
|
-
success: false,
|
|
446
|
-
error: "No packages with aicm configurations found",
|
|
447
|
-
installedRuleCount: 0,
|
|
448
|
-
packagesCount: 0,
|
|
449
|
-
};
|
|
450
|
-
}
|
|
451
|
-
if (verbose) {
|
|
452
|
-
console.log(chalk_1.default.blue(`Found ${packages.length} packages with aicm configurations:`));
|
|
453
|
-
packages.forEach((pkg) => {
|
|
454
|
-
console.log(chalk_1.default.gray(` - ${pkg.relativePath}`));
|
|
455
|
-
});
|
|
456
|
-
console.log(chalk_1.default.blue(`📦 Installing configurations...`));
|
|
457
|
-
}
|
|
458
|
-
const result = await installWorkspacesPackages(packages, {
|
|
459
|
-
installOnCI,
|
|
460
|
-
verbose,
|
|
461
|
-
});
|
|
462
|
-
if (verbose) {
|
|
463
|
-
result.packages.forEach((pkg) => {
|
|
464
|
-
if (pkg.success) {
|
|
465
|
-
console.log(chalk_1.default.green(`✅ ${pkg.path} (${pkg.installedRuleCount} rules)`));
|
|
466
|
-
}
|
|
467
|
-
else {
|
|
468
|
-
console.log(chalk_1.default.red(`❌ ${pkg.path}: ${pkg.error}`));
|
|
469
|
-
}
|
|
470
|
-
});
|
|
471
|
-
}
|
|
472
|
-
const failedPackages = result.packages.filter((r) => !r.success);
|
|
473
|
-
if (failedPackages.length > 0) {
|
|
474
|
-
console.log(chalk_1.default.yellow(`Installation completed with errors`));
|
|
475
|
-
if (verbose) {
|
|
476
|
-
console.log(chalk_1.default.green(`Successfully installed: ${result.packages.length - failedPackages.length}/${result.packages.length} packages (${result.totalRuleCount} rules total)`));
|
|
477
|
-
console.log(chalk_1.default.red(`Failed packages: ${failedPackages.map((p) => p.path).join(", ")}`));
|
|
478
|
-
}
|
|
479
|
-
const errorDetails = failedPackages
|
|
480
|
-
.map((p) => `${p.path}: ${p.error}`)
|
|
481
|
-
.join("; ");
|
|
482
|
-
return {
|
|
483
|
-
success: false,
|
|
484
|
-
error: `Package installation failed for ${failedPackages.length} package(s): ${errorDetails}`,
|
|
485
|
-
installedRuleCount: result.totalRuleCount,
|
|
486
|
-
packagesCount: result.packages.length,
|
|
487
|
-
};
|
|
488
|
-
}
|
|
489
|
-
console.log(`Successfully installed ${result.totalRuleCount} rules across ${result.packages.length} packages`);
|
|
490
|
-
return {
|
|
491
|
-
success: true,
|
|
492
|
-
installedRuleCount: result.totalRuleCount,
|
|
493
|
-
packagesCount: result.packages.length,
|
|
494
|
-
};
|
|
495
|
-
});
|
|
496
|
-
}
|
|
497
|
-
/**
|
|
498
|
-
* Core implementation of the rule installation logic
|
|
499
|
-
*/
|
|
500
|
-
async function install(options = {}) {
|
|
501
|
-
const cwd = options.cwd || process.cwd();
|
|
502
|
-
const installOnCI = options.installOnCI === true; // Default to false if not specified
|
|
503
|
-
const inCI = isInCIEnvironment();
|
|
504
|
-
if (inCI && !installOnCI) {
|
|
505
|
-
console.log(chalk_1.default.yellow("Detected CI environment, skipping install."));
|
|
506
|
-
return {
|
|
507
|
-
success: true,
|
|
508
|
-
installedRuleCount: 0,
|
|
509
|
-
packagesCount: 0,
|
|
510
|
-
};
|
|
511
|
-
}
|
|
512
|
-
return (0, working_directory_1.withWorkingDirectory)(cwd, async () => {
|
|
513
|
-
let resolvedConfig;
|
|
514
|
-
if (options.config) {
|
|
515
|
-
resolvedConfig = options.config;
|
|
516
|
-
}
|
|
517
|
-
else {
|
|
518
|
-
resolvedConfig = await (0, config_new_1.loadConfig)(cwd);
|
|
519
|
-
}
|
|
520
|
-
if (resolvedConfig === null || resolvedConfig === void 0 ? void 0 : resolvedConfig.config.workspaces) {
|
|
521
|
-
return await installWorkspaces(cwd, installOnCI, options.verbose);
|
|
522
|
-
}
|
|
523
|
-
return installPackage(options);
|
|
524
|
-
});
|
|
525
|
-
}
|
|
526
|
-
/**
|
|
527
|
-
* CLI command wrapper for install
|
|
528
|
-
*/
|
|
529
|
-
async function installCommand(installOnCI, verbose) {
|
|
530
|
-
const result = await install({ installOnCI, verbose });
|
|
531
|
-
if (!result.success) {
|
|
532
|
-
const error = new Error(result.error);
|
|
533
|
-
if (result.errorStack) {
|
|
534
|
-
error.stack = result.errorStack;
|
|
535
|
-
}
|
|
536
|
-
throw error;
|
|
537
|
-
}
|
|
538
|
-
else {
|
|
539
|
-
if (result.packagesCount > 1) {
|
|
540
|
-
console.log(`Successfully installed ${result.installedRuleCount} rules across ${result.packagesCount} packages`);
|
|
541
|
-
}
|
|
542
|
-
else {
|
|
543
|
-
console.log("Rules installation completed");
|
|
544
|
-
}
|
|
545
|
-
}
|
|
546
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { PackageInfo } from "../../types";
|
|
2
|
-
/**
|
|
3
|
-
* Discover all packages with aicm configurations
|
|
4
|
-
* @param rootDir The root directory to search from
|
|
5
|
-
* @returns Array of discovered packages
|
|
6
|
-
*/
|
|
7
|
-
export declare function discoverPackagesWithAicm(rootDir: string): Promise<PackageInfo[]>;
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.discoverPackagesWithAicm = discoverPackagesWithAicm;
|
|
7
|
-
const node_path_1 = __importDefault(require("node:path"));
|
|
8
|
-
const node_child_process_1 = require("node:child_process");
|
|
9
|
-
const config_1 = require("../../utils/config");
|
|
10
|
-
/**
|
|
11
|
-
* Discover aicm.json files using git ls-files
|
|
12
|
-
* @param rootDir The root directory to search from
|
|
13
|
-
* @returns Array of aicm.json file paths
|
|
14
|
-
*/
|
|
15
|
-
function findAicmFiles(rootDir) {
|
|
16
|
-
const output = (0, node_child_process_1.execSync)("git ls-files --cached --others --exclude-standard aicm.json **/aicm.json", {
|
|
17
|
-
cwd: rootDir,
|
|
18
|
-
encoding: "utf8",
|
|
19
|
-
});
|
|
20
|
-
return output
|
|
21
|
-
.trim()
|
|
22
|
-
.split("\n")
|
|
23
|
-
.filter(Boolean)
|
|
24
|
-
.map((file) => node_path_1.default.resolve(rootDir, file));
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Discover all packages with aicm configurations
|
|
28
|
-
* @param rootDir The root directory to search from
|
|
29
|
-
* @returns Array of discovered packages
|
|
30
|
-
*/
|
|
31
|
-
async function discoverPackagesWithAicm(rootDir) {
|
|
32
|
-
const aicmFiles = findAicmFiles(rootDir);
|
|
33
|
-
const packages = [];
|
|
34
|
-
for (const aicmFile of aicmFiles) {
|
|
35
|
-
const packageDir = node_path_1.default.dirname(aicmFile);
|
|
36
|
-
const relativePath = node_path_1.default.relative(rootDir, packageDir);
|
|
37
|
-
// Normalize to forward slashes for cross-platform compatibility
|
|
38
|
-
const normalizedRelativePath = relativePath.replace(/\\/g, "/");
|
|
39
|
-
const config = (0, config_1.getConfig)(packageDir);
|
|
40
|
-
if (config) {
|
|
41
|
-
packages.push({
|
|
42
|
-
relativePath: normalizedRelativePath || ".",
|
|
43
|
-
absolutePath: packageDir,
|
|
44
|
-
config,
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
// Sort packages by relativePath for deterministic order
|
|
49
|
-
return packages.sort((a, b) => a.relativePath.localeCompare(b.relativePath));
|
|
50
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { PackageInfo, WorkspacesInstallResult } from "../../types";
|
|
2
|
-
import { InstallOptions } from "../install";
|
|
3
|
-
/**
|
|
4
|
-
* Install aicm configurations for all packages in a workspace
|
|
5
|
-
* @param packages The packages to install configurations for
|
|
6
|
-
* @param options Install options
|
|
7
|
-
* @returns Result of the workspace installation
|
|
8
|
-
*/
|
|
9
|
-
export declare function installWorkspacesPackages(packages: PackageInfo[], options?: InstallOptions): Promise<WorkspacesInstallResult>;
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.installWorkspacesPackages = installWorkspacesPackages;
|
|
4
|
-
const install_1 = require("../install");
|
|
5
|
-
/**
|
|
6
|
-
* Install aicm configurations for all packages in a workspace
|
|
7
|
-
* @param packages The packages to install configurations for
|
|
8
|
-
* @param options Install options
|
|
9
|
-
* @returns Result of the workspace installation
|
|
10
|
-
*/
|
|
11
|
-
async function installWorkspacesPackages(packages, options = {}) {
|
|
12
|
-
const results = [];
|
|
13
|
-
let totalRuleCount = 0;
|
|
14
|
-
// Install packages sequentially for now (can be parallelized later)
|
|
15
|
-
for (const pkg of packages) {
|
|
16
|
-
const packagePath = pkg.absolutePath;
|
|
17
|
-
try {
|
|
18
|
-
const result = await (0, install_1.install)({
|
|
19
|
-
...options,
|
|
20
|
-
cwd: packagePath,
|
|
21
|
-
});
|
|
22
|
-
totalRuleCount += result.installedRuleCount;
|
|
23
|
-
results.push({
|
|
24
|
-
path: pkg.relativePath,
|
|
25
|
-
success: result.success,
|
|
26
|
-
error: result.error,
|
|
27
|
-
errorStack: result.errorStack,
|
|
28
|
-
installedRuleCount: result.installedRuleCount,
|
|
29
|
-
});
|
|
30
|
-
}
|
|
31
|
-
catch (error) {
|
|
32
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
33
|
-
results.push({
|
|
34
|
-
path: pkg.relativePath,
|
|
35
|
-
success: false,
|
|
36
|
-
error: errorMessage,
|
|
37
|
-
errorStack: error instanceof Error ? error.stack : undefined,
|
|
38
|
-
installedRuleCount: 0,
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
const failedPackages = results.filter((r) => !r.success);
|
|
43
|
-
return {
|
|
44
|
-
success: failedPackages.length === 0,
|
|
45
|
-
packages: results,
|
|
46
|
-
totalRuleCount,
|
|
47
|
-
};
|
|
48
|
-
}
|
package/dist/index.d.ts
DELETED