Repository: storybook
Issue: [Bug]: `storybook dev` craches if `StorybookConfig.refs()` returns `undefined`.
Labels: bug,needs triage

### Describe the bug

`storybook dev` craches if `StorybookConfig.refs()` returns `undefined`:

```
PS> yarn workspace storybook start
@storybook/cli v7.0.22

info => Starting manager..
D:\git\github\toolkit\toolkit\node_modules\@storybook\core-common\dist\index.js:19
    `);return typeof framework=="object"?framework.name:framework}async function getRendererName(options){let{renderer}=await options.presets.apply("core",{},options);return renderer||getFrameworkName(options)}function getStorybookConfiguration(storybookScript,shortName,longName){if(!storybookScript)return null;let parts=storybookScript.split(/[\s='"]+/),index=parts.indexOf(longName);return index===-1&&(index=parts.indexOf(shortName)),index===-1?null:parts[index+1]}var import_path8=__toESM(require("path")),import_fs_extra=__toESM(require("fs-extra"));var rendererPackages={"@storybook/react":"react","@storybook/vue":"vue","@storybook/vue3":"vue3","@storybook/angular":"angular","@storybook/html":"html","@storybook/web-components":"web-components","@storybook/polymer":"polymer","@storybook/ember":"ember","@storybook/svelte":"svelte","@storybook/preact":"preact","@storybook/server":"server","storybook-framework-qwik":"qwik","storybook-solidjs":"solid"},frameworkPackages={"@storybook/angular":"angular","@storybook/ember":"ember","@storybook/html-vite":"html-vite","@storybook/html-webpack5":"html-webpack5","@storybook/nextjs":"nextjs","@storybook/preact-vite":"preact-vite","@storybook/preact-webpack5":"preact-webpack5","@storybook/react-vite":"react-vite","@storybook/react-webpack5":"react-webpack5","@storybook/server-webpack5":"server-webpack5","@storybook/svelte-vite":"svelte-vite","@storybook/svelte-webpack5":"svelte-webpack5","@storybook/sveltekit":"sveltekit","@storybook/vue3-vite":"vue3-vite","@storybook/vue3-webpack5":"vue3-webpack5","@storybook/vue-vite":"vue-vite","@storybook/vue-webpack5":"vue-webpack5","@storybook/web-components-vite":"web-components-vite","@storybook/web-components-webpack5":"web-components-webpack5","storybook-framework-qwik":"qwik","storybook-solidjs-vite":"solid"},logger3=console,findDependency=({dependencies,devDependencies,peerDependencies},predicate)=>[Object.entries(dependencies||{}).find(predicate),Object.entries(devDependencies||{}).find(predicate),Object.entries(peerDependencies||{}).find(predicate)],getRendererInfo=packageJson=>{let[dep,devDep,peerDep]=findDependency(packageJson,([key])=>rendererPackages[key]),[pkg,version]=dep||devDep||peerDep||[],renderer=pkg?rendererPackages[pkg]:void 0;return dep&&devDep&&dep[0]===devDep[0]&&logger3.warn(`Found "${dep[0]}" in both "dependencies" and "devDependencies". This is probably a mistake.`),dep&&peerDep&&dep[0]===peerDep[0]&&logger3.warn(`Found "${dep[0]}" in both "dependencies" and "peerDependencies". This is probably a mistake.`),{version,framework:renderer,frameworkPackage:pkg,renderer,rendererPackage:pkg}},validConfigExtensions=["ts","js","tsx","jsx","mjs","cjs"],findConfigFile=(prefix,configDir)=>{let filePrefix=import_path8.default.join(configDir,prefix),extension=validConfigExtensions.find(ext=>import_fs_extra.default.existsSync(`${filePrefix}.${ext}`));return extension?`${filePrefix}.${extension}`:null},getConfigInfo=(packageJson,configDir)=>{var _a;let storybookConfigDir=configDir??".storybook",storybookScript=(_a=packageJson.scripts)==null?void 0:_a.storybook;if(storybookScript&&!configDir){let configParam=getStorybookConfiguration(storybookScript,"-c","--config-dir");configParam&&(storybookConfigDir=configParam)}return{configDir,mainConfig:findConfigFile("main",storybookConfigDir),previewConfig:findConfigFile("preview",storybookConfigDir),managerConfig:findConfigFile("manager",storybookConfigDir)}},getStorybookInfo=(packageJson,configDir)=>{let rendererInfo=getRendererInfo(packageJson),configInfo=getConfigInfo(packageJson,configDir);return{...rendererInfo,...configInfo}};var import_fs_extra2=require("fs-extra"),import_path9=require("path"),import_find_up3=__toESM(require("find-up")),import_node_fetch=__toESM(require("node-fetch")),import_resolve_from2=__toESM(require("resolve-from")),import_node_logger4=require("@storybook/node-logger"),getAutoRefs=async options=>{let location=await(0,import_find_up3.default)("package.json",{cwd:options.configDir});if(!location)return{};let directory=(0,import_path9.dirname)(location),{dependencies=[],devDependencies=[]}=await(0,import_fs_extra2.readJSON)(location)||{},deps=Object.keys({...dependencies,...devDependencies});return(await Promise.all(deps.map(async d=>{try{let l=(0,import_resolve_from2.default)(directory,(0,import_path9.join)(d,"package.json")),{storybook,name,version}=await(0,import_fs_extra2.readJSON)(l)||{};if(storybook!=null&&storybook.url)return{id:name,...storybook,version}}catch(error){if(error.code==="ERR_PACKAGE_PATH_NOT_EXPORTED")return;import_node_logger4.logger.warn(`unable to find package.json for ${d}`);return}}))).filter(Boolean).reduce((acc,cur)=>({...acc,[cur.id]:{id:cur.id.toLowerCase(),url:stripTrailingSlash(cur.url),title:cur.title,version:cur.version}}),{})},checkRef=url=>(0,import_node_fetch.default)(`${url}/iframe.html`).then(async({ok,status})=>{if(ok){if(status!==200)return!1;let data=await(0,import_node_fetch.default)(`${url}/iframe.html`,{headers:{Accept:"application/json"}});if(data.ok&&(await data.json().catch(e=>({}))).loginUrl)return!1}return ok},()=>!1),stripTrailingSlash=url=>url.replace(/\/$/,""),toTitle=input=>{let result=input.replace(/[A-Z]/g,f=>` ${f}`).replace(/[-_][A-Z]/gi,f=>` ${f.toUpperCase()}`).replace(/-/g," ").replace(/_/g," ");return`${result.substring(0,1).toUpperCase()}${result.substring(1)}`.trim()};async function getRefs(options){let refs=await options.presets.apply("refs",await getAutoRefs(options));return Object.entries(refs).forEach(([key,value])=>{if(value.disable){delete refs[key];return}refs[key.toLowerCase()]={...value,id:key.toLowerCase(),title:value.title||toTitle(value.id||key),url:stripTrailingSlash(value.url)}}),await Promise.all(Object.entries(refs).map(async([k,value])=>{let ok=await checkRef(value.url);refs[k]={...value,type:ok?"server-checked":"unknown"}})),refs}var pico=__toESM(require("picomatch"));function globToRegexp(glob2){let regex=pico.makeRe(glob2,{fastpaths:!1,noglobstar:!1,bash:!1});if(!regex.source.startsWith("^"))throw new Error(`Invalid glob: >> ${glob2} >> ${regex}`);return glob2.startsWith("./")?new RegExp(["^\\.",glob2.startsWith("./**")?"":"[\\\\/]",regex.source.substring(1)].join("")):regex}var import_handlebars=__toESM(require("handlebars"));function handlebars(source,data){return import_handlebars.default.compile(source)(data)}var interpolate=(template,bindings)=>Object.entries(bindings).reduce((acc,[k,v])=>{let escapedString=v.replace(/\\/g,"/").replace(/\$/g,"$$$");return acc.replace(new RegExp(`{{${k}}}`,"g"),escapedString)},template);var import_path10=__toESM(require("path"));async function loadMainConfig({configDir=".storybook",noCache=!1}){await validateConfigurationFiles(configDir);let mainJsPath=serverResolve(import_path10.default.resolve(configDir,"main"));return noCache&&mainJsPath&&require.cache[mainJsPath]&&delete require.cache[mainJsPath],serverRequire(mainJsPath)}var import_path11=__toESM(require("path")),import_node_logger5=require("@storybook/node-logger"),import_ts_dedent4=require("ts-dedent");function loadManagerOrAddonsFile({configDir}){let storybookCustomAddonsPath=getInterpretedFile(import_path11.default.resolve(configDir,"addons")),storybookCustomManagerPath=getInterpretedFile(import_path11.default.resolve(configDir,"manager"));if((storybookCustomAddonsPath||storybookCustomManagerPath)&&import_node_logger5.logger.info("=> Loading custom manager config"),storybookCustomAddonsPath&&storybookCustomManagerPath)throw new Error(import_ts_dedent4.dedent`

TypeError: Cannot convert undefined or null to object
    at Function.entries (<anonymous>)
    at getRefs (D:\git\github\toolkit\toolkit\node_modules\@storybook\core-common\dist\index.js:19:5504)

Node.js v18.16.0
PS>
```

And although that's not really a problem, the actual problem is that the StorybookConfig type definition allows returning `undefined`.

I only add refs when building for production:

```ts
const config: StorybookConfig = {
  // [..]
  refs: (config, { configType }) => {
    if (configType === "PRODUCTION") {
      return {
        angular: {
          title: "Angular",
          url: "/angular",
        },
        react: {
          title: "React",
          url: "/react",
        },
      };
    }
  }

  // return {}; // 👈 this is needed
};
```

### To Reproduce

_No response_

### System

```shell
System:
    OS: Windows 10 10.0.22621
    CPU: (16) x64 Intel(R) Core(TM) i7-10700 CPU @ 2.90GHz
  Binaries:
    Node: 18.16.0 - C:\Program Files\nodejs\node.EXE
    Yarn: 3.5.1 - C:\Program Files\nodejs\yarn.CMD
    npm: 9.5.1 - C:\Program Files\nodejs\npm.CMD
  Browsers:
    Edge: Spartan (44.22621.1848.0), Chromium (114.0.1823.51)
```


### Additional context

_No response_