@skmtc/core 0.0.788 → 0.0.790
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/context/ParseContext.d.ts +178 -0
- package/esm/context/ParseContext.d.ts.map +1 -1
- package/esm/context/ParseContext.js +108 -0
- package/esm/context/RenderContext.d.ts +190 -0
- package/esm/context/RenderContext.d.ts.map +1 -1
- package/esm/context/RenderContext.js +179 -0
- package/esm/dsl/Inserted.d.ts +240 -0
- package/esm/dsl/Inserted.d.ts.map +1 -1
- package/esm/dsl/Inserted.js +231 -0
- package/esm/helpers/refFns.d.ts +160 -0
- package/esm/helpers/refFns.d.ts.map +1 -1
- package/esm/helpers/refFns.js +156 -0
- package/esm/oas/boolean/Boolean.d.ts +142 -1
- package/esm/oas/boolean/Boolean.d.ts.map +1 -1
- package/esm/oas/boolean/Boolean.js +130 -1
- package/esm/oas/components/Components.d.ts +252 -2
- package/esm/oas/components/Components.d.ts.map +1 -1
- package/esm/oas/components/Components.js +241 -2
- package/esm/oas/parameter/Parameter.d.ts +160 -0
- package/esm/oas/parameter/Parameter.d.ts.map +1 -1
- package/esm/oas/parameter/Parameter.js +144 -0
- package/esm/oas/union/Union.d.ts +119 -5
- package/esm/oas/union/Union.d.ts.map +1 -1
- package/esm/oas/union/Union.js +108 -5
- package/package.json +1 -1
- package/script/context/ParseContext.d.ts +178 -0
- package/script/context/ParseContext.d.ts.map +1 -1
- package/script/context/ParseContext.js +108 -0
- package/script/context/RenderContext.d.ts +190 -0
- package/script/context/RenderContext.d.ts.map +1 -1
- package/script/context/RenderContext.js +179 -0
- package/script/dsl/Inserted.d.ts +240 -0
- package/script/dsl/Inserted.d.ts.map +1 -1
- package/script/dsl/Inserted.js +231 -0
- package/script/helpers/refFns.d.ts +160 -0
- package/script/helpers/refFns.d.ts.map +1 -1
- package/script/helpers/refFns.js +156 -0
- package/script/oas/boolean/Boolean.d.ts +142 -1
- package/script/oas/boolean/Boolean.d.ts.map +1 -1
- package/script/oas/boolean/Boolean.js +130 -1
- package/script/oas/components/Components.d.ts +252 -2
- package/script/oas/components/Components.d.ts.map +1 -1
- package/script/oas/components/Components.js +241 -2
- package/script/oas/parameter/Parameter.d.ts +160 -0
- package/script/oas/parameter/Parameter.d.ts.map +1 -1
- package/script/oas/parameter/Parameter.js +144 -0
- package/script/oas/union/Union.d.ts +119 -5
- package/script/oas/union/Union.d.ts.map +1 -1
- package/script/oas/union/Union.js +108 -5
package/esm/dsl/Inserted.js
CHANGED
|
@@ -1,11 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Represents a successfully inserted generator artifact in the SKMTC DSL system.
|
|
3
|
+
*
|
|
4
|
+
* The `Inserted` class is returned when generators are inserted into the generation
|
|
5
|
+
* context, providing access to the generated content, metadata, and configuration.
|
|
6
|
+
* It acts as a bridge between the insertion process and the consuming code that
|
|
7
|
+
* needs to reference or use the generated artifacts.
|
|
8
|
+
*
|
|
9
|
+
* This class provides type-safe access to generated values with proper handling
|
|
10
|
+
* of both forced and lazy generation modes, ensuring the correct optionality
|
|
11
|
+
* of the generated content based on the generation strategy used.
|
|
12
|
+
*
|
|
13
|
+
* ## Key Features
|
|
14
|
+
*
|
|
15
|
+
* - **Type Safety**: Generic parameters preserve exact types from generators
|
|
16
|
+
* - **Generation Modes**: Handles both 'force' and 'lazy' generation strategies
|
|
17
|
+
* - **Metadata Access**: Provides access to identifiers, export paths, and settings
|
|
18
|
+
* - **Value Extraction**: Type-safe value extraction with proper optionality
|
|
19
|
+
* - **Enrichment Support**: Full support for custom enrichment data types
|
|
20
|
+
*
|
|
21
|
+
* @template V - The type of generated value (preserves generator output type)
|
|
22
|
+
* @template T - The generation type ('force' ensures non-null, 'lazy' allows undefined)
|
|
23
|
+
* @template EnrichmentType - Optional type for custom enrichment data
|
|
24
|
+
*
|
|
25
|
+
* @example Basic usage with forced generation
|
|
26
|
+
* ```typescript
|
|
27
|
+
* import { Inserted } from '@skmtc/core';
|
|
28
|
+
*
|
|
29
|
+
* class MyGenerator extends ModelBase {
|
|
30
|
+
* generate(): Definition {
|
|
31
|
+
* // Insert a related model with forced generation
|
|
32
|
+
* const userModel = this.insertModel(
|
|
33
|
+
* new UserModelGenerator({ ... }),
|
|
34
|
+
* 'User'
|
|
35
|
+
* ); // Returns Inserted<UserModelValue, 'force', EnrichmentType>
|
|
36
|
+
*
|
|
37
|
+
* // Access the generated value (guaranteed to be present)
|
|
38
|
+
* const userTypeName = userModel.toValue(); // UserModelValue (not undefined)
|
|
39
|
+
* const exportPath = userModel.toExportPath(); // './src/models.ts'
|
|
40
|
+
* const identifier = userModel.toName(); // 'User'
|
|
41
|
+
*
|
|
42
|
+
* return new Definition({
|
|
43
|
+
* identifier: Identifier.createType(this.refName),
|
|
44
|
+
* value: {
|
|
45
|
+
* generatorKey: this.generatorKey,
|
|
46
|
+
* content: `export interface Order { user: ${userTypeName}; }`
|
|
47
|
+
* }
|
|
48
|
+
* });
|
|
49
|
+
* }
|
|
50
|
+
* }
|
|
51
|
+
* ```
|
|
52
|
+
*
|
|
53
|
+
* @example Working with lazy generation
|
|
54
|
+
* ```typescript
|
|
55
|
+
* class ConditionalGenerator extends ModelBase {
|
|
56
|
+
* generate(): Definition {
|
|
57
|
+
* // Insert with lazy generation (may not generate if already exists)
|
|
58
|
+
* const optionalModel = this.insertModel(
|
|
59
|
+
* new OptionalModelGenerator({ ... }),
|
|
60
|
+
* 'OptionalModel',
|
|
61
|
+
* { generation: 'lazy' }
|
|
62
|
+
* ); // Returns Inserted<OptionalValue, 'lazy', EnrichmentType>
|
|
63
|
+
*
|
|
64
|
+
* // Value might be undefined with lazy generation
|
|
65
|
+
* const value = optionalModel.toValue(); // OptionalValue | undefined
|
|
66
|
+
*
|
|
67
|
+
* if (value) {
|
|
68
|
+
* // Use the generated value
|
|
69
|
+
* return this.createDefinitionWith(value);
|
|
70
|
+
* } else {
|
|
71
|
+
* // Handle case where generation was skipped
|
|
72
|
+
* return this.createFallbackDefinition();
|
|
73
|
+
* }
|
|
74
|
+
* }
|
|
75
|
+
* }
|
|
76
|
+
* ```
|
|
77
|
+
*
|
|
78
|
+
* @example Accessing insertion metadata
|
|
79
|
+
* ```typescript
|
|
80
|
+
* class MetadataAwareGenerator extends OperationBase {
|
|
81
|
+
* generate(): Definition {
|
|
82
|
+
* const requestModel = this.insertModel(
|
|
83
|
+
* new RequestModelGenerator({ ... }),
|
|
84
|
+
* 'CreateUserRequest'
|
|
85
|
+
* );
|
|
86
|
+
*
|
|
87
|
+
* // Access various metadata
|
|
88
|
+
* const modelName = requestModel.toName(); // 'CreateUserRequest'
|
|
89
|
+
* const identifier = requestModel.toIdentifier(); // Full Identifier object
|
|
90
|
+
* const exportPath = requestModel.toExportPath(); // './src/api/types.ts'
|
|
91
|
+
* const enrichments = requestModel.settings.enrichments; // Custom data
|
|
92
|
+
*
|
|
93
|
+
* console.log(`Generated ${modelName} in ${exportPath}`);
|
|
94
|
+
*
|
|
95
|
+
* return new Definition({
|
|
96
|
+
* identifier: Identifier.createVariable(this.operation.operationId!),
|
|
97
|
+
* value: {
|
|
98
|
+
* generatorKey: this.generatorKey,
|
|
99
|
+
* content: `async function createUser(data: ${modelName}) { ... }`
|
|
100
|
+
* }
|
|
101
|
+
* });
|
|
102
|
+
* }
|
|
103
|
+
* }
|
|
104
|
+
* ```
|
|
105
|
+
*
|
|
106
|
+
* @example With enrichment data
|
|
107
|
+
* ```typescript
|
|
108
|
+
* type ValidationEnrichment = {
|
|
109
|
+
* validators: string[];
|
|
110
|
+
* required: boolean;
|
|
111
|
+
* };
|
|
112
|
+
*
|
|
113
|
+
* class EnrichedGenerator extends ModelBase<ValidationEnrichment> {
|
|
114
|
+
* generate(): Definition {
|
|
115
|
+
* const validatedModel = this.insertModel(
|
|
116
|
+
* new ValidatedModelGenerator({ ... }),
|
|
117
|
+
* 'ValidatedUser'
|
|
118
|
+
* ); // Returns Inserted<ModelValue, 'force', ValidationEnrichment>
|
|
119
|
+
*
|
|
120
|
+
* // Access enrichment data
|
|
121
|
+
* const enrichment = validatedModel.settings.enrichments;
|
|
122
|
+
* const validators = enrichment?.validators ?? [];
|
|
123
|
+
* const isRequired = enrichment?.required ?? false;
|
|
124
|
+
*
|
|
125
|
+
* return new Definition({
|
|
126
|
+
* identifier: Identifier.createType(this.refName),
|
|
127
|
+
* value: {
|
|
128
|
+
* generatorKey: this.generatorKey,
|
|
129
|
+
* content: this.generateWithValidation(validatedModel.toValue(), validators)
|
|
130
|
+
* }
|
|
131
|
+
* });
|
|
132
|
+
* }
|
|
133
|
+
* }
|
|
134
|
+
* ```
|
|
135
|
+
*/
|
|
1
136
|
export class Inserted {
|
|
137
|
+
/**
|
|
138
|
+
* Creates a new Inserted instance.
|
|
139
|
+
*
|
|
140
|
+
* @param args - Insertion configuration
|
|
141
|
+
* @param args.settings - Content settings with identifier and export path
|
|
142
|
+
* @param args.definition - The generated definition containing the value
|
|
143
|
+
*/
|
|
2
144
|
constructor({ settings, definition }) {
|
|
145
|
+
/** Content settings including identifier and export path */
|
|
3
146
|
Object.defineProperty(this, "settings", {
|
|
4
147
|
enumerable: true,
|
|
5
148
|
configurable: true,
|
|
6
149
|
writable: true,
|
|
7
150
|
value: void 0
|
|
8
151
|
});
|
|
152
|
+
/** The generated definition with its value */
|
|
9
153
|
Object.defineProperty(this, "definition", {
|
|
10
154
|
enumerable: true,
|
|
11
155
|
configurable: true,
|
|
@@ -15,15 +159,102 @@ export class Inserted {
|
|
|
15
159
|
this.settings = settings;
|
|
16
160
|
this.definition = definition;
|
|
17
161
|
}
|
|
162
|
+
/**
|
|
163
|
+
* Gets the name of the inserted artifact.
|
|
164
|
+
*
|
|
165
|
+
* This method returns the string name from the identifier, which is commonly
|
|
166
|
+
* used when referencing the generated artifact in code or templates.
|
|
167
|
+
*
|
|
168
|
+
* @returns The name of the inserted artifact
|
|
169
|
+
*
|
|
170
|
+
* @example
|
|
171
|
+
* ```typescript
|
|
172
|
+
* const userModel = this.insertModel(generator, 'User');
|
|
173
|
+
* const name = userModel.toName(); // 'User'
|
|
174
|
+
*
|
|
175
|
+
* // Use in generated code
|
|
176
|
+
* const code = `interface Order { user: ${name}; }`;
|
|
177
|
+
* ```
|
|
178
|
+
*/
|
|
18
179
|
toName() {
|
|
19
180
|
return this.settings.identifier.name;
|
|
20
181
|
}
|
|
182
|
+
/**
|
|
183
|
+
* Gets the full identifier of the inserted artifact.
|
|
184
|
+
*
|
|
185
|
+
* This method returns the complete Identifier object, which includes both
|
|
186
|
+
* the name and type information. Useful when you need access to entity type
|
|
187
|
+
* or type annotations.
|
|
188
|
+
*
|
|
189
|
+
* @returns The complete Identifier object
|
|
190
|
+
*
|
|
191
|
+
* @example
|
|
192
|
+
* ```typescript
|
|
193
|
+
* const model = this.insertModel(generator, 'User');
|
|
194
|
+
* const identifier = model.toIdentifier();
|
|
195
|
+
*
|
|
196
|
+
* console.log(identifier.name); // 'User'
|
|
197
|
+
* console.log(identifier.entityType); // EntityType instance
|
|
198
|
+
* console.log(identifier.typeName); // Optional type annotation
|
|
199
|
+
* ```
|
|
200
|
+
*/
|
|
21
201
|
toIdentifier() {
|
|
22
202
|
return this.settings.identifier;
|
|
23
203
|
}
|
|
204
|
+
/**
|
|
205
|
+
* Gets the export path where the artifact was generated.
|
|
206
|
+
*
|
|
207
|
+
* This method returns the file path where the generated artifact is located,
|
|
208
|
+
* which is useful for creating import statements or understanding the file
|
|
209
|
+
* structure of generated code.
|
|
210
|
+
*
|
|
211
|
+
* @returns The export path of the generated artifact
|
|
212
|
+
*
|
|
213
|
+
* @example
|
|
214
|
+
* ```typescript
|
|
215
|
+
* const userModel = this.insertModel(generator, 'User');
|
|
216
|
+
* const exportPath = userModel.toExportPath(); // './src/models/User.ts'
|
|
217
|
+
*
|
|
218
|
+
* // Create import statement
|
|
219
|
+
* const importStmt = `import { User } from '${exportPath}';`;
|
|
220
|
+
* ```
|
|
221
|
+
*/
|
|
24
222
|
toExportPath() {
|
|
25
223
|
return this.settings.exportPath;
|
|
26
224
|
}
|
|
225
|
+
/**
|
|
226
|
+
* Gets the generated value from the inserted artifact.
|
|
227
|
+
*
|
|
228
|
+
* This method returns the actual generated content with proper type safety
|
|
229
|
+
* based on the generation mode. For 'force' generation, the value is guaranteed
|
|
230
|
+
* to be present. For 'lazy' generation, the value might be undefined if
|
|
231
|
+
* generation was skipped.
|
|
232
|
+
*
|
|
233
|
+
* @returns The generated value, with optionality based on generation type
|
|
234
|
+
*
|
|
235
|
+
* @example Forced generation (guaranteed value)
|
|
236
|
+
* ```typescript
|
|
237
|
+
* const userModel = this.insertModel(generator, 'User'); // 'force' by default
|
|
238
|
+
* const value = userModel.toValue(); // UserModelValue (never undefined)
|
|
239
|
+
*
|
|
240
|
+
* // Safe to use directly
|
|
241
|
+
* const code = `type OrderUser = ${value};`;
|
|
242
|
+
* ```
|
|
243
|
+
*
|
|
244
|
+
* @example Lazy generation (optional value)
|
|
245
|
+
* ```typescript
|
|
246
|
+
* const optionalModel = this.insertModel(generator, 'Optional', { generation: 'lazy' });
|
|
247
|
+
* const value = optionalModel.toValue(); // OptionalValue | undefined
|
|
248
|
+
*
|
|
249
|
+
* if (value) {
|
|
250
|
+
* // Use the generated value
|
|
251
|
+
* const code = `type Optional = ${value};`;
|
|
252
|
+
* } else {
|
|
253
|
+
* // Handle missing value (generation was skipped)
|
|
254
|
+
* const code = 'type Optional = any; // Fallback';
|
|
255
|
+
* }
|
|
256
|
+
* ```
|
|
257
|
+
*/
|
|
27
258
|
toValue() {
|
|
28
259
|
return this.definition?.value;
|
|
29
260
|
}
|
package/esm/helpers/refFns.d.ts
CHANGED
|
@@ -2,11 +2,171 @@ import "../_dnt.polyfills.js";
|
|
|
2
2
|
import type { RefName } from '../types/RefName.js';
|
|
3
3
|
import type { OpenAPIV3 } from 'openapi-types';
|
|
4
4
|
import type { ReferenceObject } from '../oas/_merge-all-of/types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Extracts a reference name from an OpenAPI $ref string.
|
|
7
|
+
*
|
|
8
|
+
* This function parses JSON Pointer references (like '#/components/schemas/User')
|
|
9
|
+
* and extracts the final component as a branded RefName type. It's used throughout
|
|
10
|
+
* the SKMTC system to convert string references into type-safe reference names.
|
|
11
|
+
*
|
|
12
|
+
* @param $ref - The OpenAPI reference string (e.g., '#/components/schemas/User')
|
|
13
|
+
* @returns The extracted reference name as a branded RefName type
|
|
14
|
+
*
|
|
15
|
+
* @throws {Error} When the reference string is invalid or empty
|
|
16
|
+
*
|
|
17
|
+
* @example Basic usage
|
|
18
|
+
* ```typescript
|
|
19
|
+
* import { toRefName } from '@skmtc/core/helpers';
|
|
20
|
+
*
|
|
21
|
+
* const refName = toRefName('#/components/schemas/User');
|
|
22
|
+
* console.log(refName); // 'User' (typed as RefName)
|
|
23
|
+
*
|
|
24
|
+
* const responseRef = toRefName('#/components/responses/ErrorResponse');
|
|
25
|
+
* console.log(responseRef); // 'ErrorResponse' (typed as RefName)
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* @example Error cases
|
|
29
|
+
* ```typescript
|
|
30
|
+
* // These will throw errors:
|
|
31
|
+
* toRefName('invalid/ref/'); // Error: 'Invalid reference'
|
|
32
|
+
* toRefName('#/components/schemas/'); // Error: 'Invalid reference'
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* @example Integration with OAS processing
|
|
36
|
+
* ```typescript
|
|
37
|
+
* class SchemaProcessor {
|
|
38
|
+
* processReference(ref: string) {
|
|
39
|
+
* const refName = toRefName(ref);
|
|
40
|
+
* const schema = this.document.components.schemas[refName];
|
|
41
|
+
* return this.processSchema(schema, refName);
|
|
42
|
+
* }
|
|
43
|
+
* }
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
5
46
|
export declare const toRefName: ($ref: string) => RefName;
|
|
47
|
+
/**
|
|
48
|
+
* Type representing an object with a $ref property.
|
|
49
|
+
*/
|
|
6
50
|
type Ref = {
|
|
51
|
+
/** The OpenAPI reference string */
|
|
7
52
|
$ref: string;
|
|
8
53
|
};
|
|
54
|
+
/**
|
|
55
|
+
* Type guard function to check if a value is an OpenAPI reference object.
|
|
56
|
+
*
|
|
57
|
+
* This function performs runtime type checking to determine if an unknown value
|
|
58
|
+
* is an OpenAPI Reference Object (contains a $ref property with a string value).
|
|
59
|
+
* It's essential for safely handling mixed schema/reference data during processing.
|
|
60
|
+
*
|
|
61
|
+
* @param value - The value to check for reference properties
|
|
62
|
+
* @returns True if the value is a reference object, false otherwise
|
|
63
|
+
*
|
|
64
|
+
* @example Basic type checking
|
|
65
|
+
* ```typescript
|
|
66
|
+
* import { isRef } from '@skmtc/core/helpers';
|
|
67
|
+
*
|
|
68
|
+
* const schemaOrRef: unknown = { $ref: '#/components/schemas/User' };
|
|
69
|
+
*
|
|
70
|
+
* if (isRef(schemaOrRef)) {
|
|
71
|
+
* // TypeScript now knows schemaOrRef has a $ref property
|
|
72
|
+
* console.log(schemaOrRef.$ref); // Safe to access
|
|
73
|
+
* const refName = toRefName(schemaOrRef.$ref);
|
|
74
|
+
* } else {
|
|
75
|
+
* // Handle as actual schema object
|
|
76
|
+
* console.log('Direct schema object');
|
|
77
|
+
* }
|
|
78
|
+
* ```
|
|
79
|
+
*
|
|
80
|
+
* @example Processing mixed data
|
|
81
|
+
* ```typescript
|
|
82
|
+
* function processSchemaOrRef(data: unknown) {
|
|
83
|
+
* if (isRef(data)) {
|
|
84
|
+
* // Handle reference
|
|
85
|
+
* return resolveReference(data.$ref);
|
|
86
|
+
* } else {
|
|
87
|
+
* // Handle direct schema
|
|
88
|
+
* return processSchema(data as SchemaObject);
|
|
89
|
+
* }
|
|
90
|
+
* }
|
|
91
|
+
* ```
|
|
92
|
+
*
|
|
93
|
+
* @example Array processing
|
|
94
|
+
* ```typescript
|
|
95
|
+
* const mixedArray: unknown[] = [
|
|
96
|
+
* { type: 'string' },
|
|
97
|
+
* { $ref: '#/components/schemas/User' },
|
|
98
|
+
* { type: 'number' }
|
|
99
|
+
* ];
|
|
100
|
+
*
|
|
101
|
+
* const references = mixedArray.filter(isRef);
|
|
102
|
+
* const schemas = mixedArray.filter(item => !isRef(item));
|
|
103
|
+
* ```
|
|
104
|
+
*/
|
|
9
105
|
export declare const isRef: (value: unknown) => value is Ref;
|
|
106
|
+
/**
|
|
107
|
+
* Creates a reference resolver function for an OpenAPI document.
|
|
108
|
+
*
|
|
109
|
+
* This higher-order function returns a resolver that can dereference OpenAPI
|
|
110
|
+
* JSON Pointer references within the context of a specific document. It handles
|
|
111
|
+
* nested references by recursively resolving reference chains until it reaches
|
|
112
|
+
* an actual schema object.
|
|
113
|
+
*
|
|
114
|
+
* The resolver is particularly useful during schema processing where you need
|
|
115
|
+
* to follow reference chains to get the actual schema definitions.
|
|
116
|
+
*
|
|
117
|
+
* @param oasDocument - The OpenAPI document containing the schemas to resolve against
|
|
118
|
+
* @returns A function that resolves reference objects to schema objects
|
|
119
|
+
*
|
|
120
|
+
* @throws {Error} When a reference cannot be resolved or points to a non-existent schema
|
|
121
|
+
*
|
|
122
|
+
* @example Basic usage
|
|
123
|
+
* ```typescript
|
|
124
|
+
* import { toGetRef } from '@skmtc/core/helpers';
|
|
125
|
+
*
|
|
126
|
+
* const resolver = toGetRef(openApiDocument);
|
|
127
|
+
*
|
|
128
|
+
* const userSchema = resolver({ $ref: '#/components/schemas/User' });
|
|
129
|
+
* console.log(userSchema.type); // 'object'
|
|
130
|
+
* console.log(userSchema.properties); // User properties
|
|
131
|
+
* ```
|
|
132
|
+
*
|
|
133
|
+
* @example Resolving nested references
|
|
134
|
+
* ```typescript
|
|
135
|
+
* // If User references Address, and Address references Country
|
|
136
|
+
* const resolver = toGetRef(document);
|
|
137
|
+
*
|
|
138
|
+
* // This will follow the chain: User -> Address -> Country
|
|
139
|
+
* const resolvedSchema = resolver({ $ref: '#/components/schemas/User' });
|
|
140
|
+
* // Returns the final resolved schema object
|
|
141
|
+
* ```
|
|
142
|
+
*
|
|
143
|
+
* @example Error handling
|
|
144
|
+
* ```typescript
|
|
145
|
+
* const resolver = toGetRef(document);
|
|
146
|
+
*
|
|
147
|
+
* try {
|
|
148
|
+
* const schema = resolver({ $ref: '#/components/schemas/NonExistent' });
|
|
149
|
+
* } catch (error) {
|
|
150
|
+
* console.error('Reference resolution failed:', error.message);
|
|
151
|
+
* // Error: Invalid reference: #/components/schemas/NonExistent
|
|
152
|
+
* }
|
|
153
|
+
* ```
|
|
154
|
+
*
|
|
155
|
+
* @example Integration with schema processing
|
|
156
|
+
* ```typescript
|
|
157
|
+
* class SchemaProcessor {
|
|
158
|
+
* private resolver = toGetRef(this.document);
|
|
159
|
+
*
|
|
160
|
+
* processProperty(property: SchemaObject | ReferenceObject) {
|
|
161
|
+
* if (isRef(property)) {
|
|
162
|
+
* const resolved = this.resolver(property);
|
|
163
|
+
* return this.processSchema(resolved);
|
|
164
|
+
* }
|
|
165
|
+
* return this.processSchema(property);
|
|
166
|
+
* }
|
|
167
|
+
* }
|
|
168
|
+
* ```
|
|
169
|
+
*/
|
|
10
170
|
export declare const toGetRef: (oasDocument: OpenAPIV3.Document) => ({ $ref }: ReferenceObject) => OpenAPIV3.SchemaObject;
|
|
11
171
|
export {};
|
|
12
172
|
//# sourceMappingURL=refFns.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"refFns.d.ts","sourceRoot":"","sources":["../../src/helpers/refFns.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAC9C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AAEpE,eAAO,MAAM,SAAS,GAAI,MAAM,MAAM,KAAG,OASxC,CAAA;AAED,KAAK,GAAG,GAAG;IACT,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED,eAAO,MAAM,KAAK,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,GAM/C,CAAA;AAED,eAAO,MAAM,QAAQ,GAClB,aAAa,SAAS,CAAC,QAAQ,MAC/B,UAAU,eAAe,KAAG,SAAS,CAAC,YActC,CAAA"}
|
|
1
|
+
{"version":3,"file":"refFns.d.ts","sourceRoot":"","sources":["../../src/helpers/refFns.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAC9C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AAEpE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,eAAO,MAAM,SAAS,GAAI,MAAM,MAAM,KAAG,OASxC,CAAA;AAED;;GAEG;AACH,KAAK,GAAG,GAAG;IACT,mCAAmC;IACnC,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AACH,eAAO,MAAM,KAAK,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,GAM/C,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+DG;AACH,eAAO,MAAM,QAAQ,GAClB,aAAa,SAAS,CAAC,QAAQ,MAC/B,UAAU,eAAe,KAAG,SAAS,CAAC,YActC,CAAA"}
|
package/esm/helpers/refFns.js
CHANGED
|
@@ -1,4 +1,45 @@
|
|
|
1
1
|
import "../_dnt.polyfills.js";
|
|
2
|
+
/**
|
|
3
|
+
* Extracts a reference name from an OpenAPI $ref string.
|
|
4
|
+
*
|
|
5
|
+
* This function parses JSON Pointer references (like '#/components/schemas/User')
|
|
6
|
+
* and extracts the final component as a branded RefName type. It's used throughout
|
|
7
|
+
* the SKMTC system to convert string references into type-safe reference names.
|
|
8
|
+
*
|
|
9
|
+
* @param $ref - The OpenAPI reference string (e.g., '#/components/schemas/User')
|
|
10
|
+
* @returns The extracted reference name as a branded RefName type
|
|
11
|
+
*
|
|
12
|
+
* @throws {Error} When the reference string is invalid or empty
|
|
13
|
+
*
|
|
14
|
+
* @example Basic usage
|
|
15
|
+
* ```typescript
|
|
16
|
+
* import { toRefName } from '@skmtc/core/helpers';
|
|
17
|
+
*
|
|
18
|
+
* const refName = toRefName('#/components/schemas/User');
|
|
19
|
+
* console.log(refName); // 'User' (typed as RefName)
|
|
20
|
+
*
|
|
21
|
+
* const responseRef = toRefName('#/components/responses/ErrorResponse');
|
|
22
|
+
* console.log(responseRef); // 'ErrorResponse' (typed as RefName)
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
25
|
+
* @example Error cases
|
|
26
|
+
* ```typescript
|
|
27
|
+
* // These will throw errors:
|
|
28
|
+
* toRefName('invalid/ref/'); // Error: 'Invalid reference'
|
|
29
|
+
* toRefName('#/components/schemas/'); // Error: 'Invalid reference'
|
|
30
|
+
* ```
|
|
31
|
+
*
|
|
32
|
+
* @example Integration with OAS processing
|
|
33
|
+
* ```typescript
|
|
34
|
+
* class SchemaProcessor {
|
|
35
|
+
* processReference(ref: string) {
|
|
36
|
+
* const refName = toRefName(ref);
|
|
37
|
+
* const schema = this.document.components.schemas[refName];
|
|
38
|
+
* return this.processSchema(schema, refName);
|
|
39
|
+
* }
|
|
40
|
+
* }
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
2
43
|
export const toRefName = ($ref) => {
|
|
3
44
|
// TODO: Add validation here to ensure reference exists
|
|
4
45
|
const refName = $ref.split('/').slice(-1)[0];
|
|
@@ -7,6 +48,57 @@ export const toRefName = ($ref) => {
|
|
|
7
48
|
}
|
|
8
49
|
return refName;
|
|
9
50
|
};
|
|
51
|
+
/**
|
|
52
|
+
* Type guard function to check if a value is an OpenAPI reference object.
|
|
53
|
+
*
|
|
54
|
+
* This function performs runtime type checking to determine if an unknown value
|
|
55
|
+
* is an OpenAPI Reference Object (contains a $ref property with a string value).
|
|
56
|
+
* It's essential for safely handling mixed schema/reference data during processing.
|
|
57
|
+
*
|
|
58
|
+
* @param value - The value to check for reference properties
|
|
59
|
+
* @returns True if the value is a reference object, false otherwise
|
|
60
|
+
*
|
|
61
|
+
* @example Basic type checking
|
|
62
|
+
* ```typescript
|
|
63
|
+
* import { isRef } from '@skmtc/core/helpers';
|
|
64
|
+
*
|
|
65
|
+
* const schemaOrRef: unknown = { $ref: '#/components/schemas/User' };
|
|
66
|
+
*
|
|
67
|
+
* if (isRef(schemaOrRef)) {
|
|
68
|
+
* // TypeScript now knows schemaOrRef has a $ref property
|
|
69
|
+
* console.log(schemaOrRef.$ref); // Safe to access
|
|
70
|
+
* const refName = toRefName(schemaOrRef.$ref);
|
|
71
|
+
* } else {
|
|
72
|
+
* // Handle as actual schema object
|
|
73
|
+
* console.log('Direct schema object');
|
|
74
|
+
* }
|
|
75
|
+
* ```
|
|
76
|
+
*
|
|
77
|
+
* @example Processing mixed data
|
|
78
|
+
* ```typescript
|
|
79
|
+
* function processSchemaOrRef(data: unknown) {
|
|
80
|
+
* if (isRef(data)) {
|
|
81
|
+
* // Handle reference
|
|
82
|
+
* return resolveReference(data.$ref);
|
|
83
|
+
* } else {
|
|
84
|
+
* // Handle direct schema
|
|
85
|
+
* return processSchema(data as SchemaObject);
|
|
86
|
+
* }
|
|
87
|
+
* }
|
|
88
|
+
* ```
|
|
89
|
+
*
|
|
90
|
+
* @example Array processing
|
|
91
|
+
* ```typescript
|
|
92
|
+
* const mixedArray: unknown[] = [
|
|
93
|
+
* { type: 'string' },
|
|
94
|
+
* { $ref: '#/components/schemas/User' },
|
|
95
|
+
* { type: 'number' }
|
|
96
|
+
* ];
|
|
97
|
+
*
|
|
98
|
+
* const references = mixedArray.filter(isRef);
|
|
99
|
+
* const schemas = mixedArray.filter(item => !isRef(item));
|
|
100
|
+
* ```
|
|
101
|
+
*/
|
|
10
102
|
export const isRef = (value) => {
|
|
11
103
|
if (value && typeof value === 'object' && '$ref' in value && typeof value.$ref === 'string') {
|
|
12
104
|
return true;
|
|
@@ -15,6 +107,70 @@ export const isRef = (value) => {
|
|
|
15
107
|
return false;
|
|
16
108
|
}
|
|
17
109
|
};
|
|
110
|
+
/**
|
|
111
|
+
* Creates a reference resolver function for an OpenAPI document.
|
|
112
|
+
*
|
|
113
|
+
* This higher-order function returns a resolver that can dereference OpenAPI
|
|
114
|
+
* JSON Pointer references within the context of a specific document. It handles
|
|
115
|
+
* nested references by recursively resolving reference chains until it reaches
|
|
116
|
+
* an actual schema object.
|
|
117
|
+
*
|
|
118
|
+
* The resolver is particularly useful during schema processing where you need
|
|
119
|
+
* to follow reference chains to get the actual schema definitions.
|
|
120
|
+
*
|
|
121
|
+
* @param oasDocument - The OpenAPI document containing the schemas to resolve against
|
|
122
|
+
* @returns A function that resolves reference objects to schema objects
|
|
123
|
+
*
|
|
124
|
+
* @throws {Error} When a reference cannot be resolved or points to a non-existent schema
|
|
125
|
+
*
|
|
126
|
+
* @example Basic usage
|
|
127
|
+
* ```typescript
|
|
128
|
+
* import { toGetRef } from '@skmtc/core/helpers';
|
|
129
|
+
*
|
|
130
|
+
* const resolver = toGetRef(openApiDocument);
|
|
131
|
+
*
|
|
132
|
+
* const userSchema = resolver({ $ref: '#/components/schemas/User' });
|
|
133
|
+
* console.log(userSchema.type); // 'object'
|
|
134
|
+
* console.log(userSchema.properties); // User properties
|
|
135
|
+
* ```
|
|
136
|
+
*
|
|
137
|
+
* @example Resolving nested references
|
|
138
|
+
* ```typescript
|
|
139
|
+
* // If User references Address, and Address references Country
|
|
140
|
+
* const resolver = toGetRef(document);
|
|
141
|
+
*
|
|
142
|
+
* // This will follow the chain: User -> Address -> Country
|
|
143
|
+
* const resolvedSchema = resolver({ $ref: '#/components/schemas/User' });
|
|
144
|
+
* // Returns the final resolved schema object
|
|
145
|
+
* ```
|
|
146
|
+
*
|
|
147
|
+
* @example Error handling
|
|
148
|
+
* ```typescript
|
|
149
|
+
* const resolver = toGetRef(document);
|
|
150
|
+
*
|
|
151
|
+
* try {
|
|
152
|
+
* const schema = resolver({ $ref: '#/components/schemas/NonExistent' });
|
|
153
|
+
* } catch (error) {
|
|
154
|
+
* console.error('Reference resolution failed:', error.message);
|
|
155
|
+
* // Error: Invalid reference: #/components/schemas/NonExistent
|
|
156
|
+
* }
|
|
157
|
+
* ```
|
|
158
|
+
*
|
|
159
|
+
* @example Integration with schema processing
|
|
160
|
+
* ```typescript
|
|
161
|
+
* class SchemaProcessor {
|
|
162
|
+
* private resolver = toGetRef(this.document);
|
|
163
|
+
*
|
|
164
|
+
* processProperty(property: SchemaObject | ReferenceObject) {
|
|
165
|
+
* if (isRef(property)) {
|
|
166
|
+
* const resolved = this.resolver(property);
|
|
167
|
+
* return this.processSchema(resolved);
|
|
168
|
+
* }
|
|
169
|
+
* return this.processSchema(property);
|
|
170
|
+
* }
|
|
171
|
+
* }
|
|
172
|
+
* ```
|
|
173
|
+
*/
|
|
18
174
|
export const toGetRef = (oasDocument) => ({ $ref }) => {
|
|
19
175
|
const refName = toRefName($ref);
|
|
20
176
|
const item = oasDocument.components?.schemas?.[refName];
|