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