@agiflowai/aicode-utils 1.0.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 +419 -0
- package/dist/index.cjs +94 -0
- package/dist/index.d.cts +105 -80
- package/dist/index.d.ts +105 -80
- package/dist/index.js +99 -9
- package/package.json +3 -1
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
|
|
|
@@ -613,6 +615,9 @@ const print = {
|
|
|
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/
|
|
45
|
+
//#region src/types/index.d.ts
|
|
46
46
|
/**
|
|
47
|
-
*
|
|
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
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
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;
|
|
@@ -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
|
-
|
|
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/
|
|
45
|
+
//#region src/types/index.d.ts
|
|
46
46
|
/**
|
|
47
|
-
*
|
|
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
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
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;
|
|
@@ -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
|
-
|
|
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
|
|
@@ -591,6 +592,9 @@ const print = {
|
|
|
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
|
-
|
|
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": "1.0.
|
|
4
|
+
"version": "1.0.1",
|
|
5
5
|
"license": "AGPL-3.0",
|
|
6
6
|
"author": "AgiflowIO",
|
|
7
7
|
"repository": {
|
|
@@ -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",
|