[{"data":1,"prerenderedAt":812},["ShallowReactive",2],{"page:\u002Fdocs\u002F5.x\u002Fintegrations\u002Fopenapi-import":3},{"id":4,"title":5,"body":6,"description":793,"extension":794,"frontmatter":795,"heading":5,"meta":802,"navigation":804,"order":799,"path":805,"seo":806,"sitemap":807,"source":808,"stem":809,"__hash__":810,"hasPopups":811},"docs\u002Fdocs\u002F5.x\u002Fintegrations\u002Fopenapi-import.md","Import an OpenAPI spec in TypeScript with openapi-import",{"type":7,"value":8,"toc":782},"minimark",[9,25,60,72,84,348,352,358,375,447,465,469,494,548,551,715,727,731,751,755],[10,11,12,20,21,24],"p",{},[13,14,16],"a",{"href":15},"https:\u002F\u002Fgithub.com\u002Fkubb-labs\u002Fopenapi-import",[17,18,19],"code",{},"openapi-import"," lets you import a spec like a TypeScript module and get the output of every plugin in your ",[17,22,23],{},"kubb.config.ts",", without generated files:",[26,27,31],"pre",{"language":28,"code":29,"class":30},"ts","import { type Pet, petStatusEnum } from '.\u002FpetStore.openapi.yaml'","shiki shiki-themes github-light github-dark dark:github-dark",[17,32,34],{"class":33},"language-ts",[35,36,39,43,47,50,53,56],"span",{"class":37,"style":38},"line","display: inline",[35,40,42],{"style":41},"color:#D73A49;--shiki-dark:#F97583","import",[35,44,46],{"style":45},"color:#24292E;--shiki-dark:#E1E4E8"," { ",[35,48,49],{"style":41},"type",[35,51,52],{"style":45}," Pet, petStatusEnum } ",[35,54,55],{"style":41},"from",[35,57,59],{"style":58},"color:#032F62;--shiki-dark:#9ECBFF"," '.\u002FpetStore.openapi.yaml'",[10,61,62,63,67,68,71],{},"It is a ",[13,64,66],{"href":65},"https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Ftypescript-go\u002Fpull\u002F4712","TypeScript content mapper",", so ",[17,69,70],{},"tsc"," and your editor type-check the plugin output in place of the spec. Go to definition, hover, and rename jump between the generated types and the keys in the spec.",[73,74,76,77,79,80,83],"blockquote",{"as":75},"warning","",[17,78,19],{}," is experimental. It needs TypeScript 7.1.0-beta or later with ",[17,81,82],{},"--runExternalCode",".",[85,86,88,93,96,150,154,165,292,296,333,342],"steps",{"level":87},"2",[89,90,92],"h2",{"id":91},"install-openapi-import","Install openapi-import",[10,94,95],{},"Install it with Kubb and the TypeScript beta:",[97,98,100,129],"code-group",{"sync":99},"package-manager",[26,101,105],{"language":102,"filename":103,"code":104,"class":30},"shell","pnpm","pnpm add -D kubb openapi-import typescript@beta",[17,106,108],{"class":107},"language-shell",[35,109,110,113,116,120,123,126],{"class":37,"style":38},[35,111,103],{"style":112},"color:#6F42C1;--shiki-dark:#B392F0",[35,114,115],{"style":58}," add",[35,117,119],{"style":118},"color:#005CC5;--shiki-dark:#79B8FF"," -D",[35,121,122],{"style":58}," kubb",[35,124,125],{"style":58}," openapi-import",[35,127,128],{"style":58}," typescript@beta",[26,130,133],{"language":102,"filename":131,"code":132,"class":30},"npm","npm install -D kubb openapi-import typescript@beta",[17,134,135],{"class":107},[35,136,137,139,142,144,146,148],{"class":37,"style":38},[35,138,131],{"style":112},[35,140,141],{"style":58}," install",[35,143,119],{"style":118},[35,145,122],{"style":58},[35,147,125],{"style":58},[35,149,128],{"style":58},[89,151,153],{"id":152},"register-the-extension","Register the extension",[10,155,156,157,160,161,164],{},"Add the content mapper to ",[17,158,159],{},"tsconfig.json",", and name the spec ",[17,162,163],{},"\u003Cname>.openapi.yaml",":",[26,166,169],{"language":167,"filename":159,"code":168,"class":30},"json","{\n  \"compilerOptions\": {\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"Bundler\",\n    \"strict\": true,\n    \"noEmit\": true\n  },\n  \"contentMappers\": [{ \"package\": \"openapi-import\", \"extensions\": [\".openapi.yaml\", \".openapi.yml\"] }],\n  \"include\": [\".\u002Fsrc\u002F**\u002F*\"]\n}",[17,170,172,177,178,177,186,177,200,177,212,177,224,177,233,177,238,177,274,177,287],{"class":171},"language-json",[35,173,174],{"class":37,"style":38},[35,175,176],{"style":45},"{","\n",[35,179,180,183],{"class":37,"style":38},[35,181,182],{"style":118},"  \"compilerOptions\"",[35,184,185],{"style":45},": {",[35,187,188,191,194,197],{"class":37,"style":38},[35,189,190],{"style":118},"    \"module\"",[35,192,193],{"style":45},": ",[35,195,196],{"style":58},"\"ESNext\"",[35,198,199],{"style":45},",",[35,201,202,205,207,210],{"class":37,"style":38},[35,203,204],{"style":118},"    \"moduleResolution\"",[35,206,193],{"style":45},[35,208,209],{"style":58},"\"Bundler\"",[35,211,199],{"style":45},[35,213,214,217,219,222],{"class":37,"style":38},[35,215,216],{"style":118},"    \"strict\"",[35,218,193],{"style":45},[35,220,221],{"style":118},"true",[35,223,199],{"style":45},[35,225,226,229,231],{"class":37,"style":38},[35,227,228],{"style":118},"    \"noEmit\"",[35,230,193],{"style":45},[35,232,221],{"style":118},[35,234,235],{"class":37,"style":38},[35,236,237],{"style":45},"  },",[35,239,240,243,246,249,251,254,257,260,263,266,268,271],{"class":37,"style":38},[35,241,242],{"style":118},"  \"contentMappers\"",[35,244,245],{"style":45},": [{ ",[35,247,248],{"style":118},"\"package\"",[35,250,193],{"style":45},[35,252,253],{"style":58},"\"openapi-import\"",[35,255,256],{"style":45},", ",[35,258,259],{"style":118},"\"extensions\"",[35,261,262],{"style":45},": [",[35,264,265],{"style":58},"\".openapi.yaml\"",[35,267,256],{"style":45},[35,269,270],{"style":58},"\".openapi.yml\"",[35,272,273],{"style":45},"] }],",[35,275,276,279,281,284],{"class":37,"style":38},[35,277,278],{"style":118},"  \"include\"",[35,280,262],{"style":45},[35,282,283],{"style":58},"\".\u002Fsrc\u002F**\u002F*\"",[35,285,286],{"style":45},"]",[35,288,289],{"class":37,"style":38},[35,290,291],{"style":45},"}",[89,293,295],{"id":294},"run-the-type-check","Run the type check",[97,297,298,316],{"sync":99},[26,299,301],{"language":102,"filename":103,"code":300,"class":30},"pnpm tsc --noEmit --runExternalCode",[17,302,303],{"class":107},[35,304,305,307,310,313],{"class":37,"style":38},[35,306,103],{"style":112},[35,308,309],{"style":58}," tsc",[35,311,312],{"style":118}," --noEmit",[35,314,315],{"style":118}," --runExternalCode",[26,317,319],{"language":102,"filename":131,"code":318,"class":30},"node node_modules\u002Ftypescript\u002Fbin\u002Ftsc --noEmit --runExternalCode",[17,320,321],{"class":107},[35,322,323,326,329,331],{"class":37,"style":38},[35,324,325],{"style":112},"node",[35,327,328],{"style":58}," node_modules\u002Ftypescript\u002Fbin\u002Ftsc",[35,330,312],{"style":118},[35,332,315],{"style":118},[10,334,335,336,338,339,83],{},"With npm, a bare ",[17,337,70],{}," runs TypeScript 6, so call the binary from ",[17,340,341],{},"typescript",[10,343,344,345,347],{},"VS Code only passes ",[17,346,82],{}," in trusted workspaces.",[89,349,351],{"id":350},"choose-the-plugins","Choose the plugins",[10,353,354,355,357],{},"Add a ",[17,356,23],{}," to set plugin options or to run other plugins, and install each plugin it imports:",[26,359,362],{"language":102,"filename":360,"code":361,"class":30},"Terminal","pnpm add -D @kubb\u002Fplugin-ts",[17,363,364],{"class":107},[35,365,366,368,370,372],{"class":37,"style":38},[35,367,103],{"style":112},[35,369,115],{"style":58},[35,371,119],{"style":118},[35,373,374],{"style":58}," @kubb\u002Fplugin-ts",[26,376,378],{"language":28,"filename":23,"code":377,"class":30},"import { pluginTs } from '@kubb\u002Fplugin-ts'\nimport { defineConfig } from 'kubb\u002Fconfig'\n\nexport default defineConfig({\n  output: { path: '.\u002Fsrc\u002Fgen' },\n  plugins: [pluginTs()],\n})",[17,379,380,177,392,177,404,177,406,177,420,177,431,177,442],{"class":33},[35,381,382,384,387,389],{"class":37,"style":38},[35,383,42],{"style":41},[35,385,386],{"style":45}," { pluginTs } ",[35,388,55],{"style":41},[35,390,391],{"style":58}," '@kubb\u002Fplugin-ts'",[35,393,394,396,399,401],{"class":37,"style":38},[35,395,42],{"style":41},[35,397,398],{"style":45}," { defineConfig } ",[35,400,55],{"style":41},[35,402,403],{"style":58}," 'kubb\u002Fconfig'",[35,405],{"class":37,"style":38},[35,407,408,411,414,417],{"class":37,"style":38},[35,409,410],{"style":41},"export",[35,412,413],{"style":41}," default",[35,415,416],{"style":112}," defineConfig",[35,418,419],{"style":45},"({",[35,421,422,425,428],{"class":37,"style":38},[35,423,424],{"style":45},"  output: { path: ",[35,426,427],{"style":58},"'.\u002Fsrc\u002Fgen'",[35,429,430],{"style":45}," },",[35,432,433,436,439],{"class":37,"style":38},[35,434,435],{"style":45},"  plugins: [",[35,437,438],{"style":112},"pluginTs",[35,440,441],{"style":45},"()],",[35,443,444],{"class":37,"style":38},[35,445,446],{"style":45},"})",[10,448,449,450,453,454,457,458,460,461,464],{},"Add ",[17,451,452],{},".\u002Fkubb.config.ts"," to ",[17,455,456],{},"include"," in ",[17,459,159],{},". The mapper finds the config like the CLI does and reloads it when it changes. With several configs, a spec uses the one whose ",[17,462,463],{},"input"," matches it.",[89,466,468],{"id":467},"load-the-spec-at-run-time","Load the spec at run time",[10,470,471,472,475,476,479,480,484,485,488,489,491,492,164],{},"TypeScript does not emit the spec to JavaScript, so values such as ",[17,473,474],{},"petStatusEnum"," need a bundler. Add ",[17,477,478],{},"kubb()"," from any ",[13,481,483],{"href":482},"\u002Fdocs\u002F5.x\u002Fintegrations\u002Foverview#build-tools","build tool integration"," without a ",[17,486,487],{},"config"," option, so it reads the same ",[17,490,23],{}," as ",[17,493,70],{},[26,495,498],{"language":28,"filename":496,"code":497,"class":30},"vite.config.ts","import kubb from 'kubb\u002Fvite'\nimport { defineConfig } from 'vite'\n\nexport default defineConfig({\n  plugins: [kubb()],\n})",[17,499,500,177,512,177,523,177,525,177,535,177,544],{"class":33},[35,501,502,504,507,509],{"class":37,"style":38},[35,503,42],{"style":41},[35,505,506],{"style":45}," kubb ",[35,508,55],{"style":41},[35,510,511],{"style":58}," 'kubb\u002Fvite'",[35,513,514,516,518,520],{"class":37,"style":38},[35,515,42],{"style":41},[35,517,398],{"style":45},[35,519,55],{"style":41},[35,521,522],{"style":58}," 'vite'",[35,524],{"class":37,"style":38},[35,526,527,529,531,533],{"class":37,"style":38},[35,528,410],{"style":41},[35,530,413],{"style":41},[35,532,416],{"style":112},[35,534,419],{"style":45},[35,536,537,539,542],{"class":37,"style":38},[35,538,435],{"style":45},[35,540,541],{"style":112},"kubb",[35,543,441],{"style":45},[35,545,546],{"class":37,"style":38},[35,547,446],{"style":45},[10,549,550],{},"The types and the values then come from the same import:",[26,552,555],{"language":28,"filename":553,"code":554,"class":30},"src\u002Fpets.ts","import { type GetPetByIdPath, type GetPetByIdResponse, petStatusEnum } from '..\u002FpetStore.openapi.yaml'\n\nexport async function getAvailablePet({ petId }: GetPetByIdPath): Promise\u003CGetPetByIdResponse | undefined> {\n  const response = await fetch(`https:\u002F\u002Fpetstore3.swagger.io\u002Fapi\u002Fv3\u002Fpet\u002F${petId}`)\n  const pet: GetPetByIdResponse = await response.json()\n\n  return pet.status === petStatusEnum.available ? pet : undefined\n}",[17,556,557,177,578,177,580,177,631,177,661,177,685,177,687,177,711],{"class":33},[35,558,559,561,563,565,568,570,573,575],{"class":37,"style":38},[35,560,42],{"style":41},[35,562,46],{"style":45},[35,564,49],{"style":41},[35,566,567],{"style":45}," GetPetByIdPath, ",[35,569,49],{"style":41},[35,571,572],{"style":45}," GetPetByIdResponse, petStatusEnum } ",[35,574,55],{"style":41},[35,576,577],{"style":58}," '..\u002FpetStore.openapi.yaml'",[35,579],{"class":37,"style":38},[35,581,582,584,587,590,593,596,600,603,605,608,611,613,616,619,622,625,628],{"class":37,"style":38},[35,583,410],{"style":41},[35,585,586],{"style":41}," async",[35,588,589],{"style":41}," function",[35,591,592],{"style":112}," getAvailablePet",[35,594,595],{"style":45},"({ ",[35,597,599],{"style":598},"color:#E36209;--shiki-dark:#FFAB70","petId",[35,601,602],{"style":45}," }",[35,604,164],{"style":41},[35,606,607],{"style":112}," GetPetByIdPath",[35,609,610],{"style":45},")",[35,612,164],{"style":41},[35,614,615],{"style":112}," Promise",[35,617,618],{"style":45},"\u003C",[35,620,621],{"style":112},"GetPetByIdResponse",[35,623,624],{"style":41}," |",[35,626,627],{"style":118}," undefined",[35,629,630],{"style":45},"> {",[35,632,633,636,639,642,645,648,651,654,656,659],{"class":37,"style":38},[35,634,635],{"style":41},"  const",[35,637,638],{"style":118}," response",[35,640,641],{"style":41}," =",[35,643,644],{"style":41}," await",[35,646,647],{"style":112}," fetch",[35,649,650],{"style":45},"(",[35,652,653],{"style":58},"`https:\u002F\u002Fpetstore3.swagger.io\u002Fapi\u002Fv3\u002Fpet\u002F${",[35,655,599],{"style":45},[35,657,658],{"style":58},"}`",[35,660,610],{"style":45},[35,662,663,665,668,670,673,675,677,680,682],{"class":37,"style":38},[35,664,635],{"style":41},[35,666,667],{"style":118}," pet",[35,669,164],{"style":41},[35,671,672],{"style":112}," GetPetByIdResponse",[35,674,641],{"style":41},[35,676,644],{"style":41},[35,678,679],{"style":45}," response.",[35,681,167],{"style":112},[35,683,684],{"style":45},"()",[35,686],{"class":37,"style":38},[35,688,689,692,695,698,701,704,707,709],{"class":37,"style":38},[35,690,691],{"style":41},"  return",[35,693,694],{"style":45}," pet.status ",[35,696,697],{"style":41},"===",[35,699,700],{"style":45}," petStatusEnum.available ",[35,702,703],{"style":41},"?",[35,705,706],{"style":45}," pet ",[35,708,164],{"style":41},[35,710,627],{"style":118},[35,712,713],{"class":37,"style":38},[35,714,291],{"style":45},[10,716,717,718,720,721,723,724,726],{},"A config with an ",[17,719,463],{}," also writes the generated files at build time. Leave ",[17,722,463],{}," out to import specs only. The bundler reads ",[17,725,23],{}," once, so restart it after you change the config.",[89,728,730],{"id":729},"limits","Limits",[732,733,734,742,748],"ul",{},[735,736,737,738,741],"li",{},"Code a plugin writes to a separate file, such as a bundled client runtime, is not included. Point imports like the client's ",[17,739,740],{},"importPath"," at a package.",[735,743,744,745,747],{},"Files that ",[17,746,23],{}," imports are not watched. Restart the TypeScript server after you change them.",[735,749,750],{},"A changed spec runs a full Kubb build: about 0.4 s for a 10 KB spec and 2.6 s for a 1.4 MB spec.",[89,752,754],{"id":753},"see-also","See also",[732,756,757,762,768,774],{},[735,758,759],{},[13,760,761],{"href":482},"Build tool integrations",[735,763,764],{},[13,765,767],{"href":766},"\u002Fdocs\u002F5.x\u002Fintegrations\u002Fvite","Vite integration",[735,769,770],{},[13,771,773],{"href":772},"\u002Fdocs\u002F5.x\u002Freference\u002Fconfiguration","Configuration reference",[735,775,776,781],{},[13,777,778,780],{"href":15},[17,779,19],{}," on GitHub",", with a working pet-store example",{"title":76,"searchDepth":783,"depth":783,"links":784},5,[785,787,788,789,790,791,792],{"id":91,"depth":786,"text":92},2,{"id":152,"depth":786,"text":153},{"id":294,"depth":786,"text":295},{"id":350,"depth":786,"text":351},{"id":467,"depth":786,"text":468},{"id":729,"depth":786,"text":730},{"id":753,"depth":786,"text":754},"Import a .openapi.yaml spec in TypeScript with openapi-import and get the types and enums your kubb.config.ts generates, without generated files.","md",{"layout":796,"title":5,"description":793,"outline":797,"order":799,"navigation":800},"doc",[786,798],3,15,{"title":19,"icon":801},"i-simple-icons-typescript",{"layout":796,"outline":803},[786,798],{"title":19,"icon":801},"\u002Fdocs\u002F5.x\u002Fintegrations\u002Fopenapi-import",{"title":5,"description":793},{"loc":805},"kubb-labs\u002Fkubb\u002Fdocs\u002F5.x\u002Fintegrations\u002Fopenapi-import.md","docs\u002F5.x\u002Fintegrations\u002Fopenapi-import","wt1BlEncFVaJQbCqv0kFtV53qVRw5uc3zjhhH4nAPsI",false,1792782245826]