@agiflowai/aicode-utils 0.6.0 โ†’ 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,419 @@
1
+ # @agiflowai/aicode-utils
2
+
3
+ Shared utilities and types for AI-powered code generation, scaffolding, and template management in monorepo/monolith workspaces.
4
+
5
+ ## What It Does
6
+
7
+ Core utilities used across the aicode-toolkit ecosystem:
8
+ - **Template discovery** - Find templates/ folder by walking up from any directory
9
+ - **Workspace detection** - Locate .git root and resolve project structure
10
+ - **Config management** - Read/write toolkit.yaml and project.json configurations
11
+ - **CLI output** - Themed console utilities with consistent formatting
12
+ - **Project resolution** - Find which project owns a given file path
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ pnpm add @agiflowai/aicode-utils
18
+ ```
19
+
20
+ ## Quick Start
21
+
22
+ ### 1. Find Templates Directory
23
+
24
+ ```typescript
25
+ import { TemplatesManagerService } from '@agiflowai/aicode-utils';
26
+
27
+ // Searches upward from cwd, checks toolkit.yaml, defaults to templates/
28
+ const templatesPath = await TemplatesManagerService.findTemplatesPath();
29
+ console.log(templatesPath); // /workspace/templates
30
+ ```
31
+
32
+ **Algorithm**:
33
+ 1. Find workspace root (searches for .git)
34
+ 2. Check toolkit.yaml for custom templatesPath
35
+ 3. Falls back to /workspace/templates
36
+
37
+ ### 2. Read Toolkit Configuration
38
+
39
+ ```typescript
40
+ const config = await TemplatesManagerService.readToolkitConfig();
41
+ console.log(config);
42
+ // {
43
+ // version: '1.0',
44
+ // templatesPath: 'templates',
45
+ // projectType: 'monorepo',
46
+ // sourceTemplate: 'nextjs-15'
47
+ // }
48
+ ```
49
+
50
+ ### 3. Pretty CLI Output
51
+
52
+ ```typescript
53
+ import { print, messages, sections } from '@agiflowai/aicode-utils';
54
+
55
+ messages.success('Templates initialized');
56
+ print.header('Available Templates');
57
+ print.item('nextjs-15');
58
+ print.item('typescript-mcp-package');
59
+
60
+ sections.createdFiles([
61
+ 'src/app/page.tsx',
62
+ 'src/components/Button.tsx',
63
+ ]);
64
+ ```
65
+
66
+ **Output**:
67
+ ```
68
+ โœ… Templates initialized
69
+
70
+ Available Templates
71
+ - nextjs-15
72
+ - typescript-mcp-package
73
+
74
+ ๐Ÿ“ Created files:
75
+ - src/app/page.tsx
76
+ - src/components/Button.tsx
77
+ ```
78
+
79
+ ### 4. Find Project Config for File
80
+
81
+ ```typescript
82
+ import { ProjectFinderService } from '@agiflowai/aicode-utils';
83
+
84
+ const finder = new ProjectFinderService('/workspace');
85
+ const project = await finder.findProjectForFile('/workspace/apps/web/src/page.tsx');
86
+
87
+ console.log(project);
88
+ // {
89
+ // name: 'web',
90
+ // root: '/workspace/apps/web',
91
+ // sourceTemplate: 'nextjs-15',
92
+ // projectType: 'monorepo'
93
+ // }
94
+ ```
95
+
96
+ ## API Reference
97
+
98
+ ### TemplatesManagerService
99
+
100
+ Static service for template and workspace management.
101
+
102
+ #### Find Templates
103
+
104
+ ```typescript
105
+ // Async - searches upward from startPath for workspace root + templates
106
+ static async findTemplatesPath(startPath?: string): Promise<string>
107
+
108
+ // Sync version
109
+ static findTemplatesPathSync(startPath?: string): string
110
+
111
+ // Check if templates folder exists
112
+ static async isInitialized(templatesPath: string): Promise<boolean>
113
+ ```
114
+
115
+ #### Workspace Root
116
+
117
+ ```typescript
118
+ // Find workspace root (where .git exists)
119
+ static async getWorkspaceRoot(startPath?: string): Promise<string>
120
+
121
+ // Sync version
122
+ static getWorkspaceRootSync(startPath?: string): string
123
+ ```
124
+
125
+ #### Toolkit Config (toolkit.yaml)
126
+
127
+ ```typescript
128
+ // Read toolkit.yaml from workspace root
129
+ static async readToolkitConfig(startPath?: string): Promise<ToolkitConfig | null>
130
+
131
+ // Sync version
132
+ static readToolkitConfigSync(startPath?: string): ToolkitConfig | null
133
+
134
+ // Write toolkit.yaml to workspace root
135
+ static async writeToolkitConfig(config: ToolkitConfig, startPath?: string): Promise<void>
136
+ ```
137
+
138
+ **ToolkitConfig interface**:
139
+ ```typescript
140
+ interface ToolkitConfig {
141
+ version?: string;
142
+ templatesPath?: string; // Relative or absolute path
143
+ projectType?: 'monolith' | 'monorepo';
144
+ sourceTemplate?: string; // For monolith projects
145
+ }
146
+ ```
147
+
148
+ #### Constants
149
+
150
+ ```typescript
151
+ static getConfigFileName(): string // Returns 'scaffold.yaml'
152
+ static getTemplatesFolderName(): string // Returns 'templates'
153
+ ```
154
+
155
+ ### ProjectFinderService
156
+
157
+ Find project configuration by walking up directory tree.
158
+
159
+ ```typescript
160
+ constructor(workspaceRoot?: string)
161
+
162
+ // Find project.json for a given file
163
+ async findProjectForFile(filePath: string): Promise<ProjectConfig | null>
164
+
165
+ // Sync version
166
+ findProjectForFileSync(filePath: string): ProjectConfig | null
167
+
168
+ // Get workspace root
169
+ getWorkspaceRoot(): string
170
+
171
+ // Clear internal cache
172
+ clearCache(): void
173
+ ```
174
+
175
+ **ProjectConfig interface**:
176
+ ```typescript
177
+ interface ProjectConfig {
178
+ name: string;
179
+ root: string; // Absolute path to project directory
180
+ sourceTemplate?: string;
181
+ projectType?: 'monolith' | 'monorepo';
182
+ }
183
+ ```
184
+
185
+ **Use case**: Used by MCP servers to determine which template rules apply to a file being edited.
186
+
187
+ ### CLI Output Utilities
188
+
189
+ #### print - Basic output
190
+
191
+ ```typescript
192
+ import { print } from '@agiflowai/aicode-utils';
193
+
194
+ print.info('Information message'); // Cyan
195
+ print.success('Success message'); // Green
196
+ print.warning('Warning message'); // Yellow
197
+ print.error('Error message'); // Red
198
+ print.debug('Debug message'); // Gray
199
+ print.header('Section Header'); // Bold cyan
200
+ print.item('List item'); // White with " - " prefix
201
+ print.indent('Indented text'); // White with " " prefix
202
+ print.highlight('Important text'); // Bold green
203
+ print.newline(); // Empty line
204
+ ```
205
+
206
+ #### messages - Output with icons
207
+
208
+ ```typescript
209
+ import { messages } from '@agiflowai/aicode-utils';
210
+
211
+ messages.info('Info with โ„น๏ธ icon');
212
+ messages.success('Success with โœ… icon');
213
+ messages.error('Error with โŒ icon');
214
+ messages.warning('Warning with โš ๏ธ icon');
215
+ messages.hint('Hint with ๐Ÿ’ก icon');
216
+ messages.loading('Processing with ๐Ÿš€ icon');
217
+ ```
218
+
219
+ #### sections - Formatted sections
220
+
221
+ ```typescript
222
+ import { sections } from '@agiflowai/aicode-utils';
223
+
224
+ sections.header('Main Title');
225
+
226
+ sections.list('Available Options', [
227
+ 'Option 1',
228
+ 'Option 2',
229
+ ]);
230
+
231
+ sections.nextSteps([
232
+ 'Run pnpm install',
233
+ 'Run pnpm dev',
234
+ ]);
235
+
236
+ sections.createdFiles([
237
+ 'src/app/page.tsx',
238
+ 'src/components/Button.tsx',
239
+ ], 10); // maxShow = 10
240
+
241
+ sections.warnings([
242
+ 'Deprecated API usage',
243
+ 'Missing required field',
244
+ ]);
245
+ ```
246
+
247
+ #### icons - Emoji constants
248
+
249
+ ```typescript
250
+ import { icons } from '@agiflowai/aicode-utils';
251
+
252
+ console.log(icons.rocket); // ๐Ÿš€
253
+ console.log(icons.check); // โœ…
254
+ console.log(icons.cross); // โŒ
255
+ console.log(icons.warning); // โš ๏ธ
256
+ console.log(icons.package); // ๐Ÿ“ฆ
257
+ console.log(icons.folder); // ๐Ÿ“
258
+ console.log(icons.bulb); // ๐Ÿ’ก
259
+ // ... and more
260
+ ```
261
+
262
+ ### Constants
263
+
264
+ ```typescript
265
+ import { ProjectType, ConfigSource } from '@agiflowai/aicode-utils';
266
+
267
+ // Project types
268
+ ProjectType.MONOLITH // 'monolith'
269
+ ProjectType.MONOREPO // 'monorepo'
270
+
271
+ // Config sources
272
+ ConfigSource.PROJECT_JSON // 'project.json'
273
+ ConfigSource.TOOLKIT_YAML // 'toolkit.yaml'
274
+ ```
275
+
276
+ ## Use Cases
277
+
278
+ ### 1. MCP Server Project Detection
279
+
280
+ MCP servers use this package to detect which project contains a file being edited:
281
+
282
+ ```typescript
283
+ import { ProjectFinderService, TemplatesManagerService } from '@agiflowai/aicode-utils';
284
+
285
+ const workspaceRoot = await TemplatesManagerService.getWorkspaceRoot();
286
+ const finder = new ProjectFinderService(workspaceRoot);
287
+
288
+ // User editing apps/web/src/components/Button.tsx
289
+ const project = await finder.findProjectForFile(
290
+ '/workspace/apps/web/src/components/Button.tsx'
291
+ );
292
+
293
+ if (project?.sourceTemplate === 'nextjs-15') {
294
+ // Apply Next.js 15 specific rules
295
+ }
296
+ ```
297
+
298
+ ### 2. CLI Tool Template Discovery
299
+
300
+ CLI tools use this to find templates without requiring user configuration:
301
+
302
+ ```typescript
303
+ import { TemplatesManagerService } from '@agiflowai/aicode-utils';
304
+
305
+ // Automatically finds templates even when run from nested directories
306
+ const templatesPath = await TemplatesManagerService.findTemplatesPath();
307
+ const scaffoldYaml = path.join(templatesPath, 'nextjs-15', 'scaffold.yaml');
308
+ ```
309
+
310
+ ### 3. Consistent CLI Output
311
+
312
+ Build polished CLI tools with consistent formatting:
313
+
314
+ ```typescript
315
+ import { messages, sections, print } from '@agiflowai/aicode-utils';
316
+
317
+ messages.loading('Downloading templates...');
318
+
319
+ sections.header('Setup Complete!');
320
+ sections.nextSteps([
321
+ 'cd my-project',
322
+ 'pnpm install',
323
+ 'pnpm dev',
324
+ ]);
325
+
326
+ print.highlight('๐ŸŽ‰ Ready to code!');
327
+ ```
328
+
329
+ ### 4. Workspace Configuration Management
330
+
331
+ Read and write toolkit.yaml for project configuration:
332
+
333
+ ```typescript
334
+ import { TemplatesManagerService } from '@agiflowai/aicode-utils';
335
+
336
+ // Read existing config
337
+ const config = await TemplatesManagerService.readToolkitConfig();
338
+
339
+ // Update config
340
+ await TemplatesManagerService.writeToolkitConfig({
341
+ version: '1.0',
342
+ templatesPath: 'custom-templates',
343
+ projectType: 'monorepo',
344
+ });
345
+ ```
346
+
347
+ ## Architecture
348
+
349
+ **Design patterns**:
350
+ - Static service classes for utility functions
351
+ - File system traversal with caching
352
+ - Upward directory search (finds .git root)
353
+ - Consistent error handling with descriptive messages
354
+
355
+ **Key features**:
356
+ - Both async and sync APIs for flexibility
357
+ - Caching in ProjectFinderService for performance
358
+ - Graceful fallbacks (defaults to cwd if no .git found)
359
+ - Type-safe constants with `as const` assertions
360
+
361
+ **Dependencies**:
362
+ - `chalk` - Terminal colors and styling
363
+ - `fs-extra` - Enhanced file system operations
364
+ - `js-yaml` - YAML parsing for toolkit.yaml
365
+ - `pino` - Structured logging
366
+
367
+ ## Common Patterns
368
+
369
+ ### Workspace Root Discovery
370
+
371
+ All services use the same algorithm:
372
+ 1. Start from provided path (or cwd)
373
+ 2. Walk up directories looking for .git
374
+ 3. Return .git parent directory
375
+ 4. Fallback to cwd if no .git found
376
+
377
+ ### Template Path Resolution
378
+
379
+ 1. Find workspace root
380
+ 2. Check toolkit.yaml for custom templatesPath
381
+ 3. Handle absolute or relative paths
382
+ 4. Fallback to /workspace/templates
383
+ 5. Throw descriptive error if not found
384
+
385
+ ### Project Config Resolution
386
+
387
+ 1. Start from file path
388
+ 2. Walk up directories
389
+ 3. Find first project.json
390
+ 4. Parse and cache result
391
+ 5. Return null if none found
392
+
393
+ ## Development
394
+
395
+ ```bash
396
+ # Build
397
+ pnpm build
398
+
399
+ # Test
400
+ pnpm test
401
+
402
+ # Type check
403
+ pnpm typecheck
404
+ ```
405
+
406
+ ## Related Packages
407
+
408
+ - `@agiflowai/aicode-toolkit` - CLI tool using these utilities
409
+ - `@agiflowai/architect-mcp` - MCP server using project detection
410
+ - `@agiflowai/scaffold-mcp` - MCP server using template discovery
411
+
412
+ ## License
413
+
414
+ AGPL-3.0
415
+
416
+ ## Links
417
+
418
+ - [GitHub](https://github.com/AgiFlow/aicode-toolkit)
419
+ - [Issues](https://github.com/AgiFlow/aicode-toolkit/issues)
package/dist/index.cjs CHANGED
@@ -29,6 +29,8 @@ let node_os = require("node:os");
29
29
  node_os = __toESM(node_os);
30
30
  let pino = require("pino");
31
31
  pino = __toESM(pino);
32
+ let js_yaml = require("js-yaml");
33
+ js_yaml = __toESM(js_yaml);
32
34
  let chalk = require("chalk");
33
35
  chalk = __toESM(chalk);
34
36
 
@@ -603,16 +605,19 @@ const print = {
603
605
  console.log(chalk.default.bold.cyan(message));
604
606
  },
605
607
  item: (message) => {
606
- console.log(chalk.default.gray(` - ${message}`));
608
+ console.log(chalk.default.white(` - ${message}`));
607
609
  },
608
610
  indent: (message) => {
609
- console.log(chalk.default.gray(` ${message}`));
611
+ console.log(chalk.default.white(` ${message}`));
610
612
  },
611
613
  highlight: (message) => {
612
614
  console.log(chalk.default.bold.green(message));
613
615
  },
614
616
  newline: () => {
615
617
  console.log();
618
+ },
619
+ divider: () => {
620
+ console.log(chalk.default.gray("ยท".repeat(60)));
616
621
  }
617
622
  };
618
623
  /**
@@ -696,6 +701,92 @@ const sections = {
696
701
  }
697
702
  };
698
703
 
704
+ //#endregion
705
+ //#region src/utils/projectTypeDetector.ts
706
+ /**
707
+ * Monorepo configuration files that indicate a monorepo setup
708
+ */
709
+ const MONOREPO_INDICATOR_FILES = [
710
+ "nx.json",
711
+ "turbo.json",
712
+ "rush.json",
713
+ "lerna.json",
714
+ "pnpm-workspace.yaml"
715
+ ];
716
+ /**
717
+ * Detect project type (monorepo vs monolith) based on workspace files
718
+ * Deterministic detection: monorepo exists when monorepo configuration files are found
719
+ *
720
+ * Detection priority:
721
+ * 1. toolkit.yaml (highest priority - explicit configuration)
722
+ * 2. Monorepo configuration files (nx.json, turbo.json, rush.json, lerna.json, pnpm-workspace.yaml)
723
+ * 3. package.json with workspaces field (npm/yarn workspaces)
724
+ * 4. If nothing found, returns undefined (user should choose)
725
+ *
726
+ * @param workspaceRoot - Absolute path to the workspace root directory
727
+ * @returns Detection result with project type and indicators
728
+ */
729
+ async function detectProjectType(workspaceRoot) {
730
+ const indicators = [];
731
+ const toolkitYamlPath = node_path.default.join(workspaceRoot, "toolkit.yaml");
732
+ if (await fs_extra.pathExists(toolkitYamlPath)) try {
733
+ const content = await fs_extra.readFile(toolkitYamlPath, "utf-8");
734
+ const config = js_yaml.load(content);
735
+ if (config?.projectType) {
736
+ indicators.push(`toolkit.yaml specifies ${config.projectType}`);
737
+ return {
738
+ projectType: config.projectType,
739
+ indicators
740
+ };
741
+ }
742
+ } catch {}
743
+ for (const filename of MONOREPO_INDICATOR_FILES) {
744
+ const filePath = node_path.default.join(workspaceRoot, filename);
745
+ if (await fs_extra.pathExists(filePath)) {
746
+ indicators.push(`${filename} found`);
747
+ return {
748
+ projectType: ProjectType.MONOREPO,
749
+ indicators
750
+ };
751
+ }
752
+ }
753
+ const packageJsonPath = node_path.default.join(workspaceRoot, "package.json");
754
+ if (await fs_extra.pathExists(packageJsonPath)) try {
755
+ if ((await fs_extra.readJson(packageJsonPath)).workspaces) {
756
+ indicators.push("package.json with workspaces found");
757
+ return {
758
+ projectType: ProjectType.MONOREPO,
759
+ indicators
760
+ };
761
+ }
762
+ } catch {}
763
+ indicators.push("No monorepo indicators found");
764
+ return {
765
+ projectType: void 0,
766
+ indicators
767
+ };
768
+ }
769
+ /**
770
+ * Check if a workspace is a monorepo
771
+ * Convenience function that returns a boolean
772
+ *
773
+ * @param workspaceRoot - Absolute path to the workspace root directory
774
+ * @returns True if workspace is detected as monorepo, false otherwise
775
+ */
776
+ async function isMonorepo(workspaceRoot) {
777
+ return (await detectProjectType(workspaceRoot)).projectType === ProjectType.MONOREPO;
778
+ }
779
+ /**
780
+ * Check if a workspace is a monolith
781
+ * Convenience function that returns a boolean
782
+ *
783
+ * @param workspaceRoot - Absolute path to the workspace root directory
784
+ * @returns True if workspace is detected as monolith, false otherwise
785
+ */
786
+ async function isMonolith(workspaceRoot) {
787
+ return (await detectProjectType(workspaceRoot)).projectType === ProjectType.MONOLITH;
788
+ }
789
+
699
790
  //#endregion
700
791
  exports.ConfigSource = ConfigSource;
701
792
  exports.ProjectConfigResolver = ProjectConfigResolver;
@@ -703,7 +794,10 @@ exports.ProjectFinderService = ProjectFinderService;
703
794
  exports.ProjectType = ProjectType;
704
795
  exports.ScaffoldProcessingService = ScaffoldProcessingService;
705
796
  exports.TemplatesManagerService = TemplatesManagerService;
797
+ exports.detectProjectType = detectProjectType;
706
798
  exports.icons = icons;
799
+ exports.isMonolith = isMonolith;
800
+ exports.isMonorepo = isMonorepo;
707
801
  exports.log = log;
708
802
  exports.logger = logger;
709
803
  exports.messages = messages;
package/dist/index.d.cts CHANGED
@@ -42,59 +42,16 @@ interface NxProjectJson {
42
42
  [key: string]: unknown;
43
43
  }
44
44
  //#endregion
45
- //#region src/services/ProjectConfigResolver.d.ts
45
+ //#region src/types/index.d.ts
46
46
  /**
47
- * ProjectConfigResolver
48
- *
49
- * Resolves project configuration from multiple sources with priority:
50
- * 1. project.json (monorepo - Nx/Lerna/Turborepo)
51
- * 2. toolkit.yaml at workspace root (monolith)
47
+ * Toolkit configuration from toolkit.yaml
52
48
  */
53
- declare class ProjectConfigResolver {
54
- /**
55
- * Resolve project configuration with priority fallback
56
- *
57
- * Priority order:
58
- * 1. Check for project.json (monorepo case)
59
- * 2. Check for toolkit.yaml at workspace root (monolith case)
60
- * 3. Error with helpful message
61
- *
62
- * @param projectPath - Absolute path to the project directory
63
- * @param explicitTemplate - Optional explicit template override
64
- * @returns Project configuration result
65
- * @throws Error if no configuration found
66
- */
67
- static resolveProjectConfig(projectPath: string, explicitTemplate?: string): Promise<ProjectConfigResult>;
68
- /**
69
- * Get helpful error message when no configuration is found
70
- */
71
- private static getHelpfulErrorMessage;
72
- /**
73
- * Check if project has configuration (without throwing error)
74
- *
75
- * @param projectPath - Absolute path to the project directory
76
- * @returns true if configuration exists, false otherwise
77
- * @throws Error if there's a filesystem error (not just missing config)
78
- */
79
- static hasConfiguration(projectPath: string): Promise<boolean>;
80
- /**
81
- * Create toolkit.yaml for monolith projects
82
- *
83
- * @param sourceTemplate - The template identifier
84
- * @param workspaceRoot - Optional workspace root path (defaults to current directory)
85
- */
86
- static createToolkitYaml(sourceTemplate: string, workspaceRoot?: string): Promise<void>;
87
- /**
88
- * Create or update project.json for monorepo projects
89
- *
90
- * @param projectPath - Absolute path to the project directory
91
- * @param projectName - Name of the project
92
- * @param sourceTemplate - The template identifier
93
- */
94
- static createProjectJson(projectPath: string, projectName: string, sourceTemplate: string): Promise<void>;
49
+ interface ToolkitConfig {
50
+ version?: string;
51
+ templatesPath?: string;
52
+ projectType?: 'monolith' | 'monorepo';
53
+ sourceTemplate?: string;
95
54
  }
96
- //#endregion
97
- //#region src/types/index.d.ts
98
55
  /**
99
56
  * Project configuration from project.json
100
57
  */
@@ -166,6 +123,58 @@ interface GeneratorContext {
166
123
  */
167
124
  type GeneratorFunction = (context: GeneratorContext) => Promise<ScaffoldResult>;
168
125
  //#endregion
126
+ //#region src/services/ProjectConfigResolver.d.ts
127
+ /**
128
+ * ProjectConfigResolver
129
+ *
130
+ * Resolves project configuration from multiple sources with priority:
131
+ * 1. project.json (monorepo - Nx/Lerna/Turborepo)
132
+ * 2. toolkit.yaml at workspace root (monolith)
133
+ */
134
+ declare class ProjectConfigResolver {
135
+ /**
136
+ * Resolve project configuration with priority fallback
137
+ *
138
+ * Priority order:
139
+ * 1. Check for project.json (monorepo case)
140
+ * 2. Check for toolkit.yaml at workspace root (monolith case)
141
+ * 3. Error with helpful message
142
+ *
143
+ * @param projectPath - Absolute path to the project directory
144
+ * @param explicitTemplate - Optional explicit template override
145
+ * @returns Project configuration result
146
+ * @throws Error if no configuration found
147
+ */
148
+ static resolveProjectConfig(projectPath: string, explicitTemplate?: string): Promise<ProjectConfigResult>;
149
+ /**
150
+ * Get helpful error message when no configuration is found
151
+ */
152
+ private static getHelpfulErrorMessage;
153
+ /**
154
+ * Check if project has configuration (without throwing error)
155
+ *
156
+ * @param projectPath - Absolute path to the project directory
157
+ * @returns true if configuration exists, false otherwise
158
+ * @throws Error if there's a filesystem error (not just missing config)
159
+ */
160
+ static hasConfiguration(projectPath: string): Promise<boolean>;
161
+ /**
162
+ * Create toolkit.yaml for monolith projects
163
+ *
164
+ * @param sourceTemplate - The template identifier
165
+ * @param workspaceRoot - Optional workspace root path (defaults to current directory)
166
+ */
167
+ static createToolkitYaml(sourceTemplate: string, workspaceRoot?: string): Promise<void>;
168
+ /**
169
+ * Create or update project.json for monorepo projects
170
+ *
171
+ * @param projectPath - Absolute path to the project directory
172
+ * @param projectName - Name of the project
173
+ * @param sourceTemplate - The template identifier
174
+ */
175
+ static createProjectJson(projectPath: string, projectName: string, sourceTemplate: string): Promise<void>;
176
+ }
177
+ //#endregion
169
178
  //#region src/services/ProjectFinderService.d.ts
170
179
  declare class ProjectFinderService {
171
180
  private projectCache;
@@ -239,35 +248,6 @@ declare class ScaffoldProcessingService {
239
248
  }
240
249
  //#endregion
241
250
  //#region src/services/TemplatesManagerService.d.ts
242
- /**
243
- * TemplatesManagerService
244
- *
245
- * DESIGN PATTERNS:
246
- * - Class-based service pattern for encapsulating business logic
247
- * - Static methods for utility-like functionality
248
- * - File system traversal for workspace detection
249
- * - Configuration-driven template path resolution
250
- *
251
- * CODING STANDARDS:
252
- * - Service class names use PascalCase with 'Service' suffix
253
- * - Method names use camelCase with descriptive verbs
254
- * - Return types should be explicit (never use implicit any)
255
- * - Use async/await for asynchronous operations
256
- * - Handle errors with try-catch and throw descriptive Error objects
257
- * - Document public methods with JSDoc comments
258
- *
259
- * AVOID:
260
- * - Side effects in constructors (keep them lightweight)
261
- * - Mixing concerns (keep services focused on single domain)
262
- * - Direct coupling to other services (use dependency injection)
263
- * - Exposing internal implementation details
264
- */
265
- interface ToolkitConfig {
266
- version?: string;
267
- templatesPath?: string;
268
- projectType?: 'monolith' | 'monorepo';
269
- sourceTemplate?: string;
270
- }
271
251
  declare class TemplatesManagerService {
272
252
  private static SCAFFOLD_CONFIG_FILE;
273
253
  private static TEMPLATES_FOLDER;
@@ -396,11 +376,11 @@ declare const print: {
396
376
  */
397
377
  header: (message: string) => void;
398
378
  /**
399
- * Log item in a list (gray with prefix)
379
+ * Log item in a list (white with prefix)
400
380
  */
401
381
  item: (message: string) => void;
402
382
  /**
403
- * Log indented text (gray)
383
+ * Log indented text (white)
404
384
  */
405
385
  indent: (message: string) => void;
406
386
  /**
@@ -411,6 +391,10 @@ declare const print: {
411
391
  * Empty line
412
392
  */
413
393
  newline: () => void;
394
+ /**
395
+ * Print a visual divider (dots)
396
+ */
397
+ divider: () => void;
414
398
  };
415
399
  /**
416
400
  * Emoji icons for consistent visual markers
@@ -489,4 +473,45 @@ declare const sections: {
489
473
  warnings: (warnings: string[]) => void;
490
474
  };
491
475
  //#endregion
492
- export { ConfigSource, GeneratorContext, GeneratorFunction, IFileSystemService, IVariableReplacementService, NxProjectJson, ParsedInclude, ProjectConfig, ProjectConfigResolver, ProjectConfigResult, ProjectFinderService, ProjectType, ScaffoldProcessingService, ScaffoldResult, TemplatesManagerService, ToolkitConfig, icons, log, logger, messages, print, sections };
476
+ //#region src/utils/projectTypeDetector.d.ts
477
+ /**
478
+ * Result of project type detection
479
+ */
480
+ interface ProjectTypeDetectionResult {
481
+ /** Detected project type (undefined if not detected) */
482
+ projectType?: ProjectType;
483
+ /** List of indicators that led to the detection */
484
+ indicators: string[];
485
+ }
486
+ /**
487
+ * Detect project type (monorepo vs monolith) based on workspace files
488
+ * Deterministic detection: monorepo exists when monorepo configuration files are found
489
+ *
490
+ * Detection priority:
491
+ * 1. toolkit.yaml (highest priority - explicit configuration)
492
+ * 2. Monorepo configuration files (nx.json, turbo.json, rush.json, lerna.json, pnpm-workspace.yaml)
493
+ * 3. package.json with workspaces field (npm/yarn workspaces)
494
+ * 4. If nothing found, returns undefined (user should choose)
495
+ *
496
+ * @param workspaceRoot - Absolute path to the workspace root directory
497
+ * @returns Detection result with project type and indicators
498
+ */
499
+ declare function detectProjectType(workspaceRoot: string): Promise<ProjectTypeDetectionResult>;
500
+ /**
501
+ * Check if a workspace is a monorepo
502
+ * Convenience function that returns a boolean
503
+ *
504
+ * @param workspaceRoot - Absolute path to the workspace root directory
505
+ * @returns True if workspace is detected as monorepo, false otherwise
506
+ */
507
+ declare function isMonorepo(workspaceRoot: string): Promise<boolean>;
508
+ /**
509
+ * Check if a workspace is a monolith
510
+ * Convenience function that returns a boolean
511
+ *
512
+ * @param workspaceRoot - Absolute path to the workspace root directory
513
+ * @returns True if workspace is detected as monolith, false otherwise
514
+ */
515
+ declare function isMonolith(workspaceRoot: string): Promise<boolean>;
516
+ //#endregion
517
+ export { ConfigSource, GeneratorContext, GeneratorFunction, IFileSystemService, IVariableReplacementService, NxProjectJson, ParsedInclude, ProjectConfig, ProjectConfigResolver, ProjectConfigResult, ProjectFinderService, ProjectType, ProjectTypeDetectionResult, ScaffoldProcessingService, ScaffoldResult, TemplatesManagerService, ToolkitConfig, detectProjectType, icons, isMonolith, isMonorepo, log, logger, messages, print, sections };
package/dist/index.d.ts CHANGED
@@ -42,59 +42,16 @@ interface NxProjectJson {
42
42
  [key: string]: unknown;
43
43
  }
44
44
  //#endregion
45
- //#region src/services/ProjectConfigResolver.d.ts
45
+ //#region src/types/index.d.ts
46
46
  /**
47
- * ProjectConfigResolver
48
- *
49
- * Resolves project configuration from multiple sources with priority:
50
- * 1. project.json (monorepo - Nx/Lerna/Turborepo)
51
- * 2. toolkit.yaml at workspace root (monolith)
47
+ * Toolkit configuration from toolkit.yaml
52
48
  */
53
- declare class ProjectConfigResolver {
54
- /**
55
- * Resolve project configuration with priority fallback
56
- *
57
- * Priority order:
58
- * 1. Check for project.json (monorepo case)
59
- * 2. Check for toolkit.yaml at workspace root (monolith case)
60
- * 3. Error with helpful message
61
- *
62
- * @param projectPath - Absolute path to the project directory
63
- * @param explicitTemplate - Optional explicit template override
64
- * @returns Project configuration result
65
- * @throws Error if no configuration found
66
- */
67
- static resolveProjectConfig(projectPath: string, explicitTemplate?: string): Promise<ProjectConfigResult>;
68
- /**
69
- * Get helpful error message when no configuration is found
70
- */
71
- private static getHelpfulErrorMessage;
72
- /**
73
- * Check if project has configuration (without throwing error)
74
- *
75
- * @param projectPath - Absolute path to the project directory
76
- * @returns true if configuration exists, false otherwise
77
- * @throws Error if there's a filesystem error (not just missing config)
78
- */
79
- static hasConfiguration(projectPath: string): Promise<boolean>;
80
- /**
81
- * Create toolkit.yaml for monolith projects
82
- *
83
- * @param sourceTemplate - The template identifier
84
- * @param workspaceRoot - Optional workspace root path (defaults to current directory)
85
- */
86
- static createToolkitYaml(sourceTemplate: string, workspaceRoot?: string): Promise<void>;
87
- /**
88
- * Create or update project.json for monorepo projects
89
- *
90
- * @param projectPath - Absolute path to the project directory
91
- * @param projectName - Name of the project
92
- * @param sourceTemplate - The template identifier
93
- */
94
- static createProjectJson(projectPath: string, projectName: string, sourceTemplate: string): Promise<void>;
49
+ interface ToolkitConfig {
50
+ version?: string;
51
+ templatesPath?: string;
52
+ projectType?: 'monolith' | 'monorepo';
53
+ sourceTemplate?: string;
95
54
  }
96
- //#endregion
97
- //#region src/types/index.d.ts
98
55
  /**
99
56
  * Project configuration from project.json
100
57
  */
@@ -166,6 +123,58 @@ interface GeneratorContext {
166
123
  */
167
124
  type GeneratorFunction = (context: GeneratorContext) => Promise<ScaffoldResult>;
168
125
  //#endregion
126
+ //#region src/services/ProjectConfigResolver.d.ts
127
+ /**
128
+ * ProjectConfigResolver
129
+ *
130
+ * Resolves project configuration from multiple sources with priority:
131
+ * 1. project.json (monorepo - Nx/Lerna/Turborepo)
132
+ * 2. toolkit.yaml at workspace root (monolith)
133
+ */
134
+ declare class ProjectConfigResolver {
135
+ /**
136
+ * Resolve project configuration with priority fallback
137
+ *
138
+ * Priority order:
139
+ * 1. Check for project.json (monorepo case)
140
+ * 2. Check for toolkit.yaml at workspace root (monolith case)
141
+ * 3. Error with helpful message
142
+ *
143
+ * @param projectPath - Absolute path to the project directory
144
+ * @param explicitTemplate - Optional explicit template override
145
+ * @returns Project configuration result
146
+ * @throws Error if no configuration found
147
+ */
148
+ static resolveProjectConfig(projectPath: string, explicitTemplate?: string): Promise<ProjectConfigResult>;
149
+ /**
150
+ * Get helpful error message when no configuration is found
151
+ */
152
+ private static getHelpfulErrorMessage;
153
+ /**
154
+ * Check if project has configuration (without throwing error)
155
+ *
156
+ * @param projectPath - Absolute path to the project directory
157
+ * @returns true if configuration exists, false otherwise
158
+ * @throws Error if there's a filesystem error (not just missing config)
159
+ */
160
+ static hasConfiguration(projectPath: string): Promise<boolean>;
161
+ /**
162
+ * Create toolkit.yaml for monolith projects
163
+ *
164
+ * @param sourceTemplate - The template identifier
165
+ * @param workspaceRoot - Optional workspace root path (defaults to current directory)
166
+ */
167
+ static createToolkitYaml(sourceTemplate: string, workspaceRoot?: string): Promise<void>;
168
+ /**
169
+ * Create or update project.json for monorepo projects
170
+ *
171
+ * @param projectPath - Absolute path to the project directory
172
+ * @param projectName - Name of the project
173
+ * @param sourceTemplate - The template identifier
174
+ */
175
+ static createProjectJson(projectPath: string, projectName: string, sourceTemplate: string): Promise<void>;
176
+ }
177
+ //#endregion
169
178
  //#region src/services/ProjectFinderService.d.ts
170
179
  declare class ProjectFinderService {
171
180
  private projectCache;
@@ -239,35 +248,6 @@ declare class ScaffoldProcessingService {
239
248
  }
240
249
  //#endregion
241
250
  //#region src/services/TemplatesManagerService.d.ts
242
- /**
243
- * TemplatesManagerService
244
- *
245
- * DESIGN PATTERNS:
246
- * - Class-based service pattern for encapsulating business logic
247
- * - Static methods for utility-like functionality
248
- * - File system traversal for workspace detection
249
- * - Configuration-driven template path resolution
250
- *
251
- * CODING STANDARDS:
252
- * - Service class names use PascalCase with 'Service' suffix
253
- * - Method names use camelCase with descriptive verbs
254
- * - Return types should be explicit (never use implicit any)
255
- * - Use async/await for asynchronous operations
256
- * - Handle errors with try-catch and throw descriptive Error objects
257
- * - Document public methods with JSDoc comments
258
- *
259
- * AVOID:
260
- * - Side effects in constructors (keep them lightweight)
261
- * - Mixing concerns (keep services focused on single domain)
262
- * - Direct coupling to other services (use dependency injection)
263
- * - Exposing internal implementation details
264
- */
265
- interface ToolkitConfig {
266
- version?: string;
267
- templatesPath?: string;
268
- projectType?: 'monolith' | 'monorepo';
269
- sourceTemplate?: string;
270
- }
271
251
  declare class TemplatesManagerService {
272
252
  private static SCAFFOLD_CONFIG_FILE;
273
253
  private static TEMPLATES_FOLDER;
@@ -396,11 +376,11 @@ declare const print: {
396
376
  */
397
377
  header: (message: string) => void;
398
378
  /**
399
- * Log item in a list (gray with prefix)
379
+ * Log item in a list (white with prefix)
400
380
  */
401
381
  item: (message: string) => void;
402
382
  /**
403
- * Log indented text (gray)
383
+ * Log indented text (white)
404
384
  */
405
385
  indent: (message: string) => void;
406
386
  /**
@@ -411,6 +391,10 @@ declare const print: {
411
391
  * Empty line
412
392
  */
413
393
  newline: () => void;
394
+ /**
395
+ * Print a visual divider (dots)
396
+ */
397
+ divider: () => void;
414
398
  };
415
399
  /**
416
400
  * Emoji icons for consistent visual markers
@@ -489,4 +473,45 @@ declare const sections: {
489
473
  warnings: (warnings: string[]) => void;
490
474
  };
491
475
  //#endregion
492
- export { ConfigSource, GeneratorContext, GeneratorFunction, IFileSystemService, IVariableReplacementService, NxProjectJson, ParsedInclude, ProjectConfig, ProjectConfigResolver, ProjectConfigResult, ProjectFinderService, ProjectType, ScaffoldProcessingService, ScaffoldResult, TemplatesManagerService, ToolkitConfig, icons, log, logger, messages, print, sections };
476
+ //#region src/utils/projectTypeDetector.d.ts
477
+ /**
478
+ * Result of project type detection
479
+ */
480
+ interface ProjectTypeDetectionResult {
481
+ /** Detected project type (undefined if not detected) */
482
+ projectType?: ProjectType;
483
+ /** List of indicators that led to the detection */
484
+ indicators: string[];
485
+ }
486
+ /**
487
+ * Detect project type (monorepo vs monolith) based on workspace files
488
+ * Deterministic detection: monorepo exists when monorepo configuration files are found
489
+ *
490
+ * Detection priority:
491
+ * 1. toolkit.yaml (highest priority - explicit configuration)
492
+ * 2. Monorepo configuration files (nx.json, turbo.json, rush.json, lerna.json, pnpm-workspace.yaml)
493
+ * 3. package.json with workspaces field (npm/yarn workspaces)
494
+ * 4. If nothing found, returns undefined (user should choose)
495
+ *
496
+ * @param workspaceRoot - Absolute path to the workspace root directory
497
+ * @returns Detection result with project type and indicators
498
+ */
499
+ declare function detectProjectType(workspaceRoot: string): Promise<ProjectTypeDetectionResult>;
500
+ /**
501
+ * Check if a workspace is a monorepo
502
+ * Convenience function that returns a boolean
503
+ *
504
+ * @param workspaceRoot - Absolute path to the workspace root directory
505
+ * @returns True if workspace is detected as monorepo, false otherwise
506
+ */
507
+ declare function isMonorepo(workspaceRoot: string): Promise<boolean>;
508
+ /**
509
+ * Check if a workspace is a monolith
510
+ * Convenience function that returns a boolean
511
+ *
512
+ * @param workspaceRoot - Absolute path to the workspace root directory
513
+ * @returns True if workspace is detected as monolith, false otherwise
514
+ */
515
+ declare function isMonolith(workspaceRoot: string): Promise<boolean>;
516
+ //#endregion
517
+ export { ConfigSource, GeneratorContext, GeneratorFunction, IFileSystemService, IVariableReplacementService, NxProjectJson, ParsedInclude, ProjectConfig, ProjectConfigResolver, ProjectConfigResult, ProjectFinderService, ProjectType, ProjectTypeDetectionResult, ScaffoldProcessingService, ScaffoldResult, TemplatesManagerService, ToolkitConfig, detectProjectType, icons, isMonolith, isMonorepo, log, logger, messages, print, sections };
package/dist/index.js CHANGED
@@ -4,6 +4,7 @@ import path from "node:path";
4
4
  import * as fs from "fs-extra";
5
5
  import * as os from "node:os";
6
6
  import pino from "pino";
7
+ import * as yaml from "js-yaml";
7
8
  import chalk from "chalk";
8
9
 
9
10
  //#region rolldown:runtime
@@ -69,9 +70,9 @@ var TemplatesManagerService = class TemplatesManagerService {
69
70
  const workspaceRoot = await TemplatesManagerService.findWorkspaceRoot(startPath);
70
71
  const toolkitConfigPath = path.join(workspaceRoot, TemplatesManagerService.TOOLKIT_CONFIG_FILE);
71
72
  if (await fs.pathExists(toolkitConfigPath)) {
72
- const yaml = await import("js-yaml");
73
+ const yaml$1 = await import("js-yaml");
73
74
  const content = await fs.readFile(toolkitConfigPath, "utf-8");
74
- const config = yaml.load(content);
75
+ const config = yaml$1.load(content);
75
76
  if (config?.templatesPath) {
76
77
  const templatesPath$1 = path.isAbsolute(config.templatesPath) ? config.templatesPath : path.join(workspaceRoot, config.templatesPath);
77
78
  if (await fs.pathExists(templatesPath$1)) return templatesPath$1;
@@ -107,9 +108,9 @@ var TemplatesManagerService = class TemplatesManagerService {
107
108
  const workspaceRoot = TemplatesManagerService.findWorkspaceRootSync(startPath);
108
109
  const toolkitConfigPath = path.join(workspaceRoot, TemplatesManagerService.TOOLKIT_CONFIG_FILE);
109
110
  if (fs.pathExistsSync(toolkitConfigPath)) {
110
- const yaml = __require("js-yaml");
111
+ const yaml$1 = __require("js-yaml");
111
112
  const content = fs.readFileSync(toolkitConfigPath, "utf-8");
112
- const config = yaml.load(content);
113
+ const config = yaml$1.load(content);
113
114
  if (config?.templatesPath) {
114
115
  const templatesPath$1 = path.isAbsolute(config.templatesPath) ? config.templatesPath : path.join(workspaceRoot, config.templatesPath);
115
116
  if (fs.pathExistsSync(templatesPath$1)) return templatesPath$1;
@@ -165,9 +166,9 @@ var TemplatesManagerService = class TemplatesManagerService {
165
166
  const workspaceRoot = await TemplatesManagerService.findWorkspaceRoot(startPath);
166
167
  const toolkitConfigPath = path.join(workspaceRoot, TemplatesManagerService.TOOLKIT_CONFIG_FILE);
167
168
  if (!await fs.pathExists(toolkitConfigPath)) return null;
168
- const yaml = await import("js-yaml");
169
+ const yaml$1 = await import("js-yaml");
169
170
  const content = await fs.readFile(toolkitConfigPath, "utf-8");
170
- return yaml.load(content);
171
+ return yaml$1.load(content);
171
172
  }
172
173
  /**
173
174
  * Read toolkit.yaml configuration from workspace root (sync)
@@ -179,9 +180,9 @@ var TemplatesManagerService = class TemplatesManagerService {
179
180
  const workspaceRoot = TemplatesManagerService.findWorkspaceRootSync(startPath);
180
181
  const toolkitConfigPath = path.join(workspaceRoot, TemplatesManagerService.TOOLKIT_CONFIG_FILE);
181
182
  if (!fs.pathExistsSync(toolkitConfigPath)) return null;
182
- const yaml = __require("js-yaml");
183
+ const yaml$1 = __require("js-yaml");
183
184
  const content = fs.readFileSync(toolkitConfigPath, "utf-8");
184
- return yaml.load(content);
185
+ return yaml$1.load(content);
185
186
  }
186
187
  /**
187
188
  * Write toolkit.yaml configuration to workspace root
@@ -581,16 +582,19 @@ const print = {
581
582
  console.log(chalk.bold.cyan(message));
582
583
  },
583
584
  item: (message) => {
584
- console.log(chalk.gray(` - ${message}`));
585
+ console.log(chalk.white(` - ${message}`));
585
586
  },
586
587
  indent: (message) => {
587
- console.log(chalk.gray(` ${message}`));
588
+ console.log(chalk.white(` ${message}`));
588
589
  },
589
590
  highlight: (message) => {
590
591
  console.log(chalk.bold.green(message));
591
592
  },
592
593
  newline: () => {
593
594
  console.log();
595
+ },
596
+ divider: () => {
597
+ console.log(chalk.gray("ยท".repeat(60)));
594
598
  }
595
599
  };
596
600
  /**
@@ -675,4 +679,90 @@ const sections = {
675
679
  };
676
680
 
677
681
  //#endregion
678
- export { ConfigSource, ProjectConfigResolver, ProjectFinderService, ProjectType, ScaffoldProcessingService, TemplatesManagerService, icons, log, logger, messages, print, sections };
682
+ //#region src/utils/projectTypeDetector.ts
683
+ /**
684
+ * Monorepo configuration files that indicate a monorepo setup
685
+ */
686
+ const MONOREPO_INDICATOR_FILES = [
687
+ "nx.json",
688
+ "turbo.json",
689
+ "rush.json",
690
+ "lerna.json",
691
+ "pnpm-workspace.yaml"
692
+ ];
693
+ /**
694
+ * Detect project type (monorepo vs monolith) based on workspace files
695
+ * Deterministic detection: monorepo exists when monorepo configuration files are found
696
+ *
697
+ * Detection priority:
698
+ * 1. toolkit.yaml (highest priority - explicit configuration)
699
+ * 2. Monorepo configuration files (nx.json, turbo.json, rush.json, lerna.json, pnpm-workspace.yaml)
700
+ * 3. package.json with workspaces field (npm/yarn workspaces)
701
+ * 4. If nothing found, returns undefined (user should choose)
702
+ *
703
+ * @param workspaceRoot - Absolute path to the workspace root directory
704
+ * @returns Detection result with project type and indicators
705
+ */
706
+ async function detectProjectType(workspaceRoot) {
707
+ const indicators = [];
708
+ const toolkitYamlPath = path.join(workspaceRoot, "toolkit.yaml");
709
+ if (await fs.pathExists(toolkitYamlPath)) try {
710
+ const content = await fs.readFile(toolkitYamlPath, "utf-8");
711
+ const config = yaml.load(content);
712
+ if (config?.projectType) {
713
+ indicators.push(`toolkit.yaml specifies ${config.projectType}`);
714
+ return {
715
+ projectType: config.projectType,
716
+ indicators
717
+ };
718
+ }
719
+ } catch {}
720
+ for (const filename of MONOREPO_INDICATOR_FILES) {
721
+ const filePath = path.join(workspaceRoot, filename);
722
+ if (await fs.pathExists(filePath)) {
723
+ indicators.push(`${filename} found`);
724
+ return {
725
+ projectType: ProjectType.MONOREPO,
726
+ indicators
727
+ };
728
+ }
729
+ }
730
+ const packageJsonPath = path.join(workspaceRoot, "package.json");
731
+ if (await fs.pathExists(packageJsonPath)) try {
732
+ if ((await fs.readJson(packageJsonPath)).workspaces) {
733
+ indicators.push("package.json with workspaces found");
734
+ return {
735
+ projectType: ProjectType.MONOREPO,
736
+ indicators
737
+ };
738
+ }
739
+ } catch {}
740
+ indicators.push("No monorepo indicators found");
741
+ return {
742
+ projectType: void 0,
743
+ indicators
744
+ };
745
+ }
746
+ /**
747
+ * Check if a workspace is a monorepo
748
+ * Convenience function that returns a boolean
749
+ *
750
+ * @param workspaceRoot - Absolute path to the workspace root directory
751
+ * @returns True if workspace is detected as monorepo, false otherwise
752
+ */
753
+ async function isMonorepo(workspaceRoot) {
754
+ return (await detectProjectType(workspaceRoot)).projectType === ProjectType.MONOREPO;
755
+ }
756
+ /**
757
+ * Check if a workspace is a monolith
758
+ * Convenience function that returns a boolean
759
+ *
760
+ * @param workspaceRoot - Absolute path to the workspace root directory
761
+ * @returns True if workspace is detected as monolith, false otherwise
762
+ */
763
+ async function isMonolith(workspaceRoot) {
764
+ return (await detectProjectType(workspaceRoot)).projectType === ProjectType.MONOLITH;
765
+ }
766
+
767
+ //#endregion
768
+ export { ConfigSource, ProjectConfigResolver, ProjectFinderService, ProjectType, ScaffoldProcessingService, TemplatesManagerService, detectProjectType, icons, isMonolith, isMonorepo, 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.6.0",
4
+ "version": "1.0.1",
5
5
  "license": "AGPL-3.0",
6
6
  "author": "AgiflowIO",
7
7
  "repository": {
@@ -24,7 +24,7 @@
24
24
  ],
25
25
  "main": "./dist/index.cjs",
26
26
  "module": "./dist/index.js",
27
- "types": "./dist/index.d.ts",
27
+ "types": "./dist/index.d.cts",
28
28
  "files": [
29
29
  "dist",
30
30
  "README.md"
@@ -33,12 +33,14 @@
33
33
  "chalk": "5.6.2",
34
34
  "fs-extra": "11.3.2",
35
35
  "js-yaml": "4.1.0",
36
+ "ora": "^9.0.0",
36
37
  "pino": "^10.0.0"
37
38
  },
38
39
  "devDependencies": {
39
40
  "@types/fs-extra": "^11.0.4",
40
41
  "@types/js-yaml": "^4.0.9",
41
42
  "@types/node": "^22.0.0",
43
+ "@types/ora": "^3.2.0",
42
44
  "@vitest/coverage-v8": "^3.0.0",
43
45
  "tsdown": "^0.15.6",
44
46
  "typescript": "5.9.3",
@@ -48,6 +50,13 @@
48
50
  "publishConfig": {
49
51
  "access": "public"
50
52
  },
53
+ "exports": {
54
+ ".": {
55
+ "import": "./dist/index.js",
56
+ "require": "./dist/index.cjs"
57
+ },
58
+ "./package.json": "./package.json"
59
+ },
51
60
  "scripts": {
52
61
  "build": "tsdown",
53
62
  "test": "vitest --run",