@agiflowai/scaffold-mcp 1.0.0 → 1.0.2

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 CHANGED
@@ -1,9 +1,143 @@
1
- const require_stdio = require('./stdio-Cz5aRdvr.cjs');
1
+ const require_chunk = require('./chunk-CUT6urMc.cjs');
2
+ const require_stdio = require('./stdio-TGsG8akc.cjs');
2
3
  const require_ScaffoldConfigLoader = require('./ScaffoldConfigLoader-BrmvENTo.cjs');
3
- const require_ScaffoldService = require('./ScaffoldService-B-L4gwHt.cjs');
4
+ const require_ScaffoldService = require('./ScaffoldService-BwDmXt83.cjs');
4
5
  const require_TemplateService = require('./TemplateService-DRubcvS9.cjs');
5
- const require_VariableReplacementService = require('./VariableReplacementService-BL84vnKk.cjs');
6
+ const require_VariableReplacementService = require('./VariableReplacementService-D0QnWKUW.cjs');
7
+ let node_path = require("node:path");
8
+ node_path = require_chunk.__toESM(node_path);
9
+ let fs_extra = require("fs-extra");
10
+ fs_extra = require_chunk.__toESM(fs_extra);
11
+ let execa = require("execa");
12
+ execa = require_chunk.__toESM(execa);
6
13
 
14
+ //#region src/utils/git.ts
15
+ /**
16
+ * Execute a git command safely using execa to prevent command injection
17
+ */
18
+ async function execGit(args, cwd) {
19
+ try {
20
+ await (0, execa.execa)("git", args, { cwd });
21
+ } catch (error) {
22
+ const execaError = error;
23
+ throw new Error(`Git command failed: ${execaError.stderr || execaError.message}`);
24
+ }
25
+ }
26
+ /**
27
+ * Find the workspace root by searching upwards for .git folder
28
+ * Returns null if no .git folder is found (indicating a new project setup is needed)
29
+ */
30
+ async function findWorkspaceRoot(startPath = process.cwd()) {
31
+ let currentPath = node_path.default.resolve(startPath);
32
+ const rootPath = node_path.default.parse(currentPath).root;
33
+ while (true) {
34
+ const gitPath = node_path.default.join(currentPath, ".git");
35
+ if (await fs_extra.pathExists(gitPath)) return currentPath;
36
+ if (currentPath === rootPath) return null;
37
+ currentPath = node_path.default.dirname(currentPath);
38
+ }
39
+ }
40
+ /**
41
+ * Parse GitHub URL to detect if it's a subdirectory
42
+ * Supports formats:
43
+ * - https://github.com/user/repo
44
+ * - https://github.com/user/repo/tree/branch/path/to/dir
45
+ * - https://github.com/user/repo/tree/main/path/to/dir
46
+ */
47
+ function parseGitHubUrl(url) {
48
+ const treeMatch = url.match(/^https?:\/\/github\.com\/([^/]+)\/([^/]+)\/tree\/([^/]+)\/(.+)$/);
49
+ const blobMatch = url.match(/^https?:\/\/github\.com\/([^/]+)\/([^/]+)\/blob\/([^/]+)\/(.+)$/);
50
+ const rootMatch = url.match(/^https?:\/\/github\.com\/([^/]+)\/([^/]+?)(?:\.git)?$/);
51
+ if (treeMatch || blobMatch) {
52
+ const match = treeMatch || blobMatch;
53
+ return {
54
+ owner: match?.[1],
55
+ repo: match?.[2],
56
+ repoUrl: `https://github.com/${match?.[1]}/${match?.[2]}.git`,
57
+ branch: match?.[3],
58
+ subdirectory: match?.[4],
59
+ isSubdirectory: true
60
+ };
61
+ }
62
+ if (rootMatch) return {
63
+ owner: rootMatch[1],
64
+ repo: rootMatch[2],
65
+ repoUrl: `https://github.com/${rootMatch[1]}/${rootMatch[2]}.git`,
66
+ isSubdirectory: false
67
+ };
68
+ return {
69
+ repoUrl: url,
70
+ isSubdirectory: false
71
+ };
72
+ }
73
+ /**
74
+ * Clone a subdirectory from a git repository using sparse checkout
75
+ */
76
+ async function cloneSubdirectory(repoUrl, branch, subdirectory, targetFolder) {
77
+ const tempFolder = `${targetFolder}.tmp`;
78
+ try {
79
+ await execGit(["init", tempFolder]);
80
+ await execGit([
81
+ "remote",
82
+ "add",
83
+ "origin",
84
+ repoUrl
85
+ ], tempFolder);
86
+ await execGit([
87
+ "config",
88
+ "core.sparseCheckout",
89
+ "true"
90
+ ], tempFolder);
91
+ const sparseCheckoutFile = node_path.default.join(tempFolder, ".git", "info", "sparse-checkout");
92
+ await fs_extra.writeFile(sparseCheckoutFile, `${subdirectory}\n`);
93
+ await execGit([
94
+ "pull",
95
+ "--depth=1",
96
+ "origin",
97
+ branch
98
+ ], tempFolder);
99
+ const sourceDir = node_path.default.join(tempFolder, subdirectory);
100
+ if (!await fs_extra.pathExists(sourceDir)) throw new Error(`Subdirectory '${subdirectory}' not found in repository at branch '${branch}'`);
101
+ if (await fs_extra.pathExists(targetFolder)) throw new Error(`Target folder already exists: ${targetFolder}`);
102
+ await fs_extra.move(sourceDir, targetFolder);
103
+ await fs_extra.remove(tempFolder);
104
+ } catch (error) {
105
+ if (await fs_extra.pathExists(tempFolder)) await fs_extra.remove(tempFolder);
106
+ throw error;
107
+ }
108
+ }
109
+ /**
110
+ * Clone entire repository
111
+ */
112
+ async function cloneRepository(repoUrl, targetFolder) {
113
+ await execGit([
114
+ "clone",
115
+ repoUrl,
116
+ targetFolder
117
+ ]);
118
+ const gitFolder = node_path.default.join(targetFolder, ".git");
119
+ if (await fs_extra.pathExists(gitFolder)) await fs_extra.remove(gitFolder);
120
+ }
121
+ /**
122
+ * Fetch directory listing from GitHub API
123
+ */
124
+ async function fetchGitHubDirectoryContents(owner, repo, path$1, branch = "main") {
125
+ const url = `https://api.github.com/repos/${owner}/${repo}/contents/${path$1}?ref=${branch}`;
126
+ const response = await fetch(url, { headers: {
127
+ Accept: "application/vnd.github.v3+json",
128
+ "User-Agent": "scaffold-mcp"
129
+ } });
130
+ if (!response.ok) throw new Error(`Failed to fetch directory contents: ${response.statusText}`);
131
+ const data = await response.json();
132
+ if (!Array.isArray(data)) throw new Error("Expected directory but got file");
133
+ return data.map((item) => ({
134
+ name: item.name,
135
+ type: item.type,
136
+ path: item.path
137
+ }));
138
+ }
139
+
140
+ //#endregion
7
141
  exports.BoilerplateGeneratorService = require_stdio.BoilerplateGeneratorService;
8
142
  exports.BoilerplateService = require_stdio.BoilerplateService;
9
143
  exports.FileSystemService = require_stdio.FileSystemService;
@@ -25,8 +159,8 @@ exports.UseBoilerplateTool = require_stdio.UseBoilerplateTool;
25
159
  exports.UseScaffoldMethodTool = require_stdio.UseScaffoldMethodTool;
26
160
  exports.VariableReplacementService = require_VariableReplacementService.VariableReplacementService;
27
161
  exports.WriteToFileTool = require_stdio.WriteToFileTool;
28
- exports.cloneRepository = require_stdio.cloneRepository;
29
- exports.cloneSubdirectory = require_stdio.cloneSubdirectory;
30
- exports.fetchGitHubDirectoryContents = require_stdio.fetchGitHubDirectoryContents;
31
- exports.findWorkspaceRoot = require_stdio.findWorkspaceRoot;
32
- exports.parseGitHubUrl = require_stdio.parseGitHubUrl;
162
+ exports.cloneRepository = cloneRepository;
163
+ exports.cloneSubdirectory = cloneSubdirectory;
164
+ exports.fetchGitHubDirectoryContents = fetchGitHubDirectoryContents;
165
+ exports.findWorkspaceRoot = findWorkspaceRoot;
166
+ exports.parseGitHubUrl = parseGitHubUrl;
package/dist/index.d.cts CHANGED
@@ -101,7 +101,7 @@ interface BoilerplateInfo {
101
101
  includes: string[];
102
102
  }
103
103
  interface UseBoilerplateRequest {
104
- boilerplateName: string;
104
+ boilerplateName?: string;
105
105
  variables: Record<string, any>;
106
106
  monolith?: boolean;
107
107
  targetFolderOverride?: string;
@@ -365,6 +365,7 @@ declare class ScaffoldingMethodsService {
365
365
  private templateService;
366
366
  constructor(fileSystem: IFileSystemService, templatesRootPath: string);
367
367
  listScaffoldingMethods(projectPath: string): Promise<ListScaffoldingMethodsResult>;
368
+ listScaffoldingMethodsByTemplate(templateName: string): Promise<ListScaffoldingMethodsResult>;
368
369
  /**
369
370
  * Gets scaffolding methods with instructions rendered using provided variables
370
371
  */
@@ -374,6 +375,11 @@ declare class ScaffoldingMethodsService {
374
375
  */
375
376
  processScaffoldInstruction(instruction: string, variables: Record<string, any>): string;
376
377
  private findTemplatePath;
378
+ /**
379
+ * Resolves the project path, handling both monorepo and monolith cases
380
+ * Uses ProjectConfigResolver to find the correct workspace/project root
381
+ */
382
+ private resolveProjectPath;
377
383
  /**
378
384
  * Dynamically discovers all template directories
379
385
  * Supports both flat structure (templates/nextjs-15) and nested structure (templates/apps/nextjs-15)
@@ -487,7 +493,8 @@ interface ToolDefinition {
487
493
  declare class GenerateBoilerplateFileTool {
488
494
  static readonly TOOL_NAME = "generate-boilerplate-file";
489
495
  private boilerplateGeneratorService;
490
- constructor(templatesPath: string);
496
+ private isMonolith;
497
+ constructor(templatesPath: string, isMonolith?: boolean);
491
498
  /**
492
499
  * Get the tool definition for MCP
493
500
  */
@@ -496,7 +503,7 @@ declare class GenerateBoilerplateFileTool {
496
503
  * Execute the tool
497
504
  */
498
505
  execute(args: {
499
- templateName: string;
506
+ templateName?: string;
500
507
  filePath: string;
501
508
  content?: string;
502
509
  sourceFile?: string;
@@ -511,7 +518,8 @@ declare class GenerateBoilerplateFileTool {
511
518
  declare class GenerateBoilerplateTool {
512
519
  static readonly TOOL_NAME = "generate-boilerplate";
513
520
  private boilerplateGeneratorService;
514
- constructor(templatesPath: string);
521
+ private isMonolith;
522
+ constructor(templatesPath: string, isMonolith?: boolean);
515
523
  /**
516
524
  * Get the tool definition for MCP
517
525
  */
@@ -520,11 +528,11 @@ declare class GenerateBoilerplateTool {
520
528
  * Execute the tool
521
529
  */
522
530
  execute(args: {
523
- templateName: string;
531
+ templateName?: string;
524
532
  boilerplateName: string;
525
533
  description: string;
526
534
  instruction?: string;
527
- targetFolder: string;
535
+ targetFolder?: string;
528
536
  variables: Array<{
529
537
  name: string;
530
538
  description: string;
@@ -543,7 +551,8 @@ declare class GenerateBoilerplateTool {
543
551
  declare class GenerateFeatureScaffoldTool {
544
552
  static readonly TOOL_NAME = "generate-feature-scaffold";
545
553
  private scaffoldGeneratorService;
546
- constructor(templatesPath: string);
554
+ private isMonolith;
555
+ constructor(templatesPath: string, isMonolith?: boolean);
547
556
  /**
548
557
  * Get the tool definition for MCP
549
558
  */
@@ -552,7 +561,7 @@ declare class GenerateFeatureScaffoldTool {
552
561
  * Execute the tool
553
562
  */
554
563
  execute(args: {
555
- templateName: string;
564
+ templateName?: string;
556
565
  featureName: string;
557
566
  description: string;
558
567
  instruction?: string;
@@ -572,7 +581,9 @@ declare class GenerateFeatureScaffoldTool {
572
581
  declare class ListBoilerplatesTool {
573
582
  static readonly TOOL_NAME = "list-boilerplates";
574
583
  private boilerplateService;
575
- constructor(templatesPath: string);
584
+ private templateService;
585
+ private isMonolith;
586
+ constructor(templatesPath: string, isMonolith?: boolean);
576
587
  /**
577
588
  * Get the tool definition for MCP
578
589
  */
@@ -588,7 +599,9 @@ declare class ListScaffoldingMethodsTool {
588
599
  static readonly TOOL_NAME = "list-scaffolding-methods";
589
600
  private fileSystemService;
590
601
  private scaffoldingMethodsService;
591
- constructor(templatesPath: string);
602
+ private templateService;
603
+ private isMonolith;
604
+ constructor(templatesPath: string, isMonolith?: boolean);
592
605
  /**
593
606
  * Get the tool definition for MCP
594
607
  */
@@ -603,7 +616,9 @@ declare class ListScaffoldingMethodsTool {
603
616
  declare class UseBoilerplateTool {
604
617
  static readonly TOOL_NAME = "use-boilerplate";
605
618
  private boilerplateService;
606
- constructor(templatesPath: string);
619
+ private templateService;
620
+ private isMonolith;
621
+ constructor(templatesPath: string, isMonolith?: boolean);
607
622
  /**
608
623
  * Get the tool definition for MCP
609
624
  */
@@ -619,7 +634,8 @@ declare class UseScaffoldMethodTool {
619
634
  static readonly TOOL_NAME = "use-scaffold-method";
620
635
  private fileSystemService;
621
636
  private scaffoldingMethodsService;
622
- constructor(templatesPath: string);
637
+ private isMonolith;
638
+ constructor(templatesPath: string, isMonolith?: boolean);
623
639
  /**
624
640
  * Get the tool definition for MCP
625
641
  */
package/dist/index.d.ts CHANGED
@@ -102,7 +102,7 @@ interface BoilerplateInfo {
102
102
  includes: string[];
103
103
  }
104
104
  interface UseBoilerplateRequest {
105
- boilerplateName: string;
105
+ boilerplateName?: string;
106
106
  variables: Record<string, any>;
107
107
  monolith?: boolean;
108
108
  targetFolderOverride?: string;
@@ -366,6 +366,7 @@ declare class ScaffoldingMethodsService {
366
366
  private templateService;
367
367
  constructor(fileSystem: IFileSystemService, templatesRootPath: string);
368
368
  listScaffoldingMethods(projectPath: string): Promise<ListScaffoldingMethodsResult>;
369
+ listScaffoldingMethodsByTemplate(templateName: string): Promise<ListScaffoldingMethodsResult>;
369
370
  /**
370
371
  * Gets scaffolding methods with instructions rendered using provided variables
371
372
  */
@@ -375,6 +376,11 @@ declare class ScaffoldingMethodsService {
375
376
  */
376
377
  processScaffoldInstruction(instruction: string, variables: Record<string, any>): string;
377
378
  private findTemplatePath;
379
+ /**
380
+ * Resolves the project path, handling both monorepo and monolith cases
381
+ * Uses ProjectConfigResolver to find the correct workspace/project root
382
+ */
383
+ private resolveProjectPath;
378
384
  /**
379
385
  * Dynamically discovers all template directories
380
386
  * Supports both flat structure (templates/nextjs-15) and nested structure (templates/apps/nextjs-15)
@@ -488,7 +494,8 @@ interface ToolDefinition {
488
494
  declare class GenerateBoilerplateFileTool {
489
495
  static readonly TOOL_NAME = "generate-boilerplate-file";
490
496
  private boilerplateGeneratorService;
491
- constructor(templatesPath: string);
497
+ private isMonolith;
498
+ constructor(templatesPath: string, isMonolith?: boolean);
492
499
  /**
493
500
  * Get the tool definition for MCP
494
501
  */
@@ -497,7 +504,7 @@ declare class GenerateBoilerplateFileTool {
497
504
  * Execute the tool
498
505
  */
499
506
  execute(args: {
500
- templateName: string;
507
+ templateName?: string;
501
508
  filePath: string;
502
509
  content?: string;
503
510
  sourceFile?: string;
@@ -512,7 +519,8 @@ declare class GenerateBoilerplateFileTool {
512
519
  declare class GenerateBoilerplateTool {
513
520
  static readonly TOOL_NAME = "generate-boilerplate";
514
521
  private boilerplateGeneratorService;
515
- constructor(templatesPath: string);
522
+ private isMonolith;
523
+ constructor(templatesPath: string, isMonolith?: boolean);
516
524
  /**
517
525
  * Get the tool definition for MCP
518
526
  */
@@ -521,11 +529,11 @@ declare class GenerateBoilerplateTool {
521
529
  * Execute the tool
522
530
  */
523
531
  execute(args: {
524
- templateName: string;
532
+ templateName?: string;
525
533
  boilerplateName: string;
526
534
  description: string;
527
535
  instruction?: string;
528
- targetFolder: string;
536
+ targetFolder?: string;
529
537
  variables: Array<{
530
538
  name: string;
531
539
  description: string;
@@ -544,7 +552,8 @@ declare class GenerateBoilerplateTool {
544
552
  declare class GenerateFeatureScaffoldTool {
545
553
  static readonly TOOL_NAME = "generate-feature-scaffold";
546
554
  private scaffoldGeneratorService;
547
- constructor(templatesPath: string);
555
+ private isMonolith;
556
+ constructor(templatesPath: string, isMonolith?: boolean);
548
557
  /**
549
558
  * Get the tool definition for MCP
550
559
  */
@@ -553,7 +562,7 @@ declare class GenerateFeatureScaffoldTool {
553
562
  * Execute the tool
554
563
  */
555
564
  execute(args: {
556
- templateName: string;
565
+ templateName?: string;
557
566
  featureName: string;
558
567
  description: string;
559
568
  instruction?: string;
@@ -573,7 +582,9 @@ declare class GenerateFeatureScaffoldTool {
573
582
  declare class ListBoilerplatesTool {
574
583
  static readonly TOOL_NAME = "list-boilerplates";
575
584
  private boilerplateService;
576
- constructor(templatesPath: string);
585
+ private templateService;
586
+ private isMonolith;
587
+ constructor(templatesPath: string, isMonolith?: boolean);
577
588
  /**
578
589
  * Get the tool definition for MCP
579
590
  */
@@ -589,7 +600,9 @@ declare class ListScaffoldingMethodsTool {
589
600
  static readonly TOOL_NAME = "list-scaffolding-methods";
590
601
  private fileSystemService;
591
602
  private scaffoldingMethodsService;
592
- constructor(templatesPath: string);
603
+ private templateService;
604
+ private isMonolith;
605
+ constructor(templatesPath: string, isMonolith?: boolean);
593
606
  /**
594
607
  * Get the tool definition for MCP
595
608
  */
@@ -604,7 +617,9 @@ declare class ListScaffoldingMethodsTool {
604
617
  declare class UseBoilerplateTool {
605
618
  static readonly TOOL_NAME = "use-boilerplate";
606
619
  private boilerplateService;
607
- constructor(templatesPath: string);
620
+ private templateService;
621
+ private isMonolith;
622
+ constructor(templatesPath: string, isMonolith?: boolean);
608
623
  /**
609
624
  * Get the tool definition for MCP
610
625
  */
@@ -620,7 +635,8 @@ declare class UseScaffoldMethodTool {
620
635
  static readonly TOOL_NAME = "use-scaffold-method";
621
636
  private fileSystemService;
622
637
  private scaffoldingMethodsService;
623
- constructor(templatesPath: string);
638
+ private isMonolith;
639
+ constructor(templatesPath: string, isMonolith?: boolean);
624
640
  /**
625
641
  * Get the tool definition for MCP
626
642
  */
package/dist/index.js CHANGED
@@ -1,7 +1,137 @@
1
- import { BoilerplateGeneratorService, BoilerplateService, FileSystemService, GenerateBoilerplateFileTool, GenerateBoilerplateTool, GenerateFeatureScaffoldTool, HttpTransportHandler, ListBoilerplatesTool, ListScaffoldingMethodsTool, ScaffoldGeneratorService, ScaffoldingMethodsService, SseTransportHandler, StdioTransportHandler, UseBoilerplateTool, UseScaffoldMethodTool, WriteToFileTool, cloneRepository, cloneSubdirectory, fetchGitHubDirectoryContents, findWorkspaceRoot, parseGitHubUrl } from "./stdio-Dmpwju2k.js";
1
+ import { BoilerplateGeneratorService, BoilerplateService, FileSystemService, GenerateBoilerplateFileTool, GenerateBoilerplateTool, GenerateFeatureScaffoldTool, HttpTransportHandler, ListBoilerplatesTool, ListScaffoldingMethodsTool, ScaffoldGeneratorService, ScaffoldingMethodsService, SseTransportHandler, StdioTransportHandler, UseBoilerplateTool, UseScaffoldMethodTool, WriteToFileTool } from "./stdio-Bxn4A1IU.js";
2
2
  import { ScaffoldConfigLoader } from "./ScaffoldConfigLoader-CI0T6zdG.js";
3
- import { ScaffoldProcessingService, ScaffoldService } from "./ScaffoldService-QgQKHMM-.js";
3
+ import { ScaffoldProcessingService, ScaffoldService } from "./ScaffoldService-DB7-Cyod.js";
4
4
  import { TemplateService } from "./TemplateService-CiZJA06s.js";
5
- import { VariableReplacementService } from "./VariableReplacementService-B3qARIC9.js";
5
+ import { VariableReplacementService } from "./VariableReplacementService-DRxd9ILB.js";
6
+ import path from "node:path";
7
+ import * as fs$1 from "fs-extra";
8
+ import { execa } from "execa";
6
9
 
10
+ //#region src/utils/git.ts
11
+ /**
12
+ * Execute a git command safely using execa to prevent command injection
13
+ */
14
+ async function execGit(args, cwd) {
15
+ try {
16
+ await execa("git", args, { cwd });
17
+ } catch (error) {
18
+ const execaError = error;
19
+ throw new Error(`Git command failed: ${execaError.stderr || execaError.message}`);
20
+ }
21
+ }
22
+ /**
23
+ * Find the workspace root by searching upwards for .git folder
24
+ * Returns null if no .git folder is found (indicating a new project setup is needed)
25
+ */
26
+ async function findWorkspaceRoot(startPath = process.cwd()) {
27
+ let currentPath = path.resolve(startPath);
28
+ const rootPath = path.parse(currentPath).root;
29
+ while (true) {
30
+ const gitPath = path.join(currentPath, ".git");
31
+ if (await fs$1.pathExists(gitPath)) return currentPath;
32
+ if (currentPath === rootPath) return null;
33
+ currentPath = path.dirname(currentPath);
34
+ }
35
+ }
36
+ /**
37
+ * Parse GitHub URL to detect if it's a subdirectory
38
+ * Supports formats:
39
+ * - https://github.com/user/repo
40
+ * - https://github.com/user/repo/tree/branch/path/to/dir
41
+ * - https://github.com/user/repo/tree/main/path/to/dir
42
+ */
43
+ function parseGitHubUrl(url) {
44
+ const treeMatch = url.match(/^https?:\/\/github\.com\/([^/]+)\/([^/]+)\/tree\/([^/]+)\/(.+)$/);
45
+ const blobMatch = url.match(/^https?:\/\/github\.com\/([^/]+)\/([^/]+)\/blob\/([^/]+)\/(.+)$/);
46
+ const rootMatch = url.match(/^https?:\/\/github\.com\/([^/]+)\/([^/]+?)(?:\.git)?$/);
47
+ if (treeMatch || blobMatch) {
48
+ const match = treeMatch || blobMatch;
49
+ return {
50
+ owner: match?.[1],
51
+ repo: match?.[2],
52
+ repoUrl: `https://github.com/${match?.[1]}/${match?.[2]}.git`,
53
+ branch: match?.[3],
54
+ subdirectory: match?.[4],
55
+ isSubdirectory: true
56
+ };
57
+ }
58
+ if (rootMatch) return {
59
+ owner: rootMatch[1],
60
+ repo: rootMatch[2],
61
+ repoUrl: `https://github.com/${rootMatch[1]}/${rootMatch[2]}.git`,
62
+ isSubdirectory: false
63
+ };
64
+ return {
65
+ repoUrl: url,
66
+ isSubdirectory: false
67
+ };
68
+ }
69
+ /**
70
+ * Clone a subdirectory from a git repository using sparse checkout
71
+ */
72
+ async function cloneSubdirectory(repoUrl, branch, subdirectory, targetFolder) {
73
+ const tempFolder = `${targetFolder}.tmp`;
74
+ try {
75
+ await execGit(["init", tempFolder]);
76
+ await execGit([
77
+ "remote",
78
+ "add",
79
+ "origin",
80
+ repoUrl
81
+ ], tempFolder);
82
+ await execGit([
83
+ "config",
84
+ "core.sparseCheckout",
85
+ "true"
86
+ ], tempFolder);
87
+ const sparseCheckoutFile = path.join(tempFolder, ".git", "info", "sparse-checkout");
88
+ await fs$1.writeFile(sparseCheckoutFile, `${subdirectory}\n`);
89
+ await execGit([
90
+ "pull",
91
+ "--depth=1",
92
+ "origin",
93
+ branch
94
+ ], tempFolder);
95
+ const sourceDir = path.join(tempFolder, subdirectory);
96
+ if (!await fs$1.pathExists(sourceDir)) throw new Error(`Subdirectory '${subdirectory}' not found in repository at branch '${branch}'`);
97
+ if (await fs$1.pathExists(targetFolder)) throw new Error(`Target folder already exists: ${targetFolder}`);
98
+ await fs$1.move(sourceDir, targetFolder);
99
+ await fs$1.remove(tempFolder);
100
+ } catch (error) {
101
+ if (await fs$1.pathExists(tempFolder)) await fs$1.remove(tempFolder);
102
+ throw error;
103
+ }
104
+ }
105
+ /**
106
+ * Clone entire repository
107
+ */
108
+ async function cloneRepository(repoUrl, targetFolder) {
109
+ await execGit([
110
+ "clone",
111
+ repoUrl,
112
+ targetFolder
113
+ ]);
114
+ const gitFolder = path.join(targetFolder, ".git");
115
+ if (await fs$1.pathExists(gitFolder)) await fs$1.remove(gitFolder);
116
+ }
117
+ /**
118
+ * Fetch directory listing from GitHub API
119
+ */
120
+ async function fetchGitHubDirectoryContents(owner, repo, path$1, branch = "main") {
121
+ const url = `https://api.github.com/repos/${owner}/${repo}/contents/${path$1}?ref=${branch}`;
122
+ const response = await fetch(url, { headers: {
123
+ Accept: "application/vnd.github.v3+json",
124
+ "User-Agent": "scaffold-mcp"
125
+ } });
126
+ if (!response.ok) throw new Error(`Failed to fetch directory contents: ${response.statusText}`);
127
+ const data = await response.json();
128
+ if (!Array.isArray(data)) throw new Error("Expected directory but got file");
129
+ return data.map((item) => ({
130
+ name: item.name,
131
+ type: item.type,
132
+ path: item.path
133
+ }));
134
+ }
135
+
136
+ //#endregion
7
137
  export { BoilerplateGeneratorService, BoilerplateService, FileSystemService, GenerateBoilerplateFileTool, GenerateBoilerplateTool, GenerateFeatureScaffoldTool, HttpTransportHandler, ListBoilerplatesTool, ListScaffoldingMethodsTool, ScaffoldConfigLoader, ScaffoldGeneratorService, ScaffoldProcessingService, ScaffoldService, ScaffoldingMethodsService, SseTransportHandler, StdioTransportHandler, TemplateService, UseBoilerplateTool, UseScaffoldMethodTool, VariableReplacementService, WriteToFileTool, cloneRepository, cloneSubdirectory, fetchGitHubDirectoryContents, findWorkspaceRoot, parseGitHubUrl };