@gravito/scaffold 4.1.0 → 4.1.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 +2550 -188
- package/dist/index.d.cts +924 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2547 -188
- package/package.json +1 -1
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,924 @@
|
|
|
1
|
+
import Handlebars from 'handlebars';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Supported project profiles defining the set of included orbits and default drivers.
|
|
5
|
+
*
|
|
6
|
+
* @public
|
|
7
|
+
* @since 3.0.0
|
|
8
|
+
*/
|
|
9
|
+
type ProfileType = 'core' | 'scale' | 'enterprise';
|
|
10
|
+
/**
|
|
11
|
+
* Resolved configuration for a project profile.
|
|
12
|
+
*
|
|
13
|
+
* @public
|
|
14
|
+
* @since 3.0.0
|
|
15
|
+
*/
|
|
16
|
+
interface ProfileConfig {
|
|
17
|
+
/** Map of default service drivers. */
|
|
18
|
+
drivers: {
|
|
19
|
+
database: string;
|
|
20
|
+
cache: string;
|
|
21
|
+
queue: string;
|
|
22
|
+
storage: string;
|
|
23
|
+
session: string;
|
|
24
|
+
};
|
|
25
|
+
/** List of enabled features and orbits. */
|
|
26
|
+
features: string[];
|
|
27
|
+
/** Workers configuration level for job queue system */
|
|
28
|
+
workers?: 'basic' | 'advanced' | 'production';
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* ProfileResolver manages the resolution of project profiles and feature add-ons.
|
|
32
|
+
*
|
|
33
|
+
* It maps high-level profiles (Core, Scale, Enterprise) to specific sets of
|
|
34
|
+
* service drivers and orbits, and handles the conditional inclusion of
|
|
35
|
+
* additional features.
|
|
36
|
+
*
|
|
37
|
+
* @public
|
|
38
|
+
* @since 3.0.0
|
|
39
|
+
*/
|
|
40
|
+
declare class ProfileResolver {
|
|
41
|
+
private static readonly DEFAULTS;
|
|
42
|
+
resolve(profile?: ProfileType, withFeatures?: string[]): ProfileConfig;
|
|
43
|
+
private applyFeature;
|
|
44
|
+
/**
|
|
45
|
+
* Validator for profile names
|
|
46
|
+
*/
|
|
47
|
+
isValidProfile(profile: string): profile is ProfileType;
|
|
48
|
+
/**
|
|
49
|
+
* Validator for feature names
|
|
50
|
+
*/
|
|
51
|
+
isValidFeature(feature: string): boolean;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* package.json 結構
|
|
56
|
+
*/
|
|
57
|
+
interface PackageJson {
|
|
58
|
+
name?: string;
|
|
59
|
+
version?: string;
|
|
60
|
+
dependencies?: Record<string, string>;
|
|
61
|
+
devDependencies?: Record<string, string>;
|
|
62
|
+
[key: string]: unknown;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* 驗證結果
|
|
66
|
+
*/
|
|
67
|
+
interface ValidationResult {
|
|
68
|
+
/** 是否通過驗證 */
|
|
69
|
+
valid: boolean;
|
|
70
|
+
/** 錯誤訊息列表 (阻塞性問題) */
|
|
71
|
+
errors: string[];
|
|
72
|
+
/** 警告訊息列表 (非阻塞性問題) */
|
|
73
|
+
warnings: string[];
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* 依賴驗證器
|
|
77
|
+
*
|
|
78
|
+
* 負責驗證 Profile 配置的依賴完整性,包括:
|
|
79
|
+
* - Driver 必需的 packages
|
|
80
|
+
* - Feature 之間的衝突
|
|
81
|
+
* - Feature 的依賴關係
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* ```typescript
|
|
85
|
+
* const validator = new DependencyValidator()
|
|
86
|
+
* const result = validator.validate(profileConfig, packageJson)
|
|
87
|
+
*
|
|
88
|
+
* if (!result.valid) {
|
|
89
|
+
* console.error('依賴驗證失敗:', result.errors)
|
|
90
|
+
* }
|
|
91
|
+
* ```
|
|
92
|
+
*
|
|
93
|
+
* @since 3.1.0
|
|
94
|
+
* @public
|
|
95
|
+
*/
|
|
96
|
+
declare class DependencyValidator {
|
|
97
|
+
/**
|
|
98
|
+
* Driver 到 Package 的映射規則
|
|
99
|
+
*/
|
|
100
|
+
private static readonly DRIVER_DEPENDENCIES;
|
|
101
|
+
/**
|
|
102
|
+
* Feature 衝突規則
|
|
103
|
+
*/
|
|
104
|
+
private static readonly CONFLICTS;
|
|
105
|
+
/**
|
|
106
|
+
* Feature 依賴映射
|
|
107
|
+
*/
|
|
108
|
+
private static readonly FEATURE_DEPENDENCIES;
|
|
109
|
+
/**
|
|
110
|
+
* 驗證 Profile 配置
|
|
111
|
+
*
|
|
112
|
+
* @param config - Profile 配置
|
|
113
|
+
* @param packageJson - 專案的 package.json 內容
|
|
114
|
+
* @returns 驗證結果
|
|
115
|
+
*/
|
|
116
|
+
validate(config: ProfileConfig, packageJson: PackageJson): ValidationResult;
|
|
117
|
+
/**
|
|
118
|
+
* 驗證 driver 依賴
|
|
119
|
+
*/
|
|
120
|
+
private validateDriverDependencies;
|
|
121
|
+
/**
|
|
122
|
+
* 驗證 feature 衝突
|
|
123
|
+
*/
|
|
124
|
+
private validateFeatureConflicts;
|
|
125
|
+
/**
|
|
126
|
+
* 驗證 feature 依賴
|
|
127
|
+
*/
|
|
128
|
+
private validateFeatureDependencies;
|
|
129
|
+
/**
|
|
130
|
+
* 檢查 package.json 是否包含指定 package
|
|
131
|
+
*/
|
|
132
|
+
private hasPackage;
|
|
133
|
+
/**
|
|
134
|
+
* 建議安裝缺失的依賴
|
|
135
|
+
*
|
|
136
|
+
* @param result - 驗證結果
|
|
137
|
+
* @returns 安裝命令建議
|
|
138
|
+
*/
|
|
139
|
+
static suggestInstallCommand(result: ValidationResult): string | null;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Represents the results of an environment detection scan.
|
|
144
|
+
*
|
|
145
|
+
* @public
|
|
146
|
+
* @since 3.0.0
|
|
147
|
+
*/
|
|
148
|
+
interface DetectedEnvironment {
|
|
149
|
+
/** The detected cloud or hosting platform. */
|
|
150
|
+
platform: 'aws' | 'gcp' | 'azure' | 'k8s' | 'vercel' | 'netlify' | 'unknown';
|
|
151
|
+
/** The project profile most suitable for this environment. */
|
|
152
|
+
suggestedProfile: ProfileType;
|
|
153
|
+
/** The degree of certainty in the detection. */
|
|
154
|
+
confidence: 'high' | 'medium' | 'low';
|
|
155
|
+
/** The reason or heuristic used for the detection. */
|
|
156
|
+
reason: string;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* EnvironmentDetector inspects environment variables to identify the hosting platform.
|
|
160
|
+
*
|
|
161
|
+
* It uses these heuristics to suggest the most appropriate project profile
|
|
162
|
+
* (Core, Scale, or Enterprise) for the current environment.
|
|
163
|
+
*
|
|
164
|
+
* @public
|
|
165
|
+
* @since 3.0.0
|
|
166
|
+
*/
|
|
167
|
+
declare class EnvironmentDetector {
|
|
168
|
+
detect(): DetectedEnvironment;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* FileMerger handles the intelligent merging of file contents during scaffolding.
|
|
173
|
+
*
|
|
174
|
+
* It understands different file formats (JSON, ENV) and applies appropriate
|
|
175
|
+
* merging strategies instead of simple overwriting.
|
|
176
|
+
*
|
|
177
|
+
* @public
|
|
178
|
+
* @since 3.0.0
|
|
179
|
+
*/
|
|
180
|
+
declare class FileMerger {
|
|
181
|
+
/**
|
|
182
|
+
* Merge content of two files based on their type.
|
|
183
|
+
*/
|
|
184
|
+
merge(fileName: string, baseContent: string, overlayContent: string): string;
|
|
185
|
+
private mergeJson;
|
|
186
|
+
private mergeEnv;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Architecture patterns supported by the scaffolding engine.
|
|
191
|
+
*
|
|
192
|
+
* @public
|
|
193
|
+
* @since 3.0.0
|
|
194
|
+
*/
|
|
195
|
+
type ArchitectureType = 'enterprise-mvc' | 'clean' | 'ddd' | 'satellite' | 'action-domain' | 'standalone-engine';
|
|
196
|
+
/**
|
|
197
|
+
* Configuration options for creating a new project via Scaffold.
|
|
198
|
+
*
|
|
199
|
+
* @public
|
|
200
|
+
* @since 3.0.0
|
|
201
|
+
*/
|
|
202
|
+
interface ScaffoldOptions {
|
|
203
|
+
/** The name of the new project (e.g., 'my-api'). */
|
|
204
|
+
name: string;
|
|
205
|
+
/** Absolute path where the project files should be generated. */
|
|
206
|
+
targetDir: string;
|
|
207
|
+
/** The primary architectural pattern to apply. */
|
|
208
|
+
architecture: ArchitectureType;
|
|
209
|
+
/** For DDD architecture: the module template type. @default 'simple' */
|
|
210
|
+
dddModuleType?: 'simple' | 'advanced' | 'cqrs-query';
|
|
211
|
+
/** Preferred package manager for dependency installation. @default 'bun' */
|
|
212
|
+
packageManager?: 'bun' | 'npm' | 'yarn' | 'pnpm';
|
|
213
|
+
/** Whether to run `git init` in the target directory. @default true */
|
|
214
|
+
initGit?: boolean;
|
|
215
|
+
/** Whether to automatically run `install` after file generation. @default true */
|
|
216
|
+
installDeps?: boolean;
|
|
217
|
+
/** If true, includes the Spectrum observability dashboard in the scaffolded app. */
|
|
218
|
+
withSpectrum?: boolean;
|
|
219
|
+
/** Internal flag for official Gravito satellite projects. */
|
|
220
|
+
isInternal?: boolean;
|
|
221
|
+
/** Selected project profile determining the set of included orbits/packages. */
|
|
222
|
+
profile?: 'core' | 'scale' | 'enterprise';
|
|
223
|
+
/** List of additional feature orbits to include (e.g., 'redis', 'queue', 'otel'). */
|
|
224
|
+
features?: string[];
|
|
225
|
+
/** Additional template variables to be used during file generation. */
|
|
226
|
+
context?: Record<string, unknown>;
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* The outcome of a scaffolding operation.
|
|
230
|
+
*
|
|
231
|
+
* @public
|
|
232
|
+
* @since 3.0.0
|
|
233
|
+
*/
|
|
234
|
+
interface ScaffoldResult {
|
|
235
|
+
/** True if the operation completed without fatal errors. */
|
|
236
|
+
success: boolean;
|
|
237
|
+
/** The absolute path where the project was created. */
|
|
238
|
+
targetDir: string;
|
|
239
|
+
/** List of relative file paths that were successfully generated. */
|
|
240
|
+
filesCreated: string[];
|
|
241
|
+
/** Any non-fatal error messages encountered during generation. */
|
|
242
|
+
errors?: string[];
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Represents a node in the project file structure blueprint.
|
|
246
|
+
*
|
|
247
|
+
* Used to define the skeleton of a new project before generation.
|
|
248
|
+
*
|
|
249
|
+
* @public
|
|
250
|
+
* @since 3.0.0
|
|
251
|
+
*/
|
|
252
|
+
interface DirectoryNode {
|
|
253
|
+
/** The type of node (file vs folder). */
|
|
254
|
+
type: 'file' | 'directory';
|
|
255
|
+
/** The name of the file or directory. */
|
|
256
|
+
name: string;
|
|
257
|
+
/** Literal string content if this is a file node. */
|
|
258
|
+
content?: string;
|
|
259
|
+
/** The name or path of a template to use for this file's content. */
|
|
260
|
+
template?: string;
|
|
261
|
+
/** Nested nodes if this is a directory. */
|
|
262
|
+
children?: DirectoryNode[];
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
declare class TemplateManager {
|
|
266
|
+
private stubGenerator;
|
|
267
|
+
constructor(templatesDir: string);
|
|
268
|
+
render(template: string, context: Record<string, unknown>): string;
|
|
269
|
+
applyOverlay(sourceDir: string, targetDir: string, context: Record<string, unknown>, fileMerger: FileMerger, log?: (msg: string) => void): Promise<string[]>;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* BaseGenerator - Abstract base class for architecture generators.
|
|
274
|
+
*/
|
|
275
|
+
|
|
276
|
+
interface GeneratorContext {
|
|
277
|
+
name: string;
|
|
278
|
+
namePascalCase: string;
|
|
279
|
+
nameCamelCase: string;
|
|
280
|
+
nameSnakeCase: string;
|
|
281
|
+
nameKebabCase: string;
|
|
282
|
+
targetDir: string;
|
|
283
|
+
architecture: ArchitectureType;
|
|
284
|
+
packageManager: 'bun' | 'npm' | 'yarn' | 'pnpm';
|
|
285
|
+
year: string;
|
|
286
|
+
date: string;
|
|
287
|
+
[key: string]: unknown;
|
|
288
|
+
}
|
|
289
|
+
interface GeneratorConfig {
|
|
290
|
+
templatesDir: string;
|
|
291
|
+
verbose?: boolean;
|
|
292
|
+
}
|
|
293
|
+
declare abstract class BaseGenerator {
|
|
294
|
+
protected config: GeneratorConfig;
|
|
295
|
+
protected templateManager: TemplateManager;
|
|
296
|
+
protected fileMerger: FileMerger;
|
|
297
|
+
protected filesCreated: string[];
|
|
298
|
+
protected context: GeneratorContext | null;
|
|
299
|
+
constructor(config: GeneratorConfig);
|
|
300
|
+
abstract get architectureType(): ArchitectureType;
|
|
301
|
+
abstract get displayName(): string;
|
|
302
|
+
abstract get description(): string;
|
|
303
|
+
abstract getDirectoryStructure(context: GeneratorContext): DirectoryNode[];
|
|
304
|
+
generate(context: GeneratorContext): Promise<string[]>;
|
|
305
|
+
protected createStructure(basePath: string, nodes: DirectoryNode[], context: GeneratorContext): Promise<void>;
|
|
306
|
+
protected generateCommonFiles(context: GeneratorContext): Promise<void>;
|
|
307
|
+
protected generateFileFromTemplate(tplDir: string, tplName: string, targetName: string, context: GeneratorContext): Promise<void>;
|
|
308
|
+
protected generateSkills(context: GeneratorContext): Promise<void>;
|
|
309
|
+
protected applyOverlays(context: GeneratorContext): Promise<void>;
|
|
310
|
+
protected applyFeatureOverlays(context: GeneratorContext): Promise<void>;
|
|
311
|
+
protected copyOverlayDirectory(sourceDir: string, context: GeneratorContext): Promise<void>;
|
|
312
|
+
protected writeFile(basePath: string, relativePath: string, content: string): Promise<void>;
|
|
313
|
+
protected generatePackageJson(context: GeneratorContext): string;
|
|
314
|
+
protected abstract generateArchitectureDoc(context: GeneratorContext): string;
|
|
315
|
+
protected generateCheckScripts(context: GeneratorContext): Promise<void>;
|
|
316
|
+
protected log(message: string): void;
|
|
317
|
+
static createContext(name: string, targetDir: string, architecture: ArchitectureType, packageManager?: 'bun' | 'npm' | 'yarn' | 'pnpm', extra?: Record<string, unknown>): GeneratorContext;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* CleanArchitectureGenerator - Clean Architecture Generator
|
|
322
|
+
*
|
|
323
|
+
* Generates a structure following Uncle Bob's Clean Architecture:
|
|
324
|
+
* - Domain: Entities, Value Objects, Interfaces (pure business logic)
|
|
325
|
+
* - Application: Use Cases, DTOs
|
|
326
|
+
* - Infrastructure: Database, External Services
|
|
327
|
+
* - Interface: HTTP Controllers, Presenters
|
|
328
|
+
*/
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* CleanArchitectureGenerator implements Uncle Bob's Clean Architecture pattern.
|
|
332
|
+
*
|
|
333
|
+
* It generates a strictly layered structure including Domain, Application,
|
|
334
|
+
* Infrastructure, and Interface layers, ensuring business logic is isolated
|
|
335
|
+
* from framework and external dependencies.
|
|
336
|
+
*
|
|
337
|
+
* @public
|
|
338
|
+
* @since 3.0.0
|
|
339
|
+
*/
|
|
340
|
+
declare class CleanArchitectureGenerator extends BaseGenerator {
|
|
341
|
+
get architectureType(): "clean";
|
|
342
|
+
get displayName(): string;
|
|
343
|
+
get description(): string;
|
|
344
|
+
getDirectoryStructure(context: GeneratorContext): DirectoryNode[];
|
|
345
|
+
private generateAppConfig;
|
|
346
|
+
private generateDatabaseConfig;
|
|
347
|
+
private generateAuthConfig;
|
|
348
|
+
private generateCacheConfig;
|
|
349
|
+
private generateLoggingConfig;
|
|
350
|
+
private generateUserEntity;
|
|
351
|
+
private generateEmailValueObject;
|
|
352
|
+
private generateUserRepositoryInterface;
|
|
353
|
+
private generateCreateUserUseCase;
|
|
354
|
+
private generateGetUserUseCase;
|
|
355
|
+
private generateUserDTO;
|
|
356
|
+
private generateMailServiceInterface;
|
|
357
|
+
private generateUserRepository;
|
|
358
|
+
private generateMailService;
|
|
359
|
+
private generateAppServiceProvider;
|
|
360
|
+
private generateRepositoryServiceProvider;
|
|
361
|
+
private generateProvidersIndex;
|
|
362
|
+
private generateMiddlewareProvider;
|
|
363
|
+
private generateRouteProvider;
|
|
364
|
+
private generateUserController;
|
|
365
|
+
private generateApiRoutes;
|
|
366
|
+
private generateUserPresenter;
|
|
367
|
+
private generateBootstrap;
|
|
368
|
+
protected generateArchitectureDoc(context: GeneratorContext): string;
|
|
369
|
+
protected generatePackageJson(context: GeneratorContext): string;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* DddGenerator - Domain-Driven Design Architecture Generator
|
|
374
|
+
*
|
|
375
|
+
* Generates a DDD structure with:
|
|
376
|
+
* - Bounded Contexts (e.g., Ordering, Catalog, Identity)
|
|
377
|
+
* - Shared Kernel for cross-context concerns
|
|
378
|
+
* - Each context has Domain, Application, Infrastructure, UserInterface layers
|
|
379
|
+
*/
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* DDD Module Type options
|
|
383
|
+
* - simple: Basic CRUD structure
|
|
384
|
+
* - advanced: Complete Event Sourcing with Aggregates, Events, EventStore, and EventApplier
|
|
385
|
+
* - cqrs-query: CQRS Query Side with Read Models, Event Projectors, Query Services
|
|
386
|
+
*/
|
|
387
|
+
type DddModuleType = 'simple' | 'advanced' | 'cqrs-query';
|
|
388
|
+
/**
|
|
389
|
+
* DddGenerator implements the full Domain-Driven Design (DDD) architectural pattern.
|
|
390
|
+
*
|
|
391
|
+
* It generates a sophisticated structure including Bounded Contexts, Aggregates,
|
|
392
|
+
* Value Objects, Domain Events, and a Shared Kernel. It is ideal for complex
|
|
393
|
+
* enterprise applications with rich business logic.
|
|
394
|
+
*
|
|
395
|
+
* Supports multiple module templates:
|
|
396
|
+
* - **simple**: Basic DDD structure with CRUD operations
|
|
397
|
+
* - **advanced**: Complete Event Sourcing with Aggregate Roots, Domain Events, EventStore
|
|
398
|
+
* - **cqrs-query**: CQRS read-side with Event Projectors and denormalized Read Models
|
|
399
|
+
*
|
|
400
|
+
* @public
|
|
401
|
+
* @since 3.0.0
|
|
402
|
+
*/
|
|
403
|
+
declare class DddGenerator extends BaseGenerator {
|
|
404
|
+
private moduleGenerator;
|
|
405
|
+
private advancedModuleGenerator;
|
|
406
|
+
private cqrsQueryModuleGenerator;
|
|
407
|
+
private sharedKernelGenerator;
|
|
408
|
+
private bootstrapGenerator;
|
|
409
|
+
private moduleType;
|
|
410
|
+
constructor(config: GeneratorConfig);
|
|
411
|
+
/**
|
|
412
|
+
* Set the module type for generated modules
|
|
413
|
+
* @param type - 'simple' for basic CRUD, 'advanced' for Event Sourcing, 'cqrs-query' for CQRS Read Side
|
|
414
|
+
* @default 'simple'
|
|
415
|
+
*/
|
|
416
|
+
setModuleType(type: DddModuleType): void;
|
|
417
|
+
get architectureType(): "ddd";
|
|
418
|
+
get displayName(): string;
|
|
419
|
+
get description(): string;
|
|
420
|
+
getDirectoryStructure(context: GeneratorContext): DirectoryNode[];
|
|
421
|
+
/**
|
|
422
|
+
* Get the active module generator type
|
|
423
|
+
*/
|
|
424
|
+
private getModuleGenerator;
|
|
425
|
+
/**
|
|
426
|
+
* Override package.json for DDD architecture (uses main.ts instead of bootstrap.ts)
|
|
427
|
+
*/
|
|
428
|
+
protected generatePackageJson(context: GeneratorContext): string;
|
|
429
|
+
protected generateArchitectureDoc(context: GeneratorContext): string;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* AdvancedModuleGenerator - 進階 DDD 模組生成器(Event Sourcing)
|
|
434
|
+
*
|
|
435
|
+
* 為 Bounded Context 生成完整的 Event Sourcing 架構:
|
|
436
|
+
* - Aggregate Root(聚合根)
|
|
437
|
+
* - Domain Events(領域事件,支援版本管理)
|
|
438
|
+
* - Event Store(InMemory + Database 實現)
|
|
439
|
+
* - EventApplier(純函式事件應用)
|
|
440
|
+
* - EventDeserializer(事件反序列化)
|
|
441
|
+
* - 自動化的測試框架
|
|
442
|
+
*
|
|
443
|
+
* 使用場景:
|
|
444
|
+
* ```bash
|
|
445
|
+
* bun run scaffold Payment --type advanced
|
|
446
|
+
* # 生成完整的 Payment 模組,包含 Event Sourcing 支援
|
|
447
|
+
* ```
|
|
448
|
+
*/
|
|
449
|
+
|
|
450
|
+
declare class AdvancedModuleGenerator {
|
|
451
|
+
/**
|
|
452
|
+
* 生成進階 DDD 模組結構(Event Sourcing)
|
|
453
|
+
*
|
|
454
|
+
* 生成檔案:
|
|
455
|
+
* - Domain/AggregateRoots/{Name}.ts
|
|
456
|
+
* - Domain/Events/{Name}*Event.ts(3 個事件示例)
|
|
457
|
+
* - Domain/Services/{Name}EventApplier.ts
|
|
458
|
+
* - Domain/Repositories/I{Name}EventStore.ts
|
|
459
|
+
* - Domain/ValueObjects/{Name}Status.ts
|
|
460
|
+
* - Infrastructure/EventStore/InMemory{Name}EventStore.ts
|
|
461
|
+
* - Infrastructure/EventStore/Database{Name}EventStore.ts
|
|
462
|
+
* - Infrastructure/EventStore/{Name}EventDeserializer.ts
|
|
463
|
+
* - Application/Services/Create{Name}Service.ts
|
|
464
|
+
* - 完整的測試框架
|
|
465
|
+
*/
|
|
466
|
+
generate(moduleName: string, _context: GeneratorContext): DirectoryNode;
|
|
467
|
+
private generateAggregateRoot;
|
|
468
|
+
private generateEvent;
|
|
469
|
+
private generateStatusValueObject;
|
|
470
|
+
private generateIdValueObject;
|
|
471
|
+
private generateEventApplier;
|
|
472
|
+
private generateEventStoreInterface;
|
|
473
|
+
private generateInMemoryEventStore;
|
|
474
|
+
private generateDatabaseEventStore;
|
|
475
|
+
private generateEventDeserializer;
|
|
476
|
+
private generateApplicationService;
|
|
477
|
+
private generateDTO;
|
|
478
|
+
private generateController;
|
|
479
|
+
private generateRoutes;
|
|
480
|
+
private generateModuleIndex;
|
|
481
|
+
private toKebabCase;
|
|
482
|
+
private toSnakeCase;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
/**
|
|
486
|
+
* CQRSQueryModuleGenerator - CQRS 查詢側模組生成器
|
|
487
|
+
*
|
|
488
|
+
* 為查詢側(讀端)生成完整的 CQRS 架構:
|
|
489
|
+
* - Read Model(讀模型,查詢優化的數據結構)
|
|
490
|
+
* - Event Projector(事件投影器,將事件轉化為讀模型)
|
|
491
|
+
* - Query Service(查詢服務,提供查詢接口)
|
|
492
|
+
* - Event Subscriber(事件訂閱器,監聽並投影事件)
|
|
493
|
+
* - HTTP Controllers(查詢端點)
|
|
494
|
+
*
|
|
495
|
+
* 與 Phase 2a AdvancedModuleGenerator 配合使用:
|
|
496
|
+
* - Phase 2a: 寫側(事件溯源)
|
|
497
|
+
* - Phase 2b: 讀側(CQRS 投影) ← 本生成器
|
|
498
|
+
*
|
|
499
|
+
* 使用場景:
|
|
500
|
+
* ```bash
|
|
501
|
+
* bun run scaffold WalletBalance --type cqrs-query
|
|
502
|
+
* # 生成完整的查詢模組,訂閱來自 PSC 模組的事件
|
|
503
|
+
*
|
|
504
|
+
* bun run scaffold MemberStats --type cqrs-query
|
|
505
|
+
* # 生成會員統計查詢模組,訂閱來自 MOC 模組的事件
|
|
506
|
+
* ```
|
|
507
|
+
*/
|
|
508
|
+
|
|
509
|
+
interface CQRSQueryConfig {
|
|
510
|
+
moduleName: string;
|
|
511
|
+
modulePrefix?: string;
|
|
512
|
+
description?: string;
|
|
513
|
+
readModel: {
|
|
514
|
+
fields: FieldDefinition[];
|
|
515
|
+
primaryKey: string;
|
|
516
|
+
indexes?: string[];
|
|
517
|
+
};
|
|
518
|
+
events: {
|
|
519
|
+
subscribedEvents: EventMapping[];
|
|
520
|
+
};
|
|
521
|
+
queries?: {
|
|
522
|
+
methods: QueryMethodDefinition[];
|
|
523
|
+
};
|
|
524
|
+
cache?: {
|
|
525
|
+
enabled: boolean;
|
|
526
|
+
ttl?: number;
|
|
527
|
+
};
|
|
528
|
+
}
|
|
529
|
+
interface FieldDefinition {
|
|
530
|
+
name: string;
|
|
531
|
+
type: 'string' | 'number' | 'boolean' | 'date' | 'decimal';
|
|
532
|
+
description?: string;
|
|
533
|
+
indexed?: boolean;
|
|
534
|
+
}
|
|
535
|
+
interface EventMapping {
|
|
536
|
+
eventType: string;
|
|
537
|
+
eventClass: string;
|
|
538
|
+
handlerMethod: string;
|
|
539
|
+
updates: FieldUpdate[];
|
|
540
|
+
}
|
|
541
|
+
interface FieldUpdate {
|
|
542
|
+
fieldName: string;
|
|
543
|
+
operation: 'set' | 'add' | 'increment';
|
|
544
|
+
}
|
|
545
|
+
interface QueryMethodDefinition {
|
|
546
|
+
name: string;
|
|
547
|
+
parameters: QueryParameter[];
|
|
548
|
+
returnType: string;
|
|
549
|
+
description?: string;
|
|
550
|
+
}
|
|
551
|
+
interface QueryParameter {
|
|
552
|
+
name: string;
|
|
553
|
+
type: string;
|
|
554
|
+
required?: boolean;
|
|
555
|
+
}
|
|
556
|
+
/**
|
|
557
|
+
* CQRS 查詢側模組生成器
|
|
558
|
+
* 生成完整的查詢端(讀側)模組架構
|
|
559
|
+
*/
|
|
560
|
+
declare class CQRSQueryModuleGenerator {
|
|
561
|
+
/**
|
|
562
|
+
* 生成 CQRS 查詢側模組結構
|
|
563
|
+
*
|
|
564
|
+
* 生成檔案:
|
|
565
|
+
* - Domain/ReadModels/{Name}ReadModel.ts
|
|
566
|
+
* - Domain/Projectors/{Name}EventProjector.ts
|
|
567
|
+
* - Application/Services/Query{Name}Service.ts
|
|
568
|
+
* - Application/DTOs/{Name}ReadDTO.ts
|
|
569
|
+
* - Infrastructure/Subscribers/{Name}ProjectionSubscriber.ts
|
|
570
|
+
* - Infrastructure/Cache/{Name}ReadModelCache.ts
|
|
571
|
+
* - Presentation/Controllers/{Name}QueryController.ts
|
|
572
|
+
* - index.ts
|
|
573
|
+
*
|
|
574
|
+
* @param moduleName - 模組名稱(例:'Wallet')
|
|
575
|
+
* @param _context - 生成器上下文(當前未使用,預留供未來擴展)
|
|
576
|
+
* @returns 模組目錄結構
|
|
577
|
+
*/
|
|
578
|
+
generate(moduleName: string, _context: GeneratorContext): DirectoryNode;
|
|
579
|
+
/**
|
|
580
|
+
* 生成讀模型檔案
|
|
581
|
+
*/
|
|
582
|
+
private generateReadModel;
|
|
583
|
+
/**
|
|
584
|
+
* 生成事件投影器檔案
|
|
585
|
+
*/
|
|
586
|
+
private generateProjector;
|
|
587
|
+
/**
|
|
588
|
+
* 生成查詢服務檔案
|
|
589
|
+
*/
|
|
590
|
+
private generateQueryService;
|
|
591
|
+
/**
|
|
592
|
+
* 生成查詢 DTO 檔案
|
|
593
|
+
*/
|
|
594
|
+
private generateQueryDTO;
|
|
595
|
+
/**
|
|
596
|
+
* 生成倉庫介面
|
|
597
|
+
*/
|
|
598
|
+
private generateRepositoryInterface;
|
|
599
|
+
/**
|
|
600
|
+
* 生成倉庫實現
|
|
601
|
+
*/
|
|
602
|
+
private generateRepositoryImplementation;
|
|
603
|
+
/**
|
|
604
|
+
* 生成事件訂閱器
|
|
605
|
+
*/
|
|
606
|
+
private generateSubscriber;
|
|
607
|
+
/**
|
|
608
|
+
* 生成快取層
|
|
609
|
+
*/
|
|
610
|
+
private generateCache;
|
|
611
|
+
/**
|
|
612
|
+
* 生成 HTTP 控制器
|
|
613
|
+
*/
|
|
614
|
+
private generateController;
|
|
615
|
+
/**
|
|
616
|
+
* 生成路由檔案
|
|
617
|
+
*/
|
|
618
|
+
private generateRoutes;
|
|
619
|
+
/**
|
|
620
|
+
* 生成模組索引檔案
|
|
621
|
+
*/
|
|
622
|
+
private generateIndex;
|
|
623
|
+
/**
|
|
624
|
+
* 將字符串轉換為 kebab-case
|
|
625
|
+
*/
|
|
626
|
+
private toKebabCase;
|
|
627
|
+
/**
|
|
628
|
+
* 將字符串轉換為 snake_case
|
|
629
|
+
*/
|
|
630
|
+
private toSnakeCase;
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
/**
|
|
634
|
+
* EnterpriseMvcGenerator - Enterprise MVC Architecture Generator
|
|
635
|
+
*
|
|
636
|
+
* Generates a Laravel-inspired MVC structure with:
|
|
637
|
+
* - Controllers for HTTP handling
|
|
638
|
+
* - Services for business logic
|
|
639
|
+
* - Repositories for data persistence
|
|
640
|
+
* - Http/Kernel for middleware management
|
|
641
|
+
*/
|
|
642
|
+
|
|
643
|
+
/**
|
|
644
|
+
* EnterpriseMvcGenerator implements a Laravel-inspired MVC architectural pattern.
|
|
645
|
+
*
|
|
646
|
+
* It generates a pragmatic, robust structure with Controllers, Services,
|
|
647
|
+
* Repositories, and Service Providers. It is the recommended architecture
|
|
648
|
+
* for most web applications and APIs.
|
|
649
|
+
*
|
|
650
|
+
* @public
|
|
651
|
+
* @since 3.0.0
|
|
652
|
+
*/
|
|
653
|
+
declare class EnterpriseMvcGenerator extends BaseGenerator {
|
|
654
|
+
get architectureType(): "enterprise-mvc";
|
|
655
|
+
get displayName(): string;
|
|
656
|
+
get description(): string;
|
|
657
|
+
getDirectoryStructure(context: GeneratorContext): DirectoryNode[];
|
|
658
|
+
private generateAppConfig;
|
|
659
|
+
private generateDatabaseConfig;
|
|
660
|
+
private generateAuthConfig;
|
|
661
|
+
private generateCacheConfig;
|
|
662
|
+
private generateLoggingConfig;
|
|
663
|
+
private generateHttpKernel;
|
|
664
|
+
private generateBaseController;
|
|
665
|
+
private generateHomeController;
|
|
666
|
+
private generateAuthMiddleware;
|
|
667
|
+
private generateAppServiceProvider;
|
|
668
|
+
private generateProvidersIndex;
|
|
669
|
+
private generateDatabaseProvider;
|
|
670
|
+
private generateMiddlewareProvider;
|
|
671
|
+
private generateRouteProvider;
|
|
672
|
+
private generateExceptionHandler;
|
|
673
|
+
private generateBootstrap;
|
|
674
|
+
private generateRoutes;
|
|
675
|
+
protected generateArchitectureDoc(context: GeneratorContext): string;
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
/**
|
|
679
|
+
* SatelliteGenerator - Scaffolds Gravito Satellites (Plugins)
|
|
680
|
+
*
|
|
681
|
+
* Implements DDD + Clean Architecture for plugins with built-in
|
|
682
|
+
* Dogfooding support (pre-configured with Gravito modules).
|
|
683
|
+
*/
|
|
684
|
+
|
|
685
|
+
/**
|
|
686
|
+
* SatelliteGenerator scaffolds modular plug-and-play extensions for Gravito.
|
|
687
|
+
*
|
|
688
|
+
* It follows a strict DDD and Clean Architecture pattern to ensure that
|
|
689
|
+
* satellites remain decoupled from the core framework and other satellites.
|
|
690
|
+
*
|
|
691
|
+
* @public
|
|
692
|
+
* @since 3.0.0
|
|
693
|
+
*/
|
|
694
|
+
declare class SatelliteGenerator extends BaseGenerator {
|
|
695
|
+
get architectureType(): "satellite";
|
|
696
|
+
get displayName(): string;
|
|
697
|
+
get description(): string;
|
|
698
|
+
getDirectoryStructure(context: GeneratorContext): DirectoryNode[];
|
|
699
|
+
private generateIdValueObject;
|
|
700
|
+
private generateAggregate;
|
|
701
|
+
private generateCreatedEvent;
|
|
702
|
+
private generateRepositoryInterface;
|
|
703
|
+
private generateUseCase;
|
|
704
|
+
private generateAtlasRepository;
|
|
705
|
+
private generateUnitTest;
|
|
706
|
+
private generateIntegrationTest;
|
|
707
|
+
private generateController;
|
|
708
|
+
private generateEntryPoint;
|
|
709
|
+
private generateManifest;
|
|
710
|
+
protected generatePackageJson(context: GeneratorContext): string;
|
|
711
|
+
protected generateArchitectureDoc(context: GeneratorContext): string;
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
/**
|
|
715
|
+
* StubGenerator - Abstract template processor for generating code files.
|
|
716
|
+
*
|
|
717
|
+
* Provides a flexible system for processing stub templates with Handlebars,
|
|
718
|
+
* enabling extensible code generation for any file type.
|
|
719
|
+
*
|
|
720
|
+
* @example
|
|
721
|
+
* ```typescript
|
|
722
|
+
* const generator = new StubGenerator({
|
|
723
|
+
* stubsDir: './stubs',
|
|
724
|
+
* outputDir: './src',
|
|
725
|
+
* });
|
|
726
|
+
*
|
|
727
|
+
* await generator.generate('controller.stub', 'Controllers/UserController.ts', {
|
|
728
|
+
* name: 'User',
|
|
729
|
+
* namespace: 'App\\Controllers',
|
|
730
|
+
* });
|
|
731
|
+
* ```
|
|
732
|
+
*/
|
|
733
|
+
|
|
734
|
+
/**
|
|
735
|
+
* Variables passed to stub templates during processing.
|
|
736
|
+
*
|
|
737
|
+
* @public
|
|
738
|
+
* @since 3.0.0
|
|
739
|
+
*/
|
|
740
|
+
interface StubVariables {
|
|
741
|
+
[key: string]: unknown;
|
|
742
|
+
}
|
|
743
|
+
/**
|
|
744
|
+
* Configuration for the `StubGenerator`.
|
|
745
|
+
*
|
|
746
|
+
* @public
|
|
747
|
+
* @since 3.0.0
|
|
748
|
+
*/
|
|
749
|
+
interface StubConfig {
|
|
750
|
+
/** Directory containing the raw stub templates. */
|
|
751
|
+
stubsDir: string;
|
|
752
|
+
/** Root directory for all generated files. */
|
|
753
|
+
outputDir: string;
|
|
754
|
+
/** Default variables available to all templates. */
|
|
755
|
+
defaultVariables?: StubVariables;
|
|
756
|
+
/** Optional custom Handlebars helper implementations. */
|
|
757
|
+
helpers?: Record<string, Handlebars.HelperDelegate>;
|
|
758
|
+
}
|
|
759
|
+
/**
|
|
760
|
+
* StubGenerator processes template stubs using the Handlebars engine.
|
|
761
|
+
*
|
|
762
|
+
* It provides a rich set of built-in helpers for string manipulation
|
|
763
|
+
* (camelCase, PascalCase, etc.) and handles file reading and writing.
|
|
764
|
+
*
|
|
765
|
+
* @public
|
|
766
|
+
* @since 3.0.0
|
|
767
|
+
*/
|
|
768
|
+
declare class StubGenerator {
|
|
769
|
+
private config;
|
|
770
|
+
private handlebars;
|
|
771
|
+
constructor(config: StubConfig);
|
|
772
|
+
/**
|
|
773
|
+
* Register built-in Handlebars helpers.
|
|
774
|
+
*/
|
|
775
|
+
private registerBuiltinHelpers;
|
|
776
|
+
/**
|
|
777
|
+
* Generate a file from a stub template.
|
|
778
|
+
*
|
|
779
|
+
* @param stubName - Name of the stub file (relative to stubsDir)
|
|
780
|
+
* @param outputPath - Output path (relative to outputDir)
|
|
781
|
+
* @param variables - Template variables
|
|
782
|
+
* @returns Path to the generated file
|
|
783
|
+
*/
|
|
784
|
+
generate(stubName: string, outputPath: string, variables?: StubVariables): Promise<string>;
|
|
785
|
+
/**
|
|
786
|
+
* Generate multiple files from a stub template.
|
|
787
|
+
*
|
|
788
|
+
* @param stubName - Name of the stub file
|
|
789
|
+
* @param outputs - Array of [outputPath, variables] tuples
|
|
790
|
+
* @returns Array of generated file paths
|
|
791
|
+
*/
|
|
792
|
+
generateMany(stubName: string, outputs: [string, StubVariables][]): Promise<string[]>;
|
|
793
|
+
/**
|
|
794
|
+
* Render a template string directly.
|
|
795
|
+
*
|
|
796
|
+
* @param template - Template string
|
|
797
|
+
* @param variables - Template variables
|
|
798
|
+
* @returns Rendered content
|
|
799
|
+
*/
|
|
800
|
+
render(template: string, variables?: StubVariables): string;
|
|
801
|
+
/**
|
|
802
|
+
* Register a custom Handlebars helper.
|
|
803
|
+
*
|
|
804
|
+
* @param name - Helper name
|
|
805
|
+
* @param helper - Helper function
|
|
806
|
+
*/
|
|
807
|
+
registerHelper(name: string, helper: Handlebars.HelperDelegate): void;
|
|
808
|
+
/**
|
|
809
|
+
* Register a Handlebars partial.
|
|
810
|
+
*
|
|
811
|
+
* @param name - Partial name
|
|
812
|
+
* @param partial - Partial template string
|
|
813
|
+
*/
|
|
814
|
+
registerPartial(name: string, partial: string): void;
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
/**
|
|
818
|
+
* Represents the structure of a `gravito.lock.json` file.
|
|
819
|
+
*
|
|
820
|
+
* @public
|
|
821
|
+
* @since 3.0.0
|
|
822
|
+
*/
|
|
823
|
+
interface LockFile {
|
|
824
|
+
/** Information about the selected project profile. */
|
|
825
|
+
profile: {
|
|
826
|
+
name: ProfileType;
|
|
827
|
+
version: string;
|
|
828
|
+
};
|
|
829
|
+
/** List of enabled features and orbits. */
|
|
830
|
+
features: string[];
|
|
831
|
+
/** Selected default drivers for various services. */
|
|
832
|
+
drivers: {
|
|
833
|
+
database: string;
|
|
834
|
+
cache: string;
|
|
835
|
+
queue: string;
|
|
836
|
+
storage: string;
|
|
837
|
+
session: string;
|
|
838
|
+
};
|
|
839
|
+
/** Metadata about the template used for generation. */
|
|
840
|
+
manifest: {
|
|
841
|
+
template: string;
|
|
842
|
+
version: string;
|
|
843
|
+
};
|
|
844
|
+
/** ISO timestamp when the project was scaffolded. */
|
|
845
|
+
createdAt: string;
|
|
846
|
+
}
|
|
847
|
+
/**
|
|
848
|
+
* LockGenerator creates the `gravito.lock.json` file during scaffolding.
|
|
849
|
+
*
|
|
850
|
+
* This file records the architectural choices and feature set of the project,
|
|
851
|
+
* allowing the CLI to perform consistent upgrades and feature injections later.
|
|
852
|
+
*
|
|
853
|
+
* @public
|
|
854
|
+
* @since 3.0.0
|
|
855
|
+
*/
|
|
856
|
+
declare class LockGenerator {
|
|
857
|
+
generate(profileName: ProfileType, config: ProfileConfig, templateName?: string, templateVersion?: string): string;
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
/**
|
|
861
|
+
* Scaffold is the primary engine for generating Gravito project structures.
|
|
862
|
+
*
|
|
863
|
+
* It orchestrates dynamic template generation, architecture patterns,
|
|
864
|
+
* profile resolution, and environment setup.
|
|
865
|
+
*
|
|
866
|
+
* @example
|
|
867
|
+
* ```typescript
|
|
868
|
+
* const engine = new Scaffold();
|
|
869
|
+
* const result = await engine.create({
|
|
870
|
+
* name: 'new-app',
|
|
871
|
+
* targetDir: '/path/to/app',
|
|
872
|
+
* architecture: 'enterprise-mvc'
|
|
873
|
+
* });
|
|
874
|
+
* ```
|
|
875
|
+
*
|
|
876
|
+
* @public
|
|
877
|
+
* @since 3.0.0
|
|
878
|
+
*/
|
|
879
|
+
declare class Scaffold {
|
|
880
|
+
private templatesDir;
|
|
881
|
+
private verbose;
|
|
882
|
+
private static readonly packageDir;
|
|
883
|
+
constructor(options?: {
|
|
884
|
+
templatesDir?: string;
|
|
885
|
+
verbose?: boolean;
|
|
886
|
+
});
|
|
887
|
+
/**
|
|
888
|
+
* Returns a list of all architectural patterns supported by the engine,
|
|
889
|
+
* along with human-readable names and descriptions.
|
|
890
|
+
*
|
|
891
|
+
* @returns {Array<{type: ArchitectureType, name: string, description: string}>}
|
|
892
|
+
*/
|
|
893
|
+
getArchitectureTypes(): Array<{
|
|
894
|
+
type: ArchitectureType;
|
|
895
|
+
name: string;
|
|
896
|
+
description: string;
|
|
897
|
+
}>;
|
|
898
|
+
/**
|
|
899
|
+
* Orchestrates the complete project generation lifecycle.
|
|
900
|
+
* This includes directory creation, file layout, profile resolution,
|
|
901
|
+
* dependency mapping, and optional post-install hooks.
|
|
902
|
+
*
|
|
903
|
+
* @param {ScaffoldOptions} options - Detailed configuration for the new project.
|
|
904
|
+
* @returns {Promise<ScaffoldResult>}
|
|
905
|
+
*/
|
|
906
|
+
create(options: ScaffoldOptions): Promise<ScaffoldResult>;
|
|
907
|
+
/**
|
|
908
|
+
* Create a generator for the specified architecture with options.
|
|
909
|
+
* @param options - Scaffold options including architecture type and module type for DDD
|
|
910
|
+
*/
|
|
911
|
+
private createGenerator;
|
|
912
|
+
/**
|
|
913
|
+
* Generate a single module (for DDD bounded context).
|
|
914
|
+
*/
|
|
915
|
+
generateModule(_targetDir: string, _moduleName: string, _options?: {
|
|
916
|
+
architecture?: ArchitectureType;
|
|
917
|
+
}): Promise<ScaffoldResult>;
|
|
918
|
+
/**
|
|
919
|
+
* Generate a service provider.
|
|
920
|
+
*/
|
|
921
|
+
generateProvider(_targetDir: string, _providerName: string): Promise<ScaffoldResult>;
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
export { AdvancedModuleGenerator, type ArchitectureType, BaseGenerator, type CQRSQueryConfig, CQRSQueryModuleGenerator, CleanArchitectureGenerator, DddGenerator, type DddModuleType, DependencyValidator, type DetectedEnvironment, EnterpriseMvcGenerator, EnvironmentDetector, FileMerger, type GeneratorConfig, type GeneratorContext, type LockFile, LockGenerator, type PackageJson, type ProfileConfig, ProfileResolver, type ProfileType, SatelliteGenerator, Scaffold, type ScaffoldOptions, type StubConfig, StubGenerator, type StubVariables, type ValidationResult };
|