aicm 0.12.2 → 0.13.1
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/README.md +11 -10
- package/dist/api.d.ts +1 -1
- package/dist/bin/aicm.d.ts +2 -0
- package/dist/bin/aicm.js +5 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +91 -0
- package/dist/commands/init.js +0 -3
- package/dist/commands/install/install-package.d.ts +53 -0
- package/dist/commands/install/install-package.js +122 -0
- package/dist/commands/install/install-single-package.d.ts +53 -0
- package/dist/commands/install/install-single-package.js +139 -0
- package/dist/commands/install/install-workspaces.d.ts +9 -0
- package/dist/commands/install/install-workspaces.js +172 -0
- package/dist/commands/install.d.ts +2 -48
- package/dist/commands/install.js +28 -202
- package/dist/commands/list.d.ts +1 -1
- package/dist/commands/list.js +2 -2
- package/dist/commands/workspaces/workspaces-install.js +2 -0
- package/dist/index.js +0 -0
- package/dist/types/index.d.ts +2 -1
- package/dist/utils/config.d.ts +3 -3
- package/dist/utils/config.js +17 -12
- package/dist/utils/working-directory.d.ts +5 -0
- package/dist/utils/working-directory.js +21 -0
- package/package.json +7 -4
- package/dist/commands/monorepo/discovery.d.ts +0 -7
- package/dist/commands/monorepo/discovery.js +0 -50
- package/dist/commands/monorepo/installer.d.ts +0 -9
- package/dist/commands/monorepo/installer.js +0 -70
- package/dist/commands/monorepo/monorepo-install.d.ts +0 -9
- package/dist/commands/monorepo/monorepo-install.js +0 -46
- package/dist/commands/monorepo/types.d.ts +0 -1
- package/dist/commands/monorepo/types.js +0 -17
- package/dist/utils/package-detector.d.ts +0 -6
- package/dist/utils/package-detector.js +0 -25
- package/dist/utils/windsurf-writer.d.ts +0 -15
- package/dist/utils/windsurf-writer.js +0 -137
|
@@ -0,0 +1,172 @@
|
|
|
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.installWorkspaces = installWorkspaces;
|
|
7
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
8
|
+
const node_child_process_1 = require("node:child_process");
|
|
9
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
10
|
+
const config_1 = require("../../utils/config");
|
|
11
|
+
const working_directory_1 = require("../../utils/working-directory");
|
|
12
|
+
const install_package_1 = require("./install-package");
|
|
13
|
+
/**
|
|
14
|
+
* Discover aicm.json files using git ls-files
|
|
15
|
+
* @param rootDir The root directory to search from
|
|
16
|
+
* @returns Array of aicm.json file paths
|
|
17
|
+
*/
|
|
18
|
+
function findAicmFiles(rootDir) {
|
|
19
|
+
const output = (0, node_child_process_1.execSync)("git ls-files --cached --others --exclude-standard aicm.json **/aicm.json", {
|
|
20
|
+
cwd: rootDir,
|
|
21
|
+
encoding: "utf8",
|
|
22
|
+
});
|
|
23
|
+
return output
|
|
24
|
+
.trim()
|
|
25
|
+
.split("\n")
|
|
26
|
+
.filter(Boolean)
|
|
27
|
+
.map((file) => node_path_1.default.resolve(rootDir, file));
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Discover all packages with aicm configurations
|
|
31
|
+
* @param rootDir The root directory to search from
|
|
32
|
+
* @returns Array of discovered packages
|
|
33
|
+
*/
|
|
34
|
+
async function discoverPackagesWithAicm(rootDir) {
|
|
35
|
+
const aicmFiles = findAicmFiles(rootDir);
|
|
36
|
+
const packages = [];
|
|
37
|
+
for (const aicmFile of aicmFiles) {
|
|
38
|
+
const packageDir = node_path_1.default.dirname(aicmFile);
|
|
39
|
+
const relativePath = node_path_1.default.relative(rootDir, packageDir);
|
|
40
|
+
// Normalize to forward slashes for cross-platform compatibility
|
|
41
|
+
const normalizedRelativePath = relativePath.replace(/\\/g, "/");
|
|
42
|
+
const config = await (0, config_1.getConfig)(packageDir);
|
|
43
|
+
if (config) {
|
|
44
|
+
packages.push({
|
|
45
|
+
relativePath: normalizedRelativePath || ".",
|
|
46
|
+
absolutePath: packageDir,
|
|
47
|
+
config,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
// Sort packages by relativePath for deterministic order
|
|
52
|
+
return packages.sort((a, b) => a.relativePath.localeCompare(b.relativePath));
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Install aicm configurations for all packages in a workspace
|
|
56
|
+
* @param packages The packages to install configurations for
|
|
57
|
+
* @param options Install options
|
|
58
|
+
* @returns Result of the workspace installation
|
|
59
|
+
*/
|
|
60
|
+
async function installWorkspacesPackages(packages, options = {}) {
|
|
61
|
+
const results = [];
|
|
62
|
+
let totalRuleCount = 0;
|
|
63
|
+
// Install packages sequentially for now (can be parallelized later)
|
|
64
|
+
for (const pkg of packages) {
|
|
65
|
+
const packagePath = pkg.absolutePath;
|
|
66
|
+
try {
|
|
67
|
+
const result = await (0, install_package_1.installPackage)({
|
|
68
|
+
...options,
|
|
69
|
+
cwd: packagePath,
|
|
70
|
+
});
|
|
71
|
+
totalRuleCount += result.installedRuleCount;
|
|
72
|
+
results.push({
|
|
73
|
+
path: pkg.relativePath,
|
|
74
|
+
success: result.success,
|
|
75
|
+
error: result.error,
|
|
76
|
+
errorStack: result.errorStack,
|
|
77
|
+
installedRuleCount: result.installedRuleCount,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
82
|
+
results.push({
|
|
83
|
+
path: pkg.relativePath,
|
|
84
|
+
success: false,
|
|
85
|
+
error: errorMessage,
|
|
86
|
+
errorStack: error instanceof Error ? error.stack : undefined,
|
|
87
|
+
installedRuleCount: 0,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
const failedPackages = results.filter((r) => !r.success);
|
|
92
|
+
return {
|
|
93
|
+
success: failedPackages.length === 0,
|
|
94
|
+
packages: results,
|
|
95
|
+
totalRuleCount,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Install rules across multiple packages in a workspace
|
|
100
|
+
* @param cwd The current working directory
|
|
101
|
+
* @param installOnCI Whether to install on CI environments
|
|
102
|
+
* @param verbose Whether to show verbose output
|
|
103
|
+
* @returns Result of the install operation
|
|
104
|
+
*/
|
|
105
|
+
async function installWorkspaces(cwd, installOnCI, verbose = false) {
|
|
106
|
+
return (0, working_directory_1.withWorkingDirectory)(cwd, async () => {
|
|
107
|
+
if (verbose) {
|
|
108
|
+
console.log(chalk_1.default.blue("🔍 Discovering packages..."));
|
|
109
|
+
}
|
|
110
|
+
const allPackages = await discoverPackagesWithAicm(cwd);
|
|
111
|
+
const packages = allPackages.filter((pkg) => {
|
|
112
|
+
const isRoot = pkg.relativePath === ".";
|
|
113
|
+
if (!isRoot)
|
|
114
|
+
return true;
|
|
115
|
+
// For root directories, only keep if it has rules or presets
|
|
116
|
+
const hasRules = pkg.config.rules && Object.keys(pkg.config.rules).length > 0;
|
|
117
|
+
const hasPresets = pkg.config.presets && pkg.config.presets.length > 0;
|
|
118
|
+
return hasRules || hasPresets;
|
|
119
|
+
});
|
|
120
|
+
if (packages.length === 0) {
|
|
121
|
+
return {
|
|
122
|
+
success: false,
|
|
123
|
+
error: "No packages with aicm configurations found",
|
|
124
|
+
installedRuleCount: 0,
|
|
125
|
+
packagesCount: 0,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
if (verbose) {
|
|
129
|
+
console.log(chalk_1.default.blue(`Found ${packages.length} packages with aicm configurations:`));
|
|
130
|
+
packages.forEach((pkg) => {
|
|
131
|
+
console.log(chalk_1.default.gray(` - ${pkg.relativePath}`));
|
|
132
|
+
});
|
|
133
|
+
console.log(chalk_1.default.blue(`📦 Installing configurations...`));
|
|
134
|
+
}
|
|
135
|
+
const result = await installWorkspacesPackages(packages, {
|
|
136
|
+
installOnCI,
|
|
137
|
+
});
|
|
138
|
+
if (verbose) {
|
|
139
|
+
result.packages.forEach((pkg) => {
|
|
140
|
+
if (pkg.success) {
|
|
141
|
+
console.log(chalk_1.default.green(`✅ ${pkg.path} (${pkg.installedRuleCount} rules)`));
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
console.log(chalk_1.default.red(`❌ ${pkg.path}: ${pkg.error}`));
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
const failedPackages = result.packages.filter((r) => !r.success);
|
|
149
|
+
if (failedPackages.length > 0) {
|
|
150
|
+
console.log(chalk_1.default.yellow(`Installation completed with errors`));
|
|
151
|
+
if (verbose) {
|
|
152
|
+
console.log(chalk_1.default.green(`Successfully installed: ${result.packages.length - failedPackages.length}/${result.packages.length} packages (${result.totalRuleCount} rules total)`));
|
|
153
|
+
console.log(chalk_1.default.red(`Failed packages: ${failedPackages.map((p) => p.path).join(", ")}`));
|
|
154
|
+
}
|
|
155
|
+
const errorDetails = failedPackages
|
|
156
|
+
.map((p) => `${p.path}: ${p.error}`)
|
|
157
|
+
.join("; ");
|
|
158
|
+
return {
|
|
159
|
+
success: false,
|
|
160
|
+
error: `Package installation failed for ${failedPackages.length} package(s): ${errorDetails}`,
|
|
161
|
+
installedRuleCount: result.totalRuleCount,
|
|
162
|
+
packagesCount: result.packages.length,
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
console.log(`Successfully installed ${result.totalRuleCount} rules across ${result.packages.length} packages`);
|
|
166
|
+
return {
|
|
167
|
+
success: true,
|
|
168
|
+
installedRuleCount: result.totalRuleCount,
|
|
169
|
+
packagesCount: result.packages.length,
|
|
170
|
+
};
|
|
171
|
+
});
|
|
172
|
+
}
|
|
@@ -1,54 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
/**
|
|
3
|
-
* Options for the installCore function
|
|
4
|
-
*/
|
|
5
|
-
export interface InstallOptions {
|
|
6
|
-
/**
|
|
7
|
-
* Base directory to use instead of process.cwd()
|
|
8
|
-
*/
|
|
9
|
-
cwd?: string;
|
|
10
|
-
/**
|
|
11
|
-
* Custom config object to use instead of loading from file
|
|
12
|
-
*/
|
|
13
|
-
config?: NormalizedConfig;
|
|
14
|
-
/**
|
|
15
|
-
* allow installation on CI environments
|
|
16
|
-
*/
|
|
17
|
-
installOnCI?: boolean;
|
|
18
|
-
/**
|
|
19
|
-
* Enable workspaces mode
|
|
20
|
-
*/
|
|
21
|
-
workspaces?: boolean;
|
|
22
|
-
/**
|
|
23
|
-
* Show verbose output during installation
|
|
24
|
-
*/
|
|
25
|
-
verbose?: boolean;
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* Result of the install operation
|
|
29
|
-
*/
|
|
30
|
-
export interface InstallResult {
|
|
31
|
-
/**
|
|
32
|
-
* Whether the operation was successful
|
|
33
|
-
*/
|
|
34
|
-
success: boolean;
|
|
35
|
-
/**
|
|
36
|
-
* Error message if the operation failed
|
|
37
|
-
*/
|
|
38
|
-
error?: string;
|
|
39
|
-
/**
|
|
40
|
-
* Number of rules installed
|
|
41
|
-
*/
|
|
42
|
-
installedRuleCount: number;
|
|
43
|
-
/**
|
|
44
|
-
* Number of packages installed
|
|
45
|
-
*/
|
|
46
|
-
packagesCount: number;
|
|
47
|
-
}
|
|
1
|
+
import { InstallOptions, InstallResult } from "./install/install-package";
|
|
48
2
|
/**
|
|
49
3
|
* Core implementation of the rule installation logic
|
|
50
4
|
* @param options Install options
|
|
51
5
|
* @returns Result of the install operation
|
|
52
6
|
*/
|
|
53
7
|
export declare function install(options?: InstallOptions): Promise<InstallResult>;
|
|
54
|
-
export declare function installCommand(installOnCI?: boolean,
|
|
8
|
+
export declare function installCommand(installOnCI?: boolean, verbose?: boolean): Promise<void>;
|
package/dist/commands/install.js
CHANGED
|
@@ -7,32 +7,10 @@ exports.install = install;
|
|
|
7
7
|
exports.installCommand = installCommand;
|
|
8
8
|
const chalk_1 = __importDefault(require("chalk"));
|
|
9
9
|
const config_1 = require("../utils/config");
|
|
10
|
-
const rule_detector_1 = require("../utils/rule-detector");
|
|
11
|
-
const rule_collector_1 = require("../utils/rule-collector");
|
|
12
|
-
const rule_writer_1 = require("../utils/rule-writer");
|
|
13
10
|
const ci_info_1 = require("ci-info");
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
const glob_handler_1 = require("../utils/glob-handler");
|
|
18
|
-
/**
|
|
19
|
-
* Helper function to execute a function within a specific working directory
|
|
20
|
-
* and ensure the original directory is always restored
|
|
21
|
-
*/
|
|
22
|
-
async function withWorkingDirectory(targetDir, fn) {
|
|
23
|
-
const originalCwd = process.cwd();
|
|
24
|
-
if (targetDir !== originalCwd) {
|
|
25
|
-
process.chdir(targetDir);
|
|
26
|
-
}
|
|
27
|
-
try {
|
|
28
|
-
return await fn();
|
|
29
|
-
}
|
|
30
|
-
finally {
|
|
31
|
-
if (targetDir !== originalCwd) {
|
|
32
|
-
process.chdir(originalCwd);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
}
|
|
11
|
+
const working_directory_1 = require("../utils/working-directory");
|
|
12
|
+
const install_package_1 = require("./install/install-package");
|
|
13
|
+
const install_workspaces_1 = require("./install/install-workspaces");
|
|
36
14
|
/**
|
|
37
15
|
* Checks if the current environment is a CI environment
|
|
38
16
|
* This function respects any explicit settings in process.env.CI
|
|
@@ -46,64 +24,6 @@ function isInCIEnvironment() {
|
|
|
46
24
|
// Fall back to ci-info's detection
|
|
47
25
|
return ci_info_1.isCI;
|
|
48
26
|
}
|
|
49
|
-
async function handleWorkspacesInstallation(cwd, installOnCI, verbose = false) {
|
|
50
|
-
return withWorkingDirectory(cwd, async () => {
|
|
51
|
-
if (verbose) {
|
|
52
|
-
console.log(chalk_1.default.blue("🔍 Discovering packages..."));
|
|
53
|
-
}
|
|
54
|
-
const packages = await (0, discovery_1.discoverPackagesWithAicm)(cwd);
|
|
55
|
-
if (packages.length === 0) {
|
|
56
|
-
return {
|
|
57
|
-
success: false,
|
|
58
|
-
error: "No packages with aicm configurations found",
|
|
59
|
-
installedRuleCount: 0,
|
|
60
|
-
packagesCount: 0,
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
if (verbose) {
|
|
64
|
-
console.log(chalk_1.default.blue(`Found ${packages.length} packages with aicm configurations:`));
|
|
65
|
-
packages.forEach((pkg) => {
|
|
66
|
-
console.log(chalk_1.default.gray(` - ${pkg.relativePath}`));
|
|
67
|
-
});
|
|
68
|
-
console.log(chalk_1.default.blue(`📦 Installing configurations...`));
|
|
69
|
-
}
|
|
70
|
-
const result = await (0, workspaces_install_1.installWorkspacesPackages)(packages, {
|
|
71
|
-
installOnCI,
|
|
72
|
-
});
|
|
73
|
-
if (verbose) {
|
|
74
|
-
result.packages.forEach((pkg) => {
|
|
75
|
-
if (pkg.success) {
|
|
76
|
-
console.log(chalk_1.default.green(`✅ ${pkg.path} (${pkg.installedRuleCount} rules)`));
|
|
77
|
-
}
|
|
78
|
-
else {
|
|
79
|
-
console.log(chalk_1.default.red(`❌ ${pkg.path}: ${pkg.error}`));
|
|
80
|
-
}
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
const failedPackages = result.packages.filter((r) => !r.success);
|
|
84
|
-
if (failedPackages.length > 0) {
|
|
85
|
-
console.log(chalk_1.default.yellow(`Installation completed with errors`));
|
|
86
|
-
if (verbose) {
|
|
87
|
-
console.log(chalk_1.default.green(`Successfully installed: ${result.packages.length - failedPackages.length}/${result.packages.length} packages (${result.totalRuleCount} rules total)`));
|
|
88
|
-
console.log(chalk_1.default.red(`Failed packages: ${failedPackages.map((p) => p.path).join(", ")}`));
|
|
89
|
-
}
|
|
90
|
-
const errorDetails = failedPackages
|
|
91
|
-
.map((p) => `${p.path}: ${p.error}`)
|
|
92
|
-
.join("; ");
|
|
93
|
-
return {
|
|
94
|
-
success: false,
|
|
95
|
-
error: `Package installation failed for ${failedPackages.length} package(s): ${errorDetails}`,
|
|
96
|
-
installedRuleCount: result.totalRuleCount,
|
|
97
|
-
packagesCount: result.packages.length,
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
return {
|
|
101
|
-
success: true,
|
|
102
|
-
installedRuleCount: result.totalRuleCount,
|
|
103
|
-
packagesCount: result.packages.length,
|
|
104
|
-
};
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
27
|
/**
|
|
108
28
|
* Core implementation of the rule installation logic
|
|
109
29
|
* @param options Install options
|
|
@@ -112,132 +32,38 @@ async function handleWorkspacesInstallation(cwd, installOnCI, verbose = false) {
|
|
|
112
32
|
async function install(options = {}) {
|
|
113
33
|
const cwd = options.cwd || process.cwd();
|
|
114
34
|
const installOnCI = options.installOnCI === true; // Default to false if not specified
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
}
|
|
119
|
-
const config = options.config || (0, config_1.getConfig)();
|
|
120
|
-
const ruleCollection = (0, rule_collector_1.initRuleCollection)();
|
|
121
|
-
if (!config) {
|
|
122
|
-
return {
|
|
123
|
-
success: false,
|
|
124
|
-
error: "Configuration file not found",
|
|
125
|
-
installedRuleCount: 0,
|
|
126
|
-
packagesCount: 0,
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
|
-
const inCI = isInCIEnvironment();
|
|
130
|
-
if (inCI && !installOnCI && !config.installOnCI) {
|
|
131
|
-
console.log(chalk_1.default.yellow("Detected CI environment, skipping install."));
|
|
132
|
-
return {
|
|
133
|
-
success: true,
|
|
134
|
-
installedRuleCount: 0,
|
|
135
|
-
packagesCount: 0,
|
|
136
|
-
};
|
|
137
|
-
}
|
|
138
|
-
// Check if rules are defined (either directly or through presets)
|
|
139
|
-
if (!config.rules || Object.keys(config.rules).length === 0) {
|
|
140
|
-
// If there are no presets defined either, show a message
|
|
141
|
-
if (!config.presets || config.presets.length === 0) {
|
|
142
|
-
return {
|
|
143
|
-
success: false,
|
|
144
|
-
error: "No rules defined in configuration",
|
|
145
|
-
installedRuleCount: 0,
|
|
146
|
-
packagesCount: 0,
|
|
147
|
-
};
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
let expandedRules;
|
|
151
|
-
try {
|
|
152
|
-
const expansion = await (0, glob_handler_1.expandRulesGlobPatterns)(config.rules, cwd);
|
|
153
|
-
expandedRules = expansion.expandedRules;
|
|
154
|
-
if (options.verbose) {
|
|
155
|
-
for (const [expandedKey, originalPattern] of Object.entries(expansion.globSources)) {
|
|
156
|
-
console.log(chalk_1.default.gray(` Pattern "${originalPattern}" → ${expandedKey}`));
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
catch (error) {
|
|
161
|
-
return {
|
|
162
|
-
success: false,
|
|
163
|
-
error: `Error expanding glob patterns: ${error instanceof Error ? error.message : String(error)}`,
|
|
164
|
-
installedRuleCount: 0,
|
|
165
|
-
packagesCount: 0,
|
|
166
|
-
};
|
|
167
|
-
}
|
|
168
|
-
let hasErrors = false;
|
|
169
|
-
const errorMessages = [];
|
|
170
|
-
let installedRuleCount = 0;
|
|
171
|
-
for (const [name, source] of Object.entries(expandedRules)) {
|
|
172
|
-
const ruleType = (0, rule_detector_1.detectRuleType)(source);
|
|
173
|
-
const ruleBasePath = (0, config_1.getRuleSource)(config, name);
|
|
174
|
-
const originalPresetPath = (0, config_1.getOriginalPresetPath)(config, name);
|
|
175
|
-
try {
|
|
176
|
-
let ruleContent;
|
|
177
|
-
switch (ruleType) {
|
|
178
|
-
case "npm":
|
|
179
|
-
ruleContent = (0, rule_collector_1.collectNpmRule)(name, source);
|
|
180
|
-
break;
|
|
181
|
-
case "local":
|
|
182
|
-
ruleContent = (0, rule_collector_1.collectLocalRule)(name, source, ruleBasePath);
|
|
183
|
-
break;
|
|
184
|
-
default:
|
|
185
|
-
errorMessages.push(`Unknown rule type: ${ruleType}`);
|
|
186
|
-
continue;
|
|
187
|
-
}
|
|
188
|
-
if (originalPresetPath) {
|
|
189
|
-
ruleContent.presetPath = originalPresetPath;
|
|
190
|
-
}
|
|
191
|
-
(0, rule_collector_1.addRuleToCollection)(ruleCollection, ruleContent, config.ides);
|
|
192
|
-
installedRuleCount++;
|
|
193
|
-
}
|
|
194
|
-
catch (e) {
|
|
195
|
-
hasErrors = true;
|
|
196
|
-
const errorMessage = `Error processing rule ${name}: ${e instanceof Error ? e.message : String(e)}`;
|
|
197
|
-
errorMessages.push(errorMessage);
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
if (hasErrors) {
|
|
201
|
-
return {
|
|
202
|
-
success: false,
|
|
203
|
-
error: errorMessages.join("; "),
|
|
204
|
-
installedRuleCount,
|
|
205
|
-
packagesCount: 0,
|
|
206
|
-
};
|
|
207
|
-
}
|
|
208
|
-
(0, rule_writer_1.writeRulesToTargets)(ruleCollection);
|
|
209
|
-
if (config.mcpServers) {
|
|
210
|
-
const filteredMcpServers = Object.fromEntries(Object.entries(config.mcpServers).filter(([, v]) => v !== false));
|
|
211
|
-
(0, mcp_writer_1.writeMcpServersToTargets)(filteredMcpServers, config.ides, cwd);
|
|
212
|
-
}
|
|
35
|
+
const inCI = isInCIEnvironment();
|
|
36
|
+
if (inCI && !installOnCI) {
|
|
37
|
+
console.log(chalk_1.default.yellow("Detected CI environment, skipping install."));
|
|
213
38
|
return {
|
|
214
39
|
success: true,
|
|
215
|
-
installedRuleCount,
|
|
216
|
-
packagesCount:
|
|
40
|
+
installedRuleCount: 0,
|
|
41
|
+
packagesCount: 0,
|
|
217
42
|
};
|
|
43
|
+
}
|
|
44
|
+
return (0, working_directory_1.withWorkingDirectory)(cwd, async () => {
|
|
45
|
+
const config = options.config || (await (0, config_1.getConfig)());
|
|
46
|
+
if (config === null || config === void 0 ? void 0 : config.workspaces) {
|
|
47
|
+
return await (0, install_workspaces_1.installWorkspaces)(cwd, installOnCI, options.verbose);
|
|
48
|
+
}
|
|
49
|
+
return (0, install_package_1.installPackage)(options);
|
|
218
50
|
});
|
|
219
51
|
}
|
|
220
|
-
async function installCommand(installOnCI,
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
52
|
+
async function installCommand(installOnCI, verbose) {
|
|
53
|
+
const result = await install({ installOnCI, verbose });
|
|
54
|
+
if (!result.success) {
|
|
55
|
+
const error = new Error(result.error);
|
|
56
|
+
if (result.errorStack) {
|
|
57
|
+
error.stack = result.errorStack;
|
|
58
|
+
}
|
|
59
|
+
throw error;
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
if (result.packagesCount > 1) {
|
|
63
|
+
console.log(`Successfully installed ${result.installedRuleCount} rules across ${result.packagesCount} packages`);
|
|
226
64
|
}
|
|
227
65
|
else {
|
|
228
|
-
|
|
229
|
-
console.log(`Successfully installed ${result.installedRuleCount} rules across ${result.packagesCount} packages`);
|
|
230
|
-
}
|
|
231
|
-
else if (workspaces) {
|
|
232
|
-
console.log(`Successfully installed ${result.installedRuleCount} rules across ${result.packagesCount} packages`);
|
|
233
|
-
}
|
|
234
|
-
else {
|
|
235
|
-
console.log("Rules installation completed");
|
|
236
|
-
}
|
|
66
|
+
console.log("Rules installation completed");
|
|
237
67
|
}
|
|
238
68
|
}
|
|
239
|
-
catch (error) {
|
|
240
|
-
console.error(chalk_1.default.red(error instanceof Error ? error.message : String(error)));
|
|
241
|
-
process.exit(1);
|
|
242
|
-
}
|
|
243
69
|
}
|
package/dist/commands/list.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare function listCommand(): void
|
|
1
|
+
export declare function listCommand(): Promise<void>;
|
package/dist/commands/list.js
CHANGED
|
@@ -8,8 +8,8 @@ const chalk_1 = __importDefault(require("chalk"));
|
|
|
8
8
|
const config_1 = require("../utils/config");
|
|
9
9
|
const rule_status_1 = require("../utils/rule-status");
|
|
10
10
|
const rule_detector_1 = require("../utils/rule-detector");
|
|
11
|
-
function listCommand() {
|
|
12
|
-
const config = (0, config_1.getConfig)();
|
|
11
|
+
async function listCommand() {
|
|
12
|
+
const config = await (0, config_1.getConfig)();
|
|
13
13
|
if (!config) {
|
|
14
14
|
console.log(chalk_1.default.red("Configuration file not found!"));
|
|
15
15
|
console.log(`Run ${chalk_1.default.blue("npx aicm init")} to create one.`);
|
|
@@ -24,6 +24,7 @@ async function installWorkspacesPackages(packages, options = {}) {
|
|
|
24
24
|
path: pkg.relativePath,
|
|
25
25
|
success: result.success,
|
|
26
26
|
error: result.error,
|
|
27
|
+
errorStack: result.errorStack,
|
|
27
28
|
installedRuleCount: result.installedRuleCount,
|
|
28
29
|
});
|
|
29
30
|
}
|
|
@@ -33,6 +34,7 @@ async function installWorkspacesPackages(packages, options = {}) {
|
|
|
33
34
|
path: pkg.relativePath,
|
|
34
35
|
success: false,
|
|
35
36
|
error: errorMessage,
|
|
37
|
+
errorStack: error instanceof Error ? error.stack : undefined,
|
|
36
38
|
installedRuleCount: 0,
|
|
37
39
|
});
|
|
38
40
|
}
|
package/dist/index.js
CHANGED
|
File without changes
|
package/dist/types/index.d.ts
CHANGED
|
@@ -21,7 +21,7 @@ export interface Config {
|
|
|
21
21
|
rules?: Rules | string;
|
|
22
22
|
presets?: string[];
|
|
23
23
|
mcpServers?: MCPServers;
|
|
24
|
-
|
|
24
|
+
workspaces?: boolean;
|
|
25
25
|
}
|
|
26
26
|
export interface NormalizedConfig extends Omit<Config, "rules"> {
|
|
27
27
|
ides: string[];
|
|
@@ -57,6 +57,7 @@ export interface WorkspacesInstallResult {
|
|
|
57
57
|
path: string;
|
|
58
58
|
success: boolean;
|
|
59
59
|
error?: string;
|
|
60
|
+
errorStack?: string;
|
|
60
61
|
installedRuleCount: number;
|
|
61
62
|
}>;
|
|
62
63
|
totalRuleCount: number;
|
package/dist/utils/config.d.ts
CHANGED
|
@@ -22,14 +22,14 @@ export declare function loadPreset(presetPath: string, cwd?: string): {
|
|
|
22
22
|
presets?: string[];
|
|
23
23
|
} | null;
|
|
24
24
|
/**
|
|
25
|
-
* Load the aicm config using
|
|
25
|
+
* Load the aicm config using cosmiconfig, supporting both aicm.json and package.json.
|
|
26
26
|
* Returns the config object or null if not found.
|
|
27
27
|
*/
|
|
28
|
-
export declare function loadAicmConfigCosmiconfig(searchFrom?: string): NormalizedConfig | null
|
|
28
|
+
export declare function loadAicmConfigCosmiconfig(searchFrom?: string): Promise<NormalizedConfig | null>;
|
|
29
29
|
/**
|
|
30
30
|
* Get the configuration from aicm.json or package.json (using cosmiconfigSync) and merge with any presets
|
|
31
31
|
*/
|
|
32
|
-
export declare function getConfig(cwd?: string): NormalizedConfig | null
|
|
32
|
+
export declare function getConfig(cwd?: string): Promise<NormalizedConfig | null>;
|
|
33
33
|
/**
|
|
34
34
|
* Get the source preset path for a rule if it came from a preset
|
|
35
35
|
*/
|
package/dist/utils/config.js
CHANGED
|
@@ -14,6 +14,7 @@ exports.saveConfig = saveConfig;
|
|
|
14
14
|
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
15
15
|
const node_path_1 = __importDefault(require("node:path"));
|
|
16
16
|
const cosmiconfig_1 = require("cosmiconfig");
|
|
17
|
+
const glob_handler_1 = require("./glob-handler");
|
|
17
18
|
const CONFIG_FILE = "aicm.json";
|
|
18
19
|
function normalizeRules(rules) {
|
|
19
20
|
if (!rules)
|
|
@@ -108,7 +109,7 @@ const processedPresets = new Set();
|
|
|
108
109
|
/**
|
|
109
110
|
* Process presets and return a new config with merged rules and metadata
|
|
110
111
|
*/
|
|
111
|
-
function processPresets(config, cwd) {
|
|
112
|
+
async function processPresets(config, cwd) {
|
|
112
113
|
// Create a deep copy of the config to avoid mutations
|
|
113
114
|
const newConfig = JSON.parse(JSON.stringify(config));
|
|
114
115
|
const metadata = {
|
|
@@ -117,12 +118,12 @@ function processPresets(config, cwd) {
|
|
|
117
118
|
};
|
|
118
119
|
// Clear processed presets tracking set when starting from the top level
|
|
119
120
|
processedPresets.clear();
|
|
120
|
-
return processPresetsInternal(newConfig, metadata, cwd);
|
|
121
|
+
return await processPresetsInternal(newConfig, metadata, cwd);
|
|
121
122
|
}
|
|
122
123
|
/**
|
|
123
124
|
* Internal function to process presets recursively
|
|
124
125
|
*/
|
|
125
|
-
function processPresetsInternal(config, metadata, cwd) {
|
|
126
|
+
async function processPresetsInternal(config, metadata, cwd) {
|
|
126
127
|
if (!config.presets || !Array.isArray(config.presets)) {
|
|
127
128
|
return { config, metadata };
|
|
128
129
|
}
|
|
@@ -133,7 +134,7 @@ function processPresetsInternal(config, metadata, cwd) {
|
|
|
133
134
|
}
|
|
134
135
|
// Skip if we've already processed this preset (prevents circular references)
|
|
135
136
|
if (processedPresets.has(pathInfo.fullPath)) {
|
|
136
|
-
|
|
137
|
+
// Skip duplicates to prevent circular references
|
|
137
138
|
continue;
|
|
138
139
|
}
|
|
139
140
|
// Mark this preset as processed
|
|
@@ -141,6 +142,10 @@ function processPresetsInternal(config, metadata, cwd) {
|
|
|
141
142
|
const preset = loadPreset(presetPath, cwd);
|
|
142
143
|
if (!preset)
|
|
143
144
|
continue;
|
|
145
|
+
// Expand glob patterns within the preset using its base directory
|
|
146
|
+
const presetDir = node_path_1.default.dirname(pathInfo.fullPath);
|
|
147
|
+
const expansion = await (0, glob_handler_1.expandRulesGlobPatterns)(preset.rules, presetDir);
|
|
148
|
+
preset.rules = expansion.expandedRules;
|
|
144
149
|
// Process nested presets first (depth-first)
|
|
145
150
|
if (preset.presets && preset.presets.length > 0) {
|
|
146
151
|
// Create a temporary config with just the presets from this preset
|
|
@@ -150,7 +155,7 @@ function processPresetsInternal(config, metadata, cwd) {
|
|
|
150
155
|
ides: [],
|
|
151
156
|
};
|
|
152
157
|
// Recursively process the nested presets
|
|
153
|
-
const { config: nestedConfig } = processPresetsInternal(presetConfig, metadata, cwd);
|
|
158
|
+
const { config: nestedConfig } = await processPresetsInternal(presetConfig, metadata, cwd);
|
|
154
159
|
Object.assign(preset.rules, nestedConfig.rules);
|
|
155
160
|
}
|
|
156
161
|
const { updatedConfig, updatedMetadata } = mergePresetRules(config, preset.rules, pathInfo, metadata);
|
|
@@ -213,15 +218,15 @@ function mergePresetMcpServers(configMcpServers, presetMcpServers) {
|
|
|
213
218
|
return newMcpServers;
|
|
214
219
|
}
|
|
215
220
|
/**
|
|
216
|
-
* Load the aicm config using
|
|
221
|
+
* Load the aicm config using cosmiconfig, supporting both aicm.json and package.json.
|
|
217
222
|
* Returns the config object or null if not found.
|
|
218
223
|
*/
|
|
219
|
-
function loadAicmConfigCosmiconfig(searchFrom) {
|
|
220
|
-
const explorer = (0, cosmiconfig_1.
|
|
224
|
+
async function loadAicmConfigCosmiconfig(searchFrom) {
|
|
225
|
+
const explorer = (0, cosmiconfig_1.cosmiconfig)("aicm", {
|
|
221
226
|
searchPlaces: ["package.json", "aicm.json"],
|
|
222
227
|
});
|
|
223
228
|
try {
|
|
224
|
-
const result = explorer.search(searchFrom);
|
|
229
|
+
const result = await explorer.search(searchFrom);
|
|
225
230
|
if (!result || !result.config)
|
|
226
231
|
return null;
|
|
227
232
|
const rawConfig = result.config;
|
|
@@ -240,13 +245,13 @@ function loadAicmConfigCosmiconfig(searchFrom) {
|
|
|
240
245
|
/**
|
|
241
246
|
* Get the configuration from aicm.json or package.json (using cosmiconfigSync) and merge with any presets
|
|
242
247
|
*/
|
|
243
|
-
function getConfig(cwd) {
|
|
248
|
+
async function getConfig(cwd) {
|
|
244
249
|
const workingDir = cwd || process.cwd();
|
|
245
|
-
const config = loadAicmConfigCosmiconfig(workingDir);
|
|
250
|
+
const config = await loadAicmConfigCosmiconfig(workingDir);
|
|
246
251
|
if (!config) {
|
|
247
252
|
throw new Error(`No config found in ${workingDir}, create one using "aicm init"`);
|
|
248
253
|
}
|
|
249
|
-
const { config: processedConfig, metadata } = processPresets(config, workingDir);
|
|
254
|
+
const { config: processedConfig, metadata } = await processPresets(config, workingDir);
|
|
250
255
|
// Store metadata for later access
|
|
251
256
|
currentMetadata = metadata;
|
|
252
257
|
return processedConfig;
|