vike 0.4.177 → 0.4.178-commit-fae90a1

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 (50) hide show
  1. package/dist/cjs/node/plugin/plugins/envVars.js +11 -3
  2. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/crawlPlusFiles.js +131 -20
  3. package/dist/cjs/node/runtime/html/injectAssets/getHtmlTags.js +6 -9
  4. package/dist/cjs/node/runtime/html/injectAssets/{getViteDevScripts.js → getViteDevScript.js} +5 -5
  5. package/dist/cjs/node/runtime/html/injectAssets/injectHtmlTags.js +20 -18
  6. package/dist/cjs/node/runtime/html/injectAssets.js +13 -10
  7. package/dist/cjs/node/runtime/html/renderHtml.js +4 -4
  8. package/dist/cjs/node/runtime/html/stream/react-streaming.js +11 -10
  9. package/dist/cjs/node/runtime/html/stream.js +18 -10
  10. package/dist/cjs/node/runtime/utils.js +1 -0
  11. package/dist/cjs/utils/assert.js +1 -1
  12. package/dist/cjs/utils/assertSingleInstance.js +7 -7
  13. package/dist/cjs/utils/isVikeReactApp.js +9 -0
  14. package/dist/cjs/utils/parseUrl.js +17 -12
  15. package/dist/cjs/utils/projectInfo.js +1 -1
  16. package/dist/esm/client/client-routing-runtime/entry.js +5 -2
  17. package/dist/esm/client/client-routing-runtime/getPageContextFromHooks.js +1 -0
  18. package/dist/esm/client/server-routing-runtime/entry.js +5 -2
  19. package/dist/esm/client/shared/removeFoucBuster.d.ts +2 -0
  20. package/dist/esm/client/shared/removeFoucBuster.js +39 -0
  21. package/dist/esm/client/shared/utils.d.ts +1 -0
  22. package/dist/esm/client/shared/utils.js +1 -0
  23. package/dist/esm/node/plugin/plugins/envVars.js +11 -3
  24. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/crawlPlusFiles.js +132 -21
  25. package/dist/esm/node/runtime/html/injectAssets/getHtmlTags.d.ts +2 -2
  26. package/dist/esm/node/runtime/html/injectAssets/getHtmlTags.js +6 -9
  27. package/dist/esm/node/runtime/html/injectAssets/getViteDevScript.d.ts +2 -0
  28. package/dist/esm/node/runtime/html/injectAssets/{getViteDevScripts.js → getViteDevScript.js} +4 -4
  29. package/dist/esm/node/runtime/html/injectAssets/injectHtmlTags.d.ts +5 -2
  30. package/dist/esm/node/runtime/html/injectAssets/injectHtmlTags.js +19 -17
  31. package/dist/esm/node/runtime/html/injectAssets.d.ts +2 -2
  32. package/dist/esm/node/runtime/html/injectAssets.js +14 -11
  33. package/dist/esm/node/runtime/html/renderHtml.js +5 -5
  34. package/dist/esm/node/runtime/html/stream/react-streaming.d.ts +16 -23
  35. package/dist/esm/node/runtime/html/stream/react-streaming.js +11 -10
  36. package/dist/esm/node/runtime/html/stream.d.ts +2 -2
  37. package/dist/esm/node/runtime/html/stream.js +19 -11
  38. package/dist/esm/node/runtime/utils.d.ts +1 -0
  39. package/dist/esm/node/runtime/utils.js +1 -0
  40. package/dist/esm/utils/assert.js +2 -2
  41. package/dist/esm/utils/assertSingleInstance.d.ts +6 -6
  42. package/dist/esm/utils/assertSingleInstance.js +6 -6
  43. package/dist/esm/utils/isVikeReactApp.d.ts +1 -0
  44. package/dist/esm/utils/isVikeReactApp.js +5 -0
  45. package/dist/esm/utils/parseUrl.d.ts +1 -1
  46. package/dist/esm/utils/parseUrl.js +17 -12
  47. package/dist/esm/utils/projectInfo.d.ts +2 -2
  48. package/dist/esm/utils/projectInfo.js +1 -1
  49. package/package.json +3 -3
  50. package/dist/esm/node/runtime/html/injectAssets/getViteDevScripts.d.ts +0 -2
@@ -5,6 +5,15 @@ const vite_1 = require("vite");
5
5
  const utils_js_1 = require("../utils.js");
6
6
  const rollupSourceMap_js_1 = require("../shared/rollupSourceMap.js");
7
7
  const getFilePath_js_1 = require("../shared/getFilePath.js");
8
+ // TODO/enventually: (after we implemented vike.config.js)
9
+ // - Make import.meta.env work inside +config.js
10
+ // - For it to work, we'll probably need the user to define the settings (e.g. `envDir`) for loadEnv() inside vike.config.js instead of vite.config.js
11
+ // - Or stop using Vite's `mode` implemention and have Vike implement its own `mode` feature? (So that the only dependencies are `$ vike build --mode staging` and `$ MODE=staging vike build`.)
12
+ const PUBLIC_ENV_PREFIX = 'PUBLIC_ENV__';
13
+ const PUBLIC_ENV_WHITELIST = [
14
+ // https://github.com/vikejs/vike/issues/1724
15
+ 'STORYBOOK'
16
+ ];
8
17
  function envVarsPlugin() {
9
18
  let envsAll;
10
19
  let config;
@@ -37,14 +46,13 @@ function envVarsPlugin() {
37
46
  // Security check
38
47
  {
39
48
  const envStatement = getEnvStatement(envName);
40
- const publicPrefix = 'PUBLIC_ENV__';
41
- const isPrivate = !envName.startsWith(publicPrefix);
49
+ const isPrivate = !envName.startsWith(PUBLIC_ENV_PREFIX) && !PUBLIC_ENV_WHITELIST.includes(envName);
42
50
  if (isPrivate && isClientSide) {
43
51
  if (!code.includes(envStatement))
44
52
  return;
45
53
  const modulePath = (0, getFilePath_js_1.getModuleFilePath)(id, config);
46
54
  const errMsgAddendum = isBuild ? '' : ' (Vike will prevent your app from building for production)';
47
- const keyPublic = `${publicPrefix}${envName}`;
55
+ const keyPublic = `${PUBLIC_ENV_PREFIX}${envName}`;
48
56
  const errMsg = `${envStatement} is used in client-side file ${modulePath} which means that the environment variable ${envName} will be included in client-side bundles and, therefore, ${envName} will be publicly exposed which can be a security leak${errMsgAddendum}. Use ${envStatement} only in server-side files, or rename ${envName} to ${keyPublic}, see https://vike.dev/env`;
49
57
  if (isBuild) {
50
58
  (0, utils_js_1.assertUsage)(false, errMsg);
@@ -6,12 +6,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.crawlPlusFiles = void 0;
7
7
  const utils_js_1 = require("../../../../utils.js");
8
8
  const path_1 = __importDefault(require("path"));
9
+ const promises_1 = __importDefault(require("fs/promises"));
9
10
  const fast_glob_1 = __importDefault(require("fast-glob"));
10
11
  const child_process_1 = require("child_process");
11
12
  const util_1 = require("util");
12
13
  const picocolors_1 = __importDefault(require("@brillout/picocolors"));
13
14
  const transpileAndExecuteFile_js_1 = require("./transpileAndExecuteFile.js");
14
15
  const execA = (0, util_1.promisify)(child_process_1.exec);
16
+ const TOO_MANY_UNTRACKED_FILES = 5;
15
17
  (0, utils_js_1.assertIsNotProductionRuntime)();
16
18
  (0, utils_js_1.assertIsSingleModuleInstance)('crawlPlusFiles.ts');
17
19
  let gitIsNotUsable = false;
@@ -35,15 +37,17 @@ async function crawlPlusFiles(userRootDir, outDirAbsoluteFilesystem, isDev, craw
35
37
  let files = [];
36
38
  const res = crawlWithGit !== false && (await gitLsFiles(userRootDir, outDirRelativeFromUserRootDir));
37
39
  if (res &&
38
- // Fallback to fast-glob for users that dynamically generate plus files. (Assuming all (generetad) plus files to be skipped because users usually included them in `.gitignore`.)
39
- res.length > 0) {
40
- files = res;
40
+ // Fallback to fast-glob for users that dynamically generate plus files. (Assuming that no plus file is found because of the user's .gitignore list.)
41
+ res.files.length > 0) {
42
+ files = res.files;
43
+ // We cannot find files inside symlink directories with `$ git ls-files` => we use fast-glob
44
+ files.push(...(await crawlSymlinkDirs(res.symlinkDirs, userRootDir, outDirRelativeFromUserRootDir)));
41
45
  }
42
46
  else {
43
47
  files = await fastGlob(userRootDir, outDirRelativeFromUserRootDir);
44
48
  }
45
49
  // Filter build files
46
- files = files.filter((file) => !(0, transpileAndExecuteFile_js_1.isTemporaryBuildFile)(file));
50
+ files = files.filter((filePath) => !(0, transpileAndExecuteFile_js_1.isTemporaryBuildFile)(filePath));
47
51
  // Check performance
48
52
  {
49
53
  const timeAfter = new Date().getTime();
@@ -51,8 +55,8 @@ async function crawlPlusFiles(userRootDir, outDirAbsoluteFilesystem, isDev, craw
51
55
  if (isDev) {
52
56
  // We only warn in dev, because while building it's expected to take a long time as crawling is competing for resources with other tasks.
53
57
  // Although, in dev, it's also competing for resources e.g. with Vite's `optimizeDeps`.
54
- (0, utils_js_1.assertWarning)(timeSpent < 3 * 1000, `Crawling your ${picocolors_1.default.cyan('+')} files took an unexpected long time (${(0, utils_js_1.humanizeTime)(timeSpent)}). If you repeatedly get this warning, then consider creating a new issue on Vike's GitHub.`, {
55
- onlyOnce: 'slow-page-files-search'
58
+ (0, utils_js_1.assertWarning)(timeSpent < 3 * 1000, `Crawling your ${picocolors_1.default.cyan('+')} files took an unexpected long time (${(0, utils_js_1.humanizeTime)(timeSpent)}). If you consistently get this warning, then consider reaching out on GitHub.`, {
59
+ onlyOnce: 'slow-crawling'
56
60
  });
57
61
  }
58
62
  }
@@ -82,20 +86,27 @@ async function gitLsFiles(userRootDir, outDirRelativeFromUserRootDir) {
82
86
  'git',
83
87
  preserveUTF8,
84
88
  'ls-files',
85
- ...utils_js_1.scriptFileExtensionList.map((ext) => `"**/+*.${ext}"`),
89
+ // We don't filter because:
90
+ // - It would skip symlink directories
91
+ // - Performance gain seems negligible: https://github.com/vikejs/vike/pull/1688#issuecomment-2166206648
92
+ // ...scriptFileExtensionList.map((ext) => `"**/+*.${ext}"`),
93
+ // Performance gain is non-negligible.
94
+ // - https://github.com/vikejs/vike/pull/1688#issuecomment-2166206648
95
+ // - When node_modules/ is untracked the performance gain could be significant?
86
96
  ...ignoreAsPatterns.map((pattern) => `--exclude="${pattern}"`),
87
- // --others lists untracked files only (but using .gitignore because --exclude-standard)
88
- // --cached adds the tracked files to the output
89
- '--others --cached --exclude-standard'
97
+ // --others --exclude-standard => list untracked files (--others) while using .gitignore (--exclude-standard)
98
+ // --cached => list tracked files
99
+ // --stage => get file modes which we use to find symlink directories
100
+ '--others --exclude-standard --cached --stage'
90
101
  ].join(' ');
91
- let files;
102
+ let resultLines;
92
103
  let filesDeleted;
93
104
  try {
94
105
  ;
95
- [files, filesDeleted] = await Promise.all([
106
+ [resultLines, filesDeleted] = await Promise.all([
96
107
  // Main command
97
108
  runCmd1(cmd, userRootDir),
98
- // Get tracked by deleted files
109
+ // Get tracked but deleted files
99
110
  runCmd1('git ls-files --deleted', userRootDir)
100
111
  ]);
101
112
  }
@@ -106,11 +117,40 @@ async function gitLsFiles(userRootDir, outDirRelativeFromUserRootDir) {
106
117
  }
107
118
  throw err;
108
119
  }
109
- files = files
110
- // We have to repeat the same exclusion logic here because the `git ls-files` option --exclude only applies to untracked files. (We use --exclude only to speed up the command.)
111
- .filter(ignoreAsFilterFn)
112
- .filter((file) => !filesDeleted.includes(file));
113
- return files;
120
+ const filePaths = resultLines.map(parseGitLsResultLine);
121
+ // If there are too many files without mode we fallback to fast-glob
122
+ if (filePaths.filter((f) => !f.mode).length > TOO_MANY_UNTRACKED_FILES)
123
+ return null;
124
+ const symlinkDirs = [];
125
+ const files = [];
126
+ for (const { filePath, mode } of filePaths) {
127
+ // Deleted?
128
+ if (filesDeleted.includes(filePath))
129
+ continue;
130
+ // We have to repeat the same exclusion logic here because the option --exclude of `$ git ls-files` only applies to untracked files. (We use --exclude only to speed up the `$ git ls-files` command.)
131
+ if (!ignoreAsFilterFn(filePath))
132
+ continue;
133
+ // Symlink directory?
134
+ {
135
+ const isSymlinkDir = await isSymlinkDirectory(mode, filePath, userRootDir);
136
+ if (isSymlinkDir) {
137
+ symlinkDirs.push(filePath);
138
+ continue;
139
+ }
140
+ // Skip deleted files and non-symlink directories
141
+ if (isSymlinkDir === null) {
142
+ continue;
143
+ }
144
+ }
145
+ // + file?
146
+ if (!path_1.default.posix.basename(filePath).startsWith('+'))
147
+ continue;
148
+ // JavaScript file?
149
+ if (!(0, utils_js_1.isScriptFile)(filePath))
150
+ continue;
151
+ files.push(filePath);
152
+ }
153
+ return { files, symlinkDirs };
114
154
  }
115
155
  // Same as gitLsFiles() but using fast-glob
116
156
  async function fastGlob(userRootDir, outDirRelativeFromUserRootDir) {
@@ -121,7 +161,7 @@ async function fastGlob(userRootDir, outDirRelativeFromUserRootDir) {
121
161
  });
122
162
  return files;
123
163
  }
124
- // Same as getIgnoreFilter() but as glob pattern
164
+ // Same as getIgnoreAsFilterFn() but as glob pattern
125
165
  function getIgnoreAsPatterns(outDirRelativeFromUserRootDir) {
126
166
  const ignoreAsPatterns = [
127
167
  '**/node_modules/**',
@@ -138,7 +178,7 @@ function getIgnoreAsPatterns(outDirRelativeFromUserRootDir) {
138
178
  }
139
179
  return ignoreAsPatterns;
140
180
  }
141
- // Same as getIgnorePatterns() but for Array.filter()
181
+ // Same as getIgnoreAsPatterns() but for Array.filter()
142
182
  function getIgnoreAsFilterFn(outDirRelativeFromUserRootDir) {
143
183
  (0, utils_js_1.assert)(outDirRelativeFromUserRootDir === null || !outDirRelativeFromUserRootDir.startsWith('/'));
144
184
  return (file) => !file.includes('node_modules/') &&
@@ -175,6 +215,77 @@ async function isGitNotUsable(userRootDir) {
175
215
  return false;
176
216
  }
177
217
  }
218
+ async function crawlSymlinkDirs(symlinkDirs, userRootDir, outDirRelativeFromUserRootDir) {
219
+ const filesInSymlinkDirs = (await Promise.all(symlinkDirs.map(async (symlinkDir) => (await fastGlob(path_1.default.posix.join(userRootDir, symlinkDir), outDirRelativeFromUserRootDir)).map((filePath) => path_1.default.posix.join(symlinkDir, filePath))))).flat();
220
+ return filesInSymlinkDirs;
221
+ }
222
+ // Parse:
223
+ // ```
224
+ // some/not/tracked/path
225
+ // 100644 f6928073402b241b468b199893ff6f4aed0b7195 0\tpages/index/+Page.tsx
226
+ // ```
227
+ function parseGitLsResultLine(resultLine) {
228
+ const [part1, part2, ...rest] = resultLine.split('\t');
229
+ (0, utils_js_1.assert)(part1);
230
+ (0, utils_js_1.assert)(rest.length === 0);
231
+ // Git doesn't provide the mode for untracked paths.
232
+ // `resultLine` is:
233
+ // ```
234
+ // some/not/tracked/path
235
+ // ```
236
+ if (part2 === undefined) {
237
+ return { filePath: part1, mode: null };
238
+ }
239
+ (0, utils_js_1.assert)(part2);
240
+ // `resultLine` is:
241
+ // ```
242
+ // 100644 f6928073402b241b468b199893ff6f4aed0b7195 0\tpages/index/+Page.tsx
243
+ // ```
244
+ const [mode, _, __, ...rest2] = part1.split(' ');
245
+ (0, utils_js_1.assert)(mode && _ && __ && rest2.length === 0);
246
+ return { filePath: part2, mode };
247
+ }
248
+ async function isSymlinkDirectory(mode, filePath, userRootDir) {
249
+ const filePathAbsolute = path_1.default.posix.join(userRootDir, filePath);
250
+ let stats = null;
251
+ let isSymlink = false;
252
+ if (mode === '120000') {
253
+ isSymlink = true;
254
+ }
255
+ else if (mode === null) {
256
+ // `$ git ls-files` doesn't provide the mode when Git doesn't track the path
257
+ stats = await getFileStats(filePathAbsolute);
258
+ if (stats === null)
259
+ return null;
260
+ isSymlink = stats.isSymbolicLink();
261
+ if (!isSymlink && stats.isDirectory())
262
+ return null;
263
+ }
264
+ else {
265
+ (0, utils_js_1.assert)(mode);
266
+ }
267
+ if (!isSymlink)
268
+ return false;
269
+ if (!stats)
270
+ stats = await getFileStats(filePathAbsolute);
271
+ if (stats === null)
272
+ return null;
273
+ const isDirectory = stats.isDirectory();
274
+ return isDirectory;
275
+ }
276
+ async function getFileStats(filePathAbsolute) {
277
+ let stats;
278
+ try {
279
+ stats = await promises_1.default.lstat(filePathAbsolute);
280
+ }
281
+ catch (err) {
282
+ // File was deleted, usually a temporary file such as +config.js.build-j95xb988fpln.mjs
283
+ // ENOENT: no such file or directory
284
+ (0, utils_js_1.assert)(err.code === 'ENOENT');
285
+ return null;
286
+ }
287
+ return stats;
288
+ }
178
289
  async function runCmd1(cmd, cwd) {
179
290
  const { stdout } = await execA(cmd, { cwd });
180
291
  /* Not always true: https://github.com/vikejs/vike/issues/1440#issuecomment-1892831303
@@ -8,16 +8,14 @@ const utils_js_1 = require("../../utils.js");
8
8
  const serializePageContextClientSide_js_1 = require("../serializePageContextClientSide.js");
9
9
  const sanitizeJson_js_1 = require("./sanitizeJson.js");
10
10
  const inferHtmlTags_js_1 = require("./inferHtmlTags.js");
11
- const getViteDevScripts_js_1 = require("./getViteDevScripts.js");
12
11
  const mergeScriptTags_js_1 = require("./mergeScriptTags.js");
13
12
  const globalContext_js_1 = require("../../globalContext.js");
14
13
  const picocolors_1 = __importDefault(require("@brillout/picocolors"));
15
14
  const stamp = '__injectFilterEntry';
16
- async function getHtmlTags(pageContext, injectToStream, injectFilter) {
15
+ function getHtmlTags(pageContext, streamFromReactStreamingPackage, injectFilter, pageAssets, viteDevScript) {
17
16
  (0, utils_js_1.assert)([true, false].includes(pageContext._isHtmlOnly));
18
17
  const isHtmlOnly = pageContext._isHtmlOnly;
19
18
  const { isProduction } = (0, globalContext_js_1.getGlobalContext)();
20
- const pageAssets = await pageContext.__getPageAssets();
21
19
  const injectFilterEntries = pageAssets
22
20
  .filter((asset) => {
23
21
  if (asset.isEntry && asset.assetType === 'script') {
@@ -90,11 +88,11 @@ async function getHtmlTags(pageContext, injectToStream, injectFilter) {
90
88
  // See https://github.com/vikejs/vike/pull/1271
91
89
  const positionJavaScriptEntry = (() => {
92
90
  if (pageContext._pageContextPromise) {
93
- (0, utils_js_1.assertWarning)(!injectToStream, "[getHtmlTags()] We recommend against using streaming and a pageContext promise at the same time, because progressive hydration won't work.", { onlyOnce: true });
91
+ (0, utils_js_1.assertWarning)(!streamFromReactStreamingPackage, "[getHtmlTags()] We recommend against using streaming and a pageContext promise at the same time, because progressive hydration won't work.", { onlyOnce: true });
94
92
  // If there is a pageContext._pageContextPromise (which is resolved after the stream has ended) then the pageContext JSON data needs to await for it: https://vike.dev/streaming#initial-data-after-stream-end
95
93
  return 'HTML_END';
96
94
  }
97
- if (injectToStream) {
95
+ if (streamFromReactStreamingPackage && !streamFromReactStreamingPackage.hasStreamEnded()) {
98
96
  // If there is a stream then, in order to support progressive hydration, inject the JavaScript during the stream after React(/Vue/Solid/...) resolved the first suspense boundary
99
97
  return 'STREAM';
100
98
  }
@@ -112,7 +110,7 @@ async function getHtmlTags(pageContext, injectToStream, injectFilter) {
112
110
  });
113
111
  }
114
112
  // The JavaScript entry <script> tag
115
- const scriptEntry = await mergeScriptEntries(pageAssets);
113
+ const scriptEntry = mergeScriptEntries(pageAssets, viteDevScript);
116
114
  if (scriptEntry) {
117
115
  htmlTags.push({
118
116
  htmlTag: scriptEntry,
@@ -134,10 +132,9 @@ async function getHtmlTags(pageContext, injectToStream, injectFilter) {
134
132
  return htmlTags;
135
133
  }
136
134
  exports.getHtmlTags = getHtmlTags;
137
- async function mergeScriptEntries(pageAssets) {
135
+ function mergeScriptEntries(pageAssets, viteDevScript) {
138
136
  const scriptEntries = pageAssets.filter((pageAsset) => pageAsset.isEntry && pageAsset.assetType === 'script');
139
- const viteScripts = await (0, getViteDevScripts_js_1.getViteDevScripts)();
140
- const scriptTagsHtml = `${viteScripts}${scriptEntries.map((asset) => (0, inferHtmlTags_js_1.inferAssetTag)(asset)).join('')}`;
137
+ const scriptTagsHtml = `${viteDevScript}${scriptEntries.map((asset) => (0, inferHtmlTags_js_1.inferAssetTag)(asset)).join('')}`;
141
138
  const scriptTag = (0, mergeScriptTags_js_1.mergeScriptTags)(scriptTagsHtml);
142
139
  return scriptTag;
143
140
  }
@@ -3,11 +3,11 @@ 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.getViteDevScripts = void 0;
6
+ exports.getViteDevScript = void 0;
7
7
  const globalContext_js_1 = require("../../globalContext.js");
8
8
  const utils_js_1 = require("../../utils.js");
9
9
  const picocolors_1 = __importDefault(require("@brillout/picocolors"));
10
- async function getViteDevScripts() {
10
+ async function getViteDevScript() {
11
11
  const globalContext = (0, globalContext_js_1.getGlobalContext)();
12
12
  if (globalContext.isProduction) {
13
13
  return '';
@@ -23,7 +23,7 @@ async function getViteDevScripts() {
23
23
  const viteInjection = fakeHtml.slice(fakeHtmlBegin.length, -1 * fakeHtmlEnd.length);
24
24
  (0, utils_js_1.assert)(viteInjection.includes('script'));
25
25
  (0, utils_js_1.assertWarning)(!viteInjection.includes('import('), 'Unexpected Vite HMR code. Reach out to a Vike maintainer on GitHub.', { onlyOnce: true });
26
- const scriptTags = viteInjection;
27
- return scriptTags;
26
+ const viteDevScript = viteInjection;
27
+ return viteDevScript;
28
28
  }
29
- exports.getViteDevScripts = getViteDevScripts;
29
+ exports.getViteDevScript = getViteDevScript;
@@ -1,23 +1,30 @@
1
1
  "use strict";
2
2
  // Unit tests at ./injectHtmlTags.spec.ts
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.injectAtClosingTag = exports.injectAtOpeningTag = exports.createHtmlHeadIfMissing = exports.injectHtmlTags = void 0;
4
+ exports.injectAtClosingTag = exports.injectAtOpeningTag = exports.createHtmlHeadIfMissing = exports.injectHtmlTagsUsingStream = exports.injectHtmlTags = void 0;
5
5
  const utils_js_1 = require("../../utils.js");
6
- const POSITIONS = ['HTML_BEGIN', 'HTML_END', 'STREAM'];
7
- function injectHtmlTags(htmlString, htmlTags, injectToStream) {
8
- POSITIONS.forEach((position) => {
9
- const htmlFragment = htmlTags
10
- .filter((h) => h.position === position)
11
- .map((h) => resolveHtmlTag(h.htmlTag))
12
- .join('');
13
- if (htmlFragment) {
14
- htmlString = injectHtmlFragment(position, htmlFragment, htmlString, injectToStream);
15
- }
16
- });
6
+ function injectHtmlTags(htmlString, htmlTags, position) {
7
+ const htmlFragment = joinHtmlTags(htmlTags.filter((h) => h.position === position));
8
+ if (htmlFragment) {
9
+ htmlString = injectHtmlFragment(position, htmlFragment, htmlString);
10
+ }
17
11
  return htmlString;
18
12
  }
19
13
  exports.injectHtmlTags = injectHtmlTags;
20
- function injectHtmlFragment(position, htmlFragment, htmlString, injectToStream) {
14
+ async function injectHtmlTagsUsingStream(htmlTags, streamFromReactStreamingPackage) {
15
+ const htmlFragment = joinHtmlTags(htmlTags.filter((h) => h.position === 'STREAM'));
16
+ if (htmlFragment) {
17
+ (0, utils_js_1.assert)(streamFromReactStreamingPackage);
18
+ (0, utils_js_1.assert)(!streamFromReactStreamingPackage.hasStreamEnded());
19
+ await streamFromReactStreamingPackage.injectToStream(htmlFragment, { flush: true });
20
+ }
21
+ }
22
+ exports.injectHtmlTagsUsingStream = injectHtmlTagsUsingStream;
23
+ function joinHtmlTags(htmlTags) {
24
+ const htmlFragment = htmlTags.map((h) => resolveHtmlTag(h.htmlTag)).join('');
25
+ return htmlFragment;
26
+ }
27
+ function injectHtmlFragment(position, htmlFragment, htmlString) {
21
28
  if (position === 'HTML_BEGIN') {
22
29
  {
23
30
  const res = injectAtPaceholder(htmlFragment, htmlString, true);
@@ -42,11 +49,6 @@ function injectHtmlFragment(position, htmlFragment, htmlString, injectToStream)
42
49
  }
43
50
  return htmlString + '\n' + htmlFragment;
44
51
  }
45
- if (position === 'STREAM') {
46
- (0, utils_js_1.assert)(injectToStream);
47
- injectToStream(htmlFragment, { flush: true });
48
- return htmlString;
49
- }
50
52
  (0, utils_js_1.assert)(false);
51
53
  }
52
54
  function resolveHtmlTag(htmlTag) {
@@ -5,26 +5,31 @@ const utils_js_1 = require("../utils.js");
5
5
  const assertPageContextProvidedByUser_js_1 = require("../../../shared/assertPageContextProvidedByUser.js");
6
6
  const injectHtmlTags_js_1 = require("./injectAssets/injectHtmlTags.js");
7
7
  const getHtmlTags_js_1 = require("./injectAssets/getHtmlTags.js");
8
+ const getViteDevScript_js_1 = require("./injectAssets/getViteDevScript.js");
8
9
  async function injectHtmlTagsToString(htmlParts, pageContext, injectFilter) {
9
- const htmlTags = await (0, getHtmlTags_js_1.getHtmlTags)(pageContext, null, injectFilter);
10
10
  const pageAssets = await pageContext.__getPageAssets();
11
+ const viteDevScript = await (0, getViteDevScript_js_1.getViteDevScript)();
12
+ const htmlTags = (0, getHtmlTags_js_1.getHtmlTags)(pageContext, null, injectFilter, pageAssets, viteDevScript);
11
13
  let htmlString = htmlPartsToString(htmlParts, pageAssets);
12
- htmlString = injectToHtmlBegin(htmlString, htmlTags, null);
14
+ htmlString = injectToHtmlBegin(htmlString, htmlTags);
13
15
  htmlString = injectToHtmlEnd(htmlString, htmlTags);
16
+ (0, utils_js_1.assert)(htmlTags.filter((snippet) => snippet.position === 'STREAM').length === 0);
14
17
  return htmlString;
15
18
  }
16
19
  exports.injectHtmlTagsToString = injectHtmlTagsToString;
17
- function injectHtmlTagsToStream(pageContext, injectToStream, injectFilter) {
20
+ function injectHtmlTagsToStream(pageContext, streamFromReactStreamingPackage, injectFilter) {
18
21
  let htmlTags;
19
22
  return {
20
23
  injectAtStreamBegin,
21
24
  injectAtStreamEnd
22
25
  };
23
26
  async function injectAtStreamBegin(htmlPartsBegin) {
24
- htmlTags = await (0, getHtmlTags_js_1.getHtmlTags)(pageContext, injectToStream, injectFilter);
25
27
  const pageAssets = await pageContext.__getPageAssets();
28
+ const viteDevScript = await (0, getViteDevScript_js_1.getViteDevScript)();
29
+ htmlTags = (0, getHtmlTags_js_1.getHtmlTags)(pageContext, streamFromReactStreamingPackage, injectFilter, pageAssets, viteDevScript);
26
30
  let htmlBegin = htmlPartsToString(htmlPartsBegin, pageAssets);
27
- htmlBegin = injectToHtmlBegin(htmlBegin, htmlTags, injectToStream);
31
+ htmlBegin = injectToHtmlBegin(htmlBegin, htmlTags);
32
+ await (0, injectHtmlTags_js_1.injectHtmlTagsUsingStream)(htmlTags, streamFromReactStreamingPackage);
28
33
  return htmlBegin;
29
34
  }
30
35
  async function injectAtStreamEnd(htmlPartsEnd) {
@@ -37,16 +42,14 @@ function injectHtmlTagsToStream(pageContext, injectToStream, injectFilter) {
37
42
  }
38
43
  }
39
44
  exports.injectHtmlTagsToStream = injectHtmlTagsToStream;
40
- function injectToHtmlBegin(htmlBegin, htmlTags, injectToStream) {
41
- const htmlTagsAtBegin = htmlTags.filter((snippet) => snippet.position !== 'HTML_END');
45
+ function injectToHtmlBegin(htmlBegin, htmlTags) {
42
46
  // Ensure existence of `<head>`
43
47
  htmlBegin = (0, injectHtmlTags_js_1.createHtmlHeadIfMissing)(htmlBegin);
44
- htmlBegin = (0, injectHtmlTags_js_1.injectHtmlTags)(htmlBegin, htmlTagsAtBegin, injectToStream);
48
+ htmlBegin = (0, injectHtmlTags_js_1.injectHtmlTags)(htmlBegin, htmlTags, 'HTML_BEGIN');
45
49
  return htmlBegin;
46
50
  }
47
51
  function injectToHtmlEnd(htmlEnd, htmlTags) {
48
- const htmlTagsAtEnd = htmlTags.filter((snippet) => snippet.position === 'HTML_END');
49
- htmlEnd = (0, injectHtmlTags_js_1.injectHtmlTags)(htmlEnd, htmlTagsAtEnd, null);
52
+ htmlEnd = (0, injectHtmlTags_js_1.injectHtmlTags)(htmlEnd, htmlTags, 'HTML_END');
50
53
  return htmlEnd;
51
54
  }
52
55
  async function resolvePageContextPromise(pageContext) {
@@ -60,11 +60,11 @@ async function renderHtmlStream(streamOriginal, injectString, pageContext, onErr
60
60
  enableEagerStreaming: pageContext.enableEagerStreaming
61
61
  };
62
62
  if (injectString) {
63
- let injectToStream = null;
64
- if ((0, react_streaming_js_1.isStreamReactStreaming)(streamOriginal) && !streamOriginal.disabled) {
65
- injectToStream = streamOriginal.injectToStream;
63
+ let streamFromReactStreamingPackage = null;
64
+ if ((0, react_streaming_js_1.isStreamFromReactStreamingPackage)(streamOriginal) && !streamOriginal.disabled) {
65
+ streamFromReactStreamingPackage = streamOriginal;
66
66
  }
67
- const { injectAtStreamBegin, injectAtStreamEnd } = (0, injectAssets_js_1.injectHtmlTagsToStream)(pageContext, injectToStream, injectFilter);
67
+ const { injectAtStreamBegin, injectAtStreamEnd } = (0, injectAssets_js_1.injectHtmlTagsToStream)(pageContext, streamFromReactStreamingPackage, injectFilter);
68
68
  (0, utils_js_1.objectAssign)(opts, {
69
69
  injectStringAtBegin: async () => {
70
70
  return await injectAtStreamBegin(injectString.htmlPartsBegin);
@@ -1,10 +1,10 @@
1
1
  "use strict";
2
2
  // Zero-config support for https://www.npmjs.com/package/react-streaming
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.getStreamFromReactStreaming = exports.streamReactStreamingToString = exports.isStreamReactStreaming = void 0;
4
+ exports.getStreamOfReactStreamingPackage = exports.streamFromReactStreamingPackageToString = exports.isStreamFromReactStreamingPackage = void 0;
5
5
  const utils_js_1 = require("../../utils.js");
6
6
  const stream_js_1 = require("../stream.js");
7
- function streamReactStreamingToString(stream) {
7
+ function streamFromReactStreamingPackageToString(stream) {
8
8
  if (stream.pipe) {
9
9
  return (0, stream_js_1.streamPipeNodeToString)(stream.pipe);
10
10
  }
@@ -13,19 +13,20 @@ function streamReactStreamingToString(stream) {
13
13
  }
14
14
  (0, utils_js_1.assert)(false);
15
15
  }
16
- exports.streamReactStreamingToString = streamReactStreamingToString;
17
- function isStreamReactStreaming(thing) {
16
+ exports.streamFromReactStreamingPackageToString = streamFromReactStreamingPackageToString;
17
+ function isStreamFromReactStreamingPackage(thing) {
18
18
  if ((0, utils_js_1.hasProp)(thing, 'injectToStream', 'function')) {
19
+ (0, utils_js_1.assertUsage)((0, utils_js_1.hasProp)(thing, 'hasStreamEnded', 'function'), (0, utils_js_1.isVikeReactApp)()
20
+ ? //
21
+ 'Update vike-react to its latest version'
22
+ : 'Update react-streaming to its latest version');
19
23
  return true;
20
24
  }
21
- // TODO
22
- //if( isStreamPipeNode
23
25
  return false;
24
26
  }
25
- exports.isStreamReactStreaming = isStreamReactStreaming;
26
- function getStreamFromReactStreaming(stream) {
27
+ exports.isStreamFromReactStreamingPackage = isStreamFromReactStreamingPackage;
28
+ function getStreamOfReactStreamingPackage(stream) {
27
29
  if (stream.pipe) {
28
- // TODO
29
30
  return { __streamPipeNode: stream.pipe };
30
31
  }
31
32
  if (stream.readable) {
@@ -33,4 +34,4 @@ function getStreamFromReactStreaming(stream) {
33
34
  }
34
35
  (0, utils_js_1.assert)(false);
35
36
  }
36
- exports.getStreamFromReactStreaming = getStreamFromReactStreaming;
37
+ exports.getStreamOfReactStreamingPackage = getStreamOfReactStreamingPackage;
@@ -354,9 +354,9 @@ async function processStream(streamOriginal, { injectStringAtBegin, injectString
354
354
  }
355
355
  exports.processStream = processStream;
356
356
  async function createStreamWrapper({ streamOriginal, onError, onData, onEnd, onFlush, onReadyToWrite }) {
357
- if ((0, react_streaming_js_1.isStreamReactStreaming)(streamOriginal)) {
357
+ if ((0, react_streaming_js_1.isStreamFromReactStreamingPackage)(streamOriginal)) {
358
358
  debug(`onRenderHtml() hook returned ${picocolors_1.default.cyan('react-streaming')} result`);
359
- const stream = (0, react_streaming_js_1.getStreamFromReactStreaming)(streamOriginal);
359
+ const stream = (0, react_streaming_js_1.getStreamOfReactStreamingPackage)(streamOriginal);
360
360
  streamOriginal = stream;
361
361
  }
362
362
  if (isStreamPipeNode(streamOriginal)) {
@@ -376,7 +376,7 @@ async function createStreamWrapper({ streamOriginal, onError, onData, onEnd, onF
376
376
  (0, utils_js_1.assert)(writableOriginal);
377
377
  writableOriginal.write(chunk);
378
378
  if (debug.isActivated) {
379
- debug('data written (Node.js Writable)', String(chunk));
379
+ debug('data written (Node.js Writable)', getChunkAsString(chunk));
380
380
  }
381
381
  };
382
382
  // For libraries such as https://www.npmjs.com/package/compression
@@ -449,7 +449,7 @@ async function createStreamWrapper({ streamOriginal, onError, onData, onEnd, onF
449
449
  (0, utils_js_1.assert)(writerOriginal);
450
450
  writerOriginal.write(encodeForWebStream(chunk));
451
451
  if (debug.isActivated) {
452
- debug('data written (Web Writable)', String(chunk));
452
+ debug('data written (Web Writable)', getChunkAsString(chunk));
453
453
  }
454
454
  };
455
455
  // Web Streams have compression built-in
@@ -542,12 +542,12 @@ async function createStreamWrapper({ streamOriginal, onError, onData, onEnd, onF
542
542
  !controllerProxyIsClosed) {
543
543
  controllerProxy.enqueue(encodeForWebStream(chunk));
544
544
  if (debug.isActivated) {
545
- debug('data written (Web Readable)', String(chunk));
545
+ debug('data written (Web Readable)', getChunkAsString(chunk));
546
546
  }
547
547
  }
548
548
  else {
549
549
  if (debug.isActivated) {
550
- debug('data emitted but not written (Web Readable)', String(chunk));
550
+ debug('data emitted but not written (Web Readable)', getChunkAsString(chunk));
551
551
  }
552
552
  }
553
553
  };
@@ -569,7 +569,7 @@ async function createStreamWrapper({ streamOriginal, onError, onData, onEnd, onF
569
569
  const writeChunk = (chunk) => {
570
570
  readableProxy.push(chunk);
571
571
  if (debug.isActivated) {
572
- debug('data written (Node.js Readable)', String(chunk));
572
+ debug('data written (Node.js Readable)', getChunkAsString(chunk));
573
573
  }
574
574
  };
575
575
  // Readables don't have the notion of flushing
@@ -621,7 +621,7 @@ function isStream(something) {
621
621
  isStreamReadableNode(something) ||
622
622
  isStreamPipeNode(something) ||
623
623
  isStreamPipeWeb(something) ||
624
- (0, react_streaming_js_1.isStreamReactStreaming)(something)) {
624
+ (0, react_streaming_js_1.isStreamFromReactStreamingPackage)(something)) {
625
625
  (0, utils_js_1.checkType)(something);
626
626
  return true;
627
627
  }
@@ -733,8 +733,8 @@ async function streamToString(stream) {
733
733
  if (isStreamPipeWeb(stream)) {
734
734
  return await streamPipeWebToString(getStreamPipeWeb(stream));
735
735
  }
736
- if ((0, react_streaming_js_1.isStreamReactStreaming)(stream)) {
737
- return await (0, react_streaming_js_1.streamReactStreamingToString)(stream);
736
+ if ((0, react_streaming_js_1.isStreamFromReactStreamingPackage)(stream)) {
737
+ return await (0, react_streaming_js_1.streamFromReactStreamingPackageToString)(stream);
738
738
  }
739
739
  (0, utils_js_1.assert)(false);
740
740
  }
@@ -793,3 +793,11 @@ function inferStreamName(stream) {
793
793
  (0, utils_js_1.assert)(false);
794
794
  }
795
795
  exports.inferStreamName = inferStreamName;
796
+ function getChunkAsString(chunk) {
797
+ try {
798
+ return new TextDecoder().decode(chunk);
799
+ }
800
+ catch (err) {
801
+ return String(chunk);
802
+ }
803
+ }
@@ -70,3 +70,4 @@ __exportStar(require("../../utils/joinEnglish.js"), exports);
70
70
  __exportStar(require("../../utils/isArrayOfStrings.js"), exports);
71
71
  __exportStar(require("../../utils/escapeHtml.js"), exports);
72
72
  __exportStar(require("../../utils/normalizeHeaders.js"), exports);
73
+ __exportStar(require("../../utils/isVikeReactApp.js"), exports);
@@ -23,7 +23,7 @@ const globalObject = (0, getGlobalObject_js_1.getGlobalObject)('utils/assert.ts'
23
23
  },
24
24
  showStackTraceList: new WeakSet()
25
25
  });
26
- (0, assertSingleInstance_js_1.onAssertModuleLoad)();
26
+ (0, assertSingleInstance_js_1.assertSingleInstance_onAssertModuleLoad)();
27
27
  const projectTag = `[vike]`;
28
28
  const projectTagWithVersion = `[vike@${projectInfo_js_1.projectInfo.projectVersion}]`;
29
29
  const numberOfStackTraceLinesToRemove = 2;