@agiflowai/aicode-utils 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,242 @@
1
+ //#region src/types/index.d.ts
2
+ /**
3
+ * @agiflowai/aicode-utils - Type Definitions
4
+ *
5
+ * DESIGN PATTERNS:
6
+ * - Interface segregation: Keep interfaces focused and minimal
7
+ * - Type composition: Build complex types from simple primitives
8
+ * - Generics: Use type parameters for reusable, type-safe abstractions
9
+ *
10
+ * CODING STANDARDS:
11
+ * - Use PascalCase for type/interface names
12
+ * - Prefix interfaces with 'I' only for abstract contracts
13
+ * - Document complex types with JSDoc comments
14
+ * - Export all public types
15
+ *
16
+ * AVOID:
17
+ * - Any type unless absolutely necessary
18
+ * - Overly complex type gymnastics
19
+ * - Coupling types to implementation details
20
+ */
21
+ /**
22
+ * Project configuration from project.json
23
+ */
24
+ interface ProjectConfig {
25
+ name: string;
26
+ root: string;
27
+ sourceTemplate?: string;
28
+ projectType?: string;
29
+ }
30
+ /**
31
+ * Scaffold template include configuration
32
+ */
33
+ interface ParsedInclude {
34
+ sourcePath: string;
35
+ targetPath: string;
36
+ conditions?: Record<string, string>;
37
+ }
38
+ /**
39
+ * Result of a scaffold operation
40
+ */
41
+ interface ScaffoldResult {
42
+ success: boolean;
43
+ message: string;
44
+ warnings?: string[];
45
+ createdFiles?: string[];
46
+ existingFiles?: string[];
47
+ }
48
+ /**
49
+ * Abstract interface for file system operations
50
+ */
51
+ interface IFileSystemService {
52
+ pathExists(path: string): Promise<boolean>;
53
+ readFile(path: string, encoding?: BufferEncoding): Promise<string>;
54
+ readJson(path: string): Promise<any>;
55
+ writeFile(path: string, content: string, encoding?: BufferEncoding): Promise<void>;
56
+ ensureDir(path: string): Promise<void>;
57
+ copy(src: string, dest: string): Promise<void>;
58
+ readdir(path: string): Promise<string[]>;
59
+ stat(path: string): Promise<{
60
+ isDirectory(): boolean;
61
+ isFile(): boolean;
62
+ }>;
63
+ }
64
+ /**
65
+ * Abstract interface for variable replacement in templates
66
+ */
67
+ interface IVariableReplacementService {
68
+ processFilesForVariableReplacement(dirPath: string, variables: Record<string, any>): Promise<void>;
69
+ replaceVariablesInFile(filePath: string, variables: Record<string, any>): Promise<void>;
70
+ isBinaryFile(filePath: string): boolean;
71
+ }
72
+ /**
73
+ * Context object passed to generator functions
74
+ */
75
+ interface GeneratorContext {
76
+ variables: Record<string, any>;
77
+ config: any;
78
+ targetPath: string;
79
+ templatePath: string;
80
+ fileSystem: IFileSystemService;
81
+ scaffoldConfigLoader: any;
82
+ variableReplacer: IVariableReplacementService;
83
+ ScaffoldProcessingService: any;
84
+ getRootPath: () => string;
85
+ getProjectPath: (projectPath: string) => string;
86
+ }
87
+ /**
88
+ * Type definition for generator functions
89
+ */
90
+ type GeneratorFunction = (context: GeneratorContext) => Promise<ScaffoldResult>;
91
+ //#endregion
92
+ //#region src/services/ProjectFinderService.d.ts
93
+ declare class ProjectFinderService {
94
+ private projectCache;
95
+ private workspaceRoot;
96
+ constructor(workspaceRoot?: string);
97
+ /**
98
+ * Find the project containing a given file by walking up the directory tree
99
+ *
100
+ * @param filePath - Absolute path to the file
101
+ * @returns Project configuration or null if not found
102
+ */
103
+ findProjectForFile(filePath: string): Promise<ProjectConfig | null>;
104
+ /**
105
+ * Find the project containing a given file (synchronous version)
106
+ *
107
+ * @param filePath - Absolute path to the file
108
+ * @returns Project configuration or null if not found
109
+ */
110
+ findProjectForFileSync(filePath: string): ProjectConfig | null;
111
+ /**
112
+ * Load and parse a project.json file
113
+ */
114
+ private loadProjectConfig;
115
+ /**
116
+ * Load and parse a project.json file (synchronous version)
117
+ */
118
+ private loadProjectConfigSync;
119
+ /**
120
+ * Get the workspace root
121
+ */
122
+ getWorkspaceRoot(): string;
123
+ /**
124
+ * Clear the project cache
125
+ */
126
+ clearCache(): void;
127
+ }
128
+ //#endregion
129
+ //#region src/services/ScaffoldProcessingService.d.ts
130
+ /**
131
+ * Shared service for common scaffolding operations like processing templates and tracking files
132
+ */
133
+ declare class ScaffoldProcessingService {
134
+ private fileSystem;
135
+ private variableReplacer;
136
+ constructor(fileSystem: IFileSystemService, variableReplacer: IVariableReplacementService);
137
+ /**
138
+ * Process a target path for variable replacement, handling both files and directories
139
+ */
140
+ processTargetForVariableReplacement(targetPath: string, variables: Record<string, any>): Promise<void>;
141
+ /**
142
+ * Track all created files, handling both single files and directories
143
+ */
144
+ trackCreatedFiles(targetPath: string, createdFiles: string[]): Promise<void>;
145
+ /**
146
+ * Track all existing files, handling both single files and directories
147
+ */
148
+ trackExistingFiles(targetPath: string, existingFiles: string[]): Promise<void>;
149
+ /**
150
+ * Copy source to target, then process templates and track files
151
+ * Now supports tracking existing files separately from created files
152
+ */
153
+ copyAndProcess(sourcePath: string, targetPath: string, variables: Record<string, any>, createdFiles: string[], existingFiles?: string[]): Promise<void>;
154
+ /**
155
+ * Recursively collect all file paths in a directory for created files
156
+ */
157
+ private trackCreatedFilesRecursive;
158
+ /**
159
+ * Recursively collect all file paths in a directory for existing files
160
+ */
161
+ private trackExistingFilesRecursive;
162
+ }
163
+ //#endregion
164
+ //#region src/services/TemplatesManagerService.d.ts
165
+ /**
166
+ * TemplatesManagerService
167
+ *
168
+ * DESIGN PATTERNS:
169
+ * - Class-based service pattern for encapsulating business logic
170
+ * - Static methods for utility-like functionality
171
+ * - File system traversal for workspace detection
172
+ * - Configuration-driven template path resolution
173
+ *
174
+ * CODING STANDARDS:
175
+ * - Service class names use PascalCase with 'Service' suffix
176
+ * - Method names use camelCase with descriptive verbs
177
+ * - Return types should be explicit (never use implicit any)
178
+ * - Use async/await for asynchronous operations
179
+ * - Handle errors with try-catch and throw descriptive Error objects
180
+ * - Document public methods with JSDoc comments
181
+ *
182
+ * AVOID:
183
+ * - Side effects in constructors (keep them lightweight)
184
+ * - Mixing concerns (keep services focused on single domain)
185
+ * - Direct coupling to other services (use dependency injection)
186
+ * - Exposing internal implementation details
187
+ */
188
+ declare class TemplatesManagerService {
189
+ private static SCAFFOLD_CONFIG_FILE;
190
+ private static TEMPLATES_FOLDER;
191
+ private static TOOLKIT_CONFIG_FILE;
192
+ /**
193
+ * Find the templates directory by searching upwards from the starting path.
194
+ *
195
+ * Algorithm:
196
+ * 1. Start from the provided path (default: current working directory)
197
+ * 2. Search upwards to find the workspace root (where .git exists or filesystem root)
198
+ * 3. Check if toolkit.yaml exists at workspace root
199
+ * - If yes, read templatesPath from toolkit.yaml
200
+ * - If no, default to 'templates' folder in workspace root
201
+ * 4. Verify the templates directory exists
202
+ *
203
+ * @param startPath - The path to start searching from (defaults to process.cwd())
204
+ * @returns The absolute path to the templates directory
205
+ * @throws Error if templates directory is not found
206
+ */
207
+ static findTemplatesPath(startPath?: string): Promise<string>;
208
+ /**
209
+ * Find the workspace root by searching upwards for .git folder
210
+ */
211
+ private static findWorkspaceRoot;
212
+ /**
213
+ * Get the templates path synchronously.
214
+ * Use this when you need immediate access and are sure templates exist.
215
+ *
216
+ * @param startPath - The path to start searching from (defaults to process.cwd())
217
+ * @returns The absolute path to the templates directory
218
+ * @throws Error if templates directory is not found
219
+ */
220
+ static findTemplatesPathSync(startPath?: string): string;
221
+ /**
222
+ * Find the workspace root synchronously by searching upwards for .git folder
223
+ */
224
+ private static findWorkspaceRootSync;
225
+ /**
226
+ * Check if templates are initialized at the given path
227
+ *
228
+ * @param templatesPath - Path to check for templates
229
+ * @returns true if templates folder exists and is a directory
230
+ */
231
+ static isInitialized(templatesPath: string): Promise<boolean>;
232
+ /**
233
+ * Get the scaffold config file name
234
+ */
235
+ static getConfigFileName(): string;
236
+ /**
237
+ * Get the templates folder name
238
+ */
239
+ static getTemplatesFolderName(): string;
240
+ }
241
+ //#endregion
242
+ export { GeneratorContext, GeneratorFunction, IFileSystemService, IVariableReplacementService, ParsedInclude, ProjectConfig, ProjectFinderService, ScaffoldProcessingService, ScaffoldResult, TemplatesManagerService };
package/dist/index.js ADDED
@@ -0,0 +1,315 @@
1
+ import { createRequire } from "node:module";
2
+ import path from "node:path";
3
+ import * as fs from "fs-extra";
4
+
5
+ //#region rolldown:runtime
6
+ var __require = /* @__PURE__ */ createRequire(import.meta.url);
7
+
8
+ //#endregion
9
+ //#region src/services/ProjectFinderService.ts
10
+ var ProjectFinderService = class {
11
+ projectCache = /* @__PURE__ */ new Map();
12
+ workspaceRoot;
13
+ constructor(workspaceRoot) {
14
+ this.workspaceRoot = workspaceRoot || process.cwd();
15
+ }
16
+ /**
17
+ * Find the project containing a given file by walking up the directory tree
18
+ *
19
+ * @param filePath - Absolute path to the file
20
+ * @returns Project configuration or null if not found
21
+ */
22
+ async findProjectForFile(filePath) {
23
+ const normalizedPath = path.isAbsolute(filePath) ? filePath : path.join(this.workspaceRoot, filePath);
24
+ let currentDir = path.dirname(normalizedPath);
25
+ while (currentDir !== "/" && currentDir.startsWith(this.workspaceRoot)) {
26
+ const projectJsonPath = path.join(currentDir, "project.json");
27
+ try {
28
+ const project = await this.loadProjectConfig(projectJsonPath);
29
+ if (project) return project;
30
+ } catch {}
31
+ currentDir = path.dirname(currentDir);
32
+ }
33
+ return null;
34
+ }
35
+ /**
36
+ * Find the project containing a given file (synchronous version)
37
+ *
38
+ * @param filePath - Absolute path to the file
39
+ * @returns Project configuration or null if not found
40
+ */
41
+ findProjectForFileSync(filePath) {
42
+ const normalizedPath = path.isAbsolute(filePath) ? filePath : path.join(this.workspaceRoot, filePath);
43
+ let currentDir = path.dirname(normalizedPath);
44
+ while (currentDir !== "/" && currentDir.startsWith(this.workspaceRoot)) {
45
+ const projectJsonPath = path.join(currentDir, "project.json");
46
+ try {
47
+ const project = this.loadProjectConfigSync(projectJsonPath);
48
+ if (project) return project;
49
+ } catch {}
50
+ currentDir = path.dirname(currentDir);
51
+ }
52
+ return null;
53
+ }
54
+ /**
55
+ * Load and parse a project.json file
56
+ */
57
+ async loadProjectConfig(projectJsonPath) {
58
+ if (this.projectCache.has(projectJsonPath)) return this.projectCache.get(projectJsonPath);
59
+ try {
60
+ const content = await fs.readFile(projectJsonPath, "utf-8");
61
+ const config = JSON.parse(content);
62
+ const projectConfig = {
63
+ name: config.name || path.basename(path.dirname(projectJsonPath)),
64
+ root: path.dirname(projectJsonPath),
65
+ sourceTemplate: config.sourceTemplate,
66
+ projectType: config.projectType
67
+ };
68
+ this.projectCache.set(projectJsonPath, projectConfig);
69
+ return projectConfig;
70
+ } catch {
71
+ return null;
72
+ }
73
+ }
74
+ /**
75
+ * Load and parse a project.json file (synchronous version)
76
+ */
77
+ loadProjectConfigSync(projectJsonPath) {
78
+ if (this.projectCache.has(projectJsonPath)) return this.projectCache.get(projectJsonPath);
79
+ try {
80
+ const content = fs.readFileSync(projectJsonPath, "utf-8");
81
+ const config = JSON.parse(content);
82
+ const projectConfig = {
83
+ name: config.name || path.basename(path.dirname(projectJsonPath)),
84
+ root: path.dirname(projectJsonPath),
85
+ sourceTemplate: config.sourceTemplate,
86
+ projectType: config.projectType
87
+ };
88
+ this.projectCache.set(projectJsonPath, projectConfig);
89
+ return projectConfig;
90
+ } catch {
91
+ return null;
92
+ }
93
+ }
94
+ /**
95
+ * Get the workspace root
96
+ */
97
+ getWorkspaceRoot() {
98
+ return this.workspaceRoot;
99
+ }
100
+ /**
101
+ * Clear the project cache
102
+ */
103
+ clearCache() {
104
+ this.projectCache.clear();
105
+ }
106
+ };
107
+
108
+ //#endregion
109
+ //#region src/services/ScaffoldProcessingService.ts
110
+ /**
111
+ * Shared service for common scaffolding operations like processing templates and tracking files
112
+ */
113
+ var ScaffoldProcessingService = class {
114
+ constructor(fileSystem, variableReplacer) {
115
+ this.fileSystem = fileSystem;
116
+ this.variableReplacer = variableReplacer;
117
+ }
118
+ /**
119
+ * Process a target path for variable replacement, handling both files and directories
120
+ */
121
+ async processTargetForVariableReplacement(targetPath, variables) {
122
+ if ((await this.fileSystem.stat(targetPath)).isDirectory()) await this.variableReplacer.processFilesForVariableReplacement(targetPath, variables);
123
+ else await this.variableReplacer.replaceVariablesInFile(targetPath, variables);
124
+ }
125
+ /**
126
+ * Track all created files, handling both single files and directories
127
+ */
128
+ async trackCreatedFiles(targetPath, createdFiles) {
129
+ if ((await this.fileSystem.stat(targetPath)).isDirectory()) await this.trackCreatedFilesRecursive(targetPath, createdFiles);
130
+ else createdFiles.push(targetPath);
131
+ }
132
+ /**
133
+ * Track all existing files, handling both single files and directories
134
+ */
135
+ async trackExistingFiles(targetPath, existingFiles) {
136
+ if ((await this.fileSystem.stat(targetPath)).isDirectory()) await this.trackExistingFilesRecursive(targetPath, existingFiles);
137
+ else existingFiles.push(targetPath);
138
+ }
139
+ /**
140
+ * Copy source to target, then process templates and track files
141
+ * Now supports tracking existing files separately from created files
142
+ */
143
+ async copyAndProcess(sourcePath, targetPath, variables, createdFiles, existingFiles) {
144
+ await this.fileSystem.ensureDir(path.dirname(targetPath));
145
+ if (await this.fileSystem.pathExists(targetPath) && existingFiles) {
146
+ await this.trackExistingFiles(targetPath, existingFiles);
147
+ return;
148
+ }
149
+ await this.fileSystem.copy(sourcePath, targetPath);
150
+ await this.processTargetForVariableReplacement(targetPath, variables);
151
+ await this.trackCreatedFiles(targetPath, createdFiles);
152
+ }
153
+ /**
154
+ * Recursively collect all file paths in a directory for created files
155
+ */
156
+ async trackCreatedFilesRecursive(dirPath, createdFiles) {
157
+ let items = [];
158
+ try {
159
+ items = await this.fileSystem.readdir(dirPath);
160
+ } catch (error) {
161
+ console.warn(`Cannot read directory ${dirPath}: ${error}`);
162
+ return;
163
+ }
164
+ for (const item of items) {
165
+ if (!item) continue;
166
+ const itemPath = path.join(dirPath, item);
167
+ try {
168
+ const stat = await this.fileSystem.stat(itemPath);
169
+ if (stat.isDirectory()) await this.trackCreatedFilesRecursive(itemPath, createdFiles);
170
+ else if (stat.isFile()) createdFiles.push(itemPath);
171
+ } catch (error) {
172
+ console.warn(`Cannot stat ${itemPath}: ${error}`);
173
+ }
174
+ }
175
+ }
176
+ /**
177
+ * Recursively collect all file paths in a directory for existing files
178
+ */
179
+ async trackExistingFilesRecursive(dirPath, existingFiles) {
180
+ let items = [];
181
+ try {
182
+ items = await this.fileSystem.readdir(dirPath);
183
+ } catch (error) {
184
+ console.warn(`Cannot read directory ${dirPath}: ${error}`);
185
+ return;
186
+ }
187
+ for (const item of items) {
188
+ if (!item) continue;
189
+ const itemPath = path.join(dirPath, item);
190
+ try {
191
+ const stat = await this.fileSystem.stat(itemPath);
192
+ if (stat.isDirectory()) await this.trackExistingFilesRecursive(itemPath, existingFiles);
193
+ else if (stat.isFile()) existingFiles.push(itemPath);
194
+ } catch (error) {
195
+ console.warn(`Cannot stat ${itemPath}: ${error}`);
196
+ }
197
+ }
198
+ }
199
+ };
200
+
201
+ //#endregion
202
+ //#region src/services/TemplatesManagerService.ts
203
+ var TemplatesManagerService = class TemplatesManagerService {
204
+ static SCAFFOLD_CONFIG_FILE = "scaffold.yaml";
205
+ static TEMPLATES_FOLDER = "templates";
206
+ static TOOLKIT_CONFIG_FILE = "toolkit.yaml";
207
+ /**
208
+ * Find the templates directory by searching upwards from the starting path.
209
+ *
210
+ * Algorithm:
211
+ * 1. Start from the provided path (default: current working directory)
212
+ * 2. Search upwards to find the workspace root (where .git exists or filesystem root)
213
+ * 3. Check if toolkit.yaml exists at workspace root
214
+ * - If yes, read templatesPath from toolkit.yaml
215
+ * - If no, default to 'templates' folder in workspace root
216
+ * 4. Verify the templates directory exists
217
+ *
218
+ * @param startPath - The path to start searching from (defaults to process.cwd())
219
+ * @returns The absolute path to the templates directory
220
+ * @throws Error if templates directory is not found
221
+ */
222
+ static async findTemplatesPath(startPath = process.cwd()) {
223
+ const workspaceRoot = await TemplatesManagerService.findWorkspaceRoot(startPath);
224
+ const toolkitConfigPath = path.join(workspaceRoot, TemplatesManagerService.TOOLKIT_CONFIG_FILE);
225
+ if (await fs.pathExists(toolkitConfigPath)) {
226
+ const yaml = await import("js-yaml");
227
+ const content = await fs.readFile(toolkitConfigPath, "utf-8");
228
+ const config = yaml.load(content);
229
+ if (config?.templatesPath) {
230
+ const templatesPath$1 = path.isAbsolute(config.templatesPath) ? config.templatesPath : path.join(workspaceRoot, config.templatesPath);
231
+ if (await fs.pathExists(templatesPath$1)) return templatesPath$1;
232
+ else throw new Error(`Templates path specified in toolkit.yaml does not exist: ${templatesPath$1}`);
233
+ }
234
+ }
235
+ const templatesPath = path.join(workspaceRoot, TemplatesManagerService.TEMPLATES_FOLDER);
236
+ if (await fs.pathExists(templatesPath)) return templatesPath;
237
+ throw new Error(`Templates folder not found at ${templatesPath}.\nEither create a 'templates' folder or specify templatesPath in toolkit.yaml`);
238
+ }
239
+ /**
240
+ * Find the workspace root by searching upwards for .git folder
241
+ */
242
+ static async findWorkspaceRoot(startPath) {
243
+ let currentPath = path.resolve(startPath);
244
+ const rootPath = path.parse(currentPath).root;
245
+ while (true) {
246
+ const gitPath = path.join(currentPath, ".git");
247
+ if (await fs.pathExists(gitPath)) return currentPath;
248
+ if (currentPath === rootPath) return process.cwd();
249
+ currentPath = path.dirname(currentPath);
250
+ }
251
+ }
252
+ /**
253
+ * Get the templates path synchronously.
254
+ * Use this when you need immediate access and are sure templates exist.
255
+ *
256
+ * @param startPath - The path to start searching from (defaults to process.cwd())
257
+ * @returns The absolute path to the templates directory
258
+ * @throws Error if templates directory is not found
259
+ */
260
+ static findTemplatesPathSync(startPath = process.cwd()) {
261
+ const workspaceRoot = TemplatesManagerService.findWorkspaceRootSync(startPath);
262
+ const toolkitConfigPath = path.join(workspaceRoot, TemplatesManagerService.TOOLKIT_CONFIG_FILE);
263
+ if (fs.pathExistsSync(toolkitConfigPath)) {
264
+ const yaml = __require("js-yaml");
265
+ const content = fs.readFileSync(toolkitConfigPath, "utf-8");
266
+ const config = yaml.load(content);
267
+ if (config?.templatesPath) {
268
+ const templatesPath$1 = path.isAbsolute(config.templatesPath) ? config.templatesPath : path.join(workspaceRoot, config.templatesPath);
269
+ if (fs.pathExistsSync(templatesPath$1)) return templatesPath$1;
270
+ else throw new Error(`Templates path specified in toolkit.yaml does not exist: ${templatesPath$1}`);
271
+ }
272
+ }
273
+ const templatesPath = path.join(workspaceRoot, TemplatesManagerService.TEMPLATES_FOLDER);
274
+ if (fs.pathExistsSync(templatesPath)) return templatesPath;
275
+ throw new Error(`Templates folder not found at ${templatesPath}.\nEither create a 'templates' folder or specify templatesPath in toolkit.yaml`);
276
+ }
277
+ /**
278
+ * Find the workspace root synchronously by searching upwards for .git folder
279
+ */
280
+ static findWorkspaceRootSync(startPath) {
281
+ let currentPath = path.resolve(startPath);
282
+ const rootPath = path.parse(currentPath).root;
283
+ while (true) {
284
+ const gitPath = path.join(currentPath, ".git");
285
+ if (fs.pathExistsSync(gitPath)) return currentPath;
286
+ if (currentPath === rootPath) return process.cwd();
287
+ currentPath = path.dirname(currentPath);
288
+ }
289
+ }
290
+ /**
291
+ * Check if templates are initialized at the given path
292
+ *
293
+ * @param templatesPath - Path to check for templates
294
+ * @returns true if templates folder exists and is a directory
295
+ */
296
+ static async isInitialized(templatesPath) {
297
+ if (!await fs.pathExists(templatesPath)) return false;
298
+ return (await fs.stat(templatesPath)).isDirectory();
299
+ }
300
+ /**
301
+ * Get the scaffold config file name
302
+ */
303
+ static getConfigFileName() {
304
+ return TemplatesManagerService.SCAFFOLD_CONFIG_FILE;
305
+ }
306
+ /**
307
+ * Get the templates folder name
308
+ */
309
+ static getTemplatesFolderName() {
310
+ return TemplatesManagerService.TEMPLATES_FOLDER;
311
+ }
312
+ };
313
+
314
+ //#endregion
315
+ export { ProjectFinderService, ScaffoldProcessingService, TemplatesManagerService };
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@agiflowai/aicode-utils",
3
+ "description": "Shared utilities and types for AI-powered code generation, scaffolding, and analysis",
4
+ "version": "0.4.0",
5
+ "license": "AGPL-3.0",
6
+ "author": "AgiflowIO",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/AgiFlow/aicode-toolkit.git",
10
+ "directory": "packages/aicode-utils"
11
+ },
12
+ "homepage": "https://github.com/AgiFlow/aicode-toolkit#readme",
13
+ "bugs": {
14
+ "url": "https://github.com/AgiFlow/aicode-toolkit/issues"
15
+ },
16
+ "keywords": [
17
+ "typescript",
18
+ "library",
19
+ "scaffold",
20
+ "generator",
21
+ "template",
22
+ "boilerplate",
23
+ "code-generation"
24
+ ],
25
+ "main": "./dist/index.cjs",
26
+ "module": "./dist/index.js",
27
+ "types": "./dist/index.d.ts",
28
+ "files": [
29
+ "dist",
30
+ "README.md"
31
+ ],
32
+ "dependencies": {
33
+ "fs-extra": "11.3.2",
34
+ "js-yaml": "4.1.0"
35
+ },
36
+ "devDependencies": {
37
+ "@types/fs-extra": "^11.0.4",
38
+ "@types/js-yaml": "^4.0.9",
39
+ "@types/node": "^22.0.0",
40
+ "@vitest/coverage-v8": "^3.0.0",
41
+ "tsdown": "^0.15.6",
42
+ "typescript": "5.9.3",
43
+ "vitest": "^3.0.0"
44
+ },
45
+ "type": "module",
46
+ "publishConfig": {
47
+ "access": "public"
48
+ },
49
+ "scripts": {
50
+ "build": "tsdown",
51
+ "test": "vitest --run",
52
+ "typecheck": "tsc --noEmit"
53
+ }
54
+ }