vike 0.4.143-commit-dc6fea0 → 0.4.143-commit-fa295e1
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/plugins/devConfig/determineOptimizeDeps.js +30 -27
- package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +107 -54
- package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigValuesAll.js +11 -10
- package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigs.js +11 -11
- package/dist/cjs/node/prerender/runPrerender.js +9 -8
- package/dist/cjs/node/runtime/renderPage/renderPageAlreadyRouted.js +3 -2
- package/dist/cjs/node/shared/getClientEntryFilePath.js +1 -7
- package/dist/cjs/shared/getPageFiles/getExports.js +2 -5
- package/dist/cjs/shared/getPageFiles/parsePageConfigsSerialized.js +9 -6
- package/dist/cjs/shared/hooks/getHook.js +3 -1
- package/dist/cjs/shared/page-configs/getExportPath.js +2 -2
- package/dist/cjs/shared/page-configs/parseConfigValuesImported.js +8 -5
- package/dist/cjs/shared/page-configs/utils.js +66 -42
- package/dist/cjs/shared/route/loadPageRoutes.js +5 -6
- package/dist/cjs/utils/projectInfo.js +1 -1
- package/dist/esm/node/plugin/plugins/devConfig/determineOptimizeDeps.js +30 -27
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +107 -54
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigValuesAll.js +11 -10
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigs.d.ts +2 -2
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigs.js +11 -11
- package/dist/esm/node/prerender/runPrerender.js +10 -9
- package/dist/esm/node/runtime/renderPage/renderPageAlreadyRouted.js +3 -2
- package/dist/esm/node/shared/getClientEntryFilePath.js +2 -8
- package/dist/esm/shared/getPageFiles/getExports.d.ts +1 -2
- package/dist/esm/shared/getPageFiles/getExports.js +3 -6
- package/dist/esm/shared/getPageFiles/parsePageConfigsSerialized.js +9 -6
- package/dist/esm/shared/hooks/getHook.js +3 -1
- package/dist/esm/shared/page-configs/PageConfig.d.ts +34 -10
- package/dist/esm/shared/page-configs/getExportPath.d.ts +1 -1
- package/dist/esm/shared/page-configs/getExportPath.js +2 -2
- package/dist/esm/shared/page-configs/parseConfigValuesImported.js +8 -5
- package/dist/esm/shared/page-configs/utils.d.ts +19 -13
- package/dist/esm/shared/page-configs/utils.js +65 -41
- package/dist/esm/shared/route/loadPageRoutes.js +6 -7
- package/dist/esm/utils/projectInfo.d.ts +1 -1
- package/dist/esm/utils/projectInfo.js +1 -1
- package/package.json +1 -1
package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigValuesAll.js
CHANGED
|
@@ -53,30 +53,31 @@ function getLoadConfigValuesAll(pageConfig, isForClientSide, pageId, includeAsse
|
|
|
53
53
|
return code;
|
|
54
54
|
}
|
|
55
55
|
function serializeConfigValueImported(configValueSource, configName, whitespace, varCounterContainer, importStatements) {
|
|
56
|
+
assert(!configValueSource.valueIsFilePath);
|
|
56
57
|
assert(whitespace.replaceAll(' ', '').length === 0);
|
|
57
58
|
const { valueIsImportedAtRuntime, definedAtInfo } = configValueSource;
|
|
58
59
|
assert(valueIsImportedAtRuntime);
|
|
59
|
-
const {
|
|
60
|
-
|
|
61
|
-
|
|
60
|
+
const { filePathRelativeToUserRootDir, importPathAbsolute, exportName } = definedAtInfo;
|
|
61
|
+
const importPath = filePathRelativeToUserRootDir ?? importPathAbsolute;
|
|
62
|
+
assertPosixPath(importPath);
|
|
63
|
+
const fileName = path.posix.basename(importPath);
|
|
62
64
|
const isValueFile = fileName.startsWith('+');
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
const { importName, importStatement } = generateEagerImport(filePath, varCounterContainer.varCounter++, isValueFile ? undefined : fileExportName);
|
|
65
|
+
if (isValueFile)
|
|
66
|
+
assert(exportName === undefined);
|
|
67
|
+
const { importName, importStatement } = generateEagerImport(importPath, varCounterContainer.varCounter++, exportName);
|
|
67
68
|
importStatements.push(importStatement);
|
|
68
69
|
const lines = [];
|
|
69
70
|
lines.push(` {`);
|
|
70
71
|
lines.push(` configName: '${configName}',`);
|
|
71
|
-
lines.push(` importPath: '${
|
|
72
|
+
lines.push(` importPath: '${importPath}',`);
|
|
72
73
|
lines.push(` isValueFile: ${JSON.stringify(isValueFile)},`);
|
|
73
74
|
if (isValueFile) {
|
|
74
75
|
lines.push(` importFileExports: ${importName},`);
|
|
75
76
|
}
|
|
76
77
|
else {
|
|
77
78
|
lines.push(` importFileExportValue: ${importName},`);
|
|
78
|
-
assert(
|
|
79
|
-
lines.push(` exportName: ${JSON.stringify(
|
|
79
|
+
assert(exportName);
|
|
80
|
+
lines.push(` exportName: ${JSON.stringify(exportName)},`);
|
|
80
81
|
}
|
|
81
82
|
lines.push(` },`);
|
|
82
83
|
return lines;
|
package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigs.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { getVirtualFilePageConfigs };
|
|
2
2
|
export { getConfigValueSerialized };
|
|
3
|
-
import type {
|
|
3
|
+
import type { DefinedAt } from '../../../../../shared/page-configs/PageConfig.js';
|
|
4
4
|
import type { ConfigVikeResolved } from '../../../../../shared/ConfigVike.js';
|
|
5
5
|
declare function getVirtualFilePageConfigs(userRootDir: string, isForClientSide: boolean, isDev: boolean, id: string, configVike: ConfigVikeResolved, isClientRouting: boolean): Promise<string>;
|
|
6
|
-
declare function getConfigValueSerialized(value: unknown, configName: string,
|
|
6
|
+
declare function getConfigValueSerialized(value: unknown, configName: string, definedAt: DefinedAt): string;
|
|
@@ -9,6 +9,7 @@ import pc from '@brillout/picocolors';
|
|
|
9
9
|
import { getVikeConfig } from './getVikeConfig.js';
|
|
10
10
|
import { isConfigEnvMatch } from './isConfigEnvMatch.js';
|
|
11
11
|
import { serializeConfigValueImported } from './getVirtualFilePageConfigValuesAll.js';
|
|
12
|
+
import { getConfigValueFilePathToShowToUser } from '../../../../../shared/page-configs/utils.js';
|
|
12
13
|
async function getVirtualFilePageConfigs(userRootDir, isForClientSide, isDev, id, configVike, isClientRouting) {
|
|
13
14
|
const { pageConfigs, pageConfigGlobal } = await getVikeConfig(userRootDir, isDev, configVike.extensions, true);
|
|
14
15
|
return getContent(pageConfigs, pageConfigGlobal, isForClientSide, isDev, id, isClientRouting);
|
|
@@ -34,9 +35,9 @@ function getContent(pageConfigs, pageConfigGlobal, isForClientSide, isDev, id, i
|
|
|
34
35
|
assert(configEnv, configName);
|
|
35
36
|
if (!isConfigEnvMatch(configEnv, isForClientSide, isClientRouting))
|
|
36
37
|
return;
|
|
37
|
-
const { value,
|
|
38
|
-
const valueSerialized = getConfigValueSerialized(value, configName,
|
|
39
|
-
serializeConfigValue(lines, configName, {
|
|
38
|
+
const { value, definedAt } = configValue;
|
|
39
|
+
const valueSerialized = getConfigValueSerialized(value, configName, definedAt);
|
|
40
|
+
serializeConfigValue(lines, configName, { definedAt, valueSerialized });
|
|
40
41
|
}
|
|
41
42
|
});
|
|
42
43
|
lines.push(` },`);
|
|
@@ -93,13 +94,13 @@ function serializeConfigValue(lines, configName, configValueSerialized) {
|
|
|
93
94
|
lines.push(`${whitespace}['${configName}']: {`);
|
|
94
95
|
whitespace += ' ';
|
|
95
96
|
Object.entries(configValueSerialized).forEach(([key, val]) => {
|
|
96
|
-
const valSerialized = key === '
|
|
97
|
+
const valSerialized = key === 'definedAt' ? JSON.stringify(val) : val;
|
|
97
98
|
lines.push(`${whitespace} ${key}: ${valSerialized},`);
|
|
98
99
|
});
|
|
99
100
|
whitespace = whitespace.slice(2);
|
|
100
101
|
lines.push(`${whitespace}},`);
|
|
101
102
|
}
|
|
102
|
-
function getConfigValueSerialized(value, configName,
|
|
103
|
+
function getConfigValueSerialized(value, configName, definedAt) {
|
|
103
104
|
let configValueSerialized;
|
|
104
105
|
const valueName = `config${getPropAccessNotation(configName)}`;
|
|
105
106
|
try {
|
|
@@ -107,15 +108,14 @@ function getConfigValueSerialized(value, configName, definedAtInfo) {
|
|
|
107
108
|
}
|
|
108
109
|
catch (err) {
|
|
109
110
|
assert(hasProp(err, 'messageCore', 'string'));
|
|
110
|
-
|
|
111
|
+
const configValueFilePathToShowToUser = getConfigValueFilePathToShowToUser({ definedAt });
|
|
112
|
+
// definedAt is null when config value is:
|
|
111
113
|
// - computed => all computed values defined by Vike can are serializable
|
|
112
114
|
// - cumulative => the values are already ensured to be serializable
|
|
113
|
-
assert(
|
|
114
|
-
const configDefinedByFile = definedAtInfo.filePath;
|
|
115
|
-
assert(configDefinedByFile);
|
|
115
|
+
assert(configValueFilePathToShowToUser);
|
|
116
116
|
assertUsage(false, [
|
|
117
|
-
`The value of the config ${pc.cyan(configName)} cannot be defined inside the file ${
|
|
118
|
-
`its value must be defined in an another file and then imported by ${
|
|
117
|
+
`The value of the config ${pc.cyan(configName)} cannot be defined inside the file ${configValueFilePathToShowToUser}:`,
|
|
118
|
+
`its value must be defined in an another file and then imported by ${configValueFilePathToShowToUser}. (Because the value isn't serializable: ${err.messageCore}.)`,
|
|
119
119
|
`Only serializable config values can be defined inside +config.h.js files, see https://vike.dev/header-file.`
|
|
120
120
|
].join(' '));
|
|
121
121
|
}
|
|
@@ -16,7 +16,7 @@ import { getConfigVike } from '../shared/getConfigVike.js';
|
|
|
16
16
|
import { getPageFilesServerSide } from '../../shared/getPageFiles.js';
|
|
17
17
|
import { getPageContextRequestUrl } from '../../shared/getPageContextRequestUrl.js';
|
|
18
18
|
import { getUrlFromRouteString } from '../../shared/route/resolveRouteString.js';
|
|
19
|
-
import {
|
|
19
|
+
import { getConfigValue, getConfigValueFilePathToShowToUser, getHookFilePathToShowToUser } from '../../shared/page-configs/utils.js';
|
|
20
20
|
import { loadConfigValues } from '../../shared/page-configs/loadConfigValues.js';
|
|
21
21
|
import { isErrorPage } from '../../shared/error-page.js';
|
|
22
22
|
import { addUrlComputedProps } from '../../shared/addUrlComputedProps.js';
|
|
@@ -87,12 +87,13 @@ async function collectDoNoPrerenderList(renderContext, doNotPrerenderList, concu
|
|
|
87
87
|
const configName = 'prerender';
|
|
88
88
|
const configValue = getConfigValue(pageConfig, configName, 'boolean');
|
|
89
89
|
if (configValue?.value === false) {
|
|
90
|
-
const
|
|
90
|
+
const filePath = getConfigValueFilePathToShowToUser(configValue);
|
|
91
|
+
assert(filePath);
|
|
91
92
|
doNotPrerenderList.push({
|
|
92
93
|
pageId: pageConfig.pageId,
|
|
93
94
|
setByConfigName: 'prerender',
|
|
94
95
|
setByConfigValue: false,
|
|
95
|
-
setByConfigFile:
|
|
96
|
+
setByConfigFile: filePath
|
|
96
97
|
});
|
|
97
98
|
}
|
|
98
99
|
});
|
|
@@ -148,8 +149,7 @@ async function callOnBeforePrerenderStartHooks(prerenderContext, renderContext,
|
|
|
148
149
|
if (!configValue)
|
|
149
150
|
return;
|
|
150
151
|
const hookFn = configValue.value;
|
|
151
|
-
const
|
|
152
|
-
const hookFilePath = definedAtInfo.filePath;
|
|
152
|
+
const hookFilePath = getHookFilePathToShowToUser(configValue);
|
|
153
153
|
assert(hookFilePath);
|
|
154
154
|
assertHookFn(hookFn, { hookName, hookFilePath });
|
|
155
155
|
onBeforePrerenderStartHooks.push({
|
|
@@ -282,11 +282,12 @@ async function callOnPrerenderStartHook(prerenderContext, renderContext) {
|
|
|
282
282
|
// V1 design
|
|
283
283
|
if (renderContext.pageConfigs.length > 0) {
|
|
284
284
|
const { pageConfigGlobal } = renderContext;
|
|
285
|
-
|
|
286
|
-
|
|
285
|
+
const configValue = pageConfigGlobal.configValues.onPrerenderStart;
|
|
286
|
+
if (configValue?.value) {
|
|
287
|
+
const { value: hookFn } = configValue;
|
|
287
288
|
// config.onPrerenderStart isn't a computed nor a cumulative config => definedAtInfo should always be defined
|
|
288
|
-
|
|
289
|
-
|
|
289
|
+
const hookFilePath = getHookFilePathToShowToUser(configValue);
|
|
290
|
+
assert(hookFilePath);
|
|
290
291
|
onPrerenderStartHook = {
|
|
291
292
|
hookFn,
|
|
292
293
|
hookName: 'onPrerenderStart',
|
|
@@ -20,6 +20,7 @@ import { preparePageContextForUserConsumptionServerSide } from './preparePageCon
|
|
|
20
20
|
import { executeGuardHook } from '../../../shared/route/executeGuardHook.js';
|
|
21
21
|
import { loadPageRoutes } from '../../../shared/route/loadPageRoutes.js';
|
|
22
22
|
import pc from '@brillout/picocolors';
|
|
23
|
+
import { getConfigValueFilePathToShowToUser } from '../../../shared/page-configs/utils.js';
|
|
23
24
|
async function renderPageAlreadyRouted(pageContext) {
|
|
24
25
|
// pageContext._pageId can either be the:
|
|
25
26
|
// - ID of the page matching the routing, or the
|
|
@@ -166,9 +167,9 @@ function assertNonMixedDesign(pageFilesAll, pageConfigs) {
|
|
|
166
167
|
const indent = '- ';
|
|
167
168
|
const v1Files = unique(pageConfigs
|
|
168
169
|
.map((p) => Object.values(p.configValues)
|
|
169
|
-
.map(
|
|
170
|
+
.map(getConfigValueFilePathToShowToUser)
|
|
170
171
|
.filter(isNotNullish)
|
|
171
|
-
.map((
|
|
172
|
+
.map((filePathToShowToUser) => indent + filePathToShowToUser))
|
|
172
173
|
.flat(2));
|
|
173
174
|
assertUsage(false, [
|
|
174
175
|
'Mixing the new V1 design with the old V0.4 design is forbidden.',
|
|
@@ -1,15 +1,9 @@
|
|
|
1
1
|
export { getClientEntryFilePath };
|
|
2
|
-
import {
|
|
3
|
-
import { assert } from './utils.js';
|
|
2
|
+
import { getConfigValue } from '../../shared/page-configs/utils.js';
|
|
4
3
|
function getClientEntryFilePath(pageConfig) {
|
|
5
4
|
const configName = 'client';
|
|
6
5
|
const configValue = getConfigValue(pageConfig, configName, 'string');
|
|
7
6
|
if (!configValue)
|
|
8
7
|
return null;
|
|
9
|
-
|
|
10
|
-
const { value } = configValue;
|
|
11
|
-
// Users should be able to suppress client entry by setting its value to null
|
|
12
|
-
assert(value !== null);
|
|
13
|
-
const clientEntryFilePath = definedAtInfo.filePath;
|
|
14
|
-
return clientEntryFilePath;
|
|
8
|
+
return configValue.value;
|
|
15
9
|
}
|
|
@@ -9,13 +9,12 @@ import type { PageFile } from './getPageFileObject.js';
|
|
|
9
9
|
type ExportsAll = Record<string, {
|
|
10
10
|
exportValue: unknown;
|
|
11
11
|
exportSource: string;
|
|
12
|
+
filePath: string | null;
|
|
12
13
|
/** @deprecated */
|
|
13
14
|
_fileType: FileType | null;
|
|
14
15
|
/** @deprecated */
|
|
15
16
|
_isFromDefaultExport: boolean | null;
|
|
16
17
|
/** @deprecated */
|
|
17
|
-
filePath: string | null;
|
|
18
|
-
/** @deprecated */
|
|
19
18
|
_filePath: string | null;
|
|
20
19
|
}[]>;
|
|
21
20
|
/** All the config's values (including overriden ones) and where they come from.
|
|
@@ -3,7 +3,7 @@ export { getExports };
|
|
|
3
3
|
import { isScriptFile, isTemplateFile } from '../../utils/isScriptFile.js';
|
|
4
4
|
import { assert, hasProp, isObject, assertWarning, assertUsage, makeLast, isBrowser } from '../utils.js';
|
|
5
5
|
import { assertDefaultExports, forbiddenDefaultExports } from './assert_exports_old_design.js';
|
|
6
|
-
import { getConfigDefinedAtString } from '../page-configs/utils.js';
|
|
6
|
+
import { getConfigDefinedAtString, getConfigValueFilePathToShowToUser } from '../page-configs/utils.js';
|
|
7
7
|
import pc from '@brillout/picocolors';
|
|
8
8
|
function getExports(pageFiles, pageConfig) {
|
|
9
9
|
const configEntries = {};
|
|
@@ -29,11 +29,8 @@ function getExports(pageFiles, pageConfig) {
|
|
|
29
29
|
// V1 design
|
|
30
30
|
if (pageConfig) {
|
|
31
31
|
Object.entries(pageConfig.configValues).forEach(([configName, configValue]) => {
|
|
32
|
-
const { value
|
|
33
|
-
|
|
34
|
-
if (definedAtInfo) {
|
|
35
|
-
filePath = definedAtInfo.filePath;
|
|
36
|
-
}
|
|
32
|
+
const { value } = configValue;
|
|
33
|
+
const filePath = getConfigValueFilePathToShowToUser(configValue);
|
|
37
34
|
const configDefinedAt = getConfigDefinedAtString(configName, configValue, true);
|
|
38
35
|
config[configName] = config[configName] ?? value;
|
|
39
36
|
configEntries[configName] = configEntries[configName] ?? [];
|
|
@@ -2,6 +2,7 @@ export { parsePageConfigsSerialized };
|
|
|
2
2
|
import { parse } from '@brillout/json-serializer/parse';
|
|
3
3
|
import { parseConfigValuesImported } from '../page-configs/parseConfigValuesImported.js';
|
|
4
4
|
import { assert, assertUsage, isCallable } from '../utils.js';
|
|
5
|
+
import { getConfigDefinedAtString } from '../page-configs/utils.js';
|
|
5
6
|
function parsePageConfigsSerialized(pageConfigsSerialized, pageConfigGlobalSerialized) {
|
|
6
7
|
const pageConfigs = pageConfigsSerialized.map((pageConfigSerialized) => {
|
|
7
8
|
const configValues = {};
|
|
@@ -9,12 +10,12 @@ function parsePageConfigsSerialized(pageConfigsSerialized, pageConfigGlobalSeria
|
|
|
9
10
|
const { configValuesSerialized } = pageConfigSerialized;
|
|
10
11
|
Object.entries(configValuesSerialized).forEach(([configName, configValueSeriliazed]) => {
|
|
11
12
|
{
|
|
12
|
-
const { valueSerialized,
|
|
13
|
+
const { valueSerialized, definedAt } = configValueSeriliazed;
|
|
13
14
|
assert(valueSerialized);
|
|
14
15
|
assert(!configValues[configName]);
|
|
15
16
|
configValues[configName] = {
|
|
16
17
|
value: parse(valueSerialized),
|
|
17
|
-
|
|
18
|
+
definedAt
|
|
18
19
|
};
|
|
19
20
|
}
|
|
20
21
|
});
|
|
@@ -42,12 +43,14 @@ function parsePageConfigsSerialized(pageConfigsSerialized, pageConfigGlobalSeria
|
|
|
42
43
|
return { pageConfigs, pageConfigGlobal };
|
|
43
44
|
}
|
|
44
45
|
function assertRouteConfigValue(configValues) {
|
|
45
|
-
|
|
46
|
+
const configName = 'route';
|
|
47
|
+
const configValue = configValues[configName];
|
|
48
|
+
if (!configValue)
|
|
46
49
|
return;
|
|
47
|
-
const { value
|
|
50
|
+
const { value } = configValue;
|
|
48
51
|
const configValueType = typeof value;
|
|
49
|
-
|
|
50
|
-
assertUsage(configValueType === 'string' || isCallable(value), `${
|
|
52
|
+
const configDefinedAt = getConfigDefinedAtString(configName, configValue, true);
|
|
53
|
+
assertUsage(configValueType === 'string' || isCallable(value), `${configDefinedAt} has an invalid type '${configValueType}': it should be a string or a function instead, see https://vike.dev/route`);
|
|
51
54
|
/* We don't use assertRouteString() in order to avoid unnecessarily bloating the client-side bundle when using Server Routing:
|
|
52
55
|
* - When using Server Routing, this file is loaded => loading assertRouteString() would bloat the client bundle.
|
|
53
56
|
* - assertRouteString() is already called on the server-side
|
|
@@ -11,7 +11,9 @@ function getHook(pageContext, hookName) {
|
|
|
11
11
|
assert(file.exportValue === hookFn);
|
|
12
12
|
if (hookFn === null)
|
|
13
13
|
return null;
|
|
14
|
-
const hookFilePath = file.
|
|
14
|
+
const hookFilePath = file.filePath;
|
|
15
|
+
assert(hookFilePath);
|
|
16
|
+
assert(!hookFilePath.endsWith(' '));
|
|
15
17
|
assertHookFn(hookFn, { hookName, hookFilePath });
|
|
16
18
|
return { hookFn, hookName, hookFilePath };
|
|
17
19
|
}
|
|
@@ -14,8 +14,10 @@ export type { ConfigValueImported };
|
|
|
14
14
|
export type { ConfigValues };
|
|
15
15
|
export type { ConfigValueSource };
|
|
16
16
|
export type { ConfigValueSources };
|
|
17
|
-
export type {
|
|
17
|
+
export type { DefinedAt };
|
|
18
|
+
export type { DefinedAtInfoNew };
|
|
18
19
|
export type { DefinedAtInfoFull };
|
|
20
|
+
export type { DefinedAtInfoFull as DefinedAtInfo };
|
|
19
21
|
type PageConfigBase = {
|
|
20
22
|
pageId: string;
|
|
21
23
|
isErrorPage?: true;
|
|
@@ -70,7 +72,7 @@ type ConfigValueSource = {
|
|
|
70
72
|
valueIsFilePath?: true;
|
|
71
73
|
} & ({
|
|
72
74
|
isComputed: false;
|
|
73
|
-
definedAtInfo:
|
|
75
|
+
definedAtInfo: DefinedAtInfoFull;
|
|
74
76
|
} | {
|
|
75
77
|
isComputed: true;
|
|
76
78
|
definedAtInfo: null;
|
|
@@ -79,21 +81,43 @@ type ConfigValueSource = {
|
|
|
79
81
|
type ConfigValueSources = Record<string, ConfigValueSource[]>;
|
|
80
82
|
type ConfigValue = {
|
|
81
83
|
value: unknown;
|
|
82
|
-
|
|
84
|
+
definedAt: DefinedAt;
|
|
83
85
|
};
|
|
84
86
|
type ConfigValueSerialized = {
|
|
85
87
|
valueSerialized: string;
|
|
86
|
-
|
|
88
|
+
definedAt: DefinedAt;
|
|
87
89
|
};
|
|
88
90
|
type ConfigValues = Record<string, ConfigValue>;
|
|
89
|
-
type
|
|
90
|
-
|
|
91
|
-
|
|
91
|
+
type DefinedAt = {
|
|
92
|
+
source: DefinedAtInfoNew;
|
|
93
|
+
isEffect?: true;
|
|
94
|
+
isComputed?: undefined;
|
|
95
|
+
isCumulative?: undefined;
|
|
96
|
+
} | {
|
|
97
|
+
isCumulative: true;
|
|
98
|
+
sources: DefinedAtInfoNew[];
|
|
99
|
+
isEffect?: undefined;
|
|
100
|
+
isComputed?: undefined;
|
|
101
|
+
} | {
|
|
102
|
+
isComputed: true;
|
|
103
|
+
isEffect?: undefined;
|
|
104
|
+
isCumulative?: undefined;
|
|
92
105
|
};
|
|
93
|
-
type
|
|
94
|
-
|
|
106
|
+
type DefinedAtInfoNew = {
|
|
107
|
+
filePathToShowToUser: string;
|
|
108
|
+
fileExportPath: null | string[];
|
|
109
|
+
};
|
|
110
|
+
type DefinedAtInfoFull = ({
|
|
111
|
+
filePathRelativeToUserRootDir: string;
|
|
95
112
|
filePathAbsolute: string;
|
|
96
|
-
|
|
113
|
+
importPathAbsolute: null;
|
|
114
|
+
} | {
|
|
115
|
+
filePathRelativeToUserRootDir: null;
|
|
116
|
+
filePathAbsolute: string | null;
|
|
117
|
+
importPathAbsolute: string;
|
|
118
|
+
}) & {
|
|
119
|
+
exportName?: string;
|
|
120
|
+
fileExportPath: null | string[];
|
|
97
121
|
};
|
|
98
122
|
type ConfigSource = {
|
|
99
123
|
configSourceFile: string;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { getExportPath };
|
|
2
|
-
declare function getExportPath(fileExportPath: string[]): null | string;
|
|
2
|
+
declare function getExportPath(fileExportPath: null | string[]): null | string;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export { getExportPath };
|
|
2
2
|
import { assert } from '../utils.js';
|
|
3
|
-
// TODO: return null instead of 'export default'
|
|
4
|
-
// - Also return null insead of 'export *'?
|
|
5
3
|
function getExportPath(fileExportPath) {
|
|
4
|
+
if (!fileExportPath)
|
|
5
|
+
return null;
|
|
6
6
|
let prefix = '';
|
|
7
7
|
let suffix = '';
|
|
8
8
|
let [exportName, ...exportObjectPath] = fileExportPath;
|
|
@@ -4,15 +4,18 @@ import { assertExportsOfValueFile } from './assertExports.js';
|
|
|
4
4
|
import pc from '@brillout/picocolors';
|
|
5
5
|
function parseConfigValuesImported(configValuesImported) {
|
|
6
6
|
const configValues = {};
|
|
7
|
-
const addConfigValue = (configName, value,
|
|
7
|
+
const addConfigValue = (configName, value, importPath, exportName) => {
|
|
8
8
|
configValues[configName] = {
|
|
9
9
|
value,
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
definedAt: {
|
|
11
|
+
source: {
|
|
12
|
+
// importPath is always relative the user's root directory (it cannot be relative to the current file since the current file is a virtual file)
|
|
13
|
+
filePathToShowToUser: importPath,
|
|
14
|
+
fileExportPath: [exportName]
|
|
15
|
+
}
|
|
13
16
|
}
|
|
14
17
|
};
|
|
15
|
-
assertIsNotNull(value, configName,
|
|
18
|
+
assertIsNotNull(value, configName, importPath);
|
|
16
19
|
};
|
|
17
20
|
configValuesImported.forEach((configValueLoaded) => {
|
|
18
21
|
if (configValueLoaded.isValueFile) {
|
|
@@ -1,29 +1,35 @@
|
|
|
1
1
|
export { getConfigValue };
|
|
2
2
|
export { getPageConfig };
|
|
3
3
|
export { getConfigDefinedAtString };
|
|
4
|
-
export { getConfigDefinedAtInfo };
|
|
5
4
|
export { getDefinedAtString };
|
|
6
|
-
|
|
5
|
+
export { getConfigValueFilePathToShowToUser };
|
|
6
|
+
export { getHookFilePathToShowToUser };
|
|
7
|
+
import type { PageConfigRuntime, PageConfigBuildTime, ConfigValue, DefinedAt } from './PageConfig.js';
|
|
7
8
|
import type { ConfigNameBuiltIn } from './Config.js';
|
|
8
9
|
type PageConfigCommon = PageConfigRuntime | PageConfigBuildTime;
|
|
9
10
|
type ConfigName = ConfigNameBuiltIn;
|
|
10
|
-
declare function getConfigValue(pageConfig: PageConfigCommon, configName: ConfigName, type: 'string'): null | {
|
|
11
|
+
declare function getConfigValue(pageConfig: PageConfigCommon, configName: ConfigName, type: 'string'): null | ConfigValue & {
|
|
11
12
|
value: string;
|
|
12
13
|
};
|
|
13
|
-
declare function getConfigValue(pageConfig: PageConfigCommon, configName: ConfigName, type: 'boolean'): null | {
|
|
14
|
+
declare function getConfigValue(pageConfig: PageConfigCommon, configName: ConfigName, type: 'boolean'): null | ConfigValue & {
|
|
14
15
|
value: boolean;
|
|
15
16
|
};
|
|
16
|
-
declare function getConfigValue(pageConfig: PageConfigCommon, configName: ConfigName): null | {
|
|
17
|
+
declare function getConfigValue(pageConfig: PageConfigCommon, configName: ConfigName): null | ConfigValue & {
|
|
17
18
|
value: unknown;
|
|
18
19
|
};
|
|
19
|
-
declare function getConfigDefinedAtInfo(pageConfig: PageConfigCommon, configName: ConfigName): DefinedAtInfo;
|
|
20
20
|
declare function getPageConfig(pageId: string, pageConfigs: PageConfigRuntime[]): PageConfigRuntime;
|
|
21
|
-
type ConfigDefinedAtUppercase<ConfigName extends string> = `Config ${ConfigName}${string}`;
|
|
22
|
-
type ConfigDefinedAtLowercase<ConfigName extends string> = `config ${ConfigName}${string}`;
|
|
23
|
-
declare function getConfigDefinedAtString<ConfigName extends string>(configName: ConfigName, {
|
|
24
|
-
|
|
21
|
+
type ConfigDefinedAtUppercase<ConfigName extends string> = `Config ${ConfigName} defined ${string}`;
|
|
22
|
+
type ConfigDefinedAtLowercase<ConfigName extends string> = `config ${ConfigName} defined ${string}`;
|
|
23
|
+
declare function getConfigDefinedAtString<ConfigName extends string>(configName: ConfigName, { definedAt }: {
|
|
24
|
+
definedAt: DefinedAt;
|
|
25
25
|
}, sentenceBegin: true, append?: 'effect'): ConfigDefinedAtUppercase<ConfigName>;
|
|
26
|
-
declare function getConfigDefinedAtString<ConfigName extends string>(configName: ConfigName, {
|
|
27
|
-
|
|
26
|
+
declare function getConfigDefinedAtString<ConfigName extends string>(configName: ConfigName, { definedAt }: {
|
|
27
|
+
definedAt: DefinedAt;
|
|
28
28
|
}, sentenceBegin: false, append?: 'effect'): ConfigDefinedAtLowercase<ConfigName>;
|
|
29
|
-
declare function getDefinedAtString(
|
|
29
|
+
declare function getDefinedAtString(configValue: ConfigValue): string;
|
|
30
|
+
declare function getConfigValueFilePathToShowToUser({ definedAt }: {
|
|
31
|
+
definedAt: DefinedAt;
|
|
32
|
+
}): null | string;
|
|
33
|
+
declare function getHookFilePathToShowToUser({ definedAt }: {
|
|
34
|
+
definedAt: DefinedAt;
|
|
35
|
+
}): string;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
export { getConfigValue };
|
|
2
2
|
export { getPageConfig };
|
|
3
3
|
export { getConfigDefinedAtString };
|
|
4
|
-
export { getConfigDefinedAtInfo };
|
|
5
4
|
export { getDefinedAtString };
|
|
5
|
+
export { getConfigValueFilePathToShowToUser };
|
|
6
|
+
export { getHookFilePathToShowToUser };
|
|
6
7
|
import { assert, assertUsage, getValuePrintable } from '../utils.js';
|
|
7
8
|
import pc from '@brillout/picocolors';
|
|
8
9
|
import { getExportPath } from './getExportPath.js';
|
|
@@ -11,31 +12,29 @@ function getConfigValue(pageConfig, configName, type) {
|
|
|
11
12
|
const configValue = getConfigValueEntry(pageConfig, configName);
|
|
12
13
|
if (configValue === null)
|
|
13
14
|
return null;
|
|
14
|
-
const { value,
|
|
15
|
+
const { value, definedAt } = configValue;
|
|
15
16
|
if (type)
|
|
16
|
-
assertConfigValueType(value, type, configName,
|
|
17
|
-
return
|
|
17
|
+
assertConfigValueType(value, type, configName, definedAt);
|
|
18
|
+
return configValue;
|
|
18
19
|
}
|
|
19
|
-
function
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
return definedAtInfo;
|
|
20
|
+
function assertConfigValueType(value, type, configName, definedAt) {
|
|
21
|
+
assert(value !== null);
|
|
22
|
+
const typeActual = typeof value;
|
|
23
|
+
if (typeActual === type)
|
|
24
|
+
return;
|
|
25
|
+
const valuePrintable = getValuePrintable(value);
|
|
26
|
+
const problem = valuePrintable !== null ? `value ${pc.cyan(valuePrintable)}` : `type ${pc.cyan(typeActual)}`;
|
|
27
|
+
const configDefinedAt = getConfigDefinedAtString(configName, { definedAt }, true);
|
|
28
|
+
assertUsage(false, `${configDefinedAt} has an invalid ${problem}: it should be a ${pc.cyan(type)} instead`);
|
|
29
29
|
}
|
|
30
30
|
function getConfigValueEntry(pageConfig, configName) {
|
|
31
31
|
const configValue = pageConfig.configValues[configName];
|
|
32
32
|
if (!configValue)
|
|
33
33
|
return null;
|
|
34
|
-
const { value, definedAtInfo } = configValue;
|
|
35
34
|
// Enable users to suppress global config values by setting the local config value to null
|
|
36
|
-
if (value === null)
|
|
35
|
+
if (configValue.value === null)
|
|
37
36
|
return null;
|
|
38
|
-
return
|
|
37
|
+
return configValue;
|
|
39
38
|
}
|
|
40
39
|
function getPageConfig(pageId, pageConfigs) {
|
|
41
40
|
const pageConfig = pageConfigs.find((p) => p.pageId === pageId);
|
|
@@ -43,32 +42,57 @@ function getPageConfig(pageId, pageConfigs) {
|
|
|
43
42
|
assert(pageConfig);
|
|
44
43
|
return pageConfig;
|
|
45
44
|
}
|
|
46
|
-
function
|
|
47
|
-
|
|
48
|
-
const typeActual = typeof value;
|
|
49
|
-
if (typeActual === type)
|
|
50
|
-
return;
|
|
51
|
-
const valuePrintable = getValuePrintable(value);
|
|
52
|
-
const problem = valuePrintable !== null ? `value ${pc.cyan(valuePrintable)}` : `type ${pc.cyan(typeActual)}`;
|
|
53
|
-
const configDefinedAt = getConfigDefinedAtString(configName, { definedAtInfo }, true);
|
|
54
|
-
assertUsage(false, `${configDefinedAt} has an invalid ${problem}: it should be a ${pc.cyan(type)} instead`);
|
|
55
|
-
}
|
|
56
|
-
function getConfigDefinedAtString(configName, { definedAtInfo }, sentenceBegin, append) {
|
|
57
|
-
let configDefinedAt = `${sentenceBegin ? `Config` : `config`} ${pc.cyan(configName)}`;
|
|
58
|
-
if (definedAtInfo !== null) {
|
|
59
|
-
configDefinedAt = `${configDefinedAt} defined at ${getDefinedAtString(definedAtInfo, append)}`;
|
|
60
|
-
}
|
|
45
|
+
function getConfigDefinedAtString(configName, { definedAt }, sentenceBegin) {
|
|
46
|
+
const configDefinedAt = `${sentenceBegin ? `Config` : `config`} ${pc.cyan(configName)} defined ${getSourceString(definedAt)}`;
|
|
61
47
|
return configDefinedAt;
|
|
62
48
|
}
|
|
63
|
-
function
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
const exportPath = getExportPath(fileExportPath);
|
|
67
|
-
if (exportPath) {
|
|
68
|
-
definedAt = `${definedAt} > ${pc.cyan(exportPath)}`;
|
|
49
|
+
function getSourceString(definedAt) {
|
|
50
|
+
if (definedAt.isComputed) {
|
|
51
|
+
return 'internally';
|
|
69
52
|
}
|
|
70
|
-
|
|
71
|
-
|
|
53
|
+
let sources;
|
|
54
|
+
if (definedAt.isCumulative) {
|
|
55
|
+
sources = definedAt.sources;
|
|
72
56
|
}
|
|
73
|
-
|
|
57
|
+
else {
|
|
58
|
+
sources = [definedAt.source];
|
|
59
|
+
}
|
|
60
|
+
assert(sources.length >= 1);
|
|
61
|
+
const sourceString = sources
|
|
62
|
+
.map((source) => {
|
|
63
|
+
const { filePathToShowToUser, fileExportPath } = source;
|
|
64
|
+
let s = filePathToShowToUser;
|
|
65
|
+
const exportPath = getExportPath(fileExportPath);
|
|
66
|
+
if (exportPath) {
|
|
67
|
+
s = `${s} > ${pc.cyan(exportPath)}`;
|
|
68
|
+
}
|
|
69
|
+
if (definedAt.isEffect) {
|
|
70
|
+
s = `${s} > (${pc.blue('effect')})`;
|
|
71
|
+
}
|
|
72
|
+
return s;
|
|
73
|
+
})
|
|
74
|
+
.join(' / ');
|
|
75
|
+
return `at ${sourceString}`;
|
|
76
|
+
}
|
|
77
|
+
function getDefinedAtString(configValue) {
|
|
78
|
+
let sourceString = getSourceString(configValue.definedAt);
|
|
79
|
+
if (sourceString.startsWith('at '))
|
|
80
|
+
sourceString = sourceString.slice('at '.length);
|
|
81
|
+
return sourceString;
|
|
82
|
+
}
|
|
83
|
+
function getConfigValueFilePathToShowToUser({ definedAt }) {
|
|
84
|
+
// A unique file path only exists if the config value isn't cumulative nor computed:
|
|
85
|
+
// - cumulative config values have multiple file paths
|
|
86
|
+
// - computed values don't have any file path
|
|
87
|
+
if (definedAt.isComputed || definedAt.isCumulative)
|
|
88
|
+
return null;
|
|
89
|
+
const { source } = definedAt;
|
|
90
|
+
const { filePathToShowToUser } = source;
|
|
91
|
+
assert(filePathToShowToUser);
|
|
92
|
+
return filePathToShowToUser;
|
|
93
|
+
}
|
|
94
|
+
function getHookFilePathToShowToUser({ definedAt }) {
|
|
95
|
+
const filePathToShowToUser = getConfigValueFilePathToShowToUser({ definedAt });
|
|
96
|
+
assert(filePathToShowToUser);
|
|
97
|
+
return filePathToShowToUser;
|
|
74
98
|
}
|
|
@@ -3,7 +3,7 @@ import { isErrorPageId } from '../error-page.js';
|
|
|
3
3
|
import { assert, assertUsage, hasProp, slice } from './utils.js';
|
|
4
4
|
import { deduceRouteStringFromFilesystemPath } from './deduceRouteStringFromFilesystemPath.js';
|
|
5
5
|
import { isCallable } from '../utils.js';
|
|
6
|
-
import {
|
|
6
|
+
import { getConfigValue, getDefinedAtString, getHookFilePathToShowToUser } from '../page-configs/utils.js';
|
|
7
7
|
import { warnDeprecatedAllowKey } from './resolveRouteFunction.js';
|
|
8
8
|
async function loadPageRoutes(
|
|
9
9
|
// TODO: remove all arguments and use GlobalContext instead
|
|
@@ -30,9 +30,8 @@ function getPageRoutes(filesystemRoots, pageFilesAll, pageConfigs, allPageIds) {
|
|
|
30
30
|
const configName = 'route';
|
|
31
31
|
const configValue = getConfigValue(pageConfig, configName);
|
|
32
32
|
if (configValue) {
|
|
33
|
-
const definedAtInfo = getConfigDefinedAtInfo(pageConfig, configName);
|
|
34
33
|
const route = configValue.value;
|
|
35
|
-
const definedAt = getDefinedAtString(
|
|
34
|
+
const definedAt = getDefinedAtString(configValue);
|
|
36
35
|
if (typeof route === 'string') {
|
|
37
36
|
pageRoute = {
|
|
38
37
|
pageId,
|
|
@@ -138,10 +137,10 @@ function getGlobalHooks(pageFilesAll, pageConfigs, pageConfigGlobal) {
|
|
|
138
137
|
// V1 Design
|
|
139
138
|
if (pageConfigs.length > 0) {
|
|
140
139
|
if (pageConfigGlobal.configValues.onBeforeRoute?.value) {
|
|
141
|
-
const
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
140
|
+
const configValue = pageConfigGlobal.configValues.onBeforeRoute;
|
|
141
|
+
const { value: hookFn } = configValue;
|
|
142
|
+
const hookFilePath = getHookFilePathToShowToUser(configValue);
|
|
143
|
+
// TODO: use getConfigDefinedAtString()
|
|
145
144
|
assertUsage(isCallable(hookFn), `The hook onBeforeRoute() defined by ${hookFilePath} should be a function.`);
|
|
146
145
|
const onBeforeRouteHook = {
|
|
147
146
|
hookFilePath: hookFilePath,
|