From 5430874010868a62cf57de276e8633d9a648ac9b Mon Sep 17 00:00:00 2001 From: Michael M Date: Tue, 10 May 2022 21:54:49 +0400 Subject: [PATCH] chore: clean-up --- packages/ng-openapi-gen/package.json | 7 ++- packages/ng-openapi-gen/src/lib/generator.ts | 28 ++++----- packages/ng-openapi-gen/src/lib/oa-import.ts | 2 - packages/ng-openapi-gen/src/lib/oa-model.ts | 2 - .../ng-openapi-gen/src/lib/oa-operation.ts | 6 +- packages/ng-openapi-gen/src/lib/options.ts | 12 +++- .../src/lib/utils/file-system.ts | 8 +-- .../ng-openapi-gen/src/lib/utils/lo/deburr.ts | 17 +----- .../src/lib/utils/lo/has-unicode.ts | 18 +----- .../ng-openapi-gen/src/lib/utils/lo/index.ts | 6 ++ .../src/lib/utils/lo/unicode-support.ts | 33 +++++++++++ .../src/lib/utils/lo/unicode-to-array.ts | 43 ++++---------- .../src/lib/utils/lo/unicode-words.ts | 58 ++++++------------- .../ng-openapi-gen/src/lib/utils/open-api.ts | 22 ------- packages/ng-openapi-gen/src/ng-openapi-gen.ts | 19 +++--- packages/ng-openapi-gen/src/schema.json | 7 ++- .../src/templates/requestBuilder.handlebars | 1 + .../schema-generator/schema-descriptor.ts | 26 +++++++-- 18 files changed, 151 insertions(+), 164 deletions(-) create mode 100644 packages/ng-openapi-gen/src/lib/utils/lo/unicode-support.ts diff --git a/packages/ng-openapi-gen/package.json b/packages/ng-openapi-gen/package.json index 719c44c..ac8b013 100644 --- a/packages/ng-openapi-gen/package.json +++ b/packages/ng-openapi-gen/package.json @@ -8,9 +8,14 @@ "handlebars": "~4.7.0", "jsesc": "~3.0.0", "openapi3-ts": "~2.0.0", - "tslib": "^2.0.0", "yargs-parser": "^20.0.0" }, + "peerDependencies": { + "@angular/common": ">=7.0.0", + "@angular/core": ">=7.0.0", + "rxjs": ">=6.0.0", + "tslib": "^2.0.0" + }, "license": "MIT", "author": "Public JS (https://github.com/public-js/public-js)", "repository": "https://github.com/public-js/ng-openapi-gen", diff --git a/packages/ng-openapi-gen/src/lib/generator.ts b/packages/ng-openapi-gen/src/lib/generator.ts index e1b42b2..66a3882 100644 --- a/packages/ng-openapi-gen/src/lib/generator.ts +++ b/packages/ng-openapi-gen/src/lib/generator.ts @@ -59,15 +59,10 @@ export class Generator { // Context objects passed to general templates const general = { services, models }; - // todo: shorten models here const modelImports = this.globals.modelIndexFile || this.options.indexFile ? models.map((model) => new OaImport().fromModel(model)) : null; - // const modelImports = - // this.globals.modelIndexFile || this.options.indexFile - // ? models.map((model) => new OaImport().fromRef(this.options, model.name)) - // : null; // Generate the general files this.write('configuration', general, this.globals.configurationFile); @@ -86,9 +81,11 @@ export class Generator { } // Now synchronize the temp to the output folder - syncDirs(this.tempDir, this.outDir, this.options.removeStaleFiles !== false); + syncDirs(this.tempDir, this.outDir, this.options.removeStaleFiles, this.options.verbose); - // console.info(`Generation from ${this.options.input} finished with ${models.length} models and ${services.length} services.`); + console.info( + `Generated ${models.length} models and ${services.length} services from ${this.options.input}.`, + ); } finally { // Always remove the temporary directory fse.removeSync(this.tempDir); @@ -136,7 +133,6 @@ export class Generator { for (const [name, schema] of Object.entries(schemas)) { this.models.set(name, new OaModel(this.openApi, schema, name, this.options)); } - // todo: shorten models here this.shortenModels(); for (const [refName, model] of this.models.entries()) { this.imports.set(refName, new OaImport().fromModel(model)); @@ -164,14 +160,18 @@ export class Generator { while (this.operations.has(tryId)) { tryId = `${id}_${++suffix}`; } - // console.warn(`Duplicate operation id '${id}'. Assuming id ${tryId} for operation '${opPath}.${method}'.`); + console.warn( + `Duplicate operation id '${id}'. Assuming id ${tryId} for operation '${opPath}.${method}'.`, + ); id = tryId; } const operation = new OaOperation(this.openApi, opPath, pathSpec, method, id, methodSpec, this.options); // Set a default tag if no tags are found if (operation.tags.length === 0) { - // console.warn(`No tags set on operation '${opPath}.${method}'. Assuming '${this.options.defaultTag}'.`); + console.warn( + `No tags set on operation '${opPath}.${method}'. Assuming '${this.options.defaultTag}'.`, + ); operation.tags.push(this.options.defaultTag); } for (const tag of operation.tags) { @@ -192,11 +192,13 @@ export class Generator { const tags = this.openApi.tags || []; for (const [tagName, operations] of this.operationsByTag.entries()) { if (this.options.includeTags.length > 0 && !this.options.includeTags.includes(tagName)) { - // console.debug(`Ignoring tag ${tagName} because it is not listed in the 'includeTags' option`); + this.options.verbose && + console.debug(`Ignoring tag ${tagName} because it is not listed in the 'includeTags' option.`); continue; } if (this.options.excludeTags.length > 0 && this.options.excludeTags.includes(tagName)) { - // console.debug(`Ignoring tag ${tagName} because it is listed in the 'excludeTags' option`); + this.options.verbose && + console.debug(`Ignoring tag ${tagName} because it is listed in the 'excludeTags' option.`); continue; } const tag = tags.find((t) => t.name === tagName) || { name: tagName }; @@ -228,7 +230,7 @@ export class Generator { // Then delete all unused models for (const model of this.models.values()) { if (!usedNames.has(model.name)) { - // console.debug(`Ignoring model ${model.name} because it is not used anywhere`); + this.options.verbose && console.debug(`Ignoring model ${model.name} because it is not used anywhere.`); this.models.delete(model.name); } } diff --git a/packages/ng-openapi-gen/src/lib/oa-import.ts b/packages/ng-openapi-gen/src/lib/oa-import.ts index 53f0fc2..84cef4d 100644 --- a/packages/ng-openapi-gen/src/lib/oa-import.ts +++ b/packages/ng-openapi-gen/src/lib/oa-import.ts @@ -40,9 +40,7 @@ export class OaImport { this.refName = source.refName; this.typeName = source.typeName; this.qualifiedName = source.qualifiedName; - // todo: shorten models here this.useAlias = false; - // this.useAlias = this.typeName !== this.qualifiedName; [this.namespace, this.fileName] = [source.namespace, source.fileName]; this.setRelativePath(); return this; diff --git a/packages/ng-openapi-gen/src/lib/oa-model.ts b/packages/ng-openapi-gen/src/lib/oa-model.ts index 802746b..e9604c6 100644 --- a/packages/ng-openapi-gen/src/lib/oa-model.ts +++ b/packages/ng-openapi-gen/src/lib/oa-model.ts @@ -20,8 +20,6 @@ export class OaModel extends OaBase { // Simple properties public simpleType: string; public enumValues: OaEnumValue[]; - // Array properties - // public elementType: string; // Object properties public properties: OaProperty[]; public additionalPropertiesType: string; diff --git a/packages/ng-openapi-gen/src/lib/oa-operation.ts b/packages/ng-openapi-gen/src/lib/oa-operation.ts index 10d358c..2d355e0 100644 --- a/packages/ng-openapi-gen/src/lib/oa-operation.ts +++ b/packages/ng-openapi-gen/src/lib/oa-operation.ts @@ -112,7 +112,7 @@ export class OaOperation { cnt.updateProperties(imports); } } - // Now calculate the variants: request body content x success response content + // Calculate the variants: request body content x success response content this.calculateVariants(); } @@ -128,7 +128,9 @@ export class OaOperation { param = param as ParameterObject; if (param.in === 'cookie') { - // console.warn(`Ignoring cookie parameter ${this.id}.${param.name} as cookie parameters cannot be sent in XmlHttpRequests.`); + console.warn( + `Ignoring cookie parameter ${this.id}.${param.name} as cookie parameters cannot be sent in XmlHttpRequests.`, + ); } else if (this.paramIsNotExcluded(param)) { result.push(new OaParameter(param as ParameterObject)); } diff --git a/packages/ng-openapi-gen/src/lib/options.ts b/packages/ng-openapi-gen/src/lib/options.ts index a693235..03edb24 100644 --- a/packages/ng-openapi-gen/src/lib/options.ts +++ b/packages/ng-openapi-gen/src/lib/options.ts @@ -3,6 +3,8 @@ interface OptionsInput { input: string; /** Path to directory where the generated files will be written to. Defaults to 'src/app/api'. */ output?: string; + /** Whether to output additional information during generation or not. Defaults to false. */ + verbose?: boolean; /** Tag name assumed for operations without tags. Defaults to 'Api'. */ defaultTag?: string; /** Timeout for fetching spec file from remote URL, in milliseconds. Defaults to 20000. */ @@ -39,7 +41,13 @@ interface OptionsInput { requestBuilder?: string; /** Name for the response class to generate. Defaults to 'StrictHttpResponse'. */ response?: string; - /** Determines how root enums will be generated. Defaults to 'pascal'. */ + /** + * Determines how root enums will be generated. Possible values are: + * - `alias` for a type alias with the possible values; + * - `upper` for an enum with UPPER_CASE names; + * - `pascal` for an enum with PascalCase names. + * Defaults to 'pascal'. + */ enumStyle?: 'alias' | 'upper' | 'pascal'; /** Path to directory with custom templates. All `.handlebars` files will override the corresponding default. */ templates?: string; @@ -65,6 +73,7 @@ interface OptionsInput { type DefaultedOptions = | 'output' + | 'verbose' | 'defaultTag' | 'fetchTimeout' | 'includeTags' @@ -95,6 +104,7 @@ export type Options = Required> & OptionsIn export const defaultOptions: Required> = { output: 'src/app/api', + verbose: false, defaultTag: 'Api', fetchTimeout: 20_000, includeTags: [], diff --git a/packages/ng-openapi-gen/src/lib/utils/file-system.ts b/packages/ng-openapi-gen/src/lib/utils/file-system.ts index 5b0aef6..a8cdce7 100644 --- a/packages/ng-openapi-gen/src/lib/utils/file-system.ts +++ b/packages/ng-openapi-gen/src/lib/utils/file-system.ts @@ -17,7 +17,7 @@ export function fileWrite(path: string, data: string): void { } /** Synchronizes the files from the source to the target directory. Optionally remove stale files. */ -export function syncDirs(srcDir: string, destDir: string, removeStale: boolean): void { +export function syncDirs(srcDir: string, destDir: string, removeStale: boolean, verbose: boolean): void { fse.ensureDirSync(destDir); const srcFiles = readdirSync(srcDir); @@ -25,14 +25,14 @@ export function syncDirs(srcDir: string, destDir: string, removeStale: boolean): const srcFile = join(srcDir, file); const destFile = join(destDir, file); if (lstatSync(srcFile).isDirectory()) { - syncDirs(srcFile, destFile, removeStale); + syncDirs(srcFile, destFile, removeStale, verbose); } else { // Read the content of both files and update if they differ const srcContent = fileRead(srcFile); const destContent = existsSync(destFile) ? fileRead(destFile) : null; if (srcContent !== destContent) { fileWrite(destFile, srcContent); - // console.debug('Wrote ' + destFile); + verbose && console.debug('Created file ' + destFile); } } } @@ -44,7 +44,7 @@ export function syncDirs(srcDir: string, destDir: string, removeStale: boolean): const destFile = join(destDir, file); if (!existsSync(srcFile) && lstatSync(destFile).isFile()) { unlinkSync(destFile); - // console.debug('Removed stale file ' + destFile); + verbose && console.debug('Removed stale file ' + destFile); } } } diff --git a/packages/ng-openapi-gen/src/lib/utils/lo/deburr.ts b/packages/ng-openapi-gen/src/lib/utils/lo/deburr.ts index 8b23e12..1dc7b4c 100644 --- a/packages/ng-openapi-gen/src/lib/utils/lo/deburr.ts +++ b/packages/ng-openapi-gen/src/lib/utils/lo/deburr.ts @@ -1,3 +1,5 @@ +import { rsComboMark } from './unicode-support.js'; + /* eslint-disable unicorn/no-hex-escape */ /** Used to map Latin Unicode letters to basic Latin letters. */ @@ -210,25 +212,12 @@ const deburrLetter = (letter: string) => deburredLetters[letter]; // eslint-disable-next-line unicorn/better-regex const reLatin = /[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g; -/** Used to compose unicode character classes. */ -const rsComboMarksRange = '\\u0300-\\u036f'; -const reComboHalfMarksRange = '\\ufe20-\\ufe2f'; -const rsComboSymbolsRange = '\\u20d0-\\u20ff'; -const rsComboMarksExtendedRange = '\\u1ab0-\\u1aff'; -const rsComboMarksSupplementRange = '\\u1dc0-\\u1dff'; -const rsComboRange = - rsComboMarksRange + - reComboHalfMarksRange + - rsComboSymbolsRange + - rsComboMarksExtendedRange + - rsComboMarksSupplementRange; - /** * Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks) and * [combining diacritical marks for symbols](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks_for_Symbols). */ // eslint-disable-next-line no-misleading-character-class -const reComboMark = new RegExp(`[${rsComboRange}]`, 'g'); +const reComboMark = new RegExp(rsComboMark, 'g'); /** * Deburrs `string` by converting diff --git a/packages/ng-openapi-gen/src/lib/utils/lo/has-unicode.ts b/packages/ng-openapi-gen/src/lib/utils/lo/has-unicode.ts index 3e0556e..6db403c 100644 --- a/packages/ng-openapi-gen/src/lib/utils/lo/has-unicode.ts +++ b/packages/ng-openapi-gen/src/lib/utils/lo/has-unicode.ts @@ -1,20 +1,4 @@ -/** Used to compose unicode character classes. */ -const rsAstralRange = '\\ud800-\\udfff'; -const rsComboMarksRange = '\\u0300-\\u036f'; -const reComboHalfMarksRange = '\\ufe20-\\ufe2f'; -const rsComboSymbolsRange = '\\u20d0-\\u20ff'; -const rsComboMarksExtendedRange = '\\u1ab0-\\u1aff'; -const rsComboMarksSupplementRange = '\\u1dc0-\\u1dff'; -const rsComboRange = - rsComboMarksRange + - reComboHalfMarksRange + - rsComboSymbolsRange + - rsComboMarksExtendedRange + - rsComboMarksSupplementRange; -const rsVarRange = '\\ufe0e\\ufe0f'; - -/** Used to compose unicode capture groups. */ -const rsZWJ = '\\u200d'; +import { rsAstralRange, rsComboRange, rsVarRange, rsZWJ } from './unicode-support.js'; /** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */ // eslint-disable-next-line no-misleading-character-class diff --git a/packages/ng-openapi-gen/src/lib/utils/lo/index.ts b/packages/ng-openapi-gen/src/lib/utils/lo/index.ts index 6590d1c..821e232 100644 --- a/packages/ng-openapi-gen/src/lib/utils/lo/index.ts +++ b/packages/ng-openapi-gen/src/lib/utils/lo/index.ts @@ -3,3 +3,9 @@ export { deburr } from './deburr.js'; export { kebabCase } from './kebab-case.js'; export { upperCase } from './upper-case.js'; export { upperFirst } from './upper-first.js'; + +/** + * This directory contains functions extracted from https://github.com/lodash/lodash + * to minimize the amount of dependencies. + * These functions have also been optimized. + */ diff --git a/packages/ng-openapi-gen/src/lib/utils/lo/unicode-support.ts b/packages/ng-openapi-gen/src/lib/utils/lo/unicode-support.ts new file mode 100644 index 0000000..2ccd0fc --- /dev/null +++ b/packages/ng-openapi-gen/src/lib/utils/lo/unicode-support.ts @@ -0,0 +1,33 @@ +/** Used to compose unicode character classes. */ +export const rsAstralRange = '\\ud800-\\udfff'; +const rsComboMarksRange = '\\u0300-\\u036f'; +const reComboHalfMarksRange = '\\ufe20-\\ufe2f'; +const rsComboSymbolsRange = '\\u20d0-\\u20ff'; +const rsComboMarksExtendedRange = '\\u1ab0-\\u1aff'; +const rsComboMarksSupplementRange = '\\u1dc0-\\u1dff'; + +export const rsComboRange = + rsComboMarksRange + + reComboHalfMarksRange + + rsComboSymbolsRange + + rsComboMarksExtendedRange + + rsComboMarksSupplementRange; +export const rsComboMark = `[${rsComboRange}]`; + +export const rsVarRange = '\\ufe0e\\ufe0f'; + +/** Used to compose unicode capture groups. */ +export const rsFitz = '\\ud83c[\\udffb-\\udfff]'; +export const rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}'; +export const rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]'; +export const rsZWJ = '\\u200d'; + +export const rsAstralMark = `[${rsAstralRange}]`; +export const rsNonAstralMark = `[^${rsAstralRange}]`; +const rsComboFitzMark = `(?:${rsComboMark}|${rsFitz})`; +export const rsComboFitzOptionalMark = `${rsComboFitzMark}?`; +const rsVarOptionalMark = `[${rsVarRange}]?`; +const rsOptionalJoinGroup = `(?:${rsZWJ}(?:${[rsNonAstralMark, rsRegional, rsSurrPair].join('|')})${ + rsVarOptionalMark + rsComboFitzOptionalMark +})*`; +export const rsSequence = rsVarOptionalMark + rsComboFitzOptionalMark + rsOptionalJoinGroup; diff --git a/packages/ng-openapi-gen/src/lib/utils/lo/unicode-to-array.ts b/packages/ng-openapi-gen/src/lib/utils/lo/unicode-to-array.ts index 15e84c4..c51681d 100644 --- a/packages/ng-openapi-gen/src/lib/utils/lo/unicode-to-array.ts +++ b/packages/ng-openapi-gen/src/lib/utils/lo/unicode-to-array.ts @@ -1,38 +1,19 @@ -/** Used to compose unicode character classes. */ -const rsAstralRange = '\\ud800-\\udfff'; -const rsComboMarksRange = '\\u0300-\\u036f'; -const reComboHalfMarksRange = '\\ufe20-\\ufe2f'; -const rsComboSymbolsRange = '\\u20d0-\\u20ff'; -const rsComboMarksExtendedRange = '\\u1ab0-\\u1aff'; -const rsComboMarksSupplementRange = '\\u1dc0-\\u1dff'; -const rsComboRange = - rsComboMarksRange + - reComboHalfMarksRange + - rsComboSymbolsRange + - rsComboMarksExtendedRange + - rsComboMarksSupplementRange; -const rsVarRange = '\\ufe0e\\ufe0f'; - -/** Used to compose unicode capture groups. */ -const rsAstral = `[${rsAstralRange}]`; -const rsCombo = `[${rsComboRange}]`; -const rsFitz = '\\ud83c[\\udffb-\\udfff]'; -const rsModifier = `(?:${rsCombo}|${rsFitz})`; -const rsNonAstral = `[^${rsAstralRange}]`; -const rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}'; -const rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]'; -const rsZWJ = '\\u200d'; +import { + rsAstralMark, + rsComboMark, + rsFitz, + rsNonAstralMark, + rsRegional, + rsSequence, + rsSurrPair, +} from './unicode-support.js'; /** Used to compose unicode regexes. */ -const reOptMod = `${rsModifier}?`; -const rsOptVar = `[${rsVarRange}]?`; -const rsOptJoin = `(?:${rsZWJ}(?:${[rsNonAstral, rsRegional, rsSurrPair].join('|')})${rsOptVar + reOptMod})*`; -const rsSeq = rsOptVar + reOptMod + rsOptJoin; -const rsNonAstralCombo = `${rsNonAstral}${rsCombo}?`; -const rsSymbol = `(?:${[rsNonAstralCombo, rsCombo, rsRegional, rsSurrPair, rsAstral].join('|')})`; +const rsNonAstralCombo = `${rsNonAstralMark}${rsComboMark}?`; +const rsSymbol = `(?:${[rsNonAstralCombo, rsComboMark, rsRegional, rsSurrPair, rsAstralMark].join('|')})`; /** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */ -const reUnicode = new RegExp(`${rsFitz}(?=${rsFitz})|${rsSymbol + rsSeq}`, 'g'); +const reUnicode = new RegExp(`${rsFitz}(?=${rsFitz})|${rsSymbol + rsSequence}`, 'g'); /** Converts a Unicode `string` to an array. */ export function unicodeToArray(input: string): string[] { diff --git a/packages/ng-openapi-gen/src/lib/utils/lo/unicode-words.ts b/packages/ng-openapi-gen/src/lib/utils/lo/unicode-words.ts index af218f9..8143ffc 100644 --- a/packages/ng-openapi-gen/src/lib/utils/lo/unicode-words.ts +++ b/packages/ng-openapi-gen/src/lib/utils/lo/unicode-words.ts @@ -1,16 +1,6 @@ +import { rsAstralRange, rsRegional, rsSequence, rsSurrPair } from './unicode-support.js'; + /** Used to compose unicode character classes. */ -const rsAstralRange = '\\ud800-\\udfff'; -const rsComboMarksRange = '\\u0300-\\u036f'; -const reComboHalfMarksRange = '\\ufe20-\\ufe2f'; -const rsComboSymbolsRange = '\\u20d0-\\u20ff'; -const rsComboMarksExtendedRange = '\\u1ab0-\\u1aff'; -const rsComboMarksSupplementRange = '\\u1dc0-\\u1dff'; -const rsComboRange = - rsComboMarksRange + - reComboHalfMarksRange + - rsComboSymbolsRange + - rsComboMarksExtendedRange + - rsComboMarksSupplementRange; const rsDingbatRange = '\\u2700-\\u27bf'; const rsLowerRange = 'a-z\\xdf-\\xf6\\xf8-\\xff'; const rsMathOpRange = '\\xac\\xb1\\xd7\\xf7'; @@ -19,44 +9,34 @@ const rsPunctuationRange = '\\u2000-\\u206f'; const rsSpaceRange = ' \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000'; const rsUpperRange = 'A-Z\\xc0-\\xd6\\xd8-\\xde'; -const rsVarRange = '\\ufe0e\\ufe0f'; const rsBreakRange = rsMathOpRange + rsNonCharRange + rsPunctuationRange + rsSpaceRange; /** Used to compose unicode capture groups. */ -const rsApos = "['\u2019]"; -const rsBreak = `[${rsBreakRange}]`; -const rsCombo = `[${rsComboRange}]`; +const rsAposMark = "['\u2019]"; +const rsBreakMark = `[${rsBreakRange}]`; const rsDigit = '\\d'; -const rsDingbat = `[${rsDingbatRange}]`; -const rsLower = `[${rsLowerRange}]`; -const rsMisc = `[^${rsAstralRange}${rsBreakRange + rsDigit + rsDingbatRange + rsLowerRange + rsUpperRange}]`; -const rsFitz = '\\ud83c[\\udffb-\\udfff]'; -const rsModifier = `(?:${rsCombo}|${rsFitz})`; -const rsNonAstral = `[^${rsAstralRange}]`; -const rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}'; -const rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]'; -const rsUpper = `[${rsUpperRange}]`; -const rsZWJ = '\\u200d'; +const rsDingbatMark = `[${rsDingbatRange}]`; +const rsLowerMark = `[${rsLowerRange}]`; +const rsMiscMark = `[^${rsAstralRange}${rsBreakRange + rsDigit + rsDingbatRange + rsLowerRange + rsUpperRange}]`; +const rsUpperMark = `[${rsUpperRange}]`; /** Used to compose unicode regexes. */ -const rsMiscLower = `(?:${rsLower}|${rsMisc})`; -const rsMiscUpper = `(?:${rsUpper}|${rsMisc})`; -const rsOptContrLower = `(?:${rsApos}(?:d|ll|m|re|s|t|ve))?`; -const rsOptContrUpper = `(?:${rsApos}(?:D|LL|M|RE|S|T|VE))?`; -const reOptMod = `${rsModifier}?`; -const rsOptVar = `[${rsVarRange}]?`; -const rsOptJoin = `(?:${rsZWJ}(?:${[rsNonAstral, rsRegional, rsSurrPair].join('|')})${rsOptVar + reOptMod})*`; +const rsMiscLowerGroup = `(?:${rsLowerMark}|${rsMiscMark})`; +const rsMiscUpperGroup = `(?:${rsUpperMark}|${rsMiscMark})`; +const rsOptContrLowerGroup = `(?:${rsAposMark}(?:d|ll|m|re|s|t|ve))?`; +const rsOptContrUpperGroup = `(?:${rsAposMark}(?:D|LL|M|RE|S|T|VE))?`; const rsOrdLower = '\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])'; const rsOrdUpper = '\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])'; -const rsSeq = rsOptVar + reOptMod + rsOptJoin; -const rsEmoji = `(?:${[rsDingbat, rsRegional, rsSurrPair].join('|')})${rsSeq}`; +const rsEmoji = `(?:${[rsDingbatMark, rsRegional, rsSurrPair].join('|')})${rsSequence}`; const reUnicodeWords = new RegExp( [ - `${rsUpper}?${rsLower}+${rsOptContrLower}(?=${[rsBreak, rsUpper, '$'].join('|')})`, - `${rsMiscUpper}+${rsOptContrUpper}(?=${[rsBreak, rsUpper + rsMiscLower, '$'].join('|')})`, - `${rsUpper}?${rsMiscLower}+${rsOptContrLower}`, - `${rsUpper}+${rsOptContrUpper}`, + `${rsUpperMark}?${rsLowerMark}+${rsOptContrLowerGroup}(?=${[rsBreakMark, rsUpperMark, '$'].join('|')})`, + `${rsMiscUpperGroup}+${rsOptContrUpperGroup}(?=${[rsBreakMark, rsUpperMark + rsMiscLowerGroup, '$'].join( + '|', + )})`, + `${rsUpperMark}?${rsMiscLowerGroup}+${rsOptContrLowerGroup}`, + `${rsUpperMark}+${rsOptContrUpperGroup}`, rsOrdUpper, rsOrdLower, `${rsDigit}+`, diff --git a/packages/ng-openapi-gen/src/lib/utils/open-api.ts b/packages/ng-openapi-gen/src/lib/utils/open-api.ts index e1d626a..06e27cf 100644 --- a/packages/ng-openapi-gen/src/lib/utils/open-api.ts +++ b/packages/ng-openapi-gen/src/lib/utils/open-api.ts @@ -9,10 +9,8 @@ import { namespace, refName, toBasicChars, tsComments, typeName } from './string /** Returns the unqualified model class name, that is, the last part after '.' */ export function unqualifiedName(name: string, options: Options): string { - // todo: shorten models here const nameParts = name.split('_').map((part) => part.slice(part.lastIndexOf('.') + 1)); return modelClass(nameParts.join(''), options); - // return modelClass(name.slice(name.lastIndexOf('.') + 1), options); } /** Returns the qualified model class name, that is, the camelized namespace (if any) plus the unqualified name */ @@ -32,26 +30,6 @@ export function enumName(value: string, options: Options): string { return name; } -// /** Returns the file to import for a given model */ -// export function modelFile(pathToModels: string, name: string, options: Options): string { -// let dir = pathToModels || ''; -// if (dir.endsWith('/')) { -// dir = dir.slice(0, -1); -// } -// const ns = namespace(name); -// if (ns) { -// dir += `/${ns}`; -// } -// const file = unqualifiedName(name, options); -// return dir + '/' + fileName(file); -// } -// -// /** Return the file path to import relative to modelsDir */ -// export function modelFileFromModels(name: string, options: Options): string { -// const ns = namespace(name); -// return (ns ? `${ns}/` : '') + fileName(unqualifiedName(name, options)); -// } - /** Applies the prefix and suffix to a model class name */ export function modelClass(baseName: string, options: Options): string { return `${options.modelPrefix}${typeName(baseName)}${options.modelSuffix}`; diff --git a/packages/ng-openapi-gen/src/ng-openapi-gen.ts b/packages/ng-openapi-gen/src/ng-openapi-gen.ts index 94056c1..7a03d67 100644 --- a/packages/ng-openapi-gen/src/ng-openapi-gen.ts +++ b/packages/ng-openapi-gen/src/ng-openapi-gen.ts @@ -27,9 +27,9 @@ const parsedArgs = yargsParser(process.argv.slice(2), { 'fallbackPropertyType', ], number: ['fetchTimeout'], - boolean: ['ignoreUnusedModels', 'removeStaleFiles', 'indexFile', 'skipJsonSuffix'], + boolean: ['verbose', 'ignoreUnusedModels', 'removeStaleFiles', 'indexFile', 'skipJsonSuffix'], array: [{ key: 'includeTags' }, { key: 'excludeTags' }, { key: 'excludeParameters' }], - alias: { config: 'c', input: 'i', output: 'o' }, + alias: { config: 'c', input: 'i', output: 'o', verbose: 'v' }, configuration: { 'strip-dashed': true, 'strip-aliased': true }, // CONFIG_END }) as unknown as Options & { config?: string }; @@ -41,10 +41,10 @@ const parsedArgs = yargsParser(process.argv.slice(2), { try { config = JSON.parse(fileRead(parsedArgs.config)); } catch (error) { - throw new Error(`The given config file can not be loaded: ${error.message}`); + throw new Error(`The given config file can not be loaded: ${error.message}.`); } } else { - throw new Error(`The given config file does not exist: ${parsedArgs.config}`); + throw new Error(`The given config file does not exist: ${parsedArgs.config}.`); } } @@ -54,7 +54,7 @@ const parsedArgs = yargsParser(process.argv.slice(2), { config = Object.assign({}, defaultOptions, config, cleanArgs); if (!config.input) { - throw new Error(`No input file path or URL is specified`); + throw new Error(`No input file path or URL is specified.`); } const refParser = new $RefParser(); @@ -66,8 +66,7 @@ const parsedArgs = yargsParser(process.argv.slice(2), { })) as OpenAPIObject; await new Generator(openApi, config).generate(); -})(); -// .catch((error) => { -// process.stdout.write(`An error occurred\n`); -// throw error; -// }); +})().catch((error) => { + process.stdout.write(`An error occurred:\n`); + throw error; +}); diff --git a/packages/ng-openapi-gen/src/schema.json b/packages/ng-openapi-gen/src/schema.json index eef950d..3dbbf48 100644 --- a/packages/ng-openapi-gen/src/schema.json +++ b/packages/ng-openapi-gen/src/schema.json @@ -17,6 +17,11 @@ "type": "string", "default": "src/app/api" }, + "verbose": { + "description": "Whether to output additional information during generation or not. Defaults to false.", + "type": "boolean", + "default": false + }, "defaultTag": { "description": "Tag name assumed for operations without tags. Defaults to 'Api'.", "type": "string", @@ -133,7 +138,7 @@ "default": "StrictHttpResponse" }, "enumStyle": { - "description": "Determines how root enums will be generated. Defaults to 'pascal'.", + "description": "Determines how root enums will be generated. Possible values are:\n- `alias` for a type alias with the possible values;\n- `upper` for an enum with UPPER_CASE names;\n- `pascal` for an enum with PascalCase names.\nDefaults to 'pascal'.", "enum": ["alias", "upper", "pascal"], "default": "pascal" }, diff --git a/packages/ng-openapi-gen/src/templates/requestBuilder.handlebars b/packages/ng-openapi-gen/src/templates/requestBuilder.handlebars index 791c0ad..64def08 100644 --- a/packages/ng-openapi-gen/src/templates/requestBuilder.handlebars +++ b/packages/ng-openapi-gen/src/templates/requestBuilder.handlebars @@ -1,5 +1,6 @@ /* tslint:disable */ /* eslint-disable */ +{{autoGenerationNotice}} import { HttpHeaders, HttpParameterCodec, HttpParams, HttpRequest, HttpResponse } from '@angular/common/http'; /** Constrains the HTTP response body to be non-null */ diff --git a/tools/executors/schema-generator/schema-descriptor.ts b/tools/executors/schema-generator/schema-descriptor.ts index 8d9c349..fce2944 100644 --- a/tools/executors/schema-generator/schema-descriptor.ts +++ b/tools/executors/schema-generator/schema-descriptor.ts @@ -16,6 +16,12 @@ export const schemaDescriptor: { properties: Record } = { default: 'src/app/api', alias: 'o', }, + verbose: { + description: 'Whether to output additional information during generation or not.', + type: 'boolean', + default: false, + alias: 'v', + }, defaultTag: { description: 'Tag name assumed for operations without tags.', type: 'string', @@ -111,7 +117,13 @@ export const schemaDescriptor: { properties: Record } = { default: 'StrictHttpResponse', }, enumStyle: { - description: 'Determines how root enums will be generated.', + description: [ + 'Determines how root enums will be generated. Possible values are:', + '- `alias` for a type alias with the possible values;', + '- `upper` for an enum with UPPER_CASE names;', + '- `pascal` for an enum with PascalCase names.', + '', + ].join('\n'), type: 'enum', default: 'pascal', values: ['alias', 'upper', 'pascal'], @@ -159,15 +171,19 @@ export const schemaDescriptor: { properties: Record } = { responseMethodDescription: { description: 'Description template for generated $response method.', type: 'string', - default: - '{{descriptionPrefix}}This method provides access to the full `HttpResponse`, allowing access to response headers.\nTo access only the response body, use `{{methodName}}()` instead.{{descriptionSuffix}}', + default: [ + '{{descriptionPrefix}}This method provides access to the full `HttpResponse`, allowing access to response headers.', + 'To access only the response body, use `{{methodName}}()` instead.{{descriptionSuffix}}', + ].join('\n'), onlyFor: ['json', 'model'], }, bodyMethodDescription: { description: 'Description template for generated $body method.', type: 'string', - default: - '{{descriptionPrefix}}This method provides access only to the response body.\nTo access the full response (for headers, for example), use `{{responseMethodName}}()` instead.{{descriptionSuffix}}', + default: [ + '{{descriptionPrefix}}This method provides access only to the response body.', + 'To access the full response (for headers, for example), use `{{responseMethodName}}()` instead.{{descriptionSuffix}}', + ].join('\n'), onlyFor: ['json', 'model'], }, fallbackPropertyType: {