@vistagenic/vista 0.1.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/build-rsc.js +3 -2
- package/dist/bin/build.js +3 -2
- package/dist/bin/webpack.config.js +2 -1
- package/dist/build/manifest.d.ts +2 -0
- package/dist/build/manifest.js +9 -6
- package/dist/build/rsc/client-manifest.js +4 -3
- package/dist/build/rsc/compiler.js +7 -6
- package/dist/build/rsc/server-manifest.js +2 -1
- package/dist/build/webpack/plugins/vista-flight-plugin.js +2 -1
- package/dist/client/hydration.js +2 -1
- package/dist/constants.d.ts +46 -0
- package/dist/constants.js +67 -0
- package/dist/dev-error.js +2 -1
- package/dist/font/local.js +2 -1
- package/dist/image/image-config.js +2 -1
- package/dist/image/image-loader.js +2 -1
- package/dist/integrity.d.ts +28 -0
- package/dist/integrity.js +116 -0
- package/dist/server/artifact-validator.js +6 -11
- package/dist/server/engine.js +9 -8
- package/dist/server/logger.js +2 -2
- package/dist/server/rsc-engine.js +34 -24
- package/dist/server/rsc-upstream.js +14 -3
- package/dist/server/structure-watch.js +2 -1
- package/package.json +3 -3
package/dist/bin/build-rsc.js
CHANGED
|
@@ -22,6 +22,7 @@ const client_manifest_1 = require("../build/rsc/client-manifest");
|
|
|
22
22
|
const server_manifest_1 = require("../build/rsc/server-manifest");
|
|
23
23
|
const file_scanner_1 = require("./file-scanner");
|
|
24
24
|
const config_1 = require("../config");
|
|
25
|
+
const constants_1 = require("../constants");
|
|
25
26
|
const structure_validator_1 = require("../server/structure-validator");
|
|
26
27
|
const static_generator_1 = require("../server/static-generator");
|
|
27
28
|
const structure_log_1 = require("../server/structure-log");
|
|
@@ -67,7 +68,7 @@ import { createFromFetch } from 'react-server-dom-webpack/client';
|
|
|
67
68
|
import { RSCRouter } from 'vista/client/rsc-router';
|
|
68
69
|
import { callServer } from 'vista/client/server-actions';
|
|
69
70
|
|
|
70
|
-
const hydrateDocument = (window as any).
|
|
71
|
+
const hydrateDocument = (window as any).${constants_1.HYDRATE_DOCUMENT_FLAG} === true;
|
|
71
72
|
const rootElement = hydrateDocument ? document : document.getElementById('root');
|
|
72
73
|
if (!rootElement) {
|
|
73
74
|
throw new Error('Missing #root element for hydration.');
|
|
@@ -90,7 +91,7 @@ hydrateRoot(
|
|
|
90
91
|
|
|
91
92
|
// Vista live-reload: listen for server component changes via SSE
|
|
92
93
|
(function connectReload() {
|
|
93
|
-
const es = new EventSource('
|
|
94
|
+
const es = new EventSource('${constants_1.SSE_ENDPOINT}');
|
|
94
95
|
es.onmessage = (e) => {
|
|
95
96
|
if (e.data === 'reload') {
|
|
96
97
|
window.location.reload();
|
package/dist/bin/build.js
CHANGED
|
@@ -12,6 +12,7 @@ const webpack_config_1 = require("./webpack.config");
|
|
|
12
12
|
const file_scanner_1 = require("./file-scanner");
|
|
13
13
|
const manifest_1 = require("../build/manifest");
|
|
14
14
|
const config_1 = require("../config");
|
|
15
|
+
const constants_1 = require("../constants");
|
|
15
16
|
const structure_validator_1 = require("../server/structure-validator");
|
|
16
17
|
const structure_log_1 = require("../server/structure-log");
|
|
17
18
|
const _debug = !!process.env.VISTA_DEBUG;
|
|
@@ -237,7 +238,7 @@ function hideCompileError() {
|
|
|
237
238
|
if (div) div.remove();
|
|
238
239
|
}
|
|
239
240
|
|
|
240
|
-
const sse = new EventSource('
|
|
241
|
+
const sse = new EventSource('${constants_1.SSE_ENDPOINT}');
|
|
241
242
|
sse.onmessage = (event) => {
|
|
242
243
|
if (event.data === 'reload') {
|
|
243
244
|
hideCompileError();
|
|
@@ -265,7 +266,7 @@ sse.onerror = (e) => {
|
|
|
265
266
|
: '// SSE reload disabled in production'}
|
|
266
267
|
|
|
267
268
|
// Export for debugging
|
|
268
|
-
(window as any).
|
|
269
|
+
(window as any).${constants_1.CLIENT_COMPONENTS_FLAG} = CLIENT_COMPONENTS;
|
|
269
270
|
`;
|
|
270
271
|
fs_1.default.writeFileSync(path_1.default.join(vistaDir, 'client.tsx'), clientEntryContent);
|
|
271
272
|
if (_debug) {
|
|
@@ -10,9 +10,10 @@ const react_refresh_webpack_plugin_1 = __importDefault(require("@pmmmwh/react-re
|
|
|
10
10
|
const mini_css_extract_plugin_1 = __importDefault(require("mini-css-extract-plugin"));
|
|
11
11
|
const server_component_plugin_1 = require("./server-component-plugin");
|
|
12
12
|
const vista_flight_plugin_1 = require("../build/webpack/plugins/vista-flight-plugin");
|
|
13
|
+
const constants_1 = require("../constants");
|
|
13
14
|
function createWebpackConfig(options) {
|
|
14
15
|
const { cwd, isDev } = options;
|
|
15
|
-
const vistaDir = path_1.default.join(cwd,
|
|
16
|
+
const vistaDir = path_1.default.join(cwd, constants_1.BUILD_DIR);
|
|
16
17
|
const entryPoint = path_1.default.join(vistaDir, 'client.tsx');
|
|
17
18
|
// Find React - check local node_modules first, then traverse up for monorepo hoisting
|
|
18
19
|
const findModulePath = (moduleName) => {
|
package/dist/build/manifest.d.ts
CHANGED
|
@@ -38,6 +38,8 @@ export interface ArtifactManifest {
|
|
|
38
38
|
schemaVersion: number;
|
|
39
39
|
buildId: string;
|
|
40
40
|
generatedAt: string;
|
|
41
|
+
/** Integrity watermark — framework identity + hash token */
|
|
42
|
+
__integrity?: string;
|
|
41
43
|
manifests: {
|
|
42
44
|
buildManifest: string;
|
|
43
45
|
routesManifest: string;
|
package/dist/build/manifest.js
CHANGED
|
@@ -26,6 +26,8 @@ exports.cleanOldCache = cleanOldCache;
|
|
|
26
26
|
const fs_1 = __importDefault(require("fs"));
|
|
27
27
|
const path_1 = __importDefault(require("path"));
|
|
28
28
|
const crypto_1 = __importDefault(require("crypto"));
|
|
29
|
+
const constants_1 = require("../constants");
|
|
30
|
+
const integrity_1 = require("../integrity");
|
|
29
31
|
// ============================================================================
|
|
30
32
|
// BUILD_ID Generation
|
|
31
33
|
// ============================================================================
|
|
@@ -56,7 +58,7 @@ function getBuildId(vistaDir, forceNew = false) {
|
|
|
56
58
|
* In RSC mode, creates the full structure for server/client bundles.
|
|
57
59
|
*/
|
|
58
60
|
function createVistaDirectories(cwd, mode = 'legacy') {
|
|
59
|
-
const root = path_1.default.join(cwd,
|
|
61
|
+
const root = path_1.default.join(cwd, constants_1.BUILD_DIR);
|
|
60
62
|
const dirs = {
|
|
61
63
|
root,
|
|
62
64
|
cache: path_1.default.join(root, 'cache'),
|
|
@@ -93,7 +95,7 @@ function generateBuildManifest(vistaDir, buildId, pages = {}) {
|
|
|
93
95
|
polyfillFiles: [],
|
|
94
96
|
devFiles: [],
|
|
95
97
|
lowPriorityFiles: [],
|
|
96
|
-
rootMainFiles: [
|
|
98
|
+
rootMainFiles: [`${constants_1.STATIC_CHUNKS_PATH}webpack.js`, `${constants_1.STATIC_CHUNKS_PATH}main.js`],
|
|
97
99
|
pages,
|
|
98
100
|
};
|
|
99
101
|
const manifestPath = path_1.default.join(vistaDir, 'build-manifest.json');
|
|
@@ -144,10 +146,10 @@ function generateRequiredServerFilesManifest(cwd, vistaDir) {
|
|
|
144
146
|
appDir: cwd,
|
|
145
147
|
relativeAppDir: '.',
|
|
146
148
|
files: [
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
149
|
+
`${constants_1.BUILD_DIR}/BUILD_ID`,
|
|
150
|
+
`${constants_1.BUILD_DIR}/build-manifest.json`,
|
|
151
|
+
`${constants_1.BUILD_DIR}/routes-manifest.json`,
|
|
152
|
+
`${constants_1.BUILD_DIR}/app-path-routes-manifest.json`,
|
|
151
153
|
],
|
|
152
154
|
};
|
|
153
155
|
fs_1.default.writeFileSync(path_1.default.join(vistaDir, 'required-server-files.json'), JSON.stringify(manifest, null, 2));
|
|
@@ -163,6 +165,7 @@ function writeArtifactManifest(vistaDir, buildId) {
|
|
|
163
165
|
schemaVersion: 1,
|
|
164
166
|
buildId,
|
|
165
167
|
generatedAt: new Date().toISOString(),
|
|
168
|
+
__integrity: (0, integrity_1.generateBuildWatermark)(),
|
|
166
169
|
manifests: {
|
|
167
170
|
buildManifest: 'build-manifest.json',
|
|
168
171
|
routesManifest: 'routes-manifest.json',
|
|
@@ -19,6 +19,7 @@ exports.isClientComponentPath = isClientComponentPath;
|
|
|
19
19
|
const fs_1 = __importDefault(require("fs"));
|
|
20
20
|
const path_1 = __importDefault(require("path"));
|
|
21
21
|
const component_identity_1 = require("./component-identity");
|
|
22
|
+
const constants_1 = require("../../constants");
|
|
22
23
|
// Try to load Rust NAPI bindings
|
|
23
24
|
let rustNative = null;
|
|
24
25
|
try {
|
|
@@ -148,11 +149,11 @@ function generateClientManifestWithRoots(cwd, appDir, additionalRoots = []) {
|
|
|
148
149
|
pathToId[component.absolutePath] = component.id;
|
|
149
150
|
pathToId[normalizedAbsolutePath] = component.id;
|
|
150
151
|
// Map server path to client chunk for SSR
|
|
151
|
-
ssrModuleMapping[component.absolutePath] =
|
|
152
|
-
ssrModuleMapping[normalizedAbsolutePath] =
|
|
152
|
+
ssrModuleMapping[component.absolutePath] = `${constants_1.STATIC_CHUNKS_PATH}${component.chunkName}.js`;
|
|
153
|
+
ssrModuleMapping[normalizedAbsolutePath] = `${constants_1.STATIC_CHUNKS_PATH}${component.chunkName}.js`;
|
|
153
154
|
}
|
|
154
155
|
// Get or generate build ID
|
|
155
|
-
const buildIdPath = path_1.default.join(cwd,
|
|
156
|
+
const buildIdPath = path_1.default.join(cwd, constants_1.BUILD_DIR, 'BUILD_ID');
|
|
156
157
|
let buildId = 'dev';
|
|
157
158
|
try {
|
|
158
159
|
if (fs_1.default.existsSync(buildIdPath)) {
|
|
@@ -19,6 +19,7 @@ const fs_1 = __importDefault(require("fs"));
|
|
|
19
19
|
const manifest_1 = require("../manifest");
|
|
20
20
|
const client_manifest_1 = require("./client-manifest");
|
|
21
21
|
const server_manifest_1 = require("./server-manifest");
|
|
22
|
+
const constants_1 = require("../../constants");
|
|
22
23
|
// Find module path (handles monorepo hoisting)
|
|
23
24
|
const findModulePath = (moduleName, cwd) => {
|
|
24
25
|
const localPath = path_1.default.resolve(cwd, 'node_modules', moduleName);
|
|
@@ -174,8 +175,8 @@ function createServerWebpackConfig(options) {
|
|
|
174
175
|
plugins: [
|
|
175
176
|
new webpack_1.default.DefinePlugin({
|
|
176
177
|
'process.env.NODE_ENV': JSON.stringify(isDev ? 'development' : 'production'),
|
|
177
|
-
|
|
178
|
-
|
|
178
|
+
[constants_1.BUILD_ID_DEFINE]: JSON.stringify(buildId),
|
|
179
|
+
[constants_1.SERVER_DEFINE]: 'true',
|
|
179
180
|
}),
|
|
180
181
|
],
|
|
181
182
|
devtool: isDev ? 'source-map' : false,
|
|
@@ -217,7 +218,7 @@ function createClientWebpackConfig(options) {
|
|
|
217
218
|
path: vistaDirs.chunks,
|
|
218
219
|
filename: isDev ? '[name].js' : 'main-[contenthash:8].js',
|
|
219
220
|
chunkFilename: isDev ? '[name].js' : '[name]-[contenthash:8].js',
|
|
220
|
-
publicPath:
|
|
221
|
+
publicPath: constants_1.STATIC_CHUNKS_PATH,
|
|
221
222
|
clean: !isDev,
|
|
222
223
|
},
|
|
223
224
|
// Disable filesystem cache for client RSC build in dev mode.
|
|
@@ -383,11 +384,11 @@ function createClientWebpackConfig(options) {
|
|
|
383
384
|
},
|
|
384
385
|
new webpack_1.default.DefinePlugin({
|
|
385
386
|
'process.env.NODE_ENV': JSON.stringify(isDev ? 'development' : 'production'),
|
|
386
|
-
|
|
387
|
-
|
|
387
|
+
[constants_1.BUILD_ID_DEFINE]: JSON.stringify(buildId),
|
|
388
|
+
[constants_1.SERVER_DEFINE]: 'false',
|
|
388
389
|
}),
|
|
389
390
|
// No HotModuleReplacementPlugin or ReactRefreshWebpackPlugin
|
|
390
|
-
// RSC client builds use Vista's SSE live-reload (
|
|
391
|
+
// RSC client builds use Vista's SSE live-reload (${SSE_ENDPOINT}) instead
|
|
391
392
|
// Extract CSS Modules into a separate file
|
|
392
393
|
new MiniCssExtractPlugin({
|
|
393
394
|
filename: isDev ? 'modules.css' : 'modules-[contenthash:8].css',
|
|
@@ -20,6 +20,7 @@ exports.isServerComponentPath = isServerComponentPath;
|
|
|
20
20
|
const fs_1 = __importDefault(require("fs"));
|
|
21
21
|
const path_1 = __importDefault(require("path"));
|
|
22
22
|
const component_identity_1 = require("./component-identity");
|
|
23
|
+
const constants_1 = require("../../constants");
|
|
23
24
|
const RESERVED_INTERNAL_SEGMENTS = new Set(['[not-found]']);
|
|
24
25
|
function hasReservedInternalSegment(relativePath) {
|
|
25
26
|
return relativePath
|
|
@@ -323,7 +324,7 @@ function generateServerManifest(cwd, appDir) {
|
|
|
323
324
|
}
|
|
324
325
|
const routes = buildRoutes(components, appDir);
|
|
325
326
|
// Get or generate build ID
|
|
326
|
-
const buildIdPath = path_1.default.join(cwd,
|
|
327
|
+
const buildIdPath = path_1.default.join(cwd, constants_1.BUILD_DIR, 'BUILD_ID');
|
|
327
328
|
let buildId = 'dev';
|
|
328
329
|
try {
|
|
329
330
|
if (fs_1.default.existsSync(buildIdPath)) {
|
|
@@ -13,6 +13,7 @@ exports.VistaFlightPlugin = void 0;
|
|
|
13
13
|
const webpack_1 = __importDefault(require("webpack"));
|
|
14
14
|
const path_1 = __importDefault(require("path"));
|
|
15
15
|
const component_identity_1 = require("../../rsc/component-identity");
|
|
16
|
+
const constants_1 = require("../../../constants");
|
|
16
17
|
const PLUGIN_NAME = 'VistaFlightPlugin';
|
|
17
18
|
class VistaFlightPlugin {
|
|
18
19
|
appDir;
|
|
@@ -88,7 +89,7 @@ class VistaFlightPlugin {
|
|
|
88
89
|
const jsSource = `// Vista Client Reference Manifest
|
|
89
90
|
(function() {
|
|
90
91
|
if (typeof window !== 'undefined') {
|
|
91
|
-
window.
|
|
92
|
+
window.${constants_1.CLIENT_MANIFEST_FLAG} = ${JSON.stringify(manifest, null, 2)};
|
|
92
93
|
}
|
|
93
94
|
})();`;
|
|
94
95
|
compilation.emitAsset('vista-client-manifest.js', new webpack_1.default.sources.RawSource(jsSource));
|
package/dist/client/hydration.js
CHANGED
|
@@ -48,6 +48,7 @@ exports.hydrateClientComponents = hydrateClientComponents;
|
|
|
48
48
|
exports.initializeHydration = initializeHydration;
|
|
49
49
|
const React = __importStar(require("react"));
|
|
50
50
|
const client_1 = require("react-dom/client");
|
|
51
|
+
const constants_1 = require("../constants");
|
|
51
52
|
// Track hydrated components
|
|
52
53
|
const hydratedComponents = new Set();
|
|
53
54
|
const loadedChunks = new Map();
|
|
@@ -175,7 +176,7 @@ async function hydrateComponent(reference) {
|
|
|
175
176
|
async function hydrateClientComponents(options = {}) {
|
|
176
177
|
const { progressive = false, priority = 'normal', useIdleCallback = false } = options;
|
|
177
178
|
// Get references from window
|
|
178
|
-
const references = window.
|
|
179
|
+
const references = window[constants_1.CLIENT_REFS_FLAG] || [];
|
|
179
180
|
if (references.length === 0) {
|
|
180
181
|
console.log('[Vista] No client components to hydrate');
|
|
181
182
|
return;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vista Framework Constants
|
|
3
|
+
*
|
|
4
|
+
* All framework-specific naming lives here. When renaming the framework,
|
|
5
|
+
* only this file (and the Rust equivalent naming.rs) needs to change.
|
|
6
|
+
*/
|
|
7
|
+
/** Framework name used in logs, error messages, and branding */
|
|
8
|
+
export declare const FRAMEWORK_NAME = "vista";
|
|
9
|
+
/** Hidden build output directory name */
|
|
10
|
+
export declare const BUILD_DIR = ".vista";
|
|
11
|
+
/** Base URL prefix for all framework-served assets */
|
|
12
|
+
export declare const URL_PREFIX = "/_vista";
|
|
13
|
+
/** Static chunks URL path */
|
|
14
|
+
export declare const STATIC_CHUNKS_PATH = "/_vista/static/chunks/";
|
|
15
|
+
/** Image optimization endpoint URL */
|
|
16
|
+
export declare const IMAGE_ENDPOINT = "/_vista/image";
|
|
17
|
+
/** SSE live-reload endpoint */
|
|
18
|
+
export declare const SSE_ENDPOINT = "/__vista_reload";
|
|
19
|
+
/** Structure validation endpoint (dev only) */
|
|
20
|
+
export declare const STRUCTURE_ENDPOINT = "/__vista_structure";
|
|
21
|
+
/** Hydration mode flag: true = full document, false = content only */
|
|
22
|
+
export declare const HYDRATE_DOCUMENT_FLAG = "__VISTA_HYDRATE_DOCUMENT__";
|
|
23
|
+
/** Client config injection */
|
|
24
|
+
export declare const CONFIG_FLAG = "__VISTA_CONFIG__";
|
|
25
|
+
/** Client component references array */
|
|
26
|
+
export declare const CLIENT_REFS_FLAG = "__VISTA_CLIENT_REFERENCES__";
|
|
27
|
+
/** RSC payload data */
|
|
28
|
+
export declare const RSC_DATA_FLAG = "__VISTA_RSC_DATA__";
|
|
29
|
+
/** Build ID injection (webpack DefinePlugin) */
|
|
30
|
+
export declare const BUILD_ID_DEFINE = "__VISTA_BUILD_ID__";
|
|
31
|
+
/** Server-side flag (webpack DefinePlugin) */
|
|
32
|
+
export declare const SERVER_DEFINE = "__VISTA_SERVER__";
|
|
33
|
+
/** Client manifest injection */
|
|
34
|
+
export declare const CLIENT_MANIFEST_FLAG = "__VISTA_CLIENT_MANIFEST__";
|
|
35
|
+
/** Client components list */
|
|
36
|
+
export declare const CLIENT_COMPONENTS_FLAG = "__VISTA_CLIENT_COMPONENTS__";
|
|
37
|
+
/** Component wrapper marker to prevent double-wrapping */
|
|
38
|
+
export declare const WRAPPED_MARKER = "__vistaWrapped";
|
|
39
|
+
/** Theme setter function name */
|
|
40
|
+
export declare const THEME_SETTER = "__vistaSetTheme";
|
|
41
|
+
/** Client component mount ID prefix (used in Rust serializer too) */
|
|
42
|
+
export declare const MOUNT_ID_PREFIX = "__vista_cc_";
|
|
43
|
+
/** Local font family name prefix */
|
|
44
|
+
export declare const LOCAL_FONT_PREFIX = "__vista_local_";
|
|
45
|
+
/** URL prefixes to suppress in request logging */
|
|
46
|
+
export declare const LOG_IGNORE_PREFIXES: string[];
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Vista Framework Constants
|
|
4
|
+
*
|
|
5
|
+
* All framework-specific naming lives here. When renaming the framework,
|
|
6
|
+
* only this file (and the Rust equivalent naming.rs) needs to change.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.LOG_IGNORE_PREFIXES = exports.LOCAL_FONT_PREFIX = exports.MOUNT_ID_PREFIX = exports.THEME_SETTER = exports.WRAPPED_MARKER = exports.CLIENT_COMPONENTS_FLAG = exports.CLIENT_MANIFEST_FLAG = exports.SERVER_DEFINE = exports.BUILD_ID_DEFINE = exports.RSC_DATA_FLAG = exports.CLIENT_REFS_FLAG = exports.CONFIG_FLAG = exports.HYDRATE_DOCUMENT_FLAG = exports.STRUCTURE_ENDPOINT = exports.SSE_ENDPOINT = exports.IMAGE_ENDPOINT = exports.STATIC_CHUNKS_PATH = exports.URL_PREFIX = exports.BUILD_DIR = exports.FRAMEWORK_NAME = void 0;
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// Framework Identity
|
|
12
|
+
// ============================================================================
|
|
13
|
+
/** Framework name used in logs, error messages, and branding */
|
|
14
|
+
exports.FRAMEWORK_NAME = 'vista';
|
|
15
|
+
// ============================================================================
|
|
16
|
+
// Build Directory (.vista/ — equivalent to Next.js .next/)
|
|
17
|
+
// ============================================================================
|
|
18
|
+
/** Hidden build output directory name */
|
|
19
|
+
exports.BUILD_DIR = '.vista';
|
|
20
|
+
// ============================================================================
|
|
21
|
+
// URL Prefixes (/_vista/ — equivalent to Next.js /_next/)
|
|
22
|
+
// ============================================================================
|
|
23
|
+
/** Base URL prefix for all framework-served assets */
|
|
24
|
+
exports.URL_PREFIX = '/_vista';
|
|
25
|
+
/** Static chunks URL path */
|
|
26
|
+
exports.STATIC_CHUNKS_PATH = '/_vista/static/chunks/';
|
|
27
|
+
/** Image optimization endpoint URL */
|
|
28
|
+
exports.IMAGE_ENDPOINT = '/_vista/image';
|
|
29
|
+
/** SSE live-reload endpoint */
|
|
30
|
+
exports.SSE_ENDPOINT = '/__vista_reload';
|
|
31
|
+
/** Structure validation endpoint (dev only) */
|
|
32
|
+
exports.STRUCTURE_ENDPOINT = '/__vista_structure';
|
|
33
|
+
// ============================================================================
|
|
34
|
+
// Window Globals (__VISTA_* — equivalent to Next.js __NEXT_*)
|
|
35
|
+
// ============================================================================
|
|
36
|
+
/** Hydration mode flag: true = full document, false = content only */
|
|
37
|
+
exports.HYDRATE_DOCUMENT_FLAG = '__VISTA_HYDRATE_DOCUMENT__';
|
|
38
|
+
/** Client config injection */
|
|
39
|
+
exports.CONFIG_FLAG = '__VISTA_CONFIG__';
|
|
40
|
+
/** Client component references array */
|
|
41
|
+
exports.CLIENT_REFS_FLAG = '__VISTA_CLIENT_REFERENCES__';
|
|
42
|
+
/** RSC payload data */
|
|
43
|
+
exports.RSC_DATA_FLAG = '__VISTA_RSC_DATA__';
|
|
44
|
+
/** Build ID injection (webpack DefinePlugin) */
|
|
45
|
+
exports.BUILD_ID_DEFINE = '__VISTA_BUILD_ID__';
|
|
46
|
+
/** Server-side flag (webpack DefinePlugin) */
|
|
47
|
+
exports.SERVER_DEFINE = '__VISTA_SERVER__';
|
|
48
|
+
/** Client manifest injection */
|
|
49
|
+
exports.CLIENT_MANIFEST_FLAG = '__VISTA_CLIENT_MANIFEST__';
|
|
50
|
+
/** Client components list */
|
|
51
|
+
exports.CLIENT_COMPONENTS_FLAG = '__VISTA_CLIENT_COMPONENTS__';
|
|
52
|
+
// ============================================================================
|
|
53
|
+
// Internal Markers
|
|
54
|
+
// ============================================================================
|
|
55
|
+
/** Component wrapper marker to prevent double-wrapping */
|
|
56
|
+
exports.WRAPPED_MARKER = '__vistaWrapped';
|
|
57
|
+
/** Theme setter function name */
|
|
58
|
+
exports.THEME_SETTER = '__vistaSetTheme';
|
|
59
|
+
/** Client component mount ID prefix (used in Rust serializer too) */
|
|
60
|
+
exports.MOUNT_ID_PREFIX = '__vista_cc_';
|
|
61
|
+
/** Local font family name prefix */
|
|
62
|
+
exports.LOCAL_FONT_PREFIX = '__vista_local_';
|
|
63
|
+
// ============================================================================
|
|
64
|
+
// Logger Ignore Prefixes
|
|
65
|
+
// ============================================================================
|
|
66
|
+
/** URL prefixes to suppress in request logging */
|
|
67
|
+
exports.LOG_IGNORE_PREFIXES = ['/__vista', '/_vista/static/'];
|
package/dist/dev-error.js
CHANGED
|
@@ -15,6 +15,7 @@ const jsx_runtime_1 = require("react/jsx-runtime");
|
|
|
15
15
|
* Uses inline styles and vanilla JS for interactivity.
|
|
16
16
|
*/
|
|
17
17
|
const react_1 = __importDefault(require("react"));
|
|
18
|
+
const constants_1 = require("./constants");
|
|
18
19
|
// ============================================================================
|
|
19
20
|
// Inline CSS (no external dependencies)
|
|
20
21
|
// ============================================================================
|
|
@@ -297,7 +298,7 @@ function renderErrorHTML(errors) {
|
|
|
297
298
|
// Vista live-reload: auto-refresh error overlay when files change
|
|
298
299
|
(function() {
|
|
299
300
|
function connect() {
|
|
300
|
-
var es = new EventSource('
|
|
301
|
+
var es = new EventSource('${constants_1.SSE_ENDPOINT}');
|
|
301
302
|
es.onmessage = function(e) {
|
|
302
303
|
if (e.data && e.data !== 'connected') window.location.reload();
|
|
303
304
|
};
|
package/dist/font/local.js
CHANGED
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
30
30
|
exports.createLocalFont = createLocalFont;
|
|
31
31
|
const registry_1 = require("./registry");
|
|
32
|
+
const constants_1 = require("../constants");
|
|
32
33
|
// ─── Helpers ───────────────────────────────────────────────────────────────
|
|
33
34
|
let _counter = 0;
|
|
34
35
|
function hashName(name) {
|
|
@@ -85,7 +86,7 @@ function createLocalFont(options) {
|
|
|
85
86
|
const sources = typeof src === 'string' ? [{ path: src, weight: String(weight), style }] : src;
|
|
86
87
|
// Generate a unique family name
|
|
87
88
|
_counter++;
|
|
88
|
-
const familyName =
|
|
89
|
+
const familyName = `${constants_1.LOCAL_FONT_PREFIX}${hashName(sources.map((s) => s.path).join('|') + _counter)}`;
|
|
89
90
|
const className = `__font_${hashName(familyName)}`;
|
|
90
91
|
const variableName = variable || `--font-local-${hashName(familyName)}`;
|
|
91
92
|
const fontFamilyValue = `'${familyName}', ${fallback.join(', ')}`;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.VALID_LOADERS = exports.imageConfigDefault = void 0;
|
|
4
|
+
const constants_1 = require("../constants");
|
|
4
5
|
exports.imageConfigDefault = {
|
|
5
6
|
deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
|
|
6
7
|
imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
|
|
7
|
-
path:
|
|
8
|
+
path: constants_1.IMAGE_ENDPOINT,
|
|
8
9
|
loader: 'default',
|
|
9
10
|
loaderFile: '',
|
|
10
11
|
domains: [],
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.defaultLoader = void 0;
|
|
4
|
+
const constants_1 = require("../constants");
|
|
4
5
|
/**
|
|
5
6
|
* Default Vista image loader.
|
|
6
7
|
*
|
|
@@ -18,6 +19,6 @@ const defaultLoader = ({ src, width, quality }) => {
|
|
|
18
19
|
return src;
|
|
19
20
|
}
|
|
20
21
|
const q = quality || 75;
|
|
21
|
-
return
|
|
22
|
+
return `${constants_1.IMAGE_ENDPOINT}?url=${encodeURIComponent(src)}&w=${width}&q=${q}`;
|
|
22
23
|
};
|
|
23
24
|
exports.defaultLoader = defaultLoader;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vista Framework Integrity Verification
|
|
3
|
+
*
|
|
4
|
+
* Cross-checks TypeScript constants against the compiled Rust binary.
|
|
5
|
+
* If someone renames constants.ts without recompiling the Rust native
|
|
6
|
+
* binary, the tokens won't match and the framework refuses to start.
|
|
7
|
+
*
|
|
8
|
+
* This is the core of Vista's rename-prevention system.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Compute integrity token from JS constants.
|
|
12
|
+
* The order and values MUST match naming.rs::compute_integrity_token().
|
|
13
|
+
*/
|
|
14
|
+
export declare function computeJSIntegrityToken(): string;
|
|
15
|
+
/**
|
|
16
|
+
* Verify framework integrity at startup.
|
|
17
|
+
* Loads the compiled Rust binary and cross-checks naming constants.
|
|
18
|
+
*
|
|
19
|
+
* @param nativeModule - The loaded vista-napi module
|
|
20
|
+
* @returns true if integrity check passes
|
|
21
|
+
* @throws Error if integrity check fails (framework has been tampered with)
|
|
22
|
+
*/
|
|
23
|
+
export declare function verifyFrameworkIntegrity(nativeModule?: any): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Generate integrity watermark for build output.
|
|
26
|
+
* Embedded in the build manifest so built artifacts are also verified.
|
|
27
|
+
*/
|
|
28
|
+
export declare function generateBuildWatermark(): string;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Vista Framework Integrity Verification
|
|
4
|
+
*
|
|
5
|
+
* Cross-checks TypeScript constants against the compiled Rust binary.
|
|
6
|
+
* If someone renames constants.ts without recompiling the Rust native
|
|
7
|
+
* binary, the tokens won't match and the framework refuses to start.
|
|
8
|
+
*
|
|
9
|
+
* This is the core of Vista's rename-prevention system.
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.computeJSIntegrityToken = computeJSIntegrityToken;
|
|
13
|
+
exports.verifyFrameworkIntegrity = verifyFrameworkIntegrity;
|
|
14
|
+
exports.generateBuildWatermark = generateBuildWatermark;
|
|
15
|
+
const constants_1 = require("./constants");
|
|
16
|
+
// ============================================================================
|
|
17
|
+
// JS-side integrity token computation
|
|
18
|
+
// Must match the Rust-side compute_integrity_token() in naming.rs exactly.
|
|
19
|
+
// ============================================================================
|
|
20
|
+
/**
|
|
21
|
+
* Simple deterministic hash matching Rust's DefaultHasher behavior.
|
|
22
|
+
* We use the same algorithm: hash each string in the same order.
|
|
23
|
+
*
|
|
24
|
+
* NOTE: This intentionally uses a custom hasher to match Rust's DefaultHasher.
|
|
25
|
+
* Do NOT replace with crypto.createHash — it must produce the same output
|
|
26
|
+
* as the compiled binary.
|
|
27
|
+
*/
|
|
28
|
+
function hashString(str, seed) {
|
|
29
|
+
// Rust DefaultHasher (SipHash-2-4) approximation via string bytes
|
|
30
|
+
let h = seed;
|
|
31
|
+
for (let i = 0; i < str.length; i++) {
|
|
32
|
+
h = h ^ BigInt(str.charCodeAt(i));
|
|
33
|
+
h = (h * 0x100000001b3n) & 0xffffffffffffffffn;
|
|
34
|
+
}
|
|
35
|
+
// Add length (Rust hashes the string length too)
|
|
36
|
+
h = h ^ BigInt(str.length);
|
|
37
|
+
h = (h * 0x100000001b3n) & 0xffffffffffffffffn;
|
|
38
|
+
return h;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Compute integrity token from JS constants.
|
|
42
|
+
* The order and values MUST match naming.rs::compute_integrity_token().
|
|
43
|
+
*/
|
|
44
|
+
function computeJSIntegrityToken() {
|
|
45
|
+
const values = [
|
|
46
|
+
constants_1.FRAMEWORK_NAME,
|
|
47
|
+
constants_1.URL_PREFIX,
|
|
48
|
+
constants_1.STATIC_CHUNKS_PATH,
|
|
49
|
+
constants_1.MOUNT_ID_PREFIX,
|
|
50
|
+
constants_1.RSC_DATA_FLAG, // maps to RSC_DATA_GLOBAL in Rust
|
|
51
|
+
constants_1.CLIENT_REFS_FLAG, // maps to CLIENT_REFS_GLOBAL in Rust
|
|
52
|
+
constants_1.BUILD_ID_DEFINE, // maps to BUILD_ID_GLOBAL in Rust
|
|
53
|
+
constants_1.BUILD_DIR,
|
|
54
|
+
constants_1.SSE_ENDPOINT,
|
|
55
|
+
constants_1.IMAGE_ENDPOINT,
|
|
56
|
+
];
|
|
57
|
+
let hash = 0xcbf29ce484222325n; // FNV offset basis
|
|
58
|
+
for (const val of values) {
|
|
59
|
+
hash = hashString(val, hash);
|
|
60
|
+
}
|
|
61
|
+
return hash.toString(16);
|
|
62
|
+
}
|
|
63
|
+
// ============================================================================
|
|
64
|
+
// Runtime Verification
|
|
65
|
+
// ============================================================================
|
|
66
|
+
/**
|
|
67
|
+
* Verify framework integrity at startup.
|
|
68
|
+
* Loads the compiled Rust binary and cross-checks naming constants.
|
|
69
|
+
*
|
|
70
|
+
* @param nativeModule - The loaded vista-napi module
|
|
71
|
+
* @returns true if integrity check passes
|
|
72
|
+
* @throws Error if integrity check fails (framework has been tampered with)
|
|
73
|
+
*/
|
|
74
|
+
function verifyFrameworkIntegrity(nativeModule) {
|
|
75
|
+
// If native module isn't available, skip (graceful degradation)
|
|
76
|
+
if (!nativeModule?.getFrameworkIdentity) {
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
const identity = nativeModule.getFrameworkIdentity();
|
|
80
|
+
// Check 1: Framework name must match
|
|
81
|
+
if (identity.name !== constants_1.FRAMEWORK_NAME) {
|
|
82
|
+
throw new Error(`[${constants_1.FRAMEWORK_NAME}] Framework integrity check failed: ` +
|
|
83
|
+
`binary name "${identity.name}" !== constants name "${constants_1.FRAMEWORK_NAME}". ` +
|
|
84
|
+
`The native binary was compiled for a different framework version. ` +
|
|
85
|
+
`Please recompile with: cargo build --release`);
|
|
86
|
+
}
|
|
87
|
+
// Check 2: Individual constants must match
|
|
88
|
+
const mismatches = [];
|
|
89
|
+
if (identity.urlPrefix !== constants_1.URL_PREFIX)
|
|
90
|
+
mismatches.push(`URL_PREFIX: rust="${identity.urlPrefix}" ts="${constants_1.URL_PREFIX}"`);
|
|
91
|
+
if (identity.buildDir !== constants_1.BUILD_DIR)
|
|
92
|
+
mismatches.push(`BUILD_DIR: rust="${identity.buildDir}" ts="${constants_1.BUILD_DIR}"`);
|
|
93
|
+
if (identity.sseEndpoint !== constants_1.SSE_ENDPOINT)
|
|
94
|
+
mismatches.push(`SSE_ENDPOINT: rust="${identity.sseEndpoint}" ts="${constants_1.SSE_ENDPOINT}"`);
|
|
95
|
+
if (identity.imageEndpoint !== constants_1.IMAGE_ENDPOINT)
|
|
96
|
+
mismatches.push(`IMAGE_ENDPOINT: rust="${identity.imageEndpoint}" ts="${constants_1.IMAGE_ENDPOINT}"`);
|
|
97
|
+
if (identity.mountIdPrefix !== constants_1.MOUNT_ID_PREFIX)
|
|
98
|
+
mismatches.push(`MOUNT_ID_PREFIX: rust="${identity.mountIdPrefix}" ts="${constants_1.MOUNT_ID_PREFIX}"`);
|
|
99
|
+
if (identity.staticChunksPath !== constants_1.STATIC_CHUNKS_PATH)
|
|
100
|
+
mismatches.push(`STATIC_CHUNKS_PATH: rust="${identity.staticChunksPath}" ts="${constants_1.STATIC_CHUNKS_PATH}"`);
|
|
101
|
+
if (mismatches.length > 0) {
|
|
102
|
+
throw new Error(`[${constants_1.FRAMEWORK_NAME}] Framework integrity check failed — ` +
|
|
103
|
+
`TypeScript constants don't match compiled Rust binary:\n` +
|
|
104
|
+
mismatches.map((m) => ` • ${m}`).join('\n') +
|
|
105
|
+
'\n' +
|
|
106
|
+
`Please recompile the native binary: cargo build --release`);
|
|
107
|
+
}
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Generate integrity watermark for build output.
|
|
112
|
+
* Embedded in the build manifest so built artifacts are also verified.
|
|
113
|
+
*/
|
|
114
|
+
function generateBuildWatermark() {
|
|
115
|
+
return `${constants_1.FRAMEWORK_NAME}:${computeJSIntegrityToken()}`;
|
|
116
|
+
}
|
|
@@ -7,6 +7,7 @@ exports.validateVistaArtifacts = validateVistaArtifacts;
|
|
|
7
7
|
exports.assertVistaArtifacts = assertVistaArtifacts;
|
|
8
8
|
const fs_1 = __importDefault(require("fs"));
|
|
9
9
|
const path_1 = __importDefault(require("path"));
|
|
10
|
+
const constants_1 = require("../constants");
|
|
10
11
|
const BASE_REQUIRED_FILES = [
|
|
11
12
|
'BUILD_ID',
|
|
12
13
|
'artifact-manifest.json',
|
|
@@ -18,14 +19,8 @@ const BASE_REQUIRED_FILES = [
|
|
|
18
19
|
'react-client-manifest.json',
|
|
19
20
|
'react-server-manifest.json',
|
|
20
21
|
];
|
|
21
|
-
const RSC_REQUIRED_FILES = [
|
|
22
|
-
|
|
23
|
-
path_1.default.join('server', 'server-manifest.json'),
|
|
24
|
-
];
|
|
25
|
-
const LEGACY_REQUIRED_FILES = [
|
|
26
|
-
...BASE_REQUIRED_FILES,
|
|
27
|
-
'client.js',
|
|
28
|
-
];
|
|
22
|
+
const RSC_REQUIRED_FILES = [...BASE_REQUIRED_FILES, path_1.default.join('server', 'server-manifest.json')];
|
|
23
|
+
const LEGACY_REQUIRED_FILES = [...BASE_REQUIRED_FILES, 'client.js'];
|
|
29
24
|
function readJsonSafe(absolutePath) {
|
|
30
25
|
try {
|
|
31
26
|
return JSON.parse(fs_1.default.readFileSync(absolutePath, 'utf-8'));
|
|
@@ -35,11 +30,11 @@ function readJsonSafe(absolutePath) {
|
|
|
35
30
|
}
|
|
36
31
|
}
|
|
37
32
|
function validateVistaArtifacts(cwd, mode) {
|
|
38
|
-
const vistaDir = path_1.default.join(cwd,
|
|
33
|
+
const vistaDir = path_1.default.join(cwd, constants_1.BUILD_DIR);
|
|
39
34
|
const missing = [];
|
|
40
35
|
const requiredFiles = mode === 'rsc' ? RSC_REQUIRED_FILES : LEGACY_REQUIRED_FILES;
|
|
41
36
|
if (!fs_1.default.existsSync(vistaDir)) {
|
|
42
|
-
return [
|
|
37
|
+
return [`${constants_1.BUILD_DIR} directory is missing`];
|
|
43
38
|
}
|
|
44
39
|
for (const relativePath of requiredFiles) {
|
|
45
40
|
const absolutePath = path_1.default.join(vistaDir, relativePath);
|
|
@@ -59,5 +54,5 @@ function assertVistaArtifacts(cwd, mode) {
|
|
|
59
54
|
if (missing.length === 0)
|
|
60
55
|
return;
|
|
61
56
|
const missingList = missing.map((entry) => `- ${entry}`).join('\n');
|
|
62
|
-
throw new Error(`[vista:server] Missing or invalid .
|
|
57
|
+
throw new Error(`[vista:server] Missing or invalid ${constants_1.BUILD_DIR} artifacts for ${mode} mode.\n${missingList}\nRun "vista build${mode === 'rsc' ? ' --rsc' : ''}" first.`);
|
|
63
58
|
}
|
package/dist/server/engine.js
CHANGED
|
@@ -14,6 +14,7 @@ const react_1 = __importDefault(require("react"));
|
|
|
14
14
|
const stream_1 = require("stream");
|
|
15
15
|
const webpack_dev_middleware_1 = __importDefault(require("webpack-dev-middleware"));
|
|
16
16
|
const webpack_hot_middleware_1 = __importDefault(require("webpack-hot-middleware"));
|
|
17
|
+
const constants_1 = require("../constants");
|
|
17
18
|
const config_1 = require("../config");
|
|
18
19
|
const dev_error_1 = require("../dev-error");
|
|
19
20
|
const artifact_validator_1 = require("./artifact-validator");
|
|
@@ -164,10 +165,10 @@ function enableClientComponentWrapping(appDir, cwd) {
|
|
|
164
165
|
const componentId = getClientComponentId(resolved);
|
|
165
166
|
if (componentId && result?.default) {
|
|
166
167
|
// Wrap the default export if not already wrapped
|
|
167
|
-
if (!result.default.
|
|
168
|
+
if (!result.default[constants_1.WRAPPED_MARKER]) {
|
|
168
169
|
const OriginalComponent = result.default;
|
|
169
170
|
const WrappedComponent = (0, client_boundary_1.wrapClientComponent)(OriginalComponent, componentId);
|
|
170
|
-
WrappedComponent.
|
|
171
|
+
WrappedComponent[constants_1.WRAPPED_MARKER] = true;
|
|
171
172
|
result.default = WrappedComponent;
|
|
172
173
|
}
|
|
173
174
|
}
|
|
@@ -222,7 +223,7 @@ function startServer(port = 3003, compiler) {
|
|
|
222
223
|
// Enable RSC: Auto-wrap client components with hydration markers
|
|
223
224
|
enableClientComponentWrapping(appDir, cwd);
|
|
224
225
|
// Load pre-rendered static pages from disk into in-memory cache
|
|
225
|
-
const vistaDirRoot = path_1.default.join(cwd,
|
|
226
|
+
const vistaDirRoot = path_1.default.join(cwd, constants_1.BUILD_DIR);
|
|
226
227
|
const loadedStaticPages = (0, static_cache_1.loadStaticPagesFromDisk)(vistaDirRoot);
|
|
227
228
|
if (loadedStaticPages > 0) {
|
|
228
229
|
(0, logger_1.logInfo)(`Loaded ${loadedStaticPages} pre-rendered page(s) from cache`);
|
|
@@ -248,7 +249,7 @@ function startServer(port = 3003, compiler) {
|
|
|
248
249
|
// Watches server component files and triggers page reload
|
|
249
250
|
const sseClients = new Set();
|
|
250
251
|
// SSE endpoint for server reload
|
|
251
|
-
app.get(
|
|
252
|
+
app.get(constants_1.SSE_ENDPOINT, (req, res) => {
|
|
252
253
|
res.setHeader('Content-Type', 'text/event-stream');
|
|
253
254
|
res.setHeader('Cache-Control', 'no-cache');
|
|
254
255
|
res.setHeader('Connection', 'keep-alive');
|
|
@@ -375,12 +376,12 @@ function startServer(port = 3003, compiler) {
|
|
|
375
376
|
app.use(express_1.default.static(path_1.default.join(cwd, 'public')));
|
|
376
377
|
// Image optimization endpoint
|
|
377
378
|
const imageHandler = (0, image_optimizer_1.createImageHandler)(cwd, isDev);
|
|
378
|
-
app.get(
|
|
379
|
+
app.get(constants_1.IMAGE_ENDPOINT, imageHandler);
|
|
379
380
|
// Serve .vista build artifacts with proper routing
|
|
380
381
|
// /_vista/static/* -> .vista/static/*
|
|
381
|
-
app.use(
|
|
382
|
+
app.use(`${constants_1.URL_PREFIX}/static`, express_1.default.static(path_1.default.join(cwd, constants_1.BUILD_DIR, 'static')));
|
|
382
383
|
// Legacy: Serve .vista root for backward compatibility (client.css, etc.)
|
|
383
|
-
app.use(express_1.default.static(path_1.default.join(cwd,
|
|
384
|
+
app.use(express_1.default.static(path_1.default.join(cwd, constants_1.BUILD_DIR)));
|
|
384
385
|
app.use(async (req, res, next) => {
|
|
385
386
|
if (req.path.startsWith('/styles.css') || req.path.startsWith('/__webpack_hmr')) {
|
|
386
387
|
return next();
|
|
@@ -672,7 +673,7 @@ layouts) {
|
|
|
672
673
|
d.classList.add('dark');
|
|
673
674
|
d.classList.remove('light');
|
|
674
675
|
d.style.colorScheme = 'dark';
|
|
675
|
-
window.
|
|
676
|
+
window.${constants_1.THEME_SETTER} = function(newTheme) {
|
|
676
677
|
d.classList.remove('light', 'dark');
|
|
677
678
|
d.classList.add(newTheme);
|
|
678
679
|
d.style.colorScheme = newTheme;
|
package/dist/server/logger.js
CHANGED
|
@@ -21,6 +21,7 @@ exports.logEvent = logEvent;
|
|
|
21
21
|
exports.requestLogger = requestLogger;
|
|
22
22
|
exports.markStartTime = markStartTime;
|
|
23
23
|
const os_1 = __importDefault(require("os"));
|
|
24
|
+
const constants_1 = require("../constants");
|
|
24
25
|
// ─── ANSI Colors ───────────────────────────────────────────────────────────
|
|
25
26
|
const bold = (s) => `\x1b[1m${s}\x1b[22m`;
|
|
26
27
|
const dim = (s) => `\x1b[2m${s}\x1b[22m`;
|
|
@@ -199,8 +200,7 @@ function getVistaVersion() {
|
|
|
199
200
|
}
|
|
200
201
|
const INTERNAL_PREFIXES = [
|
|
201
202
|
'/__webpack',
|
|
202
|
-
|
|
203
|
-
'/_vista/static/',
|
|
203
|
+
...constants_1.LOG_IGNORE_PREFIXES,
|
|
204
204
|
'/favicon.ico',
|
|
205
205
|
'/_next',
|
|
206
206
|
'/hot-update',
|
|
@@ -30,6 +30,7 @@ const logger_1 = require("./logger");
|
|
|
30
30
|
const not_found_page_1 = require("./not-found-page");
|
|
31
31
|
const static_cache_1 = require("./static-cache");
|
|
32
32
|
const static_generator_1 = require("./static-generator");
|
|
33
|
+
const constants_1 = require("../constants");
|
|
33
34
|
const CjsModule = require('module');
|
|
34
35
|
// ---------------------------------------------------------------------------
|
|
35
36
|
// SSR Webpack Shim
|
|
@@ -85,12 +86,12 @@ function getCSSLinks(projectRoot) {
|
|
|
85
86
|
const root = projectRoot || process.cwd();
|
|
86
87
|
const links = ['<link rel="stylesheet" href="/styles.css" />'];
|
|
87
88
|
// Check for extracted CSS modules (from MiniCssExtractPlugin)
|
|
88
|
-
const chunksDir = path_1.default.join(root,
|
|
89
|
+
const chunksDir = path_1.default.join(root, constants_1.BUILD_DIR, 'static', 'chunks');
|
|
89
90
|
try {
|
|
90
91
|
if (fs_1.default.existsSync(chunksDir)) {
|
|
91
92
|
const files = fs_1.default.readdirSync(chunksDir).filter((f) => f.endsWith('.css'));
|
|
92
93
|
for (const f of files) {
|
|
93
|
-
links.push(`<link rel="stylesheet" href="
|
|
94
|
+
links.push(`<link rel="stylesheet" href="${constants_1.STATIC_CHUNKS_PATH}${f}" />`);
|
|
94
95
|
}
|
|
95
96
|
}
|
|
96
97
|
}
|
|
@@ -151,6 +152,15 @@ function setupTypeScriptRuntime(cwd) {
|
|
|
151
152
|
esModuleInterop: true,
|
|
152
153
|
},
|
|
153
154
|
});
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
catch {
|
|
158
|
+
// fallback
|
|
159
|
+
}
|
|
160
|
+
try {
|
|
161
|
+
require.resolve('tsx', { paths: [cwd] });
|
|
162
|
+
require('tsx/cjs');
|
|
163
|
+
return;
|
|
154
164
|
}
|
|
155
165
|
catch (e) {
|
|
156
166
|
console.log('Failed to setup TypeScript runtime:', e);
|
|
@@ -218,7 +228,7 @@ function withTimeout(url, options = {}, timeoutMs = 3000) {
|
|
|
218
228
|
});
|
|
219
229
|
}
|
|
220
230
|
function cleanHotUpdateFiles(cwd) {
|
|
221
|
-
const chunksDir = path_1.default.join(cwd,
|
|
231
|
+
const chunksDir = path_1.default.join(cwd, constants_1.BUILD_DIR, 'static', 'chunks');
|
|
222
232
|
if (!fs_1.default.existsSync(chunksDir))
|
|
223
233
|
return;
|
|
224
234
|
for (const f of fs_1.default.readdirSync(chunksDir)) {
|
|
@@ -231,7 +241,7 @@ function cleanHotUpdateFiles(cwd) {
|
|
|
231
241
|
}
|
|
232
242
|
}
|
|
233
243
|
function findChunkFiles(cwd) {
|
|
234
|
-
const chunksDir = path_1.default.join(cwd,
|
|
244
|
+
const chunksDir = path_1.default.join(cwd, constants_1.BUILD_DIR, 'static', 'chunks');
|
|
235
245
|
if (!fs_1.default.existsSync(chunksDir))
|
|
236
246
|
return [];
|
|
237
247
|
const files = fs_1.default
|
|
@@ -404,14 +414,14 @@ function injectBeforeClosingTag(html, tagName, injection) {
|
|
|
404
414
|
}
|
|
405
415
|
function createHtmlDocument(appHtml, metadataHtml, chunkFiles, rootMode = 'legacy') {
|
|
406
416
|
const scripts = chunkFiles
|
|
407
|
-
.map((chunk) => `<script defer src="
|
|
417
|
+
.map((chunk) => `<script defer src="${constants_1.STATIC_CHUNKS_PATH}${chunk}"></script>`)
|
|
408
418
|
.join('\n ');
|
|
409
419
|
if (rootMode === 'document' ||
|
|
410
420
|
/^\s*<!doctype html>\s*<html/i.test(appHtml) ||
|
|
411
421
|
/^\s*<html/i.test(appHtml)) {
|
|
412
422
|
const fontHtml = (0, registry_1.getAllFontHTML)();
|
|
413
423
|
const headInjection = `\n <meta charset="utf-8" />\n <meta name="viewport" content="width=device-width, initial-scale=1" />\n ${metadataHtml}\n ${fontHtml}\n ${getCSSLinks()}`;
|
|
414
|
-
const bodyInjection = `\n <script>window.
|
|
424
|
+
const bodyInjection = `\n <script>window.${constants_1.HYDRATE_DOCUMENT_FLAG} = true;</script>\n ${scripts}`;
|
|
415
425
|
let html = appHtml;
|
|
416
426
|
if (!/^\s*<!doctype html>/i.test(html)) {
|
|
417
427
|
html = `<!DOCTYPE html>\n${html}`;
|
|
@@ -431,7 +441,7 @@ function createHtmlDocument(appHtml, metadataHtml, chunkFiles, rootMode = 'legac
|
|
|
431
441
|
${getCSSLinks()}
|
|
432
442
|
</head>
|
|
433
443
|
<body>
|
|
434
|
-
<script>window.
|
|
444
|
+
<script>window.${constants_1.HYDRATE_DOCUMENT_FLAG} = false;</script>
|
|
435
445
|
<div id="root">${appHtml}</div>
|
|
436
446
|
${scripts}
|
|
437
447
|
</body>
|
|
@@ -545,7 +555,7 @@ async function renderFlightToHTMLStream(upstreamOrigin, pathname, search, metada
|
|
|
545
555
|
const element = react_1.default.createElement(FlightRoot);
|
|
546
556
|
// 5. Build script tags for client chunks
|
|
547
557
|
const scripts = chunkFiles
|
|
548
|
-
.map((chunk) => `<script defer src="
|
|
558
|
+
.map((chunk) => `<script defer src="${constants_1.STATIC_CHUNKS_PATH}${chunk}"></script>`)
|
|
549
559
|
.join('\n ');
|
|
550
560
|
// 6. Render to a pipeable HTML stream
|
|
551
561
|
return new Promise((resolve, reject) => {
|
|
@@ -574,7 +584,7 @@ async function renderFlightToHTMLStream(upstreamOrigin, pathname, search, metada
|
|
|
574
584
|
// Inject scripts before </body>
|
|
575
585
|
if (html.includes('</body>')) {
|
|
576
586
|
const bodyInjection = `
|
|
577
|
-
<script>window.
|
|
587
|
+
<script>window.${constants_1.HYDRATE_DOCUMENT_FLAG} = ${rootMode === 'document'};</script>
|
|
578
588
|
${scripts}`;
|
|
579
589
|
html = html.replace('</body>', `${bodyInjection}\n</body>`);
|
|
580
590
|
}
|
|
@@ -606,14 +616,14 @@ async function renderFlightToHTMLStream(upstreamOrigin, pathname, search, metada
|
|
|
606
616
|
*/
|
|
607
617
|
function wrapInDocumentShell(bodyContent, metadataHtml, chunkFiles, rootMode) {
|
|
608
618
|
const scripts = chunkFiles
|
|
609
|
-
.map((chunk) => `<script defer src="
|
|
619
|
+
.map((chunk) => `<script defer src="${constants_1.STATIC_CHUNKS_PATH}${chunk}"></script>`)
|
|
610
620
|
.join('\n ');
|
|
611
621
|
if (rootMode === 'document' ||
|
|
612
622
|
/^\s*<!doctype html>\s*<html/i.test(bodyContent) ||
|
|
613
623
|
/^\s*<html/i.test(bodyContent)) {
|
|
614
624
|
const fontHtml = (0, registry_1.getAllFontHTML)();
|
|
615
625
|
const headInjection = `\n <meta charset="utf-8" />\n <meta name="viewport" content="width=device-width, initial-scale=1" />\n ${metadataHtml}\n ${fontHtml}\n ${getCSSLinks()}`;
|
|
616
|
-
const bodyInjection = `\n <script>window.
|
|
626
|
+
const bodyInjection = `\n <script>window.${constants_1.HYDRATE_DOCUMENT_FLAG} = true;</script>\n ${scripts}`;
|
|
617
627
|
let html = bodyContent;
|
|
618
628
|
if (!/^\s*<!doctype html>/i.test(html)) {
|
|
619
629
|
html = `<!DOCTYPE html>\n${html}`;
|
|
@@ -633,7 +643,7 @@ function wrapInDocumentShell(bodyContent, metadataHtml, chunkFiles, rootMode) {
|
|
|
633
643
|
${getCSSLinks()}
|
|
634
644
|
</head>
|
|
635
645
|
<body>
|
|
636
|
-
<script>window.
|
|
646
|
+
<script>window.${constants_1.HYDRATE_DOCUMENT_FLAG} = false;</script>
|
|
637
647
|
<div id="root">${bodyContent}</div>
|
|
638
648
|
${scripts}
|
|
639
649
|
</body>
|
|
@@ -654,7 +664,7 @@ function startRSCServer(options = {}) {
|
|
|
654
664
|
installSingleReactResolution(cwd);
|
|
655
665
|
setupTypeScriptRuntime(cwd);
|
|
656
666
|
installSSRWebpackShim();
|
|
657
|
-
const serverManifestPath = path_1.default.join(cwd,
|
|
667
|
+
const serverManifestPath = path_1.default.join(cwd, constants_1.BUILD_DIR, 'server', 'server-manifest.json');
|
|
658
668
|
if (!fs_1.default.existsSync(serverManifestPath)) {
|
|
659
669
|
console.error(`[vista:rsc] Missing server manifest at ${serverManifestPath}. Run "vista build --rsc" first.`);
|
|
660
670
|
process.exit(1);
|
|
@@ -678,8 +688,8 @@ function startRSCServer(options = {}) {
|
|
|
678
688
|
catch (err) {
|
|
679
689
|
// Flight SSR not available — fallback to renderToString
|
|
680
690
|
}
|
|
681
|
-
const ssrManifestPath = path_1.default.join(cwd,
|
|
682
|
-
const ssrManifestLegacyPath = path_1.default.join(cwd,
|
|
691
|
+
const ssrManifestPath = path_1.default.join(cwd, constants_1.BUILD_DIR, 'react-server-manifest.json');
|
|
692
|
+
const ssrManifestLegacyPath = path_1.default.join(cwd, constants_1.BUILD_DIR, 'react-ssr-manifest.json');
|
|
683
693
|
const resolvedSSRManifestPath = fs_1.default.existsSync(ssrManifestPath)
|
|
684
694
|
? ssrManifestPath
|
|
685
695
|
: fs_1.default.existsSync(ssrManifestLegacyPath)
|
|
@@ -731,7 +741,7 @@ function startRSCServer(options = {}) {
|
|
|
731
741
|
// ========================================================================
|
|
732
742
|
// Load pre-rendered static pages from disk into in-memory cache
|
|
733
743
|
// ========================================================================
|
|
734
|
-
const vistaDirRoot = path_1.default.join(cwd,
|
|
744
|
+
const vistaDirRoot = path_1.default.join(cwd, constants_1.BUILD_DIR);
|
|
735
745
|
const loadedStaticPages = (0, static_cache_1.loadStaticPagesFromDisk)(vistaDirRoot);
|
|
736
746
|
if (loadedStaticPages > 0) {
|
|
737
747
|
(0, logger_1.logInfo)(`Loaded ${loadedStaticPages} pre-rendered page(s) from cache`);
|
|
@@ -817,7 +827,7 @@ function startRSCServer(options = {}) {
|
|
|
817
827
|
// ========================================================================
|
|
818
828
|
const sseReloadClients = new Set();
|
|
819
829
|
if (isDev) {
|
|
820
|
-
app.get(
|
|
830
|
+
app.get(constants_1.SSE_ENDPOINT, (req, res) => {
|
|
821
831
|
res.setHeader('Content-Type', 'text/event-stream');
|
|
822
832
|
res.setHeader('Cache-Control', 'no-cache');
|
|
823
833
|
res.setHeader('Connection', 'keep-alive');
|
|
@@ -849,7 +859,7 @@ function startRSCServer(options = {}) {
|
|
|
849
859
|
}
|
|
850
860
|
if (isDev && options.compiler) {
|
|
851
861
|
app.use((0, webpack_dev_middleware_1.default)(options.compiler, {
|
|
852
|
-
publicPath:
|
|
862
|
+
publicPath: constants_1.STATIC_CHUNKS_PATH,
|
|
853
863
|
stats: 'none',
|
|
854
864
|
writeToDisk: true,
|
|
855
865
|
}));
|
|
@@ -896,7 +906,7 @@ function startRSCServer(options = {}) {
|
|
|
896
906
|
// Structure Watcher SSE (RSC dev mode)
|
|
897
907
|
// ========================================================================
|
|
898
908
|
const sseStructureClients = new Set();
|
|
899
|
-
app.get(
|
|
909
|
+
app.get(constants_1.STRUCTURE_ENDPOINT, (req, res) => {
|
|
900
910
|
res.setHeader('Content-Type', 'text/event-stream');
|
|
901
911
|
res.setHeader('Cache-Control', 'no-cache');
|
|
902
912
|
res.setHeader('Connection', 'keep-alive');
|
|
@@ -949,7 +959,7 @@ function startRSCServer(options = {}) {
|
|
|
949
959
|
});
|
|
950
960
|
}
|
|
951
961
|
app.get('/styles.css', (req, res) => {
|
|
952
|
-
const cssPath = path_1.default.join(cwd,
|
|
962
|
+
const cssPath = path_1.default.join(cwd, constants_1.BUILD_DIR, 'client.css');
|
|
953
963
|
if (fs_1.default.existsSync(cssPath)) {
|
|
954
964
|
res.setHeader('Content-Type', 'text/css');
|
|
955
965
|
res.sendFile(cssPath);
|
|
@@ -959,11 +969,11 @@ function startRSCServer(options = {}) {
|
|
|
959
969
|
});
|
|
960
970
|
// Image optimization endpoint
|
|
961
971
|
const imageHandler = (0, image_optimizer_1.createImageHandler)(cwd, isDev);
|
|
962
|
-
app.get(
|
|
972
|
+
app.get(constants_1.IMAGE_ENDPOINT, imageHandler);
|
|
963
973
|
app.use(express_1.default.static(path_1.default.join(cwd, 'public')));
|
|
964
|
-
app.use(
|
|
965
|
-
app.use(
|
|
966
|
-
app.use(express_1.default.static(path_1.default.join(cwd,
|
|
974
|
+
app.use(`${constants_1.URL_PREFIX}/static`, express_1.default.static(path_1.default.join(cwd, constants_1.BUILD_DIR, 'static')));
|
|
975
|
+
app.use(constants_1.URL_PREFIX, express_1.default.static(path_1.default.join(cwd, constants_1.BUILD_DIR)));
|
|
976
|
+
app.use(express_1.default.static(path_1.default.join(cwd, constants_1.BUILD_DIR)));
|
|
967
977
|
const proxyRSCRequest = async (req, res) => {
|
|
968
978
|
try {
|
|
969
979
|
const fetchOptions = {
|
|
@@ -9,6 +9,7 @@ const path_1 = __importDefault(require("path"));
|
|
|
9
9
|
const react_1 = __importDefault(require("react"));
|
|
10
10
|
const url_1 = require("url");
|
|
11
11
|
const root_resolver_1 = require("./root-resolver");
|
|
12
|
+
const constants_1 = require("../constants");
|
|
12
13
|
// NOTE: RouteErrorBoundary and RouteSuspense are 'use client' components.
|
|
13
14
|
// Under --conditions react-server, React.Component is not available, so we
|
|
14
15
|
// must NOT import them at the top level. Instead we lazy-require them after
|
|
@@ -96,9 +97,19 @@ function setupTypeScriptRuntime(cwd) {
|
|
|
96
97
|
esModuleInterop: true,
|
|
97
98
|
},
|
|
98
99
|
});
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
// fallback
|
|
104
|
+
}
|
|
105
|
+
try {
|
|
106
|
+
require.resolve('tsx', { paths: [cwd] });
|
|
107
|
+
// tsx/cjs registers the TypeScript loader for require()
|
|
108
|
+
require('tsx/cjs');
|
|
109
|
+
return;
|
|
99
110
|
}
|
|
100
111
|
catch {
|
|
101
|
-
throw new Error('No TypeScript compiler available for RSC upstream runtime.');
|
|
112
|
+
throw new Error('No TypeScript compiler available for RSC upstream runtime. Install one of: @swc-node/register, ts-node, or tsx');
|
|
102
113
|
}
|
|
103
114
|
}
|
|
104
115
|
function hasClientBoundaryDirective(source) {
|
|
@@ -323,8 +334,8 @@ function startUpstream() {
|
|
|
323
334
|
const flightServerPath = resolveFromWorkspace('react-server-dom-webpack/server.node', cwd);
|
|
324
335
|
const flightServer = require(flightServerPath);
|
|
325
336
|
installClientLoadHook(cwd, flightServer.createClientModuleProxy);
|
|
326
|
-
const serverManifestPath = path_1.default.join(cwd,
|
|
327
|
-
const flightManifestPath = path_1.default.join(cwd,
|
|
337
|
+
const serverManifestPath = path_1.default.join(cwd, constants_1.BUILD_DIR, 'server', 'server-manifest.json');
|
|
338
|
+
const flightManifestPath = path_1.default.join(cwd, constants_1.BUILD_DIR, 'react-client-manifest.json');
|
|
328
339
|
if (!fs_1.default.existsSync(serverManifestPath)) {
|
|
329
340
|
throw new Error('Missing RSC server manifest. Run "vista build" first.');
|
|
330
341
|
}
|
|
@@ -17,6 +17,7 @@ exports.createStructureWatcher = createStructureWatcher;
|
|
|
17
17
|
const path_1 = __importDefault(require("path"));
|
|
18
18
|
const events_1 = require("events");
|
|
19
19
|
const structure_validator_1 = require("./structure-validator");
|
|
20
|
+
const constants_1 = require("../constants");
|
|
20
21
|
// ============================================================================
|
|
21
22
|
// Watch Service
|
|
22
23
|
// ============================================================================
|
|
@@ -52,7 +53,7 @@ class StructureWatcher extends events_1.EventEmitter {
|
|
|
52
53
|
];
|
|
53
54
|
this.watcher = chokidar.watch(watchPaths, {
|
|
54
55
|
ignoreInitial: true,
|
|
55
|
-
ignored: ['**/node_modules/**',
|
|
56
|
+
ignored: ['**/node_modules/**', `**/${constants_1.BUILD_DIR}/**`, '**/dist/**'],
|
|
56
57
|
persistent: true,
|
|
57
58
|
});
|
|
58
59
|
this.watcher.on('all', (event, filePath) => {
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vistagenic/vista",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "The React Framework for Visionaries - Rust-powered SSR with Server Components",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
9
|
-
"url": "https://github.com/vistagen/Vista-Js.git",
|
|
9
|
+
"url": "git+https://github.com/vistagen/Vista-Js.git",
|
|
10
10
|
"directory": "packages/vista"
|
|
11
11
|
},
|
|
12
12
|
"author": "Vista Team",
|
|
@@ -88,7 +88,7 @@
|
|
|
88
88
|
"./package.json": "./package.json"
|
|
89
89
|
},
|
|
90
90
|
"bin": {
|
|
91
|
-
"vista": "
|
|
91
|
+
"vista": "bin/vista.js"
|
|
92
92
|
},
|
|
93
93
|
"publishConfig": {
|
|
94
94
|
"access": "public"
|