{"version":3,"sources":["../../src/api/get-props.ts"],"names":["importPage","pageRoutes","RadixRouter","fs","NS","IS_WINDOWS","SLASH","ROOT_DIR","router","createRouter","handleGetProps","req","res","pilot","_a","_b","context","defaultLocale","locale","locales","path","route","getPropsType","cache","getCache","props","radixRouter","cleanPath","localePrefix","e"],"mappings":"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","sourcesContent":["/**\n * © 2022 WavePlay <dev@waveplay.com>\n */\nimport { importPage, pageRoutes } from '../_generated/pages'\nimport { RadixRouter } from '../client/core/radix-router'\nimport fs from 'fs-extra'\nimport type { Pilot } from '../client/core/pilot'\nimport type { GetStaticPropsResult, NextApiRequest, NextApiResponse } from 'next/types'\n\n// Namespace used for validating prop cache\nconst NS = '__pilot'\n\n// Make sure to use the correct slash for the platform\nconst IS_WINDOWS = /^win/.test(process.platform)\nconst SLASH = IS_WINDOWS ? '\\\\' : '/'\n\n// Root level directory of the project\nconst ROOT_DIR = process.cwd() + SLASH + '.pilot'\n\n// Create router using generated routes\nconst router = createRouter()\n\ntype GetPropsContext = {\n\tdefaultLocale?: string\n\tlocale?: string\n\tlocales?: string[]\n\tpath: string\n}\n\nexport async function handleGetProps(req: NextApiRequest, res: NextApiResponse, pilot: Pilot): Promise<void> {\n\tconst context = req.body as GetPropsContext\n\tconst { defaultLocale, locale, locales, path } = context\n\n\t// Validate path\n\tif (!path) {\n\t\treturn res.status(400).json({\n\t\t\terror: 'Invalid path. Make sure you are sending a \"path\" property in the request body.'\n\t\t})\n\t}\n\n\t// Find route\n\tconst route = router.find(path, { pilot })\n\tif (!route) {\n\t\treturn res.status(404).json({\n\t\t\terror: 'Page not found: ' + path\n\t\t})\n\t}\n\n\t// This API shouldn't even be called for pages that don't have getProps\n\tconst { getPropsType } = route\n\tif (!getPropsType) {\n\t\treturn res.status(400).json({\n\t\t\terror: 'Page does not have getProps: ' + path\n\t\t})\n\t}\n\n\t// Lookup cached props if this is a static page and return as long as it's not stale\n\tconst cache = await getCache(context, pilot)\n\tif (cache.status === 'HIT') {\n\t\treturn res.status(200).json(cache.props)\n\t}\n\n\t// Load props for page\n\tconst page = await importPage(route.path)\n\tconst props = await page[getPropsType]({\n\t\tdefaultLocale,\n\t\tlocale,\n\t\tlocales,\n\t\treq,\n\t\tres,\n\t\tparams: route.params ?? {},\n\t\tquery: route.query ?? {},\n\t\tresolvedUrl: path\n\t})\n\tpilot.log('debug', `API: Loaded props for ${path}: ${JSON.stringify(props)}`)\n\n\t// Cache props if this is a static page\n\tif (getPropsType === 'getStaticProps' && props) {\n\t\tawait fs.outputFile(\n\t\t\tcache.file,\n\t\t\tJSON.stringify(\n\t\t\t\t{\n\t\t\t\t\t...props,\n\t\t\t\t\t[NS]: {\n\t\t\t\t\t\tupdatedAt: Date.now()\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tundefined,\n\t\t\t\t2\n\t\t\t)\n\t\t)\n\t}\n\n\tres.status(200).json(props)\n}\n\nfunction createRouter() {\n\tconst radixRouter = new RadixRouter()\n\n\tfor (const route of pageRoutes) {\n\t\tradixRouter.addRoute({\n\t\t\tgetPropsType: route.getPropsType,\n\t\t\tpath: route.path,\n\t\t\tComponent: null\n\t\t})\n\t}\n\n\treturn radixRouter\n}\n\ninterface Cache {\n\tprops?: GetStaticPropsResult<unknown>\n\tfile: string\n\tstatus?: 'HIT' | 'MISS' | 'STALE'\n}\n\ntype CachedProps = GetStaticPropsResult<unknown> & {\n\t__pilot?: {\n\t\tupdatedAt?: number\n\t}\n}\n\nasync function getCache(context: GetPropsContext, pilot: Pilot): Promise<Cache> {\n\tconst { locale, path } = context\n\n\t// Create cache entry with locale prefix and without query params\n\tconst cleanPath = path.includes('?') ? path.split('?')[0] : path\n\tconst localePrefix = locale ? SLASH + locale : ''\n\tconst cache: Cache = {\n\t\tfile: ROOT_DIR + `${SLASH}cache${SLASH}static${localePrefix}${cleanPath}.json`,\n\t\tstatus: 'MISS'\n\t}\n\n\ttry {\n\t\t// Return with \"MISS\" if cache file doesn't exist\n\t\tif (!fs.existsSync(cache.file)) {\n\t\t\treturn cache\n\t\t}\n\n\t\t// Read cache file and return with \"MISS\" if it's invalid\n\t\tconst props: CachedProps = await fs.readJSON(cache.file)\n\t\tif (!props) {\n\t\t\treturn cache\n\t\t}\n\n\t\t// Check if cache is stale\n\t\tif (typeof props.revalidate === 'number') {\n\t\t\tcache.status =\n\t\t\t\tprops[NS]?.updatedAt && props[NS].updatedAt < Date.now() - props.revalidate * 1000 ? 'STALE' : 'HIT'\n\t\t} else if (!props.revalidate) {\n\t\t\tcache.status = 'HIT'\n\t\t}\n\n\t\t// Remove namespace before adding props data to cache\n\t\tdelete props[NS]\n\t\tcache.props = props\n\t} catch (e) {\n\t\tpilot.log('error', `API: Error loading cache file:`, cache.file, e)\n\t} finally {\n\t\tpilot.log('info', `API: Cache ${cache.status}:`, path)\n\t\treturn cache\n\t}\n}\n"]}