@loopback/cli 4.0.0-alpha.9 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.yo-rc.json +1697 -0
- package/{generators/project/templates/LICENSE → LICENSE} +2 -1
- package/README.md +44 -43
- package/bin/cli-main.js +61 -0
- package/generators/app/index.js +109 -15
- package/generators/app/templates/.dockerignore +5 -0
- package/generators/app/templates/Dockerfile +28 -0
- package/generators/app/templates/README.md.ejs +130 -0
- package/generators/app/templates/public/index.html.ejs +88 -0
- package/generators/app/templates/{test → src/__tests__}/README.md +0 -1
- package/generators/app/templates/src/__tests__/acceptance/home-page.acceptance.ts.ejs +31 -0
- package/generators/app/templates/src/__tests__/acceptance/ping.controller.acceptance.ts.ejs +21 -0
- package/generators/app/templates/src/__tests__/acceptance/test-helper.ts.ejs +32 -0
- package/generators/app/templates/src/application.ts.ejs +70 -0
- package/generators/app/templates/src/controllers/README.md +6 -0
- package/generators/app/templates/src/controllers/index.ts.ejs +1 -0
- package/generators/app/templates/src/controllers/ping.controller.ts.ejs +55 -0
- package/generators/app/templates/src/datasources/README.md +3 -0
- package/generators/app/templates/src/index.ts.ejs +39 -0
- package/generators/app/templates/src/migrate.ts.ejs +20 -0
- package/generators/app/templates/src/models/README.md +3 -0
- package/generators/app/templates/src/openapi-spec.ts.ejs +23 -0
- package/generators/app/templates/src/sequence.ts.ejs +3 -0
- package/generators/controller/index.js +240 -23
- package/generators/controller/templates/src/controllers/controller-rest-template.ts.ejs +150 -0
- package/generators/controller/templates/src/controllers/{controller-template.ts → controller-template.ts.ejs} +2 -2
- package/generators/copyright/fs.js +46 -0
- package/generators/copyright/git.js +78 -0
- package/generators/copyright/header.js +306 -0
- package/generators/copyright/index.js +230 -0
- package/generators/copyright/license.js +105 -0
- package/generators/datasource/index.js +341 -0
- package/generators/datasource/templates/datasource.ts.ejs +22 -0
- package/generators/discover/import-discovered-model.js +70 -0
- package/generators/discover/index.js +349 -0
- package/generators/example/downloader.js +16 -0
- package/generators/example/index.js +176 -0
- package/generators/extension/index.js +34 -5
- package/generators/extension/templates/README.md.ejs +32 -0
- package/generators/extension/templates/{test → src/__tests__}/acceptance/README.md +0 -0
- package/generators/extension/templates/{test → src/__tests__}/integration/README.md +0 -0
- package/generators/extension/templates/{test → src/__tests__}/unit/README.md +0 -0
- package/generators/extension/templates/src/component.ts.ejs +22 -0
- package/generators/extension/templates/src/controllers/README.md +3 -2
- package/generators/extension/templates/src/decorators/README.md +10 -4
- package/generators/extension/templates/src/index.ts.ejs +3 -0
- package/generators/extension/templates/src/keys.ts.ejs +11 -0
- package/generators/extension/templates/src/mixins/README.md +77 -21
- package/generators/extension/templates/src/providers/README.md +51 -25
- package/generators/extension/templates/src/repositories/README.md +1 -1
- package/generators/extension/templates/src/types.ts.ejs +15 -0
- package/generators/import-lb3-models/index.js +197 -0
- package/generators/import-lb3-models/lb3app-loader.js +31 -0
- package/generators/import-lb3-models/migrate-model.js +249 -0
- package/generators/import-lb3-models/model-names.js +32 -0
- package/generators/interceptor/index.js +178 -0
- package/generators/interceptor/templates/interceptor-template.ts.ejs +62 -0
- package/generators/model/index.js +536 -0
- package/generators/model/property-definition.js +85 -0
- package/generators/model/templates/model.ts.ejs +42 -0
- package/generators/observer/index.js +132 -0
- package/generators/observer/templates/observer-template.ts.ejs +40 -0
- package/generators/openapi/README.md +211 -0
- package/generators/openapi/index.js +535 -0
- package/generators/openapi/schema-helper.js +447 -0
- package/generators/openapi/spec-helper.js +484 -0
- package/generators/openapi/spec-loader.js +75 -0
- package/generators/openapi/templates/src/controllers/controller-template.ts.ejs +43 -0
- package/generators/openapi/templates/src/datasources/datasource.ts.ejs +42 -0
- package/generators/openapi/templates/src/models/model-template.ts.ejs +71 -0
- package/generators/openapi/templates/src/models/type-template.ts.ejs +13 -0
- package/generators/openapi/templates/src/services/service-proxy-template.ts.ejs +55 -0
- package/generators/openapi/utils.js +322 -0
- package/generators/project/templates/.eslintignore +4 -0
- package/generators/project/templates/.eslintrc.js.ejs +3 -0
- package/generators/project/templates/.mocharc.json +5 -0
- package/generators/project/templates/.prettierignore +0 -2
- package/generators/project/templates/.prettierrc +2 -1
- package/generators/project/templates/.vscode/launch.json +38 -0
- package/generators/project/templates/.vscode/settings.json +32 -0
- package/generators/project/templates/.vscode/tasks.json +29 -0
- package/generators/project/templates/DEVELOPING.md +36 -0
- package/generators/project/templates/_.gitignore +3 -5
- package/generators/project/templates/package.json.ejs +175 -0
- package/generators/project/templates/package.plain.json.ejs +176 -0
- package/generators/project/templates/tsconfig.json.ejs +39 -0
- package/generators/relation/base-relation.generator.js +220 -0
- package/generators/relation/belongs-to-relation.generator.js +196 -0
- package/generators/relation/has-many-relation.generator.js +200 -0
- package/generators/relation/has-many-through-relation.generator.js +331 -0
- package/generators/relation/has-one-relation.generator.js +200 -0
- package/generators/relation/index.js +795 -0
- package/generators/relation/references-many-relation.generator.js +142 -0
- package/generators/relation/templates/controller-relation-template-belongs-to.ts.ejs +38 -0
- package/generators/relation/templates/controller-relation-template-has-many-through.ts.ejs +110 -0
- package/generators/relation/templates/controller-relation-template-has-many.ts.ejs +110 -0
- package/generators/relation/templates/controller-relation-template-has-one.ts.ejs +110 -0
- package/generators/relation/utils.generator.js +260 -0
- package/generators/repository/index.js +576 -0
- package/generators/repository/templates/src/repositories/repository-crud-default-template.ts.ejs +21 -0
- package/generators/repository/templates/src/repositories/repository-kv-template.ts.ejs +19 -0
- package/generators/rest-crud/crud-rest-component.js +63 -0
- package/generators/rest-crud/index.js +401 -0
- package/generators/rest-crud/templates/src/model-endpoints/model.rest-config-template.ts.ejs +10 -0
- package/generators/service/index.js +351 -0
- package/generators/service/templates/local-service-class-template.ts.ejs +10 -0
- package/generators/service/templates/local-service-provider-template.ts.ejs +19 -0
- package/generators/service/templates/remote-service-proxy-template.ts.ejs +21 -0
- package/generators/update/index.js +55 -0
- package/intl/cs/messages.json +204 -0
- package/intl/de/messages.json +204 -0
- package/intl/en/messages.json +204 -0
- package/intl/es/messages.json +204 -0
- package/intl/fr/messages.json +204 -0
- package/intl/it/messages.json +204 -0
- package/intl/ja/messages.json +204 -0
- package/intl/ko/messages.json +204 -0
- package/intl/nl/messages.json +204 -0
- package/intl/pl/messages.json +204 -0
- package/intl/pt/messages.json +204 -0
- package/intl/ru/messages.json +204 -0
- package/intl/tr/messages.json +204 -0
- package/intl/zh-Hans/messages.json +204 -0
- package/intl/zh-Hant/messages.json +204 -0
- package/lib/artifact-generator.js +138 -39
- package/lib/ast-helper.js +214 -0
- package/lib/base-generator.js +509 -0
- package/lib/cli.js +233 -0
- package/lib/connectors.json +894 -0
- package/lib/debug.js +16 -0
- package/lib/globalize.js +12 -0
- package/lib/model-discoverer.js +118 -0
- package/lib/project-generator.js +154 -57
- package/lib/tab-completion.js +127 -0
- package/lib/update-index.js +44 -0
- package/lib/utils.js +689 -20
- package/lib/version-helper.js +299 -0
- package/package.json +183 -39
- package/CHANGELOG.md +0 -86
- package/bin/cli.js +0 -66
- package/generators/app/templates/index.js +0 -14
- package/generators/app/templates/src/application.ts +0 -27
- package/generators/app/templates/src/controllers/ping-controller.ts +0 -25
- package/generators/app/templates/src/index.ts +0 -25
- package/generators/app/templates/test/ping-controller.test.ts +0 -46
- package/generators/extension/templates/index.js +0 -8
- package/generators/extension/templates/src/component.ts +0 -14
- package/generators/extension/templates/src/index.ts +0 -6
- package/generators/project/templates/.npmrc +0 -1
- package/generators/project/templates/.yo-rc.json +0 -1
- package/generators/project/templates/README.md +0 -4
- package/generators/project/templates/index.d.ts +0 -6
- package/generators/project/templates/index.ts +0 -11
- package/generators/project/templates/package.json +0 -79
- package/generators/project/templates/package.plain.json +0 -82
- package/generators/project/templates/test/mocha.opts +0 -1
- package/generators/project/templates/tsconfig.json +0 -29
- package/generators/project/templates/tslint.build.json +0 -17
- package/generators/project/templates/tslint.json +0 -33
|
@@ -0,0 +1,447 @@
|
|
|
1
|
+
// Copyright IBM Corp. 2018,2020. All Rights Reserved.
|
|
2
|
+
// Node module: @loopback/cli
|
|
3
|
+
// This file is licensed under the MIT License.
|
|
4
|
+
// License text available at https://opensource.org/licenses/MIT
|
|
5
|
+
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
const {
|
|
9
|
+
isExtension,
|
|
10
|
+
titleCase,
|
|
11
|
+
escapePropertyName,
|
|
12
|
+
printSpecObject,
|
|
13
|
+
toFileName,
|
|
14
|
+
printJsonSchema,
|
|
15
|
+
} = require('./utils');
|
|
16
|
+
|
|
17
|
+
function setImport(typeSpec) {
|
|
18
|
+
if (typeSpec.fileName) {
|
|
19
|
+
typeSpec.import = `import {${typeSpec.className}} from './${getBaseName(
|
|
20
|
+
typeSpec.fileName,
|
|
21
|
+
)}';`;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function getTypeSpec(schema, options) {
|
|
26
|
+
const objectTypeMapping = options.objectTypeMapping;
|
|
27
|
+
const schemaMapping = options.schemaMapping || {};
|
|
28
|
+
const resolvedSchema = resolveSchema(schemaMapping, schema);
|
|
29
|
+
let typeSpec = objectTypeMapping.get(resolvedSchema);
|
|
30
|
+
if (!typeSpec) {
|
|
31
|
+
typeSpec = {};
|
|
32
|
+
objectTypeMapping.set(resolvedSchema, typeSpec);
|
|
33
|
+
}
|
|
34
|
+
setImport(typeSpec);
|
|
35
|
+
return typeSpec;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function getDefault(schema, options) {
|
|
39
|
+
let defaultVal = '';
|
|
40
|
+
if (options && options.includeDefault && schema.default !== undefined) {
|
|
41
|
+
defaultVal = ' = ' + printSpecObject(schema.default);
|
|
42
|
+
}
|
|
43
|
+
return defaultVal;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function getBaseName(tsFileName) {
|
|
47
|
+
if (tsFileName.endsWith('.ts')) {
|
|
48
|
+
return tsFileName.substring(0, tsFileName.length - 3);
|
|
49
|
+
}
|
|
50
|
+
return tsFileName;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Add the import statements to the given type spec's imports
|
|
55
|
+
* @param {object} typeSpec
|
|
56
|
+
* @param {string[]} imports
|
|
57
|
+
*/
|
|
58
|
+
function addImports(typeSpec, ...imports) {
|
|
59
|
+
typeSpec.imports = typeSpec.imports || [];
|
|
60
|
+
for (const i of imports) {
|
|
61
|
+
if (i == null) continue;
|
|
62
|
+
// Skip circular import
|
|
63
|
+
if (typeSpec.import === i) continue;
|
|
64
|
+
if (!typeSpec.imports.includes(i)) {
|
|
65
|
+
typeSpec.imports.push(i);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Collect import statements from a referenced type
|
|
72
|
+
* @param {*} typeSpec
|
|
73
|
+
* @param {*} referencedType
|
|
74
|
+
*/
|
|
75
|
+
function collectImports(typeSpec, referencedType) {
|
|
76
|
+
if (referencedType.className != null) {
|
|
77
|
+
// Add the referenced import
|
|
78
|
+
addImports(typeSpec, referencedType.import);
|
|
79
|
+
} else {
|
|
80
|
+
if (Array.isArray(referencedType.imports)) {
|
|
81
|
+
addImports(typeSpec, ...referencedType.imports);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Map composite type (oneOf|anyOf|allOf)
|
|
88
|
+
* @param {object} schema
|
|
89
|
+
* @param {object} options
|
|
90
|
+
*/
|
|
91
|
+
function mapCompositeType(schema, options) {
|
|
92
|
+
options = Object.assign({}, options, {includeDefault: false});
|
|
93
|
+
const typeSpec = getTypeSpec(schema, options);
|
|
94
|
+
let separator = '';
|
|
95
|
+
let candidates = [];
|
|
96
|
+
if (Array.isArray(schema.oneOf)) {
|
|
97
|
+
separator = ' | ';
|
|
98
|
+
candidates = schema.oneOf;
|
|
99
|
+
} else if (Array.isArray(schema.anyOf)) {
|
|
100
|
+
separator = ' | ';
|
|
101
|
+
candidates = schema.anyOf;
|
|
102
|
+
} else if (Array.isArray(schema.allOf)) {
|
|
103
|
+
separator = ' & ';
|
|
104
|
+
candidates = schema.allOf;
|
|
105
|
+
}
|
|
106
|
+
if (!separator) return undefined;
|
|
107
|
+
const types = candidates.map(t => mapSchemaType(t, options));
|
|
108
|
+
const members = Array.from(new Set(types));
|
|
109
|
+
typeSpec.members = members;
|
|
110
|
+
const defaultVal = getDefault(schema, options);
|
|
111
|
+
const memberSignatures = members.map(m => m.signature).join(separator);
|
|
112
|
+
typeSpec.declaration = memberSignatures;
|
|
113
|
+
typeSpec.signature = (typeSpec.className || memberSignatures) + defaultVal;
|
|
114
|
+
members.forEach(m => collectImports(typeSpec, m));
|
|
115
|
+
return typeSpec;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function mapArrayType(schema, options) {
|
|
119
|
+
if (schema.type === 'array') {
|
|
120
|
+
const opts = Object.assign({}, options, {includeDefault: false});
|
|
121
|
+
const typeSpec = getTypeSpec(schema, options);
|
|
122
|
+
const itemTypeSpec = mapSchemaType(schema.items, opts);
|
|
123
|
+
const defaultVal = getDefault(schema, options);
|
|
124
|
+
let arrayType = `${itemTypeSpec.signature}[]`;
|
|
125
|
+
if (itemTypeSpec.signature.match(/[\|\&]/)) {
|
|
126
|
+
// The type is a union or intersection
|
|
127
|
+
arrayType = `(${itemTypeSpec.signature})[]`;
|
|
128
|
+
}
|
|
129
|
+
typeSpec.name = arrayType;
|
|
130
|
+
typeSpec.declaration = arrayType;
|
|
131
|
+
typeSpec.signature = (typeSpec.className || arrayType) + defaultVal;
|
|
132
|
+
typeSpec.itemType = itemTypeSpec;
|
|
133
|
+
collectImports(typeSpec, itemTypeSpec);
|
|
134
|
+
return typeSpec;
|
|
135
|
+
}
|
|
136
|
+
return undefined;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function mapObjectType(schema, options) {
|
|
140
|
+
if (schema.type === 'object' || schema.properties) {
|
|
141
|
+
const defaultVal = getDefault(schema, options);
|
|
142
|
+
const typeSpec = getTypeSpec(schema, options);
|
|
143
|
+
if (typeSpec.className) {
|
|
144
|
+
typeSpec.kind = 'class';
|
|
145
|
+
} else {
|
|
146
|
+
typeSpec.imports = [];
|
|
147
|
+
}
|
|
148
|
+
if (typeSpec.declaration != null) {
|
|
149
|
+
if (typeSpec.declaration === '') {
|
|
150
|
+
typeSpec.signature = typeSpec.className;
|
|
151
|
+
}
|
|
152
|
+
return typeSpec;
|
|
153
|
+
} else {
|
|
154
|
+
typeSpec.declaration = ''; // in-progress
|
|
155
|
+
}
|
|
156
|
+
const properties = [];
|
|
157
|
+
const required = schema.required || [];
|
|
158
|
+
for (const p in schema.properties) {
|
|
159
|
+
const propSchema = {...schema.properties[p]};
|
|
160
|
+
const suffix = required.includes(p) ? '' : '?';
|
|
161
|
+
const propertyType = mapSchemaType(
|
|
162
|
+
schema.properties[p],
|
|
163
|
+
Object.assign({}, options, {
|
|
164
|
+
includeDefault: !!typeSpec.className, // Only include default for class
|
|
165
|
+
}),
|
|
166
|
+
);
|
|
167
|
+
// The property name might have chars such as `-`
|
|
168
|
+
const propName = escapePropertyName(p);
|
|
169
|
+
|
|
170
|
+
const propSchemaJson = printJsonSchema(propSchema);
|
|
171
|
+
|
|
172
|
+
let propDecoration = `@property({jsonSchema: ${propSchemaJson}})`;
|
|
173
|
+
|
|
174
|
+
if (required.includes(p)) {
|
|
175
|
+
propDecoration = `@property({required: true, jsonSchema: ${propSchemaJson}})`;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (propertyType.itemType) {
|
|
179
|
+
const itemType =
|
|
180
|
+
propertyType.itemType.kind === 'class'
|
|
181
|
+
? propertyType.itemType.className
|
|
182
|
+
: // The item type can be an alias such as `export type ID = string`
|
|
183
|
+
getJSType(propertyType.itemType.declaration) ||
|
|
184
|
+
// The item type can be `string`
|
|
185
|
+
getJSType(propertyType.itemType.name);
|
|
186
|
+
if (itemType) {
|
|
187
|
+
// Use `@property.array` for array types
|
|
188
|
+
propDecoration = `@property.array(${itemType}, {jsonSchema: ${propSchemaJson}})`;
|
|
189
|
+
if (propertyType.itemType.className) {
|
|
190
|
+
// The referenced item type is either a class or type
|
|
191
|
+
collectImports(typeSpec, propertyType.itemType);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
const propSpec = {
|
|
196
|
+
name: p,
|
|
197
|
+
signature: `${propName + suffix}: ${propertyType.signature};`,
|
|
198
|
+
decoration: propDecoration,
|
|
199
|
+
};
|
|
200
|
+
if (schema.properties[p].description) {
|
|
201
|
+
propSpec.description = schema.properties[p].description;
|
|
202
|
+
}
|
|
203
|
+
collectImports(typeSpec, propertyType);
|
|
204
|
+
properties.push(propSpec);
|
|
205
|
+
}
|
|
206
|
+
typeSpec.properties = properties;
|
|
207
|
+
typeSpec.importProperty = properties.length > 0;
|
|
208
|
+
|
|
209
|
+
// Handle `additionalProperties`
|
|
210
|
+
if (schema.additionalProperties === true) {
|
|
211
|
+
const signature = '[additionalProperty: string]: any;';
|
|
212
|
+
typeSpec.properties.push({
|
|
213
|
+
name: '',
|
|
214
|
+
description: 'additionalProperties',
|
|
215
|
+
comment: 'eslint-disable-next-line @typescript-eslint/no-explicit-any',
|
|
216
|
+
signature,
|
|
217
|
+
});
|
|
218
|
+
} else if (schema.additionalProperties) {
|
|
219
|
+
// TypeScript does not like `[additionalProperty: string]: string;`
|
|
220
|
+
/*
|
|
221
|
+
const signature =
|
|
222
|
+
'[additionalProperty: string]: ' +
|
|
223
|
+
mapSchemaType(schema.additionalProperties).signature +
|
|
224
|
+
';';
|
|
225
|
+
*/
|
|
226
|
+
const signature = '[additionalProperty: string]: any;';
|
|
227
|
+
typeSpec.properties.push({
|
|
228
|
+
name: '',
|
|
229
|
+
description: 'additionalProperties',
|
|
230
|
+
comment: 'eslint-disable-next-line @typescript-eslint/no-explicit-any',
|
|
231
|
+
signature,
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
const propertySignatures = properties.map(p => {
|
|
235
|
+
if (p.comment) return ` // ${p.comment}\n ${p.signature}`;
|
|
236
|
+
return p.signature;
|
|
237
|
+
});
|
|
238
|
+
typeSpec.declaration = `{
|
|
239
|
+
${propertySignatures.join('\n ')}
|
|
240
|
+
}`;
|
|
241
|
+
typeSpec.signature =
|
|
242
|
+
(typeSpec.className || typeSpec.declaration) + defaultVal;
|
|
243
|
+
return typeSpec;
|
|
244
|
+
}
|
|
245
|
+
return undefined;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
function mapPrimitiveType(schema, options) {
|
|
249
|
+
/**
|
|
250
|
+
* integer integer int32 signed 32 bits
|
|
251
|
+
* long integer int64 signed 64 bits
|
|
252
|
+
* float number float
|
|
253
|
+
* double number double
|
|
254
|
+
* string string
|
|
255
|
+
* byte string byte base64 encoded characters
|
|
256
|
+
* binary string binary any sequence of octets
|
|
257
|
+
* boolean boolean
|
|
258
|
+
* date string date As defined by full-date - RFC3339
|
|
259
|
+
* dateTime string date-time As defined by date-time - RFC3339
|
|
260
|
+
* password string password A hint to UIs to obscure input.
|
|
261
|
+
*/
|
|
262
|
+
let jsType = 'string';
|
|
263
|
+
switch (schema.type) {
|
|
264
|
+
case 'integer':
|
|
265
|
+
case 'number':
|
|
266
|
+
jsType = 'number';
|
|
267
|
+
break;
|
|
268
|
+
case 'boolean':
|
|
269
|
+
jsType = 'boolean';
|
|
270
|
+
break;
|
|
271
|
+
case 'string':
|
|
272
|
+
switch (schema.format) {
|
|
273
|
+
case 'date':
|
|
274
|
+
jsType = 'string';
|
|
275
|
+
break;
|
|
276
|
+
case 'date-time':
|
|
277
|
+
jsType = 'Date';
|
|
278
|
+
break;
|
|
279
|
+
case 'binary':
|
|
280
|
+
jsType = 'Buffer';
|
|
281
|
+
break;
|
|
282
|
+
case 'byte':
|
|
283
|
+
case 'password':
|
|
284
|
+
jsType = 'string';
|
|
285
|
+
break;
|
|
286
|
+
}
|
|
287
|
+
break;
|
|
288
|
+
}
|
|
289
|
+
// Handle enums
|
|
290
|
+
if (Array.isArray(schema.enum)) {
|
|
291
|
+
jsType = schema.enum.map(v => printSpecObject(v)).join(' | ');
|
|
292
|
+
}
|
|
293
|
+
const typeSpec = getTypeSpec(schema, options);
|
|
294
|
+
const defaultVal = getDefault(schema, options);
|
|
295
|
+
typeSpec.declaration = jsType;
|
|
296
|
+
typeSpec.signature = typeSpec.className || typeSpec.declaration + defaultVal;
|
|
297
|
+
typeSpec.name = typeSpec.name || jsType;
|
|
298
|
+
return typeSpec;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
const JSTypeMapping = {
|
|
302
|
+
number: Number,
|
|
303
|
+
boolean: Boolean,
|
|
304
|
+
string: String,
|
|
305
|
+
Date: Date,
|
|
306
|
+
Buffer: Buffer,
|
|
307
|
+
};
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Mapping simple type names to JS Type constructors
|
|
311
|
+
* @param {string} type Simple type name
|
|
312
|
+
*/
|
|
313
|
+
function getJSType(type) {
|
|
314
|
+
const ctor = JSTypeMapping[type];
|
|
315
|
+
return ctor && ctor.name;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
*
|
|
320
|
+
* https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.1.md#data-types
|
|
321
|
+
*
|
|
322
|
+
* @param {object} schema
|
|
323
|
+
*/
|
|
324
|
+
function mapSchemaType(schema, options) {
|
|
325
|
+
options = options || {};
|
|
326
|
+
if (!options.objectTypeMapping) {
|
|
327
|
+
options.objectTypeMapping = new Map();
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
const typeSpec = getTypeSpec(schema, options);
|
|
331
|
+
if (typeSpec.signature) return typeSpec;
|
|
332
|
+
|
|
333
|
+
const compositeType = mapCompositeType(schema, options);
|
|
334
|
+
if (compositeType) {
|
|
335
|
+
return compositeType;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
const arrayType = mapArrayType(schema, options);
|
|
339
|
+
if (arrayType) {
|
|
340
|
+
return arrayType;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
const objectType = mapObjectType(schema, options);
|
|
344
|
+
if (objectType) {
|
|
345
|
+
return objectType;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
return mapPrimitiveType(schema, options);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/**
|
|
352
|
+
* Map the schema by `x-$ref`
|
|
353
|
+
* @param {object} schemaMapping
|
|
354
|
+
* @param {object} schema
|
|
355
|
+
*/
|
|
356
|
+
function resolveSchema(schemaMapping, schema) {
|
|
357
|
+
if (!schema['x-$ref']) return schema;
|
|
358
|
+
let resolved = schema;
|
|
359
|
+
while (resolved && resolved['x-$ref']) {
|
|
360
|
+
resolved = schemaMapping[resolved['x-$ref']];
|
|
361
|
+
}
|
|
362
|
+
return resolved || schema;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* Generate model definitions from openapi spec
|
|
367
|
+
* @param {object} apiSpec
|
|
368
|
+
*/
|
|
369
|
+
function generateModelSpecs(apiSpec, options) {
|
|
370
|
+
options = options || {};
|
|
371
|
+
const objectTypeMapping = (options.objectTypeMapping =
|
|
372
|
+
options.objectTypeMapping || new Map());
|
|
373
|
+
|
|
374
|
+
const schemaMapping = (options.schemaMapping = options.schemaMapping || {});
|
|
375
|
+
|
|
376
|
+
registerNamedSchemas(apiSpec, options);
|
|
377
|
+
|
|
378
|
+
const models = [];
|
|
379
|
+
// Generate models from schema objects
|
|
380
|
+
for (const s in options.schemaMapping) {
|
|
381
|
+
if (isExtension(s)) continue;
|
|
382
|
+
const schema = options.schemaMapping[s];
|
|
383
|
+
const model = mapSchemaType(schema, {objectTypeMapping, schemaMapping});
|
|
384
|
+
// `model` is `undefined` for primitive types
|
|
385
|
+
if (model == null) continue;
|
|
386
|
+
if (model.className) {
|
|
387
|
+
// The model might be a $ref
|
|
388
|
+
if (!models.includes(model)) {
|
|
389
|
+
models.push(model);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
return models;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/**
|
|
397
|
+
* Register the named schema
|
|
398
|
+
* @param {string} schemaName Schema name
|
|
399
|
+
* @param {object} schema Schema object
|
|
400
|
+
* @param {object} typeRegistry Options for objectTypeMapping & schemaMapping
|
|
401
|
+
*/
|
|
402
|
+
function registerSchema(schemaName, schema, typeRegistry) {
|
|
403
|
+
if (typeRegistry.objectTypeMapping.get(schema)) return;
|
|
404
|
+
typeRegistry.schemaMapping[`#/components/schemas/${schemaName}`] = schema;
|
|
405
|
+
const className = titleCase(schemaName);
|
|
406
|
+
typeRegistry.objectTypeMapping.set(schema, {
|
|
407
|
+
description: schema.description || schemaName,
|
|
408
|
+
name: schemaName,
|
|
409
|
+
className,
|
|
410
|
+
fileName: getModelFileName(schemaName),
|
|
411
|
+
properties: [],
|
|
412
|
+
imports: [],
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* Register spec.components.schemas
|
|
418
|
+
* @param {*} apiSpec OpenAPI spec
|
|
419
|
+
* @param {*} typeRegistry options for objectTypeMapping & schemaMapping
|
|
420
|
+
*/
|
|
421
|
+
function registerNamedSchemas(apiSpec, typeRegistry) {
|
|
422
|
+
const schemas =
|
|
423
|
+
(apiSpec && apiSpec.components && apiSpec.components.schemas) || {};
|
|
424
|
+
|
|
425
|
+
// First map schema objects to names
|
|
426
|
+
for (const s in schemas) {
|
|
427
|
+
if (isExtension(s)) continue;
|
|
428
|
+
const schema = schemas[s];
|
|
429
|
+
registerSchema(s, schema, typeRegistry);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
function getModelFileName(modelName) {
|
|
434
|
+
let name = modelName;
|
|
435
|
+
if (modelName.endsWith('Model')) {
|
|
436
|
+
name = modelName.substring(0, modelName.length - 'Model'.length);
|
|
437
|
+
}
|
|
438
|
+
return toFileName(name) + '.model.ts';
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
module.exports = {
|
|
442
|
+
mapSchemaType,
|
|
443
|
+
registerSchema,
|
|
444
|
+
registerNamedSchemas,
|
|
445
|
+
generateModelSpecs,
|
|
446
|
+
getModelFileName,
|
|
447
|
+
};
|