@adobe-commerce/aio-toolkit 1.0.13 → 1.0.15

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