@agiflowai/scaffold-mcp 0.3.0 → 0.3.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/dist/ScaffoldConfigLoader-CnVkzUxL.js +3 -0
- package/dist/{ScaffoldConfigLoader-CI0T6zdG.js → ScaffoldConfigLoader-yDhzLQpC.js} +34 -25
- package/dist/{ScaffoldService-CnJ1nj1v.js → ScaffoldService-B8-dPa7L.js} +62 -52
- package/dist/ScaffoldService-BXKXXg4M.js +3 -0
- package/dist/TemplateService-B0ns4TR_.js +3 -0
- package/dist/{TemplateService-CnxvhRVW.js → TemplateService-DvKjDjQE.js} +10 -3
- package/dist/{VariableReplacementService-Bq0GDhTo.js → VariableReplacementService-DJqXiBC2.js} +11 -4
- package/dist/VariableReplacementService-_GgLG4Im.js +3 -0
- package/dist/chunk-nOFOJqeH.js +30 -0
- package/dist/index.js +229 -208
- package/package.json +2 -3
- package/dist/ScaffoldConfigLoader-DhthV6xq.js +0 -3
- package/dist/ScaffoldService-CDhYAUrp.js +0 -3
- package/dist/TemplateService-PmTU3_On.js +0 -3
- package/dist/VariableReplacementService-CrxFJrqU.js +0 -3
package/dist/index.js
CHANGED
|
@@ -1,28 +1,41 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
2
|
+
const require_chunk = require('./chunk-nOFOJqeH.js');
|
|
3
|
+
const require_ScaffoldConfigLoader = require('./ScaffoldConfigLoader-yDhzLQpC.js');
|
|
4
|
+
const require_ScaffoldService = require('./ScaffoldService-B8-dPa7L.js');
|
|
5
|
+
const require_TemplateService = require('./TemplateService-DvKjDjQE.js');
|
|
6
|
+
const require_VariableReplacementService = require('./VariableReplacementService-DJqXiBC2.js');
|
|
7
|
+
let commander = require("commander");
|
|
8
|
+
commander = require_chunk.__toESM(commander);
|
|
9
|
+
let node_path = require("node:path");
|
|
10
|
+
node_path = require_chunk.__toESM(node_path);
|
|
11
|
+
let fs_extra = require("fs-extra");
|
|
12
|
+
fs_extra = require_chunk.__toESM(fs_extra);
|
|
13
|
+
let chalk = require("chalk");
|
|
14
|
+
chalk = require_chunk.__toESM(chalk);
|
|
15
|
+
let node_child_process = require("node:child_process");
|
|
16
|
+
node_child_process = require_chunk.__toESM(node_child_process);
|
|
17
|
+
let node_util = require("node:util");
|
|
18
|
+
node_util = require_chunk.__toESM(node_util);
|
|
19
|
+
let __composio_json_schema_to_zod = require("@composio/json-schema-to-zod");
|
|
20
|
+
__composio_json_schema_to_zod = require_chunk.__toESM(__composio_json_schema_to_zod);
|
|
21
|
+
let js_yaml = require("js-yaml");
|
|
22
|
+
js_yaml = require_chunk.__toESM(js_yaml);
|
|
23
|
+
let zod = require("zod");
|
|
24
|
+
zod = require_chunk.__toESM(zod);
|
|
25
|
+
let __modelcontextprotocol_sdk_server_index_js = require("@modelcontextprotocol/sdk/server/index.js");
|
|
26
|
+
__modelcontextprotocol_sdk_server_index_js = require_chunk.__toESM(__modelcontextprotocol_sdk_server_index_js);
|
|
27
|
+
let __modelcontextprotocol_sdk_types_js = require("@modelcontextprotocol/sdk/types.js");
|
|
28
|
+
__modelcontextprotocol_sdk_types_js = require_chunk.__toESM(__modelcontextprotocol_sdk_types_js);
|
|
29
|
+
let node_crypto = require("node:crypto");
|
|
30
|
+
node_crypto = require_chunk.__toESM(node_crypto);
|
|
31
|
+
let __modelcontextprotocol_sdk_server_streamableHttp_js = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
|
|
32
|
+
__modelcontextprotocol_sdk_server_streamableHttp_js = require_chunk.__toESM(__modelcontextprotocol_sdk_server_streamableHttp_js);
|
|
33
|
+
let express = require("express");
|
|
34
|
+
express = require_chunk.__toESM(express);
|
|
35
|
+
let __modelcontextprotocol_sdk_server_sse_js = require("@modelcontextprotocol/sdk/server/sse.js");
|
|
36
|
+
__modelcontextprotocol_sdk_server_sse_js = require_chunk.__toESM(__modelcontextprotocol_sdk_server_sse_js);
|
|
37
|
+
let __modelcontextprotocol_sdk_server_stdio_js = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
38
|
+
__modelcontextprotocol_sdk_server_stdio_js = require_chunk.__toESM(__modelcontextprotocol_sdk_server_stdio_js);
|
|
26
39
|
|
|
27
40
|
//#region src/utils/console.ts
|
|
28
41
|
/**
|
|
@@ -30,34 +43,34 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
|
|
|
30
43
|
*/
|
|
31
44
|
const logger = {
|
|
32
45
|
info: (message) => {
|
|
33
|
-
console.log(chalk.cyan(message));
|
|
46
|
+
console.log(chalk.default.cyan(message));
|
|
34
47
|
},
|
|
35
48
|
success: (message) => {
|
|
36
|
-
console.log(chalk.green(message));
|
|
49
|
+
console.log(chalk.default.green(message));
|
|
37
50
|
},
|
|
38
51
|
warning: (message) => {
|
|
39
|
-
console.log(chalk.yellow(message));
|
|
52
|
+
console.log(chalk.default.yellow(message));
|
|
40
53
|
},
|
|
41
54
|
error: (message, error) => {
|
|
42
55
|
if (error) {
|
|
43
56
|
const errorMsg = error instanceof Error ? error.message : error;
|
|
44
|
-
console.error(chalk.red(message), errorMsg);
|
|
45
|
-
} else console.error(chalk.red(message));
|
|
57
|
+
console.error(chalk.default.red(message), errorMsg);
|
|
58
|
+
} else console.error(chalk.default.red(message));
|
|
46
59
|
},
|
|
47
60
|
debug: (message) => {
|
|
48
|
-
console.log(chalk.gray(message));
|
|
61
|
+
console.log(chalk.default.gray(message));
|
|
49
62
|
},
|
|
50
63
|
header: (message) => {
|
|
51
|
-
console.log(chalk.bold.cyan(message));
|
|
64
|
+
console.log(chalk.default.bold.cyan(message));
|
|
52
65
|
},
|
|
53
66
|
item: (message) => {
|
|
54
|
-
console.log(chalk.gray(` - ${message}`));
|
|
67
|
+
console.log(chalk.default.gray(` - ${message}`));
|
|
55
68
|
},
|
|
56
69
|
indent: (message) => {
|
|
57
|
-
console.log(chalk.gray(` ${message}`));
|
|
70
|
+
console.log(chalk.default.gray(` ${message}`));
|
|
58
71
|
},
|
|
59
72
|
highlight: (message) => {
|
|
60
|
-
console.log(chalk.bold.green(message));
|
|
73
|
+
console.log(chalk.default.bold.green(message));
|
|
61
74
|
},
|
|
62
75
|
newline: () => {
|
|
63
76
|
console.log();
|
|
@@ -138,7 +151,7 @@ const sections = {
|
|
|
138
151
|
|
|
139
152
|
//#endregion
|
|
140
153
|
//#region src/utils/git.ts
|
|
141
|
-
const execAsync = promisify(exec);
|
|
154
|
+
const execAsync = (0, node_util.promisify)(node_child_process.exec);
|
|
142
155
|
/**
|
|
143
156
|
* Parse GitHub URL to detect if it's a subdirectory
|
|
144
157
|
* Supports formats:
|
|
@@ -181,15 +194,15 @@ async function cloneSubdirectory(repoUrl, branch, subdirectory, targetFolder) {
|
|
|
181
194
|
await execAsync(`git init "${tempFolder}"`);
|
|
182
195
|
await execAsync(`git -C "${tempFolder}" remote add origin ${repoUrl}`);
|
|
183
196
|
await execAsync(`git -C "${tempFolder}" config core.sparseCheckout true`);
|
|
184
|
-
const sparseCheckoutFile =
|
|
185
|
-
await
|
|
197
|
+
const sparseCheckoutFile = node_path.default.join(tempFolder, ".git", "info", "sparse-checkout");
|
|
198
|
+
await fs_extra.writeFile(sparseCheckoutFile, `${subdirectory}\n`);
|
|
186
199
|
await execAsync(`git -C "${tempFolder}" pull --depth=1 origin ${branch}`);
|
|
187
|
-
const sourceDir =
|
|
188
|
-
if (!await
|
|
189
|
-
await
|
|
190
|
-
await
|
|
200
|
+
const sourceDir = node_path.default.join(tempFolder, subdirectory);
|
|
201
|
+
if (!await fs_extra.pathExists(sourceDir)) throw new Error(`Subdirectory '${subdirectory}' not found in repository at branch '${branch}'`);
|
|
202
|
+
await fs_extra.move(sourceDir, targetFolder);
|
|
203
|
+
await fs_extra.remove(tempFolder);
|
|
191
204
|
} catch (error) {
|
|
192
|
-
if (await
|
|
205
|
+
if (await fs_extra.pathExists(tempFolder)) await fs_extra.remove(tempFolder);
|
|
193
206
|
throw error;
|
|
194
207
|
}
|
|
195
208
|
}
|
|
@@ -198,14 +211,14 @@ async function cloneSubdirectory(repoUrl, branch, subdirectory, targetFolder) {
|
|
|
198
211
|
*/
|
|
199
212
|
async function cloneRepository(repoUrl, targetFolder) {
|
|
200
213
|
await execAsync(`git clone ${repoUrl} "${targetFolder}"`);
|
|
201
|
-
const gitFolder =
|
|
202
|
-
if (await
|
|
214
|
+
const gitFolder = node_path.default.join(targetFolder, ".git");
|
|
215
|
+
if (await fs_extra.pathExists(gitFolder)) await fs_extra.remove(gitFolder);
|
|
203
216
|
}
|
|
204
217
|
/**
|
|
205
218
|
* Fetch directory listing from GitHub API
|
|
206
219
|
*/
|
|
207
|
-
async function fetchGitHubDirectoryContents(owner, repo, path$
|
|
208
|
-
const url = `https://api.github.com/repos/${owner}/${repo}/contents/${path$
|
|
220
|
+
async function fetchGitHubDirectoryContents(owner, repo, path$6, branch = "main") {
|
|
221
|
+
const url = `https://api.github.com/repos/${owner}/${repo}/contents/${path$6}?ref=${branch}`;
|
|
209
222
|
const response = await fetch(url, { headers: {
|
|
210
223
|
Accept: "application/vnd.github.v3+json",
|
|
211
224
|
"User-Agent": "scaffold-mcp"
|
|
@@ -225,9 +238,9 @@ async function fetchGitHubDirectoryContents(owner, repo, path$2, branch = "main"
|
|
|
225
238
|
/**
|
|
226
239
|
* Add command - add a template to templates folder
|
|
227
240
|
*/
|
|
228
|
-
const addCommand = new Command("add").description("Add a template to templates folder").requiredOption("--name <name>", "Template name").requiredOption("--url <url>", "URL of the template repository to download").option("--path <path>", "Path to templates folder", "./templates").option("--type <type>", "Template type: boilerplate or scaffold", "boilerplate").action(async (options) => {
|
|
241
|
+
const addCommand = new commander.Command("add").description("Add a template to templates folder").requiredOption("--name <name>", "Template name").requiredOption("--url <url>", "URL of the template repository to download").option("--path <path>", "Path to templates folder", "./templates").option("--type <type>", "Template type: boilerplate or scaffold", "boilerplate").action(async (options) => {
|
|
229
242
|
try {
|
|
230
|
-
const templatesPath =
|
|
243
|
+
const templatesPath = node_path.default.resolve(options.path);
|
|
231
244
|
const templateType = options.type.toLowerCase();
|
|
232
245
|
const templateName = options.name;
|
|
233
246
|
const templateUrl = options.url;
|
|
@@ -235,13 +248,13 @@ const addCommand = new Command("add").description("Add a template to templates f
|
|
|
235
248
|
messages.error("Invalid template type. Use: boilerplate or scaffold");
|
|
236
249
|
process.exit(1);
|
|
237
250
|
}
|
|
238
|
-
const targetFolder =
|
|
239
|
-
if (await
|
|
251
|
+
const targetFolder = node_path.default.join(templatesPath, `${templateType}s`, templateName);
|
|
252
|
+
if (await fs_extra.pathExists(targetFolder)) {
|
|
240
253
|
messages.error(`Template '${templateName}' already exists at ${targetFolder}`);
|
|
241
254
|
process.exit(1);
|
|
242
255
|
}
|
|
243
256
|
logger.info(`${icons.download} Downloading template '${templateName}' from ${templateUrl}...`);
|
|
244
|
-
await
|
|
257
|
+
await fs_extra.ensureDir(node_path.default.dirname(targetFolder));
|
|
245
258
|
const parsedUrl = parseGitHubUrl(templateUrl);
|
|
246
259
|
try {
|
|
247
260
|
if (parsedUrl.isSubdirectory && parsedUrl.branch && parsedUrl.subdirectory) {
|
|
@@ -251,11 +264,11 @@ const addCommand = new Command("add").description("Add a template to templates f
|
|
|
251
264
|
messages.success(`Template '${templateName}' added successfully!`);
|
|
252
265
|
logger.header(`\n${icons.folder} Template location:`);
|
|
253
266
|
logger.indent(targetFolder);
|
|
254
|
-
const configFiles = [
|
|
267
|
+
const configFiles = [node_path.default.join(targetFolder, "boilerplate.yaml"), node_path.default.join(targetFolder, "scaffold.yaml")];
|
|
255
268
|
let hasConfig = false;
|
|
256
|
-
for (const configFile of configFiles) if (await
|
|
269
|
+
for (const configFile of configFiles) if (await fs_extra.pathExists(configFile)) {
|
|
257
270
|
logger.header(`\n${icons.config} Configuration file found:`);
|
|
258
|
-
logger.indent(
|
|
271
|
+
logger.indent(node_path.default.basename(configFile));
|
|
259
272
|
hasConfig = true;
|
|
260
273
|
break;
|
|
261
274
|
}
|
|
@@ -280,29 +293,29 @@ const addCommand = new Command("add").description("Add a template to templates f
|
|
|
280
293
|
//#endregion
|
|
281
294
|
//#region src/services/FileSystemService.ts
|
|
282
295
|
var FileSystemService = class {
|
|
283
|
-
async pathExists(path$
|
|
284
|
-
return
|
|
296
|
+
async pathExists(path$6) {
|
|
297
|
+
return fs_extra.default.pathExists(path$6);
|
|
285
298
|
}
|
|
286
|
-
async readFile(path$
|
|
287
|
-
return
|
|
299
|
+
async readFile(path$6, encoding = "utf8") {
|
|
300
|
+
return fs_extra.default.readFile(path$6, encoding);
|
|
288
301
|
}
|
|
289
|
-
async readJson(path$
|
|
290
|
-
return
|
|
302
|
+
async readJson(path$6) {
|
|
303
|
+
return fs_extra.default.readJson(path$6);
|
|
291
304
|
}
|
|
292
|
-
async writeFile(path$
|
|
293
|
-
return
|
|
305
|
+
async writeFile(path$6, content, encoding = "utf8") {
|
|
306
|
+
return fs_extra.default.writeFile(path$6, content, encoding);
|
|
294
307
|
}
|
|
295
|
-
async ensureDir(path$
|
|
296
|
-
return
|
|
308
|
+
async ensureDir(path$6) {
|
|
309
|
+
return fs_extra.default.ensureDir(path$6);
|
|
297
310
|
}
|
|
298
311
|
async copy(src, dest) {
|
|
299
|
-
return
|
|
312
|
+
return fs_extra.default.copy(src, dest);
|
|
300
313
|
}
|
|
301
|
-
async readdir(path$
|
|
302
|
-
return
|
|
314
|
+
async readdir(path$6) {
|
|
315
|
+
return fs_extra.default.readdir(path$6);
|
|
303
316
|
}
|
|
304
|
-
async stat(path$
|
|
305
|
-
return
|
|
317
|
+
async stat(path$6) {
|
|
318
|
+
return fs_extra.default.stat(path$6);
|
|
306
319
|
}
|
|
307
320
|
};
|
|
308
321
|
|
|
@@ -314,11 +327,11 @@ var BoilerplateService = class {
|
|
|
314
327
|
scaffoldService;
|
|
315
328
|
constructor(templatesPath) {
|
|
316
329
|
this.templatesPath = templatesPath;
|
|
317
|
-
this.templateService = new TemplateService();
|
|
330
|
+
this.templateService = new require_TemplateService.TemplateService();
|
|
318
331
|
const fileSystemService = new FileSystemService();
|
|
319
|
-
const scaffoldConfigLoader = new ScaffoldConfigLoader(fileSystemService, this.templateService);
|
|
320
|
-
const variableReplacementService = new VariableReplacementService(fileSystemService, this.templateService);
|
|
321
|
-
this.scaffoldService = new ScaffoldService(fileSystemService, scaffoldConfigLoader, variableReplacementService, templatesPath);
|
|
332
|
+
const scaffoldConfigLoader = new require_ScaffoldConfigLoader.ScaffoldConfigLoader(fileSystemService, this.templateService);
|
|
333
|
+
const variableReplacementService = new require_VariableReplacementService.VariableReplacementService(fileSystemService, this.templateService);
|
|
334
|
+
this.scaffoldService = new require_ScaffoldService.ScaffoldService(fileSystemService, scaffoldConfigLoader, variableReplacementService, templatesPath);
|
|
322
335
|
}
|
|
323
336
|
/**
|
|
324
337
|
* Scans all scaffold.yaml files and returns available boilerplates
|
|
@@ -327,10 +340,10 @@ var BoilerplateService = class {
|
|
|
327
340
|
const boilerplates = [];
|
|
328
341
|
const templateDirs = await this.discoverTemplateDirectories();
|
|
329
342
|
for (const templatePath of templateDirs) {
|
|
330
|
-
const scaffoldYamlPath =
|
|
331
|
-
if (
|
|
332
|
-
const scaffoldContent =
|
|
333
|
-
const scaffoldConfig =
|
|
343
|
+
const scaffoldYamlPath = node_path.join(this.templatesPath, templatePath, "scaffold.yaml");
|
|
344
|
+
if (fs_extra.existsSync(scaffoldYamlPath)) try {
|
|
345
|
+
const scaffoldContent = fs_extra.readFileSync(scaffoldYamlPath, "utf8");
|
|
346
|
+
const scaffoldConfig = js_yaml.load(scaffoldContent);
|
|
334
347
|
if (scaffoldConfig.boilerplate) for (const boilerplate of scaffoldConfig.boilerplate) {
|
|
335
348
|
if (!boilerplate.targetFolder) {
|
|
336
349
|
console.warn(`Skipping boilerplate '${boilerplate.name}' in ${templatePath}: targetFolder is required in scaffold.yaml`);
|
|
@@ -359,15 +372,15 @@ var BoilerplateService = class {
|
|
|
359
372
|
async discoverTemplateDirectories() {
|
|
360
373
|
const templateDirs = [];
|
|
361
374
|
const findTemplates = (dir, baseDir = "") => {
|
|
362
|
-
if (!
|
|
363
|
-
const items =
|
|
375
|
+
if (!fs_extra.existsSync(dir)) return;
|
|
376
|
+
const items = fs_extra.readdirSync(dir);
|
|
364
377
|
const hasPackageJson = items.includes("package.json") || items.includes("package.json.liquid");
|
|
365
378
|
const hasScaffoldYaml = items.includes("scaffold.yaml");
|
|
366
379
|
if (hasPackageJson && hasScaffoldYaml) templateDirs.push(baseDir);
|
|
367
380
|
for (const item of items) {
|
|
368
|
-
const itemPath =
|
|
369
|
-
if (
|
|
370
|
-
const newBaseDir = baseDir ?
|
|
381
|
+
const itemPath = node_path.join(dir, item);
|
|
382
|
+
if (fs_extra.statSync(itemPath).isDirectory() && !item.startsWith(".") && item !== "node_modules") {
|
|
383
|
+
const newBaseDir = baseDir ? node_path.join(baseDir, item) : item;
|
|
371
384
|
findTemplates(itemPath, newBaseDir);
|
|
372
385
|
}
|
|
373
386
|
}
|
|
@@ -452,13 +465,13 @@ var BoilerplateService = class {
|
|
|
452
465
|
validateBoilerplateVariables(boilerplate, variables) {
|
|
453
466
|
const errors = [];
|
|
454
467
|
try {
|
|
455
|
-
jsonSchemaToZod(boilerplate.variables_schema).parse(variables);
|
|
468
|
+
(0, __composio_json_schema_to_zod.jsonSchemaToZod)(boilerplate.variables_schema).parse(variables);
|
|
456
469
|
return {
|
|
457
470
|
isValid: true,
|
|
458
471
|
errors: []
|
|
459
472
|
};
|
|
460
473
|
} catch (error) {
|
|
461
|
-
if (error instanceof z.ZodError) {
|
|
474
|
+
if (error instanceof zod.z.ZodError) {
|
|
462
475
|
const zodErrors = error.errors.map((err) => {
|
|
463
476
|
return `${err.path.length > 0 ? err.path.join(".") : "root"}: ${err.message}`;
|
|
464
477
|
});
|
|
@@ -475,11 +488,11 @@ var BoilerplateService = class {
|
|
|
475
488
|
* If project.json exists, updates it; otherwise creates a new one
|
|
476
489
|
*/
|
|
477
490
|
ensureProjectJsonSourceTemplate(targetFolder, projectName, sourceTemplate) {
|
|
478
|
-
const projectJsonPath =
|
|
491
|
+
const projectJsonPath = node_path.join(targetFolder, projectName, "project.json");
|
|
479
492
|
try {
|
|
480
493
|
let projectJson;
|
|
481
|
-
if (
|
|
482
|
-
const content =
|
|
494
|
+
if (fs_extra.existsSync(projectJsonPath)) {
|
|
495
|
+
const content = fs_extra.readFileSync(projectJsonPath, "utf8");
|
|
483
496
|
projectJson = JSON.parse(content);
|
|
484
497
|
} else projectJson = {
|
|
485
498
|
name: projectName,
|
|
@@ -488,7 +501,7 @@ var BoilerplateService = class {
|
|
|
488
501
|
projectType: "application"
|
|
489
502
|
};
|
|
490
503
|
projectJson.sourceTemplate = sourceTemplate;
|
|
491
|
-
|
|
504
|
+
fs_extra.writeFileSync(projectJsonPath, `${JSON.stringify(projectJson, null, 2)}\n`, "utf8");
|
|
492
505
|
} catch (error) {
|
|
493
506
|
console.warn(`Failed to update project.json with sourceTemplate: ${error}`);
|
|
494
507
|
}
|
|
@@ -497,14 +510,14 @@ var BoilerplateService = class {
|
|
|
497
510
|
|
|
498
511
|
//#endregion
|
|
499
512
|
//#region src/cli/boilerplate.ts
|
|
500
|
-
const templatesDir$1 = TemplatesManager.findTemplatesPathSync();
|
|
501
513
|
/**
|
|
502
514
|
* Boilerplate CLI command
|
|
503
515
|
*/
|
|
504
|
-
const boilerplateCommand = new Command("boilerplate").description("Manage boilerplate templates");
|
|
516
|
+
const boilerplateCommand = new commander.Command("boilerplate").description("Manage boilerplate templates");
|
|
505
517
|
boilerplateCommand.command("list").description("List all available boilerplate templates").action(async () => {
|
|
506
518
|
try {
|
|
507
|
-
const
|
|
519
|
+
const templatesDir = await require_ScaffoldService.TemplatesManager.findTemplatesPath();
|
|
520
|
+
const { boilerplates } = await new BoilerplateService(templatesDir).listBoilerplates();
|
|
508
521
|
if (boilerplates.length === 0) {
|
|
509
522
|
messages.warning("No boilerplate templates found.");
|
|
510
523
|
return;
|
|
@@ -525,7 +538,8 @@ boilerplateCommand.command("list").description("List all available boilerplate t
|
|
|
525
538
|
});
|
|
526
539
|
boilerplateCommand.command("create <boilerplateName>").description("Create a new project from a boilerplate template").option("-v, --vars <json>", "JSON string containing variables for the boilerplate").option("--verbose", "Enable verbose logging").action(async (boilerplateName, options) => {
|
|
527
540
|
try {
|
|
528
|
-
const
|
|
541
|
+
const templatesDir = await require_ScaffoldService.TemplatesManager.findTemplatesPath();
|
|
542
|
+
const boilerplateService = new BoilerplateService(templatesDir);
|
|
529
543
|
let variables = {};
|
|
530
544
|
if (options.vars) try {
|
|
531
545
|
variables = JSON.parse(options.vars);
|
|
@@ -584,7 +598,8 @@ boilerplateCommand.command("create <boilerplateName>").description("Create a new
|
|
|
584
598
|
});
|
|
585
599
|
boilerplateCommand.command("info <boilerplateName>").description("Show detailed information about a boilerplate template").action(async (boilerplateName) => {
|
|
586
600
|
try {
|
|
587
|
-
const
|
|
601
|
+
const templatesDir = await require_ScaffoldService.TemplatesManager.findTemplatesPath();
|
|
602
|
+
const bp = await new BoilerplateService(templatesDir).getBoilerplate(boilerplateName);
|
|
588
603
|
if (!bp) {
|
|
589
604
|
messages.error(`Boilerplate '${boilerplateName}' not found.`);
|
|
590
605
|
process.exit(1);
|
|
@@ -608,13 +623,13 @@ boilerplateCommand.command("info <boilerplateName>").description("Show detailed
|
|
|
608
623
|
* Find the workspace root by searching upwards for .git folder
|
|
609
624
|
*/
|
|
610
625
|
async function findWorkspaceRoot(startPath = process.cwd()) {
|
|
611
|
-
let currentPath =
|
|
612
|
-
const rootPath =
|
|
626
|
+
let currentPath = node_path.default.resolve(startPath);
|
|
627
|
+
const rootPath = node_path.default.parse(currentPath).root;
|
|
613
628
|
while (true) {
|
|
614
|
-
const gitPath =
|
|
615
|
-
if (await
|
|
629
|
+
const gitPath = node_path.default.join(currentPath, ".git");
|
|
630
|
+
if (await fs_extra.pathExists(gitPath)) return currentPath;
|
|
616
631
|
if (currentPath === rootPath) return process.cwd();
|
|
617
|
-
currentPath =
|
|
632
|
+
currentPath = node_path.default.dirname(currentPath);
|
|
618
633
|
}
|
|
619
634
|
}
|
|
620
635
|
const DEFAULT_TEMPLATE_REPO = {
|
|
@@ -636,8 +651,8 @@ async function downloadTemplates(templatesPath) {
|
|
|
636
651
|
}
|
|
637
652
|
logger.info(`${icons.folder} Found ${templateDirs.length} template(s)`);
|
|
638
653
|
for (const template of templateDirs) {
|
|
639
|
-
const targetFolder =
|
|
640
|
-
if (await
|
|
654
|
+
const targetFolder = node_path.default.join(templatesPath, template.name);
|
|
655
|
+
if (await fs_extra.pathExists(targetFolder)) {
|
|
641
656
|
logger.info(`${icons.skip} Skipping ${template.name} (already exists)`);
|
|
642
657
|
continue;
|
|
643
658
|
}
|
|
@@ -654,13 +669,13 @@ async function downloadTemplates(templatesPath) {
|
|
|
654
669
|
/**
|
|
655
670
|
* Init command - initialize templates folder
|
|
656
671
|
*/
|
|
657
|
-
const initCommand = new Command("init").description("Initialize templates folder structure at workspace root").option("--no-download", "Skip downloading templates from repository").option("--path <path>", "Custom path for templates folder (relative to workspace root)").action(async (options) => {
|
|
672
|
+
const initCommand = new commander.Command("init").description("Initialize templates folder structure at workspace root").option("--no-download", "Skip downloading templates from repository").option("--path <path>", "Custom path for templates folder (relative to workspace root)").action(async (options) => {
|
|
658
673
|
try {
|
|
659
674
|
const workspaceRoot = await findWorkspaceRoot();
|
|
660
|
-
const templatesPath = options.path ?
|
|
675
|
+
const templatesPath = options.path ? node_path.default.join(workspaceRoot, options.path) : node_path.default.join(workspaceRoot, "templates");
|
|
661
676
|
logger.info(`${icons.rocket} Initializing templates folder at: ${templatesPath}`);
|
|
662
|
-
await
|
|
663
|
-
await
|
|
677
|
+
await fs_extra.ensureDir(templatesPath);
|
|
678
|
+
await fs_extra.writeFile(node_path.default.join(templatesPath, "README.md"), `# Templates
|
|
664
679
|
|
|
665
680
|
This folder contains boilerplate templates and scaffolding methods for your projects.
|
|
666
681
|
|
|
@@ -1151,7 +1166,7 @@ var BoilerplateGeneratorService = class {
|
|
|
1151
1166
|
* Custom YAML dumper that forces literal block style (|) for description and instruction fields
|
|
1152
1167
|
*/
|
|
1153
1168
|
dumpYamlWithLiteralBlocks(config) {
|
|
1154
|
-
const LiteralBlockType = new
|
|
1169
|
+
const LiteralBlockType = new js_yaml.Type("tag:yaml.org,2002:str", {
|
|
1155
1170
|
kind: "scalar",
|
|
1156
1171
|
construct: (data) => data,
|
|
1157
1172
|
represent: (data) => {
|
|
@@ -1159,9 +1174,9 @@ var BoilerplateGeneratorService = class {
|
|
|
1159
1174
|
},
|
|
1160
1175
|
defaultStyle: "|"
|
|
1161
1176
|
});
|
|
1162
|
-
const LITERAL_SCHEMA =
|
|
1177
|
+
const LITERAL_SCHEMA = js_yaml.DEFAULT_SCHEMA.extend([LiteralBlockType]);
|
|
1163
1178
|
const processedConfig = this.processConfigForLiteralBlocks(config);
|
|
1164
|
-
return
|
|
1179
|
+
return js_yaml.dump(processedConfig, {
|
|
1165
1180
|
schema: LITERAL_SCHEMA,
|
|
1166
1181
|
indent: 2,
|
|
1167
1182
|
lineWidth: -1,
|
|
@@ -1204,13 +1219,13 @@ var BoilerplateGeneratorService = class {
|
|
|
1204
1219
|
*/
|
|
1205
1220
|
async generateBoilerplate(options) {
|
|
1206
1221
|
const { templateName, boilerplateName, description, instruction, targetFolder, variables, includes = [] } = options;
|
|
1207
|
-
const templatePath =
|
|
1208
|
-
await
|
|
1209
|
-
const scaffoldYamlPath =
|
|
1222
|
+
const templatePath = node_path.join(this.templatesPath, templateName);
|
|
1223
|
+
await fs_extra.ensureDir(templatePath);
|
|
1224
|
+
const scaffoldYamlPath = node_path.join(templatePath, "scaffold.yaml");
|
|
1210
1225
|
let scaffoldConfig = {};
|
|
1211
|
-
if (await
|
|
1212
|
-
const yamlContent$1 = await
|
|
1213
|
-
scaffoldConfig =
|
|
1226
|
+
if (await fs_extra.pathExists(scaffoldYamlPath)) {
|
|
1227
|
+
const yamlContent$1 = await fs_extra.readFile(scaffoldYamlPath, "utf-8");
|
|
1228
|
+
scaffoldConfig = js_yaml.load(yamlContent$1);
|
|
1214
1229
|
}
|
|
1215
1230
|
if (!scaffoldConfig.boilerplate) scaffoldConfig.boilerplate = [];
|
|
1216
1231
|
if (scaffoldConfig.boilerplate.findIndex((b) => b.name === boilerplateName) !== -1) return {
|
|
@@ -1241,7 +1256,7 @@ var BoilerplateGeneratorService = class {
|
|
|
1241
1256
|
if (instruction) boilerplateDefinition.instruction = instruction;
|
|
1242
1257
|
scaffoldConfig.boilerplate.push(boilerplateDefinition);
|
|
1243
1258
|
const yamlContent = this.dumpYamlWithLiteralBlocks(scaffoldConfig);
|
|
1244
|
-
await
|
|
1259
|
+
await fs_extra.writeFile(scaffoldYamlPath, yamlContent, "utf-8");
|
|
1245
1260
|
return {
|
|
1246
1261
|
success: true,
|
|
1247
1262
|
message: `Boilerplate '${boilerplateName}' added to ${scaffoldYamlPath}`,
|
|
@@ -1253,43 +1268,43 @@ var BoilerplateGeneratorService = class {
|
|
|
1253
1268
|
* List all templates (directories in templates folder)
|
|
1254
1269
|
*/
|
|
1255
1270
|
async listTemplates() {
|
|
1256
|
-
return (await
|
|
1271
|
+
return (await fs_extra.readdir(this.templatesPath, { withFileTypes: true })).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
|
|
1257
1272
|
}
|
|
1258
1273
|
/**
|
|
1259
1274
|
* Check if a template exists
|
|
1260
1275
|
*/
|
|
1261
1276
|
async templateExists(templateName) {
|
|
1262
|
-
const templatePath =
|
|
1263
|
-
return
|
|
1277
|
+
const templatePath = node_path.join(this.templatesPath, templateName);
|
|
1278
|
+
return fs_extra.pathExists(templatePath);
|
|
1264
1279
|
}
|
|
1265
1280
|
/**
|
|
1266
1281
|
* Create or update a template file for a boilerplate
|
|
1267
1282
|
*/
|
|
1268
1283
|
async createTemplateFile(options) {
|
|
1269
1284
|
const { templateName, filePath, content, sourceFile, header } = options;
|
|
1270
|
-
const templatePath =
|
|
1271
|
-
if (!await
|
|
1285
|
+
const templatePath = node_path.join(this.templatesPath, templateName);
|
|
1286
|
+
if (!await fs_extra.pathExists(templatePath)) return {
|
|
1272
1287
|
success: false,
|
|
1273
1288
|
message: `Template directory '${templateName}' does not exist at ${templatePath}`
|
|
1274
1289
|
};
|
|
1275
1290
|
let fileContent = content || "";
|
|
1276
1291
|
if (sourceFile) {
|
|
1277
|
-
if (!await
|
|
1292
|
+
if (!await fs_extra.pathExists(sourceFile)) return {
|
|
1278
1293
|
success: false,
|
|
1279
1294
|
message: `Source file '${sourceFile}' does not exist`
|
|
1280
1295
|
};
|
|
1281
|
-
fileContent = await
|
|
1296
|
+
fileContent = await fs_extra.readFile(sourceFile, "utf-8");
|
|
1282
1297
|
}
|
|
1283
1298
|
if (!fileContent && !sourceFile) return {
|
|
1284
1299
|
success: false,
|
|
1285
1300
|
message: "Either content or sourceFile must be provided"
|
|
1286
1301
|
};
|
|
1287
1302
|
const templateFilePath = filePath.endsWith(".liquid") ? filePath : `${filePath}.liquid`;
|
|
1288
|
-
const fullPath =
|
|
1289
|
-
await
|
|
1303
|
+
const fullPath = node_path.join(templatePath, templateFilePath);
|
|
1304
|
+
await fs_extra.ensureDir(node_path.dirname(fullPath));
|
|
1290
1305
|
let finalContent = fileContent;
|
|
1291
1306
|
if (header) finalContent = `${header}\n\n${fileContent}`;
|
|
1292
|
-
await
|
|
1307
|
+
await fs_extra.writeFile(fullPath, finalContent, "utf-8");
|
|
1293
1308
|
return {
|
|
1294
1309
|
success: true,
|
|
1295
1310
|
message: "Template file created successfully",
|
|
@@ -1651,7 +1666,7 @@ var ScaffoldGeneratorService = class {
|
|
|
1651
1666
|
* Custom YAML dumper that forces literal block style (|) for description and instruction fields
|
|
1652
1667
|
*/
|
|
1653
1668
|
dumpYamlWithLiteralBlocks(config) {
|
|
1654
|
-
const LiteralBlockType = new
|
|
1669
|
+
const LiteralBlockType = new js_yaml.Type("tag:yaml.org,2002:str", {
|
|
1655
1670
|
kind: "scalar",
|
|
1656
1671
|
construct: (data) => data,
|
|
1657
1672
|
represent: (data) => {
|
|
@@ -1659,9 +1674,9 @@ var ScaffoldGeneratorService = class {
|
|
|
1659
1674
|
},
|
|
1660
1675
|
defaultStyle: "|"
|
|
1661
1676
|
});
|
|
1662
|
-
const LITERAL_SCHEMA =
|
|
1677
|
+
const LITERAL_SCHEMA = js_yaml.DEFAULT_SCHEMA.extend([LiteralBlockType]);
|
|
1663
1678
|
const processedConfig = this.processConfigForLiteralBlocks(config);
|
|
1664
|
-
return
|
|
1679
|
+
return js_yaml.dump(processedConfig, {
|
|
1665
1680
|
schema: LITERAL_SCHEMA,
|
|
1666
1681
|
indent: 2,
|
|
1667
1682
|
lineWidth: -1,
|
|
@@ -1704,13 +1719,13 @@ var ScaffoldGeneratorService = class {
|
|
|
1704
1719
|
*/
|
|
1705
1720
|
async generateFeatureScaffold(options) {
|
|
1706
1721
|
const { templateName, featureName, description, instruction, variables, includes = [], patterns = [] } = options;
|
|
1707
|
-
const templatePath =
|
|
1708
|
-
await
|
|
1709
|
-
const scaffoldYamlPath =
|
|
1722
|
+
const templatePath = node_path.join(this.templatesPath, templateName);
|
|
1723
|
+
await fs_extra.ensureDir(templatePath);
|
|
1724
|
+
const scaffoldYamlPath = node_path.join(templatePath, "scaffold.yaml");
|
|
1710
1725
|
let scaffoldConfig = {};
|
|
1711
|
-
if (await
|
|
1712
|
-
const yamlContent$1 = await
|
|
1713
|
-
scaffoldConfig =
|
|
1726
|
+
if (await fs_extra.pathExists(scaffoldYamlPath)) {
|
|
1727
|
+
const yamlContent$1 = await fs_extra.readFile(scaffoldYamlPath, "utf-8");
|
|
1728
|
+
scaffoldConfig = js_yaml.load(yamlContent$1);
|
|
1714
1729
|
}
|
|
1715
1730
|
if (!scaffoldConfig.features) scaffoldConfig.features = [];
|
|
1716
1731
|
if (scaffoldConfig.features.findIndex((f) => f.name === featureName) !== -1) return {
|
|
@@ -1741,7 +1756,7 @@ var ScaffoldGeneratorService = class {
|
|
|
1741
1756
|
if (patterns && patterns.length > 0) featureDefinition.patterns = patterns;
|
|
1742
1757
|
scaffoldConfig.features.push(featureDefinition);
|
|
1743
1758
|
const yamlContent = this.dumpYamlWithLiteralBlocks(scaffoldConfig);
|
|
1744
|
-
await
|
|
1759
|
+
await fs_extra.writeFile(scaffoldYamlPath, yamlContent, "utf-8");
|
|
1745
1760
|
return {
|
|
1746
1761
|
success: true,
|
|
1747
1762
|
message: `Feature '${featureName}' added to ${scaffoldYamlPath}`,
|
|
@@ -1753,14 +1768,14 @@ var ScaffoldGeneratorService = class {
|
|
|
1753
1768
|
* List all templates (directories in templates folder)
|
|
1754
1769
|
*/
|
|
1755
1770
|
async listTemplates() {
|
|
1756
|
-
return (await
|
|
1771
|
+
return (await fs_extra.readdir(this.templatesPath, { withFileTypes: true })).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
|
|
1757
1772
|
}
|
|
1758
1773
|
/**
|
|
1759
1774
|
* Check if a template exists
|
|
1760
1775
|
*/
|
|
1761
1776
|
async templateExists(templateName) {
|
|
1762
|
-
const templatePath =
|
|
1763
|
-
return
|
|
1777
|
+
const templatePath = node_path.join(this.templatesPath, templateName);
|
|
1778
|
+
return fs_extra.pathExists(templatePath);
|
|
1764
1779
|
}
|
|
1765
1780
|
};
|
|
1766
1781
|
|
|
@@ -2015,22 +2030,22 @@ var ScaffoldingMethodsService = class {
|
|
|
2015
2030
|
constructor(fileSystem, templatesRootPath) {
|
|
2016
2031
|
this.fileSystem = fileSystem;
|
|
2017
2032
|
this.templatesRootPath = templatesRootPath;
|
|
2018
|
-
this.templateService = new TemplateService();
|
|
2033
|
+
this.templateService = new require_TemplateService.TemplateService();
|
|
2019
2034
|
}
|
|
2020
2035
|
async listScaffoldingMethods(projectPath) {
|
|
2021
|
-
const absoluteProjectPath =
|
|
2022
|
-
const projectJsonPath =
|
|
2036
|
+
const absoluteProjectPath = node_path.default.resolve(projectPath);
|
|
2037
|
+
const projectJsonPath = node_path.default.join(absoluteProjectPath, "project.json");
|
|
2023
2038
|
if (!await this.fileSystem.pathExists(projectJsonPath)) throw new Error(`project.json not found at ${projectJsonPath}`);
|
|
2024
2039
|
const projectConfig = await this.fileSystem.readJson(projectJsonPath);
|
|
2025
2040
|
if (!projectConfig.sourceTemplate) throw new Error(`sourceTemplate not specified in project.json at ${projectJsonPath}`);
|
|
2026
2041
|
const sourceTemplate = projectConfig.sourceTemplate;
|
|
2027
2042
|
const templatePath = await this.findTemplatePath(sourceTemplate);
|
|
2028
2043
|
if (!templatePath) throw new Error(`Template not found for sourceTemplate: ${sourceTemplate}`);
|
|
2029
|
-
const fullTemplatePath =
|
|
2030
|
-
const scaffoldYamlPath =
|
|
2044
|
+
const fullTemplatePath = node_path.default.join(this.templatesRootPath, templatePath);
|
|
2045
|
+
const scaffoldYamlPath = node_path.default.join(fullTemplatePath, "scaffold.yaml");
|
|
2031
2046
|
if (!await this.fileSystem.pathExists(scaffoldYamlPath)) throw new Error(`scaffold.yaml not found at ${scaffoldYamlPath}`);
|
|
2032
2047
|
const scaffoldContent = await this.fileSystem.readFile(scaffoldYamlPath, "utf8");
|
|
2033
|
-
const architectConfig =
|
|
2048
|
+
const architectConfig = js_yaml.default.load(scaffoldContent);
|
|
2034
2049
|
const methods = [];
|
|
2035
2050
|
if (architectConfig.features && Array.isArray(architectConfig.features)) architectConfig.features.forEach((feature) => {
|
|
2036
2051
|
if (feature.name) methods.push({
|
|
@@ -2077,11 +2092,11 @@ var ScaffoldingMethodsService = class {
|
|
|
2077
2092
|
const templateDirs = await this.discoverTemplateDirs();
|
|
2078
2093
|
if (templateDirs.includes(sourceTemplate)) return sourceTemplate;
|
|
2079
2094
|
for (const templateDir of templateDirs) {
|
|
2080
|
-
const templatePath =
|
|
2081
|
-
const scaffoldYamlPath =
|
|
2095
|
+
const templatePath = node_path.default.join(this.templatesRootPath, templateDir);
|
|
2096
|
+
const scaffoldYamlPath = node_path.default.join(templatePath, "scaffold.yaml");
|
|
2082
2097
|
if (await this.fileSystem.pathExists(scaffoldYamlPath)) try {
|
|
2083
2098
|
const scaffoldContent = await this.fileSystem.readFile(scaffoldYamlPath, "utf8");
|
|
2084
|
-
const architectConfig =
|
|
2099
|
+
const architectConfig = js_yaml.default.load(scaffoldContent);
|
|
2085
2100
|
if (architectConfig.boilerplate && Array.isArray(architectConfig.boilerplate)) {
|
|
2086
2101
|
for (const boilerplate of architectConfig.boilerplate) if (boilerplate.name?.includes(sourceTemplate)) return templateDir;
|
|
2087
2102
|
}
|
|
@@ -2100,9 +2115,9 @@ var ScaffoldingMethodsService = class {
|
|
|
2100
2115
|
try {
|
|
2101
2116
|
const items = await this.fileSystem.readdir(this.templatesRootPath);
|
|
2102
2117
|
for (const item of items) {
|
|
2103
|
-
const itemPath =
|
|
2118
|
+
const itemPath = node_path.default.join(this.templatesRootPath, item);
|
|
2104
2119
|
if (!(await this.fileSystem.stat(itemPath)).isDirectory()) continue;
|
|
2105
|
-
const scaffoldYamlPath =
|
|
2120
|
+
const scaffoldYamlPath = node_path.default.join(itemPath, "scaffold.yaml");
|
|
2106
2121
|
if (await this.fileSystem.pathExists(scaffoldYamlPath)) {
|
|
2107
2122
|
templateDirs.push(item);
|
|
2108
2123
|
continue;
|
|
@@ -2110,11 +2125,11 @@ var ScaffoldingMethodsService = class {
|
|
|
2110
2125
|
try {
|
|
2111
2126
|
const subItems = await this.fileSystem.readdir(itemPath);
|
|
2112
2127
|
for (const subItem of subItems) {
|
|
2113
|
-
const subItemPath =
|
|
2128
|
+
const subItemPath = node_path.default.join(itemPath, subItem);
|
|
2114
2129
|
if (!(await this.fileSystem.stat(subItemPath)).isDirectory()) continue;
|
|
2115
|
-
const subScaffoldYamlPath =
|
|
2130
|
+
const subScaffoldYamlPath = node_path.default.join(subItemPath, "scaffold.yaml");
|
|
2116
2131
|
if (await this.fileSystem.pathExists(subScaffoldYamlPath)) {
|
|
2117
|
-
const relativePath =
|
|
2132
|
+
const relativePath = node_path.default.join(item, subItem);
|
|
2118
2133
|
templateDirs.push(relativePath);
|
|
2119
2134
|
}
|
|
2120
2135
|
}
|
|
@@ -2135,16 +2150,16 @@ var ScaffoldingMethodsService = class {
|
|
|
2135
2150
|
const availableMethods = scaffoldingMethods.methods.map((m) => m.name).join(", ");
|
|
2136
2151
|
throw new Error(`Scaffold method '${scaffold_feature_name}' not found. Available methods: ${availableMethods}`);
|
|
2137
2152
|
}
|
|
2138
|
-
const ScaffoldService$1 = (await
|
|
2139
|
-
const ScaffoldConfigLoader$1 = (await
|
|
2140
|
-
const VariableReplacementService$1 = (await
|
|
2141
|
-
const TemplateService$1 = (await
|
|
2153
|
+
const ScaffoldService$1 = (await Promise.resolve().then(() => require("./ScaffoldService-BXKXXg4M.js"))).ScaffoldService;
|
|
2154
|
+
const ScaffoldConfigLoader$1 = (await Promise.resolve().then(() => require("./ScaffoldConfigLoader-CnVkzUxL.js"))).ScaffoldConfigLoader;
|
|
2155
|
+
const VariableReplacementService$1 = (await Promise.resolve().then(() => require("./VariableReplacementService-_GgLG4Im.js"))).VariableReplacementService;
|
|
2156
|
+
const TemplateService$1 = (await Promise.resolve().then(() => require("./TemplateService-B0ns4TR_.js"))).TemplateService;
|
|
2142
2157
|
const templateService = new TemplateService$1();
|
|
2143
2158
|
const scaffoldConfigLoader = new ScaffoldConfigLoader$1(this.fileSystem, templateService);
|
|
2144
2159
|
const variableReplacer = new VariableReplacementService$1(this.fileSystem, templateService);
|
|
2145
2160
|
const scaffoldService = new ScaffoldService$1(this.fileSystem, scaffoldConfigLoader, variableReplacer, this.templatesRootPath);
|
|
2146
|
-
const absoluteProjectPath =
|
|
2147
|
-
const projectName =
|
|
2161
|
+
const absoluteProjectPath = node_path.default.resolve(projectPath);
|
|
2162
|
+
const projectName = node_path.default.basename(absoluteProjectPath);
|
|
2148
2163
|
const result = await scaffoldService.useFeature({
|
|
2149
2164
|
projectPath: absoluteProjectPath,
|
|
2150
2165
|
templateFolder: scaffoldingMethods.templatePath,
|
|
@@ -2446,8 +2461,8 @@ Parameters:
|
|
|
2446
2461
|
const { file_path, content } = args;
|
|
2447
2462
|
if (!file_path) throw new Error("Missing required parameter: file_path");
|
|
2448
2463
|
if (content === void 0 || content === null) throw new Error("Missing required parameter: content");
|
|
2449
|
-
const resolvedPath =
|
|
2450
|
-
const dirPath =
|
|
2464
|
+
const resolvedPath = node_path.default.isAbsolute(file_path) ? file_path : node_path.default.resolve(process.cwd(), file_path);
|
|
2465
|
+
const dirPath = node_path.default.dirname(resolvedPath);
|
|
2451
2466
|
await this.fileSystemService.ensureDir(dirPath);
|
|
2452
2467
|
await this.fileSystemService.writeFile(resolvedPath, content);
|
|
2453
2468
|
return { content: [{
|
|
@@ -2470,7 +2485,7 @@ Parameters:
|
|
|
2470
2485
|
//#region src/server/index.ts
|
|
2471
2486
|
function createServer(options = {}) {
|
|
2472
2487
|
const { adminEnabled = false } = options;
|
|
2473
|
-
const templatesPath = TemplatesManager.findTemplatesPathSync();
|
|
2488
|
+
const templatesPath = require_ScaffoldService.TemplatesManager.findTemplatesPathSync();
|
|
2474
2489
|
const listBoilerplatesTool = new ListBoilerplatesTool(templatesPath);
|
|
2475
2490
|
const useBoilerplateTool = new UseBoilerplateTool(templatesPath);
|
|
2476
2491
|
const listScaffoldingMethodsTool = new ListScaffoldingMethodsTool(templatesPath);
|
|
@@ -2483,7 +2498,7 @@ function createServer(options = {}) {
|
|
|
2483
2498
|
const generateFeatureScaffoldPrompt = adminEnabled ? new GenerateFeatureScaffoldPrompt() : null;
|
|
2484
2499
|
const scaffoldApplicationPrompt = new ScaffoldApplicationPrompt();
|
|
2485
2500
|
const scaffoldFeaturePrompt = new ScaffoldFeaturePrompt();
|
|
2486
|
-
const server = new Server({
|
|
2501
|
+
const server = new __modelcontextprotocol_sdk_server_index_js.Server({
|
|
2487
2502
|
name: "scaffold-mcp",
|
|
2488
2503
|
version: "1.0.0"
|
|
2489
2504
|
}, {
|
|
@@ -2547,7 +2562,7 @@ Example workflow for feature:
|
|
|
2547
2562
|
prompts: {}
|
|
2548
2563
|
}
|
|
2549
2564
|
});
|
|
2550
|
-
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
2565
|
+
server.setRequestHandler(__modelcontextprotocol_sdk_types_js.ListToolsRequestSchema, async () => {
|
|
2551
2566
|
const listBoilerplateTool = listBoilerplatesTool.getDefinition();
|
|
2552
2567
|
const useBoilerplateToolDef = useBoilerplateTool.getDefinition();
|
|
2553
2568
|
const listScaffoldingMethodsToolDef = listScaffoldingMethodsTool.getDefinition();
|
|
@@ -2567,7 +2582,7 @@ Example workflow for feature:
|
|
|
2567
2582
|
}
|
|
2568
2583
|
return { tools };
|
|
2569
2584
|
});
|
|
2570
|
-
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
2585
|
+
server.setRequestHandler(__modelcontextprotocol_sdk_types_js.CallToolRequestSchema, async (request) => {
|
|
2571
2586
|
const { name, arguments: args } = request.params;
|
|
2572
2587
|
if (name === ListBoilerplatesTool.TOOL_NAME) return await listBoilerplatesTool.execute(args || {});
|
|
2573
2588
|
if (name === UseBoilerplateTool.TOOL_NAME) return await useBoilerplateTool.execute(args || {});
|
|
@@ -2588,7 +2603,7 @@ Example workflow for feature:
|
|
|
2588
2603
|
}
|
|
2589
2604
|
throw new Error(`Unknown tool: ${name}`);
|
|
2590
2605
|
});
|
|
2591
|
-
server.setRequestHandler(ListPromptsRequestSchema, async () => {
|
|
2606
|
+
server.setRequestHandler(__modelcontextprotocol_sdk_types_js.ListPromptsRequestSchema, async () => {
|
|
2592
2607
|
const prompts = [];
|
|
2593
2608
|
prompts.push(scaffoldApplicationPrompt.getDefinition());
|
|
2594
2609
|
prompts.push(scaffoldFeaturePrompt.getDefinition());
|
|
@@ -2598,7 +2613,7 @@ Example workflow for feature:
|
|
|
2598
2613
|
}
|
|
2599
2614
|
return { prompts };
|
|
2600
2615
|
});
|
|
2601
|
-
server.setRequestHandler(GetPromptRequestSchema, async (request) => {
|
|
2616
|
+
server.setRequestHandler(__modelcontextprotocol_sdk_types_js.GetPromptRequestSchema, async (request) => {
|
|
2602
2617
|
const { name, arguments: args } = request.params;
|
|
2603
2618
|
if (name === ScaffoldApplicationPrompt.PROMPT_NAME) return { messages: scaffoldApplicationPrompt.getMessages(args) };
|
|
2604
2619
|
if (name === ScaffoldFeaturePrompt.PROMPT_NAME) return { messages: scaffoldFeaturePrompt.getMessages(args) };
|
|
@@ -2618,24 +2633,30 @@ Example workflow for feature:
|
|
|
2618
2633
|
//#endregion
|
|
2619
2634
|
//#region src/transports/http.ts
|
|
2620
2635
|
/**
|
|
2621
|
-
*
|
|
2636
|
+
* HTTP session manager
|
|
2622
2637
|
*/
|
|
2623
|
-
var
|
|
2624
|
-
|
|
2638
|
+
var HttpFullSessionManager = class {
|
|
2639
|
+
sessions = /* @__PURE__ */ new Map();
|
|
2625
2640
|
getSession(sessionId) {
|
|
2626
|
-
return this.
|
|
2641
|
+
return this.sessions.get(sessionId);
|
|
2627
2642
|
}
|
|
2628
|
-
setSession(sessionId, transport) {
|
|
2629
|
-
this.
|
|
2643
|
+
setSession(sessionId, transport, server) {
|
|
2644
|
+
this.sessions.set(sessionId, {
|
|
2645
|
+
transport,
|
|
2646
|
+
server
|
|
2647
|
+
});
|
|
2630
2648
|
}
|
|
2631
2649
|
deleteSession(sessionId) {
|
|
2632
|
-
this.
|
|
2650
|
+
const session = this.sessions.get(sessionId);
|
|
2651
|
+
if (session) session.server.close();
|
|
2652
|
+
this.sessions.delete(sessionId);
|
|
2633
2653
|
}
|
|
2634
2654
|
hasSession(sessionId) {
|
|
2635
|
-
return this.
|
|
2655
|
+
return this.sessions.has(sessionId);
|
|
2636
2656
|
}
|
|
2637
2657
|
clear() {
|
|
2638
|
-
this.
|
|
2658
|
+
for (const session of this.sessions.values()) session.server.close();
|
|
2659
|
+
this.sessions.clear();
|
|
2639
2660
|
}
|
|
2640
2661
|
};
|
|
2641
2662
|
/**
|
|
@@ -2643,15 +2664,15 @@ var HttpSessionManager = class {
|
|
|
2643
2664
|
* Provides stateful session management with resumability support
|
|
2644
2665
|
*/
|
|
2645
2666
|
var HttpTransportHandler = class {
|
|
2646
|
-
|
|
2667
|
+
serverFactory;
|
|
2647
2668
|
app;
|
|
2648
2669
|
server = null;
|
|
2649
2670
|
sessionManager;
|
|
2650
2671
|
config;
|
|
2651
|
-
constructor(
|
|
2652
|
-
this.
|
|
2653
|
-
this.app = express();
|
|
2654
|
-
this.sessionManager = new
|
|
2672
|
+
constructor(serverFactory, config) {
|
|
2673
|
+
this.serverFactory = typeof serverFactory === "function" ? serverFactory : () => serverFactory;
|
|
2674
|
+
this.app = (0, express.default)();
|
|
2675
|
+
this.sessionManager = new HttpFullSessionManager();
|
|
2655
2676
|
this.config = {
|
|
2656
2677
|
mode: config.mode,
|
|
2657
2678
|
port: config.port ?? 3e3,
|
|
@@ -2661,7 +2682,7 @@ var HttpTransportHandler = class {
|
|
|
2661
2682
|
this.setupRoutes();
|
|
2662
2683
|
}
|
|
2663
2684
|
setupMiddleware() {
|
|
2664
|
-
this.app.use(express.json());
|
|
2685
|
+
this.app.use(express.default.json());
|
|
2665
2686
|
}
|
|
2666
2687
|
setupRoutes() {
|
|
2667
2688
|
this.app.post("/mcp", async (req, res) => {
|
|
@@ -2683,18 +2704,20 @@ var HttpTransportHandler = class {
|
|
|
2683
2704
|
async handlePostRequest(req, res) {
|
|
2684
2705
|
const sessionId = req.headers["mcp-session-id"];
|
|
2685
2706
|
let transport;
|
|
2686
|
-
if (sessionId && this.sessionManager.hasSession(sessionId)) transport = this.sessionManager.getSession(sessionId);
|
|
2687
|
-
else if (!sessionId && isInitializeRequest(req.body)) {
|
|
2688
|
-
|
|
2689
|
-
|
|
2707
|
+
if (sessionId && this.sessionManager.hasSession(sessionId)) transport = this.sessionManager.getSession(sessionId).transport;
|
|
2708
|
+
else if (!sessionId && (0, __modelcontextprotocol_sdk_types_js.isInitializeRequest)(req.body)) {
|
|
2709
|
+
const mcpServer = this.serverFactory();
|
|
2710
|
+
transport = new __modelcontextprotocol_sdk_server_streamableHttp_js.StreamableHTTPServerTransport({
|
|
2711
|
+
sessionIdGenerator: () => (0, node_crypto.randomUUID)(),
|
|
2712
|
+
enableJsonResponse: true,
|
|
2690
2713
|
onsessioninitialized: (sessionId$1) => {
|
|
2691
|
-
this.sessionManager.setSession(sessionId$1, transport);
|
|
2714
|
+
this.sessionManager.setSession(sessionId$1, transport, mcpServer);
|
|
2692
2715
|
}
|
|
2693
2716
|
});
|
|
2694
2717
|
transport.onclose = () => {
|
|
2695
2718
|
if (transport.sessionId) this.sessionManager.deleteSession(transport.sessionId);
|
|
2696
2719
|
};
|
|
2697
|
-
await
|
|
2720
|
+
await mcpServer.connect(transport);
|
|
2698
2721
|
} else {
|
|
2699
2722
|
res.status(400).json({
|
|
2700
2723
|
jsonrpc: "2.0",
|
|
@@ -2714,7 +2737,7 @@ var HttpTransportHandler = class {
|
|
|
2714
2737
|
res.status(400).send("Invalid or missing session ID");
|
|
2715
2738
|
return;
|
|
2716
2739
|
}
|
|
2717
|
-
await this.sessionManager.getSession(sessionId).handleRequest(req, res);
|
|
2740
|
+
await this.sessionManager.getSession(sessionId).transport.handleRequest(req, res);
|
|
2718
2741
|
}
|
|
2719
2742
|
async handleDeleteRequest(req, res) {
|
|
2720
2743
|
const sessionId = req.headers["mcp-session-id"];
|
|
@@ -2722,7 +2745,7 @@ var HttpTransportHandler = class {
|
|
|
2722
2745
|
res.status(400).send("Invalid or missing session ID");
|
|
2723
2746
|
return;
|
|
2724
2747
|
}
|
|
2725
|
-
await this.sessionManager.getSession(sessionId).handleRequest(req, res);
|
|
2748
|
+
await this.sessionManager.getSession(sessionId).transport.handleRequest(req, res);
|
|
2726
2749
|
this.sessionManager.deleteSession(sessionId);
|
|
2727
2750
|
}
|
|
2728
2751
|
async start() {
|
|
@@ -2805,7 +2828,7 @@ var SseTransportHandler = class {
|
|
|
2805
2828
|
config;
|
|
2806
2829
|
constructor(serverFactory, config) {
|
|
2807
2830
|
this.serverFactory = typeof serverFactory === "function" ? serverFactory : () => serverFactory;
|
|
2808
|
-
this.app = express();
|
|
2831
|
+
this.app = (0, express.default)();
|
|
2809
2832
|
this.sessionManager = new SseSessionManager();
|
|
2810
2833
|
this.config = {
|
|
2811
2834
|
mode: config.mode,
|
|
@@ -2816,7 +2839,7 @@ var SseTransportHandler = class {
|
|
|
2816
2839
|
this.setupRoutes();
|
|
2817
2840
|
}
|
|
2818
2841
|
setupMiddleware() {
|
|
2819
|
-
this.app.use(express.json());
|
|
2842
|
+
this.app.use(express.default.json());
|
|
2820
2843
|
}
|
|
2821
2844
|
setupRoutes() {
|
|
2822
2845
|
this.app.get("/sse", async (req, res) => {
|
|
@@ -2835,7 +2858,7 @@ var SseTransportHandler = class {
|
|
|
2835
2858
|
async handleSseConnection(_req, res) {
|
|
2836
2859
|
try {
|
|
2837
2860
|
const mcpServer = this.serverFactory();
|
|
2838
|
-
const transport = new SSEServerTransport("/messages", res);
|
|
2861
|
+
const transport = new __modelcontextprotocol_sdk_server_sse_js.SSEServerTransport("/messages", res);
|
|
2839
2862
|
this.sessionManager.setSession(transport.sessionId, transport, mcpServer);
|
|
2840
2863
|
res.on("close", () => {
|
|
2841
2864
|
this.sessionManager.deleteSession(transport.sessionId);
|
|
@@ -2918,7 +2941,7 @@ var StdioTransportHandler = class {
|
|
|
2918
2941
|
this.server = server;
|
|
2919
2942
|
}
|
|
2920
2943
|
async start() {
|
|
2921
|
-
this.transport = new StdioServerTransport();
|
|
2944
|
+
this.transport = new __modelcontextprotocol_sdk_server_stdio_js.StdioServerTransport();
|
|
2922
2945
|
await this.server.connect(this.transport);
|
|
2923
2946
|
console.error("Scaffolding MCP server started on stdio");
|
|
2924
2947
|
}
|
|
@@ -2966,7 +2989,7 @@ async function startServer(handler) {
|
|
|
2966
2989
|
/**
|
|
2967
2990
|
* MCP Serve command
|
|
2968
2991
|
*/
|
|
2969
|
-
const mcpServeCommand = new Command("mcp-serve").description("Start MCP server with specified transport").option("-t, --type <type>", "Transport type: stdio, http, or sse", "stdio").option("-p, --port <port>", "Port to listen on (http/sse only)", (val) => parseInt(val, 10), 3e3).option("--host <host>", "Host to bind to (http/sse only)", "localhost").option("--admin-enable", "Enable admin tools (generate-boilerplate)", false).action(async (options) => {
|
|
2992
|
+
const mcpServeCommand = new commander.Command("mcp-serve").description("Start MCP server with specified transport").option("-t, --type <type>", "Transport type: stdio, http, or sse", "stdio").option("-p, --port <port>", "Port to listen on (http/sse only)", (val) => parseInt(val, 10), 3e3).option("--host <host>", "Host to bind to (http/sse only)", "localhost").option("--admin-enable", "Enable admin tools (generate-boilerplate)", false).action(async (options) => {
|
|
2970
2993
|
try {
|
|
2971
2994
|
const transportType = options.type.toLowerCase();
|
|
2972
2995
|
const serverOptions = { adminEnabled: options.adminEnable };
|
|
@@ -2975,13 +2998,12 @@ const mcpServeCommand = new Command("mcp-serve").description("Start MCP server w
|
|
|
2975
2998
|
const handler = new StdioTransportHandler(server);
|
|
2976
2999
|
await startServer(handler);
|
|
2977
3000
|
} else if (transportType === "http") {
|
|
2978
|
-
const server = createServer(serverOptions);
|
|
2979
3001
|
const config = {
|
|
2980
3002
|
mode: TransportMode.HTTP,
|
|
2981
3003
|
port: options.port || Number(process.env.MCP_PORT) || 3e3,
|
|
2982
3004
|
host: options.host || process.env.MCP_HOST || "localhost"
|
|
2983
3005
|
};
|
|
2984
|
-
const handler = new HttpTransportHandler(
|
|
3006
|
+
const handler = new HttpTransportHandler(() => createServer(serverOptions), config);
|
|
2985
3007
|
await startServer(handler);
|
|
2986
3008
|
} else if (transportType === "sse") {
|
|
2987
3009
|
const config = {
|
|
@@ -3003,21 +3025,19 @@ const mcpServeCommand = new Command("mcp-serve").description("Start MCP server w
|
|
|
3003
3025
|
|
|
3004
3026
|
//#endregion
|
|
3005
3027
|
//#region src/cli/scaffold.ts
|
|
3006
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
3007
|
-
const __dirname = path.dirname(__filename);
|
|
3008
|
-
const templatesDir = path.resolve(__dirname, "../../../../templates");
|
|
3009
3028
|
/**
|
|
3010
3029
|
* Scaffold CLI command
|
|
3011
3030
|
*/
|
|
3012
|
-
const scaffoldCommand = new Command("scaffold").description("Add features to existing projects");
|
|
3031
|
+
const scaffoldCommand = new commander.Command("scaffold").description("Add features to existing projects");
|
|
3013
3032
|
scaffoldCommand.command("list <projectPath>").description("List available scaffolding methods for a project").action(async (projectPath) => {
|
|
3014
3033
|
try {
|
|
3015
|
-
const absolutePath =
|
|
3016
|
-
if (!
|
|
3034
|
+
const absolutePath = node_path.default.resolve(projectPath);
|
|
3035
|
+
if (!fs_extra.existsSync(node_path.default.join(absolutePath, "project.json"))) {
|
|
3017
3036
|
messages.error(`No project.json found in ${absolutePath}`);
|
|
3018
3037
|
messages.hint("Make sure you are in a valid project directory");
|
|
3019
3038
|
process.exit(1);
|
|
3020
3039
|
}
|
|
3040
|
+
const templatesDir = await require_ScaffoldService.TemplatesManager.findTemplatesPath();
|
|
3021
3041
|
const fileSystemService = new FileSystemService();
|
|
3022
3042
|
const methods = (await new ScaffoldingMethodsService(fileSystemService, templatesDir).listScaffoldingMethods(absolutePath)).methods;
|
|
3023
3043
|
if (methods.length === 0) {
|
|
@@ -3038,8 +3058,8 @@ scaffoldCommand.command("list <projectPath>").description("List available scaffo
|
|
|
3038
3058
|
});
|
|
3039
3059
|
scaffoldCommand.command("add <featureName>").description("Add a feature to an existing project").option("-p, --project <path>", "Project path", process.cwd()).option("-v, --vars <json>", "JSON string containing variables for the feature").option("--verbose", "Enable verbose logging").action(async (featureName, options) => {
|
|
3040
3060
|
try {
|
|
3041
|
-
const projectPath =
|
|
3042
|
-
if (!
|
|
3061
|
+
const projectPath = node_path.default.resolve(options.project);
|
|
3062
|
+
if (!fs_extra.existsSync(node_path.default.join(projectPath, "project.json"))) {
|
|
3043
3063
|
messages.error(`No project.json found in ${projectPath}`);
|
|
3044
3064
|
messages.hint("Make sure you are in a valid project directory");
|
|
3045
3065
|
process.exit(1);
|
|
@@ -3052,6 +3072,7 @@ scaffoldCommand.command("add <featureName>").description("Add a feature to an ex
|
|
|
3052
3072
|
messages.hint("Example: --vars '{\"componentName\": \"UserProfile\", \"description\": \"User profile component\"}'");
|
|
3053
3073
|
process.exit(1);
|
|
3054
3074
|
}
|
|
3075
|
+
const templatesDir = await require_ScaffoldService.TemplatesManager.findTemplatesPath();
|
|
3055
3076
|
const fileSystemService = new FileSystemService();
|
|
3056
3077
|
const scaffoldingMethodsService = new ScaffoldingMethodsService(fileSystemService, templatesDir);
|
|
3057
3078
|
const methods = (await scaffoldingMethodsService.listScaffoldingMethods(projectPath)).methods;
|
|
@@ -3112,11 +3133,12 @@ scaffoldCommand.command("add <featureName>").description("Add a feature to an ex
|
|
|
3112
3133
|
});
|
|
3113
3134
|
scaffoldCommand.command("info <featureName>").description("Show detailed information about a scaffold method").option("-p, --project <path>", "Project path", process.cwd()).action(async (featureName, options) => {
|
|
3114
3135
|
try {
|
|
3115
|
-
const projectPath =
|
|
3116
|
-
if (!
|
|
3136
|
+
const projectPath = node_path.default.resolve(options.project);
|
|
3137
|
+
if (!fs_extra.existsSync(node_path.default.join(projectPath, "project.json"))) {
|
|
3117
3138
|
messages.error(`❌ No project.json found in ${projectPath}`);
|
|
3118
3139
|
process.exit(1);
|
|
3119
3140
|
}
|
|
3141
|
+
const templatesDir = await require_ScaffoldService.TemplatesManager.findTemplatesPath();
|
|
3120
3142
|
const fileSystemService = new FileSystemService();
|
|
3121
3143
|
const method = (await new ScaffoldingMethodsService(fileSystemService, templatesDir).listScaffoldingMethods(projectPath)).methods.find((m) => m.name === featureName);
|
|
3122
3144
|
if (!method) {
|
|
@@ -3148,7 +3170,7 @@ scaffoldCommand.command("info <featureName>").description("Show detailed informa
|
|
|
3148
3170
|
* Main entry point
|
|
3149
3171
|
*/
|
|
3150
3172
|
async function main() {
|
|
3151
|
-
const program = new Command();
|
|
3173
|
+
const program = new commander.Command();
|
|
3152
3174
|
program.name("scaffold-mcp").description("MCP server for scaffolding applications with boilerplate templates").version("1.0.0");
|
|
3153
3175
|
program.addCommand(mcpServeCommand);
|
|
3154
3176
|
program.addCommand(boilerplateCommand);
|
|
@@ -3159,5 +3181,4 @@ async function main() {
|
|
|
3159
3181
|
}
|
|
3160
3182
|
main();
|
|
3161
3183
|
|
|
3162
|
-
//#endregion
|
|
3163
|
-
export { };
|
|
3184
|
+
//#endregion
|