UNPKG

vike

Version:

The Framework *You* Control - Next.js & Nuxt alternative for unprecedented flexibility and dependability.

254 lines (253 loc) 10.4 kB
export { getPageConfigUserFriendly }; export { getPageConfigUserFriendly_oldDesign }; export { getPageConfigGlobalUserFriendly }; import { assertDefaultExports, forbiddenDefaultExports } from '../getPageFiles/assert_exports_old_design.js'; import { getConfigDefinedAtOptional, getDefinedAtString } from './getConfigDefinedAt.js'; import { getConfigValueFilePathToShowToUser } from './helpers.js'; import { assert, isObject, assertWarning, assertUsage, makeLast, isBrowser, isScriptFile, isTemplateFile } from '../utils.js'; import pc from '@brillout/picocolors'; function getPageConfigUserFriendly(pageConfigGlobalValues, pageConfig, pageConfigValues) { const pageConfigUserFriendly = getPageConfigUserFriendly_public({ pageConfigGlobalValues, pageConfigValues }); let page; if (!pageConfig.isErrorPage) { const route = pageConfigUserFriendly.config.route ?? pageConfig.routeFilesystem.routeString; page = { ...pageConfigUserFriendly, route }; } else { page = { ...pageConfigUserFriendly, isErrorPage: true }; } return [pageConfig.pageId, page]; } function getPageConfigUserFriendly_public({ pageConfigGlobalValues, pageConfigValues }) { const pageConfigUserFriendly = getPageConfigUserFriendly_base({ pageConfigGlobalValues, pageConfigValues }); return getPublicCopy(pageConfigUserFriendly); } function getPublicCopy(pageConfigUserFriendly) { const p = pageConfigUserFriendly; return { config: p.config, _source: p.source, _sources: p.sources, _from: p.from }; } function getPageConfigUserFriendly_base({ pageConfigGlobalValues, pageConfigValues }) { const configValues = { ...pageConfigGlobalValues, ...pageConfigValues }; return getPageConfigUserFriendly_V1Design({ configValues }); } function getPageConfigGlobalUserFriendly({ pageConfigGlobalValues }) { const pageConfigGlobalUserFriendly = getPageConfigUserFriendly_V1Design({ configValues: pageConfigGlobalValues }); return getPublicCopy(pageConfigGlobalUserFriendly); } function getPageConfigUserFriendly_oldDesign(pageFiles, pageConfig, pageConfigGlobal) { const config = {}; const configEntries = {}; // TODO/v1-release: remove const exportsAll = {}; // TODO/v1-release: remove // V0.4 design // TODO/v1-release: remove pageFiles.forEach((pageFile) => { const exportValues = getExportValues(pageFile); exportValues.forEach(({ exportName, exportValue, isFromDefaultExport }) => { assert(exportName !== 'default'); exportsAll[exportName] = exportsAll[exportName] ?? []; exportsAll[exportName].push({ exportValue, exportSource: `${pageFile.filePath} > ${isFromDefaultExport ? `\`export default { ${exportName} }\`` : `\`export { ${exportName} }\``}`, filePath: pageFile.filePath, _filePath: pageFile.filePath, // TODO/next-major-release: remove _fileType: pageFile.fileType, _isFromDefaultExport: isFromDefaultExport }); }); }); let source; let sources; let from; if (pageConfig) { const res = getPageConfigUserFriendly_base({ pageConfigGlobalValues: pageConfigGlobal.configValues, pageConfigValues: pageConfig.configValues }); source = res.source; sources = res.sources; from = res.from; Object.assign(config, res.config); Object.assign(configEntries, res.configEntries); Object.assign(exportsAll, res.exportsAll); } else { source = {}; sources = {}; from = { configsStandard: {}, configsCumulative: {}, configsComputed: {} }; } const pageExports = createObjectWithDeprecationWarning(); const exports = {}; Object.entries(exportsAll).forEach(([exportName, values]) => { values.forEach(({ exportValue, _fileType, _isFromDefaultExport }) => { exports[exportName] = exports[exportName] ?? exportValue; // Legacy pageContext.pageExports if (_fileType === '.page' && !_isFromDefaultExport) { if (!(exportName in pageExports)) { pageExports[exportName] = exportValue; } } }); }); assert(!('default' in exports)); assert(!('default' in exportsAll)); const pageContextExports = { config: config, from, source, sources, // TODO/eventually: deprecate/remove every prop below configEntries, exports, exportsAll, pageExports }; return pageContextExports; } // V1 design function getPageConfigUserFriendly_V1Design(pageConfig) { const config = {}; const configEntries = {}; const exportsAll = {}; const source = {}; const sources = {}; const from = { configsStandard: {}, configsCumulative: {}, configsComputed: {} }; const addSrc = (src, configName) => { source[configName] = src; sources[configName] ?? (sources[configName] = []); sources[configName].push(src); }; Object.entries(pageConfig.configValues).forEach(([configName, configValue]) => { const { value } = configValue; const configValueFilePathToShowToUser = getConfigValueFilePathToShowToUser(configValue.definedAtData); const configDefinedAt = getConfigDefinedAtOptional('Config', configName, configValue.definedAtData); config[configName] = config[configName] ?? value; configEntries[configName] = configEntries[configName] ?? []; // Currently each configName has only one entry. Adding an entry for each overriden config value isn't implemented yet. (This is an isomorphic file and it isn't clear whether this can/should be implemented on the client-side. We should load a minimum amount of code on the client-side.) assert(configEntries[configName].length === 0); configEntries[configName].push({ configValue: value, configDefinedAt, configDefinedByFile: configValueFilePathToShowToUser }); if (configValue.type === 'standard') { const src = { type: 'configsStandard', value: configValue.value, definedAt: getDefinedAtString(configValue.definedAtData, configName) }; addSrc(src, configName); from.configsStandard[configName] = src; } if (configValue.type === 'cumulative') { const src = { type: 'configsCumulative', values: configValue.value.map((value, i) => { const definedAtFile = configValue.definedAtData[i]; assert(definedAtFile); const definedAt = getDefinedAtString(definedAtFile, configName); return { value, definedAt }; }) }; addSrc(src, configName); from.configsCumulative[configName] = src; } if (configValue.type === 'computed') { const src = { type: 'configsComputed', value: configValue.value }; addSrc(src, configName); from.configsComputed[configName] = src; } // TODO/v1-release: remove const exportName = configName; exportsAll[exportName] = exportsAll[exportName] ?? []; exportsAll[exportName].push({ exportValue: value, exportSource: configDefinedAt, filePath: configValueFilePathToShowToUser, _filePath: configValueFilePathToShowToUser, _fileType: null, _isFromDefaultExport: null }); }); return { config: config, configEntries, exportsAll, source, sources, from }; } function getExportValues(pageFile) { const { filePath, fileExports } = pageFile; assert(fileExports); // assume pageFile.loadFile() was called assert(isScriptFile(filePath)); const exportValues = []; Object.entries(fileExports) .sort(makeLast(([exportName]) => exportName === 'default')) // `export { bla }` should override `export default { bla }` .forEach(([exportName, exportValue]) => { let isFromDefaultExport = exportName === 'default'; if (isFromDefaultExport) { if (isTemplateFile(filePath)) { exportName = 'Page'; } else { assertUsage(isObject(exportValue), `The ${pc.cyan('export default')} of ${filePath} should be an object.`); Object.entries(exportValue).forEach(([defaultExportName, defaultExportValue]) => { assertDefaultExports(defaultExportName, filePath); exportValues.push({ exportName: defaultExportName, exportValue: defaultExportValue, isFromDefaultExport }); }); return; } } exportValues.push({ exportName, exportValue, isFromDefaultExport }); }); exportValues.forEach(({ exportName, isFromDefaultExport }) => { assert(!(isFromDefaultExport && forbiddenDefaultExports.includes(exportName))); }); return exportValues; } // TODO/v1-release: remove function createObjectWithDeprecationWarning() { return new Proxy({}, { get(...args) { // We only show the warning in Node.js because when using Client Routing Vue integration uses `Object.assign(pageContextReactive, pageContext)` which will wrongully trigger the warning. There is no cross-browser way to catch whether the property accessor was initiated by an `Object.assign()` call. if (!isBrowser()) { assertWarning(false, '`pageContext.pageExports` is outdated. Use `pageContext.exports` instead, see https://vike.dev/exports', { onlyOnce: true, showStackTrace: true }); } return Reflect.get(...args); } }); }