fork of hey-api/openapi-ts because I need some additional things

chore: expose reserved keywords

Lubos 3fc12399 d8b973b9

+174 -116
+1 -2
.vscode/launch.json
··· 15 15 "skipFiles": ["<node_internals>/**"], 16 16 "cwd": "${workspaceFolder}/dev", 17 17 "runtimeExecutable": "node", 18 - "runtimeArgs": ["-r", "ts-node/register/transpile-only"], 19 - "program": "${workspaceFolder}/packages/openapi-ts/src/run.ts", 18 + "program": "${workspaceFolder}/packages/openapi-ts/dist/run.mjs", 20 19 "env": { 21 20 "DEBUG": "false" 22 21 }
+4 -1
dev/openapi-ts.config.ts
··· 5 5 // @ts-ignore 6 6 import { customClientPlugin } from '@hey-api/custom-client/plugin'; 7 7 // @ts-ignore 8 - import { defineConfig, utils } from '@hey-api/openapi-ts'; 8 + import { defineConfig, reserved, utils } from '@hey-api/openapi-ts'; 9 9 10 10 // @ts-ignore 11 11 import { myClientPlugin } from '../packages/openapi-ts-tests/main/test/custom/client/plugin'; 12 12 // @ts-ignore 13 13 import { getSpecsPath } from '../packages/openapi-ts-tests/utils'; 14 + 15 + reserved.runtime.set((list) => [...list, 'Agent']); 16 + reserved.type.set((list) => [...list, 'Agent']); 14 17 15 18 // @ts-ignore 16 19 export default defineConfig(() => {
+2
packages/openapi-ts/src/ts-dsl/index.ts
··· 350 350 export type { MaybeTsDsl, TypeTsDsl } from './base'; 351 351 export { TsDsl } from './base'; 352 352 export { TypeScriptRenderer } from './render/typescript'; 353 + export { keywords } from './utils/keywords'; 353 354 export { regexp } from './utils/regexp'; 355 + export { reserved } from './utils/reserved';
+104
packages/openapi-ts/src/ts-dsl/utils/keywords.ts
··· 1 + const browserGlobals = [ 2 + 'document', 3 + 'history', 4 + 'location', 5 + 'navigator', 6 + 'window', 7 + ]; 8 + 9 + const javaScriptGlobals = [ 10 + 'console', 11 + 'Array', 12 + 'Date', 13 + 'Error', 14 + 'Function', 15 + 'JSON', 16 + 'Map', 17 + 'Math', 18 + 'Object', 19 + 'Promise', 20 + 'RegExp', 21 + 'Set', 22 + 'WeakMap', 23 + 'WeakSet', 24 + ]; 25 + 26 + const javaScriptKeywords = [ 27 + 'arguments', 28 + 'async', 29 + 'await', 30 + 'break', 31 + 'case', 32 + 'catch', 33 + 'class', 34 + 'const', 35 + 'continue', 36 + 'debugger', 37 + 'default', 38 + 'delete', 39 + 'do', 40 + 'else', 41 + 'enum', 42 + 'eval', 43 + 'export', 44 + 'extends', 45 + 'false', 46 + 'finally', 47 + 'for', 48 + 'from', 49 + 'function', 50 + 'if', 51 + 'implements', 52 + 'import', 53 + 'in', 54 + 'instanceof', 55 + 'interface', 56 + 'let', 57 + 'new', 58 + 'null', 59 + 'package', 60 + 'private', 61 + 'protected', 62 + 'public', 63 + 'return', 64 + 'static', 65 + 'super', 66 + 'switch', 67 + 'this', 68 + 'throw', 69 + 'true', 70 + 'try', 71 + 'typeof', 72 + 'var', 73 + 'void', 74 + 'while', 75 + 'with', 76 + 'yield', 77 + ]; 78 + 79 + const nodeGlobals = ['global', 'process', 'Buffer']; 80 + 81 + const typeScriptKeywords = [ 82 + 'any', 83 + 'as', 84 + 'bigint', 85 + 'boolean', 86 + 'namespace', 87 + 'never', 88 + 'null', 89 + 'number', 90 + 'string', 91 + 'symbol', 92 + 'type', 93 + 'undefined', 94 + 'unknown', 95 + 'void', 96 + ]; 97 + 98 + export const keywords = { 99 + browserGlobals, 100 + javaScriptGlobals, 101 + javaScriptKeywords, 102 + nodeGlobals, 103 + typeScriptKeywords, 104 + };
+7 -21
packages/openapi-ts/src/ts-dsl/utils/name.ts
··· 4 4 import { IdTsDsl } from '../expr/id'; 5 5 import { LiteralTsDsl } from '../expr/literal'; 6 6 import { regexp } from './regexp'; 7 - import { 8 - browserGlobals, 9 - javaScriptGlobals, 10 - javaScriptKeywords, 11 - nodeGlobals, 12 - typeScriptKeywords, 13 - } from './reserved'; 7 + import type { ReservedList } from './reserved'; 8 + import { reserved } from './reserved'; 14 9 15 10 export const safeMemberName = (name: string): TsDsl<ts.PropertyName> => { 16 11 regexp.typeScriptIdentifier.lastIndex = 0; ··· 36 31 return new LiteralTsDsl(name) as TsDsl<ts.PropertyName>; 37 32 }; 38 33 39 - const sanitizeName = (name: string, reserved: Set<string>): string => { 34 + const safeName = (name: string, reserved: ReservedList): string => { 40 35 let sanitized = ''; 41 36 let index: number; 42 37 ··· 56 51 index += 1; 57 52 } 58 53 59 - if (reserved.has(sanitized)) { 54 + if (reserved['~values'].has(sanitized)) { 60 55 sanitized = `_${sanitized}`; 61 56 } 62 57 63 58 return sanitized || '_'; 64 59 }; 65 60 66 - const runtimeReserved = new Set([ 67 - ...browserGlobals, 68 - ...javaScriptGlobals, 69 - ...javaScriptKeywords, 70 - ...nodeGlobals, 71 - ...typeScriptKeywords, 72 - ]); 73 - 74 - const typeReserved = new Set([...javaScriptKeywords, ...typeScriptKeywords]); 61 + export const safeRuntimeName = (name: string) => 62 + safeName(name, reserved.runtime); 75 63 76 - export const safeRuntimeName = (name: string) => 77 - sanitizeName(name, runtimeReserved); 78 - export const safeTypeName = (name: string) => sanitizeName(name, typeReserved); 64 + export const safeTypeName = (name: string) => safeName(name, reserved.type);
+56 -92
packages/openapi-ts/src/ts-dsl/utils/reserved.ts
··· 1 - export const browserGlobals = [ 2 - 'document', 3 - 'history', 4 - 'location', 5 - 'navigator', 6 - 'window', 7 - ]; 1 + import { keywords } from './keywords'; 8 2 9 - export const javaScriptGlobals = [ 10 - 'console', 11 - 'Array', 12 - 'Date', 13 - 'Error', 14 - 'Function', 15 - 'JSON', 16 - 'Map', 17 - 'Math', 18 - 'Object', 19 - 'Promise', 20 - 'RegExp', 21 - 'Set', 22 - 'WeakMap', 23 - 'WeakSet', 24 - ]; 3 + type List = ReadonlyArray<string>; 25 4 26 - export const javaScriptKeywords = [ 27 - 'arguments', 28 - 'async', 29 - 'await', 30 - 'break', 31 - 'case', 32 - 'catch', 33 - 'class', 34 - 'const', 35 - 'continue', 36 - 'debugger', 37 - 'default', 38 - 'delete', 39 - 'do', 40 - 'else', 41 - 'enum', 42 - 'eval', 43 - 'export', 44 - 'extends', 45 - 'false', 46 - 'finally', 47 - 'for', 48 - 'from', 49 - 'function', 50 - 'if', 51 - 'implements', 52 - 'import', 53 - 'in', 54 - 'instanceof', 55 - 'interface', 56 - 'let', 57 - 'new', 58 - 'null', 59 - 'package', 60 - 'private', 61 - 'protected', 62 - 'public', 63 - 'return', 64 - 'static', 65 - 'super', 66 - 'switch', 67 - 'this', 68 - 'throw', 69 - 'true', 70 - 'try', 71 - 'typeof', 72 - 'var', 73 - 'void', 74 - 'while', 75 - 'with', 76 - 'yield', 77 - ]; 5 + export class ReservedList { 6 + private _array: List; 7 + private _set: Set<string>; 8 + 9 + constructor(values: List) { 10 + this._array = values; 11 + this._set = new Set(values); 12 + } 78 13 79 - export const nodeGlobals = ['global', 'process', 'Buffer']; 14 + get '~values'() { 15 + return this._set; 16 + } 80 17 81 - export const typeScriptKeywords = [ 82 - 'any', 83 - 'as', 84 - 'bigint', 85 - 'boolean', 86 - 'namespace', 87 - 'never', 88 - 'null', 89 - 'number', 90 - 'string', 91 - 'symbol', 92 - 'type', 93 - 'undefined', 94 - 'unknown', 95 - 'void', 96 - ]; 18 + /** 19 + * Updates the reserved list with new values. 20 + * 21 + * @param values New reserved values or a function that receives the previous 22 + * reserved values and returns the new ones. 23 + */ 24 + set(values: List | ((prev: List) => List)): void { 25 + const vals = typeof values === 'function' ? values(this._array) : values; 26 + this._array = vals; 27 + this._set = new Set(vals); 28 + } 29 + } 30 + 31 + const runtimeReserved = new ReservedList([ 32 + ...keywords.browserGlobals, 33 + ...keywords.javaScriptGlobals, 34 + ...keywords.javaScriptKeywords, 35 + ...keywords.nodeGlobals, 36 + ...keywords.typeScriptKeywords, 37 + ]); 38 + 39 + const typeReserved = new ReservedList([ 40 + ...keywords.javaScriptKeywords, 41 + ...keywords.typeScriptKeywords, 42 + ]); 43 + 44 + /** 45 + * Reserved names for identifiers. These names will not be used 46 + * for variables, functions, classes, or other identifiers in generated code. 47 + */ 48 + export const reserved = { 49 + /** 50 + * Reserved names for runtime identifiers. These names will not be used 51 + * for variables, functions, classes, or other runtime identifiers in 52 + * generated code. 53 + */ 54 + runtime: runtimeReserved, 55 + /** 56 + * Reserved names for type identifiers. These names will not be used 57 + * for type or interface identifiers in generated code. 58 + */ 59 + type: typeReserved, 60 + };