@adobe-commerce/aio-toolkit 1.0.14 → 1.0.16

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.
@@ -0,0 +1,1168 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
10
+ var __esm = (fn, res) => function __init() {
11
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
12
+ };
13
+ var __export = (target, all) => {
14
+ for (var name in all)
15
+ __defProp(target, name, { get: all[name], enumerable: true });
16
+ };
17
+ var __copyProps = (to, from, except, desc) => {
18
+ if (from && typeof from === "object" || typeof from === "function") {
19
+ for (let key of __getOwnPropNames(from))
20
+ if (!__hasOwnProp.call(to, key) && key !== except)
21
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
22
+ }
23
+ return to;
24
+ };
25
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
26
+ // If the importer is in node compatibility mode or this is not an ESM
27
+ // file that has been converted to a CommonJS file using a Babel-
28
+ // compatible transform (i.e. "__esModule" has not been set), then set
29
+ // "default" to the CommonJS "module.exports" for node compatibility.
30
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
31
+ mod
32
+ ));
33
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
34
+
35
+ // src/commands/framework/command/abstract/index.ts
36
+ var _CommandAbstract, CommandAbstract;
37
+ var init_abstract = __esm({
38
+ "src/commands/framework/command/abstract/index.ts"() {
39
+ "use strict";
40
+ _CommandAbstract = class _CommandAbstract {
41
+ /**
42
+ * Method to get the name of the command
43
+ * @returns {string} The name of the command
44
+ */
45
+ static getName() {
46
+ throw new Error("getName() must be implemented by subclass");
47
+ }
48
+ /**
49
+ * Method to get the description of the command
50
+ * @returns {string} The description of the command
51
+ */
52
+ static getDescription() {
53
+ throw new Error("getDescription() must be implemented by subclass");
54
+ }
55
+ /**
56
+ * Method to execute the command
57
+ * @param {...any} args - Command arguments
58
+ * @returns {Promise<CommandResult>} The execution result
59
+ */
60
+ static execute(...args2) {
61
+ throw new Error(`execute() must be implemented by subclass: ${args2.join(", ")}`);
62
+ }
63
+ };
64
+ __name(_CommandAbstract, "CommandAbstract");
65
+ CommandAbstract = _CommandAbstract;
66
+ }
67
+ });
68
+
69
+ // src/commands/framework/command/base-help/index.ts
70
+ var _BaseHelpCommand, BaseHelpCommand;
71
+ var init_base_help = __esm({
72
+ "src/commands/framework/command/base-help/index.ts"() {
73
+ "use strict";
74
+ init_abstract();
75
+ _BaseHelpCommand = class _BaseHelpCommand extends CommandAbstract {
76
+ /**
77
+ * Method to get the description of the command
78
+ * @returns {string} The description of the command
79
+ */
80
+ static getName() {
81
+ return this.NAME;
82
+ }
83
+ /**
84
+ * Static method to get the commands - must be implemented by subclasses
85
+ *
86
+ * @returns {CommandDescriptor[]} The commands
87
+ */
88
+ static getCliName() {
89
+ throw new Error("getCliName() must be implemented by subclass");
90
+ }
91
+ /**
92
+ * Get the commands dynamically
93
+ *
94
+ * @returns {CommandDescriptor[]} The commands array
95
+ */
96
+ static getCommands() {
97
+ throw new Error("getCommands() must be implemented by subclass");
98
+ }
99
+ /**
100
+ * Method to execute the command
101
+ * @param {...any} _args - Command arguments (unused)
102
+ * @returns {Promise<CommandResult>} The execution result
103
+ */
104
+ static execute(..._args) {
105
+ const helpText = [
106
+ this.getUsageSection(),
107
+ this.getCommandsSection(),
108
+ this.getExamplesSection(),
109
+ this.getFooterSection()
110
+ ].join("\n");
111
+ return {
112
+ success: true,
113
+ message: helpText
114
+ };
115
+ }
116
+ /**
117
+ * Get the usage section
118
+ *
119
+ * @returns {string} The usage section
120
+ */
121
+ static getUsageSection() {
122
+ return `Usage: npx ${this.getCliName()} <command>`;
123
+ }
124
+ /**
125
+ * Get the commands section
126
+ *
127
+ * @returns {string} The commands section
128
+ */
129
+ static getCommandsSection() {
130
+ const commands = this.getCommands();
131
+ const maxNameLength = Math.max(...commands.map((cmd) => cmd.name.length));
132
+ const commandsList = commands.map((cmd) => ` ${cmd.name.padEnd(maxNameLength + 2)}${cmd.description}`).join("\n");
133
+ return `
134
+ Commands:
135
+ ${commandsList}`;
136
+ }
137
+ /**
138
+ * Get the examples section
139
+ *
140
+ * @returns {string} The examples section
141
+ */
142
+ static getExamplesSection() {
143
+ const commands = this.getCommands();
144
+ const examples = commands.map((cmd) => ` npx ${this.getCliName()} ${cmd.name}`).join("\n");
145
+ return `
146
+ Examples:
147
+ ${examples}`;
148
+ }
149
+ /**
150
+ * Get the footer section with additional information
151
+ *
152
+ * @returns {string} The footer section
153
+ */
154
+ static getFooterSection() {
155
+ return `
156
+ For more information, visit:
157
+ ${this.repositoryUrl}
158
+ `;
159
+ }
160
+ };
161
+ __name(_BaseHelpCommand, "BaseHelpCommand");
162
+ /**
163
+ * Static command name
164
+ */
165
+ _BaseHelpCommand.NAME = "help";
166
+ /**
167
+ * Static repository URL
168
+ */
169
+ _BaseHelpCommand.repositoryUrl = "https://github.com/adobe-commerce/aio-toolkit";
170
+ BaseHelpCommand = _BaseHelpCommand;
171
+ }
172
+ });
173
+
174
+ // src/commands/cursor-context/lib/help/index.ts
175
+ var _CursorContextHelp, CursorContextHelp;
176
+ var init_help = __esm({
177
+ "src/commands/cursor-context/lib/help/index.ts"() {
178
+ "use strict";
179
+ init_base_help();
180
+ _CursorContextHelp = class _CursorContextHelp extends BaseHelpCommand {
181
+ /**
182
+ * Get the CLI name
183
+ * This is used to display the correct help text for the CLI.
184
+ *
185
+ * @returns {string} The CLI name
186
+ */
187
+ static getCliName() {
188
+ return "aio-toolkit-cursor-context";
189
+ }
190
+ /**
191
+ * Method to get the description of the command
192
+ * @returns {string} The description of the command
193
+ */
194
+ static getDescription() {
195
+ return this.DESCRIPTION;
196
+ }
197
+ /**
198
+ * Get commands dynamically to avoid circular dependency
199
+ * This will be populated when CursorRules is initialized
200
+ *
201
+ * @returns {CommandDescriptor[]} The commands array
202
+ */
203
+ static getCommands() {
204
+ const { CursorRules: CursorRules2 } = (init_lib(), __toCommonJS(lib_exports));
205
+ return CursorRules2.getCommands();
206
+ }
207
+ };
208
+ __name(_CursorContextHelp, "CursorContextHelp");
209
+ /**
210
+ * Static command description
211
+ */
212
+ _CursorContextHelp.DESCRIPTION = "Show help for the rules commands";
213
+ CursorContextHelp = _CursorContextHelp;
214
+ }
215
+ });
216
+
217
+ // src/commands/framework/helpers/package-rules-path/index.ts
218
+ var fs, path, _PackageRulesPath, PackageRulesPath;
219
+ var init_package_rules_path = __esm({
220
+ "src/commands/framework/helpers/package-rules-path/index.ts"() {
221
+ "use strict";
222
+ fs = __toESM(require("fs"));
223
+ path = __toESM(require("path"));
224
+ _PackageRulesPath = class _PackageRulesPath {
225
+ /**
226
+ * Get the package rules path
227
+ * @param {string} rulesPath - The relative path to rules within the package (e.g., 'src/cursor/rules')
228
+ * @returns {string | null} The absolute path to rules in the installed package, or null if not found
229
+ */
230
+ static get(rulesPath) {
231
+ try {
232
+ const packageRoot = this.findPackageRoot();
233
+ if (packageRoot) {
234
+ const fullRulesPath = path.join(packageRoot, rulesPath);
235
+ if (fs.existsSync(fullRulesPath)) {
236
+ return fullRulesPath;
237
+ }
238
+ }
239
+ return null;
240
+ } catch {
241
+ return null;
242
+ }
243
+ }
244
+ /**
245
+ * Find the package root directory
246
+ * @returns {string | null} The package root path or null if not found
247
+ */
248
+ static findPackageRoot() {
249
+ let currentDir = __dirname;
250
+ for (let i = 0; i < 10; i++) {
251
+ const packageJsonPath = path.join(currentDir, "package.json");
252
+ if (fs.existsSync(packageJsonPath)) {
253
+ try {
254
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
255
+ if (packageJson.name === "@adobe-commerce/aio-toolkit") {
256
+ return currentDir;
257
+ }
258
+ } catch {
259
+ }
260
+ }
261
+ const parentDir = path.dirname(currentDir);
262
+ if (parentDir === currentDir) break;
263
+ currentDir = parentDir;
264
+ }
265
+ return null;
266
+ }
267
+ };
268
+ __name(_PackageRulesPath, "PackageRulesPath");
269
+ PackageRulesPath = _PackageRulesPath;
270
+ }
271
+ });
272
+
273
+ // src/commands/framework/helpers/rule-files/index.ts
274
+ var fs2, _RuleFiles, RuleFiles;
275
+ var init_rule_files = __esm({
276
+ "src/commands/framework/helpers/rule-files/index.ts"() {
277
+ "use strict";
278
+ fs2 = __toESM(require("fs"));
279
+ _RuleFiles = class _RuleFiles {
280
+ /**
281
+ * Get all rule files from a directory
282
+ * @param {string} dirPath - The path to the directory containing rule files
283
+ * @returns {string[]} Array of rule file names
284
+ */
285
+ static get(dirPath) {
286
+ try {
287
+ if (!fs2.existsSync(dirPath)) {
288
+ return [];
289
+ }
290
+ const files = fs2.readdirSync(dirPath);
291
+ return files.filter((file) => this.ruleExtensions.some((ext) => file.endsWith(ext)));
292
+ } catch {
293
+ return [];
294
+ }
295
+ }
296
+ };
297
+ __name(_RuleFiles, "RuleFiles");
298
+ _RuleFiles.ruleExtensions = [".mdc", ".md"];
299
+ RuleFiles = _RuleFiles;
300
+ }
301
+ });
302
+
303
+ // src/commands/framework/helpers/directory-exists/index.ts
304
+ var fs3, _DirectoryExists, DirectoryExists;
305
+ var init_directory_exists = __esm({
306
+ "src/commands/framework/helpers/directory-exists/index.ts"() {
307
+ "use strict";
308
+ fs3 = __toESM(require("fs"));
309
+ _DirectoryExists = class _DirectoryExists {
310
+ /**
311
+ * Check if a directory exists
312
+ * @param {string} dirPath - The directory path to check
313
+ * @returns {boolean} True if directory exists and is a directory
314
+ */
315
+ static is(dirPath) {
316
+ try {
317
+ return fs3.existsSync(dirPath) && fs3.statSync(dirPath).isDirectory();
318
+ } catch {
319
+ return false;
320
+ }
321
+ }
322
+ /**
323
+ * Ensure a directory exists, create if it doesn't
324
+ * @param {string} dirPath - The directory path to ensure
325
+ * @returns {void}
326
+ */
327
+ static ensure(dirPath) {
328
+ if (!this.is(dirPath)) {
329
+ fs3.mkdirSync(dirPath, { recursive: true });
330
+ }
331
+ }
332
+ };
333
+ __name(_DirectoryExists, "DirectoryExists");
334
+ DirectoryExists = _DirectoryExists;
335
+ }
336
+ });
337
+
338
+ // src/commands/framework/helpers/format-messages/index.ts
339
+ var _FormatMessages, FormatMessages;
340
+ var init_format_messages = __esm({
341
+ "src/commands/framework/helpers/format-messages/index.ts"() {
342
+ "use strict";
343
+ _FormatMessages = class _FormatMessages {
344
+ /**
345
+ * Format an array of messages into a single string
346
+ * @param {string[]} messages - Array of message lines
347
+ * @returns {string} Formatted message string
348
+ */
349
+ static execute(messages) {
350
+ return messages.join("\n");
351
+ }
352
+ };
353
+ __name(_FormatMessages, "FormatMessages");
354
+ FormatMessages = _FormatMessages;
355
+ }
356
+ });
357
+
358
+ // src/commands/framework/helpers/package-path/index.ts
359
+ var fs4, path2, _PackagePath, PackagePath;
360
+ var init_package_path = __esm({
361
+ "src/commands/framework/helpers/package-path/index.ts"() {
362
+ "use strict";
363
+ fs4 = __toESM(require("fs"));
364
+ path2 = __toESM(require("path"));
365
+ _PackagePath = class _PackagePath {
366
+ /**
367
+ * Find the path to a package in node_modules
368
+ *
369
+ * @param {string} packageName - The name of the package to find (e.g., '@adobe-commerce/commerce-extensibility-tools')
370
+ * @param {string} projectPath - The project root path (defaults to current directory)
371
+ * @returns {string | null} The absolute path to the package, or null if not found
372
+ */
373
+ static find(packageName, projectPath = process.cwd()) {
374
+ try {
375
+ let currentDir = projectPath;
376
+ const maxIterations = 10;
377
+ for (let i = 0; i < maxIterations; i++) {
378
+ const nodeModulesPath = path2.join(currentDir, "node_modules");
379
+ if (fs4.existsSync(nodeModulesPath)) {
380
+ const packagePath = path2.join(nodeModulesPath, packageName);
381
+ if (fs4.existsSync(packagePath)) {
382
+ return packagePath;
383
+ }
384
+ }
385
+ const parentDir = path2.dirname(currentDir);
386
+ if (parentDir === currentDir) {
387
+ break;
388
+ }
389
+ currentDir = parentDir;
390
+ }
391
+ return null;
392
+ } catch (error) {
393
+ return null;
394
+ }
395
+ }
396
+ /**
397
+ * Get the entry point file path for a package
398
+ *
399
+ * @param {string} packageName - The name of the package
400
+ * @param {string} projectPath - The project root path (defaults to current directory)
401
+ * @returns {string | null} The relative path from project root to the package entry point, or null if not found
402
+ */
403
+ static getEntryPoint(packageName, projectPath = process.cwd()) {
404
+ try {
405
+ const packagePath = this.find(packageName, projectPath);
406
+ if (!packagePath) {
407
+ return null;
408
+ }
409
+ const packageJsonPath = path2.join(packagePath, "package.json");
410
+ if (!fs4.existsSync(packageJsonPath)) {
411
+ const defaultEntry = path2.join(packagePath, "index.js");
412
+ if (fs4.existsSync(defaultEntry)) {
413
+ return path2.relative(projectPath, defaultEntry);
414
+ }
415
+ return null;
416
+ }
417
+ const packageJson = JSON.parse(fs4.readFileSync(packageJsonPath, "utf-8"));
418
+ const entryPoint = packageJson.main || "index.js";
419
+ const entryPointPath = path2.join(packagePath, entryPoint);
420
+ if (!fs4.existsSync(entryPointPath)) {
421
+ return null;
422
+ }
423
+ return path2.relative(projectPath, entryPointPath);
424
+ } catch (error) {
425
+ return null;
426
+ }
427
+ }
428
+ };
429
+ __name(_PackagePath, "PackagePath");
430
+ PackagePath = _PackagePath;
431
+ }
432
+ });
433
+
434
+ // src/commands/framework/helpers/mcp-config/index.ts
435
+ var fs5, path3, _McpConfig, McpConfig;
436
+ var init_mcp_config = __esm({
437
+ "src/commands/framework/helpers/mcp-config/index.ts"() {
438
+ "use strict";
439
+ fs5 = __toESM(require("fs"));
440
+ path3 = __toESM(require("path"));
441
+ init_package_path();
442
+ _McpConfig = class _McpConfig {
443
+ /**
444
+ * Create or update MCP configuration file
445
+ *
446
+ * @param {string} projectPath - The project root path (defaults to current directory)
447
+ * @returns {McpConfigResult} Result object with success status and reason
448
+ */
449
+ static createOrUpdate(projectPath = process.cwd()) {
450
+ try {
451
+ const mcpFilePath = path3.join(projectPath, ".cursor", "mcp.json");
452
+ const packageName = "@adobe-commerce/commerce-extensibility-tools";
453
+ const packageEntryPoint = PackagePath.getEntryPoint(packageName, projectPath);
454
+ if (!packageEntryPoint) {
455
+ return {
456
+ success: false,
457
+ reason: "peer-dependency-missing",
458
+ message: `Package '${packageName}' not found. Install it to enable MCP server integration:
459
+ npm install ${packageName}`
460
+ };
461
+ }
462
+ const commerceExtensibilityConfig = {
463
+ command: "node",
464
+ args: [packageEntryPoint.replace(/\\/g, "/")],
465
+ // Normalize path separators for cross-platform
466
+ env: {}
467
+ };
468
+ let existingConfig = null;
469
+ const fileExists = fs5.existsSync(mcpFilePath);
470
+ if (fileExists) {
471
+ try {
472
+ const existingContent = fs5.readFileSync(mcpFilePath, "utf-8");
473
+ existingConfig = JSON.parse(existingContent);
474
+ } catch (error) {
475
+ existingConfig = null;
476
+ }
477
+ }
478
+ const mcpConfig = {
479
+ mcpServers: existingConfig?.mcpServers ? {
480
+ ...existingConfig.mcpServers,
481
+ "commerce-extensibility": commerceExtensibilityConfig
482
+ } : {
483
+ "commerce-extensibility": commerceExtensibilityConfig
484
+ }
485
+ };
486
+ fs5.writeFileSync(mcpFilePath, JSON.stringify(mcpConfig, null, 2) + "\n", "utf-8");
487
+ return {
488
+ success: true,
489
+ reason: fileExists ? "updated" : "created",
490
+ message: fileExists ? "MCP configuration updated at .cursor/mcp.json" : "MCP configuration created at .cursor/mcp.json"
491
+ };
492
+ } catch (error) {
493
+ return {
494
+ success: false,
495
+ reason: "error",
496
+ message: `Failed to create MCP config: ${error instanceof Error ? error.message : String(error)}`
497
+ };
498
+ }
499
+ }
500
+ /**
501
+ * Check if MCP configuration exists
502
+ *
503
+ * @param {string} projectPath - The project root path (defaults to current directory)
504
+ * @returns {boolean} True if mcp.json exists, false otherwise
505
+ */
506
+ static exists(projectPath = process.cwd()) {
507
+ const mcpFilePath = path3.join(projectPath, ".cursor", "mcp.json");
508
+ return fs5.existsSync(mcpFilePath);
509
+ }
510
+ /**
511
+ * Get the path to the MCP configuration file
512
+ *
513
+ * @param {string} projectPath - The project root path (defaults to current directory)
514
+ * @returns {string} The path to mcp.json
515
+ */
516
+ static getPath(projectPath = process.cwd()) {
517
+ return path3.join(projectPath, ".cursor", "mcp.json");
518
+ }
519
+ };
520
+ __name(_McpConfig, "McpConfig");
521
+ McpConfig = _McpConfig;
522
+ }
523
+ });
524
+
525
+ // src/commands/framework/helpers/cursor-ide-detector/index.ts
526
+ var os, _CursorIdeDetector, CursorIdeDetector;
527
+ var init_cursor_ide_detector = __esm({
528
+ "src/commands/framework/helpers/cursor-ide-detector/index.ts"() {
529
+ "use strict";
530
+ os = __toESM(require("os"));
531
+ _CursorIdeDetector = class _CursorIdeDetector {
532
+ /**
533
+ * Check if Cursor IDE is being used
534
+ * @returns {boolean} True if Cursor IDE is detected, false otherwise
535
+ */
536
+ static isCursorIde() {
537
+ try {
538
+ if (process.env.CURSOR || process.env.CURSOR_IDE || process.env.CURSOR_TRACE_ID || process.env.CURSOR_AGENT || process.env.__CFBundleIdentifier && process.env.__CFBundleIdentifier.startsWith("com.todesktop.")) {
539
+ return true;
540
+ }
541
+ const execPath = process.execPath.toLowerCase();
542
+ const cursorPaths = ["cursor.app", "cursor.exe"];
543
+ const isMacOsSpecificPath = execPath.includes("/applications/cursor.app/contents");
544
+ if (cursorPaths.some((cursorPath) => execPath.includes(cursorPath)) && !isMacOsSpecificPath) {
545
+ return true;
546
+ }
547
+ if (process.env._) {
548
+ const parentProcess = process.env._.toLowerCase();
549
+ if (parentProcess.includes("cursor.app") || parentProcess.includes("cursor.exe") || parentProcess.endsWith("/cursor")) {
550
+ return true;
551
+ }
552
+ }
553
+ const platform2 = os.platform();
554
+ if (platform2 === "darwin") {
555
+ if (execPath.includes("/applications/cursor.app/contents")) {
556
+ return true;
557
+ }
558
+ } else if (platform2 === "win32") {
559
+ if (execPath.includes("cursor") && (execPath.includes("program files") || execPath.includes("localappdata") || execPath.includes("appdata"))) {
560
+ return true;
561
+ }
562
+ } else if (platform2 === "linux") {
563
+ if (execPath.includes("cursor") && (execPath.includes("/opt/cursor") || execPath.includes("/usr/share/cursor") || execPath.includes("/.local/share/cursor"))) {
564
+ return true;
565
+ }
566
+ }
567
+ return false;
568
+ } catch {
569
+ return false;
570
+ }
571
+ }
572
+ /**
573
+ * Get a user-friendly message about Cursor IDE detection
574
+ * @returns {string} Message about Cursor IDE status
575
+ */
576
+ static getDetectionMessage() {
577
+ if (this.isCursorIde()) {
578
+ return "\u2705 Cursor IDE detected";
579
+ }
580
+ return "\u26A0\uFE0F Cursor IDE not detected - cursor rules may not work in other IDEs";
581
+ }
582
+ };
583
+ __name(_CursorIdeDetector, "CursorIdeDetector");
584
+ CursorIdeDetector = _CursorIdeDetector;
585
+ }
586
+ });
587
+
588
+ // src/commands/framework/helpers/index.ts
589
+ var init_helpers = __esm({
590
+ "src/commands/framework/helpers/index.ts"() {
591
+ "use strict";
592
+ init_package_rules_path();
593
+ init_rule_files();
594
+ init_directory_exists();
595
+ init_format_messages();
596
+ init_package_path();
597
+ init_mcp_config();
598
+ init_cursor_ide_detector();
599
+ }
600
+ });
601
+
602
+ // src/commands/framework/command/ai-agent/base-check/index.ts
603
+ var path4, _AIAgentBaseCheck, AIAgentBaseCheck;
604
+ var init_base_check = __esm({
605
+ "src/commands/framework/command/ai-agent/base-check/index.ts"() {
606
+ "use strict";
607
+ path4 = __toESM(require("path"));
608
+ init_helpers();
609
+ init_abstract();
610
+ _AIAgentBaseCheck = class _AIAgentBaseCheck extends CommandAbstract {
611
+ /**
612
+ * Method to get the description of the command
613
+ * @returns {string} The description of the command
614
+ */
615
+ static getName() {
616
+ return this.NAME;
617
+ }
618
+ /**
619
+ * Get the directory paths to check
620
+ * This is used to check if the context directories exist.
621
+ *
622
+ * @returns {string[]} Array of directory paths relative to project root
623
+ */
624
+ static getDirs() {
625
+ throw new Error("getDirs() must be implemented by subclass");
626
+ }
627
+ /**
628
+ * Static execute method to check and return the result
629
+ *
630
+ * @param {string} projectPath - The path to the project root (defaults to current directory)
631
+ * @returns {Promise<CommandResult>} The check result
632
+ */
633
+ static async execute(projectPath = process.cwd()) {
634
+ const dirs = this.getDirs();
635
+ const missingDirs = [];
636
+ const existingDirs = [];
637
+ const allContextFiles = [];
638
+ for (const dir of dirs) {
639
+ const contextPath = path4.join(projectPath, dir);
640
+ if (!DirectoryExists.is(contextPath)) {
641
+ missingDirs.push(dir);
642
+ } else {
643
+ existingDirs.push(dir);
644
+ const contextFiles = RuleFiles.get(contextPath);
645
+ if (contextFiles.length > 0) {
646
+ allContextFiles.push({ dir, files: contextFiles });
647
+ }
648
+ }
649
+ }
650
+ if (existingDirs.length === 0) {
651
+ return {
652
+ success: false,
653
+ message: FormatMessages.execute([
654
+ "\u274C Context directories not found",
655
+ "--------------------------------",
656
+ CursorIdeDetector.getDetectionMessage(),
657
+ "",
658
+ `The following directories do not exist:`,
659
+ ...missingDirs.map((dir) => ` - ${dir}`),
660
+ "Run: npx aio-toolkit-cursor-context apply"
661
+ ])
662
+ };
663
+ }
664
+ if (allContextFiles.length === 0) {
665
+ return {
666
+ success: false,
667
+ message: FormatMessages.execute([
668
+ "\u274C No context files found",
669
+ "--------------------------------",
670
+ CursorIdeDetector.getDetectionMessage(),
671
+ "",
672
+ `No context files (.mdc, .md) found in:`,
673
+ ...existingDirs.map((dir) => ` - ${dir}`),
674
+ "Run: npx aio-toolkit-cursor-context apply"
675
+ ])
676
+ };
677
+ }
678
+ const totalFiles = allContextFiles.reduce((sum, item) => sum + item.files.length, 0);
679
+ const messages = [
680
+ "\u2705 Contexts are applied to the project",
681
+ "--------------------------------",
682
+ CursorIdeDetector.getDetectionMessage(),
683
+ "",
684
+ `Found ${totalFiles} context file${totalFiles > 1 ? "s" : ""} across ${allContextFiles.length} director${allContextFiles.length > 1 ? "ies" : "y"}:`
685
+ ];
686
+ for (const { dir, files } of allContextFiles) {
687
+ messages.push(`
688
+ ${dir}:`);
689
+ files.forEach((file) => messages.push(` - ${file}`));
690
+ }
691
+ if (missingDirs.length > 0) {
692
+ messages.push("\n\u26A0\uFE0F Missing directories:");
693
+ missingDirs.forEach((dir) => messages.push(` - ${dir}`));
694
+ }
695
+ const mcpExists = McpConfig.exists(projectPath);
696
+ messages.push("");
697
+ if (mcpExists) {
698
+ messages.push("\u2705 MCP server configuration found at .cursor/mcp.json");
699
+ } else {
700
+ messages.push("\u26A0\uFE0F MCP server configuration not found");
701
+ messages.push(" Run: npx aio-toolkit-cursor-context apply");
702
+ }
703
+ return {
704
+ success: true,
705
+ message: FormatMessages.execute(messages)
706
+ };
707
+ }
708
+ };
709
+ __name(_AIAgentBaseCheck, "AIAgentBaseCheck");
710
+ /**
711
+ * Static command name
712
+ */
713
+ _AIAgentBaseCheck.NAME = "check";
714
+ AIAgentBaseCheck = _AIAgentBaseCheck;
715
+ }
716
+ });
717
+
718
+ // src/commands/cursor-context/lib/check/index.ts
719
+ var path5, _CursorContextCheck, CursorContextCheck;
720
+ var init_check = __esm({
721
+ "src/commands/cursor-context/lib/check/index.ts"() {
722
+ "use strict";
723
+ path5 = __toESM(require("path"));
724
+ init_base_check();
725
+ _CursorContextCheck = class _CursorContextCheck extends AIAgentBaseCheck {
726
+ /**
727
+ * Method to get the description of the command
728
+ * @returns {string} The description of the command
729
+ */
730
+ static getDescription() {
731
+ return this.DESCRIPTION;
732
+ }
733
+ /**
734
+ * Get the directory paths to check
735
+ * This is used to check if the context directories exist.
736
+ *
737
+ * @returns {string[]} Array of directory paths relative to project root
738
+ */
739
+ static getDirs() {
740
+ return [path5.join(".cursor", "rules"), path5.join(".cursor", "commands")];
741
+ }
742
+ };
743
+ __name(_CursorContextCheck, "CursorContextCheck");
744
+ /**
745
+ * Static command description
746
+ */
747
+ _CursorContextCheck.DESCRIPTION = "Check cursor context applied to the project";
748
+ CursorContextCheck = _CursorContextCheck;
749
+ }
750
+ });
751
+
752
+ // src/commands/framework/command/ai-agent/base-apply/index.ts
753
+ var fs6, path6, _AIAgentBaseApply, AIAgentBaseApply;
754
+ var init_base_apply = __esm({
755
+ "src/commands/framework/command/ai-agent/base-apply/index.ts"() {
756
+ "use strict";
757
+ fs6 = __toESM(require("fs"));
758
+ path6 = __toESM(require("path"));
759
+ init_format_messages();
760
+ init_helpers();
761
+ init_abstract();
762
+ _AIAgentBaseApply = class _AIAgentBaseApply extends CommandAbstract {
763
+ /**
764
+ * Method to get the description of the command
765
+ * @returns {string} The description of the command
766
+ */
767
+ static getName() {
768
+ return this.NAME;
769
+ }
770
+ /**
771
+ * Get the copy directories configuration
772
+ * @returns {Record<string, { from: string; to: string }>} Object with directory pairs to copy
773
+ */
774
+ static getCopyDirs() {
775
+ throw new Error("getCopyDirs() must be implemented by subclass");
776
+ }
777
+ /**
778
+ * Check if IDE detection is required before applying contexts
779
+ * Override this method in subclasses to enable IDE detection
780
+ * @returns {boolean} True if IDE detection should be performed
781
+ */
782
+ static shouldCheckIde() {
783
+ return false;
784
+ }
785
+ /**
786
+ * Static execute method to apply contexts
787
+ * @param {string} projectPath - The path to the project root (defaults to current directory)
788
+ * @param {string[]} args - Command arguments
789
+ * @returns {Promise<CommandResult>} The apply result
790
+ */
791
+ static async execute(projectPath = process.cwd(), args2 = []) {
792
+ let actualProjectPath = projectPath;
793
+ let actualArgs = args2;
794
+ if (projectPath.startsWith("-")) {
795
+ actualProjectPath = process.cwd();
796
+ actualArgs = [projectPath, ...args2];
797
+ }
798
+ const forceOverwrite = actualArgs.includes("--force") || actualArgs.includes("-f");
799
+ if (!forceOverwrite && this.shouldCheckIde() && !CursorIdeDetector.isCursorIde()) {
800
+ return {
801
+ success: false,
802
+ message: FormatMessages.execute([
803
+ "\u274C Cursor IDE not detected",
804
+ "--------------------------------",
805
+ CursorIdeDetector.getDetectionMessage(),
806
+ "",
807
+ "Cursor contexts can only be applied when using Cursor IDE.",
808
+ "Please run this command from within Cursor IDE.",
809
+ "",
810
+ "\u2139\uFE0F Use --force or -f to bypass this check and apply contexts anyway."
811
+ ])
812
+ };
813
+ }
814
+ try {
815
+ const copyDirs = this.getCopyDirs();
816
+ const dirKeys = Object.keys(copyDirs);
817
+ if (dirKeys.length === 0) {
818
+ return {
819
+ success: false,
820
+ message: FormatMessages.execute([
821
+ "\u274C No directories configured",
822
+ "--------------------------------",
823
+ "The getCopyDirs() method must return at least one directory pair"
824
+ ])
825
+ };
826
+ }
827
+ const allResults = {};
828
+ for (const dirKey of dirKeys) {
829
+ const dirConfig = copyDirs[dirKey];
830
+ if (!dirConfig) {
831
+ continue;
832
+ }
833
+ const { from: sourceRelativePath, to: destRelativePath } = dirConfig;
834
+ const sourcePath = PackageRulesPath.get(sourceRelativePath);
835
+ if (!sourcePath) {
836
+ return {
837
+ success: false,
838
+ message: FormatMessages.execute([
839
+ "\u274C Could not find contexts in package",
840
+ "--------------------------------",
841
+ "The package context directory does not exist",
842
+ `Expected at: ${sourceRelativePath}`
843
+ ])
844
+ };
845
+ }
846
+ const contextFiles = RuleFiles.get(sourcePath);
847
+ if (contextFiles.length === 0) {
848
+ return {
849
+ success: false,
850
+ message: FormatMessages.execute([
851
+ "\u274C No contexts found to apply",
852
+ "--------------------------------",
853
+ "The package does not contain any context files",
854
+ `Checked directory: ${sourceRelativePath}`
855
+ ])
856
+ };
857
+ }
858
+ const destPath = path6.join(actualProjectPath, destRelativePath);
859
+ DirectoryExists.ensure(destPath);
860
+ allResults[dirKey] = {
861
+ copiedFiles: [],
862
+ skippedFiles: [],
863
+ overwrittenFiles: [],
864
+ sourcePath,
865
+ destPath: destRelativePath
866
+ };
867
+ for (const file of contextFiles) {
868
+ const sourceFilePath = path6.join(sourcePath, file);
869
+ const destFilePath = path6.join(destPath, file);
870
+ const fileExists = fs6.existsSync(destFilePath);
871
+ if (forceOverwrite) {
872
+ fs6.copyFileSync(sourceFilePath, destFilePath);
873
+ if (fileExists) {
874
+ allResults[dirKey].overwrittenFiles.push(file);
875
+ } else {
876
+ allResults[dirKey].copiedFiles.push(file);
877
+ }
878
+ } else {
879
+ if (!fileExists) {
880
+ fs6.copyFileSync(sourceFilePath, destFilePath);
881
+ allResults[dirKey].copiedFiles.push(file);
882
+ } else {
883
+ allResults[dirKey].skippedFiles.push(file);
884
+ }
885
+ }
886
+ }
887
+ }
888
+ const mcpResult = McpConfig.createOrUpdate(actualProjectPath);
889
+ const messages = [];
890
+ const totalCopied = Object.values(allResults).reduce(
891
+ (sum, r) => sum + r.copiedFiles.length,
892
+ 0
893
+ );
894
+ const totalSkipped = Object.values(allResults).reduce(
895
+ (sum, r) => sum + r.skippedFiles.length,
896
+ 0
897
+ );
898
+ if (forceOverwrite) {
899
+ messages.push(
900
+ "\u2705 Contexts applied successfully (force mode)!",
901
+ "--------------------------------"
902
+ );
903
+ for (const dirKey of dirKeys) {
904
+ const result = allResults[dirKey];
905
+ if (!result) {
906
+ continue;
907
+ }
908
+ if (result.copiedFiles.length > 0 || result.overwrittenFiles.length > 0) {
909
+ messages.push(`
910
+ ${dirKey.toUpperCase()}:`);
911
+ if (result.copiedFiles.length > 0) {
912
+ messages.push(
913
+ ` Copied ${result.copiedFiles.length} new context file${result.copiedFiles.length > 1 ? "s" : ""} to ${result.destPath}:`,
914
+ ...result.copiedFiles.map((file) => ` \u2713 ${file}`)
915
+ );
916
+ }
917
+ if (result.overwrittenFiles.length > 0) {
918
+ if (result.copiedFiles.length > 0) {
919
+ messages.push("");
920
+ }
921
+ messages.push(
922
+ ` Overwritten ${result.overwrittenFiles.length} existing context file${result.overwrittenFiles.length > 1 ? "s" : ""}:`,
923
+ ...result.overwrittenFiles.map((file) => ` \u21BB ${file}`)
924
+ );
925
+ }
926
+ }
927
+ }
928
+ messages.push("");
929
+ if (mcpResult.success) {
930
+ messages.push(`\u2713 ${mcpResult.message}`, "");
931
+ } else if (mcpResult.reason === "peer-dependency-missing") {
932
+ messages.push(`\u26A0\uFE0F ${mcpResult.message}`, "");
933
+ }
934
+ messages.push("\u26A0\uFE0F Please restart your IDE to load the updated contexts");
935
+ } else {
936
+ if (totalCopied === 0 && totalSkipped > 0) {
937
+ messages.push("\u2705 All contexts are already applied!", "--------------------------------");
938
+ for (const dirKey of dirKeys) {
939
+ const result = allResults[dirKey];
940
+ if (!result) {
941
+ continue;
942
+ }
943
+ if (result.skippedFiles.length > 0) {
944
+ messages.push(
945
+ `
946
+ ${dirKey.toUpperCase()}:`,
947
+ ` All ${result.skippedFiles.length} context file${result.skippedFiles.length > 1 ? "s" : ""} already exist in ${result.destPath}:`,
948
+ ...result.skippedFiles.map((file) => ` \u229D ${file}`)
949
+ );
950
+ }
951
+ }
952
+ if (mcpResult.success) {
953
+ messages.push("", `\u2713 ${mcpResult.message}`);
954
+ } else if (mcpResult.reason === "peer-dependency-missing") {
955
+ messages.push("", `\u26A0\uFE0F ${mcpResult.message}`);
956
+ }
957
+ messages.push("", "\u2139\uFE0F Use --force or -f to overwrite existing contexts");
958
+ } else {
959
+ messages.push("\u2705 Contexts applied successfully!", "--------------------------------");
960
+ for (const dirKey of dirKeys) {
961
+ const result = allResults[dirKey];
962
+ if (!result) {
963
+ continue;
964
+ }
965
+ if (result.copiedFiles.length > 0 || result.skippedFiles.length > 0) {
966
+ messages.push(`
967
+ ${dirKey.toUpperCase()}:`);
968
+ if (result.copiedFiles.length > 0) {
969
+ messages.push(
970
+ ` Copied ${result.copiedFiles.length} new context file${result.copiedFiles.length > 1 ? "s" : ""} to ${result.destPath}:`,
971
+ ...result.copiedFiles.map((file) => ` \u2713 ${file}`)
972
+ );
973
+ }
974
+ if (result.skippedFiles.length > 0) {
975
+ if (result.copiedFiles.length > 0) {
976
+ messages.push("");
977
+ }
978
+ messages.push(
979
+ ` Skipped ${result.skippedFiles.length} existing context file${result.skippedFiles.length > 1 ? "s" : ""}:`,
980
+ ...result.skippedFiles.map((file) => ` \u229D ${file}`),
981
+ "",
982
+ " \u2139\uFE0F Use --force or -f to overwrite existing contexts"
983
+ );
984
+ }
985
+ }
986
+ }
987
+ if (totalCopied > 0) {
988
+ messages.push("");
989
+ if (mcpResult.success) {
990
+ messages.push(`\u2713 ${mcpResult.message}`, "");
991
+ } else if (mcpResult.reason === "peer-dependency-missing") {
992
+ messages.push(`\u26A0\uFE0F ${mcpResult.message}`, "");
993
+ }
994
+ messages.push("\u26A0\uFE0F Please restart your IDE to load the new contexts");
995
+ }
996
+ }
997
+ }
998
+ return {
999
+ success: true,
1000
+ message: FormatMessages.execute(messages)
1001
+ };
1002
+ } catch (error) {
1003
+ return {
1004
+ success: false,
1005
+ message: FormatMessages.execute([
1006
+ "\u274C Failed to apply contexts to the project",
1007
+ "--------------------------------",
1008
+ `Error: ${error instanceof Error ? error.message : String(error)}`
1009
+ ])
1010
+ };
1011
+ }
1012
+ }
1013
+ };
1014
+ __name(_AIAgentBaseApply, "AIAgentBaseApply");
1015
+ /**
1016
+ * Static command name
1017
+ */
1018
+ _AIAgentBaseApply.NAME = "apply";
1019
+ AIAgentBaseApply = _AIAgentBaseApply;
1020
+ }
1021
+ });
1022
+
1023
+ // src/commands/cursor-context/lib/apply/index.ts
1024
+ var path7, _CursorContextApply, CursorContextApply;
1025
+ var init_apply = __esm({
1026
+ "src/commands/cursor-context/lib/apply/index.ts"() {
1027
+ "use strict";
1028
+ path7 = __toESM(require("path"));
1029
+ init_base_apply();
1030
+ _CursorContextApply = class _CursorContextApply extends AIAgentBaseApply {
1031
+ /**
1032
+ * Method to get the description of the command
1033
+ * @returns {string} The description of the command
1034
+ */
1035
+ static getDescription() {
1036
+ return this.DESCRIPTION;
1037
+ }
1038
+ /**
1039
+ * Enable IDE detection for Cursor-specific contexts
1040
+ * @returns {boolean} True to enable IDE detection
1041
+ */
1042
+ static shouldCheckIde() {
1043
+ return true;
1044
+ }
1045
+ /**
1046
+ * Get the rules directory path
1047
+ * @returns {string} The rules directory path
1048
+ */
1049
+ static getCopyDirs() {
1050
+ return {
1051
+ rules: {
1052
+ from: path7.join("files", "cursor-context", "rules"),
1053
+ to: path7.join(".cursor", "rules")
1054
+ },
1055
+ commands: {
1056
+ from: path7.join("files", "cursor-context", "commands"),
1057
+ to: path7.join(".cursor", "commands")
1058
+ }
1059
+ };
1060
+ }
1061
+ };
1062
+ __name(_CursorContextApply, "CursorContextApply");
1063
+ /**
1064
+ * Static command description
1065
+ */
1066
+ _CursorContextApply.DESCRIPTION = "Apply contexts to your project (use --force or -f to overwrite existing)";
1067
+ CursorContextApply = _CursorContextApply;
1068
+ }
1069
+ });
1070
+
1071
+ // src/commands/framework/command/registry/index.ts
1072
+ var _CommandRegistry, CommandRegistry;
1073
+ var init_registry = __esm({
1074
+ "src/commands/framework/command/registry/index.ts"() {
1075
+ "use strict";
1076
+ _CommandRegistry = class _CommandRegistry {
1077
+ /**
1078
+ * Static method to get the commands - must be implemented by subclasses
1079
+ *
1080
+ * @returns {CommandDescriptor[]} The commands
1081
+ */
1082
+ static getCommands() {
1083
+ throw new Error("getCommands() must be implemented by subclass");
1084
+ }
1085
+ /**
1086
+ * Static execute method to execute a command
1087
+ *
1088
+ * @param {string} type - The name of the command to execute
1089
+ * @param {...any} args - The arguments to pass to the command
1090
+ * @returns {Promise<CommandResult>} The execution result
1091
+ */
1092
+ static async execute(type = "help", ...args2) {
1093
+ const command2 = this.getCommands().find((cmd) => cmd.name === type);
1094
+ if (!command2) {
1095
+ return {
1096
+ success: false,
1097
+ message: `Unknown command: ${type}`
1098
+ };
1099
+ }
1100
+ return await command2.execute(...args2);
1101
+ }
1102
+ };
1103
+ __name(_CommandRegistry, "CommandRegistry");
1104
+ CommandRegistry = _CommandRegistry;
1105
+ }
1106
+ });
1107
+
1108
+ // src/commands/cursor-context/lib/index.ts
1109
+ var lib_exports = {};
1110
+ __export(lib_exports, {
1111
+ CursorRules: () => CursorRules
1112
+ });
1113
+ var _CursorRules, CursorRules;
1114
+ var init_lib = __esm({
1115
+ "src/commands/cursor-context/lib/index.ts"() {
1116
+ "use strict";
1117
+ init_help();
1118
+ init_check();
1119
+ init_apply();
1120
+ init_registry();
1121
+ _CursorRules = class _CursorRules extends CommandRegistry {
1122
+ /**
1123
+ * Static commands array
1124
+ *
1125
+ * @returns {CommandDescriptor[]} The commands array
1126
+ */
1127
+ static getCommands() {
1128
+ return [
1129
+ {
1130
+ name: CursorContextHelp.getName(),
1131
+ description: CursorContextHelp.getDescription(),
1132
+ execute: CursorContextHelp.execute.bind(CursorContextHelp)
1133
+ },
1134
+ {
1135
+ name: CursorContextCheck.getName(),
1136
+ description: CursorContextCheck.getDescription(),
1137
+ execute: CursorContextCheck.execute.bind(CursorContextCheck)
1138
+ },
1139
+ {
1140
+ name: CursorContextApply.getName(),
1141
+ description: CursorContextApply.getDescription(),
1142
+ execute: CursorContextApply.execute.bind(CursorContextApply)
1143
+ }
1144
+ ];
1145
+ }
1146
+ };
1147
+ __name(_CursorRules, "CursorRules");
1148
+ CursorRules = _CursorRules;
1149
+ }
1150
+ });
1151
+
1152
+ // src/commands/cursor-context/bin/cli.ts
1153
+ init_lib();
1154
+ var command = process.argv[2] || "help";
1155
+ var args = process.argv.slice(3);
1156
+ async function main() {
1157
+ const result = await CursorRules.execute(command, ...args);
1158
+ console.log(result.message);
1159
+ if (!result.success) {
1160
+ process.exit(1);
1161
+ }
1162
+ }
1163
+ __name(main, "main");
1164
+ main().catch((error) => {
1165
+ console.error("Error:", error.message);
1166
+ process.exit(1);
1167
+ });
1168
+ //# sourceMappingURL=cli.js.map