@agiflowai/aicode-utils 0.4.1 → 0.5.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/dist/index.cjs CHANGED
@@ -25,7 +25,364 @@ let node_path = require("node:path");
25
25
  node_path = __toESM(node_path);
26
26
  let fs_extra = require("fs-extra");
27
27
  fs_extra = __toESM(fs_extra);
28
+ let node_os = require("node:os");
29
+ node_os = __toESM(node_os);
30
+ let pino = require("pino");
31
+ pino = __toESM(pino);
32
+ let chalk = require("chalk");
33
+ chalk = __toESM(chalk);
28
34
 
35
+ //#region src/constants/projectType.ts
36
+ /**
37
+ * Project type constants
38
+ */
39
+ const ProjectType = {
40
+ MONOLITH: "monolith",
41
+ MONOREPO: "monorepo"
42
+ };
43
+ /**
44
+ * Config source constants
45
+ */
46
+ const ConfigSource = {
47
+ PROJECT_JSON: "project.json",
48
+ TOOLKIT_YAML: "toolkit.yaml"
49
+ };
50
+
51
+ //#endregion
52
+ //#region src/utils/logger.ts
53
+ const logsDir = node_path.join(node_os.tmpdir(), "scaffold-mcp-logs");
54
+ const logger = (0, pino.default)({
55
+ level: process.env.LOG_LEVEL || "debug",
56
+ timestamp: pino.default.stdTimeFunctions.isoTime
57
+ }, pino.default.destination({
58
+ dest: node_path.join(logsDir, "scaffold-mcp.log"),
59
+ mkdir: true,
60
+ sync: true
61
+ }));
62
+ const log = {
63
+ debug: (msg, ...args) => logger.debug({ args }, msg),
64
+ info: (msg, ...args) => logger.info({ args }, msg),
65
+ warn: (msg, ...args) => logger.warn({ args }, msg),
66
+ error: (msg, ...args) => logger.error({ args }, msg)
67
+ };
68
+
69
+ //#endregion
70
+ //#region src/services/TemplatesManagerService.ts
71
+ var TemplatesManagerService = class TemplatesManagerService {
72
+ static SCAFFOLD_CONFIG_FILE = "scaffold.yaml";
73
+ static TEMPLATES_FOLDER = "templates";
74
+ static TOOLKIT_CONFIG_FILE = "toolkit.yaml";
75
+ /**
76
+ * Find the templates directory by searching upwards from the starting path.
77
+ *
78
+ * Algorithm:
79
+ * 1. Start from the provided path (default: current working directory)
80
+ * 2. Search upwards to find the workspace root (where .git exists or filesystem root)
81
+ * 3. Check if toolkit.yaml exists at workspace root
82
+ * - If yes, read templatesPath from toolkit.yaml
83
+ * - If no, default to 'templates' folder in workspace root
84
+ * 4. Verify the templates directory exists
85
+ *
86
+ * @param startPath - The path to start searching from (defaults to process.cwd())
87
+ * @returns The absolute path to the templates directory
88
+ * @throws Error if templates directory is not found
89
+ */
90
+ static async findTemplatesPath(startPath = process.cwd()) {
91
+ const workspaceRoot = await TemplatesManagerService.findWorkspaceRoot(startPath);
92
+ const toolkitConfigPath = node_path.default.join(workspaceRoot, TemplatesManagerService.TOOLKIT_CONFIG_FILE);
93
+ if (await fs_extra.pathExists(toolkitConfigPath)) {
94
+ const yaml = await import("js-yaml");
95
+ const content = await fs_extra.readFile(toolkitConfigPath, "utf-8");
96
+ const config = yaml.load(content);
97
+ if (config?.templatesPath) {
98
+ const templatesPath$1 = node_path.default.isAbsolute(config.templatesPath) ? config.templatesPath : node_path.default.join(workspaceRoot, config.templatesPath);
99
+ if (await fs_extra.pathExists(templatesPath$1)) return templatesPath$1;
100
+ else throw new Error(`Templates path specified in toolkit.yaml does not exist: ${templatesPath$1}`);
101
+ }
102
+ }
103
+ const templatesPath = node_path.default.join(workspaceRoot, TemplatesManagerService.TEMPLATES_FOLDER);
104
+ if (await fs_extra.pathExists(templatesPath)) return templatesPath;
105
+ throw new Error(`Templates folder not found at ${templatesPath}.\nEither create a 'templates' folder or specify templatesPath in toolkit.yaml`);
106
+ }
107
+ /**
108
+ * Find the workspace root by searching upwards for .git folder
109
+ */
110
+ static async findWorkspaceRoot(startPath) {
111
+ let currentPath = node_path.default.resolve(startPath);
112
+ const rootPath = node_path.default.parse(currentPath).root;
113
+ while (true) {
114
+ const gitPath = node_path.default.join(currentPath, ".git");
115
+ if (await fs_extra.pathExists(gitPath)) return currentPath;
116
+ if (currentPath === rootPath) return process.cwd();
117
+ currentPath = node_path.default.dirname(currentPath);
118
+ }
119
+ }
120
+ /**
121
+ * Get the templates path synchronously.
122
+ * Use this when you need immediate access and are sure templates exist.
123
+ *
124
+ * @param startPath - The path to start searching from (defaults to process.cwd())
125
+ * @returns The absolute path to the templates directory
126
+ * @throws Error if templates directory is not found
127
+ */
128
+ static findTemplatesPathSync(startPath = process.cwd()) {
129
+ const workspaceRoot = TemplatesManagerService.findWorkspaceRootSync(startPath);
130
+ const toolkitConfigPath = node_path.default.join(workspaceRoot, TemplatesManagerService.TOOLKIT_CONFIG_FILE);
131
+ if (fs_extra.pathExistsSync(toolkitConfigPath)) {
132
+ const yaml = require("js-yaml");
133
+ const content = fs_extra.readFileSync(toolkitConfigPath, "utf-8");
134
+ const config = yaml.load(content);
135
+ if (config?.templatesPath) {
136
+ const templatesPath$1 = node_path.default.isAbsolute(config.templatesPath) ? config.templatesPath : node_path.default.join(workspaceRoot, config.templatesPath);
137
+ if (fs_extra.pathExistsSync(templatesPath$1)) return templatesPath$1;
138
+ else throw new Error(`Templates path specified in toolkit.yaml does not exist: ${templatesPath$1}`);
139
+ }
140
+ }
141
+ const templatesPath = node_path.default.join(workspaceRoot, TemplatesManagerService.TEMPLATES_FOLDER);
142
+ if (fs_extra.pathExistsSync(templatesPath)) return templatesPath;
143
+ throw new Error(`Templates folder not found at ${templatesPath}.\nEither create a 'templates' folder or specify templatesPath in toolkit.yaml`);
144
+ }
145
+ /**
146
+ * Find the workspace root synchronously by searching upwards for .git folder
147
+ */
148
+ static findWorkspaceRootSync(startPath) {
149
+ let currentPath = node_path.default.resolve(startPath);
150
+ const rootPath = node_path.default.parse(currentPath).root;
151
+ while (true) {
152
+ const gitPath = node_path.default.join(currentPath, ".git");
153
+ if (fs_extra.pathExistsSync(gitPath)) return currentPath;
154
+ if (currentPath === rootPath) return process.cwd();
155
+ currentPath = node_path.default.dirname(currentPath);
156
+ }
157
+ }
158
+ /**
159
+ * Check if templates are initialized at the given path
160
+ *
161
+ * @param templatesPath - Path to check for templates
162
+ * @returns true if templates folder exists and is a directory
163
+ */
164
+ static async isInitialized(templatesPath) {
165
+ if (!await fs_extra.pathExists(templatesPath)) return false;
166
+ return (await fs_extra.stat(templatesPath)).isDirectory();
167
+ }
168
+ /**
169
+ * Get the scaffold config file name
170
+ */
171
+ static getConfigFileName() {
172
+ return TemplatesManagerService.SCAFFOLD_CONFIG_FILE;
173
+ }
174
+ /**
175
+ * Get the templates folder name
176
+ */
177
+ static getTemplatesFolderName() {
178
+ return TemplatesManagerService.TEMPLATES_FOLDER;
179
+ }
180
+ /**
181
+ * Read toolkit.yaml configuration from workspace root
182
+ *
183
+ * @param startPath - The path to start searching from (defaults to process.cwd())
184
+ * @returns The toolkit configuration object or null if not found
185
+ */
186
+ static async readToolkitConfig(startPath = process.cwd()) {
187
+ const workspaceRoot = await TemplatesManagerService.findWorkspaceRoot(startPath);
188
+ const toolkitConfigPath = node_path.default.join(workspaceRoot, TemplatesManagerService.TOOLKIT_CONFIG_FILE);
189
+ if (!await fs_extra.pathExists(toolkitConfigPath)) return null;
190
+ const yaml = await import("js-yaml");
191
+ const content = await fs_extra.readFile(toolkitConfigPath, "utf-8");
192
+ return yaml.load(content);
193
+ }
194
+ /**
195
+ * Read toolkit.yaml configuration from workspace root (sync)
196
+ *
197
+ * @param startPath - The path to start searching from (defaults to process.cwd())
198
+ * @returns The toolkit configuration object or null if not found
199
+ */
200
+ static readToolkitConfigSync(startPath = process.cwd()) {
201
+ const workspaceRoot = TemplatesManagerService.findWorkspaceRootSync(startPath);
202
+ const toolkitConfigPath = node_path.default.join(workspaceRoot, TemplatesManagerService.TOOLKIT_CONFIG_FILE);
203
+ if (!fs_extra.pathExistsSync(toolkitConfigPath)) return null;
204
+ const yaml = require("js-yaml");
205
+ const content = fs_extra.readFileSync(toolkitConfigPath, "utf-8");
206
+ return yaml.load(content);
207
+ }
208
+ /**
209
+ * Write toolkit.yaml configuration to workspace root
210
+ *
211
+ * @param config - The toolkit configuration to write
212
+ * @param startPath - The path to start searching from (defaults to process.cwd())
213
+ */
214
+ static async writeToolkitConfig(config, startPath = process.cwd()) {
215
+ const workspaceRoot = await TemplatesManagerService.findWorkspaceRoot(startPath);
216
+ const toolkitConfigPath = node_path.default.join(workspaceRoot, TemplatesManagerService.TOOLKIT_CONFIG_FILE);
217
+ const content = (await import("js-yaml")).dump(config, { indent: 2 });
218
+ await fs_extra.writeFile(toolkitConfigPath, content, "utf-8");
219
+ }
220
+ /**
221
+ * Get the workspace root directory
222
+ *
223
+ * @param startPath - The path to start searching from (defaults to process.cwd())
224
+ * @returns The workspace root directory path
225
+ */
226
+ static async getWorkspaceRoot(startPath = process.cwd()) {
227
+ return TemplatesManagerService.findWorkspaceRoot(startPath);
228
+ }
229
+ /**
230
+ * Get the workspace root directory (sync)
231
+ *
232
+ * @param startPath - The path to start searching from (defaults to process.cwd())
233
+ * @returns The workspace root directory path
234
+ */
235
+ static getWorkspaceRootSync(startPath = process.cwd()) {
236
+ return TemplatesManagerService.findWorkspaceRootSync(startPath);
237
+ }
238
+ };
239
+
240
+ //#endregion
241
+ //#region src/services/ProjectConfigResolver.ts
242
+ /**
243
+ * ProjectConfigResolver
244
+ *
245
+ * Resolves project configuration from multiple sources with priority:
246
+ * 1. project.json (monorepo - Nx/Lerna/Turborepo)
247
+ * 2. toolkit.yaml at workspace root (monolith)
248
+ */
249
+ var ProjectConfigResolver = class ProjectConfigResolver {
250
+ /**
251
+ * Resolve project configuration with priority fallback
252
+ *
253
+ * Priority order:
254
+ * 1. Check for project.json (monorepo case)
255
+ * 2. Check for toolkit.yaml at workspace root (monolith case)
256
+ * 3. Error with helpful message
257
+ *
258
+ * @param projectPath - Absolute path to the project directory
259
+ * @param explicitTemplate - Optional explicit template override
260
+ * @returns Project configuration result
261
+ * @throws Error if no configuration found
262
+ */
263
+ static async resolveProjectConfig(projectPath, explicitTemplate) {
264
+ try {
265
+ const absolutePath = node_path.default.resolve(projectPath);
266
+ if (explicitTemplate) return {
267
+ type: ProjectType.MONOLITH,
268
+ sourceTemplate: explicitTemplate,
269
+ configSource: ConfigSource.TOOLKIT_YAML
270
+ };
271
+ const projectJsonPath = node_path.default.join(absolutePath, "project.json");
272
+ if (await fs_extra.pathExists(projectJsonPath)) {
273
+ const projectJson = await fs_extra.readJson(projectJsonPath);
274
+ if (projectJson.sourceTemplate && typeof projectJson.sourceTemplate === "string" && projectJson.sourceTemplate.trim()) return {
275
+ type: ProjectType.MONOREPO,
276
+ sourceTemplate: projectJson.sourceTemplate.trim(),
277
+ configSource: ConfigSource.PROJECT_JSON
278
+ };
279
+ }
280
+ try {
281
+ const workspaceRoot = await TemplatesManagerService.getWorkspaceRoot(absolutePath);
282
+ const toolkitConfig = await TemplatesManagerService.readToolkitConfig(workspaceRoot);
283
+ if (toolkitConfig?.projectType === "monolith" && toolkitConfig.sourceTemplate) return {
284
+ type: ProjectType.MONOLITH,
285
+ sourceTemplate: toolkitConfig.sourceTemplate,
286
+ configSource: ConfigSource.TOOLKIT_YAML,
287
+ workspaceRoot
288
+ };
289
+ } catch (error) {}
290
+ throw new Error(ProjectConfigResolver.getHelpfulErrorMessage(absolutePath));
291
+ } catch (error) {
292
+ if (error instanceof Error && error.message.includes("No project configuration found")) throw error;
293
+ throw new Error(`Failed to resolve project configuration at ${projectPath}: ${error instanceof Error ? error.message : String(error)}`);
294
+ }
295
+ }
296
+ /**
297
+ * Get helpful error message when no configuration is found
298
+ */
299
+ static getHelpfulErrorMessage(projectPath) {
300
+ return `No project configuration found at ${projectPath}.
301
+
302
+ For monorepo projects:
303
+ - Ensure project.json exists with sourceTemplate field
304
+
305
+ For monolith projects:
306
+ - Create toolkit.yaml at workspace root:
307
+
308
+ projectType: monolith
309
+ sourceTemplate: your-template-name
310
+
311
+ - OR use --template flag:
312
+ scaffold-mcp scaffold add <feature> --template <template-name>
313
+
314
+ Run 'scaffold-mcp scaffold list --help' for more info.`;
315
+ }
316
+ /**
317
+ * Check if project has configuration (without throwing error)
318
+ *
319
+ * @param projectPath - Absolute path to the project directory
320
+ * @returns true if configuration exists, false otherwise
321
+ * @throws Error if there's a filesystem error (not just missing config)
322
+ */
323
+ static async hasConfiguration(projectPath) {
324
+ try {
325
+ await ProjectConfigResolver.resolveProjectConfig(projectPath);
326
+ return true;
327
+ } catch (error) {
328
+ if (error instanceof Error && error.message.includes("No project configuration found")) return false;
329
+ throw new Error(`Error checking project configuration: ${error instanceof Error ? error.message : String(error)}`);
330
+ }
331
+ }
332
+ /**
333
+ * Create toolkit.yaml for monolith projects
334
+ *
335
+ * @param sourceTemplate - The template identifier
336
+ * @param workspaceRoot - Optional workspace root path (defaults to current directory)
337
+ */
338
+ static async createToolkitYaml(sourceTemplate, workspaceRoot) {
339
+ try {
340
+ const rootPath = workspaceRoot || await TemplatesManagerService.getWorkspaceRoot(process.cwd());
341
+ const existingConfig = await TemplatesManagerService.readToolkitConfig(rootPath);
342
+ const toolkitConfig = {
343
+ version: existingConfig?.version || "1.0",
344
+ templatesPath: existingConfig?.templatesPath || "./templates",
345
+ projectType: "monolith",
346
+ sourceTemplate
347
+ };
348
+ await TemplatesManagerService.writeToolkitConfig(toolkitConfig, rootPath);
349
+ log.info("Created toolkit.yaml with monolith configuration");
350
+ } catch (error) {
351
+ throw new Error(`Failed to create toolkit.yaml: ${error instanceof Error ? error.message : String(error)}`);
352
+ }
353
+ }
354
+ /**
355
+ * Create or update project.json for monorepo projects
356
+ *
357
+ * @param projectPath - Absolute path to the project directory
358
+ * @param projectName - Name of the project
359
+ * @param sourceTemplate - The template identifier
360
+ */
361
+ static async createProjectJson(projectPath, projectName, sourceTemplate) {
362
+ const projectJsonPath = node_path.default.join(projectPath, "project.json");
363
+ try {
364
+ let projectJson;
365
+ if (await fs_extra.pathExists(projectJsonPath)) projectJson = await fs_extra.readJson(projectJsonPath);
366
+ else {
367
+ const relativePath = node_path.default.relative(projectPath, process.cwd());
368
+ projectJson = {
369
+ name: projectName,
370
+ $schema: relativePath ? `${relativePath}/node_modules/nx/schemas/project-schema.json` : "node_modules/nx/schemas/project-schema.json",
371
+ sourceRoot: projectPath,
372
+ projectType: "application"
373
+ };
374
+ }
375
+ projectJson.sourceTemplate = sourceTemplate;
376
+ const content = JSON.stringify(projectJson, null, 2);
377
+ await fs_extra.writeFile(projectJsonPath, `${content}\n`);
378
+ log.info(`Created/updated project.json with sourceTemplate: ${sourceTemplate}`);
379
+ } catch (error) {
380
+ throw new Error(`Failed to create project.json: ${error instanceof Error ? error.message : String(error)}`);
381
+ }
382
+ }
383
+ };
384
+
385
+ //#endregion
29
386
  //#region src/services/ProjectFinderService.ts
30
387
  var ProjectFinderService = class {
31
388
  projectCache = /* @__PURE__ */ new Map();
@@ -219,119 +576,128 @@ var ScaffoldProcessingService = class {
219
576
  };
220
577
 
221
578
  //#endregion
222
- //#region src/services/TemplatesManagerService.ts
223
- var TemplatesManagerService = class TemplatesManagerService {
224
- static SCAFFOLD_CONFIG_FILE = "scaffold.yaml";
225
- static TEMPLATES_FOLDER = "templates";
226
- static TOOLKIT_CONFIG_FILE = "toolkit.yaml";
227
- /**
228
- * Find the templates directory by searching upwards from the starting path.
229
- *
230
- * Algorithm:
231
- * 1. Start from the provided path (default: current working directory)
232
- * 2. Search upwards to find the workspace root (where .git exists or filesystem root)
233
- * 3. Check if toolkit.yaml exists at workspace root
234
- * - If yes, read templatesPath from toolkit.yaml
235
- * - If no, default to 'templates' folder in workspace root
236
- * 4. Verify the templates directory exists
237
- *
238
- * @param startPath - The path to start searching from (defaults to process.cwd())
239
- * @returns The absolute path to the templates directory
240
- * @throws Error if templates directory is not found
241
- */
242
- static async findTemplatesPath(startPath = process.cwd()) {
243
- const workspaceRoot = await TemplatesManagerService.findWorkspaceRoot(startPath);
244
- const toolkitConfigPath = node_path.default.join(workspaceRoot, TemplatesManagerService.TOOLKIT_CONFIG_FILE);
245
- if (await fs_extra.pathExists(toolkitConfigPath)) {
246
- const yaml = await import("js-yaml");
247
- const content = await fs_extra.readFile(toolkitConfigPath, "utf-8");
248
- const config = yaml.load(content);
249
- if (config?.templatesPath) {
250
- const templatesPath$1 = node_path.default.isAbsolute(config.templatesPath) ? config.templatesPath : node_path.default.join(workspaceRoot, config.templatesPath);
251
- if (await fs_extra.pathExists(templatesPath$1)) return templatesPath$1;
252
- else throw new Error(`Templates path specified in toolkit.yaml does not exist: ${templatesPath$1}`);
253
- }
254
- }
255
- const templatesPath = node_path.default.join(workspaceRoot, TemplatesManagerService.TEMPLATES_FOLDER);
256
- if (await fs_extra.pathExists(templatesPath)) return templatesPath;
257
- throw new Error(`Templates folder not found at ${templatesPath}.\nEither create a 'templates' folder or specify templatesPath in toolkit.yaml`);
258
- }
259
- /**
260
- * Find the workspace root by searching upwards for .git folder
261
- */
262
- static async findWorkspaceRoot(startPath) {
263
- let currentPath = node_path.default.resolve(startPath);
264
- const rootPath = node_path.default.parse(currentPath).root;
265
- while (true) {
266
- const gitPath = node_path.default.join(currentPath, ".git");
267
- if (await fs_extra.pathExists(gitPath)) return currentPath;
268
- if (currentPath === rootPath) return process.cwd();
269
- currentPath = node_path.default.dirname(currentPath);
270
- }
271
- }
272
- /**
273
- * Get the templates path synchronously.
274
- * Use this when you need immediate access and are sure templates exist.
275
- *
276
- * @param startPath - The path to start searching from (defaults to process.cwd())
277
- * @returns The absolute path to the templates directory
278
- * @throws Error if templates directory is not found
279
- */
280
- static findTemplatesPathSync(startPath = process.cwd()) {
281
- const workspaceRoot = TemplatesManagerService.findWorkspaceRootSync(startPath);
282
- const toolkitConfigPath = node_path.default.join(workspaceRoot, TemplatesManagerService.TOOLKIT_CONFIG_FILE);
283
- if (fs_extra.pathExistsSync(toolkitConfigPath)) {
284
- const yaml = require("js-yaml");
285
- const content = fs_extra.readFileSync(toolkitConfigPath, "utf-8");
286
- const config = yaml.load(content);
287
- if (config?.templatesPath) {
288
- const templatesPath$1 = node_path.default.isAbsolute(config.templatesPath) ? config.templatesPath : node_path.default.join(workspaceRoot, config.templatesPath);
289
- if (fs_extra.pathExistsSync(templatesPath$1)) return templatesPath$1;
290
- else throw new Error(`Templates path specified in toolkit.yaml does not exist: ${templatesPath$1}`);
291
- }
292
- }
293
- const templatesPath = node_path.default.join(workspaceRoot, TemplatesManagerService.TEMPLATES_FOLDER);
294
- if (fs_extra.pathExistsSync(templatesPath)) return templatesPath;
295
- throw new Error(`Templates folder not found at ${templatesPath}.\nEither create a 'templates' folder or specify templatesPath in toolkit.yaml`);
296
- }
297
- /**
298
- * Find the workspace root synchronously by searching upwards for .git folder
299
- */
300
- static findWorkspaceRootSync(startPath) {
301
- let currentPath = node_path.default.resolve(startPath);
302
- const rootPath = node_path.default.parse(currentPath).root;
303
- while (true) {
304
- const gitPath = node_path.default.join(currentPath, ".git");
305
- if (fs_extra.pathExistsSync(gitPath)) return currentPath;
306
- if (currentPath === rootPath) return process.cwd();
307
- currentPath = node_path.default.dirname(currentPath);
308
- }
309
- }
310
- /**
311
- * Check if templates are initialized at the given path
312
- *
313
- * @param templatesPath - Path to check for templates
314
- * @returns true if templates folder exists and is a directory
315
- */
316
- static async isInitialized(templatesPath) {
317
- if (!await fs_extra.pathExists(templatesPath)) return false;
318
- return (await fs_extra.stat(templatesPath)).isDirectory();
579
+ //#region src/utils/print.ts
580
+ /**
581
+ * Themed console utilities for consistent CLI output
582
+ */
583
+ const print = {
584
+ info: (message) => {
585
+ console.log(chalk.default.cyan(message));
586
+ },
587
+ success: (message) => {
588
+ console.log(chalk.default.green(message));
589
+ },
590
+ warning: (message) => {
591
+ console.log(chalk.default.yellow(message));
592
+ },
593
+ error: (message, error) => {
594
+ if (error) {
595
+ const errorMsg = error instanceof Error ? error.message : error;
596
+ console.error(chalk.default.red(message), errorMsg);
597
+ } else console.error(chalk.default.red(message));
598
+ },
599
+ debug: (message) => {
600
+ console.log(chalk.default.gray(message));
601
+ },
602
+ header: (message) => {
603
+ console.log(chalk.default.bold.cyan(message));
604
+ },
605
+ item: (message) => {
606
+ console.log(chalk.default.gray(` - ${message}`));
607
+ },
608
+ indent: (message) => {
609
+ console.log(chalk.default.gray(` ${message}`));
610
+ },
611
+ highlight: (message) => {
612
+ console.log(chalk.default.bold.green(message));
613
+ },
614
+ newline: () => {
615
+ console.log();
319
616
  }
320
- /**
321
- * Get the scaffold config file name
322
- */
323
- static getConfigFileName() {
324
- return TemplatesManagerService.SCAFFOLD_CONFIG_FILE;
617
+ };
618
+ /**
619
+ * Emoji icons for consistent visual markers
620
+ */
621
+ const icons = {
622
+ rocket: "🚀",
623
+ check: "✅",
624
+ cross: "❌",
625
+ warning: "âš ī¸",
626
+ info: "â„šī¸",
627
+ package: "đŸ“Ļ",
628
+ folder: "📁",
629
+ file: "📄",
630
+ config: "📝",
631
+ wrench: "🔧",
632
+ chart: "📊",
633
+ bulb: "💡",
634
+ download: "âŦ‡ī¸",
635
+ upload: "âŦ†ī¸",
636
+ gear: "âš™ī¸",
637
+ clipboard: "📋",
638
+ skip: "⏭"
639
+ };
640
+ /**
641
+ * Themed message helpers
642
+ */
643
+ const messages = {
644
+ info: (message) => {
645
+ print.info(`${icons.info} ${message}`);
646
+ },
647
+ success: (message) => {
648
+ print.success(`${icons.check} ${message}`);
649
+ },
650
+ error: (message, error) => {
651
+ print.error(`${icons.cross} ${message}`, error);
652
+ },
653
+ warning: (message) => {
654
+ print.warning(`${icons.warning} ${message}`);
655
+ },
656
+ hint: (message) => {
657
+ print.warning(`${icons.bulb} ${message}`);
658
+ },
659
+ loading: (message) => {
660
+ print.info(`${icons.rocket} ${message}`);
325
661
  }
326
- /**
327
- * Get the templates folder name
328
- */
329
- static getTemplatesFolderName() {
330
- return TemplatesManagerService.TEMPLATES_FOLDER;
662
+ };
663
+ /**
664
+ * Section formatters
665
+ */
666
+ const sections = {
667
+ header: (title) => {
668
+ print.newline();
669
+ print.header(`${title}`);
670
+ print.newline();
671
+ },
672
+ list: (title, items) => {
673
+ print.header(`\n${title}\n`);
674
+ items.forEach((item) => print.item(item));
675
+ },
676
+ nextSteps: (steps) => {
677
+ print.header(`\n${icons.clipboard} Next steps:`);
678
+ steps.forEach((step) => print.indent(step));
679
+ },
680
+ createdFiles: (files, maxShow = 10) => {
681
+ print.header(`\n${icons.folder} Created files:`);
682
+ files.slice(0, maxShow).forEach((file) => print.item(file));
683
+ if (files.length > maxShow) print.indent(`... and ${files.length - maxShow} more files`);
684
+ },
685
+ warnings: (warnings) => {
686
+ print.warning(`\n${icons.warning} Warnings:`);
687
+ warnings.forEach((warning) => print.item(warning));
331
688
  }
332
689
  };
333
690
 
334
691
  //#endregion
692
+ exports.ConfigSource = ConfigSource;
693
+ exports.ProjectConfigResolver = ProjectConfigResolver;
335
694
  exports.ProjectFinderService = ProjectFinderService;
695
+ exports.ProjectType = ProjectType;
336
696
  exports.ScaffoldProcessingService = ScaffoldProcessingService;
337
- exports.TemplatesManagerService = TemplatesManagerService;
697
+ exports.TemplatesManagerService = TemplatesManagerService;
698
+ exports.icons = icons;
699
+ exports.log = log;
700
+ exports.logger = logger;
701
+ exports.messages = messages;
702
+ exports.print = print;
703
+ exports.sections = sections;