@goast/typescript 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/README.md +11 -0
  2. package/assets/client/fetch/types.ts +9 -0
  3. package/assets/client/fetch/url-builder.ts +36 -0
  4. package/assets/service/angular/api-configuration.ts +18 -0
  5. package/assets/service/angular/base-service.ts +29 -0
  6. package/assets/service/angular/request-builder.ts +368 -0
  7. package/assets/service/angular/response-handlers.ts +127 -0
  8. package/assets/service/angular/strict-http-response.ts +8 -0
  9. package/cjs/index.js +9 -0
  10. package/cjs/lib/common-results.js +2 -0
  11. package/cjs/lib/config.js +15 -0
  12. package/cjs/lib/file-builder.js +244 -0
  13. package/cjs/lib/generators/file-generator.js +26 -0
  14. package/cjs/lib/generators/index.js +7 -0
  15. package/cjs/lib/generators/models/index.js +6 -0
  16. package/cjs/lib/generators/models/model-generator.js +317 -0
  17. package/cjs/lib/generators/models/models-generator.js +67 -0
  18. package/cjs/lib/generators/models/models.js +6 -0
  19. package/cjs/lib/generators/services/angular-services/angular-service-generator.js +360 -0
  20. package/cjs/lib/generators/services/angular-services/angular-services-generator.js +122 -0
  21. package/cjs/lib/generators/services/angular-services/index.js +6 -0
  22. package/cjs/lib/generators/services/angular-services/models.js +5 -0
  23. package/cjs/lib/generators/services/fetch-clients/fetch-client-generator.js +240 -0
  24. package/cjs/lib/generators/services/fetch-clients/fetch-clients-generator.js +83 -0
  25. package/cjs/lib/generators/services/fetch-clients/index.js +6 -0
  26. package/cjs/lib/generators/services/fetch-clients/models.js +5 -0
  27. package/cjs/lib/import-collection.js +116 -0
  28. package/cjs/lib/utils.js +56 -0
  29. package/cjs/package.json +1 -0
  30. package/esm/index.js +6 -0
  31. package/esm/lib/common-results.js +1 -0
  32. package/esm/lib/config.js +12 -0
  33. package/esm/lib/file-builder.js +240 -0
  34. package/esm/lib/generators/file-generator.js +22 -0
  35. package/esm/lib/generators/index.js +4 -0
  36. package/esm/lib/generators/models/index.js +3 -0
  37. package/esm/lib/generators/models/model-generator.js +313 -0
  38. package/esm/lib/generators/models/models-generator.js +63 -0
  39. package/esm/lib/generators/models/models.js +3 -0
  40. package/esm/lib/generators/services/angular-services/angular-service-generator.js +356 -0
  41. package/esm/lib/generators/services/angular-services/angular-services-generator.js +118 -0
  42. package/esm/lib/generators/services/angular-services/index.js +3 -0
  43. package/esm/lib/generators/services/angular-services/models.js +2 -0
  44. package/esm/lib/generators/services/fetch-clients/fetch-client-generator.js +236 -0
  45. package/esm/lib/generators/services/fetch-clients/fetch-clients-generator.js +79 -0
  46. package/esm/lib/generators/services/fetch-clients/index.js +3 -0
  47. package/esm/lib/generators/services/fetch-clients/models.js +2 -0
  48. package/esm/lib/import-collection.js +112 -0
  49. package/esm/lib/utils.js +48 -0
  50. package/package.json +29 -0
  51. package/types/index.d.ts +6 -0
  52. package/types/lib/common-results.d.ts +11 -0
  53. package/types/lib/config.d.ts +13 -0
  54. package/types/lib/file-builder.d.ts +110 -0
  55. package/types/lib/generators/file-generator.d.ts +11 -0
  56. package/types/lib/generators/index.d.ts +4 -0
  57. package/types/lib/generators/models/index.d.ts +3 -0
  58. package/types/lib/generators/models/model-generator.d.ts +40 -0
  59. package/types/lib/generators/models/models-generator.d.ts +23 -0
  60. package/types/lib/generators/models/models.d.ts +29 -0
  61. package/types/lib/generators/services/angular-services/angular-service-generator.d.ts +53 -0
  62. package/types/lib/generators/services/angular-services/angular-services-generator.d.ts +29 -0
  63. package/types/lib/generators/services/angular-services/index.d.ts +3 -0
  64. package/types/lib/generators/services/angular-services/models.d.ts +41 -0
  65. package/types/lib/generators/services/fetch-clients/fetch-client-generator.d.ts +43 -0
  66. package/types/lib/generators/services/fetch-clients/fetch-clients-generator.d.ts +24 -0
  67. package/types/lib/generators/services/fetch-clients/index.d.ts +3 -0
  68. package/types/lib/generators/services/fetch-clients/models.d.ts +34 -0
  69. package/types/lib/import-collection.d.ts +21 -0
  70. package/types/lib/utils.d.ts +6 -0
@@ -0,0 +1,244 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TypeScriptFileBuilder = void 0;
4
+ const core_1 = require("@goast/core");
5
+ const import_collection_1 = require("./import-collection");
6
+ class TypeScriptFileBuilder extends core_1.SourceBuilder {
7
+ get options() {
8
+ return super.options;
9
+ }
10
+ constructor(filePath, options) {
11
+ super(options);
12
+ this.imports = new import_collection_1.ImportExportCollection();
13
+ this.filePath = filePath;
14
+ }
15
+ addImport(name, moduleNameOrfilePath) {
16
+ this.imports.addImport(name, moduleNameOrfilePath);
17
+ return this;
18
+ }
19
+ addExport(name, filePath) {
20
+ this.imports.addExport(name, filePath);
21
+ return this;
22
+ }
23
+ clear() {
24
+ super.clear();
25
+ this.imports.clear();
26
+ }
27
+ toString(addPadding = true) {
28
+ return new core_1.SourceBuilder(this.options)
29
+ .append((builder) => this.imports.writeTo(builder, this.filePath, this.options.importModuleTransformer))
30
+ .appendIf(addPadding, (builder) => builder.ensurePreviousLineEmpty())
31
+ .append(super.toString())
32
+ .appendIf(addPadding, (builder) => builder.ensureCurrentLineEmpty())
33
+ .toString();
34
+ }
35
+ appendGenericArguments(...genericArguments) {
36
+ genericArguments = genericArguments.filter(core_1.notNullish);
37
+ if (genericArguments.length === 0)
38
+ return this;
39
+ const multiline = genericArguments.length > 1;
40
+ return this.parenthesize('<>', (builder) => builder.appendSeparated(genericArguments, multiline ? ',\n' : ', '), {
41
+ multiline,
42
+ indent: multiline,
43
+ });
44
+ }
45
+ appendParameter(parameter) {
46
+ var _a;
47
+ if (!parameter)
48
+ return;
49
+ if (typeof parameter === 'object') {
50
+ return this.append(parameter.name)
51
+ .appendIf(parameter.isOptional === true, '?')
52
+ .appendIf(parameter.type !== undefined, ': ', (builder) => {
53
+ if (!parameter.type)
54
+ throw new Error('Unreachable error');
55
+ return typeof parameter.type === 'object'
56
+ ? builder.appendExternalTypeUsage(parameter.type)
57
+ : builder.append(parameter.type);
58
+ })
59
+ .appendGenericArguments(...((_a = parameter.genericArguments) !== null && _a !== void 0 ? _a : []))
60
+ .appendIf(parameter.defaultValue !== undefined, ' = ', parameter.defaultValue);
61
+ }
62
+ else {
63
+ return this.append(parameter);
64
+ }
65
+ }
66
+ appendParameters(...parameters) {
67
+ parameters = parameters.filter(core_1.notNullish);
68
+ if (parameters.length === 0)
69
+ return this.append('()');
70
+ const multiline = parameters.length > 1;
71
+ return this.parenthesize('()', (builder) => builder.forEach(parameters, (builder, param) => builder.appendParameter(param), {
72
+ separator: multiline ? ',\n' : ', ',
73
+ }), { multiline, indent: multiline });
74
+ }
75
+ appendObjectLiteral(...properties) {
76
+ properties = properties.filter(core_1.notNullish);
77
+ if (properties.length === 0)
78
+ return this.append('{}');
79
+ const multiline = properties.length > 1;
80
+ return this.parenthesize('{}', (builder) => builder
81
+ .appendIf(!multiline, ' ')
82
+ .appendSeparated(properties, multiline ? ',\n' : ', ')
83
+ .appendIf(!multiline, ' '), { multiline, indent: multiline });
84
+ }
85
+ appendArrayLiteral(...items) {
86
+ items = items.filter(core_1.notNullish);
87
+ if (items.length === 0)
88
+ return this.append('[]');
89
+ const multiline = items.length > 1;
90
+ return this.parenthesize('[]', (builder) => builder.appendSeparated(items, multiline ? ',\n' : ', '), {
91
+ multiline,
92
+ indent: multiline,
93
+ });
94
+ }
95
+ appendCodeBlock(...content) {
96
+ return this.parenthesize('{}', (builder) => builder.append(...content).ensureCurrentLineEmpty(), {
97
+ multiline: true,
98
+ });
99
+ }
100
+ appendComment(style, comment) {
101
+ if (!comment)
102
+ return this;
103
+ if (typeof comment === 'string') {
104
+ comment = comment.trim();
105
+ }
106
+ return style === '//'
107
+ ? this.appendLineWithLinePrefix('// ', comment)
108
+ : this.appendLine(style === '/**/' ? '/*' : '/**')
109
+ .appendWithLinePrefix(' * ', comment)
110
+ .ensureCurrentLineEmpty()
111
+ .appendLine(' */');
112
+ }
113
+ appendDocumentation(documentation) {
114
+ return this.appendComment('/***/', documentation);
115
+ }
116
+ appendModelUsage(type) {
117
+ this.append(type.component);
118
+ for (const i of type.imports) {
119
+ this.addImport(i.name, i.modulePath);
120
+ }
121
+ return this;
122
+ }
123
+ appendExternalTypeUsage(type) {
124
+ return this.append(type.name).addImport(type.name, type.module);
125
+ }
126
+ appendTypeDeclaration(options) {
127
+ return this.appendDocumentation(options.documentation)
128
+ .appendIf(options.omitExport !== true, 'export ')
129
+ .append('type ')
130
+ .append(options.name)
131
+ .append(' = ')
132
+ .append(options.type)
133
+ .appendLine(';');
134
+ }
135
+ appendAnnotation(options) {
136
+ var _a;
137
+ if (options.module)
138
+ this.addImport(options.name, options.module);
139
+ return this.append(`@${options.name}`).appendParameters(...((_a = options.args) !== null && _a !== void 0 ? _a : []));
140
+ }
141
+ appendAnnotations(annotations, separator) {
142
+ if (annotations.length === 0)
143
+ return this;
144
+ return this.forEach(annotations, (builder, annotation) => builder.appendAnnotation(annotation).append(separator));
145
+ }
146
+ appendClass(options) {
147
+ var _a;
148
+ return this.appendComment('/***/', options.documentation)
149
+ .appendAnnotations((_a = options.annotations) !== null && _a !== void 0 ? _a : [], '\n')
150
+ .appendIf(options.omitExport !== true, 'export ')
151
+ .appendIf(options.isAbstract === true, 'abstract ')
152
+ .append('class ')
153
+ .append(options.name)
154
+ .indent((builder) => {
155
+ var _a;
156
+ return builder
157
+ .appendGenericArguments(...((_a = options === null || options === void 0 ? void 0 : options.genericArguments) !== null && _a !== void 0 ? _a : []))
158
+ .appendIf(options.extends !== undefined, '\nextends ', options.extends)
159
+ .appendIf(options.implements !== undefined && options.implements.length > 0, ' implements ', (builder) => { var _a; return builder.appendSeparated((_a = options.implements) !== null && _a !== void 0 ? _a : [], ', '); });
160
+ })
161
+ .append(options.extends || (options.implements !== undefined && options.implements.length > 0) ? '\n' : ' ')
162
+ .appendCodeBlock(options.body)
163
+ .appendLine();
164
+ }
165
+ appendConstructor(options) {
166
+ var _a, _b;
167
+ return this.appendComment('/***/', options.documentation)
168
+ .appendAnnotations((_a = options.annotations) !== null && _a !== void 0 ? _a : [], '\n')
169
+ .append('constructor')
170
+ .appendParameters(...((_b = options === null || options === void 0 ? void 0 : options.parameters) !== null && _b !== void 0 ? _b : []))
171
+ .append(' ')
172
+ .appendCodeBlock(options.body)
173
+ .appendLine();
174
+ }
175
+ appendMethod(options) {
176
+ var _a, _b, _c;
177
+ return this.appendComment('/***/', options.documentation)
178
+ .appendAnnotations((_a = options.annotations) !== null && _a !== void 0 ? _a : [], '\n')
179
+ .appendIf(options.accessibility !== undefined, options.accessibility, ' ')
180
+ .appendIf(options.isAbstract === true, 'abstract ')
181
+ .appendIf(options.isStatic === true, 'static ')
182
+ .appendIf(options.isAsync === true, 'async ')
183
+ .append(options.name)
184
+ .appendGenericArguments(...((_b = options === null || options === void 0 ? void 0 : options.genericArguments) !== null && _b !== void 0 ? _b : []))
185
+ .appendParameters(...((_c = options === null || options === void 0 ? void 0 : options.parameters) !== null && _c !== void 0 ? _c : []))
186
+ .appendIf(options.returnType !== undefined, ': ', options.returnType)
187
+ .append(' ')
188
+ .appendCodeBlock(options.body)
189
+ .appendLine();
190
+ }
191
+ appendProperty(options) {
192
+ var _a, _b, _c, _d, _e;
193
+ if (options.kind === 'getter' || options.kind === 'setter' || options.kind === 'getter-setter') {
194
+ if (options.kind === 'getter-setter' || options.kind === 'getter') {
195
+ this.appendComment('/***/', options.documentation)
196
+ .appendAnnotations([...((_a = options.annotations) !== null && _a !== void 0 ? _a : []), ...((_b = options.getterAnnotations) !== null && _b !== void 0 ? _b : [])], '\n')
197
+ .appendIf(options.accessibility !== undefined, options.accessibility, ' ')
198
+ .appendIf(options.isAbstract === true, 'abstract ')
199
+ .appendIf(options.isStatic === true, 'static ')
200
+ .append('get ', options.name, '()')
201
+ .appendIf(options.type !== undefined, ': ', options.type)
202
+ .if(options.isAbstract === true, (builder) => builder.append(';'), (builder) => builder.append(' ').appendCodeBlock(options.getter))
203
+ .ensureCurrentLineEmpty();
204
+ }
205
+ if (options.kind === 'getter-setter' || options.kind === 'setter') {
206
+ this.appendComment('/***/', options.documentation)
207
+ .appendAnnotations([...((_c = options.annotations) !== null && _c !== void 0 ? _c : []), ...((_d = options.setterAnnotations) !== null && _d !== void 0 ? _d : [])], '\n')
208
+ .appendIf(options.accessibility !== undefined, options.accessibility, ' ')
209
+ .appendIf(options.isAbstract === true, 'abstract ')
210
+ .appendIf(options.isStatic === true, 'static ')
211
+ .append('set ', options.name)
212
+ .parenthesize('()', (builder) => builder.append('value: ', options.type))
213
+ .if(options.isAbstract === true, (builder) => builder.append(';'), (builder) => builder.append(' ').appendCodeBlock(options.setter))
214
+ .ensureCurrentLineEmpty();
215
+ }
216
+ return this;
217
+ }
218
+ return this.appendComment('/***/', options.documentation)
219
+ .appendAnnotations((_e = options.annotations) !== null && _e !== void 0 ? _e : [], '\n')
220
+ .appendIf(options.accessibility !== undefined, options.accessibility, ' ')
221
+ .appendIf(options.isAbstract === true, 'abstract ')
222
+ .appendIf(options.isStatic === true, 'static ')
223
+ .appendIf(options.isReadonly === true, 'readonly ')
224
+ .append(options.name)
225
+ .appendIf(options.isOptional === true, '?')
226
+ .appendIf(options.type !== undefined, ': ', options.type)
227
+ .appendIf(options.initializer !== undefined, ' = ', options.initializer)
228
+ .appendLine(';');
229
+ }
230
+ appendFunction(options) {
231
+ var _a, _b;
232
+ const kind = (_a = options.kind) !== null && _a !== void 0 ? _a : 'arrow-function';
233
+ return this.appendIf(kind === 'arrow-function' && !!options.name, 'const ', options.name, ' = ')
234
+ .appendIf(options.isAsync === true, 'async ')
235
+ .appendIf(kind === 'function', 'function')
236
+ .appendIf(kind === 'function' && !!options.name, ' ', options.name)
237
+ .appendParameters(...((_b = options === null || options === void 0 ? void 0 : options.parameters) !== null && _b !== void 0 ? _b : []))
238
+ .appendIf(options.returnType !== undefined, ': ', options.returnType)
239
+ .append(' ')
240
+ .appendIf(kind === 'arrow-function', '=> ')
241
+ .parenthesizeIf(kind === 'function' || options.singleLine !== true, '{}', (builder) => builder.append(options.body), { multiline: true });
242
+ }
243
+ }
244
+ exports.TypeScriptFileBuilder = TypeScriptFileBuilder;
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TypeScriptFileGenerator = void 0;
4
+ const core_1 = require("@goast/core");
5
+ const utils_1 = require("../utils");
6
+ class TypeScriptFileGenerator {
7
+ getAnyType(context) {
8
+ return context.config.preferUnknown ? 'unknown' : 'any';
9
+ }
10
+ toTypeName(context, name) {
11
+ return (0, core_1.toCasing)(name, context.config.typeNameCasing);
12
+ }
13
+ toMethodName(context, name) {
14
+ return (0, utils_1.toTypeScriptPropertyName)((0, core_1.toCasing)(name, context.config.methodNameCasing), context.config.useSingleQuotes);
15
+ }
16
+ toPropertyName(context, name, keepCasing = false) {
17
+ return (0, utils_1.toTypeScriptPropertyName)(keepCasing ? name : (0, core_1.toCasing)(name, context.config.propertyNameCasing), context.config.useSingleQuotes);
18
+ }
19
+ toEnumValueName(context, name) {
20
+ return (0, utils_1.toTypeScriptPropertyName)((0, core_1.toCasing)(name, context.config.enumValueNameCasing), context.config.useSingleQuotes);
21
+ }
22
+ toStringLiteral(context, text) {
23
+ return (0, utils_1.toTypeScriptStringLiteral)(text, context.config.useSingleQuotes);
24
+ }
25
+ }
26
+ exports.TypeScriptFileGenerator = TypeScriptFileGenerator;
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ tslib_1.__exportStar(require("./file-generator"), exports);
5
+ tslib_1.__exportStar(require("./models"), exports);
6
+ tslib_1.__exportStar(require("./services/angular-services"), exports);
7
+ tslib_1.__exportStar(require("./services/fetch-clients"), exports);
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ tslib_1.__exportStar(require("./model-generator"), exports);
5
+ tslib_1.__exportStar(require("./models"), exports);
6
+ tslib_1.__exportStar(require("./models-generator"), exports);
@@ -0,0 +1,317 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DefaultTypeScriptModelGenerator = void 0;
4
+ const path_1 = require("path");
5
+ const fs_extra_1 = require("fs-extra");
6
+ const core_1 = require("@goast/core");
7
+ const file_builder_1 = require("../../file-builder");
8
+ const utils_1 = require("../../utils");
9
+ const file_generator_1 = require("../file-generator");
10
+ class DefaultTypeScriptModelGenerator extends file_generator_1.TypeScriptFileGenerator {
11
+ generate(ctx) {
12
+ if (this.shouldGenerateTypeDeclaration(ctx, ctx.schema)) {
13
+ const name = this.getDeclarationTypeName(ctx, ctx.schema);
14
+ const filePath = this.getFilePath(ctx, ctx.schema);
15
+ console.log(`Generating model ${name} to ${filePath}...`);
16
+ (0, fs_extra_1.ensureDirSync)((0, path_1.dirname)(filePath));
17
+ const builder = new file_builder_1.TypeScriptFileBuilder(filePath, ctx.config);
18
+ this.generateFileContent(ctx, builder);
19
+ (0, fs_extra_1.writeFileSync)(filePath, builder.toString());
20
+ return { component: name, filePath, imports: [{ kind: 'file', name, modulePath: filePath }] };
21
+ }
22
+ else {
23
+ const builder = new file_builder_1.TypeScriptFileBuilder(undefined, ctx.config);
24
+ this.generateType(ctx, builder, ctx.schema);
25
+ const imports = builder.imports.imports;
26
+ builder.imports.clear();
27
+ return { component: builder.toString(false), imports };
28
+ }
29
+ }
30
+ generateFileContent(ctx, builder) {
31
+ const interfaceSchema = this.resolveInterfaceSchema(ctx);
32
+ if (interfaceSchema) {
33
+ this.generateInterface(ctx, builder, interfaceSchema);
34
+ }
35
+ else if (ctx.config.enumGeneration !== 'union' &&
36
+ ctx.schema.kind === 'string' &&
37
+ ctx.schema.enum !== undefined &&
38
+ ctx.schema.enum.length > 0) {
39
+ this.generateEnum(ctx, builder);
40
+ }
41
+ else {
42
+ this.generateTypeAlias(ctx, builder);
43
+ }
44
+ }
45
+ generateEnum(ctx, builder) {
46
+ builder
47
+ .append((builder) => this.generateTypeDocumentation(ctx, builder))
48
+ .ensureCurrentLineEmpty()
49
+ .append((builder) => this.generateEnumSignature(ctx, builder))
50
+ .parenthesize('{}', (builder) => this.generateEnumValues(ctx, builder), { multiline: true })
51
+ .ensureCurrentLineEmpty();
52
+ }
53
+ generateEnumSignature(ctx, builder) {
54
+ builder.append('export enum ').append(this.getDeclarationTypeName(ctx, ctx.schema));
55
+ }
56
+ generateEnumValues(ctx, builder) {
57
+ var _a, _b;
58
+ builder.forEach((_b = (_a = ctx.schema.enum) === null || _a === void 0 ? void 0 : _a.map((x) => String(x))) !== null && _b !== void 0 ? _b : [], (builder, enumValue) => builder.append(`${this.toEnumValueName(ctx, enumValue)} = ${this.toStringLiteral(ctx, enumValue)}`), { separator: ',\n' });
59
+ }
60
+ generateInterface(ctx, builder, schema) {
61
+ builder
62
+ .append((builder) => this.generateTypeDocumentation(ctx, builder))
63
+ .ensureCurrentLineEmpty()
64
+ .append((builder) => this.generateInterfaceSignature(ctx, builder))
65
+ .parenthesize('{}', (builder) => builder.append((builder) => this.generateInterfaceContent(ctx, builder, schema)), { multiline: true })
66
+ .ensureCurrentLineEmpty();
67
+ }
68
+ generateInterfaceSignature(ctx, builder) {
69
+ builder.append('export interface ').append(this.getDeclarationTypeName(ctx, ctx.schema));
70
+ }
71
+ generateInterfaceContent(ctx, builder, schema) {
72
+ this.generateObjectTypeProperties(ctx, builder, schema);
73
+ if (schema.additionalProperties) {
74
+ builder.append('[key: string]: ');
75
+ if (schema.additionalProperties === true) {
76
+ builder.append(this.getAnyType(ctx));
77
+ }
78
+ else {
79
+ this.generateTypeUsage(ctx, builder, schema.additionalProperties);
80
+ }
81
+ builder.appendLine(';');
82
+ }
83
+ }
84
+ generateTypeAlias(ctx, builder) {
85
+ builder
86
+ .append((builder) => this.generateTypeDocumentation(ctx, builder))
87
+ .ensureCurrentLineEmpty()
88
+ .append((builder) => this.generateTypeAliasSignature(ctx, builder))
89
+ .append(' = ')
90
+ .append((builder) => this.generateType(ctx, builder, ctx.schema))
91
+ .appendLine(';');
92
+ }
93
+ generateTypeAliasSignature(ctx, builder) {
94
+ builder.append('export type ').append(this.getDeclarationTypeName(ctx, ctx.schema));
95
+ }
96
+ generateTypeUsage(ctx, builder, schema) {
97
+ schema = (0, core_1.getSchemaReference)(schema, ['description']);
98
+ if (this.shouldGenerateTypeDeclaration(ctx, schema)) {
99
+ const name = this.getDeclarationTypeName(ctx, schema);
100
+ const filePath = this.getFilePath(ctx, schema);
101
+ if (filePath) {
102
+ builder.addImport(name, filePath);
103
+ }
104
+ builder.append(name);
105
+ }
106
+ else {
107
+ this.generateType(ctx, builder, schema);
108
+ }
109
+ }
110
+ generateType(ctx, builder, schema) {
111
+ if (schema.enum !== undefined && schema.enum.length > 0) {
112
+ this.generateEnumType(ctx, builder, schema);
113
+ return;
114
+ }
115
+ switch (schema.kind) {
116
+ case 'boolean':
117
+ builder.append('boolean');
118
+ break;
119
+ case 'integer':
120
+ case 'number':
121
+ builder.append('number');
122
+ break;
123
+ case 'string':
124
+ builder.append('string');
125
+ break;
126
+ case 'null':
127
+ builder.append('null');
128
+ break;
129
+ case 'unknown':
130
+ builder.append(this.getAnyType(ctx));
131
+ break;
132
+ case 'array':
133
+ this.generateArrayType(ctx, builder, schema);
134
+ break;
135
+ case 'object':
136
+ this.generateObjectType(ctx, builder, schema);
137
+ break;
138
+ case 'combined':
139
+ this.generateCombinedType(ctx, builder, schema);
140
+ break;
141
+ case 'multi-type':
142
+ this.generateMultiType(ctx, builder, schema);
143
+ break;
144
+ case 'oneOf':
145
+ this.generateOneOfType(ctx, builder, schema);
146
+ break;
147
+ default:
148
+ builder.append(this.getAnyType(ctx));
149
+ break;
150
+ }
151
+ }
152
+ generateArrayType(ctx, builder, schema) {
153
+ builder
154
+ .appendIf(ctx.config.immutableTypes, 'readonly ')
155
+ .parenthesize('()', (builder) => schema.items ? this.generateTypeUsage(ctx, builder, schema.items) : builder.append(this.getAnyType(ctx)))
156
+ .append('[]');
157
+ }
158
+ generateCombinedType(ctx, builder, schema) {
159
+ if (schema.allOf.length === 0 && schema.anyOf.length === 0) {
160
+ builder.append(this.getAnyType(ctx));
161
+ return;
162
+ }
163
+ builder
164
+ .forEach(schema.allOf, (builder, schema) => this.generateTypeUsage(ctx, builder, schema), { separator: ' & ' })
165
+ .appendIf(schema.anyOf.length > 0, (builder) => builder
166
+ .appendIf(schema.allOf.length > 0, ' & ')
167
+ .forEach(schema.anyOf, (builder, schema) => builder
168
+ .append('Partial')
169
+ .parenthesize('<>', (builder) => this.generateTypeUsage(ctx, builder, schema), { indent: false }), { separator: ' & ' }));
170
+ }
171
+ generateOneOfType(ctx, builder, schema) {
172
+ if (schema.oneOf.length === 0) {
173
+ builder.append(this.getAnyType(ctx));
174
+ return;
175
+ }
176
+ builder.parenthesizeIf(schema.oneOf.length > 1, '()', (builder) => builder.forEach(schema.oneOf, (builder, schema) => this.generateTypeUsage(ctx, builder, schema), {
177
+ separator: ' | ',
178
+ }));
179
+ }
180
+ generateMultiType(ctx, builder, schema) {
181
+ if (schema.type.length === 0) {
182
+ builder.append(this.getAnyType(ctx));
183
+ return;
184
+ }
185
+ const parenthesize = schema.type.length > 1;
186
+ builder.parenthesizeIf(parenthesize, '()', (builder) => builder
187
+ .appendIf(parenthesize, (builder) => builder.appendLine().append('| '))
188
+ .forEach(schema.type, (builder, type) => {
189
+ switch (type) {
190
+ case 'string':
191
+ builder.append('string');
192
+ break;
193
+ case 'number':
194
+ case 'integer':
195
+ builder.append('number');
196
+ break;
197
+ case 'boolean':
198
+ builder.append('boolean');
199
+ break;
200
+ case 'null':
201
+ builder.append('null');
202
+ break;
203
+ case 'array':
204
+ this.generateArrayType(ctx, builder, schema);
205
+ break;
206
+ case 'object':
207
+ this.generateObjectType(ctx, builder, schema);
208
+ break;
209
+ default:
210
+ builder.append('never');
211
+ break;
212
+ }
213
+ }, { separator: (builder) => builder.appendLine().append('| ') }));
214
+ }
215
+ generateObjectType(ctx, builder, schema) {
216
+ if (schema.properties.size === 0 &&
217
+ !schema.additionalProperties &&
218
+ schema.allOf.length === 0 &&
219
+ schema.anyOf.length === 0 &&
220
+ schema.discriminator === undefined) {
221
+ builder.append('{}');
222
+ return;
223
+ }
224
+ // properties
225
+ if (schema.properties.size > 0) {
226
+ builder
227
+ .parenthesize('{}', (builder) => builder.appendLine().append((builder) => this.generateObjectTypeProperties(ctx, builder, schema)))
228
+ .appendIf(!!schema.additionalProperties || schema.allOf.length > 0 || schema.anyOf.length > 0, ' & ');
229
+ }
230
+ // additional properties
231
+ if (schema.additionalProperties) {
232
+ this.generateObjectTypeAdditionalProperties(ctx, builder, schema);
233
+ if (schema.allOf.length > 0 || schema.anyOf.length > 0) {
234
+ builder.append(' & ');
235
+ }
236
+ }
237
+ // allOf & anyOf
238
+ if (schema.allOf.length > 0 || schema.anyOf.length > 0) {
239
+ this.generateCombinedType(ctx, builder, schema);
240
+ }
241
+ }
242
+ generateObjectTypeProperties(ctx, builder, schema) {
243
+ builder.forEach(schema.properties.values(), (builder, property) => {
244
+ this.generatePropertyDocumentation(ctx, builder, property);
245
+ builder
246
+ .appendIf(ctx.config.immutableTypes, 'readonly ')
247
+ .append((0, utils_1.toTypeScriptPropertyName)(property.name, ctx.config.useSingleQuotes))
248
+ .appendIf(!schema.required.has(property.name), '?')
249
+ .append(': ')
250
+ .append((builder) => this.generateTypeUsage(ctx, builder, property.schema))
251
+ .appendIf(property.schema.nullable === true, ' | null')
252
+ .appendLine(';');
253
+ });
254
+ }
255
+ generateObjectTypeAdditionalProperties(ctx, builder, schema) {
256
+ if (!schema.additionalProperties)
257
+ return;
258
+ builder
259
+ .appendIf(ctx.config.immutableTypes, 'Readonly')
260
+ .parenthesizeIf(ctx.config.immutableTypes, '<>', (builder) => builder
261
+ .append('Record')
262
+ .appendGenericArguments('string', schema.additionalProperties === true
263
+ ? this.getAnyType(ctx)
264
+ : (builder) => this.generateTypeUsage(ctx, builder, schema.additionalProperties)));
265
+ }
266
+ generateEnumType(ctx, builder, schema) {
267
+ builder.indent((builder) => {
268
+ var _a;
269
+ builder.forEach((_a = schema.enum) !== null && _a !== void 0 ? _a : [], (builder, item) => builder.append(this.toStringLiteral(ctx, String(item))), {
270
+ separator: ' | ',
271
+ });
272
+ });
273
+ }
274
+ generateTypeDocumentation(ctx, builder) {
275
+ this.generateDocumentation(ctx, builder, ctx.schema);
276
+ }
277
+ generatePropertyDocumentation(ctx, builder, property) {
278
+ this.generateDocumentation(ctx, builder, property.schema);
279
+ }
280
+ generateDocumentation(ctx, builder, schema) {
281
+ builder.appendComment('/***/', schema.description);
282
+ }
283
+ shouldGenerateTypeDeclaration(ctx, schema) {
284
+ // All named schemas should have its own type declaration
285
+ if (!schema.isNameGenerated) {
286
+ return true;
287
+ }
288
+ // All enum types should have its own type declaration
289
+ if (schema.kind === 'string' && schema.enum !== undefined && schema.enum.length > 0) {
290
+ return true;
291
+ }
292
+ // All primitive types already exist and do not need its own type declaration
293
+ if (schema.kind !== 'array' &&
294
+ schema.kind !== 'combined' &&
295
+ schema.kind !== 'multi-type' &&
296
+ schema.kind !== 'object' &&
297
+ schema.kind !== 'oneOf') {
298
+ return false;
299
+ }
300
+ // For all other types, check if the user has enabled inline unnamed schemas
301
+ return !ctx.config.inlineUnnamedSchemas;
302
+ }
303
+ resolveInterfaceSchema(ctx) {
304
+ if (ctx.config.typeDeclaration === 'prefer-interface' &&
305
+ (ctx.schema.kind === 'object' || ctx.schema.kind === 'combined')) {
306
+ return (0, core_1.resolveAnyOfAndAllOf)(ctx.schema, true);
307
+ }
308
+ return undefined;
309
+ }
310
+ getDeclarationTypeName(ctx, schema) {
311
+ return (0, core_1.toCasing)(schema.name, ctx.config.typeNameCasing);
312
+ }
313
+ getFilePath(ctx, schema) {
314
+ return (0, path_1.resolve)(ctx.config.outputDir, ctx.config.modelsDirPath, `${(0, core_1.toCasing)(schema.name, ctx.config.fileNameCasing)}.ts`);
315
+ }
316
+ }
317
+ exports.DefaultTypeScriptModelGenerator = DefaultTypeScriptModelGenerator;
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TypeScriptModelsGenerator = void 0;
4
+ const path_1 = require("path");
5
+ const fs_extra_1 = require("fs-extra");
6
+ const core_1 = require("@goast/core");
7
+ const model_generator_1 = require("./model-generator");
8
+ const models_1 = require("./models");
9
+ const file_builder_1 = require("../../file-builder");
10
+ const import_collection_1 = require("../../import-collection");
11
+ class TypeScriptModelsGenerator extends core_1.OpenApiSchemasGenerationProviderBase {
12
+ constructor(modelGeneratorFactory) {
13
+ super();
14
+ this._modelGeneratorFactory = modelGeneratorFactory !== null && modelGeneratorFactory !== void 0 ? modelGeneratorFactory : core_1.Factory.fromValue(new model_generator_1.DefaultTypeScriptModelGenerator());
15
+ }
16
+ initResult() {
17
+ return {
18
+ models: {},
19
+ modelIndexFilePath: undefined,
20
+ };
21
+ }
22
+ buildContext(context, config) {
23
+ return this.getProviderContext(context, config, models_1.defaultTypeScriptModelsGeneratorConfig);
24
+ }
25
+ onGenerate(ctx) {
26
+ const output = super.onGenerate(ctx);
27
+ output.modelIndexFilePath = this.generateIndexFile(ctx);
28
+ return output;
29
+ }
30
+ generateSchema(ctx, schema) {
31
+ const modelGenerator = this._modelGeneratorFactory.create();
32
+ return modelGenerator.generate(Object.assign(Object.assign({}, ctx), { schema }));
33
+ }
34
+ addSchemaResult(ctx, schema, result) {
35
+ ctx.output.models[schema.id] = result;
36
+ }
37
+ generateIndexFile(ctx) {
38
+ if (!this.shouldGenerateIndexFile(ctx)) {
39
+ return undefined;
40
+ }
41
+ const filePath = this.getIndexFilePath(ctx);
42
+ console.log(`Generating model index file to ${filePath}...`);
43
+ (0, fs_extra_1.ensureDirSync)((0, path_1.dirname)(filePath));
44
+ const builder = new file_builder_1.TypeScriptFileBuilder(filePath, ctx.config);
45
+ this.generateIndexFileContent(ctx, builder);
46
+ (0, fs_extra_1.writeFileSync)(filePath, builder.toString());
47
+ return filePath;
48
+ }
49
+ getIndexFilePath(ctx) {
50
+ var _a;
51
+ return (0, path_1.resolve)(ctx.config.outputDir, (_a = ctx.config.indexFilePath) !== null && _a !== void 0 ? _a : 'models.ts');
52
+ }
53
+ shouldGenerateIndexFile(ctx) {
54
+ return ctx.config.indexFilePath !== null;
55
+ }
56
+ generateIndexFileContent(ctx, builder) {
57
+ const exports = new import_collection_1.ImportExportCollection();
58
+ for (const modelId in ctx.output.models) {
59
+ const model = ctx.output.models[modelId];
60
+ if (model.filePath) {
61
+ exports.addExport(model.component, model.filePath);
62
+ }
63
+ }
64
+ exports.writeTo(builder);
65
+ }
66
+ }
67
+ exports.TypeScriptModelsGenerator = TypeScriptModelsGenerator;