From ed135da3735cfc40769ca4cdcedc67a4d979d504 Mon Sep 17 00:00:00 2001 From: Sean Ferguson Date: Fri, 13 Oct 2023 18:28:19 -0400 Subject: [PATCH] move OpenAPI codegen to @signal24/openapi-client-codegen --- .npmignore | 2 +- package.json | 6 +- src/vite-plugins/vite-openapi-plugin.ts | 121 +----------------------- yarn.lock | 30 ++++-- 4 files changed, 28 insertions(+), 131 deletions(-) diff --git a/.npmignore b/.npmignore index 7eef75e..e11c661 100644 --- a/.npmignore +++ b/.npmignore @@ -2,4 +2,4 @@ .eslintcache node_modules .vscode -yarn.lock +tsconfig.tsbuildinfo diff --git a/package.json b/package.json index 2a2c6f8..e3e5d84 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@signal24/vue-foundation", "type": "module", - "version": "4.7.3", + "version": "4.7.4", "description": "Common components, directives, and helpers for Vue 3 apps", "module": "./dist/vue-foundation.es.js", "bin": { @@ -46,6 +46,7 @@ "devDependencies": { "@nabla/vite-plugin-eslint": "^1.5.0", "@rushstack/eslint-patch": "^1.3.2", + "@signal24/openapi-client-codegen": "^1.0.1", "@tsconfig/node18": "^18.2.0", "@types/jsdom": "^21.1.1", "@types/lodash": "^4.14.196", @@ -63,7 +64,6 @@ "eslint-plugin-unused-imports": "^3.0.0", "eslint-plugin-vue": "^9.16.1", "jsdom": "^22.1.0", - "openapi-typescript-codegen": "^0.25.0", "prettier": "^3.0.0", "sass": "^1.64.2", "start-server-and-test": "^2.0.0", @@ -72,4 +72,4 @@ "vitest": "^0.33.0", "vue-tsc": "^1.8.8" } -} +} \ No newline at end of file diff --git a/src/vite-plugins/vite-openapi-plugin.ts b/src/vite-plugins/vite-openapi-plugin.ts index b9a49d5..7f34c97 100644 --- a/src/vite-plugins/vite-openapi-plugin.ts +++ b/src/vite-plugins/vite-openapi-plugin.ts @@ -1,48 +1,4 @@ -import { createHash } from 'node:crypto'; -import { copyFileSync, existsSync, readFileSync, watch } from 'node:fs'; -import { rm } from 'node:fs/promises'; - -import * as OpenAPI from 'openapi-typescript-codegen'; - -const DEFAULT_OUT_PATH = './src/openapi-client-generated'; - -let generatedHash: string | null = null; -let generatorMap: Record = {}; -let overridesMap: Record | null = null; -let overridesInverseMap: Record | null = null; - -export function loadOpenapiConfig() { - loadGeneratorMap(); - loadOverridesMap(); -} - -function loadGeneratorMap() { - if (!existsSync('./openapi-specs.json')) { - console.error('openapi-specs.json not found. Cannot generate OpenAPI client.'); - return; - } - - try { - const specsContent = readFileSync('./openapi-specs.json', 'utf8'); - generatorMap = JSON.parse(specsContent); - } catch (e) { - console.error('Failed to load openapi-specs.json:', e); - } -} - -function loadOverridesMap() { - if (!existsSync('./openapi-specs.dev.json')) { - return; - } - - try { - const overridesContent = readFileSync('./openapi-specs.dev.json', 'utf8'); - overridesMap = JSON.parse(overridesContent); - overridesInverseMap = Object.fromEntries(Object.entries(overridesMap!).map(([k, v]) => [v, k])); - } catch (e) { - console.error('Failed to load openapi-specs.dev.json:', e); - } -} +import { createWatchfulOpenapiClientGenerators } from '@signal24/openapi-client-codegen'; export function openapiClientGeneratorPlugin(): { name: string; @@ -50,7 +6,7 @@ export function openapiClientGeneratorPlugin(): { buildStart(): void; closeBundle(): void; } { - let generators: ReturnType | null = null; + let generators: ReturnType | null = null; return { name: 'openapi-types-generator', @@ -59,7 +15,7 @@ export function openapiClientGeneratorPlugin(): { buildStart() { // apply a slight delay so any output doesn't get pushed off screen setTimeout(() => { - generators = createWatchfulGenerators(); + generators = createWatchfulOpenapiClientGenerators(); }, 250); }, @@ -72,74 +28,3 @@ export function openapiClientGeneratorPlugin(): { } }; } - -function createWatchfulGenerators() { - loadOpenapiConfig(); - return Object.entries(generatorMap).map(([openapiYamlPath, outPath]) => createWatchfulGenerator(openapiYamlPath, outPath)); -} - -function createWatchfulGenerator(openapiYamlPath: string, outPath: string) { - const resolvedPath = overridesMap?.[openapiYamlPath] ?? openapiYamlPath; - - if (!existsSync(resolvedPath)) { - console.log(`OpenAPI YAML file not found: ${resolvedPath}`); - return null; - } - - const watcher = watch(resolvedPath); - watcher.on('change', () => { - // give the writes a moment to settle - setTimeout(() => generateOpenapiClient(resolvedPath, outPath), 100); - }); - - generateOpenapiClient(resolvedPath, outPath); - - return { - close() { - watcher.close(); - } - }; -} - -export async function generateConfiguredOpenapiClients() { - loadOpenapiConfig(); - for (const [openapiYamlPath, outPath] of Object.entries(generatorMap)) { - const resolvedPath = overridesMap?.[openapiYamlPath] ?? openapiYamlPath; - await generateOpenapiClient(resolvedPath, outPath); - } -} - -export async function generateOpenapiClient(openapiYamlPath: string, outPath: string = DEFAULT_OUT_PATH) { - const yaml = readFileSync(openapiYamlPath, 'utf8'); - const hash = createHash('sha256').update(yaml).digest('hex'); - - if (hash === generatedHash) { - return; - } - - generatedHash = hash; - - try { - try { - await rm(outPath, { recursive: true }); - } catch (e) { - // ignore - } - - await OpenAPI.generate({ - input: openapiYamlPath, - output: outPath, - clientName: 'ApiClient', - useOptions: true, - useUnionTypes: true - }); - - if (overridesInverseMap?.[openapiYamlPath]) { - copyFileSync(openapiYamlPath, overridesInverseMap[openapiYamlPath]); - } - - console.log(`[${new Date().toISOString()}] Generated client from ${openapiYamlPath} to ${outPath}/`); - } catch (err) { - console.error(`[${new Date().toISOString()}] Error generating client from ${openapiYamlPath}:`, err); - } -} diff --git a/yarn.lock b/yarn.lock index 2f08463..734d69f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -444,6 +444,13 @@ resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df" integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ== +"@signal24/openapi-client-codegen@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@signal24/openapi-client-codegen/-/openapi-client-codegen-1.0.1.tgz#3053a5fbe74a76b2885bc06d57b540fb71acc544" + integrity sha512-7qUPoAT6i9bX+a/ZPDUg4iKtEZJOKhOHisP3ggQG/1lsPn7wOT8CJhNXlMCcKWUweT3+gvf1pH6XVBzzGNZdcA== + dependencies: + openapi-typescript-codegen "^0.25.0" + "@sinclair/typebox@^0.27.8": version "0.27.8" resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" @@ -498,11 +505,16 @@ "@types/tough-cookie" "*" parse5 "^7.0.0" -"@types/json-schema@*", "@types/json-schema@^7.0.6", "@types/json-schema@^7.0.9": +"@types/json-schema@*", "@types/json-schema@^7.0.9": version "7.0.11" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== +"@types/json-schema@^7.0.6": + version "7.0.13" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.13.tgz#02c24f4363176d2d18fc8b70b9f3c54aba178a85" + integrity sha512-RbSSoHliUbnXj3ny0CNFOoxrIDV6SUGyStHsvDqosw6CkdPV8TtWGlfecuK4ToyMEAql6pzNxgCFKanovUzlgQ== + "@types/lodash@^4.14.196": version "4.14.196" resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.196.tgz#a7c3d6fc52d8d71328b764e28e080b4169ec7a95" @@ -1256,9 +1268,9 @@ commander@^10.0.0: integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== commander@^11.0.0: - version "11.0.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-11.0.0.tgz#43e19c25dbedc8256203538e8d7e9346877a6f67" - integrity sha512-9HMlXtt/BNoYr8ooyjjNRdIilOTkVJXB+GhxMTtOKwk0R4j4lS4NpjuqmRxroBfnfTSHQIHQB7wryHhXarNjmQ== + version "11.1.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-11.1.0.tgz#62fdce76006a68e5c1ab3314dc92e800eb83d906" + integrity sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ== commander@^6.2.1: version "6.2.1" @@ -2162,12 +2174,12 @@ graphemer@^1.4.0: integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== handlebars@^4.7.7: - version "4.7.7" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1" - integrity sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA== + version "4.7.8" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.8.tgz#41c42c18b1be2365439188c77c6afae71c0cd9e9" + integrity sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ== dependencies: minimist "^1.2.5" - neo-async "^2.6.0" + neo-async "^2.6.2" source-map "^0.6.1" wordwrap "^1.0.0" optionalDependencies: @@ -2755,7 +2767,7 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== -neo-async@^2.6.0: +neo-async@^2.6.2: version "2.6.2" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==