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