@vesk/adapter 0.0.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/README.md +21 -0
- package/dist/api-function.d.ts +7 -0
- package/dist/api-function.d.ts.map +1 -0
- package/dist/api-function.js +187 -0
- package/dist/client-bundle.d.ts +19 -0
- package/dist/client-bundle.d.ts.map +1 -0
- package/dist/client-bundle.js +491 -0
- package/dist/dev-server.d.ts +4 -0
- package/dist/dev-server.d.ts.map +1 -0
- package/dist/dev-server.js +358 -0
- package/dist/esbuild-fallback.d.ts +3 -0
- package/dist/esbuild-fallback.d.ts.map +1 -0
- package/dist/esbuild-fallback.js +64 -0
- package/dist/hmr.d.ts +7 -0
- package/dist/hmr.d.ts.map +1 -0
- package/dist/hmr.js +411 -0
- package/dist/image-pipeline.d.ts +3 -0
- package/dist/image-pipeline.d.ts.map +1 -0
- package/dist/image-pipeline.js +120 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +291 -0
- package/dist/manifest.d.ts +3 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +47 -0
- package/dist/middleware.d.ts +4 -0
- package/dist/middleware.d.ts.map +1 -0
- package/dist/middleware.js +96 -0
- package/dist/package.json +15 -0
- package/dist/platform-deploy.d.ts +18 -0
- package/dist/platform-deploy.d.ts.map +1 -0
- package/dist/platform-deploy.js +354 -0
- package/dist/platform-handler.d.ts +32 -0
- package/dist/platform-handler.d.ts.map +1 -0
- package/dist/platform-handler.js +211 -0
- package/dist/platform-output.d.ts +30 -0
- package/dist/platform-output.d.ts.map +1 -0
- package/dist/platform-output.js +119 -0
- package/dist/platform.d.ts +17 -0
- package/dist/platform.d.ts.map +1 -0
- package/dist/platform.js +35 -0
- package/dist/prod-server.d.ts +5 -0
- package/dist/prod-server.d.ts.map +1 -0
- package/dist/prod-server.js +429 -0
- package/dist/runtime-bundle.d.ts +2 -0
- package/dist/runtime-bundle.d.ts.map +1 -0
- package/dist/runtime-bundle.js +140 -0
- package/dist/seo-audit.d.ts +3 -0
- package/dist/seo-audit.d.ts.map +1 -0
- package/dist/seo-audit.js +169 -0
- package/dist/ssr-function.d.ts +8 -0
- package/dist/ssr-function.d.ts.map +1 -0
- package/dist/ssr-function.js +415 -0
- package/dist/static.d.ts +8 -0
- package/dist/static.d.ts.map +1 -0
- package/dist/static.js +130 -0
- package/dist/types.d.ts +182 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +1 -0
- package/package.json +54 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
import { mkdirSync, writeFileSync, existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { resolve, dirname, relative } from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { cssBlockEnd } from '@vesk/compiler/src/scan';
|
|
5
|
+
import { bundleRuntime } from '@vesk/adapter/src/runtime-bundle';
|
|
6
|
+
import { generateSsrFunction } from '@vesk/adapter/src/ssr-function';
|
|
7
|
+
import { collectActionIds } from '@vesk/compiler/src/actions';
|
|
8
|
+
import { generateApiFunction } from '@vesk/adapter/src/api-function';
|
|
9
|
+
import { compileMiddleware, compileMiddlewareCode } from '@vesk/adapter/src/middleware';
|
|
10
|
+
import { generateClientBundle } from '@vesk/adapter/src/client-bundle';
|
|
11
|
+
import { generateManifest } from '@vesk/adapter/src/manifest';
|
|
12
|
+
import { copyStaticAssets } from '@vesk/adapter/src/static';
|
|
13
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
14
|
+
async function resolveCompilerApi(name) {
|
|
15
|
+
const monorepoSrc = resolve(__dirname, '..', '..', 'compiler', 'src');
|
|
16
|
+
if (existsSync(monorepoSrc)) {
|
|
17
|
+
const tsFile = resolve(monorepoSrc, name.replace(/\.js$/, '.ts'));
|
|
18
|
+
if (existsSync(tsFile)) {
|
|
19
|
+
return import(tsFile);
|
|
20
|
+
}
|
|
21
|
+
return import(resolve(monorepoSrc, name));
|
|
22
|
+
}
|
|
23
|
+
return import(`@vesk/compiler/src/${name.replace(/\.js$/, '')}`);
|
|
24
|
+
}
|
|
25
|
+
export async function build(appDir, options) {
|
|
26
|
+
appDir = resolve(appDir);
|
|
27
|
+
const outDir = resolve(options?.outDir || resolve(appDir, '..', '.vesk'));
|
|
28
|
+
const publicDir = options?.publicDir || resolve(appDir, '..', 'public');
|
|
29
|
+
const plugins = options?.plugins || [];
|
|
30
|
+
for (const plugin of plugins) {
|
|
31
|
+
if (typeof plugin.onBuildStart === 'function') {
|
|
32
|
+
await plugin.onBuildStart();
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
console.error(`vesk build: output → ${outDir}`);
|
|
36
|
+
const dirs = [
|
|
37
|
+
resolve(outDir, 'server', 'functions'),
|
|
38
|
+
resolve(outDir, 'server', 'api'),
|
|
39
|
+
resolve(outDir, 'static', 'public'),
|
|
40
|
+
resolve(outDir, 'prerendered'),
|
|
41
|
+
];
|
|
42
|
+
for (const d of dirs)
|
|
43
|
+
mkdirSync(d, { recursive: true });
|
|
44
|
+
const { scanRoutes, scanComponents } = await resolveCompilerApi('router.js');
|
|
45
|
+
const { scanApiRoutes } = await resolveCompilerApi('api-routes.js');
|
|
46
|
+
const { collectMiddlewareChain } = await resolveCompilerApi('middleware.js');
|
|
47
|
+
const routeTree = scanRoutes(appDir);
|
|
48
|
+
if (routeTree.length === 0) {
|
|
49
|
+
console.error('vesk build: no routes found in', appDir);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const projectRoot = resolve(appDir, '..');
|
|
53
|
+
const componentsDir = resolve(projectRoot, 'components');
|
|
54
|
+
const componentMap = scanComponents(componentsDir);
|
|
55
|
+
if (componentMap.size > 0) {
|
|
56
|
+
console.error(`vesk build: ${componentMap.size} external components found in ${componentsDir}`);
|
|
57
|
+
}
|
|
58
|
+
const apiDir = resolve(appDir, 'api');
|
|
59
|
+
const apiTree = existsSync(apiDir) ? scanApiRoutes(apiDir) : [];
|
|
60
|
+
console.error(`vesk build: ${routeTree.length} root routes, ${apiTree.length} API routes`);
|
|
61
|
+
console.error('vesk build: bundling server runtime...');
|
|
62
|
+
await bundleRuntime(appDir, outDir);
|
|
63
|
+
const ssrRoutes = [];
|
|
64
|
+
const actionMap = {};
|
|
65
|
+
function walk(nodes, ancestorLayouts = []) {
|
|
66
|
+
for (const node of nodes) {
|
|
67
|
+
const childAncestorLayouts = node.layout
|
|
68
|
+
? [...ancestorLayouts, { sourceDir: node.sourceDir, layoutCompName: node.layout }]
|
|
69
|
+
: ancestorLayouts;
|
|
70
|
+
if (node.page) {
|
|
71
|
+
const mwChain = collectMiddlewareChain(routeTree, node.fullPath, appDir);
|
|
72
|
+
let mwCode = null;
|
|
73
|
+
if (mwChain.length > 0) {
|
|
74
|
+
const mwSources = mwChain.map((m) => readFileSync(m.sourcePath, 'utf-8'));
|
|
75
|
+
mwCode = compileMiddlewareCode(mwSources);
|
|
76
|
+
}
|
|
77
|
+
const { funcPath, funcCode, name } = generateSsrFunction(node, appDir, outDir, componentMap, { ancestorLayouts, middlewareCode: mwCode });
|
|
78
|
+
writeFileSync(funcPath, funcCode, 'utf-8');
|
|
79
|
+
const pagePath = resolve(appDir, node.sourceDir, 'page.vsk');
|
|
80
|
+
if (existsSync(pagePath)) {
|
|
81
|
+
const src = readFileSync(pagePath, 'utf-8');
|
|
82
|
+
const actionIds = collectActionIds(src);
|
|
83
|
+
if (node.layout) {
|
|
84
|
+
const layoutSrc = readFileSync(resolve(appDir, node.sourceDir, 'layout.vsk'), 'utf-8');
|
|
85
|
+
actionIds.push(...collectActionIds(layoutSrc));
|
|
86
|
+
}
|
|
87
|
+
for (const a of ancestorLayouts) {
|
|
88
|
+
const ancestorSrc = readFileSync(resolve(appDir, a.sourceDir, 'layout.vsk'), 'utf-8');
|
|
89
|
+
actionIds.push(...collectActionIds(ancestorSrc));
|
|
90
|
+
}
|
|
91
|
+
for (const id of actionIds) {
|
|
92
|
+
if (!actionMap[id])
|
|
93
|
+
actionMap[id] = `server/functions/${name}.js`;
|
|
94
|
+
}
|
|
95
|
+
const revalidateMatch = src.match(/export\s+const\s+revalidate\s*=\s*(\d+)/);
|
|
96
|
+
if (revalidateMatch)
|
|
97
|
+
node._revalidate = parseInt(revalidateMatch[1], 10);
|
|
98
|
+
const tagsMatch = src.match(/export\s+const\s+isrTags\s*=\s*\[([^\]]*)\]/);
|
|
99
|
+
if (tagsMatch) {
|
|
100
|
+
node._isrTags = tagsMatch[1].split(',').map(t => t.trim().replace(/['"]/g, '')).filter(Boolean);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
ssrRoutes.push(node);
|
|
104
|
+
console.error(`vesk build: ssr → server/functions/${name}.js (${node.fullPath})${mwCode ? ' [mw]' : ''}`);
|
|
105
|
+
}
|
|
106
|
+
walk(node.children || [], childAncestorLayouts);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
walk(routeTree);
|
|
110
|
+
const apiRoutes = [];
|
|
111
|
+
function walkApi(nodes) {
|
|
112
|
+
for (const node of nodes) {
|
|
113
|
+
if (node.filePath) {
|
|
114
|
+
const { funcPath, funcCode, name } = generateApiFunction(node, apiDir, outDir);
|
|
115
|
+
writeFileSync(funcPath, funcCode, 'utf-8');
|
|
116
|
+
apiRoutes.push(node);
|
|
117
|
+
console.error(`vesk build: api → server/api/${name}.js (${node.fullPath})`);
|
|
118
|
+
}
|
|
119
|
+
walkApi(node.children || []);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
walkApi(apiTree);
|
|
123
|
+
let middlewareEnabled = false;
|
|
124
|
+
const mwChain = collectMiddlewareChain(routeTree, '/', appDir);
|
|
125
|
+
if (mwChain.length > 0) {
|
|
126
|
+
const mwCode = compileMiddleware(mwChain, appDir);
|
|
127
|
+
if (mwCode) {
|
|
128
|
+
writeFileSync(resolve(outDir, 'server', 'middleware.js'), mwCode, 'utf-8');
|
|
129
|
+
middlewareEnabled = true;
|
|
130
|
+
console.error(`vesk build: mw → server/middleware.js (${mwChain.length} middlewares)`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
console.error('vesk build: bundling client runtime...');
|
|
134
|
+
const bundleOpts = {};
|
|
135
|
+
if (options?.codeSplit)
|
|
136
|
+
bundleOpts.codeSplit = true;
|
|
137
|
+
if (options?.hmr)
|
|
138
|
+
bundleOpts.hmr = true;
|
|
139
|
+
if (options?.routeDataCache !== undefined)
|
|
140
|
+
bundleOpts.routeDataCache = options.routeDataCache;
|
|
141
|
+
const { main, chunks } = await generateClientBundle(routeTree, appDir, componentMap, bundleOpts);
|
|
142
|
+
writeFileSync(resolve(outDir, 'static', 'client.js'), main, 'utf-8');
|
|
143
|
+
const mode = chunks.length > 0 ? 'code-split' : 'monolithic';
|
|
144
|
+
console.error(`vesk build: client → static/client.js (${main.length} bytes, ${mode})`);
|
|
145
|
+
if (chunks.length > 0) {
|
|
146
|
+
const staticDir = resolve(outDir, 'static');
|
|
147
|
+
for (const chunk of chunks) {
|
|
148
|
+
writeFileSync(resolve(staticDir, chunk.name), chunk.code, 'utf-8');
|
|
149
|
+
console.error(`vesk build: chunk → static/${chunk.name} (${chunk.code.length} bytes)`);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
copyStaticAssets(publicDir, outDir);
|
|
153
|
+
console.error('vesk build: static → static/public/');
|
|
154
|
+
const srcDir = resolve(appDir, '..', 'src');
|
|
155
|
+
const cssSrc = resolve(srcDir, 'global.css');
|
|
156
|
+
const altCssSrc = resolve(srcDir, 'app.css');
|
|
157
|
+
let cssContent = null;
|
|
158
|
+
let cssSourcePath = null;
|
|
159
|
+
if (existsSync(cssSrc)) {
|
|
160
|
+
cssContent = readFileSync(cssSrc, 'utf-8');
|
|
161
|
+
cssSourcePath = cssSrc;
|
|
162
|
+
}
|
|
163
|
+
else if (existsSync(altCssSrc)) {
|
|
164
|
+
cssContent = readFileSync(altCssSrc, 'utf-8');
|
|
165
|
+
cssSourcePath = altCssSrc;
|
|
166
|
+
}
|
|
167
|
+
function stripTailwindDirectives(css) {
|
|
168
|
+
const blockStart = /^\s*@(theme\s*\{|layer\s+(components|utilities)\s*\{|utility\s+\w+\s*\{)/;
|
|
169
|
+
let result = css.replace(/^\s*@import\s+['"]tailwindcss['"]\s*;?\s*$/gm, '');
|
|
170
|
+
result = result.replace(/^\s*@source\s+['"][^'"]+['"]\s*;?\s*$/gm, '');
|
|
171
|
+
const output = [];
|
|
172
|
+
let pos = 0;
|
|
173
|
+
while (pos < result.length) {
|
|
174
|
+
const lineEnd = result.indexOf('\n', pos) === -1 ? result.length : result.indexOf('\n', pos) + 1;
|
|
175
|
+
const line = result.slice(pos, lineEnd);
|
|
176
|
+
if (blockStart.test(line.trim())) {
|
|
177
|
+
const end = cssBlockEnd(result, pos);
|
|
178
|
+
pos = end;
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
output.push(line);
|
|
182
|
+
pos = lineEnd;
|
|
183
|
+
}
|
|
184
|
+
return output.join('').trim();
|
|
185
|
+
}
|
|
186
|
+
if (cssContent !== null) {
|
|
187
|
+
const userCss = stripTailwindDirectives(cssContent);
|
|
188
|
+
const userCssTarget = resolve(outDir, 'static', 'global.css');
|
|
189
|
+
writeFileSync(userCssTarget, userCss, 'utf-8');
|
|
190
|
+
console.error(`vesk build: css → static/global.css (${userCss.length} bytes)`);
|
|
191
|
+
let twCss = cssContent;
|
|
192
|
+
for (const plugin of plugins) {
|
|
193
|
+
if (typeof plugin.onCSS === 'function') {
|
|
194
|
+
const result = await plugin.onCSS(twCss, cssSourcePath);
|
|
195
|
+
if (result !== null && typeof result === 'string') {
|
|
196
|
+
twCss = result;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
const twCssTarget = resolve(outDir, 'static', '_tailwind.css');
|
|
201
|
+
const hasUnresolvedTailwindImport = /@import\s+['"]tailwindcss['"]/.test(twCss);
|
|
202
|
+
if (hasUnresolvedTailwindImport) {
|
|
203
|
+
const lines = twCss.split('\n').filter(l => !/^\s*@import\s+['"]tailwindcss['"]/.test(l));
|
|
204
|
+
twCss = lines.join('\n').trim();
|
|
205
|
+
if (twCss.length === 0) {
|
|
206
|
+
writeFileSync(twCssTarget, '', 'utf-8');
|
|
207
|
+
console.error('vesk build: css → static/_tailwind.css (empty, tailwind unresolved)');
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
writeFileSync(twCssTarget, twCss, 'utf-8');
|
|
211
|
+
console.error(`vesk build: css → static/_tailwind.css (${twCss.length} bytes, tailwind partially unresolved)`);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
writeFileSync(twCssTarget, twCss, 'utf-8');
|
|
216
|
+
console.error(`vesk build: css → static/_tailwind.css (${twCss.length} bytes)`);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
let prerenderedRoutes = [];
|
|
220
|
+
if (options?.ssg) {
|
|
221
|
+
const { generateSsgRoutes } = await import('./static.js');
|
|
222
|
+
prerenderedRoutes = await generateSsgRoutes(routeTree, appDir, outDir);
|
|
223
|
+
console.error(`vesk build: ssg → prerendered/ (${prerenderedRoutes.length} pages)`);
|
|
224
|
+
}
|
|
225
|
+
{
|
|
226
|
+
const { optimizeImages } = await import('./image-pipeline.js');
|
|
227
|
+
await optimizeImages(appDir, outDir);
|
|
228
|
+
}
|
|
229
|
+
if (options?.seo) {
|
|
230
|
+
const { runSeoAudit } = await import('./seo-audit.js');
|
|
231
|
+
const audit = runSeoAudit(appDir);
|
|
232
|
+
if (options?.strictSeo && audit.errors > 0) {
|
|
233
|
+
throw new Error(`SEO audit failed with ${audit.errors} error(s) — fix them before deploying`);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
{
|
|
237
|
+
const { optimizeImages } = await import('./image-pipeline.js');
|
|
238
|
+
await optimizeImages(appDir, outDir);
|
|
239
|
+
}
|
|
240
|
+
{
|
|
241
|
+
const { generateSitemap, generateRobotsTxt } = await import('./static.js');
|
|
242
|
+
const publicDirResolved = resolve(outDir, 'static', 'public');
|
|
243
|
+
const siteUrl = options?.siteUrl || 'http://localhost:3000';
|
|
244
|
+
const sitemapOverride = resolve(publicDirResolved, 'sitemap.xml');
|
|
245
|
+
if (!existsSync(sitemapOverride)) {
|
|
246
|
+
const sitemap = generateSitemap(routeTree, ssrRoutes, prerenderedRoutes, { siteUrl });
|
|
247
|
+
writeFileSync(sitemapOverride, sitemap, 'utf-8');
|
|
248
|
+
console.error(`vesk build: seo → static/public/sitemap.xml (${sitemap.length} bytes)`);
|
|
249
|
+
}
|
|
250
|
+
const robotsOverride = resolve(publicDirResolved, 'robots.txt');
|
|
251
|
+
if (!existsSync(robotsOverride)) {
|
|
252
|
+
const robots = generateRobotsTxt(siteUrl);
|
|
253
|
+
writeFileSync(robotsOverride, robots, 'utf-8');
|
|
254
|
+
console.error(`vesk build: seo → static/public/robots.txt (${robots.length} bytes)`);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
const manifest = generateManifest(routeTree, ssrRoutes, apiRoutes, prerenderedRoutes, middlewareEnabled, actionMap);
|
|
258
|
+
writeFileSync(resolve(outDir, 'config.json'), JSON.stringify(manifest, null, 2) + '\n', 'utf-8');
|
|
259
|
+
console.error('vesk build: config → config.json');
|
|
260
|
+
{
|
|
261
|
+
const { detectPlatform } = await import('@vesk/adapter/src/platform');
|
|
262
|
+
const { emitPlatformOutput } = await import('@vesk/adapter/src/platform-deploy');
|
|
263
|
+
let platform = detectPlatform(options?.platform ? ['--platform', options.platform] : [], process.env);
|
|
264
|
+
if (platform === 'node' && options?.target === 'edge')
|
|
265
|
+
platform = 'edge';
|
|
266
|
+
if (platform !== 'node') {
|
|
267
|
+
const outRoot = await emitPlatformOutput(platform, {
|
|
268
|
+
outDir,
|
|
269
|
+
ssrRoutes,
|
|
270
|
+
apiRoutes,
|
|
271
|
+
prerenderedPaths: prerenderedRoutes.map(r => r.path),
|
|
272
|
+
prerenderedRoutes,
|
|
273
|
+
hasMiddleware: middlewareEnabled,
|
|
274
|
+
});
|
|
275
|
+
if (outRoot) {
|
|
276
|
+
console.error(`vesk build: ${platform} → ${relative(projectRoot, outRoot)}`);
|
|
277
|
+
if (platform === 'vercel') {
|
|
278
|
+
console.error('vesk build: vercel → .vercel/output (symlink)');
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
for (const plugin of plugins) {
|
|
284
|
+
if (typeof plugin.onBuildEnd === 'function') {
|
|
285
|
+
await plugin.onBuildEnd();
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
console.error(`\nvesk build: done (${outDir})`);
|
|
289
|
+
return { routeTree, apiTree, ssrRoutes, apiRoutes, manifest };
|
|
290
|
+
}
|
|
291
|
+
export { startProdServer } from '@vesk/adapter/src/prod-server';
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { RouteNode, ApiRouteNode, Manifest, SsgRouteResult } from '@vesk/adapter/src/types';
|
|
2
|
+
export declare function generateManifest(routes: RouteNode[], ssrRoutes: RouteNode[], apiRoutes: ApiRouteNode[], staticRoutes: SsgRouteResult[], middlewareEnabled: boolean, actionMap?: Record<string, string>): Manifest;
|
|
3
|
+
//# sourceMappingURL=manifest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,QAAQ,EAAqE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAEpK,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,SAAS,EAAE,EACnB,SAAS,EAAE,SAAS,EAAE,EACtB,SAAS,EAAE,YAAY,EAAE,EACzB,YAAY,EAAE,cAAc,EAAE,EAC9B,iBAAiB,EAAE,OAAO,EAC1B,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACjC,QAAQ,CAiDV"}
|
package/dist/manifest.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export function generateManifest(routes, ssrRoutes, apiRoutes, staticRoutes, middlewareEnabled, actionMap) {
|
|
2
|
+
const routeEntries = [];
|
|
3
|
+
for (const r of ssrRoutes) {
|
|
4
|
+
const urlParts = r.fullPath.split('/').filter(Boolean);
|
|
5
|
+
const name = urlParts.map(s => s.startsWith(':') ? s.slice(1) : s).join('_') || 'index';
|
|
6
|
+
const entry = {
|
|
7
|
+
path: r.fullPath,
|
|
8
|
+
type: 'ssr',
|
|
9
|
+
function: `server/functions/${name}.js`,
|
|
10
|
+
};
|
|
11
|
+
if (r._revalidate != null)
|
|
12
|
+
entry.revalidate = r._revalidate;
|
|
13
|
+
if (r._isrTags)
|
|
14
|
+
entry.tags = r._isrTags;
|
|
15
|
+
routeEntries.push(entry);
|
|
16
|
+
}
|
|
17
|
+
for (const r of apiRoutes) {
|
|
18
|
+
const urlParts = r.fullPath.split('/').filter(Boolean);
|
|
19
|
+
const name = urlParts.map(s => s.startsWith(':') ? s.slice(1) || 'param' : s).join('_') || 'index';
|
|
20
|
+
routeEntries.push({
|
|
21
|
+
path: `/api${r.fullPath}`,
|
|
22
|
+
type: 'api',
|
|
23
|
+
function: `server/api/${name}.js`,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
const ssgEntries = [];
|
|
27
|
+
for (const r of staticRoutes) {
|
|
28
|
+
ssgEntries.push({
|
|
29
|
+
path: r.path,
|
|
30
|
+
file: `prerendered${r.path === '/' ? '/index' : r.path}.html`,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
const actionEntries = actionMap
|
|
34
|
+
? Object.entries(actionMap).map(([id, fn]) => ({ id, function: fn }))
|
|
35
|
+
: [];
|
|
36
|
+
return {
|
|
37
|
+
version: 1,
|
|
38
|
+
middleware: middlewareEnabled,
|
|
39
|
+
routes: routeEntries,
|
|
40
|
+
prerendered: ssgEntries,
|
|
41
|
+
static: {
|
|
42
|
+
prefix: '/_vesk/static',
|
|
43
|
+
dir: 'static',
|
|
44
|
+
},
|
|
45
|
+
...(actionEntries.length > 0 ? { actions: actionEntries } : {}),
|
|
46
|
+
};
|
|
47
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { MiddlewareChainItem } from '@vesk/adapter/src/types';
|
|
2
|
+
export declare function compileMiddleware(mwChain: MiddlewareChainItem[], _appDir: string): string | null;
|
|
3
|
+
export declare function compileMiddlewareCode(mwSourceTexts: string[]): string | null;
|
|
4
|
+
//# sourceMappingURL=middleware.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAA2B,MAAM,yBAAyB,CAAC;AAS5F,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,mBAAmB,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CA6ChG;AAED,wBAAgB,qBAAqB,CAAC,aAAa,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,IAAI,CA2C5E"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { extractMiddlewareParts } from '@vesk/compiler/src/router';
|
|
3
|
+
function extractMiddlewareBody(src) {
|
|
4
|
+
const parts = extractMiddlewareParts(src);
|
|
5
|
+
if (!parts)
|
|
6
|
+
return null;
|
|
7
|
+
return { params: parts.params, body: parts.body };
|
|
8
|
+
}
|
|
9
|
+
export function compileMiddleware(mwChain, _appDir) {
|
|
10
|
+
if (mwChain.length === 0)
|
|
11
|
+
return null;
|
|
12
|
+
const parts = [];
|
|
13
|
+
for (let i = 0; i < mwChain.length; i++) {
|
|
14
|
+
const { sourcePath } = mwChain[i];
|
|
15
|
+
const src = readFileSync(sourcePath, 'utf-8');
|
|
16
|
+
const extracted = extractMiddlewareBody(src);
|
|
17
|
+
if (!extracted)
|
|
18
|
+
continue;
|
|
19
|
+
parts.push(`async function mw_${i}(${extracted.params}) {\n${extracted.body}\n}`);
|
|
20
|
+
}
|
|
21
|
+
if (parts.length === 0)
|
|
22
|
+
return null;
|
|
23
|
+
const code = [
|
|
24
|
+
'// Auto-generated middleware chain — do not edit',
|
|
25
|
+
'',
|
|
26
|
+
parts.join('\n\n'),
|
|
27
|
+
'',
|
|
28
|
+
`const chain = [${parts.map((_, i) => `mw_${i}`).join(', ')}];`,
|
|
29
|
+
'',
|
|
30
|
+
'export async function execute(ctx) {',
|
|
31
|
+
' let rewriteUrl = null;',
|
|
32
|
+
' async function run(index) {',
|
|
33
|
+
' if (index >= chain.length) return null;',
|
|
34
|
+
' const fn = chain[index];',
|
|
35
|
+
' let nextCalled = false;',
|
|
36
|
+
' async function next(rewrite) {',
|
|
37
|
+
' if (nextCalled) return null;',
|
|
38
|
+
' nextCalled = true;',
|
|
39
|
+
' if (rewrite) rewriteUrl = rewrite;',
|
|
40
|
+
' return run(index + 1);',
|
|
41
|
+
' }',
|
|
42
|
+
' const result = await fn(ctx, next);',
|
|
43
|
+
' if (result instanceof Response) return result;',
|
|
44
|
+
' if (!nextCalled) return run(index + 1);',
|
|
45
|
+
' return null;',
|
|
46
|
+
' }',
|
|
47
|
+
' const response = await run(0);',
|
|
48
|
+
' return { response, rewriteUrl };',
|
|
49
|
+
'}',
|
|
50
|
+
'',
|
|
51
|
+
].join('\n');
|
|
52
|
+
return code;
|
|
53
|
+
}
|
|
54
|
+
export function compileMiddlewareCode(mwSourceTexts) {
|
|
55
|
+
if (!mwSourceTexts || mwSourceTexts.length === 0)
|
|
56
|
+
return null;
|
|
57
|
+
const parts = [];
|
|
58
|
+
for (let i = 0; i < mwSourceTexts.length; i++) {
|
|
59
|
+
const extracted = extractMiddlewareBody(mwSourceTexts[i]);
|
|
60
|
+
if (!extracted)
|
|
61
|
+
continue;
|
|
62
|
+
parts.push(`async function mw_${i}(${extracted.params}) {\n${extracted.body}\n}`);
|
|
63
|
+
}
|
|
64
|
+
if (parts.length === 0)
|
|
65
|
+
return null;
|
|
66
|
+
const code = [
|
|
67
|
+
'// ── Middleware chain (inline) ──',
|
|
68
|
+
'',
|
|
69
|
+
parts.join('\n\n'),
|
|
70
|
+
'',
|
|
71
|
+
`const __mwChain = [${parts.map((_, i) => `mw_${i}`).join(', ')}];`,
|
|
72
|
+
'',
|
|
73
|
+
'async function __executeMw(ctx) {',
|
|
74
|
+
' let rewriteUrl = null;',
|
|
75
|
+
' async function run(index) {',
|
|
76
|
+
' if (index >= __mwChain.length) return null;',
|
|
77
|
+
' const fn = __mwChain[index];',
|
|
78
|
+
' let nc = false;',
|
|
79
|
+
' async function next(rewrite) {',
|
|
80
|
+
' if (nc) return null;',
|
|
81
|
+
' nc = true;',
|
|
82
|
+
' if (rewrite) rewriteUrl = rewrite;',
|
|
83
|
+
' return run(index + 1);',
|
|
84
|
+
' }',
|
|
85
|
+
' const result = await fn(ctx, next);',
|
|
86
|
+
' if (result instanceof Response) return result;',
|
|
87
|
+
' if (!nc) return run(index + 1);',
|
|
88
|
+
' return null;',
|
|
89
|
+
' }',
|
|
90
|
+
' const response = await run(0);',
|
|
91
|
+
' return { response, rewriteUrl };',
|
|
92
|
+
'}',
|
|
93
|
+
'',
|
|
94
|
+
].join('\n');
|
|
95
|
+
return code;
|
|
96
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vesk/adapter",
|
|
3
|
+
"version": "0.1.9",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./index.js",
|
|
6
|
+
"types": "./index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./index.d.ts",
|
|
10
|
+
"default": "./index.js"
|
|
11
|
+
},
|
|
12
|
+
"./src/*": "./*.js",
|
|
13
|
+
"./package.json": "./package.json"
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type PlatformBuildContext } from '@vesk/adapter/src/platform-handler';
|
|
2
|
+
import type { SsgRouteResult } from '@vesk/adapter/src/types';
|
|
3
|
+
import type { Platform } from '@vesk/adapter/src/platform';
|
|
4
|
+
export interface DeployContext extends PlatformBuildContext {
|
|
5
|
+
prerenderedRoutes: SsgRouteResult[];
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Universal deployment emit. The handler, the bundle and the static layout are
|
|
9
|
+
* shared across every platform — only the ~10-line shell each runtime mandates
|
|
10
|
+
* differs (artifact directory, bootstrap, function config). Deno-based platforms
|
|
11
|
+
* (Coxmos, Deno Deploy) share the exact same shell.
|
|
12
|
+
*
|
|
13
|
+
* Every artifact is written under `.vesk/<platform>/`; Vercel additionally gets
|
|
14
|
+
* a gitignored `.vercel/output` symlink because the Build Output API is keyed on
|
|
15
|
+
* that literal directory.
|
|
16
|
+
*/
|
|
17
|
+
export declare function emitPlatformOutput(platform: Platform, ctx: DeployContext): Promise<string | null>;
|
|
18
|
+
//# sourceMappingURL=platform-deploy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"platform-deploy.d.ts","sourceRoot":"","sources":["../src/platform-deploy.ts"],"names":[],"mappings":"AAEA,OAAO,EAAwD,KAAK,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAErI,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAE3D,MAAM,WAAW,aAAc,SAAQ,oBAAoB;IACzD,iBAAiB,EAAE,cAAc,EAAE,CAAC;CACrC;AA0BD;;;;;;;;;GASG;AACH,wBAAsB,kBAAkB,CAAC,QAAQ,EAAE,QAAQ,EAAE,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAyEvG"}
|