aicm 0.12.1 → 0.13.0
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 +26 -11
- package/dist/api.d.ts +2 -2
- 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/workspaces/workspaces-install.js +2 -0
- package/dist/index.js +0 -0
- package/dist/types/index.d.ts +9 -4
- package/dist/utils/config.d.ts +7 -6
- package/dist/utils/config.js +20 -8
- package/dist/utils/mcp-writer.d.ts +3 -3
- package/dist/utils/working-directory.d.ts +5 -0
- package/dist/utils/working-directory.js +21 -0
- package/package.json +20 -19
- 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
package/README.md
CHANGED
|
@@ -157,10 +157,12 @@ To prevent [prompt-injection](https://en.wikipedia.org/wiki/Prompt_injection), u
|
|
|
157
157
|
|
|
158
158
|
aicm supports workspaces by automatically discovering and installing configurations across multiple packages in your repository.
|
|
159
159
|
|
|
160
|
-
To enable workspaces mode,
|
|
160
|
+
To enable workspaces mode, set the `workspaces` property to `true` in your root `aicm.json`:
|
|
161
161
|
|
|
162
|
-
```
|
|
163
|
-
|
|
162
|
+
```json
|
|
163
|
+
{
|
|
164
|
+
"workspaces": true
|
|
165
|
+
}
|
|
164
166
|
```
|
|
165
167
|
|
|
166
168
|
This will:
|
|
@@ -175,6 +177,7 @@ Each directory containing an `aicm.json` file is treated as a separate package w
|
|
|
175
177
|
For example, in a workspace structure like:
|
|
176
178
|
|
|
177
179
|
```
|
|
180
|
+
├── aicm.json (with "workspaces": true)
|
|
178
181
|
├── packages/
|
|
179
182
|
│ ├── frontend/
|
|
180
183
|
│ │ └── aicm.json
|
|
@@ -185,7 +188,7 @@ For example, in a workspace structure like:
|
|
|
185
188
|
└── aicm.json
|
|
186
189
|
```
|
|
187
190
|
|
|
188
|
-
Running `npx aicm install
|
|
191
|
+
Running `npx aicm install` will install rules for each package in their respective directories:
|
|
189
192
|
|
|
190
193
|
- `packages/frontend/.cursor/rules/aicm/`
|
|
191
194
|
- `packages/backend/.cursor/rules/aicm/`
|
|
@@ -223,7 +226,15 @@ Example `aicm.json`:
|
|
|
223
226
|
|
|
224
227
|
> **Note:** The 'ides' field is default to `["cursor"]` if not specified.
|
|
225
228
|
|
|
226
|
-
- **rules**: Object containing rule configurations
|
|
229
|
+
- **rules**: Object containing rule configurations.
|
|
230
|
+
If you want to install every rule from a single directory, you can also use a
|
|
231
|
+
string as a shortcut:
|
|
232
|
+
|
|
233
|
+
```json
|
|
234
|
+
{
|
|
235
|
+
"rules": "./rules/*"
|
|
236
|
+
}
|
|
237
|
+
```
|
|
227
238
|
|
|
228
239
|
- **rule-name**: A unique identifier for the rule. Can include a directory path to install the rule to a specific directory.
|
|
229
240
|
- **source-location**: Location of the rule file (path within an npm package or local path). Supports glob patterns for automatic file discovery.
|
|
@@ -262,8 +273,6 @@ The key becomes the base namespace for discovered files:
|
|
|
262
273
|
|
|
263
274
|
- Preset files should contain a `rules` and `mcpServers` objects with the same structure as the main configuration.
|
|
264
275
|
|
|
265
|
-
- **installOnCI**: Boolean flag (default: `false`) that controls whether installation should proceed in CI environments. When set to `true`, rules will be installed even in CI environments.
|
|
266
|
-
|
|
267
276
|
### MCP Server Installation
|
|
268
277
|
|
|
269
278
|
- **Cursor**: MCP server configs are written to `.cursor/mcp.json` (see Cursor docs for latest path).
|
|
@@ -312,6 +321,8 @@ Initializes a new configuration file in your current directory.
|
|
|
312
321
|
npx aicm init
|
|
313
322
|
```
|
|
314
323
|
|
|
324
|
+
Edit this file to add your rules, presets, or other settings.
|
|
325
|
+
|
|
315
326
|
### `install`
|
|
316
327
|
|
|
317
328
|
Installs all rules and MCPs configured in your `aicm.json`.
|
|
@@ -323,8 +334,7 @@ npx aicm install
|
|
|
323
334
|
Options:
|
|
324
335
|
|
|
325
336
|
- `--ci`: run in CI environments (default: `false`)
|
|
326
|
-
- `--
|
|
327
|
-
- `--verbose`: show detailed output during installation
|
|
337
|
+
- `--verbose`: show detailed output and stack traces for debugging
|
|
328
338
|
|
|
329
339
|
## Node.js API
|
|
330
340
|
|
|
@@ -369,8 +379,7 @@ Installs rules and MCP servers based on configuration.
|
|
|
369
379
|
- `cwd`: Base directory to use instead of `process.cwd()`
|
|
370
380
|
- `config`: Custom config object to use instead of loading from file
|
|
371
381
|
- `installOnCI`: Run installation on CI environments (default: `false`)
|
|
372
|
-
- `
|
|
373
|
-
- `verbose`: Show verbose output during installation (default: `false`)
|
|
382
|
+
- `verbose`: Show verbose output and stack traces for debugging (default: `false`)
|
|
374
383
|
|
|
375
384
|
**Returns:**
|
|
376
385
|
|
|
@@ -398,3 +407,9 @@ npm run test:unit
|
|
|
398
407
|
# Run only E2E tests
|
|
399
408
|
npm run test:e2e
|
|
400
409
|
```
|
|
410
|
+
|
|
411
|
+
### Publishing
|
|
412
|
+
|
|
413
|
+
```bash
|
|
414
|
+
npm run release
|
|
415
|
+
```
|
package/dist/api.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { InstallOptions, InstallResult } from "./commands/install";
|
|
1
|
+
import { InstallOptions, InstallResult } from "./commands/install/install-package";
|
|
2
2
|
/**
|
|
3
3
|
* Install AICM rules based on configuration
|
|
4
4
|
* @param options Installation options
|
|
5
5
|
* @returns Result of the install operation
|
|
6
6
|
*/
|
|
7
7
|
export declare function install(options?: InstallOptions): Promise<InstallResult>;
|
|
8
|
-
export { Config, Rule, Rules, RuleMetadata, RuleContent, RuleCollection, } from "./types";
|
|
8
|
+
export { Config, NormalizedConfig, Rule, Rules, RuleMetadata, RuleContent, RuleCollection, } from "./types";
|
package/dist/bin/aicm.js
ADDED
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.runCli = runCli;
|
|
8
|
+
const arg_1 = __importDefault(require("arg"));
|
|
9
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
10
|
+
const init_1 = require("./commands/init");
|
|
11
|
+
const install_1 = require("./commands/install");
|
|
12
|
+
const list_1 = require("./commands/list");
|
|
13
|
+
// Define version from package.json
|
|
14
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
15
|
+
const pkg = require("../package.json");
|
|
16
|
+
async function runCli() {
|
|
17
|
+
const args = (0, arg_1.default)({
|
|
18
|
+
"--help": Boolean,
|
|
19
|
+
"--version": Boolean,
|
|
20
|
+
"--ci": Boolean,
|
|
21
|
+
"--verbose": Boolean,
|
|
22
|
+
"-h": "--help",
|
|
23
|
+
"-v": "--version",
|
|
24
|
+
}, {
|
|
25
|
+
permissive: true,
|
|
26
|
+
argv: process.argv.slice(2),
|
|
27
|
+
});
|
|
28
|
+
// Show version
|
|
29
|
+
if (args["--version"]) {
|
|
30
|
+
console.log(pkg.version);
|
|
31
|
+
process.exit(0);
|
|
32
|
+
}
|
|
33
|
+
// Show help
|
|
34
|
+
if (args["--help"]) {
|
|
35
|
+
showHelp();
|
|
36
|
+
process.exit(0);
|
|
37
|
+
}
|
|
38
|
+
const command = args._.length > 0 ? args._[0] : null;
|
|
39
|
+
try {
|
|
40
|
+
switch (command) {
|
|
41
|
+
case "init":
|
|
42
|
+
(0, init_1.initCommand)();
|
|
43
|
+
break;
|
|
44
|
+
case "install":
|
|
45
|
+
await (0, install_1.installCommand)(args["--ci"], args["--verbose"]);
|
|
46
|
+
break;
|
|
47
|
+
case "list":
|
|
48
|
+
(0, list_1.listCommand)();
|
|
49
|
+
break;
|
|
50
|
+
default:
|
|
51
|
+
showHelp();
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
logError(error, args["--verbose"]);
|
|
57
|
+
process.exit(1);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function showHelp() {
|
|
61
|
+
console.log(`
|
|
62
|
+
${chalk_1.default.bold("aicm")} - A CLI tool for managing AI IDE configurations
|
|
63
|
+
|
|
64
|
+
${chalk_1.default.bold("USAGE")}
|
|
65
|
+
$ aicm [command] [options]
|
|
66
|
+
|
|
67
|
+
${chalk_1.default.bold("COMMANDS")}
|
|
68
|
+
init Initialize a new aicm configuration file
|
|
69
|
+
install Install rules from configured sources
|
|
70
|
+
list List all configured rules and their status
|
|
71
|
+
|
|
72
|
+
${chalk_1.default.bold("OPTIONS")}
|
|
73
|
+
-h, --help Show this help message
|
|
74
|
+
-v, --version Show version number
|
|
75
|
+
--ci Run in CI environments (default: \`false\`)
|
|
76
|
+
--verbose Show detailed output and stack traces for debugging
|
|
77
|
+
|
|
78
|
+
${chalk_1.default.bold("EXAMPLES")}
|
|
79
|
+
$ aicm init
|
|
80
|
+
$ aicm install
|
|
81
|
+
$ aicm list
|
|
82
|
+
`);
|
|
83
|
+
}
|
|
84
|
+
function logError(error, verbose = false) {
|
|
85
|
+
if (verbose && error instanceof Error && error.stack) {
|
|
86
|
+
console.error(chalk_1.default.red(error.stack));
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
console.error(chalk_1.default.red(error instanceof Error ? error.message : String(error)));
|
|
90
|
+
}
|
|
91
|
+
}
|
package/dist/commands/init.js
CHANGED
|
@@ -8,10 +8,7 @@ const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
|
8
8
|
const path_1 = __importDefault(require("path"));
|
|
9
9
|
const chalk_1 = __importDefault(require("chalk"));
|
|
10
10
|
const defaultConfig = {
|
|
11
|
-
ides: ["cursor"],
|
|
12
11
|
rules: {},
|
|
13
|
-
mcpServers: {},
|
|
14
|
-
installOnCI: false,
|
|
15
12
|
};
|
|
16
13
|
function initCommand() {
|
|
17
14
|
const configPath = path_1.default.join(process.cwd(), "aicm.json");
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { NormalizedConfig } from "../../types";
|
|
2
|
+
/**
|
|
3
|
+
* Options for the install functions
|
|
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
|
+
* Show verbose output during installation
|
|
20
|
+
*/
|
|
21
|
+
verbose?: boolean;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Result of the install operation
|
|
25
|
+
*/
|
|
26
|
+
export interface InstallResult {
|
|
27
|
+
/**
|
|
28
|
+
* Whether the operation was successful
|
|
29
|
+
*/
|
|
30
|
+
success: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Error message if the operation failed
|
|
33
|
+
*/
|
|
34
|
+
error?: string;
|
|
35
|
+
/**
|
|
36
|
+
* Error stack trace for debugging (when available)
|
|
37
|
+
*/
|
|
38
|
+
errorStack?: string;
|
|
39
|
+
/**
|
|
40
|
+
* Number of rules installed
|
|
41
|
+
*/
|
|
42
|
+
installedRuleCount: number;
|
|
43
|
+
/**
|
|
44
|
+
* Number of packages installed
|
|
45
|
+
*/
|
|
46
|
+
packagesCount: number;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Install rules for a single package (used within workspaces and standalone installs)
|
|
50
|
+
* @param options Install options
|
|
51
|
+
* @returns Result of the install operation
|
|
52
|
+
*/
|
|
53
|
+
export declare function installPackage(options?: InstallOptions): Promise<InstallResult>;
|
|
@@ -0,0 +1,122 @@
|
|
|
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
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
8
|
+
const config_1 = require("../../utils/config");
|
|
9
|
+
const rule_detector_1 = require("../../utils/rule-detector");
|
|
10
|
+
const working_directory_1 = require("../../utils/working-directory");
|
|
11
|
+
const rule_collector_1 = require("../../utils/rule-collector");
|
|
12
|
+
const rule_writer_1 = require("../../utils/rule-writer");
|
|
13
|
+
const mcp_writer_1 = require("../../utils/mcp-writer");
|
|
14
|
+
const glob_handler_1 = require("../../utils/glob-handler");
|
|
15
|
+
/**
|
|
16
|
+
* Install rules for a single package (used within workspaces and standalone installs)
|
|
17
|
+
* @param options Install options
|
|
18
|
+
* @returns Result of the install operation
|
|
19
|
+
*/
|
|
20
|
+
async function installPackage(options = {}) {
|
|
21
|
+
const cwd = options.cwd || process.cwd();
|
|
22
|
+
return (0, working_directory_1.withWorkingDirectory)(cwd, async () => {
|
|
23
|
+
const config = options.config || (0, config_1.getConfig)();
|
|
24
|
+
const ruleCollection = (0, rule_collector_1.initRuleCollection)();
|
|
25
|
+
if (!config) {
|
|
26
|
+
return {
|
|
27
|
+
success: false,
|
|
28
|
+
error: "Configuration file not found",
|
|
29
|
+
installedRuleCount: 0,
|
|
30
|
+
packagesCount: 0,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
// Check if rules are defined (either directly or through presets)
|
|
34
|
+
if (!config.rules || Object.keys(config.rules).length === 0) {
|
|
35
|
+
// If there are no presets defined either, show a message
|
|
36
|
+
if (!config.presets || config.presets.length === 0) {
|
|
37
|
+
return {
|
|
38
|
+
success: false,
|
|
39
|
+
error: "No rules defined in configuration",
|
|
40
|
+
installedRuleCount: 0,
|
|
41
|
+
packagesCount: 0,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
let expandedRules;
|
|
46
|
+
try {
|
|
47
|
+
const expansion = await (0, glob_handler_1.expandRulesGlobPatterns)(config.rules, cwd);
|
|
48
|
+
expandedRules = expansion.expandedRules;
|
|
49
|
+
if (options.verbose) {
|
|
50
|
+
for (const [expandedKey, originalPattern] of Object.entries(expansion.globSources)) {
|
|
51
|
+
console.log(chalk_1.default.gray(` Pattern "${originalPattern}" → ${expandedKey}`));
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
const errorMessage = `Error expanding glob patterns: ${error instanceof Error ? error.message : String(error)}`;
|
|
57
|
+
return {
|
|
58
|
+
success: false,
|
|
59
|
+
error: errorMessage,
|
|
60
|
+
errorStack: error instanceof Error ? error.stack : undefined,
|
|
61
|
+
installedRuleCount: 0,
|
|
62
|
+
packagesCount: 0,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
let hasErrors = false;
|
|
66
|
+
const errorMessages = [];
|
|
67
|
+
let firstErrorStack;
|
|
68
|
+
let installedRuleCount = 0;
|
|
69
|
+
for (const [name, source] of Object.entries(expandedRules)) {
|
|
70
|
+
const ruleType = (0, rule_detector_1.detectRuleType)(source);
|
|
71
|
+
const ruleBasePath = (0, config_1.getRuleSource)(config, name);
|
|
72
|
+
const originalPresetPath = (0, config_1.getOriginalPresetPath)(config, name);
|
|
73
|
+
try {
|
|
74
|
+
let ruleContent;
|
|
75
|
+
switch (ruleType) {
|
|
76
|
+
case "npm":
|
|
77
|
+
ruleContent = (0, rule_collector_1.collectNpmRule)(name, source);
|
|
78
|
+
break;
|
|
79
|
+
case "local":
|
|
80
|
+
ruleContent = (0, rule_collector_1.collectLocalRule)(name, source, ruleBasePath);
|
|
81
|
+
break;
|
|
82
|
+
default:
|
|
83
|
+
errorMessages.push(`Unknown rule type: ${ruleType}`);
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
if (originalPresetPath) {
|
|
87
|
+
ruleContent.presetPath = originalPresetPath;
|
|
88
|
+
}
|
|
89
|
+
(0, rule_collector_1.addRuleToCollection)(ruleCollection, ruleContent, config.ides);
|
|
90
|
+
installedRuleCount++;
|
|
91
|
+
}
|
|
92
|
+
catch (e) {
|
|
93
|
+
hasErrors = true;
|
|
94
|
+
const errorMessage = `Error processing rule ${name}: ${e instanceof Error ? e.message : String(e)}`;
|
|
95
|
+
errorMessages.push(errorMessage);
|
|
96
|
+
// Keep the first error stack trace
|
|
97
|
+
if (!firstErrorStack && e instanceof Error && e.stack) {
|
|
98
|
+
firstErrorStack = e.stack;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
if (hasErrors) {
|
|
103
|
+
return {
|
|
104
|
+
success: false,
|
|
105
|
+
error: errorMessages.join("; "),
|
|
106
|
+
errorStack: firstErrorStack,
|
|
107
|
+
installedRuleCount,
|
|
108
|
+
packagesCount: 0,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
(0, rule_writer_1.writeRulesToTargets)(ruleCollection);
|
|
112
|
+
if (config.mcpServers) {
|
|
113
|
+
const filteredMcpServers = Object.fromEntries(Object.entries(config.mcpServers).filter(([, v]) => v !== false));
|
|
114
|
+
(0, mcp_writer_1.writeMcpServersToTargets)(filteredMcpServers, config.ides, cwd);
|
|
115
|
+
}
|
|
116
|
+
return {
|
|
117
|
+
success: true,
|
|
118
|
+
installedRuleCount,
|
|
119
|
+
packagesCount: 1,
|
|
120
|
+
};
|
|
121
|
+
});
|
|
122
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { NormalizedConfig } from "../../types";
|
|
2
|
+
/**
|
|
3
|
+
* Options for the install functions
|
|
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
|
+
* Show verbose output during installation
|
|
20
|
+
*/
|
|
21
|
+
verbose?: boolean;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Result of the install operation
|
|
25
|
+
*/
|
|
26
|
+
export interface InstallResult {
|
|
27
|
+
/**
|
|
28
|
+
* Whether the operation was successful
|
|
29
|
+
*/
|
|
30
|
+
success: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Error message if the operation failed
|
|
33
|
+
*/
|
|
34
|
+
error?: string;
|
|
35
|
+
/**
|
|
36
|
+
* Error stack trace for debugging (when available)
|
|
37
|
+
*/
|
|
38
|
+
errorStack?: string;
|
|
39
|
+
/**
|
|
40
|
+
* Number of rules installed
|
|
41
|
+
*/
|
|
42
|
+
installedRuleCount: number;
|
|
43
|
+
/**
|
|
44
|
+
* Number of packages installed
|
|
45
|
+
*/
|
|
46
|
+
packagesCount: number;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Core single package installation logic
|
|
50
|
+
* @param options Install options
|
|
51
|
+
* @returns Result of the install operation
|
|
52
|
+
*/
|
|
53
|
+
export declare function installSinglePackage(options?: InstallOptions): Promise<InstallResult>;
|
|
@@ -0,0 +1,139 @@
|
|
|
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.installSinglePackage = installSinglePackage;
|
|
7
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
8
|
+
const config_1 = require("../../utils/config");
|
|
9
|
+
const rule_detector_1 = require("../../utils/rule-detector");
|
|
10
|
+
const rule_collector_1 = require("../../utils/rule-collector");
|
|
11
|
+
const rule_writer_1 = require("../../utils/rule-writer");
|
|
12
|
+
const mcp_writer_1 = require("../../utils/mcp-writer");
|
|
13
|
+
const glob_handler_1 = require("../../utils/glob-handler");
|
|
14
|
+
/**
|
|
15
|
+
* Helper function to execute a function within a specific working directory
|
|
16
|
+
* and ensure the original directory is always restored
|
|
17
|
+
*/
|
|
18
|
+
async function withWorkingDirectory(targetDir, fn) {
|
|
19
|
+
const originalCwd = process.cwd();
|
|
20
|
+
if (targetDir !== originalCwd) {
|
|
21
|
+
process.chdir(targetDir);
|
|
22
|
+
}
|
|
23
|
+
try {
|
|
24
|
+
return await fn();
|
|
25
|
+
}
|
|
26
|
+
finally {
|
|
27
|
+
if (targetDir !== originalCwd) {
|
|
28
|
+
process.chdir(originalCwd);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Core single package installation logic
|
|
34
|
+
* @param options Install options
|
|
35
|
+
* @returns Result of the install operation
|
|
36
|
+
*/
|
|
37
|
+
async function installSinglePackage(options = {}) {
|
|
38
|
+
const cwd = options.cwd || process.cwd();
|
|
39
|
+
return withWorkingDirectory(cwd, async () => {
|
|
40
|
+
const config = options.config || (0, config_1.getConfig)();
|
|
41
|
+
const ruleCollection = (0, rule_collector_1.initRuleCollection)();
|
|
42
|
+
if (!config) {
|
|
43
|
+
return {
|
|
44
|
+
success: false,
|
|
45
|
+
error: "Configuration file not found",
|
|
46
|
+
installedRuleCount: 0,
|
|
47
|
+
packagesCount: 0,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
// Check if rules are defined (either directly or through presets)
|
|
51
|
+
if (!config.rules || Object.keys(config.rules).length === 0) {
|
|
52
|
+
// If there are no presets defined either, show a message
|
|
53
|
+
if (!config.presets || config.presets.length === 0) {
|
|
54
|
+
return {
|
|
55
|
+
success: false,
|
|
56
|
+
error: "No rules defined in configuration",
|
|
57
|
+
installedRuleCount: 0,
|
|
58
|
+
packagesCount: 0,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
let expandedRules;
|
|
63
|
+
try {
|
|
64
|
+
const expansion = await (0, glob_handler_1.expandRulesGlobPatterns)(config.rules, cwd);
|
|
65
|
+
expandedRules = expansion.expandedRules;
|
|
66
|
+
if (options.verbose) {
|
|
67
|
+
for (const [expandedKey, originalPattern] of Object.entries(expansion.globSources)) {
|
|
68
|
+
console.log(chalk_1.default.gray(` Pattern "${originalPattern}" → ${expandedKey}`));
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
const errorMessage = `Error expanding glob patterns: ${error instanceof Error ? error.message : String(error)}`;
|
|
74
|
+
return {
|
|
75
|
+
success: false,
|
|
76
|
+
error: errorMessage,
|
|
77
|
+
errorStack: error instanceof Error ? error.stack : undefined,
|
|
78
|
+
installedRuleCount: 0,
|
|
79
|
+
packagesCount: 0,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
let hasErrors = false;
|
|
83
|
+
const errorMessages = [];
|
|
84
|
+
let firstErrorStack;
|
|
85
|
+
let installedRuleCount = 0;
|
|
86
|
+
for (const [name, source] of Object.entries(expandedRules)) {
|
|
87
|
+
const ruleType = (0, rule_detector_1.detectRuleType)(source);
|
|
88
|
+
const ruleBasePath = (0, config_1.getRuleSource)(config, name);
|
|
89
|
+
const originalPresetPath = (0, config_1.getOriginalPresetPath)(config, name);
|
|
90
|
+
try {
|
|
91
|
+
let ruleContent;
|
|
92
|
+
switch (ruleType) {
|
|
93
|
+
case "npm":
|
|
94
|
+
ruleContent = (0, rule_collector_1.collectNpmRule)(name, source);
|
|
95
|
+
break;
|
|
96
|
+
case "local":
|
|
97
|
+
ruleContent = (0, rule_collector_1.collectLocalRule)(name, source, ruleBasePath);
|
|
98
|
+
break;
|
|
99
|
+
default:
|
|
100
|
+
errorMessages.push(`Unknown rule type: ${ruleType}`);
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
if (originalPresetPath) {
|
|
104
|
+
ruleContent.presetPath = originalPresetPath;
|
|
105
|
+
}
|
|
106
|
+
(0, rule_collector_1.addRuleToCollection)(ruleCollection, ruleContent, config.ides);
|
|
107
|
+
installedRuleCount++;
|
|
108
|
+
}
|
|
109
|
+
catch (e) {
|
|
110
|
+
hasErrors = true;
|
|
111
|
+
const errorMessage = `Error processing rule ${name}: ${e instanceof Error ? e.message : String(e)}`;
|
|
112
|
+
errorMessages.push(errorMessage);
|
|
113
|
+
// Keep the first error stack trace
|
|
114
|
+
if (!firstErrorStack && e instanceof Error && e.stack) {
|
|
115
|
+
firstErrorStack = e.stack;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (hasErrors) {
|
|
120
|
+
return {
|
|
121
|
+
success: false,
|
|
122
|
+
error: errorMessages.join("; "),
|
|
123
|
+
errorStack: firstErrorStack,
|
|
124
|
+
installedRuleCount,
|
|
125
|
+
packagesCount: 0,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
(0, rule_writer_1.writeRulesToTargets)(ruleCollection);
|
|
129
|
+
if (config.mcpServers) {
|
|
130
|
+
const filteredMcpServers = Object.fromEntries(Object.entries(config.mcpServers).filter(([, v]) => v !== false));
|
|
131
|
+
(0, mcp_writer_1.writeMcpServersToTargets)(filteredMcpServers, config.ides, cwd);
|
|
132
|
+
}
|
|
133
|
+
return {
|
|
134
|
+
success: true,
|
|
135
|
+
installedRuleCount,
|
|
136
|
+
packagesCount: 1,
|
|
137
|
+
};
|
|
138
|
+
});
|
|
139
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { InstallResult } from "./install-package";
|
|
2
|
+
/**
|
|
3
|
+
* Install rules across multiple packages in a workspace
|
|
4
|
+
* @param cwd The current working directory
|
|
5
|
+
* @param installOnCI Whether to install on CI environments
|
|
6
|
+
* @param verbose Whether to show verbose output
|
|
7
|
+
* @returns Result of the install operation
|
|
8
|
+
*/
|
|
9
|
+
export declare function installWorkspaces(cwd: string, installOnCI: boolean, verbose?: boolean): Promise<InstallResult>;
|