@skmtc/core 0.0.783 → 0.0.785
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/esm/dsl/File.d.ts +208 -0
- package/esm/dsl/File.d.ts.map +1 -1
- package/esm/dsl/File.js +197 -0
- package/esm/dsl/model/ModelBase.d.ts +257 -0
- package/esm/dsl/model/ModelBase.d.ts.map +1 -1
- package/esm/dsl/model/ModelBase.js +248 -0
- package/esm/dsl/operation/OperationBase.d.ts +175 -0
- package/esm/dsl/operation/OperationBase.d.ts.map +1 -1
- package/esm/dsl/operation/OperationBase.js +166 -0
- package/package.json +5 -1
- package/script/dsl/File.d.ts +208 -0
- package/script/dsl/File.d.ts.map +1 -1
- package/script/dsl/File.js +197 -0
- package/script/dsl/model/ModelBase.d.ts +257 -0
- package/script/dsl/model/ModelBase.d.ts.map +1 -1
- package/script/dsl/model/ModelBase.js +248 -0
- package/script/dsl/operation/OperationBase.d.ts +175 -0
- package/script/dsl/operation/OperationBase.d.ts.map +1 -1
- package/script/dsl/operation/OperationBase.js +166 -0
|
@@ -9,19 +9,276 @@ import type { Inserted } from '../Inserted.js';
|
|
|
9
9
|
import type { OasSchema } from '../../oas/schema/Schema.js';
|
|
10
10
|
import type { OasRef } from '../../oas/ref/Ref.js';
|
|
11
11
|
import { OasVoid } from '../../oas/void/Void.js';
|
|
12
|
+
/**
|
|
13
|
+
* Constructor arguments for {@link ModelBase}.
|
|
14
|
+
*
|
|
15
|
+
* @template EnrichmentType - Optional type for custom enrichment data
|
|
16
|
+
*/
|
|
12
17
|
export type ModelBaseArgs<EnrichmentType = undefined> = {
|
|
18
|
+
/** The generation context providing access to the processing pipeline */
|
|
13
19
|
context: GenerateContext;
|
|
20
|
+
/** Content settings including export path and enrichment configuration */
|
|
14
21
|
settings: ContentSettings<EnrichmentType>;
|
|
22
|
+
/** Unique identifier for this generator type */
|
|
15
23
|
generatorKey: GeneratorKey;
|
|
24
|
+
/** Reference name for the model being generated */
|
|
16
25
|
refName: RefName;
|
|
17
26
|
};
|
|
27
|
+
/**
|
|
28
|
+
* Base class for model generators in the SKMTC DSL system.
|
|
29
|
+
*
|
|
30
|
+
* `ModelBase` extends {@link ContentBase} to provide specialized functionality for
|
|
31
|
+
* generating code from OpenAPI schema models. It offers type-safe methods for
|
|
32
|
+
* inserting related models, managing schema references, and handling enrichments.
|
|
33
|
+
*
|
|
34
|
+
* This class serves as the foundation for creating custom model generators that
|
|
35
|
+
* transform OpenAPI schemas into various code artifacts like TypeScript interfaces,
|
|
36
|
+
* validation schemas, or database models.
|
|
37
|
+
*
|
|
38
|
+
* ## Key Features
|
|
39
|
+
*
|
|
40
|
+
* - **Model Insertion**: Insert related models with automatic reference resolution
|
|
41
|
+
* - **Schema Normalization**: Handle complex schema references and fallbacks
|
|
42
|
+
* - **Export Management**: Control which models are exported from generated files
|
|
43
|
+
* - **Enrichment Support**: Extend functionality with custom enrichment data
|
|
44
|
+
* - **Type Safety**: Full TypeScript support with generic enrichment types
|
|
45
|
+
*
|
|
46
|
+
* @template EnrichmentType - Optional type for custom enrichment data
|
|
47
|
+
*
|
|
48
|
+
* @example Basic model generator
|
|
49
|
+
* ```typescript
|
|
50
|
+
* import { ModelBase, Definition } from '@skmtc/core';
|
|
51
|
+
*
|
|
52
|
+
* class TypeScriptInterface extends ModelBase {
|
|
53
|
+
* toDefinition(): Definition {
|
|
54
|
+
* const schema = this.context.getSchema(this.refName);
|
|
55
|
+
*
|
|
56
|
+
* return new Definition({
|
|
57
|
+
* name: this.refName,
|
|
58
|
+
* content: `export interface ${this.refName} {
|
|
59
|
+
* ${this.generateProperties(schema)}
|
|
60
|
+
* }`
|
|
61
|
+
* });
|
|
62
|
+
* }
|
|
63
|
+
*
|
|
64
|
+
* private generateProperties(schema: OasSchema): string {
|
|
65
|
+
* // Generate interface properties from schema
|
|
66
|
+
* return Object.entries(schema.properties || {})
|
|
67
|
+
* .map(([key, prop]) => `${key}: ${this.getPropertyType(prop)}`)
|
|
68
|
+
* .join(';\n ');
|
|
69
|
+
* }
|
|
70
|
+
* }
|
|
71
|
+
* ```
|
|
72
|
+
*
|
|
73
|
+
* @example With enrichments
|
|
74
|
+
* ```typescript
|
|
75
|
+
* type ValidationEnrichment = {
|
|
76
|
+
* validators: string[];
|
|
77
|
+
* customRules: Record<string, string>;
|
|
78
|
+
* };
|
|
79
|
+
*
|
|
80
|
+
* class ValidationModel extends ModelBase<ValidationEnrichment> {
|
|
81
|
+
* toDefinition(): Definition {
|
|
82
|
+
* const enrichment = this.settings.enrichment;
|
|
83
|
+
* const validators = enrichment?.validators || [];
|
|
84
|
+
*
|
|
85
|
+
* return new Definition({
|
|
86
|
+
* name: `${this.refName}Validator`,
|
|
87
|
+
* content: this.generateValidator(validators)
|
|
88
|
+
* });
|
|
89
|
+
* }
|
|
90
|
+
* }
|
|
91
|
+
* ```
|
|
92
|
+
*
|
|
93
|
+
* @example Inserting related models
|
|
94
|
+
* ```typescript
|
|
95
|
+
* class ApiModel extends ModelBase {
|
|
96
|
+
* toDefinition(): Definition {
|
|
97
|
+
* const schema = this.context.getSchema(this.refName);
|
|
98
|
+
*
|
|
99
|
+
* // Insert related models automatically
|
|
100
|
+
* if (schema.properties?.user) {
|
|
101
|
+
* this.insertNormalizedModel(
|
|
102
|
+
* new TypeScriptInterface({ ... }),
|
|
103
|
+
* { schema: schema.properties.user, fallbackName: 'User' }
|
|
104
|
+
* );
|
|
105
|
+
* }
|
|
106
|
+
*
|
|
107
|
+
* return new Definition({
|
|
108
|
+
* name: this.refName,
|
|
109
|
+
* content: this.generateInterface(schema)
|
|
110
|
+
* });
|
|
111
|
+
* }
|
|
112
|
+
* }
|
|
113
|
+
* ```
|
|
114
|
+
*/
|
|
18
115
|
export declare class ModelBase<EnrichmentType = undefined> extends ContentBase {
|
|
116
|
+
/** Content settings including export path and enrichment configuration */
|
|
19
117
|
settings: ContentSettings<EnrichmentType>;
|
|
118
|
+
/** Reference name for the model being generated */
|
|
20
119
|
refName: RefName;
|
|
120
|
+
/** Generator key identifying this generator type */
|
|
21
121
|
generatorKey: GeneratorKey;
|
|
122
|
+
/**
|
|
123
|
+
* Creates a new ModelBase instance.
|
|
124
|
+
*
|
|
125
|
+
* @param args - Model generator configuration
|
|
126
|
+
* @param args.context - The generation context providing pipeline access
|
|
127
|
+
* @param args.settings - Content settings with export path and enrichments
|
|
128
|
+
* @param args.generatorKey - Unique identifier for this generator type
|
|
129
|
+
* @param args.refName - Reference name for the model being generated
|
|
130
|
+
*
|
|
131
|
+
* @example
|
|
132
|
+
* ```typescript
|
|
133
|
+
* const model = new ModelBase({
|
|
134
|
+
* context: generateContext,
|
|
135
|
+
* settings: {
|
|
136
|
+
* exportPath: './src/models.ts',
|
|
137
|
+
* enrichment: customEnrichments
|
|
138
|
+
* },
|
|
139
|
+
* generatorKey: 'typescript-models',
|
|
140
|
+
* refName: 'UserModel'
|
|
141
|
+
* });
|
|
142
|
+
* ```
|
|
143
|
+
*/
|
|
22
144
|
constructor({ context, settings, generatorKey, refName }: ModelBaseArgs<EnrichmentType>);
|
|
145
|
+
/**
|
|
146
|
+
* Inserts a related model with forced generation.
|
|
147
|
+
*
|
|
148
|
+
* This method adds a related model to the current generation context, ensuring
|
|
149
|
+
* it will be generated regardless of whether it already exists. The inserted
|
|
150
|
+
* model will be exported to the same destination path as this model unless
|
|
151
|
+
* `noExport` is specified.
|
|
152
|
+
*
|
|
153
|
+
* @template V - Type of generated value returned by the insertable
|
|
154
|
+
* @template EnrichmentType - Type of enrichment data for the insertable
|
|
155
|
+
* @param insertable - The model generator to insert
|
|
156
|
+
* @param refName - Reference name for the inserted model
|
|
157
|
+
* @param options - Insertion options
|
|
158
|
+
* @param options.noExport - Whether to skip exporting the inserted model
|
|
159
|
+
* @returns Inserted model reference with generated value
|
|
160
|
+
*
|
|
161
|
+
* @example
|
|
162
|
+
* ```typescript
|
|
163
|
+
* class UserModel extends ModelBase {
|
|
164
|
+
* toDefinition(): Definition {
|
|
165
|
+
* // Insert an address model that's always generated
|
|
166
|
+
* const address = this.insertModel(
|
|
167
|
+
* new AddressModel({ ... }),
|
|
168
|
+
* 'Address',
|
|
169
|
+
* { noExport: false }
|
|
170
|
+
* );
|
|
171
|
+
*
|
|
172
|
+
* return new Definition({
|
|
173
|
+
* name: this.refName,
|
|
174
|
+
* content: `export interface ${this.refName} {
|
|
175
|
+
* address: ${address.value}
|
|
176
|
+
* }`
|
|
177
|
+
* });
|
|
178
|
+
* }
|
|
179
|
+
* }
|
|
180
|
+
* ```
|
|
181
|
+
*/
|
|
23
182
|
insertModel<V extends GeneratedValue, EnrichmentType = undefined>(insertable: ModelInsertable<V, EnrichmentType>, refName: RefName, options?: Pick<InsertModelOptions<'force'>, 'noExport'>): Inserted<V, 'force', EnrichmentType>;
|
|
183
|
+
/**
|
|
184
|
+
* Inserts a related model with automatic schema normalization and reference resolution.
|
|
185
|
+
*
|
|
186
|
+
* This method intelligently handles schema references by automatically resolving
|
|
187
|
+
* them to appropriate model names. If the schema is a reference, it uses the
|
|
188
|
+
* referenced name; otherwise it falls back to the provided fallback name.
|
|
189
|
+
*
|
|
190
|
+
* This is particularly useful when working with complex nested schemas where
|
|
191
|
+
* you want to automatically generate models for referenced types.
|
|
192
|
+
*
|
|
193
|
+
* @template V - Type of generated value returned by the insertable
|
|
194
|
+
* @template Schema - Type of OpenAPI schema (schema object, reference, or void)
|
|
195
|
+
* @template EnrichmentType - Type of enrichment data for the insertable
|
|
196
|
+
* @param insertable - The model generator to insert
|
|
197
|
+
* @param args - Schema normalization arguments
|
|
198
|
+
* @param args.schema - The OpenAPI schema to normalize (can be reference or actual schema)
|
|
199
|
+
* @param args.fallbackName - Name to use if schema is not a reference
|
|
200
|
+
* @param options - Insertion options
|
|
201
|
+
* @param options.noExport - Whether to skip exporting the inserted model
|
|
202
|
+
* @returns Inserted model reference with normalized name and generated value
|
|
203
|
+
*
|
|
204
|
+
* @example Handling schema references
|
|
205
|
+
* ```typescript
|
|
206
|
+
* class OrderModel extends ModelBase {
|
|
207
|
+
* toDefinition(): Definition {
|
|
208
|
+
* const schema = this.context.getSchema(this.refName);
|
|
209
|
+
*
|
|
210
|
+
* // Handle customer property - could be reference or inline schema
|
|
211
|
+
* if (schema.properties?.customer) {
|
|
212
|
+
* const customer = this.insertNormalizedModel(
|
|
213
|
+
* new CustomerModel({ ... }),
|
|
214
|
+
* {
|
|
215
|
+
* schema: schema.properties.customer,
|
|
216
|
+
* fallbackName: 'Customer'
|
|
217
|
+
* }
|
|
218
|
+
* );
|
|
219
|
+
* // customer.refName will be 'Customer' or the referenced schema name
|
|
220
|
+
* }
|
|
221
|
+
*
|
|
222
|
+
* return new Definition({ ... });
|
|
223
|
+
* }
|
|
224
|
+
* }
|
|
225
|
+
* ```
|
|
226
|
+
*
|
|
227
|
+
* @example With complex nested schemas
|
|
228
|
+
* ```typescript
|
|
229
|
+
* // If schema.properties.items is { $ref: '#/components/schemas/Product' }
|
|
230
|
+
* // Then the inserted model will use refName 'Product'
|
|
231
|
+
* const items = this.insertNormalizedModel(
|
|
232
|
+
* new ProductModel({ ... }),
|
|
233
|
+
* {
|
|
234
|
+
* schema: schema.properties.items,
|
|
235
|
+
* fallbackName: 'Item' // Won't be used since schema has $ref
|
|
236
|
+
* }
|
|
237
|
+
* );
|
|
238
|
+
* ```
|
|
239
|
+
*/
|
|
24
240
|
insertNormalizedModel<V extends GeneratedValue, Schema extends OasSchema | OasRef<'schema'> | OasVoid, EnrichmentType = undefined>(insertable: ModelInsertable<V, EnrichmentType>, { schema, fallbackName }: Omit<InsertNormalisedModelArgs<Schema>, 'destinationPath'>, options?: Pick<InsertModelOptions<'force'>, 'noExport'>): InsertNormalisedModelReturn<V, Schema>;
|
|
241
|
+
/**
|
|
242
|
+
* Registers a file-level artifact with the generation context.
|
|
243
|
+
*
|
|
244
|
+
* This method allows the model generator to register additional content
|
|
245
|
+
* (like imports, exports, or file-level definitions) that should be included
|
|
246
|
+
* in the generated file. The registration is automatically scoped to this
|
|
247
|
+
* model's export path.
|
|
248
|
+
*
|
|
249
|
+
* @param args - Registration arguments
|
|
250
|
+
* @param args.content - The content to register (import, export, etc.)
|
|
251
|
+
* @param args.phase - When to register the content ('pre' or 'post')
|
|
252
|
+
*
|
|
253
|
+
* @example Registering imports
|
|
254
|
+
* ```typescript
|
|
255
|
+
* class ApiModel extends ModelBase {
|
|
256
|
+
* toDefinition(): Definition {
|
|
257
|
+
* // Register an import that all generated models need
|
|
258
|
+
* this.register({
|
|
259
|
+
* content: "import { BaseModel } from './base';",
|
|
260
|
+
* phase: 'pre'
|
|
261
|
+
* });
|
|
262
|
+
*
|
|
263
|
+
* return new Definition({ ... });
|
|
264
|
+
* }
|
|
265
|
+
* }
|
|
266
|
+
* ```
|
|
267
|
+
*
|
|
268
|
+
* @example Registering type exports
|
|
269
|
+
* ```typescript
|
|
270
|
+
* class TypeModel extends ModelBase {
|
|
271
|
+
* toDefinition(): Definition {
|
|
272
|
+
* this.register({
|
|
273
|
+
* content: "export type * from './types';",
|
|
274
|
+
* phase: 'post'
|
|
275
|
+
* });
|
|
276
|
+
*
|
|
277
|
+
* return new Definition({ ... });
|
|
278
|
+
* }
|
|
279
|
+
* }
|
|
280
|
+
* ```
|
|
281
|
+
*/
|
|
25
282
|
register(args: BaseRegisterArgs): void;
|
|
26
283
|
}
|
|
27
284
|
//# sourceMappingURL=ModelBase.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ModelBase.d.ts","sourceRoot":"","sources":["../../../src/dsl/model/ModelBase.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,eAAe,EACf,kBAAkB,EAClB,yBAAyB,EACzB,2BAA2B,EAC5B,MAAM,kCAAkC,CAAA;AACzC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAA;AACnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAChE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAA;AACrD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAC5D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC/C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAC9C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAA;AAC3D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAGlD,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAA;AAEhD,MAAM,MAAM,aAAa,CAAC,cAAc,GAAG,SAAS,IAAI;IACtD,OAAO,EAAE,eAAe,CAAA;IACxB,QAAQ,EAAE,eAAe,CAAC,cAAc,CAAC,CAAA;IACzC,YAAY,EAAE,YAAY,CAAA;IAC1B,OAAO,EAAE,OAAO,CAAA;CACjB,CAAA;AAED,qBAAa,SAAS,CAAC,cAAc,GAAG,SAAS,CAAE,SAAQ,WAAW;IACpE,QAAQ,EAAE,eAAe,CAAC,cAAc,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"ModelBase.d.ts","sourceRoot":"","sources":["../../../src/dsl/model/ModelBase.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,eAAe,EACf,kBAAkB,EAClB,yBAAyB,EACzB,2BAA2B,EAC5B,MAAM,kCAAkC,CAAA;AACzC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAA;AACnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAChE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAA;AACrD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAC5D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC/C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAC9C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAA;AAC3D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAGlD,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAA;AAEhD;;;;GAIG;AACH,MAAM,MAAM,aAAa,CAAC,cAAc,GAAG,SAAS,IAAI;IACtD,yEAAyE;IACzE,OAAO,EAAE,eAAe,CAAA;IACxB,0EAA0E;IAC1E,QAAQ,EAAE,eAAe,CAAC,cAAc,CAAC,CAAA;IACzC,gDAAgD;IAChD,YAAY,EAAE,YAAY,CAAA;IAC1B,mDAAmD;IACnD,OAAO,EAAE,OAAO,CAAA;CACjB,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuFG;AACH,qBAAa,SAAS,CAAC,cAAc,GAAG,SAAS,CAAE,SAAQ,WAAW;IACpE,0EAA0E;IAC1E,QAAQ,EAAE,eAAe,CAAC,cAAc,CAAC,CAAA;IAEzC,mDAAmD;IACnD,OAAO,EAAE,OAAO,CAAA;IAEhB,oDAAoD;IAC3C,YAAY,EAAE,YAAY,CAAA;IAEnC;;;;;;;;;;;;;;;;;;;;;OAqBG;gBACS,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,OAAO,EAAE,EAAE,aAAa,CAAC,cAAc,CAAC;IAQvF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAoCG;IACH,WAAW,CAAC,CAAC,SAAS,cAAc,EAAE,cAAc,GAAG,SAAS,EAC9D,UAAU,EAAE,eAAe,CAAC,CAAC,EAAE,cAAc,CAAC,EAC9C,OAAO,EAAE,OAAO,EAChB,OAAO,GAAE,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,EAAE,UAAU,CAAM,GAC1D,QAAQ,CAAC,CAAC,EAAE,OAAO,EAAE,cAAc,CAAC;IAQvC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAwDG;IACH,qBAAqB,CACnB,CAAC,SAAS,cAAc,EACxB,MAAM,SAAS,SAAS,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,OAAO,EACrD,cAAc,GAAG,SAAS,EAE1B,UAAU,EAAE,eAAe,CAAC,CAAC,EAAE,cAAc,CAAC,EAC9C,EAAE,MAAM,EAAE,YAAY,EAAE,EAAE,IAAI,CAAC,yBAAyB,CAAC,MAAM,CAAC,EAAE,iBAAiB,CAAC,EACpF,OAAO,GAAE,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,EAAE,UAAU,CAAM,GAC1D,2BAA2B,CAAC,CAAC,EAAE,MAAM,CAAC;IAYzC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAwCG;IACM,QAAQ,CAAC,IAAI,EAAE,gBAAgB,GAAG,IAAI;CAMhD"}
|
|
@@ -1,19 +1,132 @@
|
|
|
1
1
|
import { ContentBase } from '../ContentBase.js';
|
|
2
|
+
/**
|
|
3
|
+
* Base class for model generators in the SKMTC DSL system.
|
|
4
|
+
*
|
|
5
|
+
* `ModelBase` extends {@link ContentBase} to provide specialized functionality for
|
|
6
|
+
* generating code from OpenAPI schema models. It offers type-safe methods for
|
|
7
|
+
* inserting related models, managing schema references, and handling enrichments.
|
|
8
|
+
*
|
|
9
|
+
* This class serves as the foundation for creating custom model generators that
|
|
10
|
+
* transform OpenAPI schemas into various code artifacts like TypeScript interfaces,
|
|
11
|
+
* validation schemas, or database models.
|
|
12
|
+
*
|
|
13
|
+
* ## Key Features
|
|
14
|
+
*
|
|
15
|
+
* - **Model Insertion**: Insert related models with automatic reference resolution
|
|
16
|
+
* - **Schema Normalization**: Handle complex schema references and fallbacks
|
|
17
|
+
* - **Export Management**: Control which models are exported from generated files
|
|
18
|
+
* - **Enrichment Support**: Extend functionality with custom enrichment data
|
|
19
|
+
* - **Type Safety**: Full TypeScript support with generic enrichment types
|
|
20
|
+
*
|
|
21
|
+
* @template EnrichmentType - Optional type for custom enrichment data
|
|
22
|
+
*
|
|
23
|
+
* @example Basic model generator
|
|
24
|
+
* ```typescript
|
|
25
|
+
* import { ModelBase, Definition } from '@skmtc/core';
|
|
26
|
+
*
|
|
27
|
+
* class TypeScriptInterface extends ModelBase {
|
|
28
|
+
* toDefinition(): Definition {
|
|
29
|
+
* const schema = this.context.getSchema(this.refName);
|
|
30
|
+
*
|
|
31
|
+
* return new Definition({
|
|
32
|
+
* name: this.refName,
|
|
33
|
+
* content: `export interface ${this.refName} {
|
|
34
|
+
* ${this.generateProperties(schema)}
|
|
35
|
+
* }`
|
|
36
|
+
* });
|
|
37
|
+
* }
|
|
38
|
+
*
|
|
39
|
+
* private generateProperties(schema: OasSchema): string {
|
|
40
|
+
* // Generate interface properties from schema
|
|
41
|
+
* return Object.entries(schema.properties || {})
|
|
42
|
+
* .map(([key, prop]) => `${key}: ${this.getPropertyType(prop)}`)
|
|
43
|
+
* .join(';\n ');
|
|
44
|
+
* }
|
|
45
|
+
* }
|
|
46
|
+
* ```
|
|
47
|
+
*
|
|
48
|
+
* @example With enrichments
|
|
49
|
+
* ```typescript
|
|
50
|
+
* type ValidationEnrichment = {
|
|
51
|
+
* validators: string[];
|
|
52
|
+
* customRules: Record<string, string>;
|
|
53
|
+
* };
|
|
54
|
+
*
|
|
55
|
+
* class ValidationModel extends ModelBase<ValidationEnrichment> {
|
|
56
|
+
* toDefinition(): Definition {
|
|
57
|
+
* const enrichment = this.settings.enrichment;
|
|
58
|
+
* const validators = enrichment?.validators || [];
|
|
59
|
+
*
|
|
60
|
+
* return new Definition({
|
|
61
|
+
* name: `${this.refName}Validator`,
|
|
62
|
+
* content: this.generateValidator(validators)
|
|
63
|
+
* });
|
|
64
|
+
* }
|
|
65
|
+
* }
|
|
66
|
+
* ```
|
|
67
|
+
*
|
|
68
|
+
* @example Inserting related models
|
|
69
|
+
* ```typescript
|
|
70
|
+
* class ApiModel extends ModelBase {
|
|
71
|
+
* toDefinition(): Definition {
|
|
72
|
+
* const schema = this.context.getSchema(this.refName);
|
|
73
|
+
*
|
|
74
|
+
* // Insert related models automatically
|
|
75
|
+
* if (schema.properties?.user) {
|
|
76
|
+
* this.insertNormalizedModel(
|
|
77
|
+
* new TypeScriptInterface({ ... }),
|
|
78
|
+
* { schema: schema.properties.user, fallbackName: 'User' }
|
|
79
|
+
* );
|
|
80
|
+
* }
|
|
81
|
+
*
|
|
82
|
+
* return new Definition({
|
|
83
|
+
* name: this.refName,
|
|
84
|
+
* content: this.generateInterface(schema)
|
|
85
|
+
* });
|
|
86
|
+
* }
|
|
87
|
+
* }
|
|
88
|
+
* ```
|
|
89
|
+
*/
|
|
2
90
|
export class ModelBase extends ContentBase {
|
|
91
|
+
/**
|
|
92
|
+
* Creates a new ModelBase instance.
|
|
93
|
+
*
|
|
94
|
+
* @param args - Model generator configuration
|
|
95
|
+
* @param args.context - The generation context providing pipeline access
|
|
96
|
+
* @param args.settings - Content settings with export path and enrichments
|
|
97
|
+
* @param args.generatorKey - Unique identifier for this generator type
|
|
98
|
+
* @param args.refName - Reference name for the model being generated
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* ```typescript
|
|
102
|
+
* const model = new ModelBase({
|
|
103
|
+
* context: generateContext,
|
|
104
|
+
* settings: {
|
|
105
|
+
* exportPath: './src/models.ts',
|
|
106
|
+
* enrichment: customEnrichments
|
|
107
|
+
* },
|
|
108
|
+
* generatorKey: 'typescript-models',
|
|
109
|
+
* refName: 'UserModel'
|
|
110
|
+
* });
|
|
111
|
+
* ```
|
|
112
|
+
*/
|
|
3
113
|
constructor({ context, settings, generatorKey, refName }) {
|
|
4
114
|
super({ context });
|
|
115
|
+
/** Content settings including export path and enrichment configuration */
|
|
5
116
|
Object.defineProperty(this, "settings", {
|
|
6
117
|
enumerable: true,
|
|
7
118
|
configurable: true,
|
|
8
119
|
writable: true,
|
|
9
120
|
value: void 0
|
|
10
121
|
});
|
|
122
|
+
/** Reference name for the model being generated */
|
|
11
123
|
Object.defineProperty(this, "refName", {
|
|
12
124
|
enumerable: true,
|
|
13
125
|
configurable: true,
|
|
14
126
|
writable: true,
|
|
15
127
|
value: void 0
|
|
16
128
|
});
|
|
129
|
+
/** Generator key identifying this generator type */
|
|
17
130
|
Object.defineProperty(this, "generatorKey", {
|
|
18
131
|
enumerable: true,
|
|
19
132
|
configurable: true,
|
|
@@ -24,6 +137,43 @@ export class ModelBase extends ContentBase {
|
|
|
24
137
|
this.refName = refName;
|
|
25
138
|
this.settings = settings;
|
|
26
139
|
}
|
|
140
|
+
/**
|
|
141
|
+
* Inserts a related model with forced generation.
|
|
142
|
+
*
|
|
143
|
+
* This method adds a related model to the current generation context, ensuring
|
|
144
|
+
* it will be generated regardless of whether it already exists. The inserted
|
|
145
|
+
* model will be exported to the same destination path as this model unless
|
|
146
|
+
* `noExport` is specified.
|
|
147
|
+
*
|
|
148
|
+
* @template V - Type of generated value returned by the insertable
|
|
149
|
+
* @template EnrichmentType - Type of enrichment data for the insertable
|
|
150
|
+
* @param insertable - The model generator to insert
|
|
151
|
+
* @param refName - Reference name for the inserted model
|
|
152
|
+
* @param options - Insertion options
|
|
153
|
+
* @param options.noExport - Whether to skip exporting the inserted model
|
|
154
|
+
* @returns Inserted model reference with generated value
|
|
155
|
+
*
|
|
156
|
+
* @example
|
|
157
|
+
* ```typescript
|
|
158
|
+
* class UserModel extends ModelBase {
|
|
159
|
+
* toDefinition(): Definition {
|
|
160
|
+
* // Insert an address model that's always generated
|
|
161
|
+
* const address = this.insertModel(
|
|
162
|
+
* new AddressModel({ ... }),
|
|
163
|
+
* 'Address',
|
|
164
|
+
* { noExport: false }
|
|
165
|
+
* );
|
|
166
|
+
*
|
|
167
|
+
* return new Definition({
|
|
168
|
+
* name: this.refName,
|
|
169
|
+
* content: `export interface ${this.refName} {
|
|
170
|
+
* address: ${address.value}
|
|
171
|
+
* }`
|
|
172
|
+
* });
|
|
173
|
+
* }
|
|
174
|
+
* }
|
|
175
|
+
* ```
|
|
176
|
+
*/
|
|
27
177
|
insertModel(insertable, refName, options = {}) {
|
|
28
178
|
return this.context.insertModel(insertable, refName, {
|
|
29
179
|
generation: 'force',
|
|
@@ -31,6 +181,63 @@ export class ModelBase extends ContentBase {
|
|
|
31
181
|
noExport: options.noExport
|
|
32
182
|
});
|
|
33
183
|
}
|
|
184
|
+
/**
|
|
185
|
+
* Inserts a related model with automatic schema normalization and reference resolution.
|
|
186
|
+
*
|
|
187
|
+
* This method intelligently handles schema references by automatically resolving
|
|
188
|
+
* them to appropriate model names. If the schema is a reference, it uses the
|
|
189
|
+
* referenced name; otherwise it falls back to the provided fallback name.
|
|
190
|
+
*
|
|
191
|
+
* This is particularly useful when working with complex nested schemas where
|
|
192
|
+
* you want to automatically generate models for referenced types.
|
|
193
|
+
*
|
|
194
|
+
* @template V - Type of generated value returned by the insertable
|
|
195
|
+
* @template Schema - Type of OpenAPI schema (schema object, reference, or void)
|
|
196
|
+
* @template EnrichmentType - Type of enrichment data for the insertable
|
|
197
|
+
* @param insertable - The model generator to insert
|
|
198
|
+
* @param args - Schema normalization arguments
|
|
199
|
+
* @param args.schema - The OpenAPI schema to normalize (can be reference or actual schema)
|
|
200
|
+
* @param args.fallbackName - Name to use if schema is not a reference
|
|
201
|
+
* @param options - Insertion options
|
|
202
|
+
* @param options.noExport - Whether to skip exporting the inserted model
|
|
203
|
+
* @returns Inserted model reference with normalized name and generated value
|
|
204
|
+
*
|
|
205
|
+
* @example Handling schema references
|
|
206
|
+
* ```typescript
|
|
207
|
+
* class OrderModel extends ModelBase {
|
|
208
|
+
* toDefinition(): Definition {
|
|
209
|
+
* const schema = this.context.getSchema(this.refName);
|
|
210
|
+
*
|
|
211
|
+
* // Handle customer property - could be reference or inline schema
|
|
212
|
+
* if (schema.properties?.customer) {
|
|
213
|
+
* const customer = this.insertNormalizedModel(
|
|
214
|
+
* new CustomerModel({ ... }),
|
|
215
|
+
* {
|
|
216
|
+
* schema: schema.properties.customer,
|
|
217
|
+
* fallbackName: 'Customer'
|
|
218
|
+
* }
|
|
219
|
+
* );
|
|
220
|
+
* // customer.refName will be 'Customer' or the referenced schema name
|
|
221
|
+
* }
|
|
222
|
+
*
|
|
223
|
+
* return new Definition({ ... });
|
|
224
|
+
* }
|
|
225
|
+
* }
|
|
226
|
+
* ```
|
|
227
|
+
*
|
|
228
|
+
* @example With complex nested schemas
|
|
229
|
+
* ```typescript
|
|
230
|
+
* // If schema.properties.items is { $ref: '#/components/schemas/Product' }
|
|
231
|
+
* // Then the inserted model will use refName 'Product'
|
|
232
|
+
* const items = this.insertNormalizedModel(
|
|
233
|
+
* new ProductModel({ ... }),
|
|
234
|
+
* {
|
|
235
|
+
* schema: schema.properties.items,
|
|
236
|
+
* fallbackName: 'Item' // Won't be used since schema has $ref
|
|
237
|
+
* }
|
|
238
|
+
* );
|
|
239
|
+
* ```
|
|
240
|
+
*/
|
|
34
241
|
insertNormalizedModel(insertable, { schema, fallbackName }, options = {}) {
|
|
35
242
|
return this.context.insertNormalisedModel(insertable, {
|
|
36
243
|
schema,
|
|
@@ -38,6 +245,47 @@ export class ModelBase extends ContentBase {
|
|
|
38
245
|
destinationPath: this.settings.exportPath
|
|
39
246
|
}, options);
|
|
40
247
|
}
|
|
248
|
+
/**
|
|
249
|
+
* Registers a file-level artifact with the generation context.
|
|
250
|
+
*
|
|
251
|
+
* This method allows the model generator to register additional content
|
|
252
|
+
* (like imports, exports, or file-level definitions) that should be included
|
|
253
|
+
* in the generated file. The registration is automatically scoped to this
|
|
254
|
+
* model's export path.
|
|
255
|
+
*
|
|
256
|
+
* @param args - Registration arguments
|
|
257
|
+
* @param args.content - The content to register (import, export, etc.)
|
|
258
|
+
* @param args.phase - When to register the content ('pre' or 'post')
|
|
259
|
+
*
|
|
260
|
+
* @example Registering imports
|
|
261
|
+
* ```typescript
|
|
262
|
+
* class ApiModel extends ModelBase {
|
|
263
|
+
* toDefinition(): Definition {
|
|
264
|
+
* // Register an import that all generated models need
|
|
265
|
+
* this.register({
|
|
266
|
+
* content: "import { BaseModel } from './base';",
|
|
267
|
+
* phase: 'pre'
|
|
268
|
+
* });
|
|
269
|
+
*
|
|
270
|
+
* return new Definition({ ... });
|
|
271
|
+
* }
|
|
272
|
+
* }
|
|
273
|
+
* ```
|
|
274
|
+
*
|
|
275
|
+
* @example Registering type exports
|
|
276
|
+
* ```typescript
|
|
277
|
+
* class TypeModel extends ModelBase {
|
|
278
|
+
* toDefinition(): Definition {
|
|
279
|
+
* this.register({
|
|
280
|
+
* content: "export type * from './types';",
|
|
281
|
+
* phase: 'post'
|
|
282
|
+
* });
|
|
283
|
+
*
|
|
284
|
+
* return new Definition({ ... });
|
|
285
|
+
* }
|
|
286
|
+
* }
|
|
287
|
+
* ```
|
|
288
|
+
*/
|
|
41
289
|
register(args) {
|
|
42
290
|
this.context.register({
|
|
43
291
|
...args,
|