vike 0.4.142-commit-acfc159 → 0.4.143

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.
Files changed (39) hide show
  1. package/dist/cjs/node/plugin/plugins/buildConfig.js +4 -5
  2. package/dist/cjs/node/plugin/plugins/commonConfig.js +1 -6
  3. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +3 -0
  4. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigs.js +21 -18
  5. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/transpileAndExecuteFile.js +5 -3
  6. package/dist/cjs/node/runtime/html/stream.js +4 -1
  7. package/dist/cjs/node/shared/virtual-files/virtualFilePageConfigValuesAll.js +1 -1
  8. package/dist/cjs/shared/getPageFiles/parseGlobResults.js +15 -15
  9. package/dist/cjs/shared/page-configs/utils.js +1 -1
  10. package/dist/cjs/shared/route/resolvePrecedence.js +32 -11
  11. package/dist/cjs/shared/route/resolveRouteString.js +99 -43
  12. package/dist/cjs/shared/utils.js +1 -0
  13. package/dist/cjs/types/defineConfig.js +7 -0
  14. package/dist/cjs/types/index.js +3 -0
  15. package/dist/cjs/utils/projectInfo.js +1 -1
  16. package/dist/esm/client/client-routing-runtime/prefetch.js +3 -1
  17. package/dist/esm/node/plugin/plugins/buildConfig.js +4 -5
  18. package/dist/esm/node/plugin/plugins/commonConfig.js +1 -6
  19. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +3 -0
  20. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigs.d.ts +3 -0
  21. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigs.js +20 -17
  22. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/transpileAndExecuteFile.js +6 -4
  23. package/dist/esm/node/runtime/html/stream.js +4 -1
  24. package/dist/esm/node/shared/virtual-files/virtualFilePageConfigValuesAll.js +1 -1
  25. package/dist/esm/shared/getPageFiles/parseGlobResults.js +15 -15
  26. package/dist/esm/shared/page-configs/PageConfig.d.ts +1 -0
  27. package/dist/esm/shared/page-configs/utils.js +1 -1
  28. package/dist/esm/shared/route/resolvePrecedence.js +33 -12
  29. package/dist/esm/shared/route/resolveRouteString.d.ts +21 -4
  30. package/dist/esm/shared/route/resolveRouteString.js +98 -42
  31. package/dist/esm/shared/utils.d.ts +1 -0
  32. package/dist/esm/shared/utils.js +1 -0
  33. package/dist/esm/types/defineConfig.d.ts +3 -0
  34. package/dist/esm/types/defineConfig.js +4 -0
  35. package/dist/esm/types/index.d.ts +1 -0
  36. package/dist/esm/types/index.js +1 -1
  37. package/dist/esm/utils/projectInfo.d.ts +1 -1
  38. package/dist/esm/utils/projectInfo.js +1 -1
  39. package/package.json +2 -2
@@ -53,8 +53,10 @@ function buildConfig() {
53
53
  },
54
54
  async writeBundle(options, bundle) {
55
55
  const manifestEntry = bundle[manifestTempFile];
56
- if (generateManifest) {
57
- (0, utils_js_1.assert)(manifestEntry);
56
+ /* Fails with @vitejs/plugin-legacy because writeBundle() is called twice during the client build (once for normal client assets and a second time for legacy assets), see reproduction at https://github.com/vikejs/vike/issues/1154
57
+ assert(generateManifest === !!manifestEntry)
58
+ */
59
+ if (manifestEntry) {
58
60
  const { dir } = options;
59
61
  (0, utils_js_1.assert)(dir);
60
62
  const manifestFilePathOld = path_1.default.join(dir, manifestEntry.fileName);
@@ -64,9 +66,6 @@ function buildConfig() {
64
66
  const manifestFilePathNew = path_1.default.join(dir, '..', 'assets.json');
65
67
  await promises_1.default.rename(manifestFilePathOld, manifestFilePathNew);
66
68
  }
67
- else {
68
- (0, utils_js_1.assert)(!manifestEntry);
69
- }
70
69
  }
71
70
  };
72
71
  }
@@ -19,12 +19,7 @@ function commonConfig() {
19
19
  {
20
20
  name: 'vike-commonConfig-1',
21
21
  config: () => ({
22
- appType: 'custom',
23
- ssr: {
24
- // Needed as long as Vike is published as CJS.
25
- // TODO: can we remove this once Vike is published as ESM?
26
- external: ['vike', 'vike/server']
27
- }
22
+ appType: 'custom'
28
23
  }),
29
24
  configResolved(config) {
30
25
  (0, require_shim_1.installRequireShim_setUserRootDir)(config.root);
@@ -18,6 +18,7 @@ const removeSuperfluousViteLog_js_1 = require("../../../shared/loggerVite/remove
18
18
  const getFilePathToShowToUser_js_1 = require("./getFilePathToShowToUser.js");
19
19
  const picocolors_1 = __importDefault(require("@brillout/picocolors"));
20
20
  const utils_js_2 = require("../../../../../shared/page-configs/utils.js");
21
+ const getVirtualFilePageConfigs_js_1 = require("./getVirtualFilePageConfigs.js");
21
22
  (0, utils_js_1.assertIsNotProductionRuntime)();
22
23
  let devServerIsCorrupt = false;
23
24
  let wasConfigInvalid = null;
@@ -1078,6 +1079,8 @@ function mergeCumulative(configName, configValueSources) {
1078
1079
  /* This is more confusing than adding value. For example, this explanation shouldn't be shown for the passToClient config.
1079
1080
  const explanation = `(Because the values of ${configNameColored} are cumulative and therefore merged together.)` as const
1080
1081
  */
1082
+ // Make sure configValueSource.value is serializable
1083
+ (0, getVirtualFilePageConfigs_js_1.getConfigValueSerialized)(configValueSource.value, configName, configValueSource.definedAtInfo);
1081
1084
  const assertNoMixing = (isSet) => {
1082
1085
  const vals1 = isSet ? valuesSet : valuesArr;
1083
1086
  const t1 = isSet ? 'a Set' : 'an array';
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.getVirtualFilePageConfigs = void 0;
6
+ exports.getConfigValueSerialized = exports.getVirtualFilePageConfigs = void 0;
7
7
  const utils_js_1 = require("../../../utils.js");
8
8
  const generateEagerImport_js_1 = require("../generateEagerImport.js");
9
9
  const virtualFilePageConfigValuesAll_js_1 = require("../../../../shared/virtual-files/virtualFilePageConfigValuesAll.js");
@@ -39,23 +39,22 @@ function getContent(pageConfigs, pageConfigGlobal, isForClientSide, isDev, id, i
39
39
  if (!(0, isConfigEnvMatch_js_1.isConfigEnvMatch)(configEnv, isForClientSide, isClientRouting))
40
40
  return;
41
41
  const { value, definedAtInfo } = configValue;
42
- // TODO: use @brillout/json-serializer
43
- // - re-use getConfigValueSerialized()?
44
- const valueSerialized = JSON.stringify(value);
45
- serializeConfigValue(lines, configName, { definedAtInfo }, valueSerialized);
42
+ const valueSerialized = getConfigValueSerialized(value, configName, definedAtInfo);
43
+ const configValue2 = { definedAtInfo, valueSerialized };
44
+ serializeConfigValue(lines, configName, configValue2);
46
45
  }
47
46
  else {
48
47
  const configValueSource = sources[0];
49
48
  (0, utils_js_1.assert)(configValueSource);
50
49
  if (configValueSource.configEnv === '_routing-eager') {
51
50
  const { definedAtInfo } = configValueSource;
52
- const configValue = { configName, definedAtInfo };
53
51
  (0, utils_js_1.assert)(!configValueSource.isComputed);
54
52
  const { filePath, fileExportPath } = configValueSource.definedAtInfo;
55
53
  const [exportName] = fileExportPath;
56
54
  (0, utils_js_1.assert)(exportName);
57
55
  const configValueEagerImport = getConfigValueEagerImport(filePath, exportName, importStatements);
58
- serializeConfigValue(lines, configName, configValue, configValueEagerImport);
56
+ const configValue = { definedAtInfo, value: configValueEagerImport };
57
+ serializeConfigValue(lines, configName, configValue);
59
58
  }
60
59
  }
61
60
  });
@@ -94,16 +93,13 @@ function getContent(pageConfigs, pageConfigGlobal, isForClientSide, isDev, id, i
94
93
  (0, debug_js_1.debug)(id, isForClientSide ? 'CLIENT-SIDE' : 'SERVER-SIDE', code);
95
94
  return code;
96
95
  }
97
- function serializeConfigValue(lines, configName, configValue, valueSerialized) {
96
+ function serializeConfigValue(lines, configName, configValue) {
98
97
  let whitespace = ' ';
99
98
  lines.push(`${whitespace}['${configName}']: {`);
100
99
  whitespace += ' ';
101
- lines.push(`${whitespace} value: ${valueSerialized},`);
102
100
  Object.entries(configValue).forEach(([key, val]) => {
103
- if (key === 'value')
104
- return;
105
- // if (val === undefined) return
106
- lines.push(`${whitespace} ${key}: ${JSON.stringify(val)},`);
101
+ const valSerialized = key === 'value' || key === 'valueSerialized' ? val : JSON.stringify(val);
102
+ lines.push(`${whitespace} ${key}: ${valSerialized},`);
107
103
  });
108
104
  whitespace = whitespace.slice(2);
109
105
  lines.push(`${whitespace}},`);
@@ -119,7 +115,7 @@ function serializeConfigValueSource(configValueSource, configName, whitespace, i
119
115
  if ((0, isConfigEnvMatch_js_1.isConfigEnvMatch)(configEnv, isForClientSide, isClientRouting) || eager) {
120
116
  if ('value' in configValueSource) {
121
117
  const { value } = configValueSource;
122
- const valueSerialized = getConfigValueSerialized(value, configName, definedAtInfo.filePath);
118
+ const valueSerialized = getConfigValueSerialized(value, configName, definedAtInfo);
123
119
  lines.push(`${whitespace} valueSerialized: ${valueSerialized}`);
124
120
  }
125
121
  else if (eager) {
@@ -133,7 +129,7 @@ function serializeConfigValueSource(configValueSource, configName, whitespace, i
133
129
  lines.push(`${whitespace}},`);
134
130
  return lines.join('\n');
135
131
  }
136
- function getConfigValueSerialized(value, configName, configDefinedByFile) {
132
+ function getConfigValueSerialized(value, configName, definedAtInfo) {
137
133
  let configValueSerialized;
138
134
  const valueName = `config${(0, utils_js_1.getPropAccessNotation)(configName)}`;
139
135
  try {
@@ -141,15 +137,22 @@ function getConfigValueSerialized(value, configName, configDefinedByFile) {
141
137
  }
142
138
  catch (err) {
143
139
  (0, utils_js_1.assert)((0, utils_js_1.hasProp)(err, 'messageCore', 'string'));
140
+ // definedAtInfo is null when config value is:
141
+ // - computed => all computed values defined by Vike can are serializable
142
+ // - cumulative => the values are already ensured to be serializable
143
+ (0, utils_js_1.assert)(definedAtInfo);
144
+ const configDefinedByFile = definedAtInfo.filePath;
145
+ (0, utils_js_1.assert)(configDefinedByFile);
144
146
  (0, utils_js_1.assertUsage)(false, [
145
- `The value of the config ${picocolors_1.default.cyan(configName)} cannot be defined inside the file ${configDefinedByFile}.`,
146
- `Its value must be defined in an another file and then imported by ${configDefinedByFile} (because it isn't serializable: ${err.messageCore}).`,
147
- `Only serializable config values can be defined inside ${configDefinedByFile}, see https://vike.dev/header-file.`
147
+ `The value of the config ${picocolors_1.default.cyan(configName)} cannot be defined inside the file ${configDefinedByFile}:`,
148
+ `its value must be defined in an another file and then imported by ${configDefinedByFile}. (Because the value isn't serializable: ${err.messageCore}.)`,
149
+ `Only serializable config values can be defined inside +config.h.js files, see https://vike.dev/header-file.`
148
150
  ].join(' '));
149
151
  }
150
152
  configValueSerialized = JSON.stringify(configValueSerialized);
151
153
  return configValueSerialized;
152
154
  }
155
+ exports.getConfigValueSerialized = getConfigValueSerialized;
153
156
  function getConfigValueEagerImport(importFilePath, exportName, importStatements) {
154
157
  let configValueEagerImport;
155
158
  const { importVar, importStatement } = (0, generateEagerImport_js_1.generateEagerImport)(importFilePath);
@@ -55,7 +55,9 @@ function transpileImports(codeOriginal, filePath, isValueFile) {
55
55
  const { code, fileImports } = res;
56
56
  if (!isHeader) {
57
57
  const filePathCorrect = appendHeaderFileExtension(filePathToShowToUser);
58
- (0, utils_js_1.assertWarning)(false, `Rename ${filePathToShowToUser} to ${filePathCorrect}, see https://vike.dev/header-file`, { onlyOnce: true });
58
+ (0, utils_js_1.assertWarning)(false, `Rename ${filePathToShowToUser} to ${filePathCorrect}, see https://vike.dev/header-file`, {
59
+ onlyOnce: true
60
+ });
59
61
  }
60
62
  return { code, fileImports };
61
63
  }
@@ -231,11 +233,11 @@ function assertFileImports(fileImports, fileExports, filePath) {
231
233
  const importStatements = (0, utils_js_1.unique)(fileImportsUnused.map((fi) => fi.importStatementCode));
232
234
  const importNamesUnused = fileImportsUnused.map((fi) => picocolors_1.default.cyan(fi.importLocalName)).join(', ');
233
235
  const singular = fileImportsUnused.length === 1;
234
- (0, utils_js_1.assertWarning)(fileImportsUnused.length === 0, [
236
+ (0, utils_js_1.assertUsage)(fileImportsUnused.length === 0, [
235
237
  `${filePath} imports the following:`,
236
238
  ...importStatements.map((s) => picocolors_1.default.cyan(` ${s}`)),
237
239
  `But the import${singular ? '' : 's'} ${importNamesUnused} ${singular ? "isn't" : "aren't"} re-exported at ${picocolors_1.default.cyan('export default { ... }')} and therefore ${singular ? 'has' : 'have'} no effect, see explanation at https://vike.dev/header-file`
238
- ].join('\n'), { onlyOnce: true });
240
+ ].join('\n'));
239
241
  }
240
242
  function getExportedStrings(obj) {
241
243
  const exportedStrings = [];
@@ -627,7 +627,10 @@ exports.isStreamPipeWeb = isStreamPipeWeb;
627
627
  const __streamPipeNode = '__streamPipeNode';
628
628
  /** @deprecated */
629
629
  function pipeNodeStream(pipe) {
630
- (0, utils_js_1.assertWarning)(false, 'pipeNodeStream() is outdated, use stampPipe() instead. See https://vike.dev/stream', { onlyOnce: true, showStackTrace: true });
630
+ (0, utils_js_1.assertWarning)(false, 'pipeNodeStream() is outdated, use stampPipe() instead. See https://vike.dev/stream', {
631
+ onlyOnce: true,
632
+ showStackTrace: true
633
+ });
631
634
  return { [__streamPipeNode]: pipe };
632
635
  }
633
636
  exports.pipeNodeStream = pipeNodeStream;
@@ -7,7 +7,7 @@ const idBase = 'virtual:vike:pageConfigValuesAll:';
7
7
  const idBaseClient = `${idBase}client:`;
8
8
  const idBaseServer = `${idBase}server:`;
9
9
  function getVirtualFileIdPageConfigValuesAll(pageId, isForClientSide) {
10
- const id = `${(isForClientSide ? idBaseClient : idBaseServer)}${pageId}`;
10
+ const id = `${isForClientSide ? idBaseClient : idBaseServer}${pageId}`;
11
11
  return id;
12
12
  }
13
13
  exports.getVirtualFileIdPageConfigValuesAll = getVirtualFileIdPageConfigValuesAll;
@@ -6,6 +6,7 @@ const assertExports_js_1 = require("./assertExports.js");
6
6
  const getPageFileObject_js_1 = require("./getPageFileObject.js");
7
7
  const fileTypes_js_1 = require("./fileTypes.js");
8
8
  const assertPageConfigs_js_1 = require("./assertPageConfigs.js");
9
+ const parse_1 = require("@brillout/json-serializer/parse");
9
10
  function parseGlobResults(pageFilesExports) {
10
11
  (0, utils_js_1.assert)((0, utils_js_1.hasProp)(pageFilesExports, 'isGeneratedFile'));
11
12
  (0, utils_js_1.assert)(pageFilesExports.isGeneratedFile !== false, `vike was re-installed(/re-built). Restart your app.`);
@@ -91,22 +92,21 @@ function assertLoadModule(globValue) {
91
92
  (0, utils_js_1.assert)((0, utils_js_1.isCallable)(globValue));
92
93
  }
93
94
  function parsePageConfigs(pageConfigs) {
94
- // TODO: remove
95
- /*
96
95
  pageConfigs.forEach((pageConfig) => {
97
- Object.entries(pageConfig.configElements).forEach(([configName, configElement]) => {
98
- {
99
- const { configValueSerialized } = configElement
100
- if (configValueSerialized !== undefined) {
101
- configElement.configValue = parse(configValueSerialized)
102
- }
103
- }
104
- if (configName === 'route') {
105
- assertRouteConfigValue(configElement)
106
- }
107
- })
108
- })
109
- */
96
+ Object.entries(pageConfig.configValues).forEach(([configName, configValue]) => {
97
+ {
98
+ const { valueSerialized } = configValue;
99
+ if (valueSerialized !== undefined) {
100
+ configValue.value = (0, parse_1.parse)(valueSerialized);
101
+ }
102
+ }
103
+ /*
104
+ if (configName === 'route') {
105
+ assertRouteConfigValue(configElement)
106
+ }
107
+ */
108
+ });
109
+ });
110
110
  }
111
111
  // TODO: use again
112
112
  // function assertRouteConfigValue(configElement: ConfigElement) {
@@ -55,7 +55,7 @@ function assertConfigValueType(value, type, configName, definedAtInfo) {
55
55
  const valuePrintable = (0, utils_js_1.getValuePrintable)(value);
56
56
  const problem = valuePrintable !== null ? `value ${picocolors_1.default.cyan(valuePrintable)}` : `type ${picocolors_1.default.cyan(typeActual)}`;
57
57
  const configDefinedAt = getConfigDefinedAtString(configName, { definedAtInfo }, true);
58
- (0, utils_js_1.assertUsage)(false, `${configDefinedAt} has an invalid ${problem}: is should be a ${picocolors_1.default.cyan(type)} instead`);
58
+ (0, utils_js_1.assertUsage)(false, `${configDefinedAt} has an invalid ${problem}: it should be a ${picocolors_1.default.cyan(type)} instead`);
59
59
  }
60
60
  function getConfigDefinedAtString(configName, { definedAtInfo }, sentenceBegin, append) {
61
61
  let configDefinedAt = `${sentenceBegin ? `Config` : `config`} ${picocolors_1.default.cyan(configName)}`;
@@ -35,37 +35,58 @@ function sortMatches(routeMatch1, routeMatch2) {
35
35
  if (!routeMatch1.routeString) {
36
36
  return 0;
37
37
  }
38
+ /* DEBUG
39
+ console.log('routeMatch1.routeString', routeMatch1.routeString)
40
+ console.log('routeMatch2.routeString', routeMatch2.routeString)
41
+ console.log('parseRouteString(routeMatch1.routeString)', parseRouteString(routeMatch1.routeString))
42
+ console.log('parseRouteString(routeMatch2.routeString)', parseRouteString(routeMatch2.routeString))
43
+ //*/
38
44
  // Return route with highest number of static path segments at beginning first
39
45
  {
40
- const getValue = (routeString) => (0, resolveRouteString_js_1.analyzeRouteString)(routeString).numberOfStaticSegmentsBeginning;
46
+ const getValue = (routeString) => (0, resolveRouteString_js_1.analyzeRouteString)(routeString).numberOfStaticPartsBeginning;
41
47
  const result = (0, utils_js_1.higherFirst)(getValue)(routeMatch1.routeString, routeMatch2.routeString);
42
48
  if (result !== 0) {
49
+ /* DEBUG
50
+ console.log('analyzeRouteString(routeMatch1.routeString).numberOfStaticPartsBeginning', getValue(routeMatch1.routeString))
51
+ console.log('analyzeRouteString(routeMatch2.routeString).numberOfStaticPartsBeginning', getValue(routeMatch2.routeString))
52
+ //*/
43
53
  return result;
44
54
  }
45
55
  }
46
56
  // Return route with highest number of static path segments in total first
47
57
  {
48
- const getValue = (routeString) => (0, resolveRouteString_js_1.analyzeRouteString)(routeString).numberOfStaticSegements;
58
+ const getValue = (routeString) => (0, resolveRouteString_js_1.analyzeRouteString)(routeString).numberOfStaticParts;
49
59
  const result = (0, utils_js_1.higherFirst)(getValue)(routeMatch1.routeString, routeMatch2.routeString);
50
60
  if (result !== 0) {
61
+ /* DEBUG
62
+ console.log('analyzeRouteString(routeMatch1.routeString).numberOfStaticParts', getValue(routeMatch1.routeString))
63
+ console.log('analyzeRouteString(routeMatch2.routeString).numberOfStaticParts', getValue(routeMatch2.routeString))
64
+ //*/
51
65
  return result;
52
66
  }
53
67
  }
54
- // Return route with most parameter segements first
68
+ // Return route with least amount of globs first
55
69
  {
56
- const getValue = (routeString) => (0, resolveRouteString_js_1.analyzeRouteString)(routeString).numberOfParameterSegments;
57
- const result = (0, utils_js_1.higherFirst)(getValue)(routeMatch1.routeString, routeMatch2.routeString);
70
+ const getValue = (routeString) => (0, resolveRouteString_js_1.analyzeRouteString)(routeString).numberOfGlobs;
71
+ const result = (0, utils_js_1.lowerFirst)(getValue)(routeMatch1.routeString, routeMatch2.routeString);
58
72
  if (result !== 0) {
73
+ /* DEBUG
74
+ console.log('analyzeRouteString(routeMatch1.routeString).numberOfGlobs', getValue(routeMatch1.routeString))
75
+ console.log('analyzeRouteString(routeMatch2.routeString).numberOfGlobs', getValue(routeMatch2.routeString))
76
+ //*/
59
77
  return result;
60
78
  }
61
79
  }
62
- // Return catch-all routes last
80
+ // Return route with highest number of parameters first
63
81
  {
64
- if ((0, resolveRouteString_js_1.analyzeRouteString)(routeMatch2.routeString).isCatchAll) {
65
- return -1;
66
- }
67
- if ((0, resolveRouteString_js_1.analyzeRouteString)(routeMatch1.routeString).isCatchAll) {
68
- return 1;
82
+ const getValue = (routeString) => (0, resolveRouteString_js_1.analyzeRouteString)(routeString).numberOfParams;
83
+ const result = (0, utils_js_1.higherFirst)(getValue)(routeMatch1.routeString, routeMatch2.routeString);
84
+ if (result !== 0) {
85
+ /* DEBUG
86
+ console.log('analyzeRouteString(routeMatch1.routeString).numberOfParams', getValue(routeMatch1.routeString))
87
+ console.log('analyzeRouteString(routeMatch2.routeString).numberOfParams', getValue(routeMatch2.routeString))
88
+ //*/
89
+ return result;
69
90
  }
70
91
  }
71
92
  return 0;
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.assertRouteString = exports.analyzeRouteString = exports.isStaticRouteString = exports.getUrlFromRouteString = exports.resolveRouteString = void 0;
6
+ exports.parseRouteString = exports.assertRouteString = exports.analyzeRouteString = exports.isStaticRouteString = exports.getUrlFromRouteString = exports.resolveRouteString = void 0;
7
7
  const utils_js_1 = require("../utils.js");
8
8
  const utils_js_2 = require("./utils.js");
9
9
  const picocolors_1 = __importDefault(require("@brillout/picocolors"));
@@ -11,44 +11,105 @@ const PARAM_TOKEN_NEW = '@';
11
11
  // TODO/v1-release: remove
12
12
  const PARAM_TOKEN_OLD = ':';
13
13
  function assertRouteString(routeString, errPrefix = 'Invalid') {
14
- (0, utils_js_2.assert)(errPrefix.endsWith('Invalid') || errPrefix.endsWith('invalid'));
15
- (0, utils_js_2.assertUsage)(routeString !== '', `${errPrefix} Route String ${highlight(routeString)} (empty string): set it to ${highlight('/')} instead`);
16
- (0, utils_js_2.assertUsage)(routeString.startsWith('/') || routeString === '*', `${errPrefix} Route String ${highlight(routeString)}: Route Strings should start with a leading slash ${highlight('/')} (or be ${highlight('*')})`);
14
+ let errPrefix2 = `${errPrefix} Route String ${highlight(routeString)}`;
15
+ (0, utils_js_2.assertUsage)(routeString !== '', `${errPrefix2} (empty string): set it to ${highlight('/')} instead`);
16
+ (0, utils_js_2.assertUsage)(['/', '*'].includes(routeString[0]), `${errPrefix2}: it should start with ${highlight('/')} or ${highlight('*')}`);
17
+ (0, utils_js_2.assertUsage)(!routeString.includes('**'), `${errPrefix2}: set it to ${highlight(routeString.split('**').join('*'))} instead`);
17
18
  }
18
19
  exports.assertRouteString = assertRouteString;
19
20
  function resolveRouteString(routeString, urlPathname) {
20
21
  assertRouteString(routeString);
21
- (0, utils_js_2.assert)(urlPathname.startsWith('/'));
22
- const routeSegments = routeString.split('/');
23
- const urlSegments = urlPathname.split('/');
24
- const routeParams = {};
25
- assertGlob(routeString);
26
- if (routeString === '*') {
27
- routeString = '/*';
28
- }
29
- for (let i = 0; i < Math.max(routeSegments.length, urlSegments.length); i++) {
30
- const routeSegment = routeSegments[i];
31
- const urlSegment = urlSegments[i];
32
- if (routeSegment === '*') {
33
- routeParams['*'] = urlSegments.slice(Math.max(1, i)).join('/');
34
- return { routeParams };
22
+ const segments = parseRouteString(routeString);
23
+ const routeRegexStrInner = segments
24
+ .map((segment) => {
25
+ if (segment.param) {
26
+ return '[^/]+';
35
27
  }
36
- else if (routeSegment && isParam(routeSegment)) {
37
- (0, utils_js_1.assertWarning)(!routeSegment.startsWith(PARAM_TOKEN_OLD), `Outdated Route String ${picocolors_1.default.cyan(routeString)}, use ${picocolors_1.default.cyan(routeString.split(PARAM_TOKEN_OLD).join(PARAM_TOKEN_NEW))} instead.`, { onlyOnce: true });
38
- if (!urlSegment) {
39
- return null;
28
+ if (segment.glob) {
29
+ if (segment.isLastDir) {
30
+ return '|/.*';
40
31
  }
41
- routeParams[routeSegment.slice(1)] = urlSegment;
42
- }
43
- else {
44
- if ((routeSegment || '') !== (urlSegment || '')) {
45
- return null;
32
+ else {
33
+ return '.*';
46
34
  }
47
35
  }
48
- }
36
+ // segment.static
37
+ return (0, utils_js_1.escapeRegex)(segment.static);
38
+ })
39
+ .map((s) => `(${s})`)
40
+ .join('');
41
+ const routeRegex = new RegExp(`^${routeRegexStrInner}/?$`);
42
+ const routeRegexMatch = urlPathname.match(routeRegex);
43
+ /* DEBUG
44
+ console.log()
45
+ console.log('routeString', routeString)
46
+ console.log('urlPathname', urlPathname)
47
+ console.log('routeSegments', segments)
48
+ console.log('routeRegex', routeRegex)
49
+ console.log('routeRegexMatch', routeRegexMatch)
50
+ //*/
51
+ if (!routeRegexMatch)
52
+ return null;
53
+ const routeParams = {};
54
+ const [_, ...segmentsValue] = routeRegexMatch;
55
+ let globIdx = 0;
56
+ const hasMultipleGlobs = segments.filter((segment) => segment.glob).length > 1;
57
+ segments.forEach((segment, i) => {
58
+ let val = segmentsValue[i];
59
+ if (segment.param) {
60
+ routeParams[segment.param] = val;
61
+ }
62
+ if (segment.glob) {
63
+ const param = `*${hasMultipleGlobs ? ++globIdx : ''}`;
64
+ if (segment.isLastDir)
65
+ val = val.slice(1);
66
+ routeParams[param] = val;
67
+ }
68
+ });
49
69
  return { routeParams };
50
70
  }
51
71
  exports.resolveRouteString = resolveRouteString;
72
+ function parseRouteString(routeString) {
73
+ const segments = [];
74
+ const pushStatic = (s) => {
75
+ const segmentLast = segments[segments.length - 1];
76
+ if (segmentLast?.static) {
77
+ segmentLast.static += s;
78
+ }
79
+ else {
80
+ segments.push({ static: s });
81
+ }
82
+ };
83
+ const parts = routeString.split('/');
84
+ parts.forEach((s, i) => {
85
+ const isFirst = i === 0;
86
+ const isLast = i === parts.length - 1;
87
+ if (isParam(s)) {
88
+ (0, utils_js_1.assertWarning)(!s.startsWith(PARAM_TOKEN_OLD), `Outdated Route String ${highlight(routeString)}, use ${highlight(routeString.split(PARAM_TOKEN_OLD).join(PARAM_TOKEN_NEW))} instead`, { onlyOnce: true });
89
+ if (!isFirst)
90
+ pushStatic('/');
91
+ segments.push({ param: s.slice(1) });
92
+ }
93
+ else {
94
+ if (s === '*' && isLast && routeString !== '*' && routeString !== '/*') {
95
+ segments.push({ glob: true, isLastDir: true });
96
+ }
97
+ else {
98
+ if (!isFirst)
99
+ pushStatic('/');
100
+ s.split('*').forEach((s, i) => {
101
+ if (i !== 0)
102
+ segments.push({ glob: true });
103
+ if (s !== '') {
104
+ pushStatic(s);
105
+ }
106
+ });
107
+ }
108
+ }
109
+ });
110
+ return segments;
111
+ }
112
+ exports.parseRouteString = parseRouteString;
52
113
  function getUrlFromRouteString(routeString) {
53
114
  (0, utils_js_2.assert)(routeString.startsWith('/'));
54
115
  if (isStaticRouteString(routeString)) {
@@ -58,24 +119,19 @@ function getUrlFromRouteString(routeString) {
58
119
  return null;
59
120
  }
60
121
  exports.getUrlFromRouteString = getUrlFromRouteString;
61
- function assertGlob(routeString) {
62
- const numberOfGlobChars = routeString.split('*').length - 1;
63
- (0, utils_js_2.assertUsage)(numberOfGlobChars <= 1, `Invalid Route String ${highlight(routeString)}: Route Strings aren't allowed to contain more than one glob ${highlight('*')} (use a Route Function instead)`);
64
- (0, utils_js_2.assertUsage)(numberOfGlobChars === 0 || (numberOfGlobChars === 1 && routeString.endsWith('*')), `Invalid Route String ${highlight(routeString)}: make sure it ends with ${highlight('*')} or use a Route Function`);
65
- }
66
122
  function analyzeRouteString(routeString) {
67
- const routeSegments = routeString.split('/').filter((routeSegment) => routeSegment !== '' && routeSegment !== '*');
68
- let numberOfStaticSegmentsBeginning = 0;
69
- for (const routeSegment of routeSegments) {
70
- if (isParam(routeSegment)) {
123
+ const segments = parseRouteString(routeString);
124
+ const countStaticParts = (s) => s?.split('/').filter(Boolean).length || 0;
125
+ let numberOfStaticPartsBeginning = 0;
126
+ for (const segment of segments) {
127
+ if (!segment.static)
71
128
  break;
72
- }
73
- numberOfStaticSegmentsBeginning++;
129
+ numberOfStaticPartsBeginning += countStaticParts(segment.static);
74
130
  }
75
- const numberOfStaticSegements = routeSegments.filter((s) => !isParam(s)).length;
76
- const numberOfParameterSegments = routeSegments.filter((s) => isParam(s)).length;
77
- const isCatchAll = routeString.endsWith('*');
78
- return { numberOfParameterSegments, numberOfStaticSegmentsBeginning, numberOfStaticSegements, isCatchAll };
131
+ const numberOfStaticParts = segments.map((s) => countStaticParts(s.static)).reduce((sum, a) => sum + a, 0);
132
+ const numberOfParams = segments.filter((s) => s.param).length;
133
+ const numberOfGlobs = segments.filter((s) => s.glob).length;
134
+ return { numberOfStaticPartsBeginning, numberOfStaticParts, numberOfParams, numberOfGlobs };
79
135
  }
80
136
  exports.analyzeRouteString = analyzeRouteString;
81
137
  function isParam(routeSegment) {
@@ -41,3 +41,4 @@ __exportStar(require("../utils/checkType.js"), exports);
41
41
  __exportStar(require("../utils/assertDefaultExport.js"), exports);
42
42
  __exportStar(require("../utils/objectEntries.js"), exports);
43
43
  __exportStar(require("../utils/getValuePrintable.js"), exports);
44
+ __exportStar(require("../utils/escapeRegex.js"), exports);
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.defineConfig = void 0;
4
+ function defineConfig(config) {
5
+ return config;
6
+ }
7
+ exports.defineConfig = defineConfig;
@@ -1,2 +1,5 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.defineConfig = void 0;
4
+ var defineConfig_js_1 = require("./defineConfig.js");
5
+ Object.defineProperty(exports, "defineConfig", { enumerable: true, get: function () { return defineConfig_js_1.defineConfig; } });
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.projectInfo = void 0;
4
4
  const assertSingleInstance_js_1 = require("./assertSingleInstance.js");
5
- const PROJECT_VERSION = '0.4.142-commit-acfc159';
5
+ const PROJECT_VERSION = '0.4.143';
6
6
  const projectInfo = {
7
7
  projectName: 'Vike',
8
8
  projectVersion: PROJECT_VERSION,
@@ -18,7 +18,9 @@ const linkPrefetchHandlerAdded = new Map();
18
18
  * @param url - The URL of the page you want to prefetch.
19
19
  */
20
20
  async function prefetch(url) {
21
- assertUsage(checkIfClientRouting(), 'prefetch() only works with Client Routing, see https://vike.dev/prefetch', { showStackTrace: true });
21
+ assertUsage(checkIfClientRouting(), 'prefetch() only works with Client Routing, see https://vike.dev/prefetch', {
22
+ showStackTrace: true
23
+ });
22
24
  assertUsage(!isExternalLink(url), `You are trying to prefetch the URL ${url} of another domain which cannot be prefetched`, { showStackTrace: true });
23
25
  if (isAlreadyPrefetched(url))
24
26
  return;
@@ -50,8 +50,10 @@ function buildConfig() {
50
50
  },
51
51
  async writeBundle(options, bundle) {
52
52
  const manifestEntry = bundle[manifestTempFile];
53
- if (generateManifest) {
54
- assert(manifestEntry);
53
+ /* Fails with @vitejs/plugin-legacy because writeBundle() is called twice during the client build (once for normal client assets and a second time for legacy assets), see reproduction at https://github.com/vikejs/vike/issues/1154
54
+ assert(generateManifest === !!manifestEntry)
55
+ */
56
+ if (manifestEntry) {
55
57
  const { dir } = options;
56
58
  assert(dir);
57
59
  const manifestFilePathOld = path.join(dir, manifestEntry.fileName);
@@ -61,9 +63,6 @@ function buildConfig() {
61
63
  const manifestFilePathNew = path.join(dir, '..', 'assets.json');
62
64
  await fs.rename(manifestFilePathOld, manifestFilePathNew);
63
65
  }
64
- else {
65
- assert(!manifestEntry);
66
- }
67
66
  }
68
67
  };
69
68
  }
@@ -14,12 +14,7 @@ function commonConfig() {
14
14
  {
15
15
  name: 'vike-commonConfig-1',
16
16
  config: () => ({
17
- appType: 'custom',
18
- ssr: {
19
- // Needed as long as Vike is published as CJS.
20
- // TODO: can we remove this once Vike is published as ESM?
21
- external: ['vike', 'vike/server']
22
- }
17
+ appType: 'custom'
23
18
  }),
24
19
  configResolved(config) {
25
20
  installRequireShim_setUserRootDir(config.root);
@@ -16,6 +16,7 @@ import { removeSuperfluousViteLog_enable, removeSuperfluousViteLog_disable } fro
16
16
  import { getFilePathToShowToUser } from './getFilePathToShowToUser.js';
17
17
  import pc from '@brillout/picocolors';
18
18
  import { getConfigDefinedAtString } from '../../../../../shared/page-configs/utils.js';
19
+ import { getConfigValueSerialized } from './getVirtualFilePageConfigs.js';
19
20
  assertIsNotProductionRuntime();
20
21
  let devServerIsCorrupt = false;
21
22
  let wasConfigInvalid = null;
@@ -1072,6 +1073,8 @@ function mergeCumulative(configName, configValueSources) {
1072
1073
  /* This is more confusing than adding value. For example, this explanation shouldn't be shown for the passToClient config.
1073
1074
  const explanation = `(Because the values of ${configNameColored} are cumulative and therefore merged together.)` as const
1074
1075
  */
1076
+ // Make sure configValueSource.value is serializable
1077
+ getConfigValueSerialized(configValueSource.value, configName, configValueSource.definedAtInfo);
1075
1078
  const assertNoMixing = (isSet) => {
1076
1079
  const vals1 = isSet ? valuesSet : valuesArr;
1077
1080
  const t1 = isSet ? 'a Set' : 'an array';
@@ -1,3 +1,6 @@
1
1
  export { getVirtualFilePageConfigs };
2
+ export { getConfigValueSerialized };
3
+ import type { DefinedAtInfo } from '../../../../../shared/page-configs/PageConfig.js';
2
4
  import type { ConfigVikeResolved } from '../../../../../shared/ConfigVike.js';
3
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, definedAtInfo: null | DefinedAtInfo): string;
@@ -1,4 +1,5 @@
1
1
  export { getVirtualFilePageConfigs };
2
+ export { getConfigValueSerialized };
2
3
  import { assert, assertUsage, getPropAccessNotation, hasProp, objectEntries } from '../../../utils.js';
3
4
  import { generateEagerImport } from '../generateEagerImport.js';
4
5
  import { getVirtualFileIdPageConfigValuesAll } from '../../../../shared/virtual-files/virtualFilePageConfigValuesAll.js';
@@ -33,23 +34,22 @@ function getContent(pageConfigs, pageConfigGlobal, isForClientSide, isDev, id, i
33
34
  if (!isConfigEnvMatch(configEnv, isForClientSide, isClientRouting))
34
35
  return;
35
36
  const { value, definedAtInfo } = configValue;
36
- // TODO: use @brillout/json-serializer
37
- // - re-use getConfigValueSerialized()?
38
- const valueSerialized = JSON.stringify(value);
39
- serializeConfigValue(lines, configName, { definedAtInfo }, valueSerialized);
37
+ const valueSerialized = getConfigValueSerialized(value, configName, definedAtInfo);
38
+ const configValue2 = { definedAtInfo, valueSerialized };
39
+ serializeConfigValue(lines, configName, configValue2);
40
40
  }
41
41
  else {
42
42
  const configValueSource = sources[0];
43
43
  assert(configValueSource);
44
44
  if (configValueSource.configEnv === '_routing-eager') {
45
45
  const { definedAtInfo } = configValueSource;
46
- const configValue = { configName, definedAtInfo };
47
46
  assert(!configValueSource.isComputed);
48
47
  const { filePath, fileExportPath } = configValueSource.definedAtInfo;
49
48
  const [exportName] = fileExportPath;
50
49
  assert(exportName);
51
50
  const configValueEagerImport = getConfigValueEagerImport(filePath, exportName, importStatements);
52
- serializeConfigValue(lines, configName, configValue, configValueEagerImport);
51
+ const configValue = { definedAtInfo, value: configValueEagerImport };
52
+ serializeConfigValue(lines, configName, configValue);
53
53
  }
54
54
  }
55
55
  });
@@ -88,16 +88,13 @@ function getContent(pageConfigs, pageConfigGlobal, isForClientSide, isDev, id, i
88
88
  debug(id, isForClientSide ? 'CLIENT-SIDE' : 'SERVER-SIDE', code);
89
89
  return code;
90
90
  }
91
- function serializeConfigValue(lines, configName, configValue, valueSerialized) {
91
+ function serializeConfigValue(lines, configName, configValue) {
92
92
  let whitespace = ' ';
93
93
  lines.push(`${whitespace}['${configName}']: {`);
94
94
  whitespace += ' ';
95
- lines.push(`${whitespace} value: ${valueSerialized},`);
96
95
  Object.entries(configValue).forEach(([key, val]) => {
97
- if (key === 'value')
98
- return;
99
- // if (val === undefined) return
100
- lines.push(`${whitespace} ${key}: ${JSON.stringify(val)},`);
96
+ const valSerialized = key === 'value' || key === 'valueSerialized' ? val : JSON.stringify(val);
97
+ lines.push(`${whitespace} ${key}: ${valSerialized},`);
101
98
  });
102
99
  whitespace = whitespace.slice(2);
103
100
  lines.push(`${whitespace}},`);
@@ -113,7 +110,7 @@ function serializeConfigValueSource(configValueSource, configName, whitespace, i
113
110
  if (isConfigEnvMatch(configEnv, isForClientSide, isClientRouting) || eager) {
114
111
  if ('value' in configValueSource) {
115
112
  const { value } = configValueSource;
116
- const valueSerialized = getConfigValueSerialized(value, configName, definedAtInfo.filePath);
113
+ const valueSerialized = getConfigValueSerialized(value, configName, definedAtInfo);
117
114
  lines.push(`${whitespace} valueSerialized: ${valueSerialized}`);
118
115
  }
119
116
  else if (eager) {
@@ -127,7 +124,7 @@ function serializeConfigValueSource(configValueSource, configName, whitespace, i
127
124
  lines.push(`${whitespace}},`);
128
125
  return lines.join('\n');
129
126
  }
130
- function getConfigValueSerialized(value, configName, configDefinedByFile) {
127
+ function getConfigValueSerialized(value, configName, definedAtInfo) {
131
128
  let configValueSerialized;
132
129
  const valueName = `config${getPropAccessNotation(configName)}`;
133
130
  try {
@@ -135,10 +132,16 @@ function getConfigValueSerialized(value, configName, configDefinedByFile) {
135
132
  }
136
133
  catch (err) {
137
134
  assert(hasProp(err, 'messageCore', 'string'));
135
+ // definedAtInfo is null when config value is:
136
+ // - computed => all computed values defined by Vike can are serializable
137
+ // - cumulative => the values are already ensured to be serializable
138
+ assert(definedAtInfo);
139
+ const configDefinedByFile = definedAtInfo.filePath;
140
+ assert(configDefinedByFile);
138
141
  assertUsage(false, [
139
- `The value of the config ${pc.cyan(configName)} cannot be defined inside the file ${configDefinedByFile}.`,
140
- `Its value must be defined in an another file and then imported by ${configDefinedByFile} (because it isn't serializable: ${err.messageCore}).`,
141
- `Only serializable config values can be defined inside ${configDefinedByFile}, see https://vike.dev/header-file.`
142
+ `The value of the config ${pc.cyan(configName)} cannot be defined inside the file ${configDefinedByFile}:`,
143
+ `its value must be defined in an another file and then imported by ${configDefinedByFile}. (Because the value isn't serializable: ${err.messageCore}.)`,
144
+ `Only serializable config values can be defined inside +config.h.js files, see https://vike.dev/header-file.`
142
145
  ].join(' '));
143
146
  }
144
147
  configValueSerialized = JSON.stringify(configValueSerialized);
@@ -7,7 +7,7 @@ import fs from 'fs';
7
7
  import path from 'path';
8
8
  import pc from '@brillout/picocolors';
9
9
  import { import_ } from '@brillout/import';
10
- import { assertPosixPath, getRandomId, assertIsNotProductionRuntime, assert, assertDefaultExportObject, unique, assertWarning, isObject, toPosixPath } from '../../../utils.js';
10
+ import { assertPosixPath, getRandomId, assertIsNotProductionRuntime, assert, assertDefaultExportObject, unique, assertWarning, isObject, toPosixPath, assertUsage } from '../../../utils.js';
11
11
  import { isImportData, replaceImportStatements } from './replaceImportStatements.js';
12
12
  import { vikeConfigDependencies } from './getVikeConfig.js';
13
13
  import 'source-map-support/register.js';
@@ -52,7 +52,9 @@ function transpileImports(codeOriginal, filePath, isValueFile) {
52
52
  const { code, fileImports } = res;
53
53
  if (!isHeader) {
54
54
  const filePathCorrect = appendHeaderFileExtension(filePathToShowToUser);
55
- assertWarning(false, `Rename ${filePathToShowToUser} to ${filePathCorrect}, see https://vike.dev/header-file`, { onlyOnce: true });
55
+ assertWarning(false, `Rename ${filePathToShowToUser} to ${filePathCorrect}, see https://vike.dev/header-file`, {
56
+ onlyOnce: true
57
+ });
56
58
  }
57
59
  return { code, fileImports };
58
60
  }
@@ -225,11 +227,11 @@ function assertFileImports(fileImports, fileExports, filePath) {
225
227
  const importStatements = unique(fileImportsUnused.map((fi) => fi.importStatementCode));
226
228
  const importNamesUnused = fileImportsUnused.map((fi) => pc.cyan(fi.importLocalName)).join(', ');
227
229
  const singular = fileImportsUnused.length === 1;
228
- assertWarning(fileImportsUnused.length === 0, [
230
+ assertUsage(fileImportsUnused.length === 0, [
229
231
  `${filePath} imports the following:`,
230
232
  ...importStatements.map((s) => pc.cyan(` ${s}`)),
231
233
  `But the import${singular ? '' : 's'} ${importNamesUnused} ${singular ? "isn't" : "aren't"} re-exported at ${pc.cyan('export default { ... }')} and therefore ${singular ? 'has' : 'have'} no effect, see explanation at https://vike.dev/header-file`
232
- ].join('\n'), { onlyOnce: true });
234
+ ].join('\n'));
233
235
  }
234
236
  function getExportedStrings(obj) {
235
237
  const exportedStrings = [];
@@ -628,7 +628,10 @@ function isStreamPipeWeb(thing) {
628
628
  const __streamPipeNode = '__streamPipeNode';
629
629
  /** @deprecated */
630
630
  function pipeNodeStream(pipe) {
631
- assertWarning(false, 'pipeNodeStream() is outdated, use stampPipe() instead. See https://vike.dev/stream', { onlyOnce: true, showStackTrace: true });
631
+ assertWarning(false, 'pipeNodeStream() is outdated, use stampPipe() instead. See https://vike.dev/stream', {
632
+ onlyOnce: true,
633
+ showStackTrace: true
634
+ });
632
635
  return { [__streamPipeNode]: pipe };
633
636
  }
634
637
  function getStreamPipeNode(thing) {
@@ -6,7 +6,7 @@ const idBase = 'virtual:vike:pageConfigValuesAll:';
6
6
  const idBaseClient = `${idBase}client:`;
7
7
  const idBaseServer = `${idBase}server:`;
8
8
  function getVirtualFileIdPageConfigValuesAll(pageId, isForClientSide) {
9
- const id = `${(isForClientSide ? idBaseClient : idBaseServer)}${pageId}`;
9
+ const id = `${isForClientSide ? idBaseClient : idBaseServer}${pageId}`;
10
10
  return id;
11
11
  }
12
12
  function isVirtualFileIdPageConfigValuesAll(id) {
@@ -4,6 +4,7 @@ import { assertExportValues } from './assertExports.js';
4
4
  import { getPageFileObject } from './getPageFileObject.js';
5
5
  import { fileTypes } from './fileTypes.js';
6
6
  import { assertPageConfigGlobal, assertPageConfigs } from './assertPageConfigs.js';
7
+ import { parse } from '@brillout/json-serializer/parse';
7
8
  function parseGlobResults(pageFilesExports) {
8
9
  assert(hasProp(pageFilesExports, 'isGeneratedFile'));
9
10
  assert(pageFilesExports.isGeneratedFile !== false, `vike was re-installed(/re-built). Restart your app.`);
@@ -88,22 +89,21 @@ function assertLoadModule(globValue) {
88
89
  assert(isCallable(globValue));
89
90
  }
90
91
  function parsePageConfigs(pageConfigs) {
91
- // TODO: remove
92
- /*
93
92
  pageConfigs.forEach((pageConfig) => {
94
- Object.entries(pageConfig.configElements).forEach(([configName, configElement]) => {
95
- {
96
- const { configValueSerialized } = configElement
97
- if (configValueSerialized !== undefined) {
98
- configElement.configValue = parse(configValueSerialized)
99
- }
100
- }
101
- if (configName === 'route') {
102
- assertRouteConfigValue(configElement)
103
- }
104
- })
105
- })
106
- */
93
+ Object.entries(pageConfig.configValues).forEach(([configName, configValue]) => {
94
+ {
95
+ const { valueSerialized } = configValue;
96
+ if (valueSerialized !== undefined) {
97
+ configValue.value = parse(valueSerialized);
98
+ }
99
+ }
100
+ /*
101
+ if (configName === 'route') {
102
+ assertRouteConfigValue(configElement)
103
+ }
104
+ */
105
+ });
106
+ });
107
107
  }
108
108
  // TODO: use again
109
109
  // function assertRouteConfigValue(configElement: ConfigElement) {
@@ -44,6 +44,7 @@ type ConfigValueSource = {
44
44
  type ConfigValueSources = Record<string, ConfigValueSource[]>;
45
45
  type ConfigValue = {
46
46
  value: unknown;
47
+ valueSerialized?: string;
47
48
  definedAtInfo: null | DefinedAtInfo;
48
49
  };
49
50
  type ConfigValues = Record<string, ConfigValue>;
@@ -51,7 +51,7 @@ function assertConfigValueType(value, type, configName, definedAtInfo) {
51
51
  const valuePrintable = getValuePrintable(value);
52
52
  const problem = valuePrintable !== null ? `value ${pc.cyan(valuePrintable)}` : `type ${pc.cyan(typeActual)}`;
53
53
  const configDefinedAt = getConfigDefinedAtString(configName, { definedAtInfo }, true);
54
- assertUsage(false, `${configDefinedAt} has an invalid ${problem}: is should be a ${pc.cyan(type)} instead`);
54
+ assertUsage(false, `${configDefinedAt} has an invalid ${problem}: it should be a ${pc.cyan(type)} instead`);
55
55
  }
56
56
  function getConfigDefinedAtString(configName, { definedAtInfo }, sentenceBegin, append) {
57
57
  let configDefinedAt = `${sentenceBegin ? `Config` : `config`} ${pc.cyan(configName)}`;
@@ -1,7 +1,7 @@
1
1
  export { resolvePrecendence };
2
2
  // export type { RouteMatch }
3
3
  import { analyzeRouteString } from './resolveRouteString.js';
4
- import { higherFirst } from './utils.js';
4
+ import { higherFirst, lowerFirst } from './utils.js';
5
5
  import { makeFirst } from './utils.js';
6
6
  import { isStaticRouteString } from './resolveRouteString.js';
7
7
  // See https://vike.dev/route-function#precedence
@@ -32,37 +32,58 @@ function sortMatches(routeMatch1, routeMatch2) {
32
32
  if (!routeMatch1.routeString) {
33
33
  return 0;
34
34
  }
35
+ /* DEBUG
36
+ console.log('routeMatch1.routeString', routeMatch1.routeString)
37
+ console.log('routeMatch2.routeString', routeMatch2.routeString)
38
+ console.log('parseRouteString(routeMatch1.routeString)', parseRouteString(routeMatch1.routeString))
39
+ console.log('parseRouteString(routeMatch2.routeString)', parseRouteString(routeMatch2.routeString))
40
+ //*/
35
41
  // Return route with highest number of static path segments at beginning first
36
42
  {
37
- const getValue = (routeString) => analyzeRouteString(routeString).numberOfStaticSegmentsBeginning;
43
+ const getValue = (routeString) => analyzeRouteString(routeString).numberOfStaticPartsBeginning;
38
44
  const result = higherFirst(getValue)(routeMatch1.routeString, routeMatch2.routeString);
39
45
  if (result !== 0) {
46
+ /* DEBUG
47
+ console.log('analyzeRouteString(routeMatch1.routeString).numberOfStaticPartsBeginning', getValue(routeMatch1.routeString))
48
+ console.log('analyzeRouteString(routeMatch2.routeString).numberOfStaticPartsBeginning', getValue(routeMatch2.routeString))
49
+ //*/
40
50
  return result;
41
51
  }
42
52
  }
43
53
  // Return route with highest number of static path segments in total first
44
54
  {
45
- const getValue = (routeString) => analyzeRouteString(routeString).numberOfStaticSegements;
55
+ const getValue = (routeString) => analyzeRouteString(routeString).numberOfStaticParts;
46
56
  const result = higherFirst(getValue)(routeMatch1.routeString, routeMatch2.routeString);
47
57
  if (result !== 0) {
58
+ /* DEBUG
59
+ console.log('analyzeRouteString(routeMatch1.routeString).numberOfStaticParts', getValue(routeMatch1.routeString))
60
+ console.log('analyzeRouteString(routeMatch2.routeString).numberOfStaticParts', getValue(routeMatch2.routeString))
61
+ //*/
48
62
  return result;
49
63
  }
50
64
  }
51
- // Return route with most parameter segements first
65
+ // Return route with least amount of globs first
52
66
  {
53
- const getValue = (routeString) => analyzeRouteString(routeString).numberOfParameterSegments;
54
- const result = higherFirst(getValue)(routeMatch1.routeString, routeMatch2.routeString);
67
+ const getValue = (routeString) => analyzeRouteString(routeString).numberOfGlobs;
68
+ const result = lowerFirst(getValue)(routeMatch1.routeString, routeMatch2.routeString);
55
69
  if (result !== 0) {
70
+ /* DEBUG
71
+ console.log('analyzeRouteString(routeMatch1.routeString).numberOfGlobs', getValue(routeMatch1.routeString))
72
+ console.log('analyzeRouteString(routeMatch2.routeString).numberOfGlobs', getValue(routeMatch2.routeString))
73
+ //*/
56
74
  return result;
57
75
  }
58
76
  }
59
- // Return catch-all routes last
77
+ // Return route with highest number of parameters first
60
78
  {
61
- if (analyzeRouteString(routeMatch2.routeString).isCatchAll) {
62
- return -1;
63
- }
64
- if (analyzeRouteString(routeMatch1.routeString).isCatchAll) {
65
- return 1;
79
+ const getValue = (routeString) => analyzeRouteString(routeString).numberOfParams;
80
+ const result = higherFirst(getValue)(routeMatch1.routeString, routeMatch2.routeString);
81
+ if (result !== 0) {
82
+ /* DEBUG
83
+ console.log('analyzeRouteString(routeMatch1.routeString).numberOfParams', getValue(routeMatch1.routeString))
84
+ console.log('analyzeRouteString(routeMatch2.routeString).numberOfParams', getValue(routeMatch2.routeString))
85
+ //*/
86
+ return result;
66
87
  }
67
88
  }
68
89
  return 0;
@@ -3,15 +3,32 @@ export { getUrlFromRouteString };
3
3
  export { isStaticRouteString };
4
4
  export { analyzeRouteString };
5
5
  export { assertRouteString };
6
+ export { parseRouteString };
6
7
  declare function assertRouteString(routeString: string, errPrefix?: `${string}Invalid` | `${string}invalid`): void;
7
8
  declare function resolveRouteString(routeString: string, urlPathname: string): null | {
8
9
  routeParams: Record<string, string>;
9
10
  };
11
+ type Segment = {
12
+ glob: true;
13
+ /** Make route /a/* match URL /a */
14
+ isLastDir?: true;
15
+ static?: undefined;
16
+ param?: undefined;
17
+ } | {
18
+ glob?: undefined;
19
+ static: string;
20
+ param?: undefined;
21
+ } | {
22
+ glob?: undefined;
23
+ static?: undefined;
24
+ param: string;
25
+ };
26
+ declare function parseRouteString(routeString: string): Segment[];
10
27
  declare function getUrlFromRouteString(routeString: string): null | string;
11
28
  declare function analyzeRouteString(routeString: string): {
12
- numberOfParameterSegments: number;
13
- numberOfStaticSegmentsBeginning: number;
14
- numberOfStaticSegements: number;
15
- isCatchAll: boolean;
29
+ numberOfStaticPartsBeginning: number;
30
+ numberOfStaticParts: number;
31
+ numberOfParams: number;
32
+ numberOfGlobs: number;
16
33
  };
17
34
  declare function isStaticRouteString(routeString: string): boolean;
@@ -3,48 +3,109 @@ export { getUrlFromRouteString };
3
3
  export { isStaticRouteString };
4
4
  export { analyzeRouteString };
5
5
  export { assertRouteString };
6
- import { assertWarning, isBrowser } from '../utils.js';
6
+ export { parseRouteString };
7
+ import { assertWarning, isBrowser, escapeRegex } from '../utils.js';
7
8
  import { assert, assertUsage } from './utils.js';
8
9
  import pc from '@brillout/picocolors';
9
10
  const PARAM_TOKEN_NEW = '@';
10
11
  // TODO/v1-release: remove
11
12
  const PARAM_TOKEN_OLD = ':';
12
13
  function assertRouteString(routeString, errPrefix = 'Invalid') {
13
- assert(errPrefix.endsWith('Invalid') || errPrefix.endsWith('invalid'));
14
- assertUsage(routeString !== '', `${errPrefix} Route String ${highlight(routeString)} (empty string): set it to ${highlight('/')} instead`);
15
- assertUsage(routeString.startsWith('/') || routeString === '*', `${errPrefix} Route String ${highlight(routeString)}: Route Strings should start with a leading slash ${highlight('/')} (or be ${highlight('*')})`);
14
+ let errPrefix2 = `${errPrefix} Route String ${highlight(routeString)}`;
15
+ assertUsage(routeString !== '', `${errPrefix2} (empty string): set it to ${highlight('/')} instead`);
16
+ assertUsage(['/', '*'].includes(routeString[0]), `${errPrefix2}: it should start with ${highlight('/')} or ${highlight('*')}`);
17
+ assertUsage(!routeString.includes('**'), `${errPrefix2}: set it to ${highlight(routeString.split('**').join('*'))} instead`);
16
18
  }
17
19
  function resolveRouteString(routeString, urlPathname) {
18
20
  assertRouteString(routeString);
19
- assert(urlPathname.startsWith('/'));
20
- const routeSegments = routeString.split('/');
21
- const urlSegments = urlPathname.split('/');
22
- const routeParams = {};
23
- assertGlob(routeString);
24
- if (routeString === '*') {
25
- routeString = '/*';
26
- }
27
- for (let i = 0; i < Math.max(routeSegments.length, urlSegments.length); i++) {
28
- const routeSegment = routeSegments[i];
29
- const urlSegment = urlSegments[i];
30
- if (routeSegment === '*') {
31
- routeParams['*'] = urlSegments.slice(Math.max(1, i)).join('/');
32
- return { routeParams };
21
+ const segments = parseRouteString(routeString);
22
+ const routeRegexStrInner = segments
23
+ .map((segment) => {
24
+ if (segment.param) {
25
+ return '[^/]+';
33
26
  }
34
- else if (routeSegment && isParam(routeSegment)) {
35
- assertWarning(!routeSegment.startsWith(PARAM_TOKEN_OLD), `Outdated Route String ${pc.cyan(routeString)}, use ${pc.cyan(routeString.split(PARAM_TOKEN_OLD).join(PARAM_TOKEN_NEW))} instead.`, { onlyOnce: true });
36
- if (!urlSegment) {
37
- return null;
27
+ if (segment.glob) {
28
+ if (segment.isLastDir) {
29
+ return '|/.*';
30
+ }
31
+ else {
32
+ return '.*';
38
33
  }
39
- routeParams[routeSegment.slice(1)] = urlSegment;
34
+ }
35
+ // segment.static
36
+ return escapeRegex(segment.static);
37
+ })
38
+ .map((s) => `(${s})`)
39
+ .join('');
40
+ const routeRegex = new RegExp(`^${routeRegexStrInner}/?$`);
41
+ const routeRegexMatch = urlPathname.match(routeRegex);
42
+ /* DEBUG
43
+ console.log()
44
+ console.log('routeString', routeString)
45
+ console.log('urlPathname', urlPathname)
46
+ console.log('routeSegments', segments)
47
+ console.log('routeRegex', routeRegex)
48
+ console.log('routeRegexMatch', routeRegexMatch)
49
+ //*/
50
+ if (!routeRegexMatch)
51
+ return null;
52
+ const routeParams = {};
53
+ const [_, ...segmentsValue] = routeRegexMatch;
54
+ let globIdx = 0;
55
+ const hasMultipleGlobs = segments.filter((segment) => segment.glob).length > 1;
56
+ segments.forEach((segment, i) => {
57
+ let val = segmentsValue[i];
58
+ if (segment.param) {
59
+ routeParams[segment.param] = val;
60
+ }
61
+ if (segment.glob) {
62
+ const param = `*${hasMultipleGlobs ? ++globIdx : ''}`;
63
+ if (segment.isLastDir)
64
+ val = val.slice(1);
65
+ routeParams[param] = val;
66
+ }
67
+ });
68
+ return { routeParams };
69
+ }
70
+ function parseRouteString(routeString) {
71
+ const segments = [];
72
+ const pushStatic = (s) => {
73
+ const segmentLast = segments[segments.length - 1];
74
+ if (segmentLast?.static) {
75
+ segmentLast.static += s;
40
76
  }
41
77
  else {
42
- if ((routeSegment || '') !== (urlSegment || '')) {
43
- return null;
78
+ segments.push({ static: s });
79
+ }
80
+ };
81
+ const parts = routeString.split('/');
82
+ parts.forEach((s, i) => {
83
+ const isFirst = i === 0;
84
+ const isLast = i === parts.length - 1;
85
+ if (isParam(s)) {
86
+ assertWarning(!s.startsWith(PARAM_TOKEN_OLD), `Outdated Route String ${highlight(routeString)}, use ${highlight(routeString.split(PARAM_TOKEN_OLD).join(PARAM_TOKEN_NEW))} instead`, { onlyOnce: true });
87
+ if (!isFirst)
88
+ pushStatic('/');
89
+ segments.push({ param: s.slice(1) });
90
+ }
91
+ else {
92
+ if (s === '*' && isLast && routeString !== '*' && routeString !== '/*') {
93
+ segments.push({ glob: true, isLastDir: true });
94
+ }
95
+ else {
96
+ if (!isFirst)
97
+ pushStatic('/');
98
+ s.split('*').forEach((s, i) => {
99
+ if (i !== 0)
100
+ segments.push({ glob: true });
101
+ if (s !== '') {
102
+ pushStatic(s);
103
+ }
104
+ });
44
105
  }
45
106
  }
46
- }
47
- return { routeParams };
107
+ });
108
+ return segments;
48
109
  }
49
110
  function getUrlFromRouteString(routeString) {
50
111
  assert(routeString.startsWith('/'));
@@ -54,24 +115,19 @@ function getUrlFromRouteString(routeString) {
54
115
  }
55
116
  return null;
56
117
  }
57
- function assertGlob(routeString) {
58
- const numberOfGlobChars = routeString.split('*').length - 1;
59
- assertUsage(numberOfGlobChars <= 1, `Invalid Route String ${highlight(routeString)}: Route Strings aren't allowed to contain more than one glob ${highlight('*')} (use a Route Function instead)`);
60
- assertUsage(numberOfGlobChars === 0 || (numberOfGlobChars === 1 && routeString.endsWith('*')), `Invalid Route String ${highlight(routeString)}: make sure it ends with ${highlight('*')} or use a Route Function`);
61
- }
62
118
  function analyzeRouteString(routeString) {
63
- const routeSegments = routeString.split('/').filter((routeSegment) => routeSegment !== '' && routeSegment !== '*');
64
- let numberOfStaticSegmentsBeginning = 0;
65
- for (const routeSegment of routeSegments) {
66
- if (isParam(routeSegment)) {
119
+ const segments = parseRouteString(routeString);
120
+ const countStaticParts = (s) => s?.split('/').filter(Boolean).length || 0;
121
+ let numberOfStaticPartsBeginning = 0;
122
+ for (const segment of segments) {
123
+ if (!segment.static)
67
124
  break;
68
- }
69
- numberOfStaticSegmentsBeginning++;
125
+ numberOfStaticPartsBeginning += countStaticParts(segment.static);
70
126
  }
71
- const numberOfStaticSegements = routeSegments.filter((s) => !isParam(s)).length;
72
- const numberOfParameterSegments = routeSegments.filter((s) => isParam(s)).length;
73
- const isCatchAll = routeString.endsWith('*');
74
- return { numberOfParameterSegments, numberOfStaticSegmentsBeginning, numberOfStaticSegements, isCatchAll };
127
+ const numberOfStaticParts = segments.map((s) => countStaticParts(s.static)).reduce((sum, a) => sum + a, 0);
128
+ const numberOfParams = segments.filter((s) => s.param).length;
129
+ const numberOfGlobs = segments.filter((s) => s.glob).length;
130
+ return { numberOfStaticPartsBeginning, numberOfStaticParts, numberOfParams, numberOfGlobs };
75
131
  }
76
132
  function isParam(routeSegment) {
77
133
  return routeSegment.startsWith(PARAM_TOKEN_NEW) || routeSegment.startsWith(PARAM_TOKEN_OLD);
@@ -21,3 +21,4 @@ export * from '../utils/checkType.js';
21
21
  export * from '../utils/assertDefaultExport.js';
22
22
  export * from '../utils/objectEntries.js';
23
23
  export * from '../utils/getValuePrintable.js';
24
+ export * from '../utils/escapeRegex.js';
@@ -25,3 +25,4 @@ export * from '../utils/checkType.js';
25
25
  export * from '../utils/assertDefaultExport.js';
26
26
  export * from '../utils/objectEntries.js';
27
27
  export * from '../utils/getValuePrintable.js';
28
+ export * from '../utils/escapeRegex.js';
@@ -0,0 +1,3 @@
1
+ export { defineConfig };
2
+ import type { Config } from '../shared/page-configs/Config.js';
3
+ declare function defineConfig(config: Config): Config;
@@ -0,0 +1,4 @@
1
+ export { defineConfig };
2
+ function defineConfig(config) {
3
+ return config;
4
+ }
@@ -11,6 +11,7 @@ export type { ConfigEnv } from '../shared/page-configs/PageConfig.js';
11
11
  export type { ConfigDefinition, ConfigEffect } from '../node/plugin/plugins/importUserCode/v1-design/getVikeConfig/configDefinitionsBuiltIn.js';
12
12
  export type { ConfigEntries } from '../shared/getPageFiles/getExports.js';
13
13
  export type { InjectFilterEntry } from '../node/runtime/html/injectAssets/getHtmlTags.js';
14
+ export { defineConfig } from './defineConfig.js';
14
15
  import type { ConfigEnv } from '../shared/page-configs/PageConfig.js';
15
16
  /** @deprecated Replace:
16
17
  * `import type { Env } from 'vike/types'`
@@ -1 +1 @@
1
- export {};
1
+ export { defineConfig } from './defineConfig.js';
@@ -5,7 +5,7 @@ type ProjectVersion = typeof projectInfo.projectVersion;
5
5
  type ProjectTag = `[${PackageName}]` | `[${PackageName}@${ProjectVersion}]`;
6
6
  declare const projectInfo: {
7
7
  projectName: "Vike";
8
- projectVersion: "0.4.142-commit-acfc159";
8
+ projectVersion: "0.4.143";
9
9
  npmPackageName: "vike";
10
10
  githubRepository: "https://github.com/vikejs/vike";
11
11
  };
@@ -1,6 +1,6 @@
1
1
  export { projectInfo };
2
2
  import { onProjectInfo } from './assertSingleInstance.js';
3
- const PROJECT_VERSION = '0.4.142-commit-acfc159';
3
+ const PROJECT_VERSION = '0.4.143';
4
4
  const projectInfo = {
5
5
  projectName: 'Vike',
6
6
  projectVersion: PROJECT_VERSION,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vike",
3
- "version": "0.4.142-commit-acfc159",
3
+ "version": "0.4.143",
4
4
  "scripts": {
5
5
  "dev": "tsc --watch",
6
6
  "build": "rimraf dist/ && pnpm run build:esm && pnpm run build:cjs",
@@ -16,7 +16,7 @@
16
16
  "@brillout/json-serializer": "^0.5.6",
17
17
  "@brillout/picocolors": "^1.0.9",
18
18
  "@brillout/require-shim": "^0.1.2",
19
- "@brillout/vite-plugin-import-build": "^0.2.18",
19
+ "@brillout/vite-plugin-import-build": "^0.2.20",
20
20
  "acorn": "^8.8.2",
21
21
  "cac": "^6.7.14",
22
22
  "es-module-lexer": "^1.3.0",