{"version":3,"sources":["../../src/components/MainContent.tsx"],"sourcesContent":["import { Suspense, use, useEffect, useMemo } from 'react';\nimport { ErrorBoundary } from 'react-error-boundary';\nimport { navigate, useTinkerableLink } from '../routing';\nimport { FILES_PREFIX, underAppRoot } from '../urlUtils';\nimport { sandboxFs, type SandboxFsPort } from '../fs';\n\nimport { defaultErrorComponent, defaultLoadingComponent } from './defaults';\n\n// Repo-relative candidate paths. These are kept repo-relative because the\n// returned path is reused below to build the redirect URL (which is anchored to\n// `/app` by the file router); only the filesystem existence check is resolved\n// under `APP_ROOT`, since `bundler.fs` is rooted at `/`.\nconst candidates = [\n  '/src/App.tsx',\n  '/src/App.ts',\n  '/src/App.js',\n  '/App.tsx',\n  '/App.ts',\n  '/App.js',\n  '/README.md',\n  '/README.mdx',\n  '/README.html',\n];\n\n// R3-278: the existence probe goes through the SDK's OWN fs surface (`sandboxFs`),\n// not the injected bundler — this was the last direct `bundler.*` read on a\n// PUBLIC component, and the one with no fallback: with no injected bundler\n// (npm-fetched SDK, `vite dev`, pre-boot) the old read THREW. Unavailable fs\n// simply answers `false` for every candidate (the \"no main content file\" path),\n// so the component degrades instead of crashing — the regression case this\n// item exists to close.\nconst fileExists = async (path: string): Promise<[string, boolean]> => {\n  const fs = sandboxFs();\n  if (!fs) return [path, false];\n  const absolute = underAppRoot(path);\n  try {\n    // stat when the port has it, else readFile (dirs reject with EISDIR → false).\n    const stat = (fs.promises as { stat?: Function } | undefined)?.stat ?? (fs as { stat?: Function }).stat;\n    if (typeof stat === 'function') {\n      await stat.call(fs.promises ?? fs, absolute);\n      return [path, true];\n    }\n    const holder = fs.promises ?? (fs as { readFile: NonNullable<SandboxFsPort['readFile']> });\n    await holder.readFile(absolute);\n    return [path, true];\n  } catch {\n    return [path, false];\n  }\n};\n\n// The redirect is a COMMIT-phase effect, not a render-phase call. `navigate()` only\n// posts `urlchange` and relies on the host pushing the resolved href back; calling it\n// during render re-navigated on every re-render, and on a slow host (local dev, a\n// region app booting at `/`) the push-back never settled before the next render —\n// an unbounded \"Redirecting to /files/src/App.tsx\" loop (site-main worked around it\n// by booting region apps past `/`, R3-240). An effect keyed on the target fires once\n// per distinct URL, which is the only thing a redirect should ever do.\nexport const MainContentRedirect = ({ filename }: { filename: string }) => {\n  const url = useTinkerableLink(filename);\n  useEffect(() => {\n    navigate(url);\n  }, [url]);\n  return <>Redirecting to {filename}</>;\n};\n\nexport const MainContentInner = ({\n  candidatesExistPromise,\n}: {\n  candidatesExistPromise: Promise<[string, boolean][]>;\n}) => {\n  const candidatesExist = use(candidatesExistPromise);\n  const filename = candidatesExist.find(([_, exists]) => exists)?.[0];\n  if (!filename) {\n    // todo: show file list\n    throw new Error(`No main content file present`);\n  }\n  return <MainContentRedirect filename={FILES_PREFIX + filename} />;\n};\n\nexport const MainContent = ({\n  LoadingComponent = defaultLoadingComponent,\n  ErrorComponent = defaultErrorComponent,\n}: {\n  LoadingComponent?: typeof defaultLoadingComponent;\n  ErrorComponent?: typeof defaultErrorComponent;\n} = {}) => {\n  // TODO: when to invalidate?\n  const candidatesExistPromise = useMemo(() => Promise.all(candidates.map(fileExists)), []);\n  return (\n    <ErrorBoundary fallbackRender={ErrorComponent}>\n      <Suspense fallback={<LoadingComponent />}>\n        <MainContentInner candidatesExistPromise={candidatesExistPromise} />\n      </Suspense>\n    </ErrorBoundary>\n  );\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA8DS;AA9DT,mBAAkD;AAClD,kCAA8B;AAC9B,qBAA4C;AAC5C,sBAA2C;AAC3C,gBAA8C;AAE9C,sBAA+D;AAM/D,MAAM,aAAa;AAAA,EACjB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AASA,MAAM,aAAa,OAAO,SAA6C;AACrE,QAAM,SAAK,qBAAU;AACrB,MAAI,CAAC,GAAI,QAAO,CAAC,MAAM,KAAK;AAC5B,QAAM,eAAW,8BAAa,IAAI;AAClC,MAAI;AAEF,UAAM,OAAQ,GAAG,UAA8C,QAAS,GAA2B;AACnG,QAAI,OAAO,SAAS,YAAY;AAC9B,YAAM,KAAK,KAAK,GAAG,YAAY,IAAI,QAAQ;AAC3C,aAAO,CAAC,MAAM,IAAI;AAAA,IACpB;AACA,UAAM,SAAS,GAAG,YAAa;AAC/B,UAAM,OAAO,SAAS,QAAQ;AAC9B,WAAO,CAAC,MAAM,IAAI;AAAA,EACpB,QAAQ;AACN,WAAO,CAAC,MAAM,KAAK;AAAA,EACrB;AACF;AASO,MAAM,sBAAsB,CAAC,EAAE,SAAS,MAA4B;AACzE,QAAM,UAAM,kCAAkB,QAAQ;AACtC,8BAAU,MAAM;AACd,iCAAS,GAAG;AAAA,EACd,GAAG,CAAC,GAAG,CAAC;AACR,SAAO,4EAAE;AAAA;AAAA,IAAgB;AAAA,KAAS;AACpC;AAEO,MAAM,mBAAmB,CAAC;AAAA,EAC/B;AACF,MAEM;AACJ,QAAM,sBAAkB,kBAAI,sBAAsB;AAClD,QAAM,WAAW,gBAAgB,KAAK,CAAC,CAAC,GAAG,MAAM,MAAM,MAAM,IAAI,CAAC;AAClE,MAAI,CAAC,UAAU;AAEb,UAAM,IAAI,MAAM,8BAA8B;AAAA,EAChD;AACA,SAAO,4CAAC,uBAAoB,UAAU,+BAAe,UAAU;AACjE;AAEO,MAAM,cAAc,CAAC;AAAA,EAC1B,mBAAmB;AAAA,EACnB,iBAAiB;AACnB,IAGI,CAAC,MAAM;AAET,QAAM,6BAAyB,sBAAQ,MAAM,QAAQ,IAAI,WAAW,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC;AACxF,SACE,4CAAC,6CAAc,gBAAgB,gBAC7B,sDAAC,yBAAS,UAAU,4CAAC,oBAAiB,GACpC,sDAAC,oBAAiB,wBAAgD,GACpE,GACF;AAEJ;","names":[]}