@vistagenic/vista 0.3.6 → 0.3.9
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/bin/flashpack-agent-playground.mjs +134 -0
- package/bin/flashpack-boot.mjs +506 -0
- package/bin/flashpack-ssr-loader.mjs +42 -0
- package/bin/flashpack-ssr.mjs +202 -0
- package/bin/flashpack-vendor.mjs +97 -0
- package/bin/vista.js +56 -42
- package/dist/ai/providers/base.js +7 -1
- package/dist/bin/build-rsc.js +16 -0
- package/dist/bin/build.js +17 -11
- package/dist/bin/deploy.js +7 -0
- package/dist/bin/dev-client-runtime.d.ts +6 -0
- package/dist/bin/dev-client-runtime.js +99 -0
- package/dist/bin/dev-error-overlay-snippet.js +79 -21
- package/dist/bin/dev-error-overlay-snippet.ts +840 -0
- package/dist/bin/devtools-indicator-snippet.js +29 -13
- package/dist/bin/file-scanner.js +7 -24
- package/dist/bin/generate.js +94 -2
- package/dist/bin/webpack.config.js +3 -1
- package/dist/build/rsc/compiler.d.ts +14 -0
- package/dist/build/rsc/compiler.js +66 -6
- package/dist/build/rsc/server-manifest.js +5 -4
- package/dist/config.d.ts +5 -0
- package/dist/config.js +15 -1
- package/dist/deploy/adapters/render.js +2 -2
- package/dist/deploy/index.d.ts +1 -0
- package/dist/deploy/index.js +3 -0
- package/dist/deploy/runtime-pack.js +22 -1
- package/dist/deploy/utils.js +16 -6
- package/dist/flashpack/command.d.ts +1 -0
- package/dist/flashpack/command.js +42 -76
- package/dist/flashpack/runtime.d.ts +12 -0
- package/dist/flashpack/runtime.js +124 -22
- package/dist/metadata/generate.d.ts +1 -0
- package/dist/metadata/generate.js +117 -21
- package/dist/metadata/index.d.ts +5 -0
- package/dist/metadata/index.js +15 -1
- package/dist/metadata/json-ld.d.ts +15 -0
- package/dist/metadata/json-ld.js +19 -0
- package/dist/metadata/merge.d.ts +17 -0
- package/dist/metadata/merge.js +161 -0
- package/dist/metadata/routes.d.ts +66 -0
- package/dist/metadata/routes.js +143 -0
- package/dist/metadata/types.d.ts +1 -1
- package/dist/metadata/types.js +3 -1
- package/dist/og/image-response.d.ts +38 -0
- package/dist/og/image-response.js +88 -0
- package/dist/og/index.d.ts +2 -0
- package/dist/og/index.js +5 -0
- package/dist/rust/index.d.ts +13 -0
- package/dist/rust/index.js +132 -0
- package/dist/server/engine.js +13 -3
- package/dist/server/logger.js +2 -1
- package/dist/server/project-alias-resolver.d.ts +7 -0
- package/dist/server/project-alias-resolver.js +70 -0
- package/dist/server/rsc-engine.js +93 -16
- package/dist/server/static-generator.js +4 -3
- package/dist/server/typed-api-runtime.js +92 -0
- package/docs/ai.md +69 -0
- package/docs/app.md +30 -0
- package/docs/cli.md +29 -0
- package/docs/index.md +18 -0
- package/docs/rag.md +54 -0
- package/native/win32-x64/flashpack-cli.exe +0 -0
- package/package.json +196 -178
- package/skills/README.md +9 -0
- package/skills/vista-agent/SKILL.md +28 -0
- package/skills/vista-dev-loop/SKILL.md +25 -0
- package/skills/vista-rag/SKILL.md +26 -0
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Next-compatible MetadataRoute helpers for robots.txt, sitemap.xml, and web manifests.
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.serializeRobots = serializeRobots;
|
|
7
|
+
exports.serializeSitemap = serializeSitemap;
|
|
8
|
+
exports.robots = robots;
|
|
9
|
+
exports.sitemap = sitemap;
|
|
10
|
+
exports.manifest = manifest;
|
|
11
|
+
exports.metadataRouteToResponse = metadataRouteToResponse;
|
|
12
|
+
function asArray(value) {
|
|
13
|
+
if (value === undefined)
|
|
14
|
+
return [];
|
|
15
|
+
return Array.isArray(value) ? value : [value];
|
|
16
|
+
}
|
|
17
|
+
function escapeXml(value) {
|
|
18
|
+
return value
|
|
19
|
+
.replace(/&/g, '&')
|
|
20
|
+
.replace(/</g, '<')
|
|
21
|
+
.replace(/>/g, '>')
|
|
22
|
+
.replace(/"/g, '"')
|
|
23
|
+
.replace(/'/g, ''');
|
|
24
|
+
}
|
|
25
|
+
function formatLastModified(value) {
|
|
26
|
+
if (!value)
|
|
27
|
+
return undefined;
|
|
28
|
+
if (value instanceof Date)
|
|
29
|
+
return value.toISOString();
|
|
30
|
+
return value;
|
|
31
|
+
}
|
|
32
|
+
/** Serialize a Robots object to robots.txt body text. */
|
|
33
|
+
function serializeRobots(data) {
|
|
34
|
+
const rules = asArray(data.rules);
|
|
35
|
+
const lines = [];
|
|
36
|
+
for (const rule of rules) {
|
|
37
|
+
const agents = asArray(rule.userAgent);
|
|
38
|
+
if (agents.length === 0) {
|
|
39
|
+
lines.push('User-agent: *');
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
for (const agent of agents) {
|
|
43
|
+
lines.push(`User-agent: ${agent}`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
for (const allow of asArray(rule.allow)) {
|
|
47
|
+
lines.push(`Allow: ${allow}`);
|
|
48
|
+
}
|
|
49
|
+
for (const disallow of asArray(rule.disallow)) {
|
|
50
|
+
lines.push(`Disallow: ${disallow}`);
|
|
51
|
+
}
|
|
52
|
+
if (typeof rule.crawlDelay === 'number') {
|
|
53
|
+
lines.push(`Crawl-delay: ${rule.crawlDelay}`);
|
|
54
|
+
}
|
|
55
|
+
if (rule.other) {
|
|
56
|
+
for (const [key, raw] of Object.entries(rule.other)) {
|
|
57
|
+
for (const entry of asArray(raw)) {
|
|
58
|
+
lines.push(`${key}: ${entry}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
lines.push('');
|
|
63
|
+
}
|
|
64
|
+
if (data.host) {
|
|
65
|
+
lines.push(`Host: ${data.host}`);
|
|
66
|
+
}
|
|
67
|
+
for (const sitemapUrl of asArray(data.sitemap)) {
|
|
68
|
+
lines.push(`Sitemap: ${sitemapUrl}`);
|
|
69
|
+
}
|
|
70
|
+
return `${lines.join('\n').replace(/\n+$/, '')}\n`;
|
|
71
|
+
}
|
|
72
|
+
/** Serialize sitemap entries to XML. */
|
|
73
|
+
function serializeSitemap(entries) {
|
|
74
|
+
const urls = entries
|
|
75
|
+
.map((entry) => {
|
|
76
|
+
const parts = [`<loc>${escapeXml(entry.url)}</loc>`];
|
|
77
|
+
const lastmod = formatLastModified(entry.lastModified);
|
|
78
|
+
if (lastmod)
|
|
79
|
+
parts.push(`<lastmod>${escapeXml(lastmod)}</lastmod>`);
|
|
80
|
+
if (entry.changeFrequency) {
|
|
81
|
+
parts.push(`<changefreq>${escapeXml(entry.changeFrequency)}</changefreq>`);
|
|
82
|
+
}
|
|
83
|
+
if (typeof entry.priority === 'number') {
|
|
84
|
+
parts.push(`<priority>${entry.priority}</priority>`);
|
|
85
|
+
}
|
|
86
|
+
if (entry.alternates?.languages) {
|
|
87
|
+
for (const [lang, href] of Object.entries(entry.alternates.languages)) {
|
|
88
|
+
parts.push(`<xhtml:link rel="alternate" hreflang="${escapeXml(lang)}" href="${escapeXml(href)}" />`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
for (const image of entry.images || []) {
|
|
92
|
+
parts.push(`<image:image><image:loc>${escapeXml(image)}</image:loc></image:image>`);
|
|
93
|
+
}
|
|
94
|
+
return `<url>${parts.join('')}</url>`;
|
|
95
|
+
})
|
|
96
|
+
.join('');
|
|
97
|
+
return `<?xml version="1.0" encoding="UTF-8"?>\n<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1">${urls}</urlset>`;
|
|
98
|
+
}
|
|
99
|
+
const DEFAULT_CACHE = 'public, max-age=0, s-maxage=3600';
|
|
100
|
+
/** Build a robots.txt Response. */
|
|
101
|
+
function robots(data) {
|
|
102
|
+
return new Response(serializeRobots(data), {
|
|
103
|
+
headers: {
|
|
104
|
+
'Content-Type': 'text/plain; charset=utf-8',
|
|
105
|
+
'Cache-Control': DEFAULT_CACHE,
|
|
106
|
+
},
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
/** Build a sitemap.xml Response. */
|
|
110
|
+
function sitemap(entries) {
|
|
111
|
+
return new Response(serializeSitemap(entries), {
|
|
112
|
+
headers: {
|
|
113
|
+
'Content-Type': 'application/xml; charset=utf-8',
|
|
114
|
+
'Cache-Control': DEFAULT_CACHE,
|
|
115
|
+
},
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
/** Build a webmanifest JSON Response. */
|
|
119
|
+
function manifest(data) {
|
|
120
|
+
return new Response(JSON.stringify(data, null, 2), {
|
|
121
|
+
headers: {
|
|
122
|
+
'Content-Type': 'application/manifest+json; charset=utf-8',
|
|
123
|
+
'Cache-Control': DEFAULT_CACHE,
|
|
124
|
+
},
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
/** Convert a MetadataRoute default-export payload into a Response. */
|
|
128
|
+
function metadataRouteToResponse(stem, payload) {
|
|
129
|
+
if (payload instanceof Response)
|
|
130
|
+
return payload;
|
|
131
|
+
if (payload == null)
|
|
132
|
+
return null;
|
|
133
|
+
if (stem === 'robots' && typeof payload === 'object') {
|
|
134
|
+
return robots(payload);
|
|
135
|
+
}
|
|
136
|
+
if (stem === 'sitemap' && Array.isArray(payload)) {
|
|
137
|
+
return sitemap(payload);
|
|
138
|
+
}
|
|
139
|
+
if (stem === 'manifest' && typeof payload === 'object') {
|
|
140
|
+
return manifest(payload);
|
|
141
|
+
}
|
|
142
|
+
return null;
|
|
143
|
+
}
|
package/dist/metadata/types.d.ts
CHANGED
package/dist/metadata/types.js
CHANGED
|
@@ -11,5 +11,7 @@ exports.isTemplateString = isTemplateString;
|
|
|
11
11
|
// Export type guard
|
|
12
12
|
// ============================================================================
|
|
13
13
|
function isTemplateString(title) {
|
|
14
|
-
|
|
14
|
+
if (typeof title !== 'object' || title === null)
|
|
15
|
+
return false;
|
|
16
|
+
return 'default' in title || 'absolute' in title || 'template' in title;
|
|
15
17
|
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ImageResponse — Next/Astro-compatible OG image generation via Satori + resvg.
|
|
3
|
+
*/
|
|
4
|
+
import type { ReactElement } from 'react';
|
|
5
|
+
export type ImageResponseOptions = {
|
|
6
|
+
width?: number;
|
|
7
|
+
height?: number;
|
|
8
|
+
status?: number;
|
|
9
|
+
statusText?: string;
|
|
10
|
+
headers?: HeadersInit;
|
|
11
|
+
fonts?: Array<{
|
|
12
|
+
name: string;
|
|
13
|
+
data: ArrayBuffer | Buffer;
|
|
14
|
+
weight?: number;
|
|
15
|
+
style?: 'normal' | 'italic';
|
|
16
|
+
}>;
|
|
17
|
+
debug?: boolean;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Generate a PNG Response from a JSX tree (Satori subset of CSS).
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```tsx
|
|
24
|
+
* import { ImageResponse } from 'vista/og'
|
|
25
|
+
*
|
|
26
|
+
* export default function OpenGraphImage() {
|
|
27
|
+
* return new ImageResponse(
|
|
28
|
+
* <div style={{ fontSize: 64, background: '#111', color: 'white', width: '100%', height: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
|
|
29
|
+
* Vista
|
|
30
|
+
* </div>,
|
|
31
|
+
* { width: 1200, height: 630 }
|
|
32
|
+
* )
|
|
33
|
+
* }
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export declare class ImageResponse extends Response {
|
|
37
|
+
constructor(element: ReactElement, options?: ImageResponseOptions);
|
|
38
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* ImageResponse — Next/Astro-compatible OG image generation via Satori + resvg.
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ImageResponse = void 0;
|
|
7
|
+
async function loadSatori() {
|
|
8
|
+
const mod = await import('satori');
|
|
9
|
+
return mod.default || mod;
|
|
10
|
+
}
|
|
11
|
+
async function renderSvgToPng(svg) {
|
|
12
|
+
const resvgMod = await import('@resvg/resvg-wasm');
|
|
13
|
+
const { Resvg, initWasm } = resvgMod;
|
|
14
|
+
if (typeof initWasm === 'function') {
|
|
15
|
+
try {
|
|
16
|
+
// Prefer bundled wasm; fall back silently if already initialized.
|
|
17
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
18
|
+
const wasmUrl = require.resolve('@resvg/resvg-wasm/index_bg.wasm');
|
|
19
|
+
const fs = await import('fs');
|
|
20
|
+
const wasm = fs.readFileSync(wasmUrl);
|
|
21
|
+
await initWasm(wasm);
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
try {
|
|
25
|
+
await initWasm();
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
// Already initialized in this process.
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
const resvg = new Resvg(svg, {
|
|
33
|
+
fitTo: { mode: 'original' },
|
|
34
|
+
});
|
|
35
|
+
const pngData = resvg.render();
|
|
36
|
+
return pngData.asPng();
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Generate a PNG Response from a JSX tree (Satori subset of CSS).
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```tsx
|
|
43
|
+
* import { ImageResponse } from 'vista/og'
|
|
44
|
+
*
|
|
45
|
+
* export default function OpenGraphImage() {
|
|
46
|
+
* return new ImageResponse(
|
|
47
|
+
* <div style={{ fontSize: 64, background: '#111', color: 'white', width: '100%', height: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
|
|
48
|
+
* Vista
|
|
49
|
+
* </div>,
|
|
50
|
+
* { width: 1200, height: 630 }
|
|
51
|
+
* )
|
|
52
|
+
* }
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
class ImageResponse extends Response {
|
|
56
|
+
constructor(element, options = {}) {
|
|
57
|
+
const width = options.width ?? 1200;
|
|
58
|
+
const height = options.height ?? 630;
|
|
59
|
+
const status = options.status ?? 200;
|
|
60
|
+
const statusText = options.statusText;
|
|
61
|
+
const headers = new Headers(options.headers);
|
|
62
|
+
headers.set('Content-Type', 'image/png');
|
|
63
|
+
if (!headers.has('Cache-Control')) {
|
|
64
|
+
headers.set('Cache-Control', 'public, immutable, no-transform, max-age=31536000');
|
|
65
|
+
}
|
|
66
|
+
const body = new ReadableStream({
|
|
67
|
+
async start(controller) {
|
|
68
|
+
try {
|
|
69
|
+
const satori = await loadSatori();
|
|
70
|
+
const svg = await satori(element, {
|
|
71
|
+
width,
|
|
72
|
+
height,
|
|
73
|
+
fonts: options.fonts,
|
|
74
|
+
embedFont: true,
|
|
75
|
+
});
|
|
76
|
+
const png = await renderSvgToPng(svg);
|
|
77
|
+
controller.enqueue(png);
|
|
78
|
+
controller.close();
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
controller.error(error);
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
super(body, { status, statusText, headers });
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
exports.ImageResponse = ImageResponse;
|
package/dist/og/index.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ImageResponse = void 0;
|
|
4
|
+
var image_response_1 = require("./image-response");
|
|
5
|
+
Object.defineProperty(exports, "ImageResponse", { enumerable: true, get: function () { return image_response_1.ImageResponse; } });
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface ClassifiedSegment {
|
|
2
|
+
kind: string;
|
|
3
|
+
segment: string;
|
|
4
|
+
}
|
|
5
|
+
export declare function nativeBindingsLoaded(): boolean;
|
|
6
|
+
export declare function classifyAppSegment(folder: string): ClassifiedSegment;
|
|
7
|
+
export declare function routePattern(folders: string[]): string;
|
|
8
|
+
export declare function encodeVistaErrorCode(code: string): string;
|
|
9
|
+
export declare function findVistaErrorCodes(source: string): string[];
|
|
10
|
+
export declare function tasklessSteps(enabled: boolean): string[];
|
|
11
|
+
export declare function classifyAppSegmentFallback(folder: string): ClassifiedSegment;
|
|
12
|
+
export declare function routePatternFallback(folders: string[]): string;
|
|
13
|
+
export declare function readBoundPipeline(cwd?: string): Record<string, unknown> | null;
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.nativeBindingsLoaded = nativeBindingsLoaded;
|
|
7
|
+
exports.classifyAppSegment = classifyAppSegment;
|
|
8
|
+
exports.routePattern = routePattern;
|
|
9
|
+
exports.encodeVistaErrorCode = encodeVistaErrorCode;
|
|
10
|
+
exports.findVistaErrorCodes = findVistaErrorCodes;
|
|
11
|
+
exports.tasklessSteps = tasklessSteps;
|
|
12
|
+
exports.classifyAppSegmentFallback = classifyAppSegmentFallback;
|
|
13
|
+
exports.routePatternFallback = routePatternFallback;
|
|
14
|
+
exports.readBoundPipeline = readBoundPipeline;
|
|
15
|
+
const fs_1 = __importDefault(require("fs"));
|
|
16
|
+
const path_1 = __importDefault(require("path"));
|
|
17
|
+
let native;
|
|
18
|
+
function loadNative() {
|
|
19
|
+
if (native !== undefined)
|
|
20
|
+
return native;
|
|
21
|
+
const candidates = [
|
|
22
|
+
path_1.default.resolve(__dirname, '../../../crates/vista-napi'),
|
|
23
|
+
path_1.default.resolve(__dirname, '../../../../crates/vista-napi'),
|
|
24
|
+
path_1.default.resolve(process.cwd(), 'crates/vista-napi'),
|
|
25
|
+
path_1.default.resolve(process.cwd(), '../crates/vista-napi'),
|
|
26
|
+
];
|
|
27
|
+
for (const candidate of candidates) {
|
|
28
|
+
try {
|
|
29
|
+
native = require(candidate);
|
|
30
|
+
return native;
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
// Try the next location. The TypeScript fallback stays correct either way.
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
native = null;
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
function nativeBindingsLoaded() {
|
|
40
|
+
return loadNative() !== null;
|
|
41
|
+
}
|
|
42
|
+
function classifyAppSegment(folder) {
|
|
43
|
+
const bound = loadNative();
|
|
44
|
+
if (bound?.classifyAppSegmentInfo)
|
|
45
|
+
return bound.classifyAppSegmentInfo(folder);
|
|
46
|
+
return classifyAppSegmentFallback(folder);
|
|
47
|
+
}
|
|
48
|
+
function routePattern(folders) {
|
|
49
|
+
const bound = loadNative();
|
|
50
|
+
if (bound?.routePattern)
|
|
51
|
+
return bound.routePattern(folders);
|
|
52
|
+
return routePatternFallback(folders);
|
|
53
|
+
}
|
|
54
|
+
function isValidCode(code) {
|
|
55
|
+
return code.length > 0 && /^[A-Z0-9_]+$/.test(code);
|
|
56
|
+
}
|
|
57
|
+
function encodeVistaErrorCode(code) {
|
|
58
|
+
const bound = loadNative();
|
|
59
|
+
if (bound?.encodeVistaErrorCode)
|
|
60
|
+
return bound.encodeVistaErrorCode(code);
|
|
61
|
+
if (code.startsWith('VISTA_') && isValidCode(code.slice('VISTA_'.length)))
|
|
62
|
+
return code;
|
|
63
|
+
return `VISTA_${code}`;
|
|
64
|
+
}
|
|
65
|
+
function findVistaErrorCodes(source) {
|
|
66
|
+
const bound = loadNative();
|
|
67
|
+
if (bound?.findVistaErrorCodes)
|
|
68
|
+
return bound.findVistaErrorCodes(source);
|
|
69
|
+
const found = [];
|
|
70
|
+
const pattern = /VISTA_([A-Z0-9_]+)/g;
|
|
71
|
+
for (const match of source.matchAll(pattern)) {
|
|
72
|
+
if (!found.includes(match[1]))
|
|
73
|
+
found.push(match[1]);
|
|
74
|
+
}
|
|
75
|
+
return found;
|
|
76
|
+
}
|
|
77
|
+
function tasklessSteps(enabled) {
|
|
78
|
+
const bound = loadNative();
|
|
79
|
+
if (bound?.tasklessSteps)
|
|
80
|
+
return bound.tasklessSteps(enabled);
|
|
81
|
+
return enabled ? ['scan', 'reuse-state', 'serve'] : ['scan', 'queue-work', 'serve'];
|
|
82
|
+
}
|
|
83
|
+
function classifyAppSegmentFallback(folder) {
|
|
84
|
+
if (!folder)
|
|
85
|
+
return { kind: 'static', segment: '' };
|
|
86
|
+
if (folder.startsWith('(...)') ||
|
|
87
|
+
folder.startsWith('(..)(..)') ||
|
|
88
|
+
folder.startsWith('(..)') ||
|
|
89
|
+
folder.startsWith('(.)')) {
|
|
90
|
+
return { kind: 'interception', segment: folder };
|
|
91
|
+
}
|
|
92
|
+
if (folder.startsWith('(') && folder.endsWith(')') && folder.length >= 2) {
|
|
93
|
+
return { kind: 'group', segment: folder.slice(1, -1) };
|
|
94
|
+
}
|
|
95
|
+
if (folder.startsWith('@') && folder.length > 1) {
|
|
96
|
+
return { kind: 'parallel', segment: folder.slice(1) };
|
|
97
|
+
}
|
|
98
|
+
if (folder.startsWith('[[...') && folder.endsWith(']]') && folder.length > '[[...]]'.length) {
|
|
99
|
+
return { kind: 'optional-catch-all', segment: folder.slice(5, -2) };
|
|
100
|
+
}
|
|
101
|
+
if (folder.startsWith('[...') && folder.endsWith(']') && folder.length > '[...]'.length) {
|
|
102
|
+
return { kind: 'catch-all', segment: folder.slice(4, -1) };
|
|
103
|
+
}
|
|
104
|
+
if (folder.startsWith('[') && folder.endsWith(']') && folder.length >= 2) {
|
|
105
|
+
return { kind: 'dynamic', segment: folder.slice(1, -1) };
|
|
106
|
+
}
|
|
107
|
+
return { kind: 'static', segment: folder };
|
|
108
|
+
}
|
|
109
|
+
function routePatternFallback(folders) {
|
|
110
|
+
const parts = [];
|
|
111
|
+
for (const folder of folders) {
|
|
112
|
+
const classified = classifyAppSegmentFallback(folder);
|
|
113
|
+
if (classified.kind === 'group' || classified.kind === 'parallel' || classified.kind === 'interception') {
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
if (classified.kind === 'dynamic')
|
|
117
|
+
parts.push(`:${classified.segment}`);
|
|
118
|
+
else if (classified.kind === 'catch-all')
|
|
119
|
+
parts.push(`:${classified.segment}*`);
|
|
120
|
+
else if (classified.kind === 'optional-catch-all')
|
|
121
|
+
parts.push(`:${classified.segment}*?`);
|
|
122
|
+
else
|
|
123
|
+
parts.push(classified.segment);
|
|
124
|
+
}
|
|
125
|
+
return parts.length === 0 ? '/' : `/${parts.join('/')}`;
|
|
126
|
+
}
|
|
127
|
+
function readBoundPipeline(cwd = process.cwd()) {
|
|
128
|
+
const file = path_1.default.join(cwd, '.flash', 'pipeline', 'bound.json');
|
|
129
|
+
if (!fs_1.default.existsSync(file))
|
|
130
|
+
return null;
|
|
131
|
+
return JSON.parse(fs_1.default.readFileSync(file, 'utf8'));
|
|
132
|
+
}
|
package/dist/server/engine.js
CHANGED
|
@@ -341,6 +341,15 @@ function startServer(port = 3003, compiler) {
|
|
|
341
341
|
})
|
|
342
342
|
.filter((entry) => entry.trim().length > 0);
|
|
343
343
|
(0, logger_1.logEvent)('Build error detected, pushing to browser...');
|
|
344
|
+
console.error('');
|
|
345
|
+
(0, logger_1.logError)(`Build failed with ${errorMessages.length} error${errorMessages.length === 1 ? '' : 's'}`);
|
|
346
|
+
for (const message of errorMessages) {
|
|
347
|
+
const text = message.replace(/\u001b\[[0-9;]*m/g, '').trim();
|
|
348
|
+
if (!text)
|
|
349
|
+
continue;
|
|
350
|
+
console.error(text);
|
|
351
|
+
console.error('');
|
|
352
|
+
}
|
|
344
353
|
pushCompileError(errorMessages);
|
|
345
354
|
}
|
|
346
355
|
else {
|
|
@@ -588,22 +597,23 @@ function startServer(port = 3003, compiler) {
|
|
|
588
597
|
const pageDir = path_1.default.dirname(pagePath);
|
|
589
598
|
const layouts = (0, root_resolver_1.resolveLayoutChain)(cwd, pageDir, isDev);
|
|
590
599
|
// Metadata extraction - merge all layout metadata + page metadata
|
|
600
|
+
const { deepMergeMetadata } = require('../metadata/merge');
|
|
591
601
|
let metadata = {};
|
|
592
602
|
for (const layout of layouts) {
|
|
593
603
|
if (layout.metadata) {
|
|
594
|
-
metadata =
|
|
604
|
+
metadata = deepMergeMetadata(metadata, layout.metadata);
|
|
595
605
|
}
|
|
596
606
|
}
|
|
597
607
|
// Get page static metadata (overrides layouts)
|
|
598
608
|
if (PageModule.metadata) {
|
|
599
|
-
metadata =
|
|
609
|
+
metadata = deepMergeMetadata(metadata, PageModule.metadata);
|
|
600
610
|
}
|
|
601
611
|
// Get dynamic metadata from generateMetadata function
|
|
602
612
|
if (typeof PageModule.generateMetadata === 'function') {
|
|
603
613
|
try {
|
|
604
614
|
const dynamicMeta = await PageModule.generateMetadata({ params, searchParams: req.query }, metadata // parent metadata
|
|
605
615
|
);
|
|
606
|
-
metadata =
|
|
616
|
+
metadata = deepMergeMetadata(metadata, dynamicMeta);
|
|
607
617
|
}
|
|
608
618
|
catch (e) {
|
|
609
619
|
console.error('Error in generateMetadata:', e);
|
package/dist/server/logger.js
CHANGED
|
@@ -99,7 +99,8 @@ function printServerReady(info) {
|
|
|
99
99
|
const localUrl = `http://localhost:${port}`;
|
|
100
100
|
const networkUrl = networkAddr ? `http://${networkAddr}:${port}` : null;
|
|
101
101
|
console.log(VISTA_BANNER);
|
|
102
|
-
|
|
102
|
+
const engineLabel = process.env.VISTA_ENGINE === 'flashpack' ? ` ${cyan('(flashpack)')}` : '';
|
|
103
|
+
console.log(` ${green('▼')} ${bold('Vista.Js')} ${dim(`v${getVistaVersion()}`)}${engineLabel}`);
|
|
103
104
|
console.log('');
|
|
104
105
|
console.log(` ${dim('┃')} ${bold('Local:')} ${cyan(localUrl)}`);
|
|
105
106
|
if (networkUrl) {
|
|
@@ -2,3 +2,10 @@ export interface ProjectAliasResolver {
|
|
|
2
2
|
resolve: (request: string) => string | null;
|
|
3
3
|
}
|
|
4
4
|
export declare function createProjectAliasResolver(cwd: string, resolveFromWorkspace: (specifier: string, cwd: string) => string): ProjectAliasResolver | null;
|
|
5
|
+
/**
|
|
6
|
+
* Webpack resolve.alias entries for the project's tsconfig/jsconfig `paths`.
|
|
7
|
+
* Wildcard `@/*` becomes the prefix alias `@` so client bundles resolve `@/data/site`.
|
|
8
|
+
*/
|
|
9
|
+
export declare function loadProjectWebpackAliases(cwd: string): Record<string, string>;
|
|
10
|
+
/** True when a module request is covered by a webpack path alias. */
|
|
11
|
+
export declare function requestUsesProjectAlias(request: string, aliases: Record<string, string>): boolean;
|
|
@@ -4,6 +4,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.createProjectAliasResolver = createProjectAliasResolver;
|
|
7
|
+
exports.loadProjectWebpackAliases = loadProjectWebpackAliases;
|
|
8
|
+
exports.requestUsesProjectAlias = requestUsesProjectAlias;
|
|
7
9
|
const fs_1 = __importDefault(require("fs"));
|
|
8
10
|
const path_1 = __importDefault(require("path"));
|
|
9
11
|
const projectAliasCache = new Map();
|
|
@@ -215,3 +217,71 @@ function createProjectAliasResolver(cwd, resolveFromWorkspace) {
|
|
|
215
217
|
projectAliasCache.set(cwd, resolver);
|
|
216
218
|
return resolver;
|
|
217
219
|
}
|
|
220
|
+
/**
|
|
221
|
+
* Webpack resolve.alias entries for the project's tsconfig/jsconfig `paths`.
|
|
222
|
+
* Wildcard `@/*` becomes the prefix alias `@` so client bundles resolve `@/data/site`.
|
|
223
|
+
*/
|
|
224
|
+
function loadProjectWebpackAliases(cwd) {
|
|
225
|
+
const configPath = ['tsconfig.json', 'jsconfig.json']
|
|
226
|
+
.map((filename) => path_1.default.join(cwd, filename))
|
|
227
|
+
.find((filename) => fs_1.default.existsSync(filename));
|
|
228
|
+
if (!configPath)
|
|
229
|
+
return {};
|
|
230
|
+
let compilerOptions = null;
|
|
231
|
+
try {
|
|
232
|
+
const rawConfig = fs_1.default.readFileSync(configPath, 'utf-8');
|
|
233
|
+
const parsedConfig = JSON.parse(stripJsonComments(rawConfig));
|
|
234
|
+
compilerOptions = parsedConfig.compilerOptions ?? null;
|
|
235
|
+
}
|
|
236
|
+
catch {
|
|
237
|
+
return {};
|
|
238
|
+
}
|
|
239
|
+
const rawPaths = compilerOptions?.paths;
|
|
240
|
+
if (!rawPaths || typeof rawPaths !== 'object')
|
|
241
|
+
return {};
|
|
242
|
+
const configDir = path_1.default.dirname(configPath);
|
|
243
|
+
const baseDir = path_1.default.resolve(configDir, typeof compilerOptions?.baseUrl === 'string' && compilerOptions.baseUrl.trim()
|
|
244
|
+
? compilerOptions.baseUrl
|
|
245
|
+
: '.');
|
|
246
|
+
const aliases = {};
|
|
247
|
+
for (const [pattern, targetsValue] of Object.entries(rawPaths)) {
|
|
248
|
+
const targets = Array.isArray(targetsValue)
|
|
249
|
+
? targetsValue.filter((entry) => typeof entry === 'string' && entry.trim().length > 0)
|
|
250
|
+
: [];
|
|
251
|
+
const target = targets[0];
|
|
252
|
+
if (!target)
|
|
253
|
+
continue;
|
|
254
|
+
if (pattern.includes('*')) {
|
|
255
|
+
const starIndex = pattern.indexOf('*');
|
|
256
|
+
const requestPrefix = pattern.slice(0, starIndex);
|
|
257
|
+
const targetStar = target.indexOf('*');
|
|
258
|
+
const targetPrefix = targetStar === -1 ? target : target.slice(0, targetStar);
|
|
259
|
+
if (!requestPrefix)
|
|
260
|
+
continue;
|
|
261
|
+
// enhanced-resolve matches `name` or `${name}/`. A tsconfig prefix of
|
|
262
|
+
// `@/` must be registered as `@`, or the resolver looks for `@//`.
|
|
263
|
+
const aliasName = requestPrefix.endsWith('/')
|
|
264
|
+
? requestPrefix.slice(0, -1)
|
|
265
|
+
: requestPrefix;
|
|
266
|
+
if (!aliasName)
|
|
267
|
+
continue;
|
|
268
|
+
// The matched remainder already begins with `/`. path.resolve drops a
|
|
269
|
+
// trailing separator, so do not add one back.
|
|
270
|
+
aliases[aliasName] = path_1.default.resolve(baseDir, targetPrefix);
|
|
271
|
+
continue;
|
|
272
|
+
}
|
|
273
|
+
const resolved = resolveAliasTargetPath(path_1.default.resolve(baseDir, target));
|
|
274
|
+
if (resolved) {
|
|
275
|
+
aliases[pattern] = resolved;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
return aliases;
|
|
279
|
+
}
|
|
280
|
+
/** True when a module request is covered by a webpack path alias. */
|
|
281
|
+
function requestUsesProjectAlias(request, aliases) {
|
|
282
|
+
for (const key of Object.keys(aliases)) {
|
|
283
|
+
if (request === key || request.startsWith(`${key}/`))
|
|
284
|
+
return true;
|
|
285
|
+
}
|
|
286
|
+
return false;
|
|
287
|
+
}
|