@agiflowai/scaffold-mcp 1.0.10 → 1.0.12

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.
Files changed (32) hide show
  1. package/dist/ListScaffoldingMethodsTool-D3ecmSLf.mjs +994 -0
  2. package/dist/ListScaffoldingMethodsTool-D7S3xpJE.cjs +1082 -0
  3. package/dist/cli.cjs +101 -40
  4. package/dist/cli.mjs +95 -33
  5. package/dist/index.cjs +7 -11
  6. package/dist/index.mjs +2 -6
  7. package/dist/{stdio-AbTm52SJ.mjs → stdio-DqZJsqKM.mjs} +15 -18
  8. package/dist/{stdio-baUp7xGL.cjs → stdio-ohQyWnxq.cjs} +24 -28
  9. package/dist/{useScaffoldMethod-CPgJIBHx.mjs → useScaffoldMethod-B-q_yBnX.mjs} +1 -2
  10. package/dist/{useScaffoldMethod-BMWhFebp.mjs → useScaffoldMethod-CC8ARsl9.mjs} +7 -5
  11. package/dist/{useScaffoldMethod-CcrpFEPv.cjs → useScaffoldMethod-DqF6pT1A.cjs} +1 -3
  12. package/dist/{useScaffoldMethod-DOvwnNOJ.cjs → useScaffoldMethod-fzsnprJs.cjs} +10 -9
  13. package/package.json +5 -5
  14. package/dist/ListScaffoldingMethodsTool-B49G_iLj.mjs +0 -350
  15. package/dist/ListScaffoldingMethodsTool-DuYGFDwJ.cjs +0 -376
  16. package/dist/ScaffoldConfigLoader-8YI7v2GJ.mjs +0 -142
  17. package/dist/ScaffoldConfigLoader-BWpNpMx-.cjs +0 -150
  18. package/dist/ScaffoldConfigLoader-DKJtnrWT.mjs +0 -3
  19. package/dist/ScaffoldConfigLoader-HutEtfaH.cjs +0 -3
  20. package/dist/ScaffoldService-DSQBnAHm.cjs +0 -308
  21. package/dist/ScaffoldService-DcsGLMuD.mjs +0 -295
  22. package/dist/ScaffoldService-DfXjmrNT.cjs +0 -3
  23. package/dist/ScaffoldService-dL74anIv.mjs +0 -3
  24. package/dist/TemplateService-7QcWREot.cjs +0 -85
  25. package/dist/TemplateService-B1bd6iHw.mjs +0 -3
  26. package/dist/TemplateService-CVDL2uqt.mjs +0 -79
  27. package/dist/TemplateService-DUbdBOFs.cjs +0 -3
  28. package/dist/VariableReplacementService-B9RA8D0a.mjs +0 -66
  29. package/dist/VariableReplacementService-BO-UYgcf.mjs +0 -3
  30. package/dist/VariableReplacementService-DNYx0Dym.cjs +0 -73
  31. package/dist/VariableReplacementService-wuYKgeui.cjs +0 -3
  32. package/dist/chunk-CbDLau6x.cjs +0 -34
@@ -1,376 +0,0 @@
1
- const require_chunk = require('./chunk-CbDLau6x.cjs');
2
- const require_TemplateService = require('./TemplateService-7QcWREot.cjs');
3
- let node_path = require("node:path");
4
- node_path = require_chunk.__toESM(node_path);
5
- let __agiflowai_aicode_utils = require("@agiflowai/aicode-utils");
6
- let js_yaml = require("js-yaml");
7
- js_yaml = require_chunk.__toESM(js_yaml);
8
-
9
- //#region src/utils/pagination.ts
10
- var PaginationHelper = class PaginationHelper {
11
- /**
12
- * Default page size for pagination
13
- */
14
- static DEFAULT_PAGE_SIZE = 10;
15
- /**
16
- * Decodes a cursor string to extract the start index
17
- * @param cursor - String representing the start index (e.g., "10")
18
- * @returns Start index or 0 if invalid/undefined
19
- */
20
- static decodeCursor(cursor) {
21
- if (!cursor) return 0;
22
- const index = Number.parseInt(cursor, 10);
23
- if (Number.isNaN(index) || index < 0) return 0;
24
- return index;
25
- }
26
- /**
27
- * Encodes an index into a cursor string
28
- * @param index - Start index to encode
29
- * @returns Cursor string (e.g., "10")
30
- */
31
- static encodeCursor(index) {
32
- return index.toString();
33
- }
34
- /**
35
- * Paginates an array of items
36
- * @param items - All items to paginate
37
- * @param cursor - Optional cursor representing the start index
38
- * @param pageSize - Number of items per page (default: 10)
39
- * @param includeMeta - Whether to include metadata in response (default: true)
40
- * @returns Paginated result with items and optional nextCursor
41
- */
42
- static paginate(items, cursor, pageSize = PaginationHelper.DEFAULT_PAGE_SIZE, includeMeta = true) {
43
- const startIndex = PaginationHelper.decodeCursor(cursor);
44
- const endIndex = startIndex + pageSize;
45
- const result = {
46
- items: items.slice(startIndex, endIndex),
47
- nextCursor: endIndex < items.length ? PaginationHelper.encodeCursor(endIndex) : void 0
48
- };
49
- if (includeMeta) result._meta = {
50
- total: items.length,
51
- offset: startIndex,
52
- limit: pageSize
53
- };
54
- return result;
55
- }
56
- };
57
-
58
- //#endregion
59
- //#region src/services/FileSystemService.ts
60
- var FileSystemService = class {
61
- async pathExists(path$1) {
62
- return (0, __agiflowai_aicode_utils.pathExists)(path$1);
63
- }
64
- async readFile(path$1, encoding = "utf8") {
65
- return (0, __agiflowai_aicode_utils.readFile)(path$1, encoding);
66
- }
67
- async readJson(path$1) {
68
- return (0, __agiflowai_aicode_utils.readJson)(path$1);
69
- }
70
- async writeFile(path$1, content, encoding = "utf8") {
71
- return (0, __agiflowai_aicode_utils.writeFile)(path$1, content, encoding);
72
- }
73
- async ensureDir(path$1) {
74
- return (0, __agiflowai_aicode_utils.ensureDir)(path$1);
75
- }
76
- async copy(src, dest) {
77
- return (0, __agiflowai_aicode_utils.copy)(src, dest);
78
- }
79
- async readdir(path$1) {
80
- return (0, __agiflowai_aicode_utils.readdir)(path$1);
81
- }
82
- async stat(path$1) {
83
- return (0, __agiflowai_aicode_utils.stat)(path$1);
84
- }
85
- };
86
-
87
- //#endregion
88
- //#region src/services/ScaffoldingMethodsService.ts
89
- var ScaffoldingMethodsService = class {
90
- templateService;
91
- constructor(fileSystem, templatesRootPath) {
92
- this.fileSystem = fileSystem;
93
- this.templatesRootPath = templatesRootPath;
94
- this.templateService = new require_TemplateService.TemplateService();
95
- }
96
- async listScaffoldingMethods(projectPath, cursor) {
97
- const absoluteProjectPath = node_path.default.resolve(projectPath);
98
- const sourceTemplate = (await __agiflowai_aicode_utils.ProjectConfigResolver.resolveProjectConfig(absoluteProjectPath)).sourceTemplate;
99
- return this.listScaffoldingMethodsByTemplate(sourceTemplate, cursor);
100
- }
101
- async listScaffoldingMethodsByTemplate(templateName, cursor) {
102
- const templatePath = await this.findTemplatePath(templateName);
103
- if (!templatePath) throw new Error(`Template not found for sourceTemplate: ${templateName}`);
104
- const fullTemplatePath = node_path.default.join(this.templatesRootPath, templatePath);
105
- const scaffoldYamlPath = node_path.default.join(fullTemplatePath, "scaffold.yaml");
106
- if (!await this.fileSystem.pathExists(scaffoldYamlPath)) throw new Error(`scaffold.yaml not found at ${scaffoldYamlPath}`);
107
- const scaffoldContent = await this.fileSystem.readFile(scaffoldYamlPath, "utf8");
108
- const architectConfig = js_yaml.default.load(scaffoldContent);
109
- const methods = [];
110
- if (architectConfig.features && Array.isArray(architectConfig.features)) architectConfig.features.forEach((feature) => {
111
- const featureName = feature.name || `scaffold-${templateName}`;
112
- methods.push({
113
- name: featureName,
114
- description: feature.description || "",
115
- instruction: feature.instruction || "",
116
- variables_schema: feature.variables_schema || {
117
- type: "object",
118
- properties: {},
119
- required: [],
120
- additionalProperties: false
121
- },
122
- generator: feature.generator
123
- });
124
- });
125
- const paginatedResult = PaginationHelper.paginate(methods, cursor);
126
- return {
127
- sourceTemplate: templateName,
128
- templatePath,
129
- methods: paginatedResult.items,
130
- nextCursor: paginatedResult.nextCursor,
131
- _meta: paginatedResult._meta
132
- };
133
- }
134
- /**
135
- * Gets scaffolding methods with instructions rendered using provided variables
136
- */
137
- async listScaffoldingMethodsWithVariables(projectPath, variables, cursor) {
138
- const result = await this.listScaffoldingMethods(projectPath, cursor);
139
- const processedMethods = result.methods.map((method) => ({
140
- ...method,
141
- instruction: method.instruction ? this.processScaffoldInstruction(method.instruction, variables) : void 0
142
- }));
143
- return {
144
- ...result,
145
- methods: processedMethods
146
- };
147
- }
148
- /**
149
- * Processes scaffold instruction with template service
150
- */
151
- processScaffoldInstruction(instruction, variables) {
152
- if (this.templateService.containsTemplateVariables(instruction)) return this.templateService.renderString(instruction, variables);
153
- return instruction;
154
- }
155
- async findTemplatePath(sourceTemplate) {
156
- const templateDirs = await this.discoverTemplateDirs();
157
- if (templateDirs.includes(sourceTemplate)) return sourceTemplate;
158
- for (const templateDir of templateDirs) {
159
- const templatePath = node_path.default.join(this.templatesRootPath, templateDir);
160
- const scaffoldYamlPath = node_path.default.join(templatePath, "scaffold.yaml");
161
- if (await this.fileSystem.pathExists(scaffoldYamlPath)) try {
162
- const scaffoldContent = await this.fileSystem.readFile(scaffoldYamlPath, "utf8");
163
- const architectConfig = js_yaml.default.load(scaffoldContent);
164
- if (architectConfig.boilerplate && Array.isArray(architectConfig.boilerplate)) {
165
- for (const boilerplate of architectConfig.boilerplate) if (boilerplate.name?.includes(sourceTemplate)) return templateDir;
166
- }
167
- } catch (error) {
168
- __agiflowai_aicode_utils.log.warn(`Failed to read scaffold.yaml at ${scaffoldYamlPath}:`, error);
169
- }
170
- }
171
- return null;
172
- }
173
- /**
174
- * Resolves the project path, handling both monorepo and monolith cases
175
- * Uses ProjectConfigResolver to find the correct workspace/project root
176
- */
177
- async resolveProjectPath(projectPath) {
178
- const absolutePath = node_path.default.resolve(projectPath);
179
- return (await __agiflowai_aicode_utils.ProjectConfigResolver.resolveProjectConfig(absolutePath)).workspaceRoot || absolutePath;
180
- }
181
- /**
182
- * Dynamically discovers all template directories
183
- * Supports both flat structure (templates/nextjs-15) and nested structure (templates/apps/nextjs-15)
184
- **/
185
- async discoverTemplateDirs() {
186
- const templateDirs = [];
187
- try {
188
- const items = await this.fileSystem.readdir(this.templatesRootPath);
189
- for (const item of items) {
190
- const itemPath = node_path.default.join(this.templatesRootPath, item);
191
- if (!(await this.fileSystem.stat(itemPath)).isDirectory()) continue;
192
- const scaffoldYamlPath = node_path.default.join(itemPath, "scaffold.yaml");
193
- if (await this.fileSystem.pathExists(scaffoldYamlPath)) {
194
- templateDirs.push(item);
195
- continue;
196
- }
197
- try {
198
- const subItems = await this.fileSystem.readdir(itemPath);
199
- for (const subItem of subItems) {
200
- const subItemPath = node_path.default.join(itemPath, subItem);
201
- if (!(await this.fileSystem.stat(subItemPath)).isDirectory()) continue;
202
- const subScaffoldYamlPath = node_path.default.join(subItemPath, "scaffold.yaml");
203
- if (await this.fileSystem.pathExists(subScaffoldYamlPath)) {
204
- const relativePath = node_path.default.join(item, subItem);
205
- templateDirs.push(relativePath);
206
- }
207
- }
208
- } catch (error) {
209
- __agiflowai_aicode_utils.log.warn(`Failed to read subdirectories in ${itemPath}:`, error);
210
- }
211
- }
212
- } catch (error) {
213
- __agiflowai_aicode_utils.log.warn(`Failed to read templates root directory ${this.templatesRootPath}:`, error);
214
- }
215
- return templateDirs;
216
- }
217
- async useScaffoldMethod(request) {
218
- const { projectPath, scaffold_feature_name, variables, sessionId } = request;
219
- const absoluteProjectPath = await this.resolveProjectPath(projectPath);
220
- const scaffoldingMethods = await this.listScaffoldingMethods(absoluteProjectPath);
221
- const method = scaffoldingMethods.methods.find((m) => m.name === scaffold_feature_name);
222
- if (!method) {
223
- const availableMethods = scaffoldingMethods.methods.map((m) => m.name).join(", ");
224
- throw new Error(`Scaffold method '${scaffold_feature_name}' not found. Available methods: ${availableMethods}`);
225
- }
226
- const ScaffoldService = (await Promise.resolve().then(() => require("./ScaffoldService-DfXjmrNT.cjs"))).ScaffoldService;
227
- const ScaffoldConfigLoader = (await Promise.resolve().then(() => require("./ScaffoldConfigLoader-HutEtfaH.cjs"))).ScaffoldConfigLoader;
228
- const VariableReplacementService = (await Promise.resolve().then(() => require("./VariableReplacementService-wuYKgeui.cjs"))).VariableReplacementService;
229
- const TemplateService$1 = (await Promise.resolve().then(() => require("./TemplateService-DUbdBOFs.cjs"))).TemplateService;
230
- const templateService = new TemplateService$1();
231
- const scaffoldConfigLoader = new ScaffoldConfigLoader(this.fileSystem, templateService);
232
- const variableReplacer = new VariableReplacementService(this.fileSystem, templateService);
233
- const scaffoldService = new ScaffoldService(this.fileSystem, scaffoldConfigLoader, variableReplacer, this.templatesRootPath);
234
- const projectName = node_path.default.basename(absoluteProjectPath);
235
- const result = await scaffoldService.useFeature({
236
- projectPath: absoluteProjectPath,
237
- templateFolder: scaffoldingMethods.templatePath,
238
- featureName: scaffold_feature_name,
239
- variables: {
240
- ...variables,
241
- appPath: absoluteProjectPath,
242
- appName: projectName
243
- }
244
- });
245
- if (!result.success) throw new Error(result.message);
246
- if (sessionId && result.createdFiles && result.createdFiles.length > 0) try {
247
- const { ExecutionLogService, DECISION_ALLOW } = await import("@agiflowai/hooks-adapter");
248
- await new ExecutionLogService(sessionId).logExecution({
249
- filePath: absoluteProjectPath,
250
- operation: "scaffold",
251
- decision: DECISION_ALLOW,
252
- generatedFiles: result.createdFiles
253
- });
254
- } catch (error) {
255
- __agiflowai_aicode_utils.log.warn("Failed to log scaffold execution:", error);
256
- }
257
- return {
258
- success: true,
259
- message: `
260
- Successfully scaffolded ${scaffold_feature_name} in ${projectPath}.
261
- Please follow this **instruction**: \n ${method.instruction ? this.processScaffoldInstruction(method.instruction, variables) : ""}.
262
- -> Create or update the plan based on the instruction.
263
- `,
264
- warnings: result.warnings,
265
- createdFiles: result.createdFiles,
266
- existingFiles: result.existingFiles
267
- };
268
- }
269
- };
270
-
271
- //#endregion
272
- //#region src/instructions/tools/list-scaffolding-methods/description.md?raw
273
- var description_default = "Lists all available scaffolding methods (features) that can be added to an existing project{% if not isMonolith %} or for a specific template{% endif %}.\n\nThis tool:\n{% if isMonolith %}\n- Reads your project's sourceTemplate from toolkit.yaml at workspace root\n{% else %}\n- Reads the project's sourceTemplate from project.json (monorepo) or toolkit.yaml (monolith), OR\n- Directly uses the provided templateName to list available features\n{% endif %}\n- Returns available features for that template type\n- Provides variable schemas for each scaffolding method\n- Shows descriptions of what each method creates\n\nUse this FIRST when adding features to understand:\n- What scaffolding methods are available\n- What variables each method requires\n- What files/features will be generated\n\nExample methods might include:\n- Adding new React routes (for React apps)\n- Creating API endpoints (for backend projects)\n- Adding new components (for frontend projects)\n- Setting up database models (for API projects)\n";
274
-
275
- //#endregion
276
- //#region src/tools/ListScaffoldingMethodsTool.ts
277
- var ListScaffoldingMethodsTool = class ListScaffoldingMethodsTool {
278
- static TOOL_NAME = "list-scaffolding-methods";
279
- fileSystemService;
280
- scaffoldingMethodsService;
281
- templateService;
282
- isMonolith;
283
- constructor(templatesPath, isMonolith = false) {
284
- this.fileSystemService = new FileSystemService();
285
- this.scaffoldingMethodsService = new ScaffoldingMethodsService(this.fileSystemService, templatesPath);
286
- this.templateService = new require_TemplateService.TemplateService();
287
- this.isMonolith = isMonolith;
288
- }
289
- /**
290
- * Get the tool definition for MCP
291
- */
292
- getDefinition() {
293
- const description = this.templateService.renderString(description_default, { isMonolith: this.isMonolith });
294
- const properties = { cursor: {
295
- type: "string",
296
- description: "Optional pagination cursor to fetch the next page of results. Omit to fetch the first page."
297
- } };
298
- if (!this.isMonolith) {
299
- properties.projectPath = {
300
- type: "string",
301
- description: "Absolute path to the project directory (for monorepo: containing project.json; for monolith: workspace root with toolkit.yaml). Either projectPath or templateName is required."
302
- };
303
- properties.templateName = {
304
- type: "string",
305
- description: "Name of the template to list scaffolding methods for (e.g., \"nextjs-15\", \"typescript-mcp-package\"). Either projectPath or templateName is required."
306
- };
307
- }
308
- return {
309
- name: ListScaffoldingMethodsTool.TOOL_NAME,
310
- description: description.trim(),
311
- inputSchema: {
312
- type: "object",
313
- properties,
314
- additionalProperties: false
315
- }
316
- };
317
- }
318
- /**
319
- * Execute the tool
320
- */
321
- async execute(args) {
322
- try {
323
- const { projectPath, templateName, cursor } = args;
324
- let result;
325
- if (this.isMonolith) try {
326
- const resolvedTemplateName = (await __agiflowai_aicode_utils.ProjectConfigResolver.resolveProjectConfig(process.cwd())).sourceTemplate;
327
- result = await this.scaffoldingMethodsService.listScaffoldingMethodsByTemplate(resolvedTemplateName, cursor);
328
- } catch (error) {
329
- throw new Error(`Failed to read template name from configuration: ${error instanceof Error ? error.message : String(error)}`);
330
- }
331
- else {
332
- if (!projectPath && !templateName) throw new Error("Either projectPath or templateName must be provided");
333
- if (projectPath) result = await this.scaffoldingMethodsService.listScaffoldingMethods(projectPath, cursor);
334
- else result = await this.scaffoldingMethodsService.listScaffoldingMethodsByTemplate(templateName, cursor);
335
- }
336
- return { content: [{
337
- type: "text",
338
- text: JSON.stringify(result, null, 2)
339
- }] };
340
- } catch (error) {
341
- return {
342
- content: [{
343
- type: "text",
344
- text: `Error listing scaffolding methods: ${error instanceof Error ? error.message : String(error)}`
345
- }],
346
- isError: true
347
- };
348
- }
349
- }
350
- };
351
-
352
- //#endregion
353
- Object.defineProperty(exports, 'FileSystemService', {
354
- enumerable: true,
355
- get: function () {
356
- return FileSystemService;
357
- }
358
- });
359
- Object.defineProperty(exports, 'ListScaffoldingMethodsTool', {
360
- enumerable: true,
361
- get: function () {
362
- return ListScaffoldingMethodsTool;
363
- }
364
- });
365
- Object.defineProperty(exports, 'PaginationHelper', {
366
- enumerable: true,
367
- get: function () {
368
- return PaginationHelper;
369
- }
370
- });
371
- Object.defineProperty(exports, 'ScaffoldingMethodsService', {
372
- enumerable: true,
373
- get: function () {
374
- return ScaffoldingMethodsService;
375
- }
376
- });
@@ -1,142 +0,0 @@
1
- import path from "node:path";
2
- import yaml from "js-yaml";
3
- import { z } from "zod";
4
-
5
- //#region src/services/ScaffoldConfigLoader.ts
6
- const VariablesSchemaSchema = z.object({
7
- type: z.literal("object"),
8
- properties: z.record(z.any()),
9
- required: z.array(z.string()),
10
- additionalProperties: z.boolean()
11
- });
12
- const ScaffoldConfigEntrySchema = z.object({
13
- name: z.string(),
14
- description: z.string().optional(),
15
- instruction: z.string().optional(),
16
- targetFolder: z.string().optional(),
17
- variables_schema: VariablesSchemaSchema,
18
- includes: z.array(z.string()),
19
- generator: z.string().optional(),
20
- patterns: z.array(z.string()).optional()
21
- });
22
- const ScaffoldYamlSchema = z.object({
23
- boilerplate: z.union([ScaffoldConfigEntrySchema, z.array(ScaffoldConfigEntrySchema)]).optional(),
24
- features: z.union([ScaffoldConfigEntrySchema, z.array(ScaffoldConfigEntrySchema)]).optional()
25
- }).catchall(z.union([ScaffoldConfigEntrySchema, z.array(ScaffoldConfigEntrySchema)]));
26
- var ScaffoldConfigLoader = class {
27
- constructor(fileSystem, templateService) {
28
- this.fileSystem = fileSystem;
29
- this.templateService = templateService;
30
- }
31
- async parseArchitectConfig(templatePath) {
32
- const architectPath = path.join(templatePath, "scaffold.yaml");
33
- if (!await this.fileSystem.pathExists(architectPath)) return null;
34
- try {
35
- const content = await this.fileSystem.readFile(architectPath, "utf8");
36
- const rawConfig = yaml.load(content);
37
- return ScaffoldYamlSchema.parse(rawConfig);
38
- } catch (error) {
39
- if (error instanceof z.ZodError) {
40
- const errorMessages = error.errors.map((err) => `${err.path.join(".")}: ${err.message}`).join("; ");
41
- throw new Error(`scaffold.yaml validation failed: ${errorMessages}`);
42
- }
43
- throw new Error(`Failed to parse scaffold.yaml: ${error instanceof Error ? error.message : String(error)}`);
44
- }
45
- }
46
- parseIncludeEntry(includeEntry, variables) {
47
- const [pathPart, conditionsPart] = includeEntry.split("?");
48
- const conditions = {};
49
- if (conditionsPart) {
50
- const conditionPairs = conditionsPart.split("&");
51
- for (const pair of conditionPairs) {
52
- const [key, value] = pair.split("=");
53
- if (key && value) conditions[key.trim()] = value.trim();
54
- }
55
- }
56
- if (pathPart.includes("->")) {
57
- const [sourcePath, targetPath] = pathPart.split("->").map((p) => p.trim());
58
- return {
59
- sourcePath,
60
- targetPath: this.replaceVariablesInPath(targetPath, variables),
61
- conditions
62
- };
63
- }
64
- const processedPath = this.replaceVariablesInPath(pathPart.trim(), variables);
65
- return {
66
- sourcePath: pathPart.trim(),
67
- targetPath: processedPath,
68
- conditions
69
- };
70
- }
71
- replaceVariablesInPath(pathStr, variables) {
72
- return this.templateService.renderString(pathStr, variables);
73
- }
74
- shouldIncludeFile(conditions, variables) {
75
- if (!conditions || Object.keys(conditions).length === 0) return true;
76
- for (const [conditionKey, conditionValue] of Object.entries(conditions)) {
77
- const variableValue = variables[conditionKey];
78
- if (conditionValue === "true" || conditionValue === "false") {
79
- const expectedBoolean = conditionValue === "true";
80
- if (Boolean(variableValue) !== expectedBoolean) return false;
81
- } else if (String(variableValue) !== conditionValue) return false;
82
- }
83
- return true;
84
- }
85
- async validateTemplate(templatePath, scaffoldType) {
86
- const errors = [];
87
- const missingFiles = [];
88
- if (!await this.fileSystem.pathExists(templatePath)) {
89
- errors.push(`Template directory ${templatePath} does not exist`);
90
- return {
91
- isValid: false,
92
- errors,
93
- missingFiles
94
- };
95
- }
96
- let architectConfig;
97
- try {
98
- architectConfig = await this.parseArchitectConfig(templatePath);
99
- } catch (error) {
100
- errors.push(`Failed to parse scaffold.yaml: ${error instanceof Error ? error.message : String(error)}`);
101
- return {
102
- isValid: false,
103
- errors,
104
- missingFiles
105
- };
106
- }
107
- if (!architectConfig) {
108
- errors.push("scaffold.yaml not found in template directory");
109
- return {
110
- isValid: false,
111
- errors,
112
- missingFiles
113
- };
114
- }
115
- if (!architectConfig[scaffoldType]) {
116
- const availableTypes = Object.keys(architectConfig).join(", ");
117
- errors.push(`Scaffold type '${scaffoldType}' not found in scaffold.yaml. Available types: ${availableTypes}`);
118
- return {
119
- isValid: false,
120
- errors,
121
- missingFiles
122
- };
123
- }
124
- const config = architectConfig[scaffoldType];
125
- if (config.includes && Array.isArray(config.includes)) for (const includeFile of config.includes) {
126
- const parsed = this.parseIncludeEntry(includeFile, {});
127
- const sourcePath = path.join(templatePath, parsed.sourcePath);
128
- const liquidSourcePath = `${sourcePath}.liquid`;
129
- const sourceExists = await this.fileSystem.pathExists(sourcePath);
130
- const liquidExists = await this.fileSystem.pathExists(liquidSourcePath);
131
- if (!sourceExists && !liquidExists) missingFiles.push(includeFile);
132
- }
133
- return {
134
- isValid: errors.length === 0 && missingFiles.length === 0,
135
- errors,
136
- missingFiles
137
- };
138
- }
139
- };
140
-
141
- //#endregion
142
- export { ScaffoldConfigLoader as t };
@@ -1,150 +0,0 @@
1
- const require_chunk = require('./chunk-CbDLau6x.cjs');
2
- let node_path = require("node:path");
3
- node_path = require_chunk.__toESM(node_path);
4
- let js_yaml = require("js-yaml");
5
- js_yaml = require_chunk.__toESM(js_yaml);
6
- let zod = require("zod");
7
-
8
- //#region src/services/ScaffoldConfigLoader.ts
9
- const VariablesSchemaSchema = zod.z.object({
10
- type: zod.z.literal("object"),
11
- properties: zod.z.record(zod.z.any()),
12
- required: zod.z.array(zod.z.string()),
13
- additionalProperties: zod.z.boolean()
14
- });
15
- const ScaffoldConfigEntrySchema = zod.z.object({
16
- name: zod.z.string(),
17
- description: zod.z.string().optional(),
18
- instruction: zod.z.string().optional(),
19
- targetFolder: zod.z.string().optional(),
20
- variables_schema: VariablesSchemaSchema,
21
- includes: zod.z.array(zod.z.string()),
22
- generator: zod.z.string().optional(),
23
- patterns: zod.z.array(zod.z.string()).optional()
24
- });
25
- const ScaffoldYamlSchema = zod.z.object({
26
- boilerplate: zod.z.union([ScaffoldConfigEntrySchema, zod.z.array(ScaffoldConfigEntrySchema)]).optional(),
27
- features: zod.z.union([ScaffoldConfigEntrySchema, zod.z.array(ScaffoldConfigEntrySchema)]).optional()
28
- }).catchall(zod.z.union([ScaffoldConfigEntrySchema, zod.z.array(ScaffoldConfigEntrySchema)]));
29
- var ScaffoldConfigLoader = class {
30
- constructor(fileSystem, templateService) {
31
- this.fileSystem = fileSystem;
32
- this.templateService = templateService;
33
- }
34
- async parseArchitectConfig(templatePath) {
35
- const architectPath = node_path.default.join(templatePath, "scaffold.yaml");
36
- if (!await this.fileSystem.pathExists(architectPath)) return null;
37
- try {
38
- const content = await this.fileSystem.readFile(architectPath, "utf8");
39
- const rawConfig = js_yaml.default.load(content);
40
- return ScaffoldYamlSchema.parse(rawConfig);
41
- } catch (error) {
42
- if (error instanceof zod.z.ZodError) {
43
- const errorMessages = error.errors.map((err) => `${err.path.join(".")}: ${err.message}`).join("; ");
44
- throw new Error(`scaffold.yaml validation failed: ${errorMessages}`);
45
- }
46
- throw new Error(`Failed to parse scaffold.yaml: ${error instanceof Error ? error.message : String(error)}`);
47
- }
48
- }
49
- parseIncludeEntry(includeEntry, variables) {
50
- const [pathPart, conditionsPart] = includeEntry.split("?");
51
- const conditions = {};
52
- if (conditionsPart) {
53
- const conditionPairs = conditionsPart.split("&");
54
- for (const pair of conditionPairs) {
55
- const [key, value] = pair.split("=");
56
- if (key && value) conditions[key.trim()] = value.trim();
57
- }
58
- }
59
- if (pathPart.includes("->")) {
60
- const [sourcePath, targetPath] = pathPart.split("->").map((p) => p.trim());
61
- return {
62
- sourcePath,
63
- targetPath: this.replaceVariablesInPath(targetPath, variables),
64
- conditions
65
- };
66
- }
67
- const processedPath = this.replaceVariablesInPath(pathPart.trim(), variables);
68
- return {
69
- sourcePath: pathPart.trim(),
70
- targetPath: processedPath,
71
- conditions
72
- };
73
- }
74
- replaceVariablesInPath(pathStr, variables) {
75
- return this.templateService.renderString(pathStr, variables);
76
- }
77
- shouldIncludeFile(conditions, variables) {
78
- if (!conditions || Object.keys(conditions).length === 0) return true;
79
- for (const [conditionKey, conditionValue] of Object.entries(conditions)) {
80
- const variableValue = variables[conditionKey];
81
- if (conditionValue === "true" || conditionValue === "false") {
82
- const expectedBoolean = conditionValue === "true";
83
- if (Boolean(variableValue) !== expectedBoolean) return false;
84
- } else if (String(variableValue) !== conditionValue) return false;
85
- }
86
- return true;
87
- }
88
- async validateTemplate(templatePath, scaffoldType) {
89
- const errors = [];
90
- const missingFiles = [];
91
- if (!await this.fileSystem.pathExists(templatePath)) {
92
- errors.push(`Template directory ${templatePath} does not exist`);
93
- return {
94
- isValid: false,
95
- errors,
96
- missingFiles
97
- };
98
- }
99
- let architectConfig;
100
- try {
101
- architectConfig = await this.parseArchitectConfig(templatePath);
102
- } catch (error) {
103
- errors.push(`Failed to parse scaffold.yaml: ${error instanceof Error ? error.message : String(error)}`);
104
- return {
105
- isValid: false,
106
- errors,
107
- missingFiles
108
- };
109
- }
110
- if (!architectConfig) {
111
- errors.push("scaffold.yaml not found in template directory");
112
- return {
113
- isValid: false,
114
- errors,
115
- missingFiles
116
- };
117
- }
118
- if (!architectConfig[scaffoldType]) {
119
- const availableTypes = Object.keys(architectConfig).join(", ");
120
- errors.push(`Scaffold type '${scaffoldType}' not found in scaffold.yaml. Available types: ${availableTypes}`);
121
- return {
122
- isValid: false,
123
- errors,
124
- missingFiles
125
- };
126
- }
127
- const config = architectConfig[scaffoldType];
128
- if (config.includes && Array.isArray(config.includes)) for (const includeFile of config.includes) {
129
- const parsed = this.parseIncludeEntry(includeFile, {});
130
- const sourcePath = node_path.default.join(templatePath, parsed.sourcePath);
131
- const liquidSourcePath = `${sourcePath}.liquid`;
132
- const sourceExists = await this.fileSystem.pathExists(sourcePath);
133
- const liquidExists = await this.fileSystem.pathExists(liquidSourcePath);
134
- if (!sourceExists && !liquidExists) missingFiles.push(includeFile);
135
- }
136
- return {
137
- isValid: errors.length === 0 && missingFiles.length === 0,
138
- errors,
139
- missingFiles
140
- };
141
- }
142
- };
143
-
144
- //#endregion
145
- Object.defineProperty(exports, 'ScaffoldConfigLoader', {
146
- enumerable: true,
147
- get: function () {
148
- return ScaffoldConfigLoader;
149
- }
150
- });
@@ -1,3 +0,0 @@
1
- import { t as ScaffoldConfigLoader } from "./ScaffoldConfigLoader-8YI7v2GJ.mjs";
2
-
3
- export { ScaffoldConfigLoader };
@@ -1,3 +0,0 @@
1
- const require_ScaffoldConfigLoader = require('./ScaffoldConfigLoader-BWpNpMx-.cjs');
2
-
3
- exports.ScaffoldConfigLoader = require_ScaffoldConfigLoader.ScaffoldConfigLoader;