vike 0.4.159 → 0.4.160-commit-30d535e
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/node/plugin/index.js +20 -1
- package/dist/cjs/node/plugin/plugins/autoFullBuild.js +2 -2
- package/dist/cjs/node/plugin/plugins/buildConfig.js +9 -0
- package/dist/cjs/node/plugin/plugins/commonConfig.js +1 -1
- package/dist/cjs/node/plugin/plugins/config/stemUtils.js +1 -1
- package/dist/cjs/node/plugin/plugins/devConfig/index.js +1 -1
- package/dist/cjs/node/plugin/plugins/importBuild/index.js +1 -1
- package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getConfigFileExport.js +18 -0
- package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/crawlPlusFiles.js +1 -5
- package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/filesystemRouting.js +28 -46
- package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/loadFileAtConfigTime.js +129 -0
- package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/resolveFilePath.js +33 -0
- package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/resolveImportPath.js +139 -0
- package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/{replaceImportStatements.js → getVikeConfig/transformFileImports.js} +44 -13
- package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/{transpileAndExecuteFile.js → getVikeConfig/transpileAndExecuteFile.js} +105 -78
- package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +201 -382
- package/dist/cjs/node/plugin/plugins/previewConfig.js +1 -1
- package/dist/cjs/node/plugin/shared/getHttpRequestAsyncStore.js +1 -1
- package/dist/cjs/node/plugin/shared/loggerNotProd/log.js +3 -3
- package/dist/cjs/node/plugin/shared/loggerNotProd.js +1 -1
- package/dist/cjs/node/plugin/utils.js +1 -2
- package/dist/cjs/node/prerender/runPrerender.js +12 -5
- package/dist/cjs/node/runtime/globalContext.js +7 -3
- package/dist/cjs/node/runtime/html/injectAssets/getHtmlTags.js +2 -2
- package/dist/cjs/node/runtime/html/renderHtml.js +1 -1
- package/dist/cjs/node/runtime/html/stream.js +2 -2
- package/dist/cjs/node/runtime/renderPage/executeOnRenderHtmlHook.js +2 -2
- package/dist/cjs/node/runtime/renderPage/getHttpResponseBody.js +1 -1
- package/dist/cjs/node/runtime/renderPage/loadUserFilesServerSide.js +1 -1
- package/dist/cjs/node/runtime/renderPage/{logHintForCjsEsmError.js → logErrorHint.js} +81 -43
- package/dist/cjs/node/runtime/renderPage/loggerProd.js +3 -3
- package/dist/cjs/node/runtime/utils.js +1 -1
- package/dist/cjs/shared/page-configs/assertPlusFileExport.js +44 -0
- package/dist/cjs/shared/page-configs/serialize/parseConfigValuesImported.js +54 -27
- package/dist/cjs/shared/route/abort.js +1 -1
- package/dist/cjs/shared/route/executeGuardHook.js +3 -2
- package/dist/cjs/shared/utils.js +0 -1
- package/dist/cjs/utils/assert.js +5 -6
- package/dist/cjs/utils/assertIsNotProductionRuntime.js +35 -17
- package/dist/cjs/utils/{findUserPackageJsonPath.js → findFile.js} +11 -8
- package/dist/cjs/utils/nodeEnv.js +33 -1
- package/dist/cjs/utils/objectKeys.js +19 -3
- package/dist/cjs/utils/projectInfo.js +2 -4
- package/dist/cjs/utils/sorter.js +62 -1
- package/dist/esm/node/plugin/index.js +21 -2
- package/dist/esm/node/plugin/plugins/autoFullBuild.js +2 -2
- package/dist/esm/node/plugin/plugins/buildConfig.js +10 -1
- package/dist/esm/node/plugin/plugins/commonConfig.js +2 -2
- package/dist/esm/node/plugin/plugins/config/stemUtils.js +2 -2
- package/dist/esm/node/plugin/plugins/devConfig/index.js +2 -2
- package/dist/esm/node/plugin/plugins/importBuild/index.js +2 -2
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getConfigFileExport.d.ts +2 -0
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getConfigFileExport.js +12 -0
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/configDefinitionsBuiltIn.d.ts +8 -1
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/crawlPlusFiles.d.ts +0 -1
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/crawlPlusFiles.js +1 -5
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/filesystemRouting.d.ts +39 -12
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/filesystemRouting.js +29 -47
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/loadFileAtConfigTime.d.ts +21 -0
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/loadFileAtConfigTime.js +123 -0
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/resolveFilePath.d.ts +5 -0
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/resolveFilePath.js +27 -0
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/resolveImportPath.d.ts +12 -0
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/resolveImportPath.js +133 -0
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/{replaceImportStatements.d.ts → getVikeConfig/transformFileImports.d.ts} +5 -5
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/{replaceImportStatements.js → getVikeConfig/transformFileImports.js} +43 -12
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/{transpileAndExecuteFile.d.ts → getVikeConfig/transpileAndExecuteFile.d.ts} +3 -3
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/{transpileAndExecuteFile.js → getVikeConfig/transpileAndExecuteFile.js} +105 -78
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.d.ts +16 -1
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +199 -380
- package/dist/esm/node/plugin/plugins/previewConfig.js +2 -2
- package/dist/esm/node/plugin/shared/getHttpRequestAsyncStore.js +1 -1
- package/dist/esm/node/plugin/shared/loggerNotProd/log.js +3 -3
- package/dist/esm/node/plugin/shared/loggerNotProd.js +1 -1
- package/dist/esm/node/plugin/utils.d.ts +1 -2
- package/dist/esm/node/plugin/utils.js +1 -2
- package/dist/esm/node/prerender/runPrerender.js +13 -6
- package/dist/esm/node/runtime/globalContext.js +8 -4
- package/dist/esm/node/runtime/html/injectAssets/getHtmlTags.js +2 -2
- package/dist/esm/node/runtime/html/renderHtml.js +1 -1
- package/dist/esm/node/runtime/html/stream.js +2 -2
- package/dist/esm/node/runtime/renderPage/executeOnRenderHtmlHook.js +2 -2
- package/dist/esm/node/runtime/renderPage/getHttpResponseBody.js +1 -1
- package/dist/esm/node/runtime/renderPage/loadUserFilesServerSide.js +1 -1
- package/dist/esm/node/runtime/renderPage/logErrorHint.d.ts +8 -0
- package/dist/esm/node/runtime/renderPage/{logHintForCjsEsmError.js → logErrorHint.js} +80 -42
- package/dist/esm/node/runtime/renderPage/loggerProd.js +3 -3
- package/dist/esm/node/runtime/utils.d.ts +1 -1
- package/dist/esm/node/runtime/utils.js +1 -1
- package/dist/esm/shared/page-configs/Config.d.ts +1 -1
- package/dist/esm/shared/page-configs/PageConfig.d.ts +6 -0
- package/dist/esm/shared/page-configs/assertPlusFileExport.d.ts +2 -0
- package/dist/esm/shared/page-configs/assertPlusFileExport.js +38 -0
- package/dist/esm/shared/page-configs/serialize/parseConfigValuesImported.js +54 -27
- package/dist/esm/shared/route/abort.js +2 -2
- package/dist/esm/shared/route/executeGuardHook.js +3 -2
- package/dist/esm/shared/utils.d.ts +0 -1
- package/dist/esm/shared/utils.js +0 -1
- package/dist/esm/utils/assert.js +5 -6
- package/dist/esm/utils/assertIsNotProductionRuntime.d.ts +8 -6
- package/dist/esm/utils/assertIsNotProductionRuntime.js +35 -17
- package/dist/esm/utils/debug.d.ts +1 -1
- package/dist/esm/utils/findFile.d.ts +3 -0
- package/dist/esm/utils/findFile.js +21 -0
- package/dist/esm/utils/nodeEnv.d.ts +6 -0
- package/dist/esm/utils/nodeEnv.js +29 -0
- package/dist/esm/utils/objectKeys.d.ts +10 -1
- package/dist/esm/utils/objectKeys.js +20 -3
- package/dist/esm/utils/projectInfo.d.ts +2 -8
- package/dist/esm/utils/projectInfo.js +2 -4
- package/dist/esm/utils/sorter.d.ts +59 -0
- package/dist/esm/utils/sorter.js +61 -0
- package/package.json +1 -1
- package/dist/cjs/shared/page-configs/assertExports.js +0 -67
- package/dist/cjs/utils/objectEntries.js +0 -8
- package/dist/esm/node/runtime/renderPage/logHintForCjsEsmError.d.ts +0 -13
- package/dist/esm/shared/page-configs/assertExports.d.ts +0 -6
- package/dist/esm/shared/page-configs/assertExports.js +0 -61
- package/dist/esm/utils/findUserPackageJsonPath.d.ts +0 -2
- package/dist/esm/utils/findUserPackageJsonPath.js +0 -18
- package/dist/esm/utils/objectEntries.d.ts +0 -4
- package/dist/esm/utils/objectEntries.js +0 -5
- /package/dist/cjs/node/runtime/renderPage/{logHintForCjsEsmError → logErrorHint}/errors.js +0 -0
- /package/dist/esm/node/runtime/renderPage/{logHintForCjsEsmError → logErrorHint}/errors.d.ts +0 -0
- /package/dist/esm/node/runtime/renderPage/{logHintForCjsEsmError → logErrorHint}/errors.js +0 -0
|
@@ -2,31 +2,32 @@ export { getVikeConfig };
|
|
|
2
2
|
export { reloadVikeConfig };
|
|
3
3
|
export { vikeConfigDependencies };
|
|
4
4
|
export { isVikeConfigFile };
|
|
5
|
-
import { assertPosixPath, assert, isObject, assertUsage, assertWarning, objectEntries, hasProp, arrayIncludes, assertIsNotProductionRuntime, getMostSimilar,
|
|
5
|
+
import { assertPosixPath, assert, isObject, assertUsage, assertWarning, objectEntries, hasProp, arrayIncludes, assertIsNotProductionRuntime, getMostSimilar, joinEnglish, lowerFirst, mergeCumulativeValues, getOutDirs, assertKeys, objectKeys, objectFromEntries, makeFirst, isNpmPackageImport, reverse } from '../../../utils.js';
|
|
6
6
|
import path from 'path';
|
|
7
7
|
import { configDefinitionsBuiltIn, configDefinitionsBuiltInGlobal } from './getVikeConfig/configDefinitionsBuiltIn.js';
|
|
8
8
|
import { getLocationId, getFilesystemRouteString, getFilesystemRouteDefinedBy, isInherited, sortAfterInheritanceOrder, isGlobalLocation, applyFilesystemRoutingRootEffect } from './getVikeConfig/filesystemRouting.js';
|
|
9
|
-
import { isTmpFile
|
|
10
|
-
import { parseImportData } from './replaceImportStatements.js';
|
|
9
|
+
import { isTmpFile } from './getVikeConfig/transpileAndExecuteFile.js';
|
|
11
10
|
import { isConfigInvalid, isConfigInvalid_set } from '../../../../runtime/renderPage/isConfigInvalid.js';
|
|
12
11
|
import { getViteDevServer } from '../../../../runtime/globalContext.js';
|
|
13
12
|
import { logConfigError, logConfigErrorRecover } from '../../../shared/loggerNotProd.js';
|
|
14
13
|
import { removeSuperfluousViteLog_enable, removeSuperfluousViteLog_disable } from '../../../shared/loggerVite/removeSuperfluousViteLog.js';
|
|
15
14
|
import pc from '@brillout/picocolors';
|
|
16
15
|
import { getConfigDefinedAtString } from '../../../../../shared/page-configs/helpers.js';
|
|
17
|
-
import { assertExportsOfConfigFile, assertExportsOfValueFile } from '../../../../../shared/page-configs/assertExports.js';
|
|
18
16
|
import { getConfigVike } from '../../../../shared/getConfigVike.js';
|
|
19
17
|
import { assertConfigValueIsSerializable } from './getConfigValuesSerialized.js';
|
|
20
18
|
import { crawlPlusFiles } from './getVikeConfig/crawlPlusFiles.js';
|
|
19
|
+
import { getConfigFileExport } from './getConfigFileExport.js';
|
|
20
|
+
import { loadConfigFile, loadImportedFile, loadValueFile } from './getVikeConfig/loadFileAtConfigTime.js';
|
|
21
|
+
import { clearFilesEnvMap, resolveImport } from './getVikeConfig/resolveImportPath.js';
|
|
22
|
+
import { resolveFilePathRelativeToUserRootDir } from './getVikeConfig/resolveFilePath.js';
|
|
21
23
|
assertIsNotProductionRuntime();
|
|
22
24
|
let devServerIsCorrupt = false;
|
|
23
25
|
let wasConfigInvalid = null;
|
|
24
26
|
let vikeConfigPromise = null;
|
|
25
27
|
const vikeConfigDependencies = new Set();
|
|
26
|
-
const filesEnv = new Map();
|
|
27
28
|
function reloadVikeConfig(userRootDir, outDirRoot, extensions) {
|
|
28
29
|
vikeConfigDependencies.clear();
|
|
29
|
-
|
|
30
|
+
clearFilesEnvMap();
|
|
30
31
|
vikeConfigPromise = loadVikeConfig_withErrorHandling(userRootDir, outDirRoot, true, extensions, true);
|
|
31
32
|
handleReloadSideEffects();
|
|
32
33
|
}
|
|
@@ -82,108 +83,98 @@ async function loadInterfaceFiles(userRootDir, outDirRoot, isDev, extensions) {
|
|
|
82
83
|
}
|
|
83
84
|
});
|
|
84
85
|
let interfaceFilesByLocationId = {};
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
const interfaceFile = getInterfaceFileFromConfigFile(
|
|
94
|
-
interfaceFilesByLocationId[locationId].push(interfaceFile);
|
|
95
|
-
});
|
|
96
|
-
}));
|
|
97
|
-
// Value files
|
|
98
|
-
await Promise.all(valueFiles.map(async (filePath) => {
|
|
99
|
-
const configName = getConfigName(filePath.filePathAbsoluteVite);
|
|
100
|
-
assert(configName);
|
|
101
|
-
const interfaceFile = {
|
|
102
|
-
filePath,
|
|
103
|
-
configMap: {
|
|
104
|
-
[configName]: {}
|
|
105
|
-
},
|
|
106
|
-
isConfigFile: false,
|
|
107
|
-
isValueFile: true,
|
|
108
|
-
configName
|
|
109
|
-
};
|
|
110
|
-
{
|
|
111
|
-
// We don't have access to the custom config definitions defined by the user yet.
|
|
112
|
-
// - If `configDef` is `undefined` => we load the file +{configName}.js later.
|
|
113
|
-
// - We already need to load +meta.js here (to get the custom config definitions defined by the user)
|
|
114
|
-
const configDef = getConfigDefinitionOptional(configDefinitionsBuiltIn, configName);
|
|
115
|
-
if (configDef && isConfigEnv(configDef, configName)) {
|
|
116
|
-
await loadValueFile(interfaceFile, configName, userRootDir);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
{
|
|
120
|
-
const locationId = getLocationId(filePath.filePathAbsoluteVite);
|
|
86
|
+
await Promise.all([
|
|
87
|
+
// Config files
|
|
88
|
+
...configFiles.map(async (filePath) => {
|
|
89
|
+
const { filePathRelativeToUserRootDir } = filePath;
|
|
90
|
+
assert(filePathRelativeToUserRootDir);
|
|
91
|
+
const { configFile, extendsConfigs } = await loadConfigFile(filePath, userRootDir, [], false);
|
|
92
|
+
assert(filePath.filePathRelativeToUserRootDir);
|
|
93
|
+
const locationId = getLocationId(filePathRelativeToUserRootDir);
|
|
94
|
+
const interfaceFile = getInterfaceFileFromConfigFile(configFile, false, locationId);
|
|
121
95
|
interfaceFilesByLocationId[locationId] = interfaceFilesByLocationId[locationId] ?? [];
|
|
122
96
|
interfaceFilesByLocationId[locationId].push(interfaceFile);
|
|
123
|
-
|
|
124
|
-
|
|
97
|
+
extendsConfigs.forEach((extendsConfig) => {
|
|
98
|
+
/* We purposely use the same locationId because the Vike extension's config should only apply to where it's being extended from, for example:
|
|
99
|
+
```js
|
|
100
|
+
// /pages/admin/+config.h.js
|
|
101
|
+
|
|
102
|
+
import vikeVue from 'vike-vue/config'
|
|
103
|
+
// Should only apply to /pages/admin/**
|
|
104
|
+
export default { extends: [vikeVue] }
|
|
105
|
+
```
|
|
106
|
+
```js
|
|
107
|
+
// /pages/marketing/+config.h.js
|
|
108
|
+
|
|
109
|
+
import vikeReact from 'vike-react/config'
|
|
110
|
+
// Should only apply to /pages/marketing/**
|
|
111
|
+
export default { extends: [vikeReact] }
|
|
112
|
+
```
|
|
113
|
+
*/
|
|
114
|
+
const interfaceFile = getInterfaceFileFromConfigFile(extendsConfig, true, locationId);
|
|
115
|
+
interfaceFilesByLocationId[locationId].push(interfaceFile);
|
|
116
|
+
});
|
|
117
|
+
}),
|
|
118
|
+
// Value files
|
|
119
|
+
...valueFiles.map(async (filePath) => {
|
|
120
|
+
const { filePathRelativeToUserRootDir } = filePath;
|
|
121
|
+
assert(filePathRelativeToUserRootDir);
|
|
122
|
+
const configName = getConfigName(filePathRelativeToUserRootDir);
|
|
123
|
+
assert(configName);
|
|
124
|
+
const locationId = getLocationId(filePathRelativeToUserRootDir);
|
|
125
|
+
const interfaceFile = {
|
|
126
|
+
locationId,
|
|
127
|
+
filePath,
|
|
128
|
+
fileExportsByConfigName: {
|
|
129
|
+
[configName]: {}
|
|
130
|
+
},
|
|
131
|
+
isConfigFile: false,
|
|
132
|
+
isValueFile: true,
|
|
133
|
+
configName
|
|
134
|
+
};
|
|
135
|
+
{
|
|
136
|
+
// We don't have access to the custom config definitions defined by the user yet.
|
|
137
|
+
// - If `configDef` is `undefined` => we load the file +{configName}.js later.
|
|
138
|
+
// - We already need to load +meta.js here (to get the custom config definitions defined by the user)
|
|
139
|
+
const configDef = getConfigDefinitionOptional(configDefinitionsBuiltIn, configName);
|
|
140
|
+
if (configDef && isConfigEnv(configDef, configName)) {
|
|
141
|
+
await loadValueFile(interfaceFile, configName, userRootDir);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
{
|
|
145
|
+
interfaceFilesByLocationId[locationId] = interfaceFilesByLocationId[locationId] ?? [];
|
|
146
|
+
interfaceFilesByLocationId[locationId].push(interfaceFile);
|
|
147
|
+
}
|
|
148
|
+
})
|
|
149
|
+
]);
|
|
125
150
|
assertAllConfigsAreKnown(interfaceFilesByLocationId);
|
|
126
151
|
return interfaceFilesByLocationId;
|
|
127
152
|
}
|
|
128
|
-
function
|
|
129
|
-
const configDef = configDefinitionsRelevant[configName];
|
|
130
|
-
assertConfigExists(configName, Object.keys(configDefinitionsRelevant), filePathToShowToUser);
|
|
131
|
-
assert(configDef);
|
|
132
|
-
return configDef;
|
|
133
|
-
}
|
|
134
|
-
function getConfigDefinitionOptional(configDefinitions, configName) {
|
|
135
|
-
return configDefinitions[configName] ?? null;
|
|
136
|
-
}
|
|
137
|
-
async function loadValueFile(interfaceValueFile, configName, userRootDir) {
|
|
138
|
-
const { fileExports } = await transpileAndExecuteFile(interfaceValueFile.filePath, true, userRootDir);
|
|
139
|
-
const { filePathToShowToUser } = interfaceValueFile.filePath;
|
|
140
|
-
assertExportsOfValueFile(fileExports, filePathToShowToUser, configName);
|
|
141
|
-
Object.entries(fileExports).forEach(([exportName, configValue]) => {
|
|
142
|
-
const configName_ = exportName === 'default' ? configName : exportName;
|
|
143
|
-
interfaceValueFile.configMap[configName_] = { configValue };
|
|
144
|
-
});
|
|
145
|
-
}
|
|
146
|
-
async function loadImportedFile(filePath, userRootDir, importedFilesLoaded) {
|
|
147
|
-
const f = filePath.filePathAbsoluteFilesystem;
|
|
148
|
-
if (!importedFilesLoaded[f]) {
|
|
149
|
-
importedFilesLoaded[f] = transpileAndExecuteFile(filePath, true, userRootDir).then((r) => r.fileExports);
|
|
150
|
-
}
|
|
151
|
-
const fileExports = await importedFilesLoaded[f];
|
|
152
|
-
return fileExports;
|
|
153
|
-
}
|
|
154
|
-
function isConfigEnv(configDef, configName) {
|
|
155
|
-
const configEnv = configDef.env;
|
|
156
|
-
if (configDef.cumulative) {
|
|
157
|
-
// In principle we could lift that requirement (but it requires non-trivial modifications)
|
|
158
|
-
assertUsage(configEnv.config, `Config ${pc.cyan(configName)} needs its ${pc.cyan('env')} to have ${pc.cyan('{ config: true }')} (because ${pc.cyan(configName)} is a ${pc.cyan('cumulative')} config)`);
|
|
159
|
-
}
|
|
160
|
-
return !!configEnv.config;
|
|
161
|
-
}
|
|
162
|
-
function getInterfaceFileFromConfigFile(configFile, isConfigExtend) {
|
|
153
|
+
function getInterfaceFileFromConfigFile(configFile, isConfigExtend, locationId) {
|
|
163
154
|
const { fileExports, filePath, extendsFilePaths } = configFile;
|
|
164
155
|
const interfaceFile = {
|
|
156
|
+
locationId,
|
|
165
157
|
filePath,
|
|
166
|
-
|
|
158
|
+
fileExportsByConfigName: {},
|
|
167
159
|
isConfigFile: true,
|
|
168
160
|
isValueFile: false,
|
|
169
161
|
isConfigExtend,
|
|
170
162
|
extendsFilePaths
|
|
171
163
|
};
|
|
172
|
-
const
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
interfaceFile.configMap[configName] = { configValue };
|
|
164
|
+
const fileExport = getConfigFileExport(fileExports, filePath.filePathToShowToUser);
|
|
165
|
+
Object.entries(fileExport).forEach(([configName, configValue]) => {
|
|
166
|
+
interfaceFile.fileExportsByConfigName[configName] = { configValue };
|
|
176
167
|
});
|
|
177
168
|
return interfaceFile;
|
|
178
169
|
}
|
|
179
170
|
/** Show error message upon unknown config */
|
|
180
171
|
function assertAllConfigsAreKnown(interfaceFilesByLocationId) {
|
|
181
|
-
|
|
172
|
+
objectEntries(interfaceFilesByLocationId).forEach(([locationId, interfaceFiles]) => {
|
|
182
173
|
const interfaceFilesRelevant = getInterfaceFilesRelevant(interfaceFilesByLocationId, locationId);
|
|
183
|
-
const
|
|
174
|
+
const configDefinitions = getConfigDefinitions(interfaceFilesRelevant);
|
|
184
175
|
interfaceFiles.forEach((interfaceFile) => {
|
|
185
|
-
Object.keys(interfaceFile.
|
|
186
|
-
assertConfigExists(configName, Object.keys(
|
|
176
|
+
Object.keys(interfaceFile.fileExportsByConfigName).forEach((configName) => {
|
|
177
|
+
assertConfigExists(configName, Object.keys(configDefinitions), interfaceFile.filePath.filePathToShowToUser);
|
|
187
178
|
});
|
|
188
179
|
});
|
|
189
180
|
});
|
|
@@ -233,11 +224,11 @@ async function loadVikeConfig(userRootDir, outDirRoot, isDev, extensions) {
|
|
|
233
224
|
const interfaceFilesByLocationId = await loadInterfaceFiles(userRootDir, outDirRoot, isDev, extensions);
|
|
234
225
|
const importedFilesLoaded = {};
|
|
235
226
|
const { globalVikeConfig, pageConfigGlobal } = await getGlobalConfigs(interfaceFilesByLocationId, userRootDir, importedFilesLoaded);
|
|
236
|
-
const pageConfigs = await Promise.all(
|
|
227
|
+
const pageConfigs = await Promise.all(objectEntries(interfaceFilesByLocationId)
|
|
237
228
|
.filter(([_pageId, interfaceFiles]) => isDefiningPage(interfaceFiles))
|
|
238
229
|
.map(async ([locationId]) => {
|
|
239
230
|
const interfaceFilesRelevant = getInterfaceFilesRelevant(interfaceFilesByLocationId, locationId);
|
|
240
|
-
const
|
|
231
|
+
const configDefinitions = getConfigDefinitions(interfaceFilesRelevant);
|
|
241
232
|
// Load value files of custom config-only configs
|
|
242
233
|
await Promise.all(getInterfaceFileList(interfaceFilesRelevant).map(async (interfaceFile) => {
|
|
243
234
|
if (!interfaceFile.isValueFile)
|
|
@@ -245,7 +236,7 @@ async function loadVikeConfig(userRootDir, outDirRoot, isDev, extensions) {
|
|
|
245
236
|
const { configName } = interfaceFile;
|
|
246
237
|
if (isGlobalConfig(configName))
|
|
247
238
|
return;
|
|
248
|
-
const configDef = getConfigDefinition(
|
|
239
|
+
const configDef = getConfigDefinition(configDefinitions, configName, interfaceFile.filePath.filePathToShowToUser);
|
|
249
240
|
if (!isConfigEnv(configDef, configName))
|
|
250
241
|
return;
|
|
251
242
|
const isAlreadyLoaded = interfacefileIsAlreaydLoaded(interfaceFile);
|
|
@@ -255,8 +246,8 @@ async function loadVikeConfig(userRootDir, outDirRoot, isDev, extensions) {
|
|
|
255
246
|
assert(!(configName in configDefinitionsBuiltIn));
|
|
256
247
|
await loadValueFile(interfaceFile, configName, userRootDir);
|
|
257
248
|
}));
|
|
258
|
-
|
|
259
|
-
await Promise.all(objectEntries(
|
|
249
|
+
let configValueSources = {};
|
|
250
|
+
await Promise.all(objectEntries(configDefinitions)
|
|
260
251
|
.filter(([configName]) => !isGlobalConfig(configName))
|
|
261
252
|
.map(async ([configName, configDef]) => {
|
|
262
253
|
const sources = await resolveConfigValueSources(configName, configDef, interfaceFilesRelevant, userRootDir, importedFilesLoaded);
|
|
@@ -264,10 +255,12 @@ async function loadVikeConfig(userRootDir, outDirRoot, isDev, extensions) {
|
|
|
264
255
|
return;
|
|
265
256
|
configValueSources[configName] = sources;
|
|
266
257
|
}));
|
|
258
|
+
configValueSources = sortConfigValueSources(configValueSources, locationId);
|
|
259
|
+
console.log(JSON.stringify(configValueSources, null, 2));
|
|
267
260
|
const { routeFilesystem, isErrorPage } = determineRouteFilesystem(locationId, configValueSources);
|
|
268
|
-
applyEffectsAll(configValueSources,
|
|
269
|
-
const configValuesComputed = getComputed(configValueSources,
|
|
270
|
-
const configValues = getConfigValues(configValueSources, configValuesComputed,
|
|
261
|
+
applyEffectsAll(configValueSources, configDefinitions);
|
|
262
|
+
const configValuesComputed = getComputed(configValueSources, configDefinitions);
|
|
263
|
+
const configValues = getConfigValues(configValueSources, configValuesComputed, configDefinitions);
|
|
271
264
|
const pageConfig = {
|
|
272
265
|
pageId: locationId,
|
|
273
266
|
isErrorPage,
|
|
@@ -296,7 +289,7 @@ function assertOnBeforeRenderEnv(pageConfig) {
|
|
|
296
289
|
assertUsage(!(onBeforeRenderEnv.client && !isClientRouting), `Page ${pageConfig.pageId} has an onBeforeRender() hook with env ${pc.cyan(JSON.stringify(onBeforeRenderEnv))} which doesn't make sense because the page is using Server Routing: onBeforeRender() can be run in the client only when using Client Routing.`);
|
|
297
290
|
}
|
|
298
291
|
function interfacefileIsAlreaydLoaded(interfaceFile) {
|
|
299
|
-
const configMapValues = Object.values(interfaceFile.
|
|
292
|
+
const configMapValues = Object.values(interfaceFile.fileExportsByConfigName);
|
|
300
293
|
const isAlreadyLoaded = configMapValues.some((conf) => 'configValue' in conf);
|
|
301
294
|
if (isAlreadyLoaded) {
|
|
302
295
|
assert(configMapValues.every((conf) => 'configValue' in conf));
|
|
@@ -304,7 +297,7 @@ function interfacefileIsAlreaydLoaded(interfaceFile) {
|
|
|
304
297
|
return isAlreadyLoaded;
|
|
305
298
|
}
|
|
306
299
|
function getInterfaceFilesRelevant(interfaceFilesByLocationId, locationIdPage) {
|
|
307
|
-
const interfaceFilesRelevant = Object.fromEntries(
|
|
300
|
+
const interfaceFilesRelevant = Object.fromEntries(objectEntries(interfaceFilesByLocationId)
|
|
308
301
|
.filter(([locationId]) => {
|
|
309
302
|
return isInherited(locationId, locationIdPage);
|
|
310
303
|
})
|
|
@@ -319,14 +312,14 @@ function getInterfaceFileList(interfaceFilesByLocationId) {
|
|
|
319
312
|
return interfaceFiles;
|
|
320
313
|
}
|
|
321
314
|
async function getGlobalConfigs(interfaceFilesByLocationId, userRootDir, importedFilesLoaded) {
|
|
322
|
-
const locationIds =
|
|
323
|
-
const interfaceFilesGlobal =
|
|
315
|
+
const locationIds = objectKeys(interfaceFilesByLocationId);
|
|
316
|
+
const interfaceFilesGlobal = objectFromEntries(objectEntries(interfaceFilesByLocationId).filter(([locationId]) => {
|
|
324
317
|
return isGlobalLocation(locationId, locationIds);
|
|
325
318
|
}));
|
|
326
319
|
// Validate that global configs live in global interface files
|
|
327
320
|
{
|
|
328
321
|
const interfaceFilesGlobalPaths = [];
|
|
329
|
-
|
|
322
|
+
objectEntries(interfaceFilesGlobal).forEach(([locationId, interfaceFiles]) => {
|
|
330
323
|
assert(isGlobalLocation(locationId, locationIds));
|
|
331
324
|
interfaceFiles.forEach(({ filePath: { filePathRelativeToUserRootDir } }) => {
|
|
332
325
|
if (filePathRelativeToUserRootDir) {
|
|
@@ -335,9 +328,9 @@ async function getGlobalConfigs(interfaceFilesByLocationId, userRootDir, importe
|
|
|
335
328
|
});
|
|
336
329
|
});
|
|
337
330
|
const globalPaths = Array.from(new Set(interfaceFilesGlobalPaths.map((p) => path.posix.dirname(p))));
|
|
338
|
-
|
|
331
|
+
objectEntries(interfaceFilesByLocationId).forEach(([locationId, interfaceFiles]) => {
|
|
339
332
|
interfaceFiles.forEach((interfaceFile) => {
|
|
340
|
-
Object.keys(interfaceFile.
|
|
333
|
+
Object.keys(interfaceFile.fileExportsByConfigName).forEach((configName) => {
|
|
341
334
|
if (!isGlobalLocation(locationId, locationIds) && isGlobalConfig(configName)) {
|
|
342
335
|
assertUsage(false, [
|
|
343
336
|
`${interfaceFile.filePath.filePathToShowToUser} defines the config ${pc.cyan(configName)} which is global:`,
|
|
@@ -378,7 +371,7 @@ async function resolveConfigValueSources(configName, configDef, interfaceFilesRe
|
|
|
378
371
|
const sourcesInfo = [];
|
|
379
372
|
// interfaceFilesRelevant is sorted by sortAfterInheritanceOrder()
|
|
380
373
|
for (const interfaceFiles of Object.values(interfaceFilesRelevant)) {
|
|
381
|
-
const interfaceFilesDefiningConfig = interfaceFiles.filter((interfaceFile) => interfaceFile.
|
|
374
|
+
const interfaceFilesDefiningConfig = interfaceFiles.filter((interfaceFile) => interfaceFile.fileExportsByConfigName[configName]);
|
|
382
375
|
if (interfaceFilesDefiningConfig.length === 0)
|
|
383
376
|
continue;
|
|
384
377
|
const visited = new WeakSet();
|
|
@@ -456,13 +449,15 @@ function isInterfaceFileUserLand(interfaceFile) {
|
|
|
456
449
|
return (interfaceFile.isConfigFile && !interfaceFile.isConfigExtend) || interfaceFile.isValueFile;
|
|
457
450
|
}
|
|
458
451
|
async function getConfigValueSource(configName, interfaceFile, configDef, userRootDir, importedFilesLoaded) {
|
|
459
|
-
const conf = interfaceFile.
|
|
452
|
+
const conf = interfaceFile.fileExportsByConfigName[configName];
|
|
460
453
|
assert(conf);
|
|
461
454
|
const configEnv = configDef.env;
|
|
455
|
+
const { locationId } = interfaceFile;
|
|
462
456
|
const definedAtConfigFile = {
|
|
463
457
|
...interfaceFile.filePath,
|
|
464
458
|
fileExportPathToShowToUser: ['default', configName]
|
|
465
459
|
};
|
|
460
|
+
// +client.js
|
|
466
461
|
if (configDef._valueIsFilePath) {
|
|
467
462
|
let definedAt;
|
|
468
463
|
let valueFilePath;
|
|
@@ -483,6 +478,7 @@ async function getConfigValueSource(configName, interfaceFile, configDef, userRo
|
|
|
483
478
|
};
|
|
484
479
|
}
|
|
485
480
|
const configValueSource = {
|
|
481
|
+
locationId,
|
|
486
482
|
value: valueFilePath,
|
|
487
483
|
valueIsFilePath: true,
|
|
488
484
|
configEnv,
|
|
@@ -491,22 +487,27 @@ async function getConfigValueSource(configName, interfaceFile, configDef, userRo
|
|
|
491
487
|
};
|
|
492
488
|
return configValueSource;
|
|
493
489
|
}
|
|
490
|
+
// +config.js
|
|
494
491
|
if (interfaceFile.isConfigFile) {
|
|
495
492
|
assert('configValue' in conf);
|
|
496
493
|
const { configValue } = conf;
|
|
494
|
+
// fake import
|
|
497
495
|
const import_ = resolveImport(configValue, interfaceFile.filePath, userRootDir, configEnv, configName);
|
|
498
496
|
if (import_) {
|
|
499
497
|
const configValueSource = {
|
|
498
|
+
locationId,
|
|
500
499
|
configEnv,
|
|
501
500
|
valueIsImportedAtRuntime: true,
|
|
502
501
|
definedAt: import_
|
|
503
502
|
};
|
|
504
|
-
// Load
|
|
505
|
-
if (isConfigEnv(configDef, configName)
|
|
503
|
+
// Load fake import
|
|
504
|
+
if (isConfigEnv(configDef, configName) &&
|
|
505
|
+
// The value of `extends` was already loaded and already used: we don't need the value of `extends` anymore
|
|
506
|
+
configName !== 'extends') {
|
|
506
507
|
if (import_.filePathAbsoluteFilesystem) {
|
|
507
508
|
assert(hasProp(import_, 'filePathAbsoluteFilesystem', 'string')); // Help TS
|
|
508
|
-
const
|
|
509
|
-
configValueSource.value =
|
|
509
|
+
const fileExport = await loadImportedFile(import_, userRootDir, importedFilesLoaded);
|
|
510
|
+
configValueSource.value = fileExport;
|
|
510
511
|
}
|
|
511
512
|
else {
|
|
512
513
|
const configDefinedAt = getConfigDefinedAtString('Config', configName, configValueSource);
|
|
@@ -515,20 +516,22 @@ async function getConfigValueSource(configName, interfaceFile, configDef, userRo
|
|
|
515
516
|
}
|
|
516
517
|
return configValueSource;
|
|
517
518
|
}
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
519
|
+
// Defined by config file, i.e. +config.js file
|
|
520
|
+
const configValueSource = {
|
|
521
|
+
locationId,
|
|
522
|
+
value: configValue,
|
|
523
|
+
configEnv,
|
|
524
|
+
valueIsImportedAtRuntime: false,
|
|
525
|
+
definedAt: definedAtConfigFile
|
|
526
|
+
};
|
|
527
|
+
return configValueSource;
|
|
527
528
|
}
|
|
528
|
-
|
|
529
|
+
// Defined by value file, i.e. +{configName}.js
|
|
530
|
+
if (interfaceFile.isValueFile) {
|
|
529
531
|
const valueAlreadyLoaded = 'configValue' in conf;
|
|
530
532
|
assert(valueAlreadyLoaded === !!configEnv.config);
|
|
531
533
|
const configValueSource = {
|
|
534
|
+
locationId,
|
|
532
535
|
configEnv,
|
|
533
536
|
valueIsImportedAtRuntime: !valueAlreadyLoaded,
|
|
534
537
|
definedAt: {
|
|
@@ -546,25 +549,9 @@ async function getConfigValueSource(configName, interfaceFile, configDef, userRo
|
|
|
546
549
|
}
|
|
547
550
|
assert(false);
|
|
548
551
|
}
|
|
549
|
-
function assertFileEnv(filePathForEnvCheck, configEnv, configName) {
|
|
550
|
-
assertPosixPath(filePathForEnvCheck);
|
|
551
|
-
if (!filesEnv.has(filePathForEnvCheck)) {
|
|
552
|
-
filesEnv.set(filePathForEnvCheck, []);
|
|
553
|
-
}
|
|
554
|
-
const fileEnv = filesEnv.get(filePathForEnvCheck);
|
|
555
|
-
fileEnv.push({ configEnv, configName });
|
|
556
|
-
const configDifferentEnv = fileEnv.filter((c) => !deepEqual(c.configEnv, configEnv))[0];
|
|
557
|
-
if (configDifferentEnv) {
|
|
558
|
-
assertUsage(false, [
|
|
559
|
-
`${filePathForEnvCheck} defines the value of configs living in different environments:`,
|
|
560
|
-
...[configDifferentEnv, { configName, configEnv }].map((c) => ` - config ${pc.cyan(c.configName)} which value lives in environment ${pc.cyan(JSON.stringify(c.configEnv))}`),
|
|
561
|
-
'Defining config values in the same file is allowed only if they live in the same environment, see https://vike.dev/header-file'
|
|
562
|
-
].join('\n'));
|
|
563
|
-
}
|
|
564
|
-
}
|
|
565
552
|
function isDefiningPage(interfaceFiles) {
|
|
566
553
|
for (const interfaceFile of interfaceFiles) {
|
|
567
|
-
const configNames = Object.keys(interfaceFile.
|
|
554
|
+
const configNames = Object.keys(interfaceFile.fileExportsByConfigName);
|
|
568
555
|
if (configNames.some((configName) => isDefiningPageConfig(configName))) {
|
|
569
556
|
return true;
|
|
570
557
|
}
|
|
@@ -574,90 +561,13 @@ function isDefiningPage(interfaceFiles) {
|
|
|
574
561
|
function isDefiningPageConfig(configName) {
|
|
575
562
|
return ['Page', 'route'].includes(configName);
|
|
576
563
|
}
|
|
577
|
-
function resolveImport(configValue, importerFilePath, userRootDir, configEnv, configName) {
|
|
578
|
-
if (typeof configValue !== 'string')
|
|
579
|
-
return null;
|
|
580
|
-
const importData = parseImportData(configValue);
|
|
581
|
-
if (!importData)
|
|
582
|
-
return null;
|
|
583
|
-
const { importPath, exportName } = importData;
|
|
584
|
-
const filePathAbsoluteFilesystem = resolveImportPath(importData, importerFilePath);
|
|
585
|
-
assertFileEnv(filePathAbsoluteFilesystem ?? importPath, configEnv, configName);
|
|
586
|
-
const fileExportPathToShowToUser = exportName === 'default' || exportName === configName ? [] : [exportName];
|
|
587
|
-
if (importPath.startsWith('.')) {
|
|
588
|
-
// We need to resolve relative paths into absolute paths. Because the import paths are included in virtual files:
|
|
589
|
-
// ```
|
|
590
|
-
// [vite] Internal server error: Failed to resolve import "./onPageTransitionHooks" from "virtual:vike:pageConfigValuesAll:client:/pages/index". Does the file exist?
|
|
591
|
-
// ```
|
|
592
|
-
assertImportPath(filePathAbsoluteFilesystem, importData, importerFilePath);
|
|
593
|
-
const filePathRelativeToUserRootDir = resolveImportPath_relativeToUserRootDir(filePathAbsoluteFilesystem, importData, importerFilePath, userRootDir);
|
|
594
|
-
const filePath = {
|
|
595
|
-
filePathAbsoluteFilesystem,
|
|
596
|
-
filePathRelativeToUserRootDir,
|
|
597
|
-
filePathAbsoluteVite: filePathRelativeToUserRootDir,
|
|
598
|
-
filePathToShowToUser: filePathRelativeToUserRootDir,
|
|
599
|
-
importPathAbsolute: null
|
|
600
|
-
};
|
|
601
|
-
return {
|
|
602
|
-
...filePath,
|
|
603
|
-
fileExportName: exportName,
|
|
604
|
-
fileExportPathToShowToUser
|
|
605
|
-
};
|
|
606
|
-
}
|
|
607
|
-
else {
|
|
608
|
-
// importPath can be:
|
|
609
|
-
// - an npm package import
|
|
610
|
-
// - a path alias
|
|
611
|
-
const filePath = {
|
|
612
|
-
filePathAbsoluteFilesystem,
|
|
613
|
-
filePathRelativeToUserRootDir: null,
|
|
614
|
-
filePathAbsoluteVite: importPath,
|
|
615
|
-
filePathToShowToUser: importPath,
|
|
616
|
-
importPathAbsolute: importPath
|
|
617
|
-
};
|
|
618
|
-
return {
|
|
619
|
-
...filePath,
|
|
620
|
-
fileExportName: exportName,
|
|
621
|
-
fileExportPathToShowToUser
|
|
622
|
-
};
|
|
623
|
-
}
|
|
624
|
-
}
|
|
625
|
-
function resolveImportPath_relativeToUserRootDir(filePathAbsoluteFilesystem, importData, configFilePath, userRootDir) {
|
|
626
|
-
assertPosixPath(userRootDir);
|
|
627
|
-
let filePathRelativeToUserRootDir;
|
|
628
|
-
if (filePathAbsoluteFilesystem.startsWith(userRootDir)) {
|
|
629
|
-
filePathRelativeToUserRootDir = getVitePathFromAbsolutePath(filePathAbsoluteFilesystem, userRootDir);
|
|
630
|
-
}
|
|
631
|
-
else {
|
|
632
|
-
assertUsage(false, `${configFilePath.filePathToShowToUser} imports from a relative path ${pc.cyan(importData.importPath)} outside of ${userRootDir} which is forbidden: import from a relative path inside ${userRootDir}, or import from a dependency's package.json#exports entry instead`);
|
|
633
|
-
// None of the following works. Seems to be a Vite bug?
|
|
634
|
-
// /*
|
|
635
|
-
// assert(filePathAbsoluteFilesystem.startsWith('/'))
|
|
636
|
-
// filePath = `/@fs${filePathAbsoluteFilesystem}`
|
|
637
|
-
// /*/
|
|
638
|
-
// filePathRelativeToUserRootDir = path.posix.relative(userRootDir, filePathAbsoluteFilesystem)
|
|
639
|
-
// assert(filePathRelativeToUserRootDir.startsWith('../'))
|
|
640
|
-
// filePathRelativeToUserRootDir = '/' + filePathRelativeToUserRootDir
|
|
641
|
-
// //*/
|
|
642
|
-
}
|
|
643
|
-
assertPosixPath(filePathRelativeToUserRootDir);
|
|
644
|
-
assert(filePathRelativeToUserRootDir.startsWith('/'));
|
|
645
|
-
return filePathRelativeToUserRootDir;
|
|
646
|
-
}
|
|
647
|
-
function getVitePathFromAbsolutePath(filePathAbsoluteFilesystem, root) {
|
|
648
|
-
assertPosixPath(filePathAbsoluteFilesystem);
|
|
649
|
-
assertPosixPath(root);
|
|
650
|
-
assert(filePathAbsoluteFilesystem.startsWith(root));
|
|
651
|
-
let vitePath = path.posix.relative(root, filePathAbsoluteFilesystem);
|
|
652
|
-
assert(!vitePath.startsWith('/') && !vitePath.startsWith('.'));
|
|
653
|
-
vitePath = '/' + vitePath;
|
|
654
|
-
return vitePath;
|
|
655
|
-
}
|
|
656
564
|
function getConfigDefinitions(interfaceFilesRelevant) {
|
|
657
|
-
const
|
|
658
|
-
Object.entries(interfaceFilesRelevant)
|
|
565
|
+
const configDefinitionsMerged = { ...configDefinitionsBuiltIn };
|
|
566
|
+
Object.entries(interfaceFilesRelevant)
|
|
567
|
+
.reverse()
|
|
568
|
+
.forEach(([_locationId, interfaceFiles]) => {
|
|
659
569
|
interfaceFiles.forEach((interfaceFile) => {
|
|
660
|
-
const configMeta = interfaceFile.
|
|
570
|
+
const configMeta = interfaceFile.fileExportsByConfigName['meta'];
|
|
661
571
|
if (!configMeta)
|
|
662
572
|
return;
|
|
663
573
|
const meta = configMeta.configValue;
|
|
@@ -674,13 +584,14 @@ function getConfigDefinitions(interfaceFilesRelevant) {
|
|
|
674
584
|
});
|
|
675
585
|
objectEntries(meta).forEach(([configName, configDefinition]) => {
|
|
676
586
|
// User can override an existing config definition
|
|
677
|
-
|
|
678
|
-
...
|
|
587
|
+
configDefinitionsMerged[configName] = {
|
|
588
|
+
...configDefinitionsMerged[configName],
|
|
679
589
|
...configDefinition
|
|
680
590
|
};
|
|
681
591
|
});
|
|
682
592
|
});
|
|
683
593
|
});
|
|
594
|
+
const configDefinitions = configDefinitionsMerged;
|
|
684
595
|
return configDefinitions;
|
|
685
596
|
}
|
|
686
597
|
function assertMetaValue(metaVal, configMetaDefinedAt) {
|
|
@@ -719,8 +630,8 @@ function assertMetaValue(metaVal, configMetaDefinedAt) {
|
|
|
719
630
|
}
|
|
720
631
|
});
|
|
721
632
|
}
|
|
722
|
-
function applyEffectsAll(configValueSources,
|
|
723
|
-
objectEntries(
|
|
633
|
+
function applyEffectsAll(configValueSources, configDefinitions) {
|
|
634
|
+
objectEntries(configDefinitions).forEach(([configName, configDef]) => {
|
|
724
635
|
if (!configDef.effect)
|
|
725
636
|
return;
|
|
726
637
|
// The value needs to be loaded at config time, that's why we only support effect for configs that are config-only for now.
|
|
@@ -779,9 +690,9 @@ function applyEffect(configModFromEffect, configValueSources, configDefEffect) {
|
|
|
779
690
|
}
|
|
780
691
|
});
|
|
781
692
|
}
|
|
782
|
-
function getComputed(configValueSources,
|
|
693
|
+
function getComputed(configValueSources, configDefinitions) {
|
|
783
694
|
const configValuesComputed = {};
|
|
784
|
-
objectEntries(
|
|
695
|
+
objectEntries(configDefinitions).forEach(([configName, configDef]) => {
|
|
785
696
|
if (!configDef._computed)
|
|
786
697
|
return;
|
|
787
698
|
const value = configDef._computed(configValueSources);
|
|
@@ -796,15 +707,7 @@ function getComputed(configValueSources, configDefinitionsRelevant) {
|
|
|
796
707
|
}
|
|
797
708
|
async function findPlusFiles(userRootDir, outDirRoot, isDev, extensions) {
|
|
798
709
|
const files = await crawlPlusFiles(userRootDir, outDirRoot, isDev);
|
|
799
|
-
const plusFiles = files.map(({ filePathRelativeToUserRootDir
|
|
800
|
-
return {
|
|
801
|
-
filePathRelativeToUserRootDir,
|
|
802
|
-
filePathAbsoluteVite: filePathRelativeToUserRootDir,
|
|
803
|
-
filePathAbsoluteFilesystem,
|
|
804
|
-
filePathToShowToUser: filePathRelativeToUserRootDir,
|
|
805
|
-
importPathAbsolute: null
|
|
806
|
-
};
|
|
807
|
-
});
|
|
710
|
+
const plusFiles = files.map(({ filePathRelativeToUserRootDir }) => resolveFilePathRelativeToUserRootDir(filePathRelativeToUserRootDir, userRootDir));
|
|
808
711
|
// TODO/v1-release: remove
|
|
809
712
|
extensions.forEach((extension) => {
|
|
810
713
|
extension.pageConfigsDistFiles?.forEach((pageConfigDistFile) => {
|
|
@@ -840,125 +743,22 @@ function getConfigName(filePath) {
|
|
|
840
743
|
return configName;
|
|
841
744
|
}
|
|
842
745
|
}
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
const
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
}
|
|
856
|
-
|
|
857
|
-
}
|
|
858
|
-
|
|
859
|
-
const idx = visited.indexOf(filePathAbsoluteFilesystem);
|
|
860
|
-
if (idx === -1)
|
|
861
|
-
return;
|
|
862
|
-
const loop = visited.slice(idx);
|
|
863
|
-
assert(loop[0] === filePathAbsoluteFilesystem);
|
|
864
|
-
assertUsage(idx === -1, `Infinite extends loop ${[...loop, filePathAbsoluteFilesystem].join('>')}`);
|
|
865
|
-
}
|
|
866
|
-
async function loadExtendsConfigs(configFileExports, configFilePath, userRootDir, visited) {
|
|
867
|
-
const extendsImportData = getExtendsImportData(configFileExports, configFilePath);
|
|
868
|
-
const extendsConfigFiles = [];
|
|
869
|
-
extendsImportData.map((importData) => {
|
|
870
|
-
const { importPath: importPath } = importData;
|
|
871
|
-
const filePathAbsoluteFilesystem = resolveImportPath(importData, configFilePath);
|
|
872
|
-
assertImportPath(filePathAbsoluteFilesystem, importData, configFilePath);
|
|
873
|
-
assertExtendsImportPath(importPath, filePathAbsoluteFilesystem, configFilePath);
|
|
874
|
-
// - filePathRelativeToUserRootDir has no functionality beyond nicer error messages for user
|
|
875
|
-
// - Using importPath would be visually nicer but it's ambigous => we rather pick filePathAbsoluteFilesystem for added clarity
|
|
876
|
-
const filePathRelativeToUserRootDir = determineFilePathRelativeToUserDir(filePathAbsoluteFilesystem, userRootDir);
|
|
877
|
-
const filePathAbsoluteVite = filePathRelativeToUserRootDir ?? importPath;
|
|
878
|
-
extendsConfigFiles.push({
|
|
879
|
-
filePathAbsoluteFilesystem,
|
|
880
|
-
filePathAbsoluteVite,
|
|
881
|
-
filePathRelativeToUserRootDir,
|
|
882
|
-
filePathToShowToUser: filePathAbsoluteVite,
|
|
883
|
-
importPathAbsolute: importPath
|
|
884
|
-
});
|
|
885
|
-
});
|
|
886
|
-
const extendsConfigs = [];
|
|
887
|
-
await Promise.all(extendsConfigFiles.map(async (configFilePath) => {
|
|
888
|
-
const result = await loadConfigFile(configFilePath, userRootDir, visited);
|
|
889
|
-
extendsConfigs.push(result.configFile);
|
|
890
|
-
extendsConfigs.push(...result.extendsConfigs);
|
|
891
|
-
}));
|
|
892
|
-
const extendsFilePaths = extendsConfigFiles.map((f) => f.filePathAbsoluteFilesystem);
|
|
893
|
-
return { extendsConfigs, extendsFilePaths };
|
|
894
|
-
}
|
|
895
|
-
function determineFilePathRelativeToUserDir(filePathAbsoluteFilesystem, userRootDir) {
|
|
896
|
-
assertPosixPath(filePathAbsoluteFilesystem);
|
|
897
|
-
assertPosixPath(userRootDir);
|
|
898
|
-
if (!filePathAbsoluteFilesystem.startsWith(userRootDir)) {
|
|
899
|
-
return null;
|
|
900
|
-
}
|
|
901
|
-
let filePathRelativeToUserRootDir = filePathAbsoluteFilesystem.slice(userRootDir.length);
|
|
902
|
-
if (!filePathRelativeToUserRootDir.startsWith('/'))
|
|
903
|
-
filePathRelativeToUserRootDir = '/' + filePathRelativeToUserRootDir;
|
|
904
|
-
return filePathRelativeToUserRootDir;
|
|
905
|
-
}
|
|
906
|
-
function assertExtendsImportPath(importPath, filePath, configFilePath) {
|
|
907
|
-
if (isNpmPackageImport(importPath)) {
|
|
908
|
-
const fileDir = path.posix.dirname(filePath) + '/';
|
|
909
|
-
const fileName = path.posix.basename(filePath);
|
|
910
|
-
const fileNameBaseCorrect = '+config';
|
|
911
|
-
const [fileNameBase, ...fileNameRest] = fileName.split('.');
|
|
912
|
-
const fileNameCorrect = [fileNameBaseCorrect, ...fileNameRest].join('.');
|
|
913
|
-
assertWarning(fileNameBase === fileNameBaseCorrect, `Rename ${fileName} to ${fileNameCorrect} in ${fileDir}`, {
|
|
914
|
-
onlyOnce: true
|
|
915
|
-
});
|
|
916
|
-
}
|
|
917
|
-
else {
|
|
918
|
-
assertWarning(false, `${configFilePath.filePathToShowToUser} uses ${pc.cyan('extends')} to inherit from ${pc.cyan(importPath)} which is a user-land file: this is experimental and may be remove at any time. Reach out to a maintainer if you need this feature.`, { onlyOnce: true });
|
|
919
|
-
}
|
|
920
|
-
}
|
|
921
|
-
function getExtendsImportData(configFileExports, configFilePath) {
|
|
922
|
-
const { filePathToShowToUser } = configFilePath;
|
|
923
|
-
assertExportsOfConfigFile(configFileExports, filePathToShowToUser);
|
|
924
|
-
const defaultExports = configFileExports.default;
|
|
925
|
-
const wrongUsage = `${filePathToShowToUser} sets the config ${pc.cyan('extends')} to an invalid value, see https://vike.dev/extends`;
|
|
926
|
-
let extendList;
|
|
927
|
-
if (!('extends' in defaultExports)) {
|
|
928
|
-
return [];
|
|
929
|
-
}
|
|
930
|
-
else if (hasProp(defaultExports, 'extends', 'string')) {
|
|
931
|
-
extendList = [defaultExports.extends];
|
|
932
|
-
}
|
|
933
|
-
else if (hasProp(defaultExports, 'extends', 'string[]')) {
|
|
934
|
-
extendList = defaultExports.extends;
|
|
935
|
-
}
|
|
936
|
-
else {
|
|
937
|
-
assertUsage(false, wrongUsage);
|
|
938
|
-
}
|
|
939
|
-
const extendsImportData = extendList.map((importDataSerialized) => {
|
|
940
|
-
const importData = parseImportData(importDataSerialized);
|
|
941
|
-
assertUsage(importData, wrongUsage);
|
|
942
|
-
return importData;
|
|
943
|
-
});
|
|
944
|
-
return extendsImportData;
|
|
945
|
-
}
|
|
946
|
-
function isGlobalConfig(configName) {
|
|
947
|
-
if (configName === 'prerender')
|
|
948
|
-
return false;
|
|
949
|
-
const configNamesGlobal = getConfigNamesGlobal();
|
|
950
|
-
return arrayIncludes(configNamesGlobal, configName);
|
|
951
|
-
}
|
|
952
|
-
function getConfigNamesGlobal() {
|
|
953
|
-
return Object.keys(configDefinitionsBuiltInGlobal);
|
|
954
|
-
}
|
|
955
|
-
function assertConfigExists(configName, configNamesRelevant, filePathToShowToUser) {
|
|
956
|
-
const configNames = [...configNamesRelevant, ...getConfigNamesGlobal()];
|
|
957
|
-
if (configNames.includes(configName))
|
|
958
|
-
return;
|
|
959
|
-
handleUnknownConfig(configName, configNames, filePathToShowToUser);
|
|
960
|
-
assert(false);
|
|
961
|
-
}
|
|
746
|
+
/* https://github.com/vikejs/vike/issues/1407
|
|
747
|
+
function assertNoUnexpectedPlusSign(filePath: string, fileName: string) {
|
|
748
|
+
const dirs = path.posix.dirname(filePath).split('/')
|
|
749
|
+
dirs.forEach((dir, i) => {
|
|
750
|
+
const dirPath = dirs.slice(0, i + 1).join('/')
|
|
751
|
+
assertUsage(
|
|
752
|
+
!dir.includes('+'),
|
|
753
|
+
`Character '+' is a reserved character: remove '+' from the directory name ${dirPath}/`
|
|
754
|
+
)
|
|
755
|
+
})
|
|
756
|
+
assertUsage(
|
|
757
|
+
!fileName.slice(1).includes('+'),
|
|
758
|
+
`Character '+' is only allowed at the beginning of filenames: make sure ${filePath} doesn't contain any '+' in its filename other than its first letter`
|
|
759
|
+
)
|
|
760
|
+
}
|
|
761
|
+
*/
|
|
962
762
|
function handleUnknownConfig(configName, configNames, filePathToShowToUser) {
|
|
963
763
|
let errMsg = `${filePathToShowToUser} defines an unknown config ${pc.cyan(configName)}`;
|
|
964
764
|
let configNameSimilar = null;
|
|
@@ -1025,36 +825,10 @@ function determineIsErrorPage(routeFilesystem) {
|
|
|
1025
825
|
assertPosixPath(routeFilesystem);
|
|
1026
826
|
return routeFilesystem.split('/').includes('_error');
|
|
1027
827
|
}
|
|
1028
|
-
function resolveImportPath(importData, importerFilePath) {
|
|
1029
|
-
const importerFilePathAbsolute = importerFilePath.filePathAbsoluteFilesystem;
|
|
1030
|
-
assertPosixPath(importerFilePathAbsolute);
|
|
1031
|
-
const cwd = path.posix.dirname(importerFilePathAbsolute);
|
|
1032
|
-
// We can't use import.meta.resolve() as of Junary 2023 (and probably for a lot longer): https://stackoverflow.com/questions/54977743/do-require-resolve-for-es-modules#comment137174954_62272600:~:text=But%20the%20argument%20parent%20(aka%20cwd)%20still%20requires%20a%20flag
|
|
1033
|
-
// filePathAbsoluteFilesystem is expected to be null when importData.importPath is a Vite path alias
|
|
1034
|
-
const filePathAbsoluteFilesystem = requireResolve(importData.importPath, cwd);
|
|
1035
|
-
return filePathAbsoluteFilesystem;
|
|
1036
|
-
}
|
|
1037
|
-
function assertImportPath(filePathAbsoluteFilesystem, importData, importerFilePath) {
|
|
1038
|
-
const { importPath: importPath, importStringWasGenerated, importString } = importData;
|
|
1039
|
-
const { filePathToShowToUser } = importerFilePath;
|
|
1040
|
-
if (!filePathAbsoluteFilesystem) {
|
|
1041
|
-
const importPathString = pc.cyan(`'${importPath}'`);
|
|
1042
|
-
const errIntro = importStringWasGenerated
|
|
1043
|
-
? `The import path ${importPathString} in ${filePathToShowToUser}`
|
|
1044
|
-
: `The import ${pc.cyan(importString)} defined in ${filePathToShowToUser}`;
|
|
1045
|
-
const errIntro2 = `${errIntro} couldn't be resolved: does ${importPathString}`;
|
|
1046
|
-
if (importPath.startsWith('.')) {
|
|
1047
|
-
assertUsage(false, `${errIntro2} point to an existing file?`);
|
|
1048
|
-
}
|
|
1049
|
-
else {
|
|
1050
|
-
assertUsage(false, `${errIntro2} exist?`);
|
|
1051
|
-
}
|
|
1052
|
-
}
|
|
1053
|
-
}
|
|
1054
828
|
function isVikeConfigFile(filePath) {
|
|
1055
829
|
return !!getConfigName(filePath);
|
|
1056
830
|
}
|
|
1057
|
-
function getConfigValues(configValueSources, configValuesComputed,
|
|
831
|
+
function getConfigValues(configValueSources, configValuesComputed, configDefinitions) {
|
|
1058
832
|
const configValues = {};
|
|
1059
833
|
Object.entries(configValuesComputed).forEach(([configName, configValueComputed]) => {
|
|
1060
834
|
configValues[configName] = {
|
|
@@ -1063,7 +837,7 @@ function getConfigValues(configValueSources, configValuesComputed, configDefinit
|
|
|
1063
837
|
};
|
|
1064
838
|
});
|
|
1065
839
|
Object.entries(configValueSources).forEach(([configName, sources]) => {
|
|
1066
|
-
const configDef =
|
|
840
|
+
const configDef = configDefinitions[configName];
|
|
1067
841
|
assert(configDef);
|
|
1068
842
|
if (!configDef.cumulative) {
|
|
1069
843
|
const configValueSource = sources[0];
|
|
@@ -1177,3 +951,48 @@ function getConfigEnvValue(val, errMsgIntro) {
|
|
|
1177
951
|
*/
|
|
1178
952
|
return val;
|
|
1179
953
|
}
|
|
954
|
+
function getConfigDefinition(configDefinitions, configName, filePathToShowToUser) {
|
|
955
|
+
const configDef = configDefinitions[configName];
|
|
956
|
+
assertConfigExists(configName, Object.keys(configDefinitions), filePathToShowToUser);
|
|
957
|
+
assert(configDef);
|
|
958
|
+
return configDef;
|
|
959
|
+
}
|
|
960
|
+
function getConfigDefinitionOptional(configDefinitions, configName) {
|
|
961
|
+
return configDefinitions[configName] ?? null;
|
|
962
|
+
}
|
|
963
|
+
function isConfigEnv(configDef, configName) {
|
|
964
|
+
const configEnv = configDef.env;
|
|
965
|
+
if (configDef.cumulative) {
|
|
966
|
+
// In principle we could lift that requirement (but it requires non-trivial modifications)
|
|
967
|
+
assertUsage(configEnv.config, `Config ${pc.cyan(configName)} needs its ${pc.cyan('env')} to have ${pc.cyan('{ config: true }')} (because ${pc.cyan(configName)} is a ${pc.cyan('cumulative')} config)`);
|
|
968
|
+
}
|
|
969
|
+
return !!configEnv.config;
|
|
970
|
+
}
|
|
971
|
+
function isGlobalConfig(configName) {
|
|
972
|
+
if (configName === 'prerender')
|
|
973
|
+
return false;
|
|
974
|
+
const configNamesGlobal = getConfigNamesGlobal();
|
|
975
|
+
return arrayIncludes(configNamesGlobal, configName);
|
|
976
|
+
}
|
|
977
|
+
function getConfigNamesGlobal() {
|
|
978
|
+
return Object.keys(configDefinitionsBuiltInGlobal);
|
|
979
|
+
}
|
|
980
|
+
function assertConfigExists(configName, configNamesRelevant, filePathToShowToUser) {
|
|
981
|
+
const configNames = [...configNamesRelevant, ...getConfigNamesGlobal()];
|
|
982
|
+
if (configNames.includes(configName))
|
|
983
|
+
return;
|
|
984
|
+
handleUnknownConfig(configName, configNames, filePathToShowToUser);
|
|
985
|
+
assert(false);
|
|
986
|
+
}
|
|
987
|
+
function sortConfigValueSources(configValueSources, locationIdPage) {
|
|
988
|
+
return Object.fromEntries(Object.entries(configValueSources)
|
|
989
|
+
// Make order deterministic (no other purpose)
|
|
990
|
+
.sort(([, [source1]], [, [source2]]) => source1.definedAt.filePathAbsoluteVite < source2.definedAt.filePathAbsoluteVite ? -1 : 1)
|
|
991
|
+
// Sort after whether the config value was defined by an npm package
|
|
992
|
+
.sort(makeFirst(([, [source]]) => {
|
|
993
|
+
const { importPathAbsolute } = source.definedAt;
|
|
994
|
+
return !!importPathAbsolute && isNpmPackageImport(importPathAbsolute);
|
|
995
|
+
}))
|
|
996
|
+
// Sort after the filesystem inheritance of the config value
|
|
997
|
+
.sort(([, [source1]], [, [source2]]) => reverse(sortAfterInheritanceOrder(source1.locationId, source2.locationId, locationIdPage))));
|
|
998
|
+
}
|